diff --git a/Applications/Diffusion/splashscreen.png b/Applications/Diffusion/splashscreen.png index b4cf03a04f..9318656f66 100644 Binary files a/Applications/Diffusion/splashscreen.png and b/Applications/Diffusion/splashscreen.png differ diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.cpp b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.cpp index 9e45e3b68e..f0fffb54c2 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.cpp +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.cpp @@ -1,188 +1,192 @@ /*=================================================================== BlueBerry Platform Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "berryXMLPreferencesStorage.h" #include "berryPreferences.h" #include "berryLog.h" #define WARNMSG BERRY_WARN("XMLPreferencesStorage") #include "Poco/File.h" #include "Poco/DOM/DOMParser.h" #include "Poco/DOM/DOMWriter.h" #include "Poco/DOM/Element.h" #include "Poco/XML/XMLWriter.h" #include "Poco/DOM/Document.h" #include "Poco/DOM/NodeIterator.h" #include "Poco/DOM/NodeFilter.h" #include "Poco/DOM/AutoPtr.h" #include "Poco/SAX/InputSource.h" #include "Poco/DOM/NamedNodeMap.h" #include "Poco/DOM/NodeList.h" #include "Poco/DOM/Element.h" #include "Poco/Exception.h" #include "Poco/SAX/SAXException.h" using Poco::XML::DOMParser; using Poco::XML::InputSource; using Poco::XML::Document; using Poco::XML::NodeIterator; using Poco::XML::NodeFilter; using Poco::XML::Node; using Poco::XML::Element; using Poco::XML::AutoPtr; using Poco::Exception; #include #include namespace berry { - - XMLPreferencesStorage::XMLPreferencesStorage( const Poco::File& _File ) : AbstractPreferencesStorage(_File) { // file already exists try{ if(_File.exists()) { // build preferences tree from file InputSource src(_File.path()); DOMParser parser; AutoPtr pDoc = parser.parse(&src); this->ToPreferencesTree(pDoc->documentElement(), 0); } } catch (Poco::XML::SAXParseException& exc) { const std::string tempString = _File.path()+".backup"; BERRY_INFO << exc.what(); BERRY_INFO << "Preferences could not be loaded."; BERRY_INFO << "Creating " << tempString; BERRY_INFO << "and resetting to default values."; _File.copyTo(tempString); this->m_Root = NULL; } // if root is null make new one if(this->m_Root.IsNull()) { this->m_Root = Preferences::Pointer(new Preferences(Preferences::PropertyMap(), "", 0, this)); } } - - void XMLPreferencesStorage::Flush(IPreferences* /*_Preferences*/) throw(Poco::Exception, BackingStoreException) { +#ifdef _MSC_VER + std::locale localeBackup; // See bug #18575: Do not remove these lines! In case of any issues regarding + std::locale::global(std::locale("")); // the formatting of numbers, try to set the numeric facet. The C locale is NOT +#endif // available here at application shutdown (possibly a bug in MSVC 2013 standard + // library), i.e., it is already partly deconstructed. try { this->ToDOMTree(dynamic_cast(this->m_Root.GetPointer()), 0); // flush dom to file Poco::XML::DOMWriter writer; //writer.setNewLine("\n"); writer.setOptions(Poco::XML::XMLWriter::PRETTY_PRINT); std::ofstream f; f.open (this->m_File.path().c_str()); // PRECISION setting // f.precision(10); writer.writeNode(f, m_Document); f.close(); } catch (std::exception& e) { WARNMSG << e.what(); } + +#ifdef _MSC_VER + std::locale::global(localeBackup); +#endif } XMLPreferencesStorage::~XMLPreferencesStorage() { } void XMLPreferencesStorage::ToPreferencesTree( Poco::XML::Node* DOMNode, Preferences* prefParentNode ) { // collect properties from attributes Preferences::PropertyMap properties; Poco::XML::Element* elem = dynamic_cast(DOMNode); std::string name = elem->getAttribute("name"); // create a new Preferences node Preferences::Pointer newNode(new Preferences(properties, name, prefParentNode, this)); // save the new Preferences node as root node if needed if(prefParentNode == 0) m_Root = newNode; // recursion: now go on for all child nodes of DOMNode Poco::XML::NodeList* childNodes = elem->childNodes(); Poco::XML::Node* currentNode = 0; Poco::XML::Element* prop = 0; std::string key; std::string value; for (unsigned int i = 0; i != childNodes->length(); ++i) { currentNode = childNodes->item(i); if(currentNode->nodeName() == "preferences") this->ToPreferencesTree(currentNode, newNode.GetPointer()); else if(currentNode->nodeName() == "property") { prop = dynamic_cast(currentNode); key = prop->getAttribute("name"); value = prop->getAttribute("value"); newNode->Put(key, value); } } } void XMLPreferencesStorage::ToDOMTree( Preferences* prefNode, Poco::XML::Node* parentDOMNode ) { if(parentDOMNode == 0) { m_Document = new Poco::XML::Document; parentDOMNode = m_Document; } //# create DOMNode from Preferences Element* newNode = m_Document->createElement("preferences"); newNode->setAttribute("name", prefNode->Name()); // make attributes Preferences::PropertyMap properties = prefNode->GetProperties(); for (Preferences::PropertyMap::iterator it = properties.begin() ; it != properties.end(); it++) { Element* newProp = m_Document->createElement("property"); newProp->setAttribute("name", it->first); newProp->setAttribute("value", it->second); newNode->appendChild(newProp); } // save in parentDOMNode parentDOMNode->appendChild(newNode); // recursion: now do that for all child Preferences nodes Preferences::ChildrenList children = prefNode->GetChildren(); for (Preferences::ChildrenList::iterator it = children.begin() ; it != children.end(); it++) { this->ToDOMTree((*it).GetPointer(), newNode); } - } } diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.help/resources/helpIndex.png b/BlueBerry/Bundles/org.blueberry.ui.qt.help/resources/helpIndex.png index 88f80ca0ab..267a4788d0 100644 Binary files a/BlueBerry/Bundles/org.blueberry.ui.qt.help/resources/helpIndex.png and b/BlueBerry/Bundles/org.blueberry.ui.qt.help/resources/helpIndex.png differ diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.help/resources/helpSearch.png b/BlueBerry/Bundles/org.blueberry.ui.qt.help/resources/helpSearch.png index 63334a10c8..d9abb8c875 100644 Binary files a/BlueBerry/Bundles/org.blueberry.ui.qt.help/resources/helpSearch.png and b/BlueBerry/Bundles/org.blueberry.ui.qt.help/resources/helpSearch.png differ diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.log/resources/debug.png b/BlueBerry/Bundles/org.blueberry.ui.qt.log/resources/debug.png index b13d78106e..341db8a92e 100644 Binary files a/BlueBerry/Bundles/org.blueberry.ui.qt.log/resources/debug.png and b/BlueBerry/Bundles/org.blueberry.ui.qt.log/resources/debug.png differ diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.log/resources/fatal.png b/BlueBerry/Bundles/org.blueberry.ui.qt.log/resources/fatal.png index 5629d0c25f..be78aafff5 100644 Binary files a/BlueBerry/Bundles/org.blueberry.ui.qt.log/resources/fatal.png and b/BlueBerry/Bundles/org.blueberry.ui.qt.log/resources/fatal.png differ diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/documentation/UserManual/ObjectBrowser.png b/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/documentation/UserManual/ObjectBrowser.png index ae143a1911..3fbf0251a5 100644 Binary files a/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/documentation/UserManual/ObjectBrowser.png and b/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/documentation/UserManual/ObjectBrowser.png differ diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/resources/ObjectBrowser.png b/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/resources/ObjectBrowser.png index ae143a1911..3fbf0251a5 100644 Binary files a/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/resources/ObjectBrowser.png and b/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/resources/ObjectBrowser.png differ diff --git a/CMake/BuildConfigurations/All.cmake b/CMake/BuildConfigurations/All.cmake index 7d32f0c724..4db45f564d 100644 --- a/CMake/BuildConfigurations/All.cmake +++ b/CMake/BuildConfigurations/All.cmake @@ -1,54 +1,55 @@ set(MITK_CONFIG_PACKAGES ) set(_apple_package_excludes) if(APPLE) set(_apple_package_excludes SOFA ) endif() set(_package_excludes ${_apple_package_excludes} Python OpenCL SYSTEM_Boost Boost_LIBRARIES SYSTEM_PYTHON SOFA_PLUGINS SOFA_PLUGINS_DIR SUPERBUILD KWSTYLE MICROBIRD_TRACKER MICROBIRD_TRACKER_INCLUDE_DIR MICROBIRD_TRACKER_LIB MICRON_TRACKER OPTITRACK_TRACKER SPACENAVIGATOR TOF_KINECT TOF_KINECTV2 TOF_MESASR4000 TOF_PMDCAMBOARD TOF_PMDCAMCUBE + TOF_PMDO3 US_TELEMED_SDK videoInput WIIMOTE ) get_cmake_property(_cache_vars CACHE_VARIABLES) foreach(_cache_var ${_cache_vars}) string(REGEX REPLACE "MITK_USE_(.+)" "\\1" _package "${_cache_var}") if(_package AND NOT _package STREQUAL _cache_var) list(FIND _package_excludes ${_package} _index) if(_index EQUAL -1) list(APPEND MITK_CONFIG_PACKAGES ${_package}) endif() endif() endforeach() set(MITK_BUILD_ALL_APPS ON CACHE BOOL "Build all MITK applications" FORCE) set(MITK_BUILD_ALL_PLUGINS ON CACHE BOOL "Build all MITK plugins" FORCE) set(MITK_BUILD_EXAMPLES ON CACHE BOOL "Build the MITK examples" FORCE) set(BLUEBERRY_BUILD_ALL_PLUGINS ON CACHE BOOL "Build all BlueBerry plugins" FORCE) set(BUILD_DiffusionMiniApps ON CACHE BOOL "Build MITK Diffusion MiniApps" FORCE) diff --git a/CMake/BuildConfigurations/WorkbenchRelease.cmake b/CMake/BuildConfigurations/WorkbenchRelease.cmake index f53ca5c0c7..f5683e82e2 100644 --- a/CMake/BuildConfigurations/WorkbenchRelease.cmake +++ b/CMake/BuildConfigurations/WorkbenchRelease.cmake @@ -1,6 +1,6 @@ -include(${CMAKE_CURRENT_LIST_DIR}/mitkBuildConfigurationDefault.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/Default.cmake) set(MITK_VTK_DEBUG_LEAKS OFF CACHE BOOL "Enable VTK Debug Leaks" FORCE) # Ensure that the in-application help can be build set(BLUEBERRY_QT_HELP_REQUIRED ON CACHE BOOL "Required Qt help documentation in plug-ins" FORCE) diff --git a/CMake/BuildConfigurations/mitkDiffusion.cmake b/CMake/BuildConfigurations/mitkDiffusion.cmake index a4c03e3ef3..0e29fd0fb0 100644 --- a/CMake/BuildConfigurations/mitkDiffusion.cmake +++ b/CMake/BuildConfigurations/mitkDiffusion.cmake @@ -1,60 +1,63 @@ message(STATUS "Configuring MITK Diffusion Release Build") +# Enable Boost which is a necessary configuration +set(MITK_USE_Boost ON CACHE BOOL "MITK Use Boost Library" FORCE) + # Disable all apps but MITK Diffusion set(MITK_BUILD_ALL_APPS OFF CACHE BOOL "Build all MITK applications" FORCE) set(MITK_BUILD_APP_CoreApp OFF CACHE BOOL "Build the MITK CoreApp" FORCE) set(MITK_BUILD_APP_Workbench OFF CACHE BOOL "Build the MITK Workbench" FORCE) set(MITK_BUILD_APP_Diffusion ON CACHE BOOL "Build MITK Diffusion" FORCE) # Activate Diffusion Mini Apps set(BUILD_DiffusionMiniApps ON CACHE BOOL "Build MITK Diffusion MiniApps" FORCE) # Build neither all plugins nor examples set(MITK_BUILD_ALL_PLUGINS OFF CACHE BOOL "Build all MITK plugins" FORCE) set(MITK_BUILD_EXAMPLES OFF CACHE BOOL "Build the MITK examples" FORCE) # Activate in-application help generation set(MITK_DOXYGEN_GENERATE_QCH_FILES ON CACHE BOOL "Use doxygen to generate Qt compressed help files for MITK docs" FORCE) set(BLUEBERRY_USE_QT_HELP ON CACHE BOOL "Enable support for integrating bundle documentation into Qt Help" FORCE) # Disable console window set(MITK_SHOW_CONSOLE_WINDOW OFF CACHE BOOL "Use this to enable or disable the console window when starting MITK GUI Applications" FORCE) # Activate required plugins # should be identical to the list in /Applications/Diffusion/CMakeLists.txt set(_plugins org.commontk.configadmin org.commontk.eventadmin org.blueberry.osgi org.blueberry.compat org.blueberry.core.runtime org.blueberry.core.expressions org.blueberry.solstice.common org.blueberry.core.commands org.blueberry.ui org.blueberry.ui.qt org.blueberry.ui.qt.log org.blueberry.ui.qt.help org.mitk.core.services org.mitk.gui.common org.mitk.planarfigure org.mitk.core.ext org.mitk.diffusionimaging org.mitk.gui.qt.application org.mitk.gui.qt.ext org.mitk.gui.qt.diffusionimagingapp org.mitk.gui.qt.common org.mitk.gui.qt.stdmultiwidgeteditor org.mitk.gui.qt.common.legacy org.mitk.gui.qt.datamanager org.mitk.gui.qt.measurementtoolbox org.mitk.gui.qt.segmentation org.mitk.gui.qt.volumevisualization org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.imagenavigator org.mitk.gui.qt.moviemaker org.mitk.gui.qt.basicimageprocessing org.mitk.gui.qt.registration org.mitk.gui.qt.properties org.mitk.gui.qt.viewnavigator ) diff --git a/CMake/FindNumpy.cmake b/CMake/FindNumpy.cmake index 057833cc31..23f58bc0ae 100644 --- a/CMake/FindNumpy.cmake +++ b/CMake/FindNumpy.cmake @@ -1,32 +1,38 @@ # Variables set by this script # NUMPY_FOUND # NUMPY_INCLUDE_DIR find_package(PackageHandleStandardArgs) if(DEFINED Numpy_DIR AND EXISTS ${Numpy_DIR}) set(NUMPY_INCLUDE_DIR ${Numpy_DIR}/core/include) MESSAGE("NUMPY_DIR: " ${Numpy_DIR}) MESSAGE("NUMPY_INCLUDE_DIR: " ${NUMPY_INCLUDE_DIR}) MESSAGE("PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE}) else() + # search for the runtime if it's not already set + if( NOT DEFINED PYTHON_EXECUTABLE ) + FIND_PACKAGE(PythonLibs REQUIRED) + FIND_PACKAGE(PythonInterp REQUIRED) + endif() + set(_python ${PYTHON_EXECUTABLE}) if(UNIX) STRING(REPLACE " " "\ " _python ${PYTHON_EXECUTABLE}) endif() execute_process ( COMMAND ${_python} -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print numpy.distutils.misc_util.get_numpy_include_dirs()[0]" OUTPUT_VARIABLE output OUTPUT_STRIP_TRAILING_WHITESPACE ) if(DEFINED output AND EXISTS ${output} ) set (NUMPY_INCLUDE_DIR ${output}) endif() endif() FIND_PACKAGE_HANDLE_STANDARD_ARGS(Numpy DEFAULT_MSG NUMPY_INCLUDE_DIR) MARK_AS_ADVANCED ( NUMPY_INCLUDE_DIR ) diff --git a/CMake/MITKDashboardSetup.cmake b/CMake/MITKDashboardSetup.cmake index 60be23d0f7..9bd8dca8b8 100644 --- a/CMake/MITKDashboardSetup.cmake +++ b/CMake/MITKDashboardSetup.cmake @@ -1,154 +1,155 @@ # This file is intended to be included at the end of a custom MITKDashboardScript.TEMPLATE.cmake file list(APPEND CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") # # Automatically determined properties # set(MY_OPERATING_SYSTEM ) if(UNIX) # Download a utility script set(url "http://mitk.org/git/?p=MITK.git;a=blob_plain;f=CMake/mitkDetectOS.sh;hb=${hb}") set(dest "${CTEST_SCRIPT_DIRECTORY}/mitkDetectOS.sh") downloadFile("${url}" "${dest}") execute_process(COMMAND sh "${dest}" RESULT_VARIABLE _result OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT _result) set(MY_OPERATING_SYSTEM "${_out}") endif() endif() if(NOT MY_OPERATING_SYSTEM) set(MY_OPERATING_SYSTEM "${CMAKE_HOST_SYSTEM}") # Windows 7, Linux-2.6.32, Darwin... endif() site_name(CTEST_SITE) if(NOT DEFINED MITK_USE_QT) set(MITK_USE_QT 1) endif() if(MITK_USE_QT) if(NOT QT_QMAKE_EXECUTABLE) find_program(QT_QMAKE_EXECUTABLE NAMES qmake qmake-qt4 HINTS ${QT_BINARY_DIR}) endif() execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} --version OUTPUT_VARIABLE MY_QT_VERSION RESULT_VARIABLE qmake_error) if(qmake_error) message(FATAL_ERROR "Error when executing ${QT_QMAKE_EXECUTABLE} --version\n${qmake_error}") endif() string(REGEX REPLACE ".*Qt version ([0-9.]+) .*" "\\1" MY_QT_VERSION ${MY_QT_VERSION}) endif() # # Project specific properties # if(NOT CTEST_BUILD_NAME) if(MITK_USE_QT) set(CTEST_BUILD_NAME "${MY_OPERATING_SYSTEM} ${MY_COMPILER} Qt${MY_QT_VERSION} ${CTEST_BUILD_CONFIGURATION}") else() set(CTEST_BUILD_NAME "${MY_OPERATING_SYSTEM} ${MY_COMPILER} ${CTEST_BUILD_CONFIGURATION}") endif() set(CTEST_BUILD_NAME "${CTEST_BUILD_NAME}${CTEST_BUILD_NAME_SUFFIX}") endif() set(PROJECT_BUILD_DIR "MITK-build") set(CTEST_PATH "$ENV{PATH}") if(WIN32) set(ANN_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ANN-build/${CTEST_BUILD_CONFIGURATION}") set(CPPUNIT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/CppUnit-build/${CTEST_BUILD_CONFIGURATION}") set(GLUT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GLUT-build/${CTEST_BUILD_CONFIGURATION}") set(GLEW_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GLEW-build/${CTEST_BUILD_CONFIGURATION}") set(TINYXML_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/tinyxml-build/${CTEST_BUILD_CONFIGURATION}") set(QWT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Qwt-build/${CTEST_BUILD_CONFIGURATION}") set(VTK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/VTK-build/bin/${CTEST_BUILD_CONFIGURATION}") set(ACVD_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ACVD-build/bin/${CTEST_BUILD_CONFIGURATION}") set(ITK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ITK-build/bin/${CTEST_BUILD_CONFIGURATION}") set(BOOST_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Boost-install/lib") set(GDCM_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GDCM-build/bin/${CTEST_BUILD_CONFIGURATION}") set(DCMTK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/DCMTK-install/bin/${CTEST_BUILD_CONFIGURATION}") set(OPENCV_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/OpenCV-build/bin/${CTEST_BUILD_CONFIGURATION}") set(POCO_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Poco-install/bin") set(SOFA_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/SOFA-build/bin/${CTEST_BUILD_CONFIGURATION}") + set(REDLAND_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Redland-install/bin") set(BLUEBERRY_OSGI_DIR "${CTEST_BINARY_DIRECTORY}/MITK-build/bin/BlueBerry/org.blueberry.osgi/bin/${CTEST_BUILD_CONFIGURATION}") - set(CTEST_PATH "${CTEST_PATH};${CPPUNIT_BINARY_DIR};${QT_BINARY_DIR};${VTK_BINARY_DIR};${ANN_BINARY_DIR};${GLUT_BINARY_DIR};${GLEW_BINARY_DIR};${TINYXML_BINARY_DIR};${QWT_BINARY_DIR};${ACVD_BINARY_DIR};${ITK_BINARY_DIR};${BOOST_BINARY_DIR};${GDCM_BINARY_DIR};${DCMTK_BINARY_DIR};${OPENCV_BINARY_DIR};${POCO_BINARY_DIR};${SOFA_BINARY_DIR};${BLUEBERRY_OSGI_DIR}") + set(CTEST_PATH "${CTEST_PATH};${CPPUNIT_BINARY_DIR};${QT_BINARY_DIR};${VTK_BINARY_DIR};${ANN_BINARY_DIR};${GLUT_BINARY_DIR};${GLEW_BINARY_DIR};${TINYXML_BINARY_DIR};${QWT_BINARY_DIR};${ACVD_BINARY_DIR};${ITK_BINARY_DIR};${BOOST_BINARY_DIR};${GDCM_BINARY_DIR};${DCMTK_BINARY_DIR};${OPENCV_BINARY_DIR};${POCO_BINARY_DIR};${SOFA_BINARY_DIR};${REDLAND_BINARY_DIR};${BLUEBERRY_OSGI_DIR}") endif() set(ENV{PATH} "${CTEST_PATH}") set(SUPERBUILD_TARGETS "") # If the dashscript doesn't define a GIT_REPOSITORY variable, let's define it here. if(NOT DEFINED GIT_REPOSITORY OR GIT_REPOSITORY STREQUAL "") set(GIT_REPOSITORY "http://git.mitk.org/MITK.git") endif() # # Display build info # message("Site name: ${CTEST_SITE}") message("Build name: ${CTEST_BUILD_NAME}") message("Script Mode: ${SCRIPT_MODE}") message("Coverage: ${WITH_COVERAGE}, MemCheck: ${WITH_MEMCHECK}") # # Set initial cache options # if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") set(CTEST_USE_LAUNCHERS 1) set(ENV{CTEST_USE_LAUNCHERS_DEFAULT} 1) endif() # Remove this if block after all dartclients work if(DEFINED ADDITIONNAL_CMAKECACHE_OPTION) message(WARNING "Rename ADDITIONNAL to ADDITIONAL in your dartlclient script: ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") set(ADDITIONAL_CMAKECACHE_OPTION ${ADDITIONNAL_CMAKECACHE_OPTION}) endif() if(NOT DEFINED MITK_BUILD_CONFIGURATION) set(MITK_BUILD_CONFIGURATION "All") endif() if(NOT DEFINED MITK_VTK_DEBUG_LEAKS) set(MITK_VTK_DEBUG_LEAKS 1) endif() set(INITIAL_CMAKECACHE_OPTIONS " SUPERBUILD_EXCLUDE_MITKBUILD_TARGET:BOOL=TRUE MITK_BUILD_CONFIGURATION:STRING=${MITK_BUILD_CONFIGURATION} MITK_VTK_DEBUG_LEAKS:BOOL=${MITK_VTK_DEBUG_LEAKS} ${ADDITIONAL_CMAKECACHE_OPTION} ") if(MITK_USE_QT) set(INITIAL_CMAKECACHE_OPTIONS "${INITIAL_CMAKECACHE_OPTIONS} QT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}") endif() # Write a cache file for populating the MITK initial cache (not the superbuild cache). # This can be used to provide variables which are not passed through the # superbuild process to the MITK configure step) if(MITK_INITIAL_CACHE) set(mitk_cache_file "${CTEST_SCRIPT_DIRECTORY}/mitk_initial_cache.txt") file(WRITE "${mitk_cache_file}" "${MITK_INITIAL_CACHE}") set(INITIAL_CMAKECACHE_OPTIONS "${INITIAL_CMAKECACHE_OPTIONS} MITK_INITIAL_CACHE_FILE:INTERNAL=${mitk_cache_file} ") endif() # # Download and include dashboard driver script # set(url "http://mitk.org/git/?p=MITK.git;a=blob_plain;f=CMake/MITKDashboardDriverScript.cmake;hb=${hb}") set(dest ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}.driver) downloadFile("${url}" "${dest}") include(${dest}) diff --git a/CMakeExternals/MITKData.cmake b/CMakeExternals/MITKData.cmake index b4a09b193f..fc6fe88212 100644 --- a/CMakeExternals/MITKData.cmake +++ b/CMakeExternals/MITKData.cmake @@ -1,37 +1,37 @@ #----------------------------------------------------------------------------- # MITK Data #----------------------------------------------------------------------------- # Sanity checks if(DEFINED MITK_DATA_DIR AND NOT EXISTS ${MITK_DATA_DIR}) message(FATAL_ERROR "MITK_DATA_DIR variable is defined but corresponds to non-existing directory") endif() set(proj MITK-Data) set(proj_DEPENDENCIES) set(MITK-Data_DEPENDS ${proj}) if(BUILD_TESTING) - set(revision_tag f04939c6) # first 8 characters of hash-tag + set(revision_tag 7a7d873f) # first 8 characters of hash-tag # ^^^^^^^^ these are just to check correct length of hash part ExternalProject_Add(${proj} SOURCE_DIR ${proj} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/MITK-Data_${revision_tag}.tar.gz UPDATE_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS ${proj_DEPENDENCIES} ) set(MITK_DATA_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif(BUILD_TESTING) diff --git a/CMakeExternals/SimpleITK.cmake b/CMakeExternals/SimpleITK.cmake index 7211f88085..f93462a23a 100644 --- a/CMakeExternals/SimpleITK.cmake +++ b/CMakeExternals/SimpleITK.cmake @@ -1,126 +1,126 @@ #----------------------------------------------------------------------------- # SimpleITK #----------------------------------------------------------------------------- if(MITK_USE_SimpleITK) # Sanity checks if(DEFINED SimpleITK_DIR AND NOT EXISTS ${SimpleITK_DIR}) message(FATAL_ERROR "SimpleITK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj SimpleITK) set(proj_DEPENDENCIES ITK GDCM Swig) if(MITK_USE_OpenCV) list(APPEND proj_DEPENDENCIES OpenCV) endif() set(SimpleITK_DEPENDS ${proj}) if(NOT DEFINED SimpleITK_DIR) set(additional_cmake_args ) list(APPEND additional_cmake_args -DWRAP_CSHARP:BOOL=OFF -DWRAP_TCL:BOOL=OFF -DWRAP_LUA:BOOL=OFF -DWRAP_PYTHON:BOOL=OFF -DWRAP_JAVA:BOOL=OFF -DWRAP_RUBY:BOOL=OFF -DWRAP_R:BOOL=OFF ) if(MITK_USE_Python) list(APPEND additional_cmake_args -DWRAP_PYTHON:BOOL=ON -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} ) if(NOT MITK_USE_SYSTEM_PYTHON) list(APPEND proj_DEPENDENCIES Python) endif() endif() #TODO: Installer and testing works only with static libs on MAC set(_build_shared ON) if(APPLE) set(_build_shared OFF) endif() ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/SimpleITK-0.8.1.tar.gz URL_MD5 9126ab2eda9e88f598a962c02a705c43 PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/SimpleITK-0.8.1.patch CMAKE_ARGS ${ep_common_args} # -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=ON CMAKE_CACHE_ARGS ${additional_cmake_args} -DBUILD_SHARED_LIBS:BOOL=${_build_shared} -DSimpleITK_BUILD_DISTRIBUTE:BOOL=ON -DSimpleITK_PYTHON_THREADS:BOOL=ON -DUSE_SYSTEM_ITK:BOOL=ON -DBUILD_EXAMPLES:BOOL=OFF -DGDCM_DIR:PATH=${GDCM_DIR} -DITK_DIR:PATH=${ITK_DIR} -DSWIG_DIR:PATH=${SWIG_DIR} -DSWIG_EXECUTABLE:FILEPATH=${SWIG_EXECUTABLE} DEPENDS ${proj_DEPENDENCIES} ) set(SimpleITK_DIR ${ep_prefix}) - if( MITK_USE_Python ) + if( MITK_USE_Python AND NOT MITK_USE_SYSTEM_PYTHON ) # PythonDir needs to be fixed for the python interpreter by # changing dir delimiter for Windows set(_install_dir ${Python_DIR}) if(WIN32) STRING(REPLACE "/" "\\\\" _install_dir ${Python_DIR}) else() # escape spaces in the install path for linux STRING(REPLACE " " "\ " _install_dir ${Python_DIR}) endif() # Build python distribution with easy install. If a own runtime is used # embedd the egg into the site-package folder of the runtime if(NOT MITK_USE_SYSTEM_PYTHON) ExternalProject_Add_Step(${proj} sitk_python_install_step COMMAND ${PYTHON_EXECUTABLE} setup.py install --prefix=${_install_dir} DEPENDEES build WORKING_DIRECTORY /Wrapping/PythonPackage ) # Build egg into custom user base folder and deploy it later into installer # https://pythonhosted.org/setuptools/easy_install.html#use-the-user-option-and-customize-pythonuserbase else() set(_userbase_install /Wrapping/PythonPackage/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages) if(WIN32) set(_userbase_install /Wrapping/PythonPackage/Lib/site-packages) endif() ExternalProject_Add_Step(${proj} sitk_create_userbase_step COMMAND ${CMAKE_COMMAND} -E make_directory ${_userbase_install} DEPENDEES build WORKING_DIRECTORY ${SimpleITK_DIR}/Wrapping/PythonPackage ) ExternalProject_Add_Step(${proj} sitk_python_install_step COMMAND PYTHONUSERBASE=/Wrapping/PythonPackage ${PYTHON_EXECUTABLE} setup.py install --user DEPENDEES sitk_create_userbase_step WORKING_DIRECTORY /Wrapping/PythonPackage ) endif() endif() mitkFunctionInstallExternalCMakeProject(${proj}) # Still need to install the SimpleITK Python wrappings else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/raptor2.cmake b/CMakeExternals/raptor2.cmake index c146e593d0..9967b632a5 100644 --- a/CMakeExternals/raptor2.cmake +++ b/CMakeExternals/raptor2.cmake @@ -1,59 +1,60 @@ #----------------------------------------------------------------------------- # raptor2 #----------------------------------------------------------------------------- if(MITK_USE_raptor2) # Sanity checks if(DEFINED raptor2_DIR AND NOT EXISTS ${raptor2_DIR}) message(FATAL_ERROR "raptor2_DIR variable is defined but corresponds to non-existing directory") endif() set(proj raptor2) set(proj_DEPENDENCIES ) set(${proj}_DEPENDS ${proj}) if(NOT DEFINED raptor2_DIR) ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/raptor2-2.0.15.tar.gz URL_MD5 a39f6c07ddb20d7dd2ff1f95fa21e2cd PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/raptor2-2.0.15.patch CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DRAPTOR_ENABLE_TESTING:BOOL=OFF -DRAPTOR_PARSER_GRDDL:BOOL=OFF -DRAPTOR_PARSER_GUESS:BOOL=OFF -DRAPTOR_PARSER_JSON:BOOL=OFF -DRAPTOR_PARSER_NQUADS:BOOL=ON -DRAPTOR_PARSER_NTRIPLES:BOOL=ON -DRAPTOR_PARSER_RDFA:BOOL=OFF -DRAPTOR_PARSER_RDFXML:BOOL=OFF -DRAPTOR_PARSER_RSS:BOOL=OFF -DRAPTOR_PARSER_TRIG:BOOL=OFF -DRAPTOR_PARSER_TURTLE:BOOL=ON -DRAPTOR_SERIALIZER_ATOM:BOOL=OFF -DRAPTOR_SERIALIZER_DOT:BOOL=OFF -DRAPTOR_SERIALIZER_HTML:BOOL=OFF -DRAPTOR_SERIALIZER_JSON:BOOL=OFF -DRAPTOR_SERIALIZER_NQUADS:BOOL=ON -DRAPTOR_SERIALIZER_NTRIPLES:BOOL=ON -DRAPTOR_SERIALIZER_RDFXML:BOOL=OFF -DRAPTOR_SERIALIZER_RDFXML_ABBREV:BOOL=OFF -DRAPTOR_SERIALIZER_RSS_1_0:BOOL=OFF -DRAPTOR_SERIALIZER_TURTLE:BOOL=ON + -DCMAKE_INSTALL_NAME_DIR:STRING=${REDLAND_INSTALL_DIR}/lib DEPENDS ${proj_DEPENDENCIES} ) set(${proj}_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/rasqal.cmake b/CMakeExternals/rasqal.cmake index 2e1b39d87f..1613f0a87a 100644 --- a/CMakeExternals/rasqal.cmake +++ b/CMakeExternals/rasqal.cmake @@ -1,43 +1,44 @@ #----------------------------------------------------------------------------- # rasqal #----------------------------------------------------------------------------- if(MITK_USE_rasqal) # Sanity checks if(DEFINED rasqal_DIR AND NOT EXISTS ${rasqal_DIR}) message(FATAL_ERROR "rasqal_DIR variable is defined but corresponds to non-existing directory") endif() set(proj rasqal) set(proj_DEPENDENCIES ${raptor2_DEPENDS} ${PCRE_DEPENDS}) set(${proj}_DEPENDS ${proj}) if(NOT DEFINED rasqal_DIR) ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/rasqal-0.9.32.tar.gz URL_MD5 dc7c6107de00c47f85f6ab7db164a136 PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/rasqal-0.9.32.patch LIST_SEPARATOR ^^ CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} "-DCMAKE_C_FLAGS:STRING=-DPCRE_STATIC ${CMAKE_C_FLAGS}" -DRASQAL_REGEX:STRING=pcre -DCMAKE_PREFIX_PATH:STRING=${PCRE_DIR}^^${REDLAND_INSTALL_DIR} -DPCRE_INCLUDE_DIR:PATH=${PCRE_DIR}/include + -DCMAKE_INSTALL_NAME_DIR:STRING=${REDLAND_INSTALL_DIR}/lib DEPENDS ${proj_DEPENDENCIES} ) set(${proj}_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a1ba3bdf5..bc3234ee2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1103 +1,1105 @@ set(MITK_CMAKE_MINIMUM_REQUIRED_VERSION 3.1) cmake_minimum_required(VERSION ${MITK_CMAKE_MINIMUM_REQUIRED_VERSION}) #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # Superbuild Option - Enabled by default #----------------------------------------------------------------------------- option(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) endif() #----------------------------------------------------------------------------- # Check miminum compiler versions #----------------------------------------------------------------------------- if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # require at least gcc 4.6 as provided by Ubuntu 12.04 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) message(FATAL_ERROR "GCC version must be at least 4.6") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # require at least clang 3.2 for correct RTTI handling and C++11 support if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.2) message(FATAL_ERROR "Clang version must be at least 3.2") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") # require at least clang 5.0 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) message(FATAL_ERROR "Apple Clang version must be at least 5.0") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # require at least Visual Studio 2010 (msvc ...) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) message(FATAL_ERROR "Micorsoft Visual Studio 2010 or newer required (MSVC 16.0)") endif() else() message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang (Linux or Apple), GCC and MSVC.") endif() #----------------------------------------------------------------------------- # Warn if source or build path is too long #----------------------------------------------------------------------------- if(WIN32) set(_src_dir_length_max 50) set(_bin_dir_length_max 50) if(MITK_USE_SUPERBUILD) set(_src_dir_length_max 43) # _src_dir_length_max - strlen(ITK-src) set(_bin_dir_length_max 40) # _bin_dir_length_max - strlen(MITK-build) endif() string(LENGTH "${MITK_SOURCE_DIR}" _src_n) string(LENGTH "${MITK_BINARY_DIR}" _bin_n) # The warnings should be converted to errors if(_src_n GREATER _src_dir_length_max) message(WARNING "MITK source code directory path length is too long (${_src_n} > ${_src_dir_length_max})." "Please move the MITK source code directory to a directory with a shorter path." ) endif() if(_bin_n GREATER _bin_dir_length_max) message(WARNING "MITK build directory path length is too long (${_bin_n} > ${_bin_dir_length_max})." "Please move the MITK build directory to a directory with a shorter path." ) endif() endif() #----------------------------------------------------------------------------- # See http://cmake.org/cmake/help/cmake-2-8-docs.html#section_Policies for details #----------------------------------------------------------------------------- set(project_policies ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(MITK_CMAKE_DIR ${MITK_SOURCE_DIR}/CMake) set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR} ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionSuppressWarnings) include(mitkFunctionEnableBuildConfiguration) include(mitkFunctionWhitelists) include(FeatureSummary) include(CTestUseLaunchers) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- foreach(type LIBRARY RUNTIME ARCHIVE) # Make sure the directory exists if(DEFINED 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_USE_SUPERBUILD) set(output_dir ${MITK_BINARY_DIR}/bin) if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_BINARY_DIR}/MITK-build/bin) endif() else() if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(output_dir ${MITK_BINARY_DIR}/bin) else() set(output_dir ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) endif() endif() set(CMAKE_${type}_OUTPUT_DIRECTORY ${output_dir} CACHE INTERNAL "Single output directory for building all libraries.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Additional MITK Options (also shown during superbuild) #----------------------------------------------------------------------------- option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) macro(env_option name doc value) set(_value $ENV{${name}}) if("${_value}" STREQUAL "") set(_value ${value}) endif() option(${name} "${doc}" ${_value}) endmacro() # ----------------------------------------- # Qt version related variables set(DESIRED_QT_VERSION 4 CACHE STRING "Pick a version of Qt to use: 4 or 5") env_option(MITK_USE_QT "Use Nokia's Qt library" ON) set(MITK_DESIRED_QT_VERSION ${DESIRED_QT_VERSION}) if(MITK_USE_QT) # find the package at the very beginning, so that QT4_FOUND is available if(DESIRED_QT_VERSION MATCHES 4) set(MITK_QT4_MINIMUM_VERSION 4.7) find_package(Qt4 ${MITK_QT4_MINIMUM_VERSION} REQUIRED) set(MITK_USE_Qt4 TRUE) set(MITK_USE_Qt5 FALSE) endif() if(DESIRED_QT_VERSION MATCHES 5) set(MITK_QT5_MINIMUM_VERSION 5.0.0) set(MITK_USE_Qt4 FALSE) set(MITK_USE_Qt5 TRUE) set(QT5_INSTALL_PREFIX "" CACHE PATH "The install location of Qt5") set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT5_INSTALL_PREFIX}) find_package(Qt5Core ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5Concurrent ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5OpenGL ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5PrintSupport ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5Script ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5Sql ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5Svg ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5WebKit ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5WebKitWidgets ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5Widgets ${MITK_QT5_MINIMUM_VERSION} REQUIRED) find_package(Qt5Xml ${MITK_QT5_MINIMUM_VERSION} REQUIRED) + find_package(Qt5XmlPatterns ${MITK_QT5_MINIMUM_VERSION} REQUIRED) + find_package(Qt5UiTools ${MITK_QT5_MINIMUM_VERSION} REQUIRED) endif() else() set(MITK_USE_Qt4 FALSE) set(MITK_USE_Qt5 FALSE) endif() # ----------------------------------------- # MITK_USE_* build variables env_option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) set(MITK_BUILD_TUTORIAL OFF CACHE INTERNAL "Deprecated! Use MITK_BUILD_EXAMPLES instead!") env_option(MITK_BUILD_EXAMPLES "Build the MITK Examples" ${MITK_BUILD_TUTORIAL}) env_option(MITK_USE_ACVD "Use Approximated Centroidal Voronoi Diagrams" OFF) env_option(MITK_USE_ANN "Use Approximate Nearest Neighbor Library" ON) env_option(MITK_USE_CppUnit "Use CppUnit for unit tests" ON) 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() env_option(MITK_USE_Eigen "Use the Eigen library" ON) env_option(MITK_USE_GLEW "Use the GLEW library" ON) env_option(MITK_USE_Boost "Use the Boost C++ library" OFF) env_option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ON) env_option(MITK_USE_CTK "Use CTK in MITK" ON) env_option(MITK_USE_DCMTK "EXPERIMENTAL, superbuild only: Use DCMTK in MITK" ${MITK_USE_CTK}) env_option(MITK_USE_OpenCV "Use Intel's OpenCV library" OFF) env_option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF) env_option(MITK_USE_Poco "Use the Poco library" ON) env_option(MITK_USE_Redland "Use the Redland RDF library" OFF) env_option(MITK_USE_SOFA "Use Simulation Open Framework Architecture" OFF) env_option(MITK_USE_Python "Use Python wrapping in MITK" OFF) env_option(MITK_USE_SimpleITK "Use the SimpleITK library" OFF) set(MITK_USE_CableSwig ${MITK_USE_Python}) option(MITK_ENABLE_PIC_READER "Enable support for reading the DKFZ pic file format." ON) 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) mark_as_advanced(MITK_BUILD_ALL_APPS MITK_USE_CppUnit MITK_USE_GLEW MITK_USE_CTK MITK_USE_DCMTK MITK_ENABLE_PIC_READER MITK_BUILD_CONFIGURATION ) if(MITK_USE_Python) if(APPLE) message(WARNING "Python wrapping is unsuported on mac OSX!") set(MITK_USE_Python OFF CACHE BOOL "Use Python wrapping in MITK" FORCE) else() option(MITK_USE_SYSTEM_PYTHON "Use the system python runtime" OFF) # SimpleITK is required when python is enabled set(MITK_USE_SimpleITK ON CACHE BOOL "Use the SimpleITK library" FORCE) if(MITK_USE_SYSTEM_PYTHON) FIND_PACKAGE(PythonLibs REQUIRED) FIND_PACKAGE(PythonInterp REQUIRED) else() FIND_PACKAGE(PythonLibs) FIND_PACKAGE(PythonInterp) endif() endif() endif() if(MITK_USE_Boost) option(MITK_USE_SYSTEM_Boost "Use the system Boost" OFF) set(MITK_USE_Boost_LIBRARIES "" CACHE STRING "A semi-colon separated list of required Boost libraries") endif() if(MITK_USE_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() if(MITK_USE_CTK AND NOT MITK_USE_DCMTK) message("> Forcing MITK_USE_DCMTK to ON because of MITK_USE_CTK") set(MITK_USE_DCMTK ON CACHE BOOL "Use DCMTK in MITK" FORCE) endif() if(MITK_USE_SOFA) # SOFA requires at least CMake 2.8.8 set(SOFA_CMAKE_VERSION 2.8.8) if(${CMAKE_VERSION} VERSION_LESS ${SOFA_CMAKE_VERSION}) set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE) message(WARNING "Switched off MITK_USE_SOFA\n Minimum required CMake version: ${SOFA_CMAKE_VERSION}\n Installed CMake version: ${CMAKE_VERSION}") endif() # SOFA/ITK combination requires at least MSVC 2010 if(MSVC_VERSION AND MSVC_VERSION LESS 1600) set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE) message(WARNING "Switched off MITK_USE_SOFA\n MSVC versions less than 2010 are not supported.") endif() # SOFA requires boost library if(MITK_USE_SOFA AND NOT MITK_USE_Boost) message("Forcing MITK_USE_Boost to ON because of MITK_USE_SOFA") set(MITK_USE_Boost ON CACHE BOOL "" FORCE) endif() # SOFA requires boost system library list(FIND MITK_USE_Boost_LIBRARIES system _result) if(_result LESS 0) message("Adding 'system' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES system) endif() # SOFA requires boost thread library list(FIND MITK_USE_Boost_LIBRARIES thread _result) if(_result LESS 0) message("Adding 'thread' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES thread) endif() # Simulation plugin requires boost chrono library list(FIND MITK_USE_Boost_LIBRARIES chrono _result) if(_result LESS 0) message("Adding 'chrono' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES chrono) endif() set(MITK_USE_Boost_LIBRARIES ${MITK_USE_Boost_LIBRARIES} CACHE STRING "" FORCE) # Allow setting external SOFA plugins directory and SOFA plugins set(MITK_USE_SOFA_PLUGINS_DIR ${MITK_USE_SOFA_PLUGINS_DIR} CACHE PATH "External SOFA plugins directory" FORCE) set(MITK_USE_SOFA_PLUGINS ${MITK_USE_SOFA_PLUGINS} CACHE PATH "List of semicolon-separated plugin names" FORCE) endif() # Customize the default pixel types for multiplex macros set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") mark_as_advanced(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES MITK_ACCESSBYITK_DIMENSIONS ) # consistency checks if(NOT MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES) set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES) set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES) set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) string(REPLACE "," ";" _integral_types ${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES}) string(REPLACE "," ";" _floating_types ${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES}) foreach(_scalar_type ${_integral_types} ${_floating_types}) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}itk::VariableLengthVector<${_scalar_type}>,") endforeach() string(LENGTH "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" _length) math(EXPR _length "${_length} - 1") string(SUBSTRING "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" 0 ${_length} MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES ${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES} CACHE STRING "List of vector pixel types used in AccessByItk and InstantiateAccessFunction macros for itk::VectorImage types" FORCE) endif() if(NOT MITK_ACCESSBYITK_DIMENSIONS) set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") endif() #----------------------------------------------------------------------------- # Project.xml #----------------------------------------------------------------------------- # A list of topologically ordered targets set(CTEST_PROJECT_SUBPROJECTS) if(MITK_USE_BLUEBERRY) list(APPEND CTEST_PROJECT_SUBPROJECTS BlueBerry) endif() list(APPEND CTEST_PROJECT_SUBPROJECTS MITK-Core MITK-CoreUI MITK-IGT MITK-ToF MITK-DTI MITK-Registration MITK-Modules # all modules not contained in a specific subproject MITK-Plugins # all plugins not contained in a specific subproject MITK-Examples Unlabeled # special "subproject" catching all unlabeled targets and tests ) # Configure CTestConfigSubProject.cmake that could be used by CTest scripts configure_file(${MITK_SOURCE_DIR}/CTestConfigSubProject.cmake.in ${MITK_BINARY_DIR}/CTestConfigSubProject.cmake) if(CTEST_PROJECT_ADDITIONAL_TARGETS) # those targets will be executed at the end of the ctest driver script # and they also get their own subproject label set(subproject_list "${CTEST_PROJECT_SUBPROJECTS};${CTEST_PROJECT_ADDITIONAL_TARGETS}") else() set(subproject_list "${CTEST_PROJECT_SUBPROJECTS}") endif() # Generate Project.xml file expected by the CTest driver script mitkFunctionGenerateProjectXml(${MITK_BINARY_DIR} MITK "${subproject_list}" ${MITK_USE_SUPERBUILD}) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(MITK_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") # Print configuration summary message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL) return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(WriteBasicConfigVersionFile) include(CheckCXXSourceCompiles) include(GenerateExportHeader) include(CMakeParseArguments) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionGetGccVersion) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkFunctionOrganizeSources) include(mitkFunctionGetVersion) include(mitkFunctionGetVersionDescription) include(mitkFunctionCreateWindowsBatchScript) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionGetLibrarySearchPaths) include(mitkFunctionCompileSnippets) include(mitkFunctionUseModules) include(mitkFunctionCheckModuleDependencies) include(mitkFunctionCreateModule) include(mitkMacroCreateExecutable) include(mitkMacroCreateModuleTests) include(mitkFunctionAddCustomModuleTest) include(mitkMacroMultiplexPicType) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) include(mitkMacroGetPMDPlatformString) #----------------------------------------------------------------------------- # Set MITK specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- # ASK THE USER TO SHOW THE CONSOLE WINDOW FOR CoreApp and mitkWorkbench option(MITK_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting MITK GUI Applications" ON) mark_as_advanced(MITK_SHOW_CONSOLE_WINDOW) # TODO: check if necessary option(USE_ITKZLIB "Use the ITK zlib for pic compression." ON) mark_as_advanced(USE_ITKZLIB) if(NOT MITK_FAST_TESTING) if(DEFINED MITK_CTEST_SCRIPT_MODE AND (MITK_CTEST_SCRIPT_MODE STREQUAL "continuous" OR MITK_CTEST_SCRIPT_MODE STREQUAL "experimental") ) set(MITK_FAST_TESTING 1) endif() endif() #----------------------------------------------------------------------------- # Get MITK version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK) mitkFunctionGetVersionDescription(${MITK_SOURCE_DIR} MITK) #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- # on Mac OSX all BlueBerry plugins get copied into every # application bundle (.app directory) specified here if(MITK_USE_BLUEBERRY AND APPLE) include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) list(GET target_info_list 0 app_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} Mitk${app_name}) endif() endforeach() endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # MITK C/CXX Flags #----------------------------------------------------------------------------- set(MITK_CXX_STANDARD 11) # help keeping cross-platform compatibility # CMake 3.1 does not yet know how to handle AppleClang... # See http://public.kitware.com/Bug/view.php?id=15355 if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") set(CMAKE_CXX_EXTENSIONS 0) set(CMAKE_CXX_STANDARD ${MITK_CXX_STANDARD}) set(CMAKE_CXX_STANDARD_REQUIRED 1) endif() # Required and enabled C++11 features for all MITK code. # These are added as PUBLIC compile features to all MITK modules. set(MITK_CXX_FEATURES cxx_auto_type cxx_nullptr cxx_override) set(MITK_C_FLAGS "${COVERAGE_C_FLAGS}") set(MITK_C_FLAGS_DEBUG ) set(MITK_C_FLAGS_RELEASE ) set(MITK_CXX_FLAGS "${COVERAGE_CXX_FLAGS}") set(MITK_CXX_FLAGS_DEBUG ) set(MITK_CXX_FLAGS_RELEASE ) set(MITK_EXE_LINKER_FLAGS ) set(MITK_SHARED_LINKER_FLAGS ) mitkFunctionCheckCompilerFlags("-std=c++11" MITK_CXX_FLAGS) if(WIN32) set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} -D_WIN32_WINNT=0x0501 -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN -DNOMINMAX") mitkFunctionCheckCompilerFlags("/wd4005" MITK_CXX_FLAGS) # warning C4005: macro redefinition mitkFunctionCheckCompilerFlags("/wd4231" MITK_CXX_FLAGS) # warning C4231: nonstandard extension used : 'extern' before template explicit instantiation # the following line should be removed after fixing bug 17637 mitkFunctionCheckCompilerFlags("/wd4316" MITK_CXX_FLAGS) # warning C4316: object alignment on heap endif() if(NOT MSVC_VERSION) foreach(_flag -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -Wno-error=gnu -Wno-error=unknown-pragmas # The strict-overflow warning is generated by ITK template code -Wno-error=strict-overflow -Woverloaded-virtual -Wstrict-null-sentinel #-Wold-style-cast #-Wsign-promo # the following two lines should be removed after ITK-3097 has # been resolved, see also MITK bug 15279 -Wno-unused-local-typedefs -Wno-array-bounds -fdiagnostics-show-option ) mitkFunctionCheckCAndCXXCompilerFlags(${_flag} MITK_C_FLAGS MITK_CXX_FLAGS) endforeach() endif() if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" MITK_SHARED_LINKER_FLAGS) mitkFunctionCheckCompilerFlags("-Wl,--as-needed" MITK_SHARED_LINKER_FLAGS) endif() if(CMAKE_COMPILER_IS_GNUCXX) mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) # With older version of gcc supporting the flag -fstack-protector-all, an extra dependency to libssp.so # is introduced. If gcc is smaller than 4.4.0 and the build type is Release let's not include the flag. # Doing so should allow to build package made for distribution using older linux distro. if(${GCC_VERSION} VERSION_GREATER "4.4.0" OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ${GCC_VERSION} VERSION_LESS "4.4.0")) mitkFunctionCheckCAndCXXCompilerFlags("-fstack-protector-all" MITK_C_FLAGS MITK_CXX_FLAGS) endif() if(MINGW) # suppress warnings about auto imported symbols set(MITK_SHARED_LINKER_FLAGS "-Wl,--enable-auto-import ${MITK_SHARED_LINKER_FLAGS}") endif() set(MITK_CXX_FLAGS_RELEASE "-D_FORTIFY_SOURCE=2 ${MITK_CXX_FLAGS_RELEASE}") endif() set(MITK_MODULE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) set(MITK_EXE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) #----------------------------------------------------------------------------- # MITK Packages #----------------------------------------------------------------------------- set(MITK_MODULES_PACKAGE_DEPENDS_DIR ${MITK_SOURCE_DIR}/CMake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${MITK_MODULES_PACKAGE_DEPENDS_DIR}) find_package(GDCM PATHS ${GDCM_DIR} REQUIRED) if(MITK_USE_OpenCV) find_package(OpenCV PATHS ${OpenCV_DIR} REQUIRED) endif() if(MITK_USE_SOFA) # The SOFAConfig.cmake file does not provide exported targets or # libraries with absolute paths, hence we need to make the link # directories globally available until the SOFAConfig.cmake file # supports a proper mechanism for handling targets. # The same code is needed in MITKConfig.cmake. find_package(SOFA PATHS ${SOFA_DIR} CONFIG REQUIRED) link_directories(${SOFA_LIBRARY_DIRS}) endif() #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) option(MITK_ENABLE_RENDERING_TESTING OFF "Enable the MITK rendering tests. Requires x-server in Linux.") #Rendering testing does not work for Linux nightlies, thus it is disabled per default #and activated for Mac and Windows. if(WIN32 OR APPLE) set(MITK_ENABLE_RENDERING_TESTING ON) endif() mark_as_advanced( MITK_ENABLE_RENDERING_TESTING ) # Setup file for setting custom ctest vars configure_file( CMake/CTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) # Configuration for the CMake-generated test driver set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ") set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } catch( std::exception & excp ) { fprintf(stderr,\"%s\\n\",excp.what()); return EXIT_FAILURE; } catch( ... ) { printf(\"Exception caught in the test driver\\n\"); return EXIT_FAILURE; } ") set(MITK_TEST_OUTPUT_DIR "${MITK_BINARY_DIR}/test_output") if(NOT EXISTS ${MITK_TEST_OUTPUT_DIR}) file(MAKE_DIRECTORY ${MITK_TEST_OUTPUT_DIR}) endif() # Test the external project template if(MITK_USE_BLUEBERRY) include(mitkTestProjectTemplate) endif() # Test the package target include(mitkPackageTest) endif() configure_file(mitkTestingConfig.h.in ${MITK_BINARY_DIR}/mitkTestingConfig.h) #----------------------------------------------------------------------------- # MITK_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If MITK_SUPERBUILD_BINARY_DIR isn't defined, it means MITK is *NOT* build using Superbuild. # In that specific case, MITK_SUPERBUILD_BINARY_DIR should default to MITK_BINARY_DIR if(NOT DEFINED MITK_SUPERBUILD_BINARY_DIR) set(MITK_SUPERBUILD_BINARY_DIR ${MITK_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Set C/CXX and linker flags for MITK code #----------------------------------------------------------------------------- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MITK_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MITK_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MITK_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MITK_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MITK_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${MITK_C_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MITK_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MITK_SHARED_LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MITK_MODULE_LINKER_FLAGS}") #----------------------------------------------------------------------------- # Compile Utilities and set-up MITK variables #----------------------------------------------------------------------------- include(mitkSetupVariables) add_subdirectory(Utilities) if(MITK_USE_BLUEBERRY) # We need to hack a little bit because MITK applications may need # to enable certain BlueBerry plug-ins. However, these plug-ins # are validated separately from the MITK plug-ins and know nothing # about potential MITK plug-in dependencies of the applications. Hence # we cannot pass the MITK application list to the BlueBerry # ctkMacroSetupPlugins call but need to extract the BlueBerry dependencies # from the applications and set them explicitly. include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) # check if the application is enabled and if target_libraries.cmake exists if((${option_name} OR MITK_BUILD_ALL_APPS) AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") foreach(_target_dep ${target_libraries}) if(_target_dep MATCHES org_blueberry_) string(REPLACE _ . _app_bb_dep ${_target_dep}) # explicitly set the build option for the BlueBerry plug-in set(BLUEBERRY_BUILD_${_app_bb_dep} ON CACHE BOOL "Build the ${_app_bb_dep} plug-in") endif() endforeach() endif() endforeach() set(mbilog_DIR "${mbilog_BINARY_DIR}") if(MITK_BUILD_ALL_PLUGINS) set(BLUEBERRY_BUILD_ALL_PLUGINS ON) endif() set(BLUEBERRY_XPDOC_OUTPUT_DIR ${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html/) add_subdirectory(BlueBerry) set(BlueBerry_DIR ${CMAKE_CURRENT_BINARY_DIR}/BlueBerry CACHE PATH "The directory containing a CMake configuration file for BlueBerry" FORCE) include(mitkMacroCreateCTKPlugin) endif() #----------------------------------------------------------------------------- # Add custom targets representing CDash subprojects #----------------------------------------------------------------------------- foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) if(NOT TARGET ${subproject} AND NOT subproject MATCHES "Unlabeled") add_custom_target(${subproject}) endif() endforeach() #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- add_subdirectory(Modules) if(MITK_USE_BLUEBERRY) find_package(BlueBerry REQUIRED) set(MITK_DEFAULT_SUBPROJECTS MITK-Plugins) # Plug-in testing (needs some work to be enabled again) if(BUILD_TESTING) include(berryTestingHelpers) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp") if(TARGET CoreApp) get_target_property(_is_macosx_bundle CoreApp MACOSX_BUNDLE) if(APPLE AND _is_macosx_bundle) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp.app/Contents/MacOS/CoreApp") endif() endif() set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication") endif() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") mitkFunctionWhitelistPlugins(MITK MITK_EXT_PLUGINS) set(mitk_plugins_fullpath "") foreach(mitk_plugin ${MITK_EXT_PLUGINS}) list(APPEND mitk_plugins_fullpath Plugins/${mitk_plugin}) endforeach() if(EXISTS ${MITK_PRIVATE_MODULES}/PluginList.cmake) include(${MITK_PRIVATE_MODULES}/PluginList.cmake) foreach(mitk_plugin ${MITK_PRIVATE_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PRIVATE_MODULES}/${mitk_plugin}) endforeach() endif() if(MITK_BUILD_EXAMPLES) include("${CMAKE_CURRENT_SOURCE_DIR}/Examples/Plugins/PluginList.cmake") set(mitk_example_plugins_fullpath ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) list(APPEND mitk_example_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) list(APPEND mitk_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) endforeach() endif() # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_[a-zA-Z0-9_]+$") set(re_ctkplugin_bb "^org_blueberry_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk re_ctkplugin_bb OUTPUT_VARIABLE ${varname}) endmacro() # Get infos about application directories and build options include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") set(mitk_apps_fullpath ) foreach(mitk_app ${MITK_APPS}) string(FIND ${mitk_app} "MITK_BUILD_APP_" _index) string(SUBSTRING ${mitk_app} ${_index} -1 _var) if(${_var}) list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${mitk_app}") endif() endforeach() if (mitk_plugins_fullpath) ctkMacroSetupPlugins(${mitk_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ APPS ${mitk_apps_fullpath} BUILD_ALL ${MITK_BUILD_ALL_PLUGINS} COMPACT_OPTIONS) endif() set(MITK_PLUGIN_USE_FILE "${MITK_BINARY_DIR}/MitkPluginUseFile.cmake") if(${PROJECT_NAME}_PLUGIN_LIBRARIES) ctkFunctionGeneratePluginUseFile(${MITK_PLUGIN_USE_FILE}) else() file(REMOVE ${MITK_PLUGIN_USE_FILE}) set(MITK_PLUGIN_USE_FILE ) endif() endif() #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- add_subdirectory(Documentation) #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables # These are the default variables, which can be overwritten ( see below ) include(mitkSetupCPack) set(use_default_config ON) # MITK_APPS is set in Applications/AppList.cmake (included somewhere above # if MITK_USE_BLUEBERRY is set to ON). if(MITK_APPS) set(activated_apps_no 0) list(LENGTH MITK_APPS app_count) # Check how many apps have been enabled # If more than one app has been activated, the we use the # default CPack configuration. Otherwise that apps configuration # will be used, if present. foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) MATH(EXPR activated_apps_no "${activated_apps_no} + 1") endif() endforeach() if(app_count EQUAL 1 AND (activated_apps_no EQUAL 1 OR MITK_BUILD_ALL_APPS)) # Corner case if there is only one app in total set(use_project_cpack ON) elseif(activated_apps_no EQUAL 1 AND NOT MITK_BUILD_ALL_APPS) # Only one app is enabled (no "build all" flag set) set(use_project_cpack ON) else() # Less or more then one app is enabled set(use_project_cpack OFF) endif() foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) # check whether application specific configuration files will be used if(use_project_cpack) # use files if they exist if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") endif() if(EXISTS "${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in") set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/Applications/${target_dir}/CPackConfig.cmake") configure_file(${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in ${CPACK_PROJECT_CONFIG_FILE} @ONLY) set(use_default_config OFF) endif() endif() # add link to the list list(APPEND CPACK_CREATE_DESKTOP_LINKS "${target_dir}") endif() endforeach() endif() # if no application specific configuration file was used, use default if(use_default_config) configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in ${MITK_BINARY_DIR}/MITKCPackOptions.cmake @ONLY) set(CPACK_PROJECT_CONFIG_FILE "${MITK_BINARY_DIR}/MITKCPackOptions.cmake") endif() # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- 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() get_property(MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS_CONFIG GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) 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_file(mitkVersion.h.in ${MITK_BINARY_DIR}/mitkVersion.h) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) set(IPFUNC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipFunc) set(UTILITIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) configure_file(MITKConfig.cmake.in ${MITK_BINARY_DIR}/MITKConfig.cmake @ONLY) write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake VERSION ${MITK_VERSION_STRING} COMPATIBILITY AnyNewerVersion) # If we are under Windows, create two batch files which correctly # set up the environment for the application and for Visual Studio if(WIN32) include(mitkFunctionCreateWindowsBatchScript) set(VS_SOLUTION_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.sln") foreach(VS_BUILD_TYPE debug release) mitkFunctionCreateWindowsBatchScript("${MITK_SOURCE_DIR}/CMake/StartVS.bat.in" ${PROJECT_BINARY_DIR}/StartVS_${VS_BUILD_TYPE}.bat ${VS_BUILD_TYPE}) endforeach() endif(WIN32) #----------------------------------------------------------------------------- # MITK Applications #----------------------------------------------------------------------------- # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Applications) #----------------------------------------------------------------------------- # MITK Examples #----------------------------------------------------------------------------- if(MITK_BUILD_EXAMPLES) # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Examples) endif() #----------------------------------------------------------------------------- # Print configuration summary #----------------------------------------------------------------------------- message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL ) diff --git a/Documentation/Doxygen/3-DeveloperManual/Concepts/Exceptions.dox b/Documentation/Doxygen/3-DeveloperManual/Concepts/Exceptions.dox index c0de633c20..53e2c839eb 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Concepts/Exceptions.dox +++ b/Documentation/Doxygen/3-DeveloperManual/Concepts/Exceptions.dox @@ -1,90 +1,90 @@ /** \page ExceptionPage Error Handling and Exception Concept \tableofcontents \section ExceptionHandling General Exception Handling In MITK, errors during program execution are handled by the well known exception handling concept which is part of the C++ language. In case of unexpected exceptional behaviour or errors during program execution MITK classes throw exceptions. MITK exceptions are always objects of the class mitk::Exception or of one of its subclasses. \subsection Throw Throwing of exceptions Exceptions should always be thrown by using the predefined exception macros. If you want to throw a mitk::Exception in your code, simply use the following macro. \verbatim //This command will throw a mitk::Exception and add a message. //The macro will also add filename and line number to the exception //object. mitkThrow() << "Here comes your exception message"; \endverbatim You can also stream more complex messages, e.g. adding integers or other variables to your exception messages, like shown in the following example. \verbatim mitkThrow() << "This time we show the values of some variables:" << m_MyObject->GetSize() << m_MyInteger; \endverbatim \subsection Doc Documentation of exceptions If you throw exceptions in your code, please also document this in your doxygen comments by using the "@throws " tag. This will help users of your class to catch and handle the exceptions in a proper way. An example how to document exception throwing is given below. \verbatim class myExampleClass { /** Documentation * @brief This method does [...] * @throws mitk::Exception This exception is thrown, when the following error occures: [...] */ void MyExampleMethod() { //here comes your code //here happens an exception mitkThrow() << "An exception occured because [...], method can't continue."; } } \endverbatim In general, exceptions emit no logging messages by default because they are intended to be catched by overlying classes. This classes should then decide what to do, e.g. to log an error message or handle the exception in another way. See the logging documentation for more details on error logging. \subsection Catch Catching exceptions Exceptions should be caught by overlying classes, if they can handle them in a proper way. Catching exceptions is very simple, use the standard try-catch block to do so. An example is given below. \verbatim try { //call of a method which may throw an exception myObject->MyExampleMethod(); } -catch (mitk::Exception e) +catch (const mitk::Exception& e) { //This code is executed if an exception of the given type was thrown above. //For example log an error message here or do some other proper handling of the exception. } \endverbatim Please do not use "catch (...)" because normally your class can't garantee to handle all exceptions in a proper way without differentiating them. \section SpecializedExceptionHandling Defining and Using more Specialized Exceptions The basic MITK exception concept was kept very simple and should suffice in many cases. But you can also use more specialized exceptions, if needed. Nevertheless all MITK exceptions should be subclasses of mitk::exception. You can define your own exception classes by simply implementing new classes which derive from mitk::exception. Thus, you can catch your exception seperately when needed. The mitkExceptionClassMacro helps to keep implementing new exception classes as simple as possible, like shown in the following code example. \verbatim #include class mitk::MySpecializedException : public mitk::Exception { public: mitkExceptionClassMacro(mitk::MySpecializedException,mitk::Exception); }; \endverbatim To throw your specialized exception you should use the corresponing macro, which is shown in the next code snippet. \verbatim mitkThrowException(mitk::MySpecializedException) << "this is error info"; \endverbatim -*/ \ No newline at end of file +*/ diff --git a/Documentation/Doxygen/3-DeveloperManual/Concepts/MitkImage.dox b/Documentation/Doxygen/3-DeveloperManual/Concepts/MitkImage.dox index c473f9cc1b..70b5f280a6 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Concepts/MitkImage.dox +++ b/Documentation/Doxygen/3-DeveloperManual/Concepts/MitkImage.dox @@ -1,196 +1,199 @@ /** \page MitkImagePage MITK Image \tableofcontents \section MitkImagePage_Introduction Introduction to MITK Image The MITK Image obviously is a very central class to MITK and one of those you are most likely to work with. This section will get you up and running with the basics. Consider this document a prerequisite for the Pipelining Introduction and the \ref GeometryOverviewPage. \imageMacro{mitkimagehierarchy.png,"",16} Image is a direct descendant of SlicedData which itself inherits from BaseData. In MITK, BaseData is the common DataType from which all other Datatypes stem. SlicedData specifies this class to contain image slices, a typical example being a CT scan, and introduces properties and methods necessary to give the data a well defined geometry. Image further specializes the concept to allow for multiple channels, volumes and slices as well as additional information like image properties. For the sake of this introduction, we will have a look at three different aspects: 1. SlicedData and Geometry 2. ImageData 3. Image Properties \subsection MitkImagePage_SlicedData SlicedData and Geometry The mother class of Image introduces a fundamental aspect: Image geometry. It defines the image's spatial context: Dimension and orientation. A more in depth introduction is given here: \ref GeometryOverviewPage \subsection MitkImagePage_ImageData ImageData Objects of the class Image store the actual image data. It is important to discern four different concepts: 1. Channels, which can be of a specific data type e.g. an intensity image or a vector field. Each channel consists of one or more... 2. Volumes, which contain data of a certain type. A volume is represented by ImageDataItems that define volume properties. Inside of a channel, each volume must be of the same type (float, int, etc.). Each volume consists of several... 3. Slices, which each contain a two-dimensional image slice. There is also the pointer m_CompleteData that references all of the data (i.e. all volumes) as a singular array. This member is helpful, when one wants to copy image data from one image to another. \imageMacro{mitkimagememory.png,"",16} \subsection MitkImagePage_Properties Image Properties Lastly, we'll talk about properties. Properties are a set of additional information mainly used to save DICOM information. The functionality is introduced very early in the image's lineage, in BaseData. The system works quite similar to a hashmap by using property keys and properties. For further reference, see BaseData::GetProperty() or, for a simple example implementation, USImage::GetMetadata(). \section MitkImagePage_AccessImageData Access image data Since many modules and plugins in MITK work with the same images, it can be difficult to comprehend and control all ongoing image accesses. Thus, we decided to introduce the concept of image accessors. They are responsible for organisation of image access and for keeping data consistent. Every Image manages its image accessors and thus is responsible for them. In the following subsections, image accessors are explained and their use is depicted. Code examples are added to make understanding easier. \subsection MitkImagePage_ImageAccessors Image accessors -Image accessors provide an image access, which is +Image accessors provide an image access, which is -# controlled and surveilled: at all time it is known how many instances have access to a specific image part. -# consistent and thread-safe: a lock-mechanism allows a concurrent read access on image parts and guarantees a consistent data state during access. -# restricted to an image part: it is possible to restrict access to a specific image part (e.g. volume or slice), which is represented in an ImageDataItem. -# simple and comfortable through pixel index: get- and set-methods are provided to access pixel values easily (see next section). The existing instantiable image accessor classes are: mitk::ImageReadAccessor, mitk::ImageWriteAccessor and mitk::ImageVtkAccessor. They all inherit from mitk::ImageAccessorBase, which mainly contains the lock functionality and a representation of the specified image area. The classes mitk::ImageReadAccessor and mitk::ImageWriteAccessor provide access to an mitk::Image or mitk::ImageDataItem and supply a (const) void* pointer, while mitk::ImageVtkAccessor supports Vtk image access in a legacy mode (you should not instantiate it). \imageMacro{mitkimageaccessorhierarchy.png,"",16} \subsection MitkImagePage_HowToGetAccess How to get access Although the concept of image accessors is extensive, the use of image accessors is simple. Requesting an image access consists only of creating an instance of an image accessor. The constructor of an image accessor requires a pointer to the mitk::Image class and optionally an image part (e.g. mitk::ImageDataItem), which restricts the access of an image accessor to a specific image sector (e.g. Volume, Slice). Since the constructor can throw a mitk::Exception, it is necessary to order an image accessor within a try block. Possible exceptions are invalid images, wrong dimensions, etc. which cannot be accepted. If only a pointer to image data is needed, following code example shows how to get a const or non-const pointer. mitk::ImageReadAccessor only provides a const void* pointer while mitk::ImageWriteAccessor provides a void* pointer to image data. \verbatim // we assume you already have an mitk::Image::Pointer image try { mitk::ImageReadAccessor readAccess(image, image->GetVolumeData(0)); const void* cPointer = readAccess.GetData(); mitk::ImageWriteAccessor writeAccess(image); void* vPointer = writeAccess.GetData(); } catch(mitk::Exception& e) { // deal with the situation not to have access } \endverbatim +Please note that an explicit call of Modified() method is needed after the write access is done. +The accessor makes no such call on default. + A more convenient way to access image data is provided by the classes mitk::ImagePixelReadAccessor and mitk::ImagePixelWriteAccessor. They are equipped with set- and get-methods, which allow an index-based access. Both classes are templated and need to know about pixel type and image dimension at compile time. That means, both parameters need to be defined with arrow brackets when calling the constructor. \verbatim // we assume you already have an mitk::Image::Pointer image try { itk::Index<2> idx = {{ 12, 34 }}; mitk::ImagePixelReadAccessor readAccess(image, image->GetSliceData(2)); short value = readAccess.GetPixelByIndex(idx); mitk::ImagePixelWriteAccessor writeAccess(image, image->GetSliceData(4)); writeAccess.SetPixelByIndex(idx, 42); } catch(mitk::Exception& e) { // deal with the situation not to have access } \endverbatim \subsection MitkImagePage_AdditionalProperties Additional properties It is possible to commit options to the constructor affecting the behavior of an image accessor. Properties have to be specified using enum flags (e.g. mitk::ImageAccessorBase::ExceptionIfLocked) and can be unified by bitwise operations. The flag ExceptionIfLocked causes an exception if the requested image part is locked. Usually the requesting image accessor waits for the locking image accessor. \verbatim try { mitk::ImageReadAccessor imageAccess(image, image->GetSliceData(2), mitk::ImageAccessorBase::ExceptionIfLocked); const void* pointer = imageAccess.GetData(); } catch(mitk::MemoryIsLockedException& e) { // do something else } catch(mitk::Exception& e) { // deal with the situation not to have access } \endverbatim \section MitkImagePage_WorkingWith Working with MITK Image \subsection MitkImagePage_Cloning Cloning a MITK Image In order to clone an image, you can simply call the inherited method Clone(). It returns an itk::SmartPointer and works also with const image pointers. \verbatim mitk::Image::Pointer testMethod(const mitk::Image* image) { mitk::Image::Pointer nIm = image->Clone(); return nIm; } \endverbatim Cloning can also be done manually by copying the Geometry, the visual Data and further properties separately. The simplest way to achieve this is to first call Image::Initialize(const Image * image). This will copy the geometry information, but not the data or the properties. Afterwards, copy the image's data (e.g. with SetVolume) and, if necessary, it's properties with SetPropertyList(image->GetPropertyList()). \subsection MitkImagePage_Inheriting Inheriting from MITK Image In general, one should try to avoid inheriting from mitk Image. The simple reason for this is that your derived class will not cleanly work together with the Filters already implemented (See the chapter on Pipelining for Details). If however, mitk Image does not offer the functionality you require it is possible to do so. See the documentation for various examples of classes that inherit from image. */ diff --git a/Documentation/Doxygen/3-DeveloperManual/Concepts/images/pipelining/pipelining_example_ct.png b/Documentation/Doxygen/3-DeveloperManual/Concepts/images/pipelining/pipelining_example_ct.png index 1583a91853..7ff9191aed 100644 Binary files a/Documentation/Doxygen/3-DeveloperManual/Concepts/images/pipelining/pipelining_example_ct.png and b/Documentation/Doxygen/3-DeveloperManual/Concepts/images/pipelining/pipelining_example_ct.png differ diff --git a/Documentation/Doxygen/3-DeveloperManual/Concepts/images/pipelining/pipelining_hierarchy.png b/Documentation/Doxygen/3-DeveloperManual/Concepts/images/pipelining/pipelining_hierarchy.png index 29bc456cac..d31ad4f0b0 100644 Binary files a/Documentation/Doxygen/3-DeveloperManual/Concepts/images/pipelining/pipelining_hierarchy.png and b/Documentation/Doxygen/3-DeveloperManual/Concepts/images/pipelining/pipelining_hierarchy.png differ diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/GettingToKnow/Tutorial/step10_result.png b/Documentation/Doxygen/3-DeveloperManual/Starting/GettingToKnow/Tutorial/step10_result.png index 45686bf47e..837639fa8d 100644 Binary files a/Documentation/Doxygen/3-DeveloperManual/Starting/GettingToKnow/Tutorial/step10_result.png and b/Documentation/Doxygen/3-DeveloperManual/Starting/GettingToKnow/Tutorial/step10_result.png differ diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/ColorImageProcessing.png b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/ColorImageProcessing.png index fff2c940f5..b67adeed3e 100644 Binary files a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/ColorImageProcessing.png and b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/ColorImageProcessing.png differ diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/IsoSurfaceGUI.png b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/IsoSurfaceGUI.png index 1900424cbf..65f60bc382 100644 Binary files a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/IsoSurfaceGUI.png and b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/IsoSurfaceGUI.png differ diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/IsoSurfaceIcon.png b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/IsoSurfaceIcon.png index e7b435e83e..5afe288507 100644 Binary files a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/IsoSurfaceIcon.png and b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/IsoSurfaceIcon.png differ diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/SimpleExample.png b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/SimpleExample.png index 4ec2319e68..2636968563 100644 Binary files a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/SimpleExample.png and b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/SimpleExample.png differ diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/SimpleMeasurementIcon.png b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/SimpleMeasurementIcon.png index d2f09ad0d6..e3567b8a8b 100644 Binary files a/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/SimpleMeasurementIcon.png and b/Examples/Plugins/org.mitk.example.gui.imaging/documentation/UserManual/SimpleMeasurementIcon.png differ diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/resources/ColorImageProcessing.png b/Examples/Plugins/org.mitk.example.gui.imaging/resources/ColorImageProcessing.png index fff2c940f5..b67adeed3e 100644 Binary files a/Examples/Plugins/org.mitk.example.gui.imaging/resources/ColorImageProcessing.png and b/Examples/Plugins/org.mitk.example.gui.imaging/resources/ColorImageProcessing.png differ diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/resources/SimpleExample.png b/Examples/Plugins/org.mitk.example.gui.imaging/resources/SimpleExample.png index 4ec2319e68..2636968563 100644 Binary files a/Examples/Plugins/org.mitk.example.gui.imaging/resources/SimpleExample.png and b/Examples/Plugins/org.mitk.example.gui.imaging/resources/SimpleExample.png differ diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/resources/SimpleMeasurement.png b/Examples/Plugins/org.mitk.example.gui.imaging/resources/SimpleMeasurement.png index 99977926fc..7b6a284a24 100644 Binary files a/Examples/Plugins/org.mitk.example.gui.imaging/resources/SimpleMeasurement.png and b/Examples/Plugins/org.mitk.example.gui.imaging/resources/SimpleMeasurement.png differ diff --git a/Modules/AlgorithmsExt/Testing/files.cmake b/Modules/AlgorithmsExt/Testing/files.cmake index fc97d9b4a9..06daaeba52 100644 --- a/Modules/AlgorithmsExt/Testing/files.cmake +++ b/Modules/AlgorithmsExt/Testing/files.cmake @@ -1,13 +1,15 @@ set(MODULE_TESTS mitkAutoCropImageFilterTest.cpp mitkBoundingObjectCutterTest.cpp mitkImageToUnstructuredGridFilterTest.cpp + mitkPlaneFitTest.cpp mitkSimpleHistogramTest.cpp mitkCovarianceMatrixCalculatorTest.cpp mitkAnisotropicIterativeClosestPointRegistrationTest.cpp + mitkUnstructuredGridClusteringFilterTest.cpp mitkUnstructuredGridToUnstructuredGridFilterTest.cpp ) set(MODULE_CUSTOM_TESTS mitkLabeledImageToSurfaceFilterTest.cpp ) diff --git a/Modules/AlgorithmsExt/Testing/mitkPlaneFitTest.cpp b/Modules/AlgorithmsExt/Testing/mitkPlaneFitTest.cpp new file mode 100644 index 0000000000..abdd13d4bb --- /dev/null +++ b/Modules/AlgorithmsExt/Testing/mitkPlaneFitTest.cpp @@ -0,0 +1,97 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include +#include +#include +#include + +int mitkPlaneFitTest(int, char*[] ) +{ + //float bounds[]={0.0f,10.0f,0.0f,10.0f,0.0f,5.0f}; + + mitk::PlaneFit::Pointer PlaneFit = mitk::PlaneFit::New(); + mitk::PointSet::Pointer PointSet = mitk::PointSet::New(); + + mitk::Point3D Point; + + //first without any point, then incrementally add points within thre points there will be a plane geometry + std::cout <<"Start PlaneFitTest "<GetPointSet()->GetPoints()->InsertElement(position, Point); + } + + //Set Input + PlaneFit->SetInput(PointSet); + + const mitk::PointSet* testPointSet = PlaneFit->GetInput(); + std::cout<<" Size test of Input Method: "; + if( testPointSet->GetSize() == PointSet->GetSize() ) + { + std::cout<<"[PASSED]"<Update(); + const mitk::Point3D ¢roid = PlaneFit->GetCentroid(); + mitk::Point3D expectedCentroid; + expectedCentroid[0]=2.5; + expectedCentroid[1]=3.75; + expectedCentroid[2]=2.5; + + if ( centroid == expectedCentroid ) + { + std::cout<<"[PASSED]"<( PlaneFit->GetOutput()->GetGeometry()); + if( PlaneGeometry ) + { + std::cout<<"[PASSED]"< +#include +#include +#include + +#include + +#include +#include +#include +#include + +class mitkUnstructuredGridClusteringFilterTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkUnstructuredGridClusteringFilterTestSuite); + + vtkDebugLeaks::SetExitError(0); + + MITK_TEST(testUnstructuredGridClusteringFilterInitialization); + MITK_TEST(testInput); + MITK_TEST(testUnstructuredGridGeneration); + MITK_TEST(testReturnedCluster); + MITK_TEST(testClusterVector); + MITK_TEST(testGetNumberOfFoundClusters); + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::UnstructuredGrid::Pointer m_UnstructuredGrid; + +public: + + void setUp() + { + m_UnstructuredGrid = mitk::UnstructuredGrid::New(); + + //Loading the test data + std::vector< mitk::BaseData::Pointer > vector = mitk::IOUtil::Load(GetTestDataFilePath("UnstructuredGrid/scoredGrid.vtu")); + mitk::BaseData::Pointer base = vector.at(0); + m_UnstructuredGrid = dynamic_cast(base.GetPointer()); + } + + void testUnstructuredGridClusteringFilterInitialization() + { + mitk::UnstructuredGridClusteringFilter::Pointer clusterFilter = mitk::UnstructuredGridClusteringFilter::New(); + CPPUNIT_ASSERT_MESSAGE("Testing instantiation of filter object", clusterFilter.IsNotNull()); + } + + void testInput() + { + mitk::UnstructuredGridClusteringFilter::Pointer clusterFilter = mitk::UnstructuredGridClusteringFilter::New(); + clusterFilter->SetInput(m_UnstructuredGrid); + CPPUNIT_ASSERT_MESSAGE("Testing set / get input!", clusterFilter->GetInput() == m_UnstructuredGrid); + } + + void testUnstructuredGridGeneration() + { + mitk::UnstructuredGridClusteringFilter::Pointer clusterFilter = mitk::UnstructuredGridClusteringFilter::New(); + clusterFilter->SetInput(m_UnstructuredGrid); + clusterFilter->SetMeshing(false); + clusterFilter->SetMinPts(4); + clusterFilter->Seteps(1.2); + clusterFilter->Update(); + CPPUNIT_ASSERT_MESSAGE("Testing output generation!", clusterFilter->GetOutput() != NULL); + } + + void testReturnedCluster() + { + mitk::UnstructuredGridClusteringFilter::Pointer clusterFilter = mitk::UnstructuredGridClusteringFilter::New(); + clusterFilter->SetInput(m_UnstructuredGrid); + clusterFilter->SetMeshing(false); + clusterFilter->SetMinPts(4); + clusterFilter->Seteps(1.2); + clusterFilter->Update(); + mitk::UnstructuredGrid::Pointer cluster = clusterFilter->GetOutput(); + CPPUNIT_ASSERT_MESSAGE("Testing the output cluster!", cluster->GetVtkUnstructuredGrid()->GetPoints()->GetNumberOfPoints() == 620); + } + + void testClusterVector() + { + mitk::UnstructuredGridClusteringFilter::Pointer clusterFilter = mitk::UnstructuredGridClusteringFilter::New(); + clusterFilter->SetInput(m_UnstructuredGrid); + clusterFilter->SetMeshing(false); + clusterFilter->SetMinPts(4); + clusterFilter->Seteps(1.2); + clusterFilter->Update(); + std::vector< mitk::UnstructuredGrid::Pointer > clustervector = clusterFilter->GetAllClusters(); + //test that all clusters have points: + bool havePoints = true; + for(unsigned int i=0; iGetVtkUnstructuredGrid()->GetPoints()->GetNumberOfPoints()<1) + havePoints = false; + } + CPPUNIT_ASSERT_MESSAGE("Testing number of found clusters!", havePoints && clustervector.size() == 17); + } + + void testGetNumberOfFoundClusters() + { + mitk::UnstructuredGridClusteringFilter::Pointer clusterFilter = mitk::UnstructuredGridClusteringFilter::New(); + clusterFilter->SetInput(m_UnstructuredGrid); + clusterFilter->SetMeshing(false); + clusterFilter->SetMinPts(4); + clusterFilter->Seteps(1.2); + clusterFilter->Update(); + CPPUNIT_ASSERT_MESSAGE("Testing number of found clusters!", clusterFilter->GetNumberOfFoundClusters() == 17); + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkUnstructuredGridClusteringFilter) diff --git a/Modules/AlgorithmsExt/files.cmake b/Modules/AlgorithmsExt/files.cmake index 7df78a43aa..72ee58aa5c 100644 --- a/Modules/AlgorithmsExt/files.cmake +++ b/Modules/AlgorithmsExt/files.cmake @@ -1,29 +1,33 @@ set(CPP_FILES mitkAutoCropImageFilter.cpp mitkBoundingObjectCutter.cpp mitkBoundingObjectToSegmentationFilter.cpp mitkGeometryClipImageFilter.cpp + mitkGeometryDataSource.cpp mitkHeightFieldSurfaceClipImageFilter.cpp mitkImageToUnstructuredGridFilter.cpp mitkLabeledImageToSurfaceFilter.cpp mitkMaskAndCutRoiImageFilter.cpp mitkMaskImageFilter.cpp mitkMovieGenerator.cpp mitkNonBlockingAlgorithm.cpp mitkPadImageFilter.cpp + mitkPlaneFit.cpp mitkPlaneLandmarkProjector.cpp mitkPointLocator.cpp + mitkSegmentationSink.cpp mitkSimpleHistogram.cpp mitkSimpleUnstructuredGridHistogram.cpp mitkCovarianceMatrixCalculator.cpp mitkAnisotropicIterativeClosestPointRegistration.cpp mitkWeightedPointTransform.cpp mitkAnisotropicRegistrationCommon.cpp + mitkUnstructuredGridClusteringFilter.cpp mitkUnstructuredGridToUnstructuredGridFilter.cpp ) if(WIN32 AND NOT MINGW) list(APPEND CPP_FILES mitkMovieGeneratorWin32.cpp ) endif() diff --git a/Modules/AlgorithmsExt/mitkGeometryDataSource.cpp b/Modules/AlgorithmsExt/mitkGeometryDataSource.cpp new file mode 100644 index 0000000000..f4fc140e50 --- /dev/null +++ b/Modules/AlgorithmsExt/mitkGeometryDataSource.cpp @@ -0,0 +1,48 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkGeometryDataSource.h" +#include "mitkGeometryData.h" + +mitk::GeometryDataSource::GeometryDataSource() +{ + // Create the output. + itk::DataObject::Pointer output = this->MakeOutput(0); + Superclass::SetNumberOfRequiredOutputs(1); + Superclass::SetNthOutput(0, output); +} + +mitk::GeometryDataSource::~GeometryDataSource() +{ +} + +itk::DataObject::Pointer mitk::GeometryDataSource::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) +{ + return OutputType::New().GetPointer(); +} + +itk::DataObject::Pointer mitk::GeometryDataSource::MakeOutput( const DataObjectIdentifierType & name ) +{ + itkDebugMacro("MakeOutput(" << name << ")"); + if( this->IsIndexedOutputName(name) ) + { + return this->MakeOutput( this->MakeIndexFromOutputName(name) ); + } + return OutputType::New().GetPointer(); +} + +mitkBaseDataSourceGetOutputDefinitions(mitk::GeometryDataSource) diff --git a/Modules/AlgorithmsExt/mitkGeometryDataSource.h b/Modules/AlgorithmsExt/mitkGeometryDataSource.h new file mode 100644 index 0000000000..80c8dc77b0 --- /dev/null +++ b/Modules/AlgorithmsExt/mitkGeometryDataSource.h @@ -0,0 +1,76 @@ +/*=================================================================== + +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 MITKGEOMETRYDATASOURCE_H_HEADER_INCLUDED_C10B4740 +#define MITKGEOMETRYDATASOURCE_H_HEADER_INCLUDED_C10B4740 + +#include "mitkBaseDataSource.h" +#include "MitkAlgorithmsExtExports.h" + +namespace mitk { + +class GeometryData; + +/** + * @brief Superclass of all classes generating GeometryData (instances of class + * GeometryData) as output. + * + * In itk and vtk the generated result of a ProcessObject is only guaranteed + * to be up-to-date, when Update() of the ProcessObject or the generated + * DataObject is called immediately before access of the data stored in the + * DataObject. This is also true for subclasses of mitk::BaseProcess and thus + * for mitk::GeometryDataSource. + * @ingroup Process + */ +class MITKALGORITHMSEXT_EXPORT GeometryDataSource : public BaseDataSource +{ +public: + + mitkClassMacro(GeometryDataSource, BaseDataSource) + itkNewMacro(Self) + + typedef mitk::GeometryData OutputType; + + mitkBaseDataSourceGetOutputDeclarations + + /** + * Allocates a new output object and returns it. Currently the + * index idx is not evaluated. + * @param idx the index of the output for which an object should be created + * @returns the new object + */ + virtual itk::DataObject::Pointer MakeOutput ( DataObjectPointerArraySizeType idx ); + + /** + * This is a default implementation to make sure we have something. + * Once all the subclasses of ProcessObject provide an appopriate + * MakeOutput(), then ProcessObject::MakeOutput() can be made pure + * virtual. + */ + virtual itk::DataObject::Pointer MakeOutput(const DataObjectIdentifierType &name); + +protected: + + GeometryDataSource(); + virtual ~GeometryDataSource(); +}; + +} // namespace mitk + + + +#endif /* MITKGEOMETRYDATASOURCE_H_HEADER_INCLUDED_C10B4740 */ diff --git a/Modules/AlgorithmsExt/mitkPlaneFit.cpp b/Modules/AlgorithmsExt/mitkPlaneFit.cpp new file mode 100644 index 0000000000..cba794f3e0 --- /dev/null +++ b/Modules/AlgorithmsExt/mitkPlaneFit.cpp @@ -0,0 +1,205 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkPlaneFit.h" + +#include "mitkPlaneGeometry.h" +#include "mitkGeometryData.h" +#include + +#include +#include + + +mitk::PlaneFit::PlaneFit() +: m_PointSet( NULL ) +{ + m_TimeGeometry = mitk::ProportionalTimeGeometry::New(); +} + +mitk::PlaneFit::~PlaneFit() +{ +} + + +void mitk::PlaneFit::GenerateOutputInformation() +{ + mitk::PointSet::ConstPointer input = this->GetInput(); + mitk::GeometryData::Pointer output = this->GetOutput(); + + itkDebugMacro(<<"GenerateOutputInformation()"); + + if (input.IsNull()) return; + + if ( m_PointSet == NULL ) + { + return; + } + + bool update = false; + if ( output->GetGeometry() == NULL || output->GetTimeGeometry() == NULL ) + update = true; + if ( ( ! update ) && ( output->GetTimeGeometry()->CountTimeSteps() != input->GetTimeGeometry()->CountTimeSteps() ) ) + update = true; + if ( update ) + { + mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New(); + + ProportionalTimeGeometry::Pointer timeGeometry = dynamic_cast(m_TimeGeometry.GetPointer()); + timeGeometry->Initialize(planeGeometry, m_PointSet->GetPointSetSeriesSize()); + //m_TimeGeometry->InitializeEvenlyTimed( + // planeGeometry, m_PointSet->GetPointSetSeriesSize() ); + + TimeStepType timeStep; + for ( timeStep = 0; + (timeStep < m_PointSet->GetPointSetSeriesSize()) + && (timeStep < m_Planes.size()); + ++timeStep ) + { + timeGeometry->SetTimeStepGeometry( m_Planes[timeStep], timeStep ); + } + + output->SetTimeGeometry( m_TimeGeometry ); + } +} + +void mitk::PlaneFit::GenerateData() +{ + unsigned int t; + for ( t = 0; t < m_PointSet->GetPointSetSeriesSize(); ++t ) + { + // check number of data points - less then 3points isn't enough + if ( m_PointSet->GetSize( t ) >= 3 ) + { + this->CalculateCentroid( t ); + + this->ProcessPointSet( t ); + + this->InitializePlane( t ); + } + } +} + +void mitk::PlaneFit::SetInput( const mitk::PointSet* pointSet ) +{ + // Process object is not const-correct so the const_cast is required here + this->ProcessObject::SetNthInput(0, + const_cast< mitk::PointSet * >( pointSet ) ); + + m_PointSet = pointSet; + unsigned int pointSetSize = pointSet->GetPointSetSeriesSize(); + + m_Planes.resize( pointSetSize ); + m_Centroids.resize( pointSetSize ); + m_PlaneVectors.resize( pointSetSize ); + + unsigned int t; + for ( t = 0; t < pointSetSize; ++t ) + { + m_Planes[t] = mitk::PlaneGeometry::New(); + } +} + +const mitk::PointSet* mitk::PlaneFit::GetInput() +{ + if (this->GetNumberOfInputs() < 1) + { + return 0; + } + + return static_cast (this->ProcessObject::GetInput(0) ); +} + + +void mitk::PlaneFit::CalculateCentroid( int t ) +{ + if ( m_PointSet == NULL ) return; + + int ps_total = m_PointSet->GetSize( t ); + + m_Centroids[t][0] = m_Centroids[t][1] = m_Centroids[t][2] = 0.0; + + for (int i=0; iGetPoint(i,t); + m_Centroids[t][0] += p3d[0]; + m_Centroids[t][1] += p3d[1]; + m_Centroids[t][2] += p3d[2]; + } + + // calculation of centroid + m_Centroids[t][0] /= ps_total; + m_Centroids[t][1] /= ps_total; + m_Centroids[t][2] /= ps_total; +} + + +void mitk::PlaneFit::ProcessPointSet( int t ) +{ + if (m_PointSet == NULL ) return; + + // int matrix with POINTS x (X,Y,Z) + vnl_matrix dataM( m_PointSet->GetSize( t ), 3); + + int ps_total = m_PointSet->GetSize( t ); + for (int i=0; iGetPoint(i,t); + dataM[i][0] = p3d[0] - m_Centroids[t][0]; + dataM[i][1] = p3d[1] - m_Centroids[t][1]; + dataM[i][2] = p3d[2] - m_Centroids[t][2]; + } + // process the SVD (singular value decomposition) from ITK + // the vector will be orderd descending + vnl_svd svd(dataM, 0.0); + + // calculate the SVD of A + vnl_vector v = svd.nullvector(); + + + // Avoid erratic normal sign switching when the plane changes minimally + // by negating the vector for negative x values. + if ( v[0] < 0 ) + { + v = -v; + } + + m_PlaneVectors[t][0] = v[0]; + m_PlaneVectors[t][1] = v[1]; + m_PlaneVectors[t][2] = v[2]; + +} + +mitk::PlaneGeometry::Pointer mitk::PlaneFit::GetPlaneGeometry( int t ) +{ + return m_Planes[t]; +} + +const mitk::Vector3D &mitk::PlaneFit::GetPlaneNormal( int t ) const +{ + return m_PlaneVectors[t]; +} + +const mitk::Point3D &mitk::PlaneFit::GetCentroid( int t ) const +{ + return m_Centroids[t]; +} + +void mitk::PlaneFit::InitializePlane( int t ) +{ + m_Planes[t]->InitializePlane( m_Centroids[t], m_PlaneVectors[t] ); +} + diff --git a/Modules/AlgorithmsExt/mitkPlaneFit.h b/Modules/AlgorithmsExt/mitkPlaneFit.h new file mode 100644 index 0000000000..218df0d0bd --- /dev/null +++ b/Modules/AlgorithmsExt/mitkPlaneFit.h @@ -0,0 +1,148 @@ +/*=================================================================== + +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. + +===================================================================*/ + + +#if !defined(MITK_PLANEFIT_H__INCLUDED_) +#define MITK_PLANEFIT_H__INCLUDED_ + +#include "mitkPointSet.h" +#include "MitkAlgorithmsExtExports.h" +#include "mitkTimeGeometry.h" +#include "mitkPlaneGeometry.h" +#include "mitkGeometryDataSource.h" + +namespace mitk { + + //! + // kind regards to dr. math! + // function [x0, a, d, normd] = lsplane(X) + // --------------------------------------------------------------------- + // LSPLANE.M Least-squares plane (orthogonal distance + // regression). + // + // Version 1.0 + // Last amended I M Smith 27 May 2002. + // Created I M Smith 08 Mar 2002 + // --------------------------------------------------------------------- + // Input + // X Array [x y z] where x = vector of x-coordinates, + // y = vector of y-coordinates and z = vector of + // z-coordinates. + // Dimension: m x 3. + // + // Output + // x0 Centroid of the data = point on the best-fit plane. + // Dimension: 3 x 1. + // + // a Direction cosines of the normal to the best-fit + // plane. + // Dimension: 3 x 1. + // + // + // + // [x0, a <, d, normd >] = lsplane(X) + // --------------------------------------------------------------------- + + class MITKALGORITHMSEXT_EXPORT PlaneFit : public GeometryDataSource + { + public: + + mitkClassMacro( PlaneFit, GeometryDataSource); + itkNewMacro(Self); + + typedef mitk::PointSet::PointDataType PointDataType; + typedef mitk::PointSet::PointDataIterator PointDataIterator; + + virtual void GenerateOutputInformation(); + + virtual void GenerateData(); + + /*!Getter for point set. + * + */ + const mitk::PointSet *GetInput(); + + /*! filter initialisation. + * + */ + using mitk::GeometryDataSource::SetInput; + virtual void SetInput( const mitk::PointSet *ps ); + + /*! returns the center of gravity of the point set. + * + */ + virtual const mitk::Point3D &GetCentroid( int t = 0 ) const; + + /*! returns the plane geometry which represents the point set. + * + */ + virtual mitk::PlaneGeometry::Pointer GetPlaneGeometry( int t = 0 ); + + /*! returns the normal of the plane which represents the point set. + * + */ + virtual const mitk::Vector3D &GetPlaneNormal( int t = 0 ) const; + + protected: + PlaneFit(); + virtual ~PlaneFit(); + + /*! Calculates the centroid of the point set. + * the center of gravity is calculated through the mean value of the whole point set + */ + void CalculateCentroid( int t = 0 ); + + /*! working with an SVD algorithm form matrix dataM. + * ITK suplies the vnl_svd to solve an plan fit eigentvector problem + * points are processed in the SVD matrix. The normal vector is the + * singular vector of dataM corresponding to its smalest singular value. + * The mehtod uses VNL library from ITK and at least the mehtod nullvector() + * to extract the normalvector. + */ + void ProcessPointSet( int t = 0 ); + + /*! Initialize Plane and configuration. + * + */ + void InitializePlane( int t = 0 ); + + + private: + + /*!keeps a copy of the pointset.*/ + const mitk::PointSet* m_PointSet; + + /* output object - a time sliced geometry.*/ + mitk::TimeGeometry::Pointer m_TimeGeometry; + + std::vector< mitk::PlaneGeometry::Pointer > m_Planes; + + /*! the calculatet center point of all points in the point set.*/ + std::vector< mitk::Point3D > m_Centroids; + + /* the normal vector to descrie a plane gemoetry.*/ + std::vector< mitk::Vector3D > m_PlaneVectors; + }; +}//namespace mitk +#endif //MITK_PLANFIT_INCLUDE_ + + diff --git a/Modules/Segmentation/Algorithms/mitkSegmentationSink.cpp b/Modules/AlgorithmsExt/mitkSegmentationSink.cpp similarity index 100% rename from Modules/Segmentation/Algorithms/mitkSegmentationSink.cpp rename to Modules/AlgorithmsExt/mitkSegmentationSink.cpp diff --git a/Modules/Segmentation/Algorithms/mitkSegmentationSink.h b/Modules/AlgorithmsExt/mitkSegmentationSink.h similarity index 91% copy from Modules/Segmentation/Algorithms/mitkSegmentationSink.h copy to Modules/AlgorithmsExt/mitkSegmentationSink.h index b2bca9bdc8..d9809bb25e 100644 --- a/Modules/Segmentation/Algorithms/mitkSegmentationSink.h +++ b/Modules/AlgorithmsExt/mitkSegmentationSink.h @@ -1,56 +1,56 @@ /*=================================================================== 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 MITK_SEGMENTATION_SINK_H_INCLUDET_WAD #define MITK_SEGMENTATION_SINK_H_INCLUDET_WAD #include "mitkNonBlockingAlgorithm.h" -#include +#include namespace mitk { -class MITKSEGMENTATION_EXPORT SegmentationSink : public NonBlockingAlgorithm +class MITKALGORITHMSEXT_EXPORT SegmentationSink : public NonBlockingAlgorithm { public: mitkClassMacro( SegmentationSink, NonBlockingAlgorithm ) mitkAlgorithmNewMacro( SegmentationSink ); protected: SegmentationSink(); // use smart pointers virtual ~SegmentationSink(); virtual void Initialize(const NonBlockingAlgorithm* other = NULL); virtual bool ReadyToRun(); virtual bool ThreadedUpdateFunction(); // will be called from a thread after calling StartAlgorithm void InsertBelowGroupNode(mitk::DataNode* node); DataNode* LookForPointerTargetBelowGroupNode(const char* name); DataNode* GetGroupNode(); private: }; } // namespace #endif diff --git a/Modules/AlgorithmsExt/mitkUnstructuredGridClusteringFilter.cpp b/Modules/AlgorithmsExt/mitkUnstructuredGridClusteringFilter.cpp new file mode 100644 index 0000000000..9b1f089927 --- /dev/null +++ b/Modules/AlgorithmsExt/mitkUnstructuredGridClusteringFilter.cpp @@ -0,0 +1,218 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include +#include +#include +#include +#include +#include + + +mitk::UnstructuredGridClusteringFilter::UnstructuredGridClusteringFilter() : m_eps(0.0), m_MinPts(0), m_Meshing(true) +{ + this->m_UnstructGrid = mitk::UnstructuredGrid::New(); +} + +mitk::UnstructuredGridClusteringFilter::~UnstructuredGridClusteringFilter(){} + +std::map visited; +std::map isNoise; +std::map clusterMember; +vtkSmartPointer pLocator; + +void mitk::UnstructuredGridClusteringFilter::GenerateOutputInformation() +{ + m_UnstructGrid = this->GetOutput(); +} + +void mitk::UnstructuredGridClusteringFilter::GenerateData() +{ + mitk::UnstructuredGrid::Pointer inputGrid = const_cast(this->GetInput()); + if(inputGrid.IsNull()) return; + + vtkSmartPointer vtkInpGrid = inputGrid->GetVtkUnstructuredGrid(); + vtkSmartPointer inpPoints = vtkInpGrid->GetPoints(); + pLocator =vtkSmartPointer::New(); + std::vector< vtkSmartPointer > clusterVector; + + pLocator->SetDataSet(vtkInpGrid); + pLocator->AutomaticOn(); + pLocator->SetNumberOfPointsPerBucket(2); + pLocator->BuildLocator(); + + //fill the visited map with false for checking + for(int i=0; iGetNumberOfPoints();i++) + { + visited[i] = false; + isNoise[i] = false; + clusterMember[i] = false; + } + + for(int i=0; iGetNumberOfPoints();i++) + { + if(!visited[i]) + { + visited[i] = true; //mark P as visited + vtkSmartPointer idList = vtkSmartPointer::New(); //represent N + pLocator->FindPointsWithinRadius(m_eps, inpPoints->GetPoint(i), idList); //N = D.regionQuery(P, eps) + if(idList->GetNumberOfIds() < m_MinPts) //if sizeof(N) < MinPts + { + isNoise[i] = true; //mark P as NOISE + } + else + { + vtkSmartPointer cluster = vtkSmartPointer::New(); //represent a cluster + clusterVector.push_back(cluster); //C = next cluster + this->ExpandCluster(i,idList,cluster,inpPoints); //expandCluster(P, N, C, eps, MinPts) mod. the parameter list + } + } + } + + //OUTPUT LOGIC + m_Clusters = clusterVector; + int numberOfClusterPoints = 0; + int IdOfBiggestCluster = 0; + + for(unsigned int i=0; i points = m_Clusters.at(i); + for(int j=0; jGetNumberOfPoints();j++) + { + double point[3]; + points->GetPoint(j,point); + } + if(points->GetNumberOfPoints() > numberOfClusterPoints) + { + numberOfClusterPoints = points->GetNumberOfPoints(); + IdOfBiggestCluster = i; + } + } + + vtkSmartPointer biggestCluster = vtkSmartPointer::New(); + + vtkSmartPointer points = vtkSmartPointer::New(); + points = m_Clusters.at(IdOfBiggestCluster); + + vtkSmartPointer verts = vtkSmartPointer::New(); + verts->GetPointIds()->SetNumberOfIds(m_Clusters.at(IdOfBiggestCluster)->GetNumberOfPoints()); + for(int i=0; iGetNumberOfPoints(); i++) + { + verts->GetPointIds()->SetId(i,i); + } + + biggestCluster->Allocate(1); + biggestCluster->InsertNextCell(verts->GetCellType(), verts->GetPointIds()); + biggestCluster->SetPoints(m_Clusters.at(IdOfBiggestCluster)); + + if(m_Meshing) + { + vtkSmartPointer mesher = vtkSmartPointer::New(); + mesher->SetInputData(biggestCluster); + mesher->SetAlpha(0.9); + mesher->Update(); + + vtkSmartPointer output = mesher->GetOutput(); + m_UnstructGrid->SetVtkUnstructuredGrid(output); + } + else + { + m_UnstructGrid->SetVtkUnstructuredGrid(biggestCluster); + } +} + +void mitk::UnstructuredGridClusteringFilter::ExpandCluster(int id, vtkIdList *pointIDs, vtkPoints* cluster, vtkPoints* inpPoints) +{ + cluster->InsertNextPoint(inpPoints->GetPoint(id)); //add P to cluster C + clusterMember[id] = true; //right? + + vtkSmartPointer neighbours = vtkSmartPointer::New(); //same N as in other function + inpPoints->GetPoints(pointIDs,neighbours); + + for(int i=0; iGetNumberOfIds();i++) //for each point P' in N + { + if(!visited[pointIDs->GetId(i)]) //if P' is not visited + { + visited[pointIDs->GetId(i)] = true; //mark P' as visited + vtkSmartPointer idList = vtkSmartPointer::New(); //represent N' + pLocator->FindPointsWithinRadius(m_eps, inpPoints->GetPoint(pointIDs->GetId(i)), idList); //N' = D.regionQuery(P', eps) + if(idList->GetNumberOfIds() >= m_MinPts) //if sizeof(N') >= MinPts + { + for(int j=0; jGetNumberOfIds();j++) //N = N joined with N' + { + pointIDs->InsertNextId(idList->GetId(j)); + } + } + } + if(!clusterMember[pointIDs->GetId(i)]) //if P' is not yet member of any cluster + { + clusterMember[pointIDs->GetId(i)] = true; + cluster->InsertNextPoint(inpPoints->GetPoint(pointIDs->GetId(i))); //add P' to cluster C + } + } +} + +std::vector mitk::UnstructuredGridClusteringFilter::GetAllClusters() +{ + std::vector< mitk::UnstructuredGrid::Pointer > mitkUGridVector; + + for(unsigned int i=0; i cluster = vtkSmartPointer::New(); + + vtkSmartPointer points = m_Clusters.at(i); + + vtkSmartPointer verts = vtkSmartPointer::New(); + + verts->GetPointIds()->SetNumberOfIds(points->GetNumberOfPoints()); + for(int i=0; iGetNumberOfPoints(); i++) + { + verts->GetPointIds()->SetId(i,i); + } + + cluster->Allocate(1); + cluster->InsertNextCell(verts->GetCellType(), verts->GetPointIds()); + cluster->SetPoints(points); + + mitk::UnstructuredGrid::Pointer mitkGrid = mitk::UnstructuredGrid::New(); + + if(m_Meshing) + { + vtkSmartPointer mesher = vtkSmartPointer::New(); + mesher->SetInputData(cluster); + mesher->SetAlpha(0.9); + mesher->Update(); + + vtkSmartPointer output = mesher->GetOutput(); + mitkGrid->SetVtkUnstructuredGrid(output); + } + else + { + mitkGrid->SetVtkUnstructuredGrid(cluster); + } + + mitkUGridVector.push_back(mitkGrid); + } + + return mitkUGridVector; +} + +int mitk::UnstructuredGridClusteringFilter::GetNumberOfFoundClusters() +{ + return m_Clusters.size(); +} diff --git a/Modules/AlgorithmsExt/mitkUnstructuredGridClusteringFilter.h b/Modules/AlgorithmsExt/mitkUnstructuredGridClusteringFilter.h new file mode 100644 index 0000000000..743dae16d6 --- /dev/null +++ b/Modules/AlgorithmsExt/mitkUnstructuredGridClusteringFilter.h @@ -0,0 +1,112 @@ +/*=================================================================== + +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 _MITKUNSTRUCTUREDGRIDCLUSTERINGFILTER_h__ +#define _MITKUNSTRUCTUREDGRIDCLUSTERINGFILTER_h__ + +#include + +#include + +#include +#include +#include +#include +#include + + +namespace mitk { + + /** + * @brief The UnstructuredGridClusteringFilter class + * + * DBSCAN algorithm: + * + * DBSCAN(D, eps, MinPts) + * C = 0 + * for each unvisited point P in dataset D + * mark P as visited + * N = D.regionQuery(P, eps) + * if sizeof(N) < MinPts + * mark P as NOISE + * else + * C = next cluster + * expandCluster(P, N, C, eps, MinPts) + * + * expandCluster(P, N, C, eps, MinPts) + * add P to cluster C + * for each point P' in N + * if P' is not visited + * mark P' as visited + * N' = D.regionQuery(P', eps) + * if sizeof(N') >= MinPts + * N = N joined with N' + * if P' is not yet member of any cluster + * add P' to cluster C + */ + + class MITKALGORITHMSEXT_EXPORT UnstructuredGridClusteringFilter + : public UnstructuredGridToUnstructuredGridFilter + { + public: + + mitkClassMacro(UnstructuredGridClusteringFilter, UnstructuredGridToUnstructuredGridFilter) + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + itkSetMacro(eps, double) + itkGetMacro(eps, double) + + itkSetMacro(MinPts, int) + itkGetMacro(MinPts, int) + + itkSetMacro(Meshing, bool) + + virtual std::vector< mitk::UnstructuredGrid::Pointer> GetAllClusters(); + + virtual int GetNumberOfFoundClusters(); + + virtual void GenerateOutputInformation(); + + virtual void GenerateData(); + + protected: + + UnstructuredGridClusteringFilter(); + + virtual ~UnstructuredGridClusteringFilter(); + + private: + + void ExpandCluster(int id, vtkIdList* pointIDs, vtkPoints* cluster, vtkPoints *inpPoints); + + mitk::UnstructuredGrid::Pointer m_UnstructGrid; + + std::vector< vtkSmartPointer > m_Clusters; + + double m_eps; + + int m_MinPts; + + bool m_Meshing; + + }; + +} // namespace mitk + +#endif //_MITKUNSTRUCTUREDGRIDCLUSTERINGFILTER_h__ + + diff --git a/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h b/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h index 37ca97d5ca..fdb01a61f1 100644 --- a/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h +++ b/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h @@ -1,172 +1,212 @@ /*=================================================================== 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 mitkRenderingTestHelper_h #define mitkRenderingTestHelper_h #include #include #include #include +#include class vtkRenderWindow; class vtkRenderer; namespace mitk { class MITKTESTINGHELPER_EXPORT RenderingTestHelper { public: /** @brief Generate a rendering test helper object including a render window of the size width * height (in pixel). @param argc Number of parameters. (here: Images) "Usage: [filename1 filenam2 -V referenceScreenshot (optional -T /directory/to/save/differenceImage)] @param argv Given parameters. If no data is inserted via commandline, you can add data later via AddNodeToDataStorage(). @param renderingMode Enable Standard, Multisample or DepthPeeling **/ RenderingTestHelper(int width, int height, int argc, char *argv[], mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard); /** @brief Generate a rendering test helper object including a render window of the size width * height (in pixel).*/ RenderingTestHelper(int width, int height, mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard); /** Default destructor */ ~RenderingTestHelper(); /** @brief Getter for the vtkRenderer. **/ vtkRenderer* GetVtkRenderer(); /** @brief Getter for the vtkRenderWindow which should be used to call vtkRegressionTestImage. **/ vtkRenderWindow* GetVtkRenderWindow(); /** @brief Method can be used to save a screenshot (e.g. reference screenshot as a .png file. @param fileName The filename of the new screenshot (including path). **/ void SaveAsPNG(std::string fileName); /** * @brief SetStopRenderWindow Convenience method to make the renderwindow hold after rendering. Usefull for debugging. * @param flag Flag indicating whether the renderwindow should automatically close (false, default) or stay open (true). Usefull for debugging. */ void SetAutomaticallyCloseRenderWindow(bool automaticallyCloseRenderWindow); /** @brief This method set the property of the member datastorage @param property Set a property for each image in the datastorage m_DataStorage. If you want to set the property for a single data node, use GetDataStorage() and set the property yourself for the destinct node. **/ void SetImageProperty(const char *propertyKey, mitk::BaseProperty *property); /** @brief Set the view direction of the renderwindow (e.g. sagittal, coronal, axial) **/ void SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection); /** @brief Reorient the slice (e.g. rotation and translation like the swivel mode). **/ void ReorientSlices(mitk::Point3D origin, mitk::Vector3D rotation); /** @brief Render everything into an mitkRenderWindow. Call SetViewDirection() and SetProperty() before this method. **/ void Render(); /** @brief Returns the datastorage, in order to modify the data inside a rendering test. **/ mitk::DataStorage::Pointer GetDataStorage(); /** * @brief SetMapperID Change between Standard2D and 3D mappers. * @param id Enum mitk::BaseRenderer::StandardMapperSlot which defines the mapper. */ void SetMapperID(mitk::BaseRenderer::StandardMapperSlot id); /** * @brief AddNodeToStorage Add a node to the datastorage and perform a reinit which is necessary for rendering. * @param node The data you want to add. */ void AddNodeToStorage(mitk::DataNode::Pointer node); /** * @brief SetMapperIDToRender3D Convenience method to render in a 3D renderwindow. * @warning Does not add helper objects like the image planes to render images in 3D. */ void SetMapperIDToRender3D(); /** * @brief SetMapperIDToRender2D Convenience method to render in a 2D renderwindow. */ void SetMapperIDToRender2D(); /** * @brief SaveReferenceScreenShot Convenience method to save a reference screen shot. * @param fileName Path/to/save/the/png/file. */ void SaveReferenceScreenShot(std::string fileName); /** * @brief CompareRenderWindowAgainstReference Convenience method to compare the image rendered in the internal renderwindow against a reference screen shot. * Usage of vtkTesting::Test: vtkTesting::Test( argc, argv, vtkRenderWindow, threshold ) Set a vtkRenderWindow containing the desired scene. This is automatically rendered. vtkTesting::Test() automatically searches in argc and argv[] for a path a valid image with -V. If the test failed with the first image (foo.png) it checks if there are images of the form foo_N.png (where N=1,2,3...) and compare against them. This allows for multiple valid images. * @param argc Number of arguments. * @param argv Arguments must(!) contain the term "-V Path/To/Valid/Image.png" * @param threshold Allowed difference between two images. Default = 10.0 and was taken from VTK. * @return True if the images are equal regarding the threshold. False in all other cases. */ bool CompareRenderWindowAgainstReference(int argc, char *argv[], double threshold = 10.0); /** @brief Returns true if the opengl context is compatible for advanced vtk effects **/ bool IsAdvancedOpenGL(); + /** + * @brief The ArgcHelperClass class is a convinience class to convert a vector + * of strings to the standard c++ argv and argc arguments. This is necessary for + * the vtkTesting::Test, since is requires the reference image (and other + * optional parameters) via command line. + */ + class ArgcHelperClass{ + private: + /** + * Members for conversion. + */ + std::vector argv; + std::vector > argvec; + + public: + ArgcHelperClass(const std::vector& argstrings): + argv(argstrings.size()+1), + argvec(argstrings.size()+1) + { + std::vector cmdArgs; + cmdArgs.push_back(mitk::IOUtil::GetProgramPath()); + cmdArgs.insert(cmdArgs.end(), argstrings.begin(), argstrings.end()); + for(std::size_t i = 0 ; i #include #include #include #include //MITK #include #include #include #include #include #include -#include // include gl to read out properties #include #include #if defined _MSC_VER #if _MSC_VER >= 1700 #define RESIZE_WORKAROUND #endif #endif #ifdef RESIZE_WORKAROUND #include "vtkWin32OpenGLRenderWindow.h" #endif //VTK Testing to compare the rendered image pixel-wise against a reference screen shot #include "vtkTesting.h" mitk::RenderingTestHelper::RenderingTestHelper(int width, int height, mitk::BaseRenderer::RenderingMode::Type renderingMode) : m_AutomaticallyCloseRenderWindow(true) { this->Initialize(width, height, renderingMode ); } mitk::RenderingTestHelper::RenderingTestHelper(int width, int height, int argc, char* argv[], mitk::BaseRenderer::RenderingMode::Type renderingMode) : m_AutomaticallyCloseRenderWindow(true) { this->Initialize(width, height, renderingMode); this->SetInputFileNames(argc, argv); } void mitk::RenderingTestHelper::Initialize(int width, int height, mitk::BaseRenderer::RenderingMode::Type renderingMode) { // Global interaction must(!) be initialized mitk::GlobalInteraction::GetInstance()->Initialize("global"); m_RenderWindow = mitk::RenderWindow::New(NULL ,"unnamed renderer" , NULL, renderingMode); m_DataStorage = mitk::StandaloneDataStorage::New(); m_RenderWindow->GetRenderer()->SetDataStorage(m_DataStorage); this->SetMapperIDToRender2D(); this->GetVtkRenderWindow()->SetSize( width, height ); #ifdef RESIZE_WORKAROUND HWND hWnd = static_cast(this->GetVtkRenderWindow())->GetWindowId(); RECT r; r.left = 10; r.top = 10; r.right = r.left + width; r.bottom = r.top + height; LONG style = GetWindowLong(hWnd, GWL_STYLE); AdjustWindowRect( &r, style, FALSE ); MITK_INFO << "WANTED:"; MITK_INFO << r.right-r.left; MITK_INFO << r.bottom-r.top; RECT rect; if(GetWindowRect(hWnd, &rect)) { int width = rect.right - rect.left; int height = rect.bottom - rect.top; MITK_INFO << "ACTUAL:"; MITK_INFO << width; MITK_INFO <GetRenderer()->Resize( width, height); //Prints the glinfo after creation of the vtkrenderwindow, we always want to do this for debugging. this->PrintGLInfo(); } mitk::RenderingTestHelper::~RenderingTestHelper() { } bool mitk::RenderingTestHelper::IsAdvancedOpenGL() { const GLubyte *version = glGetString(GL_VERSION); if(!version) return false; return *version >= '2'; } void mitk::RenderingTestHelper::PrintGLInfo() { GLint maxTextureSize; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);; MITK_INFO << "OpenGL Render Context Information: \n" << "- GL_VENDOR: "<< glGetString(GL_VENDOR) << "\n" << "- GL_RENDERER: "<< glGetString(GL_RENDERER) << "\n" << "- GL_VERSION: "<< glGetString(GL_VERSION) << "\n" << "- GL_MAX_TEXTURE_SIZE: "<< maxTextureSize << "\n" << "- GL_EXTENSIONS: "<< glGetString(GL_EXTENSIONS); } void mitk::RenderingTestHelper::SetMapperID( mitk::BaseRenderer::StandardMapperSlot id) { m_RenderWindow->GetRenderer()->SetMapperID(id); } void mitk::RenderingTestHelper::SetMapperIDToRender3D() { this->SetMapperID(mitk::BaseRenderer::Standard3D); mitk::RenderingManager::GetInstance()->InitializeViews( this->GetDataStorage()->ComputeBoundingGeometry3D( this->GetDataStorage()->GetAll() ) ); } void mitk::RenderingTestHelper::SetMapperIDToRender2D() { this->SetMapperID(mitk::BaseRenderer::Standard2D); } void mitk::RenderingTestHelper::Render() { //if the datastorage is initialized and at least 1 image is loaded render it if(m_DataStorage.IsNotNull() || m_DataStorage->GetAll()->Size() >= 1 ) { //Prepare the VTK camera before rendering. m_RenderWindow->GetRenderer()->PrepareRender(); this->GetVtkRenderWindow()->Render(); if(m_AutomaticallyCloseRenderWindow == false) { //Use interaction to stop the test this->GetVtkRenderWindow()->GetInteractor()->Start(); } } else { MITK_ERROR << "No images loaded in data storage!"; } } mitk::DataStorage::Pointer mitk::RenderingTestHelper::GetDataStorage() { return m_DataStorage; } void mitk::RenderingTestHelper::SetInputFileNames(int argc, char* argv[]) { //i is set 1, because 0 is the testname as string //parse parameters for (int i = 1; i < argc; ++i) { //add everything to a list but -T and -V std::string tmp = argv[i]; if((tmp.compare("-T")) && (tmp.compare("-V"))) { this->AddToStorage(tmp); } else { break; } } } void mitk::RenderingTestHelper::SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection) { mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetSliceNavigationController()->SetDefaultViewDirection(viewDirection); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()) ); } void mitk::RenderingTestHelper::ReorientSlices(mitk::Point3D origin, mitk::Vector3D rotation) { mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetSliceNavigationController(); sliceNavigationController->ReorientSlices(origin, rotation); } vtkRenderer* mitk::RenderingTestHelper::GetVtkRenderer() { return m_RenderWindow->GetRenderer()->GetVtkRenderer(); } void mitk::RenderingTestHelper::SetImageProperty(const char *propertyKey, mitk::BaseProperty* property ) { this->m_DataStorage->GetNode(mitk::NodePredicateDataType::New("Image"))->SetProperty(propertyKey, property); } vtkRenderWindow* mitk::RenderingTestHelper::GetVtkRenderWindow() { return m_RenderWindow->GetVtkRenderWindow(); } bool mitk::RenderingTestHelper::CompareRenderWindowAgainstReference(int argc, char* argv[], double threshold) { this->Render(); m_RenderWindow->GetRenderer()->ForceImmediateUpdate(); //retVal meanings: (see VTK/Rendering/vtkTesting.h) //0 = test failed //1 = test passed //2 = test not run //3 = something with vtkInteraction if(vtkTesting::Test(argc, argv, this->GetVtkRenderWindow(), threshold) == 1) return true; else return false; } //method to save a screenshot of the renderwindow (e.g. create a reference screenshot) void mitk::RenderingTestHelper::SaveAsPNG(std::string fileName) { vtkSmartPointer renderer = this->GetVtkRenderer(); bool doubleBuffering( renderer->GetRenderWindow()->GetDoubleBuffer() ); renderer->GetRenderWindow()->DoubleBufferOff(); vtkSmartPointer magnifier = vtkSmartPointer::New(); magnifier->SetInput(renderer); magnifier->SetMagnification(1); vtkSmartPointer fileWriter = vtkSmartPointer::New(); fileWriter->SetInputConnection(magnifier->GetOutputPort()); fileWriter->SetFileName(fileName.c_str()); fileWriter->Write(); renderer->GetRenderWindow()->SetDoubleBuffer(doubleBuffering); } void mitk::RenderingTestHelper::SetAutomaticallyCloseRenderWindow(bool automaticallyCloseRenderWindow) { m_AutomaticallyCloseRenderWindow = automaticallyCloseRenderWindow; } void mitk::RenderingTestHelper::SaveReferenceScreenShot(std::string fileName) { this->SaveAsPNG(fileName); } void mitk::RenderingTestHelper::AddToStorage(const std::string &filename) { try { mitk::IOUtil::Load(filename, *m_DataStorage.GetPointer()); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()) ); } catch ( itk::ExceptionObject & e ) { MITK_ERROR << "Failed loading test data '" << filename << "': " << e.what(); } } void mitk::RenderingTestHelper::AddNodeToStorage(mitk::DataNode::Pointer node) { this->m_DataStorage->Add(node); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()) ); } diff --git a/Modules/Core/include/mitkAbstractFileReader.h b/Modules/Core/include/mitkAbstractFileReader.h index a71926158b..58e2ffb108 100644 --- a/Modules/Core/include/mitkAbstractFileReader.h +++ b/Modules/Core/include/mitkAbstractFileReader.h @@ -1,231 +1,231 @@ /*=================================================================== 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 AbstractFileReader_H_HEADER_INCLUDED_C1E7E521 #define AbstractFileReader_H_HEADER_INCLUDED_C1E7E521 // Macro #include // MITK #include #include #include // Microservices #include #include #include namespace us { struct PrototypeServiceFactory; } namespace mitk { class CustomMimeType; /** * @brief Base class for creating mitk::BaseData objects from files or streams. * @ingroup IO */ class MITKCORE_EXPORT AbstractFileReader : public mitk::IFileReader { public: virtual void SetInput(const std::string& location); virtual void SetInput(const std::string &location, std::istream* is); virtual std::string GetInputLocation() const; virtual std::istream* GetInputStream() const; MimeType GetRegisteredMimeType() const; /** * @brief Reads a path or stream and creates a list of BaseData objects. * * This method must be implemented for each specific reader. Call * GetInputStream() first and check for a non-null stream to read from. * If the input stream is \c NULL, use GetInputLocation() to read from a local * file-system path. * * If the reader cannot use streams directly, use GetLocalFileName() instead. * * @return The created BaseData objects. * @throws mitk::Exception * * @see GetLocalFileName() * @see IFileReader::Read() */ virtual std::vector > Read() = 0; virtual DataStorage::SetOfObjects::Pointer Read(mitk::DataStorage& ds); virtual ConfidenceLevel GetConfidenceLevel() const; virtual Options GetOptions() const; virtual us::Any GetOption(const std::string &name) const; virtual void SetOptions(const Options& options); virtual void SetOption(const std::string& name, const us::Any& value); virtual void AddProgressCallback(const ProgressCallback& callback); virtual void RemoveProgressCallback(const ProgressCallback& callback); /** * Associate this reader with the MIME type returned by the current IMimeTypeProvider * service for the provided extension if the MIME type exists, otherwise registers * a new MIME type when RegisterService() is called. * * If no MIME type for \c extension is already registered, a call to RegisterService() * will register a new MIME type and associate this reader instance with it. The MIME * type id can be set via SetMimeType() or it will be auto-generated using \c extension, * having the form "application/vnd.mitk.". * * @param extension The file extension (without a leading period) for which a registered * mime-type object is looked up and associated with this reader instance. * @param description A human readable description of this reader. */ us::ServiceRegistration RegisterService(us::ModuleContext* context = us::GetModuleContext()); void UnregisterService(); protected: /** * @brief An input stream wrapper. * * If a reader can only work with input streams, use an instance * of this class to either wrap the specified input stream or * create a new input stream based on the input location in the * file system. */ - class InputStream : public std::istream + class MITKCORE_EXPORT InputStream : public std::istream { public: InputStream(IFileReader* writer, std::ios_base::openmode mode = std::ios_base::in); ~InputStream(); private: std::istream* m_Stream; }; AbstractFileReader(); ~AbstractFileReader(); AbstractFileReader(const AbstractFileReader& other); /** * Associate this reader instance with the given MIME type. * * If \c mimeType does not provide an extension list, an already * registered mime-type object is used. Otherwise, the first entry in * the extensions list is used to construct a mime-type name and * register it as a new CustomMimeType service object in the default * implementation of RegisterMimeType(). * * @param mimeType The mime type this reader can read. * @param description A human readable description of this reader. * * @throws std::invalid_argument if \c mimeType is empty. * * @see RegisterService */ explicit AbstractFileReader(const CustomMimeType& mimeType, const std::string& description); virtual us::ServiceProperties GetServiceProperties() const; /** * Registers a new CustomMimeType service object. * * This method is called from RegisterService and the default implementation * registers a new mime-type service object if all of the following conditions * are true: * * - TODO * * @param context * @return * @throws std::invalid_argument if \c context is NULL. */ virtual us::ServiceRegistration RegisterMimeType(us::ModuleContext* context); void SetMimeType(const CustomMimeType& mimeType); /** * @return The mime-type this reader can handle. */ const CustomMimeType* GetMimeType() const; void SetMimeTypePrefix(const std::string& prefix); std::string GetMimeTypePrefix() const; void SetDescription(const std::string& description); std::string GetDescription() const; void SetDefaultOptions(const Options& defaultOptions); Options GetDefaultOptions() const; /** * \brief Set the service ranking for this file reader. * * Default is zero and should only be chosen differently for a reason. * The ranking is used to determine which reader to use if several * equivalent readers have been found. * It may be used to replace a default reader from MITK in your own project. * E.g. if you want to use your own reader for nrrd files instead of the default, * implement it and give it a higher ranking than zero. */ void SetRanking(int ranking); int GetRanking() const; /** * @brief Get a local file name for reading. * * This is a convenience method for readers which cannot work natively * with input streams. If no input stream has been been set, * this method just returns the result of GetLocation(). However, if * SetLocation(std::string, std::istream*) has been called with a non-null * input stream, this method writes the contents of the stream to a temporary * file and returns the name of the temporary file. * * The temporary file is deleted when either SetLocation(std::string, std::istream*) * is called again with a different input stream or the destructor of this * class is called. * * This method does not validate file names set via SetInput(std::string). * * @return A file path in the local file-system for reading. */ std::string GetLocalFileName() const; virtual void SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath); private: AbstractFileReader& operator=(const AbstractFileReader& other); virtual mitk::IFileReader* Clone() const = 0; class Impl; std::auto_ptr d; }; } // namespace mitk #endif /* AbstractFileReader_H_HEADER_INCLUDED_C1E7E521 */ diff --git a/Modules/Core/include/mitkAbstractFileWriter.h b/Modules/Core/include/mitkAbstractFileWriter.h index de33a172d7..b5c16907ae 100644 --- a/Modules/Core/include/mitkAbstractFileWriter.h +++ b/Modules/Core/include/mitkAbstractFileWriter.h @@ -1,232 +1,232 @@ /*=================================================================== 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 AbstractFileWriter_H_HEADER_INCLUDED_C1E7E521 #define AbstractFileWriter_H_HEADER_INCLUDED_C1E7E521 // Macro #include // MITK #include #include // Microservices #include #include #include #include namespace us { struct PrototypeServiceFactory; } namespace mitk { class CustomMimeType; /** * @brief Base class for writing mitk::BaseData objects to files or streams. * * In general, all file writers should derive from this class, this way it is * made sure that the new implementation is * exposed to the Microservice-Framework and that is automatically available troughout MITK. * The default implementation only requires one Write() * method and the Clone() method to be implemented. * * @ingroup IO */ class MITKCORE_EXPORT AbstractFileWriter : public mitk::IFileWriter { public: virtual void SetInput(const BaseData* data); virtual const BaseData* GetInput() const; virtual void SetOutputLocation(const std::string& location); virtual std::string GetOutputLocation() const; virtual void SetOutputStream(const std::string& location, std::ostream* os); virtual std::ostream* GetOutputStream() const; /** * \brief Write the base data to the specified location or output stream. * * This method must be implemented for each specific writer. Call * GetOutputStream() first and check for a non-null stream to write to. * If the output stream is \c NULL, use GetOutputLocation() to write * to a local file-system path. * * If the reader cannot use streams directly, use GetLocalFile() to retrieve * a temporary local file name instead. * * \throws mitk::Exception * * \see GetLocalFile() * \see IFileWriter::Write() */ virtual void Write() = 0; virtual ConfidenceLevel GetConfidenceLevel() const; MimeType GetRegisteredMimeType() const; virtual Options GetOptions() const; virtual us::Any GetOption(const std::string &name) const; virtual void SetOptions(const Options& options); virtual void SetOption(const std::string& name, const us::Any& value); virtual void AddProgressCallback(const ProgressCallback& callback); virtual void RemoveProgressCallback(const ProgressCallback& callback); us::ServiceRegistration RegisterService(us::ModuleContext* context = us::GetModuleContext()); void UnregisterService(); protected: /** * @brief A local file representation for streams. * * If a writer can only work with local files, use an instance * of this class to get either a temporary file name for writing * to the specified output stream or the original output location * if no output stream was set. */ - class LocalFile + class MITKCORE_EXPORT LocalFile { public: LocalFile(IFileWriter* writer); // Writes to the ostream and removes the temporary file ~LocalFile(); // Creates a temporary file for output operations. std::string GetFileName(); private: // disabled LocalFile(); LocalFile(const LocalFile&); LocalFile& operator=(const LocalFile& other); struct Impl; std::auto_ptr d; }; /** * @brief An output stream wrapper. * * If a writer can only work with output streams, use an instance * of this class to either wrap the specified output stream or * create a new output stream based on the output location in the * file system. */ class OutputStream : public std::ostream { public: OutputStream(IFileWriter* writer, std::ios_base::openmode mode = std::ios_base::trunc | std::ios_base::out); ~OutputStream(); private: std::ostream* m_Stream; }; ~AbstractFileWriter(); AbstractFileWriter(const AbstractFileWriter& other); AbstractFileWriter(const std::string& baseDataType); AbstractFileWriter(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description); virtual us::ServiceProperties GetServiceProperties() const; /** * Registers a new CustomMimeType service object. * * This method is called from RegisterService and the default implementation * registers a new mime-type service object if all of the following conditions * are true: * * - TODO * * @param context * @return * @throws std::invalid_argument if \c context is NULL. */ virtual us::ServiceRegistration RegisterMimeType(us::ModuleContext* context); void SetMimeType(const CustomMimeType& mimeType); /** * @return Get the mime-type this writer can handle. */ const CustomMimeType* GetMimeType() const; void SetMimeTypePrefix(const std::string& prefix); std::string GetMimeTypePrefix() const; /** * \brief Sets a human readable description of this writer. * * This will be used in file dialogs for example. */ void SetDescription(const std::string& description); std::string GetDescription() const; void SetDefaultOptions(const Options& defaultOptions); Options GetDefaultOptions() const; /** * \brief Set the service ranking for this file writer. * * Default is zero and should only be chosen differently for a reason. * The ranking is used to determine which writer to use if several * equivalent writers have been found. * It may be used to replace a default writer from MITK in your own project. * E.g. if you want to use your own writer for nrrd files instead of the default, * implement it and give it a higher ranking than zero. */ void SetRanking(int ranking); int GetRanking() const; /** * \brief Sets the name of the mitk::Basedata that this writer is able to handle. * * The correct value is the one given as the first parameter in the mitkNewMacro of that BaseData derivate. * You can also retrieve it by calling GetNameOfClass() on an instance of said data. */ void SetBaseDataType(const std::string& baseDataType); virtual std::string GetBaseDataType() const; void ValidateOutputLocation() const; private: AbstractFileWriter& operator=(const AbstractFileWriter& other); virtual mitk::IFileWriter* Clone() const = 0; class Impl; std::auto_ptr d; }; } // namespace mitk #endif /* AbstractFileWriter_H_HEADER_INCLUDED_C1E7E521 */ diff --git a/Modules/Core/include/mitkBaseGeometry.h b/Modules/Core/include/mitkBaseGeometry.h index 02fd708f36..daf92fcd83 100644 --- a/Modules/Core/include/mitkBaseGeometry.h +++ b/Modules/Core/include/mitkBaseGeometry.h @@ -1,744 +1,744 @@ /*=================================================================== 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 BaseGeometry_H_HEADER_INCLUDED #define BaseGeometry_H_HEADER_INCLUDED #include #include #include "mitkOperationActor.h" #include #include "mitkNumericTypes.h" #include #include #include "itkScalableAffineTransform.h" #include #include #include #include class vtkMatrix4x4; class vtkMatrixToLinearTransform; class vtkLinearTransform; namespace mitk { //##Documentation //## @brief Standard 3D-BoundingBox typedef //## //## Standard 3D-BoundingBox typedef to get rid of template arguments (3D, type). typedef itk::BoundingBox BoundingBox; //##Documentation //## @brief Standard typedef for time-bounds typedef itk::FixedArray TimeBounds; typedef itk::FixedArray FixedArrayType; typedef itk::AffineGeometryFrame AffineGeometryFrame3D; //##Documentation //## @brief BaseGeometry Describes the geometry of a data object //## //## The class holds //## \li a bounding box which is axes-parallel in intrinsic coordinates //## (often integer indices of pixels), to be accessed by //## GetBoundingBox() //## \li a transform to convert intrinsic coordinates into a //## world-coordinate system with coordinates in millimeters //## and milliseconds (all are floating point values), to //## be accessed by GetIndexToWorldTransform() //## \li an origin and spacing to define the geometry //## //## BaseGeometry and its sub-classes allow converting between //## intrinsic coordinates (called index or unit coordinates) //## and world-coordinates (called world or mm coordinates), //## e.g. WorldToIndex. //## In case you need integer index coordinates, provide an //## mitk::Index3D (or itk::Index) as target variable to //## WorldToIndex, otherwise you will get a continuous index //## (floating point values). //## //## An important sub-class is SlicedGeometry3D, which descibes //## data objects consisting of slices, e.g., objects of type Image. //## Conversions between world coordinates (in mm) and unit coordinates //## (e.g., pixels in the case of an Image) can be performed. //## //## For more information on related classes, see \ref Geometry. //## //## BaseGeometry instances referring to an Image need a slightly //## different definition of corners, see SetImageGeometry. This //## is usualy automatically called by Image. //## //## BaseGeometry 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 //## itk::ProcessObject::GenerateOutputInformation(), //## itk::DataObject::CopyInformation() and //## itk::DataObject::UpdateOutputInformation(). //## //## At least, it can return the bounding box of the data object. //## //## The BaseGeometry class is an abstract class. The most simple implementation //## is the sublass Geometry3D. //## //## Rule: everything is in mm (ms) if not stated otherwise. //## @ingroup Geometry class MITKCORE_EXPORT BaseGeometry : public itk::Object, public OperationActor { public: mitkClassMacro(BaseGeometry, itk::Object); itkCloneMacro(Self) // ********************************** TypeDef ********************************** typedef GeometryTransformHolder::TransformType TransformType; typedef itk::BoundingBox BoundingBoxType; typedef BoundingBoxType::BoundsArrayType BoundsArrayType; typedef BoundingBoxType::Pointer BoundingBoxPointer; // ********************************** Origin, Spacing ********************************** //##Documentation //## @brief Get the origin, e.g. the upper-left corner of the plane const Point3D GetOrigin() const; //##Documentation //## @brief Set the origin, i.e. the upper-left corner of the plane //## void SetOrigin(const Point3D& origin); //##Documentation //## @brief Get the spacing (size of a pixel). //## const mitk::Vector3D GetSpacing() const; //##Documentation //## @brief Set the spacing (m_Spacing). //## //##The spacing is also changed in the IndexToWorldTransform. void SetSpacing(const mitk::Vector3D& aSpacing, bool enforceSetSpacing = false); //##Documentation //## @brief Get the origin as VnlVector //## //## \sa GetOrigin VnlVector GetOriginVnl() const; // ********************************** other functions ********************************** //##Documentation //## @brief Get the DICOM FrameOfReferenceID referring to the //## used world coordinate system itkGetConstMacro(FrameOfReferenceID, unsigned int); //##Documentation //## @brief Set the DICOM FrameOfReferenceID referring to the //## used world coordinate system itkSetMacro(FrameOfReferenceID, unsigned int); itkGetConstMacro(IndexToWorldTransformLastModified, unsigned long); //##Documentation //## @brief Overload of function Modified() to prohibit several calls of Modified() using the ModifiedLock class. //## //## For the use of Modified(), see class ModifiedLock. void Modified() const; friend class ModifiedLock; //##Documentation //## @brief Is this BaseGeometry in a state that is valid? //## //## This function returns always true in the BaseGeometry class. Other implementations are possible in subclasses. virtual bool IsValid() const; // ********************************** Initialize ********************************** //##Documentation //## @brief Initialize the BaseGeometry void Initialize(); void InitializeGeometry(Self * newGeometry) const; // ********************************** Transformations Set/Get ********************************** //##Documentation //## @brief Get the transformation used to convert from index //## to world coordinates mitk::AffineTransform3D* GetIndexToWorldTransform(); //##Documentation //## @brief Get the transformation used to convert from index //## to world coordinates const mitk::AffineTransform3D* GetIndexToWorldTransform() const; //## @brief Set the transformation used to convert from index //## to world coordinates. The spacing of the new transform is //## copied to m_spacing. void SetIndexToWorldTransform(mitk::AffineTransform3D* transform); //##Documentation //## @brief Convenience method for setting the ITK transform //## (m_IndexToWorldTransform) via an vtkMatrix4x4.The spacing of //## the new transform is copied to m_spacing. //## \sa SetIndexToWorldTransform virtual void SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4* vtkmatrix); //## @brief Set the transformation used to convert from index //## to world coordinates.This function keeps the original spacing. void SetIndexToWorldTransformWithoutChangingSpacing(mitk::AffineTransform3D* transform); //##Documentation //## @brief Convenience method for setting the ITK transform //## (m_IndexToWorldTransform) via an vtkMatrix4x4. This function keeps the original spacing. //## \sa SetIndexToWorldTransform void SetIndexToWorldTransformByVtkMatrixWithoutChangingSpacing(vtkMatrix4x4* vtkmatrix); //## Get the Vtk Matrix which describes the transform. vtkMatrix4x4* GetVtkMatrix(); //##Documentation //## @brief Get the m_IndexToWorldTransform as a vtkLinearTransform vtkLinearTransform* GetVtkTransform() const; //##Documentation //## @brief Set the transform to identity, the spacing to 1 and origin to 0 //## virtual void SetIdentity(); // ********************************** Transformations ********************************** //##Documentation //## @brief Compose new IndexToWorldTransform with a given transform. //## //## This method composes m_IndexToWorldTransform with another transform, //## modifying self to be the composition of self and other. //## If the argument pre is true, then other is precomposed with self; //## that is, the resulting transformation consists of first applying //## other to the source, followed by self. If pre is false or omitted, //## then other is post-composed with self; that is the resulting //## transformation consists of first applying self to the source, //## followed by other. //## This method also changes m_spacing. void Compose( const TransformType * other, bool pre = 0 ); //##Documentation //## @brief Compose new IndexToWorldTransform with a given vtkMatrix4x4. //## //## Converts the vtkMatrix4x4 into a itk-transform and calls the previous method. void Compose( const vtkMatrix4x4 * vtkmatrix, bool pre = 0 ); //##Documentation //## @brief Translate the origin by a vector //## void Translate(const Vector3D& vector); //##Documentation //##@brief executes affine operations (translate, rotate, scale) virtual void ExecuteOperation(Operation* operation); //##Documentation //## @brief Convert world coordinates (in mm) of a \em point to (continuous!) index coordinates //## \warning If you need (discrete) integer index coordinates (e.g., for iterating easily over an image), //## use WorldToIndex(const mitk::Point3D& pt_mm, itk::Index &index). //## For further information about coordinates types, please see the Geometry documentation void WorldToIndex(const mitk::Point3D& pt_mm, mitk::Point3D& pt_units) const; //##Documentation //## @brief Convert world coordinates (in mm) of a \em vector //## \a vec_mm to (continuous!) index coordinates. //## For further information about coordinates types, please see the Geometry documentation void WorldToIndex(const mitk::Vector3D& vec_mm, mitk::Vector3D& vec_units) const; //##Documentation //## @brief Convert world coordinates (in mm) of a \em point to (discrete!) index coordinates. //## This method rounds to integer indices! //## For further information about coordinates types, please see the Geometry documentation template void WorldToIndex(const mitk::Point3D& pt_mm, itk::Index &index) const { typedef itk::Index IndexType; mitk::Point3D pt_units; this->WorldToIndex(pt_mm, pt_units); int i, dim=index.GetIndexDimension(); if(dim>3) { index.Fill(0); dim=3; } for(i=0;i( pt_units[i] ); } } //##Documentation //## @brief Convert (continuous or discrete) index coordinates of a \em vector //## \a vec_units to world coordinates (in mm) //## For further information about coordinates types, please see the Geometry documentation void IndexToWorld(const mitk::Vector3D& vec_units, mitk::Vector3D& vec_mm) const; //##Documentation //## @brief Convert (continuous or discrete) index coordinates of a \em point to world coordinates (in mm) //## For further information about coordinates types, please see the Geometry documentation void IndexToWorld(const mitk::Point3D& pt_units, mitk::Point3D& pt_mm) const; //##Documentation //## @brief Convert (discrete) index coordinates of a \em point to world coordinates (in mm) //## For further information about coordinates types, please see the Geometry documentation template void IndexToWorld(const itk::Index &index, mitk::Point3D& pt_mm ) const { mitk::Point3D pt_units; pt_units.Fill(0); int i, dim=index.GetIndexDimension(); if(dim>3) { dim=3; } for(i=0;i void ItkPhysicalPointToWorld(const itk::Point& itkPhysicalPoint, mitk::Point3D& pt_mm) const { mitk::vtk2itk(itkPhysicalPoint, pt_mm); } //##Documentation //## @brief Deprecated for use with ITK version 3.10 or newer. //## Convert world coordinates (in mm) of a \em point to //## ITK physical coordinates (in mm, but without a possible rotation) //## //## This method is useful if you have want to access an mitk::Image //## via an itk::Image. ITK v3.8 and older did not support rotated (tilted) //## images, i.e., ITK images are always parallel to the coordinate axes. //## When accessing a (possibly rotated) mitk::Image via an itk::Image //## the rotational part of the transformation in the BaseGeometry is //## simply discarded; in other word: only the origin and spacing is //## used by ITK, not the complete matrix available in MITK. //## With WorldToItkPhysicalPoint you can convert an MITK world //## coordinate (including the rotation) into a coordinate that //## can be used with the ITK image as a ITK physical coordinate //## (excluding the rotation). template void WorldToItkPhysicalPoint(const mitk::Point3D& pt_mm, itk::Point& itkPhysicalPoint) const { mitk::vtk2itk(pt_mm, itkPhysicalPoint); } // ********************************** BoundingBox ********************************** /** Get the bounding box */ itkGetConstObjectMacro(BoundingBox, BoundingBoxType); //##Documentation //## @brief Get the time bounds (in ms) //itkGetConstReferenceMacro(TimeBounds, TimeBounds); // a bit of a misuse, but we want only doxygen to see the following: #ifdef DOXYGEN_SKIP //##Documentation //## @brief Get bounding box (in index/unit coordinates) itkGetConstObjectMacro(BoundingBox, BoundingBoxType); //##Documentation //## @brief Get bounding box (in index/unit coordinates) as a BoundsArrayType const BoundsArrayType GetBounds() const; #endif const BoundsArrayType GetBounds() const; //##Documentation //## \brief Set the bounding box (in index/unit coordinates) //## //## Only possible via the BoundsArray to make clear that a //## copy of the bounding-box is stored, not a reference to it. void SetBounds(const BoundsArrayType& bounds); //##Documentation //## @brief Set the bounding box (in index/unit coordinates) via a float array void SetFloatBounds(const float bounds[6]); //##Documentation //## @brief Set the bounding box (in index/unit coordinates) via a double array void SetFloatBounds(const double bounds[6]); //##Documentation //## @brief Get a VnlVector along bounding-box in the specified //## @a direction, length is spacing //## //## \sa GetAxisVector VnlVector GetMatrixColumn(unsigned int direction) const; //##Documentation //## @brief Calculates a bounding-box around the geometry relative //## to a coordinate system defined by a transform //## mitk::BoundingBox::Pointer CalculateBoundingBoxRelativeToTransform(const mitk::AffineTransform3D* transform) const; //##Documentation //## @brief Set the time bounds (in ms) //void SetTimeBounds(const TimeBounds& timebounds); // ********************************** Geometry ********************************** #ifdef DOXYGEN_SKIP //##Documentation //## @brief Get the extent of the bounding box (in index/unit coordinates) //## //## To access the extent in mm use GetExtentInMM ScalarType GetExtent(unsigned int direction) const; #endif /** Get the extent of the bounding box */ ScalarType GetExtent(unsigned int direction) const; //##Documentation //## @brief Get the extent of the bounding-box in the specified @a direction in mm //## //## Equals length of GetAxisVector(direction). ScalarType GetExtentInMM(int direction) const; //##Documentation //## @brief Get vector along bounding-box in the specified @a direction in mm //## //## The length of the vector is the size of the bounding-box in the //## specified @a direction in mm //## \sa GetMatrixColumn Vector3D GetAxisVector(unsigned int direction) const; //##Documentation //## @brief Checks, if the given geometry can be converted to 2D without information loss //## e.g. when a 2D image is saved, the matrix is usually cropped to 2x2, and when you load it back to MITK //## it will be filled with standard values. This function checks, if information would be lost during this //## procedure virtual bool Is2DConvertable(); //##Documentation //## @brief Get the center of the bounding-box in mm //## Point3D GetCenter() const; //##Documentation //## @brief Get the squared length of the diagonal of the bounding-box in mm //## double GetDiagonalLength2() const; //##Documentation //## @brief Get the length of the diagonal of the bounding-box in mm //## double GetDiagonalLength() const; //##Documentation //## @brief Get the position of the corner number \a id (in world coordinates) //## //## See SetImageGeometry for how a corner is defined on images. Point3D GetCornerPoint(int id) const; //##Documentation //## @brief Get the position of a corner (in world coordinates) //## //## See SetImageGeometry for how a corner is defined on images. Point3D GetCornerPoint(bool xFront=true, bool yFront=true, bool zFront=true) const; //##Documentation //## @brief Set the extent of the bounding-box in the specified @a direction in mm //## //## @note This changes the matrix in the transform, @a not the bounds, which are given in units! void SetExtentInMM(int direction, ScalarType extentInMM); //##Documentation //## @brief Test whether the point \a p (world coordinates in mm) is //## inside the bounding box bool IsInside(const mitk::Point3D& p) const; //##Documentation //## @brief Test whether the point \a p ((continous!)index coordinates in units) is //## inside the bounding box bool IsIndexInside(const mitk::Point3D& index) const; //##Documentation //## @brief Convenience method for working with ITK indices template bool IsIndexInside(const itk::Index &index) const { int i, dim=index.GetIndexDimension(); Point3D pt_index; pt_index.Fill(0); for ( i = 0; i < dim; ++i ) { pt_index[i] = index[i]; } return IsIndexInside(pt_index); } // ********************************* Image Geometry ******************************** //##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. virtual void ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry ); //##Documentation //## @brief Is this an ImageGeometry? //## //## For more information, see SetImageGeometry - itkGetConstMacro(ImageGeometry, bool); + itkGetConstMacro(ImageGeometry, bool) //##Documentation //## @brief Define that this BaseGeometry is refering to an Image //## //## A geometry referring to an Image needs a slightly different //## definition of the position of the corners (see GetCornerPoint). //## The position of a voxel is defined by the position of its center. //## If we would use the origin (position of the (center of) the first //## voxel) as a corner and display this point, it would seem to be //## \em not at the corner but a bit within the image. Even worse for //## the opposite corner of the image: here the corner would appear //## outside the image (by half of the voxel diameter). Thus, we have //## to correct for this and to be able to do that, we need to know //## that the BaseGeometry is referring to an Image. - itkSetMacro(ImageGeometry, bool); - itkBooleanMacro(ImageGeometry); + itkSetMacro(ImageGeometry, bool) + itkBooleanMacro(ImageGeometry) const GeometryTransformHolder* GetGeometryTransformHolder() const; protected: // ********************************** Constructor ********************************** BaseGeometry(); BaseGeometry(const BaseGeometry& other); virtual ~BaseGeometry(); //##Documentation //## @brief clones the geometry //## //## Overwrite in all sub-classes. //## Normally looks like: //## \code //## Self::Pointer newGeometry = new Self(*this); //## newGeometry->UnRegister(); //## return newGeometry.GetPointer(); //## \endcode virtual itk::LightObject::Pointer InternalClone() const =0; virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; void BackTransform(const mitk::Point3D& in, mitk::Point3D& out) const; //Without redundant parameter Point3D void BackTransform(const mitk::Vector3D& in, mitk::Vector3D& out) const; //##Documentation //## @brief Deprecated void BackTransform(const mitk::Point3D& at, const mitk::Vector3D& in, mitk::Vector3D& out) const; static const std::string GetTransformAsString( TransformType* transformType ); - itkGetConstMacro(NDimensions, unsigned int); + itkGetConstMacro(NDimensions, unsigned int) bool IsBoundingBoxNull() const; bool IsIndexToWorldTransformNull() const; void SetVtkMatrixDeepCopy(vtkTransform *vtktransform); void _SetSpacing(const mitk::Vector3D& aSpacing, bool enforceSetSpacing = false); //##Documentation //## @brief Pre- and Post-functions are empty in BaseGeometry //## //## These virtual functions allow for a different beahiour in subclasses. //## Do implement them in every subclass of BaseGeometry. If not needed, use {}. //## If this class is inherited from a subclass of BaseGeometry, call {Superclass::Pre...();};, example: DisplayGeometry class - virtual void PreSetBounds(const BoundsArrayType& /*bounds*/){}; - virtual void PostInitialize(){}; - virtual void PostInitializeGeometry(mitk::BaseGeometry::Self * /*newGeometry*/) const {}; - virtual void PostSetExtentInMM(int /*direction*/, ScalarType /*extentInMM*/) {}; - virtual void PreSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {}; - virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {}; - virtual void PreSetSpacing(const mitk::Vector3D& /*aSpacing*/) {}; + virtual void PreSetBounds(const BoundsArrayType& /*bounds*/) {} + virtual void PostInitialize() {} + virtual void PostInitializeGeometry(mitk::BaseGeometry::Self * /*newGeometry*/) const {} + virtual void PostSetExtentInMM(int /*direction*/, ScalarType /*extentInMM*/) {} + virtual void PreSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {} + virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {} + virtual void PreSetSpacing(const mitk::Vector3D& /*aSpacing*/) {} private: GeometryTransformHolder* m_GeometryTransform; void InitializeGeometryTransformHolder(const BaseGeometry* otherGeometry); //##Documentation //## @brief Bounding Box, which is axes-parallel in intrinsic coordinates //## (often integer indices of pixels) BoundingBoxPointer m_BoundingBox; unsigned int m_FrameOfReferenceID; //mitk::TimeBounds m_TimeBounds; static const unsigned int m_NDimensions = 3; mutable TransformType::Pointer m_InvertedTransform; mutable unsigned long m_IndexToWorldTransformLastModified; bool m_ImageGeometry; //##Documentation //## @brief ModifiedLockFlag is used to prohibit the call of Modified() //## //## For the use of this Flag, see class ModifiedLock. This flag should only be set //## by the ModifiedLock class! bool m_ModifiedLockFlag; //##Documentation //## @brief ModifiedcalledFlag is used to collect calls of Modified(). //## //## For the use of this Flag, see class ModifiedLock. This flag should only be set //## by the Modified() function! mutable bool m_ModifiedCalledFlag; }; // ********************************** Equal Functions ********************************** // // Static compare functions mainly for testing // /** * @brief Equal A function comparing two geometries for beeing identical. * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::mitk::BaseGeometry& g1, const mitk::BaseGeometry& g2) instead. * * @ingroup MITKTestingAPI * * The function compares the spacing, origin, axisvectors, extents, the matrix of the * IndexToWorldTransform (elementwise), the bounding (elementwise) and the ImageGeometry flag. * * The parameter eps is a tolarence value for all methods which are internally used for comparion. * If you want to use different tolarance values for different parts of the geometry, feel free to use * the other comparison methods and write your own implementation of Equal. * @param rightHandSide Compare this against leftHandSide. * @param leftHandSide Compare this against rightHandSide. * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return True, if all comparison are true. False in any other case. */ DEPRECATED( MITKCORE_EXPORT bool Equal(const mitk::BaseGeometry* leftHandSide, const mitk::BaseGeometry* rightHandSide, ScalarType eps, bool verbose)); /** * @brief Equal A function comparing two geometries for beeing identical. * * @ingroup MITKTestingAPI * * The function compares the spacing, origin, axisvectors, extents, the matrix of the * IndexToWorldTransform (elementwise), the bounding (elementwise) and the ImageGeometry flag. * * The parameter eps is a tolarence value for all methods which are internally used for comparion. * If you want to use different tolarance values for different parts of the geometry, feel free to use * the other comparison methods and write your own implementation of Equal. * @param rightHandSide Compare this against leftHandSide. * @param leftHandSide Compare this against rightHandSide. * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return True, if all comparison are true. False in any other case. */ MITKCORE_EXPORT bool Equal(const mitk::BaseGeometry& leftHandSide, const mitk::BaseGeometry& rightHandSide, ScalarType eps, bool verbose); /** * @brief Equal A function comparing two transforms (TransformType) for beeing identical. * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::mitk::BaseGeometry::TransformType& t1, const mitk::BaseGeometry::TransformType& t2) instead. * * @ingroup MITKTestingAPI * * The function compares the IndexToWorldTransform (elementwise). * * The parameter eps is a tolarence value for all methods which are internally used for comparion. * @param rightHandSide Compare this against leftHandSide. * @param leftHandSide Compare this against rightHandSide. * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return True, if all comparison are true. False in any other case. */ DEPRECATED( MITKCORE_EXPORT bool Equal(const mitk::BaseGeometry::TransformType *leftHandSide, const mitk::BaseGeometry::TransformType *rightHandSide, ScalarType eps, bool verbose)); /** * @brief Equal A function comparing two transforms (TransformType) for beeing identical. * * @ingroup MITKTestingAPI * * The function compares the IndexToWorldTransform (elementwise). * * The parameter eps is a tolarence value for all methods which are internally used for comparion. * @param rightHandSide Compare this against leftHandSide. * @param leftHandSide Compare this against rightHandSide. * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return True, if all comparison are true. False in any other case. */ MITKCORE_EXPORT bool Equal(const mitk::BaseGeometry::TransformType& leftHandSide, const mitk::BaseGeometry::TransformType& rightHandSide, ScalarType eps, bool verbose); /** * @brief Equal A function comparing two bounding boxes (BoundingBoxType) for beeing identical. * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::mitk::BaseGeometry::BoundingBoxType& b1, const mitk::BaseGeometry::BoundingBoxType& b2) instead. * * @ingroup MITKTestingAPI * * The function compares the bounds (elementwise). * * The parameter eps is a tolarence value for all methods which are internally used for comparion. * @param rightHandSide Compare this against leftHandSide. * @param leftHandSide Compare this against rightHandSide. * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return True, if all comparison are true. False in any other case. */ DEPRECATED( MITKCORE_EXPORT bool Equal( const mitk::BaseGeometry::BoundingBoxType *leftHandSide, const mitk::BaseGeometry::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose)); /** * @brief Equal A function comparing two bounding boxes (BoundingBoxType) for beeing identical. * * @ingroup MITKTestingAPI * * The function compares the bounds (elementwise). * * The parameter eps is a tolarence value for all methods which are internally used for comparion. * @param rightHandSide Compare this against leftHandSide. * @param leftHandSide Compare this against rightHandSide. * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return True, if all comparison are true. False in any other case. */ MITKCORE_EXPORT bool Equal( const mitk::BaseGeometry::BoundingBoxType& leftHandSide, const mitk::BaseGeometry::BoundingBoxType& rightHandSide, ScalarType eps, bool verbose); } // namespace mitk #endif /* BaseGeometry_H_HEADER_INCLUDED */ diff --git a/Modules/Core/include/mitkCustomMimeType.h b/Modules/Core/include/mitkCustomMimeType.h index a3a73d663f..b05d8a2cee 100644 --- a/Modules/Core/include/mitkCustomMimeType.h +++ b/Modules/Core/include/mitkCustomMimeType.h @@ -1,85 +1,102 @@ /*=================================================================== 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 MITKCUSTOMMIMETYPE_H #define MITKCUSTOMMIMETYPE_H #include #include #include #include namespace mitk { class MimeType; /** * @ingroup IO * @ingroup MicroServices_Interfaces * * @brief The CustomMimeType class represents a custom mime-type which * may be registered as a service object. * * Instances of this class are usually created and registered as a service. * They wire files to specific IFileReader instances and provide data format * meta-data for selecting compatible IFileWriter instances. */ class MITKCORE_EXPORT CustomMimeType { public: CustomMimeType(); CustomMimeType(const std::string& name); CustomMimeType(const CustomMimeType& other); explicit CustomMimeType(const MimeType& other); virtual ~CustomMimeType(); CustomMimeType& operator=(const CustomMimeType& other); CustomMimeType& operator=(const MimeType& other); std::string GetName() const; std::string GetCategory() const; std::vector GetExtensions() const; std::string GetComment() const; virtual bool AppliesTo(const std::string& path) const; + /** + * \brief Provides the first matching extension + * + * Checks whether any of its extensions are present at the end of the provided path. + * Returns the first found one. + */ + std::string GetExtension(const std::string& path) const; + /** + * \brief Provides the filename minus the extension + * + * Checks whether any of its extensions are present at the end of the provided path. + * Returns the filename without that extension and without the directory. + */ + std::string GetFilenameWithoutExtension(const std::string& path) const; void SetName(const std::string& name); void SetCategory(const std::string& category); void SetExtension(const std::string& extension); void AddExtension(const std::string& extension); void SetComment(const std::string& comment); void Swap(CustomMimeType& r); virtual CustomMimeType* Clone() const; private: + // returns true if an extension was found + bool ParsePathForExtension(const std::string& path, std::string& extension, std::string& filename ) const; + struct Impl; Impl* d; }; void swap(CustomMimeType& l, CustomMimeType& r); } MITK_DECLARE_SERVICE_INTERFACE(mitk::CustomMimeType, "org.mitk.CustomMimeType") #endif // MITKCUSTOMMIMETYPE_H diff --git a/Modules/Core/include/mitkGeometry3D.h b/Modules/Core/include/mitkGeometry3D.h index bdaa248f9d..f561276232 100644 --- a/Modules/Core/include/mitkGeometry3D.h +++ b/Modules/Core/include/mitkGeometry3D.h @@ -1,87 +1,87 @@ /*=================================================================== 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 GEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD #define GEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD #include #include #include "mitkNumericTypes.h" #include "itkScalableAffineTransform.h" #include #include "mitkBaseGeometry.h" class vtkLinearTransform; namespace mitk { //##Documentation //## @brief Standard implementation of BaseGeometry. //## //## @ingroup Geometry class MITKCORE_EXPORT Geometry3D : public BaseGeometry { public: - mitkClassMacro(Geometry3D, mitk::BaseGeometry); + mitkClassMacro(Geometry3D, mitk::BaseGeometry) typedef itk::QuaternionRigidTransform< ScalarType > QuaternionTransformType; typedef QuaternionTransformType::VnlQuaternionType VnlQuaternionType; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) - mitkNewMacro1Param(Self, const Self&); + mitkNewMacro1Param(Self, const Self&) itkCloneMacro(Self) //itkGetConstReferenceMacro(TimeBounds, TimeBounds); //virtual void SetTimeBounds(const TimeBounds& timebounds); protected: Geometry3D(); - Geometry3D(const Geometry3D& other); + Geometry3D(const Geometry3D& ); //##Documentation //## @brief clones the geometry //## //## Overwrite in all sub-classes. //## Normally looks like: //## \code //## Self::Pointer newGeometry = new Self(*this); //## newGeometry->UnRegister(); //## return newGeometry.GetPointer(); //## \endcode virtual itk::LightObject::Pointer InternalClone() const; virtual ~Geometry3D(); //##Documentation //## @brief Pre- and Post-functions are empty in BaseGeometry //## //## These virtual functions allow for a different beahiour in subclasses. //## Do implement them in every subclass of BaseGeometry. If not needed, use {}. //## If this class is inherited from a subclass of BaseGeometry, call {Superclass::Pre...();};, example: DisplayGeometry class - virtual void PreSetBounds(const BoundsArrayType& /*bounds*/){}; - virtual void PostInitialize(){}; - virtual void PostInitializeGeometry(mitk::BaseGeometry::Self * /*newGeometry*/) const{}; - virtual void PostSetExtentInMM(int /*direction*/, ScalarType /*extentInMM*/){}; - virtual void PreSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/){}; - virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/){}; - virtual void PreSetSpacing(const mitk::Vector3D& /*aSpacing*/){}; + virtual void PreSetBounds(const BoundsArrayType& /*bounds*/) {} + virtual void PostInitialize() {} + virtual void PostInitializeGeometry(mitk::BaseGeometry::Self * /*newGeometry*/) const {} + virtual void PostSetExtentInMM(int /*direction*/, ScalarType /*extentInMM*/) {} + virtual void PreSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {} + virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {} + virtual void PreSetSpacing(const mitk::Vector3D& /*aSpacing*/) {} }; } // namespace mitk #endif /* GEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD */ diff --git a/Modules/Core/include/mitkImagePixelWriteAccessor.h b/Modules/Core/include/mitkImagePixelWriteAccessor.h index 00df8d2b24..234f6b3ba2 100644 --- a/Modules/Core/include/mitkImagePixelWriteAccessor.h +++ b/Modules/Core/include/mitkImagePixelWriteAccessor.h @@ -1,155 +1,159 @@ /*=================================================================== 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 MITKIMAGEPIXELWRITEACCESSOR_H #define MITKIMAGEPIXELWRITEACCESSOR_H #include "mitkImagePixelAccessor.h" #include "mitkImageWriteAccessor.h" namespace mitk { /** * @brief Gives locked and index-based write access for a particular image part. * The class provides several set- and get-methods, which allow an easy pixel access. * It needs to know about pixel type and dimension of its image at compile time. * @tparam TPixel defines the PixelType * @tparam VDimension defines the dimension for accessing data * @ingroup Data */ template class ImagePixelWriteAccessor : public ImagePixelAccessor { friend class Image; public: typedef ImagePixelAccessor ImagePixelAccessorType; typedef itk::SmartPointer ImagePointer; /** \brief Instantiates a mitk::ImageWriteAccessor (see its doxygen page for more details) * \param Image::Pointer specifies the associated Image * \param ImageDataItem* specifies the allocated image part * \param OptionFlags properties from mitk::ImageAccessorBase::Options can be chosen and assembled with bitwise unification. * \throws mitk::Exception if the Constructor was created inappropriately * \throws mitk::MemoryIsLockedException if requested image area is exclusively locked and mitk::ImageAccessorBase::ExceptionIfLocked is set in OptionFlags * * Includes a check if typeid of PixelType coincides with templated TPixel - * and a check if VDimension equals to the Dimension of the Image.*/ + * and a check if VDimension equals to the Dimension of the Image. + * + * \note + * To avoid intermittent Update() calls to a predecessing filter pipeline, a call to Modifed() method after the access is finished is left to the developer. + */ ImagePixelWriteAccessor( ImagePointer iP, const ImageDataItem* iDI = NULL, int OptionFlags = ImageAccessorBase::DefaultBehavior ) : ImagePixelAccessor(iP.GetPointer(),iDI) , m_WriteAccessor(iP , iDI, OptionFlags) { } /** \brief Gives full data access. */ virtual inline TPixel * GetData() const { return static_cast(m_WriteAccessor.m_AddressBegin); } /// Sets a pixel value at given index. void SetPixelByIndex(const itk::Index& idx, const TPixel & value) { unsigned int offset = ImagePixelAccessor::GetOffset(idx); *(((TPixel*)m_WriteAccessor.m_AddressBegin) + offset) = value; } /** Extends SetPixel by integrating index validation to prevent overflow. */ void SetPixelByIndexSafe(const itk::Index& idx, const TPixel & value) { unsigned int offset = ImagePixelAccessorType::GetOffset(idx); TPixel* targetAddress = ((TPixel*)m_WriteAccessor.m_AddressBegin) + offset; if(targetAddress >= m_WriteAccessor.m_AddressBegin && targetAddress < m_WriteAccessor.m_AddressEnd) { *targetAddress = value; } else { //printf("image dimensions = %d, %d, %d\n", imageDims[0], imageDims[1], imageDims[2]); //printf("m_AddressBegin: %p, m_AddressEnd: %p, offset: %u\n", m_WriteAccessor.m_AddressBegin, m_WriteAccessor.m_AddressEnd, offset); mitkThrow() << "ImageAccessor Overflow: image access exceeds the requested image area at " << idx << "."; } } /** Returns a const reference to the pixel at given index. */ const TPixel & GetPixelByIndex(const itk::Index& idx) const { unsigned int offset = ImagePixelAccessorType::GetOffset(idx); return *(((TPixel*)m_WriteAccessor.m_AddressBegin) + offset); } /** Extends GetPixel by integrating index validation to prevent overflow. * \throws mitk::Exception in case of overflow */ const TPixel & GetPixelByIndexSafe(const itk::Index& idx) const { unsigned int offset = ImagePixelAccessorType::GetOffset(idx); TPixel* targetAddress = ((TPixel*)m_WriteAccessor.m_AddressBegin) + offset; if(!(targetAddress >= m_WriteAccessor.m_AddressBegin && targetAddress < m_WriteAccessor.m_AddressEnd)) { mitkThrow() << "ImageAccessor Overflow: image access exceeds the requested image area at " << idx << "."; } return *targetAddress; } /** Returns a const reference to the pixel at given world coordinate - works only with three-dimensional ImageAccessor */ const TPixel & GetPixelByWorldCoordinates(mitk::Point3D position) { itk::Index<3> itkIndex; m_WriteAccessor.GetImage()->GetGeometry()->WorldToIndex(position, itkIndex); return GetPixelByIndex( itkIndex); } /** Returns a reference to the pixel at given world coordinate */ void SetPixelByWorldCoordinates(const mitk::Point3D&, const TPixel & value, unsigned int timestep = 0); virtual ~ImagePixelWriteAccessor() { } private: ImageWriteAccessor m_WriteAccessor; ImagePixelWriteAccessor& operator=(const ImagePixelWriteAccessor&); // Not implemented on purpose. ImagePixelWriteAccessor(const ImagePixelWriteAccessor &); }; } #endif // MITKIMAGEWRITEACCESSOR_H diff --git a/Modules/Core/include/mitkPlaneGeometry.h b/Modules/Core/include/mitkPlaneGeometry.h index 632932e7ba..9ec4de8475 100644 --- a/Modules/Core/include/mitkPlaneGeometry.h +++ b/Modules/Core/include/mitkPlaneGeometry.h @@ -1,577 +1,577 @@ /*=================================================================== 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. ===================================================================*/ /** * \brief Describes the geometry of a plane object * * Describes a two-dimensional manifold, i.e., to put it simply, * an object that can be described using a 2D coordinate-system. * * PlaneGeometry can map points between 3D world coordinates * (in mm) and the described 2D coordinate-system (in mm) by first projecting * the 3D point onto the 2D manifold and then calculating the 2D-coordinates * (in mm). These 2D-mm-coordinates can be further converted into * 2D-unit-coordinates (e.g., pixels), giving a parameter representation of * the object with parameter values inside a rectangle * (e.g., [0,0]..[width, height]), which is the bounding box (bounding range * in z-direction always [0]..[1]). * * A PlaneGeometry describes the 2D representation within a 3D object (derived from BaseGeometry). For example, * a single CT-image (slice) is 2D in the sense that you can access the * pixels using 2D-coordinates, but is also 3D, as the pixels are really * voxels, thus have an extension (thickness) in the 3rd dimension. * * * Optionally, a reference BaseGeometry can be specified, which usually would * be the geometry associated with the underlying dataset. This is currently * used for calculating the intersection of inclined / rotated planes * (represented as PlaneGeometry) with the bounding box of the associated * BaseGeometry. * * \warning The PlaneGeometry are not necessarily up-to-date and not even * initialized. As described in the previous paragraph, one of the * Generate-/Copy-/UpdateOutputInformation methods have to initialize it. * mitk::BaseData::GetPlaneGeometry() makes sure, that the PlaneGeometry is * up-to-date before returning it (by setting the update extent appropriately * and calling UpdateOutputInformation). * * Rule: everything is in mm (or ms for temporal information) if not * stated otherwise. * \ingroup Geometry */ #ifndef PLANEGEOMETRY_H_HEADER_INCLUDED_C1C68A2C #define PLANEGEOMETRY_H_HEADER_INCLUDED_C1C68A2C #include #include "mitkBaseGeometry.h" #include "mitkRestorePlanePositionOperation.h" #include namespace mitk { template < class TCoordRep, unsigned int NPointDimension > class Line; typedef Line Line3D; class PlaneGeometry; /** \deprecatedSince{2014_10} This class is deprecated. Please use PlaneGeometry instead. */ DEPRECATED( typedef PlaneGeometry Geometry2D); /** * \brief Describes a two-dimensional, rectangular plane * * \ingroup Geometry */ class MITKCORE_EXPORT PlaneGeometry : public BaseGeometry { public: mitkClassMacro(PlaneGeometry,BaseGeometry); /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) enum PlaneOrientation { Axial, Sagittal, Frontal }; virtual void IndexToWorld(const Point2D &pt_units, Point2D &pt_mm) const; virtual void WorldToIndex(const Point2D &pt_mm, Point2D &pt_units) const; //##Documentation //## @brief Convert (continuous or discrete) index coordinates of a \em vector //## \a vec_units to world coordinates (in mm) //## @deprecated First parameter (Point2D) is not used. If possible, please use void IndexToWorld(const mitk::Vector2D& vec_units, mitk::Vector2D& vec_mm) const. //## For further information about coordinates types, please see the Geometry documentation virtual void IndexToWorld(const mitk::Point2D &atPt2d_untis, const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const; //##Documentation //## @brief Convert (continuous or discrete) index coordinates of a \em vector //## \a vec_units to world coordinates (in mm) //## For further information about coordinates types, please see the Geometry documentation virtual void IndexToWorld(const mitk::Vector2D &vec_units, mitk::Vector2D &vec_mm) const; //##Documentation //## @brief Convert world coordinates (in mm) of a \em vector //## \a vec_mm to (continuous!) index coordinates. //## @deprecated First parameter (Point2D) is not used. If possible, please use void WorldToIndex(const mitk::Vector2D& vec_mm, mitk::Vector2D& vec_units) const. //## For further information about coordinates types, please see the Geometry documentation virtual void WorldToIndex(const mitk::Point2D &atPt2d_mm, const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const; //##Documentation //## @brief Convert world coordinates (in mm) of a \em vector //## \a vec_mm to (continuous!) index coordinates. //## For further information about coordinates types, please see the Geometry documentation virtual void WorldToIndex(const mitk::Vector2D &vec_mm, mitk::Vector2D &vec_units) const; /** * \brief Initialize a plane with orientation \a planeorientation * (default: axial) with respect to \a BaseGeometry (default: identity). * Spacing also taken from \a BaseGeometry. * * \warning A former version of this method created a geometry with unit * spacing. For unit spacing use * * \code * // for in-plane unit spacing: * thisgeometry->SetSizeInUnits(thisgeometry->GetExtentInMM(0), * thisgeometry->GetExtentInMM(1)); * // additionally, for unit spacing in normal direction (former version * // did not do this): * thisgeometry->SetExtentInMM(2, 1.0); * \endcode */ virtual void InitializeStandardPlane( const BaseGeometry* geometry3D, PlaneOrientation planeorientation = Axial, ScalarType zPosition = 0, bool frontside=true, bool rotated=false ); /** * \brief Initialize a plane with orientation \a planeorientation * (default: axial) with respect to \a BaseGeometry (default: identity). * Spacing also taken from \a BaseGeometry. * * \param top if \a true, create plane at top, otherwise at bottom * (for PlaneOrientation Axial, for other plane locations respectively) */ virtual void InitializeStandardPlane( const BaseGeometry* geometry3D, bool top, PlaneOrientation planeorientation = Axial, bool frontside=true, bool rotated=false ); /** * \brief Initialize a plane with orientation \a planeorientation * (default: axial) with respect to \a transform (default: identity) * given width and height in units. * */ virtual void InitializeStandardPlane( ScalarType width, ScalarType height, const AffineTransform3D* transform = NULL, PlaneOrientation planeorientation = Axial, ScalarType zPosition = 0, bool frontside=true, bool rotated=false ); /** * \brief Initialize plane with orientation \a planeorientation * (default: axial) given width, height and spacing. * */ virtual void InitializeStandardPlane( ScalarType width, ScalarType height, const Vector3D & spacing, PlaneOrientation planeorientation = Axial, ScalarType zPosition = 0, bool frontside = true, bool rotated = false ); /** * \brief Initialize plane by width and height in pixels, right-/down-vector * (itk) to describe orientation in world-space (vectors will be normalized) * and spacing (default: 1.0 mm in all directions). * * The vectors are normalized and multiplied by the respective spacing before * they are set in the matrix. */ virtual void InitializeStandardPlane( ScalarType width, ScalarType height, const Vector3D& rightVector, const Vector3D& downVector, const Vector3D *spacing = NULL ); /** * \brief Initialize plane by width and height in pixels, * right-/down-vector (vnl) to describe orientation in world-space (vectors * will be normalized) and spacing (default: 1.0 mm in all directions). * * The vectors are normalized and multiplied by the respective spacing * before they are set in the matrix. */ virtual void InitializeStandardPlane( ScalarType width, ScalarType height, const VnlVector& rightVector, const VnlVector& downVector, const Vector3D * spacing = NULL ); /** * \brief Initialize plane by right-/down-vector (itk) and spacing * (default: 1.0 mm in all directions). * * The length of the right-/-down-vector is used as width/height in units, * respectively. Then, the vectors are normalized and multiplied by the * respective spacing before they are set in the matrix. */ virtual void InitializeStandardPlane( const Vector3D& rightVector, const Vector3D& downVector, const Vector3D * spacing = NULL ); /** * \brief Initialize plane by right-/down-vector (vnl) and spacing * (default: 1.0 mm in all directions). * * The length of the right-/-down-vector is used as width/height in units, * respectively. Then, the vectors are normalized and multiplied by the * respective spacing before they are set in the matrix. */ virtual void InitializeStandardPlane( const VnlVector& rightVector, const VnlVector& downVector, const Vector3D * spacing = NULL ); /** * \brief Initialize plane by origin and normal (size is 1.0 mm in * all directions, direction of right-/down-vector valid but * undefined). * */ virtual void InitializePlane( const Point3D& origin, const Vector3D& normal); /** * \brief Initialize plane by right-/down-vector. * * \warning The vectors are set into the matrix as they are, * \em without normalization! */ void SetMatrixByVectors( const VnlVector& rightVector, const VnlVector& downVector, ScalarType thickness=1.0 ); /** * \brief Change \a transform so that the third column of the * transform-martix is perpendicular to the first two columns * */ static void EnsurePerpendicularNormal( AffineTransform3D* transform ); /** * \brief Normal of the plane * */ Vector3D GetNormal() const; /** * \brief Normal of the plane as VnlVector * */ VnlVector GetNormalVnl() const; virtual ScalarType SignedDistance( const Point3D& pt3d_mm ) const; /** * \brief Calculates, whether a point is below or above the plane. There are two different *calculation methods, with or without consideration of the bounding box. */ virtual bool IsAbove( const Point3D& pt3d_mm , bool considerBoundingBox=false) const; /** * \brief Distance of the point from the plane * (bounding-box \em not considered) * */ ScalarType DistanceFromPlane( const Point3D& pt3d_mm ) const ; /** * \brief Signed distance of the point from the plane * (bounding-box \em not considered) * * > 0 : point is in the direction of the direction vector. */ inline ScalarType SignedDistanceFromPlane( const Point3D& pt3d_mm ) const { ScalarType len = GetNormalVnl().two_norm(); if( len == 0 ) return 0; return (pt3d_mm-GetOrigin())*GetNormal() / len; } /** * \brief Distance of the plane from another plane * (bounding-box \em not considered) * * Result is 0 if planes are not parallel. */ ScalarType DistanceFromPlane(const PlaneGeometry* plane) const { return fabs(SignedDistanceFromPlane(plane)); } /** * \brief Signed distance of the plane from another plane * (bounding-box \em not considered) * * Result is 0 if planes are not parallel. */ inline ScalarType SignedDistanceFromPlane( const PlaneGeometry *plane ) const { if(IsParallel(plane)) { return SignedDistance(plane->GetOrigin()); } return 0; } /** * \brief Calculate the intersecting line of two planes * * \return \a true planes are intersecting * \return \a false planes do not intersect */ bool IntersectionLine( const PlaneGeometry *plane, Line3D &crossline ) const; /** * \brief Calculate two points where another plane intersects the border of this plane * * \return number of intersection points (0..2). First interection point (if existing) * is returned in \a lineFrom, second in \a lineTo. */ unsigned int IntersectWithPlane2D(const PlaneGeometry *plane, Point2D &lineFrom, Point2D &lineTo ) const ; /** * \brief Calculate the angle between two planes * * \return angle in radiants */ double Angle( const PlaneGeometry *plane ) const; /** * \brief Calculate the angle between the plane and a line * * \return angle in radiants */ double Angle( const Line3D &line ) const; /** * \brief Calculate intersection point between the plane and a line * * \param intersectionPoint intersection point * \return \a true if \em unique intersection exists, i.e., if line * is \em not on or parallel to the plane */ bool IntersectionPoint( const Line3D &line, Point3D &intersectionPoint ) const; /** * \brief Calculate line parameter of intersection point between the * plane and a line * * \param t parameter of line: intersection point is * line.GetPoint()+t*line.GetDirection() * \return \a true if \em unique intersection exists, i.e., if line * is \em not on or parallel to the plane */ bool IntersectionPointParam( const Line3D &line, double &t ) const; /** * \brief Returns whether the plane is parallel to another plane * * @return true iff the normal vectors both point to the same or exactly oposit direction */ bool IsParallel( const PlaneGeometry *plane ) const; /** * \brief Returns whether the point is on the plane * (bounding-box \em not considered) */ bool IsOnPlane( const Point3D &point ) const; /** * \brief Returns whether the line is on the plane * (bounding-box \em not considered) */ bool IsOnPlane( const Line3D &line ) const; /** * \brief Returns whether the plane is on the plane * (bounding-box \em not considered) * * @return true iff the normal vector of the planes point to the same or the exactly oposit direction and * the distance of the planes is < eps * */ bool IsOnPlane( const PlaneGeometry *plane ) const; /** * \brief Returns the lot from the point to the plane */ Point3D ProjectPointOntoPlane( const Point3D &pt ) const; virtual itk::LightObject::Pointer InternalClone() const; /** Implements operation to re-orient the plane */ virtual void ExecuteOperation( Operation *operation ); /** * \brief Project a 3D point given in mm (\a pt3d_mm) onto the 2D * geometry. The result is a 2D point in mm (\a pt2d_mm). * * The result is a 2D point in mm (\a pt2d_mm) relative to the upper-left * corner of the geometry. To convert this point into units (e.g., pixels * in case of an image), use WorldToIndex. * \return true projection was possible * \sa Project(const mitk::Point3D &pt3d_mm, mitk::Point3D * &projectedPt3d_mm) */ virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const; /** * \brief Converts a 2D point given in mm (\a pt2d_mm) relative to the * upper-left corner of the geometry into the corresponding * world-coordinate (a 3D point in mm, \a pt3d_mm). * * To convert a 2D point given in units (e.g., pixels in case of an * image) into a 2D point given in mm (as required by this method), use * IndexToWorld. */ virtual void Map(const mitk::Point2D &pt2d_mm, mitk::Point3D &pt3d_mm) const; /** * \brief Set the width and height of this 2D-geometry in units by calling * SetBounds. This does \a not change the extent in mm! * * For an image, this is the number of pixels in x-/y-direction. * \note In contrast to calling SetBounds directly, this does \a not change * the extent in mm! */ virtual void SetSizeInUnits(mitk::ScalarType width, mitk::ScalarType height); /** * \brief Project a 3D point given in mm (\a pt3d_mm) onto the 2D * geometry. The result is a 3D point in mm (\a projectedPt3d_mm). * * \return true projection was possible */ virtual bool Project(const mitk::Point3D &pt3d_mm, mitk::Point3D &projectedPt3d_mm) const; /** * \brief Project a 3D vector given in mm (\a vec3d_mm) onto the 2D * geometry. The result is a 2D vector in mm (\a vec2d_mm). * * The result is a 2D vector in mm (\a vec2d_mm) relative to the * upper-left * corner of the geometry. To convert this point into units (e.g., pixels * in case of an image), use WorldToIndex. * \return true projection was possible * \sa Project(const mitk::Vector3D &vec3d_mm, mitk::Vector3D * &projectedVec3d_mm) */ virtual bool Map(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector2D &vec2d_mm) const; /** * \brief Converts a 2D vector given in mm (\a vec2d_mm) relative to the * upper-left corner of the geometry into the corresponding * world-coordinate (a 3D vector in mm, \a vec3d_mm). * * To convert a 2D vector given in units (e.g., pixels in case of an * image) into a 2D vector given in mm (as required by this method), use * IndexToWorld. */ virtual void Map(const mitk::Point2D & atPt2d_mm, const mitk::Vector2D &vec2d_mm, mitk::Vector3D &vec3d_mm) const; /** * \brief Project a 3D vector given in mm (\a vec3d_mm) onto the 2D * geometry. The result is a 3D vector in mm (\a projectedVec3d_mm). * * DEPRECATED. Use Project(vector,vector) instead * * \return true projection was possible */ virtual bool Project(const mitk::Point3D & atPt3d_mm, const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const; /** * \brief Project a 3D vector given in mm (\a vec3d_mm) onto the 2D * geometry. The result is a 3D vector in mm (\a projectedVec3d_mm). * * \return true projection was possible */ virtual bool Project( const mitk::Vector3D &vec3d_mm, mitk::Vector3D &projectedVec3d_mm) const; /** * \brief Distance of the point from the geometry * (bounding-box \em not considered) * */ inline ScalarType Distance(const Point3D& pt3d_mm) const { return fabs(SignedDistance(pt3d_mm)); } /** * \brief Set the geometrical frame of reference in which this PlaneGeometry * is placed. * * This would usually be the BaseGeometry of the underlying dataset, but * setting it is optional. */ void SetReferenceGeometry( mitk::BaseGeometry *geometry ); /** * \brief Get the geometrical frame of reference for this PlaneGeometry. */ BaseGeometry *GetReferenceGeometry() const; bool HasReferenceGeometry() const; protected: PlaneGeometry(); PlaneGeometry(const PlaneGeometry& other); virtual ~PlaneGeometry(); virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const; /** * \brief factor to convert x-coordinates from mm to units and vice versa * */ mutable mitk::ScalarType m_ScaleFactorMMPerUnitX; /** * \brief factor to convert y-coordinates from mm to units and vice versa * */ mutable mitk::ScalarType m_ScaleFactorMMPerUnitY; mitk::BaseGeometry *m_ReferenceGeometry; //##Documentation //## @brief Pre- and Post-functions are empty in BaseGeometry //## //## These virtual functions allow for a different beahiour in subclasses. //## Do implement them in every subclass. If not needed, use {}. - virtual void PostInitialize(){}; - virtual void PostInitializeGeometry(mitk::BaseGeometry::Self * /*newGeometry*/) const{}; - virtual void PreSetSpacing(const mitk::Vector3D& /*aSpacing*/){}; - - virtual void PreSetBounds(const BoundsArrayType& /*bounds*/); - virtual void PreSetIndexToWorldTransform( AffineTransform3D * /*transform*/); - virtual void PostSetExtentInMM(int /*direction*/, ScalarType /*extentInMM*/); - virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/); + virtual void PostInitialize() {} + virtual void PostInitializeGeometry(mitk::BaseGeometry::Self * /*newGeometry*/) const {} + virtual void PreSetSpacing(const mitk::Vector3D& /*aSpacing*/) {} + + virtual void PreSetBounds(const BoundsArrayType& bounds); + virtual void PreSetIndexToWorldTransform( AffineTransform3D * transform); + virtual void PostSetExtentInMM(int direction, ScalarType extentInMM); + virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* transform); private: /** * \brief Compares plane with another plane: \a true if IsOnPlane * (bounding-box \em not considered) */ virtual bool operator==( const PlaneGeometry * ) const { return false; }; /** * \brief Compares plane with another plane: \a false if IsOnPlane * (bounding-box \em not considered) */ virtual bool operator!=( const PlaneGeometry * ) const { return false; }; }; } // namespace mitk #endif /* PLANEGEOMETRY_H_HEADER_INCLUDED_C1C68A2C */ diff --git a/Modules/Core/include/mitkPointSetVtkMapper2D.h b/Modules/Core/include/mitkPointSetVtkMapper2D.h index 75f56993f7..8f085d70f6 100644 --- a/Modules/Core/include/mitkPointSetVtkMapper2D.h +++ b/Modules/Core/include/mitkPointSetVtkMapper2D.h @@ -1,223 +1,224 @@ /*=================================================================== 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 MITKPointSetVtkMAPPER2D_H_HEADER_INCLUDED_C1902626 -#define MITKPointSetVtkMAPPER2D_H_HEADER_INCLUDED_C1902626 +#ifndef mitkPointSetVtkMapper2D_h +#define mitkPointSetVtkMapper2D_h #include +#include #include "mitkVtkMapper.h" #include "mitkBaseRenderer.h" #include "mitkLocalStorageHandler.h" -#include "mitkPointSetShapeProperty.h" -#include +//VTK +#include class vtkActor; class vtkPropAssembly; class vtkPolyData; class vtkPolyDataMapper; class vtkGlyphSource2D; class vtkGlyph3D; class vtkFloatArray; class vtkCellArray; namespace mitk { class PointSet; /** * @brief Vtk-based 2D mapper for PointSet * * Due to the need of different colors for selected * and unselected points and the facts, that we also have a contour and * labels for the points, the vtk structure is build up the following way: * * We have three PolyData, one selected, and one unselected and one * for a contour between the points. Each one is connected to an own * PolyDataMapper and an Actor. The different color for the unselected and * selected state and for the contour is read from properties. * * This mapper has several additional functionalities, such as rendering * a contour between points, calculating and displaying distances or angles * between points. * * Then the three Actors are combined inside a vtkPropAssembly and this * object is returned in GetProp() and so hooked up into the rendering * pipeline. * Properties that can be set for point sets and influence the PointSetVTKMapper2D are: * * - \b "line width": (IntProperty 2) // line width of the line from one point to another * - \b "point line width": (IntProperty 1) // line width of the cross marking a point * - \b "point 2D size": (IntProperty 6) // size of the glyph marking a point * - \b "show contour": (BoolProperty false) // enable contour rendering between points (lines) * - \b "close contour": (BoolProperty false) // if enabled, the open strip is closed (first point connected with last point) * - \b "show points": (BoolProperty true) // show or hide points * - \b "show distances": (BoolProperty false) // show or hide distance measure * - \b "distance decimal digits": (IntProperty 2) // set the number of decimal digits to be shown when rendering the distance information * - \b "show angles": (BoolProperty false) // show or hide angle measurement * - \b "show distant lines": (BoolProperty false) // show the line between to points from a distant view (equals "always on top" option) * - \b "layer": (IntProperty 1) // default is drawing pointset above images (they have a default layer of 0) * - \b "PointSet.2D.shape" (EnumerationProperty Cross) // provides different shapes marking a point * 0 = "None", 1 = "Vertex", 2 = "Dash", 3 = "Cross", 4 = "ThickCross", 5 = "Triangle", 6 = "Square", 7 = "Circle", * 8 = "Diamond", 9 = "Arrow", 10 = "ThickArrow", 11 = "HookedArrow", 12 = "Cross" * - \b "PointSet.2D.fill shape": (BoolProperty false) // fill or do not fill the glyph shape * - \b "Pointset.2D.distance to plane": (FloatProperty 4.0) //In the 2D render window, points are rendered which lie within a certain distance * to the current plane. They are projected on the current plane and scalled according to their distance. * Point markers appear smaller as the plane moves away from their true location. * The distance threshold can be adjusted by this float property, which ables the user to delineate the points * that lie exactly on the plane. (+/- rounding error) * * Other Properties used here but not defined in this class: * * - \b "selectedcolor": (ColorProperty (1.0f, 0.0f, 0.0f)) // default color of the selected pointset e.g. the current point is red * - \b "contourcolor" : (ColorProperty (1.0f, 0.0f, 0.0f)) // default color for the contour is red * - \b "color": (ColorProperty (1.0f, 1.0f, 0.0f)) // default color of the (unselected) pointset is yellow * - \b "opacity": (FloatProperty 1.0) // opacity of point set, contours * - \b "label": (StringProperty NULL) // a label can be defined for each point, which is rendered in proximity to the point * * @ingroup Mapper */ class MITKCORE_EXPORT PointSetVtkMapper2D : public VtkMapper { public: mitkClassMacro(PointSetVtkMapper2D, VtkMapper); itkFactorylessNewMacro(Self) itkCloneMacro(Self) virtual const mitk::PointSet* GetInput() const; /** \brief returns the a prop assembly */ virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); /** \brief set the default properties for this mapper */ static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); /** \brief Internal class holding the mapper, actor, etc. for each of the 3 2D render windows */ class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /* constructor */ LocalStorage(); /* destructor */ ~LocalStorage(); // points vtkSmartPointer m_UnselectedPoints; vtkSmartPointer m_SelectedPoints; vtkSmartPointer m_ContourPoints; // scales vtkSmartPointer m_UnselectedScales; vtkSmartPointer m_SelectedScales; // distances vtkSmartPointer m_DistancesBetweenPoints; // lines vtkSmartPointer m_ContourLines; // glyph source (provides different shapes for the points) vtkSmartPointer m_UnselectedGlyphSource2D; vtkSmartPointer m_SelectedGlyphSource2D; // glyph vtkSmartPointer m_UnselectedGlyph3D; vtkSmartPointer m_SelectedGlyph3D; // polydata vtkSmartPointer m_VtkUnselectedPointListPolyData; vtkSmartPointer m_VtkSelectedPointListPolyData; vtkSmartPointer m_VtkContourPolyData; // actor vtkSmartPointer m_UnselectedActor; vtkSmartPointer m_SelectedActor; vtkSmartPointer m_ContourActor; vtkSmartPointer m_VtkTextActor; std::vector < vtkSmartPointer > m_VtkTextLabelActors; std::vector < vtkSmartPointer > m_VtkTextDistanceActors; std::vector < vtkSmartPointer > m_VtkTextAngleActors; // mappers vtkSmartPointer m_VtkUnselectedPolyDataMapper; vtkSmartPointer m_VtkSelectedPolyDataMapper; vtkSmartPointer m_VtkContourPolyDataMapper; // propassembly vtkSmartPointer m_PropAssembly; }; /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::LocalStorageHandler m_LSH; protected: /* constructor */ PointSetVtkMapper2D(); /* destructor */ virtual ~PointSetVtkMapper2D(); /* \brief Applies the color and opacity properties and calls CreateVTKRenderObjects */ virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); /* \brief Called in mitk::Mapper::Update * If TimeSlicedGeometry or time step is not valid of point set: reset mapper so that nothing is * displayed e.g. toggle visiblity of the propassembly */ virtual void ResetMapper( BaseRenderer* renderer ); /* \brief Fills the vtk objects, thus it is only called when the point set has been changed. * This function iterates over the input point set and determines the glyphs which lie in a specific * range around the current slice. Those glyphs are rendered using a specific shape defined in vtk glyph source * to mark each point. The shape can be changed in MITK using the property "PointSet.2D.shape". * * There were issues when rendering vtk glyphs in the 2D-render windows. By default, the glyphs are * rendered within the x-y plane in each 2D-render window, so you would only see them from the * side in the saggital and coronal 2D-render window. The solution to this is to rotate the glyphs in order * to be ortogonal to the current view vector. To achieve this, the rotation (vtktransform) of the current * PlaneGeometry is applied to the orienation of the glyphs. */ virtual void CreateVTKRenderObjects(mitk::BaseRenderer* renderer); // member variables holding the current value of the properties used in this mapper bool m_ShowContour; // "show contour" property bool m_CloseContour; // "close contour" property bool m_ShowPoints; // "show points" property bool m_ShowDistances; // "show distances" property int m_DistancesDecimalDigits; // "distance decimal digits" property bool m_ShowAngles; // "show angles" property bool m_ShowDistantLines; // "show distant lines" property int m_LineWidth; // "line width" property int m_PointLineWidth; // "point line width" property int m_Point2DSize; // "point 2D size" property int m_IDShapeProperty; // ID for mitkPointSetShape Enumeration Property "Pointset.2D.shape" bool m_FillShape; // "Pointset.2D.fill shape" property float m_DistanceToPlane; // "Pointset.2D.distance to plane" property }; } // namespace mitk -#endif /* MITKPointSetVtkMAPPER2D_H_HEADER_INCLUDED_C1902626 */ +#endif /* mitkPointSetVtkMapper2D_h */ diff --git a/Modules/Core/include/mitkProperties.h b/Modules/Core/include/mitkProperties.h index b5657e2f58..10edd5084b 100644 --- a/Modules/Core/include/mitkProperties.h +++ b/Modules/Core/include/mitkProperties.h @@ -1,54 +1,58 @@ /*=================================================================== 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 MITKPROPERTIES_H_HEADER_INCLUDED #define MITKPROPERTIES_H_HEADER_INCLUDED #include "mitkGenericProperty.h" #include "mitkNumericTypes.h" #include "mitkLookupTables.h" namespace mitk { mitkDeclareGenericProperty(BoolProperty,bool,MITKCORE_EXPORT); mitkDeclareGenericProperty(IntProperty,int,MITKCORE_EXPORT); + mitkDeclareGenericProperty(UIntProperty,unsigned int,MITKCORE_EXPORT); + + mitkDeclareGenericProperty(UShortProperty,unsigned short,MITKCORE_EXPORT); + mitkDeclareGenericProperty(FloatProperty,float,MITKCORE_EXPORT); mitkDeclareGenericProperty(DoubleProperty,double,MITKCORE_EXPORT); mitkDeclareGenericProperty(Vector3DProperty,Vector3D,MITKCORE_EXPORT); mitkDeclareGenericProperty(Point2dProperty,Point2D,MITKCORE_EXPORT); mitkDeclareGenericProperty(Point3dProperty,Point3D,MITKCORE_EXPORT); mitkDeclareGenericProperty(Point4dProperty,Point4D,MITKCORE_EXPORT); mitkDeclareGenericProperty(Point3iProperty,Point3I,MITKCORE_EXPORT); mitkDeclareGenericProperty(FloatLookupTableProperty, FloatLookupTable,MITKCORE_EXPORT); mitkDeclareGenericProperty(BoolLookupTableProperty, BoolLookupTable,MITKCORE_EXPORT); mitkDeclareGenericProperty(IntLookupTableProperty, IntLookupTable,MITKCORE_EXPORT); mitkDeclareGenericProperty(StringLookupTableProperty, StringLookupTable,MITKCORE_EXPORT); /** * \warning If you add more specialization of GenericProperty, you must also add these to the * templated GetPropertyValue() method in mitkPropertyList.cpp! */ } // namespace mitk #endif /* MITKPROPERTIES_H_HEADER_INCLUDED */ diff --git a/Modules/Core/include/mitkSlicedGeometry3D.h b/Modules/Core/include/mitkSlicedGeometry3D.h index 82a7bd6f44..7bf25fc880 100644 --- a/Modules/Core/include/mitkSlicedGeometry3D.h +++ b/Modules/Core/include/mitkSlicedGeometry3D.h @@ -1,334 +1,335 @@ /*=================================================================== 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); + 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);}; + 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);}; + 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. virtual void ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry ); //virtual void SetTimeBounds( const mitk::TimeBounds& timebounds ); virtual const mitk::BoundingBox* GetBoundingBox() const; /** * \brief Get the number of slices */ - itkGetConstMacro( Slices, unsigned int ); + 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 void SetReferenceGeometry( BaseGeometry *referenceGeometry ); /** * \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); + 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&); + itkGetConstMacro(DirectionVector, const mitk::Vector3D&) virtual itk::LightObject::Pointer InternalClone() const; static const std::string SLICES; const static std::string DIRECTION_VECTOR; const static std::string EVENLY_SPACED; /** * \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, bool flipped=false ); /** * \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, bool flipped=false ); /** * \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 ); virtual void SetImageGeometry(const bool isAnImageGeometry); virtual void ExecuteOperation(Operation* operation); static double CalculateSpacing( const mitk::Vector3D spacing, const mitk::Vector3D &d ); protected: SlicedGeometry3D(); SlicedGeometry3D(const SlicedGeometry3D& other); virtual ~SlicedGeometry3D(); /** * 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; /** 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 */ 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 Pre- and Post-functions are empty in BaseGeometry - //## - //## These virtual functions allow for a different beahiour in subclasses. - //## Do implement them in every subclass. If not needed, use {}. - virtual void PostInitialize(){}; - virtual void PostInitializeGeometry(mitk::BaseGeometry::Self * /*newGeometry*/) const{}; - virtual void PostSetExtentInMM(int /*direction*/, ScalarType /*extentInMM*/){}; - virtual void PreSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/){}; - virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/){}; - virtual void PreSetBounds(const BoundsArrayType& /*bounds*/){}; + /** + * @brief Pre- and Post-functions are empty in BaseGeometry + * + * These virtual functions allow for a different beahiour in subclasses. + * Do implement them in every subclass. If not needed, use {}. + */ + virtual void PostInitialize() {} + virtual void PostInitializeGeometry(mitk::BaseGeometry::Self * /*newGeometry*/) const {} + virtual void PostSetExtentInMM(int /*direction*/, ScalarType /*extentInMM*/) {} + virtual void PreSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {} + virtual void PostSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {} + virtual void PreSetBounds(const BoundsArrayType& /*bounds*/) {} /** * \brief Set the spacing (m_Spacing), in direction of the plane normal. */ virtual void PreSetSpacing( const mitk::Vector3D &aSpacing ); }; } // namespace mitk #endif /* MITKSLICEDGEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD */ diff --git a/Modules/Core/include/mitkSurfaceVtkMapper2D.h b/Modules/Core/include/mitkSurfaceVtkMapper2D.h index da3e4fbdfa..72d651818a 100644 --- a/Modules/Core/include/mitkSurfaceVtkMapper2D.h +++ b/Modules/Core/include/mitkSurfaceVtkMapper2D.h @@ -1,193 +1,209 @@ /*=================================================================== 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 mitkSurfaceVtkMapper2D_h #define mitkSurfaceVtkMapper2D_h #include #include "mitkVtkMapper.h" #include "mitkBaseRenderer.h" #include "mitkLocalStorageHandler.h" //VTK #include -class vtkPropAssembly; +class vtkAssembly; class vtkCutter; class vtkPlane; class vtkLookupTable; class vtkGlyph3D; class vtkArrowSource; class vtkReverseSense; namespace mitk { class Surface; /** * @brief Vtk-based mapper for cutting 2D slices out of Surfaces. * - * The mapper uses a vtkCutter filter to cut out slices of the 3D - * volume and render these slices as vtkPolyData. + * The mapper uses a vtkCutter filter to cut out slices (contours) of the 3D + * volume and render these slices as vtkPolyData. The data is transformed + * according to its geometry before cutting, to support the geometry concept + * of MITK. * * Properties: * \b Surface.2D.Line Width: Thickness of the rendered lines in 2D. * \b Surface.2D.Normals.Draw Normals: enables drawing of normals as 3D arrows * in the 2D render window. The normals are created with a vtkGlyph3D from * the vtkPolyData. * \b Surface.2D.Normals.Draw Inverse Normals: same as normals, but in the * other direction. The inverse normals are computed with a vtkReverseSense * filter. * \b Surface.2D.Normals.(Inverse) Normals Color: Color of the (inverse) normals. * \b Surface.2D.Normals.(Inverse) Normals Scale Factor: Regulates the size of the normals. * * @ingroup Mapper */ class MITKCORE_EXPORT SurfaceVtkMapper2D : public VtkMapper { public: mitkClassMacro(SurfaceVtkMapper2D, VtkMapper); itkFactorylessNewMacro(Self) itkCloneMacro(Self) virtual const mitk::Surface* GetInput() const; /** \brief returns the prop assembly */ virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); /** \brief set the default properties for this mapper */ static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); /** \brief Internal class holding the mapper, actor, etc. for each of the 3 2D render windows */ class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** * @brief m_PropAssembly Contains all vtkProps for the final rendering. * * Consists of 3 actors: * The surface cut (the slice from the 3D surface). * The normals and the inverse normals. */ - vtkSmartPointer m_PropAssembly; + vtkSmartPointer m_PropAssembly; /** * @brief m_Actor actor for the surface cut. */ vtkSmartPointer m_Actor; /** * @brief m_NormalActor actor for the normals. */ vtkSmartPointer m_NormalActor; /** * @brief m_InverseNormalActor actor for the inverse normals. */ vtkSmartPointer m_InverseNormalActor; /** * @brief m_Mapper VTK mapper for all types of 2D polydata e.g. werewolves. */ vtkSmartPointer m_Mapper; /** * @brief m_Cutter Filter to cut out the 2D slice. */ vtkSmartPointer m_Cutter; /** * @brief m_CuttingPlane The plane where to cut off the 2D slice. */ vtkSmartPointer m_CuttingPlane; /** * @brief m_NormalMapper Mapper for the normals. */ vtkSmartPointer m_NormalMapper; /** * @brief m_InverseNormalMapper Mapper for the inverse normals. */ vtkSmartPointer m_InverseNormalMapper; /** * @brief m_NormalGlyph Glyph for creating normals. */ vtkSmartPointer m_NormalGlyph; /** * @brief m_InverseNormalGlyph Glyph for creating inverse normals. */ vtkSmartPointer m_InverseNormalGlyph; /** * @brief m_ArrowSource Arrow representation of the normals. */ vtkSmartPointer m_ArrowSource; /** * @brief m_ReverseSense Filter to invert the normals. */ vtkSmartPointer m_ReverseSense; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage(); }; /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::LocalStorageHandler m_LSH; + /** + * @brief UpdateVtkTransform Overwrite the method of the base class. + * + * The base class transforms the actor according to the respective + * geometry which is correct for most cases. This mapper, however, + * uses a vtkCutter to cut out a contour. To cut out the correct + * contour, the data has to be transformed beforehand. Else the + * current plane geometry will point the cutter to en empty location + * (if the surface does have a geometry, which is a rather rare case). + */ + void UpdateVtkTransform(mitk::BaseRenderer* /*renderer*/) + { + } + protected: /** * @brief SurfaceVtkMapper2D default constructor. */ SurfaceVtkMapper2D(); /** * @brief ~SurfaceVtkMapper2D default destructor. */ virtual ~SurfaceVtkMapper2D(); /** * @brief GenerateDataForRenderer produces all the data. * @param renderer The respective renderer of the mitkRenderWindow. */ virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); /** * @brief ResetMapper Called in mitk::Mapper::Update to hide objects. * If TimeSlicedGeometry or time step is not valid, reset the mapper. * so that nothing is displayed e.g. toggle visiblity of the propassembly. * * @param renderer The respective renderer of the mitkRenderWindow. */ virtual void ResetMapper( BaseRenderer* renderer ); /** * @brief ApplyAllProperties Pass all the properties to VTK. * @param renderer The respective renderer of the mitkRenderWindow. */ void ApplyAllProperties( BaseRenderer* renderer); /** * @brief Update Check if data should be generated. * @param renderer The respective renderer of the mitkRenderWindow. */ void Update(BaseRenderer* renderer); }; } // namespace mitk #endif /* mitkSurfaceVtkMapper2D_h */ diff --git a/Modules/Core/include/mitkSurfaceVtkMapper3D.h b/Modules/Core/include/mitkSurfaceVtkMapper3D.h index 78ddc2b1ae..2ba365655f 100644 --- a/Modules/Core/include/mitkSurfaceVtkMapper3D.h +++ b/Modules/Core/include/mitkSurfaceVtkMapper3D.h @@ -1,155 +1,149 @@ /*=================================================================== 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 MITKSURFACEDATAVTKMAPPER3D_H_HEADER_INCLUDED_C1907273 -#define MITKSURFACEDATAVTKMAPPER3D_H_HEADER_INCLUDED_C1907273 +#ifndef mitkSurfaceVtkMapper3D_h +#define mitkSurfaceVtkMapper3D_h #include +#include #include "mitkVtkMapper.h" -#include "mitkSurface.h" #include "mitkBaseRenderer.h" #include "mitkLocalStorageHandler.h" #include #include #include #include #include #include #include #include namespace mitk { -//##Documentation -//## @brief Vtk-based mapper for Surface -//## -//## @ingroup Mapper - /** - * @brief Vtk-based mapper for Surface + * @brief Vtk-based mapper for Surfaces. + * + * The mapper renders a surface in 3D. The actor is adapted according to the geometry in + * the base class in mitk::VtkMapper::UpdateVtkTransform(). * * Properties that can be set for surfaces and influence the surfaceVTKMapper3D are: * * - \b "Backface Culling": True enables backface culling, which means only front-facing polygons will be visualized. False/disabled by default. * - \b "color": (ColorProperty) Diffuse color of the surface object (this property will be read when material.diffuseColor is not defined) * - \b "Opacity": (FloatProperty) Opacity of the surface object * - \b "material.ambientColor": (ColorProperty) Ambient color of the surface object * - \b "material.ambientCoefficient": ( FloatProperty) Ambient coefficient of the surface object * - \b "material.diffuseColor": ( ColorProperty) Diffuse color of the surface object * - \b "material.diffuseCoefficient": (FloatProperty) Diffuse coefficient of the surface object * - \b "material.specularColor": (ColorProperty) Specular Color of the surface object * - \b "material.specularCoefficient": (FloatProperty) Specular coefficient of the surface object * - \b "material.specularPower": (FloatProperty) Specular power of the surface object * - \b "material.interpolation": (VtkInterpolationProperty) Interpolation * - \b "material.representation": (VtkRepresentationProperty*) Representation * - \b "material.wireframeLineWidth": (FloatProperty) Width in pixels of the lines drawn. * - \b "scalar visibility": (BoolProperty) If the scarlars of the surface are visible * - \b "Surface.TransferFunction (TransferFunctionProperty) Set a transferfunction for coloring the surface * - \b "LookupTable (LookupTableProperty) LookupTable * Properties to look for are: * * - \b "scalar visibility": if set to on, scalars assigned to the data are shown * Turn this on if using a lookup table. * - \b "ScalarsRangeMinimum": Optional. Can be used to store the scalar min, e.g. * for the level window settings. * - \b "ScalarsRangeMaximum": Optional. See above. * * There might be still some other, deprecated properties. These will not be documented anymore. * Please check the source if you really need them. * * @ingroup Mapper */ class MITKCORE_EXPORT SurfaceVtkMapper3D : public VtkMapper { public: mitkClassMacro(SurfaceVtkMapper3D, VtkMapper); itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkSetMacro(GenerateNormals, bool); itkGetMacro(GenerateNormals, bool); virtual const mitk::Surface* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); virtual void ApplyAllProperties(mitk::BaseRenderer* renderer, vtkActor* actor); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: SurfaceVtkMapper3D(); virtual ~SurfaceVtkMapper3D(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual void ResetMapper( mitk::BaseRenderer* renderer ); /** Checks whether the specified property is a ClippingProperty and if yes, * adds it to m_ClippingPlaneCollection (internal method). */ virtual void CheckForClippingProperty( mitk::BaseRenderer* renderer, mitk::BaseProperty *property ); bool m_GenerateNormals; public: class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: - vtkActor* m_Actor; - vtkPolyDataMapper *m_VtkPolyDataMapper; - vtkPolyDataNormals *m_VtkPolyDataNormals; - vtkPlaneCollection *m_ClippingPlaneCollection; + vtkSmartPointer m_Actor; + vtkSmartPointer m_VtkPolyDataMapper; + vtkSmartPointer m_VtkPolyDataNormals; + vtkSmartPointer m_ClippingPlaneCollection; vtkSmartPointer m_DepthSort; itk::TimeStamp m_ShaderTimestampUpdate; LocalStorage() { - m_VtkPolyDataMapper = vtkOpenGLPolyDataMapper::New(); - m_VtkPolyDataNormals = vtkPolyDataNormals::New(); - m_Actor = vtkActor::New(); - m_ClippingPlaneCollection = vtkPlaneCollection::New(); + m_VtkPolyDataMapper = vtkSmartPointer::New(); + m_VtkPolyDataNormals = vtkSmartPointer::New(); + m_Actor = vtkSmartPointer::New(); + m_ClippingPlaneCollection = vtkSmartPointer::New(); m_Actor->SetMapper(m_VtkPolyDataMapper); m_DepthSort = vtkSmartPointer::New(); } ~LocalStorage() { - m_VtkPolyDataMapper->Delete(); - m_VtkPolyDataNormals->Delete(); - m_Actor->Delete(); - m_ClippingPlaneCollection->Delete(); } }; mitk::LocalStorageHandler m_LSH; static void ApplyMitkPropertiesToVtkProperty(mitk::DataNode *node, vtkProperty* property, mitk::BaseRenderer* renderer); static void SetDefaultPropertiesForVtkProperty(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite); }; } // namespace mitk -#endif /* MITKSURFACEDATAVTKMAPPER3D_H_HEADER_INCLUDED_C1907273 */ \ No newline at end of file +#endif /* mitkSurfaceVtkMapper3D_h */ diff --git a/Modules/Core/include/mitkVtkMapper.h b/Modules/Core/include/mitkVtkMapper.h index 324c30c9ad..6bb8b77393 100644 --- a/Modules/Core/include/mitkVtkMapper.h +++ b/Modules/Core/include/mitkVtkMapper.h @@ -1,181 +1,188 @@ /*=================================================================== 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. ===================================================================*/ // change number #ifndef VTKMAPPER_H_HEADER_INCLUDED_C1C5453B #define VTKMAPPER_H_HEADER_INCLUDED_C1C5453B #include #include "mitkMapper.h" #include "mitkBaseRenderer.h" #include "mitkDataNode.h" #include "mitkVtkPropRenderer.h" #include "mitkLocalStorageHandler.h" #include "mitkIShaderRepository.h" #include #include #include #include #include #include #include #include #include class vtkProp; class vtkProp3D; class vtkActor; namespace mitk { /** \brief Base class of all Vtk Mappers in order to display primitives * by exploiting Vtk functionality. * * Rendering of opaque, translucent or volumetric geometry and overlays * is done in consecutive render passes. * * \ingroup Mapper */ class MITKCORE_EXPORT VtkMapper : public Mapper { public: mitkClassMacro(VtkMapper,Mapper); virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) = 0; /** \brief Re-issues all drawing commands required to describe * the entire scene each time a new frame is required, * regardless of actual changes. */ static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); /** * \brief Returns whether this is an vtk-based mapper * \deprecatedSince{2013_03} All mappers of superclass VTKMapper are vtk based, use a dynamic_cast instead */ DEPRECATED( virtual bool IsVtkBased() const ); /** \brief Determines which geometry should be rendered * (opaque, translucent, volumetric, overlay) * and calls the appropriate function. * * Called by mitk::VtkPropRenderer::Render */ void MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType type); /** \brief Checks visibility and renders the overlay */ virtual void MitkRenderOverlay(BaseRenderer* renderer); /** \brief Checks visibility and renders untransparent geometry */ virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer); /** \brief Checks visiblity and renders transparent geometry */ virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer); /** \brief Checks visibility and renders volumes */ virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer); /** \brief Returns true if this mapper owns the specified vtkProp for * the given BaseRenderer. * * Note: returns false by default; should be implemented for VTK-based * Mapper subclasses. */ virtual bool HasVtkProp( const vtkProp *prop, BaseRenderer *renderer ); /** \brief Set the vtkTransform of the m_Prop3D for * the current time step of \a renderer * - * Called by mitk::VtkPropRenderer::Update before rendering + * Called by mitk::VtkPropRenderer::Update before rendering. This + * method will transform all actors (e.g. of an vtkAssembly) according + * the geometry. + * + * \warning This method transforms only props which derive + * from vtkProp3D. Make sure to use vtkAssembly, if you have + * multiple props. vtkPropAssembly does not work, since it derives + * from vtkProp. */ virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer); /** * \brief Apply color and opacity properties read from the PropertyList * \deprecatedSince{2013_03} Use ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor * actor) instead */ DEPRECATED(inline virtual void ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer)) { ApplyColorAndOpacityProperties(renderer, actor); } /** * \brief SHADERTODO */ void ApplyShaderProperties( mitk::BaseRenderer* renderer); /** * \brief Apply color and opacity properties read from the PropertyList. * Called by mapper subclasses. */ virtual void ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor * actor); /** * \brief Release vtk-based graphics resources that are being consumed by this mapper. * * Method called by mitk::VtkPropRenderer. The parameter renderer could be used to * determine which graphic resources to release. The local storage is accessible * by the parameter renderer. Should be overwritten in subclasses. */ virtual void ReleaseGraphicsResources(mitk::BaseRenderer* /*renderer*/) { } class VtkMapperLocalStorage : public mitk::Mapper::BaseLocalStorage { public: mitk::IShaderRepository::ShaderProgram::Pointer m_ShaderProgram; itk::TimeStamp m_ModifiedTimeStamp; VtkMapperLocalStorage() { IShaderRepository* shaderRepo = CoreServices::GetShaderRepository(); if (shaderRepo) { m_ShaderProgram = shaderRepo->CreateShaderProgram(); } } ~VtkMapperLocalStorage() { } }; mitk::LocalStorageHandler m_VtkMapperLSH; protected: /** constructor */ VtkMapper(); /** virtual destructor in order to derive from this class */ virtual ~VtkMapper(); private: /** copy constructor */ VtkMapper( const VtkMapper &); /** assignment operator */ VtkMapper & operator=(const VtkMapper &); }; } // namespace mitk #endif /* VTKMAPPER_H_HEADER_INCLUDED_C1C5453B */ diff --git a/Modules/Core/include/vtkNeverTranslucentTexture.h b/Modules/Core/include/vtkNeverTranslucentTexture.h index 2dd2d5188b..77e7d7c1a5 100644 --- a/Modules/Core/include/vtkNeverTranslucentTexture.h +++ b/Modules/Core/include/vtkNeverTranslucentTexture.h @@ -1,107 +1,107 @@ /*=================================================================== 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 mitkNeverTranslucentTexture_h #define mitkNeverTranslucentTexture_h #include #include #include /** \brief VTK Fix to speed up our image rendering. The way we render images while changing the contrast via level/window extremely slows down rendering. The cause of this slowdown is that VTK asks a texture (via a call to IsTranslucent) if it is translucent. When the texture refers to a lookup table this question is answered in a most expensive way: pushing every pixel through the lookup table to see whether it would render translucent. We can speed this up extremely by always answering NO. 2D Image rendering in the context of MITK is still correct. This class is injected into the VTK system by registering it with vtkObjectFactory as a replacement for vtkTexture. We chose vtkOpenGLTexture as super class, because it seems that the other texture super class is deprecated: http://www.cmake.org/Wiki/VTK:How_I_mangled_Mesa \sa ImageVtkMapper2D */ /* NOT exported, this is a 2D image mapper helper */ -class vtkNeverTranslucentTexture : public vtkOpenGLTexture +class MITKCORE_EXPORT vtkNeverTranslucentTexture : public vtkOpenGLTexture { public: static vtkNeverTranslucentTexture* New(); vtkTypeMacro(vtkNeverTranslucentTexture, vtkTexture); void PrintSelf(ostream& os, vtkIndent indent); /** \brief The FIX (see class description). VTK Description: Is this Texture Translucent? Returns false (0) if the texture is either fully opaque or has only fully transparent pixels and fully opaque pixels and the Interpolate flag is turn off. */ virtual int IsTranslucent(); protected: vtkNeverTranslucentTexture(); private: vtkNeverTranslucentTexture(const vtkNeverTranslucentTexture&); // Not implemented. void operator=(const vtkNeverTranslucentTexture&); // Not implemented. }; /** \brief Factory for vtkNeverTranslucentTexture (see this class!). Registered in CoreActivator to replace all instances of vtkTexture with vtkNeverTranslucentTexture. Required to make rendering of images during level/window operations acceptably fast. */ class vtkNeverTranslucentTextureFactory : public vtkObjectFactory { public: vtkNeverTranslucentTextureFactory(); static vtkNeverTranslucentTextureFactory* New(); virtual const char* GetVTKSourceVersion(); const char* GetDescription(); protected: vtkNeverTranslucentTextureFactory(const vtkNeverTranslucentTextureFactory&); void operator=(const vtkNeverTranslucentTextureFactory&); }; #endif diff --git a/Modules/Core/src/DataManagement/mitkLookupTable.cpp b/Modules/Core/src/DataManagement/mitkLookupTable.cpp index 1de6effd15..35435a23e6 100644 --- a/Modules/Core/src/DataManagement/mitkLookupTable.cpp +++ b/Modules/Core/src/DataManagement/mitkLookupTable.cpp @@ -1,567 +1,567 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkLookupTable.h" #include #include #include #include #include #include #include #include const char* const mitk::LookupTable::typenameList[] = { "Grayscale", "Inverse Grayscale", "Hot Iron", "Jet", "Legacy Binary", "Legacy Rainbow Color", "Multilabel", "PET Color", "PET 20", "END_OF_ARRAY" // Do not add typenames after this entry (see QmitkDataManagerView::ColormapMenuAboutToShow()) }; mitk::LookupTable::LookupTable(): m_Window(0.0), m_Level(0.0), m_Opacity(1.0), m_type(mitk::LookupTable::GRAYSCALE) { m_LookupTable = vtkSmartPointer::New(); this->BuildGrayScaleLookupTable(); } mitk::LookupTable::LookupTable(const LookupTable& other) : itk::DataObject() , m_LookupTable(vtkSmartPointer::New()) { m_LookupTable->DeepCopy(other.m_LookupTable); } mitk::LookupTable::~LookupTable() { } void mitk::LookupTable::SetVtkLookupTable( vtkSmartPointer lut ) { if ((!lut) || (m_LookupTable == lut)) { return; } m_LookupTable = lut; this->Modified(); } void mitk::LookupTable::SetType(const mitk::LookupTable::LookupTableType type) { if (m_type == type) return; switch(type) { case (mitk::LookupTable::GRAYSCALE): this->BuildGrayScaleLookupTable(); break; case (mitk::LookupTable::INVERSE_GRAYSCALE): this->BuildInverseGrayScaleLookupTable(); break; case (mitk::LookupTable::HOT_IRON): this->BuildHotIronLookupTable(); break; case (mitk::LookupTable::JET): this->BuildJetLookupTable(); break; case (mitk::LookupTable::LEGACY_BINARY): this->BuildLegacyBinaryLookupTable(); break; case (mitk::LookupTable::MULTILABEL): this->BuildMultiLabelLookupTable(); break; case (mitk::LookupTable::PET_COLOR): this->BuildPETColorLookupTable(); break; case (mitk::LookupTable::PET_20): this->BuildPET20LookupTable(); break; case (mitk::LookupTable::LEGACY_RAINBOW_COLOR): this->BuildLegacyRainbowColorLookupTable(); break; default: MITK_ERROR << "non-existing colormap"; return; } m_type = type; } void mitk::LookupTable::SetType(const std::string& typeName) { int i = 0; std::string lutType = this->typenameList[i]; while (lutType != "END_OF_ARRAY") { if (lutType == typeName) { this->SetType(static_cast(i)); } lutType = this->typenameList[++i]; } } const std::string mitk::LookupTable::GetActiveTypeAsString() { return std::string(typenameList[(int)m_type]); } void mitk::LookupTable::ChangeOpacityForAll( float opacity ) { int noValues = m_LookupTable->GetNumberOfTableValues (); double rgba[ 4 ]; for ( int i = 0;i < noValues;i++ ) { m_LookupTable->GetTableValue ( i, rgba ); rgba[ 3 ] = opacity; m_LookupTable->SetTableValue ( i, rgba ); } this->Modified(); // need to call modified, since LookupTableProperty seems to be unchanged so no widget-update is executed } void mitk::LookupTable::ChangeOpacity(int index, float opacity ) { int noValues = m_LookupTable->GetNumberOfTableValues (); if (index>noValues) { MITK_INFO << "could not change opacity. index exceed size of lut ... " << std::endl; return; } double rgba[ 4 ]; m_LookupTable->GetTableValue ( index, rgba ); rgba[ 3 ] = opacity; m_LookupTable->SetTableValue ( index, rgba ); this->Modified(); // need to call modified, since LookupTableProperty seems to be unchanged so no widget-update is executed } void mitk::LookupTable::GetColor(int x, double rgb[3]) { this->GetVtkLookupTable()->GetColor(x,rgb); } void mitk::LookupTable::GetTableValue(int x, double rgba[4]) { this->GetVtkLookupTable()->GetTableValue(x,rgba); } void mitk::LookupTable::SetTableValue(int x, double rgba[4]) { this->GetVtkLookupTable()->SetTableValue(x,rgba); } vtkSmartPointer mitk::LookupTable::GetVtkLookupTable() const { return m_LookupTable; } mitk::LookupTable::RawLookupTableType * mitk::LookupTable::GetRawLookupTable() const { return m_LookupTable->GetPointer( 0 ); } /*! * \brief equality operator inplementation */ bool mitk::LookupTable::operator==( const mitk::LookupTable& other ) const { if ( m_LookupTable == other.GetVtkLookupTable()) return true; vtkLookupTable* olut = other.GetVtkLookupTable(); if (olut == NULL) return false; bool equal = (m_LookupTable->GetNumberOfColors() == olut->GetNumberOfColors()) && (m_LookupTable->GetTableRange()[0] == olut->GetTableRange()[0]) && (m_LookupTable->GetTableRange()[1] == olut->GetTableRange()[1]) && (m_LookupTable->GetHueRange()[0] == olut->GetHueRange()[0]) && (m_LookupTable->GetHueRange()[1] == olut->GetHueRange()[1]) && (m_LookupTable->GetSaturationRange()[0] == olut->GetSaturationRange()[0]) && (m_LookupTable->GetSaturationRange()[1] == olut->GetSaturationRange()[1]) && (m_LookupTable->GetValueRange()[0] == olut->GetValueRange()[0]) && (m_LookupTable->GetValueRange()[1] == olut->GetValueRange()[1]) && (m_LookupTable->GetAlphaRange()[0] == olut->GetAlphaRange()[0]) && (m_LookupTable->GetAlphaRange()[1] == olut->GetAlphaRange()[1]) && (m_LookupTable->GetRamp() == olut->GetRamp()) && (m_LookupTable->GetScale() == olut->GetScale()) && (m_LookupTable->GetAlpha() == olut->GetAlpha()) && (m_LookupTable->GetTable()->GetNumberOfTuples() == olut->GetTable()->GetNumberOfTuples()); if (equal == false) return false; for (vtkIdType i=0; i < m_LookupTable->GetNumberOfTableValues(); i++) { bool tvequal = (m_LookupTable->GetTableValue(i)[0] == olut->GetTableValue(i)[0]) && (m_LookupTable->GetTableValue(i)[1] == olut->GetTableValue(i)[1]) && (m_LookupTable->GetTableValue(i)[2] == olut->GetTableValue(i)[2]) && (m_LookupTable->GetTableValue(i)[3] == olut->GetTableValue(i)[3]); if (tvequal == false) return false; } return true; } /*! * \brief un-equality operator implementation */ bool mitk::LookupTable::operator!=( const mitk::LookupTable& other ) const { return !(*this == other); } /*! * \brief assignment operator implementation */ mitk::LookupTable& mitk::LookupTable::operator=( const mitk::LookupTable& LookupTable ) { if ( this == &LookupTable ) { return * this; } else { m_LookupTable = LookupTable.GetVtkLookupTable(); return *this; } } void mitk::LookupTable::UpdateOutputInformation( ) { if ( this->GetSource( ) ) { this->GetSource( ) ->UpdateOutputInformation( ); } } void mitk::LookupTable::SetRequestedRegionToLargestPossibleRegion( ) {} bool mitk::LookupTable::RequestedRegionIsOutsideOfTheBufferedRegion( ) { return false; } bool mitk::LookupTable::VerifyRequestedRegion( ) { //normally we should check if the requested region lies within the //largest possible region. Since for lookup-tables we assume, that the //requested region is always the largest possible region, we can always //return true! return true; } void mitk::LookupTable::SetRequestedRegion(const itk::DataObject *) { //not implemented, since we always want to have the RequestedRegion //to be set to LargestPossibleRegion } vtkSmartPointer mitk::LookupTable::CreateColorTransferFunction() { vtkSmartPointer colorFunction = vtkSmartPointer::New(); mitk::LookupTable::RawLookupTableType *rawLookupTable = this->GetRawLookupTable(); int num_of_values = m_LookupTable->GetNumberOfTableValues(); double* cols = new double[3*num_of_values]; double* colsHead = cols; for (int i = 0; i(*rawLookupTable)/255.0; ++cols; ++rawLookupTable; *cols=static_cast(*rawLookupTable)/255.0; ++cols; ++rawLookupTable; *cols=static_cast(*rawLookupTable)/255.0; ++cols; ++rawLookupTable; ++rawLookupTable; } colorFunction->BuildFunctionFromTable(m_LookupTable->GetTableRange()[0], m_LookupTable->GetTableRange()[1], num_of_values, colsHead); return colorFunction; } void mitk::LookupTable::CreateColorTransferFunction(vtkColorTransferFunction*& colorFunction) { colorFunction = this->CreateColorTransferFunction(); } vtkSmartPointer mitk::LookupTable::CreateOpacityTransferFunction() { vtkSmartPointer opacityFunction = vtkSmartPointer::New(); mitk::LookupTable::RawLookupTableType *rgba = this->GetRawLookupTable(); int num_of_values=m_LookupTable->GetNumberOfTableValues(); double *alphas = new double [num_of_values]; double *alphasHead = alphas; rgba+=3; for(int i=0;i(*rgba)/255.0; ++alphas; rgba+=4; } opacityFunction->BuildFunctionFromTable(m_LookupTable->GetTableRange()[0], m_LookupTable->GetTableRange()[1], num_of_values, alphasHead); return opacityFunction; } void mitk::LookupTable::CreateOpacityTransferFunction(vtkPiecewiseFunction*& opacityFunction) { opacityFunction = this->CreateOpacityTransferFunction(); } vtkSmartPointer mitk::LookupTable::CreateGradientTransferFunction() { vtkSmartPointer gradientFunction = vtkSmartPointer::New(); mitk::LookupTable::RawLookupTableType *rgba = this->GetRawLookupTable(); int num_of_values=m_LookupTable->GetNumberOfTableValues(); double *alphas = new double [num_of_values]; double *alphasHead = alphas; rgba+=3; for(int i=0;i(*rgba)/255.0; ++alphas; rgba+=4; } gradientFunction->BuildFunctionFromTable(m_LookupTable->GetTableRange()[0], m_LookupTable->GetTableRange()[1], num_of_values, alphasHead); return gradientFunction; } void mitk::LookupTable::CreateGradientTransferFunction(vtkPiecewiseFunction*& gradientFunction) { gradientFunction = this->CreateGradientTransferFunction(); } void mitk::LookupTable::PrintSelf(std::ostream &os, itk::Indent indent) const { os << indent; m_LookupTable->PrintHeader(os, vtkIndent()); } itk::LightObject::Pointer mitk::LookupTable::InternalClone() const { itk::LightObject::Pointer result(new Self(*this)); result->UnRegister(); return result; } void mitk::LookupTable::BuildGrayScaleLookupTable() { vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetRampToLinear(); lut->SetSaturationRange( 0.0, 0.0 ); lut->SetHueRange( 0.0, 0.0 ); lut->SetValueRange( 0.0, 1.0 ); lut->Build(); m_LookupTable = lut; this->Modified(); } void mitk::LookupTable::BuildLegacyBinaryLookupTable() { vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetRampToLinear(); lut->SetSaturationRange( 0.0, 0.0 ); lut->SetHueRange( 0.0, 0.0 ); lut->SetValueRange( 0.0, 1.0 ); lut->Build(); lut->SetTableValue(0,0.0,0.0,0.0,0.0); m_LookupTable = lut; this->Modified(); } void mitk::LookupTable::BuildInverseGrayScaleLookupTable() { vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetTableRange (0, 1); lut->SetSaturationRange (0, 0); lut->SetHueRange (0, 0); lut->SetValueRange (1, 0); lut->SetAlphaRange (1, 0); lut->Build(); m_LookupTable = lut; this->Modified(); } void mitk::LookupTable::BuildHotIronLookupTable() { vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetNumberOfTableValues(256); lut->Build(); for( int i=0; i<256; i++) { lut->SetTableValue(i, (double)HotIron[i][0]/255.0, (double)HotIron[i][1]/255.0, (double)HotIron[i][2]/255.0, 1.0); } m_LookupTable = lut; this->Modified(); } void mitk::LookupTable::BuildJetLookupTable() { vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetNumberOfTableValues(256); lut->Build(); for (int i = 0; i < 256; i++) { lut->SetTableValue(i, (double)Jet[i][0] / 255.0, (double)Jet[i][1] / 255.0, (double)Jet[i][2] / 255.0, 1.0); } m_LookupTable = lut; this->Modified(); } void mitk::LookupTable::BuildPETColorLookupTable() { vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetNumberOfTableValues(256); lut->SetTableRange ( (m_Level - m_Window/2.0), (m_Level + m_Window/2.0) ); lut->Build(); for( int i=0; i<256; i++) { lut->SetTableValue(i, (double)PETColor[i][0]/255.0, (double)PETColor[i][1]/255.0, (double)PETColor[i][2]/255.0, 1.0); } m_LookupTable = lut; this->Modified(); } void mitk::LookupTable::BuildPET20LookupTable() { vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetNumberOfTableValues(256); lut->SetTableRange ( (m_Level - m_Window/2.0), (m_Level + m_Window/2.0) ); lut->Build(); for( int i=0; i<256; i++) { lut->SetTableValue(i, (double)PET20[i][0]/255.0, (double)PET20[i][1]/255.0, (double)PET20[i][2]/255.0, 1.0); } m_LookupTable = lut; this->Modified(); } void mitk::LookupTable::BuildMultiLabelLookupTable() { vtkSmartPointer lut = vtkSmartPointer::New(); - lut->SetNumberOfTableValues (256); - lut->SetTableRange ( 0, 255 ); + lut->SetNumberOfTableValues (65536); + lut->SetTableRange ( 0, 65536 ); lut->SetTableValue (0, 0.0, 0.0, 0.0, 0.0); // background lut->SetTableValue (1, 1.0, 1.0, 0.0, 0.4); lut->SetTableValue (2, 0.0, 1.0, 0.0, 0.4); lut->SetTableValue (3, 0.0, 0.0, 1.0, 0.4); lut->SetTableValue (4, 1.0, 1.0, 0.4, 0.4); lut->SetTableValue (5, 0.0, 0.4, 0.7, 0.4); lut->SetTableValue (6, 1.0, 0.0, 1.0, 0.4); lut->SetTableValue (7, 1.0, 0.5, 0.0, 0.4); lut->SetTableValue (8, 0.0, 1.0, 0.5, 0.4); lut->SetTableValue (9, 0.5, 0.0, 1.0, 0.4); lut->SetTableValue (10, 1.0, 1.0, 0.5, 0.4); lut->SetTableValue (11, 0.5, 1.0, 1.0, 0.4); lut->SetTableValue (12, 1.0, 0.5, 0.6, 0.4); lut->SetTableValue (13, 1.0, 0.3, 0.3, 0.4); lut->SetTableValue (14, 0.4, 0.7, 1.0, 0.4); lut->SetTableValue (15, 0.4, 0.5, 1.0, 0.4); lut->SetTableValue (16, 0.8, 0.5, 1.0, 0.4); lut->SetTableValue (17, 1.0, 0.3, 1.0, 0.4); lut->SetTableValue (18, 1.0, 0.5, 0.6, 0.4); lut->SetTableValue (19, 1.0, 0.5, 0.4, 0.4); lut->SetTableValue (20, 0.4, 0.5, 0.4, 0.4); lut->SetTableValue (21, 1.0, 0.5, 0.76, 0.4); lut->SetTableValue (22, 0.76, 0.4, 0.4, 0.4); lut->SetTableValue (23, 1.0, 0.5, 0.4, 0.4); lut->SetTableValue (24, 0.76, 0.3, 0.4, 0.4); lut->SetTableValue (25, 1.0, 0.3, 0.4, 0.4); - for (int i = 26; i < 256; i++) + for (int i = 26; i < 65536; i++) { if (i%12 == 0) lut->SetTableValue (i, 1.0, 0.0, 0.0, 0.4); else if (i%12 == 1) lut->SetTableValue (i, 0.0, 1.0, 0.0, 0.4); else if (i%12 == 2) lut->SetTableValue (i, 0.0, 0.0, 1.0, 0.4); else if (i%12 == 3) lut->SetTableValue (i, 1.0, 1.0, 0.0, 0.4); else if (i%12 == 4) lut->SetTableValue (i, 0.0, 1.0, 1.0, 0.4); else if (i%12 == 5) lut->SetTableValue (i, 1.0, 0.0, 1.0, 0.4); else if (i%12 == 6) lut->SetTableValue (i, 1.0, 0.5, 0.0, 0.4); else if (i%12 == 7) lut->SetTableValue (i, 0.0, 1.0, 0.5, 0.4); else if (i%12 == 8) lut->SetTableValue (i, 0.5, 0.0, 1.0, 0.4); else if (i%12 == 9) lut->SetTableValue (i, 1.0, 1.0, 0.5, 0.4); else if (i%12 == 10) lut->SetTableValue (i, 0.5, 1.0, 1.0, 0.4); else if (i%12 == 11) lut->SetTableValue (i, 1.0, 0.5, 1.0, 0.4); } m_LookupTable = lut; this->Modified(); } void mitk::LookupTable::BuildLegacyRainbowColorLookupTable() { vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetRampToLinear(); lut->SetHueRange(0.6667, 0.0); lut->SetTableRange(0.0, 20.0); lut->Build(); m_LookupTable = lut; this->Modified(); } diff --git a/Modules/Core/src/DataManagement/mitkProperties.cpp b/Modules/Core/src/DataManagement/mitkProperties.cpp index 880b64ff8d..8e531f991c 100644 --- a/Modules/Core/src/DataManagement/mitkProperties.cpp +++ b/Modules/Core/src/DataManagement/mitkProperties.cpp @@ -1,41 +1,45 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkProperties.h" mitkDefineGenericProperty(BoolProperty,bool,false); mitkDefineGenericProperty(IntProperty,int,0); +mitkDefineGenericProperty(UIntProperty,unsigned int,0); + +mitkDefineGenericProperty(UShortProperty,unsigned short,0); + mitkDefineGenericProperty(FloatProperty,float,0.0f); mitkDefineGenericProperty(DoubleProperty,double,0.0); mitkDefineGenericProperty(Vector3DProperty,Vector3D,Vector3D(0.0f)); mitkDefineGenericProperty(Point2dProperty,Point2D,Point2D::BaseArray::Filled(0.0f).GetDataPointer() ); mitkDefineGenericProperty(Point3dProperty,Point3D,Point3D::BaseArray::Filled(0.0f).GetDataPointer() ); mitkDefineGenericProperty(Point4dProperty,Point4D,Point4D::BaseArray::Filled(0.0f).GetDataPointer() ); mitkDefineGenericProperty(Point3iProperty,Point3I,Point3I::BaseArray::Filled(0).GetDataPointer() ); mitkDefineGenericProperty(FloatLookupTableProperty, FloatLookupTable, FloatLookupTable()); mitkDefineGenericProperty(BoolLookupTableProperty, BoolLookupTable, BoolLookupTable()); mitkDefineGenericProperty(IntLookupTableProperty, IntLookupTable, IntLookupTable()); mitkDefineGenericProperty(StringLookupTableProperty, StringLookupTable, StringLookupTable()); diff --git a/Modules/Core/src/IO/mitkAbstractFileReader.cpp b/Modules/Core/src/IO/mitkAbstractFileReader.cpp index 1da29fd58d..31cc02d446 100644 --- a/Modules/Core/src/IO/mitkAbstractFileReader.cpp +++ b/Modules/Core/src/IO/mitkAbstractFileReader.cpp @@ -1,414 +1,414 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include namespace mitk { AbstractFileReader::InputStream::InputStream(IFileReader* reader, std::ios_base::openmode mode) : std::istream(NULL) , m_Stream(NULL) { std::istream* stream = reader->GetInputStream(); if (stream) { this->init(stream->rdbuf()); } else { m_Stream = new std::ifstream(reader->GetInputLocation().c_str(), mode); this->init(m_Stream->rdbuf()); } } AbstractFileReader::InputStream::~InputStream() { delete m_Stream; } class AbstractFileReader::Impl : public FileReaderWriterBase { public: Impl() : FileReaderWriterBase() , m_Stream(NULL) , m_PrototypeFactory(NULL) {} Impl(const Impl& other) : FileReaderWriterBase(other) , m_Stream(NULL) , m_PrototypeFactory(NULL) {} std::string m_Location; std::string m_TmpFile; std::istream* m_Stream; us::PrototypeServiceFactory* m_PrototypeFactory; us::ServiceRegistration m_Reg; }; AbstractFileReader::AbstractFileReader() : d(new Impl) { } AbstractFileReader::~AbstractFileReader() { UnregisterService(); delete d->m_PrototypeFactory; if (!d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); } } AbstractFileReader::AbstractFileReader(const AbstractFileReader& other) : IFileReader(), d(new Impl(*other.d.get())) { } AbstractFileReader::AbstractFileReader(const CustomMimeType& mimeType, const std::string& description) : d(new Impl) { d->SetMimeType(mimeType); d->SetDescription(description); } ////////////////////// Reading ///////////////////////// std::vector AbstractFileReader::Read() { std::vector result; DataStorage::Pointer ds = StandaloneDataStorage::New().GetPointer(); this->Read(*ds); DataStorage::SetOfObjects::ConstPointer dataNodes = ds->GetAll(); for (DataStorage::SetOfObjects::ConstIterator iter = dataNodes->Begin(), iterEnd = dataNodes->End(); iter != iterEnd; ++iter) { result.push_back(iter.Value()->GetData()); } return result; } DataStorage::SetOfObjects::Pointer AbstractFileReader::Read(DataStorage& ds) { DataStorage::SetOfObjects::Pointer result = DataStorage::SetOfObjects::New(); std::vector data = this->Read(); for (std::vector::iterator iter = data.begin(); iter != data.end(); ++iter) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(*iter); this->SetDefaultDataNodeProperties(node, this->GetInputLocation()); ds.Add(node); result->InsertElement(result->Size(), node); } return result; } IFileReader::ConfidenceLevel AbstractFileReader::GetConfidenceLevel() const { if (d->m_Stream) { if (*d->m_Stream) return Supported; } else { if (itksys::SystemTools::FileExists(this->GetInputLocation().c_str(), true)) { return Supported; } } return Unsupported; } //////////// µS Registration & Properties ////////////// us::ServiceRegistration AbstractFileReader::RegisterService(us::ModuleContext* context) { if (d->m_PrototypeFactory) return us::ServiceRegistration(); if(context == NULL) { context = us::GetModuleContext(); } d->RegisterMimeType(context); if (this->GetMimeType()->GetName().empty()) { MITK_WARN << "Not registering reader due to empty MIME type."; return us::ServiceRegistration(); } struct PrototypeFactory : public us::PrototypeServiceFactory { AbstractFileReader* const m_Prototype; PrototypeFactory(AbstractFileReader* prototype) : m_Prototype(prototype) {} us::InterfaceMap GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/) { return us::MakeInterfaceMap(m_Prototype->Clone()); } void UngetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/, const us::InterfaceMap& service) { delete us::ExtractInterface(service); } }; d->m_PrototypeFactory = new PrototypeFactory(this); us::ServiceProperties props = this->GetServiceProperties(); d->m_Reg = context->RegisterService(d->m_PrototypeFactory, props); return d->m_Reg; } void AbstractFileReader::UnregisterService() { try { d->m_Reg.Unregister(); } catch (const std::exception&) {} } us::ServiceProperties AbstractFileReader::GetServiceProperties() const { us::ServiceProperties result; result[IFileReader::PROP_DESCRIPTION()] = this->GetDescription(); result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType()->GetName(); result[us::ServiceConstants::SERVICE_RANKING()] = this->GetRanking(); return result; } us::ServiceRegistration AbstractFileReader::RegisterMimeType(us::ModuleContext* context) { return d->RegisterMimeType(context); } void AbstractFileReader::SetMimeType(const CustomMimeType& mimeType) { d->SetMimeType(mimeType); } void AbstractFileReader::SetDescription(const std::string& description) { d->SetDescription(description); } void AbstractFileReader::SetRanking(int ranking) { d->SetRanking(ranking); } int AbstractFileReader::GetRanking() const { return d->GetRanking(); } std::string AbstractFileReader::GetLocalFileName() const { std::string localFileName; if (d->m_Stream) { if (d->m_TmpFile.empty()) { // write the stream contents to temporary file std::string ext = itksys::SystemTools::GetFilenameExtension(this->GetInputLocation()); std::ofstream tmpStream; localFileName = mitk::IOUtil::CreateTemporaryFile(tmpStream, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary, "XXXXXX" + ext); tmpStream << d->m_Stream->rdbuf(); d->m_TmpFile = localFileName; } else { localFileName = d->m_TmpFile; } } else { localFileName = d->m_Location; } return localFileName; } //////////////////////// Options /////////////////////// void AbstractFileReader::SetDefaultOptions(const IFileReader::Options& defaultOptions) { d->SetDefaultOptions(defaultOptions); } IFileReader::Options AbstractFileReader::GetDefaultOptions() const { return d->GetDefaultOptions(); } void AbstractFileReader::SetInput(const std::string& location) { d->m_Location = location; d->m_Stream = NULL; } void AbstractFileReader::SetInput(const std::string& location, std::istream* is) { if (d->m_Stream != is && !d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); d->m_TmpFile.clear(); } d->m_Location = location; d->m_Stream = is; } std::string AbstractFileReader::GetInputLocation() const { return d->m_Location; } std::istream*AbstractFileReader::GetInputStream() const { return d->m_Stream; } MimeType AbstractFileReader::GetRegisteredMimeType() const { return d->GetRegisteredMimeType(); } IFileReader::Options AbstractFileReader::GetOptions() const { return d->GetOptions(); } us::Any AbstractFileReader::GetOption(const std::string& name) const { return d->GetOption(name); } void AbstractFileReader::SetOptions(const Options& options) { d->SetOptions(options); } void AbstractFileReader::SetOption(const std::string& name, const us::Any& value) { d->SetOption(name, value); } ////////////////// MISC ////////////////// void AbstractFileReader::AddProgressCallback(const ProgressCallback& callback) { d->AddProgressCallback(callback); } void AbstractFileReader::RemoveProgressCallback(const ProgressCallback& callback) { d->RemoveProgressCallback(callback); } ////////////////// µS related Getters ////////////////// const CustomMimeType* AbstractFileReader::GetMimeType() const { return d->GetMimeType(); } void AbstractFileReader::SetMimeTypePrefix(const std::string& prefix) { d->SetMimeTypePrefix(prefix); } std::string AbstractFileReader::GetMimeTypePrefix() const { return d->GetMimeTypePrefix(); } std::string AbstractFileReader::GetDescription() const { return d->GetDescription(); } void AbstractFileReader::SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath) { // path if (!filePath.empty()) { mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New( itksys::SystemTools::GetFilenamePath(filePath) ); node->SetProperty(StringProperty::PATH, pathProp); } // name already defined? mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name")); if(nameProp.IsNull() || (strcmp(nameProp->GetValue(),"No Name!")==0)) { // name already defined in BaseData mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer() ); if(baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(),"No Name!")==0)) { // name neither defined in node, nor in BaseData -> name = filebasename; - nameProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenameWithoutExtension(itksys::SystemTools::GetFilenameName(filePath))); + nameProp = mitk::StringProperty::New( this->GetMimeType()->GetFilenameWithoutExtension(filePath) ); node->SetProperty("name", nameProp); } else { // name defined in BaseData! nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue()); node->SetProperty("name", nameProp); } } // visibility if(!node->GetProperty("visible")) { node->SetVisibility(true); } } } diff --git a/Modules/Core/src/IO/mitkCustomMimeType.cpp b/Modules/Core/src/IO/mitkCustomMimeType.cpp index cb938e0f0b..fca265ac1e 100644 --- a/Modules/Core/src/IO/mitkCustomMimeType.cpp +++ b/Modules/Core/src/IO/mitkCustomMimeType.cpp @@ -1,185 +1,210 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCustomMimeType.h" #include "mitkMimeType.h" #include +#include + namespace mitk { class FindCaseInsensitive { public: FindCaseInsensitive(std::string value) { lcValue.resize(value.size()); std::transform(value.begin(), value.end(), lcValue.begin(), ::tolower); } bool operator()(std::string elem) { std::transform(elem.begin(), elem.end(), elem.begin(), ::tolower); return elem == lcValue; } private: std::string lcValue; }; struct CustomMimeType::Impl { std::string m_Name; std::string m_Category; std::vector m_Extensions; std::string m_Comment; }; CustomMimeType::~CustomMimeType() { delete d; } CustomMimeType::CustomMimeType() : d(new Impl) { } CustomMimeType::CustomMimeType(const std::string& name) : d(new Impl) { d->m_Name = name; } CustomMimeType::CustomMimeType(const CustomMimeType& other) : d(new Impl(*other.d)) { } CustomMimeType::CustomMimeType(const MimeType& other) : d(new Impl) { d->m_Name = other.GetName(); d->m_Category = other.GetCategory(); d->m_Extensions = other.GetExtensions(); d->m_Comment = other.GetComment(); } CustomMimeType& CustomMimeType::operator=(const CustomMimeType& other) { CustomMimeType tmp(other); Swap(tmp); return *this; } CustomMimeType&CustomMimeType::operator=(const MimeType& other) { CustomMimeType tmp(other); Swap(tmp); return *this; } std::string CustomMimeType::GetName() const { return d->m_Name; } std::string CustomMimeType::GetCategory() const { return d->m_Category; } std::vector CustomMimeType::GetExtensions() const { return d->m_Extensions; } std::string CustomMimeType::GetComment() const { if (!d->m_Comment.empty()) return d->m_Comment; if (!d->m_Extensions.empty()) { return d->m_Extensions.front() + " File"; } return "Unknown"; } bool CustomMimeType::AppliesTo(const std::string& path) const +{ + std::string extension,filename; + return ParsePathForExtension(path,extension,filename); +} + +std::string CustomMimeType::GetExtension(const std::string& path) const +{ + std::string extension,filename; + ParsePathForExtension(path,extension,filename); + return extension; +} + +std::string CustomMimeType::GetFilenameWithoutExtension(const std::string& path) const +{ + std::string extension,filename; + ParsePathForExtension(path,extension,filename); + return filename; +} + +bool CustomMimeType::ParsePathForExtension(const std::string& path, std::string& extension, std::string& filename ) const { for (std::vector::const_iterator iter = d->m_Extensions.begin(), - iterEnd = d->m_Extensions.end(); iter != iterEnd; ++iter) + iterEnd = d->m_Extensions.end(); iter != iterEnd; ++iter) { if (!iter->empty() && path.size() >= iter->size()) { FindCaseInsensitive cmp(*iter); if (cmp(path.substr(path.size() - iter->size()))) { + extension = "." + *iter; + std::string filenameWithExtension = itksys::SystemTools::GetFilenameName(path); + filename = filenameWithExtension.substr(0,filenameWithExtension.size() - extension.size()); return true; } } } return false; } void CustomMimeType::SetName(const std::string& name) { d->m_Name = name; } void CustomMimeType::SetCategory(const std::string& category) { d->m_Category = category; } void CustomMimeType::SetExtension(const std::string& extension) { d->m_Extensions.clear(); d->m_Extensions.push_back(extension); } void CustomMimeType::AddExtension(const std::string& extension) { if (std::find_if(d->m_Extensions.begin(), d->m_Extensions.end(), FindCaseInsensitive(extension)) == d->m_Extensions.end()) { d->m_Extensions.push_back(extension); } } void CustomMimeType::SetComment(const std::string& comment) { d->m_Comment = comment; } void CustomMimeType::Swap(CustomMimeType& r) { Impl* d1 = d; d = r.d; r.d = d1; } CustomMimeType* CustomMimeType::Clone() const { return new CustomMimeType(*this); } void swap(CustomMimeType& l, CustomMimeType& r) { l.Swap(r); } } diff --git a/Modules/Core/src/IO/mitkDicomSeriesReaderService.cpp b/Modules/Core/src/IO/mitkDicomSeriesReaderService.cpp index c355574436..f8a6b20d78 100644 --- a/Modules/Core/src/IO/mitkDicomSeriesReaderService.cpp +++ b/Modules/Core/src/IO/mitkDicomSeriesReaderService.cpp @@ -1,134 +1,134 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDicomSeriesReaderService.h" #include #include #include #include #include #include namespace mitk { DicomSeriesReaderService::DicomSeriesReaderService() - : AbstractFileReader(CustomMimeType(IOMimeTypes::DICOM_MIMETYPE_NAME()), "MITK DICOM Reader") + : AbstractFileReader(CustomMimeType(IOMimeTypes::DICOM_MIMETYPE()), "MITK DICOM Reader") { this->RegisterService(); } std::vector > DicomSeriesReaderService::Read() { std::vector result; const char* previousCLocale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); std::locale previousCppLocale( std::cin.getloc() ); std::locale l( "C" ); std::cin.imbue(l); std::string fileName = this->GetLocalFileName(); if ( DicomSeriesReader::IsPhilips3DDicom(fileName) ) { MITK_INFO << "it is a Philips3D US Dicom file" << std::endl; DataNode::Pointer node = DataNode::New(); mitk::DicomSeriesReader::StringContainer stringvec; stringvec.push_back(fileName); if (DicomSeriesReader::LoadDicomSeries(stringvec, *node)) { BaseData::Pointer data = node->GetData(); StringProperty::Pointer nameProp = StringProperty::New(itksys::SystemTools::GetFilenameName(fileName)); data->GetPropertyList()->SetProperty("name", nameProp); result.push_back(data); } setlocale(LC_NUMERIC, previousCLocale); std::cin.imbue(previousCppLocale); return result; } DicomSeriesReader::FileNamesGrouping imageBlocks = DicomSeriesReader::GetSeries(itksys::SystemTools::GetFilenamePath(fileName), true); // true = group gantry tilt images const unsigned int size = imageBlocks.size(); ProgressBar::GetInstance()->AddStepsToDo(size); ProgressBar::GetInstance()->Progress(); unsigned int outputIndex = 0u; const DicomSeriesReader::FileNamesGrouping::const_iterator n_end = imageBlocks.end(); for (DicomSeriesReader::FileNamesGrouping::const_iterator n_it = imageBlocks.begin(); n_it != n_end; ++n_it) { const std::string &uid = n_it->first; DataNode::Pointer node = DataNode::New(); const DicomSeriesReader::ImageBlockDescriptor& imageBlockDescriptor( n_it->second ); MITK_INFO << "--------------------------------------------------------------------------------"; MITK_INFO << "DicomSeriesReader: Loading DICOM series " << outputIndex << ": Series UID " << imageBlockDescriptor.GetSeriesInstanceUID() << std::endl; MITK_INFO << " " << imageBlockDescriptor.GetFilenames().size() << " '" << imageBlockDescriptor.GetModality() << "' files (" << imageBlockDescriptor.GetSOPClassUIDAsString() << ") loaded into 1 mitk::Image"; MITK_INFO << " multi-frame: " << (imageBlockDescriptor.IsMultiFrameImage()?"Yes":"No"); MITK_INFO << " reader support: " << DicomSeriesReader::ReaderImplementationLevelToString(imageBlockDescriptor.GetReaderImplementationLevel()); MITK_INFO << " pixel spacing type: " << DicomSeriesReader::PixelSpacingInterpretationToString( imageBlockDescriptor.GetPixelSpacingType() ); MITK_INFO << " gantry tilt corrected: " << (imageBlockDescriptor.HasGantryTiltCorrected()?"Yes":"No"); MITK_INFO << " 3D+t: " << (imageBlockDescriptor.HasMultipleTimePoints()?"Yes":"No"); MITK_INFO << "--------------------------------------------------------------------------------"; if (DicomSeriesReader::LoadDicomSeries(n_it->second.GetFilenames(), *node, true, true, true)) { BaseData::Pointer data = node->GetData(); PropertyList::Pointer dataProps = data->GetPropertyList(); std::string nodeName(uid); std::string studyDescription; if ( dataProps->GetStringProperty( "dicom.study.StudyDescription", studyDescription ) ) { nodeName = studyDescription; std::string seriesDescription; if ( dataProps->GetStringProperty( "dicom.series.SeriesDescription", seriesDescription ) ) { nodeName += "/" + seriesDescription; } } StringProperty::Pointer nameProp = StringProperty::New(nodeName); data->SetProperty("name", nameProp); result.push_back(data); ++outputIndex; } else { MITK_ERROR << "DicomSeriesReader: Skipping series " << outputIndex << " due to some unspecified error..." << std::endl; } ProgressBar::GetInstance()->Progress(); } setlocale(LC_NUMERIC, previousCLocale); std::cin.imbue(previousCppLocale); return result; } DicomSeriesReaderService* DicomSeriesReaderService::Clone() const { return new DicomSeriesReaderService(*this); } } diff --git a/Modules/Core/src/IO/mitkPointSetReaderService.cpp b/Modules/Core/src/IO/mitkPointSetReaderService.cpp index e26b0a7be2..955d587de2 100644 --- a/Modules/Core/src/IO/mitkPointSetReaderService.cpp +++ b/Modules/Core/src/IO/mitkPointSetReaderService.cpp @@ -1,130 +1,130 @@ /*=================================================================== 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. ===================================================================*/ // MITK #include "mitkPointSetReaderService.h" #include "mitkIOMimeTypes.h" // STL #include #include #include #include mitk::PointSetReaderService::PointSetReaderService() - : AbstractFileReader(CustomMimeType(IOMimeTypes::POINTSET_MIMETYPE_NAME()), "MITK Point Set Reader") + : AbstractFileReader(CustomMimeType(IOMimeTypes::POINTSET_MIMETYPE()), "MITK Point Set Reader") { RegisterService(); } mitk::PointSetReaderService::~PointSetReaderService() {} std::vector< itk::SmartPointer > mitk::PointSetReaderService::Read() { // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); std::vector< itk::SmartPointer > result; InputStream stream(this); TiXmlDocument doc; stream >> doc; if (!doc.Error()) { TiXmlHandle docHandle( &doc ); //unsigned int pointSetCounter(0); for( TiXmlElement* currentPointSetElement = docHandle.FirstChildElement("point_set_file").FirstChildElement("point_set").ToElement(); currentPointSetElement != NULL; currentPointSetElement = currentPointSetElement->NextSiblingElement()) { mitk::PointSet::Pointer newPointSet = mitk::PointSet::New(); if(currentPointSetElement->FirstChildElement("time_series") != NULL) { for( TiXmlElement* currentTimeSeries = currentPointSetElement->FirstChildElement("time_series")->ToElement(); currentTimeSeries != NULL; currentTimeSeries = currentTimeSeries->NextSiblingElement()) { unsigned int currentTimeStep(0); TiXmlElement* currentTimeSeriesID = currentTimeSeries->FirstChildElement("time_series_id"); currentTimeStep = atoi(currentTimeSeriesID->GetText()); newPointSet = this->ReadPoint(newPointSet, currentTimeSeries, currentTimeStep); } } else { newPointSet = this->ReadPoint(newPointSet, currentPointSetElement, 0); } result.push_back( newPointSet.GetPointer() ); } } else { mitkThrow() << "Parsing error at line " << doc.ErrorRow() << ", col " << doc.ErrorCol() << ": " << doc.ErrorDesc(); } return result; } mitk::PointSet::Pointer mitk::PointSetReaderService::ReadPoint(mitk::PointSet::Pointer newPointSet, TiXmlElement* currentTimeSeries, unsigned int currentTimeStep) { if(currentTimeSeries->FirstChildElement("point") != NULL) { for( TiXmlElement* currentPoint = currentTimeSeries->FirstChildElement("point")->ToElement(); currentPoint != NULL; currentPoint = currentPoint->NextSiblingElement()) { unsigned int id(0); mitk::PointSpecificationType spec((mitk::PointSpecificationType) 0); double x(0.0); double y(0.0); double z(0.0); id = atoi(currentPoint->FirstChildElement("id")->GetText()); if(currentPoint->FirstChildElement("specification") != NULL) { spec = (mitk::PointSpecificationType) atoi(currentPoint->FirstChildElement("specification")->GetText()); } x = atof(currentPoint->FirstChildElement("x")->GetText()); y = atof(currentPoint->FirstChildElement("y")->GetText()); z = atof(currentPoint->FirstChildElement("z")->GetText()); mitk::Point3D point; mitk::FillVector3D(point, x, y, z); newPointSet->SetPoint(id, point, spec, currentTimeStep); } } else { if(currentTimeStep != newPointSet->GetTimeSteps()+1) { newPointSet->Expand(currentTimeStep+1); // expand time step series with empty time step } } return newPointSet; } mitk::PointSetReaderService::PointSetReaderService(const mitk::PointSetReaderService& other) : mitk::AbstractFileReader(other) { } mitk::PointSetReaderService* mitk::PointSetReaderService::Clone() const { return new mitk::PointSetReaderService(*this); } diff --git a/Modules/Core/src/IO/mitkPointSetWriterService.cpp b/Modules/Core/src/IO/mitkPointSetWriterService.cpp index acf8e2f955..f70c461c16 100644 --- a/Modules/Core/src/IO/mitkPointSetWriterService.cpp +++ b/Modules/Core/src/IO/mitkPointSetWriterService.cpp @@ -1,194 +1,194 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPointSetWriterService.h" #include "mitkIOMimeTypes.h" #include #include #include // // Initialization of the xml tags. // const std::string mitk::PointSetWriterService::XML_POINT_SET_FILE = "point_set_file" ; const std::string mitk::PointSetWriterService::XML_FILE_VERSION = "file_version" ; const std::string mitk::PointSetWriterService::XML_POINT_SET = "point_set" ; const std::string mitk::PointSetWriterService::XML_TIME_SERIES = "time_series"; const std::string mitk::PointSetWriterService::XML_TIME_SERIES_ID = "time_series_id"; const std::string mitk::PointSetWriterService::XML_POINT = "point" ; const std::string mitk::PointSetWriterService::XML_ID = "id" ; const std::string mitk::PointSetWriterService::XML_SPEC = "specification" ; const std::string mitk::PointSetWriterService::XML_X = "x" ; const std::string mitk::PointSetWriterService::XML_Y = "y" ; const std::string mitk::PointSetWriterService::XML_Z = "z" ; const std::string mitk::PointSetWriterService::VERSION_STRING = "0.1" ; mitk::PointSetWriterService::PointSetWriterService() : AbstractFileWriter(PointSet::GetStaticNameOfClass(), - CustomMimeType(IOMimeTypes::POINTSET_MIMETYPE_NAME()), + CustomMimeType(IOMimeTypes::POINTSET_MIMETYPE()), "MITK Point Set Writer") , m_IndentDepth(0) , m_Indent(2) { RegisterService(); } mitk::PointSetWriterService::PointSetWriterService(const mitk::PointSetWriterService& other) : AbstractFileWriter(other) , m_IndentDepth(other.m_IndentDepth) , m_Indent(other.m_Indent) { } mitk::PointSetWriterService::~PointSetWriterService() {} void mitk::PointSetWriterService::Write() { OutputStream out(this); if ( !out.good() ) { mitkThrow() << "Stream not good."; } std::locale previousLocale(out.getloc()); std::locale I("C"); out.imbue(I); // // Here the actual xml writing begins // WriteXMLHeader( out ); WriteStartElement( XML_POINT_SET_FILE, out ); WriteStartElement( XML_FILE_VERSION, out ); out << VERSION_STRING; WriteEndElement( XML_FILE_VERSION, out, false ); WriteXML( static_cast(this->GetInput()), out ); WriteEndElement( XML_POINT_SET_FILE, out ); out.imbue(previousLocale); if ( !out.good() ) // some error during output { mitkThrow() << "Some error during point set writing."; } } mitk::PointSetWriterService*mitk::PointSetWriterService::Clone() const { return new PointSetWriterService(*this); } void mitk::PointSetWriterService::WriteXML( const mitk::PointSet* pointSet, std::ostream& out ) { WriteStartElement( XML_POINT_SET, out ); unsigned int timecount = pointSet->GetTimeSteps(); for(unsigned int i=0; i< timecount; i++) { WriteStartElement( XML_TIME_SERIES, out ); WriteStartElement( XML_TIME_SERIES_ID, out ); out << ConvertToString( i ); WriteEndElement( XML_TIME_SERIES_ID, out, false ); mitk::PointSet::PointsContainer* pointsContainer = pointSet->GetPointSet(i)->GetPoints(); mitk::PointSet::PointsContainer::Iterator it; for ( it = pointsContainer->Begin(); it != pointsContainer->End(); ++it ) { WriteStartElement( XML_POINT, out ); WriteStartElement( XML_ID, out ); out << ConvertToString( it->Index() ); WriteEndElement( XML_ID, out, false ); mitk::PointSet::PointType point = it->Value(); WriteStartElement( XML_SPEC, out ); out << ConvertToString( pointSet->GetSpecificationTypeInfo(it->Index(), i) ); WriteEndElement( XML_SPEC, out, false ); WriteStartElement( XML_X, out ); out << ConvertToString( point[ 0 ] ); WriteEndElement( XML_X, out, false ); WriteStartElement( XML_Y, out ); out << ConvertToString( point[ 1 ] ); WriteEndElement( XML_Y, out, false ); WriteStartElement( XML_Z, out ); out << ConvertToString( point[ 2 ] ); WriteEndElement( XML_Z, out, false ); WriteEndElement( XML_POINT, out ); } WriteEndElement( XML_TIME_SERIES, out ); } WriteEndElement( XML_POINT_SET, out ); } template < typename T> std::string mitk::PointSetWriterService::ConvertToString( T value ) { std::ostringstream o; std::locale I("C"); o.imbue(I); if ( o << value ) { return o.str(); } else { return "conversion error"; } } void mitk::PointSetWriterService::WriteXMLHeader( std::ostream &file ) { file << ""; } void mitk::PointSetWriterService::WriteStartElement( const std::string& tag, std::ostream &file ) { file << std::endl; WriteIndent( file ); file << '<' << tag << '>'; m_IndentDepth++; } void mitk::PointSetWriterService::WriteEndElement( const std::string& tag, std::ostream &file, const bool& indent ) { m_IndentDepth--; if ( indent ) { file << std::endl; WriteIndent( file ); } file << '<' << '/' << tag << '>'; } void mitk::PointSetWriterService::WriteIndent( std::ostream& file ) { std::string spaces( m_IndentDepth * m_Indent, ' ' ); file << spaces; } diff --git a/Modules/Core/src/IO/mitkRawImageFileReader.cpp b/Modules/Core/src/IO/mitkRawImageFileReader.cpp index 1a37448ac2..9db4c3fb41 100644 --- a/Modules/Core/src/IO/mitkRawImageFileReader.cpp +++ b/Modules/Core/src/IO/mitkRawImageFileReader.cpp @@ -1,182 +1,182 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRawImageFileReader.h" #include "mitkITKImageImport.h" #include "mitkImageCast.h" #include "mitkIOConstants.h" #include "mitkIOMimeTypes.h" #include #include #include mitk::RawImageFileReaderService::RawImageFileReaderService() - : AbstractFileReader(CustomMimeType(IOMimeTypes::RAW_MIMETYPE_NAME()), "ITK raw image reader") + : AbstractFileReader(CustomMimeType(IOMimeTypes::RAW_MIMETYPE()), "ITK raw image reader") { Options defaultOptions; defaultOptions[IOConstants::PIXEL_TYPE()] = IOConstants::PIXEL_TYPE_USHORT(); std::vector pixelEnum; pixelEnum.push_back(IOConstants::PIXEL_TYPE_UCHAR()); pixelEnum.push_back(IOConstants::PIXEL_TYPE_CHAR()); pixelEnum.push_back(IOConstants::PIXEL_TYPE_USHORT()); pixelEnum.push_back(IOConstants::PIXEL_TYPE_SHORT()); pixelEnum.push_back(IOConstants::PIXEL_TYPE_UINT()); pixelEnum.push_back(IOConstants::PIXEL_TYPE_INT()); pixelEnum.push_back(IOConstants::PIXEL_TYPE_FLOAT()); pixelEnum.push_back(IOConstants::PIXEL_TYPE_DOUBLE()); defaultOptions[IOConstants::PIXEL_TYPE_ENUM()] = pixelEnum; defaultOptions[IOConstants::DIMENSION()] = std::string("3"); std::vector dimEnum; dimEnum.push_back("2"); dimEnum.push_back("3"); defaultOptions[IOConstants::DIMENSION_ENUM()] = dimEnum; defaultOptions[IOConstants::ENDIANNESS()] = IOConstants::ENDIANNESS_LITTLE(); std::vector endianEnum; endianEnum.push_back(IOConstants::ENDIANNESS_LITTLE()); endianEnum.push_back(IOConstants::ENDIANNESS_BIG()); defaultOptions[IOConstants::ENDIANNESS_ENUM()] = endianEnum; defaultOptions[IOConstants::SIZE_X()] = 0; defaultOptions[IOConstants::SIZE_Y()] = 0; defaultOptions[IOConstants::SIZE_Z()] = 0; //defaultOptions[IOConstants::SIZE_T()] = 0; this->SetDefaultOptions(defaultOptions); this->RegisterService(); } mitk::RawImageFileReaderService::RawImageFileReaderService(const mitk::RawImageFileReaderService& other) : AbstractFileReader(other) { } std::vector > mitk::RawImageFileReaderService::Read() { std::vector result; const std::string path = this->GetLocalFileName(); const Options options = this->GetOptions(); const std::string dimensionality = options.find(IOConstants::DIMENSION())->second.ToString(); const std::string pixelType = options.find(IOConstants::PIXEL_TYPE())->second.ToString(); EndianityType endianity = options.find(IOConstants::ENDIANNESS())->second.ToString() == IOConstants::ENDIANNESS_LITTLE() ? LITTLE : BIG; int dimensions[4]; dimensions[0] = us::any_cast(options.find(IOConstants::SIZE_X())->second); dimensions[1] = us::any_cast(options.find(IOConstants::SIZE_Y())->second); dimensions[2] = us::any_cast(options.find(IOConstants::SIZE_Z())->second); dimensions[3] = 0 ;//us::any_cast(options.find(IOConstants::SIZE_T())->second); // check file dimensionality and pixel type and perform reading according to it if (dimensionality == "2") { if (pixelType == IOConstants::PIXEL_TYPE_CHAR()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_UCHAR()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_SHORT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_USHORT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_UINT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_INT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_FLOAT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_DOUBLE())result.push_back(TypedRead(path, endianity, dimensions)); else { MITK_INFO << "Error while reading raw file: Dimensionality or pixel type not supported or not properly set" << std::endl; } } else if (dimensionality == "3") { if (pixelType == IOConstants::PIXEL_TYPE_CHAR()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_UCHAR()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_SHORT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_USHORT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_UINT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_INT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_FLOAT()) result.push_back(TypedRead(path, endianity, dimensions)); else if (pixelType == IOConstants::PIXEL_TYPE_DOUBLE()) result.push_back(TypedRead(path, endianity, dimensions)); else { MITK_INFO << "Error while reading raw file: Dimensionality or pixel type not supported or not properly set" << std::endl; } } else { MITK_INFO << "Error while reading raw file: Dimensionality not supported" << std::endl; } return result; } template < typename TPixel, unsigned int VImageDimensions > mitk::BaseData::Pointer mitk::RawImageFileReaderService::TypedRead(const std::string& path, EndianityType endianity, int* size) { typedef itk::Image< TPixel, VImageDimensions > ImageType; typedef itk::ImageFileReader< ImageType > ReaderType; typedef itk::RawImageIO< TPixel, VImageDimensions > IOType; typename ReaderType::Pointer reader = ReaderType::New(); typename IOType::Pointer io = IOType::New(); io->SetFileDimensionality(VImageDimensions); for (unsigned short int dim = 0; dim < VImageDimensions; ++dim) { io->SetDimensions(dim, size[dim] ); } if (endianity == LITTLE) { io->SetByteOrderToLittleEndian(); } else if (endianity == BIG) { io->SetByteOrderToBigEndian(); } else { MITK_INFO << "Warning: endianity not properly set. Resulting image might be incorrect"; } reader->SetImageIO( io ); reader->SetFileName(path); try { reader->Update(); } catch( itk::ExceptionObject & err ) { MITK_ERROR <<"An error occurred during the raw image reading process: "; MITK_INFO << err << std::endl; } mitk::Image::Pointer image = mitk::Image::New(); mitk::CastToMitkImage(reader->GetOutput(), image); image->SetVolume( reader->GetOutput()->GetBufferPointer()); return image.GetPointer(); } mitk::RawImageFileReaderService*mitk::RawImageFileReaderService::Clone() const { return new RawImageFileReaderService(*this); } diff --git a/Modules/Core/src/Rendering/mitkPointSetVtkMapper2D.cpp b/Modules/Core/src/Rendering/mitkPointSetVtkMapper2D.cpp index 39c7e029c9..833c828976 100644 --- a/Modules/Core/src/Rendering/mitkPointSetVtkMapper2D.cpp +++ b/Modules/Core/src/Rendering/mitkPointSetVtkMapper2D.cpp @@ -1,714 +1,713 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPointSetVtkMapper2D.h" //mitk includes -#include "mitkDataNode.h" -#include "mitkProperties.h" #include "mitkVtkPropRenderer.h" -#include "mitkPointSet.h" -#include "mitkPlaneGeometry.h" +#include +#include +#include +#include //vtk includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include // constructor LocalStorage mitk::PointSetVtkMapper2D::LocalStorage::LocalStorage() { // points m_UnselectedPoints = vtkSmartPointer::New(); m_SelectedPoints = vtkSmartPointer::New(); m_ContourPoints = vtkSmartPointer::New(); // scales m_UnselectedScales = vtkSmartPointer::New(); m_SelectedScales = vtkSmartPointer::New(); // distances m_DistancesBetweenPoints = vtkSmartPointer::New(); // lines m_ContourLines = vtkSmartPointer::New(); // glyph source (provides the different shapes) m_UnselectedGlyphSource2D = vtkSmartPointer::New(); m_SelectedGlyphSource2D = vtkSmartPointer::New(); // glyphs m_UnselectedGlyph3D = vtkSmartPointer::New(); m_SelectedGlyph3D = vtkSmartPointer::New(); // polydata m_VtkUnselectedPointListPolyData = vtkSmartPointer::New(); m_VtkSelectedPointListPolyData = vtkSmartPointer ::New(); m_VtkContourPolyData = vtkSmartPointer::New(); // actors m_UnselectedActor = vtkSmartPointer ::New(); m_SelectedActor = vtkSmartPointer ::New(); m_ContourActor = vtkSmartPointer ::New(); // mappers m_VtkUnselectedPolyDataMapper = vtkSmartPointer::New(); m_VtkSelectedPolyDataMapper = vtkSmartPointer::New(); m_VtkContourPolyDataMapper = vtkSmartPointer::New(); // propassembly m_PropAssembly = vtkSmartPointer ::New(); } // destructor LocalStorage mitk::PointSetVtkMapper2D::LocalStorage::~LocalStorage() { } // input for this mapper ( = point set) const mitk::PointSet* mitk::PointSetVtkMapper2D::GetInput() const { return static_cast ( GetDataNode()->GetData() ); } // constructor PointSetVtkMapper2D mitk::PointSetVtkMapper2D::PointSetVtkMapper2D() : m_ShowContour(false), m_CloseContour(false), m_ShowPoints(true), m_ShowDistances(false), m_DistancesDecimalDigits(1), m_ShowAngles(false), m_ShowDistantLines(false), m_LineWidth(1), m_PointLineWidth(1), m_Point2DSize(6), m_IDShapeProperty(mitk::PointSetShapeProperty::CROSS), m_FillShape(false), m_DistanceToPlane(4.0f) { } // destructor mitk::PointSetVtkMapper2D::~PointSetVtkMapper2D() { } // reset mapper so that nothing is displayed e.g. toggle visiblity of the propassembly void mitk::PointSetVtkMapper2D::ResetMapper( BaseRenderer* renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_PropAssembly->VisibilityOff(); } // returns propassembly vtkProp* mitk::PointSetVtkMapper2D::GetVtkProp(mitk::BaseRenderer * renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); return ls->m_PropAssembly; } static bool makePerpendicularVector2D(const mitk::Vector2D& in, mitk::Vector2D& out) { // The dot product of orthogonal vectors is zero. // In two dimensions the slopes of perpendicular lines are negative reciprocals. if((fabs(in[0])>0) && ( (fabs(in[0])>fabs(in[1])) || (in[1] == 0) ) ) { // negative reciprocal out[0]=-in[1]/in[0]; out[1]=1; out.Normalize(); return true; } else if(fabs(in[1])>0) { out[0]=1; // negative reciprocal out[1]=-in[0]/in[1]; out.Normalize(); return true; } else return false; } void mitk::PointSetVtkMapper2D::CreateVTKRenderObjects(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); unsigned i = 0; // The vtk text actors need to be removed manually from the propassembly // since the same vtk text actors are not overwriten within this function, // but new actors are added to the propassembly each time this function is executed. // Thus, the actors from the last call must be removed in the beginning. for(i=0; i< ls->m_VtkTextLabelActors.size(); i++) { if(ls->m_PropAssembly->GetParts()->IsItemPresent(ls->m_VtkTextLabelActors.at(i))) ls->m_PropAssembly->RemovePart(ls->m_VtkTextLabelActors.at(i)); } for(i=0; i< ls->m_VtkTextDistanceActors.size(); i++) { if(ls->m_PropAssembly->GetParts()->IsItemPresent(ls->m_VtkTextDistanceActors.at(i))) ls->m_PropAssembly->RemovePart(ls->m_VtkTextDistanceActors.at(i)); } for(i=0; i< ls->m_VtkTextAngleActors.size(); i++) { if(ls->m_PropAssembly->GetParts()->IsItemPresent(ls->m_VtkTextAngleActors.at(i))) ls->m_PropAssembly->RemovePart(ls->m_VtkTextAngleActors.at(i)); } // initialize polydata here, otherwise we have update problems when // executing this function again ls->m_VtkUnselectedPointListPolyData = vtkSmartPointer::New(); ls->m_VtkSelectedPointListPolyData = vtkSmartPointer ::New(); ls->m_VtkContourPolyData = vtkSmartPointer::New(); // get input point set and update the PointSet mitk::PointSet::Pointer input = const_cast(this->GetInput()); // only update the input data, if the property tells us to bool update = true; this->GetDataNode()->GetBoolProperty("updateDataOnRender", update); if (update == true) input->Update(); int timestep = this->GetTimestep(); mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timestep ); if ( itkPointSet.GetPointer() == NULL) { ls->m_PropAssembly->VisibilityOff(); return; } //iterator for point set mitk::PointSet::PointsContainer::Iterator pointsIter = itkPointSet->GetPoints()->Begin(); // PointDataContainer has additional information to each point, e.g. whether // it is selected or not mitk::PointSet::PointDataContainer::Iterator pointDataIter; pointDataIter = itkPointSet->GetPointData()->Begin(); //check if the list for the PointDataContainer is the same size as the PointsContainer. //If not, then the points were inserted manually and can not be visualized according to the PointData (selected/unselected) bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size()); if( itkPointSet->GetPointData()->size() == 0 || pointDataBroken) { ls->m_PropAssembly->VisibilityOff(); return; } ls->m_PropAssembly->VisibilityOn(); // empty point sets, cellarrays, scalars ls->m_UnselectedPoints->Reset(); ls->m_SelectedPoints->Reset(); ls->m_ContourPoints->Reset(); ls->m_ContourLines->Reset(); ls->m_UnselectedScales->Reset(); ls->m_SelectedScales->Reset(); ls->m_DistancesBetweenPoints->Reset(); ls->m_VtkTextLabelActors.clear(); ls->m_VtkTextDistanceActors.clear(); ls->m_VtkTextAngleActors.clear(); ls->m_UnselectedScales->SetNumberOfComponents(3); ls->m_SelectedScales->SetNumberOfComponents(3); int NumberContourPoints = 0; bool pointsOnSameSideOfPlane = false; const int text2dDistance = 10; // initialize points with a random start value // current point in point set itk::Point point = pointsIter->Value(); mitk::Point3D p = point; // currently visited point mitk::Point3D lastP = point; // last visited point (predecessor in point set of "point") mitk::Vector3D vec; // p - lastP mitk::Vector3D lastVec; // lastP - point before lastP vec.Fill(0.0); lastVec.Fill(0.0); mitk::Point3D projected_p = point; // p projected on viewplane mitk::Point2D pt2d; pt2d[0] = point[0]; // projected_p in display coordinates pt2d[1] = point[1]; mitk::Point2D lastPt2d = pt2d; // last projected_p in display coordinates (predecessor in point set of "pt2d") mitk::Point2D preLastPt2d = pt2d ; // projected_p in display coordinates before lastPt2 mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); const mitk::PlaneGeometry* geo2D = renderer->GetCurrentWorldPlaneGeometry(); vtkLinearTransform* dataNodeTransform = input->GetGeometry()->GetVtkTransform(); int count = 0; for (pointsIter=itkPointSet->GetPoints()->Begin(); pointsIter!=itkPointSet->GetPoints()->End(); pointsIter++) { lastP = p; // valid for number of points count > 0 preLastPt2d = lastPt2d; // valid only for count > 1 lastPt2d = pt2d; // valid for number of points count > 0 lastVec = vec; // valid only for counter > 1 // get current point in point set point = pointsIter->Value(); // transform point { float vtkp[3]; itk2vtk(point, vtkp); dataNodeTransform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,point); } p[0] = point[0]; p[1] = point[1]; p[2] = point[2]; displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); vec = p-lastP; // valid only for counter > 0 // compute distance to current plane float diff = geo2D->Distance(point); diff = diff * diff; - // draw markers on slices a certain distance away from the points true location according to the tolerance threshold (m_DistanceToPlane) + //draw markers on slices a certain distance away from the points + //location according to the tolerance threshold (m_DistanceToPlane) if(diff < m_DistanceToPlane) { // is point selected or not? if (pointDataIter->Value().selected) { ls->m_SelectedPoints->InsertNextPoint(point[0],point[1],point[2]); // point is scaled according to its distance to the plane ls->m_SelectedScales->InsertNextTuple3(m_Point2DSize - (2*diff),0,0); } else { ls->m_UnselectedPoints->InsertNextPoint(point[0],point[1],point[2]); // point is scaled according to its distance to the plane ls->m_UnselectedScales->InsertNextTuple3(m_Point2DSize - (2*diff),0,0); } //---- LABEL -----// - - // paint label for each point if available + //paint label for each point if available if (dynamic_cast(this->GetDataNode()->GetProperty("label")) != NULL) { const char * pointLabel = dynamic_cast( this->GetDataNode()->GetProperty("label"))->GetValue(); std::string l = pointLabel; if (input->GetSize()>1) { std::stringstream ss; ss << pointsIter->Index(); l.append(ss.str()); } ls->m_VtkTextActor = vtkSmartPointer::New(); ls->m_VtkTextActor->SetPosition(pt2d[0] + text2dDistance, pt2d[1] + text2dDistance); ls->m_VtkTextActor->SetInput(l.c_str()); ls->m_VtkTextActor->GetTextProperty()->SetOpacity( 100 ); float unselectedColor[4] = {1.0, 1.0, 0.0, 1.0}; //check if there is a color property GetDataNode()->GetColor(unselectedColor); ls->m_VtkTextActor->GetTextProperty()->SetColor(unselectedColor[0], unselectedColor[1], unselectedColor[2]); ls->m_VtkTextLabelActors.push_back(ls->m_VtkTextActor); } } // draw contour, distance text and angle text in render window // lines between points, which intersect the current plane, are drawn if( m_ShowContour && count > 0 ) { ScalarType distance = displayGeometry->GetWorldGeometry()->SignedDistance(point); ScalarType lastDistance = displayGeometry->GetWorldGeometry()->SignedDistance(lastP); pointsOnSameSideOfPlane = (distance * lastDistance) > 0.5; // Points must be on different side of plane in order to draw a contour. // If "show distant lines" is enabled this condition is disregarded. if ( !pointsOnSameSideOfPlane || m_ShowDistantLines) { vtkSmartPointer line = vtkSmartPointer::New(); ls->m_ContourPoints->InsertNextPoint(lastP[0],lastP[1],lastP[2]); line->GetPointIds()->SetId(0, NumberContourPoints); NumberContourPoints++; ls->m_ContourPoints->InsertNextPoint(point[0], point[1], point[2]); line->GetPointIds()->SetId(1, NumberContourPoints); NumberContourPoints++; ls->m_ContourLines->InsertNextCell(line); if(m_ShowDistances) // calculate and print distance between adjacent points { float distancePoints = point.EuclideanDistanceTo(lastP); std::stringstream buffer; buffer<m_VtkTextActor = vtkSmartPointer::New(); ls->m_VtkTextActor->SetPosition(pos2d[0],pos2d[1]); ls->m_VtkTextActor->SetInput(buffer.str().c_str()); ls->m_VtkTextActor->GetTextProperty()->SetColor(0.0, 1.0, 0.0); ls->m_VtkTextDistanceActors.push_back(ls->m_VtkTextActor); } if(m_ShowAngles && count > 1) // calculate and print angle between connected lines { std::stringstream buffer; - //(char) 176 is the degree sign - buffer << angle(vec.GetVnlVector(), -lastVec.GetVnlVector())*180/vnl_math::pi << (char)176; + buffer << angle(vec.GetVnlVector(), -lastVec.GetVnlVector())*180/vnl_math::pi << "°"; //compute desired display position of text Vector2D vec2d = pt2d-lastPt2d; // first arm enclosing the angle vec2d.Normalize(); Vector2D lastVec2d = lastPt2d-preLastPt2d; // second arm enclosing the angle lastVec2d.Normalize(); vec2d=vec2d-lastVec2d; // vector connecting both arms vec2d.Normalize(); // middle between two vectors that enclose the angle Vector2D pos2d = lastPt2d.GetVectorFromOrigin() + vec2d * text2dDistance * text2dDistance; ls->m_VtkTextActor = vtkSmartPointer::New(); ls->m_VtkTextActor->SetPosition(pos2d[0],pos2d[1]); ls->m_VtkTextActor->SetInput(buffer.str().c_str()); ls->m_VtkTextActor->GetTextProperty()->SetColor(0.0, 1.0, 0.0); ls->m_VtkTextAngleActors.push_back(ls->m_VtkTextActor); } } } if(pointDataIter != itkPointSet->GetPointData()->End()) { pointDataIter++; count++; } } // add each single text actor to the assembly for(i=0; i< ls->m_VtkTextLabelActors.size(); i++) { ls->m_PropAssembly->AddPart(ls->m_VtkTextLabelActors.at(i)); } for(i=0; i< ls->m_VtkTextDistanceActors.size(); i++) { ls->m_PropAssembly->AddPart(ls->m_VtkTextDistanceActors.at(i)); } for(i=0; i< ls->m_VtkTextAngleActors.size(); i++) { ls->m_PropAssembly->AddPart(ls->m_VtkTextAngleActors.at(i)); } //---- CONTOUR -----// //create lines between the points which intersect the plane if (m_ShowContour) { // draw line between first and last point which is rendered if(m_CloseContour && NumberContourPoints > 1){ vtkSmartPointer closingLine = vtkSmartPointer::New(); closingLine->GetPointIds()->SetId(0, 0); // index of first point closingLine->GetPointIds()->SetId(1, NumberContourPoints-1); // index of last point ls->m_ContourLines->InsertNextCell(closingLine); } ls->m_VtkContourPolyData->SetPoints(ls->m_ContourPoints); ls->m_VtkContourPolyData->SetLines(ls->m_ContourLines); ls->m_VtkContourPolyDataMapper->SetInputData(ls->m_VtkContourPolyData); ls->m_ContourActor->SetMapper(ls->m_VtkContourPolyDataMapper); ls->m_ContourActor->GetProperty()->SetLineWidth(m_LineWidth); ls->m_PropAssembly->AddPart(ls->m_ContourActor); } // the point set must be transformed in order to obtain the appropriate glyph orientation // according to the current view vtkSmartPointer transform = vtkSmartPointer::New(); vtkSmartPointer a,b = vtkSmartPointer::New(); a = geo2D->GetVtkTransform()->GetMatrix(); b->DeepCopy( a ); // delete transformation from matrix, only take orientation b->SetElement(3,3,1); b->SetElement(2,3,0); b->SetElement(1,3,0); b->SetElement(0,3,0); b->SetElement(3,2,0); b->SetElement(3,1,0); b->SetElement(3,0,0); transform->SetMatrix( b ); //---- UNSELECTED POINTS -----// // apply properties to glyph ls->m_UnselectedGlyphSource2D->SetGlyphType(m_IDShapeProperty); if(m_FillShape) ls->m_UnselectedGlyphSource2D->FilledOn(); else ls->m_UnselectedGlyphSource2D->FilledOff(); // apply transform vtkSmartPointer transformFilterU = vtkSmartPointer::New(); transformFilterU->SetInputConnection(ls->m_UnselectedGlyphSource2D->GetOutputPort()); transformFilterU->SetTransform(transform); ls->m_VtkUnselectedPointListPolyData->SetPoints(ls->m_UnselectedPoints); ls->m_VtkUnselectedPointListPolyData->GetPointData()->SetVectors(ls->m_UnselectedScales); // apply transform of current plane to glyphs ls->m_UnselectedGlyph3D->SetSourceConnection(transformFilterU->GetOutputPort()); ls->m_UnselectedGlyph3D->SetInputData(ls->m_VtkUnselectedPointListPolyData); ls->m_UnselectedGlyph3D->SetScaleModeToScaleByVector(); ls->m_UnselectedGlyph3D->SetVectorModeToUseVector(); ls->m_VtkUnselectedPolyDataMapper->SetInputConnection(ls->m_UnselectedGlyph3D->GetOutputPort()); ls->m_UnselectedActor->SetMapper(ls->m_VtkUnselectedPolyDataMapper); ls->m_UnselectedActor->GetProperty()->SetLineWidth(m_PointLineWidth); ls->m_PropAssembly->AddPart(ls->m_UnselectedActor); //---- SELECTED POINTS -----// ls->m_SelectedGlyphSource2D->SetGlyphTypeToDiamond(); ls->m_SelectedGlyphSource2D->CrossOn(); ls->m_SelectedGlyphSource2D->FilledOff(); // apply transform vtkSmartPointer transformFilterS = vtkSmartPointer::New(); transformFilterS->SetInputConnection(ls->m_SelectedGlyphSource2D->GetOutputPort()); transformFilterS->SetTransform(transform); ls->m_VtkSelectedPointListPolyData->SetPoints(ls->m_SelectedPoints); ls->m_VtkSelectedPointListPolyData->GetPointData()->SetVectors(ls->m_SelectedScales); // apply transform of current plane to glyphs ls->m_SelectedGlyph3D->SetSourceConnection(transformFilterS->GetOutputPort()); ls->m_SelectedGlyph3D->SetInputData(ls->m_VtkSelectedPointListPolyData); ls->m_SelectedGlyph3D->SetScaleModeToScaleByVector(); ls->m_SelectedGlyph3D->SetVectorModeToUseVector(); ls->m_VtkSelectedPolyDataMapper->SetInputConnection(ls->m_SelectedGlyph3D->GetOutputPort()); ls->m_SelectedActor->SetMapper(ls->m_VtkSelectedPolyDataMapper); ls->m_SelectedActor->GetProperty()->SetLineWidth(m_PointLineWidth); ls->m_PropAssembly->AddPart(ls->m_SelectedActor); } void mitk::PointSetVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { const mitk::DataNode* node = GetDataNode(); if( node == NULL ) return; LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // check whether the input data has been changed bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() ); // toggle visibility bool visible = true; node->GetVisibility(visible, renderer, "visible"); if(!visible) { ls->m_UnselectedActor->VisibilityOff(); ls->m_SelectedActor->VisibilityOff(); ls->m_ContourActor->VisibilityOff(); ls->m_PropAssembly->VisibilityOff(); return; }else{ ls->m_PropAssembly->VisibilityOn(); } node->GetBoolProperty("show contour", m_ShowContour, renderer); node->GetBoolProperty("close contour", m_CloseContour, renderer); node->GetBoolProperty("show points", m_ShowPoints, renderer); node->GetBoolProperty("show distances", m_ShowDistances, renderer); node->GetIntProperty("distance decimal digits", m_DistancesDecimalDigits, renderer); node->GetBoolProperty("show angles", m_ShowAngles, renderer); node->GetBoolProperty("show distant lines", m_ShowDistantLines, renderer); node->GetIntProperty("line width", m_LineWidth, renderer); node->GetIntProperty("point line width", m_PointLineWidth, renderer); node->GetIntProperty("point 2D size", m_Point2DSize, renderer); node->GetBoolProperty("Pointset.2D.fill shape", m_FillShape, renderer); node->GetFloatProperty("Pointset.2D.distance to plane", m_DistanceToPlane, renderer ); mitk::PointSetShapeProperty::Pointer shape = dynamic_cast(this->GetDataNode()->GetProperty( "Pointset.2D.shape", renderer )); if(shape.IsNotNull()) { m_IDShapeProperty = shape->GetPointSetShape(); } //check for color props and use it for rendering of selected/unselected points and contour //due to different params in VTK (double/float) we have to convert float unselectedColor[4]; double selectedColor[4]={1.0f,0.0f,0.0f,1.0f}; //red double contourColor[4]={1.0f,0.0f,0.0f,1.0f}; //red float opacity = 1.0; GetDataNode()->GetOpacity(opacity, renderer); // apply color and opacity if(m_ShowPoints) { ls->m_UnselectedActor->VisibilityOn(); ls->m_SelectedActor->VisibilityOn(); //check if there is a color property GetDataNode()->GetColor(unselectedColor); //get selected color property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; // alpha value } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; // alpha value } ls->m_SelectedActor->GetProperty()->SetColor(selectedColor); ls->m_SelectedActor->GetProperty()->SetOpacity(opacity); ls->m_UnselectedActor->GetProperty()->SetColor(unselectedColor[0],unselectedColor[1],unselectedColor[2]); ls->m_UnselectedActor->GetProperty()->SetOpacity(opacity); } else { ls->m_UnselectedActor->VisibilityOff(); ls-> m_SelectedActor->VisibilityOff(); } if (m_ShowContour) { ls->m_ContourActor->VisibilityOn(); //get contour color property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } ls->m_ContourActor->GetProperty()->SetColor(contourColor); ls->m_ContourActor->GetProperty()->SetOpacity(opacity); } else { ls->m_ContourActor->VisibilityOff(); } if(needGenerateData) { // create new vtk render objects (e.g. a circle for a point) this->CreateVTKRenderObjects(renderer); } } void mitk::PointSetVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "line width", mitk::IntProperty::New(2), renderer, overwrite ); node->AddProperty( "point line width", mitk::IntProperty::New(1), renderer, overwrite ); node->AddProperty( "point 2D size", mitk::IntProperty::New(6), renderer, overwrite ); node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "close contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "show points", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "show distances", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "distance decimal digits", mitk::IntProperty::New(2), renderer, overwrite ); node->AddProperty( "show angles", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "show distant lines", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "layer", mitk::IntProperty::New(1), renderer, overwrite ); node->AddProperty( "Pointset.2D.fill shape", mitk::BoolProperty::New(false), renderer, overwrite); // fill or do not fill the glyph shape mitk::PointSetShapeProperty::Pointer pointsetShapeProperty = mitk::PointSetShapeProperty::New(); node->AddProperty( "Pointset.2D.shape", pointsetShapeProperty, renderer, overwrite); node->AddProperty( "Pointset.2D.distance to plane", mitk::FloatProperty::New(4.0f), renderer, overwrite ); //show the point at a certain distance above/below the 2D imaging plane. Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/Core/src/Rendering/mitkSurfaceVtkMapper2D.cpp b/Modules/Core/src/Rendering/mitkSurfaceVtkMapper2D.cpp index e7819c7bc6..51d1f2867e 100644 --- a/Modules/Core/src/Rendering/mitkSurfaceVtkMapper2D.cpp +++ b/Modules/Core/src/Rendering/mitkSurfaceVtkMapper2D.cpp @@ -1,334 +1,340 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurfaceVtkMapper2D.h" //mitk includes #include #include #include "mitkVtkPropRenderer.h" #include #include #include #include #include #include //vtk includes #include #include #include #include #include -#include +#include #include #include #include #include +#include // constructor LocalStorage mitk::SurfaceVtkMapper2D::LocalStorage::LocalStorage() { m_Mapper = vtkSmartPointer::New(); m_Mapper->ScalarVisibilityOff(); m_Actor = vtkSmartPointer::New(); m_Actor->SetMapper( m_Mapper ); - m_PropAssembly = vtkSmartPointer ::New(); + m_PropAssembly = vtkSmartPointer ::New(); m_PropAssembly->AddPart( m_Actor ); m_CuttingPlane = vtkSmartPointer::New(); m_Cutter = vtkSmartPointer::New(); m_Cutter->SetCutFunction(m_CuttingPlane); m_Mapper->SetInputConnection( m_Cutter->GetOutputPort() ); m_NormalGlyph = vtkSmartPointer::New(); m_InverseNormalGlyph = vtkSmartPointer::New(); // Source for the glyph filter m_ArrowSource = vtkSmartPointer::New(); //set small default values for fast rendering m_ArrowSource->SetTipRadius(0.05); m_ArrowSource->SetTipLength(0.20); m_ArrowSource->SetTipResolution(5); m_ArrowSource->SetShaftResolution(5); m_ArrowSource->SetShaftRadius(0.01); m_NormalGlyph->SetSourceConnection(m_ArrowSource->GetOutputPort()); m_NormalGlyph->SetVectorModeToUseNormal(); m_NormalGlyph->OrientOn(); m_InverseNormalGlyph->SetSourceConnection(m_ArrowSource->GetOutputPort()); m_InverseNormalGlyph->SetVectorModeToUseNormal(); m_InverseNormalGlyph->OrientOn(); m_NormalMapper = vtkSmartPointer::New(); m_NormalMapper->SetInputConnection(m_NormalGlyph->GetOutputPort()); m_NormalMapper->ScalarVisibilityOff(); m_InverseNormalMapper = vtkSmartPointer::New(); m_InverseNormalMapper->SetInputConnection(m_NormalGlyph->GetOutputPort()); m_InverseNormalMapper->ScalarVisibilityOff(); m_NormalActor = vtkSmartPointer::New(); m_NormalActor->SetMapper(m_NormalMapper); m_InverseNormalActor = vtkSmartPointer::New(); m_InverseNormalActor->SetMapper(m_InverseNormalMapper); m_ReverseSense = vtkSmartPointer::New(); m_PropAssembly->AddPart( m_NormalActor ); } // destructor LocalStorage mitk::SurfaceVtkMapper2D::LocalStorage::~LocalStorage() { } const mitk::Surface* mitk::SurfaceVtkMapper2D::GetInput() const { return static_cast ( GetDataNode()->GetData() ); } // constructor PointSetVtkMapper2D mitk::SurfaceVtkMapper2D::SurfaceVtkMapper2D() { } mitk::SurfaceVtkMapper2D::~SurfaceVtkMapper2D() { } // reset mapper so that nothing is displayed e.g. toggle visiblity of the propassembly void mitk::SurfaceVtkMapper2D::ResetMapper( BaseRenderer* renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_PropAssembly->VisibilityOff(); } vtkProp* mitk::SurfaceVtkMapper2D::GetVtkProp(mitk::BaseRenderer * renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); return ls->m_PropAssembly; } void mitk::SurfaceVtkMapper2D::Update(mitk::BaseRenderer* renderer) { const mitk::DataNode* node = GetDataNode(); if( node == NULL ) return; bool visible = true; node->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; mitk::Surface* surface = static_cast( node->GetData() ); if ( surface == NULL ) return; // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); // Check if time step is valid const mitk::TimeGeometry *dataTimeGeometry = surface->GetTimeGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->CountTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTimeStep( this->GetTimestep() ) ) ) { return; } surface->UpdateOutputInformation(); LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); //check if something important has changed and we need to rerender if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? || (localStorage->m_LastUpdateTime < surface->GetPipelineMTime()) //Was the data modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { this->GenerateDataForRenderer( renderer ); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } void mitk::SurfaceVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { const DataNode* node = GetDataNode(); Surface* surface = static_cast( node->GetData() ); const TimeGeometry *dataTimeGeometry = surface->GetTimeGeometry(); LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); ScalarType time =renderer->GetTime(); int timestep=0; if( time > itk::NumericTraits::NonpositiveMin() ) timestep = dataTimeGeometry->TimePointToTimeStep( time ); vtkSmartPointer inputPolyData = surface->GetVtkPolyData( timestep ); if((inputPolyData==NULL) || (inputPolyData->GetNumberOfPoints() < 1 )) return; //apply color and opacity read from the PropertyList this->ApplyAllProperties(renderer); const PlaneGeometry* planeGeometry = renderer->GetCurrentWorldPlaneGeometry(); if( ( planeGeometry == NULL ) || ( !planeGeometry->IsValid() ) || ( !planeGeometry->HasReferenceGeometry() )) { return; } double origin[3]; origin[0] = planeGeometry->GetOrigin()[0]; origin[1] = planeGeometry->GetOrigin()[1]; origin[2] = planeGeometry->GetOrigin()[2]; double normal[3]; normal[0] = planeGeometry->GetNormal()[0]; normal[1] = planeGeometry->GetNormal()[1]; normal[2] = planeGeometry->GetNormal()[2]; localStorage->m_CuttingPlane->SetOrigin(origin); localStorage->m_CuttingPlane->SetNormal(normal); - - localStorage->m_Cutter->SetInputData(inputPolyData); + //Transform the data according to its geometry. + //See UpdateVtkTransform documentation for details. + vtkSmartPointer vtktransform = GetDataNode()->GetVtkTransform(this->GetTimestep()); + vtkSmartPointer filter = vtkSmartPointer::New(); + filter->SetTransform(vtktransform); + filter->SetInputData(inputPolyData); + localStorage->m_Cutter->SetInputConnection(filter->GetOutputPort()); localStorage->m_Cutter->Update(); bool generateNormals = false; node->GetBoolProperty("draw normals 2D", generateNormals); if(generateNormals) { localStorage->m_NormalGlyph->SetInputConnection( localStorage->m_Cutter->GetOutputPort() ); localStorage->m_NormalGlyph->Update(); localStorage->m_NormalMapper->SetInputConnection( localStorage->m_NormalGlyph->GetOutputPort() ); localStorage->m_PropAssembly->AddPart( localStorage->m_NormalActor ); } else { localStorage->m_NormalGlyph->SetInputConnection( NULL ); localStorage->m_PropAssembly->RemovePart( localStorage->m_NormalActor ); } bool generateInverseNormals = false; node->GetBoolProperty("invert normals", generateInverseNormals); if(generateInverseNormals) { localStorage->m_ReverseSense->SetInputConnection( localStorage->m_Cutter->GetOutputPort() ); localStorage->m_ReverseSense->ReverseCellsOff(); localStorage->m_ReverseSense->ReverseNormalsOn(); localStorage->m_InverseNormalGlyph->SetInputConnection( localStorage->m_ReverseSense->GetOutputPort() ); localStorage->m_InverseNormalGlyph->Update(); localStorage->m_InverseNormalMapper->SetInputConnection( localStorage->m_InverseNormalGlyph->GetOutputPort() ); localStorage->m_PropAssembly->AddPart( localStorage->m_InverseNormalActor ); } else { localStorage->m_ReverseSense->SetInputConnection( NULL ); localStorage->m_PropAssembly->RemovePart( localStorage->m_InverseNormalActor ); } } void mitk::SurfaceVtkMapper2D::ApplyAllProperties(mitk::BaseRenderer* renderer) { const DataNode * node = GetDataNode(); if(node == NULL) { return; } float lineWidth = 1.0f; node->GetFloatProperty("line width", lineWidth, renderer); LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); // check for color and opacity properties, use it for rendering if they exists float color[3]= { 1.0f, 1.0f, 1.0f }; node->GetColor(color, renderer, "color"); float opacity = 1.0f; node->GetOpacity(opacity, renderer, "opacity"); //Pass properties to VTK localStorage->m_Actor->GetProperty()->SetColor(color[0], color[1], color[2]); localStorage->m_Actor->GetProperty()->SetOpacity(opacity); localStorage->m_NormalActor->GetProperty()->SetOpacity(opacity); localStorage->m_InverseNormalActor->GetProperty()->SetOpacity(opacity); localStorage->m_Actor->GetProperty()->SetLineWidth(lineWidth); //By default, the cutter will also copy/compute normals of the cut //to the output polydata. The normals will influence the //vtkPolyDataMapper lightning. To view a clean cut the lighting has //to be disabled. localStorage->m_Actor->GetProperty()->SetLighting(0); bool scalarVisibility = false; node->GetBoolProperty("scalar visibility", scalarVisibility); localStorage->m_Mapper->SetScalarVisibility(scalarVisibility); //color for inverse normals float inverseNormalsColor[3]= { 1.0f, 0.0f, 0.0f }; node->GetColor(inverseNormalsColor, renderer, "back color"); localStorage->m_InverseNormalActor->GetProperty()->SetColor(inverseNormalsColor[0], inverseNormalsColor[1], inverseNormalsColor[2]); //color for normals float normalsColor[3]= { 0.0f, 1.0f, 0.0f }; node->GetColor(normalsColor, renderer, "front color"); localStorage->m_NormalActor->GetProperty()->SetColor(normalsColor[0], normalsColor[1], normalsColor[2]); //normals scaling float normalScaleFactor = 10.0f; node->GetFloatProperty( "front normal lenth (px)", normalScaleFactor, renderer ); localStorage->m_NormalGlyph->SetScaleFactor(normalScaleFactor); //inverse normals scaling float inverseNormalScaleFactor = 10.0f; node->GetFloatProperty( "back normal lenth (px)", inverseNormalScaleFactor, renderer ); localStorage->m_InverseNormalGlyph->SetScaleFactor(inverseNormalScaleFactor); } void mitk::SurfaceVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { mitk::IPropertyAliases* aliases = mitk::CoreServices::GetPropertyAliases(); node->AddProperty( "line width", FloatProperty::New(2.0f), renderer, overwrite ); aliases->AddAlias( "line width", "Surface.2D.Line Width", "Surface"); node->AddProperty( "scalar mode", VtkScalarModeProperty::New(), renderer, overwrite ); node->AddProperty( "draw normals 2D", BoolProperty::New(false), renderer, overwrite ); aliases->AddAlias( "draw normals 2D", "Surface.2D.Normals.Draw Normals", "Surface"); node->AddProperty( "invert normals", BoolProperty::New(false), renderer, overwrite ); aliases->AddAlias( "invert normals", "Surface.2D.Normals.Draw Inverse Normals", "Surface"); node->AddProperty( "front color", ColorProperty::New(0.0, 1.0, 0.0), renderer, overwrite ); aliases->AddAlias( "front color", "Surface.2D.Normals.Normals Color", "Surface"); node->AddProperty( "back color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite ); aliases->AddAlias( "back color", "Surface.2D.Normals.Inverse Normals Color", "Surface"); node->AddProperty( "front normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); aliases->AddAlias( "front normal lenth (px)", "Surface.2D.Normals.Normals Scale Factor", "Surface"); node->AddProperty( "back normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); aliases->AddAlias( "back normal lenth (px)", "Surface.2D.Normals.Inverse Normals Scale Factor", "Surface"); node->AddProperty( "layer", IntProperty::New(100), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/Core/src/Rendering/mitkSurfaceVtkMapper3D.cpp b/Modules/Core/src/Rendering/mitkSurfaceVtkMapper3D.cpp index 7bc7474084..d52d75e8f7 100644 --- a/Modules/Core/src/Rendering/mitkSurfaceVtkMapper3D.cpp +++ b/Modules/Core/src/Rendering/mitkSurfaceVtkMapper3D.cpp @@ -1,511 +1,499 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurfaceVtkMapper3D.h" -#include "mitkDataNode.h" -#include "mitkProperties.h" -#include "mitkColorProperty.h" -#include "mitkLookupTableProperty.h" -#include "mitkVtkRepresentationProperty.h" -#include "mitkVtkInterpolationProperty.h" -#include "mitkVtkScalarModeProperty.h" -#include "mitkClippingProperty.h" -#include "mitkSmartPointerProperty.h" - -//#include "mitkShaderProperty.h" -#include "mitkIShaderRepository.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include #include //VTK #include #include #include #include #include #include #include #include const mitk::Surface* mitk::SurfaceVtkMapper3D::GetInput() { return static_cast ( GetDataNode()->GetData() ); } mitk::SurfaceVtkMapper3D::SurfaceVtkMapper3D() { - // m_Prop3D = vtkActor::New(); m_GenerateNormals = false; } mitk::SurfaceVtkMapper3D::~SurfaceVtkMapper3D() { - // m_Prop3D->Delete(); } void mitk::SurfaceVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if(!visible) { ls->m_Actor->VisibilityOff(); return; } // // set the input-object at time t for the mapper // mitk::Surface::Pointer input = const_cast< mitk::Surface* >( this->GetInput() ); - vtkPolyData * polydata = input->GetVtkPolyData( this->GetTimestep() ); + vtkSmartPointer polydata = input->GetVtkPolyData( this->GetTimestep() ); if(polydata == NULL) { ls->m_Actor->VisibilityOff(); return; } if ( m_GenerateNormals ) { ls->m_VtkPolyDataNormals->SetInputData( polydata ); ls->m_VtkPolyDataMapper->SetInputConnection( ls->m_VtkPolyDataNormals->GetOutputPort() ); } else { bool depthsorting = false; GetDataNode()->GetBoolProperty("Depth Sorting", depthsorting); if (depthsorting) { ls->m_DepthSort->SetInputData( polydata ); ls->m_DepthSort->SetCamera( renderer->GetVtkRenderer()->GetActiveCamera() ); ls->m_DepthSort->SetDirectionToBackToFront(); ls->m_DepthSort->Update(); ls->m_VtkPolyDataMapper->SetInputConnection(ls->m_DepthSort->GetOutputPort()); } else { ls->m_VtkPolyDataMapper->SetInputData( polydata ); } } // // apply properties read from the PropertyList // ApplyAllProperties(renderer, ls->m_Actor); if(visible) ls->m_Actor->VisibilityOn(); } void mitk::SurfaceVtkMapper3D::ResetMapper( BaseRenderer* renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_Actor->VisibilityOff(); } void mitk::SurfaceVtkMapper3D::ApplyMitkPropertiesToVtkProperty(mitk::DataNode *node, vtkProperty* property, mitk::BaseRenderer* renderer) { // Backface culling { mitk::BoolProperty::Pointer p; node->GetProperty(p, "Backface Culling", renderer); bool useCulling = false; if(p.IsNotNull()) useCulling = p->GetValue(); property->SetBackfaceCulling(useCulling); } // Colors { double ambient [3] = { 0.5,0.5,0.0 }; double diffuse [3] = { 0.5,0.5,0.0 }; double specular[3] = { 1.0,1.0,1.0 }; float coeff_ambient = 0.5f; float coeff_diffuse = 0.5f; float coeff_specular= 0.5f; float power_specular=10.0f; // Color { mitk::ColorProperty::Pointer p; node->GetProperty(p, "color", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); ambient[0]=c.GetRed(); ambient[1]=c.GetGreen(); ambient[2]=c.GetBlue(); diffuse[0]=c.GetRed(); diffuse[1]=c.GetGreen(); diffuse[2]=c.GetBlue(); // Setting specular color to the same, make physically no real sense, however vtk rendering slows down, if these colors are different. specular[0]=c.GetRed(); specular[1]=c.GetGreen(); specular[2]=c.GetBlue(); } } // Ambient { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.ambientColor", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); ambient[0]=c.GetRed(); ambient[1]=c.GetGreen(); ambient[2]=c.GetBlue(); } } // Diffuse { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.diffuseColor", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); diffuse[0]=c.GetRed(); diffuse[1]=c.GetGreen(); diffuse[2]=c.GetBlue(); } } // Specular { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.specularColor", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); specular[0]=c.GetRed(); specular[1]=c.GetGreen(); specular[2]=c.GetBlue(); } } // Ambient coeff { node->GetFloatProperty("material.ambientCoefficient", coeff_ambient, renderer); } // Diffuse coeff { node->GetFloatProperty("material.diffuseCoefficient", coeff_diffuse, renderer); } // Specular coeff { node->GetFloatProperty("material.specularCoefficient", coeff_specular, renderer); } // Specular power { node->GetFloatProperty("material.specularPower", power_specular, renderer); } property->SetAmbient( coeff_ambient ); property->SetDiffuse( coeff_diffuse ); property->SetSpecular( coeff_specular ); property->SetSpecularPower( power_specular ); property->SetAmbientColor( ambient ); property->SetDiffuseColor( diffuse ); property->SetSpecularColor( specular ); } // Render mode { // Opacity { float opacity = 1.0f; if( node->GetOpacity(opacity,renderer) ) property->SetOpacity( opacity ); } // Wireframe line width { float lineWidth = 1; node->GetFloatProperty("material.wireframeLineWidth", lineWidth, renderer); property->SetLineWidth( lineWidth ); } // Representation { mitk::VtkRepresentationProperty::Pointer p; node->GetProperty(p, "material.representation", renderer); if(p.IsNotNull()) property->SetRepresentation( p->GetVtkRepresentation() ); } // Interpolation { mitk::VtkInterpolationProperty::Pointer p; node->GetProperty(p, "material.interpolation", renderer); if(p.IsNotNull()) property->SetInterpolation( p->GetVtkInterpolation() ); } } } void mitk::SurfaceVtkMapper3D::ApplyAllProperties( mitk::BaseRenderer* renderer, vtkActor* /*actor*/) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // Applying shading properties Superclass::ApplyColorAndOpacityProperties( renderer, ls->m_Actor ) ; this->ApplyShaderProperties(renderer); // VTK Properties ApplyMitkPropertiesToVtkProperty( this->GetDataNode(), ls->m_Actor->GetProperty(), renderer ); mitk::TransferFunctionProperty::Pointer transferFuncProp; this->GetDataNode()->GetProperty(transferFuncProp, "Surface.TransferFunction", renderer); if (transferFuncProp.IsNotNull() ) { ls->m_VtkPolyDataMapper->SetLookupTable(transferFuncProp->GetValue()->GetColorTransferFunction()); } mitk::LookupTableProperty::Pointer lookupTableProp; this->GetDataNode()->GetProperty(lookupTableProp, "LookupTable", renderer); if (lookupTableProp.IsNotNull() ) { ls->m_VtkPolyDataMapper->SetLookupTable(lookupTableProp->GetLookupTable()->GetVtkLookupTable()); } mitk::LevelWindow levelWindow; if(this->GetDataNode()->GetLevelWindow(levelWindow, renderer, "levelWindow")) { ls->m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetLowerWindowBound(),levelWindow.GetUpperWindowBound()); } else if(this->GetDataNode()->GetLevelWindow(levelWindow, renderer)) { ls->m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetLowerWindowBound(),levelWindow.GetUpperWindowBound()); } bool scalarVisibility = false; this->GetDataNode()->GetBoolProperty("scalar visibility", scalarVisibility); ls->m_VtkPolyDataMapper->SetScalarVisibility( (scalarVisibility ? 1 : 0) ); if(scalarVisibility) { mitk::VtkScalarModeProperty* scalarMode; if(this->GetDataNode()->GetProperty(scalarMode, "scalar mode", renderer)) ls->m_VtkPolyDataMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); else ls->m_VtkPolyDataMapper->SetScalarModeToDefault(); bool colorMode = false; this->GetDataNode()->GetBoolProperty("color mode", colorMode); ls->m_VtkPolyDataMapper->SetColorMode( (colorMode ? 1 : 0) ); double scalarsMin = 0; this->GetDataNode()->GetDoubleProperty("ScalarsRangeMinimum", scalarsMin, renderer); double scalarsMax = 1.0; this->GetDataNode()->GetDoubleProperty("ScalarsRangeMaximum", scalarsMax, renderer); ls->m_VtkPolyDataMapper->SetScalarRange(scalarsMin,scalarsMax); } mitk::SmartPointerProperty::Pointer imagetextureProp = dynamic_cast< mitk::SmartPointerProperty * >(GetDataNode()->GetProperty("Surface.Texture", renderer)); if(imagetextureProp.IsNotNull()) { mitk::Image* miktTexture = dynamic_cast< mitk::Image* >( imagetextureProp->GetSmartPointer().GetPointer() ); vtkSmartPointer vtkTxture = vtkSmartPointer::New(); //Either select the first slice of a volume if(miktTexture->GetDimension(2) > 1) { MITK_WARN << "3D Textures are not supported by VTK and MITK. The first slice of the volume will be used instead!"; mitk::ImageSliceSelector::Pointer sliceselector = mitk::ImageSliceSelector::New(); sliceselector->SetSliceNr(0); sliceselector->SetChannelNr(0); sliceselector->SetTimeNr(0); sliceselector->SetInput(miktTexture); sliceselector->Update(); vtkTxture->SetInputData(sliceselector->GetOutput()->GetVtkImageData()); } else //or just use the 2D image { vtkTxture->SetInputData(miktTexture->GetVtkImageData()); } //pass the texture to the actor ls->m_Actor->SetTexture(vtkTxture); if(ls->m_VtkPolyDataMapper->GetInput()->GetPointData()->GetTCoords() == NULL) { MITK_ERROR << "Surface.Texture property was set, but there are no texture coordinates. Please provide texture coordinates for the vtkPolyData via vtkPolyData->GetPointData()->SetTCoords()."; } // if no texture is set, this will also remove a previously used texture // and reset the actor to it's default behaviour } else { ls->m_Actor->SetTexture(0); } // deprecated settings bool deprecatedUseCellData = false; this->GetDataNode()->GetBoolProperty("deprecated useCellDataForColouring", deprecatedUseCellData); bool deprecatedUsePointData = false; this->GetDataNode()->GetBoolProperty("deprecated usePointDataForColouring", deprecatedUsePointData); if (deprecatedUseCellData) { ls->m_VtkPolyDataMapper->SetColorModeToDefault(); ls->m_VtkPolyDataMapper->SetScalarRange(0,255); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_VtkPolyDataMapper->SetScalarModeToUseCellData(); ls->m_Actor->GetProperty()->SetSpecular (1); ls->m_Actor->GetProperty()->SetSpecularPower (50); ls->m_Actor->GetProperty()->SetInterpolationToPhong(); } else if (deprecatedUsePointData) { float scalarsMin = 0; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != NULL) scalarsMin = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue(); float scalarsMax = 0.1; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != NULL) scalarsMax = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue(); ls->m_VtkPolyDataMapper->SetScalarRange(scalarsMin,scalarsMax); ls->m_VtkPolyDataMapper->SetColorModeToMapScalars(); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_Actor->GetProperty()->SetSpecular (1); ls->m_Actor->GetProperty()->SetSpecularPower (50); ls->m_Actor->GetProperty()->SetInterpolationToPhong(); } int deprecatedScalarMode = VTK_COLOR_MODE_DEFAULT; if(this->GetDataNode()->GetIntProperty("deprecated scalar mode", deprecatedScalarMode, renderer)) { ls->m_VtkPolyDataMapper->SetScalarMode(deprecatedScalarMode); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_Actor->GetProperty()->SetSpecular (1); ls->m_Actor->GetProperty()->SetSpecularPower (50); - //m_Actor->GetProperty()->SetInterpolationToPhong(); } // Check whether one or more ClippingProperty objects have been defined for // this node. Check both renderer specific and global property lists, since // properties in both should be considered. const PropertyList::PropertyMap *rendererProperties = this->GetDataNode()->GetPropertyList( renderer )->GetMap(); const PropertyList::PropertyMap *globalProperties = this->GetDataNode()->GetPropertyList( NULL )->GetMap(); // Add clipping planes (if any) ls->m_ClippingPlaneCollection->RemoveAllItems(); PropertyList::PropertyMap::const_iterator it; for ( it = rendererProperties->begin(); it != rendererProperties->end(); ++it ) { this->CheckForClippingProperty( renderer,(*it).second.GetPointer() ); } for ( it = globalProperties->begin(); it != globalProperties->end(); ++it ) { this->CheckForClippingProperty( renderer,(*it).second.GetPointer() ); } if ( ls->m_ClippingPlaneCollection->GetNumberOfItems() > 0 ) { ls->m_VtkPolyDataMapper->SetClippingPlanes( ls->m_ClippingPlaneCollection ); } else { ls->m_VtkPolyDataMapper->RemoveAllClippingPlanes(); } } vtkProp *mitk::SurfaceVtkMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); return ls->m_Actor; } void mitk::SurfaceVtkMapper3D::CheckForClippingProperty( mitk::BaseRenderer* renderer, mitk::BaseProperty *property ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - // m_Prop3D = ls->m_Actor; ClippingProperty *clippingProperty = dynamic_cast< ClippingProperty * >( property ); if ( (clippingProperty != NULL) && (clippingProperty->GetClippingEnabled()) ) { const Point3D &origin = clippingProperty->GetOrigin(); const Vector3D &normal = clippingProperty->GetNormal(); - vtkPlane *clippingPlane = vtkPlane::New(); + vtkSmartPointer clippingPlane = vtkSmartPointer::New(); clippingPlane->SetOrigin( origin[0], origin[1], origin[2] ); clippingPlane->SetNormal( normal[0], normal[1], normal[2] ); ls->m_ClippingPlaneCollection->AddItem( clippingPlane ); - - clippingPlane->UnRegister( NULL ); } } void mitk::SurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { // Shading { node->AddProperty( "material.wireframeLineWidth", mitk::FloatProperty::New(1.0f) , renderer, overwrite ); node->AddProperty( "material.ambientCoefficient" , mitk::FloatProperty::New(0.05f) , renderer, overwrite ); node->AddProperty( "material.diffuseCoefficient" , mitk::FloatProperty::New(0.9f) , renderer, overwrite ); node->AddProperty( "material.specularCoefficient", mitk::FloatProperty::New(1.0f) , renderer, overwrite ); node->AddProperty( "material.specularPower" , mitk::FloatProperty::New(16.0f) , renderer, overwrite ); - //node->AddProperty( "material.ambientColor" , mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); - //node->AddProperty( "material.diffuseColor" , mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); - //node->AddProperty( "material.specularColor" , mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); - node->AddProperty( "material.representation" , mitk::VtkRepresentationProperty::New() , renderer, overwrite ); node->AddProperty( "material.interpolation" , mitk::VtkInterpolationProperty::New() , renderer, overwrite ); } // Shaders IShaderRepository* shaderRepo = CoreServices::GetShaderRepository(); if (shaderRepo) { shaderRepo->AddDefaultProperties(node, renderer, overwrite); } } void mitk::SurfaceVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "color", mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New(1.0), renderer, overwrite ); mitk::SurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(node,renderer,overwrite); // Shading node->AddProperty( "scalar visibility", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "color mode", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "scalar mode", mitk::VtkScalarModeProperty::New(), renderer, overwrite ); mitk::Surface::Pointer surface = dynamic_cast(node->GetData()); if(surface.IsNotNull()) { if((surface->GetVtkPolyData() != 0) && (surface->GetVtkPolyData()->GetPointData() != NULL) && (surface->GetVtkPolyData()->GetPointData()->GetScalars() != 0)) { node->AddProperty( "scalar visibility", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "color mode", mitk::BoolProperty::New(true), renderer, overwrite ); } } // Backface culling node->AddProperty( "Backface Culling", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "Depth Sorting", mitk::BoolProperty::New(false), renderer, overwrite ); mitk::CoreServices::GetPropertyDescriptions()->AddDescription( "Depth Sorting", "Enables correct rendering for transparent objects by ordering polygons according to the distance to the camera. It is not recommended to enable this property for large surfaces (rendering might be slow)."); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/Core/src/mitkCoreActivator.cpp b/Modules/Core/src/mitkCoreActivator.cpp index 73fc958e81..6d01ef12f3 100644 --- a/Modules/Core/src/mitkCoreActivator.cpp +++ b/Modules/Core/src/mitkCoreActivator.cpp @@ -1,468 +1,468 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCoreActivator.h" // File IO #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkLegacyFileWriterService.h" #include "mitkDicomSeriesReaderService.h" #include #include // Micro Services #include #include #include #include #include #include #include #include #include #include // ITK "injects" static initialization code for IO factories // via the itkImageIOFactoryRegisterManager.h header (which // is generated in the application library build directory). // To ensure that the code is called *before* the CppMicroServices // static initialization code (which triggers the Activator::Start // method), we include the ITK header here. #include void HandleMicroServicesMessages(us::MsgType type, const char* msg) { switch (type) { case us::DebugMsg: MITK_DEBUG << msg; break; case us::InfoMsg: MITK_INFO << msg; break; case us::WarningMsg: MITK_WARN << msg; break; case us::ErrorMsg: MITK_ERROR << msg; break; } } void AddMitkAutoLoadPaths(const std::string& programPath) { us::ModuleSettings::AddAutoLoadPath(programPath); #ifdef __APPLE__ // Walk up three directories since that is where the .dylib files are located // for build trees. std::string additionalPath = programPath; bool addPath = true; for(int i = 0; i < 3; ++i) { std::size_t index = additionalPath.find_last_of('/'); if (index != std::string::npos) { additionalPath = additionalPath.substr(0, index); } else { addPath = false; break; } } if (addPath) { us::ModuleSettings::AddAutoLoadPath(additionalPath); } #endif } class ShaderRepositoryTracker : public us::ServiceTracker { public: ShaderRepositoryTracker() : Superclass(us::GetModuleContext()) { } virtual void Close() { us::GetModuleContext()->RemoveModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); Superclass::Close(); } virtual void Open() { us::GetModuleContext()->AddModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); Superclass::Open(); } private: typedef us::ServiceTracker Superclass; TrackedType AddingService(const ServiceReferenceType &reference) { mitk::IShaderRepository* shaderRepo = Superclass::AddingService(reference); if (shaderRepo) { // Add all existing shaders from modules to the new shader repository. // If the shader repository is registered in a modules activator, the // GetLoadedModules() function call below will also return the module // which is currently registering the repository. The HandleModuleEvent // method contains code to avoid double registrations due to a fired // ModuleEvent::LOADED event after the activators Load() method finished. std::vector modules = us::ModuleRegistry::GetLoadedModules(); for (std::vector::const_iterator iter = modules.begin(), endIter = modules.end(); iter != endIter; ++iter) { this->AddModuleShaderToRepository(*iter, shaderRepo); } m_ShaderRepositories.push_back(shaderRepo); } return shaderRepo; } void RemovedService(const ServiceReferenceType& /*reference*/, TrackedType tracked) { m_ShaderRepositories.erase(std::remove(m_ShaderRepositories.begin(), m_ShaderRepositories.end(), tracked), m_ShaderRepositories.end()); } void HandleModuleEvent(const us::ModuleEvent moduleEvent) { if (moduleEvent.GetType() == us::ModuleEvent::LOADED) { std::vector shaderRepos; for (std::map > >::const_iterator shaderMapIter = m_ModuleIdToShaderIds.begin(), shaderMapEndIter = m_ModuleIdToShaderIds.end(); shaderMapIter != shaderMapEndIter; ++shaderMapIter) { if (shaderMapIter->second.find(moduleEvent.GetModule()->GetModuleId()) == shaderMapIter->second.end()) { shaderRepos.push_back(shaderMapIter->first); } } AddModuleShadersToRepositories(moduleEvent.GetModule(), shaderRepos); } else if (moduleEvent.GetType() == us::ModuleEvent::UNLOADED) { RemoveModuleShadersFromRepositories(moduleEvent.GetModule(), m_ShaderRepositories); } } void AddModuleShadersToRepositories(us::Module* module, const std::vector& shaderRepos) { // search and load shader files std::vector shaderResources = module->FindResources("Shaders", "*.xml", true); for (std::vector::iterator i = shaderResources.begin(); i != shaderResources.end(); ++i) { if (*i) { us::ModuleResourceStream rs(*i); for (std::vector::const_iterator shaderRepoIter = shaderRepos.begin(), shaderRepoEndIter = shaderRepos.end(); shaderRepoIter != shaderRepoEndIter; ++shaderRepoIter) { int id = (*shaderRepoIter)->LoadShader(rs, i->GetBaseName()); if (id >= 0) { m_ModuleIdToShaderIds[*shaderRepoIter][module->GetModuleId()].push_back(id); } } rs.seekg(0, std::ios_base::beg); } } } void AddModuleShaderToRepository(us::Module* module, mitk::IShaderRepository* shaderRepo) { std::vector shaderRepos; shaderRepos.push_back(shaderRepo); this->AddModuleShadersToRepositories(module, shaderRepos); } void RemoveModuleShadersFromRepositories(us::Module* module, const std::vector& shaderRepos) { for (std::vector::const_iterator shaderRepoIter = shaderRepos.begin(), shaderRepoEndIter = shaderRepos.end(); shaderRepoIter != shaderRepoEndIter; ++shaderRepoIter) { std::map >& moduleIdToShaderIds = m_ModuleIdToShaderIds[*shaderRepoIter]; std::map >::iterator shaderIdsIter = moduleIdToShaderIds.find(module->GetModuleId()); if (shaderIdsIter != moduleIdToShaderIds.end()) { for (std::vector::iterator idIter = shaderIdsIter->second.begin(); idIter != shaderIdsIter->second.end(); ++idIter) { (*shaderRepoIter)->UnloadShader(*idIter); } moduleIdToShaderIds.erase(shaderIdsIter); } } } private: // Maps to each shader repository a map containing module ids and related // shader registration ids std::map > > m_ModuleIdToShaderIds; std::vector m_ShaderRepositories; }; class FixedNiftiImageIO : public itk::NiftiImageIO { public: /** Standard class typedefs. */ typedef FixedNiftiImageIO Self; typedef itk::NiftiImageIO Superclass; typedef itk::SmartPointer< Self > Pointer; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(FixedNiftiImageIO, Superclass) virtual bool SupportsDimension(unsigned long dim) { return dim > 1 && dim < 5; } }; void MitkCoreActivator::Load(us::ModuleContext* context) { // Handle messages from CppMicroServices us::installMsgHandler(HandleMicroServicesMessages); this->m_Context = context; // Add the current application directory to the auto-load paths. // This is useful for third-party executables. std::string programPath = mitk::IOUtil::GetProgramPath(); if (programPath.empty()) { MITK_WARN << "Could not get the program path."; } else { AddMitkAutoLoadPaths(programPath); } m_ShaderRepositoryTracker.reset(new ShaderRepositoryTracker); //m_RenderingManager = mitk::RenderingManager::New(); //context->RegisterService(renderingManager.GetPointer()); m_PlanePositionManager.reset(new mitk::PlanePositionManagerService); context->RegisterService(m_PlanePositionManager.get()); m_PropertyAliases.reset(new mitk::PropertyAliases); context->RegisterService(m_PropertyAliases.get()); m_PropertyDescriptions.reset(new mitk::PropertyDescriptions); context->RegisterService(m_PropertyDescriptions.get()); m_PropertyExtensions.reset(new mitk::PropertyExtensions); context->RegisterService(m_PropertyExtensions.get()); m_PropertyFilters.reset(new mitk::PropertyFilters); context->RegisterService(m_PropertyFilters.get()); m_MimeTypeProvider.reset(new mitk::MimeTypeProvider); m_MimeTypeProvider->Start(); m_MimeTypeProviderReg = context->RegisterService(m_MimeTypeProvider.get()); this->RegisterDefaultMimeTypes(); this->RegisterItkReaderWriter(); this->RegisterVtkReaderWriter(); // Add custom Reader / Writer Services m_FileReaders.push_back(new mitk::PointSetReaderService()); m_FileWriters.push_back(new mitk::PointSetWriterService()); m_FileReaders.push_back(new mitk::DicomSeriesReaderService()); m_FileReaders.push_back(new mitk::RawImageFileReaderService()); m_ShaderRepositoryTracker->Open(); /* There IS an option to exchange ALL vtkTexture instances against vtkNeverTranslucentTextureFactory. This code is left here as a reminder, just in case we might need to do that some time. vtkNeverTranslucentTextureFactory* textureFactory = vtkNeverTranslucentTextureFactory::New(); vtkObjectFactory::RegisterFactory( textureFactory ); textureFactory->Delete(); */ this->RegisterLegacyWriter(); } void MitkCoreActivator::Unload(us::ModuleContext* ) { for(std::vector::iterator iter = m_FileReaders.begin(), endIter = m_FileReaders.end(); iter != endIter; ++iter) { delete *iter; } for(std::vector::iterator iter = m_FileWriters.begin(), endIter = m_FileWriters.end(); iter != endIter; ++iter) { delete *iter; } for(std::vector::iterator iter = m_FileIOs.begin(), endIter = m_FileIOs.end(); iter != endIter; ++iter) { delete *iter; } for(std::vector::iterator iter = m_LegacyWriters.begin(), endIter = m_LegacyWriters.end(); iter != endIter; ++iter) { delete *iter; } // The mitk::ModuleContext* argument of the Unload() method // will always be 0 for the Mitk library. It makes no sense // to use it at this stage anyway, since all libraries which // know about the module system have already been unloaded. // we need to close the internal service tracker of the // MimeTypeProvider class here. Otherwise it // would hold on to the ModuleContext longer than it is // actually valid. m_MimeTypeProviderReg.Unregister(); m_MimeTypeProvider->Stop(); for (std::vector::const_iterator mimeTypeIter = m_DefaultMimeTypes.begin(), iterEnd = m_DefaultMimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { delete *mimeTypeIter; } m_ShaderRepositoryTracker->Close(); } void MitkCoreActivator::RegisterDefaultMimeTypes() { // Register some default mime-types std::vector mimeTypes = mitk::IOMimeTypes::Get(); for (std::vector::const_iterator mimeTypeIter = mimeTypes.begin(), iterEnd = mimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { m_DefaultMimeTypes.push_back(*mimeTypeIter); m_Context->RegisterService(m_DefaultMimeTypes.back()); } } void MitkCoreActivator::RegisterItkReaderWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("itkImageIOBase"); for (std::list::iterator i = allobjects.begin(), endIter = allobjects.end(); i != endIter; ++i) { itk::ImageIOBase* io = dynamic_cast(i->GetPointer()); // NiftiImageIO does not provide a correct "SupportsDimension()" methods // and the supported read/write extensions are not ordered correctly if (dynamic_cast(io)) continue; // Use a custom mime-type for GDCMImageIO below if (dynamic_cast(i->GetPointer())) { // MITK provides its own DICOM reader (which internally uses GDCMImageIO). continue; } if (io) { m_FileIOs.push_back(new mitk::ItkImageIO(io)); } else { MITK_WARN << "Error ImageIO factory did not return an ImageIOBase: " << ( *i )->GetNameOfClass(); } } FixedNiftiImageIO::Pointer itkNiftiIO = FixedNiftiImageIO::New(); - mitk::ItkImageIO* niftiIO = new mitk::ItkImageIO(mitk::CustomMimeType(mitk::IOMimeTypes::NIFTI_MIMETYPE_NAME()), + mitk::ItkImageIO* niftiIO = new mitk::ItkImageIO(mitk::IOMimeTypes::NIFTI_MIMETYPE(), itkNiftiIO.GetPointer(), 0); m_FileIOs.push_back(niftiIO); } void MitkCoreActivator::RegisterVtkReaderWriter() { m_FileIOs.push_back(new mitk::SurfaceVtkXmlIO()); m_FileIOs.push_back(new mitk::SurfaceStlIO()); m_FileIOs.push_back(new mitk::SurfaceVtkLegacyIO()); m_FileIOs.push_back(new mitk::ImageVtkXmlIO()); m_FileIOs.push_back(new mitk::ImageVtkLegacyIO()); } void MitkCoreActivator::RegisterLegacyWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("IOWriter"); for( std::list::iterator i = allobjects.begin(); i != allobjects.end(); ++i) { mitk::FileWriter::Pointer io = dynamic_cast(i->GetPointer()); if(io) { std::string description = std::string("Legacy ") + io->GetNameOfClass() + " Writer"; mitk::IFileWriter* writer = new mitk::LegacyFileWriterService(io, description); m_LegacyWriters.push_back(writer); } else { MITK_ERROR << "Error IOWriter override is not of type mitk::FileWriter: " << (*i)->GetNameOfClass() << std::endl; } } } US_EXPORT_MODULE_ACTIVATOR(MitkCoreActivator) // Call CppMicroservices initialization code at the end of the file. // This especially ensures that VTK object factories have already // been registered (VTK initialization code is injected by implicitly // include VTK header files at the top of this file). US_INITIALIZE_MODULE diff --git a/Modules/Core/tests/CMakeLists.txt b/Modules/Core/tests/CMakeLists.txt index 98e18399cb..ab0a902344 100644 --- a/Modules/Core/tests/CMakeLists.txt +++ b/Modules/Core/tests/CMakeLists.txt @@ -1,240 +1,225 @@ # The core tests need relaxed compiler flags... # TODO fix core tests to compile without these additional no-error flags if(MSVC_VERSION) # disable deprecated warnings (they would lead to errors) mitkFunctionCheckCAndCXXCompilerFlags("/wd4996" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) else() mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=deprecated" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=deprecated-declarations" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() MITK_CREATE_MODULE_TESTS(US_MODULE) mitk_use_modules(TARGET ${TESTDRIVER} PACKAGES ITK|ITKThresholding+ITKTestKernel VTK|vtkTestingRendering tinyxml) mitkAddCustomModuleTest(mitkVolumeCalculatorTest_Png2D-bw mitkVolumeCalculatorTest ${MITK_DATA_DIR}/Png2D-bw.png ${MITK_DATA_DIR}/Pic2DplusT.nrrd ) mitkAddCustomModuleTest(mitkEventMapperTest_Test1And2 mitkEventMapperTest ${MITK_DATA_DIR}/TestStateMachine1.xml ${MITK_DATA_DIR}/TestStateMachine2.xml ) mitkAddCustomModuleTest(mitkEventConfigTest_CreateObjectInDifferentWays mitkEventConfigTest - ${MITK_SOURCE_DIR}/Modules/Core/Testing/Resources/Interactions/StatemachineConfigTest.xml + ${MITK_SOURCE_DIR}/Modules/Core/tests/resources/Interactions/StatemachineConfigTest.xml ) mitkAddCustomModuleTest(mitkNodeDependentPointSetInteractorTest mitkNodeDependentPointSetInteractorTest ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/BallBinary30x30x30.nrrd ) mitkAddCustomModuleTest(mitkDataStorageTest_US4DCyl mitkDataStorageTest ${MITK_DATA_DIR}/US4DCyl.nrrd ) mitkAddCustomModuleTest(mitkStateMachineFactoryTest_TestStateMachine1_2 mitkStateMachineFactoryTest ${MITK_DATA_DIR}/TestStateMachine1.xml ${MITK_DATA_DIR}/TestStateMachine2.xml ) mitkAddCustomModuleTest(mitkDicomSeriesReaderTest_CTImage mitkDicomSeriesReaderTest ${MITK_DATA_DIR}/TinyCTAbdomen ${MITK_DATA_DIR}/DICOMReader/Broken-Series ) mitkAddCustomModuleTest(mitkPointSetReaderTest mitkPointSetReaderTest ${MITK_DATA_DIR}/PointSetReaderTestData.mps ) mitkAddCustomModuleTest(mitkImageTest_4DImageData mitkImageTest ${MITK_DATA_DIR}/US4DCyl.nrrd ) mitkAddCustomModuleTest(mitkImageTest_2D+tImageData mitkImageTest ${MITK_DATA_DIR}/Pic2DplusT.nrrd ) mitkAddCustomModuleTest(mitkImageTest_3DImageData mitkImageTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkImageEqualTest mitkImageEqualTest) mitkAddCustomModuleTest(mitkImageTest_brainImage mitkImageTest ${MITK_DATA_DIR}/brain.mhd ) mitkAddCustomModuleTest(mitkImageTest_3DImageData mitkImageGeneratorTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkLevelWindowManagerTest mitkLevelWindowManagerTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkMultiComponentImageDataComparisonFilterTest mitkMultiComponentImageDataComparisonFilterTest ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg ) mitkAddCustomModuleTest(mitkImageToItkTest mitkImageToItkTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkImageSliceSelectorTest mitkImageSliceSelectorTest ${MITK_DATA_DIR}/Pic2DplusT.nrrd ) if(MITK_ENABLE_RENDERING_TESTING) ### since the rendering test's do not run in ubuntu, yet, we build them only for other systems or if the user explicitly sets the variable MITK_ENABLE_RENDERING_TESTING mitkAddCustomModuleTest(mitkImageVtkMapper2D_rgbaImage640x480 mitkImageVtkMapper2DTest ${MITK_DATA_DIR}/RenderingTestData/rgbaImage.png #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/rgbaImage640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3d640x480 mitkImageVtkMapper2DTest #test for standard Pic3D axial slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3d640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dColorBlue640x480 mitkImageVtkMapper2DColorTest #test for color property (=blue) Pic3D sagittal slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dColorBlue640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dLevelWindow640x480 mitkImageVtkMapper2DLevelWindowTest #test for levelwindow property (=blood) #Pic3D sagittal slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dLevelWindowBlood640x480REF.png #corresponding reference #screenshot ) #mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dOpacity640x480 mitkImageVtkMapper2DOpacityTest #test for opacity (=0.5) Pic3D coronal slice # ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage # -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dOpacity640x480REF.png corresponding reference screenshot #) mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dSwivel640x480 mitkImageVtkMapper2DSwivelTest #test for a randomly chosen Pic3D swivelled slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dSwivel640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkPointSetVtkMapper2D_openMeAlone640x480 mitkPointSetVtkMapper2DTest ${MITK_DATA_DIR}/RenderingTestData/openMeAlone.mps #input point set to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/openMeAlone640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkPointSetVtkMapper2D_Pic3DPointSetForPic3D640x480 mitkPointSetVtkMapper2DImageTest ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/RenderingTestData/PointSetForPic3D.mps #input point set and image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Pic3DPointSetForPic3D640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkPointSetVtkMapper2D_openMeAloneGlyphType640x480 mitkPointSetVtkMapper2DGlyphTypeTest ${MITK_DATA_DIR}/RenderingTestData/openMeAlone.mps #input point set to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/openMeAloneGlyphType640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkPointSetVtkMapper2D_openMeAloneTransformed640x480 mitkPointSetVtkMapper2DTransformedPointsTest ${MITK_DATA_DIR}/RenderingTestData/openMeAlone.mps #input point set to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/openMeAloneTransformedPoints640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkSurfaceDepthSortingTransparency_StanfordBunnySTL640x480 mitkSurfaceDepthSortingTest ${MITK_DATA_DIR}/RenderingTestData/Stanford_bunny.stl -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Stanford_bunnySTLDepthSorting640x480REF.png ) if(NOT APPLE) mitkAddCustomModuleTest(mitkSurfaceDepthPeelingTransparency_StanfordBunnySTL640x480 mitkSurfaceDepthPeelingTest ${MITK_DATA_DIR}/RenderingTestData/Stanford_bunny.stl -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Stanford_bunnySTLDepthPeeling640x480REF.png #corresponding reference screenshot ) endif() #Test reslice interpolation #note: nearest mode is already tested by swivel test mitkAddCustomModuleTest(ResliceInterpolationIsLinear mitkImageVtkMapper2DResliceInterpolationPropertyTest 1 #linear ${MITK_DATA_DIR}/Pic3D.nrrd -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dRefLinear.png #corresponding reference screenshot LINEAR ) mitkAddCustomModuleTest(ResliceInterpolationIsCubic mitkImageVtkMapper2DResliceInterpolationPropertyTest 3 #cubic ${MITK_DATA_DIR}/Pic3D.nrrd -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dRefCubic.png #corresponding reference screenshot CUBIC ) #End test reslice interpolation # Testing of the rendering of binary images #mitkAddCustomModuleTest(mitkImageVtkMapper2D_binaryTestImage640x480 mitkImageVtkMapper2DTest #test for standard Pic3D axial slice # ${MITK_DATA_DIR}/RenderingTestData/binaryImage.nrrd #input image to load in data storage # -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/binaryImage640x480REF.png #corresponding reference screenshot #) #mitkAddCustomModuleTest(mitkImageVtkMapper2D_binaryTestImageWithRef640x480 mitkImageVtkMapper2DTest #test for standard Pic3D axial slice # ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/RenderingTestData/binaryImage.nrrd #input image to load in data storage # -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/binaryImageWithRef640x480REF.png #corresponding reference screenshot #) # End of binary image tests mitkAddCustomModuleTest(mitkSurfaceVtkMapper3DTest_TextureProperty mitkSurfaceVtkMapper3DTest ${MITK_DATA_DIR}/ToF-Data/Kinect_LiverPhantom.vtp ${MITK_DATA_DIR}/ToF-Data/Kinect_LiverPhantom_RGBImage.nrrd -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/texturedLiver640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2DTransferFunctionTest_Png2D-bw mitkImageVtkMapper2DTransferFunctionTest ${MITK_DATA_DIR}/Png2D-bw.png -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Png2D-bw-TransferFunctionRGBImage640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2DOpacityTransferFunctionTest_Png2D-bw mitkImageVtkMapper2DOpacityTransferFunctionTest ${MITK_DATA_DIR}/Png2D-bw.png -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Png2D-bw-OpacityTransferFunctionRGBImage640x480REF.png #corresponding reference screenshot ) -mitkAddCustomModuleTest(mitkSurfaceVtkMapper2DColorTest_RedBall mitkSurfaceVtkMapper2DColorTest - ${MITK_DATA_DIR}/ball.stl - -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/ballColorRed640x480REF.png #corresponding reference screenshot -) - -mitkAddCustomModuleTest(mitkSurfaceVtkMapper2DColorTest_DasArmeSchwein mitkSurfaceVtkMapper2DColorTest - ${MITK_DATA_DIR}/binary.stl - -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/binaryColorRed640x480REF.png #corresponding reference screenshot -) - -mitkAddCustomModuleTest(mitkSurfaceVtkMapper2DOpacityTest_BallOpacity mitkSurfaceVtkMapper2DOpacityTest #opacity = 50% (0.5) - ${MITK_DATA_DIR}/ball.stl - -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/ballOpacity640x480REF.png #corresponding reference screenshot -) - ############################## DISABLED TESTS #Removed due to high rendering error. #mitkAddCustomModuleTest(mitkSurfaceVtkMapper3DTexturedSphereTest_Football mitkSurfaceVtkMapper3DTexturedSphereTest # ${MITK_DATA_DIR}/RenderingTestData/texture.jpg #input texture # -V # ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/texturedSphere640x480REF.png corresponding reference screenshot #) mitkAddCustomModuleTest(mitkImageVtkMapper2DLookupTableTest_Png2D-bw mitkImageVtkMapper2DLookupTableTest ${MITK_DATA_DIR}/Png2D-bw.png -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Png2D-bw-LookupTableRGBImage640x480REF.png #corresponding reference screenshot ) #mitkAddCustomModuleTest(mitkImageTest_color2DImage mitkImageTest # ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg #) #mitkAddCustomModuleTest(mitkNodeDependentPointSetInteractorTest mitkNodeDependentPointSetInteractorTest # ${MITK_DATA_DIR}/Pic3D.pic.gz ${MITK_DATA_DIR}/BallBinary30x30x30.pic.gz #) SET_PROPERTY(TEST mitkImageVtkMapper2D_rgbaImage640x480 mitkImageVtkMapper2D_pic3d640x480 mitkImageVtkMapper2D_pic3dColorBlue640x480 mitkImageVtkMapper2D_pic3dLevelWindow640x480 mitkImageVtkMapper2D_pic3dSwivel640x480 mitkImageVtkMapper2DTransferFunctionTest_Png2D-bw # mitkImageVtkMapper2D_pic3dOpacity640x480 - mitkSurfaceVtkMapper2DOpacityTest_BallOpacity mitkSurfaceVtkMapper2DColorTest_DasArmeSchwein mitkSurfaceVtkMapper2DColorTest_RedBall mitkSurfaceVtkMapper3DTest_TextureProperty mitkPointSetVtkMapper2D_Pic3DPointSetForPic3D640x480 mitkPointSetVtkMapper2D_openMeAlone640x480 mitkPointSetVtkMapper2D_openMeAloneGlyphType640x480 mitkPointSetVtkMapper2D_openMeAloneTransformed640x480 #mitkSurfaceVtkMapper3DTexturedSphereTest_Football + mitkSurfaceVtkMapper2DTest mitkSurfaceVtkMapper3DTest_TextureProperty mitkPointSetVtkMapper2D_Pic3DPointSetForPic3D640x480 mitkPointSetVtkMapper2D_openMeAlone640x480 mitkPointSetVtkMapper2D_openMeAloneGlyphType640x480 mitkPointSetVtkMapper2D_openMeAloneTransformed640x480 #mitkSurfaceVtkMapper3DTexturedSphereTest_Football PROPERTY RUN_SERIAL TRUE) endif() add_test(mitkPointSetLocaleTest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkPointSetLocaleTest ${MITK_DATA_DIR}/pointSet.mps) set_property(TEST mitkPointSetLocaleTest PROPERTY LABELS MITK-Core) add_test(mitkImageWriterTest_nrrdImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg) add_test(mitkImageWriterTest_2DPNGImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/Png2D-bw.png) add_test(mitkImageWriterTest_rgbPNGImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/RenderingTestData/rgbImage.png) add_test(mitkImageWriterTest_rgbaPNGImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/RenderingTestData/rgbaImage.png) set_property(TEST mitkImageWriterTest_nrrdImage PROPERTY LABELS MITK-Core) set_property(TEST mitkImageWriterTest_2DPNGImage PROPERTY LABELS MITK-Core) set_property(TEST mitkImageWriterTest_rgbPNGImage PROPERTY LABELS MITK-Core) set_property(TEST mitkImageWriterTest_rgbaPNGImage PROPERTY LABELS MITK-Core) diff --git a/Modules/Core/tests/files.cmake b/Modules/Core/tests/files.cmake index 80b985774a..56ea2372e7 100644 --- a/Modules/Core/tests/files.cmake +++ b/Modules/Core/tests/files.cmake @@ -1,190 +1,190 @@ # tests with no extra command line parameter set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## DISABLED TESTS ################################################# #mitkAbstractTransformGeometryTest.cpp #seems as tested class mitkExternAbstractTransformGeometry doesnt exist any more #mitkStateMachineContainerTest.cpp #rewrite test, indirect since no longer exported Bug 14529 #mitkRegistrationBaseTest.cpp #tested class mitkRegistrationBase doesn't exist any more #mitkSegmentationInterpolationTest.cpp #file doesn't exist! #mitkPipelineSmartPointerCorrectnessTest.cpp #file doesn't exist! #mitkITKThreadingTest.cpp #test outdated because itk::Semaphore was removed from ITK #mitkAbstractTransformPlaneGeometryTest.cpp #mitkVtkAbstractTransformPlaneGeometry doesn't exist any more #mitkTestUtilSharedLibrary.cpp #Linker problem with this test... #mitkTextOverlay2DSymbolsRenderingTest.cpp #Implementation of the tested feature is not finished yet. Ask Christoph or see bug 15104 for details. ################# RUNNING TESTS ################################################### mitkAccessByItkTest.cpp mitkCoreObjectFactoryTest.cpp mitkDataNodeTest.cpp mitkMaterialTest.cpp mitkActionTest.cpp mitkDispatcherTest.cpp mitkEnumerationPropertyTest.cpp mitkEventTest.cpp mitkFileReaderRegistryTest.cpp #mitkFileWriterRegistryTest.cpp mitkFocusManagerTest.cpp mitkGenericPropertyTest.cpp mitkGeometry3DTest.cpp mitkGeometry3DEqualTest.cpp mitkGeometryDataToSurfaceFilterTest.cpp mitkGlobalInteractionTest.cpp mitkImageCastTest.cpp mitkImageEqualTest.cpp mitkImageDataItemTest.cpp mitkImageGeneratorTest.cpp mitkIOUtilTest.cpp mitkBaseDataTest.cpp mitkImportItkImageTest.cpp mitkGrabItkImageMemoryTest.cpp mitkInstantiateAccessFunctionTest.cpp mitkInteractorTest.cpp mitkLevelWindowTest.cpp mitkMessageTest.cpp mitkPixelTypeTest.cpp mitkPlaneGeometryTest.cpp mitkPointSetTest.cpp mitkPointSetEqualTest.cpp mitkPointSetFileIOTest.cpp mitkPointSetOnEmptyTest.cpp mitkPointSetWriterTest.cpp mitkPointSetReaderTest.cpp mitkPointSetInteractorTest.cpp mitkPointSetPointOperationsTest.cpp mitkProgressBarTest.cpp mitkPropertyTest.cpp mitkPropertyListTest.cpp mitkSlicedGeometry3DTest.cpp mitkSliceNavigationControllerTest.cpp mitkStateMachineTest.cpp mitkStateTest.cpp mitkSurfaceTest.cpp mitkSurfaceEqualTest.cpp mitkSurfaceToSurfaceFilterTest.cpp mitkTimeGeometryTest.cpp mitkProportionalTimeGeometryTest.cpp mitkTransitionTest.cpp mitkUndoControllerTest.cpp mitkVtkWidgetRenderingTest.cpp mitkVerboseLimitedLinearUndoTest.cpp mitkWeakPointerTest.cpp mitkTransferFunctionTest.cpp mitkStepperTest.cpp mitkRenderingManagerTest.cpp vtkMitkThickSlicesFilterTest.cpp mitkNodePredicateSourceTest.cpp mitkVectorTest.cpp mitkClippedSurfaceBoundsCalculatorTest.cpp mitkExceptionTest.cpp mitkExtractSliceFilterTest.cpp mitkLogTest.cpp mitkImageDimensionConverterTest.cpp mitkLoggingAdapterTest.cpp mitkUIDGeneratorTest.cpp mitkShaderRepositoryTest.cpp mitkPlanePositionManagerTest.cpp mitkAffineTransformBaseTest.cpp mitkPropertyAliasesTest.cpp mitkPropertyDescriptionsTest.cpp mitkPropertyExtensionsTest.cpp mitkPropertyFiltersTest.cpp mitkTinyXMLTest.cpp mitkRawImageFileReaderTest.cpp mitkInteractionEventTest.cpp mitkLookupTableTest.cpp mitkSTLFileReaderTest.cpp mitkPointTypeConversionTest.cpp mitkVectorTypeConversionTest.cpp mitkMatrixTypeConversionTest.cpp mitkArrayTypeConversionTest.cpp mitkSurfaceToImageFilterTest.cpp mitkBaseGeometryTest.cpp mitkImageToSurfaceFilterTest.cpp mitkEqualTest.cpp mitkLineTest.cpp + mitkSurfaceVtkMapper2DTest.cpp ) -if(MITK_ENABLE_RENDERING_TESTING) #since mitkInteractionTestHelper is currently creating a vtkRenderWindow +if(MITK_ENABLE_RENDERING_TESTING) set(MODULE_TESTS ${MODULE_TESTS} - mitkPointSetDataInteractorTest.cpp + mitkPointSetDataInteractorTest.cpp #since mitkInteractionTestHelper is currently creating a vtkRenderWindow + mitkSurfaceVtkMapper2DTest.cpp #new rendering test in CppUnit style ) endif() # test with image filename as an extra command line parameter set(MODULE_IMAGE_TESTS mitkImageTimeSelectorTest.cpp #only runs on images mitkImageAccessorTest.cpp #only runs on images ) set(MODULE_SURFACE_TESTS mitkSurfaceVtkWriterTest.cpp #only runs on surfaces ) # list of images for which the tests are run set(MODULE_TESTIMAGES US4DCyl.nrrd Pic3D.nrrd Pic2DplusT.nrrd BallBinary30x30x30.nrrd Png2D-bw.png ) set(MODULE_TESTSURFACES binary.stl ball.stl ) set(MODULE_CUSTOM_TESTS mitkDataStorageTest.cpp mitkDicomSeriesReaderTest.cpp mitkDICOMLocaleTest.cpp mitkDataNodeTest.cpp mitkEventMapperTest.cpp mitkEventConfigTest.cpp mitkNodeDependentPointSetInteractorTest.cpp mitkStateMachineFactoryTest.cpp mitkPointSetLocaleTest.cpp mitkImageTest.cpp mitkImageWriterTest.cpp mitkImageVtkMapper2DTest.cpp mitkImageVtkMapper2DLevelWindowTest.cpp mitkImageVtkMapper2DOpacityTest.cpp mitkImageVtkMapper2DResliceInterpolationPropertyTest.cpp mitkImageVtkMapper2DColorTest.cpp mitkImageVtkMapper2DSwivelTest.cpp mitkImageVtkMapper2DTransferFunctionTest.cpp mitkImageVtkMapper2DOpacityTransferFunctionTest.cpp mitkImageVtkMapper2DLookupTableTest.cpp mitkSurfaceVtkMapper3DTest mitkSurfaceVtkMapper3DTexturedSphereTest.cpp - mitkSurfaceVtkMapper2DColorTest.cpp - mitkSurfaceVtkMapper2DOpacityTest.cpp mitkVolumeCalculatorTest.cpp mitkLevelWindowManagerTest.cpp mitkPointSetVtkMapper2DTest.cpp mitkPointSetVtkMapper2DImageTest.cpp mitkPointSetVtkMapper2DGlyphTypeTest.cpp mitkPointSetVtkMapper2DTransformedPointsTest.cpp mitkVTKRenderWindowSizeTest.cpp mitkMultiComponentImageDataComparisonFilterTest.cpp mitkImageToItkTest.cpp mitkImageSliceSelectorTest.cpp mitkSurfaceDepthPeelingTest.cpp mitkSurfaceDepthSortingTest.cpp ) set(RESOURCE_FILES Interactions/AddAndRemovePoints.xml Interactions/globalConfig.xml Interactions/StatemachineTest.xml Interactions/StatemachineConfigTest.xml ) diff --git a/Modules/Core/tests/mitkGenericPropertyTest.cpp b/Modules/Core/tests/mitkGenericPropertyTest.cpp index 0897dd81a0..3333591e4d 100644 --- a/Modules/Core/tests/mitkGenericPropertyTest.cpp +++ b/Modules/Core/tests/mitkGenericPropertyTest.cpp @@ -1,109 +1,111 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" #include "mitkGenericProperty.h" #include "mitkStringProperty.h" #include "mitkProperties.h" #include "mitkNumericTypes.h" #include #include // call with testValue1 != testValue2 template int TestGenericPropertyForDataType(typename T::ValueType testValue1, typename T::ValueType testValue2, std::string testValue1AsString, std::string testValue2AsString, std::string type) { std::cout << "Testing mitk::GenericProperty<" << type << ">(" << testValue1AsString << ", " << testValue2AsString << ") \n"; typename T::Pointer prop(T::New()); typename T::Pointer prop2(T::New(testValue1)); typename T::Pointer prop3(T::New(testValue2)); unsigned long tBefore = prop->GetMTime(); prop->SetValue(testValue1); unsigned long tAfter = prop->GetMTime(); prop->SetValue(testValue1); unsigned long tAfterAll = prop->GetMTime(); MITK_TEST_CONDITION_REQUIRED(prop->GetValue() == testValue1 && prop->GetValueAsString() == testValue1AsString,"Testing SetValue") MITK_TEST_CONDITION_REQUIRED((*prop == *prop2),"Testing equality operator (operator==)"); prop->SetValue(testValue2); unsigned long tAfterEverything = prop->GetMTime(); std::cout << " Testing MTime correctness when changing property value: "; if (tBefore >= tAfter || tAfterAll != tAfter || tAfterEverything <= tAfterAll) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; prop->SetValue(testValue1); std::cout << " Testing Assignment: "; prop->AssignProperty(*prop3); if ( (! (*prop == *prop3)) || (*prop == *prop2) ) { std::cout << " [FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << std::endl; return EXIT_SUCCESS; } int mitkGenericPropertyTest(int /*argc*/, char* /*argv*/[]) { MITK_TEST_BEGIN(GenericPropertyTest) // testing for some different data types TestGenericPropertyForDataType(1, 2, "1", "2", "int"); TestGenericPropertyForDataType(true, false, "1", "0", "bool"); TestGenericPropertyForDataType(1.0, -1.0, "1", "-1", "float"); TestGenericPropertyForDataType(1.0, -1.0, "1", "-1", "double"); + TestGenericPropertyForDataType(1, 100000, "1", "100000", "unsigned int"); + TestGenericPropertyForDataType(1, 20000, "1", "20000", "unsigned short"); TestGenericPropertyForDataType(std::string("eins"), std::string("zwei"), std::string("eins"), std::string("zwei"), "std::string"); { mitk::Point3D p1; p1[0] = 2.0; p1[1] = 3.0; p1[2] = 4.0; mitk::Point3D p2; p2[0] =-1.0; p2[1] = 2.0; p2[2] = 3.0; TestGenericPropertyForDataType( p1, p2, "[2, 3, 4]", "[-1, 2, 3]", "mitk::Point3D"); } { mitk::Point4D p1; p1[0] = 2.0; p1[1] = 3.0; p1[2] = 4.0; p1[3] =-2.0; mitk::Point4D p2; p2[0] =-1.0; p2[1] = 2.0; p2[2] = 3.0; p2[3] = 5.0; TestGenericPropertyForDataType( p1, p2, "[2, 3, 4, -2]", "[-1, 2, 3, 5]", "mitk::Point4D"); } /* THIS won't compile because of the interface of XMLWriter... that should be reworked perhaps { mitk::Vector2D p1; p1[0] = 2.0; p1[1] = 3.0; mitk::Vector2D p2; p2[0] =-1.0; p2[1] = 2.0; TestGenericPropertyForDataType( p1, p2, "[2, 3]", "[-1, 2]", "mitk::Vector2D"); } */ { mitk::Vector3D p1; p1[0] = 2.0; p1[1] = 3.0; p1[2] = 4.0; mitk::Vector3D p2; p2[0] =-1.0; p2[1] = 2.0; p2[2] = 3.0; TestGenericPropertyForDataType( p1, p2, "[2, 3, 4]", "[-1, 2, 3]", "mitk::Vector3D"); } MITK_TEST_END(); } diff --git a/Modules/Core/tests/mitkSurfaceVtkMapper2DColorTest.cpp b/Modules/Core/tests/mitkSurfaceVtkMapper2DColorTest.cpp deleted file mode 100644 index 7395d79a62..0000000000 --- a/Modules/Core/tests/mitkSurfaceVtkMapper2DColorTest.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -//MITK -#include "mitkTestingMacros.h" -#include "mitkRenderingTestHelper.h" -#include - -//VTK -#include - - -int mitkSurfaceVtkMapper2DColorTest(int argc, char* argv[]) -{ - // load all arguments into a datastorage, take last argument as reference rendering - // setup a renderwindow of fixed size X*Y - // render the datastorage - // compare rendering to reference image - MITK_TEST_BEGIN("mitkSurfaceVtkMapper2DColorTest") - - mitk::RenderingTestHelper renderingHelper(640, 480, argc, argv); - //Set the opacity for all images - - renderingHelper.GetDataStorage()->GetNode(mitk::NodePredicateDataType::New("Surface"))->SetProperty("color", mitk::ColorProperty::New(255.0f, 0.0f, 0.0f)); - - //### Usage of CompareRenderWindowAgainstReference: See docu of mitkRrenderingTestHelper - MITK_TEST_CONDITION( renderingHelper.CompareRenderWindowAgainstReference(argc, argv) == true, "CompareRenderWindowAgainstReference test result positive?" ); - - //#################### - //Use this to generate a reference screenshot or save the file. - //(Only in your local version of the test!) - if(false) - { - renderingHelper.SaveReferenceScreenShot("/home/kilgus/Pictures/RenderingTestData/output.png"); - } - //#################### - MITK_TEST_END(); -} diff --git a/Modules/Core/tests/mitkSurfaceVtkMapper2DOpacityTest.cpp b/Modules/Core/tests/mitkSurfaceVtkMapper2DOpacityTest.cpp deleted file mode 100644 index 737bca41ab..0000000000 --- a/Modules/Core/tests/mitkSurfaceVtkMapper2DOpacityTest.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -//MITK -#include "mitkTestingMacros.h" -#include "mitkRenderingTestHelper.h" -#include - -//VTK -#include - - -int mitkSurfaceVtkMapper2DOpacityTest(int argc, char* argv[]) -{ - // load all arguments into a datastorage, take last argument as reference rendering - // setup a renderwindow of fixed size X*Y - // render the datastorage - // compare rendering to reference image - MITK_TEST_BEGIN("mitkSurfaceVtkMapper2DOpacityTest") - - mitk::RenderingTestHelper renderingHelper(640, 480, argc, argv); - //Set the opacity for all images - - renderingHelper.GetDataStorage()->GetNode(mitk::NodePredicateDataType::New("Surface"))->SetProperty("opacity", mitk::FloatProperty::New(0.5f)); - - //### Usage of CompareRenderWindowAgainstReference: See docu of mitkRrenderingTestHelper - MITK_TEST_CONDITION( renderingHelper.CompareRenderWindowAgainstReference(argc, argv) == true, "CompareRenderWindowAgainstReference test result positive?" ); - - //#################### - //Use this to generate a reference screenshot or save the file. - //(Only in your local version of the test!) - if(false) - { - renderingHelper.SaveReferenceScreenShot("/home/kilgus/Pictures/RenderingTestData/output.png"); - } - //#################### - MITK_TEST_END(); -} diff --git a/Modules/Core/tests/mitkSurfaceVtkMapper2DTest.cpp b/Modules/Core/tests/mitkSurfaceVtkMapper2DTest.cpp new file mode 100644 index 0000000000..f58b868b2a --- /dev/null +++ b/Modules/Core/tests/mitkSurfaceVtkMapper2DTest.cpp @@ -0,0 +1,151 @@ +/*=================================================================== + +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. + +===================================================================*/ + +//MITK +#include +#include +#include +#include +#include + +class mitkSurfaceVtkMapper2DTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkSurfaceVtkMapper2DTestSuite); + MITK_TEST(RenderBall); + MITK_TEST(RenderOpaqueBall); + MITK_TEST(RenderRedBall); + MITK_TEST(RenderBallWithGeometry); + MITK_TEST(RenderRedBinary); + CPPUNIT_TEST_SUITE_END(); + +private: + + /** Members used inside the different test methods. All members are initialized via setUp().*/ + mitk::RenderingTestHelper m_RenderingTestHelper; + std::vector m_CommandlineArgs; + std::string m_PathToBall; + std::string m_PathToBinary; + +public: + + /** + * @brief mitkSurfaceVtkMapper2DTestSuite Because the RenderingTestHelper does not have an + * empty default constructor, we need this constructor to initialize the helper with a + * resolution. + */ + mitkSurfaceVtkMapper2DTestSuite(): + m_RenderingTestHelper(640, 480) + {} + + /** + * @brief Setup Initialize a fresh rendering test helper and a vector of strings + * to simulate commandline arguments for vtkTesting::Test. + */ + void setUp() + { + m_RenderingTestHelper = mitk::RenderingTestHelper(640, 480); + + m_PathToBall = GetTestDataFilePath("ball.stl"); + m_PathToBinary = GetTestDataFilePath("binary.stl"); + + //Build a command line for the vtkTesting::Test method. + //See VTK documentation and RenderingTestHelper for more information. + //Use the following command line option to save the difference image + //and the test image in some tmp folder + //m_CommandlineArgs.push_back("-T"); + //m_CommandlineArgs.push_back("/path/to/save/tmp/difference/images/"); + m_CommandlineArgs.push_back("-V"); + } + + void tearDown() + { + } + + void RenderBall() + { + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData(mitk::IOUtil::Load(m_PathToBall)[0]); + m_RenderingTestHelper.AddNodeToStorage( node ); + + //reference screenshot for this test + m_CommandlineArgs.push_back(GetTestDataFilePath("RenderingTestData/ReferenceScreenshots/ball640x480REF.png")); + //Convert vector of strings to argc/argv + mitk::RenderingTestHelper::ArgcHelperClass arg(m_CommandlineArgs); + CPPUNIT_ASSERT( m_RenderingTestHelper.CompareRenderWindowAgainstReference(arg.GetArgc(),arg.GetArgv()) == true); + } + + void RenderBallWithGeometry() + { + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData(mitk::IOUtil::Load(m_PathToBall)[0]); + //Modify the geometry a little + mitk::Vector3D spacing; + spacing[0] = 0.5; + spacing[1] = 1.5; + spacing[2] = 0.75; + node->GetData()->GetGeometry()->SetSpacing(spacing); + m_RenderingTestHelper.AddNodeToStorage( node ); + + //reference screenshot for this test + m_CommandlineArgs.push_back(GetTestDataFilePath("RenderingTestData/ReferenceScreenshots/ballWithGeometry640x480REF.png")); + //Convert vector of strings to argc/argv + mitk::RenderingTestHelper::ArgcHelperClass arg(m_CommandlineArgs); + CPPUNIT_ASSERT( m_RenderingTestHelper.CompareRenderWindowAgainstReference(arg.GetArgc(),arg.GetArgv()) == true); + } + + void RenderOpaqueBall() + { + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData(mitk::IOUtil::Load(m_PathToBall)[0]); + node->SetOpacity(0.5); + m_RenderingTestHelper.AddNodeToStorage( node ); + + //reference screenshot for this test + m_CommandlineArgs.push_back(GetTestDataFilePath("RenderingTestData/ReferenceScreenshots/ballOpacity640x480REF.png")); + //Convert vector of strings to argc/argv + mitk::RenderingTestHelper::ArgcHelperClass arg(m_CommandlineArgs); + CPPUNIT_ASSERT( m_RenderingTestHelper.CompareRenderWindowAgainstReference(arg.GetArgc(),arg.GetArgv()) == true); + } + + void RenderRedBall() + { + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData(mitk::IOUtil::Load(m_PathToBall)[0]); + node->SetProperty("color", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f)); + m_RenderingTestHelper.AddNodeToStorage( node ); + + //reference screenshot for this test + m_CommandlineArgs.push_back(GetTestDataFilePath("RenderingTestData/ReferenceScreenshots/ballColorRed640x480REF.png")); + //Convert vector of strings to argc/argv + mitk::RenderingTestHelper::ArgcHelperClass arg(m_CommandlineArgs); + CPPUNIT_ASSERT( m_RenderingTestHelper.CompareRenderWindowAgainstReference(arg.GetArgc(),arg.GetArgv()) == true); + } + + void RenderRedBinary() + { + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData(mitk::IOUtil::Load(m_PathToBinary)[0]); + node->SetProperty("color", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f)); + m_RenderingTestHelper.AddNodeToStorage( node ); + + //reference screenshot for this test + m_CommandlineArgs.push_back(GetTestDataFilePath("RenderingTestData/ReferenceScreenshots/binaryColorRed640x480REF.png")); + //Convert vector of strings to argc/argv + mitk::RenderingTestHelper::ArgcHelperClass arg(m_CommandlineArgs); + CPPUNIT_ASSERT( m_RenderingTestHelper.CompareRenderWindowAgainstReference(arg.GetArgc(),arg.GetArgv()) == true); + } +}; +MITK_TEST_SUITE_REGISTRATION(mitkSurfaceVtkMapper2D) diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp new file mode 100644 index 0000000000..af2cf2feef --- /dev/null +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp @@ -0,0 +1,3920 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include "mitkFreeSurferParcellationTranslator.h" +using namespace mitk; +using namespace std; + + +/*########### Static Members ###########*/ +LookupTable::Pointer FreeSurferParcellationTranslator::m_LookupTable = FreeSurferParcellationTranslator::CreateLookupTable(); +const FreeSurferParcellationTranslator::NameTable FreeSurferParcellationTranslator::m_NameTable = FreeSurferParcellationTranslator::CreateNameTable(); +TransferFunction::Pointer FreeSurferParcellationTranslator::m_TransferFunction = FreeSurferParcellationTranslator::CreateTransferFunction(); + + +/*########### Constructors ###########*/ +FreeSurferParcellationTranslator::FreeSurferParcellationTranslator() +{ +} +FreeSurferParcellationTranslator::~FreeSurferParcellationTranslator() +{ +} + + +/*########### Methods ###########*/ +// Assign the lookup table to the given node +void FreeSurferParcellationTranslator::AssignLookupTable(DataNode::Pointer node) const +{ + LookupTableProperty::Pointer lookupTableProp = LookupTableProperty::New( this->GetLookupTable() ); + node->SetProperty( "LookupTable", lookupTableProp ); +} +// Assign the color transfer function to the given node +void FreeSurferParcellationTranslator::AssignTransferFunction(DataNode::Pointer node) const +{ + TransferFunctionProperty::Pointer transferFunctionProp = TransferFunctionProperty::New( this->GetTransferFunction() ); + node->SetProperty( "Image Rendering.Transfer Function", transferFunctionProp ); +} +// Get the label assigned to the given name +const string FreeSurferParcellationTranslator::GetLabel(const string& name) const +{ + NameTable::const_iterator iter; + for( iter = m_NameTable.begin(); iter != m_NameTable.end(); ++iter ) + { + if( iter->second == name ) + return iter->first; + } + return "0"; +} +// Get the label assigned to the given name as integer +int FreeSurferParcellationTranslator::GetLabelAsNumber(const string &name) const +{ + return std::atoi(this->GetLabel( name ).c_str()) ; +} +// Return the lookup table +LookupTable::Pointer FreeSurferParcellationTranslator::GetLookupTable() const +{ + return m_LookupTable; +} +// Get the name assigned to the given label +const string FreeSurferParcellationTranslator::GetName(const string & label) const +{ + NameTable::const_iterator endIter = this->m_NameTable.end(); + NameTable::const_iterator iter = this->m_NameTable.find( label ); + if( iter != endIter ) + { + return iter->second; + } + else + { + return "Unknown area or outside the cerebrum."; + } +} +// Get the name assigned to the given label +const string FreeSurferParcellationTranslator::GetName(int label) const +{ + stringstream ss;//create a stringstream + ss << label;//add number to the stream + return this->GetName( ss.str() ); +} +// Get the transfer function +TransferFunction::Pointer FreeSurferParcellationTranslator::GetTransferFunction() const +{ + return m_TransferFunction; +} + +LookupTable::Pointer FreeSurferParcellationTranslator::CreateLookupTable() +{ + vtkSmartPointer table = vtkSmartPointer::New(); + table->SetRange(0.0, 14175.0); + table->SetNumberOfTableValues( 14176.0 ); // Count of the overall range (0 - 14175) + table->Build(); + table->SetTableValue( 0.0, 0, 0, 0, 0); + table->SetTableValue( 1.0, 0.27451, 0.509804, 0.705882 ); + table->SetTableValue( 2.0, 0.960784, 0.960784, 0.960784 ); + table->SetTableValue( 3.0, 0.803922, 0.243137, 0.305882 ); + table->SetTableValue( 4.0, 0.470588, 0.0705882, 0.52549 ); + table->SetTableValue( 5.0, 0.768627, 0.227451, 0.980392 ); + table->SetTableValue( 6.0, 0, 0.580392, 0 ); + table->SetTableValue( 7.0, 0.862745, 0.972549, 0.643137 ); + table->SetTableValue( 8.0, 0.901961, 0.580392, 0.133333 ); + table->SetTableValue( 9.0, 0, 0.462745, 0.054902 ); + table->SetTableValue( 10.0, 0, 0.462745, 0.054902 ); + table->SetTableValue( 11.0, 0.478431, 0.729412, 0.862745 ); + table->SetTableValue( 12.0, 0.92549, 0.0509804, 0.690196 ); + table->SetTableValue( 13.0, 0.0470588, 0.188235, 1 ); + table->SetTableValue( 14.0, 0.8, 0.713725, 0.556863 ); + table->SetTableValue( 15.0, 0.164706, 0.8, 0.643137 ); + table->SetTableValue( 16.0, 0.466667, 0.623529, 0.690196 ); + table->SetTableValue( 17.0, 0.862745, 0.847059, 0.0784314 ); + table->SetTableValue( 18.0, 0.403922, 1, 1 ); + table->SetTableValue( 19.0, 0.313725, 0.768627, 0.384314 ); + table->SetTableValue( 20.0, 0.235294, 0.227451, 0.823529 ); + table->SetTableValue( 21.0, 0.235294, 0.227451, 0.823529 ); + table->SetTableValue( 22.0, 0.235294, 0.227451, 0.823529 ); + table->SetTableValue( 23.0, 0.235294, 0.227451, 0.823529 ); + table->SetTableValue( 24.0, 0.235294, 0.235294, 0.235294 ); + table->SetTableValue( 25.0, 1, 0.647059, 0 ); + table->SetTableValue( 26.0, 1, 0.647059, 0 ); + table->SetTableValue( 27.0, 0, 1, 0.498039 ); + table->SetTableValue( 28.0, 0.647059, 0.164706, 0.164706 ); + table->SetTableValue( 29.0, 0.529412, 0.807843, 0.921569 ); + table->SetTableValue( 30.0, 0.627451, 0.12549, 0.941176 ); + table->SetTableValue( 31.0, 0, 0.784314, 0.784314 ); + table->SetTableValue( 32.0, 0.392157, 0.196078, 0.392157 ); + table->SetTableValue( 33.0, 0.529412, 0.196078, 0.290196 ); + table->SetTableValue( 34.0, 0.478431, 0.529412, 0.196078 ); + table->SetTableValue( 35.0, 0.2, 0.196078, 0.529412 ); + table->SetTableValue( 36.0, 0.290196, 0.607843, 0.235294 ); + table->SetTableValue( 37.0, 0.470588, 0.243137, 0.168627 ); + table->SetTableValue( 38.0, 0.290196, 0.607843, 0.235294 ); + table->SetTableValue( 39.0, 0.478431, 0.529412, 0.196078 ); + table->SetTableValue( 40.0, 0.27451, 0.509804, 0.705882 ); + table->SetTableValue( 41.0, 0, 0.882353, 0 ); + table->SetTableValue( 42.0, 0.803922, 0.243137, 0.305882 ); + table->SetTableValue( 43.0, 0.470588, 0.0705882, 0.52549 ); + table->SetTableValue( 44.0, 0.768627, 0.227451, 0.980392 ); + table->SetTableValue( 45.0, 0, 0.580392, 0 ); + table->SetTableValue( 46.0, 0.862745, 0.972549, 0.643137 ); + table->SetTableValue( 47.0, 0.901961, 0.580392, 0.133333 ); + table->SetTableValue( 48.0, 0, 0.462745, 0.054902 ); + table->SetTableValue( 49.0, 0, 0.462745, 0.054902 ); + table->SetTableValue( 50.0, 0.478431, 0.729412, 0.862745 ); + table->SetTableValue( 51.0, 0.92549, 0.0509804, 0.690196 ); + table->SetTableValue( 52.0, 0.0509804, 0.188235, 1 ); + table->SetTableValue( 53.0, 0.862745, 0.847059, 0.0784314 ); + table->SetTableValue( 54.0, 0.403922, 1, 1 ); + table->SetTableValue( 55.0, 0.313725, 0.768627, 0.384314 ); + table->SetTableValue( 56.0, 0.235294, 0.227451, 0.823529 ); + table->SetTableValue( 57.0, 1, 0.647059, 0 ); + table->SetTableValue( 58.0, 1, 0.647059, 0 ); + table->SetTableValue( 59.0, 0, 1, 0.498039 ); + table->SetTableValue( 60.0, 0.647059, 0.164706, 0.164706 ); + table->SetTableValue( 61.0, 0.529412, 0.807843, 0.921569 ); + table->SetTableValue( 62.0, 0.627451, 0.12549, 0.941176 ); + table->SetTableValue( 63.0, 0, 0.784314, 0.866667 ); + table->SetTableValue( 64.0, 0.392157, 0.196078, 0.392157 ); + table->SetTableValue( 65.0, 0.529412, 0.196078, 0.290196 ); + table->SetTableValue( 66.0, 0.478431, 0.529412, 0.196078 ); + table->SetTableValue( 67.0, 0.2, 0.196078, 0.529412 ); + table->SetTableValue( 68.0, 0.290196, 0.607843, 0.235294 ); + table->SetTableValue( 69.0, 0.470588, 0.243137, 0.168627 ); + table->SetTableValue( 70.0, 0.290196, 0.607843, 0.235294 ); + table->SetTableValue( 71.0, 0.478431, 0.529412, 0.196078 ); + table->SetTableValue( 72.0, 0.470588, 0.745098, 0.588235 ); + table->SetTableValue( 73.0, 0.478431, 0.529412, 0.196078 ); + table->SetTableValue( 74.0, 0.478431, 0.529412, 0.196078 ); + table->SetTableValue( 77.0, 0.784314, 0.27451, 1 ); + table->SetTableValue( 78.0, 1, 0.580392, 0.0392157 ); + table->SetTableValue( 79.0, 1, 0.580392, 0.0392157 ); + table->SetTableValue( 80.0, 0.643137, 0.423529, 0.886275 ); + table->SetTableValue( 81.0, 0.643137, 0.423529, 0.886275 ); + table->SetTableValue( 82.0, 0.643137, 0.423529, 0.886275 ); + table->SetTableValue( 83.0, 1, 0.854902, 0.72549 ); + table->SetTableValue( 84.0, 1, 0.854902, 0.72549 ); + table->SetTableValue( 85.0, 0.917647, 0.662745, 0.117647 ); + table->SetTableValue( 192.0, 0.980392, 1, 0.196078 ); + table->SetTableValue( 86.0, 0.784314, 0.470588, 1 ); + table->SetTableValue( 87.0, 0.784314, 0.47451, 1 ); + table->SetTableValue( 88.0, 0.784314, 0.478431, 1 ); + table->SetTableValue( 96.0, 0.803922, 0.0392157, 0.490196 ); + table->SetTableValue( 97.0, 0.803922, 0.0392157, 0.490196 ); + table->SetTableValue( 98.0, 0.627451, 0.12549, 0.941176 ); + table->SetTableValue( 100.0, 0.486275, 0.54902, 0.698039 ); + table->SetTableValue( 101.0, 0.490196, 0.54902, 0.698039 ); + table->SetTableValue( 102.0, 0.494118, 0.54902, 0.698039 ); + table->SetTableValue( 103.0, 0.498039, 0.54902, 0.698039 ); + table->SetTableValue( 104.0, 0.486275, 0.552941, 0.698039 ); + table->SetTableValue( 105.0, 0.486275, 0.556863, 0.698039 ); + table->SetTableValue( 106.0, 0.486275, 0.560784, 0.698039 ); + table->SetTableValue( 107.0, 0.486275, 0.564706, 0.698039 ); + table->SetTableValue( 108.0, 0.486275, 0.54902, 0.701961 ); + table->SetTableValue( 109.0, 0.486275, 0.54902, 0.698039 ); + table->SetTableValue( 110.0, 0.490196, 0.54902, 0.698039 ); + table->SetTableValue( 111.0, 0.494118, 0.54902, 0.698039 ); + table->SetTableValue( 112.0, 0.498039, 0.54902, 0.698039 ); + table->SetTableValue( 113.0, 0.486275, 0.552941, 0.698039 ); + table->SetTableValue( 114.0, 0.486275, 0.556863, 0.698039 ); + table->SetTableValue( 115.0, 0.486275, 0.560784, 0.698039 ); + table->SetTableValue( 116.0, 0.486275, 0.564706, 0.698039 ); + table->SetTableValue( 117.0, 0.486275, 0.54902, 0.701961 ); + table->SetTableValue( 118.0, 1, 0.0784314, 0.576471 ); + table->SetTableValue( 119.0, 0.803922, 0.701961, 0.545098 ); + table->SetTableValue( 120.0, 0.933333, 0.933333, 0.819608 ); + table->SetTableValue( 121.0, 0.784314, 0.784314, 0.784314 ); + table->SetTableValue( 122.0, 0.290196, 1, 0.290196 ); + table->SetTableValue( 123.0, 0.933333, 0, 0 ); + table->SetTableValue( 124.0, 0, 0, 0.545098 ); + table->SetTableValue( 125.0, 0.678431, 1, 0.184314 ); + table->SetTableValue( 126.0, 0.521569, 0.796078, 0.898039 ); + table->SetTableValue( 127.0, 0.101961, 0.929412, 0.223529 ); + table->SetTableValue( 128.0, 0.133333, 0.545098, 0.133333 ); + table->SetTableValue( 129.0, 0.117647, 0.564706, 1 ); + table->SetTableValue( 130.0, 0.576471, 0.0745098, 0.678431 ); + table->SetTableValue( 131.0, 0.933333, 0.231373, 0.231373 ); + table->SetTableValue( 132.0, 0.866667, 0.152941, 0.784314 ); + table->SetTableValue( 133.0, 0.933333, 0.682353, 0.933333 ); + table->SetTableValue( 134.0, 1, 0, 0 ); + table->SetTableValue( 135.0, 0.282353, 0.239216, 0.545098 ); + table->SetTableValue( 136.0, 0.0823529, 0.152941, 0.517647 ); + table->SetTableValue( 137.0, 0.0823529, 0.152941, 0.517647 ); + table->SetTableValue( 138.0, 0.254902, 0.529412, 0.0784314 ); + table->SetTableValue( 139.0, 0.254902, 0.529412, 0.0784314 ); + table->SetTableValue( 140.0, 0.52549, 0.0156863, 0.627451 ); + table->SetTableValue( 142.0, 0.866667, 0.886275, 0.266667 ); + table->SetTableValue( 143.0, 1, 1, 0.996078 ); + table->SetTableValue( 144.0, 0.203922, 0.819608, 0.886275 ); + table->SetTableValue( 145.0, 0.937255, 0.627451, 0.87451 ); + table->SetTableValue( 146.0, 0.27451, 0.509804, 0.705882 ); + table->SetTableValue( 147.0, 0.27451, 0.509804, 0.709804 ); + table->SetTableValue( 148.0, 0.545098, 0.47451, 0.368627 ); + table->SetTableValue( 149.0, 0.878431, 0.878431, 0.878431 ); + table->SetTableValue( 150.0, 1, 0, 0 ); + table->SetTableValue( 151.0, 0.803922, 0.803922, 0 ); + table->SetTableValue( 152.0, 0.933333, 0.933333, 0.819608 ); + table->SetTableValue( 153.0, 0.545098, 0.47451, 0.368627 ); + table->SetTableValue( 154.0, 0.933333, 0.231373, 0.231373 ); + table->SetTableValue( 155.0, 0.933333, 0.231373, 0.231373 ); + table->SetTableValue( 156.0, 0.933333, 0.231373, 0.231373 ); + table->SetTableValue( 157.0, 0.243137, 0.0392157, 0.803922 ); + table->SetTableValue( 158.0, 0.243137, 0.0392157, 0.803922 ); + table->SetTableValue( 159.0, 0, 0.462745, 0.054902 ); + table->SetTableValue( 160.0, 0, 0.462745, 0.054902 ); + table->SetTableValue( 161.0, 0.862745, 0.847059, 0.0823529 ); + table->SetTableValue( 162.0, 0.862745, 0.847059, 0.0823529 ); + table->SetTableValue( 163.0, 0.478431, 0.729412, 0.862745 ); + table->SetTableValue( 164.0, 0.478431, 0.729412, 0.862745 ); + table->SetTableValue( 165.0, 1, 0.647059, 0 ); + table->SetTableValue( 166.0, 0.054902, 0.188235, 1 ); + table->SetTableValue( 167.0, 0.65098, 0.164706, 0.164706 ); + table->SetTableValue( 168.0, 0.47451, 0.0705882, 0.52549 ); + table->SetTableValue( 169.0, 0.92549, 0.0509804, 0.498039 ); + table->SetTableValue( 176.0, 0.92549, 0.0509804, 0.494118 ); + table->SetTableValue( 170.0, 0.466667, 0.623529, 0.690196 ); + table->SetTableValue( 171.0, 0.466667, 0, 0.690196 ); + table->SetTableValue( 172.0, 0.466667, 0.392157, 0.690196 ); + table->SetTableValue( 173.0, 0.466667, 0.784314, 0.690196 ); + table->SetTableValue( 174.0, 0.466667, 0.623529, 0.392157 ); + table->SetTableValue( 175.0, 0.466667, 0.623529, 0.784314 ); + table->SetTableValue( 180.0, 0.286275, 0.239216, 0.545098 ); + table->SetTableValue( 181.0, 0.286275, 0.243137, 0.545098 ); + table->SetTableValue( 193.0, 0, 0.768627, 1 ); + table->SetTableValue( 194.0, 1, 0.643137, 0.643137 ); + table->SetTableValue( 195.0, 0.768627, 0.768627, 0 ); + table->SetTableValue( 196.0, 0, 0.392157, 1 ); + table->SetTableValue( 197.0, 0.501961, 0.768627, 0.643137 ); + table->SetTableValue( 198.0, 0, 0.494118, 0.294118 ); + table->SetTableValue( 199.0, 0.501961, 0.376471, 0.25098 ); + table->SetTableValue( 200.0, 0, 0.196078, 0.501961 ); + table->SetTableValue( 201.0, 1, 0.8, 0.6 ); + table->SetTableValue( 202.0, 1, 0.501961, 0.501961 ); + table->SetTableValue( 203.0, 1, 1, 0 ); + table->SetTableValue( 204.0, 0.25098, 0, 0.25098 ); + table->SetTableValue( 205.0, 0, 0, 1 ); + table->SetTableValue( 206.0, 1, 0, 0 ); + table->SetTableValue( 207.0, 0.501961, 0.501961, 1 ); + table->SetTableValue( 208.0, 0, 0.501961, 0 ); + table->SetTableValue( 209.0, 0.768627, 0.627451, 0.501961 ); + table->SetTableValue( 210.0, 0.12549, 0.784314, 1 ); + table->SetTableValue( 211.0, 0.501961, 1, 0.501961 ); + table->SetTableValue( 212.0, 0.8, 0.6, 0.8 ); + table->SetTableValue( 213.0, 0.47451, 0.0666667, 0.533333 ); + table->SetTableValue( 214.0, 0.501961, 0, 0 ); + table->SetTableValue( 215.0, 0.501961, 0.12549, 1 ); + table->SetTableValue( 216.0, 1, 0.8, 0.4 ); + table->SetTableValue( 217.0, 0.501961, 0.501961, 0.501961 ); + table->SetTableValue( 218.0, 0.407843, 1, 1 ); + table->SetTableValue( 219.0, 0, 0.886275, 0 ); + table->SetTableValue( 220.0, 0.803922, 0.247059, 0.305882 ); + table->SetTableValue( 221.0, 0.772549, 0.227451, 0.980392 ); + table->SetTableValue( 222.0, 0.129412, 0.588235, 0.980392 ); + table->SetTableValue( 223.0, 0.886275, 0, 0 ); + table->SetTableValue( 224.0, 0.392157, 0.392157, 0.392157 ); + table->SetTableValue( 225.0, 0.772549, 0.588235, 0.980392 ); + table->SetTableValue( 226.0, 0.666667, 0.666667, 1 ); + table->SetTableValue( 250.0, 1, 0, 0 ); + table->SetTableValue( 251.0, 0, 0, 0.25098 ); + table->SetTableValue( 252.0, 0, 0, 0.439216 ); + table->SetTableValue( 253.0, 0, 0, 0.627451 ); + table->SetTableValue( 254.0, 0, 0, 0.815686 ); + table->SetTableValue( 255.0, 0, 0, 1 ); + table->SetTableValue( 256.0, 0, 0, 0, 0); + table->SetTableValue( 331.0, 1, 0, 0 ); + table->SetTableValue( 332.0, 1, 0.313725, 0 ); + table->SetTableValue( 333.0, 1, 0.627451, 0 ); + table->SetTableValue( 334.0, 1, 1, 0 ); + table->SetTableValue( 335.0, 0, 1, 0 ); + table->SetTableValue( 336.0, 1, 0, 0.627451 ); + table->SetTableValue( 337.0, 1, 0, 1 ); + table->SetTableValue( 338.0, 1, 0.196078, 0.313725 ); + table->SetTableValue( 339.0, 0.313725, 1, 0.196078 ); + table->SetTableValue( 340.0, 0.627451, 1, 0.196078 ); + table->SetTableValue( 341.0, 0.627451, 0.784314, 1 ); + table->SetTableValue( 342.0, 0, 1, 0.627451 ); + table->SetTableValue( 343.0, 0, 0, 1 ); + table->SetTableValue( 344.0, 0.313725, 0.196078, 1 ); + table->SetTableValue( 345.0, 0.627451, 0, 1 ); + table->SetTableValue( 346.0, 1, 0.823529, 0 ); + table->SetTableValue( 347.0, 0, 0.627451, 1 ); + table->SetTableValue( 348.0, 1, 0.784314, 0.313725 ); + table->SetTableValue( 349.0, 1, 0.784314, 0.627451 ); + table->SetTableValue( 350.0, 1, 0.313725, 0.784314 ); + table->SetTableValue( 351.0, 1, 0.627451, 0.784314 ); + table->SetTableValue( 352.0, 0.117647, 1, 0.313725 ); + table->SetTableValue( 353.0, 0.313725, 0.784314, 1 ); + table->SetTableValue( 354.0, 0.313725, 1, 0.784314 ); + table->SetTableValue( 355.0, 0.764706, 1, 0.784314 ); + table->SetTableValue( 356.0, 0.470588, 0.784314, 0.0784314 ); + table->SetTableValue( 357.0, 0.666667, 0.0392157, 0.784314 ); + table->SetTableValue( 358.0, 0.0784314, 0.509804, 0.705882 ); + table->SetTableValue( 359.0, 0.0784314, 0.705882, 0.509804 ); + table->SetTableValue( 400.0, 0.807843, 0.243137, 0.305882 ); + table->SetTableValue( 401.0, 0.47451, 0.0705882, 0.52549 ); + table->SetTableValue( 402.0, 0.780392, 0.227451, 0.980392 ); + table->SetTableValue( 403.0, 0.00392157, 0.580392, 0 ); + table->SetTableValue( 404.0, 0.866667, 0.972549, 0.643137 ); + table->SetTableValue( 405.0, 0.905882, 0.580392, 0.133333 ); + table->SetTableValue( 406.0, 0.00392157, 0.462745, 0.054902 ); + table->SetTableValue( 407.0, 0.470588, 0.462745, 0.054902 ); + table->SetTableValue( 408.0, 0.482353, 0.729412, 0.866667 ); + table->SetTableValue( 409.0, 0.933333, 0.0509804, 0.694118 ); + table->SetTableValue( 410.0, 0.482353, 0.729412, 0.862745 ); + table->SetTableValue( 411.0, 0.541176, 0.0509804, 0.807843 ); + table->SetTableValue( 412.0, 0.933333, 0.509804, 0.690196 ); + table->SetTableValue( 413.0, 0.854902, 0.901961, 0.298039 ); + table->SetTableValue( 414.0, 0.14902, 0.835294, 0.690196 ); + table->SetTableValue( 415.0, 0.00392157, 0.882353, 0.690196 ); + table->SetTableValue( 416.0, 0.00392157, 0.882353, 0.690196 ); + table->SetTableValue( 417.0, 0.784314, 0.00784314, 0.392157 ); + table->SetTableValue( 418.0, 0.784314, 0.00784314, 0.392157 ); + table->SetTableValue( 419.0, 0.0196078, 0.784314, 0.352941 ); + table->SetTableValue( 420.0, 0.0196078, 0.784314, 0.352941 ); + table->SetTableValue( 421.0, 0.392157, 0.0196078, 0.784314 ); + table->SetTableValue( 422.0, 0.0980392, 1, 0.392157 ); + table->SetTableValue( 423.0, 0.0980392, 1, 0.392157 ); + table->SetTableValue( 424.0, 0.901961, 0.027451, 0.392157 ); + table->SetTableValue( 425.0, 0.901961, 0.027451, 0.392157 ); + table->SetTableValue( 426.0, 0.392157, 0.0196078, 0.784314 ); + table->SetTableValue( 427.0, 0.588235, 0.0392157, 0.784314 ); + table->SetTableValue( 428.0, 0.588235, 0.0392157, 0.784314 ); + table->SetTableValue( 429.0, 0.686275, 0.0392157, 0.690196 ); + table->SetTableValue( 430.0, 0.686275, 0.0392157, 0.690196 ); + table->SetTableValue( 431.0, 0.0392157, 0.392157, 1 ); + table->SetTableValue( 432.0, 0.0392157, 0.392157, 1 ); + table->SetTableValue( 433.0, 0.588235, 0.176471, 0.27451 ); + table->SetTableValue( 434.0, 0.588235, 0.176471, 0.27451 ); + table->SetTableValue( 435.0, 0.176471, 0.784314, 0.0588235 ); + table->SetTableValue( 436.0, 0.176471, 0.784314, 0.0588235 ); + table->SetTableValue( 437.0, 0.890196, 0.176471, 0.392157 ); + table->SetTableValue( 438.0, 0.890196, 0.176471, 0.392157 ); + table->SetTableValue( 439.0, 0.890196, 0.176471, 0.392157 ); + table->SetTableValue( 498.0, 0.560784, 0.737255, 0.560784 ); + table->SetTableValue( 499.0, 1, 0.972549, 0.862745 ); + table->SetTableValue( 500.0, 0.0666667, 0.333333, 0.533333 ); + table->SetTableValue( 501.0, 0.466667, 0.733333, 0.4 ); + table->SetTableValue( 502.0, 0.8, 0.266667, 0.133333 ); + table->SetTableValue( 503.0, 0.8, 0, 1 ); + table->SetTableValue( 504.0, 0.866667, 0.733333, 0.0666667 ); + table->SetTableValue( 505.0, 0.6, 0.866667, 0.933333 ); + table->SetTableValue( 506.0, 0.2, 0.0666667, 0.0666667 ); + table->SetTableValue( 507.0, 0, 0.466667, 0.333333 ); + table->SetTableValue( 508.0, 0.0784314, 0.392157, 0.784314 ); + table->SetTableValue( 550.0, 0.0666667, 0.333333, 0.537255 ); + table->SetTableValue( 551.0, 0.466667, 0.733333, 0.403922 ); + table->SetTableValue( 552.0, 0.8, 0.266667, 0.137255 ); + table->SetTableValue( 553.0, 0.8, 0, 0.996078 ); + table->SetTableValue( 554.0, 0.866667, 0.733333, 0.0627451 ); + table->SetTableValue( 555.0, 0.6, 0.866667, 0.937255 ); + table->SetTableValue( 556.0, 0.2, 0.0666667, 0.0705882 ); + table->SetTableValue( 557.0, 0, 0.466667, 0.337255 ); + table->SetTableValue( 558.0, 0.0784314, 0.392157, 0.788235 ); + table->SetTableValue( 600.0, 0.996078, 0.996078, 0.996078 ); + table->SetTableValue( 601.0, 0.27451, 0.509804, 0.705882 ); + table->SetTableValue( 602.0, 0.960784, 0.960784, 0.960784 ); + table->SetTableValue( 603.0, 0.803922, 0.243137, 0.305882 ); + table->SetTableValue( 604.0, 0.470588, 0.0705882, 0.52549 ); + table->SetTableValue( 605.0, 0.768627, 0.227451, 0.980392 ); + table->SetTableValue( 606.0, 0, 0.580392, 0 ); + table->SetTableValue( 607.0, 0.862745, 0.972549, 0.643137 ); + table->SetTableValue( 608.0, 0.901961, 0.580392, 0.133333 ); + table->SetTableValue( 609.0, 0, 0.462745, 0.054902 ); + table->SetTableValue( 610.0, 0, 0.462745, 0.054902 ); + table->SetTableValue( 611.0, 0.478431, 0.729412, 0.862745 ); + table->SetTableValue( 612.0, 0.92549, 0.0509804, 0.690196 ); + table->SetTableValue( 613.0, 0.0470588, 0.188235, 1 ); + table->SetTableValue( 614.0, 0.8, 0.713725, 0.556863 ); + table->SetTableValue( 615.0, 0.164706, 0.8, 0.643137 ); + table->SetTableValue( 616.0, 0.466667, 0.623529, 0.690196 ); + table->SetTableValue( 617.0, 0.862745, 0.847059, 0.0784314 ); + table->SetTableValue( 618.0, 0.403922, 1, 1 ); + table->SetTableValue( 619.0, 0.313725, 0.768627, 0.384314 ); + table->SetTableValue( 620.0, 0.235294, 0.227451, 0.823529 ); + table->SetTableValue( 621.0, 0.235294, 0.227451, 0.823529 ); + table->SetTableValue( 622.0, 0.235294, 0.227451, 0.823529 ); + table->SetTableValue( 623.0, 0.235294, 0.227451, 0.823529 ); + table->SetTableValue( 624.0, 0.235294, 0.235294, 0.235294 ); + table->SetTableValue( 625.0, 1, 0.647059, 0 ); + table->SetTableValue( 626.0, 1, 0.647059, 0 ); + table->SetTableValue( 627.0, 0, 1, 0.498039 ); + table->SetTableValue( 628.0, 0.647059, 0.164706, 0.164706 ); + table->SetTableValue( 640.0, 0.8, 0, 0 ); + table->SetTableValue( 641.0, 1, 0, 0 ); + table->SetTableValue( 642.0, 0, 0, 1 ); + table->SetTableValue( 643.0, 0.117647, 0.564706, 1 ); + table->SetTableValue( 644.0, 0.392157, 0.831373, 0.929412 ); + table->SetTableValue( 645.0, 0.854902, 0.647059, 0.12549 ); + table->SetTableValue( 646.0, 1, 0.843137, 0 ); + table->SetTableValue( 647.0, 1, 1, 0.65098 ); + table->SetTableValue( 648.0, 0.6, 0, 0.8 ); + table->SetTableValue( 649.0, 0.6, 0.552941, 0.819608 ); + table->SetTableValue( 650.0, 0.8, 0.8, 1 ); + table->SetTableValue( 651.0, 0.121569, 0.831373, 0.760784 ); + table->SetTableValue( 652.0, 0.0117647, 1, 0.929412 ); + table->SetTableValue( 653.0, 0.8, 1, 1 ); + table->SetTableValue( 654.0, 0.337255, 0.290196, 0.576471 ); + table->SetTableValue( 655.0, 0.447059, 0.447059, 0.745098 ); + table->SetTableValue( 656.0, 0.721569, 0.698039, 1 ); + table->SetTableValue( 657.0, 0.494118, 0.541176, 0.145098 ); + table->SetTableValue( 658.0, 0.741176, 0.772549, 0.458824 ); + table->SetTableValue( 659.0, 0.941176, 0.901961, 0.54902 ); + table->SetTableValue( 660.0, 0.8, 0, 0 ); + table->SetTableValue( 661.0, 1, 0, 0 ); + table->SetTableValue( 662.0, 0, 0, 1 ); + table->SetTableValue( 663.0, 0.117647, 0.564706, 1 ); + table->SetTableValue( 664.0, 0.392157, 0.831373, 0.929412 ); + table->SetTableValue( 665.0, 0.854902, 0.647059, 0.12549 ); + table->SetTableValue( 666.0, 1, 0.843137, 0 ); + table->SetTableValue( 667.0, 1, 1, 0.65098 ); + table->SetTableValue( 668.0, 0.6, 0, 0.8 ); + table->SetTableValue( 669.0, 0.6, 0.552941, 0.819608 ); + table->SetTableValue( 670.0, 0.8, 0.8, 1 ); + table->SetTableValue( 671.0, 0.121569, 0.831373, 0.760784 ); + table->SetTableValue( 672.0, 0.0117647, 1, 0.929412 ); + table->SetTableValue( 673.0, 0.8, 1, 1 ); + table->SetTableValue( 674.0, 0.337255, 0.290196, 0.576471 ); + table->SetTableValue( 675.0, 0.447059, 0.447059, 0.745098 ); + table->SetTableValue( 676.0, 0.721569, 0.698039, 1 ); + table->SetTableValue( 677.0, 0.494118, 0.541176, 0.145098 ); + table->SetTableValue( 678.0, 0.741176, 0.772549, 0.458824 ); + table->SetTableValue( 679.0, 0.941176, 0.901961, 0.54902 ); + table->SetTableValue( 701.0, 0.470588, 0.0705882, 0.52549 ); + table->SetTableValue( 702.0, 0.803922, 0.243137, 0.305882 ); + table->SetTableValue( 703.0, 0, 0.882353, 0 ); + table->SetTableValue( 999.0, 1, 0.392157, 0.392157 ); + table->SetTableValue( 1000.0, 0.0980392, 0.0196078, 0.0980392 ); + table->SetTableValue( 1001.0, 0.0980392, 0.392157, 0.156863 ); + table->SetTableValue( 1002.0, 0.490196, 0.392157, 0.627451 ); + table->SetTableValue( 1003.0, 0.392157, 0.0980392, 0 ); + table->SetTableValue( 1004.0, 0.470588, 0.27451, 0.196078 ); + table->SetTableValue( 1005.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 1006.0, 0.862745, 0.0784314, 0.0392157 ); + table->SetTableValue( 1007.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 1008.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 1009.0, 0.705882, 0.156863, 0.470588 ); + table->SetTableValue( 1010.0, 0.54902, 0.0784314, 0.54902 ); + table->SetTableValue( 1011.0, 0.0784314, 0.117647, 0.54902 ); + table->SetTableValue( 1012.0, 0.137255, 0.294118, 0.196078 ); + table->SetTableValue( 1013.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 1014.0, 0.784314, 0.137255, 0.294118 ); + table->SetTableValue( 1015.0, 0.627451, 0.392157, 0.196078 ); + table->SetTableValue( 1016.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 1017.0, 0.235294, 0.862745, 0.235294 ); + table->SetTableValue( 1018.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 1019.0, 0.0784314, 0.392157, 0.196078 ); + table->SetTableValue( 1020.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 1021.0, 0.470588, 0.392157, 0.235294 ); + table->SetTableValue( 1022.0, 0.862745, 0.0784314, 0.0784314 ); + table->SetTableValue( 1023.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 1024.0, 0.235294, 0.0784314, 0.862745 ); + table->SetTableValue( 1025.0, 0.627451, 0.54902, 0.705882 ); + table->SetTableValue( 1026.0, 0.313725, 0.0784314, 0.54902 ); + table->SetTableValue( 1027.0, 0.294118, 0.196078, 0.490196 ); + table->SetTableValue( 1028.0, 0.0784314, 0.862745, 0.627451 ); + table->SetTableValue( 1029.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 1030.0, 0.54902, 0.862745, 0.862745 ); + table->SetTableValue( 1031.0, 0.313725, 0.627451, 0.0784314 ); + table->SetTableValue( 1032.0, 0.392157, 0, 0.392157 ); + table->SetTableValue( 1033.0, 0.27451, 0.27451, 0.27451 ); + table->SetTableValue( 1034.0, 0.588235, 0.588235, 0.784314 ); + table->SetTableValue( 1035.0, 1, 0.752941, 0.12549 ); + table->SetTableValue( 2000.0, 0.0980392, 0.0196078, 0.0980392 ); + table->SetTableValue( 2001.0, 0.0980392, 0.392157, 0.156863 ); + table->SetTableValue( 2002.0, 0.490196, 0.392157, 0.627451 ); + table->SetTableValue( 2003.0, 0.392157, 0.0980392, 0 ); + table->SetTableValue( 2004.0, 0.470588, 0.27451, 0.196078 ); + table->SetTableValue( 2005.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 2006.0, 0.862745, 0.0784314, 0.0392157 ); + table->SetTableValue( 2007.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 2008.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 2009.0, 0.705882, 0.156863, 0.470588 ); + table->SetTableValue( 2010.0, 0.54902, 0.0784314, 0.54902 ); + table->SetTableValue( 2011.0, 0.0784314, 0.117647, 0.54902 ); + table->SetTableValue( 2012.0, 0.137255, 0.294118, 0.196078 ); + table->SetTableValue( 2013.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 2014.0, 0.784314, 0.137255, 0.294118 ); + table->SetTableValue( 2015.0, 0.627451, 0.392157, 0.196078 ); + table->SetTableValue( 2016.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 2017.0, 0.235294, 0.862745, 0.235294 ); + table->SetTableValue( 2018.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 2019.0, 0.0784314, 0.392157, 0.196078 ); + table->SetTableValue( 2020.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 2021.0, 0.470588, 0.392157, 0.235294 ); + table->SetTableValue( 2022.0, 0.862745, 0.0784314, 0.0784314 ); + table->SetTableValue( 2023.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 2024.0, 0.235294, 0.0784314, 0.862745 ); + table->SetTableValue( 2025.0, 0.627451, 0.54902, 0.705882 ); + table->SetTableValue( 2026.0, 0.313725, 0.0784314, 0.54902 ); + table->SetTableValue( 2027.0, 0.294118, 0.196078, 0.490196 ); + table->SetTableValue( 2028.0, 0.0784314, 0.862745, 0.627451 ); + table->SetTableValue( 2029.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 2030.0, 0.54902, 0.862745, 0.862745 ); + table->SetTableValue( 2031.0, 0.313725, 0.627451, 0.0784314 ); + table->SetTableValue( 2032.0, 0.392157, 0, 0.392157 ); + table->SetTableValue( 2033.0, 0.27451, 0.27451, 0.27451 ); + table->SetTableValue( 2034.0, 0.588235, 0.588235, 0.784314 ); + table->SetTableValue( 2035.0, 1, 0.752941, 0.12549 ); + table->SetTableValue( 3000.0, 0.901961, 0.980392, 0.901961 ); + table->SetTableValue( 3001.0, 0.901961, 0.607843, 0.843137 ); + table->SetTableValue( 3002.0, 0.509804, 0.607843, 0.372549 ); + table->SetTableValue( 3003.0, 0.607843, 0.901961, 1 ); + table->SetTableValue( 3004.0, 0.529412, 0.72549, 0.803922 ); + table->SetTableValue( 3005.0, 0.137255, 0.921569, 0.607843 ); + table->SetTableValue( 3006.0, 0.137255, 0.921569, 0.960784 ); + table->SetTableValue( 3007.0, 0.294118, 0.137255, 0.45098 ); + table->SetTableValue( 3008.0, 0.137255, 0.764706, 0.137255 ); + table->SetTableValue( 3009.0, 0.294118, 0.843137, 0.529412 ); + table->SetTableValue( 3010.0, 0.45098, 0.921569, 0.45098 ); + table->SetTableValue( 3011.0, 0.921569, 0.882353, 0.45098 ); + table->SetTableValue( 3012.0, 0.862745, 0.705882, 0.803922 ); + table->SetTableValue( 3013.0, 0.117647, 0.45098, 0.45098 ); + table->SetTableValue( 3014.0, 0.215686, 0.862745, 0.705882 ); + table->SetTableValue( 3015.0, 0.372549, 0.607843, 0.803922 ); + table->SetTableValue( 3016.0, 0.921569, 0.137255, 0.764706 ); + table->SetTableValue( 3017.0, 0.764706, 0.137255, 0.764706 ); + table->SetTableValue( 3018.0, 0.137255, 0.294118, 0.45098 ); + table->SetTableValue( 3019.0, 0.921569, 0.607843, 0.803922 ); + table->SetTableValue( 3020.0, 0.137255, 0.764706, 0.921569 ); + table->SetTableValue( 3021.0, 0.529412, 0.607843, 0.764706 ); + table->SetTableValue( 3022.0, 0.137255, 0.921569, 0.921569 ); + table->SetTableValue( 3023.0, 0.137255, 0.294118, 0.137255 ); + table->SetTableValue( 3024.0, 0.764706, 0.921569, 0.137255 ); + table->SetTableValue( 3025.0, 0.372549, 0.45098, 0.294118 ); + table->SetTableValue( 3026.0, 0.686275, 0.921569, 0.45098 ); + table->SetTableValue( 3027.0, 0.705882, 0.803922, 0.509804 ); + table->SetTableValue( 3028.0, 0.921569, 0.137255, 0.372549 ); + table->SetTableValue( 3029.0, 0.921569, 0.294118, 0.45098 ); + table->SetTableValue( 3030.0, 0.45098, 0.137255, 0.137255 ); + table->SetTableValue( 3031.0, 0.686275, 0.372549, 0.921569 ); + table->SetTableValue( 3032.0, 0.607843, 1, 0.607843 ); + table->SetTableValue( 3033.0, 0.72549, 0.72549, 0.72549 ); + table->SetTableValue( 3034.0, 0.411765, 0.411765, 0.215686 ); + table->SetTableValue( 3035.0, 0.996078, 0.74902, 0.121569 ); + table->SetTableValue( 4000.0, 0.901961, 0.980392, 0.901961 ); + table->SetTableValue( 4001.0, 0.901961, 0.607843, 0.843137 ); + table->SetTableValue( 4002.0, 0.509804, 0.607843, 0.372549 ); + table->SetTableValue( 4003.0, 0.607843, 0.901961, 1 ); + table->SetTableValue( 4004.0, 0.529412, 0.72549, 0.803922 ); + table->SetTableValue( 4005.0, 0.137255, 0.921569, 0.607843 ); + table->SetTableValue( 4006.0, 0.137255, 0.921569, 0.960784 ); + table->SetTableValue( 4007.0, 0.294118, 0.137255, 0.45098 ); + table->SetTableValue( 4008.0, 0.137255, 0.764706, 0.137255 ); + table->SetTableValue( 4009.0, 0.294118, 0.843137, 0.529412 ); + table->SetTableValue( 4010.0, 0.45098, 0.921569, 0.45098 ); + table->SetTableValue( 4011.0, 0.921569, 0.882353, 0.45098 ); + table->SetTableValue( 4012.0, 0.862745, 0.705882, 0.803922 ); + table->SetTableValue( 4013.0, 0.117647, 0.45098, 0.45098 ); + table->SetTableValue( 4014.0, 0.215686, 0.862745, 0.705882 ); + table->SetTableValue( 4015.0, 0.372549, 0.607843, 0.803922 ); + table->SetTableValue( 4016.0, 0.921569, 0.137255, 0.764706 ); + table->SetTableValue( 4017.0, 0.764706, 0.137255, 0.764706 ); + table->SetTableValue( 4018.0, 0.137255, 0.294118, 0.45098 ); + table->SetTableValue( 4019.0, 0.921569, 0.607843, 0.803922 ); + table->SetTableValue( 4020.0, 0.137255, 0.764706, 0.921569 ); + table->SetTableValue( 4021.0, 0.529412, 0.607843, 0.764706 ); + table->SetTableValue( 4022.0, 0.137255, 0.921569, 0.921569 ); + table->SetTableValue( 4023.0, 0.137255, 0.294118, 0.137255 ); + table->SetTableValue( 4024.0, 0.764706, 0.921569, 0.137255 ); + table->SetTableValue( 4025.0, 0.372549, 0.45098, 0.294118 ); + table->SetTableValue( 4026.0, 0.686275, 0.921569, 0.45098 ); + table->SetTableValue( 4027.0, 0.705882, 0.803922, 0.509804 ); + table->SetTableValue( 4028.0, 0.921569, 0.137255, 0.372549 ); + table->SetTableValue( 4029.0, 0.921569, 0.294118, 0.45098 ); + table->SetTableValue( 4030.0, 0.45098, 0.137255, 0.137255 ); + table->SetTableValue( 4031.0, 0.686275, 0.372549, 0.921569 ); + table->SetTableValue( 4032.0, 0.607843, 1, 0.607843 ); + table->SetTableValue( 4033.0, 0.72549, 0.72549, 0.72549 ); + table->SetTableValue( 4034.0, 0.411765, 0.411765, 0.215686 ); + table->SetTableValue( 4035.0, 0.996078, 0.74902, 0.121569 ); + table->SetTableValue( 1100.0, 0, 0, 0, 0); + table->SetTableValue( 1101.0, 0.196078, 0.196078, 0.196078 ); + table->SetTableValue( 1102.0, 0.705882, 0.0784314, 0.117647 ); + table->SetTableValue( 1103.0, 0.235294, 0.0980392, 0.0980392 ); + table->SetTableValue( 1104.0, 0.0980392, 0.235294, 0.235294 ); + table->SetTableValue( 1200.0, 0.0980392, 0.235294, 0.239216 ); + table->SetTableValue( 1201.0, 0.0980392, 0.352941, 0.235294 ); + table->SetTableValue( 1202.0, 0.0980392, 0.470588, 0.235294 ); + table->SetTableValue( 1205.0, 0.0980392, 0.588235, 0.235294 ); + table->SetTableValue( 1206.0, 0.0980392, 0.705882, 0.235294 ); + table->SetTableValue( 1207.0, 0.0980392, 0.823529, 0.235294 ); + table->SetTableValue( 1210.0, 0.0980392, 0.588235, 0.352941 ); + table->SetTableValue( 1211.0, 0.0980392, 0.705882, 0.352941 ); + table->SetTableValue( 1212.0, 0.0980392, 0.823529, 0.352941 ); + table->SetTableValue( 1105.0, 0.705882, 0.0784314, 0.0784314 ); + table->SetTableValue( 1106.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 1107.0, 0.54902, 0.235294, 0.235294 ); + table->SetTableValue( 1108.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 1109.0, 0.54902, 0.392157, 0.705882 ); + table->SetTableValue( 1110.0, 0.705882, 0.0784314, 0.54902 ); + table->SetTableValue( 1111.0, 0.54902, 0.0784314, 0.54902 ); + table->SetTableValue( 1112.0, 0.0823529, 0.0392157, 0.0392157 ); + table->SetTableValue( 1113.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 1114.0, 0.0901961, 0.235294, 0.705882 ); + table->SetTableValue( 1115.0, 0.705882, 0.235294, 0.705882 ); + table->SetTableValue( 1116.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 1117.0, 0.235294, 0.0784314, 0.54902 ); + table->SetTableValue( 1118.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 1119.0, 0.254902, 0.392157, 0.0784314 ); + table->SetTableValue( 1120.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 1121.0, 0.235294, 0.392157, 0.235294 ); + table->SetTableValue( 1122.0, 0.0784314, 0.235294, 0.862745 ); + table->SetTableValue( 1123.0, 0.392157, 0.392157, 0.235294 ); + table->SetTableValue( 1124.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 1125.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 1126.0, 0.235294, 0.54902, 0.705882 ); + table->SetTableValue( 1127.0, 0.0980392, 0.0784314, 0.54902 ); + table->SetTableValue( 1128.0, 0.0784314, 0.235294, 0.392157 ); + table->SetTableValue( 1129.0, 0.235294, 0.862745, 0.0784314 ); + table->SetTableValue( 1130.0, 0.235294, 0.0784314, 0.862745 ); + table->SetTableValue( 1131.0, 0.862745, 0.862745, 0.392157 ); + table->SetTableValue( 1132.0, 0.705882, 0.235294, 0.235294 ); + table->SetTableValue( 1133.0, 0.235294, 0.235294, 0.862745 ); + table->SetTableValue( 1134.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 1135.0, 0.254902, 0.862745, 0.235294 ); + table->SetTableValue( 1136.0, 0.0980392, 0.54902, 0.0784314 ); + table->SetTableValue( 1137.0, 0.0509804, 0, 0.980392 ); + table->SetTableValue( 1138.0, 0.239216, 0.0784314, 0.862745 ); + table->SetTableValue( 1139.0, 0.239216, 0.0784314, 0.235294 ); + table->SetTableValue( 1140.0, 0.239216, 0.235294, 0.392157 ); + table->SetTableValue( 1141.0, 0.0980392, 0.0980392, 0.0980392 ); + table->SetTableValue( 1142.0, 0.54902, 0.0784314, 0.235294 ); + table->SetTableValue( 1143.0, 0.862745, 0.705882, 0.0784314 ); + table->SetTableValue( 1144.0, 0.247059, 0.705882, 0.705882 ); + table->SetTableValue( 1145.0, 0.866667, 0.0784314, 0.0392157 ); + table->SetTableValue( 1146.0, 0.0823529, 0.862745, 0.0784314 ); + table->SetTableValue( 1147.0, 0.717647, 0.392157, 0.0784314 ); + table->SetTableValue( 1148.0, 0.866667, 0.0784314, 0.392157 ); + table->SetTableValue( 1149.0, 0.866667, 0.235294, 0.54902 ); + table->SetTableValue( 1150.0, 0.866667, 0.0784314, 0.862745 ); + table->SetTableValue( 1151.0, 0.239216, 0.862745, 0.862745 ); + table->SetTableValue( 1152.0, 0.392157, 0.784314, 0.784314 ); + table->SetTableValue( 1153.0, 0.0392157, 0.784314, 0.784314 ); + table->SetTableValue( 1154.0, 0.866667, 0.862745, 0.0784314 ); + table->SetTableValue( 1155.0, 0.552941, 0.0784314, 0.392157 ); + table->SetTableValue( 1156.0, 0.239216, 0.862745, 0.392157 ); + table->SetTableValue( 1157.0, 0.0823529, 0.862745, 0.235294 ); + table->SetTableValue( 1158.0, 0.552941, 0.235294, 0.0784314 ); + table->SetTableValue( 1159.0, 0.560784, 0.0784314, 0.862745 ); + table->SetTableValue( 1160.0, 0.239216, 0.0784314, 0.705882 ); + table->SetTableValue( 1161.0, 0.396078, 0.235294, 0.862745 ); + table->SetTableValue( 1162.0, 0.0823529, 0.0784314, 0.54902 ); + table->SetTableValue( 1163.0, 0.866667, 0.54902, 0.0784314 ); + table->SetTableValue( 1164.0, 0.552941, 0.392157, 0.862745 ); + table->SetTableValue( 1165.0, 0.396078, 0.0784314, 0.0784314 ); + table->SetTableValue( 1166.0, 0.866667, 0.392157, 0.0784314 ); + table->SetTableValue( 1167.0, 0.709804, 0.784314, 0.0784314 ); + table->SetTableValue( 1168.0, 0.0823529, 0.705882, 0.54902 ); + table->SetTableValue( 1169.0, 0.396078, 0.392157, 0.705882 ); + table->SetTableValue( 1170.0, 0.709804, 0.862745, 0.0784314 ); + table->SetTableValue( 1171.0, 0.0823529, 0.54902, 0.784314 ); + table->SetTableValue( 1172.0, 0.0823529, 0.0784314, 0.941176 ); + table->SetTableValue( 1173.0, 0.0823529, 0.0784314, 0.784314 ); + table->SetTableValue( 1174.0, 0.239216, 0.705882, 0.235294 ); + table->SetTableValue( 1175.0, 0.239216, 0.705882, 0.980392 ); + table->SetTableValue( 1176.0, 0.0823529, 0.0784314, 0.235294 ); + table->SetTableValue( 1177.0, 0.396078, 0.235294, 0.235294 ); + table->SetTableValue( 1178.0, 0.0823529, 0.862745, 0.862745 ); + table->SetTableValue( 1179.0, 0.0823529, 0.705882, 0.705882 ); + table->SetTableValue( 1180.0, 0.87451, 0.862745, 0.235294 ); + table->SetTableValue( 1181.0, 0.866667, 0.235294, 0.235294 ); + table->SetTableValue( 2100.0, 0, 0, 0, 0); + table->SetTableValue( 2101.0, 0.196078, 0.196078, 0.196078 ); + table->SetTableValue( 2102.0, 0.705882, 0.0784314, 0.117647 ); + table->SetTableValue( 2103.0, 0.235294, 0.0980392, 0.0980392 ); + table->SetTableValue( 2104.0, 0.0980392, 0.235294, 0.235294 ); + table->SetTableValue( 2105.0, 0.705882, 0.0784314, 0.0784314 ); + table->SetTableValue( 2106.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 2107.0, 0.54902, 0.235294, 0.235294 ); + table->SetTableValue( 2108.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 2109.0, 0.54902, 0.392157, 0.705882 ); + table->SetTableValue( 2110.0, 0.705882, 0.0784314, 0.54902 ); + table->SetTableValue( 2111.0, 0.54902, 0.0784314, 0.54902 ); + table->SetTableValue( 2112.0, 0.0823529, 0.0392157, 0.0392157 ); + table->SetTableValue( 2113.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 2114.0, 0.0901961, 0.235294, 0.705882 ); + table->SetTableValue( 2115.0, 0.705882, 0.235294, 0.705882 ); + table->SetTableValue( 2116.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 2117.0, 0.235294, 0.0784314, 0.54902 ); + table->SetTableValue( 2118.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 2119.0, 0.254902, 0.392157, 0.0784314 ); + table->SetTableValue( 2120.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 2121.0, 0.235294, 0.392157, 0.235294 ); + table->SetTableValue( 2122.0, 0.0784314, 0.235294, 0.862745 ); + table->SetTableValue( 2123.0, 0.392157, 0.392157, 0.235294 ); + table->SetTableValue( 2124.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 2125.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 2126.0, 0.235294, 0.54902, 0.705882 ); + table->SetTableValue( 2127.0, 0.0980392, 0.0784314, 0.54902 ); + table->SetTableValue( 2128.0, 0.0784314, 0.235294, 0.392157 ); + table->SetTableValue( 2129.0, 0.235294, 0.862745, 0.0784314 ); + table->SetTableValue( 2130.0, 0.235294, 0.0784314, 0.862745 ); + table->SetTableValue( 2131.0, 0.862745, 0.862745, 0.392157 ); + table->SetTableValue( 2132.0, 0.705882, 0.235294, 0.235294 ); + table->SetTableValue( 2133.0, 0.235294, 0.235294, 0.862745 ); + table->SetTableValue( 2134.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 2135.0, 0.254902, 0.862745, 0.235294 ); + table->SetTableValue( 2136.0, 0.0980392, 0.54902, 0.0784314 ); + table->SetTableValue( 2137.0, 0.0509804, 0, 0.980392 ); + table->SetTableValue( 2138.0, 0.239216, 0.0784314, 0.862745 ); + table->SetTableValue( 2139.0, 0.239216, 0.0784314, 0.235294 ); + table->SetTableValue( 2140.0, 0.239216, 0.235294, 0.392157 ); + table->SetTableValue( 2141.0, 0.0980392, 0.0980392, 0.0980392 ); + table->SetTableValue( 2142.0, 0.54902, 0.0784314, 0.235294 ); + table->SetTableValue( 2143.0, 0.862745, 0.705882, 0.0784314 ); + table->SetTableValue( 2144.0, 0.247059, 0.705882, 0.705882 ); + table->SetTableValue( 2145.0, 0.866667, 0.0784314, 0.0392157 ); + table->SetTableValue( 2146.0, 0.0823529, 0.862745, 0.0784314 ); + table->SetTableValue( 2147.0, 0.717647, 0.392157, 0.0784314 ); + table->SetTableValue( 2148.0, 0.866667, 0.0784314, 0.392157 ); + table->SetTableValue( 2149.0, 0.866667, 0.235294, 0.54902 ); + table->SetTableValue( 2150.0, 0.866667, 0.0784314, 0.862745 ); + table->SetTableValue( 2151.0, 0.239216, 0.862745, 0.862745 ); + table->SetTableValue( 2152.0, 0.392157, 0.784314, 0.784314 ); + table->SetTableValue( 2153.0, 0.0392157, 0.784314, 0.784314 ); + table->SetTableValue( 2154.0, 0.866667, 0.862745, 0.0784314 ); + table->SetTableValue( 2155.0, 0.552941, 0.0784314, 0.392157 ); + table->SetTableValue( 2156.0, 0.239216, 0.862745, 0.392157 ); + table->SetTableValue( 2157.0, 0.0823529, 0.862745, 0.235294 ); + table->SetTableValue( 2158.0, 0.552941, 0.235294, 0.0784314 ); + table->SetTableValue( 2159.0, 0.560784, 0.0784314, 0.862745 ); + table->SetTableValue( 2160.0, 0.239216, 0.0784314, 0.705882 ); + table->SetTableValue( 2161.0, 0.396078, 0.235294, 0.862745 ); + table->SetTableValue( 2162.0, 0.0823529, 0.0784314, 0.54902 ); + table->SetTableValue( 2163.0, 0.866667, 0.54902, 0.0784314 ); + table->SetTableValue( 2164.0, 0.552941, 0.392157, 0.862745 ); + table->SetTableValue( 2165.0, 0.396078, 0.0784314, 0.0784314 ); + table->SetTableValue( 2166.0, 0.866667, 0.392157, 0.0784314 ); + table->SetTableValue( 2167.0, 0.709804, 0.784314, 0.0784314 ); + table->SetTableValue( 2168.0, 0.0823529, 0.705882, 0.54902 ); + table->SetTableValue( 2169.0, 0.396078, 0.392157, 0.705882 ); + table->SetTableValue( 2170.0, 0.709804, 0.862745, 0.0784314 ); + table->SetTableValue( 2171.0, 0.0823529, 0.54902, 0.784314 ); + table->SetTableValue( 2172.0, 0.0823529, 0.0784314, 0.941176 ); + table->SetTableValue( 2173.0, 0.0823529, 0.0784314, 0.784314 ); + table->SetTableValue( 2174.0, 0.239216, 0.705882, 0.235294 ); + table->SetTableValue( 2175.0, 0.239216, 0.705882, 0.980392 ); + table->SetTableValue( 2176.0, 0.0823529, 0.0784314, 0.235294 ); + table->SetTableValue( 2177.0, 0.396078, 0.235294, 0.235294 ); + table->SetTableValue( 2178.0, 0.0823529, 0.862745, 0.862745 ); + table->SetTableValue( 2179.0, 0.0823529, 0.705882, 0.705882 ); + table->SetTableValue( 2180.0, 0.87451, 0.862745, 0.235294 ); + table->SetTableValue( 2181.0, 0.866667, 0.235294, 0.235294 ); + table->SetTableValue( 2200.0, 0.0980392, 0.235294, 0.239216 ); + table->SetTableValue( 2201.0, 0.0980392, 0.352941, 0.235294 ); + table->SetTableValue( 2202.0, 0.0980392, 0.470588, 0.235294 ); + table->SetTableValue( 2205.0, 0.0980392, 0.588235, 0.235294 ); + table->SetTableValue( 2206.0, 0.0980392, 0.705882, 0.235294 ); + table->SetTableValue( 2207.0, 0.0980392, 0.823529, 0.235294 ); + table->SetTableValue( 2210.0, 0.0980392, 0.588235, 0.352941 ); + table->SetTableValue( 2211.0, 0.0980392, 0.705882, 0.352941 ); + table->SetTableValue( 2212.0, 0.0980392, 0.823529, 0.352941 ); + table->SetTableValue( 3100.0, 0, 0, 0, 0); + table->SetTableValue( 3101.0, 0.196078, 0.196078, 0.196078 ); + table->SetTableValue( 3102.0, 0.705882, 0.0784314, 0.117647 ); + table->SetTableValue( 3103.0, 0.235294, 0.0980392, 0.0980392 ); + table->SetTableValue( 3104.0, 0.0980392, 0.235294, 0.235294 ); + table->SetTableValue( 3105.0, 0.705882, 0.0784314, 0.0784314 ); + table->SetTableValue( 3106.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 3107.0, 0.54902, 0.235294, 0.235294 ); + table->SetTableValue( 3108.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 3109.0, 0.54902, 0.392157, 0.705882 ); + table->SetTableValue( 3110.0, 0.705882, 0.0784314, 0.54902 ); + table->SetTableValue( 3111.0, 0.54902, 0.0784314, 0.54902 ); + table->SetTableValue( 3112.0, 0.0823529, 0.0392157, 0.0392157 ); + table->SetTableValue( 3113.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 3114.0, 0.0901961, 0.235294, 0.705882 ); + table->SetTableValue( 3115.0, 0.705882, 0.235294, 0.705882 ); + table->SetTableValue( 3116.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 3117.0, 0.235294, 0.0784314, 0.54902 ); + table->SetTableValue( 3118.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 3119.0, 0.254902, 0.392157, 0.0784314 ); + table->SetTableValue( 3120.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 3121.0, 0.235294, 0.392157, 0.235294 ); + table->SetTableValue( 3122.0, 0.0784314, 0.235294, 0.862745 ); + table->SetTableValue( 3123.0, 0.392157, 0.392157, 0.235294 ); + table->SetTableValue( 3124.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 3125.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 3126.0, 0.235294, 0.54902, 0.705882 ); + table->SetTableValue( 3127.0, 0.0980392, 0.0784314, 0.54902 ); + table->SetTableValue( 3128.0, 0.0784314, 0.235294, 0.392157 ); + table->SetTableValue( 3129.0, 0.235294, 0.862745, 0.0784314 ); + table->SetTableValue( 3130.0, 0.235294, 0.0784314, 0.862745 ); + table->SetTableValue( 3131.0, 0.862745, 0.862745, 0.392157 ); + table->SetTableValue( 3132.0, 0.705882, 0.235294, 0.235294 ); + table->SetTableValue( 3133.0, 0.235294, 0.235294, 0.862745 ); + table->SetTableValue( 3134.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 3135.0, 0.254902, 0.862745, 0.235294 ); + table->SetTableValue( 3136.0, 0.0980392, 0.54902, 0.0784314 ); + table->SetTableValue( 3137.0, 0.0509804, 0, 0.980392 ); + table->SetTableValue( 3138.0, 0.239216, 0.0784314, 0.862745 ); + table->SetTableValue( 3139.0, 0.239216, 0.0784314, 0.235294 ); + table->SetTableValue( 3140.0, 0.239216, 0.235294, 0.392157 ); + table->SetTableValue( 3141.0, 0.0980392, 0.0980392, 0.0980392 ); + table->SetTableValue( 3142.0, 0.54902, 0.0784314, 0.235294 ); + table->SetTableValue( 3143.0, 0.862745, 0.705882, 0.0784314 ); + table->SetTableValue( 3144.0, 0.247059, 0.705882, 0.705882 ); + table->SetTableValue( 3145.0, 0.866667, 0.0784314, 0.0392157 ); + table->SetTableValue( 3146.0, 0.0823529, 0.862745, 0.0784314 ); + table->SetTableValue( 3147.0, 0.717647, 0.392157, 0.0784314 ); + table->SetTableValue( 3148.0, 0.866667, 0.0784314, 0.392157 ); + table->SetTableValue( 3149.0, 0.866667, 0.235294, 0.54902 ); + table->SetTableValue( 3150.0, 0.866667, 0.0784314, 0.862745 ); + table->SetTableValue( 3151.0, 0.239216, 0.862745, 0.862745 ); + table->SetTableValue( 3152.0, 0.392157, 0.784314, 0.784314 ); + table->SetTableValue( 3153.0, 0.0392157, 0.784314, 0.784314 ); + table->SetTableValue( 3154.0, 0.866667, 0.862745, 0.0784314 ); + table->SetTableValue( 3155.0, 0.552941, 0.0784314, 0.392157 ); + table->SetTableValue( 3156.0, 0.239216, 0.862745, 0.392157 ); + table->SetTableValue( 3157.0, 0.0823529, 0.862745, 0.235294 ); + table->SetTableValue( 3158.0, 0.552941, 0.235294, 0.0784314 ); + table->SetTableValue( 3159.0, 0.560784, 0.0784314, 0.862745 ); + table->SetTableValue( 3160.0, 0.239216, 0.0784314, 0.705882 ); + table->SetTableValue( 3161.0, 0.396078, 0.235294, 0.862745 ); + table->SetTableValue( 3162.0, 0.0823529, 0.0784314, 0.54902 ); + table->SetTableValue( 3163.0, 0.866667, 0.54902, 0.0784314 ); + table->SetTableValue( 3164.0, 0.552941, 0.392157, 0.862745 ); + table->SetTableValue( 3165.0, 0.396078, 0.0784314, 0.0784314 ); + table->SetTableValue( 3166.0, 0.866667, 0.392157, 0.0784314 ); + table->SetTableValue( 3167.0, 0.709804, 0.784314, 0.0784314 ); + table->SetTableValue( 3168.0, 0.0823529, 0.705882, 0.54902 ); + table->SetTableValue( 3169.0, 0.396078, 0.392157, 0.705882 ); + table->SetTableValue( 3170.0, 0.709804, 0.862745, 0.0784314 ); + table->SetTableValue( 3171.0, 0.0823529, 0.54902, 0.784314 ); + table->SetTableValue( 3172.0, 0.0823529, 0.0784314, 0.941176 ); + table->SetTableValue( 3173.0, 0.0823529, 0.0784314, 0.784314 ); + table->SetTableValue( 3174.0, 0.239216, 0.705882, 0.235294 ); + table->SetTableValue( 3175.0, 0.239216, 0.705882, 0.980392 ); + table->SetTableValue( 3176.0, 0.0823529, 0.0784314, 0.235294 ); + table->SetTableValue( 3177.0, 0.396078, 0.235294, 0.235294 ); + table->SetTableValue( 3178.0, 0.0823529, 0.862745, 0.862745 ); + table->SetTableValue( 3179.0, 0.0823529, 0.705882, 0.705882 ); + table->SetTableValue( 3180.0, 0.87451, 0.862745, 0.235294 ); + table->SetTableValue( 3181.0, 0.866667, 0.235294, 0.235294 ); + table->SetTableValue( 4100.0, 0, 0, 0, 0); + table->SetTableValue( 4101.0, 0.196078, 0.196078, 0.196078 ); + table->SetTableValue( 4102.0, 0.705882, 0.0784314, 0.117647 ); + table->SetTableValue( 4103.0, 0.235294, 0.0980392, 0.0980392 ); + table->SetTableValue( 4104.0, 0.0980392, 0.235294, 0.235294 ); + table->SetTableValue( 4105.0, 0.705882, 0.0784314, 0.0784314 ); + table->SetTableValue( 4106.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 4107.0, 0.54902, 0.235294, 0.235294 ); + table->SetTableValue( 4108.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 4109.0, 0.54902, 0.392157, 0.705882 ); + table->SetTableValue( 4110.0, 0.705882, 0.0784314, 0.54902 ); + table->SetTableValue( 4111.0, 0.54902, 0.0784314, 0.54902 ); + table->SetTableValue( 4112.0, 0.0823529, 0.0392157, 0.0392157 ); + table->SetTableValue( 4113.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 4114.0, 0.0901961, 0.235294, 0.705882 ); + table->SetTableValue( 4115.0, 0.705882, 0.235294, 0.705882 ); + table->SetTableValue( 4116.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 4117.0, 0.235294, 0.0784314, 0.54902 ); + table->SetTableValue( 4118.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 4119.0, 0.254902, 0.392157, 0.0784314 ); + table->SetTableValue( 4120.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 4121.0, 0.235294, 0.392157, 0.235294 ); + table->SetTableValue( 4122.0, 0.0784314, 0.235294, 0.862745 ); + table->SetTableValue( 4123.0, 0.392157, 0.392157, 0.235294 ); + table->SetTableValue( 4124.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 4125.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 4126.0, 0.235294, 0.54902, 0.705882 ); + table->SetTableValue( 4127.0, 0.0980392, 0.0784314, 0.54902 ); + table->SetTableValue( 4128.0, 0.0784314, 0.235294, 0.392157 ); + table->SetTableValue( 4129.0, 0.235294, 0.862745, 0.0784314 ); + table->SetTableValue( 4130.0, 0.235294, 0.0784314, 0.862745 ); + table->SetTableValue( 4131.0, 0.862745, 0.862745, 0.392157 ); + table->SetTableValue( 4132.0, 0.705882, 0.235294, 0.235294 ); + table->SetTableValue( 4133.0, 0.235294, 0.235294, 0.862745 ); + table->SetTableValue( 4134.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 4135.0, 0.254902, 0.862745, 0.235294 ); + table->SetTableValue( 4136.0, 0.0980392, 0.54902, 0.0784314 ); + table->SetTableValue( 4137.0, 0.0509804, 0, 0.980392 ); + table->SetTableValue( 4138.0, 0.239216, 0.0784314, 0.862745 ); + table->SetTableValue( 4139.0, 0.239216, 0.0784314, 0.235294 ); + table->SetTableValue( 4140.0, 0.239216, 0.235294, 0.392157 ); + table->SetTableValue( 4141.0, 0.0980392, 0.0980392, 0.0980392 ); + table->SetTableValue( 4142.0, 0.54902, 0.0784314, 0.235294 ); + table->SetTableValue( 4143.0, 0.862745, 0.705882, 0.0784314 ); + table->SetTableValue( 4144.0, 0.247059, 0.705882, 0.705882 ); + table->SetTableValue( 4145.0, 0.866667, 0.0784314, 0.0392157 ); + table->SetTableValue( 4146.0, 0.0823529, 0.862745, 0.0784314 ); + table->SetTableValue( 4147.0, 0.717647, 0.392157, 0.0784314 ); + table->SetTableValue( 4148.0, 0.866667, 0.0784314, 0.392157 ); + table->SetTableValue( 4149.0, 0.866667, 0.235294, 0.54902 ); + table->SetTableValue( 4150.0, 0.866667, 0.0784314, 0.862745 ); + table->SetTableValue( 4151.0, 0.239216, 0.862745, 0.862745 ); + table->SetTableValue( 4152.0, 0.392157, 0.784314, 0.784314 ); + table->SetTableValue( 4153.0, 0.0392157, 0.784314, 0.784314 ); + table->SetTableValue( 4154.0, 0.866667, 0.862745, 0.0784314 ); + table->SetTableValue( 4155.0, 0.552941, 0.0784314, 0.392157 ); + table->SetTableValue( 4156.0, 0.239216, 0.862745, 0.392157 ); + table->SetTableValue( 4157.0, 0.0823529, 0.862745, 0.235294 ); + table->SetTableValue( 4158.0, 0.552941, 0.235294, 0.0784314 ); + table->SetTableValue( 4159.0, 0.560784, 0.0784314, 0.862745 ); + table->SetTableValue( 4160.0, 0.239216, 0.0784314, 0.705882 ); + table->SetTableValue( 4161.0, 0.396078, 0.235294, 0.862745 ); + table->SetTableValue( 4162.0, 0.0823529, 0.0784314, 0.54902 ); + table->SetTableValue( 4163.0, 0.866667, 0.54902, 0.0784314 ); + table->SetTableValue( 4164.0, 0.552941, 0.392157, 0.862745 ); + table->SetTableValue( 4165.0, 0.396078, 0.0784314, 0.0784314 ); + table->SetTableValue( 4166.0, 0.866667, 0.392157, 0.0784314 ); + table->SetTableValue( 4167.0, 0.709804, 0.784314, 0.0784314 ); + table->SetTableValue( 4168.0, 0.0823529, 0.705882, 0.54902 ); + table->SetTableValue( 4169.0, 0.396078, 0.392157, 0.705882 ); + table->SetTableValue( 4170.0, 0.709804, 0.862745, 0.0784314 ); + table->SetTableValue( 4171.0, 0.0823529, 0.54902, 0.784314 ); + table->SetTableValue( 4172.0, 0.0823529, 0.0784314, 0.941176 ); + table->SetTableValue( 4173.0, 0.0823529, 0.0784314, 0.784314 ); + table->SetTableValue( 4174.0, 0.239216, 0.705882, 0.235294 ); + table->SetTableValue( 4175.0, 0.239216, 0.705882, 0.980392 ); + table->SetTableValue( 4176.0, 0.0823529, 0.0784314, 0.235294 ); + table->SetTableValue( 4177.0, 0.396078, 0.235294, 0.235294 ); + table->SetTableValue( 4178.0, 0.0823529, 0.862745, 0.862745 ); + table->SetTableValue( 4179.0, 0.0823529, 0.705882, 0.705882 ); + table->SetTableValue( 4180.0, 0.87451, 0.862745, 0.235294 ); + table->SetTableValue( 4181.0, 0.866667, 0.235294, 0.235294 ); + table->SetTableValue( 5001.0, 0.0784314, 0.117647, 0.156863 ); + table->SetTableValue( 5002.0, 0.0784314, 0.117647, 0.156863 ); + table->SetTableValue( 5100.0, 0.8, 0.4, 0.4 ); + table->SetTableValue( 5101.0, 0.8, 0.4, 0.4 ); + table->SetTableValue( 5102.0, 1, 1, 0.4 ); + table->SetTableValue( 5103.0, 0.6, 0.8, 0 ); + table->SetTableValue( 5104.0, 0, 0.6, 0.6 ); + table->SetTableValue( 5105.0, 0.8, 0.6, 1 ); + table->SetTableValue( 5106.0, 1, 0.6, 0.2 ); + table->SetTableValue( 5107.0, 0.8, 0.8, 0.8 ); + table->SetTableValue( 5108.0, 0.6, 1, 1 ); + table->SetTableValue( 5109.0, 0.4, 0.6, 1 ); + table->SetTableValue( 5110.0, 1, 1, 0.4 ); + table->SetTableValue( 5111.0, 0.6, 0.8, 0 ); + table->SetTableValue( 5112.0, 0, 0.6, 0.6 ); + table->SetTableValue( 5113.0, 0.8, 0.6, 1 ); + table->SetTableValue( 5114.0, 1, 0.6, 0.2 ); + table->SetTableValue( 5115.0, 0.8, 0.8, 0.8 ); + table->SetTableValue( 5116.0, 0.6, 1, 1 ); + table->SetTableValue( 5117.0, 0.4, 0.6, 1 ); + table->SetTableValue( 5200.0, 0.8, 0.4, 0.4 ); + table->SetTableValue( 5201.0, 0.8, 0.4, 0.4 ); + table->SetTableValue( 5202.0, 1, 1, 0.4 ); + table->SetTableValue( 5203.0, 0.6, 0.8, 0 ); + table->SetTableValue( 5204.0, 0, 0.6, 0.6 ); + table->SetTableValue( 5205.0, 0.8, 0.6, 1 ); + table->SetTableValue( 5206.0, 1, 0.6, 0.2 ); + table->SetTableValue( 5207.0, 0.8, 0.8, 0.8 ); + table->SetTableValue( 5208.0, 0.6, 1, 1 ); + table->SetTableValue( 5209.0, 0.4, 0.6, 1 ); + table->SetTableValue( 5210.0, 1, 1, 0.4 ); + table->SetTableValue( 5211.0, 0.6, 0.8, 0 ); + table->SetTableValue( 5212.0, 0, 0.6, 0.6 ); + table->SetTableValue( 5213.0, 0.8, 0.6, 1 ); + table->SetTableValue( 5214.0, 1, 0.6, 0.2 ); + table->SetTableValue( 5215.0, 0.8, 0.8, 0.8 ); + table->SetTableValue( 5216.0, 0.6, 1, 1 ); + table->SetTableValue( 5217.0, 0.4, 0.6, 1 ); + table->SetTableValue( 6000.0, 0, 1, 0 ); + table->SetTableValue( 6001.0, 1, 1, 0 ); + table->SetTableValue( 6002.0, 0, 1, 1 ); + table->SetTableValue( 6003.0, 0, 0, 1 ); + table->SetTableValue( 6010.0, 0.92549, 0.0627451, 0.905882 ); + table->SetTableValue( 6020.0, 0.929412, 0.0705882, 0.909804 ); + table->SetTableValue( 6030.0, 0.92549, 0.0509804, 0.890196 ); + table->SetTableValue( 6040.0, 0.92549, 0.0666667, 0.894118 ); + table->SetTableValue( 6050.0, 0.00392157, 1, 0.00392157 ); + table->SetTableValue( 6060.0, 0.00784314, 1, 0.00392157 ); + table->SetTableValue( 6070.0, 0.92549, 0.054902, 0.901961 ); + table->SetTableValue( 6080.0, 0.929412, 0.054902, 0.901961 ); + table->SetTableValue( 7001.0, 0.282353, 0.517647, 0.709804 ); + table->SetTableValue( 7002.0, 0.952941, 0.952941, 0.952941 ); + table->SetTableValue( 7003.0, 0.811765, 0.247059, 0.309804 ); + table->SetTableValue( 7004.0, 0.47451, 0.0784314, 0.529412 ); + table->SetTableValue( 7005.0, 0.772549, 0.235294, 0.972549 ); + table->SetTableValue( 7006.0, 0.00784314, 0.584314, 0.00784314 ); + table->SetTableValue( 7007.0, 0.866667, 0.976471, 0.65098 ); + table->SetTableValue( 7008.0, 0.909804, 0.572549, 0.137255 ); + table->SetTableValue( 7009.0, 0.0784314, 0.235294, 0.470588 ); + table->SetTableValue( 7010.0, 0.980392, 0.980392, 0 ); + table->SetTableValue( 7011.0, 0.478431, 0.733333, 0.870588 ); + table->SetTableValue( 7012.0, 0.929412, 0.0470588, 0.694118 ); + table->SetTableValue( 7013.0, 0.0392157, 0.192157, 1 ); + table->SetTableValue( 7014.0, 0.803922, 0.721569, 0.564706 ); + table->SetTableValue( 7015.0, 0.176471, 0.803922, 0.647059 ); + table->SetTableValue( 7016.0, 0.458824, 0.627451, 0.686275 ); + table->SetTableValue( 7017.0, 0.866667, 0.85098, 0.0823529 ); + table->SetTableValue( 7018.0, 0.0784314, 0.235294, 0.470588 ); + table->SetTableValue( 7019.0, 0.552941, 0.0823529, 0.392157 ); + table->SetTableValue( 7020.0, 0.882353, 0.54902, 0.552941 ); + table->SetTableValue( 7100.0, 0.164706, 0.788235, 0.658824 ); + table->SetTableValue( 7101.0, 0.658824, 0.407843, 0.635294 ); + table->SetTableValue( 8001.0, 0.290196, 0.509804, 0.709804 ); + table->SetTableValue( 8002.0, 0.94902, 0.945098, 0.941176 ); + table->SetTableValue( 8003.0, 0.807843, 0.254902, 0.305882 ); + table->SetTableValue( 8004.0, 0.470588, 0.0823529, 0.521569 ); + table->SetTableValue( 8005.0, 0.764706, 0.239216, 0.964706 ); + table->SetTableValue( 8006.0, 0.0117647, 0.576471, 0.0235294 ); + table->SetTableValue( 8007.0, 0.862745, 0.984314, 0.639216 ); + table->SetTableValue( 8008.0, 0.909804, 0.572549, 0.129412 ); + table->SetTableValue( 8009.0, 0.0156863, 0.447059, 0.054902 ); + table->SetTableValue( 8010.0, 0.47451, 0.721569, 0.862745 ); + table->SetTableValue( 8011.0, 0.921569, 0.0431373, 0.686275 ); + table->SetTableValue( 8012.0, 0.0470588, 0.180392, 0.980392 ); + table->SetTableValue( 8013.0, 0.796078, 0.713725, 0.560784 ); + table->SetTableValue( 8014.0, 0.164706, 0.8, 0.654902 ); + table->SetTableValue( 9000.0, 0.117647, 0.0196078, 0.117647 ); + table->SetTableValue( 9001.0, 0.117647, 0.392157, 0.176471 ); + table->SetTableValue( 9002.0, 0.509804, 0.392157, 0.647059 ); + table->SetTableValue( 9003.0, 0.411765, 0.0980392, 0.0196078 ); + table->SetTableValue( 9004.0, 0.490196, 0.27451, 0.215686 ); + table->SetTableValue( 9005.0, 0.882353, 0.0784314, 0.411765 ); + table->SetTableValue( 9006.0, 0.882353, 0.0784314, 0.0588235 ); + table->SetTableValue( 9500.0, 0.117647, 0.215686, 0.117647 ); + table->SetTableValue( 9501.0, 0.117647, 0.588235, 0.176471 ); + table->SetTableValue( 9502.0, 0.509804, 0.588235, 0.647059 ); + table->SetTableValue( 9503.0, 0.411765, 0.294118, 0.0196078 ); + table->SetTableValue( 9504.0, 0.490196, 0.470588, 0.215686 ); + table->SetTableValue( 9505.0, 0.882353, 0.27451, 0.411765 ); + table->SetTableValue( 9506.0, 0.882353, 0.27451, 0.0588235 ); + table->SetTableValue( 11100.0, 0, 0, 0, 0); + table->SetTableValue( 11101.0, 0.0901961, 0.862745, 0.235294 ); + table->SetTableValue( 11102.0, 0.0901961, 0.235294, 0.705882 ); + table->SetTableValue( 11103.0, 0.247059, 0.392157, 0.235294 ); + table->SetTableValue( 11104.0, 0.247059, 0.0784314, 0.862745 ); + table->SetTableValue( 11105.0, 0.0509804, 0, 0.980392 ); + table->SetTableValue( 11106.0, 0.101961, 0.235294, 0 ); + table->SetTableValue( 11107.0, 0.101961, 0.235294, 0.294118 ); + table->SetTableValue( 11108.0, 0.101961, 0.235294, 0.588235 ); + table->SetTableValue( 11109.0, 0.0980392, 0.235294, 0.980392 ); + table->SetTableValue( 11110.0, 0.235294, 0.0980392, 0.0980392 ); + table->SetTableValue( 11111.0, 0.705882, 0.0784314, 0.0784314 ); + table->SetTableValue( 11112.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 11113.0, 0.54902, 0.235294, 0.235294 ); + table->SetTableValue( 11114.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 11115.0, 0.54902, 0.392157, 0.705882 ); + table->SetTableValue( 11116.0, 0.705882, 0.0784314, 0.54902 ); + table->SetTableValue( 11117.0, 0.0901961, 0.0392157, 0.0392157 ); + table->SetTableValue( 11118.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 11119.0, 0.705882, 0.235294, 0.705882 ); + table->SetTableValue( 11120.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 11121.0, 0.235294, 0.0784314, 0.54902 ); + table->SetTableValue( 11122.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 11123.0, 0.254902, 0.392157, 0.0784314 ); + table->SetTableValue( 11124.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 11125.0, 0.0784314, 0.235294, 0.862745 ); + table->SetTableValue( 11126.0, 0.392157, 0.392157, 0.235294 ); + table->SetTableValue( 11127.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 11128.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 11129.0, 0.235294, 0.54902, 0.705882 ); + table->SetTableValue( 11130.0, 0.0980392, 0.0784314, 0.54902 ); + table->SetTableValue( 11131.0, 0.0784314, 0.235294, 0.392157 ); + table->SetTableValue( 11132.0, 0.235294, 0.862745, 0.0784314 ); + table->SetTableValue( 11133.0, 0.235294, 0.235294, 0.862745 ); + table->SetTableValue( 11134.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 11135.0, 0.254902, 0.862745, 0.235294 ); + table->SetTableValue( 11136.0, 0.0980392, 0.54902, 0.0784314 ); + table->SetTableValue( 11137.0, 0.862745, 0.862745, 0.392157 ); + table->SetTableValue( 11138.0, 0.705882, 0.235294, 0.235294 ); + table->SetTableValue( 11139.0, 0.239216, 0.0784314, 0.862745 ); + table->SetTableValue( 11140.0, 0.239216, 0.0784314, 0.235294 ); + table->SetTableValue( 11141.0, 0.239216, 0.235294, 0.392157 ); + table->SetTableValue( 11142.0, 0.0980392, 0.0980392, 0.0980392 ); + table->SetTableValue( 11143.0, 0.54902, 0.0784314, 0.235294 ); + table->SetTableValue( 11144.0, 0.862745, 0.705882, 0.0784314 ); + table->SetTableValue( 11145.0, 0.247059, 0.705882, 0.705882 ); + table->SetTableValue( 11146.0, 0.866667, 0.0784314, 0.0392157 ); + table->SetTableValue( 11147.0, 0.866667, 0.0784314, 0.392157 ); + table->SetTableValue( 11148.0, 0.866667, 0.235294, 0.54902 ); + table->SetTableValue( 11149.0, 0.866667, 0.0784314, 0.862745 ); + table->SetTableValue( 11150.0, 0.239216, 0.862745, 0.862745 ); + table->SetTableValue( 11151.0, 0.392157, 0.784314, 0.784314 ); + table->SetTableValue( 11152.0, 0.0392157, 0.784314, 0.784314 ); + table->SetTableValue( 11153.0, 0.866667, 0.862745, 0.0784314 ); + table->SetTableValue( 11154.0, 0.552941, 0.0784314, 0.392157 ); + table->SetTableValue( 11155.0, 0.239216, 0.862745, 0.392157 ); + table->SetTableValue( 11156.0, 0.552941, 0.235294, 0.0784314 ); + table->SetTableValue( 11157.0, 0.560784, 0.0784314, 0.862745 ); + table->SetTableValue( 11158.0, 0.396078, 0.235294, 0.862745 ); + table->SetTableValue( 11159.0, 0.0823529, 0.0784314, 0.54902 ); + table->SetTableValue( 11160.0, 0.239216, 0.0784314, 0.705882 ); + table->SetTableValue( 11161.0, 0.866667, 0.54902, 0.0784314 ); + table->SetTableValue( 11162.0, 0.552941, 0.392157, 0.862745 ); + table->SetTableValue( 11163.0, 0.866667, 0.392157, 0.0784314 ); + table->SetTableValue( 11164.0, 0.709804, 0.784314, 0.0784314 ); + table->SetTableValue( 11165.0, 0.396078, 0.0784314, 0.0784314 ); + table->SetTableValue( 11166.0, 0.396078, 0.392157, 0.705882 ); + table->SetTableValue( 11167.0, 0.709804, 0.862745, 0.0784314 ); + table->SetTableValue( 11168.0, 0.0823529, 0.54902, 0.784314 ); + table->SetTableValue( 11169.0, 0.0823529, 0.0784314, 0.941176 ); + table->SetTableValue( 11170.0, 0.0823529, 0.0784314, 0.784314 ); + table->SetTableValue( 11171.0, 0.0823529, 0.0784314, 0.235294 ); + table->SetTableValue( 11172.0, 0.396078, 0.235294, 0.235294 ); + table->SetTableValue( 11173.0, 0.0823529, 0.705882, 0.705882 ); + table->SetTableValue( 11174.0, 0.87451, 0.862745, 0.235294 ); + table->SetTableValue( 11175.0, 0.866667, 0.235294, 0.235294 ); + table->SetTableValue( 12100.0, 0, 0, 0, 0); + table->SetTableValue( 12101.0, 0.0901961, 0.862745, 0.235294 ); + table->SetTableValue( 12102.0, 0.0901961, 0.235294, 0.705882 ); + table->SetTableValue( 12103.0, 0.247059, 0.392157, 0.235294 ); + table->SetTableValue( 12104.0, 0.247059, 0.0784314, 0.862745 ); + table->SetTableValue( 12105.0, 0.0509804, 0, 0.980392 ); + table->SetTableValue( 12106.0, 0.101961, 0.235294, 0 ); + table->SetTableValue( 12107.0, 0.101961, 0.235294, 0.294118 ); + table->SetTableValue( 12108.0, 0.101961, 0.235294, 0.588235 ); + table->SetTableValue( 12109.0, 0.0980392, 0.235294, 0.980392 ); + table->SetTableValue( 12110.0, 0.235294, 0.0980392, 0.0980392 ); + table->SetTableValue( 12111.0, 0.705882, 0.0784314, 0.0784314 ); + table->SetTableValue( 12112.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 12113.0, 0.54902, 0.235294, 0.235294 ); + table->SetTableValue( 12114.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 12115.0, 0.54902, 0.392157, 0.705882 ); + table->SetTableValue( 12116.0, 0.705882, 0.0784314, 0.54902 ); + table->SetTableValue( 12117.0, 0.0901961, 0.0392157, 0.0392157 ); + table->SetTableValue( 12118.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 12119.0, 0.705882, 0.235294, 0.705882 ); + table->SetTableValue( 12120.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 12121.0, 0.235294, 0.0784314, 0.54902 ); + table->SetTableValue( 12122.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 12123.0, 0.254902, 0.392157, 0.0784314 ); + table->SetTableValue( 12124.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 12125.0, 0.0784314, 0.235294, 0.862745 ); + table->SetTableValue( 12126.0, 0.392157, 0.392157, 0.235294 ); + table->SetTableValue( 12127.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 12128.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 12129.0, 0.235294, 0.54902, 0.705882 ); + table->SetTableValue( 12130.0, 0.0980392, 0.0784314, 0.54902 ); + table->SetTableValue( 12131.0, 0.0784314, 0.235294, 0.392157 ); + table->SetTableValue( 12132.0, 0.235294, 0.862745, 0.0784314 ); + table->SetTableValue( 12133.0, 0.235294, 0.235294, 0.862745 ); + table->SetTableValue( 12134.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 12135.0, 0.254902, 0.862745, 0.235294 ); + table->SetTableValue( 12136.0, 0.0980392, 0.54902, 0.0784314 ); + table->SetTableValue( 12137.0, 0.862745, 0.862745, 0.392157 ); + table->SetTableValue( 12138.0, 0.705882, 0.235294, 0.235294 ); + table->SetTableValue( 12139.0, 0.239216, 0.0784314, 0.862745 ); + table->SetTableValue( 12140.0, 0.239216, 0.0784314, 0.235294 ); + table->SetTableValue( 12141.0, 0.239216, 0.235294, 0.392157 ); + table->SetTableValue( 12142.0, 0.0980392, 0.0980392, 0.0980392 ); + table->SetTableValue( 12143.0, 0.54902, 0.0784314, 0.235294 ); + table->SetTableValue( 12144.0, 0.862745, 0.705882, 0.0784314 ); + table->SetTableValue( 12145.0, 0.247059, 0.705882, 0.705882 ); + table->SetTableValue( 12146.0, 0.866667, 0.0784314, 0.0392157 ); + table->SetTableValue( 12147.0, 0.866667, 0.0784314, 0.392157 ); + table->SetTableValue( 12148.0, 0.866667, 0.235294, 0.54902 ); + table->SetTableValue( 12149.0, 0.866667, 0.0784314, 0.862745 ); + table->SetTableValue( 12150.0, 0.239216, 0.862745, 0.862745 ); + table->SetTableValue( 12151.0, 0.392157, 0.784314, 0.784314 ); + table->SetTableValue( 12152.0, 0.0392157, 0.784314, 0.784314 ); + table->SetTableValue( 12153.0, 0.866667, 0.862745, 0.0784314 ); + table->SetTableValue( 12154.0, 0.552941, 0.0784314, 0.392157 ); + table->SetTableValue( 12155.0, 0.239216, 0.862745, 0.392157 ); + table->SetTableValue( 12156.0, 0.552941, 0.235294, 0.0784314 ); + table->SetTableValue( 12157.0, 0.560784, 0.0784314, 0.862745 ); + table->SetTableValue( 12158.0, 0.396078, 0.235294, 0.862745 ); + table->SetTableValue( 12159.0, 0.0823529, 0.0784314, 0.54902 ); + table->SetTableValue( 12160.0, 0.239216, 0.0784314, 0.705882 ); + table->SetTableValue( 12161.0, 0.866667, 0.54902, 0.0784314 ); + table->SetTableValue( 12162.0, 0.552941, 0.392157, 0.862745 ); + table->SetTableValue( 12163.0, 0.866667, 0.392157, 0.0784314 ); + table->SetTableValue( 12164.0, 0.709804, 0.784314, 0.0784314 ); + table->SetTableValue( 12165.0, 0.396078, 0.0784314, 0.0784314 ); + table->SetTableValue( 12166.0, 0.396078, 0.392157, 0.705882 ); + table->SetTableValue( 12167.0, 0.709804, 0.862745, 0.0784314 ); + table->SetTableValue( 12168.0, 0.0823529, 0.54902, 0.784314 ); + table->SetTableValue( 12169.0, 0.0823529, 0.0784314, 0.941176 ); + table->SetTableValue( 12170.0, 0.0823529, 0.0784314, 0.784314 ); + table->SetTableValue( 12171.0, 0.0823529, 0.0784314, 0.235294 ); + table->SetTableValue( 12172.0, 0.396078, 0.235294, 0.235294 ); + table->SetTableValue( 12173.0, 0.0823529, 0.705882, 0.705882 ); + table->SetTableValue( 12174.0, 0.87451, 0.862745, 0.235294 ); + table->SetTableValue( 12175.0, 0.866667, 0.235294, 0.235294 ); + table->SetTableValue( 13100.0, 0, 0, 0, 0); + table->SetTableValue( 13101.0, 0.0901961, 0.862745, 0.235294 ); + table->SetTableValue( 13102.0, 0.0901961, 0.235294, 0.705882 ); + table->SetTableValue( 13103.0, 0.247059, 0.392157, 0.235294 ); + table->SetTableValue( 13104.0, 0.247059, 0.0784314, 0.862745 ); + table->SetTableValue( 13105.0, 0.0509804, 0, 0.980392 ); + table->SetTableValue( 13106.0, 0.101961, 0.235294, 0 ); + table->SetTableValue( 13107.0, 0.101961, 0.235294, 0.294118 ); + table->SetTableValue( 13108.0, 0.101961, 0.235294, 0.588235 ); + table->SetTableValue( 13109.0, 0.0980392, 0.235294, 0.980392 ); + table->SetTableValue( 13110.0, 0.235294, 0.0980392, 0.0980392 ); + table->SetTableValue( 13111.0, 0.705882, 0.0784314, 0.0784314 ); + table->SetTableValue( 13112.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 13113.0, 0.54902, 0.235294, 0.235294 ); + table->SetTableValue( 13114.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 13115.0, 0.54902, 0.392157, 0.705882 ); + table->SetTableValue( 13116.0, 0.705882, 0.0784314, 0.54902 ); + table->SetTableValue( 13117.0, 0.0901961, 0.0392157, 0.0392157 ); + table->SetTableValue( 13118.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 13119.0, 0.705882, 0.235294, 0.705882 ); + table->SetTableValue( 13120.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 13121.0, 0.235294, 0.0784314, 0.54902 ); + table->SetTableValue( 13122.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 13123.0, 0.254902, 0.392157, 0.0784314 ); + table->SetTableValue( 13124.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 13125.0, 0.0784314, 0.235294, 0.862745 ); + table->SetTableValue( 13126.0, 0.392157, 0.392157, 0.235294 ); + table->SetTableValue( 13127.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 13128.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 13129.0, 0.235294, 0.54902, 0.705882 ); + table->SetTableValue( 13130.0, 0.0980392, 0.0784314, 0.54902 ); + table->SetTableValue( 13131.0, 0.0784314, 0.235294, 0.392157 ); + table->SetTableValue( 13132.0, 0.235294, 0.862745, 0.0784314 ); + table->SetTableValue( 13133.0, 0.235294, 0.235294, 0.862745 ); + table->SetTableValue( 13134.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 13135.0, 0.254902, 0.862745, 0.235294 ); + table->SetTableValue( 13136.0, 0.0980392, 0.54902, 0.0784314 ); + table->SetTableValue( 13137.0, 0.862745, 0.862745, 0.392157 ); + table->SetTableValue( 13138.0, 0.705882, 0.235294, 0.235294 ); + table->SetTableValue( 13139.0, 0.239216, 0.0784314, 0.862745 ); + table->SetTableValue( 13140.0, 0.239216, 0.0784314, 0.235294 ); + table->SetTableValue( 13141.0, 0.239216, 0.235294, 0.392157 ); + table->SetTableValue( 13142.0, 0.0980392, 0.0980392, 0.0980392 ); + table->SetTableValue( 13143.0, 0.54902, 0.0784314, 0.235294 ); + table->SetTableValue( 13144.0, 0.862745, 0.705882, 0.0784314 ); + table->SetTableValue( 13145.0, 0.247059, 0.705882, 0.705882 ); + table->SetTableValue( 13146.0, 0.866667, 0.0784314, 0.0392157 ); + table->SetTableValue( 13147.0, 0.866667, 0.0784314, 0.392157 ); + table->SetTableValue( 13148.0, 0.866667, 0.235294, 0.54902 ); + table->SetTableValue( 13149.0, 0.866667, 0.0784314, 0.862745 ); + table->SetTableValue( 13150.0, 0.239216, 0.862745, 0.862745 ); + table->SetTableValue( 13151.0, 0.392157, 0.784314, 0.784314 ); + table->SetTableValue( 13152.0, 0.0392157, 0.784314, 0.784314 ); + table->SetTableValue( 13153.0, 0.866667, 0.862745, 0.0784314 ); + table->SetTableValue( 13154.0, 0.552941, 0.0784314, 0.392157 ); + table->SetTableValue( 13155.0, 0.239216, 0.862745, 0.392157 ); + table->SetTableValue( 13156.0, 0.552941, 0.235294, 0.0784314 ); + table->SetTableValue( 13157.0, 0.560784, 0.0784314, 0.862745 ); + table->SetTableValue( 13158.0, 0.396078, 0.235294, 0.862745 ); + table->SetTableValue( 13159.0, 0.0823529, 0.0784314, 0.54902 ); + table->SetTableValue( 13160.0, 0.239216, 0.0784314, 0.705882 ); + table->SetTableValue( 13161.0, 0.866667, 0.54902, 0.0784314 ); + table->SetTableValue( 13162.0, 0.552941, 0.392157, 0.862745 ); + table->SetTableValue( 13163.0, 0.866667, 0.392157, 0.0784314 ); + table->SetTableValue( 13164.0, 0.709804, 0.784314, 0.0784314 ); + table->SetTableValue( 13165.0, 0.396078, 0.0784314, 0.0784314 ); + table->SetTableValue( 13166.0, 0.396078, 0.392157, 0.705882 ); + table->SetTableValue( 13167.0, 0.709804, 0.862745, 0.0784314 ); + table->SetTableValue( 13168.0, 0.0823529, 0.54902, 0.784314 ); + table->SetTableValue( 13169.0, 0.0823529, 0.0784314, 0.941176 ); + table->SetTableValue( 13170.0, 0.0823529, 0.0784314, 0.784314 ); + table->SetTableValue( 13171.0, 0.0823529, 0.0784314, 0.235294 ); + table->SetTableValue( 13172.0, 0.396078, 0.235294, 0.235294 ); + table->SetTableValue( 13173.0, 0.0823529, 0.705882, 0.705882 ); + table->SetTableValue( 13174.0, 0.87451, 0.862745, 0.235294 ); + table->SetTableValue( 13175.0, 0.866667, 0.235294, 0.235294 ); + table->SetTableValue( 14100.0, 0, 0, 0, 0); + table->SetTableValue( 14101.0, 0.0901961, 0.862745, 0.235294 ); + table->SetTableValue( 14102.0, 0.0901961, 0.235294, 0.705882 ); + table->SetTableValue( 14103.0, 0.247059, 0.392157, 0.235294 ); + table->SetTableValue( 14104.0, 0.247059, 0.0784314, 0.862745 ); + table->SetTableValue( 14105.0, 0.0509804, 0, 0.980392 ); + table->SetTableValue( 14106.0, 0.101961, 0.235294, 0 ); + table->SetTableValue( 14107.0, 0.101961, 0.235294, 0.294118 ); + table->SetTableValue( 14108.0, 0.101961, 0.235294, 0.588235 ); + table->SetTableValue( 14109.0, 0.0980392, 0.235294, 0.980392 ); + table->SetTableValue( 14110.0, 0.235294, 0.0980392, 0.0980392 ); + table->SetTableValue( 14111.0, 0.705882, 0.0784314, 0.0784314 ); + table->SetTableValue( 14112.0, 0.862745, 0.0784314, 0.392157 ); + table->SetTableValue( 14113.0, 0.54902, 0.235294, 0.235294 ); + table->SetTableValue( 14114.0, 0.705882, 0.862745, 0.54902 ); + table->SetTableValue( 14115.0, 0.54902, 0.392157, 0.705882 ); + table->SetTableValue( 14116.0, 0.705882, 0.0784314, 0.54902 ); + table->SetTableValue( 14117.0, 0.0901961, 0.0392157, 0.0392157 ); + table->SetTableValue( 14118.0, 0.882353, 0.54902, 0.54902 ); + table->SetTableValue( 14119.0, 0.705882, 0.235294, 0.705882 ); + table->SetTableValue( 14120.0, 0.0784314, 0.862745, 0.235294 ); + table->SetTableValue( 14121.0, 0.235294, 0.0784314, 0.54902 ); + table->SetTableValue( 14122.0, 0.862745, 0.705882, 0.54902 ); + table->SetTableValue( 14123.0, 0.254902, 0.392157, 0.0784314 ); + table->SetTableValue( 14124.0, 0.862745, 0.235294, 0.0784314 ); + table->SetTableValue( 14125.0, 0.0784314, 0.235294, 0.862745 ); + table->SetTableValue( 14126.0, 0.392157, 0.392157, 0.235294 ); + table->SetTableValue( 14127.0, 0.862745, 0.705882, 0.862745 ); + table->SetTableValue( 14128.0, 0.0784314, 0.705882, 0.54902 ); + table->SetTableValue( 14129.0, 0.235294, 0.54902, 0.705882 ); + table->SetTableValue( 14130.0, 0.0980392, 0.0784314, 0.54902 ); + table->SetTableValue( 14131.0, 0.0784314, 0.235294, 0.392157 ); + table->SetTableValue( 14132.0, 0.235294, 0.862745, 0.0784314 ); + table->SetTableValue( 14133.0, 0.235294, 0.235294, 0.862745 ); + table->SetTableValue( 14134.0, 0.862745, 0.235294, 0.862745 ); + table->SetTableValue( 14135.0, 0.254902, 0.862745, 0.235294 ); + table->SetTableValue( 14136.0, 0.0980392, 0.54902, 0.0784314 ); + table->SetTableValue( 14137.0, 0.862745, 0.862745, 0.392157 ); + table->SetTableValue( 14138.0, 0.705882, 0.235294, 0.235294 ); + table->SetTableValue( 14139.0, 0.239216, 0.0784314, 0.862745 ); + table->SetTableValue( 14140.0, 0.239216, 0.0784314, 0.235294 ); + table->SetTableValue( 14141.0, 0.239216, 0.235294, 0.392157 ); + table->SetTableValue( 14142.0, 0.0980392, 0.0980392, 0.0980392 ); + table->SetTableValue( 14143.0, 0.54902, 0.0784314, 0.235294 ); + table->SetTableValue( 14144.0, 0.862745, 0.705882, 0.0784314 ); + table->SetTableValue( 14145.0, 0.247059, 0.705882, 0.705882 ); + table->SetTableValue( 14146.0, 0.866667, 0.0784314, 0.0392157 ); + table->SetTableValue( 14147.0, 0.866667, 0.0784314, 0.392157 ); + table->SetTableValue( 14148.0, 0.866667, 0.235294, 0.54902 ); + table->SetTableValue( 14149.0, 0.866667, 0.0784314, 0.862745 ); + table->SetTableValue( 14150.0, 0.239216, 0.862745, 0.862745 ); + table->SetTableValue( 14151.0, 0.392157, 0.784314, 0.784314 ); + table->SetTableValue( 14152.0, 0.0392157, 0.784314, 0.784314 ); + table->SetTableValue( 14153.0, 0.866667, 0.862745, 0.0784314 ); + table->SetTableValue( 14154.0, 0.552941, 0.0784314, 0.392157 ); + table->SetTableValue( 14155.0, 0.239216, 0.862745, 0.392157 ); + table->SetTableValue( 14156.0, 0.552941, 0.235294, 0.0784314 ); + table->SetTableValue( 14157.0, 0.560784, 0.0784314, 0.862745 ); + table->SetTableValue( 14158.0, 0.396078, 0.235294, 0.862745 ); + table->SetTableValue( 14159.0, 0.0823529, 0.0784314, 0.54902 ); + table->SetTableValue( 14160.0, 0.239216, 0.0784314, 0.705882 ); + table->SetTableValue( 14161.0, 0.866667, 0.54902, 0.0784314 ); + table->SetTableValue( 14162.0, 0.552941, 0.392157, 0.862745 ); + table->SetTableValue( 14163.0, 0.866667, 0.392157, 0.0784314 ); + table->SetTableValue( 14164.0, 0.709804, 0.784314, 0.0784314 ); + table->SetTableValue( 14165.0, 0.396078, 0.0784314, 0.0784314 ); + table->SetTableValue( 14166.0, 0.396078, 0.392157, 0.705882 ); + table->SetTableValue( 14167.0, 0.709804, 0.862745, 0.0784314 ); + table->SetTableValue( 14168.0, 0.0823529, 0.54902, 0.784314 ); + table->SetTableValue( 14169.0, 0.0823529, 0.0784314, 0.941176 ); + table->SetTableValue( 14170.0, 0.0823529, 0.0784314, 0.784314 ); + table->SetTableValue( 14171.0, 0.0823529, 0.0784314, 0.235294 ); + table->SetTableValue( 14172.0, 0.396078, 0.235294, 0.235294 ); + table->SetTableValue( 14173.0, 0.0823529, 0.705882, 0.705882 ); + table->SetTableValue( 14174.0, 0.87451, 0.862745, 0.235294 ); + table->SetTableValue( 14175.0, 0.866667, 0.235294, 0.235294 ); + mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); + lookupTable->SetVtkLookupTable( table ); + return lookupTable; +} + +TransferFunction::Pointer FreeSurferParcellationTranslator::CreateTransferFunction() +{ + mitk::TransferFunction::Pointer transferFunction = mitk::TransferFunction::New(); + transferFunction->AddRGBPoint( 1.0, 0.27451, 0.509804, 0.705882 ); + transferFunction->AddRGBPoint( 2.0, 0.960784, 0.960784, 0.960784 ); + transferFunction->AddRGBPoint( 3.0, 0.803922, 0.243137, 0.305882 ); + transferFunction->AddRGBPoint( 4.0, 0.470588, 0.0705882, 0.52549 ); + transferFunction->AddRGBPoint( 5.0, 0.768627, 0.227451, 0.980392 ); + transferFunction->AddRGBPoint( 6.0, 0, 0.580392, 0 ); + transferFunction->AddRGBPoint( 7.0, 0.862745, 0.972549, 0.643137 ); + transferFunction->AddRGBPoint( 8.0, 0.901961, 0.580392, 0.133333 ); + transferFunction->AddRGBPoint( 9.0, 0, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 10.0, 0, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 11.0, 0.478431, 0.729412, 0.862745 ); + transferFunction->AddRGBPoint( 12.0, 0.92549, 0.0509804, 0.690196 ); + transferFunction->AddRGBPoint( 13.0, 0.0470588, 0.188235, 1 ); + transferFunction->AddRGBPoint( 14.0, 0.8, 0.713725, 0.556863 ); + transferFunction->AddRGBPoint( 15.0, 0.164706, 0.8, 0.643137 ); + transferFunction->AddRGBPoint( 16.0, 0.466667, 0.623529, 0.690196 ); + transferFunction->AddRGBPoint( 17.0, 0.862745, 0.847059, 0.0784314 ); + transferFunction->AddRGBPoint( 18.0, 0.403922, 1, 1 ); + transferFunction->AddRGBPoint( 19.0, 0.313725, 0.768627, 0.384314 ); + transferFunction->AddRGBPoint( 20.0, 0.235294, 0.227451, 0.823529 ); + transferFunction->AddRGBPoint( 21.0, 0.235294, 0.227451, 0.823529 ); + transferFunction->AddRGBPoint( 22.0, 0.235294, 0.227451, 0.823529 ); + transferFunction->AddRGBPoint( 23.0, 0.235294, 0.227451, 0.823529 ); + transferFunction->AddRGBPoint( 24.0, 0.235294, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 25.0, 1, 0.647059, 0 ); + transferFunction->AddRGBPoint( 26.0, 1, 0.647059, 0 ); + transferFunction->AddRGBPoint( 27.0, 0, 1, 0.498039 ); + transferFunction->AddRGBPoint( 28.0, 0.647059, 0.164706, 0.164706 ); + transferFunction->AddRGBPoint( 29.0, 0.529412, 0.807843, 0.921569 ); + transferFunction->AddRGBPoint( 30.0, 0.627451, 0.12549, 0.941176 ); + transferFunction->AddRGBPoint( 31.0, 0, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 32.0, 0.392157, 0.196078, 0.392157 ); + transferFunction->AddRGBPoint( 33.0, 0.529412, 0.196078, 0.290196 ); + transferFunction->AddRGBPoint( 34.0, 0.478431, 0.529412, 0.196078 ); + transferFunction->AddRGBPoint( 35.0, 0.2, 0.196078, 0.529412 ); + transferFunction->AddRGBPoint( 36.0, 0.290196, 0.607843, 0.235294 ); + transferFunction->AddRGBPoint( 37.0, 0.470588, 0.243137, 0.168627 ); + transferFunction->AddRGBPoint( 38.0, 0.290196, 0.607843, 0.235294 ); + transferFunction->AddRGBPoint( 39.0, 0.478431, 0.529412, 0.196078 ); + transferFunction->AddRGBPoint( 40.0, 0.27451, 0.509804, 0.705882 ); + transferFunction->AddRGBPoint( 41.0, 0, 0.882353, 0 ); + transferFunction->AddRGBPoint( 42.0, 0.803922, 0.243137, 0.305882 ); + transferFunction->AddRGBPoint( 43.0, 0.470588, 0.0705882, 0.52549 ); + transferFunction->AddRGBPoint( 44.0, 0.768627, 0.227451, 0.980392 ); + transferFunction->AddRGBPoint( 45.0, 0, 0.580392, 0 ); + transferFunction->AddRGBPoint( 46.0, 0.862745, 0.972549, 0.643137 ); + transferFunction->AddRGBPoint( 47.0, 0.901961, 0.580392, 0.133333 ); + transferFunction->AddRGBPoint( 48.0, 0, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 49.0, 0, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 50.0, 0.478431, 0.729412, 0.862745 ); + transferFunction->AddRGBPoint( 51.0, 0.92549, 0.0509804, 0.690196 ); + transferFunction->AddRGBPoint( 52.0, 0.0509804, 0.188235, 1 ); + transferFunction->AddRGBPoint( 53.0, 0.862745, 0.847059, 0.0784314 ); + transferFunction->AddRGBPoint( 54.0, 0.403922, 1, 1 ); + transferFunction->AddRGBPoint( 55.0, 0.313725, 0.768627, 0.384314 ); + transferFunction->AddRGBPoint( 56.0, 0.235294, 0.227451, 0.823529 ); + transferFunction->AddRGBPoint( 57.0, 1, 0.647059, 0 ); + transferFunction->AddRGBPoint( 58.0, 1, 0.647059, 0 ); + transferFunction->AddRGBPoint( 59.0, 0, 1, 0.498039 ); + transferFunction->AddRGBPoint( 60.0, 0.647059, 0.164706, 0.164706 ); + transferFunction->AddRGBPoint( 61.0, 0.529412, 0.807843, 0.921569 ); + transferFunction->AddRGBPoint( 62.0, 0.627451, 0.12549, 0.941176 ); + transferFunction->AddRGBPoint( 63.0, 0, 0.784314, 0.866667 ); + transferFunction->AddRGBPoint( 64.0, 0.392157, 0.196078, 0.392157 ); + transferFunction->AddRGBPoint( 65.0, 0.529412, 0.196078, 0.290196 ); + transferFunction->AddRGBPoint( 66.0, 0.478431, 0.529412, 0.196078 ); + transferFunction->AddRGBPoint( 67.0, 0.2, 0.196078, 0.529412 ); + transferFunction->AddRGBPoint( 68.0, 0.290196, 0.607843, 0.235294 ); + transferFunction->AddRGBPoint( 69.0, 0.470588, 0.243137, 0.168627 ); + transferFunction->AddRGBPoint( 70.0, 0.290196, 0.607843, 0.235294 ); + transferFunction->AddRGBPoint( 71.0, 0.478431, 0.529412, 0.196078 ); + transferFunction->AddRGBPoint( 72.0, 0.470588, 0.745098, 0.588235 ); + transferFunction->AddRGBPoint( 73.0, 0.478431, 0.529412, 0.196078 ); + transferFunction->AddRGBPoint( 74.0, 0.478431, 0.529412, 0.196078 ); + transferFunction->AddRGBPoint( 77.0, 0.784314, 0.27451, 1 ); + transferFunction->AddRGBPoint( 78.0, 1, 0.580392, 0.0392157 ); + transferFunction->AddRGBPoint( 79.0, 1, 0.580392, 0.0392157 ); + transferFunction->AddRGBPoint( 80.0, 0.643137, 0.423529, 0.886275 ); + transferFunction->AddRGBPoint( 81.0, 0.643137, 0.423529, 0.886275 ); + transferFunction->AddRGBPoint( 82.0, 0.643137, 0.423529, 0.886275 ); + transferFunction->AddRGBPoint( 83.0, 1, 0.854902, 0.72549 ); + transferFunction->AddRGBPoint( 84.0, 1, 0.854902, 0.72549 ); + transferFunction->AddRGBPoint( 85.0, 0.917647, 0.662745, 0.117647 ); + transferFunction->AddRGBPoint( 192.0, 0.980392, 1, 0.196078 ); + transferFunction->AddRGBPoint( 86.0, 0.784314, 0.470588, 1 ); + transferFunction->AddRGBPoint( 87.0, 0.784314, 0.47451, 1 ); + transferFunction->AddRGBPoint( 88.0, 0.784314, 0.478431, 1 ); + transferFunction->AddRGBPoint( 96.0, 0.803922, 0.0392157, 0.490196 ); + transferFunction->AddRGBPoint( 97.0, 0.803922, 0.0392157, 0.490196 ); + transferFunction->AddRGBPoint( 98.0, 0.627451, 0.12549, 0.941176 ); + transferFunction->AddRGBPoint( 100.0, 0.486275, 0.54902, 0.698039 ); + transferFunction->AddRGBPoint( 101.0, 0.490196, 0.54902, 0.698039 ); + transferFunction->AddRGBPoint( 102.0, 0.494118, 0.54902, 0.698039 ); + transferFunction->AddRGBPoint( 103.0, 0.498039, 0.54902, 0.698039 ); + transferFunction->AddRGBPoint( 104.0, 0.486275, 0.552941, 0.698039 ); + transferFunction->AddRGBPoint( 105.0, 0.486275, 0.556863, 0.698039 ); + transferFunction->AddRGBPoint( 106.0, 0.486275, 0.560784, 0.698039 ); + transferFunction->AddRGBPoint( 107.0, 0.486275, 0.564706, 0.698039 ); + transferFunction->AddRGBPoint( 108.0, 0.486275, 0.54902, 0.701961 ); + transferFunction->AddRGBPoint( 109.0, 0.486275, 0.54902, 0.698039 ); + transferFunction->AddRGBPoint( 110.0, 0.490196, 0.54902, 0.698039 ); + transferFunction->AddRGBPoint( 111.0, 0.494118, 0.54902, 0.698039 ); + transferFunction->AddRGBPoint( 112.0, 0.498039, 0.54902, 0.698039 ); + transferFunction->AddRGBPoint( 113.0, 0.486275, 0.552941, 0.698039 ); + transferFunction->AddRGBPoint( 114.0, 0.486275, 0.556863, 0.698039 ); + transferFunction->AddRGBPoint( 115.0, 0.486275, 0.560784, 0.698039 ); + transferFunction->AddRGBPoint( 116.0, 0.486275, 0.564706, 0.698039 ); + transferFunction->AddRGBPoint( 117.0, 0.486275, 0.54902, 0.701961 ); + transferFunction->AddRGBPoint( 118.0, 1, 0.0784314, 0.576471 ); + transferFunction->AddRGBPoint( 119.0, 0.803922, 0.701961, 0.545098 ); + transferFunction->AddRGBPoint( 120.0, 0.933333, 0.933333, 0.819608 ); + transferFunction->AddRGBPoint( 121.0, 0.784314, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 122.0, 0.290196, 1, 0.290196 ); + transferFunction->AddRGBPoint( 123.0, 0.933333, 0, 0 ); + transferFunction->AddRGBPoint( 124.0, 0, 0, 0.545098 ); + transferFunction->AddRGBPoint( 125.0, 0.678431, 1, 0.184314 ); + transferFunction->AddRGBPoint( 126.0, 0.521569, 0.796078, 0.898039 ); + transferFunction->AddRGBPoint( 127.0, 0.101961, 0.929412, 0.223529 ); + transferFunction->AddRGBPoint( 128.0, 0.133333, 0.545098, 0.133333 ); + transferFunction->AddRGBPoint( 129.0, 0.117647, 0.564706, 1 ); + transferFunction->AddRGBPoint( 130.0, 0.576471, 0.0745098, 0.678431 ); + transferFunction->AddRGBPoint( 131.0, 0.933333, 0.231373, 0.231373 ); + transferFunction->AddRGBPoint( 132.0, 0.866667, 0.152941, 0.784314 ); + transferFunction->AddRGBPoint( 133.0, 0.933333, 0.682353, 0.933333 ); + transferFunction->AddRGBPoint( 134.0, 1, 0, 0 ); + transferFunction->AddRGBPoint( 135.0, 0.282353, 0.239216, 0.545098 ); + transferFunction->AddRGBPoint( 136.0, 0.0823529, 0.152941, 0.517647 ); + transferFunction->AddRGBPoint( 137.0, 0.0823529, 0.152941, 0.517647 ); + transferFunction->AddRGBPoint( 138.0, 0.254902, 0.529412, 0.0784314 ); + transferFunction->AddRGBPoint( 139.0, 0.254902, 0.529412, 0.0784314 ); + transferFunction->AddRGBPoint( 140.0, 0.52549, 0.0156863, 0.627451 ); + transferFunction->AddRGBPoint( 142.0, 0.866667, 0.886275, 0.266667 ); + transferFunction->AddRGBPoint( 143.0, 1, 1, 0.996078 ); + transferFunction->AddRGBPoint( 144.0, 0.203922, 0.819608, 0.886275 ); + transferFunction->AddRGBPoint( 145.0, 0.937255, 0.627451, 0.87451 ); + transferFunction->AddRGBPoint( 146.0, 0.27451, 0.509804, 0.705882 ); + transferFunction->AddRGBPoint( 147.0, 0.27451, 0.509804, 0.709804 ); + transferFunction->AddRGBPoint( 148.0, 0.545098, 0.47451, 0.368627 ); + transferFunction->AddRGBPoint( 149.0, 0.878431, 0.878431, 0.878431 ); + transferFunction->AddRGBPoint( 150.0, 1, 0, 0 ); + transferFunction->AddRGBPoint( 151.0, 0.803922, 0.803922, 0 ); + transferFunction->AddRGBPoint( 152.0, 0.933333, 0.933333, 0.819608 ); + transferFunction->AddRGBPoint( 153.0, 0.545098, 0.47451, 0.368627 ); + transferFunction->AddRGBPoint( 154.0, 0.933333, 0.231373, 0.231373 ); + transferFunction->AddRGBPoint( 155.0, 0.933333, 0.231373, 0.231373 ); + transferFunction->AddRGBPoint( 156.0, 0.933333, 0.231373, 0.231373 ); + transferFunction->AddRGBPoint( 157.0, 0.243137, 0.0392157, 0.803922 ); + transferFunction->AddRGBPoint( 158.0, 0.243137, 0.0392157, 0.803922 ); + transferFunction->AddRGBPoint( 159.0, 0, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 160.0, 0, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 161.0, 0.862745, 0.847059, 0.0823529 ); + transferFunction->AddRGBPoint( 162.0, 0.862745, 0.847059, 0.0823529 ); + transferFunction->AddRGBPoint( 163.0, 0.478431, 0.729412, 0.862745 ); + transferFunction->AddRGBPoint( 164.0, 0.478431, 0.729412, 0.862745 ); + transferFunction->AddRGBPoint( 165.0, 1, 0.647059, 0 ); + transferFunction->AddRGBPoint( 166.0, 0.054902, 0.188235, 1 ); + transferFunction->AddRGBPoint( 167.0, 0.65098, 0.164706, 0.164706 ); + transferFunction->AddRGBPoint( 168.0, 0.47451, 0.0705882, 0.52549 ); + transferFunction->AddRGBPoint( 169.0, 0.92549, 0.0509804, 0.498039 ); + transferFunction->AddRGBPoint( 176.0, 0.92549, 0.0509804, 0.494118 ); + transferFunction->AddRGBPoint( 170.0, 0.466667, 0.623529, 0.690196 ); + transferFunction->AddRGBPoint( 171.0, 0.466667, 0, 0.690196 ); + transferFunction->AddRGBPoint( 172.0, 0.466667, 0.392157, 0.690196 ); + transferFunction->AddRGBPoint( 173.0, 0.466667, 0.784314, 0.690196 ); + transferFunction->AddRGBPoint( 174.0, 0.466667, 0.623529, 0.392157 ); + transferFunction->AddRGBPoint( 175.0, 0.466667, 0.623529, 0.784314 ); + transferFunction->AddRGBPoint( 180.0, 0.286275, 0.239216, 0.545098 ); + transferFunction->AddRGBPoint( 181.0, 0.286275, 0.243137, 0.545098 ); + transferFunction->AddRGBPoint( 193.0, 0, 0.768627, 1 ); + transferFunction->AddRGBPoint( 194.0, 1, 0.643137, 0.643137 ); + transferFunction->AddRGBPoint( 195.0, 0.768627, 0.768627, 0 ); + transferFunction->AddRGBPoint( 196.0, 0, 0.392157, 1 ); + transferFunction->AddRGBPoint( 197.0, 0.501961, 0.768627, 0.643137 ); + transferFunction->AddRGBPoint( 198.0, 0, 0.494118, 0.294118 ); + transferFunction->AddRGBPoint( 199.0, 0.501961, 0.376471, 0.25098 ); + transferFunction->AddRGBPoint( 200.0, 0, 0.196078, 0.501961 ); + transferFunction->AddRGBPoint( 201.0, 1, 0.8, 0.6 ); + transferFunction->AddRGBPoint( 202.0, 1, 0.501961, 0.501961 ); + transferFunction->AddRGBPoint( 203.0, 1, 1, 0 ); + transferFunction->AddRGBPoint( 204.0, 0.25098, 0, 0.25098 ); + transferFunction->AddRGBPoint( 205.0, 0, 0, 1 ); + transferFunction->AddRGBPoint( 206.0, 1, 0, 0 ); + transferFunction->AddRGBPoint( 207.0, 0.501961, 0.501961, 1 ); + transferFunction->AddRGBPoint( 208.0, 0, 0.501961, 0 ); + transferFunction->AddRGBPoint( 209.0, 0.768627, 0.627451, 0.501961 ); + transferFunction->AddRGBPoint( 210.0, 0.12549, 0.784314, 1 ); + transferFunction->AddRGBPoint( 211.0, 0.501961, 1, 0.501961 ); + transferFunction->AddRGBPoint( 212.0, 0.8, 0.6, 0.8 ); + transferFunction->AddRGBPoint( 213.0, 0.47451, 0.0666667, 0.533333 ); + transferFunction->AddRGBPoint( 214.0, 0.501961, 0, 0 ); + transferFunction->AddRGBPoint( 215.0, 0.501961, 0.12549, 1 ); + transferFunction->AddRGBPoint( 216.0, 1, 0.8, 0.4 ); + transferFunction->AddRGBPoint( 217.0, 0.501961, 0.501961, 0.501961 ); + transferFunction->AddRGBPoint( 218.0, 0.407843, 1, 1 ); + transferFunction->AddRGBPoint( 219.0, 0, 0.886275, 0 ); + transferFunction->AddRGBPoint( 220.0, 0.803922, 0.247059, 0.305882 ); + transferFunction->AddRGBPoint( 221.0, 0.772549, 0.227451, 0.980392 ); + transferFunction->AddRGBPoint( 222.0, 0.129412, 0.588235, 0.980392 ); + transferFunction->AddRGBPoint( 223.0, 0.886275, 0, 0 ); + transferFunction->AddRGBPoint( 224.0, 0.392157, 0.392157, 0.392157 ); + transferFunction->AddRGBPoint( 225.0, 0.772549, 0.588235, 0.980392 ); + transferFunction->AddRGBPoint( 226.0, 0.666667, 0.666667, 1 ); + transferFunction->AddRGBPoint( 250.0, 1, 0, 0 ); + transferFunction->AddRGBPoint( 251.0, 0, 0, 0.25098 ); + transferFunction->AddRGBPoint( 252.0, 0, 0, 0.439216 ); + transferFunction->AddRGBPoint( 253.0, 0, 0, 0.627451 ); + transferFunction->AddRGBPoint( 254.0, 0, 0, 0.815686 ); + transferFunction->AddRGBPoint( 255.0, 0, 0, 1 ); + transferFunction->AddRGBPoint( 331.0, 1, 0, 0 ); + transferFunction->AddRGBPoint( 332.0, 1, 0.313725, 0 ); + transferFunction->AddRGBPoint( 333.0, 1, 0.627451, 0 ); + transferFunction->AddRGBPoint( 334.0, 1, 1, 0 ); + transferFunction->AddRGBPoint( 335.0, 0, 1, 0 ); + transferFunction->AddRGBPoint( 336.0, 1, 0, 0.627451 ); + transferFunction->AddRGBPoint( 337.0, 1, 0, 1 ); + transferFunction->AddRGBPoint( 338.0, 1, 0.196078, 0.313725 ); + transferFunction->AddRGBPoint( 339.0, 0.313725, 1, 0.196078 ); + transferFunction->AddRGBPoint( 340.0, 0.627451, 1, 0.196078 ); + transferFunction->AddRGBPoint( 341.0, 0.627451, 0.784314, 1 ); + transferFunction->AddRGBPoint( 342.0, 0, 1, 0.627451 ); + transferFunction->AddRGBPoint( 343.0, 0, 0, 1 ); + transferFunction->AddRGBPoint( 344.0, 0.313725, 0.196078, 1 ); + transferFunction->AddRGBPoint( 345.0, 0.627451, 0, 1 ); + transferFunction->AddRGBPoint( 346.0, 1, 0.823529, 0 ); + transferFunction->AddRGBPoint( 347.0, 0, 0.627451, 1 ); + transferFunction->AddRGBPoint( 348.0, 1, 0.784314, 0.313725 ); + transferFunction->AddRGBPoint( 349.0, 1, 0.784314, 0.627451 ); + transferFunction->AddRGBPoint( 350.0, 1, 0.313725, 0.784314 ); + transferFunction->AddRGBPoint( 351.0, 1, 0.627451, 0.784314 ); + transferFunction->AddRGBPoint( 352.0, 0.117647, 1, 0.313725 ); + transferFunction->AddRGBPoint( 353.0, 0.313725, 0.784314, 1 ); + transferFunction->AddRGBPoint( 354.0, 0.313725, 1, 0.784314 ); + transferFunction->AddRGBPoint( 355.0, 0.764706, 1, 0.784314 ); + transferFunction->AddRGBPoint( 356.0, 0.470588, 0.784314, 0.0784314 ); + transferFunction->AddRGBPoint( 357.0, 0.666667, 0.0392157, 0.784314 ); + transferFunction->AddRGBPoint( 358.0, 0.0784314, 0.509804, 0.705882 ); + transferFunction->AddRGBPoint( 359.0, 0.0784314, 0.705882, 0.509804 ); + transferFunction->AddRGBPoint( 400.0, 0.807843, 0.243137, 0.305882 ); + transferFunction->AddRGBPoint( 401.0, 0.47451, 0.0705882, 0.52549 ); + transferFunction->AddRGBPoint( 402.0, 0.780392, 0.227451, 0.980392 ); + transferFunction->AddRGBPoint( 403.0, 0.00392157, 0.580392, 0 ); + transferFunction->AddRGBPoint( 404.0, 0.866667, 0.972549, 0.643137 ); + transferFunction->AddRGBPoint( 405.0, 0.905882, 0.580392, 0.133333 ); + transferFunction->AddRGBPoint( 406.0, 0.00392157, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 407.0, 0.470588, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 408.0, 0.482353, 0.729412, 0.866667 ); + transferFunction->AddRGBPoint( 409.0, 0.933333, 0.0509804, 0.694118 ); + transferFunction->AddRGBPoint( 410.0, 0.482353, 0.729412, 0.862745 ); + transferFunction->AddRGBPoint( 411.0, 0.541176, 0.0509804, 0.807843 ); + transferFunction->AddRGBPoint( 412.0, 0.933333, 0.509804, 0.690196 ); + transferFunction->AddRGBPoint( 413.0, 0.854902, 0.901961, 0.298039 ); + transferFunction->AddRGBPoint( 414.0, 0.14902, 0.835294, 0.690196 ); + transferFunction->AddRGBPoint( 415.0, 0.00392157, 0.882353, 0.690196 ); + transferFunction->AddRGBPoint( 416.0, 0.00392157, 0.882353, 0.690196 ); + transferFunction->AddRGBPoint( 417.0, 0.784314, 0.00784314, 0.392157 ); + transferFunction->AddRGBPoint( 418.0, 0.784314, 0.00784314, 0.392157 ); + transferFunction->AddRGBPoint( 419.0, 0.0196078, 0.784314, 0.352941 ); + transferFunction->AddRGBPoint( 420.0, 0.0196078, 0.784314, 0.352941 ); + transferFunction->AddRGBPoint( 421.0, 0.392157, 0.0196078, 0.784314 ); + transferFunction->AddRGBPoint( 422.0, 0.0980392, 1, 0.392157 ); + transferFunction->AddRGBPoint( 423.0, 0.0980392, 1, 0.392157 ); + transferFunction->AddRGBPoint( 424.0, 0.901961, 0.027451, 0.392157 ); + transferFunction->AddRGBPoint( 425.0, 0.901961, 0.027451, 0.392157 ); + transferFunction->AddRGBPoint( 426.0, 0.392157, 0.0196078, 0.784314 ); + transferFunction->AddRGBPoint( 427.0, 0.588235, 0.0392157, 0.784314 ); + transferFunction->AddRGBPoint( 428.0, 0.588235, 0.0392157, 0.784314 ); + transferFunction->AddRGBPoint( 429.0, 0.686275, 0.0392157, 0.690196 ); + transferFunction->AddRGBPoint( 430.0, 0.686275, 0.0392157, 0.690196 ); + transferFunction->AddRGBPoint( 431.0, 0.0392157, 0.392157, 1 ); + transferFunction->AddRGBPoint( 432.0, 0.0392157, 0.392157, 1 ); + transferFunction->AddRGBPoint( 433.0, 0.588235, 0.176471, 0.27451 ); + transferFunction->AddRGBPoint( 434.0, 0.588235, 0.176471, 0.27451 ); + transferFunction->AddRGBPoint( 435.0, 0.176471, 0.784314, 0.0588235 ); + transferFunction->AddRGBPoint( 436.0, 0.176471, 0.784314, 0.0588235 ); + transferFunction->AddRGBPoint( 437.0, 0.890196, 0.176471, 0.392157 ); + transferFunction->AddRGBPoint( 438.0, 0.890196, 0.176471, 0.392157 ); + transferFunction->AddRGBPoint( 439.0, 0.890196, 0.176471, 0.392157 ); + transferFunction->AddRGBPoint( 498.0, 0.560784, 0.737255, 0.560784 ); + transferFunction->AddRGBPoint( 499.0, 1, 0.972549, 0.862745 ); + transferFunction->AddRGBPoint( 500.0, 0.0666667, 0.333333, 0.533333 ); + transferFunction->AddRGBPoint( 501.0, 0.466667, 0.733333, 0.4 ); + transferFunction->AddRGBPoint( 502.0, 0.8, 0.266667, 0.133333 ); + transferFunction->AddRGBPoint( 503.0, 0.8, 0, 1 ); + transferFunction->AddRGBPoint( 504.0, 0.866667, 0.733333, 0.0666667 ); + transferFunction->AddRGBPoint( 505.0, 0.6, 0.866667, 0.933333 ); + transferFunction->AddRGBPoint( 506.0, 0.2, 0.0666667, 0.0666667 ); + transferFunction->AddRGBPoint( 507.0, 0, 0.466667, 0.333333 ); + transferFunction->AddRGBPoint( 508.0, 0.0784314, 0.392157, 0.784314 ); + transferFunction->AddRGBPoint( 550.0, 0.0666667, 0.333333, 0.537255 ); + transferFunction->AddRGBPoint( 551.0, 0.466667, 0.733333, 0.403922 ); + transferFunction->AddRGBPoint( 552.0, 0.8, 0.266667, 0.137255 ); + transferFunction->AddRGBPoint( 553.0, 0.8, 0, 0.996078 ); + transferFunction->AddRGBPoint( 554.0, 0.866667, 0.733333, 0.0627451 ); + transferFunction->AddRGBPoint( 555.0, 0.6, 0.866667, 0.937255 ); + transferFunction->AddRGBPoint( 556.0, 0.2, 0.0666667, 0.0705882 ); + transferFunction->AddRGBPoint( 557.0, 0, 0.466667, 0.337255 ); + transferFunction->AddRGBPoint( 558.0, 0.0784314, 0.392157, 0.788235 ); + transferFunction->AddRGBPoint( 600.0, 0.996078, 0.996078, 0.996078 ); + transferFunction->AddRGBPoint( 601.0, 0.27451, 0.509804, 0.705882 ); + transferFunction->AddRGBPoint( 602.0, 0.960784, 0.960784, 0.960784 ); + transferFunction->AddRGBPoint( 603.0, 0.803922, 0.243137, 0.305882 ); + transferFunction->AddRGBPoint( 604.0, 0.470588, 0.0705882, 0.52549 ); + transferFunction->AddRGBPoint( 605.0, 0.768627, 0.227451, 0.980392 ); + transferFunction->AddRGBPoint( 606.0, 0, 0.580392, 0 ); + transferFunction->AddRGBPoint( 607.0, 0.862745, 0.972549, 0.643137 ); + transferFunction->AddRGBPoint( 608.0, 0.901961, 0.580392, 0.133333 ); + transferFunction->AddRGBPoint( 609.0, 0, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 610.0, 0, 0.462745, 0.054902 ); + transferFunction->AddRGBPoint( 611.0, 0.478431, 0.729412, 0.862745 ); + transferFunction->AddRGBPoint( 612.0, 0.92549, 0.0509804, 0.690196 ); + transferFunction->AddRGBPoint( 613.0, 0.0470588, 0.188235, 1 ); + transferFunction->AddRGBPoint( 614.0, 0.8, 0.713725, 0.556863 ); + transferFunction->AddRGBPoint( 615.0, 0.164706, 0.8, 0.643137 ); + transferFunction->AddRGBPoint( 616.0, 0.466667, 0.623529, 0.690196 ); + transferFunction->AddRGBPoint( 617.0, 0.862745, 0.847059, 0.0784314 ); + transferFunction->AddRGBPoint( 618.0, 0.403922, 1, 1 ); + transferFunction->AddRGBPoint( 619.0, 0.313725, 0.768627, 0.384314 ); + transferFunction->AddRGBPoint( 620.0, 0.235294, 0.227451, 0.823529 ); + transferFunction->AddRGBPoint( 621.0, 0.235294, 0.227451, 0.823529 ); + transferFunction->AddRGBPoint( 622.0, 0.235294, 0.227451, 0.823529 ); + transferFunction->AddRGBPoint( 623.0, 0.235294, 0.227451, 0.823529 ); + transferFunction->AddRGBPoint( 624.0, 0.235294, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 625.0, 1, 0.647059, 0 ); + transferFunction->AddRGBPoint( 626.0, 1, 0.647059, 0 ); + transferFunction->AddRGBPoint( 627.0, 0, 1, 0.498039 ); + transferFunction->AddRGBPoint( 628.0, 0.647059, 0.164706, 0.164706 ); + transferFunction->AddRGBPoint( 640.0, 0.8, 0, 0 ); + transferFunction->AddRGBPoint( 641.0, 1, 0, 0 ); + transferFunction->AddRGBPoint( 642.0, 0, 0, 1 ); + transferFunction->AddRGBPoint( 643.0, 0.117647, 0.564706, 1 ); + transferFunction->AddRGBPoint( 644.0, 0.392157, 0.831373, 0.929412 ); + transferFunction->AddRGBPoint( 645.0, 0.854902, 0.647059, 0.12549 ); + transferFunction->AddRGBPoint( 646.0, 1, 0.843137, 0 ); + transferFunction->AddRGBPoint( 647.0, 1, 1, 0.65098 ); + transferFunction->AddRGBPoint( 648.0, 0.6, 0, 0.8 ); + transferFunction->AddRGBPoint( 649.0, 0.6, 0.552941, 0.819608 ); + transferFunction->AddRGBPoint( 650.0, 0.8, 0.8, 1 ); + transferFunction->AddRGBPoint( 651.0, 0.121569, 0.831373, 0.760784 ); + transferFunction->AddRGBPoint( 652.0, 0.0117647, 1, 0.929412 ); + transferFunction->AddRGBPoint( 653.0, 0.8, 1, 1 ); + transferFunction->AddRGBPoint( 654.0, 0.337255, 0.290196, 0.576471 ); + transferFunction->AddRGBPoint( 655.0, 0.447059, 0.447059, 0.745098 ); + transferFunction->AddRGBPoint( 656.0, 0.721569, 0.698039, 1 ); + transferFunction->AddRGBPoint( 657.0, 0.494118, 0.541176, 0.145098 ); + transferFunction->AddRGBPoint( 658.0, 0.741176, 0.772549, 0.458824 ); + transferFunction->AddRGBPoint( 659.0, 0.941176, 0.901961, 0.54902 ); + transferFunction->AddRGBPoint( 660.0, 0.8, 0, 0 ); + transferFunction->AddRGBPoint( 661.0, 1, 0, 0 ); + transferFunction->AddRGBPoint( 662.0, 0, 0, 1 ); + transferFunction->AddRGBPoint( 663.0, 0.117647, 0.564706, 1 ); + transferFunction->AddRGBPoint( 664.0, 0.392157, 0.831373, 0.929412 ); + transferFunction->AddRGBPoint( 665.0, 0.854902, 0.647059, 0.12549 ); + transferFunction->AddRGBPoint( 666.0, 1, 0.843137, 0 ); + transferFunction->AddRGBPoint( 667.0, 1, 1, 0.65098 ); + transferFunction->AddRGBPoint( 668.0, 0.6, 0, 0.8 ); + transferFunction->AddRGBPoint( 669.0, 0.6, 0.552941, 0.819608 ); + transferFunction->AddRGBPoint( 670.0, 0.8, 0.8, 1 ); + transferFunction->AddRGBPoint( 671.0, 0.121569, 0.831373, 0.760784 ); + transferFunction->AddRGBPoint( 672.0, 0.0117647, 1, 0.929412 ); + transferFunction->AddRGBPoint( 673.0, 0.8, 1, 1 ); + transferFunction->AddRGBPoint( 674.0, 0.337255, 0.290196, 0.576471 ); + transferFunction->AddRGBPoint( 675.0, 0.447059, 0.447059, 0.745098 ); + transferFunction->AddRGBPoint( 676.0, 0.721569, 0.698039, 1 ); + transferFunction->AddRGBPoint( 677.0, 0.494118, 0.541176, 0.145098 ); + transferFunction->AddRGBPoint( 678.0, 0.741176, 0.772549, 0.458824 ); + transferFunction->AddRGBPoint( 679.0, 0.941176, 0.901961, 0.54902 ); + transferFunction->AddRGBPoint( 701.0, 0.470588, 0.0705882, 0.52549 ); + transferFunction->AddRGBPoint( 702.0, 0.803922, 0.243137, 0.305882 ); + transferFunction->AddRGBPoint( 703.0, 0, 0.882353, 0 ); + transferFunction->AddRGBPoint( 999.0, 1, 0.392157, 0.392157 ); + transferFunction->AddRGBPoint( 1000.0, 0.0980392, 0.0196078, 0.0980392 ); + transferFunction->AddRGBPoint( 1001.0, 0.0980392, 0.392157, 0.156863 ); + transferFunction->AddRGBPoint( 1002.0, 0.490196, 0.392157, 0.627451 ); + transferFunction->AddRGBPoint( 1003.0, 0.392157, 0.0980392, 0 ); + transferFunction->AddRGBPoint( 1004.0, 0.470588, 0.27451, 0.196078 ); + transferFunction->AddRGBPoint( 1005.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 1006.0, 0.862745, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 1007.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 1008.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 1009.0, 0.705882, 0.156863, 0.470588 ); + transferFunction->AddRGBPoint( 1010.0, 0.54902, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 1011.0, 0.0784314, 0.117647, 0.54902 ); + transferFunction->AddRGBPoint( 1012.0, 0.137255, 0.294118, 0.196078 ); + transferFunction->AddRGBPoint( 1013.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 1014.0, 0.784314, 0.137255, 0.294118 ); + transferFunction->AddRGBPoint( 1015.0, 0.627451, 0.392157, 0.196078 ); + transferFunction->AddRGBPoint( 1016.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 1017.0, 0.235294, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 1018.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 1019.0, 0.0784314, 0.392157, 0.196078 ); + transferFunction->AddRGBPoint( 1020.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 1021.0, 0.470588, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 1022.0, 0.862745, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 1023.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 1024.0, 0.235294, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 1025.0, 0.627451, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 1026.0, 0.313725, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 1027.0, 0.294118, 0.196078, 0.490196 ); + transferFunction->AddRGBPoint( 1028.0, 0.0784314, 0.862745, 0.627451 ); + transferFunction->AddRGBPoint( 1029.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 1030.0, 0.54902, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 1031.0, 0.313725, 0.627451, 0.0784314 ); + transferFunction->AddRGBPoint( 1032.0, 0.392157, 0, 0.392157 ); + transferFunction->AddRGBPoint( 1033.0, 0.27451, 0.27451, 0.27451 ); + transferFunction->AddRGBPoint( 1034.0, 0.588235, 0.588235, 0.784314 ); + transferFunction->AddRGBPoint( 1035.0, 1, 0.752941, 0.12549 ); + transferFunction->AddRGBPoint( 2000.0, 0.0980392, 0.0196078, 0.0980392 ); + transferFunction->AddRGBPoint( 2001.0, 0.0980392, 0.392157, 0.156863 ); + transferFunction->AddRGBPoint( 2002.0, 0.490196, 0.392157, 0.627451 ); + transferFunction->AddRGBPoint( 2003.0, 0.392157, 0.0980392, 0 ); + transferFunction->AddRGBPoint( 2004.0, 0.470588, 0.27451, 0.196078 ); + transferFunction->AddRGBPoint( 2005.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 2006.0, 0.862745, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 2007.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 2008.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 2009.0, 0.705882, 0.156863, 0.470588 ); + transferFunction->AddRGBPoint( 2010.0, 0.54902, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 2011.0, 0.0784314, 0.117647, 0.54902 ); + transferFunction->AddRGBPoint( 2012.0, 0.137255, 0.294118, 0.196078 ); + transferFunction->AddRGBPoint( 2013.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 2014.0, 0.784314, 0.137255, 0.294118 ); + transferFunction->AddRGBPoint( 2015.0, 0.627451, 0.392157, 0.196078 ); + transferFunction->AddRGBPoint( 2016.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 2017.0, 0.235294, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 2018.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 2019.0, 0.0784314, 0.392157, 0.196078 ); + transferFunction->AddRGBPoint( 2020.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 2021.0, 0.470588, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 2022.0, 0.862745, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 2023.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 2024.0, 0.235294, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 2025.0, 0.627451, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 2026.0, 0.313725, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 2027.0, 0.294118, 0.196078, 0.490196 ); + transferFunction->AddRGBPoint( 2028.0, 0.0784314, 0.862745, 0.627451 ); + transferFunction->AddRGBPoint( 2029.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 2030.0, 0.54902, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 2031.0, 0.313725, 0.627451, 0.0784314 ); + transferFunction->AddRGBPoint( 2032.0, 0.392157, 0, 0.392157 ); + transferFunction->AddRGBPoint( 2033.0, 0.27451, 0.27451, 0.27451 ); + transferFunction->AddRGBPoint( 2034.0, 0.588235, 0.588235, 0.784314 ); + transferFunction->AddRGBPoint( 2035.0, 1, 0.752941, 0.12549 ); + transferFunction->AddRGBPoint( 3000.0, 0.901961, 0.980392, 0.901961 ); + transferFunction->AddRGBPoint( 3001.0, 0.901961, 0.607843, 0.843137 ); + transferFunction->AddRGBPoint( 3002.0, 0.509804, 0.607843, 0.372549 ); + transferFunction->AddRGBPoint( 3003.0, 0.607843, 0.901961, 1 ); + transferFunction->AddRGBPoint( 3004.0, 0.529412, 0.72549, 0.803922 ); + transferFunction->AddRGBPoint( 3005.0, 0.137255, 0.921569, 0.607843 ); + transferFunction->AddRGBPoint( 3006.0, 0.137255, 0.921569, 0.960784 ); + transferFunction->AddRGBPoint( 3007.0, 0.294118, 0.137255, 0.45098 ); + transferFunction->AddRGBPoint( 3008.0, 0.137255, 0.764706, 0.137255 ); + transferFunction->AddRGBPoint( 3009.0, 0.294118, 0.843137, 0.529412 ); + transferFunction->AddRGBPoint( 3010.0, 0.45098, 0.921569, 0.45098 ); + transferFunction->AddRGBPoint( 3011.0, 0.921569, 0.882353, 0.45098 ); + transferFunction->AddRGBPoint( 3012.0, 0.862745, 0.705882, 0.803922 ); + transferFunction->AddRGBPoint( 3013.0, 0.117647, 0.45098, 0.45098 ); + transferFunction->AddRGBPoint( 3014.0, 0.215686, 0.862745, 0.705882 ); + transferFunction->AddRGBPoint( 3015.0, 0.372549, 0.607843, 0.803922 ); + transferFunction->AddRGBPoint( 3016.0, 0.921569, 0.137255, 0.764706 ); + transferFunction->AddRGBPoint( 3017.0, 0.764706, 0.137255, 0.764706 ); + transferFunction->AddRGBPoint( 3018.0, 0.137255, 0.294118, 0.45098 ); + transferFunction->AddRGBPoint( 3019.0, 0.921569, 0.607843, 0.803922 ); + transferFunction->AddRGBPoint( 3020.0, 0.137255, 0.764706, 0.921569 ); + transferFunction->AddRGBPoint( 3021.0, 0.529412, 0.607843, 0.764706 ); + transferFunction->AddRGBPoint( 3022.0, 0.137255, 0.921569, 0.921569 ); + transferFunction->AddRGBPoint( 3023.0, 0.137255, 0.294118, 0.137255 ); + transferFunction->AddRGBPoint( 3024.0, 0.764706, 0.921569, 0.137255 ); + transferFunction->AddRGBPoint( 3025.0, 0.372549, 0.45098, 0.294118 ); + transferFunction->AddRGBPoint( 3026.0, 0.686275, 0.921569, 0.45098 ); + transferFunction->AddRGBPoint( 3027.0, 0.705882, 0.803922, 0.509804 ); + transferFunction->AddRGBPoint( 3028.0, 0.921569, 0.137255, 0.372549 ); + transferFunction->AddRGBPoint( 3029.0, 0.921569, 0.294118, 0.45098 ); + transferFunction->AddRGBPoint( 3030.0, 0.45098, 0.137255, 0.137255 ); + transferFunction->AddRGBPoint( 3031.0, 0.686275, 0.372549, 0.921569 ); + transferFunction->AddRGBPoint( 3032.0, 0.607843, 1, 0.607843 ); + transferFunction->AddRGBPoint( 3033.0, 0.72549, 0.72549, 0.72549 ); + transferFunction->AddRGBPoint( 3034.0, 0.411765, 0.411765, 0.215686 ); + transferFunction->AddRGBPoint( 3035.0, 0.996078, 0.74902, 0.121569 ); + transferFunction->AddRGBPoint( 4000.0, 0.901961, 0.980392, 0.901961 ); + transferFunction->AddRGBPoint( 4001.0, 0.901961, 0.607843, 0.843137 ); + transferFunction->AddRGBPoint( 4002.0, 0.509804, 0.607843, 0.372549 ); + transferFunction->AddRGBPoint( 4003.0, 0.607843, 0.901961, 1 ); + transferFunction->AddRGBPoint( 4004.0, 0.529412, 0.72549, 0.803922 ); + transferFunction->AddRGBPoint( 4005.0, 0.137255, 0.921569, 0.607843 ); + transferFunction->AddRGBPoint( 4006.0, 0.137255, 0.921569, 0.960784 ); + transferFunction->AddRGBPoint( 4007.0, 0.294118, 0.137255, 0.45098 ); + transferFunction->AddRGBPoint( 4008.0, 0.137255, 0.764706, 0.137255 ); + transferFunction->AddRGBPoint( 4009.0, 0.294118, 0.843137, 0.529412 ); + transferFunction->AddRGBPoint( 4010.0, 0.45098, 0.921569, 0.45098 ); + transferFunction->AddRGBPoint( 4011.0, 0.921569, 0.882353, 0.45098 ); + transferFunction->AddRGBPoint( 4012.0, 0.862745, 0.705882, 0.803922 ); + transferFunction->AddRGBPoint( 4013.0, 0.117647, 0.45098, 0.45098 ); + transferFunction->AddRGBPoint( 4014.0, 0.215686, 0.862745, 0.705882 ); + transferFunction->AddRGBPoint( 4015.0, 0.372549, 0.607843, 0.803922 ); + transferFunction->AddRGBPoint( 4016.0, 0.921569, 0.137255, 0.764706 ); + transferFunction->AddRGBPoint( 4017.0, 0.764706, 0.137255, 0.764706 ); + transferFunction->AddRGBPoint( 4018.0, 0.137255, 0.294118, 0.45098 ); + transferFunction->AddRGBPoint( 4019.0, 0.921569, 0.607843, 0.803922 ); + transferFunction->AddRGBPoint( 4020.0, 0.137255, 0.764706, 0.921569 ); + transferFunction->AddRGBPoint( 4021.0, 0.529412, 0.607843, 0.764706 ); + transferFunction->AddRGBPoint( 4022.0, 0.137255, 0.921569, 0.921569 ); + transferFunction->AddRGBPoint( 4023.0, 0.137255, 0.294118, 0.137255 ); + transferFunction->AddRGBPoint( 4024.0, 0.764706, 0.921569, 0.137255 ); + transferFunction->AddRGBPoint( 4025.0, 0.372549, 0.45098, 0.294118 ); + transferFunction->AddRGBPoint( 4026.0, 0.686275, 0.921569, 0.45098 ); + transferFunction->AddRGBPoint( 4027.0, 0.705882, 0.803922, 0.509804 ); + transferFunction->AddRGBPoint( 4028.0, 0.921569, 0.137255, 0.372549 ); + transferFunction->AddRGBPoint( 4029.0, 0.921569, 0.294118, 0.45098 ); + transferFunction->AddRGBPoint( 4030.0, 0.45098, 0.137255, 0.137255 ); + transferFunction->AddRGBPoint( 4031.0, 0.686275, 0.372549, 0.921569 ); + transferFunction->AddRGBPoint( 4032.0, 0.607843, 1, 0.607843 ); + transferFunction->AddRGBPoint( 4033.0, 0.72549, 0.72549, 0.72549 ); + transferFunction->AddRGBPoint( 4034.0, 0.411765, 0.411765, 0.215686 ); + transferFunction->AddRGBPoint( 4035.0, 0.996078, 0.74902, 0.121569 ); + transferFunction->AddRGBPoint( 1101.0, 0.196078, 0.196078, 0.196078 ); + transferFunction->AddRGBPoint( 1102.0, 0.705882, 0.0784314, 0.117647 ); + transferFunction->AddRGBPoint( 1103.0, 0.235294, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 1104.0, 0.0980392, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 1200.0, 0.0980392, 0.235294, 0.239216 ); + transferFunction->AddRGBPoint( 1201.0, 0.0980392, 0.352941, 0.235294 ); + transferFunction->AddRGBPoint( 1202.0, 0.0980392, 0.470588, 0.235294 ); + transferFunction->AddRGBPoint( 1205.0, 0.0980392, 0.588235, 0.235294 ); + transferFunction->AddRGBPoint( 1206.0, 0.0980392, 0.705882, 0.235294 ); + transferFunction->AddRGBPoint( 1207.0, 0.0980392, 0.823529, 0.235294 ); + transferFunction->AddRGBPoint( 1210.0, 0.0980392, 0.588235, 0.352941 ); + transferFunction->AddRGBPoint( 1211.0, 0.0980392, 0.705882, 0.352941 ); + transferFunction->AddRGBPoint( 1212.0, 0.0980392, 0.823529, 0.352941 ); + transferFunction->AddRGBPoint( 1105.0, 0.705882, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 1106.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 1107.0, 0.54902, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 1108.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 1109.0, 0.54902, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 1110.0, 0.705882, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 1111.0, 0.54902, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 1112.0, 0.0823529, 0.0392157, 0.0392157 ); + transferFunction->AddRGBPoint( 1113.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 1114.0, 0.0901961, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 1115.0, 0.705882, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 1116.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 1117.0, 0.235294, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 1118.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 1119.0, 0.254902, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 1120.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 1121.0, 0.235294, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 1122.0, 0.0784314, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 1123.0, 0.392157, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 1124.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 1125.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 1126.0, 0.235294, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 1127.0, 0.0980392, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 1128.0, 0.0784314, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 1129.0, 0.235294, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 1130.0, 0.235294, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 1131.0, 0.862745, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 1132.0, 0.705882, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 1133.0, 0.235294, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 1134.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 1135.0, 0.254902, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 1136.0, 0.0980392, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 1137.0, 0.0509804, 0, 0.980392 ); + transferFunction->AddRGBPoint( 1138.0, 0.239216, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 1139.0, 0.239216, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 1140.0, 0.239216, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 1141.0, 0.0980392, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 1142.0, 0.54902, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 1143.0, 0.862745, 0.705882, 0.0784314 ); + transferFunction->AddRGBPoint( 1144.0, 0.247059, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 1145.0, 0.866667, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 1146.0, 0.0823529, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 1147.0, 0.717647, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 1148.0, 0.866667, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 1149.0, 0.866667, 0.235294, 0.54902 ); + transferFunction->AddRGBPoint( 1150.0, 0.866667, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 1151.0, 0.239216, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 1152.0, 0.392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 1153.0, 0.0392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 1154.0, 0.866667, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 1155.0, 0.552941, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 1156.0, 0.239216, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 1157.0, 0.0823529, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 1158.0, 0.552941, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 1159.0, 0.560784, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 1160.0, 0.239216, 0.0784314, 0.705882 ); + transferFunction->AddRGBPoint( 1161.0, 0.396078, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 1162.0, 0.0823529, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 1163.0, 0.866667, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 1164.0, 0.552941, 0.392157, 0.862745 ); + transferFunction->AddRGBPoint( 1165.0, 0.396078, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 1166.0, 0.866667, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 1167.0, 0.709804, 0.784314, 0.0784314 ); + transferFunction->AddRGBPoint( 1168.0, 0.0823529, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 1169.0, 0.396078, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 1170.0, 0.709804, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 1171.0, 0.0823529, 0.54902, 0.784314 ); + transferFunction->AddRGBPoint( 1172.0, 0.0823529, 0.0784314, 0.941176 ); + transferFunction->AddRGBPoint( 1173.0, 0.0823529, 0.0784314, 0.784314 ); + transferFunction->AddRGBPoint( 1174.0, 0.239216, 0.705882, 0.235294 ); + transferFunction->AddRGBPoint( 1175.0, 0.239216, 0.705882, 0.980392 ); + transferFunction->AddRGBPoint( 1176.0, 0.0823529, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 1177.0, 0.396078, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 1178.0, 0.0823529, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 1179.0, 0.0823529, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 1180.0, 0.87451, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 1181.0, 0.866667, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 2101.0, 0.196078, 0.196078, 0.196078 ); + transferFunction->AddRGBPoint( 2102.0, 0.705882, 0.0784314, 0.117647 ); + transferFunction->AddRGBPoint( 2103.0, 0.235294, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 2104.0, 0.0980392, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 2105.0, 0.705882, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 2106.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 2107.0, 0.54902, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 2108.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 2109.0, 0.54902, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 2110.0, 0.705882, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 2111.0, 0.54902, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 2112.0, 0.0823529, 0.0392157, 0.0392157 ); + transferFunction->AddRGBPoint( 2113.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 2114.0, 0.0901961, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 2115.0, 0.705882, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 2116.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 2117.0, 0.235294, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 2118.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 2119.0, 0.254902, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 2120.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 2121.0, 0.235294, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 2122.0, 0.0784314, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 2123.0, 0.392157, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 2124.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 2125.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 2126.0, 0.235294, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 2127.0, 0.0980392, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 2128.0, 0.0784314, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 2129.0, 0.235294, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 2130.0, 0.235294, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 2131.0, 0.862745, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 2132.0, 0.705882, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 2133.0, 0.235294, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 2134.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 2135.0, 0.254902, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 2136.0, 0.0980392, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 2137.0, 0.0509804, 0, 0.980392 ); + transferFunction->AddRGBPoint( 2138.0, 0.239216, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 2139.0, 0.239216, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 2140.0, 0.239216, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 2141.0, 0.0980392, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 2142.0, 0.54902, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 2143.0, 0.862745, 0.705882, 0.0784314 ); + transferFunction->AddRGBPoint( 2144.0, 0.247059, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 2145.0, 0.866667, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 2146.0, 0.0823529, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 2147.0, 0.717647, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 2148.0, 0.866667, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 2149.0, 0.866667, 0.235294, 0.54902 ); + transferFunction->AddRGBPoint( 2150.0, 0.866667, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 2151.0, 0.239216, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 2152.0, 0.392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 2153.0, 0.0392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 2154.0, 0.866667, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 2155.0, 0.552941, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 2156.0, 0.239216, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 2157.0, 0.0823529, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 2158.0, 0.552941, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 2159.0, 0.560784, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 2160.0, 0.239216, 0.0784314, 0.705882 ); + transferFunction->AddRGBPoint( 2161.0, 0.396078, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 2162.0, 0.0823529, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 2163.0, 0.866667, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 2164.0, 0.552941, 0.392157, 0.862745 ); + transferFunction->AddRGBPoint( 2165.0, 0.396078, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 2166.0, 0.866667, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 2167.0, 0.709804, 0.784314, 0.0784314 ); + transferFunction->AddRGBPoint( 2168.0, 0.0823529, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 2169.0, 0.396078, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 2170.0, 0.709804, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 2171.0, 0.0823529, 0.54902, 0.784314 ); + transferFunction->AddRGBPoint( 2172.0, 0.0823529, 0.0784314, 0.941176 ); + transferFunction->AddRGBPoint( 2173.0, 0.0823529, 0.0784314, 0.784314 ); + transferFunction->AddRGBPoint( 2174.0, 0.239216, 0.705882, 0.235294 ); + transferFunction->AddRGBPoint( 2175.0, 0.239216, 0.705882, 0.980392 ); + transferFunction->AddRGBPoint( 2176.0, 0.0823529, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 2177.0, 0.396078, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 2178.0, 0.0823529, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 2179.0, 0.0823529, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 2180.0, 0.87451, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 2181.0, 0.866667, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 2200.0, 0.0980392, 0.235294, 0.239216 ); + transferFunction->AddRGBPoint( 2201.0, 0.0980392, 0.352941, 0.235294 ); + transferFunction->AddRGBPoint( 2202.0, 0.0980392, 0.470588, 0.235294 ); + transferFunction->AddRGBPoint( 2205.0, 0.0980392, 0.588235, 0.235294 ); + transferFunction->AddRGBPoint( 2206.0, 0.0980392, 0.705882, 0.235294 ); + transferFunction->AddRGBPoint( 2207.0, 0.0980392, 0.823529, 0.235294 ); + transferFunction->AddRGBPoint( 2210.0, 0.0980392, 0.588235, 0.352941 ); + transferFunction->AddRGBPoint( 2211.0, 0.0980392, 0.705882, 0.352941 ); + transferFunction->AddRGBPoint( 2212.0, 0.0980392, 0.823529, 0.352941 ); + transferFunction->AddRGBPoint( 3101.0, 0.196078, 0.196078, 0.196078 ); + transferFunction->AddRGBPoint( 3102.0, 0.705882, 0.0784314, 0.117647 ); + transferFunction->AddRGBPoint( 3103.0, 0.235294, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 3104.0, 0.0980392, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 3105.0, 0.705882, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 3106.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 3107.0, 0.54902, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 3108.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 3109.0, 0.54902, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 3110.0, 0.705882, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 3111.0, 0.54902, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 3112.0, 0.0823529, 0.0392157, 0.0392157 ); + transferFunction->AddRGBPoint( 3113.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 3114.0, 0.0901961, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 3115.0, 0.705882, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 3116.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 3117.0, 0.235294, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 3118.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 3119.0, 0.254902, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 3120.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 3121.0, 0.235294, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 3122.0, 0.0784314, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 3123.0, 0.392157, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 3124.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 3125.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 3126.0, 0.235294, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 3127.0, 0.0980392, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 3128.0, 0.0784314, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 3129.0, 0.235294, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 3130.0, 0.235294, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 3131.0, 0.862745, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 3132.0, 0.705882, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 3133.0, 0.235294, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 3134.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 3135.0, 0.254902, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 3136.0, 0.0980392, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 3137.0, 0.0509804, 0, 0.980392 ); + transferFunction->AddRGBPoint( 3138.0, 0.239216, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 3139.0, 0.239216, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 3140.0, 0.239216, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 3141.0, 0.0980392, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 3142.0, 0.54902, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 3143.0, 0.862745, 0.705882, 0.0784314 ); + transferFunction->AddRGBPoint( 3144.0, 0.247059, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 3145.0, 0.866667, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 3146.0, 0.0823529, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 3147.0, 0.717647, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 3148.0, 0.866667, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 3149.0, 0.866667, 0.235294, 0.54902 ); + transferFunction->AddRGBPoint( 3150.0, 0.866667, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 3151.0, 0.239216, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 3152.0, 0.392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 3153.0, 0.0392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 3154.0, 0.866667, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 3155.0, 0.552941, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 3156.0, 0.239216, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 3157.0, 0.0823529, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 3158.0, 0.552941, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 3159.0, 0.560784, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 3160.0, 0.239216, 0.0784314, 0.705882 ); + transferFunction->AddRGBPoint( 3161.0, 0.396078, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 3162.0, 0.0823529, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 3163.0, 0.866667, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 3164.0, 0.552941, 0.392157, 0.862745 ); + transferFunction->AddRGBPoint( 3165.0, 0.396078, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 3166.0, 0.866667, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 3167.0, 0.709804, 0.784314, 0.0784314 ); + transferFunction->AddRGBPoint( 3168.0, 0.0823529, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 3169.0, 0.396078, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 3170.0, 0.709804, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 3171.0, 0.0823529, 0.54902, 0.784314 ); + transferFunction->AddRGBPoint( 3172.0, 0.0823529, 0.0784314, 0.941176 ); + transferFunction->AddRGBPoint( 3173.0, 0.0823529, 0.0784314, 0.784314 ); + transferFunction->AddRGBPoint( 3174.0, 0.239216, 0.705882, 0.235294 ); + transferFunction->AddRGBPoint( 3175.0, 0.239216, 0.705882, 0.980392 ); + transferFunction->AddRGBPoint( 3176.0, 0.0823529, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 3177.0, 0.396078, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 3178.0, 0.0823529, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 3179.0, 0.0823529, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 3180.0, 0.87451, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 3181.0, 0.866667, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 4101.0, 0.196078, 0.196078, 0.196078 ); + transferFunction->AddRGBPoint( 4102.0, 0.705882, 0.0784314, 0.117647 ); + transferFunction->AddRGBPoint( 4103.0, 0.235294, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 4104.0, 0.0980392, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 4105.0, 0.705882, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 4106.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 4107.0, 0.54902, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 4108.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 4109.0, 0.54902, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 4110.0, 0.705882, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 4111.0, 0.54902, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 4112.0, 0.0823529, 0.0392157, 0.0392157 ); + transferFunction->AddRGBPoint( 4113.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 4114.0, 0.0901961, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 4115.0, 0.705882, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 4116.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 4117.0, 0.235294, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 4118.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 4119.0, 0.254902, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 4120.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 4121.0, 0.235294, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 4122.0, 0.0784314, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 4123.0, 0.392157, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 4124.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 4125.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 4126.0, 0.235294, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 4127.0, 0.0980392, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 4128.0, 0.0784314, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 4129.0, 0.235294, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 4130.0, 0.235294, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 4131.0, 0.862745, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 4132.0, 0.705882, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 4133.0, 0.235294, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 4134.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 4135.0, 0.254902, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 4136.0, 0.0980392, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 4137.0, 0.0509804, 0, 0.980392 ); + transferFunction->AddRGBPoint( 4138.0, 0.239216, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 4139.0, 0.239216, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 4140.0, 0.239216, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 4141.0, 0.0980392, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 4142.0, 0.54902, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 4143.0, 0.862745, 0.705882, 0.0784314 ); + transferFunction->AddRGBPoint( 4144.0, 0.247059, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 4145.0, 0.866667, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 4146.0, 0.0823529, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 4147.0, 0.717647, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 4148.0, 0.866667, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 4149.0, 0.866667, 0.235294, 0.54902 ); + transferFunction->AddRGBPoint( 4150.0, 0.866667, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 4151.0, 0.239216, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 4152.0, 0.392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 4153.0, 0.0392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 4154.0, 0.866667, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 4155.0, 0.552941, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 4156.0, 0.239216, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 4157.0, 0.0823529, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 4158.0, 0.552941, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 4159.0, 0.560784, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 4160.0, 0.239216, 0.0784314, 0.705882 ); + transferFunction->AddRGBPoint( 4161.0, 0.396078, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 4162.0, 0.0823529, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 4163.0, 0.866667, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 4164.0, 0.552941, 0.392157, 0.862745 ); + transferFunction->AddRGBPoint( 4165.0, 0.396078, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 4166.0, 0.866667, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 4167.0, 0.709804, 0.784314, 0.0784314 ); + transferFunction->AddRGBPoint( 4168.0, 0.0823529, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 4169.0, 0.396078, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 4170.0, 0.709804, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 4171.0, 0.0823529, 0.54902, 0.784314 ); + transferFunction->AddRGBPoint( 4172.0, 0.0823529, 0.0784314, 0.941176 ); + transferFunction->AddRGBPoint( 4173.0, 0.0823529, 0.0784314, 0.784314 ); + transferFunction->AddRGBPoint( 4174.0, 0.239216, 0.705882, 0.235294 ); + transferFunction->AddRGBPoint( 4175.0, 0.239216, 0.705882, 0.980392 ); + transferFunction->AddRGBPoint( 4176.0, 0.0823529, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 4177.0, 0.396078, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 4178.0, 0.0823529, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 4179.0, 0.0823529, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 4180.0, 0.87451, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 4181.0, 0.866667, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 5001.0, 0.0784314, 0.117647, 0.156863 ); + transferFunction->AddRGBPoint( 5002.0, 0.0784314, 0.117647, 0.156863 ); + transferFunction->AddRGBPoint( 5100.0, 0.8, 0.4, 0.4 ); + transferFunction->AddRGBPoint( 5101.0, 0.8, 0.4, 0.4 ); + transferFunction->AddRGBPoint( 5102.0, 1, 1, 0.4 ); + transferFunction->AddRGBPoint( 5103.0, 0.6, 0.8, 0 ); + transferFunction->AddRGBPoint( 5104.0, 0, 0.6, 0.6 ); + transferFunction->AddRGBPoint( 5105.0, 0.8, 0.6, 1 ); + transferFunction->AddRGBPoint( 5106.0, 1, 0.6, 0.2 ); + transferFunction->AddRGBPoint( 5107.0, 0.8, 0.8, 0.8 ); + transferFunction->AddRGBPoint( 5108.0, 0.6, 1, 1 ); + transferFunction->AddRGBPoint( 5109.0, 0.4, 0.6, 1 ); + transferFunction->AddRGBPoint( 5110.0, 1, 1, 0.4 ); + transferFunction->AddRGBPoint( 5111.0, 0.6, 0.8, 0 ); + transferFunction->AddRGBPoint( 5112.0, 0, 0.6, 0.6 ); + transferFunction->AddRGBPoint( 5113.0, 0.8, 0.6, 1 ); + transferFunction->AddRGBPoint( 5114.0, 1, 0.6, 0.2 ); + transferFunction->AddRGBPoint( 5115.0, 0.8, 0.8, 0.8 ); + transferFunction->AddRGBPoint( 5116.0, 0.6, 1, 1 ); + transferFunction->AddRGBPoint( 5117.0, 0.4, 0.6, 1 ); + transferFunction->AddRGBPoint( 5200.0, 0.8, 0.4, 0.4 ); + transferFunction->AddRGBPoint( 5201.0, 0.8, 0.4, 0.4 ); + transferFunction->AddRGBPoint( 5202.0, 1, 1, 0.4 ); + transferFunction->AddRGBPoint( 5203.0, 0.6, 0.8, 0 ); + transferFunction->AddRGBPoint( 5204.0, 0, 0.6, 0.6 ); + transferFunction->AddRGBPoint( 5205.0, 0.8, 0.6, 1 ); + transferFunction->AddRGBPoint( 5206.0, 1, 0.6, 0.2 ); + transferFunction->AddRGBPoint( 5207.0, 0.8, 0.8, 0.8 ); + transferFunction->AddRGBPoint( 5208.0, 0.6, 1, 1 ); + transferFunction->AddRGBPoint( 5209.0, 0.4, 0.6, 1 ); + transferFunction->AddRGBPoint( 5210.0, 1, 1, 0.4 ); + transferFunction->AddRGBPoint( 5211.0, 0.6, 0.8, 0 ); + transferFunction->AddRGBPoint( 5212.0, 0, 0.6, 0.6 ); + transferFunction->AddRGBPoint( 5213.0, 0.8, 0.6, 1 ); + transferFunction->AddRGBPoint( 5214.0, 1, 0.6, 0.2 ); + transferFunction->AddRGBPoint( 5215.0, 0.8, 0.8, 0.8 ); + transferFunction->AddRGBPoint( 5216.0, 0.6, 1, 1 ); + transferFunction->AddRGBPoint( 5217.0, 0.4, 0.6, 1 ); + transferFunction->AddRGBPoint( 6000.0, 0, 1, 0 ); + transferFunction->AddRGBPoint( 6001.0, 1, 1, 0 ); + transferFunction->AddRGBPoint( 6002.0, 0, 1, 1 ); + transferFunction->AddRGBPoint( 6003.0, 0, 0, 1 ); + transferFunction->AddRGBPoint( 6010.0, 0.92549, 0.0627451, 0.905882 ); + transferFunction->AddRGBPoint( 6020.0, 0.929412, 0.0705882, 0.909804 ); + transferFunction->AddRGBPoint( 6030.0, 0.92549, 0.0509804, 0.890196 ); + transferFunction->AddRGBPoint( 6040.0, 0.92549, 0.0666667, 0.894118 ); + transferFunction->AddRGBPoint( 6050.0, 0.00392157, 1, 0.00392157 ); + transferFunction->AddRGBPoint( 6060.0, 0.00784314, 1, 0.00392157 ); + transferFunction->AddRGBPoint( 6070.0, 0.92549, 0.054902, 0.901961 ); + transferFunction->AddRGBPoint( 6080.0, 0.929412, 0.054902, 0.901961 ); + transferFunction->AddRGBPoint( 7001.0, 0.282353, 0.517647, 0.709804 ); + transferFunction->AddRGBPoint( 7002.0, 0.952941, 0.952941, 0.952941 ); + transferFunction->AddRGBPoint( 7003.0, 0.811765, 0.247059, 0.309804 ); + transferFunction->AddRGBPoint( 7004.0, 0.47451, 0.0784314, 0.529412 ); + transferFunction->AddRGBPoint( 7005.0, 0.772549, 0.235294, 0.972549 ); + transferFunction->AddRGBPoint( 7006.0, 0.00784314, 0.584314, 0.00784314 ); + transferFunction->AddRGBPoint( 7007.0, 0.866667, 0.976471, 0.65098 ); + transferFunction->AddRGBPoint( 7008.0, 0.909804, 0.572549, 0.137255 ); + transferFunction->AddRGBPoint( 7009.0, 0.0784314, 0.235294, 0.470588 ); + transferFunction->AddRGBPoint( 7010.0, 0.980392, 0.980392, 0 ); + transferFunction->AddRGBPoint( 7011.0, 0.478431, 0.733333, 0.870588 ); + transferFunction->AddRGBPoint( 7012.0, 0.929412, 0.0470588, 0.694118 ); + transferFunction->AddRGBPoint( 7013.0, 0.0392157, 0.192157, 1 ); + transferFunction->AddRGBPoint( 7014.0, 0.803922, 0.721569, 0.564706 ); + transferFunction->AddRGBPoint( 7015.0, 0.176471, 0.803922, 0.647059 ); + transferFunction->AddRGBPoint( 7016.0, 0.458824, 0.627451, 0.686275 ); + transferFunction->AddRGBPoint( 7017.0, 0.866667, 0.85098, 0.0823529 ); + transferFunction->AddRGBPoint( 7018.0, 0.0784314, 0.235294, 0.470588 ); + transferFunction->AddRGBPoint( 7019.0, 0.552941, 0.0823529, 0.392157 ); + transferFunction->AddRGBPoint( 7020.0, 0.882353, 0.54902, 0.552941 ); + transferFunction->AddRGBPoint( 7100.0, 0.164706, 0.788235, 0.658824 ); + transferFunction->AddRGBPoint( 7101.0, 0.658824, 0.407843, 0.635294 ); + transferFunction->AddRGBPoint( 8001.0, 0.290196, 0.509804, 0.709804 ); + transferFunction->AddRGBPoint( 8002.0, 0.94902, 0.945098, 0.941176 ); + transferFunction->AddRGBPoint( 8003.0, 0.807843, 0.254902, 0.305882 ); + transferFunction->AddRGBPoint( 8004.0, 0.470588, 0.0823529, 0.521569 ); + transferFunction->AddRGBPoint( 8005.0, 0.764706, 0.239216, 0.964706 ); + transferFunction->AddRGBPoint( 8006.0, 0.0117647, 0.576471, 0.0235294 ); + transferFunction->AddRGBPoint( 8007.0, 0.862745, 0.984314, 0.639216 ); + transferFunction->AddRGBPoint( 8008.0, 0.909804, 0.572549, 0.129412 ); + transferFunction->AddRGBPoint( 8009.0, 0.0156863, 0.447059, 0.054902 ); + transferFunction->AddRGBPoint( 8010.0, 0.47451, 0.721569, 0.862745 ); + transferFunction->AddRGBPoint( 8011.0, 0.921569, 0.0431373, 0.686275 ); + transferFunction->AddRGBPoint( 8012.0, 0.0470588, 0.180392, 0.980392 ); + transferFunction->AddRGBPoint( 8013.0, 0.796078, 0.713725, 0.560784 ); + transferFunction->AddRGBPoint( 8014.0, 0.164706, 0.8, 0.654902 ); + transferFunction->AddRGBPoint( 9000.0, 0.117647, 0.0196078, 0.117647 ); + transferFunction->AddRGBPoint( 9001.0, 0.117647, 0.392157, 0.176471 ); + transferFunction->AddRGBPoint( 9002.0, 0.509804, 0.392157, 0.647059 ); + transferFunction->AddRGBPoint( 9003.0, 0.411765, 0.0980392, 0.0196078 ); + transferFunction->AddRGBPoint( 9004.0, 0.490196, 0.27451, 0.215686 ); + transferFunction->AddRGBPoint( 9005.0, 0.882353, 0.0784314, 0.411765 ); + transferFunction->AddRGBPoint( 9006.0, 0.882353, 0.0784314, 0.0588235 ); + transferFunction->AddRGBPoint( 9500.0, 0.117647, 0.215686, 0.117647 ); + transferFunction->AddRGBPoint( 9501.0, 0.117647, 0.588235, 0.176471 ); + transferFunction->AddRGBPoint( 9502.0, 0.509804, 0.588235, 0.647059 ); + transferFunction->AddRGBPoint( 9503.0, 0.411765, 0.294118, 0.0196078 ); + transferFunction->AddRGBPoint( 9504.0, 0.490196, 0.470588, 0.215686 ); + transferFunction->AddRGBPoint( 9505.0, 0.882353, 0.27451, 0.411765 ); + transferFunction->AddRGBPoint( 9506.0, 0.882353, 0.27451, 0.0588235 ); + transferFunction->AddRGBPoint( 11101.0, 0.0901961, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 11102.0, 0.0901961, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 11103.0, 0.247059, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 11104.0, 0.247059, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 11105.0, 0.0509804, 0, 0.980392 ); + transferFunction->AddRGBPoint( 11106.0, 0.101961, 0.235294, 0 ); + transferFunction->AddRGBPoint( 11107.0, 0.101961, 0.235294, 0.294118 ); + transferFunction->AddRGBPoint( 11108.0, 0.101961, 0.235294, 0.588235 ); + transferFunction->AddRGBPoint( 11109.0, 0.0980392, 0.235294, 0.980392 ); + transferFunction->AddRGBPoint( 11110.0, 0.235294, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 11111.0, 0.705882, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 11112.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 11113.0, 0.54902, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 11114.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 11115.0, 0.54902, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 11116.0, 0.705882, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 11117.0, 0.0901961, 0.0392157, 0.0392157 ); + transferFunction->AddRGBPoint( 11118.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 11119.0, 0.705882, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 11120.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 11121.0, 0.235294, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 11122.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 11123.0, 0.254902, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 11124.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 11125.0, 0.0784314, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 11126.0, 0.392157, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 11127.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 11128.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 11129.0, 0.235294, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 11130.0, 0.0980392, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 11131.0, 0.0784314, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 11132.0, 0.235294, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 11133.0, 0.235294, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 11134.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 11135.0, 0.254902, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 11136.0, 0.0980392, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 11137.0, 0.862745, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 11138.0, 0.705882, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 11139.0, 0.239216, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 11140.0, 0.239216, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 11141.0, 0.239216, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 11142.0, 0.0980392, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 11143.0, 0.54902, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 11144.0, 0.862745, 0.705882, 0.0784314 ); + transferFunction->AddRGBPoint( 11145.0, 0.247059, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 11146.0, 0.866667, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 11147.0, 0.866667, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 11148.0, 0.866667, 0.235294, 0.54902 ); + transferFunction->AddRGBPoint( 11149.0, 0.866667, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 11150.0, 0.239216, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 11151.0, 0.392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 11152.0, 0.0392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 11153.0, 0.866667, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 11154.0, 0.552941, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 11155.0, 0.239216, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 11156.0, 0.552941, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 11157.0, 0.560784, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 11158.0, 0.396078, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 11159.0, 0.0823529, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 11160.0, 0.239216, 0.0784314, 0.705882 ); + transferFunction->AddRGBPoint( 11161.0, 0.866667, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 11162.0, 0.552941, 0.392157, 0.862745 ); + transferFunction->AddRGBPoint( 11163.0, 0.866667, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 11164.0, 0.709804, 0.784314, 0.0784314 ); + transferFunction->AddRGBPoint( 11165.0, 0.396078, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 11166.0, 0.396078, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 11167.0, 0.709804, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 11168.0, 0.0823529, 0.54902, 0.784314 ); + transferFunction->AddRGBPoint( 11169.0, 0.0823529, 0.0784314, 0.941176 ); + transferFunction->AddRGBPoint( 11170.0, 0.0823529, 0.0784314, 0.784314 ); + transferFunction->AddRGBPoint( 11171.0, 0.0823529, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 11172.0, 0.396078, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 11173.0, 0.0823529, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 11174.0, 0.87451, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 11175.0, 0.866667, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 12101.0, 0.0901961, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 12102.0, 0.0901961, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 12103.0, 0.247059, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 12104.0, 0.247059, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 12105.0, 0.0509804, 0, 0.980392 ); + transferFunction->AddRGBPoint( 12106.0, 0.101961, 0.235294, 0 ); + transferFunction->AddRGBPoint( 12107.0, 0.101961, 0.235294, 0.294118 ); + transferFunction->AddRGBPoint( 12108.0, 0.101961, 0.235294, 0.588235 ); + transferFunction->AddRGBPoint( 12109.0, 0.0980392, 0.235294, 0.980392 ); + transferFunction->AddRGBPoint( 12110.0, 0.235294, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 12111.0, 0.705882, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 12112.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 12113.0, 0.54902, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 12114.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 12115.0, 0.54902, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 12116.0, 0.705882, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 12117.0, 0.0901961, 0.0392157, 0.0392157 ); + transferFunction->AddRGBPoint( 12118.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 12119.0, 0.705882, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 12120.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 12121.0, 0.235294, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 12122.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 12123.0, 0.254902, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 12124.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 12125.0, 0.0784314, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 12126.0, 0.392157, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 12127.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 12128.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 12129.0, 0.235294, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 12130.0, 0.0980392, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 12131.0, 0.0784314, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 12132.0, 0.235294, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 12133.0, 0.235294, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 12134.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 12135.0, 0.254902, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 12136.0, 0.0980392, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 12137.0, 0.862745, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 12138.0, 0.705882, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 12139.0, 0.239216, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 12140.0, 0.239216, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 12141.0, 0.239216, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 12142.0, 0.0980392, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 12143.0, 0.54902, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 12144.0, 0.862745, 0.705882, 0.0784314 ); + transferFunction->AddRGBPoint( 12145.0, 0.247059, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 12146.0, 0.866667, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 12147.0, 0.866667, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 12148.0, 0.866667, 0.235294, 0.54902 ); + transferFunction->AddRGBPoint( 12149.0, 0.866667, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 12150.0, 0.239216, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 12151.0, 0.392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 12152.0, 0.0392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 12153.0, 0.866667, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 12154.0, 0.552941, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 12155.0, 0.239216, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 12156.0, 0.552941, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 12157.0, 0.560784, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 12158.0, 0.396078, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 12159.0, 0.0823529, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 12160.0, 0.239216, 0.0784314, 0.705882 ); + transferFunction->AddRGBPoint( 12161.0, 0.866667, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 12162.0, 0.552941, 0.392157, 0.862745 ); + transferFunction->AddRGBPoint( 12163.0, 0.866667, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 12164.0, 0.709804, 0.784314, 0.0784314 ); + transferFunction->AddRGBPoint( 12165.0, 0.396078, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 12166.0, 0.396078, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 12167.0, 0.709804, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 12168.0, 0.0823529, 0.54902, 0.784314 ); + transferFunction->AddRGBPoint( 12169.0, 0.0823529, 0.0784314, 0.941176 ); + transferFunction->AddRGBPoint( 12170.0, 0.0823529, 0.0784314, 0.784314 ); + transferFunction->AddRGBPoint( 12171.0, 0.0823529, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 12172.0, 0.396078, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 12173.0, 0.0823529, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 12174.0, 0.87451, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 12175.0, 0.866667, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 13101.0, 0.0901961, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 13102.0, 0.0901961, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 13103.0, 0.247059, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 13104.0, 0.247059, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 13105.0, 0.0509804, 0, 0.980392 ); + transferFunction->AddRGBPoint( 13106.0, 0.101961, 0.235294, 0 ); + transferFunction->AddRGBPoint( 13107.0, 0.101961, 0.235294, 0.294118 ); + transferFunction->AddRGBPoint( 13108.0, 0.101961, 0.235294, 0.588235 ); + transferFunction->AddRGBPoint( 13109.0, 0.0980392, 0.235294, 0.980392 ); + transferFunction->AddRGBPoint( 13110.0, 0.235294, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 13111.0, 0.705882, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 13112.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 13113.0, 0.54902, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 13114.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 13115.0, 0.54902, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 13116.0, 0.705882, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 13117.0, 0.0901961, 0.0392157, 0.0392157 ); + transferFunction->AddRGBPoint( 13118.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 13119.0, 0.705882, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 13120.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 13121.0, 0.235294, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 13122.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 13123.0, 0.254902, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 13124.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 13125.0, 0.0784314, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 13126.0, 0.392157, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 13127.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 13128.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 13129.0, 0.235294, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 13130.0, 0.0980392, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 13131.0, 0.0784314, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 13132.0, 0.235294, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 13133.0, 0.235294, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 13134.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 13135.0, 0.254902, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 13136.0, 0.0980392, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 13137.0, 0.862745, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 13138.0, 0.705882, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 13139.0, 0.239216, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 13140.0, 0.239216, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 13141.0, 0.239216, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 13142.0, 0.0980392, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 13143.0, 0.54902, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 13144.0, 0.862745, 0.705882, 0.0784314 ); + transferFunction->AddRGBPoint( 13145.0, 0.247059, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 13146.0, 0.866667, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 13147.0, 0.866667, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 13148.0, 0.866667, 0.235294, 0.54902 ); + transferFunction->AddRGBPoint( 13149.0, 0.866667, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 13150.0, 0.239216, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 13151.0, 0.392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 13152.0, 0.0392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 13153.0, 0.866667, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 13154.0, 0.552941, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 13155.0, 0.239216, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 13156.0, 0.552941, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 13157.0, 0.560784, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 13158.0, 0.396078, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 13159.0, 0.0823529, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 13160.0, 0.239216, 0.0784314, 0.705882 ); + transferFunction->AddRGBPoint( 13161.0, 0.866667, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 13162.0, 0.552941, 0.392157, 0.862745 ); + transferFunction->AddRGBPoint( 13163.0, 0.866667, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 13164.0, 0.709804, 0.784314, 0.0784314 ); + transferFunction->AddRGBPoint( 13165.0, 0.396078, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 13166.0, 0.396078, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 13167.0, 0.709804, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 13168.0, 0.0823529, 0.54902, 0.784314 ); + transferFunction->AddRGBPoint( 13169.0, 0.0823529, 0.0784314, 0.941176 ); + transferFunction->AddRGBPoint( 13170.0, 0.0823529, 0.0784314, 0.784314 ); + transferFunction->AddRGBPoint( 13171.0, 0.0823529, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 13172.0, 0.396078, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 13173.0, 0.0823529, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 13174.0, 0.87451, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 13175.0, 0.866667, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 14101.0, 0.0901961, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 14102.0, 0.0901961, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 14103.0, 0.247059, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 14104.0, 0.247059, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 14105.0, 0.0509804, 0, 0.980392 ); + transferFunction->AddRGBPoint( 14106.0, 0.101961, 0.235294, 0 ); + transferFunction->AddRGBPoint( 14107.0, 0.101961, 0.235294, 0.294118 ); + transferFunction->AddRGBPoint( 14108.0, 0.101961, 0.235294, 0.588235 ); + transferFunction->AddRGBPoint( 14109.0, 0.0980392, 0.235294, 0.980392 ); + transferFunction->AddRGBPoint( 14110.0, 0.235294, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 14111.0, 0.705882, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 14112.0, 0.862745, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 14113.0, 0.54902, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 14114.0, 0.705882, 0.862745, 0.54902 ); + transferFunction->AddRGBPoint( 14115.0, 0.54902, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 14116.0, 0.705882, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 14117.0, 0.0901961, 0.0392157, 0.0392157 ); + transferFunction->AddRGBPoint( 14118.0, 0.882353, 0.54902, 0.54902 ); + transferFunction->AddRGBPoint( 14119.0, 0.705882, 0.235294, 0.705882 ); + transferFunction->AddRGBPoint( 14120.0, 0.0784314, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 14121.0, 0.235294, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 14122.0, 0.862745, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 14123.0, 0.254902, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 14124.0, 0.862745, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 14125.0, 0.0784314, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 14126.0, 0.392157, 0.392157, 0.235294 ); + transferFunction->AddRGBPoint( 14127.0, 0.862745, 0.705882, 0.862745 ); + transferFunction->AddRGBPoint( 14128.0, 0.0784314, 0.705882, 0.54902 ); + transferFunction->AddRGBPoint( 14129.0, 0.235294, 0.54902, 0.705882 ); + transferFunction->AddRGBPoint( 14130.0, 0.0980392, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 14131.0, 0.0784314, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 14132.0, 0.235294, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 14133.0, 0.235294, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 14134.0, 0.862745, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 14135.0, 0.254902, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 14136.0, 0.0980392, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 14137.0, 0.862745, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 14138.0, 0.705882, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 14139.0, 0.239216, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 14140.0, 0.239216, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 14141.0, 0.239216, 0.235294, 0.392157 ); + transferFunction->AddRGBPoint( 14142.0, 0.0980392, 0.0980392, 0.0980392 ); + transferFunction->AddRGBPoint( 14143.0, 0.54902, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 14144.0, 0.862745, 0.705882, 0.0784314 ); + transferFunction->AddRGBPoint( 14145.0, 0.247059, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 14146.0, 0.866667, 0.0784314, 0.0392157 ); + transferFunction->AddRGBPoint( 14147.0, 0.866667, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 14148.0, 0.866667, 0.235294, 0.54902 ); + transferFunction->AddRGBPoint( 14149.0, 0.866667, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 14150.0, 0.239216, 0.862745, 0.862745 ); + transferFunction->AddRGBPoint( 14151.0, 0.392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 14152.0, 0.0392157, 0.784314, 0.784314 ); + transferFunction->AddRGBPoint( 14153.0, 0.866667, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 14154.0, 0.552941, 0.0784314, 0.392157 ); + transferFunction->AddRGBPoint( 14155.0, 0.239216, 0.862745, 0.392157 ); + transferFunction->AddRGBPoint( 14156.0, 0.552941, 0.235294, 0.0784314 ); + transferFunction->AddRGBPoint( 14157.0, 0.560784, 0.0784314, 0.862745 ); + transferFunction->AddRGBPoint( 14158.0, 0.396078, 0.235294, 0.862745 ); + transferFunction->AddRGBPoint( 14159.0, 0.0823529, 0.0784314, 0.54902 ); + transferFunction->AddRGBPoint( 14160.0, 0.239216, 0.0784314, 0.705882 ); + transferFunction->AddRGBPoint( 14161.0, 0.866667, 0.54902, 0.0784314 ); + transferFunction->AddRGBPoint( 14162.0, 0.552941, 0.392157, 0.862745 ); + transferFunction->AddRGBPoint( 14163.0, 0.866667, 0.392157, 0.0784314 ); + transferFunction->AddRGBPoint( 14164.0, 0.709804, 0.784314, 0.0784314 ); + transferFunction->AddRGBPoint( 14165.0, 0.396078, 0.0784314, 0.0784314 ); + transferFunction->AddRGBPoint( 14166.0, 0.396078, 0.392157, 0.705882 ); + transferFunction->AddRGBPoint( 14167.0, 0.709804, 0.862745, 0.0784314 ); + transferFunction->AddRGBPoint( 14168.0, 0.0823529, 0.54902, 0.784314 ); + transferFunction->AddRGBPoint( 14169.0, 0.0823529, 0.0784314, 0.941176 ); + transferFunction->AddRGBPoint( 14170.0, 0.0823529, 0.0784314, 0.784314 ); + transferFunction->AddRGBPoint( 14171.0, 0.0823529, 0.0784314, 0.235294 ); + transferFunction->AddRGBPoint( 14172.0, 0.396078, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 14173.0, 0.0823529, 0.705882, 0.705882 ); + transferFunction->AddRGBPoint( 14174.0, 0.87451, 0.862745, 0.235294 ); + transferFunction->AddRGBPoint( 14175.0, 0.866667, 0.235294, 0.235294 ); + transferFunction->AddRGBPoint( 0.0, 0.0, 0.0, 0.0 ); + transferFunction->AddRGBPoint( 256.0, 0.0, 0.0, 0.0 ); + transferFunction->AddRGBPoint( 1100.0, 0.0, 0.0, 0.0 ); + transferFunction->AddRGBPoint( 2100.0, 0.0, 0.0, 0.0 ); + transferFunction->AddRGBPoint( 3100.0, 0.0, 0.0, 0.0 ); + transferFunction->AddRGBPoint( 4100.0, 0.0, 0.0, 0.0 ); + transferFunction->AddRGBPoint( 11100.0, 0.0, 0.0, 0.0 ); + transferFunction->AddRGBPoint( 12100.0, 0.0, 0.0, 0.0 ); + transferFunction->AddRGBPoint( 13100.0, 0.0, 0.0, 0.0 ); + transferFunction->AddRGBPoint( 14100.0, 0.0, 0.0, 0.0 ); + return transferFunction; +} + +FreeSurferParcellationTranslator::NameTable FreeSurferParcellationTranslator::CreateNameTable() +{ + mitk::FreeSurferParcellationTranslator::NameTable nameTable; + nameTable["0"] = "Unknown"; + nameTable["1"] = "Left-Cerebral-Exterior"; + nameTable["2"] = "Left-Cerebral-White-Matter"; + nameTable["3"] = "Left-Cerebral-Cortex"; + nameTable["4"] = "Left-Lateral-Ventricle"; + nameTable["5"] = "Left-Inf-Lat-Vent"; + nameTable["6"] = "Left-Cerebellum-Exterior"; + nameTable["7"] = "Left-Cerebellum-White-Matter"; + nameTable["8"] = "Left-Cerebellum-Cortex"; + nameTable["9"] = "Left-Thalamus"; + nameTable["10"] = "Left-Thalamus-Proper"; + nameTable["11"] = "Left-Caudate"; + nameTable["12"] = "Left-Putamen"; + nameTable["13"] = "Left-Pallidum"; + nameTable["14"] = "3rd-Ventricle"; + nameTable["15"] = "4th-Ventricle"; + nameTable["16"] = "Brain-Stem"; + nameTable["17"] = "Left-Hippocampus"; + nameTable["18"] = "Left-Amygdala"; + nameTable["19"] = "Left-Insula"; + nameTable["20"] = "Left-Operculum"; + nameTable["21"] = "Line-1"; + nameTable["22"] = "Line-2"; + nameTable["23"] = "Line-3"; + nameTable["24"] = "CSF"; + nameTable["25"] = "Left-Lesion"; + nameTable["26"] = "Left-Accumbens-area"; + nameTable["27"] = "Left-Substancia-Nigra"; + nameTable["28"] = "Left-VentralDC"; + nameTable["29"] = "Left-undetermined"; + nameTable["30"] = "Left-vessel"; + nameTable["31"] = "Left-choroid-plexus"; + nameTable["32"] = "Left-F3orb"; + nameTable["33"] = "Left-lOg"; + nameTable["34"] = "Left-aOg"; + nameTable["35"] = "Left-mOg"; + nameTable["36"] = "Left-pOg"; + nameTable["37"] = "Left-Stellate"; + nameTable["38"] = "Left-Porg"; + nameTable["39"] = "Left-Aorg"; + nameTable["40"] = "Right-Cerebral-Exterior"; + nameTable["41"] = "Right-Cerebral-White-Matter"; + nameTable["42"] = "Right-Cerebral-Cortex"; + nameTable["43"] = "Right-Lateral-Ventricle"; + nameTable["44"] = "Right-Inf-Lat-Vent"; + nameTable["45"] = "Right-Cerebellum-Exterior"; + nameTable["46"] = "Right-Cerebellum-White-Matter"; + nameTable["47"] = "Right-Cerebellum-Cortex"; + nameTable["48"] = "Right-Thalamus"; + nameTable["49"] = "Right-Thalamus-Proper"; + nameTable["50"] = "Right-Caudate"; + nameTable["51"] = "Right-Putamen"; + nameTable["52"] = "Right-Pallidum"; + nameTable["53"] = "Right-Hippocampus"; + nameTable["54"] = "Right-Amygdala"; + nameTable["55"] = "Right-Insula"; + nameTable["56"] = "Right-Operculum"; + nameTable["57"] = "Right-Lesion"; + nameTable["58"] = "Right-Accumbens-area"; + nameTable["59"] = "Right-Substancia-Nigra"; + nameTable["60"] = "Right-VentralDC"; + nameTable["61"] = "Right-undetermined"; + nameTable["62"] = "Right-vessel"; + nameTable["63"] = "Right-choroid-plexus"; + nameTable["64"] = "Right-F3orb"; + nameTable["65"] = "Right-lOg"; + nameTable["66"] = "Right-aOg"; + nameTable["67"] = "Right-mOg"; + nameTable["68"] = "Right-pOg"; + nameTable["69"] = "Right-Stellate"; + nameTable["70"] = "Right-Porg"; + nameTable["71"] = "Right-Aorg"; + nameTable["72"] = "5th-Ventricle"; + nameTable["73"] = "Left-Interior"; + nameTable["74"] = "Right-Interior"; + nameTable["77"] = "WM-hypointensities"; + nameTable["78"] = "Left-WM-hypointensities"; + nameTable["79"] = "Right-WM-hypointensities"; + nameTable["80"] = "non-WM-hypointensities"; + nameTable["81"] = "Left-non-WM-hypointensities"; + nameTable["82"] = "Right-non-WM-hypointensities"; + nameTable["83"] = "Left-F1"; + nameTable["84"] = "Right-F1"; + nameTable["85"] = "Optic-Chiasm"; + nameTable["192"] = "Corpus_Callosum"; + nameTable["86"] = "Left_future_WMSA"; + nameTable["87"] = "Right_future_WMSA"; + nameTable["88"] = "future_WMSA"; + nameTable["96"] = "Left-Amygdala-Anterior"; + nameTable["97"] = "Right-Amygdala-Anterior"; + nameTable["98"] = "Dura"; + nameTable["100"] = "Left-wm-intensity-abnormality"; + nameTable["101"] = "Left-caudate-intensity-abnormality"; + nameTable["102"] = "Left-putamen-intensity-abnormality"; + nameTable["103"] = "Left-accumbens-intensity-abnormality"; + nameTable["104"] = "Left-pallidum-intensity-abnormality"; + nameTable["105"] = "Left-amygdala-intensity-abnormality"; + nameTable["106"] = "Left-hippocampus-intensity-abnormality"; + nameTable["107"] = "Left-thalamus-intensity-abnormality"; + nameTable["108"] = "Left-VDC-intensity-abnormality"; + nameTable["109"] = "Right-wm-intensity-abnormality"; + nameTable["110"] = "Right-caudate-intensity-abnormality"; + nameTable["111"] = "Right-putamen-intensity-abnormality"; + nameTable["112"] = "Right-accumbens-intensity-abnormality"; + nameTable["113"] = "Right-pallidum-intensity-abnormality"; + nameTable["114"] = "Right-amygdala-intensity-abnormality"; + nameTable["115"] = "Right-hippocampus-intensity-abnormality"; + nameTable["116"] = "Right-thalamus-intensity-abnormality"; + nameTable["117"] = "Right-VDC-intensity-abnormality"; + nameTable["118"] = "Epidermis"; + nameTable["119"] = "Conn-Tissue"; + nameTable["120"] = "SC-Fat-Muscle"; + nameTable["121"] = "Cranium"; + nameTable["122"] = "CSF-SA"; + nameTable["123"] = "Muscle"; + nameTable["124"] = "Ear"; + nameTable["125"] = "Adipose"; + nameTable["126"] = "Spinal-Cord"; + nameTable["127"] = "Soft-Tissue"; + nameTable["128"] = "Nerve"; + nameTable["129"] = "Bone"; + nameTable["130"] = "Air"; + nameTable["131"] = "Orbital-Fat"; + nameTable["132"] = "Tongue"; + nameTable["133"] = "Nasal-Structures"; + nameTable["134"] = "Globe"; + nameTable["135"] = "Teeth"; + nameTable["136"] = "Left-Caudate-Putamen"; + nameTable["137"] = "Right-Caudate-Putamen"; + nameTable["138"] = "Left-Claustrum"; + nameTable["139"] = "Right-Claustrum"; + nameTable["140"] = "Cornea"; + nameTable["142"] = "Diploe"; + nameTable["143"] = "Vitreous-Humor"; + nameTable["144"] = "Lens"; + nameTable["145"] = "Aqueous-Humor"; + nameTable["146"] = "Outer-Table"; + nameTable["147"] = "Inner-Table"; + nameTable["148"] = "Periosteum"; + nameTable["149"] = "Endosteum"; + nameTable["150"] = "R-C-S"; + nameTable["151"] = "Iris"; + nameTable["152"] = "SC-Adipose-Muscle"; + nameTable["153"] = "SC-Tissue"; + nameTable["154"] = "Orbital-Adipose"; + nameTable["155"] = "Left-IntCapsule-Ant"; + nameTable["156"] = "Right-IntCapsule-Ant"; + nameTable["157"] = "Left-IntCapsule-Pos"; + nameTable["158"] = "Right-IntCapsule-Pos"; + nameTable["159"] = "Left-Cerebral-WM-unmyelinated"; + nameTable["160"] = "Right-Cerebral-WM-unmyelinated"; + nameTable["161"] = "Left-Cerebral-WM-myelinated"; + nameTable["162"] = "Right-Cerebral-WM-myelinated"; + nameTable["163"] = "Left-Subcortical-Gray-Matter"; + nameTable["164"] = "Right-Subcortical-Gray-Matter"; + nameTable["165"] = "Skull"; + nameTable["166"] = "Posterior-fossa"; + nameTable["167"] = "Scalp"; + nameTable["168"] = "Hematoma"; + nameTable["169"] = "Left-Basal-Ganglia"; + nameTable["176"] = "Right-Basal-Ganglia"; + nameTable["170"] = "brainstem"; + nameTable["171"] = "DCG"; + nameTable["172"] = "Vermis"; + nameTable["173"] = "Midbrain"; + nameTable["174"] = "Pons"; + nameTable["175"] = "Medulla"; + nameTable["180"] = "Left-Cortical-Dysplasia"; + nameTable["181"] = "Right-Cortical-Dysplasia"; + nameTable["193"] = "Left-hippocampal_fissure"; + nameTable["194"] = "Left-CADG-head"; + nameTable["195"] = "Left-subiculum"; + nameTable["196"] = "Left-fimbria"; + nameTable["197"] = "Right-hippocampal_fissure"; + nameTable["198"] = "Right-CADG-head"; + nameTable["199"] = "Right-subiculum"; + nameTable["200"] = "Right-fimbria"; + nameTable["201"] = "alveus"; + nameTable["202"] = "perforant_pathway"; + nameTable["203"] = "parasubiculum"; + nameTable["204"] = "presubiculum"; + nameTable["205"] = "subiculum"; + nameTable["206"] = "CA1"; + nameTable["207"] = "CA2"; + nameTable["208"] = "CA3"; + nameTable["209"] = "CA4"; + nameTable["210"] = "GC-ML-DG"; + nameTable["211"] = "HATA"; + nameTable["212"] = "fimbria"; + nameTable["213"] = "lateral_ventricle"; + nameTable["214"] = "molecular_layer_HP"; + nameTable["215"] = "hippocampal_fissure"; + nameTable["216"] = "entorhinal_cortex"; + nameTable["217"] = "molecular_layer_subiculum"; + nameTable["218"] = "Amygdala"; + nameTable["219"] = "Cerebral_White_Matter"; + nameTable["220"] = "Cerebral_Cortex"; + nameTable["221"] = "Inf_Lat_Vent"; + nameTable["222"] = "Perirhinal"; + nameTable["223"] = "Cerebral_White_Matter_Edge"; + nameTable["224"] = "Background"; + nameTable["225"] = "Ectorhinal"; + nameTable["226"] = "HP_tail"; + nameTable["250"] = "Fornix"; + nameTable["251"] = "CC_Posterior"; + nameTable["252"] = "CC_Mid_Posterior"; + nameTable["253"] = "CC_Central"; + nameTable["254"] = "CC_Mid_Anterior"; + nameTable["255"] = "CC_Anterior"; + nameTable["256"] = "Voxel-Unchanged"; + nameTable["331"] = "Aorta"; + nameTable["332"] = "Left-Common-IliacA"; + nameTable["333"] = "Right-Common-IliacA"; + nameTable["334"] = "Left-External-IliacA"; + nameTable["335"] = "Right-External-IliacA"; + nameTable["336"] = "Left-Internal-IliacA"; + nameTable["337"] = "Right-Internal-IliacA"; + nameTable["338"] = "Left-Lateral-SacralA"; + nameTable["339"] = "Right-Lateral-SacralA"; + nameTable["340"] = "Left-ObturatorA"; + nameTable["341"] = "Right-ObturatorA"; + nameTable["342"] = "Left-Internal-PudendalA"; + nameTable["343"] = "Right-Internal-PudendalA"; + nameTable["344"] = "Left-UmbilicalA"; + nameTable["345"] = "Right-UmbilicalA"; + nameTable["346"] = "Left-Inf-RectalA"; + nameTable["347"] = "Right-Inf-RectalA"; + nameTable["348"] = "Left-Common-IliacV"; + nameTable["349"] = "Right-Common-IliacV"; + nameTable["350"] = "Left-External-IliacV"; + nameTable["351"] = "Right-External-IliacV"; + nameTable["352"] = "Left-Internal-IliacV"; + nameTable["353"] = "Right-Internal-IliacV"; + nameTable["354"] = "Left-ObturatorV"; + nameTable["355"] = "Right-ObturatorV"; + nameTable["356"] = "Left-Internal-PudendalV"; + nameTable["357"] = "Right-Internal-PudendalV"; + nameTable["358"] = "Pos-Lymph"; + nameTable["359"] = "Neg-Lymph"; + nameTable["400"] = "V1"; + nameTable["401"] = "V2"; + nameTable["402"] = "BA44"; + nameTable["403"] = "BA45"; + nameTable["404"] = "BA4a"; + nameTable["405"] = "BA4p"; + nameTable["406"] = "BA6"; + nameTable["407"] = "BA2"; + nameTable["408"] = "BA1_old"; + nameTable["409"] = "BAun2"; + nameTable["410"] = "BA1"; + nameTable["411"] = "BA2b"; + nameTable["412"] = "BA3a"; + nameTable["413"] = "BA3b"; + nameTable["414"] = "MT"; + nameTable["415"] = "AIPS_AIP_l"; + nameTable["416"] = "AIPS_AIP_r"; + nameTable["417"] = "AIPS_VIP_l"; + nameTable["418"] = "AIPS_VIP_r"; + nameTable["419"] = "IPL_PFcm_l"; + nameTable["420"] = "IPL_PFcm_r"; + nameTable["421"] = "IPL_PF_l"; + nameTable["422"] = "IPL_PFm_l"; + nameTable["423"] = "IPL_PFm_r"; + nameTable["424"] = "IPL_PFop_l"; + nameTable["425"] = "IPL_PFop_r"; + nameTable["426"] = "IPL_PF_r"; + nameTable["427"] = "IPL_PFt_l"; + nameTable["428"] = "IPL_PFt_r"; + nameTable["429"] = "IPL_PGa_l"; + nameTable["430"] = "IPL_PGa_r"; + nameTable["431"] = "IPL_PGp_l"; + nameTable["432"] = "IPL_PGp_r"; + nameTable["433"] = "Visual_V3d_l"; + nameTable["434"] = "Visual_V3d_r"; + nameTable["435"] = "Visual_V4_l"; + nameTable["436"] = "Visual_V4_r"; + nameTable["437"] = "Visual_V5_b"; + nameTable["438"] = "Visual_VP_l"; + nameTable["439"] = "Visual_VP_r"; + nameTable["498"] = "wmsa"; + nameTable["499"] = "other_wmsa"; + nameTable["500"] = "right_CA2_3"; + nameTable["501"] = "right_alveus"; + nameTable["502"] = "right_CA1"; + nameTable["503"] = "right_fimbria"; + nameTable["504"] = "right_presubiculum"; + nameTable["505"] = "right_hippocampal_fissure"; + nameTable["506"] = "right_CA4_DG"; + nameTable["507"] = "right_subiculum"; + nameTable["508"] = "right_fornix"; + nameTable["550"] = "left_CA2_3"; + nameTable["551"] = "left_alveus"; + nameTable["552"] = "left_CA1"; + nameTable["553"] = "left_fimbria"; + nameTable["554"] = "left_presubiculum"; + nameTable["555"] = "left_hippocampal_fissure"; + nameTable["556"] = "left_CA4_DG"; + nameTable["557"] = "left_subiculum"; + nameTable["558"] = "left_fornix"; + nameTable["600"] = "Tumor"; + nameTable["601"] = "Cbm_Left_I_IV"; + nameTable["602"] = "Cbm_Right_I_IV"; + nameTable["603"] = "Cbm_Left_V"; + nameTable["604"] = "Cbm_Right_V"; + nameTable["605"] = "Cbm_Left_VI"; + nameTable["606"] = "Cbm_Vermis_VI"; + nameTable["607"] = "Cbm_Right_VI"; + nameTable["608"] = "Cbm_Left_CrusI"; + nameTable["609"] = "Cbm_Vermis_CrusI"; + nameTable["610"] = "Cbm_Right_CrusI"; + nameTable["611"] = "Cbm_Left_CrusII"; + nameTable["612"] = "Cbm_Vermis_CrusII"; + nameTable["613"] = "Cbm_Right_CrusII"; + nameTable["614"] = "Cbm_Left_VIIb"; + nameTable["615"] = "Cbm_Vermis_VIIb"; + nameTable["616"] = "Cbm_Right_VIIb"; + nameTable["617"] = "Cbm_Left_VIIIa"; + nameTable["618"] = "Cbm_Vermis_VIIIa"; + nameTable["619"] = "Cbm_Right_VIIIa"; + nameTable["620"] = "Cbm_Left_VIIIb"; + nameTable["621"] = "Cbm_Vermis_VIIIb"; + nameTable["622"] = "Cbm_Right_VIIIb"; + nameTable["623"] = "Cbm_Left_IX"; + nameTable["624"] = "Cbm_Vermis_IX"; + nameTable["625"] = "Cbm_Right_IX"; + nameTable["626"] = "Cbm_Left_X"; + nameTable["627"] = "Cbm_Vermis_X"; + nameTable["628"] = "Cbm_Right_X"; + nameTable["640"] = "Cbm_Right_I_V_med"; + nameTable["641"] = "Cbm_Right_I_V_mid"; + nameTable["642"] = "Cbm_Right_VI_med"; + nameTable["643"] = "Cbm_Right_VI_mid"; + nameTable["644"] = "Cbm_Right_VI_lat"; + nameTable["645"] = "Cbm_Right_CrusI_med"; + nameTable["646"] = "Cbm_Right_CrusI_mid"; + nameTable["647"] = "Cbm_Right_CrusI_lat"; + nameTable["648"] = "Cbm_Right_CrusII_med"; + nameTable["649"] = "Cbm_Right_CrusII_mid"; + nameTable["650"] = "Cbm_Right_CrusII_lat"; + nameTable["651"] = "Cbm_Right_7med"; + nameTable["652"] = "Cbm_Right_7mid"; + nameTable["653"] = "Cbm_Right_7lat"; + nameTable["654"] = "Cbm_Right_8med"; + nameTable["655"] = "Cbm_Right_8mid"; + nameTable["656"] = "Cbm_Right_8lat"; + nameTable["657"] = "Cbm_Right_PUNs"; + nameTable["658"] = "Cbm_Right_TONs"; + nameTable["659"] = "Cbm_Right_FLOs"; + nameTable["660"] = "Cbm_Left_I_V_med"; + nameTable["661"] = "Cbm_Left_I_V_mid"; + nameTable["662"] = "Cbm_Left_VI_med"; + nameTable["663"] = "Cbm_Left_VI_mid"; + nameTable["664"] = "Cbm_Left_VI_lat"; + nameTable["665"] = "Cbm_Left_CrusI_med"; + nameTable["666"] = "Cbm_Left_CrusI_mid"; + nameTable["667"] = "Cbm_Left_CrusI_lat"; + nameTable["668"] = "Cbm_Left_CrusII_med"; + nameTable["669"] = "Cbm_Left_CrusII_mid"; + nameTable["670"] = "Cbm_Left_CrusII_lat"; + nameTable["671"] = "Cbm_Left_7med"; + nameTable["672"] = "Cbm_Left_7mid"; + nameTable["673"] = "Cbm_Left_7lat"; + nameTable["674"] = "Cbm_Left_8med"; + nameTable["675"] = "Cbm_Left_8mid"; + nameTable["676"] = "Cbm_Left_8lat"; + nameTable["677"] = "Cbm_Left_PUNs"; + nameTable["678"] = "Cbm_Left_TONs"; + nameTable["679"] = "Cbm_Left_FLOs"; + nameTable["701"] = "CSF-FSL-FAST"; + nameTable["702"] = "GrayMatter-FSL-FAST"; + nameTable["703"] = "WhiteMatter-FSL-FAST"; + nameTable["999"] = "SUSPICIOUS"; + nameTable["1000"] = "ctx-lh-unknown"; + nameTable["1001"] = "ctx-lh-bankssts"; + nameTable["1002"] = "ctx-lh-caudalanteriorcingulate"; + nameTable["1003"] = "ctx-lh-caudalmiddlefrontal"; + nameTable["1004"] = "ctx-lh-corpuscallosum"; + nameTable["1005"] = "ctx-lh-cuneus"; + nameTable["1006"] = "ctx-lh-entorhinal"; + nameTable["1007"] = "ctx-lh-fusiform"; + nameTable["1008"] = "ctx-lh-inferiorparietal"; + nameTable["1009"] = "ctx-lh-inferiortemporal"; + nameTable["1010"] = "ctx-lh-isthmuscingulate"; + nameTable["1011"] = "ctx-lh-lateraloccipital"; + nameTable["1012"] = "ctx-lh-lateralorbitofrontal"; + nameTable["1013"] = "ctx-lh-lingual"; + nameTable["1014"] = "ctx-lh-medialorbitofrontal"; + nameTable["1015"] = "ctx-lh-middletemporal"; + nameTable["1016"] = "ctx-lh-parahippocampal"; + nameTable["1017"] = "ctx-lh-paracentral"; + nameTable["1018"] = "ctx-lh-parsopercularis"; + nameTable["1019"] = "ctx-lh-parsorbitalis"; + nameTable["1020"] = "ctx-lh-parstriangularis"; + nameTable["1021"] = "ctx-lh-pericalcarine"; + nameTable["1022"] = "ctx-lh-postcentral"; + nameTable["1023"] = "ctx-lh-posteriorcingulate"; + nameTable["1024"] = "ctx-lh-precentral"; + nameTable["1025"] = "ctx-lh-precuneus"; + nameTable["1026"] = "ctx-lh-rostralanteriorcingulate"; + nameTable["1027"] = "ctx-lh-rostralmiddlefrontal"; + nameTable["1028"] = "ctx-lh-superiorfrontal"; + nameTable["1029"] = "ctx-lh-superiorparietal"; + nameTable["1030"] = "ctx-lh-superiortemporal"; + nameTable["1031"] = "ctx-lh-supramarginal"; + nameTable["1032"] = "ctx-lh-frontalpole"; + nameTable["1033"] = "ctx-lh-temporalpole"; + nameTable["1034"] = "ctx-lh-transversetemporal"; + nameTable["1035"] = "ctx-lh-insula"; + nameTable["2000"] = "ctx-rh-unknown"; + nameTable["2001"] = "ctx-rh-bankssts"; + nameTable["2002"] = "ctx-rh-caudalanteriorcingulate"; + nameTable["2003"] = "ctx-rh-caudalmiddlefrontal"; + nameTable["2004"] = "ctx-rh-corpuscallosum"; + nameTable["2005"] = "ctx-rh-cuneus"; + nameTable["2006"] = "ctx-rh-entorhinal"; + nameTable["2007"] = "ctx-rh-fusiform"; + nameTable["2008"] = "ctx-rh-inferiorparietal"; + nameTable["2009"] = "ctx-rh-inferiortemporal"; + nameTable["2010"] = "ctx-rh-isthmuscingulate"; + nameTable["2011"] = "ctx-rh-lateraloccipital"; + nameTable["2012"] = "ctx-rh-lateralorbitofrontal"; + nameTable["2013"] = "ctx-rh-lingual"; + nameTable["2014"] = "ctx-rh-medialorbitofrontal"; + nameTable["2015"] = "ctx-rh-middletemporal"; + nameTable["2016"] = "ctx-rh-parahippocampal"; + nameTable["2017"] = "ctx-rh-paracentral"; + nameTable["2018"] = "ctx-rh-parsopercularis"; + nameTable["2019"] = "ctx-rh-parsorbitalis"; + nameTable["2020"] = "ctx-rh-parstriangularis"; + nameTable["2021"] = "ctx-rh-pericalcarine"; + nameTable["2022"] = "ctx-rh-postcentral"; + nameTable["2023"] = "ctx-rh-posteriorcingulate"; + nameTable["2024"] = "ctx-rh-precentral"; + nameTable["2025"] = "ctx-rh-precuneus"; + nameTable["2026"] = "ctx-rh-rostralanteriorcingulate"; + nameTable["2027"] = "ctx-rh-rostralmiddlefrontal"; + nameTable["2028"] = "ctx-rh-superiorfrontal"; + nameTable["2029"] = "ctx-rh-superiorparietal"; + nameTable["2030"] = "ctx-rh-superiortemporal"; + nameTable["2031"] = "ctx-rh-supramarginal"; + nameTable["2032"] = "ctx-rh-frontalpole"; + nameTable["2033"] = "ctx-rh-temporalpole"; + nameTable["2034"] = "ctx-rh-transversetemporal"; + nameTable["2035"] = "ctx-rh-insula"; + nameTable["3000"] = "wm-lh-unknown"; + nameTable["3001"] = "wm-lh-bankssts"; + nameTable["3002"] = "wm-lh-caudalanteriorcingulate"; + nameTable["3003"] = "wm-lh-caudalmiddlefrontal"; + nameTable["3004"] = "wm-lh-corpuscallosum"; + nameTable["3005"] = "wm-lh-cuneus"; + nameTable["3006"] = "wm-lh-entorhinal"; + nameTable["3007"] = "wm-lh-fusiform"; + nameTable["3008"] = "wm-lh-inferiorparietal"; + nameTable["3009"] = "wm-lh-inferiortemporal"; + nameTable["3010"] = "wm-lh-isthmuscingulate"; + nameTable["3011"] = "wm-lh-lateraloccipital"; + nameTable["3012"] = "wm-lh-lateralorbitofrontal"; + nameTable["3013"] = "wm-lh-lingual"; + nameTable["3014"] = "wm-lh-medialorbitofrontal"; + nameTable["3015"] = "wm-lh-middletemporal"; + nameTable["3016"] = "wm-lh-parahippocampal"; + nameTable["3017"] = "wm-lh-paracentral"; + nameTable["3018"] = "wm-lh-parsopercularis"; + nameTable["3019"] = "wm-lh-parsorbitalis"; + nameTable["3020"] = "wm-lh-parstriangularis"; + nameTable["3021"] = "wm-lh-pericalcarine"; + nameTable["3022"] = "wm-lh-postcentral"; + nameTable["3023"] = "wm-lh-posteriorcingulate"; + nameTable["3024"] = "wm-lh-precentral"; + nameTable["3025"] = "wm-lh-precuneus"; + nameTable["3026"] = "wm-lh-rostralanteriorcingulate"; + nameTable["3027"] = "wm-lh-rostralmiddlefrontal"; + nameTable["3028"] = "wm-lh-superiorfrontal"; + nameTable["3029"] = "wm-lh-superiorparietal"; + nameTable["3030"] = "wm-lh-superiortemporal"; + nameTable["3031"] = "wm-lh-supramarginal"; + nameTable["3032"] = "wm-lh-frontalpole"; + nameTable["3033"] = "wm-lh-temporalpole"; + nameTable["3034"] = "wm-lh-transversetemporal"; + nameTable["3035"] = "wm-lh-insula"; + nameTable["4000"] = "wm-rh-unknown"; + nameTable["4001"] = "wm-rh-bankssts"; + nameTable["4002"] = "wm-rh-caudalanteriorcingulate"; + nameTable["4003"] = "wm-rh-caudalmiddlefrontal"; + nameTable["4004"] = "wm-rh-corpuscallosum"; + nameTable["4005"] = "wm-rh-cuneus"; + nameTable["4006"] = "wm-rh-entorhinal"; + nameTable["4007"] = "wm-rh-fusiform"; + nameTable["4008"] = "wm-rh-inferiorparietal"; + nameTable["4009"] = "wm-rh-inferiortemporal"; + nameTable["4010"] = "wm-rh-isthmuscingulate"; + nameTable["4011"] = "wm-rh-lateraloccipital"; + nameTable["4012"] = "wm-rh-lateralorbitofrontal"; + nameTable["4013"] = "wm-rh-lingual"; + nameTable["4014"] = "wm-rh-medialorbitofrontal"; + nameTable["4015"] = "wm-rh-middletemporal"; + nameTable["4016"] = "wm-rh-parahippocampal"; + nameTable["4017"] = "wm-rh-paracentral"; + nameTable["4018"] = "wm-rh-parsopercularis"; + nameTable["4019"] = "wm-rh-parsorbitalis"; + nameTable["4020"] = "wm-rh-parstriangularis"; + nameTable["4021"] = "wm-rh-pericalcarine"; + nameTable["4022"] = "wm-rh-postcentral"; + nameTable["4023"] = "wm-rh-posteriorcingulate"; + nameTable["4024"] = "wm-rh-precentral"; + nameTable["4025"] = "wm-rh-precuneus"; + nameTable["4026"] = "wm-rh-rostralanteriorcingulate"; + nameTable["4027"] = "wm-rh-rostralmiddlefrontal"; + nameTable["4028"] = "wm-rh-superiorfrontal"; + nameTable["4029"] = "wm-rh-superiorparietal"; + nameTable["4030"] = "wm-rh-superiortemporal"; + nameTable["4031"] = "wm-rh-supramarginal"; + nameTable["4032"] = "wm-rh-frontalpole"; + nameTable["4033"] = "wm-rh-temporalpole"; + nameTable["4034"] = "wm-rh-transversetemporal"; + nameTable["4035"] = "wm-rh-insula"; + nameTable["1100"] = "ctx-lh-Unknown"; + nameTable["1101"] = "ctx-lh-Corpus_callosum"; + nameTable["1102"] = "ctx-lh-G_and_S_Insula_ONLY_AVERAGE"; + nameTable["1103"] = "ctx-lh-G_cingulate-Isthmus"; + nameTable["1104"] = "ctx-lh-G_cingulate-Main_part"; + nameTable["1200"] = "ctx-lh-G_cingulate-caudal_ACC"; + nameTable["1201"] = "ctx-lh-G_cingulate-rostral_ACC"; + nameTable["1202"] = "ctx-lh-G_cingulate-posterior"; + nameTable["1205"] = "ctx-lh-S_cingulate-caudal_ACC"; + nameTable["1206"] = "ctx-lh-S_cingulate-rostral_ACC"; + nameTable["1207"] = "ctx-lh-S_cingulate-posterior"; + nameTable["1210"] = "ctx-lh-S_pericallosal-caudal"; + nameTable["1211"] = "ctx-lh-S_pericallosal-rostral"; + nameTable["1212"] = "ctx-lh-S_pericallosal-posterior"; + nameTable["1105"] = "ctx-lh-G_cuneus"; + nameTable["1106"] = "ctx-lh-G_frontal_inf-Opercular_part"; + nameTable["1107"] = "ctx-lh-G_frontal_inf-Orbital_part"; + nameTable["1108"] = "ctx-lh-G_frontal_inf-Triangular_part"; + nameTable["1109"] = "ctx-lh-G_frontal_middle"; + nameTable["1110"] = "ctx-lh-G_frontal_superior"; + nameTable["1111"] = "ctx-lh-G_frontomarginal"; + nameTable["1112"] = "ctx-lh-G_insular_long"; + nameTable["1113"] = "ctx-lh-G_insular_short"; + nameTable["1114"] = "ctx-lh-G_and_S_occipital_inferior"; + nameTable["1115"] = "ctx-lh-G_occipital_middle"; + nameTable["1116"] = "ctx-lh-G_occipital_superior"; + nameTable["1117"] = "ctx-lh-G_occipit-temp_lat-Or_fusiform"; + nameTable["1118"] = "ctx-lh-G_occipit-temp_med-Lingual_part"; + nameTable["1119"] = "ctx-lh-G_occipit-temp_med-Parahippocampal_part"; + nameTable["1120"] = "ctx-lh-G_orbital"; + nameTable["1121"] = "ctx-lh-G_paracentral"; + nameTable["1122"] = "ctx-lh-G_parietal_inferior-Angular_part"; + nameTable["1123"] = "ctx-lh-G_parietal_inferior-Supramarginal_part"; + nameTable["1124"] = "ctx-lh-G_parietal_superior"; + nameTable["1125"] = "ctx-lh-G_postcentral"; + nameTable["1126"] = "ctx-lh-G_precentral"; + nameTable["1127"] = "ctx-lh-G_precuneus"; + nameTable["1128"] = "ctx-lh-G_rectus"; + nameTable["1129"] = "ctx-lh-G_subcallosal"; + nameTable["1130"] = "ctx-lh-G_subcentral"; + nameTable["1131"] = "ctx-lh-G_temporal_inferior"; + nameTable["1132"] = "ctx-lh-G_temporal_middle"; + nameTable["1133"] = "ctx-lh-G_temp_sup-G_temp_transv_and_interm_S"; + nameTable["1134"] = "ctx-lh-G_temp_sup-Lateral_aspect"; + nameTable["1135"] = "ctx-lh-G_temp_sup-Planum_polare"; + nameTable["1136"] = "ctx-lh-G_temp_sup-Planum_tempolare"; + nameTable["1137"] = "ctx-lh-G_and_S_transverse_frontopolar"; + nameTable["1138"] = "ctx-lh-Lat_Fissure-ant_sgt-ramus_horizontal"; + nameTable["1139"] = "ctx-lh-Lat_Fissure-ant_sgt-ramus_vertical"; + nameTable["1140"] = "ctx-lh-Lat_Fissure-post_sgt"; + nameTable["1141"] = "ctx-lh-Medial_wall"; + nameTable["1142"] = "ctx-lh-Pole_occipital"; + nameTable["1143"] = "ctx-lh-Pole_temporal"; + nameTable["1144"] = "ctx-lh-S_calcarine"; + nameTable["1145"] = "ctx-lh-S_central"; + nameTable["1146"] = "ctx-lh-S_central_insula"; + nameTable["1147"] = "ctx-lh-S_cingulate-Main_part_and_Intracingulate"; + nameTable["1148"] = "ctx-lh-S_cingulate-Marginalis_part"; + nameTable["1149"] = "ctx-lh-S_circular_insula_anterior"; + nameTable["1150"] = "ctx-lh-S_circular_insula_inferior"; + nameTable["1151"] = "ctx-lh-S_circular_insula_superior"; + nameTable["1152"] = "ctx-lh-S_collateral_transverse_ant"; + nameTable["1153"] = "ctx-lh-S_collateral_transverse_post"; + nameTable["1154"] = "ctx-lh-S_frontal_inferior"; + nameTable["1155"] = "ctx-lh-S_frontal_middle"; + nameTable["1156"] = "ctx-lh-S_frontal_superior"; + nameTable["1157"] = "ctx-lh-S_frontomarginal"; + nameTable["1158"] = "ctx-lh-S_intermedius_primus-Jensen"; + nameTable["1159"] = "ctx-lh-S_intraparietal-and_Parietal_transverse"; + nameTable["1160"] = "ctx-lh-S_occipital_anterior"; + nameTable["1161"] = "ctx-lh-S_occipital_middle_and_Lunatus"; + nameTable["1162"] = "ctx-lh-S_occipital_superior_and_transversalis"; + nameTable["1163"] = "ctx-lh-S_occipito-temporal_lateral"; + nameTable["1164"] = "ctx-lh-S_occipito-temporal_medial_and_S_Lingual"; + nameTable["1165"] = "ctx-lh-S_orbital-H_shapped"; + nameTable["1166"] = "ctx-lh-S_orbital_lateral"; + nameTable["1167"] = "ctx-lh-S_orbital_medial-Or_olfactory"; + nameTable["1168"] = "ctx-lh-S_paracentral"; + nameTable["1169"] = "ctx-lh-S_parieto_occipital"; + nameTable["1170"] = "ctx-lh-S_pericallosal"; + nameTable["1171"] = "ctx-lh-S_postcentral"; + nameTable["1172"] = "ctx-lh-S_precentral-Inferior-part"; + nameTable["1173"] = "ctx-lh-S_precentral-Superior-part"; + nameTable["1174"] = "ctx-lh-S_subcentral_ant"; + nameTable["1175"] = "ctx-lh-S_subcentral_post"; + nameTable["1176"] = "ctx-lh-S_suborbital"; + nameTable["1177"] = "ctx-lh-S_subparietal"; + nameTable["1178"] = "ctx-lh-S_supracingulate"; + nameTable["1179"] = "ctx-lh-S_temporal_inferior"; + nameTable["1180"] = "ctx-lh-S_temporal_superior"; + nameTable["1181"] = "ctx-lh-S_temporal_transverse"; + nameTable["2100"] = "ctx-rh-Unknown"; + nameTable["2101"] = "ctx-rh-Corpus_callosum"; + nameTable["2102"] = "ctx-rh-G_and_S_Insula_ONLY_AVERAGE"; + nameTable["2103"] = "ctx-rh-G_cingulate-Isthmus"; + nameTable["2104"] = "ctx-rh-G_cingulate-Main_part"; + nameTable["2105"] = "ctx-rh-G_cuneus"; + nameTable["2106"] = "ctx-rh-G_frontal_inf-Opercular_part"; + nameTable["2107"] = "ctx-rh-G_frontal_inf-Orbital_part"; + nameTable["2108"] = "ctx-rh-G_frontal_inf-Triangular_part"; + nameTable["2109"] = "ctx-rh-G_frontal_middle"; + nameTable["2110"] = "ctx-rh-G_frontal_superior"; + nameTable["2111"] = "ctx-rh-G_frontomarginal"; + nameTable["2112"] = "ctx-rh-G_insular_long"; + nameTable["2113"] = "ctx-rh-G_insular_short"; + nameTable["2114"] = "ctx-rh-G_and_S_occipital_inferior"; + nameTable["2115"] = "ctx-rh-G_occipital_middle"; + nameTable["2116"] = "ctx-rh-G_occipital_superior"; + nameTable["2117"] = "ctx-rh-G_occipit-temp_lat-Or_fusiform"; + nameTable["2118"] = "ctx-rh-G_occipit-temp_med-Lingual_part"; + nameTable["2119"] = "ctx-rh-G_occipit-temp_med-Parahippocampal_part"; + nameTable["2120"] = "ctx-rh-G_orbital"; + nameTable["2121"] = "ctx-rh-G_paracentral"; + nameTable["2122"] = "ctx-rh-G_parietal_inferior-Angular_part"; + nameTable["2123"] = "ctx-rh-G_parietal_inferior-Supramarginal_part"; + nameTable["2124"] = "ctx-rh-G_parietal_superior"; + nameTable["2125"] = "ctx-rh-G_postcentral"; + nameTable["2126"] = "ctx-rh-G_precentral"; + nameTable["2127"] = "ctx-rh-G_precuneus"; + nameTable["2128"] = "ctx-rh-G_rectus"; + nameTable["2129"] = "ctx-rh-G_subcallosal"; + nameTable["2130"] = "ctx-rh-G_subcentral"; + nameTable["2131"] = "ctx-rh-G_temporal_inferior"; + nameTable["2132"] = "ctx-rh-G_temporal_middle"; + nameTable["2133"] = "ctx-rh-G_temp_sup-G_temp_transv_and_interm_S"; + nameTable["2134"] = "ctx-rh-G_temp_sup-Lateral_aspect"; + nameTable["2135"] = "ctx-rh-G_temp_sup-Planum_polare"; + nameTable["2136"] = "ctx-rh-G_temp_sup-Planum_tempolare"; + nameTable["2137"] = "ctx-rh-G_and_S_transverse_frontopolar"; + nameTable["2138"] = "ctx-rh-Lat_Fissure-ant_sgt-ramus_horizontal"; + nameTable["2139"] = "ctx-rh-Lat_Fissure-ant_sgt-ramus_vertical"; + nameTable["2140"] = "ctx-rh-Lat_Fissure-post_sgt"; + nameTable["2141"] = "ctx-rh-Medial_wall"; + nameTable["2142"] = "ctx-rh-Pole_occipital"; + nameTable["2143"] = "ctx-rh-Pole_temporal"; + nameTable["2144"] = "ctx-rh-S_calcarine"; + nameTable["2145"] = "ctx-rh-S_central"; + nameTable["2146"] = "ctx-rh-S_central_insula"; + nameTable["2147"] = "ctx-rh-S_cingulate-Main_part_and_Intracingulate"; + nameTable["2148"] = "ctx-rh-S_cingulate-Marginalis_part"; + nameTable["2149"] = "ctx-rh-S_circular_insula_anterior"; + nameTable["2150"] = "ctx-rh-S_circular_insula_inferior"; + nameTable["2151"] = "ctx-rh-S_circular_insula_superior"; + nameTable["2152"] = "ctx-rh-S_collateral_transverse_ant"; + nameTable["2153"] = "ctx-rh-S_collateral_transverse_post"; + nameTable["2154"] = "ctx-rh-S_frontal_inferior"; + nameTable["2155"] = "ctx-rh-S_frontal_middle"; + nameTable["2156"] = "ctx-rh-S_frontal_superior"; + nameTable["2157"] = "ctx-rh-S_frontomarginal"; + nameTable["2158"] = "ctx-rh-S_intermedius_primus-Jensen"; + nameTable["2159"] = "ctx-rh-S_intraparietal-and_Parietal_transverse"; + nameTable["2160"] = "ctx-rh-S_occipital_anterior"; + nameTable["2161"] = "ctx-rh-S_occipital_middle_and_Lunatus"; + nameTable["2162"] = "ctx-rh-S_occipital_superior_and_transversalis"; + nameTable["2163"] = "ctx-rh-S_occipito-temporal_lateral"; + nameTable["2164"] = "ctx-rh-S_occipito-temporal_medial_and_S_Lingual"; + nameTable["2165"] = "ctx-rh-S_orbital-H_shapped"; + nameTable["2166"] = "ctx-rh-S_orbital_lateral"; + nameTable["2167"] = "ctx-rh-S_orbital_medial-Or_olfactory"; + nameTable["2168"] = "ctx-rh-S_paracentral"; + nameTable["2169"] = "ctx-rh-S_parieto_occipital"; + nameTable["2170"] = "ctx-rh-S_pericallosal"; + nameTable["2171"] = "ctx-rh-S_postcentral"; + nameTable["2172"] = "ctx-rh-S_precentral-Inferior-part"; + nameTable["2173"] = "ctx-rh-S_precentral-Superior-part"; + nameTable["2174"] = "ctx-rh-S_subcentral_ant"; + nameTable["2175"] = "ctx-rh-S_subcentral_post"; + nameTable["2176"] = "ctx-rh-S_suborbital"; + nameTable["2177"] = "ctx-rh-S_subparietal"; + nameTable["2178"] = "ctx-rh-S_supracingulate"; + nameTable["2179"] = "ctx-rh-S_temporal_inferior"; + nameTable["2180"] = "ctx-rh-S_temporal_superior"; + nameTable["2181"] = "ctx-rh-S_temporal_transverse"; + nameTable["2200"] = "ctx-rh-G_cingulate-caudal_ACC"; + nameTable["2201"] = "ctx-rh-G_cingulate-rostral_ACC"; + nameTable["2202"] = "ctx-rh-G_cingulate-posterior"; + nameTable["2205"] = "ctx-rh-S_cingulate-caudal_ACC"; + nameTable["2206"] = "ctx-rh-S_cingulate-rostral_ACC"; + nameTable["2207"] = "ctx-rh-S_cingulate-posterior"; + nameTable["2210"] = "ctx-rh-S_pericallosal-caudal"; + nameTable["2211"] = "ctx-rh-S_pericallosal-rostral"; + nameTable["2212"] = "ctx-rh-S_pericallosal-posterior"; + nameTable["3100"] = "wm-lh-Unknown"; + nameTable["3101"] = "wm-lh-Corpus_callosum"; + nameTable["3102"] = "wm-lh-G_and_S_Insula_ONLY_AVERAGE"; + nameTable["3103"] = "wm-lh-G_cingulate-Isthmus"; + nameTable["3104"] = "wm-lh-G_cingulate-Main_part"; + nameTable["3105"] = "wm-lh-G_cuneus"; + nameTable["3106"] = "wm-lh-G_frontal_inf-Opercular_part"; + nameTable["3107"] = "wm-lh-G_frontal_inf-Orbital_part"; + nameTable["3108"] = "wm-lh-G_frontal_inf-Triangular_part"; + nameTable["3109"] = "wm-lh-G_frontal_middle"; + nameTable["3110"] = "wm-lh-G_frontal_superior"; + nameTable["3111"] = "wm-lh-G_frontomarginal"; + nameTable["3112"] = "wm-lh-G_insular_long"; + nameTable["3113"] = "wm-lh-G_insular_short"; + nameTable["3114"] = "wm-lh-G_and_S_occipital_inferior"; + nameTable["3115"] = "wm-lh-G_occipital_middle"; + nameTable["3116"] = "wm-lh-G_occipital_superior"; + nameTable["3117"] = "wm-lh-G_occipit-temp_lat-Or_fusiform"; + nameTable["3118"] = "wm-lh-G_occipit-temp_med-Lingual_part"; + nameTable["3119"] = "wm-lh-G_occipit-temp_med-Parahippocampal_part"; + nameTable["3120"] = "wm-lh-G_orbital"; + nameTable["3121"] = "wm-lh-G_paracentral"; + nameTable["3122"] = "wm-lh-G_parietal_inferior-Angular_part"; + nameTable["3123"] = "wm-lh-G_parietal_inferior-Supramarginal_part"; + nameTable["3124"] = "wm-lh-G_parietal_superior"; + nameTable["3125"] = "wm-lh-G_postcentral"; + nameTable["3126"] = "wm-lh-G_precentral"; + nameTable["3127"] = "wm-lh-G_precuneus"; + nameTable["3128"] = "wm-lh-G_rectus"; + nameTable["3129"] = "wm-lh-G_subcallosal"; + nameTable["3130"] = "wm-lh-G_subcentral"; + nameTable["3131"] = "wm-lh-G_temporal_inferior"; + nameTable["3132"] = "wm-lh-G_temporal_middle"; + nameTable["3133"] = "wm-lh-G_temp_sup-G_temp_transv_and_interm_S"; + nameTable["3134"] = "wm-lh-G_temp_sup-Lateral_aspect"; + nameTable["3135"] = "wm-lh-G_temp_sup-Planum_polare"; + nameTable["3136"] = "wm-lh-G_temp_sup-Planum_tempolare"; + nameTable["3137"] = "wm-lh-G_and_S_transverse_frontopolar"; + nameTable["3138"] = "wm-lh-Lat_Fissure-ant_sgt-ramus_horizontal"; + nameTable["3139"] = "wm-lh-Lat_Fissure-ant_sgt-ramus_vertical"; + nameTable["3140"] = "wm-lh-Lat_Fissure-post_sgt"; + nameTable["3141"] = "wm-lh-Medial_wall"; + nameTable["3142"] = "wm-lh-Pole_occipital"; + nameTable["3143"] = "wm-lh-Pole_temporal"; + nameTable["3144"] = "wm-lh-S_calcarine"; + nameTable["3145"] = "wm-lh-S_central"; + nameTable["3146"] = "wm-lh-S_central_insula"; + nameTable["3147"] = "wm-lh-S_cingulate-Main_part_and_Intracingulate"; + nameTable["3148"] = "wm-lh-S_cingulate-Marginalis_part"; + nameTable["3149"] = "wm-lh-S_circular_insula_anterior"; + nameTable["3150"] = "wm-lh-S_circular_insula_inferior"; + nameTable["3151"] = "wm-lh-S_circular_insula_superior"; + nameTable["3152"] = "wm-lh-S_collateral_transverse_ant"; + nameTable["3153"] = "wm-lh-S_collateral_transverse_post"; + nameTable["3154"] = "wm-lh-S_frontal_inferior"; + nameTable["3155"] = "wm-lh-S_frontal_middle"; + nameTable["3156"] = "wm-lh-S_frontal_superior"; + nameTable["3157"] = "wm-lh-S_frontomarginal"; + nameTable["3158"] = "wm-lh-S_intermedius_primus-Jensen"; + nameTable["3159"] = "wm-lh-S_intraparietal-and_Parietal_transverse"; + nameTable["3160"] = "wm-lh-S_occipital_anterior"; + nameTable["3161"] = "wm-lh-S_occipital_middle_and_Lunatus"; + nameTable["3162"] = "wm-lh-S_occipital_superior_and_transversalis"; + nameTable["3163"] = "wm-lh-S_occipito-temporal_lateral"; + nameTable["3164"] = "wm-lh-S_occipito-temporal_medial_and_S_Lingual"; + nameTable["3165"] = "wm-lh-S_orbital-H_shapped"; + nameTable["3166"] = "wm-lh-S_orbital_lateral"; + nameTable["3167"] = "wm-lh-S_orbital_medial-Or_olfactory"; + nameTable["3168"] = "wm-lh-S_paracentral"; + nameTable["3169"] = "wm-lh-S_parieto_occipital"; + nameTable["3170"] = "wm-lh-S_pericallosal"; + nameTable["3171"] = "wm-lh-S_postcentral"; + nameTable["3172"] = "wm-lh-S_precentral-Inferior-part"; + nameTable["3173"] = "wm-lh-S_precentral-Superior-part"; + nameTable["3174"] = "wm-lh-S_subcentral_ant"; + nameTable["3175"] = "wm-lh-S_subcentral_post"; + nameTable["3176"] = "wm-lh-S_suborbital"; + nameTable["3177"] = "wm-lh-S_subparietal"; + nameTable["3178"] = "wm-lh-S_supracingulate"; + nameTable["3179"] = "wm-lh-S_temporal_inferior"; + nameTable["3180"] = "wm-lh-S_temporal_superior"; + nameTable["3181"] = "wm-lh-S_temporal_transverse"; + nameTable["4100"] = "wm-rh-Unknown"; + nameTable["4101"] = "wm-rh-Corpus_callosum"; + nameTable["4102"] = "wm-rh-G_and_S_Insula_ONLY_AVERAGE"; + nameTable["4103"] = "wm-rh-G_cingulate-Isthmus"; + nameTable["4104"] = "wm-rh-G_cingulate-Main_part"; + nameTable["4105"] = "wm-rh-G_cuneus"; + nameTable["4106"] = "wm-rh-G_frontal_inf-Opercular_part"; + nameTable["4107"] = "wm-rh-G_frontal_inf-Orbital_part"; + nameTable["4108"] = "wm-rh-G_frontal_inf-Triangular_part"; + nameTable["4109"] = "wm-rh-G_frontal_middle"; + nameTable["4110"] = "wm-rh-G_frontal_superior"; + nameTable["4111"] = "wm-rh-G_frontomarginal"; + nameTable["4112"] = "wm-rh-G_insular_long"; + nameTable["4113"] = "wm-rh-G_insular_short"; + nameTable["4114"] = "wm-rh-G_and_S_occipital_inferior"; + nameTable["4115"] = "wm-rh-G_occipital_middle"; + nameTable["4116"] = "wm-rh-G_occipital_superior"; + nameTable["4117"] = "wm-rh-G_occipit-temp_lat-Or_fusiform"; + nameTable["4118"] = "wm-rh-G_occipit-temp_med-Lingual_part"; + nameTable["4119"] = "wm-rh-G_occipit-temp_med-Parahippocampal_part"; + nameTable["4120"] = "wm-rh-G_orbital"; + nameTable["4121"] = "wm-rh-G_paracentral"; + nameTable["4122"] = "wm-rh-G_parietal_inferior-Angular_part"; + nameTable["4123"] = "wm-rh-G_parietal_inferior-Supramarginal_part"; + nameTable["4124"] = "wm-rh-G_parietal_superior"; + nameTable["4125"] = "wm-rh-G_postcentral"; + nameTable["4126"] = "wm-rh-G_precentral"; + nameTable["4127"] = "wm-rh-G_precuneus"; + nameTable["4128"] = "wm-rh-G_rectus"; + nameTable["4129"] = "wm-rh-G_subcallosal"; + nameTable["4130"] = "wm-rh-G_subcentral"; + nameTable["4131"] = "wm-rh-G_temporal_inferior"; + nameTable["4132"] = "wm-rh-G_temporal_middle"; + nameTable["4133"] = "wm-rh-G_temp_sup-G_temp_transv_and_interm_S"; + nameTable["4134"] = "wm-rh-G_temp_sup-Lateral_aspect"; + nameTable["4135"] = "wm-rh-G_temp_sup-Planum_polare"; + nameTable["4136"] = "wm-rh-G_temp_sup-Planum_tempolare"; + nameTable["4137"] = "wm-rh-G_and_S_transverse_frontopolar"; + nameTable["4138"] = "wm-rh-Lat_Fissure-ant_sgt-ramus_horizontal"; + nameTable["4139"] = "wm-rh-Lat_Fissure-ant_sgt-ramus_vertical"; + nameTable["4140"] = "wm-rh-Lat_Fissure-post_sgt"; + nameTable["4141"] = "wm-rh-Medial_wall"; + nameTable["4142"] = "wm-rh-Pole_occipital"; + nameTable["4143"] = "wm-rh-Pole_temporal"; + nameTable["4144"] = "wm-rh-S_calcarine"; + nameTable["4145"] = "wm-rh-S_central"; + nameTable["4146"] = "wm-rh-S_central_insula"; + nameTable["4147"] = "wm-rh-S_cingulate-Main_part_and_Intracingulate"; + nameTable["4148"] = "wm-rh-S_cingulate-Marginalis_part"; + nameTable["4149"] = "wm-rh-S_circular_insula_anterior"; + nameTable["4150"] = "wm-rh-S_circular_insula_inferior"; + nameTable["4151"] = "wm-rh-S_circular_insula_superior"; + nameTable["4152"] = "wm-rh-S_collateral_transverse_ant"; + nameTable["4153"] = "wm-rh-S_collateral_transverse_post"; + nameTable["4154"] = "wm-rh-S_frontal_inferior"; + nameTable["4155"] = "wm-rh-S_frontal_middle"; + nameTable["4156"] = "wm-rh-S_frontal_superior"; + nameTable["4157"] = "wm-rh-S_frontomarginal"; + nameTable["4158"] = "wm-rh-S_intermedius_primus-Jensen"; + nameTable["4159"] = "wm-rh-S_intraparietal-and_Parietal_transverse"; + nameTable["4160"] = "wm-rh-S_occipital_anterior"; + nameTable["4161"] = "wm-rh-S_occipital_middle_and_Lunatus"; + nameTable["4162"] = "wm-rh-S_occipital_superior_and_transversalis"; + nameTable["4163"] = "wm-rh-S_occipito-temporal_lateral"; + nameTable["4164"] = "wm-rh-S_occipito-temporal_medial_and_S_Lingual"; + nameTable["4165"] = "wm-rh-S_orbital-H_shapped"; + nameTable["4166"] = "wm-rh-S_orbital_lateral"; + nameTable["4167"] = "wm-rh-S_orbital_medial-Or_olfactory"; + nameTable["4168"] = "wm-rh-S_paracentral"; + nameTable["4169"] = "wm-rh-S_parieto_occipital"; + nameTable["4170"] = "wm-rh-S_pericallosal"; + nameTable["4171"] = "wm-rh-S_postcentral"; + nameTable["4172"] = "wm-rh-S_precentral-Inferior-part"; + nameTable["4173"] = "wm-rh-S_precentral-Superior-part"; + nameTable["4174"] = "wm-rh-S_subcentral_ant"; + nameTable["4175"] = "wm-rh-S_subcentral_post"; + nameTable["4176"] = "wm-rh-S_suborbital"; + nameTable["4177"] = "wm-rh-S_subparietal"; + nameTable["4178"] = "wm-rh-S_supracingulate"; + nameTable["4179"] = "wm-rh-S_temporal_inferior"; + nameTable["4180"] = "wm-rh-S_temporal_superior"; + nameTable["4181"] = "wm-rh-S_temporal_transverse"; + nameTable["5001"] = "Left-UnsegmentedWhiteMatter"; + nameTable["5002"] = "Right-UnsegmentedWhiteMatter"; + nameTable["5100"] = "fmajor"; + nameTable["5101"] = "fminor"; + nameTable["5102"] = "lh.atr"; + nameTable["5103"] = "lh.cab"; + nameTable["5104"] = "lh.ccg"; + nameTable["5105"] = "lh.cst"; + nameTable["5106"] = "lh.ilf"; + nameTable["5107"] = "lh.slfp"; + nameTable["5108"] = "lh.slft"; + nameTable["5109"] = "lh.unc"; + nameTable["5110"] = "rh.atr"; + nameTable["5111"] = "rh.cab"; + nameTable["5112"] = "rh.ccg"; + nameTable["5113"] = "rh.cst"; + nameTable["5114"] = "rh.ilf"; + nameTable["5115"] = "rh.slfp"; + nameTable["5116"] = "rh.slft"; + nameTable["5117"] = "rh.unc"; + nameTable["5200"] = "CC-ForcepsMajor"; + nameTable["5201"] = "CC-ForcepsMinor"; + nameTable["5202"] = "LAntThalRadiation"; + nameTable["5203"] = "LCingulumAngBundle"; + nameTable["5204"] = "LCingulumCingGyrus"; + nameTable["5205"] = "LCorticospinalTract"; + nameTable["5206"] = "LInfLongFas"; + nameTable["5207"] = "LSupLongFasParietal"; + nameTable["5208"] = "LSupLongFasTemporal"; + nameTable["5209"] = "LUncinateFas"; + nameTable["5210"] = "RAntThalRadiation"; + nameTable["5211"] = "RCingulumAngBundle"; + nameTable["5212"] = "RCingulumCingGyrus"; + nameTable["5213"] = "RCorticospinalTract"; + nameTable["5214"] = "RInfLongFas"; + nameTable["5215"] = "RSupLongFasParietal"; + nameTable["5216"] = "RSupLongFasTemporal"; + nameTable["5217"] = "RUncinateFas"; + nameTable["6000"] = "CST-orig"; + nameTable["6001"] = "CST-hammer"; + nameTable["6002"] = "CST-CVS"; + nameTable["6003"] = "CST-flirt"; + nameTable["6010"] = "Left-SLF1"; + nameTable["6020"] = "Right-SLF1"; + nameTable["6030"] = "Left-SLF3"; + nameTable["6040"] = "Right-SLF3"; + nameTable["6050"] = "Left-CST"; + nameTable["6060"] = "Right-CST"; + nameTable["6070"] = "Left-SLF2"; + nameTable["6080"] = "Right-SLF2"; + nameTable["7001"] = "Lateral-nucleus"; + nameTable["7002"] = "Basolateral-nucleus"; + nameTable["7003"] = "Basal-nucleus"; + nameTable["7004"] = "Centromedial-nucleus"; + nameTable["7005"] = "Central-nucleus"; + nameTable["7006"] = "Medial-nucleus"; + nameTable["7007"] = "Cortical-nucleus"; + nameTable["7008"] = "Accessory-Basal-nucleus"; + nameTable["7009"] = "Corticoamygdaloid-transitio"; + nameTable["7010"] = "Anterior-amygdaloid-area-AAA"; + nameTable["7011"] = "Fusion-amygdala-HP-FAH"; + nameTable["7012"] = "Hippocampal-amygdala-transition-HATA"; + nameTable["7013"] = "Endopiriform-nucleus"; + nameTable["7014"] = "Lateral-nucleus-olfactory-tract"; + nameTable["7015"] = "Paralaminar-nucleus"; + nameTable["7016"] = "Intercalated-nucleus"; + nameTable["7017"] = "Prepiriform-cortex"; + nameTable["7018"] = "Periamygdaloid-cortex"; + nameTable["7019"] = "Envelope-Amygdala"; + nameTable["7020"] = "Extranuclear-Amydala"; + nameTable["7100"] = "Brainstem-inferior-colliculus"; + nameTable["7101"] = "Brainstem-cochlear-nucleus"; + nameTable["8001"] = "Thalamus-Anterior"; + nameTable["8002"] = "Thalamus-Ventral-anterior"; + nameTable["8003"] = "Thalamus-Lateral-dorsal"; + nameTable["8004"] = "Thalamus-Lateral-posterior"; + nameTable["8005"] = "Thalamus-Ventral-lateral"; + nameTable["8006"] = "Thalamus-Ventral-posterior-medial"; + nameTable["8007"] = "Thalamus-Ventral-posterior-lateral"; + nameTable["8008"] = "Thalamus-intralaminar"; + nameTable["8009"] = "Thalamus-centromedian"; + nameTable["8010"] = "Thalamus-mediodorsal"; + nameTable["8011"] = "Thalamus-medial"; + nameTable["8012"] = "Thalamus-pulvinar"; + nameTable["8013"] = "Thalamus-lateral-geniculate"; + nameTable["8014"] = "Thalamus-medial-geniculate"; + nameTable["9000"] = "ctx-lh-prefrontal"; + nameTable["9001"] = "ctx-lh-primary-motor"; + nameTable["9002"] = "ctx-lh-premotor"; + nameTable["9003"] = "ctx-lh-temporal"; + nameTable["9004"] = "ctx-lh-posterior-parietal"; + nameTable["9005"] = "ctx-lh-prim-sec-somatosensory"; + nameTable["9006"] = "ctx-lh-occipital"; + nameTable["9500"] = "ctx-rh-prefrontal"; + nameTable["9501"] = "ctx-rh-primary-motor"; + nameTable["9502"] = "ctx-rh-premotor"; + nameTable["9503"] = "ctx-rh-temporal"; + nameTable["9504"] = "ctx-rh-posterior-parietal"; + nameTable["9505"] = "ctx-rh-prim-sec-somatosensory"; + nameTable["9506"] = "ctx-rh-occipital"; + nameTable["11100"] = "ctx_lh_Unknown"; + nameTable["11101"] = "ctx_lh_G_and_S_frontomargin"; + nameTable["11102"] = "ctx_lh_G_and_S_occipital_inf"; + nameTable["11103"] = "ctx_lh_G_and_S_paracentral"; + nameTable["11104"] = "ctx_lh_G_and_S_subcentral"; + nameTable["11105"] = "ctx_lh_G_and_S_transv_frontopol"; + nameTable["11106"] = "ctx_lh_G_and_S_cingul-Ant"; + nameTable["11107"] = "ctx_lh_G_and_S_cingul-Mid-Ant"; + nameTable["11108"] = "ctx_lh_G_and_S_cingul-Mid-Post"; + nameTable["11109"] = "ctx_lh_G_cingul-Post-dorsal"; + nameTable["11110"] = "ctx_lh_G_cingul-Post-ventral"; + nameTable["11111"] = "ctx_lh_G_cuneus"; + nameTable["11112"] = "ctx_lh_G_front_inf-Opercular"; + nameTable["11113"] = "ctx_lh_G_front_inf-Orbital"; + nameTable["11114"] = "ctx_lh_G_front_inf-Triangul"; + nameTable["11115"] = "ctx_lh_G_front_middle"; + nameTable["11116"] = "ctx_lh_G_front_sup"; + nameTable["11117"] = "ctx_lh_G_Ins_lg_and_S_cent_ins"; + nameTable["11118"] = "ctx_lh_G_insular_short"; + nameTable["11119"] = "ctx_lh_G_occipital_middle"; + nameTable["11120"] = "ctx_lh_G_occipital_sup"; + nameTable["11121"] = "ctx_lh_G_oc-temp_lat-fusifor"; + nameTable["11122"] = "ctx_lh_G_oc-temp_med-Lingual"; + nameTable["11123"] = "ctx_lh_G_oc-temp_med-Parahip"; + nameTable["11124"] = "ctx_lh_G_orbital"; + nameTable["11125"] = "ctx_lh_G_pariet_inf-Angular"; + nameTable["11126"] = "ctx_lh_G_pariet_inf-Supramar"; + nameTable["11127"] = "ctx_lh_G_parietal_sup"; + nameTable["11128"] = "ctx_lh_G_postcentral"; + nameTable["11129"] = "ctx_lh_G_precentral"; + nameTable["11130"] = "ctx_lh_G_precuneus"; + nameTable["11131"] = "ctx_lh_G_rectus"; + nameTable["11132"] = "ctx_lh_G_subcallosal"; + nameTable["11133"] = "ctx_lh_G_temp_sup-G_T_transv"; + nameTable["11134"] = "ctx_lh_G_temp_sup-Lateral"; + nameTable["11135"] = "ctx_lh_G_temp_sup-Plan_polar"; + nameTable["11136"] = "ctx_lh_G_temp_sup-Plan_tempo"; + nameTable["11137"] = "ctx_lh_G_temporal_inf"; + nameTable["11138"] = "ctx_lh_G_temporal_middle"; + nameTable["11139"] = "ctx_lh_Lat_Fis-ant-Horizont"; + nameTable["11140"] = "ctx_lh_Lat_Fis-ant-Vertical"; + nameTable["11141"] = "ctx_lh_Lat_Fis-post"; + nameTable["11142"] = "ctx_lh_Medial_wall"; + nameTable["11143"] = "ctx_lh_Pole_occipital"; + nameTable["11144"] = "ctx_lh_Pole_temporal"; + nameTable["11145"] = "ctx_lh_S_calcarine"; + nameTable["11146"] = "ctx_lh_S_central"; + nameTable["11147"] = "ctx_lh_S_cingul-Marginalis"; + nameTable["11148"] = "ctx_lh_S_circular_insula_ant"; + nameTable["11149"] = "ctx_lh_S_circular_insula_inf"; + nameTable["11150"] = "ctx_lh_S_circular_insula_sup"; + nameTable["11151"] = "ctx_lh_S_collat_transv_ant"; + nameTable["11152"] = "ctx_lh_S_collat_transv_post"; + nameTable["11153"] = "ctx_lh_S_front_inf"; + nameTable["11154"] = "ctx_lh_S_front_middle"; + nameTable["11155"] = "ctx_lh_S_front_sup"; + nameTable["11156"] = "ctx_lh_S_interm_prim-Jensen"; + nameTable["11157"] = "ctx_lh_S_intrapariet_and_P_trans"; + nameTable["11158"] = "ctx_lh_S_oc_middle_and_Lunatus"; + nameTable["11159"] = "ctx_lh_S_oc_sup_and_transversal"; + nameTable["11160"] = "ctx_lh_S_occipital_ant"; + nameTable["11161"] = "ctx_lh_S_oc-temp_lat"; + nameTable["11162"] = "ctx_lh_S_oc-temp_med_and_Lingual"; + nameTable["11163"] = "ctx_lh_S_orbital_lateral"; + nameTable["11164"] = "ctx_lh_S_orbital_med-olfact"; + nameTable["11165"] = "ctx_lh_S_orbital-H_Shaped"; + nameTable["11166"] = "ctx_lh_S_parieto_occipital"; + nameTable["11167"] = "ctx_lh_S_pericallosal"; + nameTable["11168"] = "ctx_lh_S_postcentral"; + nameTable["11169"] = "ctx_lh_S_precentral-inf-part"; + nameTable["11170"] = "ctx_lh_S_precentral-sup-part"; + nameTable["11171"] = "ctx_lh_S_suborbital"; + nameTable["11172"] = "ctx_lh_S_subparietal"; + nameTable["11173"] = "ctx_lh_S_temporal_inf"; + nameTable["11174"] = "ctx_lh_S_temporal_sup"; + nameTable["11175"] = "ctx_lh_S_temporal_transverse"; + nameTable["12100"] = "ctx_rh_Unknown"; + nameTable["12101"] = "ctx_rh_G_and_S_frontomargin"; + nameTable["12102"] = "ctx_rh_G_and_S_occipital_inf"; + nameTable["12103"] = "ctx_rh_G_and_S_paracentral"; + nameTable["12104"] = "ctx_rh_G_and_S_subcentral"; + nameTable["12105"] = "ctx_rh_G_and_S_transv_frontopol"; + nameTable["12106"] = "ctx_rh_G_and_S_cingul-Ant"; + nameTable["12107"] = "ctx_rh_G_and_S_cingul-Mid-Ant"; + nameTable["12108"] = "ctx_rh_G_and_S_cingul-Mid-Post"; + nameTable["12109"] = "ctx_rh_G_cingul-Post-dorsal"; + nameTable["12110"] = "ctx_rh_G_cingul-Post-ventral"; + nameTable["12111"] = "ctx_rh_G_cuneus"; + nameTable["12112"] = "ctx_rh_G_front_inf-Opercular"; + nameTable["12113"] = "ctx_rh_G_front_inf-Orbital"; + nameTable["12114"] = "ctx_rh_G_front_inf-Triangul"; + nameTable["12115"] = "ctx_rh_G_front_middle"; + nameTable["12116"] = "ctx_rh_G_front_sup"; + nameTable["12117"] = "ctx_rh_G_Ins_lg_and_S_cent_ins"; + nameTable["12118"] = "ctx_rh_G_insular_short"; + nameTable["12119"] = "ctx_rh_G_occipital_middle"; + nameTable["12120"] = "ctx_rh_G_occipital_sup"; + nameTable["12121"] = "ctx_rh_G_oc-temp_lat-fusifor"; + nameTable["12122"] = "ctx_rh_G_oc-temp_med-Lingual"; + nameTable["12123"] = "ctx_rh_G_oc-temp_med-Parahip"; + nameTable["12124"] = "ctx_rh_G_orbital"; + nameTable["12125"] = "ctx_rh_G_pariet_inf-Angular"; + nameTable["12126"] = "ctx_rh_G_pariet_inf-Supramar"; + nameTable["12127"] = "ctx_rh_G_parietal_sup"; + nameTable["12128"] = "ctx_rh_G_postcentral"; + nameTable["12129"] = "ctx_rh_G_precentral"; + nameTable["12130"] = "ctx_rh_G_precuneus"; + nameTable["12131"] = "ctx_rh_G_rectus"; + nameTable["12132"] = "ctx_rh_G_subcallosal"; + nameTable["12133"] = "ctx_rh_G_temp_sup-G_T_transv"; + nameTable["12134"] = "ctx_rh_G_temp_sup-Lateral"; + nameTable["12135"] = "ctx_rh_G_temp_sup-Plan_polar"; + nameTable["12136"] = "ctx_rh_G_temp_sup-Plan_tempo"; + nameTable["12137"] = "ctx_rh_G_temporal_inf"; + nameTable["12138"] = "ctx_rh_G_temporal_middle"; + nameTable["12139"] = "ctx_rh_Lat_Fis-ant-Horizont"; + nameTable["12140"] = "ctx_rh_Lat_Fis-ant-Vertical"; + nameTable["12141"] = "ctx_rh_Lat_Fis-post"; + nameTable["12142"] = "ctx_rh_Medial_wall"; + nameTable["12143"] = "ctx_rh_Pole_occipital"; + nameTable["12144"] = "ctx_rh_Pole_temporal"; + nameTable["12145"] = "ctx_rh_S_calcarine"; + nameTable["12146"] = "ctx_rh_S_central"; + nameTable["12147"] = "ctx_rh_S_cingul-Marginalis"; + nameTable["12148"] = "ctx_rh_S_circular_insula_ant"; + nameTable["12149"] = "ctx_rh_S_circular_insula_inf"; + nameTable["12150"] = "ctx_rh_S_circular_insula_sup"; + nameTable["12151"] = "ctx_rh_S_collat_transv_ant"; + nameTable["12152"] = "ctx_rh_S_collat_transv_post"; + nameTable["12153"] = "ctx_rh_S_front_inf"; + nameTable["12154"] = "ctx_rh_S_front_middle"; + nameTable["12155"] = "ctx_rh_S_front_sup"; + nameTable["12156"] = "ctx_rh_S_interm_prim-Jensen"; + nameTable["12157"] = "ctx_rh_S_intrapariet_and_P_trans"; + nameTable["12158"] = "ctx_rh_S_oc_middle_and_Lunatus"; + nameTable["12159"] = "ctx_rh_S_oc_sup_and_transversal"; + nameTable["12160"] = "ctx_rh_S_occipital_ant"; + nameTable["12161"] = "ctx_rh_S_oc-temp_lat"; + nameTable["12162"] = "ctx_rh_S_oc-temp_med_and_Lingual"; + nameTable["12163"] = "ctx_rh_S_orbital_lateral"; + nameTable["12164"] = "ctx_rh_S_orbital_med-olfact"; + nameTable["12165"] = "ctx_rh_S_orbital-H_Shaped"; + nameTable["12166"] = "ctx_rh_S_parieto_occipital"; + nameTable["12167"] = "ctx_rh_S_pericallosal"; + nameTable["12168"] = "ctx_rh_S_postcentral"; + nameTable["12169"] = "ctx_rh_S_precentral-inf-part"; + nameTable["12170"] = "ctx_rh_S_precentral-sup-part"; + nameTable["12171"] = "ctx_rh_S_suborbital"; + nameTable["12172"] = "ctx_rh_S_subparietal"; + nameTable["12173"] = "ctx_rh_S_temporal_inf"; + nameTable["12174"] = "ctx_rh_S_temporal_sup"; + nameTable["12175"] = "ctx_rh_S_temporal_transverse"; + nameTable["13100"] = "wm_lh_Unknown"; + nameTable["13101"] = "wm_lh_G_and_S_frontomargin"; + nameTable["13102"] = "wm_lh_G_and_S_occipital_inf"; + nameTable["13103"] = "wm_lh_G_and_S_paracentral"; + nameTable["13104"] = "wm_lh_G_and_S_subcentral"; + nameTable["13105"] = "wm_lh_G_and_S_transv_frontopol"; + nameTable["13106"] = "wm_lh_G_and_S_cingul-Ant"; + nameTable["13107"] = "wm_lh_G_and_S_cingul-Mid-Ant"; + nameTable["13108"] = "wm_lh_G_and_S_cingul-Mid-Post"; + nameTable["13109"] = "wm_lh_G_cingul-Post-dorsal"; + nameTable["13110"] = "wm_lh_G_cingul-Post-ventral"; + nameTable["13111"] = "wm_lh_G_cuneus"; + nameTable["13112"] = "wm_lh_G_front_inf-Opercular"; + nameTable["13113"] = "wm_lh_G_front_inf-Orbital"; + nameTable["13114"] = "wm_lh_G_front_inf-Triangul"; + nameTable["13115"] = "wm_lh_G_front_middle"; + nameTable["13116"] = "wm_lh_G_front_sup"; + nameTable["13117"] = "wm_lh_G_Ins_lg_and_S_cent_ins"; + nameTable["13118"] = "wm_lh_G_insular_short"; + nameTable["13119"] = "wm_lh_G_occipital_middle"; + nameTable["13120"] = "wm_lh_G_occipital_sup"; + nameTable["13121"] = "wm_lh_G_oc-temp_lat-fusifor"; + nameTable["13122"] = "wm_lh_G_oc-temp_med-Lingual"; + nameTable["13123"] = "wm_lh_G_oc-temp_med-Parahip"; + nameTable["13124"] = "wm_lh_G_orbital"; + nameTable["13125"] = "wm_lh_G_pariet_inf-Angular"; + nameTable["13126"] = "wm_lh_G_pariet_inf-Supramar"; + nameTable["13127"] = "wm_lh_G_parietal_sup"; + nameTable["13128"] = "wm_lh_G_postcentral"; + nameTable["13129"] = "wm_lh_G_precentral"; + nameTable["13130"] = "wm_lh_G_precuneus"; + nameTable["13131"] = "wm_lh_G_rectus"; + nameTable["13132"] = "wm_lh_G_subcallosal"; + nameTable["13133"] = "wm_lh_G_temp_sup-G_T_transv"; + nameTable["13134"] = "wm_lh_G_temp_sup-Lateral"; + nameTable["13135"] = "wm_lh_G_temp_sup-Plan_polar"; + nameTable["13136"] = "wm_lh_G_temp_sup-Plan_tempo"; + nameTable["13137"] = "wm_lh_G_temporal_inf"; + nameTable["13138"] = "wm_lh_G_temporal_middle"; + nameTable["13139"] = "wm_lh_Lat_Fis-ant-Horizont"; + nameTable["13140"] = "wm_lh_Lat_Fis-ant-Vertical"; + nameTable["13141"] = "wm_lh_Lat_Fis-post"; + nameTable["13142"] = "wm_lh_Medial_wall"; + nameTable["13143"] = "wm_lh_Pole_occipital"; + nameTable["13144"] = "wm_lh_Pole_temporal"; + nameTable["13145"] = "wm_lh_S_calcarine"; + nameTable["13146"] = "wm_lh_S_central"; + nameTable["13147"] = "wm_lh_S_cingul-Marginalis"; + nameTable["13148"] = "wm_lh_S_circular_insula_ant"; + nameTable["13149"] = "wm_lh_S_circular_insula_inf"; + nameTable["13150"] = "wm_lh_S_circular_insula_sup"; + nameTable["13151"] = "wm_lh_S_collat_transv_ant"; + nameTable["13152"] = "wm_lh_S_collat_transv_post"; + nameTable["13153"] = "wm_lh_S_front_inf"; + nameTable["13154"] = "wm_lh_S_front_middle"; + nameTable["13155"] = "wm_lh_S_front_sup"; + nameTable["13156"] = "wm_lh_S_interm_prim-Jensen"; + nameTable["13157"] = "wm_lh_S_intrapariet_and_P_trans"; + nameTable["13158"] = "wm_lh_S_oc_middle_and_Lunatus"; + nameTable["13159"] = "wm_lh_S_oc_sup_and_transversal"; + nameTable["13160"] = "wm_lh_S_occipital_ant"; + nameTable["13161"] = "wm_lh_S_oc-temp_lat"; + nameTable["13162"] = "wm_lh_S_oc-temp_med_and_Lingual"; + nameTable["13163"] = "wm_lh_S_orbital_lateral"; + nameTable["13164"] = "wm_lh_S_orbital_med-olfact"; + nameTable["13165"] = "wm_lh_S_orbital-H_Shaped"; + nameTable["13166"] = "wm_lh_S_parieto_occipital"; + nameTable["13167"] = "wm_lh_S_pericallosal"; + nameTable["13168"] = "wm_lh_S_postcentral"; + nameTable["13169"] = "wm_lh_S_precentral-inf-part"; + nameTable["13170"] = "wm_lh_S_precentral-sup-part"; + nameTable["13171"] = "wm_lh_S_suborbital"; + nameTable["13172"] = "wm_lh_S_subparietal"; + nameTable["13173"] = "wm_lh_S_temporal_inf"; + nameTable["13174"] = "wm_lh_S_temporal_sup"; + nameTable["13175"] = "wm_lh_S_temporal_transverse"; + nameTable["14100"] = "wm_rh_Unknown"; + nameTable["14101"] = "wm_rh_G_and_S_frontomargin"; + nameTable["14102"] = "wm_rh_G_and_S_occipital_inf"; + nameTable["14103"] = "wm_rh_G_and_S_paracentral"; + nameTable["14104"] = "wm_rh_G_and_S_subcentral"; + nameTable["14105"] = "wm_rh_G_and_S_transv_frontopol"; + nameTable["14106"] = "wm_rh_G_and_S_cingul-Ant"; + nameTable["14107"] = "wm_rh_G_and_S_cingul-Mid-Ant"; + nameTable["14108"] = "wm_rh_G_and_S_cingul-Mid-Post"; + nameTable["14109"] = "wm_rh_G_cingul-Post-dorsal"; + nameTable["14110"] = "wm_rh_G_cingul-Post-ventral"; + nameTable["14111"] = "wm_rh_G_cuneus"; + nameTable["14112"] = "wm_rh_G_front_inf-Opercular"; + nameTable["14113"] = "wm_rh_G_front_inf-Orbital"; + nameTable["14114"] = "wm_rh_G_front_inf-Triangul"; + nameTable["14115"] = "wm_rh_G_front_middle"; + nameTable["14116"] = "wm_rh_G_front_sup"; + nameTable["14117"] = "wm_rh_G_Ins_lg_and_S_cent_ins"; + nameTable["14118"] = "wm_rh_G_insular_short"; + nameTable["14119"] = "wm_rh_G_occipital_middle"; + nameTable["14120"] = "wm_rh_G_occipital_sup"; + nameTable["14121"] = "wm_rh_G_oc-temp_lat-fusifor"; + nameTable["14122"] = "wm_rh_G_oc-temp_med-Lingual"; + nameTable["14123"] = "wm_rh_G_oc-temp_med-Parahip"; + nameTable["14124"] = "wm_rh_G_orbital"; + nameTable["14125"] = "wm_rh_G_pariet_inf-Angular"; + nameTable["14126"] = "wm_rh_G_pariet_inf-Supramar"; + nameTable["14127"] = "wm_rh_G_parietal_sup"; + nameTable["14128"] = "wm_rh_G_postcentral"; + nameTable["14129"] = "wm_rh_G_precentral"; + nameTable["14130"] = "wm_rh_G_precuneus"; + nameTable["14131"] = "wm_rh_G_rectus"; + nameTable["14132"] = "wm_rh_G_subcallosal"; + nameTable["14133"] = "wm_rh_G_temp_sup-G_T_transv"; + nameTable["14134"] = "wm_rh_G_temp_sup-Lateral"; + nameTable["14135"] = "wm_rh_G_temp_sup-Plan_polar"; + nameTable["14136"] = "wm_rh_G_temp_sup-Plan_tempo"; + nameTable["14137"] = "wm_rh_G_temporal_inf"; + nameTable["14138"] = "wm_rh_G_temporal_middle"; + nameTable["14139"] = "wm_rh_Lat_Fis-ant-Horizont"; + nameTable["14140"] = "wm_rh_Lat_Fis-ant-Vertical"; + nameTable["14141"] = "wm_rh_Lat_Fis-post"; + nameTable["14142"] = "wm_rh_Medial_wall"; + nameTable["14143"] = "wm_rh_Pole_occipital"; + nameTable["14144"] = "wm_rh_Pole_temporal"; + nameTable["14145"] = "wm_rh_S_calcarine"; + nameTable["14146"] = "wm_rh_S_central"; + nameTable["14147"] = "wm_rh_S_cingul-Marginalis"; + nameTable["14148"] = "wm_rh_S_circular_insula_ant"; + nameTable["14149"] = "wm_rh_S_circular_insula_inf"; + nameTable["14150"] = "wm_rh_S_circular_insula_sup"; + nameTable["14151"] = "wm_rh_S_collat_transv_ant"; + nameTable["14152"] = "wm_rh_S_collat_transv_post"; + nameTable["14153"] = "wm_rh_S_front_inf"; + nameTable["14154"] = "wm_rh_S_front_middle"; + nameTable["14155"] = "wm_rh_S_front_sup"; + nameTable["14156"] = "wm_rh_S_interm_prim-Jensen"; + nameTable["14157"] = "wm_rh_S_intrapariet_and_P_trans"; + nameTable["14158"] = "wm_rh_S_oc_middle_and_Lunatus"; + nameTable["14159"] = "wm_rh_S_oc_sup_and_transversal"; + nameTable["14160"] = "wm_rh_S_occipital_ant"; + nameTable["14161"] = "wm_rh_S_oc-temp_lat"; + nameTable["14162"] = "wm_rh_S_oc-temp_med_and_Lingual"; + nameTable["14163"] = "wm_rh_S_orbital_lateral"; + nameTable["14164"] = "wm_rh_S_orbital_med-olfact"; + nameTable["14165"] = "wm_rh_S_orbital-H_Shaped"; + nameTable["14166"] = "wm_rh_S_parieto_occipital"; + nameTable["14167"] = "wm_rh_S_pericallosal"; + nameTable["14168"] = "wm_rh_S_postcentral"; + nameTable["14169"] = "wm_rh_S_precentral-inf-part"; + nameTable["14170"] = "wm_rh_S_precentral-sup-part"; + nameTable["14171"] = "wm_rh_S_suborbital"; + nameTable["14172"] = "wm_rh_S_subparietal"; + nameTable["14173"] = "wm_rh_S_temporal_inf"; + nameTable["14174"] = "wm_rh_S_temporal_sup"; + nameTable["14175"] = "wm_rh_S_temporal_transverse"; + return nameTable; +} diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h new file mode 100644 index 0000000000..0ec3abc881 --- /dev/null +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h @@ -0,0 +1,112 @@ +/*=================================================================== + +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 mitkFreeSurferParcellationTranslator_h +#define mitkFreeSurferParcellationTranslator_h + +// MITK +#include +#include +#include +#include +#include +// VTK +#include + +using namespace mitk; +using namespace std; + +namespace mitk +{ + /** + * @brief The mitkFreeSurferParcellationTranslator class + * + * This class provides a ready to use lookup table for freesurfer processed images and further functions e.g. to get the name assigned to a given label. + * Additional you can assign the lookup table or transferfunction by using the AssignLookupTable(DataNode* node) or AssignTransferfunction(DataNode* node) methods. + * + */ + class MITKCONNECTOMICS_EXPORT FreeSurferParcellationTranslator : public itk::Object + { + /*########### Constructors, Typedefs and Enumerations ###########*/ + public: + typedef map NameTable; + mitkClassMacro( FreeSurferParcellationTranslator, Object ) + itkNewMacro( FreeSurferParcellationTranslator ) + protected: + FreeSurferParcellationTranslator(); + ~FreeSurferParcellationTranslator(); + + + /*########### Methods ###########*/ + public: + /** + * @brief Assign the lookup table to the given node + * @param node the lookup table should be assigned to + */ + virtual void AssignLookupTable( DataNode::Pointer node ) const; + /** + * @brief Assign the color transfer function to the given node + * @param node the transferfunction should be assigned to + */ + virtual void AssignTransferFunction( DataNode::Pointer node ) const; + /** + * @brief Get the label assigned to the given name + * @param name the label should be assigned to + * @return label + */ + virtual const string GetLabel( const string & name ) const; + /** + * @brief Get the label assigned to the given name + * @param name the label should be assigned to + * @return label + */ + virtual int GetLabelAsNumber( const string & name ) const; + /** + * @brief Return the lookup table + * @return lookup table + */ + virtual LookupTable::Pointer GetLookupTable() const; + /** + * @brief Get the name assigned to the given label + * @param label + * @return name + */ + virtual const string GetName( const string & label ) const; + /** + * @brief Get the name assigned to the given label + * @param label + * @return name + */ + virtual const string GetName( int label ) const; + /** + * @brief Get the transfer function + * @return transfer function + */ + virtual TransferFunction::Pointer GetTransferFunction() const; + private: + static LookupTable::Pointer CreateLookupTable(); + static TransferFunction::Pointer CreateTransferFunction(); + static NameTable CreateNameTable(); + + + /*########### Static Members ###########*/ + private: + static LookupTable::Pointer m_LookupTable; + static TransferFunction::Pointer m_TransferFunction; + static const NameTable m_NameTable; + }; +} +#endif // mitkFreeSurferParcellationTranslator_h diff --git a/Modules/DiffusionImaging/Connectomics/files.cmake b/Modules/DiffusionImaging/Connectomics/files.cmake index 71f64af741..7c8f843242 100644 --- a/Modules/DiffusionImaging/Connectomics/files.cmake +++ b/Modules/DiffusionImaging/Connectomics/files.cmake @@ -1,78 +1,80 @@ set(CPP_FILES # DataStructures Connectomics IODataStructures/mitkConnectomicsNetwork.cpp IODataStructures/mitkConnectomicsConstantsManager.cpp # Rendering Connectomics Rendering/mitkConnectomicsNetworkMapper3D.cpp Rendering/mitkConnectomicsRenderingSchemeProperty.cpp Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.cpp Rendering/mitkConnectomicsRenderingNodeFilteringProperty.cpp Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.cpp Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.cpp Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.cpp Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.cpp Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.cpp Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.cpp Rendering/mitkConnectomicsEnumerationSubclassesSerializer.cpp # Algorithms Connectomics Algorithms/mitkConnectomicsNetworkCreator.cpp Algorithms/mitkConnectomicsHistogramBase.cpp Algorithms/mitkConnectomicsDegreeHistogram.cpp Algorithms/mitkConnectomicsShortestPathHistogram.cpp Algorithms/mitkConnectomicsBetweennessHistogram.cpp Algorithms/mitkConnectomicsHistogramCache.cpp Algorithms/mitkConnectomicsSyntheticNetworkGenerator.cpp Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp Algorithms/mitkConnectomicsSimulatedAnnealingManager.cpp Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp Algorithms/mitkConnectomicsStatisticsCalculator.cpp Algorithms/mitkConnectomicsNetworkConverter.cpp Algorithms/mitkConnectomicsNetworkThresholder.cpp + Algorithms/mitkFreeSurferParcellationTranslator.cpp ) set(H_FILES # Rendering Connectomics Rendering/mitkConnectomicsNetworkMapper3D.h Rendering/mitkConnectomicsRenderingProperties.h Rendering/mitkConnectomicsRenderingSchemeProperty.h Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.h Rendering/mitkConnectomicsRenderingNodeFilteringProperty.h Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.h Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.h Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.h Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.h Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.h Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.h # Datastructures Connectomics IODataStructures/mitkConnectomicsNetwork.h IODataStructures/mitkConnectomicsConstantsManager.h # Algorithms Connectomics Algorithms/mitkConnectomicsNetworkCreator.h Algorithms/mitkConnectomicsHistogramBase.h Algorithms/mitkConnectomicsDegreeHistogram.h Algorithms/mitkConnectomicsShortestPathHistogram.h Algorithms/mitkConnectomicsBetweennessHistogram.h Algorithms/mitkConnectomicsHistogramCache.h Algorithms/mitkConnectomicsSyntheticNetworkGenerator.h Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.h Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.h Algorithms/mitkConnectomicsSimulatedAnnealingManager.h Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.h Algorithms/mitkConnectomicsStatisticsCalculator.h Algorithms/mitkConnectomicsNetworkConverter.h Algorithms/BrainParcellation/mitkCostFunctionBase.h Algorithms/BrainParcellation/mitkRandomParcellationGenerator.h Algorithms/BrainParcellation/mitkRegionVoxelCounter.h + Algorithms/mitkFreeSurferParcellationTranslator.h ) diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp index 22ec4e672b..adb6b13c99 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp @@ -1,526 +1,597 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPyramidImageRegistrationMethod.h" #include "mitkException.h" #include "mitkImageAccessByItk.h" mitk::PyramidImageRegistrationMethod::PyramidImageRegistrationMethod() : m_FixedImage(NULL), m_MovingImage(NULL), m_CrossModalityRegistration(true), m_UseAffineTransform(true), m_UseWindowedSincInterpolator(false), m_UseNearestNeighborInterpolator(false), m_UseMask(false), m_EstimatedParameters(0), m_InitialParameters(0), m_Verbose(false) { } mitk::PyramidImageRegistrationMethod::~PyramidImageRegistrationMethod() { if( m_EstimatedParameters != NULL) { delete [] m_EstimatedParameters; } } void mitk::PyramidImageRegistrationMethod::SetFixedImage(mitk::Image::Pointer fixed) { if( fixed.IsNotNull() ) { m_FixedImage = fixed; } } void mitk::PyramidImageRegistrationMethod::SetMovingImage(mitk::Image::Pointer moving) { if( moving.IsNotNull() ) { m_MovingImage = moving; } } void mitk::PyramidImageRegistrationMethod::SetFixedImageMask(mitk::Image::Pointer mask) { m_FixedImageMask = mask; } void mitk::PyramidImageRegistrationMethod::Update() { if( m_MovingImage.IsNull() ) { mitkThrow() << " Moving image is null"; } if( m_FixedImage.IsNull() ) { mitkThrow() << " Moving image is null"; } unsigned int allowedDimension = 3; if( m_FixedImage->GetDimension() != allowedDimension || m_MovingImage->GetDimension() != allowedDimension ) { mitkThrow() << " Only 3D Images supported."; } // // One possibility: use the FixedDimesnionByItk, but this instantiates ALL possible // pixel type combinations! // AccessTwoImagesFixedDimensionByItk( m_FixedImage, m_MovingImage, RegisterTwoImages, 3); // in helper: TypeSubset : short, float AccessTwoImagesFixedDimensionTypeSubsetByItk( m_FixedImage, m_MovingImage, RegisterTwoImagesV4, 3); } mitk::PyramidImageRegistrationMethod::TransformMatrixType mitk::PyramidImageRegistrationMethod ::GetLastRotationMatrix() { TransformMatrixType output; if( m_EstimatedParameters == NULL ) { output.set_identity(); return output; } typedef itk::MatrixOffsetTransformBase< double, 3, 3> BaseTransformType; BaseTransformType::Pointer base_transform = BaseTransformType::New(); if( this->m_UseAffineTransform ) { typedef itk::AffineTransform< double > TransformType; TransformType::Pointer transform = TransformType::New(); TransformType::ParametersType affine_params( TransformType::ParametersDimension ); this->GetParameters( &affine_params[0] ); transform->SetParameters( affine_params ); base_transform = transform; } else { typedef itk::Euler3DTransform< double > RigidTransformType; RigidTransformType::Pointer rtransform = RigidTransformType::New(); RigidTransformType::ParametersType rigid_params( RigidTransformType::ParametersDimension ); this->GetParameters( &rigid_params[0] ); rtransform->SetParameters( rigid_params ); base_transform = rtransform; } return base_transform->GetMatrix().GetVnlMatrix(); } mitk::Image::Pointer mitk::PyramidImageRegistrationMethod ::GetResampledMovingImage() { mitk::Image::Pointer output = mitk::Image::New(); //output->Initialize( this->m_FixedImage ); AccessFixedDimensionByItk_1( this->m_MovingImage, ResampleMitkImage, 3, output ); return output; } mitk::Image::Pointer mitk::PyramidImageRegistrationMethod::GetResampledMovingImage(mitk::Image::Pointer movingImage, double* transform) { mitk::Image::Pointer output = mitk::Image::New(); unsigned int dim = 12; if( !m_UseAffineTransform ) dim = 6; if (m_EstimatedParameters == NULL) m_EstimatedParameters = new double[dim]; double tmpParams[12]; // save and set temporal transformation values for( unsigned int i=0; i #include #include #include #include #include #include template void mitk::PyramidImageRegistrationMethod:: RegisterTwoImagesV4(itk::Image* itkImage1, itk::Image* itkImage2) { // Basic typedefs needed typedef typename itk::Image ItkImageTypeFixed; typedef typename itk::Image ItkImageTypeMoving; typedef itk::MatrixOffsetTransformBase< double, VImageDimension1, VImageDimension2 > BaseTransformType; typedef itk::Image< double, 3> ItkRegistrationImageType; typedef itk::CastImageFilter< ItkImageTypeFixed, ItkRegistrationImageType> FixedCastFilterType; typedef itk::CastImageFilter< ItkImageTypeMoving, ItkRegistrationImageType> MovingCastFilterType; typedef typename itk::ImageRegistrationMethodv4< ItkRegistrationImageType, ItkRegistrationImageType, AffineTransformType> RegistrationType; typedef typename itk::MattesMutualInformationImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType> MIMetricType; typedef typename itk::CorrelationImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType > NCMetricType; typedef typename itk::ImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType > BaseMetricType; + typedef typename itk::ImageRegistrationMethodv4< ItkRegistrationImageType, ItkRegistrationImageType, RigidTransformType> RigidRegistrationType; + typedef itk::GradientDescentLineSearchOptimizerv4 OptimizerType; typename ItkImageTypeFixed::Pointer referenceImage = itkImage1; typename ItkImageTypeMoving::Pointer movingImage = itkImage2; // initial parameter dimension ( affine = default ) unsigned int paramDim = 12; typename BaseTransformType::Pointer transform; if( m_UseAffineTransform ) { transform = AffineTransformType::New(); } else { transform = RigidTransformType::New(); paramDim = 6; } typename BaseTransformType::ParametersType initialParams(paramDim); initialParams.Fill(0); if( m_UseAffineTransform ) { initialParams[0] = initialParams[4] = initialParams[8] = 1; } // [Prepare registration] // The ITKv4 Methods ( the MI Metric ) require double-type images so we need to perform cast first typename FixedCastFilterType::Pointer caster_f = FixedCastFilterType::New(); typename MovingCastFilterType::Pointer caster_m = MovingCastFilterType::New(); try { caster_f->SetInput(0, referenceImage ); caster_m->SetInput(0, movingImage ); caster_f->Update(); caster_m->Update(); } catch( const itk::ExceptionObject &/*e*/ ) { return ; } // [Prepare Registration] // Estimate the size of the pyramid based on image dimension // here the image size on the topmost level must remain higher than the threshold unsigned int max_pyramid_lvl = 4; unsigned int max_schedule_val = 8; const unsigned int min_required_image_size = 12; typename ItkImageTypeFixed::RegionType::SizeType image_size = referenceImage->GetLargestPossibleRegion().GetSize(); unsigned int min_value = std::min( image_size[0], std::min( image_size[1], image_size[2])); // Adapt also the optimizer settings to the number of levels float optmaxstep = 10; float optminstep = 0.1f; unsigned int iterations = 40; unsigned int convergence_win_size = 8; double convergence_tolerance = 1e-5; while( min_value / max_schedule_val < min_required_image_size ) { max_schedule_val /= 2; max_pyramid_lvl--; optmaxstep -= 2; optminstep *= 0.5f; convergence_win_size += 4; convergence_tolerance *= 0.5; } typename RegistrationType::ShrinkFactorsArrayType shrink_factors(max_pyramid_lvl); shrink_factors.Fill(1); shrink_factors[0] = max_schedule_val; for( unsigned int i=1; i::Pointer mi_estimator = itk::RegistrationParameterScalesFromPhysicalShift< MIMetricType >::New(); mi_estimator->SetMetric( metric ); optimizer->SetScalesEstimator( mi_estimator ); base_metric = metric; } else { typename NCMetricType::Pointer metric = NCMetricType::New(); typename itk::RegistrationParameterScalesFromPhysicalShift< NCMetricType >::Pointer nc_estimator = itk::RegistrationParameterScalesFromPhysicalShift< NCMetricType >::New(); nc_estimator->SetMetric( metric ); optimizer->SetScalesEstimator( nc_estimator ); base_metric = metric; } optimizer->SetDoEstimateLearningRateOnce( false ); optimizer->SetDoEstimateLearningRateAtEachIteration( true ); optimizer->SetNumberOfIterations( iterations ); optimizer->SetConvergenceWindowSize( convergence_win_size ); optimizer->SetMaximumStepSizeInPhysicalUnits( optmaxstep ); optimizer->SetMinimumConvergenceValue( convergence_tolerance ); // line search options optimizer->SetEpsilon( 1e-3 ); optimizer->SetLowerLimit( 0.3 ); optimizer->SetUpperLimit( 1.7 ); optimizer->SetMaximumLineSearchIterations( 20 ); // add observer tag if verbose unsigned long vopt_tag = 0; if(m_Verbose) { MITK_INFO << " :: Starting at " << initialParams; OptimizerIterationCommandv4< OptimizerType >::Pointer iterationObserver = OptimizerIterationCommandv4::New(); vopt_tag = optimizer->AddObserver( itk::IterationEvent(), iterationObserver ); } // Initializing by Geometry if( !m_UseAffineTransform && m_InitializeByGeometry ) { typedef itk::CenteredVersorTransformInitializer< ItkImageTypeFixed, ItkImageTypeMoving> TransformInitializerType; typename TransformInitializerType::TransformType::Pointer rigidTransform = TransformInitializerType::TransformType::New() ; MITK_INFO << "Initializer starting at : " << rigidTransform->GetParameters(); typename TransformInitializerType::Pointer initializer = TransformInitializerType::New(); initializer->SetTransform( rigidTransform); initializer->SetFixedImage( referenceImage.GetPointer() ); initializer->SetMovingImage( movingImage.GetPointer() ); initializer->MomentsOn(); initializer->InitializeTransform(); MITK_INFO << "Initialized Rigid position : " << rigidTransform->GetParameters(); initialParams[3] = rigidTransform->GetParameters()[3]; initialParams[4] = rigidTransform->GetParameters()[4]; initialParams[5] = rigidTransform->GetParameters()[5]; } // [Prepare Registration] // Masking (Optional) if( m_UseMask ) { typedef itk::Image BinaryImageType; BinaryImageType::Pointer itkFixedImageMask = BinaryImageType::New(); itk::ImageMaskSpatialObject< 3 >::Pointer fixedMaskSpatialObject = itk::ImageMaskSpatialObject< 3 >::New(); CastToItkImage( m_FixedImageMask, itkFixedImageMask); itk::NotImageFilter::Pointer notFilter = itk::NotImageFilter::New(); notFilter->SetInput(itkFixedImageMask); notFilter->Update(); fixedMaskSpatialObject->SetImage( notFilter->GetOutput() ); base_metric->SetFixedImageMask( fixedMaskSpatialObject ); } + + if( m_EstimatedParameters != NULL) + { + delete [] m_EstimatedParameters; + } + + m_EstimatedParameters = new double[paramDim]; + + //----------------- + //----------------- + // [Prepare Registration] // combine all components to set-up registration - typename RegistrationType::Pointer registration = RegistrationType::New(); + if( m_UseAffineTransform ) + { - registration->SetFixedImage( 0, caster_f->GetOutput() ); - registration->SetMovingImage( 0, caster_m->GetOutput() ); - registration->SetMetric( base_metric ); - registration->SetOptimizer( optimizer ); - registration->SetMovingInitialTransform( transform.GetPointer() ); - registration->SetNumberOfLevels(max_pyramid_lvl); - registration->SetShrinkFactorsPerLevel( shrink_factors ); + typename RegistrationType::Pointer registration = RegistrationType::New(); - // observe the pyramid level change in order to adapt parameters - typename PyramidOptControlCommandv4::Pointer pyramid_observer = - PyramidOptControlCommandv4::New(); - unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer ); + registration->SetFixedImage( 0, caster_f->GetOutput() ); + registration->SetMovingImage( 0, caster_m->GetOutput() ); + registration->SetMetric( base_metric ); + registration->SetOptimizer( optimizer ); + registration->SetMovingInitialTransform( transform.GetPointer() ); + registration->SetNumberOfLevels(max_pyramid_lvl); + registration->SetShrinkFactorsPerLevel( shrink_factors ); + // observe the pyramid level change in order to adapt parameters + typename PyramidOptControlCommandv4::Pointer pyramid_observer = + PyramidOptControlCommandv4::New(); + unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer ); + + + try + { + registration->Update(); + } + catch( const itk::ExceptionObject &e) + { + registration->Print( std::cout ); + + MITK_ERROR << "[Registration Update] Caught ITK exception: "; + MITK_ERROR("itk.exception") << e.what(); + + mitkThrow() << "Registration failed with exception: " << e.what(); + } + + // [Post Registration] + // Retrieve the last transformation parameters from the performed registration task + typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition(); + for( unsigned int i=0; iGetValue() << " :: " << finalParameters; + } + + if( pyramid_tag ) + { + registration->RemoveObserver( pyramid_tag ); + } - try - { - registration->Update(); } - catch( const itk::ExceptionObject &e) + //----------- + //----------- + else { - registration->Print( std::cout ); - MITK_ERROR << "[Registration Update] Caught ITK exception: "; - MITK_ERROR("itk.exception") << e.what(); + typename RigidRegistrationType::Pointer registration = RigidRegistrationType::New(); - mitkThrow() << "Registration failed with exception: " << e.what(); - } + registration->SetFixedImage( 0, caster_f->GetOutput() ); + registration->SetMovingImage( 0, caster_m->GetOutput() ); + registration->SetMetric( base_metric ); + registration->SetOptimizer( optimizer ); + registration->SetMovingInitialTransform( transform.GetPointer() ); + registration->SetNumberOfLevels(max_pyramid_lvl); + registration->SetShrinkFactorsPerLevel( shrink_factors ); - // [Post Registration] - // Retrieve the last transformation parameters from the performed registration task - if( m_EstimatedParameters != NULL) - { - delete [] m_EstimatedParameters; - } + // observe the pyramid level change in order to adapt parameters + typename PyramidOptControlCommandv4::Pointer pyramid_observer = + PyramidOptControlCommandv4::New(); + unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer ); - m_EstimatedParameters = new double[paramDim]; - typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition(); - for( unsigned int i=0; iUpdate(); + } + catch( const itk::ExceptionObject &e) + { + registration->Print( std::cout ); - MITK_INFO("Params") << optimizer->GetValue() << " :: " << finalParameters; + MITK_ERROR << "[Registration Update] Caught ITK exception: "; + MITK_ERROR("itk.exception") << e.what(); + + mitkThrow() << "Registration failed with exception: " << e.what(); + } + + // [Post Registration] + // Retrieve the last transformation parameters from the performed registration task + typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition(); + for( unsigned int i=0; iGetValue() << " :: " << finalParameters; + } + + if( pyramid_tag ) + { + registration->RemoveObserver( pyramid_tag ); + } + + } if( m_Verbose ) { MITK_INFO("Termination") << optimizer->GetStopConditionDescription(); } // remove optimizer tag if used if( vopt_tag ) { optimizer->RemoveObserver( vopt_tag ); } - if( pyramid_tag ) - { - registration->RemoveObserver( pyramid_tag ); - } + + } template< typename TPixel, unsigned int VDimension> void mitk::PyramidImageRegistrationMethod:: ResampleMitkImage( itk::Image* itkImage, mitk::Image::Pointer& outputImage ) { typedef typename itk::Image< TPixel, VDimension> ImageType; typedef typename itk::ResampleImageFilter< ImageType, ImageType, double> ResampleImageFilterType; typedef itk::LinearInterpolateImageFunction< ImageType, double > InterpolatorType; typename InterpolatorType::Pointer linear_interpolator = InterpolatorType::New(); typedef itk::NearestNeighborInterpolateImageFunction< ImageType, double > NearestNeighborInterpolatorType; typename NearestNeighborInterpolatorType::Pointer nn_interpolator = NearestNeighborInterpolatorType::New(); typedef itk::WindowedSincInterpolateImageFunction< ImageType, 7> WindowedSincInterpolatorType; typename WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typename ImageType::Pointer reference_image = ImageType::New(); CastToItkImage(m_FixedImage,reference_image); typedef itk::MatrixOffsetTransformBase< double, 3, 3> BaseTransformType; BaseTransformType::Pointer base_transform = BaseTransformType::New(); if( this->m_UseAffineTransform ) { typedef itk::AffineTransform< double > TransformType; TransformType::Pointer transform = TransformType::New(); TransformType::ParametersType affine_params( TransformType::ParametersDimension ); this->GetParameters( &affine_params[0] ); transform->SetParameters( affine_params ); base_transform = transform; } // Rigid else { typedef itk::Euler3DTransform< double > RigidTransformType; RigidTransformType::Pointer rtransform = RigidTransformType::New(); RigidTransformType::ParametersType rigid_params( RigidTransformType::ParametersDimension ); this->GetParameters( &rigid_params[0] ); rtransform->SetParameters( rigid_params ); base_transform = rtransform; } typename ResampleImageFilterType::Pointer resampler = ResampleImageFilterType::New(); resampler->SetInterpolator( linear_interpolator ); if( m_UseWindowedSincInterpolator ) resampler->SetInterpolator( sinc_interpolator ); if ( m_UseNearestNeighborInterpolator) resampler->SetInterpolator ( nn_interpolator ); //resampler->SetNumberOfThreads(1); resampler->SetInput( itkImage ); resampler->SetTransform( base_transform ); resampler->SetReferenceImage( reference_image ); resampler->UseReferenceImageOn(); resampler->Update(); mitk::GrabItkImageMemory( resampler->GetOutput(), outputImage); } diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h index 97b7e06792..4b0b84fad9 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h @@ -1,212 +1,212 @@ /*=================================================================== 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 MITKPYRAMIDREGISTRATIONMETHODHELPER_H #define MITKPYRAMIDREGISTRATIONMETHODHELPER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkImageAccessByItk.h" /** * @brief Provides same functionality as \a AccessTwoImagesFixedDimensionByItk for a subset of types * * For now, the subset defined is only short and float. */ #define AccessTwoImagesFixedDimensionTypeSubsetByItk(mitkImage1, mitkImage2, itkImageTypeFunction, dimension) \ { \ const mitk::PixelType& pixelType1 = mitkImage1->GetPixelType(); \ const mitk::PixelType& pixelType2 = mitkImage2->GetPixelType(); \ const mitk::Image* constImage1 = mitkImage1; \ const mitk::Image* constImage2 = mitkImage2; \ mitk::Image* nonConstImage1 = const_cast(constImage1); \ mitk::Image* nonConstImage2 = const_cast(constImage2); \ nonConstImage1->Update(); \ nonConstImage2->Update(); \ _checkSpecificDimension(mitkImage1, (dimension)); \ _checkSpecificDimension(mitkImage2, (dimension)); \ _accessTwoImagesByItkForEach(itkImageTypeFunction, ((short, dimension))((unsigned short, dimension))((float, dimension))((double, dimension)), ((short, dimension))((unsigned short, dimension))((float, dimension))((double, dimension)) ) \ { \ std::string msg("Pixel type "); \ msg.append(pixelType1.GetComponentTypeAsString() ); \ msg.append(" or pixel type "); \ msg.append(pixelType2.GetComponentTypeAsString() ); \ msg.append(" is not in " MITK_PP_STRINGIZE(MITK_ACCESSBYITK_TYPES_DIMN_SEQ(dimension))); \ throw mitk::AccessByItkException(msg); \ } \ } /** * @brief The PyramidOptControlCommand class stears the step lenght of the * gradient descent optimizer in multi-scale registration methods */ template class PyramidOptControlCommand : public itk::Command { public: typedef itk::RegularStepGradientDescentOptimizer OptimizerType; mitkClassMacro(PyramidOptControlCommand, itk::Command) itkFactorylessNewMacro(Self) itkCloneMacro(Self) void Execute(itk::Object *caller, const itk::EventObject & /*event*/) { RegistrationType* registration = dynamic_cast< RegistrationType* >( caller ); if( registration == NULL) return; MITK_DEBUG << "\t - Pyramid level " << registration->GetCurrentLevel(); if( registration->GetCurrentLevel() == 0 ) { MITK_WARN("OptCommand") << "Cast to registration failed"; return; } OptimizerType* optimizer = dynamic_cast< OptimizerType* >(registration->GetOptimizer()); if( optimizer == NULL) { MITK_WARN("OptCommand") << "Cast to optimizer failed"; return; } - MITK_INFO /*<< optimizer->GetStopConditionDescription() << "\n"*/ + MITK_DEBUG /*<< optimizer->GetStopConditionDescription() << "\n"*/ << optimizer->GetValue() << " : " << optimizer->GetCurrentPosition(); optimizer->SetMaximumStepLength( optimizer->GetMaximumStepLength() * 0.25f ); optimizer->SetMinimumStepLength( optimizer->GetMinimumStepLength() * 0.1f ); // optimizer->SetNumberOfIterations( optimizer->GetNumberOfIterations() * 1.5f ); } void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/){} }; #include template class PyramidOptControlCommandv4 : public itk::Command { public: typedef itk::GradientDescentLineSearchOptimizerv4 OptimizerType; mitkClassMacro(PyramidOptControlCommandv4, itk::Command) itkFactorylessNewMacro(Self) itkCloneMacro(Self) void Execute(itk::Object *caller, const itk::EventObject & /*event*/) { RegistrationType* registration = dynamic_cast< RegistrationType* >( caller ); if( registration == NULL) return; MITK_DEBUG << "\t - Pyramid level " << registration->GetCurrentLevel(); if( registration->GetCurrentLevel() == 0 ) return; OptimizerType* optimizer = dynamic_cast< OptimizerType* >( registration->GetOptimizer() ); if( optimizer == NULL) { MITK_WARN("OptCommand4") << "Cast to optimizer failed"; return; } optimizer->SetNumberOfIterations( optimizer->GetNumberOfIterations() * 2.5 ); optimizer->SetMaximumStepSizeInPhysicalUnits( optimizer->GetMaximumStepSizeInPhysicalUnits() * 0.4); MITK_INFO("Pyramid.Command.Iter") << optimizer->GetNumberOfIterations(); MITK_INFO("Pyramid.Command.MaxStep") << optimizer->GetMaximumStepSizeInPhysicalUnits(); } void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/){} }; template class OptimizerIterationCommand : public itk::Command { public: mitkClassMacro(OptimizerIterationCommand, itk::Command) itkFactorylessNewMacro(Self) itkCloneMacro(Self) void Execute(itk::Object *caller, const itk::EventObject & /*event*/) { OptimizerType* optimizer = dynamic_cast< OptimizerType* >( caller ); unsigned int currentIter = optimizer->GetCurrentIteration(); MITK_INFO << "[" << currentIter << "] : " << optimizer->GetValue() << " : " << optimizer->GetCurrentPosition(); } void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/) { } }; template class OptimizerIterationCommandv4 : public itk::Command { public: itkNewMacro( OptimizerIterationCommandv4 ) void Execute(itk::Object *object, const itk::EventObject & event) { OptimizerType* optimizer = dynamic_cast< OptimizerType* >( object ); if( typeid( event ) != typeid( itk::IterationEvent ) ) { return; } unsigned int currentIter = optimizer->GetCurrentIteration(); MITK_INFO << "[" << currentIter << "] : " << optimizer->GetCurrentMetricValue() << " : " << optimizer->GetMetric()->GetParameters() ; //<< " : " << optimizer->GetScales(); } void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/) { } }; #endif // MITKPYRAMIDREGISTRATIONMETHODHELPER_H diff --git a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp index 09443b53e8..9d463749d1 100644 --- a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp @@ -1,404 +1,410 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDiffusionPropertyHelper.h" #include #include #include #include const std::string mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME = "meta.GradientDirections"; const std::string mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME = "meta.OriginalGradientDirections"; const std::string mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME = "meta.MeasurementFrame"; const std::string mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME = "meta.ReferenceBValue"; const std::string mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME = "BValueMap"; mitk::DiffusionPropertyHelper::DiffusionPropertyHelper() { } mitk::DiffusionPropertyHelper::DiffusionPropertyHelper( mitk::Image* inputImage) : m_Image( inputImage ) { // Update props } mitk::DiffusionPropertyHelper::~DiffusionPropertyHelper() { } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::CalcAveragedDirectionSet(double precision, GradientDirectionsContainerType::Pointer directions) { // save old and construct new direction container GradientDirectionsContainerType::Pointer newDirections = GradientDirectionsContainerType::New(); // fill new direction container for(GradientDirectionsContainerType::ConstIterator gdcitOld = directions->Begin(); gdcitOld != directions->End(); ++gdcitOld) { // already exists? bool found = false; for(GradientDirectionsContainerType::ConstIterator gdcitNew = newDirections->Begin(); gdcitNew != newDirections->End(); ++gdcitNew) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { found = true; break; } } // if not found, add it to new container if(!found) { newDirections->push_back(gdcitOld.Value()); } } return newDirections; } void mitk::DiffusionPropertyHelper::AverageRedundantGradients(double precision) { mitk::GradientDirectionsProperty* DirectionsProperty = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ); GradientDirectionsContainerType::Pointer oldDirs = DirectionsProperty->GetGradientDirectionsContainer(); GradientDirectionsContainerType::Pointer newDirs = CalcAveragedDirectionSet(precision, oldDirs); // if sizes equal, we do not need to do anything in this function if(oldDirs->size() == newDirs->size()) return; // new image ImageType::Pointer oldImage = ImageType::New(); mitk::CastToItkImage( m_Image, oldImage); ImageType::Pointer newITKImage = ImageType::New(); newITKImage->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing newITKImage->SetOrigin( oldImage->GetOrigin() ); // Set the image origin newITKImage->SetDirection( oldImage->GetDirection() ); // Set the image direction newITKImage->SetLargestPossibleRegion( oldImage->GetLargestPossibleRegion() ); newITKImage->SetVectorLength( newDirs->size() ); newITKImage->SetBufferedRegion( oldImage->GetLargestPossibleRegion() ); newITKImage->Allocate(); // average image data that corresponds to identical directions itk::ImageRegionIterator< ImageType > newIt(newITKImage, newITKImage->GetLargestPossibleRegion()); newIt.GoToBegin(); itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); oldIt.GoToBegin(); // initial new value of voxel ImageType::PixelType newVec; newVec.SetSize(newDirs->size()); newVec.AllocateElements(newDirs->size()); // find which gradients should be averaged GradientDirectionsContainerType::Pointer oldDirections = oldDirs; std::vector > dirIndices; for(GradientDirectionsContainerType::ConstIterator gdcitNew = newDirs->Begin(); gdcitNew != newDirs->End(); ++gdcitNew) { dirIndices.push_back(std::vector(0)); for(GradientDirectionsContainerType::ConstIterator gdcitOld = oldDirs->Begin(); gdcitOld != oldDirections->End(); ++gdcitOld) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { //MITK_INFO << gdcitNew.Value() << " " << gdcitOld.Value(); dirIndices[gdcitNew.Index()].push_back(gdcitOld.Index()); } } } //int ind1 = -1; while(!newIt.IsAtEnd()) { // progress //typename ImageType::IndexType ind = newIt.GetIndex(); //ind1 = ind.m_Index[2]; // init new vector with zeros newVec.Fill(0.0); // the old voxel value with duplicates ImageType::PixelType oldVec = oldIt.Get(); for(unsigned int i=0; iSetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( newDirs ) ); m_Image->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( newDirs ) ); ApplyMeasurementFrame(); UpdateBValueMap(); std::cout << std::endl; } void mitk::DiffusionPropertyHelper::ApplyMeasurementFrame() { if( m_Image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).IsNull() ) { return; } GradientDirectionsContainerType::Pointer originalDirections = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); MeasurementFrameType measurementFrame = GetMeasurementFrame(m_Image); GradientDirectionsContainerType::Pointer directions = GradientDirectionsContainerType::New(); if( originalDirections.IsNull() || ( originalDirections->size() == 0 ) ) { // original direction container was not set return; } - GradientDirectionsContainerType::Pointer direction = GradientDirectionsContainerType::New(); int c = 0; for(GradientDirectionsContainerType::ConstIterator gdcit = originalDirections->Begin(); gdcit != originalDirections->End(); ++gdcit) { vnl_vector vec = gdcit.Value(); vec = vec.pre_multiply(measurementFrame); + MITK_INFO << gdcit.Value(); directions->InsertElement(c, vec); c++; } m_Image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( directions ) ); } void mitk::DiffusionPropertyHelper::UpdateBValueMap() { BValueMapType b_ValueMap; if(m_Image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).IsNull()) { } else { b_ValueMap = static_cast(m_Image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); } if(!b_ValueMap.empty()) { b_ValueMap.clear(); } if( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).IsNotNull() ) { GradientDirectionsContainerType::Pointer directions = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); GradientDirectionsContainerType::ConstIterator gdcit; for( gdcit = directions->Begin(); gdcit != directions->End(); ++gdcit) { + MITK_INFO << gdcit.Value(); b_ValueMap[GetB_Value(gdcit.Index())].push_back(gdcit.Index()); } } m_Image->SetProperty( mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New( b_ValueMap ) ); } bool mitk::DiffusionPropertyHelper::AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision) { GradientDirectionType diff = g1 - g2; GradientDirectionType diff2 = g1 + g2; return diff.two_norm() < precision || diff2.two_norm() < precision; } float mitk::DiffusionPropertyHelper::GetB_Value(unsigned int i) { GradientDirectionsContainerType::Pointer directions = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); float b_value = static_cast(m_Image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); if(i > directions->Size()-1) return -1; if(directions->ElementAt(i).one_norm() <= 0.0) { return 0; } else { double twonorm = directions->ElementAt(i).two_norm(); double bval = b_value*twonorm*twonorm; if (bval<0) bval = ceil(bval - 0.5); else bval = floor(bval + 0.5); return bval; } } void mitk::DiffusionPropertyHelper::InitializeImage() { this->ApplyMeasurementFrame(); this->UpdateBValueMap(); // initialize missing properties mitk::MeasurementFrameProperty::Pointer mf = dynamic_cast( m_Image->GetProperty(MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer()); if( mf.IsNull() ) { //no measurement frame present, identity is assumed MeasurementFrameType identity; identity.set_identity(); m_Image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( identity )); } } +bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(const mitk::DataNode* node) +{ + return IsDiffusionWeightedImage(dynamic_cast(node->GetData())); +} + bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(const mitk::Image * image) { bool isDiffusionWeightedImage( true ); if( image == NULL ) { isDiffusionWeightedImage = false; } if( isDiffusionWeightedImage ) { mitk::FloatProperty::Pointer referenceBValue = dynamic_cast(image->GetProperty(REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer()); if( referenceBValue.IsNull() ) { isDiffusionWeightedImage = false; } } unsigned int gradientDirections( 0 ); if( isDiffusionWeightedImage ) { mitk::GradientDirectionsProperty::Pointer gradientDirectionsProperty = dynamic_cast(image->GetProperty(GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer()); if( gradientDirectionsProperty.IsNull() ) { isDiffusionWeightedImage = false; } else { gradientDirections = gradientDirectionsProperty->GetGradientDirectionsContainer()->size(); } } if( isDiffusionWeightedImage ) { unsigned int components = image->GetPixelType().GetNumberOfComponents(); if( components != gradientDirections ) { isDiffusionWeightedImage = false; } } return isDiffusionWeightedImage; } const mitk::DiffusionPropertyHelper::BValueMapType & mitk::DiffusionPropertyHelper::GetBValueMap(const mitk::Image *image) { return dynamic_cast(image->GetProperty(BVALUEMAPPROPERTYNAME.c_str()).GetPointer())->GetBValueMap(); } float mitk::DiffusionPropertyHelper::GetReferenceBValue(const mitk::Image *image) { return dynamic_cast(image->GetProperty(REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer())->GetValue(); } const mitk::DiffusionPropertyHelper::MeasurementFrameType & mitk::DiffusionPropertyHelper::GetMeasurementFrame(const mitk::Image *image) { mitk::MeasurementFrameProperty::Pointer mf = dynamic_cast( image->GetProperty(MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer()); if( mf.IsNull() ) { //no measurement frame present, identity is assumed MeasurementFrameType identity; identity.set_identity(); mf = mitk::MeasurementFrameProperty::New( identity ); } return mf->GetMeasurementFrame(); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(const mitk::Image *image) { return dynamic_cast(image->GetProperty(ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetGradientContainer(const mitk::Image *image) { return dynamic_cast(image->GetProperty(GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); } bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage() const { return IsDiffusionWeightedImage(m_Image); } const mitk::DiffusionPropertyHelper::BValueMapType &mitk::DiffusionPropertyHelper::GetBValueMap() const { return GetBValueMap(m_Image); } float mitk::DiffusionPropertyHelper::GetReferenceBValue() const { return GetReferenceBValue(m_Image); } const mitk::DiffusionPropertyHelper::MeasurementFrameType & mitk::DiffusionPropertyHelper::GetMeasurementFrame() const { return GetMeasurementFrame(m_Image); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetOriginalGradientContainer() const { return GetOriginalGradientContainer(m_Image); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetGradientContainer() const { return GetGradientContainer(m_Image); } diff --git a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h index 94eea676fa..be48d90e8c 100644 --- a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h +++ b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h @@ -1,133 +1,135 @@ /*=================================================================== 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 MITKDIFFUSIONPROPERTYHELPER_H #define MITKDIFFUSIONPROPERTYHELPER_H #include #include #include #include #include +#include namespace mitk { /** \brief Helper class for mitk::Images containing diffusion weighted data * * This class takes a pointer to a mitk::Image containing diffusion weighted information and provides * functions to manipulate the diffusion meta-data. Will log an error if required information is * missing. */ class MITKDIFFUSIONCORE_EXPORT DiffusionPropertyHelper { public: typedef short DiffusionPixelType; typedef mitk::BValueMapProperty::BValueMap BValueMapType; typedef GradientDirectionsProperty::GradientDirectionType GradientDirectionType; typedef GradientDirectionsProperty::GradientDirectionsContainerType GradientDirectionsContainerType; typedef mitk::MeasurementFrameProperty::MeasurementFrameType MeasurementFrameType; typedef itk::VectorImage< DiffusionPixelType, 3> ImageType; static const std::string GRADIENTCONTAINERPROPERTYNAME; static const std::string ORIGINALGRADIENTCONTAINERPROPERTYNAME; static const std::string MEASUREMENTFRAMEPROPERTYNAME; static const std::string REFERENCEBVALUEPROPERTYNAME; static const std::string BVALUEMAPPROPERTYNAME; /// Public constructor, takes a mitk::Image pointer as argument DiffusionPropertyHelper( mitk::Image* inputImage ); ~DiffusionPropertyHelper(); /** \brief Decide whether a provided image is a valid diffusion weighted image * * An image will be considered a valid diffusion weighted image if the following are true * - It has a reference b value * - It has a gradient directions property * - The number of gradients directions matches the number of components of the image * * This does not guarantee that the data is sensible or accurate, it just verfies that it * meets the formal requirements to possibly be a valid diffusion weighted image. */ static bool IsDiffusionWeightedImage(const mitk::Image *); + static bool IsDiffusionWeightedImage(const mitk::DataNode* node); /// Convenience method to get the BValueMap static const BValueMapType & GetBValueMap(const mitk::Image *); /// Convenience method to get the BValue static float GetReferenceBValue(const mitk::Image *); /** \brief Convenience method to get the measurement frame * * This method will return the measurement frame of the image. * * \note If the image has no associated measurement frame the identity will be returned. */ static const MeasurementFrameType & GetMeasurementFrame(const mitk::Image *); /// Convenience method to get the original gradient directions static GradientDirectionsContainerType::Pointer GetOriginalGradientContainer(const mitk::Image *); /// Convenience method to get the gradient directions static GradientDirectionsContainerType::Pointer GetGradientContainer(const mitk::Image *); const BValueMapType & GetBValueMap() const; float GetReferenceBValue() const; const MeasurementFrameType & GetMeasurementFrame() const; GradientDirectionsContainerType::Pointer GetOriginalGradientContainer() const; GradientDirectionsContainerType::Pointer GetGradientContainer() const; bool IsDiffusionWeightedImage() const; void AverageRedundantGradients(double precision); /** \brief Make certain the owned image is up to date with all necessary properties * * This function will generate the B Value map and copy all properties to the owned image. */ void InitializeImage(); GradientDirectionsContainerType::Pointer CalcAveragedDirectionSet(double precision, GradientDirectionsContainerType::Pointer directions); protected: DiffusionPropertyHelper(); /** * \brief Apply the previouse set MeasurementFrame to all gradients in the GradientsDirectionContainer (m_Directions) * * \warning first set the MeasurementFrame */ void ApplyMeasurementFrame(); /** * \brief Update the BValueMap (m_B_ValueMap) using the current gradient directions (m_Directions) * * \warning Have to be called after each manipulation on the GradientDirectionContainer * !especially after manipulation of the m_Directions (GetDirections()) container via pointer access! */ void UpdateBValueMap(); /// Determines whether gradients can be considered to be equal bool AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision); /// Get the b value belonging to an index float GetB_Value(unsigned int i); mitk::Image* m_Image; }; } #endif diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx index c6bc7b0d53..91bb189c78 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx @@ -1,881 +1,882 @@ /*=================================================================== 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 __mitkOdfVtkMapper2D_txx__ #define __mitkOdfVtkMapper2D_txx__ #include "mitkOdfVtkMapper2D.h" #include "mitkDataNode.h" #include "mitkBaseRenderer.h" #include "mitkMatrixConvert.h" #include "mitkGeometry3D.h" #include "mitkTimeGeometry.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkProperties.h" #include "mitkTensorImage.h" #include "vtkSphereSource.h" #include "vtkPropCollection.h" #include "vtkMaskedGlyph3D.h" #include "vtkGlyph2D.h" #include "vtkGlyph3D.h" #include "vtkMaskedProgrammableGlyphFilter.h" #include "vtkImageData.h" #include "vtkLinearTransform.h" #include "vtkCamera.h" #include "vtkPointData.h" #include "vtkTransformPolyDataFilter.h" #include "vtkTransform.h" #include "vtkOdfSource.h" #include "vtkDoubleArray.h" #include "vtkLookupTable.h" #include "vtkProperty.h" #include "vtkPolyDataNormals.h" #include "vtkLight.h" #include "vtkLightCollection.h" #include "vtkMath.h" #include "vtkFloatArray.h" #include "vtkDelaunay2D.h" #include "vtkMapper.h" #include "vtkRenderer.h" #include "itkOrientationDistributionFunction.h" #include "itkFixedArray.h" #include #include "vtkOpenGLRenderer.h" #define _USE_MATH_DEFINES #include template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfTransform = vtkSmartPointer::New(); template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfSource = vtkSmartPointer::New(); template float mitk::OdfVtkMapper2D::m_Scaling; template int mitk::OdfVtkMapper2D::m_Normalization; template int mitk::OdfVtkMapper2D::m_ScaleBy; template float mitk::OdfVtkMapper2D::m_IndexParam1; template float mitk::OdfVtkMapper2D::m_IndexParam2; #define ODF_MAPPER_PI M_PI template mitk::OdfVtkMapper2D::LocalStorage::LocalStorage() { m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes[0]->AddInputData(vtkPolyData::New()); m_OdfsPlanes[1]->AddInputData(vtkPolyData::New()); m_OdfsPlanes[2]->AddInputData(vtkPolyData::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors[0]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[1]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[2]->GetProperty()->SetInterpolationToGouraud(); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); vtkLookupTable *lut = vtkLookupTable::New(); m_OdfsMappers[0]->SetLookupTable(lut); m_OdfsMappers[1]->SetLookupTable(lut); m_OdfsMappers[2]->SetLookupTable(lut); m_OdfsActors[0]->SetMapper(m_OdfsMappers[0]); m_OdfsActors[1]->SetMapper(m_OdfsMappers[1]); m_OdfsActors[2]->SetMapper(m_OdfsMappers[2]); } template mitk::OdfVtkMapper2D ::OdfVtkMapper2D() { m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters[0]->SetCutFunction( m_Planes[0] ); m_Cutters[0]->GenerateValues( 1, 0, 1 ); m_Cutters[1]->SetCutFunction( m_Planes[1] ); m_Cutters[1]->GenerateValues( 1, 0, 1 ); m_Cutters[2]->SetCutFunction( m_Planes[2] ); m_Cutters[2]->GenerateValues( 1, 0, 1 ); // Windowing the cutted planes in direction 1 m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1[0]->SetClipFunction( m_ThickPlanes1[0] ); m_Clippers1[1]->SetClipFunction( m_ThickPlanes1[1] ); m_Clippers1[2]->SetClipFunction( m_ThickPlanes1[2] ); // Windowing the cutted planes in direction 2 m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2[0]->SetClipFunction( m_ThickPlanes2[0] ); m_Clippers2[1]->SetClipFunction( m_ThickPlanes2[1] ); m_Clippers2[2]->SetClipFunction( m_ThickPlanes2[2] ); m_ShowMaxNumber = 500; } template mitk::OdfVtkMapper2D ::~OdfVtkMapper2D() { } template mitk::Image* mitk::OdfVtkMapper2D ::GetInput() { return static_cast ( m_DataNode->GetData() ); } template vtkProp* mitk::OdfVtkMapper2D ::GetVtkProp(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); return localStorage->m_PropAssemblies[GetIndex(renderer)]; } template int mitk::OdfVtkMapper2D ::GetIndex(mitk::BaseRenderer* renderer) { if(!strcmp(renderer->GetName(),"stdmulti.widget1")) return 0; if(!strcmp(renderer->GetName(),"stdmulti.widget2")) return 1; if(!strcmp(renderer->GetName(),"stdmulti.widget3")) return 2; return 0; } template void mitk::OdfVtkMapper2D ::GlyphMethod(void *arg) { vtkMaskedProgrammableGlyphFilter* pfilter=(vtkMaskedProgrammableGlyphFilter*)arg; double point[3]; double debugpoint[3]; pfilter->GetPoint(point); pfilter->GetPoint(debugpoint); itk::Point p(point); Vector3D spacing = pfilter->GetGeometry()->GetSpacing(); p[0] /= spacing[0]; p[1] /= spacing[1]; p[2] /= spacing[2]; mitk::Point3D p2; pfilter->GetGeometry()->IndexToWorld( p, p2 ); point[0] = p2[0]; point[1] = p2[1]; point[2] = p2[2]; vtkPointData* data = pfilter->GetPointData(); vtkDataArray* odfvals = data->GetArray("vector"); vtkIdType id = pfilter->GetPointId(); m_OdfTransform->Identity(); m_OdfTransform->Translate(point[0],point[1],point[2]); typedef itk::OrientationDistributionFunction OdfType; OdfType odf; if(odfvals->GetNumberOfComponents()==6) { float tensorelems[6] = { (float)odfvals->GetComponent(id,0), (float)odfvals->GetComponent(id,1), (float)odfvals->GetComponent(id,2), (float)odfvals->GetComponent(id,3), (float)odfvals->GetComponent(id,4), (float)odfvals->GetComponent(id,5), }; itk::DiffusionTensor3D tensor(tensorelems); odf.InitFromTensor(tensor); } else { for(int i=0; iGetComponent(id,i); } switch(m_ScaleBy) { case ODFSB_NONE: m_OdfSource->SetScale(m_Scaling); break; case ODFSB_GFA: m_OdfSource->SetScale(m_Scaling*odf.GetGeneralizedGFA(m_IndexParam1, m_IndexParam2)); break; case ODFSB_PC: m_OdfSource->SetScale(m_Scaling*odf.GetPrincipleCurvature(m_IndexParam1, m_IndexParam2, 0)); break; } m_OdfSource->SetNormalization(m_Normalization); m_OdfSource->SetOdf(odf); m_OdfSource->Modified(); } template typename mitk::OdfVtkMapper2D::OdfDisplayGeometry mitk::OdfVtkMapper2D ::MeasureDisplayedGeometry(mitk::BaseRenderer* renderer) { PlaneGeometry::ConstPointer worldPlaneGeometry = renderer->GetCurrentWorldPlaneGeometry(); // set up the cutter orientation according to the current geometry of // the renderers plane double vp[ 3 ], vnormal[ 3 ]; Point3D point = worldPlaneGeometry->GetOrigin(); Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( point.GetVnlVector(), vp ); vnl2vtk( normal.GetVnlVector(), vnormal ); mitk::DisplayGeometry::Pointer dispGeometry = renderer->GetDisplayGeometry(); mitk::Vector2D size = dispGeometry->GetSizeInMM(); mitk::Vector2D origin = dispGeometry->GetOriginInMM(); // // |------O------| // | d2 | // L d1 M | // | | // |-------------| // mitk::Vector2D M; mitk::Vector2D L; mitk::Vector2D O; M[0] = origin[0] + size[0]/2; M[1] = origin[1] + size[1]/2; L[0] = origin[0]; L[1] = origin[1] + size[1]/2; O[0] = origin[0] + size[0]/2; O[1] = origin[1] + size[1]; mitk::Point2D point1; point1[0] = M[0]; point1[1] = M[1]; mitk::Point3D M3D; dispGeometry->Map(point1, M3D); point1[0] = L[0]; point1[1] = L[1]; mitk::Point3D L3D; dispGeometry->Map(point1, L3D); point1[0] = O[0]; point1[1] = O[1]; mitk::Point3D O3D; dispGeometry->Map(point1, O3D); double d1 = sqrt((M3D[0]-L3D[0])*(M3D[0]-L3D[0]) + (M3D[1]-L3D[1])*(M3D[1]-L3D[1]) + (M3D[2]-L3D[2])*(M3D[2]-L3D[2])); double d2 = sqrt((M3D[0]-O3D[0])*(M3D[0]-O3D[0]) + (M3D[1]-O3D[1])*(M3D[1]-O3D[1]) + (M3D[2]-O3D[2])*(M3D[2]-O3D[2])); double d = d1>d2 ? d1 : d2; d = d2; OdfDisplayGeometry retval; retval.vp[0] = vp[0]; retval.vp[1] = vp[1]; retval.vp[2] = vp[2]; retval.vnormal[0] = vnormal[0]; retval.vnormal[1] = vnormal[1]; retval.vnormal[2] = vnormal[2]; retval.normal[0] = normal[0]; retval.normal[1] = normal[1]; retval.normal[2] = normal[2]; retval.d = d; retval.d1 = d1; retval.d2 = d2; retval.M3D[0] = M3D[0]; retval.M3D[1] = M3D[1]; retval.M3D[2] = M3D[2]; retval.L3D[0] = L3D[0]; retval.L3D[1] = L3D[1]; retval.L3D[2] = L3D[2]; retval.O3D[0] = O3D[0]; retval.O3D[1] = O3D[1]; retval.O3D[2] = O3D[2]; retval.vp_original[0] = vp[0]; retval.vp_original[1] = vp[1]; retval.vp_original[2] = vp[2]; retval.vnormal_original[0] = vnormal[0]; retval.vnormal_original[1] = vnormal[1]; retval.vnormal_original[2] = vnormal[2]; retval.size[0] = size[0]; retval.size[1] = size[1]; retval.origin[0] = origin[0]; retval.origin[1] = origin[1]; return retval; } template void mitk::OdfVtkMapper2D ::Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); int index = GetIndex(renderer); vtkSmartPointer inversetransform = vtkSmartPointer::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); // vtk works in axis align coords // thus the normal also must be axis align, since // we do not allow arbitrary cutting through volume // // vnormal should already be axis align, but in order // to get rid of precision effects, we set the two smaller // components to zero here int dims[3]; m_VtkImage->GetDimensions(dims); double spac[3]; m_VtkImage->GetSpacing(spac); if(fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[0]/spac[0]) < 0.4) dispGeo.vp[0] = 0.4*spac[0]; if(fabs(dispGeo.vp[0]/spac[0]) > (dims[0]-1)-0.4) dispGeo.vp[0] = ((dims[0]-1)-0.4)*spac[0]; dispGeo.vnormal[1] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[0]) && fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[1]/spac[1]) < 0.4) dispGeo.vp[1] = 0.4*spac[1]; if(fabs(dispGeo.vp[1]/spac[1]) > (dims[1]-1)-0.4) dispGeo.vp[1] = ((dims[1]-1)-0.4)*spac[1]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[0]) ) { if(fabs(dispGeo.vp[2]/spac[2]) < 0.4) dispGeo.vp[2] = 0.4*spac[2]; if(fabs(dispGeo.vp[2]/spac[2]) > (dims[2]-1)-0.4) dispGeo.vp[2] = ((dims[2]-1)-0.4)*spac[2]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[1] = 0; } m_Planes[index]->SetTransform( (vtkAbstractTransform*)NULL ); m_Planes[index]->SetOrigin( dispGeo.vp ); m_Planes[index]->SetNormal( dispGeo.vnormal ); vtkSmartPointer points; vtkSmartPointer tmppoints; vtkSmartPointer polydata; vtkSmartPointer pointdata; vtkSmartPointer delaunay; vtkSmartPointer cuttedPlane; // the cutter only works if we do not have a 2D-image // or if we have a 2D-image and want to see the whole image. // // for side views of 2D-images, we need some special treatment if(!( (dims[0] == 1 && dispGeo.vnormal[0] != 0) || (dims[1] == 1 && dispGeo.vnormal[1] != 0) || (dims[2] == 1 && dispGeo.vnormal[2] != 0) )) { m_Cutters[index]->SetCutFunction( m_Planes[index] ); m_Cutters[index]->SetInputData( m_VtkImage ); m_Cutters[index]->Update(); cuttedPlane = m_Cutters[index]->GetOutput(); } else { // cutting of a 2D-Volume does not work, // so we have to build up our own polydata object cuttedPlane = vtkPolyData::New(); points = vtkPoints::New(); points->SetNumberOfPoints(m_VtkImage->GetNumberOfPoints()); for(int i=0; iGetNumberOfPoints(); i++) { points->SetPoint(i, m_VtkImage->GetPoint(i)); } cuttedPlane->SetPoints(points); pointdata = vtkFloatArray::New(); int comps = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfComponents(); pointdata->SetNumberOfComponents(comps); int tuples = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfTuples(); pointdata->SetNumberOfTuples(tuples); for(int i=0; iSetTuple(i,m_VtkImage->GetPointData()->GetScalars()->GetTuple(i)); pointdata->SetName( "vector" ); cuttedPlane->GetPointData()->AddArray(pointdata); int nZero1, nZero2; if(dims[0]==1) { nZero1 = 1; nZero2 = 2; } else if(dims[1]==1) { nZero1 = 0; nZero2 = 2; } else { nZero1 = 0; nZero2 = 1; } tmppoints = vtkPoints::New(); for(int j=0; jGetNumberOfPoints(); j++){ double pt[3]; m_VtkImage->GetPoint(j,pt); tmppoints->InsertNextPoint(pt[nZero1],pt[nZero2],0); } polydata = vtkPolyData::New(); polydata->SetPoints( tmppoints ); delaunay = vtkDelaunay2D::New(); delaunay->SetInputData( polydata ); delaunay->Update(); vtkCellArray* polys = delaunay->GetOutput()->GetPolys(); cuttedPlane->SetPolys(polys); } if(cuttedPlane->GetNumberOfPoints()) { // WINDOWING HERE inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.O3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.O3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.O3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes1[index]->count = 0; m_ThickPlanes1[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes1[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes1[index]->SetThickness(dispGeo.d2); m_Clippers1[index]->SetClipFunction( m_ThickPlanes1[index] ); m_Clippers1[index]->SetInputData( cuttedPlane ); m_Clippers1[index]->SetInsideOut(1); m_Clippers1[index]->Update(); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.L3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.L3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.L3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes2[index]->count = 0; m_ThickPlanes2[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes2[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes2[index]->SetThickness(dispGeo.d1); m_Clippers2[index]->SetClipFunction( m_ThickPlanes2[index] ); m_Clippers2[index]->SetInputData( m_Clippers1[index]->GetOutput() ); m_Clippers2[index]->SetInsideOut(1); m_Clippers2[index]->Update(); cuttedPlane = m_Clippers2[index]->GetOutput (); if(cuttedPlane->GetNumberOfPoints()) { localStorage->m_OdfsPlanes[index]->RemoveAllInputs(); vtkSmartPointer normals = vtkSmartPointer::New(); normals->SetInputConnection( m_OdfSource->GetOutputPort() ); normals->SplittingOff(); normals->ConsistencyOff(); normals->AutoOrientNormalsOff(); normals->ComputePointNormalsOn(); normals->ComputeCellNormalsOff(); normals->FlipNormalsOff(); normals->NonManifoldTraversalOff(); vtkSmartPointer trans = vtkSmartPointer::New(); trans->SetInputConnection( normals->GetOutputPort() ); trans->SetTransform(m_OdfTransform); vtkSmartPointer glyphGenerator = vtkSmartPointer::New(); glyphGenerator->SetMaximumNumberOfPoints(std::min(m_ShowMaxNumber,(int)cuttedPlane->GetNumberOfPoints())); glyphGenerator->SetRandomMode(0); glyphGenerator->SetUseMaskPoints(1); glyphGenerator->SetSourceConnection(trans->GetOutputPort() ); glyphGenerator->SetInput(cuttedPlane); glyphGenerator->SetColorModeToColorBySource(); glyphGenerator->SetInputArrayToProcess(0,0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector"); glyphGenerator->SetGeometry(this->GetDataNode()->GetData()->GetGeometry()); glyphGenerator->SetGlyphMethod(&(GlyphMethod),(void *)glyphGenerator); try { glyphGenerator->Update(); } catch( itk::ExceptionObject& err ) { std::cout << err << std::endl; } localStorage->m_OdfsPlanes[index]->AddInputConnection(glyphGenerator->GetOutputPort()); localStorage->m_OdfsPlanes[index]->Update(); } } localStorage->m_PropAssemblies[index]->VisibilityOn(); if(localStorage->m_PropAssemblies[index]->GetParts()->IsItemPresent(localStorage->m_OdfsActors[index])) localStorage->m_PropAssemblies[index]->RemovePart(localStorage->m_OdfsActors[index]); localStorage->m_OdfsMappers[index]->SetInputData(localStorage->m_OdfsPlanes[index]->GetOutput()); localStorage->m_PropAssemblies[index]->AddPart(localStorage->m_OdfsActors[index]); } template bool mitk::OdfVtkMapper2D ::IsVisibleOdfs(mitk::BaseRenderer* renderer) { mitk::Image::Pointer input = const_cast(this->GetInput()); const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); if(inputTimeGeometry==NULL || inputTimeGeometry->CountTimeSteps()==0 || !inputTimeGeometry->IsValidTimeStep(this->GetTimestep())) return false; if(this->IsPlaneRotated(renderer)) return false; bool retval = false; switch(GetIndex(renderer)) { case 0: GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_T"); break; case 1: GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_S"); break; case 2: GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_C"); break; } return retval; } template void mitk::OdfVtkMapper2D ::MitkRenderOverlay(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs( renderer )==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { // adapt cam pos this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); } } template void mitk::OdfVtkMapper2D ::MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::Update(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; mitk::Image::Pointer input = const_cast( this->GetInput() ); if ( input.IsNull() ) return ; std::string classname("TensorImage"); if(classname.compare(input->GetNameOfClass())==0) m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); std::string qclassname("QBallImage"); if(qclassname.compare(input->GetNameOfClass())==0) m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); if( m_VtkImage ) { // make sure, that we have point data with more than 1 component (as vectors) vtkPointData* pointData = m_VtkImage->GetPointData(); if ( pointData == NULL ) { itkWarningMacro( << "m_VtkImage->GetPointData() returns NULL!" ); return ; } if ( pointData->GetNumberOfArrays() == 0 ) { itkWarningMacro( << "m_VtkImage->GetPointData()->GetNumberOfArrays() is 0!" ); return ; } else if ( pointData->GetArray(0)->GetNumberOfComponents() != N && pointData->GetArray(0)->GetNumberOfComponents() != 6 /*for tensor visualization*/) { itkWarningMacro( << "number of components != number of directions in ODF!" ); return; } else if ( pointData->GetArrayName( 0 ) == NULL ) { m_VtkImage->GetPointData()->GetArray(0)->SetName("vector"); } GenerateDataForRenderer(renderer); } else { itkWarningMacro( << "m_VtkImage is NULL!" ); return ; } } template void mitk::OdfVtkMapper2D ::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer); if ( (localStorage->m_LastUpdateTime >= m_DataNode->GetMTime()) //was the node modified? && (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList()->GetMTime()) //was a property modified? && (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList(renderer)->GetMTime()) && dispGeo.Equals(m_LastDisplayGeometry)) return; localStorage->m_LastUpdateTime.Modified(); if(!IsVisibleOdfs(renderer)) { localStorage->m_OdfsActors[0]->VisibilityOff(); localStorage->m_OdfsActors[1]->VisibilityOff(); localStorage->m_OdfsActors[2]->VisibilityOff(); } else { localStorage->m_OdfsActors[0]->VisibilityOn(); localStorage->m_OdfsActors[1]->VisibilityOn(); localStorage->m_OdfsActors[2]->VisibilityOn(); m_OdfSource->SetAdditionalScale(GetMinImageSpacing(GetIndex(renderer))); ApplyPropertySettings(); Slice(renderer, dispGeo); m_LastDisplayGeometry = dispGeo; } } template double mitk::OdfVtkMapper2D::GetMinImageSpacing( int index ) { // Spacing adapted scaling double spacing[3]; m_VtkImage->GetSpacing(spacing); double min = spacing[0]; if(index==0) { min = spacing[0]; min = min > spacing[1] ? spacing[1] : min; } if(index==1) { min = spacing[1]; min = min > spacing[2] ? spacing[2] : min; } if(index==2) { min = spacing[0]; min = min > spacing[2] ? spacing[2] : min; } return min; } template void mitk::OdfVtkMapper2D ::ApplyPropertySettings() { this->GetDataNode()->GetFloatProperty( "Scaling", m_Scaling ); this->GetDataNode()->GetIntProperty( "ShowMaxNumber", m_ShowMaxNumber ); OdfNormalizationMethodProperty* nmp = dynamic_cast(this->GetDataNode()->GetProperty( "Normalization" )); if(nmp) m_Normalization = nmp->GetNormalization(); OdfScaleByProperty* sbp = dynamic_cast(this->GetDataNode()->GetProperty( "ScaleBy" )); if(sbp) m_ScaleBy = sbp->GetScaleBy(); this->GetDataNode()->GetFloatProperty( "IndexParam1", m_IndexParam1); this->GetDataNode()->GetFloatProperty( "IndexParam2", m_IndexParam2); } template bool mitk::OdfVtkMapper2D ::IsPlaneRotated(mitk::BaseRenderer* renderer) { - PlaneGeometry::ConstPointer worldPlaneGeometry = - renderer->GetCurrentWorldPlaneGeometry(); + PlaneGeometry::ConstPointer worldPlaneGeometry = renderer->GetCurrentWorldPlaneGeometry(); double vnormal[ 3 ]; Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( normal.GetVnlVector(), vnormal ); - vtkLinearTransform * vtktransform = - this->GetDataNode()->GetVtkTransform(this->GetTimestep()); - - vtkSmartPointer inversetransform = vtkSmartPointer::New(); - inversetransform->Identity(); - inversetransform->Concatenate(vtktransform->GetLinearInverse()); - double* n = inversetransform->TransformNormal(vnormal); - - int nonZeros = 0; - for (int j=0; j<3; j++) - { - if (fabs(n[j])>mitk::eps){ - nonZeros++; - } - } - if(nonZeros>1) + mitk::Image* currentImage = dynamic_cast( this->GetDataNode()->GetData() ); + if( currentImage == NULL ) + return false; + mitk::Vector3D imageNormal0 = currentImage->GetSlicedGeometry()->GetAxisVector(0); + mitk::Vector3D imageNormal1 = currentImage->GetSlicedGeometry()->GetAxisVector(1); + mitk::Vector3D imageNormal2 = currentImage->GetSlicedGeometry()->GetAxisVector(2); + imageNormal0.Normalize(); + imageNormal1.Normalize(); + imageNormal2.Normalize(); + + double eps = 0.000001; + int test = 0; + if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) + test++; + if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) + test++; + if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) + test++; + if (test==3) return true; - return false; } template void mitk::OdfVtkMapper2D ::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* /*renderer*/, bool /*overwrite*/) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 150 ) ); node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.0 ) ); node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New()); node->SetProperty( "ScaleBy", mitk::OdfScaleByProperty::New()); node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2)); node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1)); node->SetProperty( "visible", mitk::BoolProperty::New( true ) ); node->SetProperty( "VisibleOdfs_T", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_C", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_S", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); } #endif // __mitkOdfVtkMapper2D_txx__ diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkReader.cpp index d0d579f1a5..546cc879de 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkReader.cpp @@ -1,214 +1,214 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkConnectomicsNetworkReader.h" #include "mitkConnectomicsNetworkDefinitions.h" #include #include "itksys/SystemTools.hxx" #include #include "mitkGeometry3D.h" #include #include "mitkDiffusionIOMimeTypes.h" namespace mitk { ConnectomicsNetworkReader::ConnectomicsNetworkReader(const ConnectomicsNetworkReader& other) : mitk::AbstractFileReader(other) { } ConnectomicsNetworkReader::ConnectomicsNetworkReader() - : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_DESCRIPTION() ) + : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE() ), mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_DESCRIPTION() ) { m_ServiceReg = this->RegisterService(); } ConnectomicsNetworkReader::~ConnectomicsNetworkReader() { } std::vector > ConnectomicsNetworkReader::Read() { std::vector > result; std::string location = GetInputLocation(); std::string ext = itksys::SystemTools::GetFilenameLastExtension(location); ext = itksys::SystemTools::LowerCase(ext); if ( location == "") { MITK_ERROR << "No file name specified."; } else if (ext == ".cnf") { try { mitk::ConnectomicsNetwork::Pointer outputNetwork = mitk::ConnectomicsNetwork::New(); TiXmlDocument doc( location ); bool loadOkay = doc.LoadFile(); if(!loadOkay) { mitkThrow() << "Could not open file " << location << " for reading."; } TiXmlHandle hDoc(&doc); TiXmlElement* pElem; TiXmlHandle hRoot(0); pElem = hDoc.FirstChildElement().Element(); // save this for later hRoot = TiXmlHandle(pElem); pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY).Element(); // read geometry mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); // read origin mitk::Point3D origin; double temp = 0; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X, &temp); origin[0] = temp; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y, &temp); origin[1] = temp; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z, &temp); origin[2] = temp; geometry->SetOrigin(origin); // read spacing ScalarType spacing[3]; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X, &temp); spacing[0] = temp; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y, &temp); spacing[1] = temp; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z, &temp); spacing[2] = temp; geometry->SetSpacing(spacing); // read transform vtkMatrix4x4* m = vtkMatrix4x4::New(); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX, &temp); m->SetElement(0,0,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY, &temp); m->SetElement(1,0,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ, &temp); m->SetElement(2,0,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX, &temp); m->SetElement(0,1,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY, &temp); m->SetElement(1,1,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ, &temp); m->SetElement(2,1,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX, &temp); m->SetElement(0,2,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY, &temp); m->SetElement(1,2,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ, &temp); m->SetElement(2,2,temp); m->SetElement(0,3,origin[0]); m->SetElement(1,3,origin[1]); m->SetElement(2,3,origin[2]); m->SetElement(3,3,1); geometry->SetIndexToWorldTransformByVtkMatrix(m); geometry->SetImageGeometry(true); outputNetwork->SetGeometry(geometry); // read network std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap; // read vertices pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTICES).Element(); { // walk through the vertices TiXmlElement* vertexElement = pElem->FirstChildElement(); for( ; vertexElement; vertexElement=vertexElement->NextSiblingElement()) { std::vector< float > pos; std::string label; int vertexID(0); vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X, &temp); pos.push_back(temp); vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y, &temp); pos.push_back(temp); vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z, &temp); pos.push_back(temp); vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID, &vertexID); vertexElement->QueryStringAttribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL, &label); mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = outputNetwork->AddVertex( vertexID ); outputNetwork->SetLabel( newVertex, label ); outputNetwork->SetCoordinates( newVertex, pos ); if ( idToVertexMap.count( vertexID ) > 0 ) { MITK_ERROR << "Aborting network creation, duplicate vertex ID in file."; return result; } idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( vertexID, newVertex) ); } } // read edges pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGES).Element(); { // walk through the edges TiXmlElement* edgeElement = pElem->FirstChildElement(); for( ; edgeElement; edgeElement=edgeElement->NextSiblingElement()) { int edgeID(0), edgeSourceID(0), edgeTargetID(0), edgeWeight(0); edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID, &edgeID); edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID, &edgeSourceID); edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID, &edgeTargetID); edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_WEIGHT_ID, &edgeWeight); mitk::ConnectomicsNetwork::VertexDescriptorType source = idToVertexMap.find( edgeSourceID )->second; mitk::ConnectomicsNetwork::VertexDescriptorType target = idToVertexMap.find( edgeTargetID )->second; outputNetwork->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight); } } outputNetwork->UpdateBounds(); result.push_back(outputNetwork.GetPointer()); MITK_INFO << "Network read"; } catch (mitk::Exception e) { MITK_ERROR << e.GetDescription(); } catch(...) { MITK_ERROR << "Unknown error occured while trying to read file."; } } return result; } } //namespace MITK mitk::ConnectomicsNetworkReader* mitk::ConnectomicsNetworkReader::Clone() const { return new ConnectomicsNetworkReader(*this); } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkWriter.cpp index f4913056d2..aed4bd9da4 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkWriter.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkConnectomicsNetworkWriter.cpp @@ -1,143 +1,143 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkConnectomicsNetworkWriter.h" #include "mitkConnectomicsNetworkDefinitions.h" #include #include "itksys/SystemTools.hxx" #include "mitkDiffusionIOMimeTypes.h" mitk::ConnectomicsNetworkWriter::ConnectomicsNetworkWriter() - : AbstractFileWriter(mitk::ConnectomicsNetwork::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_DESCRIPTION() ) + : AbstractFileWriter(mitk::ConnectomicsNetwork::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE() ), mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_DESCRIPTION() ) { RegisterService(); } mitk::ConnectomicsNetworkWriter::ConnectomicsNetworkWriter(const mitk::ConnectomicsNetworkWriter& other) : AbstractFileWriter(other) { } mitk::ConnectomicsNetworkWriter::~ConnectomicsNetworkWriter() {} mitk::ConnectomicsNetworkWriter* mitk::ConnectomicsNetworkWriter::Clone() const { return new ConnectomicsNetworkWriter(*this); } void mitk::ConnectomicsNetworkWriter::Write() { MITK_INFO << "Writing connectomics network"; InputType::ConstPointer input = dynamic_cast(this->GetInput()); if (input.IsNull() ) { MITK_ERROR <<"Sorry, input to ConnectomicsNetworkWriter is NULL!"; return; } if ( this->GetOutputLocation().empty() ) { MITK_ERROR << "Sorry, filename has not been set!" ; return ; } std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation()); ext = itksys::SystemTools::LowerCase(ext); // default extension is .cnf if(ext == "") { ext = ".cnf"; this->SetOutputLocation(this->GetOutputLocation() + ext); } if (ext == ".cnf") { // Get geometry of the network mitk::BaseGeometry* geometry = input->GetGeometry(); // Create XML document TiXmlDocument documentXML; { // begin document TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); // TODO what to write here? encoding? etc.... documentXML.LinkEndChild( declXML ); TiXmlElement* mainXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_CONNECTOMICS_FILE); mainXML->SetAttribute(mitk::ConnectomicsNetworkDefinitions::XML_FILE_VERSION, mitk::ConnectomicsNetworkDefinitions::VERSION_STRING); documentXML.LinkEndChild(mainXML); TiXmlElement* geometryXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY); { // begin geometry geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX, geometry->GetMatrixColumn(0)[0]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY, geometry->GetMatrixColumn(0)[1]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ, geometry->GetMatrixColumn(0)[2]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX, geometry->GetMatrixColumn(1)[0]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY, geometry->GetMatrixColumn(1)[1]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ, geometry->GetMatrixColumn(1)[2]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX, geometry->GetMatrixColumn(2)[0]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY, geometry->GetMatrixColumn(2)[1]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ, geometry->GetMatrixColumn(2)[2]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X, geometry->GetOrigin()[0]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y, geometry->GetOrigin()[1]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z, geometry->GetOrigin()[2]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X, geometry->GetSpacing()[0]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y, geometry->GetSpacing()[1]); geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z, geometry->GetSpacing()[2]); } // end geometry mainXML->LinkEndChild(geometryXML); TiXmlElement* verticesXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTICES); { // begin vertices section VertexVectorType vertexVector = dynamic_cast(this->GetInput())->GetVectorOfAllNodes(); for( unsigned int index = 0; index < vertexVector.size(); index++ ) { // not localized as of yet TODO TiXmlElement* vertexXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX ); vertexXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID , vertexVector[ index ].id ); vertexXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL , vertexVector[ index ].label ); vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X , vertexVector[ index ].coordinates[0] ); vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y , vertexVector[ index ].coordinates[1] ); vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z , vertexVector[ index ].coordinates[2] ); verticesXML->LinkEndChild(vertexXML); } } // end vertices section mainXML->LinkEndChild(verticesXML); TiXmlElement* edgesXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGES); { // begin edges section EdgeVectorType edgeVector = dynamic_cast(this->GetInput())->GetVectorOfAllEdges(); for(unsigned int index = 0; index < edgeVector.size(); index++ ) { TiXmlElement* edgeXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGE ); edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID , index ); edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID , edgeVector[ index ].second.sourceId ); edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID , edgeVector[ index ].second.targetId ); edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_WEIGHT_ID , edgeVector[ index ].second.weight ); edgesXML->LinkEndChild(edgeXML); } } // end edges section mainXML->LinkEndChild(edgesXML); } // end document documentXML.SaveFile( this->GetOutputLocation().c_str() ); MITK_INFO << "Connectomics network written"; } } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.cpp index fd84df0658..fc7de2ff13 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.cpp @@ -1,212 +1,199 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -/* - * mitkFiberBundleMapper2D.cpp - * mitk-all - * - * Created by HAL9000 on 1/17/11. - * Copyright 2011 __MyCompanyName__. All rights reserved. - * - */ #include "mitkFiberBundleXMapper2D.h" #include - - #include #include #include #include -//#include - -//#include +#include #include #include #include #include #include #include #include #include - -//#include +#include #include #include - #include #include - #include mitk::FiberBundleXMapper2D::FiberBundleXMapper2D() + : m_LineWidth(1) { m_lut = vtkLookupTable::New(); m_lut->Build(); } mitk::FiberBundleXMapper2D::~FiberBundleXMapper2D() { } mitk::FiberBundleX* mitk::FiberBundleXMapper2D::GetInput() { return dynamic_cast< mitk::FiberBundleX * > ( GetDataNode()->GetData() ); } void mitk::FiberBundleXMapper2D::Update(mitk::BaseRenderer * renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); //set renderer independent shader properties const DataNode::Pointer node = this->GetDataNode(); float thickness = 2.0; if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness)) MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR"; bool fiberfading = false; if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading)) MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR"; float fiberOpacity; this->GetDataNode()->GetOpacity(fiberOpacity, NULL); node->SetFloatProperty("shader.mitkShaderFiberClipping.fiberThickness",thickness); node->SetIntProperty("shader.mitkShaderFiberClipping.fiberFadingON",fiberfading); node->SetFloatProperty("shader.mitkShaderFiberClipping.fiberOpacity",fiberOpacity); mitk::FiberBundleX* fiberBundle = this->GetInput(); if (fiberBundle==NULL) return; + int lineWidth = 0; + node->GetIntProperty("LineWidth", lineWidth); + if (m_LineWidth!=lineWidth) + { + m_LineWidth = lineWidth; + fiberBundle->RequestUpdate2D(); + } + if ( localStorage->m_LastUpdateTimeGetDisplayGeometry()->GetMTime() || localStorage->m_LastUpdateTimeGetUpdateTime2D() ) { this->UpdateShaderParameter(renderer); this->GenerateDataForRenderer( renderer ); } } void mitk::FiberBundleXMapper2D::UpdateShaderParameter(mitk::BaseRenderer * renderer) { //get information about current position of views mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController(); mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry(); //generate according cutting planes based on the view position float planeNormal[3]; planeNormal[0] = planeGeo->GetNormal()[0]; planeNormal[1] = planeGeo->GetNormal()[1]; planeNormal[2] = planeGeo->GetNormal()[2]; float tmp1 = planeGeo->GetOrigin()[0] * planeNormal[0]; float tmp2 = planeGeo->GetOrigin()[1] * planeNormal[1]; float tmp3 = planeGeo->GetOrigin()[2] * planeNormal[2]; float thickness = tmp1 + tmp2 + tmp3; //attention, correct normalvector DataNode::Pointer node = this->GetDataNode(); node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.w",thickness,renderer); node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.x",planeNormal[0],renderer); node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.y",planeNormal[1],renderer); node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.z",planeNormal[2],renderer); } // vtkActors and Mappers are feeded here void mitk::FiberBundleXMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { mitk::FiberBundleX* fiberBundle = this->GetInput(); //the handler of local storage gets feeded in this method with requested data for related renderwindow FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); mitk::DataNode* node = this->GetDataNode(); if ( node == NULL ) return; + vtkSmartPointer fiberPolyData = fiberBundle->GetFiberPolyData(); + if (fiberPolyData == NULL) + return; + + fiberPolyData->GetPointData()->AddArray(fiberBundle->GetFiberColors()); localStorage->m_FiberMapper->ScalarVisibilityOn(); localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData(); localStorage->m_FiberMapper->SetLookupTable(m_lut); //apply the properties after the slice was set localStorage->m_PointActor->GetProperty()->SetOpacity(0.999); + localStorage->m_FiberMapper->SelectColorArray("FIBER_COLORS"); - // set color - if (fiberBundle->GetCurrentColorCoding() != NULL) - { - localStorage->m_FiberMapper->SelectColorArray(fiberBundle->GetCurrentColorCoding()); - - if(fiberBundle->GetCurrentColorCoding() == fiberBundle->COLORCODING_CUSTOM){ - float temprgb[3]; - this->GetDataNode()->GetColor( temprgb, NULL ); - double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; - localStorage->m_PointActor->GetProperty()->SetColor(trgb); - } - } - int lineWidth = 1; - node->GetIntProperty("LineWidth",lineWidth); - localStorage->m_FiberMapper->SetInputData(fiberBundle->GetFiberPolyData()); + localStorage->m_FiberMapper->SetInputData(fiberPolyData); localStorage->m_PointActor->SetMapper(localStorage->m_FiberMapper); localStorage->m_PointActor->GetProperty()->ShadingOn(); - localStorage->m_PointActor->GetProperty()->SetLineWidth(lineWidth); + localStorage->m_PointActor->GetProperty()->SetLineWidth(m_LineWidth); // Applying shading properties this->ApplyShaderProperties(renderer); // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } vtkProp* mitk::FiberBundleXMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { this->Update(renderer); return m_LocalStorageHandler.GetLocalStorage(renderer)->m_PointActor; } void mitk::FiberBundleXMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { + Superclass::SetDefaultProperties(node, renderer, overwrite); node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping")); // Shaders IShaderRepository* shaderRepo = CoreServices::GetShaderRepository(); if (shaderRepo) { shaderRepo->AddDefaultProperties(node, renderer, overwrite); } //add other parameters to propertylist - node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(2.0f), renderer, overwrite ); + node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite ); - - Superclass::SetDefaultProperties(node, renderer, overwrite); + node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), renderer, overwrite); + node->AddProperty( "TubeRadius",mitk::FloatProperty::New( 0.0 ), renderer, overwrite); } mitk::FiberBundleXMapper2D::FBXLocalStorage::FBXLocalStorage() { m_PointActor = vtkSmartPointer::New(); m_FiberMapper = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.h index 6832499c4f..85d61d0df8 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.h @@ -1,108 +1,109 @@ /*=================================================================== 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 FIBERBUNDLEXMAPPER2D_H_HEADER_INCLUDED #define FIBERBUNDLEXMAPPER2D_H_HEADER_INCLUDED //MITK Rendering #include #include //#include #include #include #include class vtkActor; //class vtkPropAssembly; //lets see if we need it class mitkBaseRenderer; class vtkPolyDataMapper; class vtkCutter; class vtkPlane; class vtkPolyData; namespace mitk { struct IShaderRepository; class FiberBundleXMapper2D : public VtkMapper { public: mitkClassMacro(FiberBundleXMapper2D, VtkMapper); itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitk::FiberBundleX* GetInput(); /** \brief Checks whether this mapper needs to update itself and generate data. */ virtual void Update(mitk::BaseRenderer * renderer); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); //### methods of MITK-VTK rendering pipeline virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); //### end of methods of MITK-VTK rendering pipeline class FBXLocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Point Actor of a 2D render window. */ vtkSmartPointer m_PointActor; /** \brief Point Mapper of a 2D render window. */ vtkSmartPointer m_FiberMapper; vtkSmartPointer m_SlicingPlane; //needed later when optimized 2D mapper vtkSmartPointer m_SlicedResult; //might be depricated in optimized 2D mapper /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Constructor of the local storage. Do as much actions as possible in here to avoid double executions. */ FBXLocalStorage(); //if u copy&paste from this 2Dmapper, be aware that the implementation of this constructor is in the cpp file ~FBXLocalStorage() { } }; /** \brief This member holds all three LocalStorages for the three 2D render windows. */ mitk::LocalStorageHandler m_LocalStorageHandler; protected: FiberBundleXMapper2D(); virtual ~FiberBundleXMapper2D(); /** Does the actual resampling, without rendering. */ virtual void GenerateDataForRenderer(mitk::BaseRenderer*); void UpdateShaderParameter(mitk::BaseRenderer*); private: vtkSmartPointer m_lut; + int m_LineWidth; }; }//end namespace #endif diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.cpp index caea82c3a1..fd949cdbfa 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.cpp @@ -1,168 +1,189 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberBundleXMapper3D.h" #include -//#include -//#include #include #include #include #include - -//not essential for mapper -// #include +#include +#include +#include mitk::FiberBundleXMapper3D::FiberBundleXMapper3D() + : m_TubeRadius(0.0) + , m_TubeSides(15) + , m_LineWidth(1) { m_lut = vtkLookupTable::New(); m_lut->Build(); } mitk::FiberBundleXMapper3D::~FiberBundleXMapper3D() { } const mitk::FiberBundleX* mitk::FiberBundleXMapper3D::GetInput() { return static_cast ( GetDataNode()->GetData() ); } /* This method is called once the mapper gets new input, for UI rotation or changes in colorcoding this method is NOT called */ void mitk::FiberBundleXMapper3D::InternalGenerateData(mitk::BaseRenderer *renderer) { mitk::FiberBundleX* fiberBundle = dynamic_cast (GetDataNode()->GetData()); if (fiberBundle == NULL) return; vtkSmartPointer fiberPolyData = fiberBundle->GetFiberPolyData(); if (fiberPolyData == NULL) return; + fiberPolyData->GetPointData()->AddArray(fiberBundle->GetFiberColors()); + float tmpopa; + this->GetDataNode()->GetOpacity(tmpopa, NULL); FBXLocalStorage3D *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); - localStorage->m_FiberMapper->SetInputData(fiberPolyData); - if ( fiberPolyData->GetPointData()->GetNumberOfArrays() > 0 ) - localStorage->m_FiberMapper->SelectColorArray( fiberBundle->GetCurrentColorCoding() ); + if (m_TubeRadius>0.0) + { + vtkSmartPointer tubeFilter = vtkSmartPointer::New(); + tubeFilter->SetInputData(fiberPolyData); + tubeFilter->SetNumberOfSides(m_TubeSides); + tubeFilter->SetRadius(m_TubeRadius); + tubeFilter->Update(); + fiberPolyData = tubeFilter->GetOutput(); + } + if (tmpopa<1) + { + vtkSmartPointer depthSort = vtkSmartPointer::New(); + depthSort->SetInputData( fiberPolyData ); + depthSort->SetCamera( renderer->GetVtkRenderer()->GetActiveCamera() ); + depthSort->SetDirectionToFrontToBack(); + depthSort->Update(); + localStorage->m_FiberMapper->SetInputConnection(depthSort->GetOutputPort()); + } + else + { + localStorage->m_FiberMapper->SetInputData(fiberPolyData); + } + + localStorage->m_FiberMapper->SelectColorArray("FIBER_COLORS"); localStorage->m_FiberMapper->ScalarVisibilityOn(); localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData(); localStorage->m_FiberActor->SetMapper(localStorage->m_FiberMapper); localStorage->m_FiberMapper->SetLookupTable(m_lut); // set Opacity - float tmpopa; - this->GetDataNode()->GetOpacity(tmpopa, NULL); localStorage->m_FiberActor->GetProperty()->SetOpacity((double) tmpopa); - - int lineWidth = 1; - this->GetDataNode()->GetIntProperty("LineWidth",lineWidth); - localStorage->m_FiberActor->GetProperty()->SetLineWidth(lineWidth); - - // set color - if (fiberBundle->GetCurrentColorCoding() != NULL){ - // localStorage->m_FiberMapper->SelectColorArray(""); - localStorage->m_FiberMapper->SelectColorArray(fiberBundle->GetCurrentColorCoding()); - MITK_DEBUG << "MapperFBX: " << fiberBundle->GetCurrentColorCoding(); - - if(fiberBundle->GetCurrentColorCoding() == fiberBundle->COLORCODING_CUSTOM) { - float temprgb[3]; - this->GetDataNode()->GetColor( temprgb, NULL ); - double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; - localStorage->m_FiberActor->GetProperty()->SetColor(trgb); - } - } + localStorage->m_FiberActor->GetProperty()->SetLineWidth(m_LineWidth); localStorage->m_FiberAssembly->AddPart(localStorage->m_FiberActor); localStorage->m_LastUpdateTime.Modified(); } void mitk::FiberBundleXMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; const DataNode* node = this->GetDataNode(); FBXLocalStorage3D* localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); mitk::FiberBundleX* fiberBundle = dynamic_cast(node->GetData()); + + // did any rendering properties change? + float tubeRadius = 0; + node->GetFloatProperty("TubeRadius", tubeRadius); + if (m_TubeRadius!=tubeRadius) + { + m_TubeRadius = tubeRadius; + fiberBundle->RequestUpdate3D(); + } + + int tubeSides = 0; + node->GetIntProperty("TubeSides", tubeSides); + if (m_TubeSides!=tubeSides) + { + m_TubeSides = tubeSides; + fiberBundle->RequestUpdate3D(); + } + + int lineWidth = 0; + node->GetIntProperty("LineWidth", lineWidth); + if (m_LineWidth!=lineWidth) + { + m_LineWidth = lineWidth; + fiberBundle->RequestUpdate3D(); + } + if (localStorage->m_LastUpdateTime>=fiberBundle->GetUpdateTime3D()) return; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); this->InternalGenerateData(renderer); } void mitk::FiberBundleXMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { - // node->AddProperty( "DisplayChannel", mitk::IntProperty::New( true ), renderer, overwrite ); + Superclass::SetDefaultProperties(node, renderer, overwrite); node->AddProperty( "LineWidth", mitk::IntProperty::New( true ), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); - // node->AddProperty( "VertexOpacity_1", mitk::BoolProperty::New( false ), renderer, overwrite); - // node->AddProperty( "Set_FA_VertexAlpha", mitk::BoolProperty::New( false ), renderer, overwrite); - // node->AddProperty( "pointSize", mitk::FloatProperty::New(0.5), renderer, overwrite); - // node->AddProperty( "setShading", mitk::IntProperty::New(1), renderer, overwrite); - // node->AddProperty( "Xmove", mitk::IntProperty::New( 0 ), renderer, overwrite); - // node->AddProperty( "Ymove", mitk::IntProperty::New( 0 ), renderer, overwrite); - // node->AddProperty( "Zmove", mitk::IntProperty::New( 0 ), renderer, overwrite); - // node->AddProperty( "RepPoints", mitk::BoolProperty::New( false ), renderer, overwrite); - // node->AddProperty( "TubeSides", mitk::IntProperty::New( 8 ), renderer, overwrite); - // node->AddProperty( "TubeRadius", mitk::FloatProperty::New( 0.15 ), renderer, overwrite); - // node->AddProperty( "TubeOpacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); + node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), renderer, overwrite); node->AddProperty( "pickable", mitk::BoolProperty::New( true ), renderer, overwrite); - Superclass::SetDefaultProperties(node, renderer, overwrite); + + node->AddProperty( "TubeRadius",mitk::FloatProperty::New( 0.0 ), renderer, overwrite); + node->AddProperty( "TubeSides",mitk::IntProperty::New( 15 ), renderer, overwrite); } vtkProp* mitk::FiberBundleXMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { - //MITK_INFO << "FiberBundleXxXXMapper3D()GetVTKProp"; - //this->GenerateData(); return m_LocalStorageHandler.GetLocalStorage(renderer)->m_FiberAssembly; - } void mitk::FiberBundleXMapper3D::UpdateVtkObjects() { } void mitk::FiberBundleXMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } mitk::FiberBundleXMapper3D::FBXLocalStorage3D::FBXLocalStorage3D() { m_FiberActor = vtkSmartPointer::New(); m_FiberMapper = vtkSmartPointer::New(); m_FiberAssembly = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.h index 4f8424637d..b583b97a98 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.h @@ -1,103 +1,104 @@ /*=================================================================== 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 FiberBundleXMapper3D_H_HEADER_INCLUDED #define FiberBundleXMapper3D_H_HEADER_INCLUDED //#include //?? necessary #include #include #include #include #include #include class vtkPropAssembly; namespace mitk { //##Documentation //## @brief Mapper for FiberBundleX //## @ingroup Mapper class FiberBundleXMapper3D : public VtkMapper { public: mitkClassMacro(FiberBundleXMapper3D, VtkMapper) itkFactorylessNewMacro(Self) itkCloneMacro(Self) //========== essential implementation for 3D mapper ======== const FiberBundleX* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); //looks like depricated.. should be replaced bz GetViewProp() static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); //========================================================= class FBXLocalStorage3D : public mitk::Mapper::BaseLocalStorage { public: /** \brief Point Actor of a 3D render window. */ vtkSmartPointer m_FiberActor; /** \brief Point Mapper of a 3D render window. */ vtkSmartPointer m_FiberMapper; vtkSmartPointer m_FiberAssembly; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Constructor of the local storage. Do as much actions as possible in here to avoid double executions. */ FBXLocalStorage3D(); //if u copy&paste from this 2Dmapper, be aware that the implementation of this constructor is in the cpp file ~FBXLocalStorage3D() { } }; /** \brief This member holds all three LocalStorages for the 3D render window(s). */ mitk::LocalStorageHandler m_LocalStorageHandler; protected: FiberBundleXMapper3D(); virtual ~FiberBundleXMapper3D(); void InternalGenerateData(mitk::BaseRenderer *renderer); void UpdateVtkObjects(); //?? private: vtkSmartPointer m_lut; - - + float m_TubeRadius; + int m_TubeSides; + int m_LineWidth; }; } // end namespace mitk #endif /* FiberBundleXMapper3D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.cpp index f6ff88e5a5..025f2bbe20 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.cpp @@ -1,207 +1,229 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberBundleXReader.h" #include #include #include #include #include #include #include +#include +#include +#include +#include #include #include #include #include #include #include "mitkDiffusionIOMimeTypes.h" mitk::FiberBundleXReader::FiberBundleXReader() - : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_DESCRIPTION() ) + : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE() ), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_DESCRIPTION() ) { m_ServiceReg = this->RegisterService(); } mitk::FiberBundleXReader::FiberBundleXReader(const FiberBundleXReader &other) :mitk::AbstractFileReader(other) { } mitk::FiberBundleXReader * mitk::FiberBundleXReader::Clone() const { return new FiberBundleXReader(*this); } std::vector > mitk::FiberBundleXReader::Read() { std::vector > result; try { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); setlocale(LC_ALL, locale.c_str()); std::string filename = this->GetInputLocation(); std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); ext = itksys::SystemTools::LowerCase(ext); if (ext==".trk") { FiberBundleX::Pointer image = FiberBundleX::New(); TrackVisFiberReader reader; reader.open(this->GetInputLocation().c_str()); reader.read(image.GetPointer()); result.push_back(image.GetPointer()); return result; } vtkSmartPointer chooser=vtkSmartPointer::New(); chooser->SetFileName( this->GetInputLocation().c_str() ); if( chooser->IsFilePolyData()) { vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName( this->GetInputLocation().c_str() ); reader->Update(); if ( reader->GetOutput() != NULL ) { vtkSmartPointer fiberPolyData = reader->GetOutput(); - FiberBundleX::Pointer image = FiberBundleX::New(fiberPolyData); - result.push_back(image.GetPointer()); + FiberBundleX::Pointer fiberBundle = FiberBundleX::New(fiberPolyData); + + vtkSmartPointer weights = vtkFloatArray::SafeDownCast(fiberPolyData->GetCellData()->GetArray("FIBER_WEIGHTS")); + if (weights!=NULL) + { +// float weight=0; +// for (int i=0; iGetSize(); i++) +// if (!mitk::Equal(weights->GetValue(i),weight,0.00001)) +// { +// MITK_INFO << "Weight: " << weights->GetValue(i); +// weight = weights->GetValue(i); +// } + fiberBundle->SetFiberWeights(weights); + } + + vtkSmartPointer fiberColors = vtkUnsignedCharArray::SafeDownCast(fiberPolyData->GetPointData()->GetArray("FIBER_COLORS")); + if (fiberColors!=NULL) + fiberBundle->SetFiberColors(fiberColors); + + result.push_back(fiberBundle.GetPointer()); return result; } } else // try to read deprecated fiber bundle file format { MITK_INFO << "Reading xml fiber bundle"; vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); vtkSmartPointer cellArray = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); TiXmlDocument doc( this->GetInputLocation().c_str() ); if(doc.LoadFile()) { TiXmlHandle hDoc(&doc); TiXmlElement* pElem; TiXmlHandle hRoot(0); pElem = hDoc.FirstChildElement().Element(); // save this for later hRoot = TiXmlHandle(pElem); pElem = hRoot.FirstChildElement("geometry").Element(); // read geometry mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); // read origin mitk::Point3D origin; double temp = 0; pElem->Attribute("origin_x", &temp); origin[0] = temp; pElem->Attribute("origin_y", &temp); origin[1] = temp; pElem->Attribute("origin_z", &temp); origin[2] = temp; geometry->SetOrigin(origin); // read spacing ScalarType spacing[3]; pElem->Attribute("spacing_x", &temp); spacing[0] = temp; pElem->Attribute("spacing_y", &temp); spacing[1] = temp; pElem->Attribute("spacing_z", &temp); spacing[2] = temp; geometry->SetSpacing(spacing); // read transform vtkMatrix4x4* m = vtkMatrix4x4::New(); pElem->Attribute("xx", &temp); m->SetElement(0,0,temp); pElem->Attribute("xy", &temp); m->SetElement(1,0,temp); pElem->Attribute("xz", &temp); m->SetElement(2,0,temp); pElem->Attribute("yx", &temp); m->SetElement(0,1,temp); pElem->Attribute("yy", &temp); m->SetElement(1,1,temp); pElem->Attribute("yz", &temp); m->SetElement(2,1,temp); pElem->Attribute("zx", &temp); m->SetElement(0,2,temp); pElem->Attribute("zy", &temp); m->SetElement(1,2,temp); pElem->Attribute("zz", &temp); m->SetElement(2,2,temp); m->SetElement(0,3,origin[0]); m->SetElement(1,3,origin[1]); m->SetElement(2,3,origin[2]); m->SetElement(3,3,1); geometry->SetIndexToWorldTransformByVtkMatrix(m); // read bounds float bounds[] = {0, 0, 0, 0, 0, 0}; pElem->Attribute("size_x", &temp); bounds[1] = temp; pElem->Attribute("size_y", &temp); bounds[3] = temp; pElem->Attribute("size_z", &temp); bounds[5] = temp; geometry->SetFloatBounds(bounds); geometry->SetImageGeometry(true); pElem = hRoot.FirstChildElement("fiber_bundle").FirstChild().Element(); for( ; pElem ; pElem=pElem->NextSiblingElement()) { TiXmlElement* pElem2 = pElem->FirstChildElement(); vtkSmartPointer container = vtkSmartPointer::New(); for( ; pElem2; pElem2=pElem2->NextSiblingElement()) { Point3D point; pElem2->Attribute("pos_x", &temp); point[0] = temp; pElem2->Attribute("pos_y", &temp); point[1] = temp; pElem2->Attribute("pos_z", &temp); point[2] = temp; geometry->IndexToWorld(point, point); vtkIdType id = points->InsertNextPoint(point.GetDataPointer()); container->GetPointIds()->InsertNextId(id); } cellArray->InsertNextCell(container); } fiberPolyData->SetPoints(points); fiberPolyData->SetLines(cellArray); vtkSmartPointer cleaner = vtkSmartPointer::New(); cleaner->SetInputData(fiberPolyData); cleaner->Update(); fiberPolyData = cleaner->GetOutput(); FiberBundleX::Pointer image = FiberBundleX::New(fiberPolyData); result.push_back(image.GetPointer()); return result; } else { MITK_ERROR << "could not open xml file"; throw "could not open xml file"; } } setlocale(LC_ALL, currLocale.c_str()); MITK_INFO << "Fiber bundle read"; } catch(...) { throw; } return result; } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.cpp index 643219e16d..987d8f75fc 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.cpp @@ -1,133 +1,139 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberBundleXWriter.h" #include #include #include #include #include - +#include +#include +#include #include #include #include "mitkDiffusionIOMimeTypes.h" mitk::FiberBundleXWriter::FiberBundleXWriter() - : mitk::AbstractFileWriter(mitk::FiberBundleX::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_DESCRIPTION()) + : mitk::AbstractFileWriter(mitk::FiberBundleX::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE() ), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_DESCRIPTION()) { RegisterService(); } mitk::FiberBundleXWriter::FiberBundleXWriter(const mitk::FiberBundleXWriter & other) :mitk::AbstractFileWriter(other) {} mitk::FiberBundleXWriter::~FiberBundleXWriter() {} mitk::FiberBundleXWriter * mitk::FiberBundleXWriter::Clone() const { return new mitk::FiberBundleXWriter(*this); } void mitk::FiberBundleXWriter::Write() { std::ostream* out; std::ofstream outStream; if( this->GetOutputStream() ) { out = this->GetOutputStream(); }else{ outStream.open( this->GetOutputLocation().c_str() ); out = &outStream; } if ( !out->good() ) { mitkThrow() << "Stream not good."; } try { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); setlocale(LC_ALL, locale.c_str()); std::locale previousLocale(out->getloc()); std::locale I("C"); out->imbue(I); std::string filename = this->GetOutputLocation().c_str(); mitk::FiberBundleX::ConstPointer input = dynamic_cast(this->GetInput()); std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation().c_str()); + vtkSmartPointer fibPoly = input->GetFiberPolyData(); + fibPoly->GetCellData()->AddArray(input->GetFiberWeights()); + fibPoly->GetPointData()->AddArray(input->GetFiberColors()); + // default extension is .fib if(ext == "") { ext = ".fib"; this->SetOutputLocation(this->GetOutputLocation() + ext); } if (ext==".fib" || ext==".vtk") { MITK_INFO << "Writing fiber bundle as binary VTK"; vtkSmartPointer writer = vtkSmartPointer::New(); - writer->SetInputData(input->GetFiberPolyData()); - writer->SetFileName(this->GetOutputLocation().c_str()); + writer->SetInputData(fibPoly); + writer->SetFileName(filename.c_str()); writer->SetFileTypeToBinary(); writer->Write(); } else if (ext==".afib") { itksys::SystemTools::ReplaceString(filename,".afib",".fib"); MITK_INFO << "Writing fiber bundle as ascii VTK"; vtkSmartPointer writer = vtkSmartPointer::New(); - writer->SetInputData(input->GetFiberPolyData()); - writer->SetFileName(this->GetOutputLocation().c_str()); + writer->SetInputData(fibPoly); + writer->SetFileName(filename.c_str()); writer->SetFileTypeToASCII(); writer->Write(); } else if (ext==".avtk") { itksys::SystemTools::ReplaceString(filename,".avtk",".vtk"); MITK_INFO << "Writing fiber bundle as ascii VTK"; vtkSmartPointer writer = vtkSmartPointer::New(); - writer->SetInputData(input->GetFiberPolyData()); - writer->SetFileName(this->GetOutputLocation().c_str()); + writer->SetInputData(fibPoly); + writer->SetFileName(filename.c_str()); writer->SetFileTypeToASCII(); writer->Write(); } else if (ext==".trk") { MITK_INFO << "Writing fiber bundle as TRK"; TrackVisFiberReader trk; trk.create(filename, input.GetPointer()); trk.writeHdr(); trk.append(input.GetPointer()); } setlocale(LC_ALL, currLocale.c_str()); MITK_INFO << "Fiber bundle written"; } catch(...) { throw; } } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.cpp index cf8846e1fa..cb78e2f291 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.cpp @@ -1,127 +1,114 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberTrackingObjectFactory.h" mitk::FiberTrackingObjectFactory::FiberTrackingObjectFactory() : CoreObjectFactoryBase() { } mitk::FiberTrackingObjectFactory::~FiberTrackingObjectFactory() { } mitk::Mapper::Pointer mitk::FiberTrackingObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id) { mitk::Mapper::Pointer newMapper=NULL; if ( id == mitk::BaseRenderer::Standard2D ) { std::string classname("FiberBundleX"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::FiberBundleXMapper2D::New(); newMapper->SetDataNode(node); } } else if ( id == mitk::BaseRenderer::Standard3D ) { std::string classname("FiberBundleX"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::FiberBundleXMapper3D::New(); newMapper->SetDataNode(node); } - -// classname = "FiberBundleXThreadMonitor"; -// if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) -// { -// newMapper = mitk::FiberBundleXThreadMonitorMapper3D::New(); -// newMapper->SetDataNode(node); -// } } return newMapper; } void mitk::FiberTrackingObjectFactory::SetDefaultProperties(mitk::DataNode* node) { std::string classname("FiberBundleX"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::FiberBundleXMapper3D::SetDefaultProperties(node); mitk::FiberBundleXMapper2D::SetDefaultProperties(node); } - -// classname = "FiberBundleXThreadMonitor"; -// if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) -// { -// mitk::FiberBundleXThreadMonitorMapper3D::SetDefaultProperties(node); -// } } const char* mitk::FiberTrackingObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::FiberTrackingObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } const char* mitk::FiberTrackingObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::FiberTrackingObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::FiberTrackingObjectFactory::CreateFileExtensionsMap() { } void mitk::FiberTrackingObjectFactory::RegisterIOFactories() { } struct RegisterFiberTrackingObjectFactory{ RegisterFiberTrackingObjectFactory() : m_Factory( mitk::FiberTrackingObjectFactory::New() ) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory ); } ~RegisterFiberTrackingObjectFactory() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory ); } mitk::FiberTrackingObjectFactory::Pointer m_Factory; }; static RegisterFiberTrackingObjectFactory registerFiberTrackingObjectFactory; diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp index bd86415a15..a2b29fd956 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp @@ -1,434 +1,434 @@ /*=================================================================== 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 __mitkNrrdDiffusionImageReader_cpp #define __mitkNrrdDiffusionImageReader_cpp #include "mitkNrrdDiffusionImageReader.h" #include #include // Diffusion properties #include #include #include #include // ITK includes #include #include #include "itksys/SystemTools.hxx" #include "itkImageFileReader.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include "itkNiftiImageIO.h" #include "mitkCustomMimeType.h" #include "mitkDiffusionIOMimeTypes.h" #include #include #include #include #include "mitkIOUtil.h" namespace mitk { NrrdDiffusionImageReader:: NrrdDiffusionImageReader(const NrrdDiffusionImageReader & other) : AbstractFileReader(other) { } NrrdDiffusionImageReader* NrrdDiffusionImageReader::Clone() const { return new NrrdDiffusionImageReader(*this); } NrrdDiffusionImageReader:: ~NrrdDiffusionImageReader() {} NrrdDiffusionImageReader:: NrrdDiffusionImageReader() - : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::DWI_MIMETYPE_DESCRIPTION() ) + : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_MIMETYPE_DESCRIPTION() ) { m_ServiceReg = this->RegisterService(); } std::vector > NrrdDiffusionImageReader:: Read() { std::vector > result; // Since everything is completely read in GenerateOutputInformation() it is stored // in a cache variable. A timestamp is associated. // If the timestamp of the cache variable is newer than the MTime, we only need to // assign the cache variable to the DataObject. // Otherwise, the tree must be read again from the file and OuputInformation must // be updated! if(m_OutputCache.IsNull()) InternalRead(); result.push_back(m_OutputCache.GetPointer()); return result; } void NrrdDiffusionImageReader::InternalRead() { OutputType::Pointer outputForCache = OutputType::New(); if ( this->GetInputLocation() == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename to be read is empty!"); } else { try { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } MITK_INFO << "NrrdDiffusionImageReader: reading image information"; VectorImageType::Pointer itkVectorImage; std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetInputLocation()); ext = itksys::SystemTools::LowerCase(ext); if (ext == ".hdwi" || ext == ".dwi" || ext == ".nrrd") { typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetFileName(this->GetInputLocation()); itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); reader->SetImageIO(io); reader->Update(); itkVectorImage = reader->GetOutput(); } else if(ext == ".fsl" || ext == ".fslgz") { // create temporary file with correct ending for nifti-io std::string fname3 = "temp_dwi"; fname3 += ext == ".fsl" ? ".nii" : ".nii.gz"; itksys::SystemTools::CopyAFile(this->GetInputLocation().c_str(), fname3.c_str()); // create reader and read file typedef itk::Image ImageType4D; itk::NiftiImageIO::Pointer io2 = itk::NiftiImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetFileName(fname3); reader->SetImageIO(io2); reader->Update(); ImageType4D::Pointer img4 = reader->GetOutput(); // delete temporary file itksys::SystemTools::RemoveFile(fname3.c_str()); // convert 4D file to vector image itkVectorImage = VectorImageType::New(); VectorImageType::SpacingType spacing; ImageType4D::SpacingType spacing4 = img4->GetSpacing(); for(int i=0; i<3; i++) spacing[i] = spacing4[i]; itkVectorImage->SetSpacing( spacing ); // Set the image spacing VectorImageType::PointType origin; ImageType4D::PointType origin4 = img4->GetOrigin(); for(int i=0; i<3; i++) origin[i] = origin4[i]; itkVectorImage->SetOrigin( origin ); // Set the image origin VectorImageType::DirectionType direction; ImageType4D::DirectionType direction4 = img4->GetDirection(); for(int i=0; i<3; i++) for(int j=0; j<3; j++) direction[i][j] = direction4[i][j]; itkVectorImage->SetDirection( direction ); // Set the image direction VectorImageType::RegionType region; ImageType4D::RegionType region4 = img4->GetLargestPossibleRegion(); VectorImageType::RegionType::SizeType size; ImageType4D::RegionType::SizeType size4 = region4.GetSize(); for(int i=0; i<3; i++) size[i] = size4[i]; VectorImageType::RegionType::IndexType index; ImageType4D::RegionType::IndexType index4 = region4.GetIndex(); for(int i=0; i<3; i++) index[i] = index4[i]; region.SetSize(size); region.SetIndex(index); itkVectorImage->SetRegions( region ); itkVectorImage->SetVectorLength(size4[3]); itkVectorImage->Allocate(); itk::ImageRegionIterator it ( itkVectorImage, itkVectorImage->GetLargestPossibleRegion() ); typedef VectorImageType::PixelType VecPixType; for (it.GoToBegin(); !it.IsAtEnd(); ++it) { VecPixType vec = it.Get(); VectorImageType::IndexType currentIndex = it.GetIndex(); for(int i=0; i<3; i++) index4[i] = currentIndex[i]; for(unsigned int ind=0; indGetPixel(index4); } it.Set(vec); } } // Diffusion Image information START GradientDirectionContainerType::Pointer DiffusionVectors = GradientDirectionContainerType::New(); GradientDirectionContainerType::Pointer OriginalDiffusionVectors = GradientDirectionContainerType::New(); MeasurementFrameType MeasurementFrame; float BValue = -1; // Diffusion Image information END if (ext == ".hdwi" || ext == ".dwi" || ext == ".nrrd") { itk::MetaDataDictionary imgMetaDictionary = itkVectorImage->GetMetaDataDictionary(); std::vector imgMetaKeys = imgMetaDictionary.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString; GradientDirectionType vect3d; int numberOfImages = 0; int numberOfGradientImages = 0; bool readb0 = false; double xx, xy, xz, yx, yy, yz, zx, zy, zz; for (; itKey != imgMetaKeys.end(); itKey ++) { double x,y,z; itk::ExposeMetaData (imgMetaDictionary, *itKey, metaString); if (itKey->find("DWMRI_gradient") != std::string::npos) { sscanf(metaString.c_str(), "%lf %lf %lf\n", &x, &y, &z); vect3d[0] = x; vect3d[1] = y; vect3d[2] = z; DiffusionVectors->InsertElement( numberOfImages, vect3d ); ++numberOfImages; // If the direction is 0.0, this is a reference image if (vect3d[0] == 0.0 && vect3d[1] == 0.0 && vect3d[2] == 0.0) { continue; } ++numberOfGradientImages;; } else if (itKey->find("DWMRI_b-value") != std::string::npos) { readb0 = true; BValue = atof(metaString.c_str()); } else if (itKey->find("measurement frame") != std::string::npos) { sscanf(metaString.c_str(), " ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) \n", &xx, &xy, &xz, &yx, &yy, &yz, &zx, &zy, &zz); if (xx>10e-10 || xy>10e-10 || xz>10e-10 || yx>10e-10 || yy>10e-10 || yz>10e-10 || zx>10e-10 || zy>10e-10 || zz>10e-10 ) { MeasurementFrame(0,0) = xx; MeasurementFrame(0,1) = xy; MeasurementFrame(0,2) = xz; MeasurementFrame(1,0) = yx; MeasurementFrame(1,1) = yy; MeasurementFrame(1,2) = yz; MeasurementFrame(2,0) = zx; MeasurementFrame(2,1) = zy; MeasurementFrame(2,2) = zz; } else { MeasurementFrame(0,0) = 1; MeasurementFrame(0,1) = 0; MeasurementFrame(0,2) = 0; MeasurementFrame(1,0) = 0; MeasurementFrame(1,1) = 1; MeasurementFrame(1,2) = 0; MeasurementFrame(2,0) = 0; MeasurementFrame(2,1) = 0; MeasurementFrame(2,2) = 1; } } } if(!readb0) { MITK_INFO << "BValue not specified in header file"; } } else if(ext == ".fsl" || ext == ".fslgz") { std::string line; std::vector bvec_entries; std::string fname = this->GetInputLocation(); fname += ".bvecs"; std::ifstream myfile (fname.c_str()); if (myfile.is_open()) { while ( myfile.good() ) { getline (myfile,line); char* pch = strtok (const_cast(line.c_str())," "); while (pch != NULL) { bvec_entries.push_back(atof(pch)); pch = strtok (NULL, " "); } } myfile.close(); } else { MITK_INFO << "Unable to open bvecs file"; } std::vector bval_entries; std::string fname2 = this->GetInputLocation(); fname2 += ".bvals"; std::ifstream myfile2 (fname2.c_str()); if (myfile2.is_open()) { while ( myfile2.good() ) { getline (myfile2,line); char* pch = strtok (const_cast(line.c_str())," "); while (pch != NULL) { bval_entries.push_back(atof(pch)); pch = strtok (NULL, " "); } } myfile2.close(); } else { MITK_INFO << "Unable to open bvals file"; } BValue = -1; unsigned int numb = bval_entries.size(); for(unsigned int i=0; i vec; vec[0] = bvec_entries.at(i); vec[1] = bvec_entries.at(i+numb); vec[2] = bvec_entries.at(i+2*numb); // Adjust the vector length to encode gradient strength float factor = b_val/BValue; if(vec.magnitude() > 0) { vec[0] = sqrt(factor)*vec[0]; vec[1] = sqrt(factor)*vec[1]; vec[2] = sqrt(factor)*vec[2]; } DiffusionVectors->InsertElement(i,vec); } for(int i=0; i<3; i++) for(int j=0; j<3; j++) MeasurementFrame[i][j] = i==j ? 1 : 0; } outputForCache = mitk::GrabItkImageMemory( itkVectorImage); // create BValueMap mitk::BValueMapProperty::BValueMap BValueMap = mitk::BValueMapProperty::CreateBValueMap(DiffusionVectors,BValue); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( DiffusionVectors ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( OriginalDiffusionVectors ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( MeasurementFrame ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New( BValueMap ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( BValue ) ); // Since we have already read the tree, we can store it in a cache variable // so that it can be assigned to the DataObject in GenerateData(); m_OutputCache = outputForCache; m_CacheTime.Modified(); try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } catch(std::exception& e) { MITK_INFO << "Std::Exception while reading file!!"; MITK_INFO << e.what(); throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { MITK_INFO << "Exception while reading file!!"; throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!"); } } } } //namespace MITK #endif diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.cpp index 95f42b98e3..179126a472 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.cpp @@ -1,332 +1,332 @@ /*=================================================================== 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 __mitkNrrdDiffusionImageWriter__cpp #define __mitkNrrdDiffusionImageWriter__cpp #include "mitkNrrdDiffusionImageWriter.h" #include "itkMetaDataDictionary.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include "itkNiftiImageIO.h" #include "itkImageFileWriter.h" #include "itksys/SystemTools.hxx" #include "mitkDiffusionIOMimeTypes.h" #include "mitkImageCast.h" #include #include mitk::NrrdDiffusionImageWriter::NrrdDiffusionImageWriter() - : AbstractFileWriter(mitk::Image::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::DWI_MIMETYPE_DESCRIPTION()) + : AbstractFileWriter(mitk::Image::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_MIMETYPE_DESCRIPTION()) { RegisterService(); } mitk::NrrdDiffusionImageWriter::NrrdDiffusionImageWriter(const mitk::NrrdDiffusionImageWriter& other) : AbstractFileWriter(other) { } mitk::NrrdDiffusionImageWriter::~NrrdDiffusionImageWriter() {} void mitk::NrrdDiffusionImageWriter::Write() { mitk::Image::ConstPointer input = dynamic_cast(this->GetInput()); VectorImageType::Pointer itkImg; mitk::CastToItkImage(input,itkImg); if (input.IsNull()) { MITK_ERROR <<"Sorry, input to NrrdDiffusionImageWriter is NULL!"; return; } if ( this->GetOutputLocation().empty() ) { MITK_ERROR << "Sorry, filename has not been set!"; return ; } const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } char keybuffer[512]; char valbuffer[512]; //itk::MetaDataDictionary dic = input->GetImage()->GetMetaDataDictionary(); vnl_matrix_fixed measurementFrame = mitk::DiffusionPropertyHelper::GetMeasurementFrame(input); if (measurementFrame(0,0) || measurementFrame(0,1) || measurementFrame(0,2) || measurementFrame(1,0) || measurementFrame(1,1) || measurementFrame(1,2) || measurementFrame(2,0) || measurementFrame(2,1) || measurementFrame(2,2)) { sprintf( valbuffer, " (%lf,%lf,%lf) (%lf,%lf,%lf) (%lf,%lf,%lf)", measurementFrame(0,0), measurementFrame(0,1), measurementFrame(0,2), measurementFrame(1,0), measurementFrame(1,1), measurementFrame(1,2), measurementFrame(2,0), measurementFrame(2,1), measurementFrame(2,2)); itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string("measurement frame"),std::string(valbuffer)); } sprintf( valbuffer, "DWMRI"); itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string("modality"),std::string(valbuffer)); if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size()) { sprintf( valbuffer, "%1f", mitk::DiffusionPropertyHelper::GetReferenceBValue(input) ); itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string("DWMRI_b-value"),std::string(valbuffer)); } for(unsigned int i=0; iSize(); i++) { sprintf( keybuffer, "DWMRI_gradient_%04d", i ); /*if(itk::ExposeMetaData(input->GetMetaDataDictionary(), std::string(keybuffer),tmp)) continue;*/ sprintf( valbuffer, "%1f %1f %1f", mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(0), mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(1), mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(2)); itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string(keybuffer),std::string(valbuffer)); } typedef itk::VectorImage ImageType; std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation()); ext = itksys::SystemTools::LowerCase(ext); // default extension is .dwi if( ext == "") { ext = ".nrrd"; this->SetOutputLocation(this->GetOutputLocation() + ext); } if (ext == ".hdwi" || ext == ".nrrd" || ext == ".dwi") { MITK_INFO << "Extension " << ext; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); //io->SetNrrdVectorType( nrrdKindList ); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); typedef itk::ImageFileWriter WriterType; WriterType::Pointer nrrdWriter = WriterType::New(); nrrdWriter->UseInputMetaDataDictionaryOn(); nrrdWriter->SetInput( itkImg ); nrrdWriter->SetImageIO(io); nrrdWriter->SetFileName(this->GetOutputLocation()); nrrdWriter->UseCompressionOn(); nrrdWriter->SetImageIO(io); try { nrrdWriter->Update(); } catch (itk::ExceptionObject e) { std::cout << e << std::endl; throw; } } else if (ext == ".fsl" || ext == ".fslgz") { MITK_INFO << "Writing Nifti-Image for FSL"; typedef itk::Image ImageType4D; ImageType4D::Pointer img4 = ImageType4D::New(); ImageType::SpacingType spacing = itkImg->GetSpacing(); ImageType4D::SpacingType spacing4; for(int i=0; i<3; i++) spacing4[i] = spacing[i]; spacing4[3] = 1; img4->SetSpacing( spacing4 ); // Set the image spacing ImageType::PointType origin = itkImg->GetOrigin(); ImageType4D::PointType origin4; for(int i=0; i<3; i++) origin4[i] = origin[i]; origin4[3] = 0; img4->SetOrigin( origin4 ); // Set the image origin ImageType::DirectionType direction = itkImg->GetDirection(); ImageType4D::DirectionType direction4; for(int i=0; i<3; i++) for(int j=0; j<3; j++) direction4[i][j] = direction[i][j]; for(int i=0; i<4; i++) direction4[i][3] = 0; for(int i=0; i<4; i++) direction4[3][i] = 0; direction4[3][3] = 1; img4->SetDirection( direction4 ); // Set the image direction ImageType::RegionType region = itkImg->GetLargestPossibleRegion(); ImageType4D::RegionType region4; ImageType::RegionType::SizeType size = region.GetSize(); ImageType4D::RegionType::SizeType size4; for(int i=0; i<3; i++) size4[i] = size[i]; size4[3] = itkImg->GetVectorLength(); ImageType::RegionType::IndexType index = region.GetIndex(); ImageType4D::RegionType::IndexType index4; for(int i=0; i<3; i++) index4[i] = index[i]; index4[3] = 0; region4.SetSize(size4); region4.SetIndex(index4); img4->SetRegions( region4 ); img4->Allocate(); itk::ImageRegionIterator it (itkImg, itkImg->GetLargestPossibleRegion() ); typedef ImageType::PixelType VecPixType; for (it.GoToBegin(); !it.IsAtEnd(); ++it) { VecPixType vec = it.Get(); ImageType::IndexType currentIndex = it.GetIndex(); for(unsigned int ind=0; indSetPixel(index4, vec[ind]); } } // create copy of file with correct ending for mitk std::string fname3 = this->GetOutputLocation(); std::string::iterator itend = fname3.end(); if (ext == ".fsl") fname3.replace( itend-3, itend, "nii"); else fname3.replace( itend-5, itend, "nii.gz"); itk::NiftiImageIO::Pointer io4 = itk::NiftiImageIO::New(); typedef itk::VectorImage ImageType; typedef itk::ImageFileWriter WriterType4; WriterType4::Pointer nrrdWriter4 = WriterType4::New(); nrrdWriter4->UseInputMetaDataDictionaryOn(); nrrdWriter4->SetInput( img4 ); nrrdWriter4->SetFileName(fname3); nrrdWriter4->UseCompressionOn(); nrrdWriter4->SetImageIO(io4); try { nrrdWriter4->Update(); } catch (itk::ExceptionObject e) { std::cout << e << std::endl; throw; } itksys::SystemTools::CopyAFile(fname3.c_str(), this->GetOutputLocation().c_str()); if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size()) { std::ofstream myfile; std::string fname = this->GetOutputLocation(); fname += ".bvals"; myfile.open (fname.c_str()); for(unsigned int i=0; iSize(); i++) { double twonorm = mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).two_norm(); myfile << mitk::DiffusionPropertyHelper::GetReferenceBValue(input)*twonorm*twonorm << " "; } myfile.close(); std::ofstream myfile2; std::string fname2 = this->GetOutputLocation(); fname2 += ".bvecs"; myfile2.open (fname2.c_str()); for(int j=0; j<3; j++) { for(unsigned int i=0; iSize(); i++) { //need to modify the length GradientDirectionContainerType::Pointer grads = mitk::DiffusionPropertyHelper::GetGradientContainer(input); GradientDirectionType direction = grads->ElementAt(i); direction.normalize(); myfile2 << direction.get(j) << " "; //myfile2 << input->GetDirections()->ElementAt(i).get(j) << " "; } myfile2 << std::endl; } std::ofstream myfile3; std::string fname4 = this->GetOutputLocation(); fname4 += ".ttk"; myfile3.open (fname4.c_str()); for(unsigned int i=0; iSize(); i++) { for(int j=0; j<3; j++) { myfile3 << mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(j) << " "; } myfile3 << std::endl; } } } try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } mitk::NrrdDiffusionImageWriter* mitk::NrrdDiffusionImageWriter::Clone() const { return new NrrdDiffusionImageWriter(*this); } mitk::IFileWriter::ConfidenceLevel mitk::NrrdDiffusionImageWriter::GetConfidenceLevel() const { mitk::Image::ConstPointer input = dynamic_cast(this->GetInput()); if (input.IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( input ) ) { return Unsupported; } else { return Supported; } } #endif //__mitkNrrdDiffusionImageWriter__cpp diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdQBallImageReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdQBallImageReader.cpp index ded1f8939f..b53dd5b608 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdQBallImageReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdQBallImageReader.cpp @@ -1,138 +1,138 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNrrdQBallImageReader.h" #include #include "mitkDiffusionIOMimeTypes.h" #include "itkImageFileReader.h" #include "itkImageRegionIterator.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include "mitkITKImageImport.h" #include "mitkImageDataItem.h" namespace mitk { NrrdQBallImageReader::NrrdQBallImageReader(const NrrdQBallImageReader& other) : mitk::AbstractFileReader(other) { } NrrdQBallImageReader::NrrdQBallImageReader() - : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::QBI_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::QBI_MIMETYPE_DESCRIPTION() ) + : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::QBI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::QBI_MIMETYPE_DESCRIPTION() ) { m_ServiceReg = this->RegisterService(); } NrrdQBallImageReader::~NrrdQBallImageReader() { } std::vector > NrrdQBallImageReader::Read() { std::vector > result; std::string location = GetInputLocation(); if ( location == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename of the vessel tree to be read is empty!"); } else { try { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } typedef itk::VectorImage ImageType; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(location); reader->Update(); ImageType::Pointer img = reader->GetOutput(); typedef itk::Image,3> VecImgType; VecImgType::Pointer vecImg = VecImgType::New(); vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin vecImg->SetDirection( img->GetDirection() ); // Set the image direction vecImg->SetLargestPossibleRegion( img->GetLargestPossibleRegion()); vecImg->SetBufferedRegion( img->GetLargestPossibleRegion() ); vecImg->Allocate(); itk::ImageRegionIterator ot (vecImg, vecImg->GetLargestPossibleRegion() ); ot.GoToBegin(); itk::ImageRegionIterator it (img, img->GetLargestPossibleRegion() ); typedef ImageType::PixelType VarPixType; typedef VecImgType::PixelType FixPixType; for (it.GoToBegin(); !it.IsAtEnd(); ++it) { VarPixType vec = it.Get(); FixPixType fixVec(vec.GetDataPointer()); ot.Set(fixVec); ++ot; } OutputType::Pointer resultImage = OutputType::New(); resultImage->InitializeByItk( vecImg.GetPointer() ); resultImage->SetVolume( vecImg->GetBufferPointer() ); result.push_back( resultImage.GetPointer() ); try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } catch(std::exception& e) { throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!"); } } return result; } } //namespace MITK mitk::NrrdQBallImageReader* mitk::NrrdQBallImageReader::Clone() const { return new NrrdQBallImageReader(*this); } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdQBallImageWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdQBallImageWriter.cpp index ca5a85ed7a..9753499e85 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdQBallImageWriter.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdQBallImageWriter.cpp @@ -1,149 +1,149 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNrrdQBallImageWriter.h" #include "itkMetaDataDictionary.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include "itkImageFileWriter.h" #include "mitkImageCast.h" #include "mitkIOMimeTypes.h" #include "mitkDiffusionIOMimeTypes.h" mitk::NrrdQBallImageWriter::NrrdQBallImageWriter() - : AbstractFileWriter(mitk::QBallImage::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::QBI_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::QBI_MIMETYPE_DESCRIPTION()) + : AbstractFileWriter(mitk::QBallImage::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::QBI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::QBI_MIMETYPE_DESCRIPTION()) { RegisterService(); } mitk::NrrdQBallImageWriter::NrrdQBallImageWriter(const mitk::NrrdQBallImageWriter& other) : AbstractFileWriter(other) { } mitk::NrrdQBallImageWriter::~NrrdQBallImageWriter() {} void mitk::NrrdQBallImageWriter::Write() { InputType::ConstPointer input = dynamic_cast(this->GetInput()); if (input.IsNull()) { MITK_ERROR <<"Sorry, input to NrrdQBallImageWriter is NULL!"; return; } if ( this->GetOutputLocation().empty() ) { MITK_ERROR << "Sorry, filename has not been set!"; return ; } const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); typedef itk::VectorImage VecImgType; typedef itk::Image,3> ImageType; typedef itk::ImageFileWriter WriterType; WriterType::Pointer nrrdWriter = WriterType::New(); ImageType::Pointer outimage = ImageType::New(); CastToItkImage(input, outimage); VecImgType::Pointer vecImg = VecImgType::New(); vecImg->SetSpacing( outimage->GetSpacing() ); // Set the image spacing vecImg->SetOrigin( outimage->GetOrigin() ); // Set the image origin vecImg->SetDirection( outimage->GetDirection() ); // Set the image direction vecImg->SetLargestPossibleRegion( outimage->GetLargestPossibleRegion()); vecImg->SetBufferedRegion( outimage->GetLargestPossibleRegion() ); vecImg->SetVectorLength(QBALL_ODFSIZE); vecImg->Allocate(); itk::ImageRegionIterator ot (vecImg, vecImg->GetLargestPossibleRegion() ); ot.GoToBegin(); itk::ImageRegionIterator it (outimage, outimage->GetLargestPossibleRegion() ); typedef ImageType::PixelType VecPixType; typedef VecImgType::PixelType VarVecType; for (it.GoToBegin(); !it.IsAtEnd(); ++it) { VecPixType vec = it.Get(); VarVecType varVec(vec.GetVnlVector().data_block(), QBALL_ODFSIZE); ot.Set(varVec); ++ot; } nrrdWriter->SetInput( vecImg ); nrrdWriter->SetImageIO(io); nrrdWriter->SetFileName(this->GetOutputLocation().c_str()); nrrdWriter->UseCompressionOn(); try { nrrdWriter->Update(); } catch (itk::ExceptionObject e) { std::cout << e << std::endl; } try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } mitk::NrrdQBallImageWriter* mitk::NrrdQBallImageWriter::Clone() const { return new NrrdQBallImageWriter(*this); } mitk::IFileWriter::ConfidenceLevel mitk::NrrdQBallImageWriter::GetConfidenceLevel() const { InputType::ConstPointer input = dynamic_cast(this->GetInput()); if (input.IsNull() ) { return Unsupported; } else { return Supported; } } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdTensorImageReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdTensorImageReader.cpp index e729705f60..81debc15d9 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdTensorImageReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdTensorImageReader.cpp @@ -1,441 +1,441 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNrrdTensorImageReader.h" #include #include "mitkDiffusionIOMimeTypes.h" #include "itkImageFileReader.h" #include "itkImageRegionIterator.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include #include "mitkITKImageImport.h" #include "mitkImageDataItem.h" namespace mitk { NrrdTensorImageReader::NrrdTensorImageReader(const NrrdTensorImageReader& other) : mitk::AbstractFileReader(other) { } NrrdTensorImageReader::NrrdTensorImageReader() - : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DTI_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::DTI_MIMETYPE_DESCRIPTION() ) + : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DTI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DTI_MIMETYPE_DESCRIPTION() ) { m_ServiceReg = this->RegisterService(); } NrrdTensorImageReader::~NrrdTensorImageReader() { } std::vector > NrrdTensorImageReader::Read() { std::vector > result; std::string location = GetInputLocation(); if ( location == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename is empty!"); } else { try { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } try { std::string fname3 = "temp_dti.nii"; itksys::SystemTools::CopyAFile(location.c_str(), fname3.c_str()); typedef itk::VectorImage ImageType; itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(fname3); reader->Update(); ImageType::Pointer img = reader->GetOutput(); typedef itk::Image,3> VecImgType; VecImgType::Pointer vecImg = VecImgType::New(); vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin vecImg->SetDirection( img->GetDirection() ); // Set the image direction vecImg->SetRegions( img->GetLargestPossibleRegion()); vecImg->Allocate(); itk::ImageRegionIterator ot (vecImg, vecImg->GetLargestPossibleRegion() ); ot.GoToBegin(); itk::ImageRegionIterator it (img, img->GetLargestPossibleRegion() ); it.GoToBegin(); typedef ImageType::PixelType VarPixType; typedef VecImgType::PixelType FixPixType; int numComponents = img->GetNumberOfComponentsPerPixel(); if (numComponents==6) { MITK_INFO << "Trying to load dti as 6-comp nifti ..."; while (!it.IsAtEnd()) { VarPixType vec = it.Get(); FixPixType fixVec(vec.GetDataPointer()); itk::DiffusionTensor3D tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(3)); tensor.SetElement(4, vec.GetElement(4)); tensor.SetElement(5, vec.GetElement(5)); fixVec = tensor; ot.Set(fixVec); ++ot; ++it; } } else if(numComponents==9) { MITK_INFO << "Trying to load dti as 9-comp nifti ..."; while (!it.IsAtEnd()) { VarPixType vec = it.Get(); itk::DiffusionTensor3D tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(4)); tensor.SetElement(4, vec.GetElement(5)); tensor.SetElement(5, vec.GetElement(8)); FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; ++it; } } else if (numComponents==1) { MITK_INFO << "Trying to load dti as 4D nifti ..."; typedef itk::Image ImageType; typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(fname3); reader->Update(); ImageType::Pointer img = reader->GetOutput(); itk::Size<4> size = img->GetLargestPossibleRegion().GetSize(); while (!ot.IsAtEnd()) { itk::DiffusionTensor3D tensor; ImageType::IndexType idx; idx[0] = ot.GetIndex()[0]; idx[1] = ot.GetIndex()[1]; idx[2] = ot.GetIndex()[2]; if (size[3]==6) { for (unsigned int te=0; teGetPixel(idx)); } } else if (size[3]==9) { idx[3] = 0; tensor.SetElement(0, img->GetPixel(idx)); idx[3] = 1; tensor.SetElement(1, img->GetPixel(idx)); idx[3] = 2; tensor.SetElement(2, img->GetPixel(idx)); idx[3] = 4; tensor.SetElement(3, img->GetPixel(idx)); idx[3] = 5; tensor.SetElement(4, img->GetPixel(idx)); idx[3] = 8; tensor.SetElement(5, img->GetPixel(idx)); } else throw itk::ImageFileReaderException(__FILE__, __LINE__, "Unknown number of components for DTI file. Should be 6 or 9!"); FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; } } OutputType::Pointer resultImage = OutputType::New(); resultImage->InitializeByItk( vecImg.GetPointer() ); resultImage->SetVolume( vecImg->GetBufferPointer() ); result.push_back( resultImage.GetPointer() ); } catch(...) { MITK_INFO << "Trying to load dti as nrrd ..."; typedef itk::VectorImage ImageType; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(location); reader->Update(); ImageType::Pointer img = reader->GetOutput(); typedef itk::Image,3> VecImgType; VecImgType::Pointer vecImg = VecImgType::New(); vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin vecImg->SetDirection( img->GetDirection() ); // Set the image direction vecImg->SetRegions( img->GetLargestPossibleRegion()); vecImg->Allocate(); itk::ImageRegionIterator ot (vecImg, vecImg->GetLargestPossibleRegion() ); ot.GoToBegin(); itk::ImageRegionIterator it (img, img->GetLargestPossibleRegion() ); it.GoToBegin(); typedef ImageType::PixelType VarPixType; typedef VecImgType::PixelType FixPixType; int numComponents = img->GetNumberOfComponentsPerPixel(); itk::MetaDataDictionary imgMetaDictionary = img->GetMetaDataDictionary(); std::vector imgMetaKeys = imgMetaDictionary.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString; bool readFrame = false; double xx, xy, xz, yx, yy, yz, zx, zy, zz; MeasurementFrameType measFrame; measFrame.SetIdentity(); MeasurementFrameType measFrameTransp; measFrameTransp.SetIdentity(); for (; itKey != imgMetaKeys.end(); itKey ++) { itk::ExposeMetaData (imgMetaDictionary, *itKey, metaString); if (itKey->find("measurement frame") != std::string::npos) { sscanf(metaString.c_str(), " ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) \n", &xx, &xy, &xz, &yx, &yy, &yz, &zx, &zy, &zz); if (xx>10e-10 || xy>10e-10 || xz>10e-10 || yx>10e-10 || yy>10e-10 || yz>10e-10 || zx>10e-10 || zy>10e-10 || zz>10e-10 ) { readFrame = true; measFrame(0,0) = xx; measFrame(0,1) = xy; measFrame(0,2) = xz; measFrame(1,0) = yx; measFrame(1,1) = yy; measFrame(1,2) = yz; measFrame(2,0) = zx; measFrame(2,1) = zy; measFrame(2,2) = zz; measFrameTransp = measFrame.GetTranspose(); } } } if (numComponents==6) { while (!it.IsAtEnd()) { // T'=RTR' VarPixType vec = it.Get(); FixPixType fixVec(vec.GetDataPointer()); if(readFrame) { itk::DiffusionTensor3D tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(3)); tensor.SetElement(4, vec.GetElement(4)); tensor.SetElement(5, vec.GetElement(5)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp)); fixVec = tensor; } ot.Set(fixVec); ++ot; ++it; } } else if(numComponents==9) { while (!it.IsAtEnd()) { VarPixType vec = it.Get(); itk::DiffusionTensor3D tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(4)); tensor.SetElement(4, vec.GetElement(5)); tensor.SetElement(5, vec.GetElement(8)); if(readFrame) { tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp)); } FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; ++it; } } else if (numComponents==1) { typedef itk::Image ImageType; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(location); reader->Update(); ImageType::Pointer img = reader->GetOutput(); itk::Size<4> size = img->GetLargestPossibleRegion().GetSize(); while (!ot.IsAtEnd()) { itk::DiffusionTensor3D tensor; ImageType::IndexType idx; idx[0] = ot.GetIndex()[0]; idx[1] = ot.GetIndex()[1]; idx[2] = ot.GetIndex()[2]; if (size[3]==6) { for (unsigned int te=0; teGetPixel(idx)); } } else if (size[3]==9) { idx[3] = 0; tensor.SetElement(0, img->GetPixel(idx)); idx[3] = 1; tensor.SetElement(1, img->GetPixel(idx)); idx[3] = 2; tensor.SetElement(2, img->GetPixel(idx)); idx[3] = 4; tensor.SetElement(3, img->GetPixel(idx)); idx[3] = 5; tensor.SetElement(4, img->GetPixel(idx)); idx[3] = 8; tensor.SetElement(5, img->GetPixel(idx)); } else throw itk::ImageFileReaderException(__FILE__, __LINE__, "Unknown number of komponents for DTI file. Should be 6 or 9!"); if(readFrame) { tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp)); } FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; } } else { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Image has wrong number of pixel components!"); } OutputType::Pointer resultImage = OutputType::New(); resultImage->InitializeByItk( vecImg.GetPointer() ); resultImage->SetVolume( vecImg->GetBufferPointer() ); result.push_back( resultImage.GetPointer() ); } try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } catch(std::exception& e) { throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested DTI file!"); } } return result; } itk::DiffusionTensor3D NrrdTensorImageReader ::ConvertMatrixTypeToFixedArrayType(const itk::DiffusionTensor3D::Superclass::MatrixType & matrix) { /* | 0 1 2 | * | X 3 4 | * | X X 5 | */ itk::DiffusionTensor3D arr; arr.SetElement(0,matrix(0,0)); arr.SetElement(1,matrix(0,1)); arr.SetElement(2,matrix(0,2)); arr.SetElement(3,matrix(1,3)); arr.SetElement(4,matrix(1,4)); arr.SetElement(5,matrix(2,5)); return arr; } } //namespace MITK mitk::NrrdTensorImageReader* mitk::NrrdTensorImageReader::Clone() const { return new NrrdTensorImageReader(*this); } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdTensorImageWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdTensorImageWriter.cpp index 5941d905cb..ae52ef1aab 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdTensorImageWriter.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkNrrdTensorImageWriter.cpp @@ -1,122 +1,122 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNrrdTensorImageWriter.h" #include "itkMetaDataDictionary.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include "itkImageFileWriter.h" #include "itkDiffusionTensor3D.h" #include "mitkImageCast.h" #include "mitkDiffusionIOMimeTypes.h" mitk::NrrdTensorImageWriter::NrrdTensorImageWriter() - : AbstractFileWriter(mitk::TensorImage::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DTI_MIMETYPE_NAME() ), mitk::DiffusionIOMimeTypes::DTI_MIMETYPE_DESCRIPTION() ) + : AbstractFileWriter(mitk::TensorImage::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DTI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DTI_MIMETYPE_DESCRIPTION() ) { RegisterService(); } mitk::NrrdTensorImageWriter::NrrdTensorImageWriter(const mitk::NrrdTensorImageWriter& other) : AbstractFileWriter(other) { } mitk::NrrdTensorImageWriter::~NrrdTensorImageWriter() {} void mitk::NrrdTensorImageWriter::Write() { InputType::ConstPointer input = dynamic_cast(this->GetInput()); if (input.IsNull() ) { MITK_ERROR <<"Sorry, input to NrrdTensorImageWriter is NULL!"; return; } if ( this->GetOutputLocation().empty() ) { MITK_ERROR << "Sorry, filename has not been set!" ; return ; } const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); typedef itk::Image,3> ImageType; typedef itk::ImageFileWriter WriterType; WriterType::Pointer nrrdWriter = WriterType::New(); ImageType::Pointer outimage = ImageType::New(); CastToItkImage(input, outimage); nrrdWriter->SetInput( outimage ); nrrdWriter->SetImageIO(io); nrrdWriter->SetFileName(this->GetOutputLocation().c_str()); nrrdWriter->UseCompressionOn(); try { nrrdWriter->Update(); } catch (itk::ExceptionObject e) { std::cout << e << std::endl; } try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } mitk::NrrdTensorImageWriter* mitk::NrrdTensorImageWriter::Clone() const { return new NrrdTensorImageWriter(*this); } mitk::IFileWriter::ConfidenceLevel mitk::NrrdTensorImageWriter::GetConfidenceLevel() const { InputType::ConstPointer input = dynamic_cast(this->GetInput()); if (input.IsNull() ) { return Unsupported; } else { return Supported; } } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp index c9dccdeb1b..13df693a5d 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp @@ -1,241 +1,248 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Coindex[1]right (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkTractDensityImageFilter.h" // VTK #include #include #include #include // misc #include #include namespace itk{ template< class OutputImageType > TractDensityImageFilter< OutputImageType >::TractDensityImageFilter() : m_InvertImage(false) , m_FiberBundle(NULL) , m_UpsamplingFactor(1) , m_InputImage(NULL) , m_BinaryOutput(false) , m_UseImageGeometry(false) , m_OutputAbsoluteValues(false) , m_UseTrilinearInterpolation(false) + , m_DoFiberResampling(true) { } template< class OutputImageType > TractDensityImageFilter< OutputImageType >::~TractDensityImageFilter() { } template< class OutputImageType > itk::Point TractDensityImageFilter< OutputImageType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class OutputImageType > void TractDensityImageFilter< OutputImageType >::GenerateData() { // generate upsampled image mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry(); typename OutputImageType::Pointer outImage = this->GetOutput(); // calculate new image parameters itk::Vector newSpacing; mitk::Point3D newOrigin; itk::Matrix newDirection; ImageRegion<3> upsampledRegion; if (m_UseImageGeometry && !m_InputImage.IsNull()) { MITK_INFO << "TractDensityImageFilter: using image geometry"; newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor; upsampledRegion = m_InputImage->GetLargestPossibleRegion(); newOrigin = m_InputImage->GetOrigin(); typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize(); size[0] *= m_UpsamplingFactor; size[1] *= m_UpsamplingFactor; size[2] *= m_UpsamplingFactor; upsampledRegion.SetSize(size); newDirection = m_InputImage->GetDirection(); } else { MITK_INFO << "TractDensityImageFilter: using fiber bundle geometry"; newSpacing = geometry->GetSpacing()/m_UpsamplingFactor; newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); for (int i=0; i<3; i++) for (int j=0; j<3; j++) newDirection[j][i] = geometry->GetMatrixColumn(i)[j]; upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); } typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); // apply new image parameters outImage->SetSpacing( newSpacing ); outImage->SetOrigin( newOrigin ); outImage->SetDirection( newDirection ); outImage->SetLargestPossibleRegion( upsampledRegion ); outImage->SetBufferedRegion( upsampledRegion ); outImage->SetRequestedRegion( upsampledRegion ); outImage->Allocate(); outImage->FillBuffer(0.0); int w = upsampledSize[0]; int h = upsampledSize[1]; int d = upsampledSize[2]; // set/initialize output OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer(); // resample fiber bundle float minSpacing = 1; if(newSpacing[0]GetDeepCopy(); - m_FiberBundle->ResampleSpline(minSpacing/10); + if (m_DoFiberResampling) + { + m_FiberBundle = m_FiberBundle->GetDeepCopy(); + m_FiberBundle->ResampleSpline(minSpacing/10); + } MITK_INFO << "TractDensityImageFilter: starting image generation"; vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int numFibers = m_FiberBundle->GetNumFibers(); boost::progress_display disp(numFibers); for( int i=0; iGetNextCell ( numPoints, points ); + float weight = m_FiberBundle->GetFiberWeight(i); // fill output image for( int j=0; j vertex = GetItkPoint(fiberPolyData->GetPoint(points[j])); itk::Index<3> index; itk::ContinuousIndex contIndex; outImage->TransformPhysicalPointToIndex(vertex, index); outImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); if (!m_UseTrilinearInterpolation && outImage->GetLargestPossibleRegion().IsInside(index)) { if (m_BinaryOutput) outImage->SetPixel(index, 1); else - outImage->SetPixel(index, outImage->GetPixel(index)+0.01); + outImage->SetPixel(index, outImage->GetPixel(index)+0.01*weight); continue; } float frac_x = contIndex[0] - index[0]; float frac_y = contIndex[1] - index[1]; float frac_z = contIndex[2] - index[2]; if (frac_x<0) { index[0] -= 1; frac_x += 1; } if (frac_y<0) { index[1] -= 1; frac_y += 1; } if (frac_z<0) { index[2] -= 1; frac_z += 1; } frac_x = 1-frac_x; frac_y = 1-frac_y; frac_z = 1-frac_z; // int coordinates inside image? if (index[0] < 0 || index[0] >= w-1) continue; if (index[1] < 0 || index[1] >= h-1) continue; if (index[2] < 0 || index[2] >= d-1) continue; if (m_BinaryOutput) { outImageBufferPointer[( index[0] + w*(index[1] + h*index[2] ))] = 1; outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2] ))] = 1; outImageBufferPointer[( index[0] + w*(index[1] + h*index[2]+h))] = 1; outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2]+h))] = 1; outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2] ))] = 1; outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2]+h))] = 1; outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2] ))] = 1; outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2]+h))] = 1; } else { outImageBufferPointer[( index[0] + w*(index[1] + h*index[2] ))] += ( frac_x)*( frac_y)*( frac_z); outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2] ))] += ( frac_x)*(1-frac_y)*( frac_z); outImageBufferPointer[( index[0] + w*(index[1] + h*index[2]+h))] += ( frac_x)*( frac_y)*(1-frac_z); outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2]+h))] += ( frac_x)*(1-frac_y)*(1-frac_z); outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2] ))] += (1-frac_x)*( frac_y)*( frac_z); outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2]+h))] += (1-frac_x)*( frac_y)*(1-frac_z); outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2] ))] += (1-frac_x)*(1-frac_y)*( frac_z); outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2]+h))] += (1-frac_x)*(1-frac_y)*(1-frac_z); } } } if (!m_OutputAbsoluteValues && !m_BinaryOutput) { MITK_INFO << "TractDensityImageFilter: max-normalizing output image"; OutPixelType max = 0; for (int i=0; i0) for (int i=0; i #include #include #include #include namespace itk{ /** * \brief Generates tract density images from input fiberbundles (Calamante 2010). */ template< class OutputImageType > class TractDensityImageFilter : public ImageSource< OutputImageType > { public: typedef TractDensityImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename OutputImageType::PixelType OutPixelType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( TractDensityImageFilter, ImageSource ) itkSetMacro( UpsamplingFactor, float) ///< use higher resolution for ouput image itkGetMacro( UpsamplingFactor, float) ///< use higher resolution for ouput image itkSetMacro( InvertImage, bool) ///< voxelvalue = 1-voxelvalue itkGetMacro( InvertImage, bool) ///< voxelvalue = 1-voxelvalue itkSetMacro( BinaryOutput, bool) ///< generate binary fiber envelope itkGetMacro( BinaryOutput, bool) ///< generate binary fiber envelope itkSetMacro( OutputAbsoluteValues, bool) ///< output absolute values of the number of fibers per voxel itkGetMacro( OutputAbsoluteValues, bool) ///< output absolute values of the number of fibers per voxel itkSetMacro( UseImageGeometry, bool) ///< use input image geometry to initialize output image itkGetMacro( UseImageGeometry, bool) ///< use input image geometry to initialize output image itkSetMacro( FiberBundle, mitk::FiberBundleX::Pointer) ///< input fiber bundle itkSetMacro( InputImage, typename OutputImageType::Pointer) ///< use input image geometry to initialize output image itkSetMacro( UseTrilinearInterpolation, bool ) + itkSetMacro( DoFiberResampling, bool ) void GenerateData(); protected: itk::Point GetItkPoint(double point[3]); TractDensityImageFilter(); virtual ~TractDensityImageFilter(); typename OutputImageType::Pointer m_InputImage; ///< use input image geometry to initialize output image mitk::FiberBundleX::Pointer m_FiberBundle; ///< input fiber bundle float m_UpsamplingFactor; ///< use higher resolution for ouput image bool m_InvertImage; ///< voxelvalue = 1-voxelvalue bool m_BinaryOutput; ///< generate binary fiber envelope bool m_UseImageGeometry; ///< use input image geometry to initialize output image bool m_OutputAbsoluteValues; ///< do not normalize image values to 0-1 bool m_UseTrilinearInterpolation; + bool m_DoFiberResampling; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractDensityImageFilter.cpp" #endif #endif // __itkTractDensityImageFilter_h__ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp index 1805a97fb1..86093896aa 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp @@ -1,1301 +1,1302 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkTractsToDWIImageFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace itk { template< class PixelType > TractsToDWIImageFilter< PixelType >::TractsToDWIImageFilter() : m_FiberBundle(NULL) , m_StatusText("") , m_UseConstantRandSeed(false) , m_RandGen(itk::Statistics::MersenneTwisterRandomVariateGenerator::New()) { m_RandGen->SetSeed(); } template< class PixelType > TractsToDWIImageFilter< PixelType >::~TractsToDWIImageFilter() { } template< class PixelType > TractsToDWIImageFilter< PixelType >::DoubleDwiType::Pointer TractsToDWIImageFilter< PixelType >::DoKspaceStuff( std::vector< DoubleDwiType::Pointer >& images ) { int numFiberCompartments = m_Parameters.m_FiberModelList.size(); // create slice object ImageRegion<2> sliceRegion; sliceRegion.SetSize(0, m_UpsampledImageRegion.GetSize()[0]); sliceRegion.SetSize(1, m_UpsampledImageRegion.GetSize()[1]); Vector< double, 2 > sliceSpacing; sliceSpacing[0] = m_UpsampledSpacing[0]; sliceSpacing[1] = m_UpsampledSpacing[1]; // frequency map slice SliceType::Pointer fMapSlice = NULL; if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull()) { fMapSlice = SliceType::New(); ImageRegion<2> region; region.SetSize(0, m_UpsampledImageRegion.GetSize()[0]); region.SetSize(1, m_UpsampledImageRegion.GetSize()[1]); fMapSlice->SetLargestPossibleRegion( region ); fMapSlice->SetBufferedRegion( region ); fMapSlice->SetRequestedRegion( region ); fMapSlice->Allocate(); fMapSlice->FillBuffer(0.0); } DoubleDwiType::Pointer newImage = DoubleDwiType::New(); newImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); newImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin ); newImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); newImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_ImageRegion ); newImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_ImageRegion ); newImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_ImageRegion ); newImage->SetVectorLength( images.at(0)->GetVectorLength() ); newImage->Allocate(); std::vector< unsigned int > spikeVolume; for (unsigned int i=0; iGetIntegerVariate()%images.at(0)->GetVectorLength()); std::sort (spikeVolume.begin(), spikeVolume.end()); std::reverse (spikeVolume.begin(), spikeVolume.end()); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; unsigned long lastTick = 0; boost::progress_display disp(2*images.at(0)->GetVectorLength()*images.at(0)->GetLargestPossibleRegion().GetSize(2)); for (unsigned int g=0; gGetVectorLength(); g++) { std::vector< unsigned int > spikeSlice; while (!spikeVolume.empty() && spikeVolume.back()==g) { spikeSlice.push_back(m_RandGen->GetIntegerVariate()%images.at(0)->GetLargestPossibleRegion().GetSize(2)); spikeVolume.pop_back(); } std::sort (spikeSlice.begin(), spikeSlice.end()); std::reverse (spikeSlice.begin(), spikeSlice.end()); for (unsigned int z=0; zGetLargestPossibleRegion().GetSize(2); z++) { std::vector< SliceType::Pointer > compartmentSlices; std::vector< double > t2Vector; for (unsigned int i=0; i* signalModel; if (iSetLargestPossibleRegion( sliceRegion ); slice->SetBufferedRegion( sliceRegion ); slice->SetRequestedRegion( sliceRegion ); slice->SetSpacing(sliceSpacing); slice->Allocate(); slice->FillBuffer(0.0); // extract slice from channel g for (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; slice->SetPixel(index2D, images.at(i)->GetPixel(index3D)[g]); if (fMapSlice.IsNotNull() && i==0) fMapSlice->SetPixel(index2D, m_Parameters.m_SignalGen.m_FrequencyMap->GetPixel(index3D)); } compartmentSlices.push_back(slice); t2Vector.push_back(signalModel->GetT2()); } if (this->GetAbortGenerateData()) return NULL; // create k-sapce (inverse fourier transform slices) itk::Size<2> outSize; outSize.SetElement(0, m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0)); outSize.SetElement(1, m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)); itk::KspaceImageFilter< SliceType::PixelType >::Pointer idft = itk::KspaceImageFilter< SliceType::PixelType >::New(); idft->SetCompartmentImages(compartmentSlices); idft->SetT2(t2Vector); idft->SetUseConstantRandSeed(m_UseConstantRandSeed); idft->SetParameters(m_Parameters); idft->SetZ((double)z-(double)images.at(0)->GetLargestPossibleRegion().GetSize(2)/2.0); idft->SetDiffusionGradientDirection(m_Parameters.m_SignalGen.GetGradientDirection(g)); idft->SetFrequencyMapSlice(fMapSlice); idft->SetOutSize(outSize); int numSpikes = 0; while (!spikeSlice.empty() && spikeSlice.back()==z) { numSpikes++; spikeSlice.pop_back(); } idft->SetSpikesPerSlice(numSpikes); idft->Update(); ComplexSliceType::Pointer fSlice; fSlice = idft->GetOutput(); ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; // fourier transform slice SliceType::Pointer newSlice; itk::DftImageFilter< SliceType::PixelType >::Pointer dft = itk::DftImageFilter< SliceType::PixelType >::New(); dft->SetInput(fSlice); dft->Update(); newSlice = dft->GetOutput(); // put slice back into channel g for (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; DoubleDwiType::PixelType pix3D = newImage->GetPixel(index3D); pix3D[g] = newSlice->GetPixel(index2D); newImage->SetPixel(index3D, pix3D); } ++disp; newTick = 50*disp.count()/disp.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; } } m_StatusText += "\n\n"; return newImage; } template< class PixelType > void TractsToDWIImageFilter< PixelType >::GenerateData() { m_TimeProbe.Start(); m_StatusText = "Starting simulation\n"; // check input data if (m_FiberBundle.IsNull()) itkExceptionMacro("Input fiber bundle is NULL!"); if (m_Parameters.m_FiberModelList.empty()) itkExceptionMacro("No diffusion model for fiber compartments defined!"); if (m_Parameters.m_NonFiberModelList.empty()) itkExceptionMacro("No diffusion model for non-fiber compartments defined!"); int baselineIndex = m_Parameters.m_SignalGen.GetFirstBaselineIndex(); if (baselineIndex<0) itkExceptionMacro("No baseline index found!"); if (!m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition) m_Parameters.m_SignalGen.m_DoAddGibbsRinging = false; if (m_UseConstantRandSeed) // always generate the same random numbers? m_RandGen->SetSeed(0); else m_RandGen->SetSeed(); // initialize output dwi image ImageRegion<3> croppedRegion = m_Parameters.m_SignalGen.m_ImageRegion; croppedRegion.SetSize(1, croppedRegion.GetSize(1)*m_Parameters.m_SignalGen.m_CroppingFactor); itk::Point shiftedOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; shiftedOrigin[1] += (m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)-croppedRegion.GetSize(1))*m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; typename OutputImageType::Pointer outImage = OutputImageType::New(); outImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); outImage->SetOrigin( shiftedOrigin ); outImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); outImage->SetLargestPossibleRegion( croppedRegion ); outImage->SetBufferedRegion( croppedRegion ); outImage->SetRequestedRegion( croppedRegion ); outImage->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); outImage->Allocate(); typename OutputImageType::PixelType temp; temp.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); temp.Fill(0.0); outImage->FillBuffer(temp); // ADJUST GEOMETRY FOR FURTHER PROCESSING // is input slize size a power of two? unsigned int x=m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0); unsigned int y=m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1); ItkDoubleImgType::SizeType pad; pad[0]=x%2; pad[1]=y%2; pad[2]=0; m_Parameters.m_SignalGen.m_ImageRegion.SetSize(0, x+pad[0]); m_Parameters.m_SignalGen.m_ImageRegion.SetSize(1, y+pad[1]); if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull() && (pad[0]>0 || pad[1]>0)) { itk::ConstantPadImageFilter::Pointer zeroPadder = itk::ConstantPadImageFilter::New(); zeroPadder->SetInput(m_Parameters.m_SignalGen.m_FrequencyMap); zeroPadder->SetConstant(0); zeroPadder->SetPadUpperBound(pad); zeroPadder->Update(); m_Parameters.m_SignalGen.m_FrequencyMap = zeroPadder->GetOutput(); } if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull() && (pad[0]>0 || pad[1]>0)) { itk::ConstantPadImageFilter::Pointer zeroPadder = itk::ConstantPadImageFilter::New(); zeroPadder->SetInput(m_Parameters.m_SignalGen.m_MaskImage); zeroPadder->SetConstant(0); zeroPadder->SetPadUpperBound(pad); zeroPadder->Update(); m_Parameters.m_SignalGen.m_MaskImage = zeroPadder->GetOutput(); } // Apply in-plane upsampling for Gibbs ringing artifact double upsampling = 1; if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) upsampling = 2; m_UpsampledSpacing = m_Parameters.m_SignalGen.m_ImageSpacing; m_UpsampledSpacing[0] /= upsampling; m_UpsampledSpacing[1] /= upsampling; m_UpsampledImageRegion = m_Parameters.m_SignalGen.m_ImageRegion; m_UpsampledImageRegion.SetSize(0, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[0]*upsampling); m_UpsampledImageRegion.SetSize(1, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[1]*upsampling); m_UpsampledOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; m_UpsampledOrigin[0] -= m_Parameters.m_SignalGen.m_ImageSpacing[0]/2; m_UpsampledOrigin[0] += m_UpsampledSpacing[0]/2; m_UpsampledOrigin[1] -= m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; m_UpsampledOrigin[1] += m_UpsampledSpacing[1]/2; m_UpsampledOrigin[2] -= m_Parameters.m_SignalGen.m_ImageSpacing[2]/2; m_UpsampledOrigin[2] += m_UpsampledSpacing[2]/2; // generate double images to store the individual compartment signals m_CompartmentImages.clear(); int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); for (int i=0; iSetSpacing( m_UpsampledSpacing ); doubleDwi->SetOrigin( m_UpsampledOrigin ); doubleDwi->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); doubleDwi->SetLargestPossibleRegion( m_UpsampledImageRegion ); doubleDwi->SetBufferedRegion( m_UpsampledImageRegion ); doubleDwi->SetRequestedRegion( m_UpsampledImageRegion ); doubleDwi->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); doubleDwi->Allocate(); DoubleDwiType::PixelType pix; pix.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); pix.Fill(0.0); doubleDwi->FillBuffer(pix); m_CompartmentImages.push_back(doubleDwi); } // initialize output volume fraction images m_VolumeFractions.clear(); for (int i=0; iSetSpacing( m_UpsampledSpacing ); doubleImg->SetOrigin( m_UpsampledOrigin ); doubleImg->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); doubleImg->SetLargestPossibleRegion( m_UpsampledImageRegion ); doubleImg->SetBufferedRegion( m_UpsampledImageRegion ); doubleImg->SetRequestedRegion( m_UpsampledImageRegion ); doubleImg->Allocate(); doubleImg->FillBuffer(0); m_VolumeFractions.push_back(doubleImg); } // get volume fraction images ItkDoubleImgType::Pointer sumImage = ItkDoubleImgType::New(); bool foundVolumeFractionImage = false; for (int i=0; iGetVolumeFractionImage().IsNotNull()) { foundVolumeFractionImage = true; itk::ConstantPadImageFilter::Pointer zeroPadder = itk::ConstantPadImageFilter::New(); zeroPadder->SetInput(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()); zeroPadder->SetConstant(0); zeroPadder->SetPadUpperBound(pad); zeroPadder->Update(); m_Parameters.m_NonFiberModelList[i]->SetVolumeFractionImage(zeroPadder->GetOutput()); sumImage->SetSpacing( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetSpacing() ); sumImage->SetOrigin( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetOrigin() ); sumImage->SetDirection( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetDirection() ); sumImage->SetLargestPossibleRegion( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion() ); sumImage->SetBufferedRegion( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion() ); sumImage->SetRequestedRegion( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion() ); sumImage->Allocate(); sumImage->FillBuffer(0); break; } } if (!foundVolumeFractionImage) { sumImage->SetSpacing( m_UpsampledSpacing ); sumImage->SetOrigin( m_UpsampledOrigin ); sumImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); sumImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); sumImage->SetBufferedRegion( m_UpsampledImageRegion ); sumImage->SetRequestedRegion( m_UpsampledImageRegion ); sumImage->Allocate(); sumImage->FillBuffer(0.0); } for (int i=0; iGetVolumeFractionImage().IsNull()) { ItkDoubleImgType::Pointer doubleImg = ItkDoubleImgType::New(); doubleImg->SetSpacing( sumImage->GetSpacing() ); doubleImg->SetOrigin( sumImage->GetOrigin() ); doubleImg->SetDirection( sumImage->GetDirection() ); doubleImg->SetLargestPossibleRegion( sumImage->GetLargestPossibleRegion() ); doubleImg->SetBufferedRegion( sumImage->GetLargestPossibleRegion() ); doubleImg->SetRequestedRegion( sumImage->GetLargestPossibleRegion() ); doubleImg->Allocate(); doubleImg->FillBuffer(1.0/numNonFiberCompartments); m_Parameters.m_NonFiberModelList[i]->SetVolumeFractionImage(doubleImg); } ImageRegionIterator it(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage(), m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { sumImage->SetPixel(it.GetIndex(), sumImage->GetPixel(it.GetIndex())+it.Get()); ++it; } } for (int i=0; i it(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage(), m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { if (sumImage->GetPixel(it.GetIndex())>0) it.Set(it.Get()/sumImage->GetPixel(it.GetIndex())); ++it; } } // resample mask image and frequency map to fit upsampled geometry if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) { if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull()) { // rescale mask image (otherwise there are problems with the resampling) itk::RescaleIntensityImageFilter::Pointer rescaler = itk::RescaleIntensityImageFilter::New(); rescaler->SetInput(0,m_Parameters.m_SignalGen.m_MaskImage); rescaler->SetOutputMaximum(100); rescaler->SetOutputMinimum(0); rescaler->Update(); // resample mask image itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(rescaler->GetOutput()); resampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage); resampler->SetSize(m_UpsampledImageRegion.GetSize()); resampler->SetOutputSpacing(m_UpsampledSpacing); resampler->SetOutputOrigin(m_UpsampledOrigin); itk::NearestNeighborInterpolateImageFunction::Pointer nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(nn_interpolator); resampler->Update(); m_Parameters.m_SignalGen.m_MaskImage = resampler->GetOutput(); itk::ImageFileWriter::Pointer w = itk::ImageFileWriter::New(); w->SetFileName("/local/mask_ups.nrrd"); w->SetInput(m_Parameters.m_SignalGen.m_MaskImage); w->Update(); } // resample frequency map if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull()) { itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(m_Parameters.m_SignalGen.m_FrequencyMap); resampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_FrequencyMap); resampler->SetSize(m_UpsampledImageRegion.GetSize()); resampler->SetOutputSpacing(m_UpsampledSpacing); resampler->SetOutputOrigin(m_UpsampledOrigin); itk::NearestNeighborInterpolateImageFunction::Pointer nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(nn_interpolator); resampler->Update(); m_Parameters.m_SignalGen.m_FrequencyMap = resampler->GetOutput(); } } // no input tissue mask is set -> create default m_MaskImageSet = true; if (m_Parameters.m_SignalGen.m_MaskImage.IsNull()) { m_StatusText += "No tissue mask set\n"; MITK_INFO << "No tissue mask set"; m_Parameters.m_SignalGen.m_MaskImage = ItkUcharImgType::New(); m_Parameters.m_SignalGen.m_MaskImage->SetSpacing( m_UpsampledSpacing ); m_Parameters.m_SignalGen.m_MaskImage->SetOrigin( m_UpsampledOrigin ); m_Parameters.m_SignalGen.m_MaskImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); m_Parameters.m_SignalGen.m_MaskImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->SetBufferedRegion( m_UpsampledImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->SetRequestedRegion( m_UpsampledImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->Allocate(); m_Parameters.m_SignalGen.m_MaskImage->FillBuffer(1); m_MaskImageSet = false; } else { m_StatusText += "Using tissue mask\n"; MITK_INFO << "Using tissue mask"; } m_Parameters.m_SignalGen.m_ImageRegion = croppedRegion; x=m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0); y=m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1); if ( x%2 == 1 ) m_Parameters.m_SignalGen.m_ImageRegion.SetSize(0, x+1); if ( y%2 == 1 ) m_Parameters.m_SignalGen.m_ImageRegion.SetSize(1, y+1); // resample fiber bundle for sufficient voxel coverage m_StatusText += "\n"+this->GetTime()+" > Resampling fibers ...\n"; double segmentVolume = 0.0001; float minSpacing = 1; if(m_UpsampledSpacing[0]GetDeepCopy(); double volumeAccuracy = 10; m_FiberBundleWorkingCopy->ResampleSpline(minSpacing/volumeAccuracy); double mmRadius = m_Parameters.m_SignalGen.m_AxonRadius/1000; if (mmRadius>0) segmentVolume = M_PI*mmRadius*mmRadius*minSpacing/volumeAccuracy; double maxVolume = 0; m_VoxelVolume = m_UpsampledSpacing[0]*m_UpsampledSpacing[1]*m_UpsampledSpacing[2]; if (m_Parameters.m_SignalGen.m_DoAddMotion) { std::string fileName = "fiberfox_motion_0.log"; std::string filePath = mitk::IOUtil::GetTempPath(); if (m_Parameters.m_Misc.m_OutputPath.size()>0) filePath = m_Parameters.m_Misc.m_OutputPath; int c = 1; while (itksys::SystemTools::FileExists((filePath+fileName).c_str())) { fileName = "fiberfox_motion_"; fileName += boost::lexical_cast(c); fileName += ".log"; c++; } m_Logfile.open((filePath+fileName).c_str()); m_Logfile << "0 rotation: 0,0,0; translation: 0,0,0\n"; if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { m_StatusText += "Adding random motion artifacts:\n"; m_StatusText += "Maximum rotation: +/-" + boost::lexical_cast(m_Parameters.m_SignalGen.m_Rotation) + "°\n"; m_StatusText += "Maximum translation: +/-" + boost::lexical_cast(m_Parameters.m_SignalGen.m_Translation) + "mm\n"; } else { m_StatusText += "Adding linear motion artifacts:\n"; m_StatusText += "Maximum rotation: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Rotation) + "°\n"; m_StatusText += "Maximum translation: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Translation) + "mm\n"; } m_StatusText += "Motion logfile: " + (filePath+fileName) + "\n"; MITK_INFO << "Adding motion artifacts"; MITK_INFO << "Maximum rotation: " << m_Parameters.m_SignalGen.m_Rotation; MITK_INFO << "Maxmimum translation: " << m_Parameters.m_SignalGen.m_Translation; } maxVolume = 0; m_StatusText += "\n"+this->GetTime()+" > Generating " + boost::lexical_cast(numFiberCompartments+numNonFiberCompartments) + "-compartment diffusion-weighted signal.\n"; MITK_INFO << "Generating " << numFiberCompartments+numNonFiberCompartments << "-compartment diffusion-weighted signal."; int numFibers = m_FiberBundle->GetNumFibers(); boost::progress_display disp(numFibers*m_Parameters.m_SignalGen.GetNumVolumes()); // get transform for motion artifacts m_FiberBundleTransformed = m_FiberBundleWorkingCopy; m_Rotation = m_Parameters.m_SignalGen.m_Rotation/m_Parameters.m_SignalGen.GetNumVolumes(); m_Translation = m_Parameters.m_SignalGen.m_Translation/m_Parameters.m_SignalGen.GetNumVolumes(); // creat image to hold transformed mask (motion artifact) m_MaskImage = ItkUcharImgType::New(); itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(m_Parameters.m_SignalGen.m_MaskImage); duplicator->Update(); m_MaskImage = duplicator->GetOutput(); // second upsampling needed for motion artifacts ImageRegion<3> upsampledImageRegion = m_UpsampledImageRegion; DoubleVectorType upsampledSpacing = m_UpsampledSpacing; upsampledSpacing[0] /= 4; upsampledSpacing[1] /= 4; upsampledSpacing[2] /= 4; upsampledImageRegion.SetSize(0, m_UpsampledImageRegion.GetSize()[0]*4); upsampledImageRegion.SetSize(1, m_UpsampledImageRegion.GetSize()[1]*4); upsampledImageRegion.SetSize(2, m_UpsampledImageRegion.GetSize()[2]*4); itk::Point upsampledOrigin = m_UpsampledOrigin; upsampledOrigin[0] -= m_UpsampledSpacing[0]/2; upsampledOrigin[0] += upsampledSpacing[0]/2; upsampledOrigin[1] -= m_UpsampledSpacing[1]/2; upsampledOrigin[1] += upsampledSpacing[1]/2; upsampledOrigin[2] -= m_UpsampledSpacing[2]/2; upsampledOrigin[2] += upsampledSpacing[2]/2; m_UpsampledMaskImage = ItkUcharImgType::New(); itk::ResampleImageFilter::Pointer upsampler = itk::ResampleImageFilter::New(); upsampler->SetInput(m_Parameters.m_SignalGen.m_MaskImage); upsampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage); upsampler->SetSize(upsampledImageRegion.GetSize()); upsampler->SetOutputSpacing(upsampledSpacing); upsampler->SetOutputOrigin(upsampledOrigin); itk::NearestNeighborInterpolateImageFunction::Pointer nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); upsampler->SetInterpolator(nn_interpolator); upsampler->Update(); m_UpsampledMaskImage = upsampler->GetOutput(); unsigned long lastTick = 0; int signalModelSeed = m_RandGen->GetIntegerVariate(); switch (m_Parameters.m_SignalGen.m_DiffusionDirectionMode) { case(SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS): // use fiber tangent directions to determine diffusion direction { m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; for (unsigned int g=0; gSetSeed(signalModelSeed); for (int i=0; iSetSeed(signalModelSeed); ItkDoubleImgType::Pointer intraAxonalVolumeImage = ItkDoubleImgType::New(); intraAxonalVolumeImage->SetSpacing( m_UpsampledSpacing ); intraAxonalVolumeImage->SetOrigin( m_UpsampledOrigin ); intraAxonalVolumeImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); intraAxonalVolumeImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); intraAxonalVolumeImage->SetBufferedRegion( m_UpsampledImageRegion ); intraAxonalVolumeImage->SetRequestedRegion( m_UpsampledImageRegion ); intraAxonalVolumeImage->Allocate(); intraAxonalVolumeImage->FillBuffer(0); vtkPolyData* fiberPolyData = m_FiberBundleTransformed->GetFiberPolyData(); // generate fiber signal (if there are any fiber models present) if (!m_Parameters.m_FiberModelList.empty()) for( int i=0; iGetFiberWeight(i); vtkCell* cell = fiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (numPoints<2) continue; for( int j=0; jGetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } double* temp = points->GetPoint(j); itk::Point vertex = GetItkPoint(temp); itk::Vector v = GetItkVector(temp); itk::Vector dir(3); if (jGetPoint(j+1))-v; else dir = v-GetItkVector(points->GetPoint(j-1)); if (dir.GetSquaredNorm()<0.0001 || dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2]) continue; itk::Index<3> idx; itk::ContinuousIndex contIndex; m_MaskImage->TransformPhysicalPointToIndex(vertex, idx); m_MaskImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); if (!m_MaskImage->GetLargestPossibleRegion().IsInside(idx) || m_MaskImage->GetPixel(idx)<=0) continue; // generate signal for each fiber compartment for (int k=0; kSetFiberDirection(dir); DoubleDwiType::PixelType pix = m_CompartmentImages.at(k)->GetPixel(idx); - pix[g] += segmentVolume*m_Parameters.m_FiberModelList[k]->SimulateMeasurement(g); + pix[g] += fiberWeight*segmentVolume*m_Parameters.m_FiberModelList[k]->SimulateMeasurement(g); m_CompartmentImages.at(k)->SetPixel(idx, pix); } // update fiber volume image - double vol = intraAxonalVolumeImage->GetPixel(idx) + segmentVolume; + double vol = intraAxonalVolumeImage->GetPixel(idx) + segmentVolume*fiberWeight; intraAxonalVolumeImage->SetPixel(idx, vol); if (g==0 && vol>maxVolume) maxVolume = vol; } // progress report ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; } // generate non-fiber signal ImageRegionIterator it3(m_MaskImage, m_MaskImage->GetLargestPossibleRegion()); double fact = 1; if (m_Parameters.m_SignalGen.m_AxonRadius<0.0001 || maxVolume>m_VoxelVolume) fact = m_VoxelVolume/maxVolume; while(!it3.IsAtEnd()) { if (it3.Get()>0) { DoubleDwiType::IndexType index = it3.GetIndex(); // adjust intra-axonal signal to abtain an only-fiber voxel if (fabs(fact-1.0)>0.0001) for (int i=0; iGetPixel(index); pix[g] *= fact; m_CompartmentImages.at(i)->SetPixel(index, pix); } // simulate other compartments SimulateNonFiberSignal(index, intraAxonalVolumeImage->GetPixel(index)*fact, g); } ++it3; } // move fibers SimulateMotion(g); } break; } case (SignalGenerationParameters::MAIN_FIBER_DIRECTIONS): // use main fiber directions to determine voxel-wise diffusion directions { typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; // calculate main fiber directions itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(m_FiberBundleTransformed); fOdfFilter->SetMaskImage(m_MaskImage); fOdfFilter->SetAngularThreshold(cos(m_Parameters.m_SignalGen.m_FiberSeparationThreshold*M_PI/180.0)); fOdfFilter->SetNormalizeVectors(false); fOdfFilter->SetUseWorkingCopy(true); fOdfFilter->SetSizeThreshold(0); fOdfFilter->SetMaxNumDirections(3); fOdfFilter->Update(); ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); // allocate image storing intra-axonal volume fraction information ItkDoubleImgType::Pointer intraAxonalVolumeImage = ItkDoubleImgType::New(); intraAxonalVolumeImage->SetSpacing( m_UpsampledSpacing ); intraAxonalVolumeImage->SetOrigin( m_UpsampledOrigin ); intraAxonalVolumeImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); intraAxonalVolumeImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); intraAxonalVolumeImage->SetBufferedRegion( m_UpsampledImageRegion ); intraAxonalVolumeImage->SetRequestedRegion( m_UpsampledImageRegion ); intraAxonalVolumeImage->Allocate(); intraAxonalVolumeImage->FillBuffer(0); // determine intra-axonal volume fraction using the tract density itk::TractDensityImageFilter< ItkDoubleImgType >::Pointer tdiFilter = itk::TractDensityImageFilter< ItkDoubleImgType >::New(); tdiFilter->SetFiberBundle(m_FiberBundleTransformed); tdiFilter->SetBinaryOutput(false); tdiFilter->SetOutputAbsoluteValues(false); tdiFilter->SetInputImage(intraAxonalVolumeImage); tdiFilter->SetUseImageGeometry(true); tdiFilter->Update(); intraAxonalVolumeImage = tdiFilter->GetOutput(); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; boost::progress_display disp(m_MaskImage->GetLargestPossibleRegion().GetNumberOfPixels()*m_Parameters.m_SignalGen.GetNumVolumes()); for (unsigned int g=0; gSetSeed(signalModelSeed); for (int i=0; iSetSeed(signalModelSeed); if (m_Parameters.m_SignalGen.m_DoAddMotion && g>0) // if fibers have moved we need a new TDI and new directions { fOdfFilter->SetFiberBundle(m_FiberBundleTransformed); fOdfFilter->SetMaskImage(m_MaskImage); fOdfFilter->Update(); directionImageContainer = fOdfFilter->GetDirectionImageContainer(); tdiFilter->SetFiberBundle(m_FiberBundleTransformed); tdiFilter->Update(); intraAxonalVolumeImage = tdiFilter->GetOutput(); } ImageRegionIterator< ItkUcharImgType > it(m_MaskImage, m_MaskImage->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } if (it.Get()>0) { // generate fiber signal for (int c=0; cGetPixel(it.GetIndex()); for (unsigned int i=0; iSize(); i++) { itk::Vector< double, 3> dir; dir.CastFrom(directionImageContainer->GetElement(i)->GetPixel(it.GetIndex())); double norm = dir.GetNorm(); if (norm>0.0001) { m_Parameters.m_FiberModelList.at(c)->SetFiberDirection(dir); pix[g] += m_Parameters.m_FiberModelList.at(c)->SimulateMeasurement(g)*norm; count++; } } if (count>0) pix[g] /= count; pix[g] *= intraAxonalVolumeImage->GetPixel(it.GetIndex())*m_VoxelVolume; m_CompartmentImages.at(c)->SetPixel(it.GetIndex(), pix); } // simulate other compartments SimulateNonFiberSignal(it.GetIndex(), intraAxonalVolumeImage->GetPixel(it.GetIndex())*m_VoxelVolume, g); } ++it; } SimulateMotion(g); } itk::ImageFileWriter< ItkUcharImgType >::Pointer wr = itk::ImageFileWriter< ItkUcharImgType >::New(); wr->SetInput(fOdfFilter->GetNumDirectionsImage()); wr->SetFileName(mitk::IOUtil::GetTempPath()+"/NumDirections_MainFiberDirections.nrrd"); wr->Update(); break; } case (SignalGenerationParameters::RANDOM_DIRECTIONS): { ItkUcharImgType::Pointer numDirectionsImage = ItkUcharImgType::New(); numDirectionsImage->SetSpacing( m_UpsampledSpacing ); numDirectionsImage->SetOrigin( m_UpsampledOrigin ); numDirectionsImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); numDirectionsImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); numDirectionsImage->SetBufferedRegion( m_UpsampledImageRegion ); numDirectionsImage->SetRequestedRegion( m_UpsampledImageRegion ); numDirectionsImage->Allocate(); numDirectionsImage->FillBuffer(0); double sepAngle = cos(m_Parameters.m_SignalGen.m_FiberSeparationThreshold*M_PI/180.0); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; boost::progress_display disp(m_MaskImage->GetLargestPossibleRegion().GetNumberOfPixels()); ImageRegionIterator it(m_MaskImage, m_MaskImage->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } if (it.Get()>0) { int numFibs = m_RandGen->GetIntegerVariate(2)+1; DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(it.GetIndex()); double volume = m_RandGen->GetVariateWithClosedRange(0.3); // double sum = 0; std::vector< double > fractions; for (int i=0; iGetVariateWithClosedRange(0.5)); // sum += fractions.at(i); } // for (int i=0; i > directions; for (int i=0; iGetVariateWithClosedRange(2)-1.0; fib[1] = m_RandGen->GetVariateWithClosedRange(2)-1.0; fib[2] = m_RandGen->GetVariateWithClosedRange(2)-1.0; fib.Normalize(); double min = 0; for (unsigned int d=0; dmin) min = angle; } if (minSetFiberDirection(fib); pix += m_Parameters.m_FiberModelList.at(0)->SimulateMeasurement()*fractions[i]; directions.push_back(fib); } else i--; } pix *= (1-volume); m_CompartmentImages.at(0)->SetPixel(it.GetIndex(), pix); // CSF/GM { pix += volume*m_Parameters.m_NonFiberModelList.at(0)->SimulateMeasurement(); } numDirectionsImage->SetPixel(it.GetIndex(), numFibs); } ++it; } itk::ImageFileWriter< ItkUcharImgType >::Pointer wr = itk::ImageFileWriter< ItkUcharImgType >::New(); wr->SetInput(numDirectionsImage); wr->SetFileName(mitk::IOUtil::GetTempPath()+"/NumDirections_RandomDirections.nrrd"); wr->Update(); } } if (m_Logfile.is_open()) { m_Logfile << "DONE"; m_Logfile.close(); } m_StatusText += "\n\n"; if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } DoubleDwiType::Pointer doubleOutImage; if ( m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition ) // do k-space stuff { m_StatusText += this->GetTime()+" > Adjusting complex signal\n"; MITK_INFO << "Adjusting complex signal:"; if (m_Parameters.m_SignalGen.m_DoSimulateRelaxation) m_StatusText += "Simulating signal relaxation\n"; if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull()) m_StatusText += "Simulating distortions\n"; if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) m_StatusText += "Simulating ringing artifacts\n"; if (m_Parameters.m_SignalGen.m_EddyStrength>0) m_StatusText += "Simulating eddy currents\n"; if (m_Parameters.m_SignalGen.m_Spikes>0) m_StatusText += "Simulating spikes\n"; if (m_Parameters.m_SignalGen.m_CroppingFactor<1.0) m_StatusText += "Simulating aliasing artifacts\n"; if (m_Parameters.m_SignalGen.m_KspaceLineOffset>0) m_StatusText += "Simulating ghosts\n"; doubleOutImage = DoKspaceStuff(m_CompartmentImages); m_Parameters.m_SignalGen.m_SignalScale = 1; // already scaled in DoKspaceStuff } else // don't do k-space stuff, just sum compartments { m_StatusText += this->GetTime()+" > Summing compartments\n"; MITK_INFO << "Summing compartments"; doubleOutImage = m_CompartmentImages.at(0); for (unsigned int i=1; i::Pointer adder = itk::AddImageFilter< DoubleDwiType, DoubleDwiType, DoubleDwiType>::New(); adder->SetInput1(doubleOutImage); adder->SetInput2(m_CompartmentImages.at(i)); adder->Update(); doubleOutImage = adder->GetOutput(); } } if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } m_StatusText += this->GetTime()+" > Finalizing image\n"; MITK_INFO << "Finalizing image"; if (m_Parameters.m_SignalGen.m_SignalScale>1) m_StatusText += " Scaling signal\n"; if (m_Parameters.m_NoiseModel!=NULL) m_StatusText += " Adding noise\n"; unsigned int window = 0; unsigned int min = itk::NumericTraits::max(); ImageRegionIterator it4 (outImage, outImage->GetLargestPossibleRegion()); DoubleDwiType::PixelType signal; signal.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); boost::progress_display disp2(outImage->GetLargestPossibleRegion().GetNumberOfPixels()); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; lastTick = 0; while(!it4.IsAtEnd()) { if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } ++disp2; unsigned long newTick = 50*disp2.count()/disp2.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; typename OutputImageType::IndexType index = it4.GetIndex(); signal = doubleOutImage->GetPixel(index)*m_Parameters.m_SignalGen.m_SignalScale; if (m_Parameters.m_NoiseModel!=NULL) m_Parameters.m_NoiseModel->AddNoise(signal); for (unsigned int i=0; i0) signal[i] = floor(signal[i]+0.5); else signal[i] = ceil(signal[i]-0.5); if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]>window) window = signal[i]; if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]SetNthOutput(0, outImage); m_StatusText += "\n\n"; m_StatusText += "Finished simulation\n"; m_StatusText += "Simulation time: "+GetTime(); m_TimeProbe.Stop(); } template< class PixelType > void TractsToDWIImageFilter< PixelType >::SimulateMotion(int g) { if (m_Parameters.m_SignalGen.m_DoAddMotion && gGetDeepCopy(); m_Rotation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[0]*2)-m_Parameters.m_SignalGen.m_Rotation[0]; m_Rotation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[1]*2)-m_Parameters.m_SignalGen.m_Rotation[1]; m_Rotation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[2]*2)-m_Parameters.m_SignalGen.m_Rotation[2]; m_Translation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[0]*2)-m_Parameters.m_SignalGen.m_Translation[0]; m_Translation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[1]*2)-m_Parameters.m_SignalGen.m_Translation[1]; m_Translation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[2]*2)-m_Parameters.m_SignalGen.m_Translation[2]; } // rotate mask image if (m_MaskImageSet) { ImageRegionIterator maskIt(m_UpsampledMaskImage, m_UpsampledMaskImage->GetLargestPossibleRegion()); m_MaskImage->FillBuffer(0); while(!maskIt.IsAtEnd()) { if (maskIt.Get()<=0) { ++maskIt; continue; } DoubleDwiType::IndexType index = maskIt.GetIndex(); itk::Point point; m_UpsampledMaskImage->TransformIndexToPhysicalPoint(index, point); if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), m_Rotation[0],m_Rotation[1],m_Rotation[2],m_Translation[0],m_Translation[1],m_Translation[2]); else point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), m_Rotation[0]*(g+1),m_Rotation[1]*(g+1),m_Rotation[2]*(g+1),m_Translation[0]*(g+1),m_Translation[1]*(g+1),m_Translation[2]*(g+1)); m_MaskImage->TransformPhysicalPointToIndex(point, index); if (m_MaskImage->GetLargestPossibleRegion().IsInside(index)) m_MaskImage->SetPixel(index,100); ++maskIt; } } // rotate fibers if (m_Logfile.is_open()) { m_Logfile << g+1 << " rotation: " << m_Rotation[0] << "," << m_Rotation[1] << "," << m_Rotation[2] << ";"; m_Logfile << " translation: " << m_Translation[0] << "," << m_Translation[1] << "," << m_Translation[2] << "\n"; } m_FiberBundleTransformed->TransformFibers(m_Rotation[0],m_Rotation[1],m_Rotation[2],m_Translation[0],m_Translation[1],m_Translation[2]); } } template< class PixelType > void TractsToDWIImageFilter< PixelType >::SimulateNonFiberSignal(ItkUcharImgType::IndexType index, double intraAxonalVolume, int g) { int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); if (intraAxonalVolume>0.0001 && m_Parameters.m_SignalGen.m_DoDisablePartialVolume) // only fiber in voxel { DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(index); if (g>=0) pix[g] *= m_VoxelVolume/intraAxonalVolume; else pix *= m_VoxelVolume/intraAxonalVolume; m_CompartmentImages.at(0)->SetPixel(index, pix); m_VolumeFractions.at(0)->SetPixel(index, 1); for (int i=1; iGetPixel(index); if (g>=0) pix[g] = 0.0; else pix.Fill(0.0); m_CompartmentImages.at(i)->SetPixel(index, pix); } } else { m_VolumeFractions.at(0)->SetPixel(index, intraAxonalVolume/m_VoxelVolume); itk::Point point; m_MaskImage->TransformIndexToPhysicalPoint(index, point); if (m_Parameters.m_SignalGen.m_DoAddMotion) { if (m_Parameters.m_SignalGen.m_DoRandomizeMotion && g>0) point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), -m_Rotation[0],-m_Rotation[1],-m_Rotation[2],-m_Translation[0],-m_Translation[1],-m_Translation[2]); else if (g>=0) point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), -m_Rotation[0]*g,-m_Rotation[1]*g,-m_Rotation[2]*g,-m_Translation[0]*g,-m_Translation[1]*g,-m_Translation[2]*g); } if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume) { int maxVolumeIndex = 0; double maxWeight = 0; for (int i=0; i1) { DoubleDwiType::IndexType newIndex; m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->TransformPhysicalPointToIndex(point, newIndex); if (!m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion().IsInside(newIndex)) continue; weight = m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetPixel(newIndex); } if (weight>maxWeight) { maxWeight = weight; maxVolumeIndex = i; } } DoubleDwiType::Pointer doubleDwi = m_CompartmentImages.at(maxVolumeIndex+numFiberCompartments); DoubleDwiType::PixelType pix = doubleDwi->GetPixel(index); if (g>=0) pix[g] += m_Parameters.m_NonFiberModelList[maxVolumeIndex]->SimulateMeasurement(g); else pix += m_Parameters.m_NonFiberModelList[maxVolumeIndex]->SimulateMeasurement(); doubleDwi->SetPixel(index, pix); m_VolumeFractions.at(maxVolumeIndex+numFiberCompartments)->SetPixel(index, 1); } else { double extraAxonalVolume = m_VoxelVolume-intraAxonalVolume; // non-fiber volume double interAxonalVolume = 0; if (numFiberCompartments>1) interAxonalVolume = extraAxonalVolume * intraAxonalVolume/m_VoxelVolume; // inter-axonal fraction of non fiber compartment scales linearly with f double other = extraAxonalVolume - interAxonalVolume; // rest of compartment double singleinter = interAxonalVolume/(numFiberCompartments-1); // adjust non-fiber and intra-axonal signal for (int i=1; iGetPixel(index); if (intraAxonalVolume>0) // remove scaling by intra-axonal volume from inter-axonal compartment { if (g>=0) pix[g] /= intraAxonalVolume; else pix /= intraAxonalVolume; } if (g>=0) pix[g] *= singleinter; else pix *= singleinter; m_CompartmentImages.at(i)->SetPixel(index, pix); m_VolumeFractions.at(i)->SetPixel(index, singleinter/m_VoxelVolume); } for (int i=0; i1) { DoubleDwiType::IndexType newIndex; m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->TransformPhysicalPointToIndex(point, newIndex); if (!m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion().IsInside(newIndex)) continue; weight = m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetPixel(newIndex); } DoubleDwiType::Pointer doubleDwi = m_CompartmentImages.at(i+numFiberCompartments); DoubleDwiType::PixelType pix = doubleDwi->GetPixel(index); if (g>=0) pix[g] += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement(g)*other*weight; else pix += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement()*other*weight; doubleDwi->SetPixel(index, pix); m_VolumeFractions.at(i+numFiberCompartments)->SetPixel(index, other/m_VoxelVolume*weight); } } } } template< class PixelType > itk::Point TractsToDWIImageFilter< PixelType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class PixelType > itk::Vector TractsToDWIImageFilter< PixelType >::GetItkVector(double point[3]) { itk::Vector itkVector; itkVector[0] = point[0]; itkVector[1] = point[1]; itkVector[2] = point[2]; return itkVector; } template< class PixelType > vnl_vector_fixed TractsToDWIImageFilter< PixelType >::GetVnlVector(double point[3]) { vnl_vector_fixed vnlVector; vnlVector[0] = point[0]; vnlVector[1] = point[1]; vnlVector[2] = point[2]; return vnlVector; } template< class PixelType > vnl_vector_fixed TractsToDWIImageFilter< PixelType >::GetVnlVector(Vector& vector) { vnl_vector_fixed vnlVector; vnlVector[0] = vector[0]; vnlVector[1] = vector[1]; vnlVector[2] = vector[2]; return vnlVector; } template< class PixelType > double TractsToDWIImageFilter< PixelType >::RoundToNearest(double num) { return (num > 0.0) ? floor(num + 0.5) : ceil(num - 0.5); } template< class PixelType > std::string TractsToDWIImageFilter< PixelType >::GetTime() { m_TimeProbe.Stop(); unsigned long total = RoundToNearest(m_TimeProbe.GetTotal()); unsigned long hours = total/3600; unsigned long minutes = (total%3600)/60; unsigned long seconds = total%60; std::string out = ""; out.append(boost::lexical_cast(hours)); out.append(":"); out.append(boost::lexical_cast(minutes)); out.append(":"); out.append(boost::lexical_cast(seconds)); m_TimeProbe.Start(); return out; } } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp index 82ef991340..ad60351fb8 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp @@ -1,566 +1,565 @@ #include "itkTractsToVectorImageFilter.h" // VTK #include #include #include // ITK #include #include // misc #define _USE_MATH_DEFINES #include #include namespace itk{ static bool CompareVectorLengths(const vnl_vector_fixed< double, 3 >& v1, const vnl_vector_fixed< double, 3 >& v2) { return (v1.magnitude()>v2.magnitude()); } template< class PixelType > TractsToVectorImageFilter< PixelType >::TractsToVectorImageFilter(): m_AngularThreshold(0.7), m_Epsilon(0.999), m_MaskImage(NULL), m_NormalizeVectors(false), m_UseWorkingCopy(true), m_MaxNumDirections(3), - m_SizeThreshold(0.2), + m_SizeThreshold(0.3), m_NumDirectionsImage(NULL), m_CreateDirectionImages(true) { this->SetNumberOfRequiredOutputs(1); } template< class PixelType > TractsToVectorImageFilter< PixelType >::~TractsToVectorImageFilter() { } template< class PixelType > vnl_vector_fixed TractsToVectorImageFilter< PixelType >::GetVnlVector(double point[]) { vnl_vector_fixed vnlVector; vnlVector[0] = point[0]; vnlVector[1] = point[1]; vnlVector[2] = point[2]; return vnlVector; } template< class PixelType > itk::Point TractsToVectorImageFilter< PixelType >::GetItkPoint(double point[]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class PixelType > void TractsToVectorImageFilter< PixelType >::GenerateData() { mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry(); // calculate new image parameters itk::Vector spacing; itk::Point origin; itk::Matrix direction; ImageRegion<3> imageRegion; if (!m_MaskImage.IsNull()) { spacing = m_MaskImage->GetSpacing(); imageRegion = m_MaskImage->GetLargestPossibleRegion(); origin = m_MaskImage->GetOrigin(); direction = m_MaskImage->GetDirection(); } else { spacing = geometry->GetSpacing(); origin = geometry->GetOrigin(); mitk::BaseGeometry::BoundsArrayType bounds = geometry->GetBounds(); origin[0] += bounds.GetElement(0); origin[1] += bounds.GetElement(2); origin[2] += bounds.GetElement(4); for (int i=0; i<3; i++) for (int j=0; j<3; j++) direction[j][i] = geometry->GetMatrixColumn(i)[j]; imageRegion.SetSize(0, geometry->GetExtent(0)); imageRegion.SetSize(1, geometry->GetExtent(1)); imageRegion.SetSize(2, geometry->GetExtent(2)); m_MaskImage = ItkUcharImgType::New(); m_MaskImage->SetSpacing( spacing ); m_MaskImage->SetOrigin( origin ); m_MaskImage->SetDirection( direction ); m_MaskImage->SetRegions( imageRegion ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } OutputImageType::RegionType::SizeType outImageSize = imageRegion.GetSize(); m_OutImageSpacing = m_MaskImage->GetSpacing(); m_ClusteredDirectionsContainer = ContainerType::New(); // initialize num directions image m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( spacing ); m_NumDirectionsImage->SetOrigin( origin ); m_NumDirectionsImage->SetDirection( direction ); m_NumDirectionsImage->SetRegions( imageRegion ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); // initialize direction images m_DirectionImageContainer = DirectionImageContainerType::New(); // resample fiber bundle double minSpacing = 1; if(m_OutImageSpacing[0]GetDeepCopy(); // resample fiber bundle for sufficient voxel coverage m_FiberBundle->ResampleSpline(minSpacing/10); // iterate over all fibers vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); int numFibers = m_FiberBundle->GetNumFibers(); m_DirectionsContainer = ContainerType::New(); MITK_INFO << "Generating directions from tractogram"; boost::progress_display disp(numFibers); for( int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (numPoints<2) continue; vnl_vector_fixed dir; itk::Point worldPos; vnl_vector v; for( int j=0; jGetPoint(j); worldPos = GetItkPoint(temp); itk::Index<3> index; m_MaskImage->TransformPhysicalPointToIndex(worldPos, index); if (!m_MaskImage->GetLargestPossibleRegion().IsInside(index) || m_MaskImage->GetPixel(index)==0) continue; // get fiber tangent direction at this position v = GetVnlVector(temp); dir = GetVnlVector(points->GetPoint(j+1))-v; if (dir.is_zero()) continue; dir.normalize(); // add direction to container unsigned int idx = index[0] + outImageSize[0]*(index[1] + outImageSize[1]*index[2]); DirectionContainerType::Pointer dirCont; if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->push_back(dir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->push_back(dir); } else { dirCont = DirectionContainerType::New(); dirCont->push_back(dir); m_DirectionsContainer->InsertElement(idx, dirCont); } } } vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); itk::ImageRegionIterator dirIt(m_NumDirectionsImage, m_NumDirectionsImage->GetLargestPossibleRegion()); MITK_INFO << "Clustering directions"; boost::progress_display disp2(outImageSize[0]*outImageSize[1]*outImageSize[2]); while(!dirIt.IsAtEnd()) { ++disp2; OutputImageType::IndexType index = dirIt.GetIndex(); int idx = index[0]+(index[1]+index[2]*outImageSize[1])*outImageSize[0]; if (!m_DirectionsContainer->IndexExists(idx)) { ++dirIt; continue; } DirectionContainerType::Pointer dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull() || dirCont->empty()) { ++dirIt; continue; } std::vector< double > lengths; lengths.resize(dirCont->size(), 1); // all peaks have size 1 DirectionContainerType::Pointer directions; if (m_MaxNumDirections>0) { directions = FastClustering(dirCont, lengths); std::sort( directions->begin(), directions->end(), CompareVectorLengths ); } else directions = dirCont; unsigned int numDir = directions->size(); if (m_MaxNumDirections>0 && numDir>m_MaxNumDirections) numDir = m_MaxNumDirections; int count = 0; for (unsigned int i=0; i container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; itk::Point worldCenter; m_MaskImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); DirectionType dir = directions->at(i); if (dir.magnitude()size()) { ItkDirectionImageType::Pointer directionImage = ItkDirectionImageType::New(); directionImage->SetSpacing( spacing ); directionImage->SetOrigin( origin ); directionImage->SetDirection( direction ); directionImage->SetRegions( imageRegion ); directionImage->Allocate(); Vector< float, 3 > nullVec; nullVec.Fill(0.0); directionImage->FillBuffer(nullVec); m_DirectionImageContainer->InsertElement(i, directionImage); } // set direction image pixel ItkDirectionImageType::Pointer directionImage = m_DirectionImageContainer->GetElement(i); Vector< float, 3 > pixel; pixel.SetElement(0, dir[0]); pixel.SetElement(1, dir[1]); pixel.SetElement(2, dir[2]); directionImage->SetPixel(index, pixel); } // add direction to vector field (with spacing compensation) itk::Point worldStart; worldStart[0] = worldCenter[0]-dir[0]/2*minSpacing; worldStart[1] = worldCenter[1]-dir[1]/2*minSpacing; worldStart[2] = worldCenter[2]-dir[2]/2*minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dir[0]/2*minSpacing; worldEnd[1] = worldCenter[1]+dir[1]/2*minSpacing; worldEnd[2] = worldCenter[2]+dir[2]/2*minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); } dirIt.Set(count); ++dirIt; } vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData); } template< class PixelType > TractsToVectorImageFilter< PixelType >::DirectionContainerType::Pointer TractsToVectorImageFilter< PixelType >::FastClustering(DirectionContainerType::Pointer inDirs, std::vector< double > lengths) { DirectionContainerType::Pointer outDirs = DirectionContainerType::New(); if (inDirs->size()<2) return inDirs; DirectionType oldMean, currentMean; std::vector< int > touched; // initialize touched.resize(inDirs->size(), 0); bool free = true; currentMean = inDirs->at(0); // initialize first seed currentMean.normalize(); double length = lengths.at(0); touched[0] = 1; std::vector< double > newLengths; bool meanChanged = false; double max = 0; while (free) { oldMean.fill(0.0); // start mean-shift clustering double angle = 0; while (fabs(dot_product(currentMean, oldMean))<0.99) { oldMean = currentMean; currentMean.fill(0.0); for (unsigned int i=0; isize(); i++) { angle = dot_product(oldMean, inDirs->at(i)); if (angle>=m_AngularThreshold) { currentMean += inDirs->at(i); if (meanChanged) length += lengths.at(i); touched[i] = 1; meanChanged = true; } else if (-angle>=m_AngularThreshold) { currentMean -= inDirs->at(i); if (meanChanged) length += lengths.at(i); touched[i] = 1; meanChanged = true; } } if(!meanChanged) currentMean = oldMean; else currentMean.normalize(); } // found stable mean outDirs->push_back(currentMean); newLengths.push_back(length); if (length>max) max = length; // find next unused seed free = false; for (unsigned int i=0; iat(i); free = true; meanChanged = false; length = lengths.at(i); touched[i] = 1; break; } } if (inDirs->size()==outDirs->size()) { - if (!m_NormalizeVectors && max>0) + if (max>0) for (unsigned int i=0; isize(); i++) outDirs->SetElement(i, outDirs->at(i)*newLengths.at(i)/max); return outDirs; } else return FastClustering(outDirs, newLengths); } //template< class PixelType > //std::vector< DirectionType > TractsToVectorImageFilter< PixelType >::Clustering(std::vector< DirectionType >& inDirs) //{ // std::vector< DirectionType > outDirs; // if (inDirs.empty()) // return outDirs; // DirectionType oldMean, currentMean, workingMean; // std::vector< DirectionType > normalizedDirs; // std::vector< int > touched; // for (std::size_t i=0; i0.0001) // { // counter = 0; // oldMean = currentMean; // workingMean = oldMean; // workingMean.normalize(); // currentMean.fill(0.0); // for (std::size_t i=0; i=m_AngularThreshold) // { // currentMean += inDirs[i]; // counter++; // } // else if (-angle>=m_AngularThreshold) // { // currentMean -= inDirs[i]; // counter++; // } // } // } // // found stable mean // if (counter>0) // { // bool add = true; // DirectionType normMean = currentMean; // normMean.normalize(); // for (std::size_t i=0; i0) // { // if (mag>max) // max = mag; // outDirs.push_back(currentMean); // } // } // } // } // if (m_NormalizeVectors) // for (std::size_t i=0; i0) // for (std::size_t i=0; i //TractsToVectorImageFilter< PixelType >::DirectionContainerType::Pointer TractsToVectorImageFilter< PixelType >::MeanShiftClustering(DirectionContainerType::Pointer dirCont) //{ // DirectionContainerType::Pointer container = DirectionContainerType::New(); // double max = 0; // for (DirectionContainerType::ConstIterator it = dirCont->Begin(); it!=dirCont->End(); ++it) // { // vnl_vector_fixed mean = ClusterStep(dirCont, it.Value()); // if (mean.is_zero()) // continue; // bool addMean = true; // for (DirectionContainerType::ConstIterator it2 = container->Begin(); it2!=container->End(); ++it2) // { // vnl_vector_fixed dir = it2.Value(); // double angle = fabs(dot_product(mean, dir)/(mean.magnitude()*dir.magnitude())); // if (angle>=m_Epsilon) // { // addMean = false; // break; // } // } // if (addMean) // { // if (m_NormalizeVectors) // mean.normalize(); // else if (mean.magnitude()>max) // max = mean.magnitude(); // container->InsertElement(container->Size(), mean); // } // } // // max normalize voxel directions // if (max>0 && !m_NormalizeVectors) // for (std::size_t i=0; iSize(); i++) // container->ElementAt(i) /= max; // if (container->Size()Size()) // return MeanShiftClustering(container); // else // return container; //} //template< class PixelType > //vnl_vector_fixed TractsToVectorImageFilter< PixelType >::ClusterStep(DirectionContainerType::Pointer dirCont, vnl_vector_fixed currentMean) //{ // vnl_vector_fixed newMean; newMean.fill(0); // for (DirectionContainerType::ConstIterator it = dirCont->Begin(); it!=dirCont->End(); ++it) // { // vnl_vector_fixed dir = it.Value(); // double angle = dot_product(currentMean, dir)/(currentMean.magnitude()*dir.magnitude()); // if (angle>=m_AngularThreshold) // newMean += dir; // else if (-angle>=m_AngularThreshold) // newMean -= dir; // } // if (fabs(dot_product(currentMean, newMean)/(currentMean.magnitude()*newMean.magnitude()))>=m_Epsilon || newMean.is_zero()) // return newMean; // else // return ClusterStep(dirCont, newMean); //} } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp index 27f97c58ef..7d5e97f8ac 100755 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp @@ -1,1915 +1,1849 @@ /*=================================================================== 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. ===================================================================*/ #define _USE_MATH_DEFINES #include "mitkFiberBundleX.h" #include #include #include #include "mitkImagePixelReadAccessor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include +#include -const char* mitk::FiberBundleX::COLORCODING_ORIENTATION_BASED = "Color_Orient"; -//const char* mitk::FiberBundleX::COLORCODING_FA_AS_OPACITY = "Color_Orient_FA_Opacity"; -const char* mitk::FiberBundleX::COLORCODING_FA_BASED = "FA_Values"; -const char* mitk::FiberBundleX::COLORCODING_CUSTOM = "custom"; const char* mitk::FiberBundleX::FIBER_ID_ARRAY = "Fiber_IDs"; using namespace std; mitk::FiberBundleX::FiberBundleX( vtkPolyData* fiberPolyData ) - : m_CurrentColorCoding(NULL) - , m_NumFibers(0) + : m_NumFibers(0) , m_FiberSampling(0) { + m_FiberWeights = vtkSmartPointer::New(); + m_FiberWeights->SetName("FIBER_WEIGHTS"); + m_FiberPolyData = vtkSmartPointer::New(); if (fiberPolyData != NULL) { m_FiberPolyData = fiberPolyData; - //m_FiberPolyData->DeepCopy(fiberPolyData); this->DoColorCodingOrientationBased(); } this->UpdateFiberGeometry(); - this->SetColorCoding(COLORCODING_ORIENTATION_BASED); this->GenerateFiberIds(); } mitk::FiberBundleX::~FiberBundleX() { } mitk::FiberBundleX::Pointer mitk::FiberBundleX::GetDeepCopy() { mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(m_FiberPolyData); - newFib->SetColorCoding(m_CurrentColorCoding); + newFib->SetFiberColors(this->m_FiberColors); + newFib->SetFiberWeights(this->m_FiberWeights); return newFib; } vtkSmartPointer mitk::FiberBundleX::GeneratePolyDataByIds(std::vector fiberIds) { - MITK_DEBUG << "\n=====FINAL RESULT: fib_id ======\n"; - MITK_DEBUG << "Number of new Fibers: " << fiberIds.size(); - // iterate through the vectorcontainer hosting all desired fiber Ids - vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); vtkSmartPointer newLineSet = vtkSmartPointer::New(); vtkSmartPointer newPointSet = vtkSmartPointer::New(); - // if FA array available, initialize fa double array - // if color orient array is available init color array - vtkSmartPointer faValueArray; - vtkSmartPointer colorsT; - //colors and alpha value for each single point, RGBA = 4 components - unsigned char rgba[4] = {0,0,0,0}; - int componentSize = sizeof(rgba); - - if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ - MITK_DEBUG << "FA VALUES AVAILABLE, init array for new fiberbundle"; - faValueArray = vtkSmartPointer::New(); - } - - if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ - MITK_DEBUG << "colorValues available, init array for new fiberbundle"; - colorsT = vtkUnsignedCharArray::New(); - colorsT->SetNumberOfComponents(componentSize); - colorsT->SetName(COLORCODING_ORIENTATION_BASED); - } - - - std::vector::iterator finIt = fiberIds.begin(); while ( finIt != fiberIds.end() ) { if (*finIt < 0 || *finIt>GetNumFibers()){ MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt; break; } vtkSmartPointer fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber); - vtkSmartPointer fibPoints = fiber->GetPoints(); - vtkSmartPointer newFiber = vtkSmartPointer::New(); newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() ); for(int i=0; iGetNumberOfPoints(); i++) { - // MITK_DEBUG << "id: " << fiber->GetPointId(i); - // MITK_DEBUG << fibPoints->GetPoint(i)[0] << " | " << fibPoints->GetPoint(i)[1] << " | " << fibPoints->GetPoint(i)[2]; newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); - - - if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ - // MITK_DEBUG << m_FiberIdDataSet->GetPointData()->GetArray(FA_VALUE_ARRAY)->GetTuple(fiber->GetPointId(i)); - } - - if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ - // MITK_DEBUG << "ColorValue: " << m_FiberIdDataSet->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetTuple(fiber->GetPointId(i))[0]; - } } newLineSet->InsertNextCell(newFiber); ++finIt; } newFiberPolyData->SetPoints(newPointSet); newFiberPolyData->SetLines(newLineSet); - MITK_DEBUG << "new fiberbundle polydata points: " << newFiberPolyData->GetNumberOfPoints(); - MITK_DEBUG << "new fiberbundle polydata lines: " << newFiberPolyData->GetNumberOfLines(); - MITK_DEBUG << "=====================\n"; - - // mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newFiberPolyData); return newFiberPolyData; } // merge two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::AddBundle(mitk::FiberBundleX* fib) { if (fib==NULL) { MITK_WARN << "trying to call AddBundle with NULL argument"; return NULL; } MITK_INFO << "Adding fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // add current fiber bundle + vtkSmartPointer weights = vtkSmartPointer::New(); + weights->SetNumberOfValues(this->GetNumFibers()+fib->GetNumFibers()); + + unsigned int counter = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } + weights->InsertValue(counter, this->GetFiberWeight(i)); vNewLines->InsertNextCell(container); + counter++; } // add new fiber bundle for (int i=0; iGetFiberPolyData()->GetNumberOfCells(); i++) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } + weights->InsertValue(counter, fib->GetFiberWeight(i)); vNewLines->InsertNextCell(container); + counter++; } // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); + newFib->SetFiberWeights(weights); return newFib; } // subtract two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::SubtractBundle(mitk::FiberBundleX* fib) { MITK_INFO << "Subtracting fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // iterate over current fibers boost::progress_display disp(m_NumFibers); for( int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==NULL || numPoints<=0) continue; int numFibers2 = fib->GetNumFibers(); bool contained = false; for( int i2=0; i2GetFiberPolyData()->GetCell(i2); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (points2==NULL)// || numPoints2<=0) continue; // check endpoints if (numPoints2==numPoints) { itk::Point point_start = GetItkPoint(points->GetPoint(0)); itk::Point point_end = GetItkPoint(points->GetPoint(numPoints-1)); itk::Point point2_start = GetItkPoint(points2->GetPoint(0)); itk::Point point2_end = GetItkPoint(points2->GetPoint(numPoints2-1)); if ((point_start.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps) || (point_start.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps)) { // further checking ??? contained = true; break; } } } // add to result because fiber is not subtracted if (!contained) { vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(points->GetPoint(j)); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } } if(vNewLines->GetNumberOfCells()==0) return NULL; // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle return mitk::FiberBundleX::New(vNewPolyData); } itk::Point mitk::FiberBundleX::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } /* * set polydata (additional flag to recompute fiber geometry, default = true) */ void mitk::FiberBundleX::SetFiberPolyData(vtkSmartPointer fiberPD, bool updateGeometry) { if (fiberPD == NULL) this->m_FiberPolyData = vtkSmartPointer::New(); else { m_FiberPolyData->DeepCopy(fiberPD); DoColorCodingOrientationBased(); } m_NumFibers = m_FiberPolyData->GetNumberOfLines(); if (updateGeometry) UpdateFiberGeometry(); - SetColorCoding(COLORCODING_ORIENTATION_BASED); GenerateFiberIds(); } /* * return vtkPolyData */ vtkSmartPointer mitk::FiberBundleX::GetFiberPolyData() const { return m_FiberPolyData; } void mitk::FiberBundleX::DoColorCodingOrientationBased() { //===== FOR WRITING A TEST ======================== // colorT size == tupelComponents * tupelElements // compare color results // to cover this code 100% also polydata needed, where colorarray already exists // + one fiber with exactly 1 point // + one fiber with 0 points //================================================= - /* make sure that processing colorcoding is only called when necessary */ - if ( m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) && - m_FiberPolyData->GetNumberOfPoints() == - m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetNumberOfTuples() ) - { - // fiberstructure is already colorcoded - MITK_DEBUG << " NO NEED TO REGENERATE COLORCODING! " ; - this->ResetFiberOpacity(); - this->SetColorCoding(COLORCODING_ORIENTATION_BASED); - return; - } - - /* Finally, execute color calculation */ vtkPoints* extrPoints = NULL; extrPoints = m_FiberPolyData->GetPoints(); int numOfPoints = 0; if (extrPoints!=NULL) numOfPoints = extrPoints->GetNumberOfPoints(); //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; - // int componentSize = sizeof(rgba); int componentSize = 4; + m_FiberColors = vtkSmartPointer::New(); + m_FiberColors->Allocate(numOfPoints * componentSize); + m_FiberColors->SetNumberOfComponents(componentSize); + m_FiberColors->SetName("FIBER_COLORS"); - vtkSmartPointer colorsT = vtkSmartPointer::New(); - colorsT->Allocate(numOfPoints * componentSize); - colorsT->SetNumberOfComponents(componentSize); - colorsT->SetName(COLORCODING_ORIENTATION_BASED); - - /* checkpoint: does polydata contain any fibers */ int numOfFibers = m_FiberPolyData->GetNumberOfLines(); if (numOfFibers < 1) return; /* extract single fibers of fiberBundle */ vtkCellArray* fiberList = m_FiberPolyData->GetLines(); fiberList->InitTraversal(); for (int fi=0; fiGetNextCell(pointsPerFiber, idList); /* single fiber checkpoints: is number of points valid */ if (pointsPerFiber > 1) { /* operate on points of single fiber */ for (int i=0; i 0) { /* The color value of the current point is influenced by the previous point and next point. */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; vnl_vector_fixed< double, 3 > diff; diff = (diff1 - diff2) / 2.0; diff.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2])); rgba[3] = (unsigned char) (255.0); } else if (i==0) { /* First point has no previous point, therefore only diff1 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; diff1.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2])); rgba[3] = (unsigned char) (255.0); } else if (i==pointsPerFiber-1) { /* Last point has no next point, therefore only diff2 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; diff2.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2])); rgba[3] = (unsigned char) (255.0); - } - colorsT->InsertTupleValue(idList[i], rgba); - } //end for loop + m_FiberColors->InsertTupleValue(idList[i], rgba); + } } else if (pointsPerFiber == 1) { /* a single point does not define a fiber (use vertex mechanisms instead */ continue; } else { MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ; continue; } - }//end for loop - - m_FiberPolyData->GetPointData()->AddArray(colorsT); - - this->SetColorCoding(COLORCODING_ORIENTATION_BASED); - - //mini test, shall be ported to MITK TESTINGS! - if (colorsT->GetSize() != numOfPoints*componentSize) - MITK_DEBUG << "ALLOCATION ERROR IN INITIATING COLOR ARRAY"; -} - -void mitk::FiberBundleX::DoColorCodingFaBased() -{ - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) - return; - - this->SetColorCoding(COLORCODING_FA_BASED); - // this->GenerateFiberIds(); + } + m_UpdateTime3D.Modified(); + m_UpdateTime2D.Modified(); } -void mitk::FiberBundleX::DoUseFaFiberOpacity() +void mitk::FiberBundleX::SetFiberOpacity(vtkDoubleArray* FAValArray) { - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) - return; - - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) != 1 ) - return; - - vtkDoubleArray* FAValArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_FA_BASED); - vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); - - for(long i=0; iGetNumberOfTuples(); i++) { + for(long i=0; iGetNumberOfTuples(); i++) + { double faValue = FAValArray->GetValue(i); faValue = faValue * 255.0; - ColorArray->SetComponent(i,3, (unsigned char) faValue ); + m_FiberColors->SetComponent(i,3, (unsigned char) faValue ); } - - this->SetColorCoding(COLORCODING_ORIENTATION_BASED); - // this->GenerateFiberIds(); + m_UpdateTime3D.Modified(); + m_UpdateTime2D.Modified(); } -void mitk::FiberBundleX::ResetFiberOpacity() { - vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); - if (ColorArray==NULL) - return; - for(long i=0; iGetNumberOfTuples(); i++) - ColorArray->SetComponent(i,3, 255.0 ); +void mitk::FiberBundleX::ResetFiberOpacity() +{ + for(long i=0; iGetNumberOfTuples(); i++) + m_FiberColors->SetComponent(i,3, 255.0 ); + m_UpdateTime3D.Modified(); + m_UpdateTime2D.Modified(); } -void mitk::FiberBundleX::SetFAMap(mitk::Image::Pointer FAimage) +void mitk::FiberBundleX::ColorFibersByScalarMap(mitk::Image::Pointer FAimage, bool opacity) { - mitkPixelTypeMultiplex1( SetFAMap, FAimage->GetPixelType(), FAimage ); + mitkPixelTypeMultiplex2( ColorFibersByScalarMap, FAimage->GetPixelType(), FAimage, opacity ); + m_UpdateTime3D.Modified(); + m_UpdateTime2D.Modified(); } template -void mitk::FiberBundleX::SetFAMap(const mitk::PixelType, mitk::Image::Pointer FAimage) +void mitk::FiberBundleX::ColorFibersByScalarMap(const mitk::PixelType, mitk::Image::Pointer image, bool opacity) { - MITK_DEBUG << "SetFAMap"; - vtkSmartPointer faValues = vtkSmartPointer::New(); - faValues->SetName(COLORCODING_FA_BASED); - faValues->Allocate(m_FiberPolyData->GetNumberOfPoints()); - faValues->SetNumberOfValues(m_FiberPolyData->GetNumberOfPoints()); + m_FiberColors = vtkSmartPointer::New(); + m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); + m_FiberColors->SetNumberOfComponents(4); + m_FiberColors->SetName("FIBER_COLORS"); - mitk::ImagePixelReadAccessor readFAimage (FAimage, FAimage->GetVolumeData(0)); + mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0)); + unsigned char rgba[4] = {0,0,0,0}; vtkPoints* pointSet = m_FiberPolyData->GetPoints(); + + mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); + vtkSmartPointer lookupTable = vtkSmartPointer::New(); + lookupTable->SetTableRange(0.0, 0.8); + lookupTable->Build(); + mitkLookup->SetVtkLookupTable(lookupTable); + mitkLookup->SetType(mitk::LookupTable::JET); + for(long i=0; iGetNumberOfPoints(); ++i) { Point3D px; px[0] = pointSet->GetPoint(i)[0]; px[1] = pointSet->GetPoint(i)[1]; px[2] = pointSet->GetPoint(i)[2]; - double faPixelValue = 1-readFAimage.GetPixelByWorldCoordinates(px); - faValues->InsertValue(i, faPixelValue); - } - - m_FiberPolyData->GetPointData()->AddArray(faValues); - this->GenerateFiberIds(); + double pixelValue = readimage.GetPixelByWorldCoordinates(px); - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED)) - MITK_DEBUG << "FA VALUE ARRAY SET"; + double color[3]; + lookupTable->GetColor(pixelValue, color); + rgba[0] = (unsigned char) (255.0 * color[0]); + rgba[1] = (unsigned char) (255.0 * color[1]); + rgba[2] = (unsigned char) (255.0 * color[2]); + if (opacity) + rgba[3] = (unsigned char) (255.0 * pixelValue); + else + rgba[3] = (unsigned char) (255.0); + m_FiberColors->InsertTupleValue(i, rgba); + } + m_UpdateTime3D.Modified(); + m_UpdateTime2D.Modified(); } +void mitk::FiberBundleX::SetFiberColors(float r, float g, float b, float alpha) +{ + m_FiberColors = vtkSmartPointer::New(); + m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); + m_FiberColors->SetNumberOfComponents(4); + m_FiberColors->SetName("FIBER_COLORS"); + + unsigned char rgba[4] = {0,0,0,0}; + for(long i=0; iGetNumberOfPoints(); ++i) + { + rgba[0] = (unsigned char) r; + rgba[1] = (unsigned char) g; + rgba[2] = (unsigned char) b; + rgba[3] = (unsigned char) alpha; + m_FiberColors->InsertTupleValue(i, rgba); + } + m_UpdateTime3D.Modified(); + m_UpdateTime2D.Modified(); +} void mitk::FiberBundleX::GenerateFiberIds() { if (m_FiberPolyData == NULL) return; vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); idFiberFilter->SetInputData(m_FiberPolyData); idFiberFilter->CellIdsOn(); // idFiberFilter->PointIdsOn(); // point id's are not needed idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); idFiberFilter->FieldDataOn(); idFiberFilter->Update(); m_FiberIdDataSet = idFiberFilter->GetOutput(); - MITK_DEBUG << "Generating Fiber Ids...[done] | " << m_FiberIdDataSet->GetNumberOfCells(); - } mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert) { vtkSmartPointer polyData = m_FiberPolyData; if (anyPoint) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; mitk::FiberBundleX::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleSpline(minSpacing/5); polyData = fibCopy->GetFiberPolyData(); } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Extracting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cellOriginal = m_FiberPolyData->GetCell(i); int numPointsOriginal = cellOriginal->GetNumberOfPoints(); vtkPoints* pointsOriginal = cellOriginal->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1 && numPointsOriginal) { if (anyPoint) { if (!invert) { for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } break; } } } else { bool includeFiber = true; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { includeFiber = false; break; } } if (includeFiber) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } else { double* start = pointsOriginal->GetPoint(0); itk::Point itkStart; itkStart[0] = start[0]; itkStart[1] = start[1]; itkStart[2] = start[2]; itk::Index<3> idxStart; mask->TransformPhysicalPointToIndex(itkStart, idxStart); double* end = pointsOriginal->GetPoint(numPointsOriginal-1); itk::Point itkEnd; itkEnd[0] = end[0]; itkEnd[1] = end[1]; itkEnd[2] = end[2]; itk::Index<3> idxEnd; mask->TransformPhysicalPointToIndex(itkEnd, idxEnd); if ( mask->GetPixel(idxStart)>0 && mask->GetPixel(idxEnd)>0 && mask->GetLargestPossibleRegion().IsInside(idxStart) && mask->GetLargestPossibleRegion().IsInside(idxEnd) ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()<=0) return NULL; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); return mitk::FiberBundleX::New(newPolyData); } mitk::FiberBundleX::Pointer mitk::FiberBundleX::RemoveFibersOutside(ItkUcharImgType* mask, bool invert) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; mitk::FiberBundleX::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleSpline(minSpacing/10); vtkSmartPointer polyData =fibCopy->GetFiberPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Cutting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1) { int newNumPoints = 0; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) && !invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if ( (mask->GetPixel(idx)<=0 || !mask->GetLargestPossibleRegion().IsInside(idx)) && invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if (newNumPoints>0) { vtkNewCells->InsertNextCell(container); newNumPoints = 0; container = vtkSmartPointer::New(); } } if (newNumPoints>0) vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return NULL; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newPolyData); newFib->ResampleSpline(minSpacing/2); return newFib; } mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(BaseData* roi) { if (roi==NULL || !(dynamic_cast(roi) || dynamic_cast(roi)) ) return NULL; std::vector tmp = ExtractFiberIdSubset(roi); if (tmp.size()<=0) return mitk::FiberBundleX::New(); vtkSmartPointer pTmp = GeneratePolyDataByIds(tmp); return mitk::FiberBundleX::New(pTmp); } std::vector mitk::FiberBundleX::ExtractFiberIdSubset(BaseData* roi) { std::vector result; if (roi==NULL) return result; mitk::PlanarFigureComposite::Pointer pfc = dynamic_cast(roi); if (!pfc.IsNull()) // handle composite { switch (pfc->getOperationType()) { case 0: // AND { result = this->ExtractFiberIdSubset(pfc->getChildAt(0)); std::vector::iterator it; for (int i=1; igetNumberOfChildren(); ++i) { std::vector inRoi = this->ExtractFiberIdSubset(pfc->getChildAt(i)); std::vector rest(std::min(result.size(),inRoi.size())); it = std::set_intersection(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } case 1: // OR { result = ExtractFiberIdSubset(pfc->getChildAt(0)); std::vector::iterator it; for (int i=1; igetNumberOfChildren(); ++i) { it = result.end(); std::vector inRoi = ExtractFiberIdSubset(pfc->getChildAt(i)); result.insert(it, inRoi.begin(), inRoi.end()); } // remove duplicates sort(result.begin(), result.end()); it = unique(result.begin(), result.end()); result.resize( it - result.begin() ); break; } case 2: // NOT { for(long i=0; iGetNumFibers(); i++) result.push_back(i); std::vector::iterator it; for (long i=0; igetNumberOfChildren(); ++i) { std::vector inRoi = ExtractFiberIdSubset(pfc->getChildAt(i)); std::vector rest(result.size()-inRoi.size()); it = std::set_difference(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } } } else if ( dynamic_cast(roi) ) // actual extraction { - mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(roi); - Vector3D planeNormal = planarFigure->GetPlaneGeometry()->GetNormal(); - planeNormal.Normalize(); - Point3D planeOrigin = planarFigure->GetPlaneGeometry()->GetOrigin(); - - // define cutting plane by ROI geometry (PlanarFigure) - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetOrigin(planeOrigin[0],planeOrigin[1],planeOrigin[2]); - plane->SetNormal(planeNormal[0],planeNormal[1],planeNormal[2]); - - // get all fiber/plane intersection points - vtkSmartPointer clipper = vtkSmartPointer::New(); - clipper->SetInputData(m_FiberIdDataSet); - clipper->SetClipFunction(plane); - clipper->GenerateClipScalarsOn(); - clipper->GenerateClippedOutputOn(); - clipper->Update(); - vtkSmartPointer clipperout = clipper->GetClippedOutput(); - if (!clipperout->GetCellData()->HasArray(FIBER_ID_ARRAY)) - return result; - - vtkSmartPointer distanceList = clipperout->GetPointData()->GetScalars(); - vtkIdType numPoints = distanceList->GetNumberOfTuples(); - - std::vector pointsOnPlane; - pointsOnPlane.reserve(numPoints); - for (int i=0; i(roi) ) { - double distance = distanceList->GetTuple(i)[0]; - // check if point is on plane - if (distance >= -0.01 && distance <= 0.01) - pointsOnPlane.push_back(i); + mitk::PlanarFigure::Pointer planarPoly = dynamic_cast(roi); + + //create vtkPolygon using controlpoints from planarFigure polygon + vtkSmartPointer polygonVtk = vtkSmartPointer::New(); + for (unsigned int i=0; iGetNumberOfControlPoints(); ++i) + { + itk::Point p = planarPoly->GetWorldControlPoint(i); + vtkIdType id = polygonVtk->GetPoints()->InsertNextPoint(p[0], p[1], p[2] ); + polygonVtk->GetPointIds()->InsertNextId(id); + } + + MITK_INFO << "Extracting with polygon"; + boost::progress_display disp(m_NumFibers); + for (int i=0; iGetCell(i); + int numPoints = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); + + for (int j=0; jGetPoint(j, p1); + double p2[3] = {0,0,0}; + points->GetPoint(j+1, p2); + double tolerance = 0.001; + + // Outputs + double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) + double x[3] = {0,0,0}; // The coordinate of the intersection + double pcoords[3] = {0,0,0}; + int subId = 0; + + int iD = polygonVtk->IntersectWithLine(p1, p2, tolerance, t, x, pcoords, subId); + if (iD!=0) + { + result.push_back(i); + break; + } + } + } } - if (pointsOnPlane.empty()) - return result; - - // get all point IDs inside the ROI - std::vector pointsInROI; - pointsInROI.reserve(pointsOnPlane.size()); - mitk::PlanarCircle::Pointer circleName = mitk::PlanarCircle::New(); - mitk::PlanarPolygon::Pointer polyName = mitk::PlanarPolygon::New(); - if ( planarFigure->GetNameOfClass() == circleName->GetNameOfClass() ) + else if ( dynamic_cast(roi) ) { + mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(roi); + Vector3D planeNormal = planarFigure->GetPlaneGeometry()->GetNormal(); + planeNormal.Normalize(); + //calculate circle radius mitk::Point3D V1w = planarFigure->GetWorldControlPoint(0); //centerPoint mitk::Point3D V2w = planarFigure->GetWorldControlPoint(1); //radiusPoint double radius = V1w.EuclideanDistanceTo(V2w); radius *= radius; - for (unsigned int i=0; iGetPoint(pointsOnPlane[i], p); - double dist = (p[0]-V1w[0])*(p[0]-V1w[0])+(p[1]-V1w[1])*(p[1]-V1w[1])+(p[2]-V1w[2])*(p[2]-V1w[2]); - if( dist <= radius) - pointsInROI.push_back(pointsOnPlane[i]); - } - } - else if ( planarFigure->GetNameOfClass() == polyName->GetNameOfClass() ) - { - //create vtkPolygon using controlpoints from planarFigure polygon - vtkSmartPointer polygonVtk = vtkSmartPointer::New(); - for (unsigned int i=0; iGetNumberOfControlPoints(); ++i) + MITK_INFO << "Extracting with circle"; + boost::progress_display disp(m_NumFibers); + for (int i=0; i p = planarFigure->GetWorldControlPoint(i); - polygonVtk->GetPoints()->InsertNextPoint(p[0], p[1], p[2] ); - } - //prepare everything for using pointInPolygon function - double n[3]; - polygonVtk->ComputeNormal(polygonVtk->GetPoints()->GetNumberOfPoints(), static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), n); - double bounds[6]; - polygonVtk->GetPoints()->GetBounds(bounds); + ++disp ; + vtkCell* cell = m_FiberPolyData->GetCell(i); + int numPoints = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); - for (unsigned int i=0; iGetPoint(pointsOnPlane[i], p); - int isInPolygon = polygonVtk->PointInPolygon(p, polygonVtk->GetPoints()->GetNumberOfPoints(), static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), bounds, n); - if( isInPolygon ) - pointsInROI.push_back(pointsOnPlane[i]); - } - } - if (pointsInROI.empty()) - return result; + for (int j=0; jGetPoint(j, p1); + double p2[3] = {0,0,0}; + points->GetPoint(j+1, p2); - // get the fiber IDs corresponding to all clipped points - std::vector< long > pointToFiberMap; // pointToFiberMap[PointID] = FiberIndex - pointToFiberMap.resize(clipperout->GetNumberOfPoints()); + // Outputs + double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) + double x[3] = {0,0,0}; // The coordinate of the intersection - vtkCellArray* clipperlines = clipperout->GetLines(); - clipperlines->InitTraversal(); - for (int i=0, ic=0 ; iGetNumberOfCells(); i++, ic+=3) - { - // ic is the index counter for the cells hosting the desired information. each cell consits of 3 items. - long fiberID = clipperout->GetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0]; - vtkIdType numPoints; - vtkIdType* pointIDs; - clipperlines->GetCell(ic, numPoints, pointIDs); - - for (long j=0; j=0) - result.push_back( pointToFiberMap[pointsInROI[k]] ); - else - MITK_INFO << "ERROR in ExtractFiberIdSubset; impossible fiber id detected"; + if (iD!=0) + { + double dist = (x[0]-V1w[0])*(x[0]-V1w[0])+(x[1]-V1w[1])*(x[1]-V1w[1])+(x[2]-V1w[2])*(x[2]-V1w[2]); + if( dist <= radius) + { + result.push_back(i); + break; + } + } + } + } } - - // remove duplicates - std::vector::iterator it; - sort(result.begin(), result.end()); - it = unique (result.begin(), result.end()); - result.resize( it - result.begin() ); + return result; } return result; } void mitk::FiberBundleX::UpdateFiberGeometry() { vtkSmartPointer cleaner = vtkSmartPointer::New(); cleaner->SetInputData(m_FiberPolyData); cleaner->PointMergingOff(); cleaner->Update(); m_FiberPolyData = cleaner->GetOutput(); m_FiberLengths.clear(); m_MeanFiberLength = 0; m_MedianFiberLength = 0; m_LengthStDev = 0; m_NumFibers = m_FiberPolyData->GetNumberOfCells(); + if (m_FiberColors==NULL || m_FiberColors->GetNumberOfTuples()!=m_FiberPolyData->GetNumberOfPoints()) + this->DoColorCodingOrientationBased(); + + if (m_FiberWeights->GetSize()!=m_NumFibers) + { + m_FiberWeights = vtkSmartPointer::New(); + m_FiberWeights->SetName("FIBER_WEIGHTS"); + m_FiberWeights->SetNumberOfValues(m_NumFibers); + this->SetFiberWeights(1); + } + if (m_NumFibers<=0) // no fibers present; apply default geometry { m_MinFiberLength = 0; m_MaxFiberLength = 0; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(false); float b[] = {0, 1, 0, 1, 0, 1}; geometry->SetFloatBounds(b); SetGeometry(geometry); return; } double b[6]; m_FiberPolyData->GetBounds(b); // calculate statistics for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int p = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); float length = 0; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); float dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2])); length += dist; } m_FiberLengths.push_back(length); m_MeanFiberLength += length; if (i==0) { m_MinFiberLength = length; m_MaxFiberLength = length; } else { if (lengthm_MaxFiberLength) m_MaxFiberLength = length; } } m_MeanFiberLength /= m_NumFibers; std::vector< float > sortedLengths = m_FiberLengths; std::sort(sortedLengths.begin(), sortedLengths.end()); for (int i=0; i1) m_LengthStDev /= (m_NumFibers-1); else m_LengthStDev = 0; m_LengthStDev = std::sqrt(m_LengthStDev); m_MedianFiberLength = sortedLengths.at(m_NumFibers/2); mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetFloatBounds(b); this->SetGeometry(geometry); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } -std::vector mitk::FiberBundleX::GetAvailableColorCodings() +float mitk::FiberBundleX::GetFiberWeight(unsigned int fiber) { - std::vector availableColorCodings; - int numColors = m_FiberPolyData->GetPointData()->GetNumberOfArrays(); - for(int i=0; iGetPointData()->GetArrayName(i)); - } - - //this controlstructure shall be implemented by the calling method - if (availableColorCodings.empty()) - MITK_DEBUG << "no colorcodings available in fiberbundleX"; - - return availableColorCodings; + return m_FiberWeights->GetValue(fiber); } - -char* mitk::FiberBundleX::GetCurrentColorCoding() +void mitk::FiberBundleX::SetFiberWeights(float newWeight) { - return m_CurrentColorCoding; + for (int i=0; iGetSize(); i++) + m_FiberWeights->SetValue(i, newWeight); } -void mitk::FiberBundleX::SetColorCoding(const char* requestedColorCoding) +void mitk::FiberBundleX::SetFiberWeights(vtkSmartPointer weights) { - if (requestedColorCoding==NULL) + if (m_NumFibers!=weights->GetSize()) return; - if( strcmp (COLORCODING_ORIENTATION_BASED,requestedColorCoding) == 0 ) { - this->m_CurrentColorCoding = (char*) COLORCODING_ORIENTATION_BASED; + for (int i=0; iGetSize(); i++) + m_FiberWeights->SetValue(i, weights->GetValue(i)); - } else if( strcmp (COLORCODING_FA_BASED,requestedColorCoding) == 0 ) { - this->m_CurrentColorCoding = (char*) COLORCODING_FA_BASED; + m_FiberWeights->SetName("FIBER_WEIGHTS"); +} - } else if( strcmp (COLORCODING_CUSTOM,requestedColorCoding) == 0 ) { - this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; +void mitk::FiberBundleX::SetFiberWeight(unsigned int fiber, float weight) +{ + m_FiberWeights->SetValue(fiber, weight); +} - } else { - MITK_DEBUG << "FIBERBUNDLE X: UNKNOWN COLORCODING in FIBERBUNDLEX Datastructure"; - this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; //will cause blank colorcoding of fibers +void mitk::FiberBundleX::SetFiberColors(vtkSmartPointer fiberColors) +{ + for(long i=0; iGetNumberOfPoints(); ++i) + { + unsigned char source[4] = {0,0,0,0}; + fiberColors->GetTupleValue(i, source); + + unsigned char target[4] = {0,0,0,0}; + target[0] = source[0]; + target[1] = source[1]; + target[2] = source[2]; + target[3] = source[3]; + m_FiberColors->InsertTupleValue(i, target); } - m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } itk::Matrix< double, 3, 3 > mitk::FiberBundleX::TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; m = rot*m; return m; } itk::Point mitk::FiberBundleX::TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); point[0] -= center[0]; point[1] -= center[1]; point[2] -= center[2]; point = rot*point; point[0] += center[0]+tx; point[1] += center[1]+ty; point[2] += center[2]+tz; itk::Point out; out[0] = point[0]; out[1] = point[1]; out[2] = point[2]; return out; } void mitk::FiberBundleX::TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rot*dir; dir[0] += center[0]+tx; dir[1] += center[1]+ty; dir[2] += center[2]+tz; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundleX::RotateAroundAxis(double x, double y, double z) { x = x*M_PI/180; y = y*M_PI/180; z = z*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rotZ*rotY*rotX*dir; dir[0] += center[0]; dir[1] += center[1]; dir[2] += center[2]; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundleX::ScaleFibers(double x, double y, double z, bool subtractCenter) { MITK_INFO << "Scaling fibers"; boost::progress_display disp(m_NumFibers); mitk::BaseGeometry* geom = this->GetGeometry(); mitk::Point3D c = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); if (subtractCenter) { p[0] -= c[0]; p[1] -= c[1]; p[2] -= c[2]; } p[0] *= x; p[1] *= y; p[2] *= z; if (subtractCenter) { p[0] += c[0]; p[1] += c[1]; p[2] += c[2]; } vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundleX::TranslateFibers(double x, double y, double z) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[0] += x; p[1] += y; p[2] += z; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundleX::MirrorFibers(unsigned int axis) { if (axis>2) return; MITK_INFO << "Mirroring fibers"; boost::progress_display disp(m_NumFibers); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[axis] = -p[axis]; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundleX::RemoveDir(vnl_vector_fixed dir, double threshold) { dir.normalize(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); bool discard = false; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); vnl_vector_fixed< double, 3 > v1; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; if (v1.magnitude()>0.001) { v1.normalize(); if (fabs(dot_product(v1,dir))>threshold) { discard = true; break; } } } if (!discard) { for (int j=0; jGetPoint(j, p1); vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); -// UpdateColorCoding(); -// UpdateFiberGeometry(); + // UpdateColorCoding(); + // UpdateFiberGeometry(); } bool mitk::FiberBundleX::ApplyCurvatureThreshold(float minRadius, bool deleteFibers) { if (minRadius<0) return true; vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Applying curvature threshold"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); double p3[3]; points->GetPoint(j+2, p3); vnl_vector_fixed< float, 3 > v1, v2, v3; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; v2[0] = p3[0]-p2[0]; v2[1] = p3[1]-p2[1]; v2[2] = p3[2]-p2[2]; v3[0] = p1[0]-p3[0]; v3[1] = p1[1]-p3[1]; v3[2] = p1[2]-p3[2]; float a = v1.magnitude(); float b = v2.magnitude(); float c = v3.magnitude(); float r = a*b*c/std::sqrt((a+b+c)*(a+b-c)*(b+c-a)*(a-b+c)); // radius of triangle via Heron's formula (area of triangle) vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); if (deleteFibers && rInsertNextCell(container); container = vtkSmartPointer::New(); } else if (j==numPoints-3) { id = vtkNewPoints->InsertNextPoint(p2); container->GetPointIds()->InsertNextId(id); id = vtkNewPoints->InsertNextPoint(p3); container->GetPointIds()->InsertNextId(id); vtkNewCells->InsertNextCell(container); } } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } bool mitk::FiberBundleX::RemoveShortFibers(float lengthInMM) { MITK_INFO << "Removing short fibers"; if (lengthInMM<=0 || lengthInMMm_MaxFiberLength) // can't remove all fibers { MITK_WARN << "Process aborted. No fibers would be left!"; return false; } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); float min = m_MaxFiberLength; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)>=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); if (m_FiberLengths.at(i)GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } bool mitk::FiberBundleX::RemoveLongFibers(float lengthInMM) { if (lengthInMM<=0 || lengthInMM>m_MaxFiberLength) return true; if (lengthInMM vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Removing long fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)<=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } void mitk::FiberBundleX::ResampleSpline(float pointDistance, double tension, double continuity, double bias ) { if (pointDistance<=0) return; vtkSmartPointer vtkSmoothPoints = vtkSmartPointer::New(); //in smoothpoints the interpolated points representing a fiber are stored. //in vtkcells all polylines are stored, actually all id's of them are stored vtkSmartPointer vtkSmoothCells = vtkSmartPointer::New(); //cellcontainer for smoothed lines vtkIdType pointHelperCnt = 0; MITK_INFO << "Smoothing fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer newPoints = vtkSmartPointer::New(); for (int j=0; jInsertNextPoint(points->GetPoint(j)); float length = m_FiberLengths.at(i); int sampling = std::ceil(length/pointDistance); vtkSmartPointer xSpline = vtkSmartPointer::New(); vtkSmartPointer ySpline = vtkSmartPointer::New(); vtkSmartPointer zSpline = vtkSmartPointer::New(); xSpline->SetDefaultBias(bias); xSpline->SetDefaultTension(tension); xSpline->SetDefaultContinuity(continuity); ySpline->SetDefaultBias(bias); ySpline->SetDefaultTension(tension); ySpline->SetDefaultContinuity(continuity); zSpline->SetDefaultBias(bias); zSpline->SetDefaultTension(tension); zSpline->SetDefaultContinuity(continuity); vtkSmartPointer spline = vtkSmartPointer::New(); spline->SetXSpline(xSpline); spline->SetYSpline(ySpline); spline->SetZSpline(zSpline); spline->SetPoints(newPoints); vtkSmartPointer functionSource = vtkSmartPointer::New(); functionSource->SetParametricFunction(spline); functionSource->SetUResolution(sampling); functionSource->SetVResolution(sampling); functionSource->SetWResolution(sampling); functionSource->Update(); vtkPolyData* outputFunction = functionSource->GetOutput(); vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber vtkSmartPointer smoothLine = vtkSmartPointer::New(); smoothLine->GetPointIds()->SetNumberOfIds(tmpSmoothPnts->GetNumberOfPoints()); for (int j=0; jGetNumberOfPoints(); j++) { smoothLine->GetPointIds()->SetId(j, j+pointHelperCnt); vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j)); } vtkSmoothCells->InsertNextCell(smoothLine); pointHelperCnt += tmpSmoothPnts->GetNumberOfPoints(); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkSmoothPoints); m_FiberPolyData->SetLines(vtkSmoothCells); this->SetFiberPolyData(m_FiberPolyData, true); m_FiberSampling = 10/pointDistance; } void mitk::FiberBundleX::ResampleSpline(float pointDistance) { ResampleSpline(pointDistance, 0, 0, 0 ); } unsigned long mitk::FiberBundleX::GetNumberOfPoints() { unsigned long points = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); points += cell->GetNumberOfPoints(); } return points; } void mitk::FiberBundleX::Compress(float error) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Compressing fibers"; unsigned long numRemovedPoints = 0; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures std::vector< int > removedPoints; removedPoints.resize(numPoints, 0); removedPoints[0]=-1; removedPoints[numPoints-1]=-1; vtkSmartPointer container = vtkSmartPointer::New(); bool pointFound = true; while (pointFound) { pointFound = false; double minError = error; int removeIndex = -1; for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< double, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; int validP = -1; vnl_vector_fixed< double, 3 > pred; for (int k=j-1; k>=0; k--) if (removedPoints[k]<=0) { double ref[3]; points->GetPoint(k, ref); pred[0]=ref[0]; pred[1]=ref[1]; pred[2]=ref[2]; validP = k; break; } int validS = -1; vnl_vector_fixed< double, 3 > succ; for (int k=j+1; kGetPoint(k, ref); succ[0]=ref[0]; succ[1]=ref[1]; succ[2]=ref[2]; validS = k; break; } if (validP>=0 && validS>=0) { double a = (candV-pred).magnitude(); double b = (candV-succ).magnitude(); double c = (pred-succ).magnitude(); double s=0.5*(a+b+c); double hc=(2.0/c)*sqrt(fabs(s*(s-a)*(s-b)*(s-c))); if (hcGetPoint(j, cand); vtkIdType id = vtkNewPoints->InsertNextPoint(cand); container->GetPointIds()->InsertNextId(id); } } vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()>0) { MITK_INFO << "Removed points: " << numRemovedPoints; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } } -// reapply selected colorcoding in case polydata structure has changed -void mitk::FiberBundleX::UpdateColorCoding() -{ - char* cc = GetCurrentColorCoding(); - - if( strcmp (COLORCODING_ORIENTATION_BASED,cc) == 0 ) - DoColorCodingOrientationBased(); - else if( strcmp (COLORCODING_FA_BASED,cc) == 0 ) - DoColorCodingFaBased(); -} - // reapply selected colorcoding in case polydata structure has changed bool mitk::FiberBundleX::Equals(mitk::FiberBundleX* fib, double eps) { if (fib==NULL) { MITK_INFO << "Reference bundle is NULL!"; return false; } if (m_NumFibers!=fib->GetNumFibers()) { MITK_INFO << "Unequal number of fibers!"; MITK_INFO << m_NumFibers << " vs. " << fib->GetNumFibers(); return false; } for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cell2 = fib->GetFiberPolyData()->GetCell(i); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (numPoints2!=numPoints) { MITK_INFO << "Unequal number of points in fiber " << i << "!"; MITK_INFO << numPoints2 << " vs. " << numPoints; return false; } for (int j=0; jGetPoint(j); double* p2 = points2->GetPoint(j); if (fabs(p1[0]-p2[0])>eps || fabs(p1[1]-p2[1])>eps || fabs(p1[2]-p2[2])>eps) { MITK_INFO << "Unequal points in fiber " << i << " at position " << j << "!"; MITK_INFO << "p1: " << p1[0] << ", " << p1[1] << ", " << p1[2]; MITK_INFO << "p2: " << p2[0] << ", " << p2[1] << ", " << p2[2]; return false; } } } return true; } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void mitk::FiberBundleX::UpdateOutputInformation() { } void mitk::FiberBundleX::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::FiberBundleX::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::FiberBundleX::VerifyRequestedRegion() { return true; } void mitk::FiberBundleX::SetRequestedRegion(const itk::DataObject* ) { } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h index 88800c8dc1..a20c166205 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h @@ -1,177 +1,178 @@ /*=================================================================== 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 _MITK_FiberBundleX_H #define _MITK_FiberBundleX_H //includes for MITK datastructure #include #include #include //includes storing fiberdata #include #include #include #include #include +#include //#include #include #include #include namespace mitk { /** * \brief Base Class for Fiber Bundles; */ class MITKFIBERTRACKING_EXPORT FiberBundleX : public BaseData { public: typedef itk::Image ItkUcharImgType; // fiber colorcodings - static const char* COLORCODING_ORIENTATION_BASED; - static const char* COLORCODING_FA_BASED; - static const char* COLORCODING_CUSTOM; static const char* FIBER_ID_ARRAY; virtual void UpdateOutputInformation(); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual bool VerifyRequestedRegion(); virtual void SetRequestedRegion(const itk::DataObject*); mitkClassMacro( FiberBundleX, BaseData ) itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkNewMacro1Param(Self, vtkSmartPointer) // custom constructor // colorcoding related methods - void SetColorCoding(const char*); - void SetFAMap(mitk::Image::Pointer); + void ColorFibersByScalarMap(mitk::Image::Pointer, bool opacity); template - void SetFAMap(const mitk::PixelType pixelType, mitk::Image::Pointer); + void ColorFibersByScalarMap(const mitk::PixelType pixelType, mitk::Image::Pointer, bool opacity); void DoColorCodingOrientationBased(); - void DoColorCodingFaBased(); - void DoUseFaFiberOpacity(); + void SetFiberOpacity(vtkDoubleArray *FAValArray); void ResetFiberOpacity(); + void SetFiberColors(vtkSmartPointer fiberColors); + void SetFiberColors(float r, float g, float b, float alpha=255); + vtkSmartPointer GetFiberColors() const { return m_FiberColors; } // fiber compression void Compress(float error = 0.0); // fiber resampling void ResampleSpline(float pointDistance=1); void ResampleSpline(float pointDistance, double tension, double continuity, double bias ); bool RemoveShortFibers(float lengthInMM); bool RemoveLongFibers(float lengthInMM); bool ApplyCurvatureThreshold(float minRadius, bool deleteFibers); void MirrorFibers(unsigned int axis); void RotateAroundAxis(double x, double y, double z); void TranslateFibers(double x, double y, double z); void ScaleFibers(double x, double y, double z, bool subtractCenter=true); void TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz); void RemoveDir(vnl_vector_fixed dir, double threshold); itk::Point TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz); itk::Matrix< double, 3, 3 > TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz); // add/subtract fibers FiberBundleX::Pointer AddBundle(FiberBundleX* fib); FiberBundleX::Pointer SubtractBundle(FiberBundleX* fib); // fiber subset extraction FiberBundleX::Pointer ExtractFiberSubset(BaseData* roi); std::vector ExtractFiberIdSubset(BaseData* roi); FiberBundleX::Pointer ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert=false); FiberBundleX::Pointer RemoveFibersOutside(ItkUcharImgType* mask, bool invert=false); vtkSmartPointer GeneratePolyDataByIds( std::vector ); // TODO: make protected void GenerateFiberIds(); // TODO: make protected // get/set data + vtkSmartPointer GetFiberWeights() const { return m_FiberWeights; } + float GetFiberWeight(unsigned int fiber); + void SetFiberWeights(float newWeight); + void SetFiberWeight(unsigned int fiber, float weight); + void SetFiberWeights(vtkSmartPointer weights); void SetFiberPolyData(vtkSmartPointer, bool updateGeometry = true); vtkSmartPointer GetFiberPolyData() const; - std::vector< std::string > GetAvailableColorCodings(); - char* GetCurrentColorCoding(); itkGetMacro( NumFibers, int) //itkGetMacro( FiberSampling, int) int GetNumFibers() const {return m_NumFibers;} itkGetMacro( MinFiberLength, float ) itkGetMacro( MaxFiberLength, float ) itkGetMacro( MeanFiberLength, float ) itkGetMacro( MedianFiberLength, float ) itkGetMacro( LengthStDev, float ) itkGetMacro( UpdateTime2D, itk::TimeStamp ) itkGetMacro( UpdateTime3D, itk::TimeStamp ) void RequestUpdate2D(){ m_UpdateTime2D.Modified(); } void RequestUpdate3D(){ m_UpdateTime3D.Modified(); } + void RequestUpdate(){ m_UpdateTime2D.Modified(); m_UpdateTime3D.Modified(); } unsigned long GetNumberOfPoints(); // copy fiber bundle mitk::FiberBundleX::Pointer GetDeepCopy(); // compare fiber bundles bool Equals(FiberBundleX* fib, double eps=0.0001); itkSetMacro( ReferenceGeometry, mitk::BaseGeometry::Pointer ) itkGetConstMacro( ReferenceGeometry, mitk::BaseGeometry::Pointer ) protected: FiberBundleX( vtkPolyData* fiberPolyData = NULL ); virtual ~FiberBundleX(); itk::Point GetItkPoint(double point[3]); // calculate geometry from fiber extent void UpdateFiberGeometry(); - // calculate colorcoding values according to m_CurrentColorCoding - void UpdateColorCoding(); - private: // actual fiber container vtkSmartPointer m_FiberPolyData; // contains fiber ids vtkSmartPointer m_FiberIdDataSet; - char* m_CurrentColorCoding; int m_NumFibers; + vtkSmartPointer m_FiberColors; + vtkSmartPointer m_FiberWeights; std::vector< float > m_FiberLengths; float m_MinFiberLength; float m_MaxFiberLength; float m_MeanFiberLength; float m_MedianFiberLength; float m_LengthStDev; int m_FiberSampling; itk::TimeStamp m_UpdateTime2D; itk::TimeStamp m_UpdateTime3D; mitk::BaseGeometry::Pointer m_ReferenceGeometry; }; } // namespace mitk #endif /* _MITK_FiberBundleX_H */ diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp index 9b49819365..1d7bd6c369 100755 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp @@ -1,167 +1,167 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include using namespace std; int mitkLocalFiberPlausibilityTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkLocalFiberPlausibilityTest"); MITK_TEST_CONDITION_REQUIRED(argc==8,"check for input data") string fibFile = argv[1]; vector< string > referenceImages; referenceImages.push_back(argv[2]); referenceImages.push_back(argv[3]); string LDFP_ERROR_IMAGE = argv[4]; string LDFP_NUM_DIRECTIONS = argv[5]; string LDFP_VECTOR_FIELD = argv[6]; string LDFP_ERROR_IMAGE_IGNORE = argv[7]; - float angularThreshold = 25; + float angularThreshold = 30; try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; // load fiber bundle mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::LoadDataNode(referenceImages.at(i))->GetData()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ MITK_INFO << "could not load: " << referenceImages.at(i); } } ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); itkMaskImage->SetSpacing( dirImg->GetSpacing() ); itkMaskImage->SetOrigin( dirImg->GetOrigin() ); itkMaskImage->SetDirection( dirImg->GetDirection() ); itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->Allocate(); itkMaskImage->FillBuffer(1); // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); fOdfFilter->SetNormalizeVectors(true); - //fOdfFilter->SetMaxNumDirections(1); - fOdfFilter->SetSizeThreshold(0.0); + fOdfFilter->SetMaxNumDirections(3); + fOdfFilter->SetSizeThreshold(0.3); fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->SetNumberOfThreads(1); fOdfFilter->Update(); ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); // Get directions and num directions image ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); mitk::Image::Pointer mitkNumDirImage = mitk::Image::New(); mitkNumDirImage->InitializeByItk( numDirImage.GetPointer() ); mitkNumDirImage->SetVolume( numDirImage->GetBufferPointer() ); mitk::FiberBundleX::Pointer testDirections = fOdfFilter->GetOutputFiberBundle(); + //mitk::IOUtil::SaveImage(mitkNumDirImage, "/local/mitk/release-binary/MITK-superbuild/CMakeExternals/Source/MITK-Data/DiffusionImaging/LDFP_NUM_DIRECTIONS.nrrd"); + //mitk::IOUtil::SaveBaseData(testDirections, "/local/mitk/release-binary/MITK-superbuild/CMakeExternals/Source/MITK-Data/DiffusionImaging/LDFP_VECTOR_FIELD.fib"); + // evaluate directions with missing directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(false); evaluationFilter->Update(); EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); mitk::Image::Pointer mitkAngularErrorImage = mitk::Image::New(); mitkAngularErrorImage->InitializeByItk( angularErrorImage.GetPointer() ); mitkAngularErrorImage->SetVolume( angularErrorImage->GetBufferPointer() ); + //mitk::IOUtil::SaveImage(mitkAngularErrorImage, "/local/mitk/release-binary/MITK-superbuild/CMakeExternals/Source/MITK-Data/DiffusionImaging/LDFP_ERROR_IMAGE.nrrd"); // evaluate directions without missing directions evaluationFilter->SetIgnoreMissingDirections(true); evaluationFilter->Update(); EvaluationFilterType::OutputImageType::Pointer angularErrorImageIgnore = evaluationFilter->GetOutput(0); mitk::Image::Pointer mitkAngularErrorImageIgnore = mitk::Image::New(); mitkAngularErrorImageIgnore->InitializeByItk( angularErrorImageIgnore.GetPointer() ); mitkAngularErrorImageIgnore->SetVolume( angularErrorImageIgnore->GetBufferPointer() ); + //mitk::IOUtil::SaveImage(mitkAngularErrorImageIgnore, "/local/mitk/release-binary/MITK-superbuild/CMakeExternals/Source/MITK-Data/DiffusionImaging/LDFP_ERROR_IMAGE_IGNORE.nrrd"); mitk::Image::Pointer gtAngularErrorImageIgnore = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_ERROR_IMAGE_IGNORE)->GetData()); mitk::Image::Pointer gtAngularErrorImage = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_ERROR_IMAGE)->GetData()); mitk::Image::Pointer gtNumTestDirImage = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_NUM_DIRECTIONS)->GetData()); mitk::FiberBundleX::Pointer gtTestDirections = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_VECTOR_FIELD)->GetData()); -// mitk::IOUtil::SaveBaseData(mitkAngularErrorImageIgnore, mitk::IOUtil::GetTempPath()+"mitkAngularErrorImageIgnore.nrrd"); -// mitk::IOUtil::SaveBaseData(mitkAngularErrorImage, mitk::IOUtil::GetTempPath()+"mitkAngularErrorImage.nrrd"); -// mitk::IOUtil::SaveBaseData(mitkNumDirImage, mitk::IOUtil::GetTempPath()+"mitkNumDirImage.nrrd"); -// mitk::IOUtil::SaveBaseData(testDirections, mitk::IOUtil::GetTempPath()+"testDirections.fib"); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(gtAngularErrorImageIgnore, mitkAngularErrorImageIgnore, 0.01, true), "Check if error images are equal (ignored missing directions)."); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(gtAngularErrorImage, mitkAngularErrorImage, 0.01, true), "Check if error images are equal."); MITK_TEST_CONDITION_REQUIRED(testDirections->Equals(gtTestDirections), "Check if vector fields are equal."); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(gtNumTestDirImage, mitkNumDirImage, 0.1, true), "Check if num direction images are equal."); } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/MiniApps/CMakeLists.txt b/Modules/DiffusionImaging/MiniApps/CMakeLists.txt index 43be92ff29..3325706db6 100755 --- a/Modules/DiffusionImaging/MiniApps/CMakeLists.txt +++ b/Modules/DiffusionImaging/MiniApps/CMakeLists.txt @@ -1,165 +1,115 @@ option(BUILD_DiffusionMiniApps "Build commandline tools for diffusion" OFF) if(BUILD_DiffusionMiniApps OR MITK_BUILD_ALL_APPS) # needed include directories include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) + # list of diffusion miniapps + # if an app requires additional dependencies + # they are added after a "^^" and separated by "_" + set( diffusionminiapps + DwiDenoising^^ + ImageResampler^^ + NetworkCreation^^MitkFiberTracking_MitkConnectomics + NetworkStatistics^^MitkConnectomics + ExportShImage^^ + Fiberfox^^MitkFiberTracking + MultishellMethods^^MitkFiberTracking + PeaksAngularError^^MitkFiberTracking + PeakExtraction^^MitkFiberTracking + FiberExtraction^^MitkFiberTracking + FiberProcessing^^MitkFiberTracking + FiberDirectionExtraction^^MitkFiberTracking + LocalDirectionalFiberPlausibility^^MitkFiberTracking + StreamlineTracking^^MitkFiberTracking + GibbsTracking^^MitkFiberTracking + CopyGeometry^^ + DiffusionIndices^^ + TractometerMetrics^^MitkFiberTracking + QballReconstruction^^ + Registration^^ + FileFormatConverter^^MitkFiberTracking + TensorReconstruction^^ + TensorDerivedMapsExtraction^^ + DICOMLoader^^ + ) - mitk_create_executable(DwiDenoising - DEPENDS MitkCore MitkDiffusionCore - PACKAGE_DEPENDS ITK - CPP_FILES DwiDenoising.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(ImageResampler - DEPENDS MitkCore MitkDiffusionCore - PACKAGE_DEPENDS ITK - CPP_FILES ImageResampler.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(NetworkCreation - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking MitkConnectomics - PACKAGE_DEPENDS ITK - CPP_FILES NetworkCreation.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(NetworkStatistics - DEPENDS MitkCore MitkDiffusionCore MitkConnectomics - PACKAGE_DEPENDS ITK - CPP_FILES NetworkStatistics.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(ExportShImage - DEPENDS MitkCore MitkDiffusionCore - PACKAGE_DEPENDS ITK - CPP_FILES ExportShImage.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(Fiberfox - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES Fiberfox.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(MultishellMethods - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES MultishellMethods.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(PeaksAngularError - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES PeaksAngularError.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(PeakExtraction - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES PeakExtraction.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(FiberExtraction - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES FiberExtraction.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(FiberProcessing - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES FiberProcessing.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(FiberDirectionExtraction - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES FiberDirectionExtraction.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(LocalDirectionalFiberPlausibility - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES LocalDirectionalFiberPlausibility.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(StreamlineTracking - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES StreamlineTracking.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(GibbsTracking - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES GibbsTracking.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(CopyGeometry - DEPENDS MitkCore MitkDiffusionCore - PACKAGE_DEPENDS ITK - CPP_FILES CopyGeometry.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(DiffusionIndices - DEPENDS MitkCore MitkDiffusionCore - PACKAGE_DEPENDS ITK - CPP_FILES DiffusionIndices.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(TractometerMetrics - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking - PACKAGE_DEPENDS ITK - CPP_FILES TractometerMetrics.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(QballReconstruction - DEPENDS MitkCore MitkDiffusionCore - PACKAGE_DEPENDS ITK - CPP_FILES QballReconstruction.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(FolderRegistration - DEPENDS MitkCore MitkDiffusionCore - PACKAGE_DEPENDS ITK - CPP_FILES mitkRegistration.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(FileFormatConverter - DEPENDS MitkCore MitkDiffusionCore MitkFiberTracking MitkDiffusionIO - PACKAGE_DEPENDS ITK - CPP_FILES mitkFileFormatConverter.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(TensorReconstruction - DEPENDS MitkCore MitkDiffusionCore MitkDiffusionIO - PACKAGE_DEPENDS ITK - CPP_FILES TensorReconstruction.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(TensorDerivedMapExtraction - DEPENDS MitkCore MitkDiffusionCore MitkDiffusionIO - PACKAGE_DEPENDS ITK - CPP_FILES TensorDerivedMapsExtraction.cpp mitkCommandLineParser.cpp - ) - - mitk_create_executable(DICOMLoader - DEPENDS MitkCore MitkDiffusionCore - PACKAGE_DEPENDS ITK - CPP_FILES DICOMLoader.cpp mitkCommandLineParser.cpp - ) - + foreach(diffusionminiapp ${diffusionminiapps}) + # extract mini app name and dependencies + string(REPLACE "^^" "\\;" miniapp_info ${diffusionminiapp}) + set(miniapp_info_list ${miniapp_info}) + list(GET miniapp_info_list 0 appname) + list(GET miniapp_info_list 1 raw_dependencies) + string(REPLACE "_" "\\;" dependencies "${raw_dependencies}") + set(dependencies_list ${dependencies}) + + mitk_create_executable(${appname} + DEPENDS MitkCore MitkDiffusionCore ${dependencies_list} + PACKAGE_DEPENDS ITK + CPP_FILES ${appname}.cpp mitkCommandLineParser.cpp + ) + + if(EXECUTABLE_IS_ENABLED) + + # On Linux, create a shell script to start a relocatable application + if(UNIX AND NOT APPLE) + install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh) + endif() + + get_target_property(_is_bundle ${EXECUTABLE_TARGET} MACOSX_BUNDLE) + + if(APPLE) + if(_is_bundle) + set(_target_locations ${EXECUTABLE_TARGET}.app) + set(${_target_locations}_qt_plugins_install_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) + set(_bundle_dest_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) + set(_qt_plugins_for_current_bundle ${EXECUTABLE_TARGET}.app/Contents/MacOS) + set(_qt_conf_install_dirs ${EXECUTABLE_TARGET}.app/Contents/Resources) + install(TARGETS ${EXECUTABLE_TARGET} BUNDLE DESTINATION . ) + else() + if(NOT MACOSX_BUNDLE_NAMES) + set(_qt_conf_install_dirs bin) + set(_target_locations bin/${EXECUTABLE_TARGET}) + set(${_target_locations}_qt_plugins_install_dir bin) + install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) + else() + foreach(bundle_name ${MACOSX_BUNDLE_NAMES}) + list(APPEND _qt_conf_install_dirs ${bundle_name}.app/Contents/Resources) + set(_current_target_location ${bundle_name}.app/Contents/MacOS/${EXECUTABLE_TARGET}) + list(APPEND _target_locations ${_current_target_location}) + set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) + message( " set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) ") + + install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION ${bundle_name}.app/Contents/MacOS/) + endforeach() + endif() + endif() + else() + set(_target_locations bin/${EXECUTABLE_TARGET}${CMAKE_EXECUTABLE_SUFFIX}) + set(${_target_locations}_qt_plugins_install_dir bin) + set(_qt_conf_install_dirs bin) + install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) + endif() + endif() + endforeach() + + # This mini app does not depend on mitkDiffusionImaging at all mitk_create_executable(Dicom2Nrrd DEPENDS MitkCore CPP_FILES Dicom2Nrrd.cpp mitkCommandLineParser.cpp ) + # On Linux, create a shell script to start a relocatable application + if(UNIX AND NOT APPLE) + install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh) + endif() + if(EXECUTABLE_IS_ENABLED) MITK_INSTALL_TARGETS(EXECUTABLES ${EXECUTABLE_TARGET}) endif() endif() diff --git a/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp b/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp index 7fb1ae16ac..fee3f5a616 100755 --- a/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp +++ b/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp @@ -1,81 +1,81 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include "mitkCommandLineParser.h" using namespace mitk; int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Copy Geometry"); parser.setCategory("Preprocessing Tools"); - parser.setDescription(""); + parser.setDescription("Copies Geometry from one image unto another"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("in", "i", mitkCommandLineParser::InputFile, "Input:", "input image", us::Any(), false); parser.addArgument("ref", "r", mitkCommandLineParser::InputFile, "Reference:", "reference image", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output:", "output image", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments string imageName = us::any_cast(parsedArgs["in"]); string refImage = us::any_cast(parsedArgs["ref"]); string outImage = us::any_cast(parsedArgs["out"]); try { const std::string s1="", s2=""; std::vector infile = BaseDataIO::LoadBaseDataFromFile( refImage, s1, s2, false ); Image::Pointer source = dynamic_cast(infile.at(0).GetPointer()); infile = BaseDataIO::LoadBaseDataFromFile( imageName, s1, s2, false ); Image::Pointer target = dynamic_cast(infile.at(0).GetPointer()); mitk::BaseGeometry* s_geom = source->GetGeometry(); mitk::BaseGeometry* t_geom = target->GetGeometry(); t_geom->SetIndexToWorldTransform(s_geom->GetIndexToWorldTransform()); target->SetGeometry(t_geom); mitk::IOUtil::Save(target.GetPointer(), outImage.c_str()); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/DICOMLoader.cpp b/Modules/DiffusionImaging/MiniApps/DICOMLoader.cpp index e84237b798..40b1980dbf 100644 --- a/Modules/DiffusionImaging/MiniApps/DICOMLoader.cpp +++ b/Modules/DiffusionImaging/MiniApps/DICOMLoader.cpp @@ -1,277 +1,286 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBaseDataIOFactory.h" #include "mitkImage.h" #include "mitkBaseData.h" #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include "mitkDiffusionDICOMFileReader.h" #include "mitkDICOMTagBasedSorter.h" #include "mitkDICOMSortByTag.h" #include "itkMergeDiffusionImagesFilter.h" #include static mitk::StringList& GetInputFilenames() { static mitk::StringList inputs; return inputs; } void SetInputFileNames( std::string input_directory ) { // I. Get all files in directory itksys::Directory input; input.Load( input_directory.c_str() ); // II. Push back files mitk::StringList inputlist;//, mergedlist; for( unsigned long idx=0; idxAddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0010) ); // Number of Rows tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0011) ); // Number of Columns tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0030) ); // Pixel Spacing tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x1164) ); // Imager Pixel Spacing tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0037) ); // Image Orientation (Patient) // TODO add tolerance parameter (l. 1572 of original code) tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x0050) ); // Slice Thickness tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0008) ); // Number of Frames tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0052) ); // Frame of Reference UID mitk::DICOMSortCriterion::ConstPointer sorting = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0013), // instance number mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0012) //acquisition number ).GetPointer() ).GetPointer(); tagSorter->SetSortCriterion( sorting ); MITK_INFO("dicom.loader.read.init") << "[]" ; MITK_INFO("dicom.loader.read.inputs") << " " << input_files.size(); gdcmReader->SetInputFiles( input_files ); gdcmReader->AddSortingElement( tagSorter ); gdcmReader->AnalyzeInputFiles(); gdcmReader->LoadImages(); mitk::Image::Pointer loaded_image = gdcmReader->GetOutput(0).GetMitkImage(); return loaded_image; } typedef short DiffusionPixelType; typedef itk::VectorImage DwiImageType; typedef DwiImageType::PixelType DwiPixelType; typedef DwiImageType::RegionType DwiRegionType; typedef std::vector< DwiImageType::Pointer > DwiImageContainerType; typedef mitk::Image DiffusionImageType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientContainerType; typedef std::vector< GradientContainerType::Pointer > GradientListContainerType; void SearchForInputInSubdirs( std::string root_directory, std::string subdir_prefix , std::vector& output_container) { // I. Get all dirs in directory itksys::Directory rootdir; rootdir.Load( root_directory.c_str() ); MITK_INFO("dicom.loader.setinputdirs.start") << "Prefix = " << subdir_prefix; for( unsigned int idx=0; idx parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) { return EXIT_FAILURE; } std::string inputDirectory = us::any_cast( parsedArgs["inputdir"] ); MITK_INFO << "Loading data from directory: " << inputDirectory; // retrieve the prefix flag (if set) bool search_for_subdirs = false; std::string subdir_prefix; if( parsedArgs.count("dwprefix")) { - MITK_INFO << "Prefix specified, will search for subdirs in the input directory!"; subdir_prefix = us::any_cast( parsedArgs["dwprefix"] ); - search_for_subdirs = true; + if (subdir_prefix != "") + { + MITK_INFO << "Prefix specified, will search for subdirs in the input directory!"; + search_for_subdirs = true; + } } // retrieve the output std::string outputFile = us::any_cast< std::string >( parsedArgs["output"] ); // if the executable is called with a single directory, just parse the given folder for files and read them into a diffusion image if( !search_for_subdirs ) { SetInputFileNames( inputDirectory ); MITK_INFO << "Got " << GetInputFilenames().size() << " input files."; mitk::Image::Pointer d_img = ReadInDICOMFiles( GetInputFilenames(), outputFile ); try { mitk::IOUtil::Save(d_img, outputFile.c_str()); } catch( const itk::ExceptionObject& e) { MITK_ERROR << "Failed to write out the output file. \n\t Reason : ITK Exception " << e.what(); } } // if the --dwprefix flag is set, then we have to look for the directories, load each of them separately and afterwards merge the images else { std::vector output_container; SearchForInputInSubdirs( inputDirectory, subdir_prefix, output_container ); // final output image mitk::Image::Pointer image = mitk::Image::New(); if( output_container.size() > 1 ) { DwiImageContainerType imageContainer; GradientListContainerType gradientListContainer; std::vector< double > bValueContainer; for ( std::vector< mitk::Image::Pointer >::iterator dwi = output_container.begin(); dwi != output_container.end(); ++dwi ) { mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(*dwi, itkVectorImagePointer); imageContainer.push_back(itkVectorImagePointer); gradientListContainer.push_back( mitk::DiffusionPropertyHelper::GetGradientContainer(*dwi)); bValueContainer.push_back( mitk::DiffusionPropertyHelper::GetReferenceBValue(*dwi)); } typedef itk::MergeDiffusionImagesFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetImageVolumes(imageContainer); filter->SetGradientLists(gradientListContainer); filter->SetBValues(bValueContainer); filter->Update(); vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity(); image = mitk::GrabItkImageMemory( filter->GetOutput() ); image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetOutputGradients() ) ); image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetB_Value() ) ); image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); } // just output the image if there was only one folder found else { image = output_container.at(0); } MITK_INFO("dicom.import.writeout") << " [OutputFile] " << outputFile.c_str(); try { mitk::IOUtil::Save(image, outputFile.c_str()); } catch( const itk::ExceptionObject& e) { MITK_ERROR << "Failed to write out the output file. \n\t Reason : ITK Exception " << e.what(); } } return 1; } diff --git a/Modules/DiffusionImaging/MiniApps/Dicom2Nrrd.cpp b/Modules/DiffusionImaging/MiniApps/Dicom2Nrrd.cpp index 4e6472aa90..f75d1e793b 100644 --- a/Modules/DiffusionImaging/MiniApps/Dicom2Nrrd.cpp +++ b/Modules/DiffusionImaging/MiniApps/Dicom2Nrrd.cpp @@ -1,88 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDicomSeriesReader.h" #include "mitkProperties.h" #include "mitkCommandLineParser.h" #include "mitkIOUtil.h" int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Dicom Loader"); parser.setCategory("Preprocessing Tools"); parser.setDescription(""); parser.setContributor("MBI"); parser.setArgumentPrefix("--","-"); // Add command line argument names parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.addArgument("input", "i", mitkCommandLineParser::InputDirectory, "Input folder:", "Input folder",us::Any(),false); - parser.addArgument("output", "o", mitkCommandLineParser::OutputDirectory, "Output folder:", "Output folder (ending with /)",us::Any(),false); - parser.addArgument("filename", "f", mitkCommandLineParser::String, "Output name:", "Output filename (incl. .nrrd)",us::Any(),false); + parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output file:", "Output file",us::Any(),false); + map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // Show a help message if ( parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } std::string inputFolder = us::any_cast(parsedArgs["input"]); - std::string outputFolder = us::any_cast(parsedArgs["output"]); - std::string outFileName = us::any_cast(parsedArgs["filename"]); + std::string outFileName = us::any_cast(parsedArgs["output"]); //check if DICOMTags have been set as property for mitk::Image mitk::DicomSeriesReader::FileNamesGrouping seriesInFiles = mitk::DicomSeriesReader::GetSeries( inputFolder, true ); std::list images; std::map fileMap; // TODO sort series UIDs, implementation of map iterator might differ on different platforms (or verify this is a standard topic??) for (mitk::DicomSeriesReader::FileNamesGrouping::const_iterator seriesIter = seriesInFiles.begin(); seriesIter != seriesInFiles.end(); ++seriesIter) { mitk::DicomSeriesReader::StringContainer files = seriesIter->second.GetFilenames(); mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries( files ); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); images.push_back( image ); fileMap.insert( std::pair(image,files)); } } // WARN: EXPECT ONLY ONE ITEM PER FOLDER for ( std::list::const_iterator imageIter = images.begin(); imageIter != images.end(); ++imageIter ) { const mitk::Image::Pointer image = *imageIter; - mitk::IOUtil::SaveImage(image,outputFolder + outFileName); + mitk::IOUtil::SaveImage(image,outFileName); } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/DiffusionIndices.cpp b/Modules/DiffusionImaging/MiniApps/DiffusionIndices.cpp index 4454344ef2..1e7d950ae2 100644 --- a/Modules/DiffusionImaging/MiniApps/DiffusionIndices.cpp +++ b/Modules/DiffusionImaging/MiniApps/DiffusionIndices.cpp @@ -1,144 +1,144 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include /** * Calculate indices derived from Qball or tensor images */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Diffusion Indices"); parser.setCategory("Diffusion Related Measures"); - parser.setDescription(""); + parser.setDescription("Computes requested diffusion related measures"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input image (tensor, Q-ball or FSL/MRTrix SH-coefficient image)", us::Any(), false); parser.addArgument("index", "idx", mitkCommandLineParser::String, "Index:", "index (fa, gfa, ra, ad, rd, ca, l2, l3, md)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output:", "output file", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFileName = us::any_cast(parsedArgs["input"]); string index = us::any_cast(parsedArgs["index"]); string outFileName = us::any_cast(parsedArgs["outFile"]); string ext = itksys::SystemTools::GetFilenameLastExtension(outFileName); if (ext.empty()) outFileName += ".nrrd"; try { // load input image const std::string s1="", s2=""; std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( inFileName, s1, s2, false ); if( boost::algorithm::ends_with(inFileName, ".qbi") && index=="gfa" ) { typedef itk::Vector OdfVectorType; typedef itk::Image ItkQballImageType; mitk::QBallImage::Pointer mitkQballImage = dynamic_cast(infile.at(0).GetPointer()); ItkQballImageType::Pointer itk_qbi = ItkQballImageType::New(); mitk::CastToItkImage(mitkQballImage, itk_qbi); typedef itk::DiffusionQballGeneralizedFaImageFilter GfaFilterType; GfaFilterType::Pointer gfaFilter = GfaFilterType::New(); gfaFilter->SetInput(itk_qbi); gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); gfaFilter->Update(); itk::ImageFileWriter< itk::Image >::Pointer fileWriter = itk::ImageFileWriter< itk::Image >::New(); fileWriter->SetInput(gfaFilter->GetOutput()); fileWriter->SetFileName(outFileName); fileWriter->Update(); } else if( boost::algorithm::ends_with(inFileName, ".dti") ) { typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(infile.at(0).GetPointer()); ItkTensorImage::Pointer itk_dti = ItkTensorImage::New(); mitk::CastToItkImage(mitkTensorImage, itk_dti); typedef itk::TensorDerivedMeasurementsFilter MeasurementsType; MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itk_dti.GetPointer() ); if(index=="fa") measurementsCalculator->SetMeasure(MeasurementsType::FA); else if(index=="ra") measurementsCalculator->SetMeasure(MeasurementsType::RA); else if(index=="ad") measurementsCalculator->SetMeasure(MeasurementsType::AD); else if(index=="rd") measurementsCalculator->SetMeasure(MeasurementsType::RD); else if(index=="ca") measurementsCalculator->SetMeasure(MeasurementsType::CA); else if(index=="l2") measurementsCalculator->SetMeasure(MeasurementsType::L2); else if(index=="l3") measurementsCalculator->SetMeasure(MeasurementsType::L3); else if(index=="md") measurementsCalculator->SetMeasure(MeasurementsType::MD); else { MITK_WARN << "No valid diffusion index for input image (tensor image) defined"; return EXIT_FAILURE; } measurementsCalculator->Update(); itk::ImageFileWriter< itk::Image >::Pointer fileWriter = itk::ImageFileWriter< itk::Image >::New(); fileWriter->SetInput(measurementsCalculator->GetOutput()); fileWriter->SetFileName(outFileName); fileWriter->Update(); } else std::cout << "Diffusion index " << index << " not supported for supplied file type."; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp b/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp index f30bfd5189..e611fa8580 100644 --- a/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp +++ b/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp @@ -1,163 +1,162 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include typedef mitk::Image DiffusionImageType; typedef itk::Image ImageType; mitk::BaseData::Pointer LoadFile(std::string filename) { if( filename.empty() ) return NULL; const std::string s1="", s2=""; std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( filename, s1, s2, false ); if( infile.empty() ) { std::cout << "File " << filename << " could not be read!"; return NULL; } mitk::BaseData::Pointer baseData = infile.at(0); return baseData; } /** * Denoises DWI using the Nonlocal - Means algorithm */ int main(int argc, char* argv[]) { - std::cout << "DwiDenoising"; mitkCommandLineParser parser; parser.setTitle("DWI Denoising"); parser.setCategory("Preprocessing Tools"); parser.setContributor("MBI"); parser.setDescription("Denoising for diffusion weighted images using a non-local means algorithm."); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input image (DWI)", us::Any(), false); parser.addArgument("variance", "v", mitkCommandLineParser::Float, "Variance:", "noise variance", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask:", "brainmask for input image", us::Any(), true); parser.addArgument("search", "s", mitkCommandLineParser::Int, "Search radius:", "search radius", us::Any(), true); parser.addArgument("compare", "c", mitkCommandLineParser::Int, "Comparison radius:", "comparison radius", us::Any(), true); parser.addArgument("joint", "j", mitkCommandLineParser::Bool, "Joint information:", "use joint information"); parser.addArgument("rician", "r", mitkCommandLineParser::Bool, "Rician adaption:", "use rician adaption"); parser.changeParameterGroup("Output", "Output of this miniapp"); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output:", "output image (DWI)", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFileName = us::any_cast(parsedArgs["input"]); double variance = static_cast(us::any_cast(parsedArgs["variance"])); string maskName; if (parsedArgs.count("mask")) maskName = us::any_cast(parsedArgs["mask"]); string outFileName = us::any_cast(parsedArgs["output"]); // boost::algorithm::erase_all(outFileName, ".dwi"); int search = 4; if (parsedArgs.count("search")) search = us::any_cast(parsedArgs["search"]); int compare = 1; if (parsedArgs.count("compare")) compare = us::any_cast(parsedArgs["compare"]); bool joint = false; if (parsedArgs.count("joint")) joint = true; bool rician = false; if (parsedArgs.count("rician")) rician = true; try { if( boost::algorithm::ends_with(inFileName, ".dwi")) { DiffusionImageType::Pointer dwi = dynamic_cast(LoadFile(inFileName).GetPointer()); mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); itk::NonLocalMeansDenoisingFilter::Pointer filter = itk::NonLocalMeansDenoisingFilter::New(); filter->SetNumberOfThreads(12); filter->SetInputImage( itkVectorImagePointer ); if (!maskName.empty()) { mitk::Image::Pointer mask = dynamic_cast(LoadFile(maskName).GetPointer()); ImageType::Pointer itkMask = ImageType::New(); mitk::CastToItkImage(mask, itkMask); filter->SetInputMask(itkMask); } filter->SetUseJointInformation(joint); filter->SetUseRicianAdaption(rician); filter->SetSearchRadius(search); filter->SetComparisonRadius(compare); filter->SetVariance(variance); filter->Update(); DiffusionImageType::Pointer output = mitk::GrabItkImageMemory( filter->GetOutput() ); output->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi) ) ); output->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi) ) ); mitk::DiffusionPropertyHelper propertyHelper( output ); propertyHelper.InitializeImage(); // std::stringstream name; // name << outFileName << "_NLM_" << search << "-" << compare << "-" << variance << ".dwi"; mitk::IOUtil::Save(output, outFileName.c_str()); } else { std::cout << "Only supported for .dwi!"; } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp b/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp index b42ebf97b4..385489228b 100755 --- a/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp +++ b/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp @@ -1,136 +1,136 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include template int StartShConversion(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Export SH Image"); parser.setCategory("Preprocessing Tools"); - parser.setDescription(""); + parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "MITK SH image", us::Any(), false); parser.addArgument("output", "o", mitkCommandLineParser::InputFile, "Output", "MRtrix SH image", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "SH order:", "spherical harmonics order"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFile = us::any_cast(parsedArgs["input"]); string outFile = us::any_cast(parsedArgs["output"]); try { typedef itk::Image< float, 4 > OutImageType; typedef itk::Image< itk::Vector< float, (shOrder*shOrder + shOrder + 2)/2 + shOrder >, 3 > InputImageType; typename InputImageType::Pointer itkInImage = InputImageType::New(); typedef itk::ImageFileReader< InputImageType > ReaderType; typename ReaderType::Pointer reader = ReaderType::New(); std::cout << "reading " << inFile; reader->SetFileName(inFile.c_str()); reader->Update(); itkInImage = reader->GetOutput(); // extract directions from fiber bundle typename itk::ShCoefficientImageExporter::Pointer filter = itk::ShCoefficientImageExporter::New(); filter->SetInputImage(itkInImage); filter->GenerateData(); OutImageType::Pointer outImage = filter->GetOutputImage(); typedef itk::ImageFileWriter< OutImageType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outFile.c_str()); writer->SetInput(outImage); writer->Update(); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input image", "MITK SH image", us::Any(), false); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output image", "MRtrix SH image", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "Spherical harmonics order", "spherical harmonics order"); parser.setCategory("Preprocessing Tools"); parser.setTitle("Export SH Image"); - parser.setDescription(""); + parser.setDescription(" "); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; int shOrder = -1; if (parsedArgs.count("shOrder")) shOrder = us::any_cast(parsedArgs["shOrder"]); switch (shOrder) { case 4: return StartShConversion<4>(argc, argv); case 6: return StartShConversion<6>(argc, argv); case 8: return StartShConversion<8>(argc, argv); case 10: return StartShConversion<10>(argc, argv); case 12: return StartShConversion<12>(argc, argv); } return EXIT_FAILURE; } diff --git a/Modules/DiffusionImaging/MiniApps/FiberDirectionExtraction.cpp b/Modules/DiffusionImaging/MiniApps/FiberDirectionExtraction.cpp index c50a85159d..85643a5636 100755 --- a/Modules/DiffusionImaging/MiniApps/FiberDirectionExtraction.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberDirectionExtraction.cpp @@ -1,174 +1,174 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fiber Direction Extraction"); parser.setCategory("Fiber Tracking and Processing Methods"); - parser.setDescription(""); + parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib/.trk)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask:", "mask image"); parser.addArgument("athresh", "a", mitkCommandLineParser::Float, "Angular threshold:", "angular threshold in degrees. closer fiber directions are regarded as one direction and clustered together.", 25, true); parser.addArgument("peakthresh", "t", mitkCommandLineParser::Float, "Peak size threshold:", "peak size threshold relative to largest peak in voxel", 0.2, true); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose:", "output optional and intermediate calculation results"); parser.addArgument("numdirs", "d", mitkCommandLineParser::Int, "Max. num. directions:", "maximum number of fibers per voxel", 3, true); parser.addArgument("normalize", "n", mitkCommandLineParser::Bool, "Normalize:", "normalize vectors"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string fibFile = us::any_cast(parsedArgs["input"]); string maskImage(""); if (parsedArgs.count("mask")) maskImage = us::any_cast(parsedArgs["mask"]); float peakThreshold = 0.2; if (parsedArgs.count("peakthresh")) peakThreshold = us::any_cast(parsedArgs["peakthresh"]); float angularThreshold = 25; if (parsedArgs.count("athresh")) angularThreshold = us::any_cast(parsedArgs["athresh"]); string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); int maxNumDirs = 3; if (parsedArgs.count("numdirs")) maxNumDirs = us::any_cast(parsedArgs["numdirs"]); bool normalize = false; if (parsedArgs.count("normalize")) normalize = us::any_cast(parsedArgs["normalize"]); try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; // load fiber bundle mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); // load/create mask image ItkUcharImgType::Pointer itkMaskImage = NULL; if (maskImage.compare("")!=0) { std::cout << "Using mask image"; itkMaskImage = ItkUcharImgType::New(); mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::LoadDataNode(maskImage)->GetData()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); } // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); fOdfFilter->SetNormalizeVectors(normalize); fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->SetSizeThreshold(peakThreshold); fOdfFilter->SetMaxNumDirections(maxNumDirs); fOdfFilter->Update(); ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); // write direction images for (unsigned int i=0; iSize(); i++) { itk::TractsToVectorImageFilter::ItkDirectionImageType::Pointer itkImg = directionImageContainer->GetElement(i); typedef itk::ImageFileWriter< itk::TractsToVectorImageFilter::ItkDirectionImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_DIRECTION_"); outfilename.append(boost::lexical_cast(i)); outfilename.append(".nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(itkImg); writer->Update(); } if (verbose) { // write vector field mitk::FiberBundleX::Pointer directions = fOdfFilter->GetOutputFiberBundle(); string outfilename = outRoot; outfilename.append("_VECTOR_FIELD.fib"); mitk::IOUtil::SaveBaseData(directions.GetPointer(), outfilename ); // write num direction image { ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_NUM_DIRECTIONS.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(numDirImage); writer->Update(); } } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp b/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp index b14e5a6b57..802a70f1e4 100755 --- a/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp @@ -1,156 +1,155 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int main(int argc, char* argv[]) { - std::cout << "FiberExtraction"; mitkCommandLineParser parser; parser.setTitle("Fiber Extraction"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setContributor("MBI"); - parser.setDescription(""); + parser.setDescription(" "); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::String, "Input:", "input tractogram (.fib/.trk)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::String, "Output:", "output tractogram", us::Any(), false); parser.addArgument("planfirgure1", "pf1", mitkCommandLineParser::String, "Figure 1:", "first ROI", us::Any(), false); parser.addArgument("planfirgure2", "pf2", mitkCommandLineParser::String, "Figure 2:", "second ROI", us::Any()); parser.addArgument("operation", "op", mitkCommandLineParser::String, "Operation:", "logical operation (AND, OR, NOT)", us::Any()); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFib = us::any_cast(parsedArgs["input"]); string outFib = us::any_cast(parsedArgs["out"]); string pf1_path = us::any_cast(parsedArgs["planfirgure1"]); string operation(""); string pf2_path(""); if (parsedArgs.count("operation")) { operation = us::any_cast(parsedArgs["operation"]); if (parsedArgs.count("planfirgure2") && (operation=="AND" || operation=="OR")) pf2_path = us::any_cast(parsedArgs["planfirgure2"]); } try { typedef itk::Image ItkUcharImgType; // load fiber bundle mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(inFib)->GetData()); mitk::FiberBundleX::Pointer result; mitk::BaseData::Pointer input1 = mitk::IOUtil::LoadDataNode(pf1_path)->GetData(); mitk::PlanarFigure::Pointer pf1 = dynamic_cast(input1.GetPointer()); if (pf1.IsNotNull()) { mitk::BaseData::Pointer input2; mitk::PlanarFigure::Pointer pf2; if (!pf2_path.empty()) { input2 = mitk::IOUtil::LoadDataNode(pf2_path)->GetData(); pf2 = dynamic_cast(input2.GetPointer()); } mitk::PlanarFigureComposite::Pointer pfc = mitk::PlanarFigureComposite::New(); if (operation.empty()) { result = inputTractogram->ExtractFiberSubset(input1); } else if (operation=="NOT") { pfc->setOperationType(mitk::PFCOMPOSITION_NOT_OPERATION); pfc->addPlanarFigure(input1); result = inputTractogram->ExtractFiberSubset(pfc); } else if (operation=="AND" && pf2.IsNotNull()) { pfc->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION); pfc->addPlanarFigure(input1); pfc->addPlanarFigure(input2); result = inputTractogram->ExtractFiberSubset(pfc); } else if (operation=="OR" && pf2.IsNotNull()) { pfc->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION); pfc->addPlanarFigure(input1); pfc->addPlanarFigure(input2); result = inputTractogram->ExtractFiberSubset(pfc); } else { std::cout << "Could not process input:"; std::cout << pf1_path; std::cout << pf2_path; std::cout << operation; } } else { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::LoadDataNode(pf1_path)->GetData()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); if (operation=="NOT") result = inputTractogram->ExtractFiberSubset(itkMaskImage, true, true); else result = inputTractogram->ExtractFiberSubset(itkMaskImage, true, false); } if (result.IsNotNull()) mitk::IOUtil::SaveBaseData(result, outFib); else std::cout << "No valid fiber bundle extracted."; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/FiberProcessing.cpp b/Modules/DiffusionImaging/MiniApps/FiberProcessing.cpp index b88d9012f9..3408851a97 100644 --- a/Modules/DiffusionImaging/MiniApps/FiberProcessing.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberProcessing.cpp @@ -1,207 +1,206 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include mitk::FiberBundleX::Pointer LoadFib(std::string filename) { const std::string s1="", s2=""; std::vector fibInfile = mitk::BaseDataIO::LoadBaseDataFromFile( filename, s1, s2, false ); if( fibInfile.empty() ) std::cout << "File " << filename << " could not be read!"; mitk::BaseData::Pointer baseData = fibInfile.at(0); return dynamic_cast(baseData.GetPointer()); } int main(int argc, char* argv[]) { - std::cout << "FiberProcessing"; mitkCommandLineParser parser; parser.setTitle("Fiber Processing"); parser.setCategory("Fiber Tracking and Processing Methods"); - parser.setDescription(""); + parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input fiber bundle (.fib)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output:", "output fiber bundle (.fib)", us::Any(), false); parser.addArgument("smooth", "s", mitkCommandLineParser::Float, "Spline resampling:", "Resample fiber using splines with the given point distance (in mm)"); parser.addArgument("compress", "c", mitkCommandLineParser::Float, "Compress:", "Compress fiber using the given error threshold (in mm)"); parser.addArgument("minLength", "l", mitkCommandLineParser::Float, "Minimum length:", "Minimum fiber length (in mm)"); parser.addArgument("maxLength", "m", mitkCommandLineParser::Float, "Maximum length:", "Maximum fiber length (in mm)"); parser.addArgument("minCurv", "a", mitkCommandLineParser::Float, "Minimum curvature radius:", "Minimum curvature radius (in mm)"); parser.addArgument("mirror", "p", mitkCommandLineParser::Int, "Invert coordinates:", "Invert fiber coordinates XYZ (e.g. 010 to invert y-coordinate of each fiber point)"); parser.addArgument("rotate-x", "rx", mitkCommandLineParser::Float, "Rotate x-axis:", "Rotate around x-axis (if copy is given the copy is rotated, in deg)"); parser.addArgument("rotate-y", "ry", mitkCommandLineParser::Float, "Rotate y-axis:", "Rotate around y-axis (if copy is given the copy is rotated, in deg)"); parser.addArgument("rotate-z", "rz", mitkCommandLineParser::Float, "Rotate z-axis:", "Rotate around z-axis (if copy is given the copy is rotated, in deg)"); parser.addArgument("scale-x", "sx", mitkCommandLineParser::Float, "Scale x-axis:", "Scale in direction of x-axis (if copy is given the copy is scaled)"); parser.addArgument("scale-y", "sy", mitkCommandLineParser::Float, "Scale y-axis:", "Scale in direction of y-axis (if copy is given the copy is scaled)"); parser.addArgument("scale-z", "sz", mitkCommandLineParser::Float, "Scale z-axis", "Scale in direction of z-axis (if copy is given the copy is scaled)"); parser.addArgument("translate-x", "tx", mitkCommandLineParser::Float, "Translate x-axis:", "Translate in direction of x-axis (if copy is given the copy is translated, in mm)"); parser.addArgument("translate-y", "ty", mitkCommandLineParser::Float, "Translate y-axis:", "Translate in direction of y-axis (if copy is given the copy is translated, in mm)"); parser.addArgument("translate-z", "tz", mitkCommandLineParser::Float, "Translate z-axis:", "Translate in direction of z-axis (if copy is given the copy is translated, in mm)"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; float smoothDist = -1; if (parsedArgs.count("smooth")) smoothDist = us::any_cast(parsedArgs["smooth"]); float compress = -1; if (parsedArgs.count("compress")) compress = us::any_cast(parsedArgs["compress"]); float minFiberLength = -1; if (parsedArgs.count("minLength")) minFiberLength = us::any_cast(parsedArgs["minLength"]); float maxFiberLength = -1; if (parsedArgs.count("maxLength")) maxFiberLength = us::any_cast(parsedArgs["maxLength"]); float curvThres = -1; if (parsedArgs.count("minCurv")) curvThres = us::any_cast(parsedArgs["minCurv"]); int axis = 0; if (parsedArgs.count("mirror")) axis = us::any_cast(parsedArgs["mirror"]); float rotateX = 0; if (parsedArgs.count("rotate-x")) rotateX = us::any_cast(parsedArgs["rotate-x"]); float rotateY = 0; if (parsedArgs.count("rotate-y")) rotateY = us::any_cast(parsedArgs["rotate-y"]); float rotateZ = 0; if (parsedArgs.count("rotate-z")) rotateZ = us::any_cast(parsedArgs["rotate-z"]); float scaleX = 0; if (parsedArgs.count("scale-x")) scaleX = us::any_cast(parsedArgs["scale-x"]); float scaleY = 0; if (parsedArgs.count("scale-y")) scaleY = us::any_cast(parsedArgs["scale-y"]); float scaleZ = 0; if (parsedArgs.count("scale-z")) scaleZ = us::any_cast(parsedArgs["scale-z"]); float translateX = 0; if (parsedArgs.count("translate-x")) translateX = us::any_cast(parsedArgs["translate-x"]); float translateY = 0; if (parsedArgs.count("translate-y")) translateY = us::any_cast(parsedArgs["translate-y"]); float translateZ = 0; if (parsedArgs.count("translate-z")) translateZ = us::any_cast(parsedArgs["translate-z"]); string inFileName = us::any_cast(parsedArgs["input"]); string outFileName = us::any_cast(parsedArgs["outFile"]); try { mitk::FiberBundleX::Pointer fib = LoadFib(inFileName); if (minFiberLength>0) fib->RemoveShortFibers(minFiberLength); if (maxFiberLength>0) fib->RemoveLongFibers(maxFiberLength); if (curvThres>0) fib->ApplyCurvatureThreshold(curvThres, false); if (smoothDist>0) fib->ResampleSpline(smoothDist); if (compress>0) fib->Compress(compress); if (axis/100==1) fib->MirrorFibers(0); if ((axis%100)/10==1) fib->MirrorFibers(1); if (axis%10==1) fib->MirrorFibers(2); if (rotateX > 0 || rotateY > 0 || rotateZ > 0){ std::cout << "Rotate " << rotateX << " " << rotateY << " " << rotateZ; fib->RotateAroundAxis(rotateX, rotateY, rotateZ); } if (translateX > 0 || translateY > 0 || translateZ > 0){ fib->TranslateFibers(translateX, translateY, translateZ); } if (scaleX > 0 || scaleY > 0 || scaleZ > 0) fib->ScaleFibers(scaleX, scaleY, scaleZ); mitk::IOUtil::SaveBaseData(fib.GetPointer(), outFileName ); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/Fiberfox.cpp b/Modules/DiffusionImaging/MiniApps/Fiberfox.cpp index 324fecfba2..07f78f9e38 100755 --- a/Modules/DiffusionImaging/MiniApps/Fiberfox.cpp +++ b/Modules/DiffusionImaging/MiniApps/Fiberfox.cpp @@ -1,80 +1,84 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include "boost/property_tree/ptree.hpp" #include "boost/property_tree/xml_parser.hpp" #include "boost/foreach.hpp" /** TODO: Proritype signal komplett speichern oder bild mit speichern. */ /** TODO: Tarball aus images und parametern? */ /** TODO: Artefakte auf bild in miniapp */ using namespace mitk; int main(int argc, char* argv[]) { mitkCommandLineParser parser; + parser.setTitle("FiberFox"); + parser.setCategory("Fiber Tracking and Processing Methods"); + parser.setContributor("MBI"); + parser.setDescription(" "); parser.setArgumentPrefix("--", "-"); parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output root:", "output root", us::Any(), false); parser.addArgument("parameters", "p", mitkCommandLineParser::InputFile, "Parameter file:", "fiberfox parameter file", us::Any(), false); parser.addArgument("fiberbundle", "f", mitkCommandLineParser::String, "Fiberbundle:", "", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string outName = us::any_cast(parsedArgs["out"]); string paramName = us::any_cast(parsedArgs["parameters"]); string fibFile = ""; if (parsedArgs.count("fiberbundle")) fibFile = us::any_cast(parsedArgs["fiberbundle"]); { FiberfoxParameters parameters; parameters.LoadParameters(paramName); mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); tractsToDwiFilter->SetParameters(parameters); tractsToDwiFilter->SetFiberBundle(inputTractogram); tractsToDwiFilter->Update(); mitk::Image::Pointer image = mitk::GrabItkImageMemory( tractsToDwiFilter->GetOutput() ); image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( parameters.m_SignalGen.GetGradientDirections() ) ); image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( parameters.m_SignalGen.m_Bvalue ) ); mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); mitk::IOUtil::Save(image, outName.c_str()); } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/mitkFileFormatConverter.cpp b/Modules/DiffusionImaging/MiniApps/FileFormatConverter.cpp old mode 100755 new mode 100644 similarity index 100% rename from Modules/DiffusionImaging/MiniApps/mitkFileFormatConverter.cpp rename to Modules/DiffusionImaging/MiniApps/FileFormatConverter.cpp diff --git a/Modules/DiffusionImaging/MiniApps/GibbsTracking.cpp b/Modules/DiffusionImaging/MiniApps/GibbsTracking.cpp index 21f316dd0d..d980327a74 100755 --- a/Modules/DiffusionImaging/MiniApps/GibbsTracking.cpp +++ b/Modules/DiffusionImaging/MiniApps/GibbsTracking.cpp @@ -1,242 +1,241 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include template typename itk::ShCoefficientImageImporter< float, shOrder >::QballImageType::Pointer TemplatedConvertShCoeffs(mitk::Image* mitkImg, int toolkit, bool noFlip = false) { typedef itk::ShCoefficientImageImporter< float, shOrder > FilterType; typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImg); caster->Update(); itk::Image< float, 4 >::Pointer itkImage = caster->GetOutput(); typename FilterType::Pointer filter = FilterType::New(); if (noFlip) { filter->SetInputImage(itkImage); } else { std::cout << "Flipping image"; itk::FixedArray flipAxes; flipAxes[0] = true; flipAxes[1] = true; flipAxes[2] = false; flipAxes[3] = false; itk::FlipImageFilter< itk::Image< float, 4 > >::Pointer flipper = itk::FlipImageFilter< itk::Image< float, 4 > >::New(); flipper->SetInput(itkImage); flipper->SetFlipAxes(flipAxes); flipper->Update(); itk::Image< float, 4 >::Pointer flipped = flipper->GetOutput(); itk::Matrix< double,4,4 > m = itkImage->GetDirection(); m[0][0] *= -1; m[1][1] *= -1; flipped->SetDirection(m); itk::Point< float, 4 > o = itkImage->GetOrigin(); o[0] -= (flipped->GetLargestPossibleRegion().GetSize(0)-1); o[1] -= (flipped->GetLargestPossibleRegion().GetSize(1)-1); flipped->SetOrigin(o); filter->SetInputImage(flipped); } switch (toolkit) { case 0: filter->SetToolkit(FilterType::FSL); break; case 1: filter->SetToolkit(FilterType::MRTRIX); break; default: filter->SetToolkit(FilterType::FSL); } filter->GenerateData(); return filter->GetQballImage(); } int main(int argc, char* argv[]) { - std::cout << "GibbsTracking"; mitkCommandLineParser parser; parser.setTitle("Gibbs Tracking"); parser.setCategory("Fiber Tracking and Processing Methods"); - parser.setDescription(""); + parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input image (tensor, Q-ball or FSL/MRTrix SH-coefficient image)", us::Any(), false); parser.addArgument("parameters", "p", mitkCommandLineParser::InputFile, "Parameters:", "parameter file (.gtp)", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask:", "binary mask image"); parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "SH coefficient:", "sh coefficient convention (FSL, MRtrix)", string("FSL"), true); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output:", "output fiber bundle (.fib)", us::Any(), false); parser.addArgument("noFlip", "f", mitkCommandLineParser::Bool, "No flip:", "do not flip input image to match MITK coordinate convention"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFileName = us::any_cast(parsedArgs["input"]); string paramFileName = us::any_cast(parsedArgs["parameters"]); string outFileName = us::any_cast(parsedArgs["outFile"]); bool noFlip = false; if (parsedArgs.count("noFlip")) noFlip = us::any_cast(parsedArgs["noFlip"]); try { // instantiate gibbs tracker typedef itk::Vector OdfVectorType; typedef itk::Image ItkQballImageType; typedef itk::GibbsTrackingFilter GibbsTrackingFilterType; GibbsTrackingFilterType::Pointer gibbsTracker = GibbsTrackingFilterType::New(); // load input image const std::string s1="", s2=""; std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( inFileName, s1, s2, false ); mitk::Image::Pointer mitkImage = dynamic_cast(infile.at(0).GetPointer()); // try to cast to qball image if( boost::algorithm::ends_with(inFileName, ".qbi") ) { std::cout << "Loading qball image ..."; mitk::QBallImage::Pointer mitkQballImage = dynamic_cast(infile.at(0).GetPointer()); ItkQballImageType::Pointer itk_qbi = ItkQballImageType::New(); mitk::CastToItkImage(mitkQballImage, itk_qbi); gibbsTracker->SetQBallImage(itk_qbi.GetPointer()); } else if( boost::algorithm::ends_with(inFileName, ".dti") ) { std::cout << "Loading tensor image ..."; typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(infile.at(0).GetPointer()); ItkTensorImage::Pointer itk_dti = ItkTensorImage::New(); mitk::CastToItkImage(mitkTensorImage, itk_dti); gibbsTracker->SetTensorImage(itk_dti); } else if ( boost::algorithm::ends_with(inFileName, ".nii") ) { std::cout << "Loading sh-coefficient image ..."; int nrCoeffs = mitkImage->GetLargestPossibleRegion().GetSize()[3]; int c=3, d=2-2*nrCoeffs; double D = c*c-4*d; int shOrder; if (D>0) { shOrder = (-c+sqrt(D))/2.0; if (shOrder<0) shOrder = (-c-sqrt(D))/2.0; } else if (D==0) shOrder = -c/2.0; std::cout << "using SH-order " << shOrder; int toolkitConvention = 0; if (parsedArgs.count("shConvention")) { string convention = us::any_cast(parsedArgs["shConvention"]).c_str(); if ( boost::algorithm::equals(convention, "MRtrix") ) { toolkitConvention = 1; std::cout << "Using MRtrix style sh-coefficient convention"; } else std::cout << "Using FSL style sh-coefficient convention"; } else std::cout << "Using FSL style sh-coefficient convention"; switch (shOrder) { case 4: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<4>(mitkImage, toolkitConvention, noFlip)); break; case 6: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<6>(mitkImage, toolkitConvention, noFlip)); break; case 8: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<8>(mitkImage, toolkitConvention, noFlip)); break; case 10: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<10>(mitkImage, toolkitConvention, noFlip)); break; case 12: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<12>(mitkImage, toolkitConvention, noFlip)); break; default: std::cout << "SH-order " << shOrder << " not supported"; } } else return EXIT_FAILURE; // global tracking if (parsedArgs.count("mask")) { typedef itk::Image MaskImgType; mitk::Image::Pointer mitkMaskImage = mitk::IOUtil::LoadImage(us::any_cast(parsedArgs["mask"])); MaskImgType::Pointer itk_mask = MaskImgType::New(); mitk::CastToItkImage(mitkMaskImage, itk_mask); gibbsTracker->SetMaskImage(itk_mask); } gibbsTracker->SetDuplicateImage(false); gibbsTracker->SetLoadParameterFile( paramFileName ); // gibbsTracker->SetLutPath( "" ); gibbsTracker->Update(); mitk::FiberBundleX::Pointer mitkFiberBundle = mitk::FiberBundleX::New(gibbsTracker->GetFiberBundle()); mitkFiberBundle->SetReferenceGeometry(mitkImage->GetGeometry()); mitk::IOUtil::SaveBaseData(mitkFiberBundle.GetPointer(), outFileName ); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp b/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp index a05ce2419b..c7058badc0 100644 --- a/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp +++ b/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp @@ -1,314 +1,314 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include // ITK #include #include #include "itkLinearInterpolateImageFunction.h" #include "itkWindowedSincInterpolateImageFunction.h" #include "itkIdentityTransform.h" #include "itkResampleImageFilter.h" #include "itkResampleDwiImageFilter.h" typedef itk::Image InputImageType; static mitk::Image::Pointer TransformToReference(mitk::Image *reference, mitk::Image *moving, bool sincInterpol = false) { // Convert to itk Images InputImageType::Pointer itkReference = InputImageType::New(); InputImageType::Pointer itkMoving = InputImageType::New(); mitk::CastToItkImage(reference,itkReference); mitk::CastToItkImage(moving,itkMoving); // Identify Transform typedef itk::IdentityTransform T_Transform; T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 3> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typedef itk::ResampleImageFilter ResampleFilterType; ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(itkMoving); resampler->SetReferenceImage( itkReference ); resampler->UseReferenceImageOn(); resampler->SetTransform(_pTransform); resampler->SetInterpolator(sinc_interpolator); resampler->Update(); // Convert back to mitk mitk::Image::Pointer result = mitk::Image::New(); result->InitializeByItk(resampler->GetOutput()); GrabItkImageMemory( resampler->GetOutput() , result ); return result; } static std::vector &split(const std::string &s, char delim, std::vector &elems) { std::stringstream ss(s); std::string item; while (std::getline(ss, item, delim)) { elems.push_back(item); } return elems; } static std::vector split(const std::string &s, char delim) { std::vector < std::string > elems; return split(s, delim, elems); } static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing, bool useLinInt = true) { InputImageType::Pointer itkImage = InputImageType::New(); CastToItkImage(input,itkImage); /** * 1) Resampling * */ // Identity transform. // We don't want any transform on our image except rescaling which is not // specified by a transform but by the input/output spacing as we will see // later. // So no transform will be specified. typedef itk::IdentityTransform T_Transform; // The resampler type itself. typedef itk::ResampleImageFilter T_ResampleFilter; // Prepare the resampler. // Instantiate the transform and specify it should be the id transform. T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); // Instantiate the resampler. Wire in the transform and the interpolator. T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New(); // Specify the input. _pResizeFilter->SetInput(itkImage); _pResizeFilter->SetTransform(_pTransform); // Set the output origin. _pResizeFilter->SetOutputOrigin(itkImage->GetOrigin()); // Compute the size of the output. // The size (# of pixels) in the output is recomputed using // the ratio of the input and output sizes. InputImageType::SpacingType inputSpacing = itkImage->GetSpacing(); InputImageType::SpacingType outputSpacing; const InputImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion(); InputImageType::SizeType outputSize; typedef InputImageType::SizeType::SizeValueType SizeValueType; // Set the output spacing. outputSpacing[0] = spacing[0]; outputSpacing[1] = spacing[1]; outputSpacing[2] = spacing[2]; outputSize[0] = static_cast(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5); outputSize[1] = static_cast(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5); outputSize[2] = static_cast(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5); _pResizeFilter->SetOutputSpacing(outputSpacing); _pResizeFilter->SetSize(outputSize); typedef itk::LinearInterpolateImageFunction< InputImageType > LinearInterpolatorType; LinearInterpolatorType::Pointer lin_interpolator = LinearInterpolatorType::New(); typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 4> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); if (useLinInt) _pResizeFilter->SetInterpolator(lin_interpolator); else _pResizeFilter->SetInterpolator(sinc_interpolator); _pResizeFilter->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(_pResizeFilter->GetOutput()); mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image); return image; } /// Save images according to file type static void SaveImage(std::string fileName, mitk::Image* image, std::string fileType ) { std::cout << "----Save to " << fileName; mitk::IOUtil::Save(image, fileName); } mitk::Image::Pointer ResampleDWIbySpacing(mitk::Image::Pointer input, float* spacing, bool useLinInt = true) { itk::Vector spacingVector; spacingVector[0] = spacing[0]; spacingVector[1] = spacing[1]; spacingVector[2] = spacing[2]; typedef itk::ResampleDwiImageFilter ResampleFilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(input, itkVectorImagePointer); ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput( itkVectorImagePointer ); resampler->SetInterpolation(ResampleFilterType::Interpolate_Linear); resampler->SetNewSpacing(spacingVector); resampler->Update(); mitk::Image::Pointer output = mitk::GrabItkImageMemory( resampler->GetOutput() ); output->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer(input) ) ); output->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( mitk::DiffusionPropertyHelper::GetReferenceBValue(input) ) ); mitk::DiffusionPropertyHelper propertyHelper( output ); propertyHelper.InitializeImage(); return output; } int main( int argc, char* argv[] ) { mitkCommandLineParser parser; parser.setArgumentPrefix("--","-"); parser.setTitle("Image Resampler"); parser.setCategory("Preprocessing Tools"); parser.setContributor("MBI"); parser.setDescription("Resample an image to eigther a specific spacing or to a reference image."); // Add command line argument names parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Show this help text"); parser.addArgument("input", "i", mitkCommandLineParser::InputImage, "Input:", "Input file",us::Any(),false); - parser.addArgument("output", "o", mitkCommandLineParser::OutputDirectory, "Output:", "Output folder (ending with /)",us::Any(),false); + parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output:", "Output file",us::Any(),false); parser.addArgument("spacing", "s", mitkCommandLineParser::String, "Spacing:", "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any()); - parser.addArgument("reference", "r", mitkCommandLineParser::String, "Reference:", "Resample using supplied reference image. Also cuts image to same dimensions",us::Any()); + parser.addArgument("reference", "r", mitkCommandLineParser::InputImage, "Reference:", "Resample using supplied reference image. Also cuts image to same dimensions",us::Any()); parser.addArgument("win-sinc", "w", mitkCommandLineParser::Bool, "Windowed-sinc interpolation:", "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any()); map parsedArgs = parser.parseArguments(argc, argv); // Handle special arguments bool useSpacing = false; bool useLinearInterpol = true; { if (parsedArgs.size() == 0) { return EXIT_FAILURE; } if (parsedArgs.count("sinc-int")) useLinearInterpol = false; // Show a help message if ( parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } - } + } - std::string outputPath = us::any_cast(parsedArgs["output"]); + std::string outputFile = us::any_cast(parsedArgs["output"]); std::string inputFile = us::any_cast(parsedArgs["input"]); std::vector spacings; float spacing[3]; if (parsedArgs.count("spacing")) { + std::string arg = us::any_cast(parsedArgs["spacing"]); - spacings = split(arg ,','); - spacing[0] = atoi(spacings.at(0).c_str()); - spacing[1] = atoi(spacings.at(1).c_str()); - spacing[2] = atoi(spacings.at(2).c_str()); - useSpacing = true; + if (arg != "") + { + spacings = split(arg ,','); + spacing[0] = atoi(spacings.at(0).c_str()); + spacing[1] = atoi(spacings.at(1).c_str()); + spacing[2] = atoi(spacings.at(2).c_str()); + useSpacing = true; + } } std::string refImageFile = ""; if (parsedArgs.count("reference")) { refImageFile = us::any_cast(parsedArgs["reference"]); } if (refImageFile =="" && useSpacing == false) { MITK_ERROR << "No information how to resample is supplied. Use eigther --spacing or --reference !"; return EXIT_FAILURE; } mitk::Image::Pointer refImage; if (!useSpacing) - refImage = mitk::IOUtil::LoadImage(refImageFile); + refImage = mitk::IOUtil::LoadImage(refImageFile); mitk::Image::Pointer inputDWI = dynamic_cast(mitk::IOUtil::LoadBaseData(inputFile).GetPointer()); if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(inputDWI)) { mitk::Image::Pointer outputImage; if (useSpacing) outputImage = ResampleDWIbySpacing(inputDWI, spacing); else { MITK_WARN << "Not supported yet, to resample a DWI please set a new spacing."; return EXIT_FAILURE; } - std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(inputFile); - - std::string outName(outputPath + fileStem + "_res.dwi"); - mitk::IOUtil::Save(outputImage, outName.c_str()); + mitk::IOUtil::Save(outputImage, outputFile.c_str()); return EXIT_SUCCESS; } mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(inputFile); mitk::Image::Pointer resultImage; if (useSpacing) resultImage = ResampleBySpacing(inputImage,spacing); else resultImage = TransformToReference(refImage,inputImage); - std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(inputFile); - mitk::IOUtil::SaveImage(resultImage, outputPath + fileStem + "_res.nrrd"); + mitk::IOUtil::SaveImage(resultImage, outputFile); return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/LocalDirectionalFiberPlausibility.cpp b/Modules/DiffusionImaging/MiniApps/LocalDirectionalFiberPlausibility.cpp index c73052c411..0b58518ab5 100755 --- a/Modules/DiffusionImaging/MiniApps/LocalDirectionalFiberPlausibility.cpp +++ b/Modules/DiffusionImaging/MiniApps/LocalDirectionalFiberPlausibility.cpp @@ -1,302 +1,301 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int main(int argc, char* argv[]) { - std::cout << "LocalDirectionalFiberPlausibility"; mitkCommandLineParser parser; parser.setTitle("Local Directional Fiber Plausibility"); parser.setCategory("Fiber Tracking and Processing Methods"); - parser.setDescription(""); + parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("reference", "r", mitkCommandLineParser::StringList, "Reference images:", "reference direction images", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::StringList, "Masks:", "mask images"); parser.addArgument("athresh", "a", mitkCommandLineParser::Float, "Angular threshold:", "angular threshold in degrees. closer fiber directions are regarded as one direction and clustered together.", 25, true); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose:", "output optional and intermediate calculation results"); parser.addArgument("ignore", "n", mitkCommandLineParser::Bool, "Ignore:", "don't increase error for missing or too many directions"); parser.addArgument("fileID", "id", mitkCommandLineParser::String, "ID:", "optional ID field"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType referenceImages = us::any_cast(parsedArgs["reference"]); mitkCommandLineParser::StringContainerType maskImages; if (parsedArgs.count("mask")) maskImages = us::any_cast(parsedArgs["mask"]); string fibFile = us::any_cast(parsedArgs["input"]); float angularThreshold = 25; if (parsedArgs.count("athresh")) angularThreshold = us::any_cast(parsedArgs["athresh"]); string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); bool ignore = false; if (parsedArgs.count("ignore")) ignore = us::any_cast(parsedArgs["ignore"]); string fileID = ""; if (parsedArgs.count("fileID")) fileID = us::any_cast(parsedArgs["fileID"]); try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; // load fiber bundle mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::LoadDataNode(referenceImages.at(i))->GetData()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ std::cout << "could not load: " << referenceImages.at(i); } } ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); itkMaskImage->SetSpacing( dirImg->GetSpacing() ); itkMaskImage->SetOrigin( dirImg->GetOrigin() ); itkMaskImage->SetDirection( dirImg->GetDirection() ); itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->Allocate(); itkMaskImage->FillBuffer(1); // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); fOdfFilter->SetNormalizeVectors(true); fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->Update(); ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); if (verbose) { // write vector field mitk::FiberBundleX::Pointer directions = fOdfFilter->GetOutputFiberBundle(); string outfilename = outRoot; outfilename.append("_VECTOR_FIELD.fib"); mitk::IOUtil::SaveBaseData(directions.GetPointer(), outfilename ); // write direction images for (unsigned int i=0; iSize(); i++) { itk::TractsToVectorImageFilter::ItkDirectionImageType::Pointer itkImg = directionImageContainer->GetElement(i); typedef itk::ImageFileWriter< itk::TractsToVectorImageFilter::ItkDirectionImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_DIRECTION_"); outfilename.append(boost::lexical_cast(i)); outfilename.append(".nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(itkImg); writer->Update(); } // write num direction image { ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_NUM_DIRECTIONS.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(numDirImage); writer->Update(); } } string logFile = outRoot; logFile.append("_ANGULAR_ERROR.csv"); ofstream file; file.open (logFile.c_str()); if (maskImages.size()>0) { for (unsigned int i=0; i(mitk::IOUtil::LoadDataNode(maskImages.at(i))->GetData()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); // evaluate directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(ignore); evaluationFilter->Update(); if (verbose) { EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_ERROR_IMAGE.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(angularErrorImage); writer->Update(); } string maskFileName = itksys::SystemTools::GetFilenameWithoutExtension(maskImages.at(i)); unsigned found = maskFileName.find_last_of("_"); string sens = itksys::SystemTools::GetFilenameWithoutLastExtension(fibFile); if (!fileID.empty()) sens = fileID; sens.append(","); sens.append(maskFileName.substr(found+1)); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); sens.append(","); sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); sens.append(";\n"); file << sens; } } else { // evaluate directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(ignore); evaluationFilter->Update(); if (verbose) { EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_ERROR_IMAGE.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(angularErrorImage); writer->Update(); } string sens = itksys::SystemTools::GetFilenameWithoutLastExtension(fibFile); if (!fileID.empty()) sens = fileID; sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); sens.append(","); sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); sens.append(";\n"); file << sens; } file.close(); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/NetworkCreation.cpp b/Modules/DiffusionImaging/MiniApps/NetworkCreation.cpp index 08c92ab5c0..0641920173 100644 --- a/Modules/DiffusionImaging/MiniApps/NetworkCreation.cpp +++ b/Modules/DiffusionImaging/MiniApps/NetworkCreation.cpp @@ -1,133 +1,139 @@ /*=================================================================== 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. ===================================================================*/ // std includes #include // CTK includes #include "mitkCommandLineParser.h" // MITK includes #include #include "mitkConnectomicsNetworkCreator.h" #include #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; + + parser.setTitle("Network Creation"); + parser.setCategory("Connectomics"); + parser.setDescription(""); + parser.setContributor("MBI"); + parser.setArgumentPrefix("--", "-"); parser.addArgument("fiberImage", "f", mitkCommandLineParser::InputFile, "Input image", "input fiber image (.fib)", us::Any(), false); parser.addArgument("parcellation", "p", mitkCommandLineParser::InputFile, "Parcellation image", "parcellation image", us::Any(), false); parser.addArgument("outputNetwork", "o", mitkCommandLineParser::String, "Output network", "where to save the output (.cnf)", us::Any(), false); parser.addArgument("radius", "r", mitkCommandLineParser::Int, "Radius", "Search radius in mm", 15, true); parser.addArgument("noCenterOfMass", "com", mitkCommandLineParser::Bool, "No center of mass", "Do not use center of mass for node positions"); parser.setCategory("Connectomics"); parser.setTitle("Network Creation"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; //default values int searchRadius( 15 ); bool noCenterOfMass( false ); // parse command line arguments std::string fiberFilename = us::any_cast(parsedArgs["fiberImage"]); std::string parcellationFilename = us::any_cast(parsedArgs["parcellation"]); std::string outputFilename = us::any_cast(parsedArgs["outputNetwork"]); if (parsedArgs.count("radius")) searchRadius = us::any_cast(parsedArgs["radius"]); if (parsedArgs.count("noCenterOfMass")) noCenterOfMass = us::any_cast(parsedArgs["noCenterOfMass"]); try { const std::string s1="", s2=""; // load fiber image std::vector fiberInfile = mitk::BaseDataIO::LoadBaseDataFromFile( fiberFilename, s1, s2, false ); if( fiberInfile.empty() ) { std::string errorMessage = "Fiber Image at " + fiberFilename + " could not be read. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } mitk::BaseData* fiberBaseData = fiberInfile.at(0); mitk::FiberBundleX* fiberBundle = dynamic_cast( fiberBaseData ); // load parcellation std::vector parcellationInFile = mitk::BaseDataIO::LoadBaseDataFromFile( parcellationFilename, s1, s2, false ); if( parcellationInFile.empty() ) { std::string errorMessage = "Parcellation at " + parcellationFilename + " could not be read. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } mitk::BaseData* parcellationBaseData = parcellationInFile.at(0); mitk::Image* parcellationImage = dynamic_cast( parcellationBaseData ); // do creation mitk::ConnectomicsNetworkCreator::Pointer connectomicsNetworkCreator = mitk::ConnectomicsNetworkCreator::New(); connectomicsNetworkCreator->SetSegmentation( parcellationImage ); connectomicsNetworkCreator->SetFiberBundle( fiberBundle ); if( !noCenterOfMass ) { connectomicsNetworkCreator->CalculateCenterOfMass(); } connectomicsNetworkCreator->SetEndPointSearchRadius( searchRadius ); connectomicsNetworkCreator->CreateNetworkFromFibersAndSegmentation(); mitk::ConnectomicsNetwork::Pointer network = connectomicsNetworkCreator->GetNetwork(); std::cout << "searching writer"; mitk::IOUtil::SaveBaseData(network.GetPointer(), outputFilename ); return EXIT_SUCCESS; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } std::cout << "DONE"; return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/NetworkStatistics.cpp b/Modules/DiffusionImaging/MiniApps/NetworkStatistics.cpp index 2d124f8659..35065cf252 100644 --- a/Modules/DiffusionImaging/MiniApps/NetworkStatistics.cpp +++ b/Modules/DiffusionImaging/MiniApps/NetworkStatistics.cpp @@ -1,516 +1,522 @@ /*=================================================================== 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. ===================================================================*/ // std includes #include #include #include #include #include #include // boost includes #include // ITK includes #include // CTK includes #include "mitkCommandLineParser.h" // MITK includes #include #include #include #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; + + parser.setTitle("Network Creation"); + parser.setCategory("Connectomics"); + parser.setDescription(""); + parser.setContributor("MBI"); + parser.setArgumentPrefix("--", "-"); parser.addArgument("inputNetwork", "i", mitkCommandLineParser::InputFile, "Input network", "input connectomics network (.cnf)", us::Any(), false); parser.addArgument("outputFile", "o", mitkCommandLineParser::OutputFile, "Output file", "name of output file", us::Any(), false); parser.addArgument("noGlobalStatistics", "g", mitkCommandLineParser::Bool, "No global statistics", "Do not calculate global statistics"); parser.addArgument("createConnectivityMatriximage", "I", mitkCommandLineParser::Bool, "Write connectivity matrix image", "Write connectivity matrix image"); parser.addArgument("binaryConnectivity", "b", mitkCommandLineParser::Bool, "Binary connectivity", "Whether to create a binary connectivity matrix"); parser.addArgument("rescaleConnectivity", "r", mitkCommandLineParser::Bool, "Rescale connectivity", "Whether to rescale the connectivity matrix"); parser.addArgument("localStatistics", "L", mitkCommandLineParser::StringList, "Local statistics", "Provide a list of node labels for local statistics", us::Any()); parser.addArgument("regionList", "R", mitkCommandLineParser::StringList, "Region list", "A space separated list of regions. Each region has the format\n regionname;label1;label2;...;labelN", us::Any()); - parser.addArgument("granularity", "gr", mitkCommandLineParser::Int, "Granularity", "How finely to test the density range and how many thresholds to consider"); - parser.addArgument("startDensity", "d", mitkCommandLineParser::Float, "Start Density", "Largest density for the range"); - parser.addArgument("thresholdStepSize", "t", mitkCommandLineParser::Int, "Step size threshold", "Distance of two adjacent thresholds"); + parser.addArgument("granularity", "gr", mitkCommandLineParser::Int, "Granularity", "How finely to test the density range and how many thresholds to consider",1); + parser.addArgument("startDensity", "d", mitkCommandLineParser::Float, "Start Density", "Largest density for the range",1.0); + parser.addArgument("thresholdStepSize", "t", mitkCommandLineParser::Int, "Step size threshold", "Distance of two adjacent thresholds",3); parser.setCategory("Connectomics"); parser.setTitle("Network Statistics"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; //default values bool noGlobalStatistics( false ); bool binaryConnectivity( false ); bool rescaleConnectivity( false ); bool createConnectivityMatriximage( false ); int granularity( 1 ); double startDensity( 1.0 ); int thresholdStepSize( 3 ); // parse command line arguments std::string networkName = us::any_cast(parsedArgs["inputNetwork"]); std::string outName = us::any_cast(parsedArgs["outputFile"]); mitkCommandLineParser::StringContainerType localLabels; if(parsedArgs.count("localStatistics")) { localLabels = us::any_cast(parsedArgs["localStatistics"]); } mitkCommandLineParser::StringContainerType unparsedRegions; std::map< std::string, std::vector > parsedRegions; std::map< std::string, std::vector >::iterator parsedRegionsIterator; if(parsedArgs.count("regionList")) { unparsedRegions = us::any_cast(parsedArgs["regionList"]); for(unsigned int index(0); index < unparsedRegions.size(); index++ ) { std::vector< std::string > tempRegionVector; boost::split(tempRegionVector, unparsedRegions.at(index), boost::is_any_of(";")); std::vector< std::string >::const_iterator begin = tempRegionVector.begin(); std::vector< std::string >::const_iterator last = tempRegionVector.begin() + tempRegionVector.size(); std::vector< std::string > insertRegionVector(begin + 1, last); if( parsedRegions.count( tempRegionVector.at(0) ) == 0 ) { parsedRegions.insert( std::pair< std::string, std::vector >( tempRegionVector.at(0), insertRegionVector) ); } else { MITK_ERROR << "Region already exists. Skipping second occurrence."; } } } if (parsedArgs.count("noGlobalStatistics")) noGlobalStatistics = us::any_cast(parsedArgs["noGlobalStatistics"]); if (parsedArgs.count("binaryConnectivity")) binaryConnectivity = us::any_cast(parsedArgs["binaryConnectivity"]); if (parsedArgs.count("rescaleConnectivity")) rescaleConnectivity = us::any_cast(parsedArgs["rescaleConnectivity"]); if (parsedArgs.count("createConnectivityMatriximage")) createConnectivityMatriximage = us::any_cast(parsedArgs["createConnectivityMatriximage"]); if (parsedArgs.count("granularity")) granularity = us::any_cast(parsedArgs["granularity"]); if (parsedArgs.count("startDensity")) startDensity = us::any_cast(parsedArgs["startDensity"]); if (parsedArgs.count("thresholdStepSize")) thresholdStepSize = us::any_cast(parsedArgs["thresholdStepSize"]); try { const std::string s1="", s2=""; // load network std::vector networkFile = mitk::BaseDataIO::LoadBaseDataFromFile( networkName, s1, s2, false ); if( networkFile.empty() ) { std::string errorMessage = "File at " + networkName + " could not be read. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } mitk::BaseData* networkBaseData = networkFile.at(0); mitk::ConnectomicsNetwork* network = dynamic_cast( networkBaseData ); if( !network ) { std::string errorMessage = "Read file at " + networkName + " could not be recognized as network. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } // streams std::stringstream globalHeaderStream; globalHeaderStream << "NumberOfVertices " << "NumberOfEdges " << "AverageDegree " << "ConnectionDensity " << "NumberOfConnectedComponents " << "AverageComponentSize " << "LargestComponentSize " << "RatioOfNodesInLargestComponent " << "HopPlotExponent " << "EffectiveHopDiameter " << "AverageClusteringCoefficientsC " << "AverageClusteringCoefficientsD " << "AverageClusteringCoefficientsE " << "AverageVertexBetweennessCentrality " << "AverageEdgeBetweennessCentrality " << "NumberOfIsolatedPoints " << "RatioOfIsolatedPoints " << "NumberOfEndPoints " << "RatioOfEndPoints " << "Diameter " << "Diameter90 " << "Radius " << "Radius90 " << "AverageEccentricity " << "AverageEccentricity90 " << "AveragePathLength " << "NumberOfCentralPoints " << "RatioOfCentralPoints " << "SpectralRadius " << "SecondLargestEigenValue " << "AdjacencyTrace " << "AdjacencyEnergy " << "LaplacianTrace " << "LaplacianEnergy " << "LaplacianSpectralGap " << "NormalizedLaplacianTrace " << "NormalizedLaplacianEnergy " << "NormalizedLaplacianNumberOf2s " << "NormalizedLaplacianNumberOf1s " << "NormalizedLaplacianNumberOf0s " << "NormalizedLaplacianLowerSlope " << "NormalizedLaplacianUpperSlope " << "SmallWorldness" << std::endl; std::stringstream localHeaderStream; std::stringstream regionalHeaderStream; std::stringstream globalDataStream; std::stringstream localDataStream; std::stringstream regionalDataStream; std::string globalOutName = outName + "_global.txt"; std::string localOutName = outName + "_local.txt"; std::string regionalOutName = outName + "_regional.txt"; bool firstRun( true ); // iterate over all three possible methods for(unsigned int method( 0 ); method < 3; method++) { // 0 - Random removal threshold // 1 - Largest density below threshold // 2 - Threshold based // iterate over possible targets for( unsigned int step( 0 ); step < granularity; step++ ) { double targetValue( 0.0 ); bool newStep( true ); switch ( method ) { case mitk::ConnectomicsNetworkThresholder::RandomRemovalOfWeakest : case mitk::ConnectomicsNetworkThresholder::LargestLowerThanDensity : targetValue = startDensity * (1 - static_cast( step ) / ( granularity + 0.5 ) ); break; case mitk::ConnectomicsNetworkThresholder::ThresholdBased : targetValue = static_cast( thresholdStepSize * step ); break; default: MITK_ERROR << "Invalid thresholding method called, aborting."; return EXIT_FAILURE; break; } mitk::ConnectomicsNetworkThresholder::Pointer thresholder = mitk::ConnectomicsNetworkThresholder::New(); thresholder->SetNetwork( network ); thresholder->SetTargetThreshold( targetValue ); thresholder->SetTargetDensity( targetValue ); thresholder->SetThresholdingScheme( static_cast(method) ); mitk::ConnectomicsNetwork::Pointer thresholdedNetwork = thresholder->GetThresholdedNetwork(); mitk::ConnectomicsStatisticsCalculator::Pointer statisticsCalculator = mitk::ConnectomicsStatisticsCalculator::New(); statisticsCalculator->SetNetwork( thresholdedNetwork ); statisticsCalculator->Update(); // global statistics if( !noGlobalStatistics ) { globalDataStream << statisticsCalculator->GetNumberOfVertices() << " " << statisticsCalculator->GetNumberOfEdges() << " " << statisticsCalculator->GetAverageDegree() << " " << statisticsCalculator->GetConnectionDensity() << " " << statisticsCalculator->GetNumberOfConnectedComponents() << " " << statisticsCalculator->GetAverageComponentSize() << " " << statisticsCalculator->GetLargestComponentSize() << " " << statisticsCalculator->GetRatioOfNodesInLargestComponent() << " " << statisticsCalculator->GetHopPlotExponent() << " " << statisticsCalculator->GetEffectiveHopDiameter() << " " << statisticsCalculator->GetAverageClusteringCoefficientsC() << " " << statisticsCalculator->GetAverageClusteringCoefficientsD() << " " << statisticsCalculator->GetAverageClusteringCoefficientsE() << " " << statisticsCalculator->GetAverageVertexBetweennessCentrality() << " " << statisticsCalculator->GetAverageEdgeBetweennessCentrality() << " " << statisticsCalculator->GetNumberOfIsolatedPoints() << " " << statisticsCalculator->GetRatioOfIsolatedPoints() << " " << statisticsCalculator->GetNumberOfEndPoints() << " " << statisticsCalculator->GetRatioOfEndPoints() << " " << statisticsCalculator->GetDiameter() << " " << statisticsCalculator->GetDiameter90() << " " << statisticsCalculator->GetRadius() << " " << statisticsCalculator->GetRadius90() << " " << statisticsCalculator->GetAverageEccentricity() << " " << statisticsCalculator->GetAverageEccentricity90() << " " << statisticsCalculator->GetAveragePathLength() << " " << statisticsCalculator->GetNumberOfCentralPoints() << " " << statisticsCalculator->GetRatioOfCentralPoints() << " " << statisticsCalculator->GetSpectralRadius() << " " << statisticsCalculator->GetSecondLargestEigenValue() << " " << statisticsCalculator->GetAdjacencyTrace() << " " << statisticsCalculator->GetAdjacencyEnergy() << " " << statisticsCalculator->GetLaplacianTrace() << " " << statisticsCalculator->GetLaplacianEnergy() << " " << statisticsCalculator->GetLaplacianSpectralGap() << " " << statisticsCalculator->GetNormalizedLaplacianTrace() << " " << statisticsCalculator->GetNormalizedLaplacianEnergy() << " " << statisticsCalculator->GetNormalizedLaplacianNumberOf2s() << " " << statisticsCalculator->GetNormalizedLaplacianNumberOf1s() << " " << statisticsCalculator->GetNormalizedLaplacianNumberOf0s() << " " << statisticsCalculator->GetNormalizedLaplacianLowerSlope() << " " << statisticsCalculator->GetNormalizedLaplacianUpperSlope() << " " << statisticsCalculator->GetSmallWorldness() << std::endl; } // end global statistics //create connectivity matrix png if( createConnectivityMatriximage ) { std::string connectivity_png_postfix = "_connectivity"; if( binaryConnectivity ) { connectivity_png_postfix += "_binary"; } else if( rescaleConnectivity ) { connectivity_png_postfix += "_rescaled"; } connectivity_png_postfix += ".png"; /* File format * A png file depicting the binary connectivity matrix */ itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::Pointer filter = itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::New(); filter->SetInputNetwork( network ); filter->SetBinaryConnectivity( binaryConnectivity ); filter->SetRescaleConnectivity( rescaleConnectivity ); filter->Update(); typedef itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::OutputImageType connectivityMatrixImageType; itk::ImageFileWriter< connectivityMatrixImageType >::Pointer connectivityWriter = itk::ImageFileWriter< connectivityMatrixImageType >::New(); connectivityWriter->SetInput( filter->GetOutput() ); connectivityWriter->SetFileName( outName + connectivity_png_postfix); connectivityWriter->Update(); std::cout << "Connectivity matrix image written."; } // end create connectivity matrix png /* * We can either calculate local indices for specific nodes, or specific regions */ // Create LabelToIndex translation std::map< std::string, int > labelToIdMap; std::vector< mitk::ConnectomicsNetwork::NetworkNode > nodeVector = thresholdedNetwork->GetVectorOfAllNodes(); for(int loop(0); loop < nodeVector.size(); loop++) { labelToIdMap.insert( std::pair< std::string, int>(nodeVector.at(loop).label, nodeVector.at(loop).id) ); } std::vector< int > degreeVector = thresholdedNetwork->GetDegreeOfNodes(); std::vector< double > ccVector = thresholdedNetwork->GetLocalClusteringCoefficients( ); std::vector< double > bcVector = thresholdedNetwork->GetNodeBetweennessVector( ); // calculate local indices { // only add to header for the first step of the first method if( firstRun ) { localHeaderStream << "Th_method " << "Th_target " << "density"; } double density = statisticsCalculator->GetConnectionDensity(); localDataStream << "\n" << method << " " << targetValue << " " << density; for(unsigned int loop(0); loop < localLabels.size(); loop++ ) { if( network->CheckForLabel(localLabels.at( loop )) ) { if( firstRun ) { localHeaderStream << " " << localLabels.at( loop ) << "_Degree " << localLabels.at( loop ) << "_CC " << localLabels.at( loop ) << "_BC"; } localDataStream << " " << degreeVector.at( labelToIdMap.find( localLabels.at( loop ) )->second ) << " " << ccVector.at( labelToIdMap.find( localLabels.at( loop ) )->second ) << " " << bcVector.at( labelToIdMap.find( localLabels.at( loop ) )->second ); } else { MITK_ERROR << "Illegal label. Label: \"" << localLabels.at( loop ) << "\" not found."; } } } // calculate regional indices { // only add to header for the first step of the first method if( firstRun ) { regionalHeaderStream << "Th_method " << "Th_target " << "density"; } double density = statisticsCalculator->GetConnectionDensity(); regionalDataStream << "\n" << method << " " << targetValue << " " << density; for( parsedRegionsIterator = parsedRegions.begin(); parsedRegionsIterator != parsedRegions.end(); parsedRegionsIterator++ ) { std::vector regionLabelsVector = parsedRegionsIterator->second; std::string regionName = parsedRegionsIterator->first; double sumDegree( 0 ); double sumCC( 0 ); double sumBC( 0 ); double count( 0 ); for( int loop(0); loop < regionLabelsVector.size(); loop++ ) { if( thresholdedNetwork->CheckForLabel(regionLabelsVector.at( loop )) ) { sumDegree = sumDegree + degreeVector.at( labelToIdMap.find( regionLabelsVector.at( loop ) )->second ); sumCC = sumCC + ccVector.at( labelToIdMap.find( regionLabelsVector.at( loop ) )->second ); sumBC = sumBC + bcVector.at( labelToIdMap.find( regionLabelsVector.at( loop ) )->second ); count = count + 1; } else { MITK_ERROR << "Illegal label. Label: \"" << regionLabelsVector.at( loop ) << "\" not found."; } } // only add to header for the first step of the first method if( firstRun ) { regionalHeaderStream << " " << regionName << "_LocalAverageDegree " << regionName << "_LocalAverageCC " << regionName << "_LocalAverageBC " << regionName << "_NumberOfNodes"; } regionalDataStream << " " << sumDegree / count << " " << sumCC / count << " " << sumBC / count << " " << count; } } firstRun = false; } }// end calculate local averages if( !noGlobalStatistics ) { std::cout << "Writing to " << globalOutName; std::ofstream glocalOutFile( globalOutName.c_str(), ios::out ); if( ! glocalOutFile.is_open() ) { std::string errorMessage = "Could not open " + globalOutName + " for writing."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } glocalOutFile << globalHeaderStream.str() << globalDataStream.str(); glocalOutFile.close(); } if( localLabels.size() > 0 ) { std::cout << "Writing to " << localOutName; std::ofstream localOutFile( localOutName.c_str(), ios::out ); if( ! localOutFile.is_open() ) { std::string errorMessage = "Could not open " + localOutName + " for writing."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } localOutFile << localHeaderStream.str() << localDataStream.str(); localOutFile.close(); } if( parsedRegions.size() > 0 ) { std::cout << "Writing to " << regionalOutName; std::ofstream regionalOutFile( regionalOutName.c_str(), ios::out ); if( ! regionalOutFile.is_open() ) { std::string errorMessage = "Could not open " + regionalOutName + " for writing."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } regionalOutFile << regionalHeaderStream.str() << regionalDataStream.str(); regionalOutFile.close(); } return EXIT_SUCCESS; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } std::cout << "DONE"; return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/mitkRegistration.cpp b/Modules/DiffusionImaging/MiniApps/Registration.cpp similarity index 99% rename from Modules/DiffusionImaging/MiniApps/mitkRegistration.cpp rename to Modules/DiffusionImaging/MiniApps/Registration.cpp index 30077621d1..e21698dba1 100644 --- a/Modules/DiffusionImaging/MiniApps/mitkRegistration.cpp +++ b/Modules/DiffusionImaging/MiniApps/Registration.cpp @@ -1,457 +1,457 @@ /*=================================================================== 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. ===================================================================*/ // CTK #include "mitkCommandLineParser.h" #include #include #include #include #include #include // ITK #include #include #include "itkLinearInterpolateImageFunction.h" #include "itkWindowedSincInterpolateImageFunction.h" #include "itkIdentityTransform.h" #include "itkResampleImageFilter.h" typedef std::vector FileListType; typedef itk::Image InputImageType; static mitk::Image::Pointer ExtractFirstTS(mitk::Image* image, std::string fileType) { if (fileType == ".dwi") return image; mitk::ImageTimeSelector::Pointer selector = mitk::ImageTimeSelector::New(); selector->SetInput(image); selector->SetTimeNr(0); selector->UpdateLargestPossibleRegion(); mitk::Image::Pointer img =selector->GetOutput()->Clone(); return img; } static std::vector &split(const std::string &s, char delim, std::vector &elems) { std::stringstream ss(s); std::string item; while (std::getline(ss, item, delim)) { elems.push_back(item); } return elems; } static std::vector split(const std::string &s, char delim) { std::vector < std::string > elems; return split(s, delim, elems); } /// Create list of all files in provided folder ending with same postfix static FileListType CreateFileList(std::string folder , std::string postfix) { itk::Directory::Pointer dir = itk::Directory::New(); FileListType fileList; if( dir->Load(folder.c_str() ) ) { int n = dir->GetNumberOfFiles(); for(int r=0;rGetFile( r ); if (filename == "." || filename == "..") continue; filename = folder + filename; if (!itksys::SystemTools::FileExists( filename.c_str())) continue; if (filename.substr(filename.length() -postfix.length() ) == postfix) fileList.push_back(filename); } } return fileList; } static std::string GetSavePath(std::string outputFolder, std::string fileName) { std::string fileType = itksys::SystemTools::GetFilenameExtension(fileName); std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(fileName); std::string savePathAndFileName = outputFolder +fileStem + fileType; return savePathAndFileName; } static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing, bool useLinInt = false) { InputImageType::Pointer itkImage = InputImageType::New(); CastToItkImage(input,itkImage); /** * 1) Resampling * */ // Identity transform. // We don't want any transform on our image except rescaling which is not // specified by a transform but by the input/output spacing as we will see // later. // So no transform will be specified. typedef itk::IdentityTransform T_Transform; // The resampler type itself. typedef itk::ResampleImageFilter T_ResampleFilter; // Prepare the resampler. // Instantiate the transform and specify it should be the id transform. T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); // Instantiate the resampler. Wire in the transform and the interpolator. T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New(); _pResizeFilter->SetTransform(_pTransform); // Set the output origin. _pResizeFilter->SetOutputOrigin(itkImage->GetOrigin()); // Compute the size of the output. // The size (# of pixels) in the output is recomputed using // the ratio of the input and output sizes. InputImageType::SpacingType inputSpacing = itkImage->GetSpacing(); InputImageType::SpacingType outputSpacing; const InputImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion(); InputImageType::SizeType outputSize; typedef InputImageType::SizeType::SizeValueType SizeValueType; // Set the output spacing. outputSpacing[0] = spacing[0]; outputSpacing[1] = spacing[1]; outputSpacing[2] = spacing[2]; outputSize[0] = static_cast(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5); outputSize[1] = static_cast(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5); outputSize[2] = static_cast(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5); _pResizeFilter->SetOutputSpacing(outputSpacing); _pResizeFilter->SetSize(outputSize); typedef itk::LinearInterpolateImageFunction< InputImageType > LinearInterpolatorType; LinearInterpolatorType::Pointer lin_interpolator = LinearInterpolatorType::New(); typedef itk::Function::WelchWindowFunction<4> WelchWindowFunction; typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 4,WelchWindowFunction> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); if (useLinInt) _pResizeFilter->SetInterpolator(lin_interpolator); else _pResizeFilter->SetInterpolator(sinc_interpolator); // Specify the input. _pResizeFilter->SetInput(itkImage); _pResizeFilter->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(_pResizeFilter->GetOutput()); mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image); return image; } /// Build a derived file name from moving images e.g. xxx_T2.nrrd becomes xxx_GTV.nrrd static FileListType CreateDerivedFileList(std::string baseFN, std::string baseSuffix, std::vector derivedPatterns) { FileListType files; for (unsigned int i=0; i < derivedPatterns.size(); i++) { std::string derResourceSuffix = derivedPatterns.at(i); std::string derivedResourceFilename = baseFN.substr(0,baseFN.length() -baseSuffix.length()) + derResourceSuffix; MITK_INFO <<" Looking for file: " << derivedResourceFilename; if (!itksys::SystemTools::FileExists(derivedResourceFilename.c_str())) { MITK_INFO << "CreateDerivedFileList: File does not exit. Skipping entry."; continue; } files.push_back(derivedResourceFilename); } return files; } /// Save images according to file type static void SaveImage(std::string fileName, mitk::Image* image, std::string fileType ) { MITK_INFO << "----Save to " << fileName; mitk::IOUtil::Save(image, fileName); } /// Copy derived resources from first time step. Append _reg tag, but leave data untouched. static void CopyResources(FileListType fileList, std::string outputPath) { for (unsigned int j=0; j < fileList.size(); j++) { std::string derivedResourceFilename = fileList.at(j); std::string fileType = itksys::SystemTools::GetFilenameExtension(derivedResourceFilename); std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(derivedResourceFilename); std::string savePathAndFileName = outputPath +fileStem + "." + fileType; MITK_INFO << "Copy resource " << savePathAndFileName; mitk::Image::Pointer resImage = ExtractFirstTS(mitk::IOUtil::LoadImage(derivedResourceFilename), fileType); mitk::IOUtil::SaveImage(resImage, savePathAndFileName); } } int main( int argc, char* argv[] ) { mitkCommandLineParser parser; parser.setArgumentPrefix("--","-"); - parser.setTitle("Folder Registraton"); + parser.setTitle("Folder Registration"); parser.setCategory("Preprocessing Tools"); - parser.setDescription("http://docs.mitk.org/nightly-qt4/DiffusionMiniApps.html"); + parser.setDescription("For detail description see http://docs.mitk.org/nightly-qt4/DiffusionMiniApps.html"); parser.setContributor("MBI"); // Add command line argument names parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help", "Show this help text"); //parser.addArgument("usemask", "u", QVariant::Bool, "Use segmentations (derived resources) to exclude areas from registration metrics"); parser.addArgument("input", "i", mitkCommandLineParser::InputDirectory, "Input:", "Input folder",us::Any(),false); parser.addArgument("output", "o", mitkCommandLineParser::OutputDirectory, "Output:", "Output folder (ending with /)",us::Any(),false); parser.addArgument("fixed", "f", mitkCommandLineParser::String, "Fixed images:", "Suffix for fixed image (if none is supplied first file matching moving pattern is chosen)",us::Any(),true); parser.addArgument("moving", "m", mitkCommandLineParser::String, "Moving images:", "Suffix for moving images",us::Any(),false); parser.addArgument("derived", "d", mitkCommandLineParser::String, "Derived resources:", "Derived resources suffixes (replaces suffix for moving images); comma separated",us::Any(),true); parser.addArgument("silent", "s", mitkCommandLineParser::Bool, "Silent:" "No xml progress output."); parser.addArgument("resample", "r", mitkCommandLineParser::String, "Resample (x,y,z)mm:", "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any()); parser.addArgument("binary", "b", mitkCommandLineParser::Bool, "Binary:", "Speficies that derived resource are binary (interpolation using nearest neighbor)",us::Any()); parser.addArgument("correct-origin", "c", mitkCommandLineParser::Bool, "Origin correction:", "Correct for large origin displacement. Switch when you reveive: Joint PDF summed to zero ",us::Any()); parser.addArgument("sinc-int", "s", mitkCommandLineParser::Bool, "Windowed-sinc interpolation:", "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any()); map parsedArgs = parser.parseArguments(argc, argv); // Handle special arguments bool silent = false; bool isBinary = false; bool alignOrigin = false; bool useLinearInterpol = true; { if (parsedArgs.size() == 0) { return EXIT_FAILURE; } if (parsedArgs.count("sinc-int")) useLinearInterpol = false; if (parsedArgs.count("silent")) silent = true; if (parsedArgs.count("binary")) isBinary = true; if (parsedArgs.count("correct-origin")) alignOrigin = true; // Show a help message if ( parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } } std::string refPattern = ""; bool useFirstMoving = false; std::string movingImgPattern = us::any_cast(parsedArgs["moving"]); if (parsedArgs.count("fixed")) { refPattern = us::any_cast(parsedArgs["fixed"]); } else { useFirstMoving = true; refPattern = movingImgPattern; } std::string outputPath = us::any_cast(parsedArgs["output"]); std::string inputPath = us::any_cast(parsedArgs["input"]); //QString resampleReference = parsedArgs["resample"].toString(); //bool maskTumor = parsedArgs["usemask"].toBool(); // if derived sources pattern is provided, populate QStringList with possible filename postfixes std::vector derPatterns; if (parsedArgs.count("derived") || parsedArgs.count("d") ) { std::string arg = us::any_cast(parsedArgs["derived"]); derPatterns = split(arg ,','); } std::vector spacings; float spacing[3]; bool doResampling = false; if (parsedArgs.count("resample") || parsedArgs.count("d") ) { std::string arg = us::any_cast(parsedArgs["resample"]); spacings = split(arg ,','); spacing[0] = atoi(spacings.at(0).c_str()); spacing[1] = atoi(spacings.at(1).c_str()); spacing[2] = atoi(spacings.at(2).c_str()); doResampling = true; } MITK_INFO << "Input Folder : " << inputPath; MITK_INFO << "Looking for reference image ..."; FileListType referenceFileList = CreateFileList(inputPath,refPattern); if ((!useFirstMoving && referenceFileList.size() != 1) || (useFirstMoving && referenceFileList.size() == 0)) { MITK_ERROR << "None or more than one possible reference images (" << refPattern <<") found. Exiting." << referenceFileList.size(); MITK_INFO << "Choose a fixed arguement that is unique in the given folder!"; return EXIT_FAILURE; } std::string referenceFileName = referenceFileList.at(0); MITK_INFO << "Loading Reference (fixed) image: " << referenceFileName; std::string fileType = itksys::SystemTools::GetFilenameExtension(referenceFileName); mitk::Image::Pointer refImage = ExtractFirstTS(mitk::IOUtil::LoadImage(referenceFileName), fileType); mitk::Image::Pointer resampleReference = NULL; if (doResampling) { refImage = ResampleBySpacing(refImage,spacing); resampleReference = refImage; } if (refImage.IsNull()) MITK_ERROR << "Loaded fixed image is NULL"; // Copy reference image to destination std::string savePathAndFileName = GetSavePath(outputPath, referenceFileName); mitk::IOUtil::SaveImage(refImage, savePathAndFileName); // Copy all derived resources also to output folder, adding _reg suffix referenceFileList = CreateDerivedFileList(referenceFileName, movingImgPattern,derPatterns); CopyResources(referenceFileList, outputPath); std::string derivedResourceFilename; mitk::Image::Pointer referenceMask = NULL; // union of all segmentations if (!silent) { // XML Output to report progress std::cout << ""; std::cout << "Batched Registration"; std::cout << "Starting registration ... "; std::cout << ""; } // Now iterate over all files and register them to the reference image, // also register derived resources based on file patterns // ------------------------------------------------------------------------------ // Create File list FileListType movingImagesList = CreateFileList(inputPath, movingImgPattern); // TODO Reactivate Resampling Feature // mitk::Image::Pointer resampleImage = NULL; // if (QFileInfo(resampleReference).isFile()) // { // resampleImage = mitk::IOUtil::LoadImage(resampleReference.toStdString()); // } for (unsigned int i =0; i < movingImagesList.size(); i++) { std::string fileMorphName = movingImagesList.at(i); if (fileMorphName == referenceFileName) { // do not process reference image again continue; } MITK_INFO << "Processing image " << fileMorphName; // 1 Register morphological file to reference image if (!itksys::SystemTools::FileExists(fileMorphName.c_str())) { MITK_WARN << "File does not exit. Skipping entry."; continue; } // Origin of images is cancelled // TODO make this optional!! double transf[6]; double offset[3]; { std::string fileType = itksys::SystemTools::GetFilenameExtension(fileMorphName); mitk::Image::Pointer movingImage = ExtractFirstTS(mitk::IOUtil::LoadImage(fileMorphName), fileType); if (movingImage.IsNull()) MITK_ERROR << "Loaded moving image is NULL"; // Store transformation, apply it to morph file MITK_INFO << "----------Registering moving image to reference----------"; mitk::RegistrationWrapper::GetTransformation(refImage, movingImage, transf, offset, alignOrigin, referenceMask); mitk::RegistrationWrapper::ApplyTransformationToImage(movingImage, transf,offset, resampleReference); // , resampleImage savePathAndFileName = GetSavePath(outputPath, fileMorphName); if (fileType == ".dwi") fileType = "dwi"; SaveImage(savePathAndFileName,movingImage,fileType ); } if (!silent) { std::cout << "."; } // Now parse all derived resource and apply the above calculated transformation to them // ------------------------------------------------------------------------------------ FileListType fList = CreateDerivedFileList(fileMorphName, movingImgPattern,derPatterns); if (fList.size() > 0) MITK_INFO << "----------DERIVED RESOURCES ---------"; for (unsigned int j=0; j < fList.size(); j++) { derivedResourceFilename = fList.at(j); MITK_INFO << "----Processing derived resorce " << derivedResourceFilename << " ..."; std::string fileType = itksys::SystemTools::GetFilenameExtension(derivedResourceFilename); mitk::Image::Pointer derivedMovingResource = ExtractFirstTS(mitk::IOUtil::LoadImage(derivedResourceFilename), fileType); // Apply transformation to derived resource, treat derived resource as binary mitk::RegistrationWrapper::ApplyTransformationToImage(derivedMovingResource, transf,offset, resampleReference,isBinary); savePathAndFileName = GetSavePath(outputPath, derivedResourceFilename); SaveImage(savePathAndFileName,derivedMovingResource,fileType ); } } if (!silent) std::cout << ""; return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/TensorDerivedMapsExtraction.cpp b/Modules/DiffusionImaging/MiniApps/TensorDerivedMapsExtraction.cpp index ecbe39b53b..270033e7b6 100644 --- a/Modules/DiffusionImaging/MiniApps/TensorDerivedMapsExtraction.cpp +++ b/Modules/DiffusionImaging/MiniApps/TensorDerivedMapsExtraction.cpp @@ -1,190 +1,176 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkImage.h" #include #include "mitkITKImageImport.h" #include #include #include #include #include #include "itkTensorDerivedMeasurementsFilter.h" #include "itkDiffusionTensor3DReconstructionImageFilter.h" #include "mitkCommandLineParser.h" #include #include #include typedef short DiffusionPixelType; typedef double TTensorPixelType; static void ExtractMapsAndSave(mitk::TensorImage::Pointer tensorImage, std::string filename, std::string postfix = "") { mitk::Image* image = dynamic_cast (tensorImage.GetPointer()); typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(image, itkvol); typedef itk::TensorDerivedMeasurementsFilter MeasurementsType; MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); mitk::Image::Pointer map = mitk::Image::New(); // FA measurementsCalculator->SetMeasure(MeasurementsType::FA); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::SaveImage(map, filename + "_dti_FA" + postfix + ".nrrd"); // MD measurementsCalculator->SetMeasure(MeasurementsType::MD); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::SaveImage(map, filename + "_dti_MD" + postfix + ".nrrd"); // AD measurementsCalculator->SetMeasure(MeasurementsType::AD); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::SaveImage(map, filename + "_dti_AD" + postfix + ".nrrd"); // CA measurementsCalculator->SetMeasure(MeasurementsType::CA); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::SaveImage(map, filename + "_dti_CA" + postfix + ".nrrd"); // RA measurementsCalculator->SetMeasure(MeasurementsType::RA); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::SaveImage(map, filename + "_dti_RA" + postfix + ".nrrd"); // RD measurementsCalculator->SetMeasure(MeasurementsType::RD); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::SaveImage(map, filename + "_dti_RD" + postfix + ".nrrd"); } int main(int argc, char* argv[]) { - - std::cout << "TensorDerivedMapsExtraction"; mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("help", "h", mitkCommandLineParser::String, "Help", "Show this help text"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input file", "input dwi file", us::Any(),false); - parser.addArgument("out", "o", mitkCommandLineParser::String, "Output folder", "output folder and base name, e.g. /tmp/outPatient1 ", us::Any(),false); + parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output folder", "output folder and base name, e.g. /tmp/outPatient1 ", us::Any(),false); - parser.setCategory("Diffusion Related Measures"); parser.setTitle("Tensor Derived Maps Extraction"); + parser.setCategory("Diffusion Related Measures"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); - if (parsedArgs.size()==0 || parsedArgs.count("help") || parsedArgs.count("h")) - { - std::cout << "\n\nMiniApp Description: \nPerforms tensor reconstruction on DWI file," << endl; - std::cout << "and computes tensor derived measures." << endl; - std::cout << "\n\n For out parameter /tmp/outPatient1 it will produce :"<< endl; - std::cout << " /tmp/outPatient1_dti.dti , /tmp/outPatient1_dti_FA.nrrd, ..."<< endl; - std::cout << "\n\n Parameters:"<< endl; - std::cout << parser.helpText(); - return EXIT_SUCCESS; - } - + if (parsedArgs.size()==0) + return EXIT_FAILURE; std::string inputFile = us::any_cast(parsedArgs["input"]); std::string baseFileName = us::any_cast(parsedArgs["out"]); std::string dtiFileName = "_dti.dti"; - std::cout << "BaseFileName: " << baseFileName; - - mitk::Image::Pointer diffusionImage = mitk::IOUtil::LoadImage(inputFile); if (diffusionImage.IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(diffusionImage)) // does NULL pointer check make sense after static cast ? { MITK_ERROR << "Invalid Input Image. Must be DWI. Aborting."; return -1; } typedef itk::DiffusionTensor3DReconstructionImageFilter< DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter = TensorReconstructionImageFilterType::New(); mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientContainerCopy = mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::New(); for( mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::ConstIterator it = mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImage)->Begin(); it != mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImage)->End(); it++) { gradientContainerCopy->push_back(it.Value()); } mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(diffusionImage, itkVectorImagePointer); tensorReconstructionFilter->SetGradientImage( gradientContainerCopy, itkVectorImagePointer ); tensorReconstructionFilter->SetBValue( mitk::DiffusionPropertyHelper::GetReferenceBValue( diffusionImage ) ); tensorReconstructionFilter->SetThreshold(50); tensorReconstructionFilter->Update(); typedef itk::Image, 3> TensorImageType; TensorImageType::Pointer tensorImage = tensorReconstructionFilter->GetOutput(); tensorImage->SetDirection( itkVectorImagePointer->GetDirection() ); mitk::TensorImage::Pointer tensorImageMitk = mitk::TensorImage::New(); tensorImageMitk->InitializeByItk(tensorImage.GetPointer()); tensorImageMitk->SetVolume( tensorImage->GetBufferPointer() ); itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< double >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< double >, 3 > >::New(); writer->SetInput(tensorReconstructionFilter->GetOutput()); writer->SetFileName(baseFileName + dtiFileName); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); ExtractMapsAndSave(tensorImageMitk,baseFileName); return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/TensorReconstruction.cpp b/Modules/DiffusionImaging/MiniApps/TensorReconstruction.cpp index a1b066cc54..f0063b77a4 100644 --- a/Modules/DiffusionImaging/MiniApps/TensorReconstruction.cpp +++ b/Modules/DiffusionImaging/MiniApps/TensorReconstruction.cpp @@ -1,103 +1,102 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBaseDataIOFactory.h" #include "mitkImage.h" #include #include "mitkBaseData.h" #include #include #include #include #include #include "mitkCommandLineParser.h" #include using namespace mitk; /** * Convert files from one ending to the other */ int main(int argc, char* argv[]) { - std::cout << "TensorReconstruction"; mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input file", "input raw dwi (.dwi or .fsl/.fslgz)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output file", "output file", us::Any(), false); parser.addArgument("b0Threshold", "t", mitkCommandLineParser::Int, "b0 threshold", "baseline image intensity threshold", 0, true); parser.setCategory("Preprocessing Tools"); parser.setTitle("Tensor Reconstruction"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; std::string inFileName = us::any_cast(parsedArgs["input"]); std::string outfilename = us::any_cast(parsedArgs["outFile"]); outfilename = itksys::SystemTools::GetFilenamePath(outfilename)+"/"+itksys::SystemTools::GetFilenameWithoutExtension(outfilename); outfilename += ".dti"; int threshold = 0; if (parsedArgs.count("b0Threshold")) threshold = us::any_cast(parsedArgs["b0Threshold"]); try { const std::string s1="", s2=""; std::vector infile = BaseDataIO::LoadBaseDataFromFile( inFileName, s1, s2, false ); Image::Pointer dwi = dynamic_cast(infile.at(0).GetPointer()); mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue( mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi )); filter->SetThreshold(threshold); filter->Update(); // Save tensor image itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::New(); writer->SetInput(filter->GetOutput()); writer->SetFileName(outfilename); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); } catch ( itk::ExceptionObject &err) { std::cout << "Exception: " << err; } catch ( std::exception err) { std::cout << "Exception: " << err.what(); } catch ( ... ) { std::cout << "Exception!"; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/mitkCommandLineParser.cpp b/Modules/DiffusionImaging/MiniApps/mitkCommandLineParser.cpp index 71db4fc8bd..4ddf671fc3 100755 --- a/Modules/DiffusionImaging/MiniApps/mitkCommandLineParser.cpp +++ b/Modules/DiffusionImaging/MiniApps/mitkCommandLineParser.cpp @@ -1,893 +1,900 @@ /*=================================================================== 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. ===================================================================*/ /*========================================================================= Library: CTK Copyright (c) Kitware Inc. 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. =========================================================================*/ // STL includes #include #include // MITK includes #include "mitkCommandLineParser.h" using namespace std; namespace { // -------------------------------------------------------------------------- class CommandLineParserArgumentDescription { public: CommandLineParserArgumentDescription( const string& longArg, const string& longArgPrefix, const string& shortArg, const string& shortArgPrefix, mitkCommandLineParser::Type type, const string& argHelp, const string& argLabel, const us::Any& defaultValue, bool ignoreRest, bool deprecated, bool optional, string& argGroup, string& groupDescription) : LongArg(longArg), LongArgPrefix(longArgPrefix), ShortArg(shortArg), ShortArgPrefix(shortArgPrefix), ArgHelp(argHelp), ArgLabel(argLabel), IgnoreRest(ignoreRest), NumberOfParametersToProcess(0), Deprecated(deprecated), DefaultValue(defaultValue), Value(type), ValueType(type), Optional(optional), ArgGroup(argGroup), ArgGroupDescription(groupDescription) { Value = defaultValue; switch (type) { case mitkCommandLineParser::String: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::Bool: { NumberOfParametersToProcess = 0; } break; case mitkCommandLineParser::StringList: { NumberOfParametersToProcess = -1; } break; case mitkCommandLineParser::Int: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::Float: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::OutputDirectory: case mitkCommandLineParser::InputDirectory: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::OutputFile: case mitkCommandLineParser::InputFile: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::InputImage: { NumberOfParametersToProcess = 1; } break; default: std::cout << "Type not supported: " << static_cast(type); } } ~CommandLineParserArgumentDescription(){} bool addParameter(const string& value); string helpText(); string LongArg; string LongArgPrefix; string ShortArg; string ShortArgPrefix; string ArgHelp; string ArgLabel; string ArgGroup; string ArgGroupDescription; bool IgnoreRest; int NumberOfParametersToProcess; bool Deprecated; bool Optional; us::Any DefaultValue; us::Any Value; mitkCommandLineParser::Type ValueType; }; // -------------------------------------------------------------------------- bool CommandLineParserArgumentDescription::addParameter(const string &value) { switch (ValueType) { case mitkCommandLineParser::String: { Value = value; } break; case mitkCommandLineParser::Bool: { if (value.compare("true")==0) Value = true; else Value = false; } break; case mitkCommandLineParser::StringList: { try { mitkCommandLineParser::StringContainerType list = us::any_cast(Value); list.push_back(value); Value = list; } catch(...) { mitkCommandLineParser::StringContainerType list; list.push_back(value); Value = list; } } break; case mitkCommandLineParser::Int: { stringstream ss(value); int i; ss >> i; Value = i; } break; case mitkCommandLineParser::Float: { stringstream ss(value); float f; ss >> f; Value = f; } break; case mitkCommandLineParser::InputDirectory: case mitkCommandLineParser::OutputDirectory: { Value = value; } break; case mitkCommandLineParser::InputFile: case mitkCommandLineParser::InputImage: case mitkCommandLineParser::OutputFile: { Value = value; } break; default: return false; } return true; } // -------------------------------------------------------------------------- string CommandLineParserArgumentDescription::helpText() { string text; string shortAndLongArg; if (!this->ShortArg.empty()) { shortAndLongArg = " "; shortAndLongArg += this->ShortArgPrefix; shortAndLongArg += this->ShortArg; } if (!this->LongArg.empty()) { if (this->ShortArg.empty()) shortAndLongArg.append(" "); else shortAndLongArg.append(", "); shortAndLongArg += this->LongArgPrefix; shortAndLongArg += this->LongArg; } text = text + shortAndLongArg + ", " + this->ArgHelp; if (this->Optional) text += " (optional)"; if (!this->DefaultValue.Empty()) { text = text + ", (default: " + this->DefaultValue.ToString() + ")"; } text += "\n"; return text; } } // -------------------------------------------------------------------------- // ctkCommandLineParser::ctkInternal class // -------------------------------------------------------------------------- class mitkCommandLineParser::ctkInternal { public: ctkInternal() : Debug(false), FieldWidth(0), StrictMode(false) {} ~ctkInternal() { } CommandLineParserArgumentDescription* argumentDescription(const string& argument); vector ArgumentDescriptionList; map ArgNameToArgumentDescriptionMap; map > GroupToArgumentDescriptionListMap; StringContainerType UnparsedArguments; StringContainerType ProcessedArguments; string ErrorString; bool Debug; int FieldWidth; string LongPrefix; string ShortPrefix; string CurrentGroup; string DisableQSettingsLongArg; string DisableQSettingsShortArg; bool StrictMode; }; // -------------------------------------------------------------------------- // ctkCommandLineParser::ctkInternal methods // -------------------------------------------------------------------------- CommandLineParserArgumentDescription* mitkCommandLineParser::ctkInternal::argumentDescription(const string& argument) { string unprefixedArg = argument; if (!LongPrefix.empty() && argument.compare(0, LongPrefix.size(), LongPrefix)==0) { // Case when (ShortPrefix + UnPrefixedArgument) matches LongPrefix if (argument == LongPrefix && !ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix)==0) { unprefixedArg = argument.substr(ShortPrefix.size(),argument.size()); } else { unprefixedArg = argument.substr(LongPrefix.size(),argument.size()); } } else if (!ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix)==0) { unprefixedArg = argument.substr(ShortPrefix.size(),argument.size()); } else if (!LongPrefix.empty() && !ShortPrefix.empty()) { return 0; } if (ArgNameToArgumentDescriptionMap.count(unprefixedArg)) { return this->ArgNameToArgumentDescriptionMap[unprefixedArg]; } return 0; } // -------------------------------------------------------------------------- // ctkCommandLineParser methods // -------------------------------------------------------------------------- mitkCommandLineParser::mitkCommandLineParser() { this->Internal = new ctkInternal(); this->Category = string(); this->Title = string(); this->Contributor = string(); this->Description = string(); this->ParameterGroupName = "Parameters"; - this->ParameterGroupDescription = "Groupbox containing parameters."; + this->ParameterGroupDescription = "Parameters"; } // -------------------------------------------------------------------------- mitkCommandLineParser::~mitkCommandLineParser() { delete this->Internal; } // -------------------------------------------------------------------------- map mitkCommandLineParser::parseArguments(const StringContainerType& arguments, bool* ok) { // Reset this->Internal->UnparsedArguments.clear(); this->Internal->ProcessedArguments.clear(); this->Internal->ErrorString.clear(); // foreach (CommandLineParserArgumentDescription* desc, this->Internal->ArgumentDescriptionList) for (unsigned int i=0; iArgumentDescriptionList.size(); i++) { CommandLineParserArgumentDescription* desc = Internal->ArgumentDescriptionList.at(i); desc->Value = us::Any(desc->ValueType); if (!desc->DefaultValue.Empty()) { desc->Value = desc->DefaultValue; } } bool error = false; bool ignoreRest = false; CommandLineParserArgumentDescription * currentArgDesc = 0; vector parsedArgDescriptions; for(unsigned int i = 1; i < arguments.size(); ++i) { string argument = arguments.at(i); if (this->Internal->Debug) { std::cout << "Processing" << argument; } if (!argument.compare("--xml") || !argument.compare("-xml") || !argument.compare("--XML") || !argument.compare("-XML")) { this->generateXmlOutput(); return map(); } // should argument be ignored ? if (ignoreRest) { if (this->Internal->Debug) { std::cout << " Skipping: IgnoreRest flag was been set"; } this->Internal->UnparsedArguments.push_back(argument); continue; } // Skip if the argument does not start with the defined prefix if (!(argument.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix)==0 || argument.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix)==0)) { if (this->Internal->StrictMode) { this->Internal->ErrorString = "Unknown argument "; this->Internal->ErrorString += argument; error = true; break; } if (this->Internal->Debug) { std::cout << " Skipping: It does not start with the defined prefix"; } this->Internal->UnparsedArguments.push_back(argument); continue; } // Skip if argument has already been parsed ... bool alreadyProcessed = false; for (unsigned int i=0; iProcessedArguments.size(); i++) if (argument.compare(Internal->ProcessedArguments.at(i))==0) { alreadyProcessed = true; break; } if (alreadyProcessed) { if (this->Internal->StrictMode) { this->Internal->ErrorString = "Argument "; this->Internal->ErrorString += argument; this->Internal->ErrorString += " already processed !"; error = true; break; } if (this->Internal->Debug) { std::cout << " Skipping: Already processed !"; } continue; } // Retrieve corresponding argument description currentArgDesc = this->Internal->argumentDescription(argument); // Is there a corresponding argument description ? if (currentArgDesc) { // If the argument is deprecated, print the help text but continue processing if (currentArgDesc->Deprecated) { std::cout << "Deprecated argument " << argument << ": " << currentArgDesc->ArgHelp; } else { parsedArgDescriptions.push_back(currentArgDesc); } this->Internal->ProcessedArguments.push_back(currentArgDesc->ShortArg); this->Internal->ProcessedArguments.push_back(currentArgDesc->LongArg); int numberOfParametersToProcess = currentArgDesc->NumberOfParametersToProcess; ignoreRest = currentArgDesc->IgnoreRest; if (this->Internal->Debug && ignoreRest) { std::cout << " IgnoreRest flag is True"; } // Is the number of parameters associated with the argument being processed known ? if (numberOfParametersToProcess == 0) { currentArgDesc->addParameter("true"); } else if (numberOfParametersToProcess > 0) { string missingParameterError = "Argument %1 has %2 value(s) associated whereas exacly %3 are expected."; for(int j=1; j <= numberOfParametersToProcess; ++j) { if (i + j >= arguments.size()) { // this->Internal->ErrorString = // missingParameterError.arg(argument).arg(j-1).arg(numberOfParametersToProcess); // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } string parameter = arguments.at(i + j); if (this->Internal->Debug) { std::cout << " Processing parameter" << j << ", value:" << parameter; } if (this->argumentAdded(parameter)) { // this->Internal->ErrorString = // missingParameterError.arg(argument).arg(j-1).arg(numberOfParametersToProcess); // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } if (!currentArgDesc->addParameter(parameter)) { // this->Internal->ErrorString = string( // "Value(s) associated with argument %1 are incorrect. %2"). // arg(argument).arg(currentArgDesc->ExactMatchFailedMessage); // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } } // Update main loop increment i = i + numberOfParametersToProcess; } else if (numberOfParametersToProcess == -1) { if (this->Internal->Debug) { std::cout << " Proccessing StringList ..."; } int j = 1; while(j + i < arguments.size()) { if (this->argumentAdded(arguments.at(j + i))) { if (this->Internal->Debug) { std::cout << " No more parameter for" << argument; } break; } string parameter = arguments.at(j + i); if (parameter.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix)==0 || parameter.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix)==0) { j--; break; } if (this->Internal->Debug) { std::cout << " Processing parameter" << j << ", value:" << parameter; } if (!currentArgDesc->addParameter(parameter)) { // this->Internal->ErrorString = string( // "Value(s) associated with argument %1 are incorrect. %2"). // arg(argument).arg(currentArgDesc->ExactMatchFailedMessage); // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } j++; } // Update main loop increment i = i + j; } } else { if (this->Internal->StrictMode) { this->Internal->ErrorString = "Unknown argument "; this->Internal->ErrorString += argument; error = true; break; } if (this->Internal->Debug) { std::cout << " Skipping: Unknown argument"; } this->Internal->UnparsedArguments.push_back(argument); } } if (ok) { *ok = !error; } map parsedArguments; int obligatoryArgs = 0; vector::iterator it; for(it = Internal->ArgumentDescriptionList.begin(); it != Internal->ArgumentDescriptionList.end();++it) { CommandLineParserArgumentDescription* desc = *it; if(!desc->Optional) obligatoryArgs++; } int parsedObligatoryArgs = 0; for(it = parsedArgDescriptions.begin(); it != parsedArgDescriptions.end();++it) { CommandLineParserArgumentDescription* desc = *it; string key; if (!desc->LongArg.empty()) { key = desc->LongArg; } else { key = desc->ShortArg; } if(!desc->Optional) parsedObligatoryArgs++; std::pair elem; elem.first = key; elem.second = desc->Value; parsedArguments.insert(elem); } if (obligatoryArgs>parsedObligatoryArgs) { parsedArguments.clear(); cout << helpText(); } return parsedArguments; } // ------------------------------------------------------------------------- map mitkCommandLineParser::parseArguments(int argc, char** argv, bool* ok) { StringContainerType arguments; // Create a StringContainerType of arguments for(int i = 0; i < argc; ++i) arguments.push_back(argv[i]); return this->parseArguments(arguments, ok); } // ------------------------------------------------------------------------- string mitkCommandLineParser::errorString() const { return this->Internal->ErrorString; } // ------------------------------------------------------------------------- const mitkCommandLineParser::StringContainerType& mitkCommandLineParser::unparsedArguments() const { return this->Internal->UnparsedArguments; } // -------------------------------------------------------------------------- void mitkCommandLineParser::addArgument(const string& longarg, const string& shortarg, Type type, const string& argLabel, const string& argHelp, - const us::Any& defaultValue, bool optional, bool ignoreRest, + const us::Any &defaultValue, bool optional, bool ignoreRest, bool deprecated) { if (longarg.empty() && shortarg.empty()) { return; } /* Make sure it's not already added */ bool added = this->Internal->ArgNameToArgumentDescriptionMap.count(longarg); if (added) { return; } added = this->Internal->ArgNameToArgumentDescriptionMap.count(shortarg); if (added) { return; } CommandLineParserArgumentDescription* argDesc = new CommandLineParserArgumentDescription(longarg, this->Internal->LongPrefix, shortarg, this->Internal->ShortPrefix, type, argHelp, argLabel, defaultValue, ignoreRest, deprecated, optional, ParameterGroupName, ParameterGroupDescription); int argWidth = 0; if (!longarg.empty()) { this->Internal->ArgNameToArgumentDescriptionMap[longarg] = argDesc; argWidth += longarg.size() + this->Internal->LongPrefix.size(); } if (!shortarg.empty()) { this->Internal->ArgNameToArgumentDescriptionMap[shortarg] = argDesc; argWidth += shortarg.size() + this->Internal->ShortPrefix.size() + 2; } argWidth += 5; // Set the field width for the arguments if (argWidth > this->Internal->FieldWidth) { this->Internal->FieldWidth = argWidth; } this->Internal->ArgumentDescriptionList.push_back(argDesc); this->Internal->GroupToArgumentDescriptionListMap[this->Internal->CurrentGroup].push_back(argDesc); } // -------------------------------------------------------------------------- void mitkCommandLineParser::addDeprecatedArgument( const string& longarg, const string& shortarg, const string& argLabel, const string& argHelp) { addArgument(longarg, shortarg, StringList, argLabel, argHelp, us::Any(), false, true, false); } // -------------------------------------------------------------------------- int mitkCommandLineParser::fieldWidth() const { return this->Internal->FieldWidth; } // -------------------------------------------------------------------------- void mitkCommandLineParser::beginGroup(const string& description) { this->Internal->CurrentGroup = description; } // -------------------------------------------------------------------------- void mitkCommandLineParser::endGroup() { this->Internal->CurrentGroup.clear(); } // -------------------------------------------------------------------------- string mitkCommandLineParser::helpText() const { string text; vector deprecatedArgs; // Loop over grouped argument descriptions map >::iterator it; for(it = Internal->GroupToArgumentDescriptionListMap.begin(); it != Internal->GroupToArgumentDescriptionListMap.end();++it) { if (!(*it).first.empty()) { text = text + "\n" + (*it).first + "\n"; } vector::iterator it2; for(it2 = (*it).second.begin(); it2 != (*it).second.end(); ++it2) { CommandLineParserArgumentDescription* argDesc = *it2; if (argDesc->Deprecated) { deprecatedArgs.push_back(argDesc); } else { text += argDesc->helpText(); } } } if (!deprecatedArgs.empty()) { text += "\nDeprecated arguments:\n"; vector::iterator it2; for(it2 = deprecatedArgs.begin(); it2 != deprecatedArgs.end(); ++it2) { CommandLineParserArgumentDescription* argDesc = *it2; text += argDesc->helpText(); } } return text; } // -------------------------------------------------------------------------- bool mitkCommandLineParser::argumentAdded(const string& argument) const { return this->Internal->ArgNameToArgumentDescriptionMap.count(argument); } // -------------------------------------------------------------------------- bool mitkCommandLineParser::argumentParsed(const string& argument) const { for (unsigned int i=0; iProcessedArguments.size(); i++) if (argument.compare(Internal->ProcessedArguments.at(i))==0) return true; return false; } // -------------------------------------------------------------------------- void mitkCommandLineParser::setArgumentPrefix(const string& longPrefix, const string& shortPrefix) { this->Internal->LongPrefix = longPrefix; this->Internal->ShortPrefix = shortPrefix; } // -------------------------------------------------------------------------- void mitkCommandLineParser::setStrictModeEnabled(bool strictMode) { this->Internal->StrictMode = strictMode; } void mitkCommandLineParser::generateXmlOutput() { std::stringstream xml; xml << "" << endl; xml << "" << Category << "" << endl; xml << "" << Title <<"" << endl; xml << "" << Description << "" << endl; xml << "" << Contributor << "" << endl; xml << "" << endl; std::vector::iterator it; std::string lastParameterGroup = ""; for (it = this->Internal->ArgumentDescriptionList.begin(); it != this->Internal->ArgumentDescriptionList.end(); it++) { std::string type; switch ((*it)->ValueType) { case mitkCommandLineParser::String: type = "string"; break; case mitkCommandLineParser::Bool: type = "boolean"; break; case mitkCommandLineParser::StringList: type = "string-vector"; break; case mitkCommandLineParser::Int: type = "integer"; break; case mitkCommandLineParser::Float: type = "float"; break; case mitkCommandLineParser::OutputDirectory: case mitkCommandLineParser::InputDirectory: type = "directory"; break; case mitkCommandLineParser::InputImage: type = "image"; break; case mitkCommandLineParser::OutputFile: case mitkCommandLineParser::InputFile: type = "file"; break; } if (lastParameterGroup.compare((*it)->ArgGroup)) { if (it != this->Internal->ArgumentDescriptionList.begin()) { xml << "" << endl; xml << "" << endl; } xml << "" << endl; xml << "" << (*it)->ArgGroupDescription << "" << endl; lastParameterGroup = (*it)->ArgGroup; } + // Skip help item, as it's no use in GUI + if ((*it)->ShortArg == "h") + continue; + xml << "<" << type << ">" << endl; xml << "" << (*it)->LongArg << "" << endl; - xml << "" << endl; xml << "" << (*it)->ArgHelp << "" << endl; + xml << "" << endl; + if (!(*it)->DefaultValue.Empty()) + xml << "" << (*it)->DefaultValue.ToString() << "" << endl; + xml << "" << (*it)->LongArg << "" << endl; xml << "" << (*it)->ShortArg << "" << endl; if ((*it)->ValueType == mitkCommandLineParser::InputDirectory || (*it)->ValueType == mitkCommandLineParser::InputFile || (*it)->ValueType == mitkCommandLineParser::InputImage) { xml << "input" << endl; } else if ((*it)->ValueType == mitkCommandLineParser::OutputDirectory || (*it)->ValueType == mitkCommandLineParser::OutputFile) { xml << "output" << endl; } xml << "" << endl; } xml << "" << endl; xml << "" << endl; cout << xml.str(); } void mitkCommandLineParser::setTitle(string title) { Title = title; } void mitkCommandLineParser::setContributor(string contributor) { Contributor = contributor; } void mitkCommandLineParser::setCategory(string category) { Category = category; } void mitkCommandLineParser::setDescription(string description) { Description = description; } void mitkCommandLineParser::changeParameterGroup(string name, string tooltip) { ParameterGroupName = name; ParameterGroupDescription = tooltip; } diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp b/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp index 3de7925cdf..45d3b67ef0 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp +++ b/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp @@ -1,145 +1,155 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataSource.h" #include "mitkUIDGenerator.h" //Microservices #include #include #include #include const std::string mitk::NavigationDataSource::US_INTERFACE_NAME = "org.mitk.services.NavigationDataSource"; const std::string mitk::NavigationDataSource::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; const std::string mitk::NavigationDataSource::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; const std::string mitk::NavigationDataSource::US_PROPKEY_ISACTIVE = US_INTERFACE_NAME + ".isActive"; mitk::NavigationDataSource::NavigationDataSource() - : itk::ProcessObject(), m_Name("NavigationDataSource (no defined type)") +: itk::ProcessObject(), m_Name("NavigationDataSource (no defined type)"), m_IsFrozen(false) { } mitk::NavigationDataSource::~NavigationDataSource() { } mitk::NavigationData* mitk::NavigationDataSource::GetOutput() { if (this->GetNumberOfIndexedOutputs() < 1) return NULL; return static_cast(this->ProcessObject::GetPrimaryOutput()); } mitk::NavigationData* mitk::NavigationDataSource::GetOutput(DataObjectPointerArraySizeType idx) { NavigationData* out = dynamic_cast( this->ProcessObject::GetOutput(idx) ); if ( out == NULL && this->ProcessObject::GetOutput(idx) != NULL ) { itkWarningMacro (<< "Unable to convert output number " << idx << " to type " << typeid( NavigationData ).name () ); } return out; } mitk::NavigationData* mitk::NavigationDataSource::GetOutput(const std::string& navDataName) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) if (navDataName == (static_cast(it->GetPointer()))->GetName()) return static_cast(it->GetPointer()); return NULL; } itk::ProcessObject::DataObjectPointerArraySizeType mitk::NavigationDataSource::GetOutputIndex( std::string navDataName ) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) if (navDataName == (static_cast(outputs.at(i).GetPointer()))->GetName()) return i; throw std::invalid_argument("output name does not exist"); } void mitk::NavigationDataSource::RegisterAsMicroservice(){ // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator ("org.mitk.services.NavigationDataSource.id_", 16); props[ US_PROPKEY_ID ] = uidGen.GetUID(); props[ US_PROPKEY_DEVICENAME ] = m_Name; m_ServiceRegistration = context->RegisterService(this, props); } void mitk::NavigationDataSource::UnRegisterMicroservice(){ if (m_ServiceRegistration != NULL) m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } std::string mitk::NavigationDataSource::GetMicroserviceID(){ return this->m_ServiceRegistration.GetReference().GetProperty(US_PROPKEY_ID).ToString(); } void mitk::NavigationDataSource::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::NavigationDataSource::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfIndexedOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter only has " << this->GetNumberOfIndexedOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a NULL pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" ); } // Call Graft on NavigationData to copy member data output->Graft( graft ); } itk::DataObject::Pointer mitk::NavigationDataSource::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) { return mitk::NavigationData::New().GetPointer(); } itk::DataObject::Pointer mitk::NavigationDataSource::MakeOutput( const DataObjectIdentifierType & name ) { itkDebugMacro("MakeOutput(" << name << ")"); if( this->IsIndexedOutputName(name) ) { return this->MakeOutput( this->MakeIndexFromOutputName(name) ); } return static_cast(mitk::NavigationData::New().GetPointer()); } mitk::PropertyList::ConstPointer mitk::NavigationDataSource::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); // add properties to p like this: //p->SetProperty("MyFilter_MyParameter", mitk::PropertyDataType::New(m_MyParameter)); return mitk::PropertyList::ConstPointer(p); -} \ No newline at end of file +} + +void mitk::NavigationDataSource::Freeze() +{ + m_IsFrozen = true; +} + +void mitk::NavigationDataSource::UnFreeze() +{ + m_IsFrozen = false; +} diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSource.h b/Modules/IGT/DataManagement/mitkNavigationDataSource.h index 375810c62e..6b1601691e 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSource.h +++ b/Modules/IGT/DataManagement/mitkNavigationDataSource.h @@ -1,171 +1,185 @@ /*=================================================================== 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 MITKNAVIGATIONDATASOURCE_H_HEADER_INCLUDED_ #define MITKNAVIGATIONDATASOURCE_H_HEADER_INCLUDED_ #include #include "mitkNavigationData.h" #include "mitkPropertyList.h" // Microservices #include #include namespace mitk { /**Documentation * \brief Navigation Data source * * Base class for all navigation filters that produce NavigationData objects as output. * This class defines the output-interface for NavigationDataFilters. * \warning: if Update() is called on any output object, all NavigationData filters will * generate new output data for all outputs, not just the one on which Update() was called. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationDataSource : public itk::ProcessObject { public: mitkClassMacro(NavigationDataSource, itk::ProcessObject); /** @return Returns a human readable name of this source. There will be a default name, * or you can set the name with the method SetName() if you want to change it. */ itkGetMacro(Name,std::string); /** @brief Sets the human readable name of this source. There is also a default name, * but you can use this method if you need to define it on your own. */ itkSetMacro(Name,std::string); /** *\brief return the output (output with id 0) of the filter */ NavigationData* GetOutput(void); /** *\brief return the output with id idx of the filter */ NavigationData* GetOutput(DataObjectPointerArraySizeType idx); /** *\brief return the output with name navDataName of the filter */ NavigationData* GetOutput(const std::string& navDataName); /** *\brief return the index of the output with name navDataName, -1 if no output with that name was found * * \warning if a subclass has outputs that have different data type than mitk::NavigationData, they have to overwrite this method */ DataObjectPointerArraySizeType GetOutputIndex(std::string navDataName); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. * To unregister, call UnregisterMicroservice(). */ virtual void RegisterAsMicroservice(); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. */ virtual void UnRegisterMicroservice(); /** *\brief Returns the id that this device is registered with. The id will only be valid, if the * NavigationDataSource has been registered using RegisterAsMicroservice(). */ std::string GetMicroserviceID(); /** *\brief These Constants are used in conjunction with Microservices */ static const std::string US_INTERFACE_NAME; static const std::string US_PROPKEY_DEVICENAME; static const std::string US_PROPKEY_ID; static const std::string US_PROPKEY_ISACTIVE; //NOT IMPLEMENTED YET! /** *\brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::GraftNthOutput for details */ virtual void GraftNthOutput(unsigned int idx, itk::DataObject *graft); /** * \brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::Graft Output for details */ virtual void GraftOutput(itk::DataObject *graft); /** * Allocates a new output object and returns it. Currently the * index idx is not evaluated. * @param idx the index of the output for which an object should be created * @returns the new object */ virtual itk::DataObject::Pointer MakeOutput ( DataObjectPointerArraySizeType idx ); /** * This is a default implementation to make sure we have something. * Once all the subclasses of ProcessObject provide an appopriate * MakeOutput(), then ProcessObject::MakeOutput() can be made pure * virtual. */ virtual itk::DataObject::Pointer MakeOutput(const DataObjectIdentifierType &name); /** * \brief Set all filter parameters as the PropertyList p * * This method allows to set all parameters of a filter with one * method call. For the names of the parameters, take a look at * the GetParameters method of the filter * This method has to be overwritten by each MITK-IGT filter. */ virtual void SetParameters(const mitk::PropertyList*){}; /** * \brief Get all filter parameters as a PropertyList * * This method allows to get all parameters of a filter with one * method call. The returned PropertyList must be assigned to a * SmartPointer immediately, or else it will get destroyed. * Every filter must overwrite this method to create a filter-specific * PropertyList. Note that property names must be unique over all * MITK-IGT filters. Therefore each filter should use its name as a prefix * for each property name. * Secondly, each filter should list the property names and data types * in the method documentation. */ virtual mitk::PropertyList::ConstPointer GetParameters() const; + /** Freezes the navigation data source which means the current state is frozen and the output + * navigation data stays at it is. Calling Update() does not have any effect until UnFreeze() + * is called. This also means that the data source is not updated any more. */ + virtual void Freeze(); + + /** Unfreezes the data source. */ + virtual void UnFreeze(); + + /** @return Returns whether the data source is currently frozen. */ + itkGetMacro(IsFrozen,bool); + + protected: NavigationDataSource(); virtual ~NavigationDataSource(); std::string m_Name; + bool m_IsFrozen; + private: us::ServiceRegistration m_ServiceRegistration; }; } // namespace mitk // This is the microservice declaration. Do not meddle! MITK_DECLARE_SERVICE_INTERFACE(mitk::NavigationDataSource, "org.mitk.services.NavigationDataSource") #endif /* MITKNAVIGATIONDATASOURCE_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/DataManagement/mitkTrackingDeviceSource.cpp b/Modules/IGT/DataManagement/mitkTrackingDeviceSource.cpp index bc7b5c929d..38929bef77 100644 --- a/Modules/IGT/DataManagement/mitkTrackingDeviceSource.cpp +++ b/Modules/IGT/DataManagement/mitkTrackingDeviceSource.cpp @@ -1,213 +1,213 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTrackingDeviceSource.h" #include "mitkTrackingDevice.h" #include "mitkTrackingTool.h" #include "mitkIGTTimeStamp.h" #include "mitkIGTException.h" mitk::TrackingDeviceSource::TrackingDeviceSource() : mitk::NavigationDataSource(), m_TrackingDevice(NULL) { } mitk::TrackingDeviceSource::~TrackingDeviceSource() { if (m_TrackingDevice.IsNotNull()) { if (m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking) { this->StopTracking(); } if (m_TrackingDevice->GetState() == mitk::TrackingDevice::Ready) { this->Disconnect(); } m_TrackingDevice = NULL; } } void mitk::TrackingDeviceSource::GenerateData() { - if (m_TrackingDevice.IsNull()) - return; + if (m_IsFrozen) {return;} //no update at all if device is frozen + else if (m_TrackingDevice.IsNull()) {return;} if (m_TrackingDevice->GetToolCount() < 1) return; if (this->GetNumberOfIndexedOutputs() != m_TrackingDevice->GetToolCount()) // mismatch between tools and outputs. What should we do? Were tools added to the tracking device after SetTrackingDevice() was called? { //check this: TODO: ////this might happen if a tool is plugged into an aurora during tracking. //this->CreateOutputs(); std::stringstream ss; ss << "mitk::TrackingDeviceSource: not enough outputs available for all tools. " << this->GetNumberOfOutputs() << " outputs available, but " << m_TrackingDevice->GetToolCount() << " tools available in the tracking device."; throw std::out_of_range(ss.str()); } /* update outputs with tracking data from tools */ unsigned int toolCount = m_TrackingDevice->GetToolCount(); for (unsigned int i = 0; i < toolCount; ++i) { mitk::NavigationData* nd = this->GetOutput(i); assert(nd); mitk::TrackingTool* t = m_TrackingDevice->GetTool(i); assert(t); if ((t->IsEnabled() == false) || (t->IsDataValid() == false)) { nd->SetDataValid(false); continue; } nd->SetDataValid(true); mitk::NavigationData::PositionType p; t->GetPosition(p); nd->SetPosition(p); mitk::NavigationData::OrientationType o; t->GetOrientation(o); nd->SetOrientation(o); nd->SetOrientationAccuracy(t->GetTrackingError()); nd->SetPositionAccuracy(t->GetTrackingError()); nd->SetIGTTimeStamp(t->GetIGTTimeStamp()); //for backward compatibility: check if the timestamp was set, if not create a default timestamp if (nd->GetIGTTimeStamp()==0) nd->SetIGTTimeStamp(mitk::IGTTimeStamp::GetInstance()->GetElapsed()); } } void mitk::TrackingDeviceSource::SetTrackingDevice( mitk::TrackingDevice* td ) { MITK_DEBUG << "Setting TrackingDevice to " << td; if (this->m_TrackingDevice.GetPointer() != td) { this->m_TrackingDevice = td; this->CreateOutputs(); std::stringstream name; // create a human readable name for the source name << td->GetData().Model << " Tracking Source"; this->SetName(name.str()); } } void mitk::TrackingDeviceSource::CreateOutputs(){ //if outputs are set then delete them if (this->GetNumberOfOutputs() > 0) { for (int numOP = this->GetNumberOfOutputs() -1; numOP >= 0; numOP--) this->RemoveOutput(numOP); this->Modified(); } //fill the outputs if a valid tracking device is set if (m_TrackingDevice.IsNull()) return; this->SetNumberOfIndexedOutputs(m_TrackingDevice->GetToolCount()); // create outputs for all tools unsigned int numberOfOutputs = this->GetNumberOfIndexedOutputs(); MITK_DEBUG << "Number of tools at start of method CreateOutputs(): " << m_TrackingDevice->GetToolCount(); MITK_DEBUG << "Number of outputs at start of method CreateOutputs(): " << numberOfOutputs; for (unsigned int idx = 0; idx < m_TrackingDevice->GetToolCount(); ++idx) { if (this->GetOutput(idx) == NULL) { DataObjectPointer newOutput = this->MakeOutput(idx); static_cast(newOutput.GetPointer())->SetName(m_TrackingDevice->GetTool(idx)->GetToolName()); // set NavigationData name to ToolName this->SetNthOutput(idx, newOutput); this->Modified(); } } } void mitk::TrackingDeviceSource::Connect() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (this->IsConnected()) return; try {m_TrackingDevice->OpenConnection();} catch (mitk::IGTException &e) { throw std::runtime_error(std::string("mitk::TrackingDeviceSource: Could not open connection to tracking device. Error: ") + e.GetDescription()); } /* NDI Aurora needs a connection to discover tools that are connected to it. Therefore we need to create outputs for these tools now */ //if (m_TrackingDevice->GetType() == mitk::NDIAurora) //this->CreateOutputs(); } void mitk::TrackingDeviceSource::StartTracking() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking) return; if (m_TrackingDevice->StartTracking() == false) throw std::runtime_error("mitk::TrackingDeviceSource: Could not start tracking"); } void mitk::TrackingDeviceSource::Disconnect() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (m_TrackingDevice->CloseConnection() == false) throw std::runtime_error("mitk::TrackingDeviceSource: Could not close connection to tracking device"); } void mitk::TrackingDeviceSource::StopTracking() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (m_TrackingDevice->StopTracking() == false) throw std::runtime_error("mitk::TrackingDeviceSource: Could not stop tracking"); } void mitk::TrackingDeviceSource::UpdateOutputInformation() { if(this->GetTrackingDevice()->GetToolCount() != this->GetNumberOfIndexedOutputs()) this->CreateOutputs(); this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } //unsigned int mitk::TrackingDeviceSource::GetToolCount() //{ // if (m_TrackingDevice) // return m_TrackingDevice->GetToolCount(); // return 0; //} bool mitk::TrackingDeviceSource::IsConnected() { if (m_TrackingDevice.IsNull()) return false; return (m_TrackingDevice->GetState() == mitk::TrackingDevice::Ready) || (m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking); } bool mitk::TrackingDeviceSource::IsTracking() { if (m_TrackingDevice.IsNull()) return false; return m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking; } diff --git a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp index 22bfb69930..6c49aab91b 100644 --- a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp +++ b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp @@ -1,306 +1,332 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTrackingDeviceSourceConfigurator.h" #include "mitkNDITrackingDevice.h" #include "mitkClaronTrackingDevice.h" #include "mitkOptitrackTrackingDevice.h" +#include "mitkVirtualTrackingDevice.h" #include #include mitk::TrackingDeviceSourceConfigurator::TrackingDeviceSourceConfigurator(mitk::NavigationToolStorage::Pointer NavigationTools, mitk::TrackingDevice::Pointer TrackingDevice) { //make a copy of the navigation tool storage because we will modify the storage if (NavigationTools.IsNotNull()) { m_NavigationTools = mitk::NavigationToolStorage::New(); for (int i=0; iGetToolCount(); i++) { m_NavigationTools->AddTool(NavigationTools->GetTool(i)); } } m_TrackingDevice = TrackingDevice; m_ToolCorrespondencesInToolStorage = std::vector(); m_ErrorMessage = ""; } mitk::NavigationToolStorage::Pointer mitk::TrackingDeviceSourceConfigurator::GetUpdatedNavigationToolStorage() { return m_NavigationTools; } mitk::TrackingDeviceSourceConfigurator::~TrackingDeviceSourceConfigurator() { } bool mitk::TrackingDeviceSourceConfigurator::IsCreateTrackingDeviceSourcePossible() { if (m_NavigationTools.IsNull()) { m_ErrorMessage = "NavigationToolStorage is NULL!"; return false; } else if (m_TrackingDevice.IsNull()) { m_ErrorMessage = "TrackingDevice is NULL!"; return false; } else { for (int i=0; iGetToolCount(); i++) { if (m_NavigationTools->GetTool(i)->GetTrackingDeviceType() != m_TrackingDevice->GetType()) { m_ErrorMessage = "At least one tool is not of the same type like the tracking device."; return false; } } //TODO in case of Aurora: check if the tools are automatically detected by comparing the serial number return true; } } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateTrackingDeviceSource() { mitk::NavigationDataObjectVisualizationFilter::Pointer dummy; //this dummy is lost directly after creating the device return this->CreateTrackingDeviceSource(dummy); } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateTrackingDeviceSource(mitk::NavigationDataObjectVisualizationFilter::Pointer &visualizationFilter) { if (!this->IsCreateTrackingDeviceSourcePossible()) {MITK_WARN << "Cannot create tracking decive: " << m_ErrorMessage; return NULL;} mitk::TrackingDeviceSource::Pointer returnValue; //create tracking device source if (m_TrackingDevice->GetType()==mitk::NDIAurora) {returnValue = CreateNDIAuroraTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} else if (m_TrackingDevice->GetType()==mitk::NDIPolaris) {returnValue = CreateNDIPolarisTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} else if (m_TrackingDevice->GetType()==mitk::ClaronMicron) {returnValue = CreateMicronTrackerTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} else if (m_TrackingDevice->GetType()==mitk::NPOptitrack) {returnValue = CreateNPOptitrackTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} + else if (m_TrackingDevice->GetType()==mitk::VirtualTracker) {returnValue = CreateVirtualTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} //TODO: insert other tracking systems? if (returnValue.IsNull()) {MITK_WARN << "Cannot create tracking decive: " << m_ErrorMessage; return NULL;} //create visualization filter visualizationFilter = CreateNavigationDataObjectVisualizationFilter(returnValue,m_NavigationTools); if (visualizationFilter.IsNull()) {MITK_WARN << "Cannot create tracking decive: " << m_ErrorMessage; return NULL;} return returnValue; } std::string mitk::TrackingDeviceSourceConfigurator::GetErrorMessage() { return this->m_ErrorMessage; } //############################ internal help methods ######################################## mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateNDIPolarisTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::NDITrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); m_ToolCorrespondencesInToolStorage = std::vector(); //add the tools to the tracking device for (int i=0; iGetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = m_NavigationTools->GetTool(i); m_ToolCorrespondencesInToolStorage.push_back(i); bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str(),thisNavigationTool->GetCalibrationFile().c_str()); if (!toolAddSuccess) { //todo: error handling this->m_ErrorMessage = "Can't add tool, is the SROM-file valid?"; return NULL; } thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(),thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateNDIAuroraTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) { MITK_DEBUG << "Creating Aurora tracking device."; mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::NDITrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); try { //connect to aurora to dectect tools automatically thisDevice->OpenConnection(); } catch (mitk::IGTHardwareException& e) { m_ErrorMessage = std::string("Hardware error on opening the connection (") + e.GetDescription() + ")"; return NULL; } catch (mitk::IGTException& e) { m_ErrorMessage = std::string("Error on opening the connection (") + e.GetDescription() + ")"; return NULL; } //now search for automatically detected tools in the tool storage and save them mitk::NavigationToolStorage::Pointer newToolStorageInRightOrder = mitk::NavigationToolStorage::New(); std::vector alreadyFoundTools = std::vector(); m_ToolCorrespondencesInToolStorage = std::vector(); for (unsigned int i=0; iGetToolCount(); i++) { bool toolFound = false; for (int j=0; jGetToolCount(); j++) { //check if the serial number is the same to identify the tool if ((dynamic_cast(thisDevice->GetTool(i)))->GetSerialNumber() == navigationTools->GetTool(j)->GetSerialNumber()) { //check if this tool was already added to make sure that every tool is only added once (in case of same serial numbers) bool toolAlreadyAdded = false; for(unsigned int k=0; kAddTool(navigationTools->GetTool(j)); m_ToolCorrespondencesInToolStorage.push_back(j); //adapt name of tool dynamic_cast(thisDevice->GetTool(i))->SetToolName(navigationTools->GetTool(j)->GetToolName()); //set tip of tool dynamic_cast(thisDevice->GetTool(i))->SetToolTip(navigationTools->GetTool(j)->GetToolTipPosition(),navigationTools->GetTool(j)->GetToolTipOrientation()); //rember that this tool was already found alreadyFoundTools.push_back(j); toolFound = true; break; } } } if (!toolFound) { this->m_ErrorMessage = "Error: did not find every automatically detected tool in the loaded tool storage: aborting initialization."; return NULL; } } //delete all tools from the tool storage navigationTools->DeleteAllTools(); //and add only the detected tools in the right order for (int i=0; iGetToolCount(); i++) { navigationTools->AddTool(newToolStorageInRightOrder->GetTool(i)); } returnValue->SetTrackingDevice(thisDevice); MITK_DEBUG << "Number of tools of created tracking device: " << thisDevice->GetToolCount(); MITK_DEBUG << "Number of outputs of created source: " << returnValue->GetNumberOfOutputs(); return returnValue; } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateMicronTrackerTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::ClaronTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); m_ToolCorrespondencesInToolStorage = std::vector(); //add the tools to the tracking device for (int i=0; iGetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = m_NavigationTools->GetTool(i); m_ToolCorrespondencesInToolStorage.push_back(i); bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str(),thisNavigationTool->GetCalibrationFile().c_str()); if (!toolAddSuccess) { //todo error handling this->m_ErrorMessage = "Can't add tool, is the toolfile valid?"; return NULL; } thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(),thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateNPOptitrackTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::OptitrackTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); m_ToolCorrespondencesInToolStorage = std::vector(); //OpenConnection with Optitrack thisDevice->OpenConnection(); //add the tools to the tracking device for (int i=0; iGetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = m_NavigationTools->GetTool(i); m_ToolCorrespondencesInToolStorage.push_back(i); bool toolAddSuccess = thisDevice->AddToolByDefinitionFile(thisNavigationTool->GetCalibrationFile()); thisDevice->GetOptitrackTool(i)->SetToolName(thisNavigationTool->GetToolName().c_str()); if (!toolAddSuccess) { //todo error handling this->m_ErrorMessage = "Can't add tool, is the toolfile valid?"; return NULL; } //thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(),thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } + +mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateVirtualTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) + { + mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); + mitk::VirtualTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); + m_ToolCorrespondencesInToolStorage = std::vector(); + + //add the tools to the tracking device + for (int i=0; iGetToolCount(); i++) + { + mitk::NavigationTool::Pointer thisNavigationTool = m_NavigationTools->GetTool(i); + m_ToolCorrespondencesInToolStorage.push_back(i); + bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str()); + if (!toolAddSuccess) + { + //todo error handling + this->m_ErrorMessage = "Can't add tool, is the toolfile valid?"; + return NULL; + } + } + returnValue->SetTrackingDevice(thisDevice); + return returnValue; + } + mitk::NavigationDataObjectVisualizationFilter::Pointer mitk::TrackingDeviceSourceConfigurator::CreateNavigationDataObjectVisualizationFilter(mitk::TrackingDeviceSource::Pointer trackingDeviceSource, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::NavigationDataObjectVisualizationFilter::Pointer returnValue = mitk::NavigationDataObjectVisualizationFilter::New(); for (unsigned int i=0; iGetNumberOfIndexedOutputs(); i++) { mitk::NavigationTool::Pointer currentTool = navigationTools->GetToolByName(trackingDeviceSource->GetOutput(i)->GetName()); if (currentTool.IsNull()) { this->m_ErrorMessage = "Error: did not find correspondig tool in tracking device after initialization."; return NULL; } returnValue->SetInput(i,trackingDeviceSource->GetOutput(i)); returnValue->SetRepresentationObject(i,currentTool->GetDataNode()->GetData()); } return returnValue; } int mitk::TrackingDeviceSourceConfigurator::GetToolNumberInToolStorage(unsigned int outputID) { if (outputID < m_ToolCorrespondencesInToolStorage.size()) return m_ToolCorrespondencesInToolStorage.at(outputID); else return -1; } std::string mitk::TrackingDeviceSourceConfigurator::GetToolIdentifierInToolStorage(unsigned int outputID) { if (outputID < m_ToolCorrespondencesInToolStorage.size()) return m_NavigationTools->GetTool(m_ToolCorrespondencesInToolStorage.at(outputID))->GetIdentifier(); else return ""; } std::vector mitk::TrackingDeviceSourceConfigurator::GetToolNumbersInToolStorage() { return m_ToolCorrespondencesInToolStorage; } std::vector mitk::TrackingDeviceSourceConfigurator::GetToolIdentifiersInToolStorage() { std::vector returnValue = std::vector(); for (unsigned int i=0; iGetTool(m_ToolCorrespondencesInToolStorage.at(i))->GetIdentifier());} return returnValue; } diff --git a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.h b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.h index 0ecee7d843..ab71f032f2 100644 --- a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.h +++ b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.h @@ -1,106 +1,107 @@ /*=================================================================== 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 MITKTRACKINGDEVICESOURCECONFIGURATOR_H_HEADER_INCLUDED_ #define MITKTRACKINGDEVICESOURCECONFIGURATOR_H_HEADER_INCLUDED_ #include //itk includes #include //mitk IGT includes #include "mitkTrackingDeviceSource.h" #include "mitkNavigationToolStorage.h" #include "mitkNavigationDataObjectVisualizationFilter.h" namespace mitk { /**Documentation * \brief This class offers a factory method for objects of the class TrackingDeviceSource. It initializes this TrackingDeviceSource with * the given navigation tools and the given tracking device. The factory method also checks if all tools are valid and of the same * type like the TrackingDevice. You can do this check before trying to create the TrackingDeviceSource by calling the method * IsCreateTrackingDeviceSourcePossible(), if it returns false you might want to get the error message by calling the method * GetErrorMessage(). * \ingroup IGT */ class MITKIGT_EXPORT TrackingDeviceSourceConfigurator : public itk::Object { public: mitkClassMacro(TrackingDeviceSourceConfigurator, itk::Object); mitkNewMacro2Param(Self,mitk::NavigationToolStorage::Pointer,mitk::TrackingDevice::Pointer); /** @return Returns if it's possible to create a tracking device source, which means the tools are checked * if they are of the same type like the tracking device, etc. If it returns false you can get * the reason for this by getting the error message. */ bool IsCreateTrackingDeviceSourcePossible(); /** @return Returns a new TrackingDeviceSource. Returns NULL if there was an error on creating the * TrackingDeviceSource. If there was an error it's availiable as error message. */ mitk::TrackingDeviceSource::Pointer CreateTrackingDeviceSource(); /** @return Returns a new TrackingDeviceSource. Returns NULL if there was an error on creating the * TrackingDeviceSource. If there was an error it's availiable as error message. * @param visualizationFilter (return value) returns a visualization filter which is already connected to the tracking device source. * This filter visualises the surfaces which are availiable by the navigation tool storage. */ mitk::TrackingDeviceSource::Pointer CreateTrackingDeviceSource(mitk::NavigationDataObjectVisualizationFilter::Pointer &visualizationFilter); /** @return Returns the internal number of the corresponding tool in the tool storage of a output navigation data. Returns -1 if there was an error. */ int GetToolNumberInToolStorage(unsigned int outputID); /** @return Returns the identifier of the corresponding tool in the tool storage of a output navigation data. Returns an empty string if there was an error.*/ std::string GetToolIdentifierInToolStorage(unsigned int outputID); /** @return Returns a vector with all internal numbers of the corresponding tools in the tool storage of all outputs. * The order is the same like the order of the outputs. Returns an empty vector if there was an error. */ std::vector GetToolNumbersInToolStorage(); /** @return Returns a vector with all identifier of the corresponding tools in the tool storage of all outputs. * The order is the same like the order of the outputs. Returns an empty vector if there was an error. */ std::vector GetToolIdentifiersInToolStorage(); /** @return Returns a modified navigation tool storage which holds the tools currently in use in * the same order like the output ids of the pipline. */ mitk::NavigationToolStorage::Pointer GetUpdatedNavigationToolStorage(); /** @return Returns the current error message. Returns an empty string if there was no error. */ std::string GetErrorMessage(); protected: TrackingDeviceSourceConfigurator(mitk::NavigationToolStorage::Pointer NavigationTools, mitk::TrackingDevice::Pointer TrackingDevice); virtual ~TrackingDeviceSourceConfigurator(); mitk::NavigationToolStorage::Pointer m_NavigationTools; mitk::TrackingDevice::Pointer m_TrackingDevice; std::string m_ErrorMessage; std::vector m_ToolCorrespondencesInToolStorage; mitk::TrackingDeviceSource::Pointer CreateNDIPolarisTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); mitk::TrackingDeviceSource::Pointer CreateNDIAuroraTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); mitk::TrackingDeviceSource::Pointer CreateMicronTrackerTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); mitk::TrackingDeviceSource::Pointer CreateNPOptitrackTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); + mitk::TrackingDeviceSource::Pointer CreateVirtualTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); mitk::NavigationDataObjectVisualizationFilter::Pointer CreateNavigationDataObjectVisualizationFilter(mitk::TrackingDeviceSource::Pointer trackingDeviceSource, mitk::NavigationToolStorage::Pointer navigationTools); }; } // namespace mitk #endif /* MITKTrackingDeviceSource_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationToolWriter.cpp b/Modules/IGT/IO/mitkNavigationToolWriter.cpp index 6895d06bae..1cb2165199 100644 --- a/Modules/IGT/IO/mitkNavigationToolWriter.cpp +++ b/Modules/IGT/IO/mitkNavigationToolWriter.cpp @@ -1,142 +1,169 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //Poco headers #include #include //mitk headers #include "mitkNavigationToolWriter.h" #include #include #include #include #include //std headers #include mitk::NavigationToolWriter::NavigationToolWriter() { } mitk::NavigationToolWriter::~NavigationToolWriter() { } bool mitk::NavigationToolWriter::DoWrite(std::string FileName,mitk::NavigationTool::Pointer Tool) { + //some initial validation checks... + if ( Tool.IsNull()) + { + m_ErrorMessage = "Cannot write a navigation tool containing invalid tool data, aborting!"; + MITK_ERROR << m_ErrorMessage; + return false; + } + + + // Workaround for a problem: the geometry might be modified if the tool is tracked. If this + // modified geometry is saved the surface representation is moved by this offset. To avoid + // this bug, the geometry is set to identity for the saving progress and restored later. + mitk::BaseGeometry::Pointer geometryBackup; + if ( Tool->GetDataNode().IsNull() + || (Tool->GetDataNode()->GetData()==NULL) + || (Tool->GetDataNode()->GetData()->GetGeometry()==NULL) + ) + { + geometryBackup = Tool->GetDataNode()->GetData()->GetGeometry()->Clone(); + Tool->GetDataNode()->GetData()->GetGeometry()->SetIdentity(); + } + else {MITK_WARN << "Saving a tool with invalid data node, proceeding but errors might occure!";} + //convert whole data to a mitk::DataStorage mitk::StandaloneDataStorage::Pointer saveStorage = mitk::StandaloneDataStorage::New(); mitk::DataNode::Pointer thisTool = ConvertToDataNode(Tool); saveStorage->Add(thisTool); //use SceneSerialization to save the DataStorage std::string DataStorageFileName = mitk::IOUtil::CreateTemporaryDirectory() + Poco::Path::separator() + GetFileWithoutPath(FileName) + ".storage"; mitk::SceneIO::Pointer mySceneIO = mitk::SceneIO::New(); mySceneIO->SaveScene(saveStorage->GetAll(),saveStorage,DataStorageFileName); //now put the DataStorage and the Toolfile in a ZIP-file std::ofstream file( FileName.c_str(), std::ios::binary | std::ios::out); if (!file.good()) { m_ErrorMessage = "Could not open a zip file for writing: '" + FileName + "'"; + MITK_ERROR << m_ErrorMessage; return false; } else { Poco::Zip::Compress zipper( file, true ); zipper.addFile(DataStorageFileName,GetFileWithoutPath(DataStorageFileName)); if (Tool->GetCalibrationFile()!="none") zipper.addFile(Tool->GetCalibrationFile(),GetFileWithoutPath(Tool->GetCalibrationFile())); zipper.close(); } //delete the data storage std::remove(DataStorageFileName.c_str()); + //restore original geometry + if (geometryBackup.IsNotNull()) {Tool->GetDataNode()->GetData()->SetGeometry(geometryBackup);} + return true; } mitk::DataNode::Pointer mitk::NavigationToolWriter::ConvertToDataNode(mitk::NavigationTool::Pointer Tool) { mitk::DataNode::Pointer thisTool = mitk::DataNode::New(); //Name if (Tool->GetDataNode().IsNull()) thisTool->SetName("none"); else thisTool->SetName(Tool->GetDataNode()->GetName().c_str()); //Identifier thisTool->AddProperty("identifier",mitk::StringProperty::New(Tool->GetIdentifier().c_str())); //Serial Number thisTool->AddProperty("serial number",mitk::StringProperty::New(Tool->GetSerialNumber().c_str())); //Tracking Device thisTool->AddProperty("tracking device type",mitk::IntProperty::New(Tool->GetTrackingDeviceType())); //Tool Type thisTool->AddProperty("tracking tool type",mitk::IntProperty::New(Tool->GetType())); //Calibration File Name thisTool->AddProperty("toolfileName",mitk::StringProperty::New(GetFileWithoutPath(Tool->GetCalibrationFile()))); //Surface if (Tool->GetDataNode().IsNotNull()) if (Tool->GetDataNode()->GetData()!=NULL) thisTool->SetData(Tool->GetDataNode()->GetData()); //Tool Landmarks thisTool->AddProperty("ToolRegistrationLandmarks",mitk::StringProperty::New(ConvertPointSetToString(Tool->GetToolRegistrationLandmarks()))); thisTool->AddProperty("ToolCalibrationLandmarks",mitk::StringProperty::New(ConvertPointSetToString(Tool->GetToolCalibrationLandmarks()))); //Tool Tip if (Tool->IsToolTipSet()) { thisTool->AddProperty("ToolTipPosition",mitk::StringProperty::New(ConvertPointToString(Tool->GetToolTipPosition()))); thisTool->AddProperty("ToolTipOrientation",mitk::StringProperty::New(ConvertQuaternionToString(Tool->GetToolTipOrientation()))); } //Material is not needed, to avoid errors in scene serialization we have to do this: thisTool->ReplaceProperty("material",NULL); return thisTool; } std::string mitk::NavigationToolWriter::GetFileWithoutPath(std::string FileWithPath) { Poco::Path myFile(FileWithPath.c_str()); return myFile.getFileName(); } std::string mitk::NavigationToolWriter::ConvertPointSetToString(mitk::PointSet::Pointer pointSet) { std::stringstream returnValue; mitk::PointSet::PointDataIterator it; for ( it = pointSet->GetPointSet()->GetPointData()->Begin();it != pointSet->GetPointSet()->GetPointData()->End();it++ ) { mitk::Point3D thisPoint = pointSet->GetPoint(it->Index()); returnValue << it->Index() << ";" << ConvertPointToString(thisPoint) << "|"; } return returnValue.str(); } std::string mitk::NavigationToolWriter::ConvertPointToString(mitk::Point3D point) { std::stringstream returnValue; returnValue << point[0] << ";" << point[1] << ";" << point[2]; return returnValue.str(); } std::string mitk::NavigationToolWriter::ConvertQuaternionToString(mitk::Quaternion quat) { std::stringstream returnValue; returnValue << quat.x() << ";" << quat.y() << ";" << quat.z() << ";" << quat.r(); return returnValue.str(); } diff --git a/Modules/IGT/Testing/files.cmake b/Modules/IGT/Testing/files.cmake index daf0b4f348..8a89a47489 100644 --- a/Modules/IGT/Testing/files.cmake +++ b/Modules/IGT/Testing/files.cmake @@ -1,64 +1,64 @@ set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## ON THE FENCE TESTS ################################################# # none ################## DISABLED TESTS ##################################################### # mitkNavigationToolStorageDeserializerTest.cpp # This test was disabled because of bug 17303. # mitkNavigationToolStorageSerializerAndDeserializerIntegrationTest.cpp # This test was disabled because of bug 17181. + # mitkNavigationToolStorageSerializerTest.cpp # This test was disabled because of bug 18671 ################# RUNNING TESTS ####################################################### mitkCameraVisualizationTest.cpp mitkClaronInterfaceTest.cpp mitkClaronToolTest.cpp mitkClaronTrackingDeviceTest.cpp mitkInternalTrackingToolTest.cpp mitkNavigationDataDisplacementFilterTest.cpp mitkNavigationDataLandmarkTransformFilterTest.cpp mitkNavigationDataObjectVisualizationFilterTest.cpp mitkNavigationDataSetTest.cpp mitkNavigationDataTest.cpp mitkNavigationDataRecorderTest.cpp mitkNavigationDataReferenceTransformFilterTest.cpp mitkNavigationDataSequentialPlayerTest.cpp mitkNavigationDataSetReaderWriterXMLTest.cpp mitkNavigationDataSetReaderWriterCSVTest.cpp mitkNavigationDataSourceTest.cpp mitkNavigationDataToMessageFilterTest.cpp mitkNavigationDataToNavigationDataFilterTest.cpp mitkNavigationDataToPointSetFilterTest.cpp mitkNavigationDataTransformFilterTest.cpp mitkNDIPassiveToolTest.cpp mitkNDIProtocolTest.cpp mitkNDITrackingDeviceTest.cpp mitkTimeStampTest.cpp mitkTrackingVolumeGeneratorTest.cpp mitkTrackingDeviceTest.cpp mitkTrackingToolTest.cpp mitkVirtualTrackingDeviceTest.cpp # mitkNavigationDataPlayerTest.cpp # random fails see bug 16485. # We decided to won't fix because of complete restructuring via bug 15959. mitkTrackingDeviceSourceTest.cpp mitkTrackingDeviceSourceConfiguratorTest.cpp mitkNavigationDataEvaluationFilterTest.cpp mitkTrackingTypesTest.cpp # ------------------ Navigation Tool Management Tests ------------------- mitkNavigationToolStorageTest.cpp mitkNavigationToolTest.cpp mitkNavigationToolReaderAndWriterTest.cpp - mitkNavigationToolStorageSerializerTest.cpp # ----------------------------------------------------------------------- ) set(MODULE_CUSTOM_TESTS mitkNDIAuroraHardwareTest.cpp mitkNDIPolarisHardwareTest.cpp mitkClaronTrackingDeviceHardwareTest.cpp ) diff --git a/Modules/IGT/Testing/mitkNavigationToolReaderAndWriterTest.cpp b/Modules/IGT/Testing/mitkNavigationToolReaderAndWriterTest.cpp index 28f6d740c1..70ad72db64 100644 --- a/Modules/IGT/Testing/mitkNavigationToolReaderAndWriterTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationToolReaderAndWriterTest.cpp @@ -1,198 +1,224 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //Poco headers #include "Poco/Path.h" //mitk headers #include "mitkNavigationToolWriter.h" #include "mitkCommon.h" #include "mitkTestingMacros.h" #include "mitkNavigationTool.h" #include "mitkBaseData.h" #include "mitkDataNode.h" #include "mitkSurface.h" #include "mitkStandaloneDataStorage.h" #include "mitkDataStorage.h" #include "mitkNavigationToolReader.h" #include "mitkIGTConfig.h" #include #include #include mitk::Surface::Pointer m_testSurface; static void TestInstantiation() { // let's create an object of our class mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); MITK_TEST_CONDITION_REQUIRED(myWriter.IsNotNull(),"Testing instantiation") } static void TestWrite() { //testcase with first test tool: a claron tool //create a NavigationTool which we can write on the harddisc std::string toolFileName(MITK_IGT_DATA_DIR); toolFileName.append("/ClaronTool"); mitk::NavigationTool::Pointer myNavigationTool = mitk::NavigationTool::New(); myNavigationTool->SetCalibrationFile(toolFileName); mitk::DataNode::Pointer myNode = mitk::DataNode::New(); myNode->SetName("ClaronTool"); std::string surfaceFileName(MITK_IGT_DATA_DIR); surfaceFileName.append("/ClaronTool.stl"); m_testSurface = mitk::IOUtil::LoadSurface( surfaceFileName ); myNode->SetData(m_testSurface); myNavigationTool->SetDataNode(myNode); myNavigationTool->SetIdentifier("ClaronTool#1"); myNavigationTool->SetSerialNumber("0815"); myNavigationTool->SetTrackingDeviceType(mitk::ClaronMicron); myNavigationTool->SetType(mitk::NavigationTool::Fiducial); //now create a writer and write it to the harddisc mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = "TestTool.tool"; MITK_TEST_OUTPUT(<<"---- Testing navigation tool writer with first test tool (claron tool) ----"); bool test = myWriter->DoWrite(filename,myNavigationTool); MITK_TEST_CONDITION_REQUIRED(test,"OK"); } static void TestRead() { mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); mitk::NavigationTool::Pointer readTool = myReader->DoRead("TestTool.tool"); MITK_TEST_OUTPUT(<<"---- Testing navigation tool reader with first test tool (claron tool) ----"); //Test if the surfaces do have the same number of vertexes (it would be better to test for real equality of the surfaces!) MITK_TEST_CONDITION_REQUIRED(dynamic_cast(readTool->GetDataNode()->GetData())->GetSizeOfPolyDataSeries()==m_testSurface->GetSizeOfPolyDataSeries(),"Test if surface was restored correctly ..."); MITK_TEST_CONDITION_REQUIRED(readTool->GetType()==mitk::NavigationTool::Fiducial,"Testing Tool Type"); MITK_TEST_CONDITION_REQUIRED(readTool->GetTrackingDeviceType()==mitk::ClaronMicron,"Testing Tracking Device Type"); MITK_TEST_CONDITION_REQUIRED(readTool->GetSerialNumber()=="0815","Testing Serial Number"); std::ifstream TestFile(readTool->GetCalibrationFile().c_str()); MITK_TEST_CONDITION_REQUIRED(TestFile,"Testing If Calibration File Exists"); } static void TestWrite2() { //testcase with second test tool: an aurora tool //create a NavigationTool which we can write on the harddisc mitk::NavigationTool::Pointer myNavigationTool = mitk::NavigationTool::New(); mitk::DataNode::Pointer myNode = mitk::DataNode::New(); myNode->SetName("AuroraTool"); std::string surfaceFileName(MITK_IGT_DATA_DIR); surfaceFileName.append("/EMTool.stl"); m_testSurface = mitk::IOUtil::LoadSurface( surfaceFileName ); myNode->SetData(m_testSurface); myNavigationTool->SetDataNode(myNode); myNavigationTool->SetIdentifier("AuroraTool#1"); myNavigationTool->SetSerialNumber("0816"); myNavigationTool->SetTrackingDeviceType(mitk::NDIAurora); myNavigationTool->SetType(mitk::NavigationTool::Instrument); //now create a writer and write it to the harddisc mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = "TestTool2.tool"; MITK_TEST_OUTPUT(<<"---- Testing navigation tool writer with second tool (aurora tool) ----"); bool test = myWriter->DoWrite(filename,myNavigationTool); MITK_TEST_CONDITION_REQUIRED(test,"OK"); } static void TestRead2() { mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); mitk::NavigationTool::Pointer readTool = myReader->DoRead("TestTool2.tool"); MITK_TEST_OUTPUT(<<"---- Testing navigation tool reader with second tool (aurora tool) ----"); //Test if the surfaces do have the same number of vertexes (it would be better to test for real equality of the surfaces!) MITK_TEST_CONDITION_REQUIRED(dynamic_cast(readTool->GetDataNode()->GetData())->GetSizeOfPolyDataSeries()==m_testSurface->GetSizeOfPolyDataSeries(),"Test if surface was restored correctly ..."); //Test if the tool type is the same MITK_TEST_CONDITION_REQUIRED(readTool->GetType()==mitk::NavigationTool::Instrument,"Testing Tool Type"); MITK_TEST_CONDITION_REQUIRED(readTool->GetTrackingDeviceType()==mitk::NDIAurora,"Testing Tracking Device Type"); MITK_TEST_CONDITION_REQUIRED(readTool->GetSerialNumber()=="0816","Testing Serial Number"); MITK_TEST_CONDITION_REQUIRED(readTool->GetCalibrationFile()=="none","Testing Calibration File"); } static void CleanUp() { std::remove("TestTool.tool"); std::remove("TestTool2.tool"); } static void TestReadInvalidData() { mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); mitk::NavigationTool::Pointer readTool = myReader->DoRead("invalidTool"); MITK_TEST_CONDITION_REQUIRED(readTool.IsNull(), "Testing return value if filename is invalid"); MITK_TEST_CONDITION_REQUIRED(myReader->GetErrorMessage() == "Cannot open 'invalidTool' for reading", "Testing error message in this case"); } -static void TestWriteInvalidData() +static void TestWriteInvalidFilename() { + //create a test navigation tool mitk::NavigationTool::Pointer myNavigationTool = mitk::NavigationTool::New(); - myNavigationTool->SetIdentifier("ClaronTool#1"); - myNavigationTool->SetSerialNumber("0815"); - myNavigationTool->SetTrackingDeviceType(mitk::ClaronMicron); - myNavigationTool->SetType(mitk::NavigationTool::Fiducial); + mitk::DataNode::Pointer myNode = mitk::DataNode::New(); + myNode->SetName("AuroraTool"); + std::string surfaceFileName(MITK_IGT_DATA_DIR); + surfaceFileName.append("/EMTool.stl"); + m_testSurface = mitk::IOUtil::LoadSurface( surfaceFileName ); + myNode->SetData(m_testSurface); + myNavigationTool->SetDataNode(myNode); + myNavigationTool->SetIdentifier("AuroraTool#1"); + myNavigationTool->SetSerialNumber("0816"); + myNavigationTool->SetTrackingDeviceType(mitk::NDIAurora); + myNavigationTool->SetType(mitk::NavigationTool::Instrument); //now create a writer and write it to the harddisc mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = "NH:/sfdsfsdsf.&%%%"; MITK_TEST_OUTPUT(<<"---- Testing write invalid file ----"); bool test = myWriter->DoWrite(filename,myNavigationTool); MITK_TEST_CONDITION_REQUIRED(!test,"testing write"); MITK_TEST_CONDITION_REQUIRED(myWriter->GetErrorMessage() == "Could not open a zip file for writing: 'NH:/sfdsfsdsf.&%%%'","testing error message"); } +static void TestWriteInvalidData() +{ + mitk::NavigationTool::Pointer myNavigationTool; + //tool is invalid because no data note is created + + //now create a writer and write it to the harddisc + mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); + std::string filename = "NH:/sfdsfsdsf.&%%%"; + + MITK_TEST_OUTPUT(<<"---- Testing write invalid tool ----"); + bool test = myWriter->DoWrite(filename,myNavigationTool); + MITK_TEST_CONDITION_REQUIRED(!test,"testing write"); + MITK_TEST_CONDITION_REQUIRED(myWriter->GetErrorMessage() == "Cannot write a navigation tool containing invalid tool data, aborting!","testing error message"); +} + + + /** This function is testing the TrackingVolume class. */ int mitkNavigationToolReaderAndWriterTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationToolWriter") TestInstantiation(); TestWrite(); TestRead(); TestWrite2(); TestRead2(); TestReadInvalidData(); TestWriteInvalidData(); + TestWriteInvalidFilename(); CleanUp(); MITK_TEST_END() } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp index 5b65583c4b..7afb644a11 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp @@ -1,341 +1,346 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNavigationToolCreationWidget.h" //mitk headers -#include "mitkTrackingTypes.h" +#include #include #include -#include "mitkNavigationData.h" -#include "mitkRenderingManager.h" +#include +#include //qt headers #include #include #include //poco headers #include // vtk #include -#include "vtkConeSource.h" +#include const std::string QmitkNavigationToolCreationWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationwizardwidget"; QmitkNavigationToolCreationWidget::QmitkNavigationToolCreationWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = NULL; m_AdvancedWidget = new QmitkNavigationToolCreationAdvancedWidget(this); m_AdvancedWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); m_AdvancedWidget->setWindowTitle("Tool Creation Advanced Options"); m_AdvancedWidget->setModal(false); CreateQtPartControl(this); CreateConnections(); } QmitkNavigationToolCreationWidget::~QmitkNavigationToolCreationWidget() { m_Controls->m_CalibrationLandmarksList->SetPointSetNode(NULL); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(NULL); delete m_AdvancedWidget; } void QmitkNavigationToolCreationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolCreationWidgetControls; m_Controls->setupUi(parent); } } void QmitkNavigationToolCreationWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_cancel), SIGNAL(clicked()), this, SLOT(OnCancel()) ); connect( (QObject*)(m_Controls->m_finished), SIGNAL(clicked()), this, SLOT(OnFinished()) ); connect( (QObject*)(m_Controls->m_LoadSurface), SIGNAL(clicked()), this, SLOT(OnLoadSurface()) ); connect( (QObject*)(m_Controls->m_LoadCalibrationFile), SIGNAL(clicked()), this, SLOT(OnLoadCalibrationFile()) ); connect( (QObject*)(m_Controls->m_ShowAdvancedOptionsPB), SIGNAL(toggled(bool)), this, SLOT(OnShowAdvancedOptions(bool)) ); connect( (QObject*)(m_AdvancedWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessDialogCloseRequest()) ); connect( (QObject*)(m_AdvancedWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation()) ); connect( m_Controls->m_Surface_Use_Other, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceUseOtherToggled(bool))); } } void QmitkNavigationToolCreationWidget::Initialize(mitk::DataStorage* dataStorage, std::string supposedIdentifier, std::string supposedName) { m_DataStorage = dataStorage; //initialize UI components m_Controls->m_SurfaceChooser->SetDataStorage(m_DataStorage); m_Controls->m_SurfaceChooser->SetAutoSelectNewItems(true); m_Controls->m_SurfaceChooser->SetPredicate(mitk::NodePredicateDataType::New("Surface")); //set default data m_Controls->m_ToolNameEdit->setText(supposedName.c_str()); m_Controls->m_CalibrationFileName->setText("none"); m_Controls->m_Surface_Use_Sphere->setChecked(true); m_AdvancedWidget->SetDataStorage(m_DataStorage); m_Controls->m_IdentifierEdit->setText(supposedIdentifier.c_str()); this->InitializeUIToolLandmarkLists(); m_Controls->m_CalibrationLandmarksList->EnableEditButton(false); m_Controls->m_RegistrationLandmarksList->EnableEditButton(false); } void QmitkNavigationToolCreationWidget::SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable) { switch(type) { -case mitk::NDIAurora: -m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break; -case mitk::NDIPolaris: -m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break; -case mitk::ClaronMicron: -m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break; -case mitk::NPOptitrack: -m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(3);break; -default: -m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0); + case mitk::NDIAurora: + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break; + case mitk::NDIPolaris: + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break; + case mitk::ClaronMicron: + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break; + case mitk::NPOptitrack: + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(3);break; + case mitk::VirtualTracker: + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(4);break; + default: + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(4); } m_Controls->m_TrackingDeviceTypeChooser->setEnabled(changeable); } mitk::NavigationTool::Pointer QmitkNavigationToolCreationWidget::GetCreatedTool() { return m_CreatedTool; } //################################################################################## //############################## slots ############################ //################################################################################## void QmitkNavigationToolCreationWidget::OnFinished() { //here we create a new tool m_CreatedTool = mitk::NavigationTool::New(); //create DataNode... mitk::DataNode::Pointer newNode = mitk::DataNode::New(); if(m_Controls->m_Surface_Use_Sphere->isChecked()) { //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkConeSource *vtkData = vtkConeSource::New(); vtkData->SetAngle(5.0); vtkData->SetResolution(50); vtkData->SetHeight(6.0f); vtkData->SetRadius(2.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); newNode->SetData(mySphere); } else { newNode->SetData(m_Controls->m_SurfaceChooser->GetSelectedNode()->GetData()); } newNode->SetName(m_Controls->m_ToolNameEdit->text().toLatin1()); m_CreatedTool->SetDataNode(newNode); //fill NavigationTool object m_CreatedTool->SetCalibrationFile(m_Controls->m_CalibrationFileName->text().toLatin1().data()); m_CreatedTool->SetIdentifier(m_Controls->m_IdentifierEdit->text().toLatin1().data()); m_CreatedTool->SetSerialNumber(m_Controls->m_SerialNumberEdit->text().toLatin1().data()); //Tracking Device if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Aurora") m_CreatedTool->SetTrackingDeviceType(mitk::NDIAurora); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Polaris") m_CreatedTool->SetTrackingDeviceType(mitk::NDIPolaris); -else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="Claron Technology Micron Tracker") m_CreatedTool->SetTrackingDeviceType(mitk::ClaronMicron); +else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="CT MicronTracker") m_CreatedTool->SetTrackingDeviceType(mitk::ClaronMicron); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NP Optitrack") m_CreatedTool->SetTrackingDeviceType(mitk::NPOptitrack); +else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="Virtual Tracker") m_CreatedTool->SetTrackingDeviceType(mitk::VirtualTracker); else m_CreatedTool->SetTrackingDeviceType(mitk::TrackingSystemNotSpecified); //ToolType if (m_Controls->m_ToolTypeChooser->currentText()=="Instrument") m_CreatedTool->SetType(mitk::NavigationTool::Instrument); else if (m_Controls->m_ToolTypeChooser->currentText()=="Fiducial") m_CreatedTool->SetType(mitk::NavigationTool::Fiducial); else if (m_Controls->m_ToolTypeChooser->currentText()=="Skinmarker") m_CreatedTool->SetType(mitk::NavigationTool::Skinmarker); else m_CreatedTool->SetType(mitk::NavigationTool::Unknown); //Tool Tip mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_AdvancedWidget->GetManipulatedToolTip()); m_CreatedTool->SetToolTipOrientation(tempND->GetOrientation()); m_CreatedTool->SetToolTipPosition(tempND->GetPosition()); //Tool Landmarks mitk::PointSet::Pointer toolCalLandmarks, toolRegLandmarks; GetUIToolLandmarksLists(toolCalLandmarks,toolRegLandmarks); m_CreatedTool->SetToolCalibrationLandmarks(toolCalLandmarks); m_CreatedTool->SetToolRegistrationLandmarks(toolRegLandmarks); emit NavigationToolFinished(); } void QmitkNavigationToolCreationWidget::OnCancel() { m_CreatedTool = NULL; emit Canceled(); } void QmitkNavigationToolCreationWidget::OnLoadSurface() { std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Surface"), "/", tr("STL (*.stl)")).toLatin1().data(); mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New(); try { stlReader->SetFileName( filename.c_str() ); stlReader->Update(); } catch (...) { } if ( stlReader->GetOutput() == NULL ); else { mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetName(filename); newNode->SetData(stlReader->GetOutput()); m_DataStorage->Add(newNode); } } void QmitkNavigationToolCreationWidget::OnLoadCalibrationFile() { m_Controls->m_CalibrationFileName->setText(QFileDialog::getOpenFileName(NULL,tr("Open Calibration File"), "/", "*.*")); } void QmitkNavigationToolCreationWidget::SetDefaultData(mitk::NavigationTool::Pointer DefaultTool) { m_Controls->m_ToolNameEdit->setText(QString(DefaultTool->GetDataNode()->GetName().c_str())); m_Controls->m_IdentifierEdit->setText(QString(DefaultTool->GetIdentifier().c_str())); m_Controls->m_SerialNumberEdit->setText(QString(DefaultTool->GetSerialNumber().c_str())); m_AdvancedWidget->SetDefaultTooltip( DefaultTool->GetToolTipTransform() ); switch(DefaultTool->GetTrackingDeviceType()) { case mitk::NDIAurora: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break; case mitk::NDIPolaris: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break; case mitk::ClaronMicron: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break; case mitk::NPOptitrack: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(3);break; +case mitk::VirtualTracker: +m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(4);break; default: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0); } m_Controls->m_CalibrationFileName->setText(QString(DefaultTool->GetCalibrationFile().c_str())); m_Controls->m_Surface_Use_Other->setChecked(true); switch(DefaultTool->GetType()) { case mitk::NavigationTool::Instrument: m_Controls->m_ToolTypeChooser->setCurrentIndex(0); break; case mitk::NavigationTool::Fiducial: m_Controls->m_ToolTypeChooser->setCurrentIndex(1); break; case mitk::NavigationTool::Skinmarker: m_Controls->m_ToolTypeChooser->setCurrentIndex(2); break; case mitk::NavigationTool::Unknown: m_Controls->m_ToolTypeChooser->setCurrentIndex(3); break; } m_Controls->m_SurfaceChooser->SetSelectedNode(DefaultTool->GetDataNode()); FillUIToolLandmarkLists(DefaultTool->GetToolCalibrationLandmarks(),DefaultTool->GetToolRegistrationLandmarks()); } //################################################################################## //############################## internal help methods ############################# //################################################################################## void QmitkNavigationToolCreationWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkNavigationToolCreationWidget::OnShowAdvancedOptions(bool state) { if(state) { m_AdvancedWidget->show(); m_AdvancedWidget->SetDefaultTooltip(m_AdvancedWidget->GetManipulatedToolTip()); //use the last one, if there is one m_AdvancedWidget->ReInitialize(); // reinit the views with the new nodes mitk::DataStorage::SetOfObjects::ConstPointer rs = m_DataStorage->GetAll(); mitk::TimeGeometry::Pointer bounds = m_DataStorage->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } else { m_AdvancedWidget->hide(); } } void QmitkNavigationToolCreationWidget::OnProcessDialogCloseRequest() { m_AdvancedWidget->hide(); m_Controls->m_ShowAdvancedOptionsPB->setChecked(false); } void QmitkNavigationToolCreationWidget::OnRetrieveDataForManualTooltipManipulation() { if(m_Controls->m_Surface_Use_Sphere->isChecked()) { m_AdvancedWidget->SetToolTipSurface(true); } else { m_AdvancedWidget->SetToolTipSurface(false, dynamic_cast(m_Controls->m_SurfaceChooser->GetSelectedNode().GetPointer())); } } void QmitkNavigationToolCreationWidget::OnSurfaceUseOtherToggled(bool checked) { m_Controls->m_LoadSurface->setEnabled(checked); } void QmitkNavigationToolCreationWidget::FillUIToolLandmarkLists(mitk::PointSet::Pointer calLandmarks, mitk::PointSet::Pointer regLandmarks) { m_calLandmarkNode->SetData(calLandmarks); m_regLandmarkNode->SetData(regLandmarks); m_Controls->m_CalibrationLandmarksList->SetPointSetNode(m_calLandmarkNode); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(m_regLandmarkNode); } void QmitkNavigationToolCreationWidget::GetUIToolLandmarksLists(mitk::PointSet::Pointer& calLandmarks, mitk::PointSet::Pointer& regLandmarks) { calLandmarks = dynamic_cast(m_calLandmarkNode->GetData()); regLandmarks = dynamic_cast(m_regLandmarkNode->GetData()); } void QmitkNavigationToolCreationWidget::InitializeUIToolLandmarkLists() { m_calLandmarkNode = mitk::DataNode::New(); m_regLandmarkNode = mitk::DataNode::New(); FillUIToolLandmarkLists(mitk::PointSet::New(),mitk::PointSet::New()); } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui index 28beb9ffb6..079e60455e 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui @@ -1,531 +1,536 @@ QmitkNavigationToolCreationWidgetControls 0 0 254 309 Form Device Type: 150 0 150 16777215 NDI Aurora NDI Polaris - Claron Technology Micron Tracker + CT MicronTracker NP Optitrack + + + Virtual Tracker + + 0 0 0 236 - 90 + 115 Basic Information 100 0 Name: NewTool 100 0 Calibration File: none 40 16777215 Load Qt::Vertical 20 40 0 0 - 310 - 113 + 303 + 98 Tool Visualization Use Simple Cone true Use Surface: Qt::Horizontal QSizePolicy::Fixed 25 20 200 0 150 16777215 false 40 16777215 Load Qt::Horizontal 40 20 Qt::Vertical 20 8 0 0 - 232 - 85 + 236 + 115 Tool Landmarks 0 Calibration Landmarks Registration Landmarks 0 0 - 281 - 152 + 276 + 133 Advanced 100 0 Tool Type: 150 0 150 16777215 Instrument Fiducial Skinmarker Unkown 100 0 Identifier: <not given> 100 0 Serial Number: <not given> Tooltip: Qt::Horizontal 40 20 Edit Tooltip true Qt::Vertical 20 40 Qt::Horizontal Qt::Horizontal 40 20 Cancel Finished QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
1
QmitkPointListWidget QWidget
QmitkPointListWidget.h
1
diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp index f35c1781bb..37d457de5d 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp @@ -1,357 +1,359 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNavigationToolManagementWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include //qt headers #include #include #include //poco headers #include const std::string QmitkNavigationToolManagementWidget::VIEW_ID = "org.mitk.views.navigationtoolmanagementwidget"; QmitkNavigationToolManagementWidget::QmitkNavigationToolManagementWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); } QmitkNavigationToolManagementWidget::~QmitkNavigationToolManagementWidget() { } void QmitkNavigationToolManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolManagementWidgetControls; m_Controls->setupUi(parent); } //Disable StorageControls in the beginning, because there is no storage to edit DisableStorageControls(); } void QmitkNavigationToolManagementWidget::OnLoadTool() { if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); std::string filename = QFileDialog::getOpenFileName(NULL,tr("Add Navigation Tool"), "/", "*.IGTTool").toLatin1().data(); if (filename == "") return; mitk::NavigationTool::Pointer readTool = myReader->DoRead(filename); if (readTool.IsNull()) MessageBox("Error: " + myReader->GetErrorMessage()); else { if (!m_NavigationToolStorage->AddTool(readTool)) { MessageBox("Error: Can't add tool!"); m_DataStorage->Remove(readTool->GetDataNode()); } UpdateToolTable(); } } void QmitkNavigationToolManagementWidget::OnSaveTool() { //if no item is selected, show error message: if (m_Controls->m_ToolList->currentItem() == NULL) {MessageBox("Error: Please select tool first!");return;} mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = QFileDialog::getSaveFileName(NULL,tr("Save Navigation Tool"), "/", "*.IGTTool").toLatin1().data(); if (filename == "") return; if (!myWriter->DoWrite(filename,m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()))) MessageBox("Error: "+ myWriter->GetErrorMessage()); } void QmitkNavigationToolManagementWidget::CreateConnections() { if ( m_Controls ) { //main widget page: connect( (QObject*)(m_Controls->m_AddTool), SIGNAL(clicked()), this, SLOT(OnAddTool()) ); connect( (QObject*)(m_Controls->m_DeleteTool), SIGNAL(clicked()), this, SLOT(OnDeleteTool()) ); connect( (QObject*)(m_Controls->m_EditTool), SIGNAL(clicked()), this, SLOT(OnEditTool()) ); connect( (QObject*)(m_Controls->m_LoadStorage), SIGNAL(clicked()), this, SLOT(OnLoadStorage()) ); connect( (QObject*)(m_Controls->m_SaveStorage), SIGNAL(clicked()), this, SLOT(OnSaveStorage()) ); connect( (QObject*)(m_Controls->m_LoadTool), SIGNAL(clicked()), this, SLOT(OnLoadTool()) ); connect( (QObject*)(m_Controls->m_SaveTool), SIGNAL(clicked()), this, SLOT(OnSaveTool()) ); connect( (QObject*)(m_Controls->m_CreateNewStorage), SIGNAL(clicked()), this, SLOT(OnCreateStorage()) ); //widget page "add tool": connect( (QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(Canceled()), this, SLOT(OnAddToolCancel()) ); connect( (QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(NavigationToolFinished()), this, SLOT(OnAddToolSave()) ); } } void QmitkNavigationToolManagementWidget::Initialize(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage,"Tool0"); } void QmitkNavigationToolManagementWidget::LoadStorage(mitk::NavigationToolStorage::Pointer storageToLoad) { if(storageToLoad.IsNotNull()) { m_NavigationToolStorage = storageToLoad; m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); } else { m_NavigationToolStorage = NULL; DisableStorageControls(); } UpdateToolTable(); } //################################################################################## //############################## slots: main widget ################################ //################################################################################## void QmitkNavigationToolManagementWidget::OnAddTool() { if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } QString defaultIdentifier = "NavigationTool#"+QString::number(m_NavigationToolStorage->GetToolCount()); m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage,defaultIdentifier.toStdString()); m_edit = false; m_Controls->m_MainWidgets->setCurrentIndex(1); } void QmitkNavigationToolManagementWidget::OnDeleteTool() { //first: some checks if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } m_DataStorage->Remove(m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetDataNode()); m_NavigationToolStorage->DeleteTool(m_Controls->m_ToolList->currentIndex().row()); UpdateToolTable(); } void QmitkNavigationToolManagementWidget::OnEditTool() { if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } mitk::NavigationTool::Pointer selectedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); m_Controls->m_ToolCreationWidget->SetDefaultData(selectedTool); m_edit = true; m_Controls->m_MainWidgets->setCurrentIndex(1); } void QmitkNavigationToolManagementWidget::OnCreateStorage() { QString storageName = QInputDialog::getText(NULL,"Storage Name","Name of the new tool storage:"); if (storageName.isNull()) return; m_NavigationToolStorage = mitk::NavigationToolStorage::New(this->m_DataStorage); m_NavigationToolStorage->SetName(storageName.toStdString()); m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); emit NewStorageAdded(m_NavigationToolStorage, storageName.toStdString()); } void QmitkNavigationToolManagementWidget::OnLoadStorage() { mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(m_DataStorage); std::string filename = QFileDialog::getOpenFileName(NULL, tr("Open Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); if (filename == "") return; try { mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); if (tempStorage.IsNull()) MessageBox("Error" + myDeserializer->GetErrorMessage()); else { Poco::Path myPath = Poco::Path(filename.c_str()); tempStorage->SetName(myPath.getFileName()); //set the filename as name for the storage, so the user can identify it this->LoadStorage(tempStorage); emit NewStorageAdded(m_NavigationToolStorage,myPath.getFileName()); } } catch (const mitk::Exception& exception) { MessageBox(exception.GetDescription()); } } void QmitkNavigationToolManagementWidget::OnSaveStorage() { //read in filename QString filename = QFileDialog::getSaveFileName(NULL, tr("Save Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")); if (filename.isEmpty()) return; //canceled by the user // add file extension if it wasn't added by the file dialog if ( filename.right(15) != ".IGTToolStorage" ) { filename += ".IGTToolStorage"; } //serialize tool storage mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); if (!mySerializer->Serialize(filename.toStdString(),m_NavigationToolStorage)) { MessageBox("Error: " + mySerializer->GetErrorMessage()); return; } Poco::Path myPath = Poco::Path(filename.toStdString()); m_Controls->m_StorageName->setText(QString::fromStdString(myPath.getFileName())); } //################################################################################## //############################## slots: add tool widget ############################ //################################################################################## void QmitkNavigationToolManagementWidget::OnAddToolSave() { mitk::NavigationTool::Pointer newTool = m_Controls->m_ToolCreationWidget->GetCreatedTool(); if (m_edit) //here we edit a existing tool { mitk::NavigationTool::Pointer editedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); editedTool->Graft(newTool); } else //here we create a new tool { m_NavigationToolStorage->AddTool(newTool); } UpdateToolTable(); m_Controls->m_MainWidgets->setCurrentIndex(0); } void QmitkNavigationToolManagementWidget::OnAddToolCancel() { m_Controls->m_MainWidgets->setCurrentIndex(0); } //################################################################################## //############################## private help methods ############################## //################################################################################## void QmitkNavigationToolManagementWidget::UpdateToolTable() { m_Controls->m_ToolList->clear(); if(m_NavigationToolStorage.IsNull()) return; for(int i=0; iGetToolCount(); i++) { QString currentTool = "Tool" + QString::number(i) + ": " + QString(m_NavigationToolStorage->GetTool(i)->GetDataNode()->GetName().c_str())+ " "; switch (m_NavigationToolStorage->GetTool(i)->GetTrackingDeviceType()) { case mitk::ClaronMicron: currentTool += "(MicronTracker/"; break; case mitk::NDIAurora: currentTool += "(NDI Aurora/"; break; case mitk::NDIPolaris: currentTool += "(NDI Polaris/"; break; - case mitk::NPOptitrack: + case mitk::NPOptitrack: currentTool += "(NP Optitrack/"; break; + case mitk::VirtualTracker: + currentTool += "(Virtual Tracker/"; break; default: currentTool += "(unknown tracking system/"; break; } switch (m_NavigationToolStorage->GetTool(i)->GetType()) { case mitk::NavigationTool::Instrument: currentTool += "Instrument)"; break; case mitk::NavigationTool::Fiducial: currentTool += "Fiducial)"; break; case mitk::NavigationTool::Skinmarker: currentTool += "Skinmarker)"; break; default: currentTool += "Unknown)"; } m_Controls->m_ToolList->addItem(currentTool); } } void QmitkNavigationToolManagementWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkNavigationToolManagementWidget::DisableStorageControls() { m_Controls->m_StorageName->setText(""); m_Controls->m_AddTool->setEnabled(false); m_Controls->m_LoadTool->setEnabled(false); m_Controls->m_selectedLabel->setEnabled(false); m_Controls->m_DeleteTool->setEnabled(false); m_Controls->m_EditTool->setEnabled(false); m_Controls->m_SaveTool->setEnabled(false); m_Controls->m_ToolList->setEnabled(false); m_Controls->m_SaveStorage->setEnabled(false); m_Controls->m_ToolLabel->setEnabled(false); } void QmitkNavigationToolManagementWidget::EnableStorageControls() { m_Controls->m_AddTool->setEnabled(true); m_Controls->m_LoadTool->setEnabled(true); m_Controls->m_selectedLabel->setEnabled(true); m_Controls->m_DeleteTool->setEnabled(true); m_Controls->m_EditTool->setEnabled(true); m_Controls->m_SaveTool->setEnabled(true); m_Controls->m_ToolList->setEnabled(true); m_Controls->m_SaveStorage->setEnabled(true); m_Controls->m_ToolLabel->setEnabled(true); } diff --git a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp index f5cb6899d9..e28ee0ee90 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp @@ -1,728 +1,732 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkTrackingDeviceConfigurationWidget.h" #include +#include #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkTrackingDeviceConfigurationWidget::VIEW_ID = "org.mitk.views.trackingdeviceconfigurationwidget"; QmitkTrackingDeviceConfigurationWidget::QmitkTrackingDeviceConfigurationWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { //initialize worker thread m_TestConnectionWorker = new QmitkTrackingDeviceConfigurationWidgetConnectionWorker(); m_ScanPortsWorker = new QmitkTrackingDeviceConfigurationWidgetScanPortsWorker(); m_ScanPortsWorkerThread = new QThread(); m_TestConnectionWorkerThread = new QThread(); //initializations m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); m_MTCalibrationFile = ""; m_AdvancedUserControl = true; //initialize a few UI elements this->m_TrackingDeviceConfigurated = false; AddOutput("
NDI Polaris selected"); //Polaris is selected by default m_Controls->m_trackingDeviceChooser->setCurrentIndex(0); m_Controls->m_TrackingSystemWidget->setCurrentIndex(0); //reset a few things ResetOutput(); //restore old UI settings LoadUISettings(); } void QmitkTrackingDeviceConfigurationWidget::SetGUIStyle(QmitkTrackingDeviceConfigurationWidget::Style style) { switch(style) { case QmitkTrackingDeviceConfigurationWidget::SIMPLE: //move all UI elements to an empty dummy layout //m_Controls->dummyLayout->addItem(m_Controls->mainLayout); m_Controls->dummyLayout->addWidget(m_Controls->widget_title_label); m_Controls->dummyLayout->addWidget(m_Controls->choose_tracking_device_label); m_Controls->dummyLayout->addWidget(m_Controls->polaris_label); m_Controls->dummyLayout->addWidget(m_Controls->aurora_label); //m_Controls->dummyLayout->addWidget(m_Controls->aurora_label); m_Controls->dummyLayout->addWidget(m_Controls->microntracker_label); m_Controls->dummyLayout->addWidget(m_Controls->m_testConnectionMicronTracker); m_Controls->dummyLayout->addWidget(m_Controls->m_outputTextMicronTracker); m_Controls->dummyLayout->addWidget(m_Controls->m_outputTextAurora); m_Controls->dummyLayout->addWidget(m_Controls->m_testConnectionAurora); m_Controls->dummyLayout->addWidget(m_Controls->m_outputTextPolaris); m_Controls->dummyLayout->addWidget(m_Controls->m_testConnectionPolaris); m_Controls->dummyLayout->addWidget(m_Controls->m_polarisTrackingModeBox); m_Controls->dummyLayout->addWidget(m_Controls->m_testConnectionOptitrack); m_Controls->dummyLayout->addWidget(m_Controls->m_outputTextOptitrack); m_Controls->dummyLayout->addWidget(m_Controls->m_OptitrackExp); m_Controls->dummyLayout->addWidget(m_Controls->m_OptitrackThr); m_Controls->dummyLayout->addWidget(m_Controls->m_OptitrackLed); m_Controls->dummyLayout->addWidget(m_Controls->Optitrack_label); m_Controls->dummyLayout->addWidget(m_Controls->m_finishedLine); m_Controls->dummyLayout->addWidget(m_Controls->line); m_Controls->dummyLayout->addWidget(m_Controls->configuration_finished_label); m_Controls->dummyLayout->addItem(m_Controls->horizontalLayout_4); m_Controls->mainLayout->removeItem(m_Controls->horizontalLayout_4); m_Controls->dummyLayout->addWidget(m_Controls->configuration_finished_label); m_Controls->dummyLayout->addItem(m_Controls->verticalSpacer_2); m_Controls->verticalLayout_3->removeItem(m_Controls->verticalSpacer_2); m_Controls->dummyLayout->addItem(m_Controls->horizontalSpacer_9); m_Controls->horizontalLayout_9->removeItem(m_Controls->horizontalSpacer_9); m_Controls->dummyLayout->addItem(m_Controls->horizontalSpacer_3); m_Controls->horizontalLayout_11->removeItem(m_Controls->horizontalSpacer_3); m_Controls->dummyLayout->addItem(m_Controls->verticalSpacer_3); m_Controls->verticalLayout_7->removeItem(m_Controls->verticalSpacer_3); m_Controls->dummyLayout->addItem(m_Controls->verticalSpacer_4); m_Controls->verticalLayout_10->removeItem(m_Controls->verticalSpacer_4); m_Controls->dummyLayout->addItem(m_Controls->horizontalSpacer_10); m_Controls->verticalLayout_10->removeItem(m_Controls->horizontalSpacer_10); //set height to min m_Controls->m_outputTextPolaris->setMinimumHeight(0); m_Controls->m_outputTextPolaris->setMaximumHeight(0); m_Controls->m_outputTextMicronTracker->setMinimumHeight(0); m_Controls->m_outputTextMicronTracker->setMaximumHeight(0); m_Controls->m_outputTextAurora->setMinimumHeight(0); m_Controls->m_outputTextAurora->setMaximumHeight(0); m_Controls->m_finishedButton->setMinimumHeight(0); m_Controls->m_finishedButton->setMaximumHeight(0); m_Controls->m_resetButton->setMinimumHeight(0); m_Controls->m_resetButton->setMaximumHeight(0); //set the height of the tracking device combo box m_Controls->m_trackingDeviceChooser->setMinimumHeight(50); //move back the used elemets to the main layout m_Controls->simpleLayout->addWidget(m_Controls->m_trackingDeviceChooser); m_Controls->simpleLayout->addWidget(m_Controls->m_TrackingSystemWidget); m_Controls->mainWidget->setCurrentIndex(1); this->setMaximumHeight(150); this->EnableAdvancedUserControl(false); break; case QmitkTrackingDeviceConfigurationWidget::ADVANCED: //default at the moment => start settings are advanced break; } } QmitkTrackingDeviceConfigurationWidget::~QmitkTrackingDeviceConfigurationWidget() { StoreUISettings(); if (m_ScanPortsWorker) delete m_ScanPortsWorker; if (m_TestConnectionWorker) delete m_TestConnectionWorker; if (m_ScanPortsWorkerThread) delete m_ScanPortsWorkerThread; if (m_TestConnectionWorkerThread) delete m_TestConnectionWorkerThread; } void QmitkTrackingDeviceConfigurationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkTrackingDeviceConfigurationWidgetControls; m_Controls->setupUi(parent); } } void QmitkTrackingDeviceConfigurationWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_trackingDeviceChooser), SIGNAL(currentIndexChanged(int)), this, SLOT(TrackingDeviceChanged()) ); connect( (QObject*)(m_Controls->m_testConnectionPolaris), SIGNAL(clicked()), this, SLOT(TestConnection()) ); connect( (QObject*)(m_Controls->m_testConnectionAurora), SIGNAL(clicked()), this, SLOT(TestConnection()) ); connect( (QObject*)(m_Controls->m_testConnectionMicronTracker), SIGNAL(clicked()), this, SLOT(TestConnection()) ); connect( (QObject*)(m_Controls->m_testConnectionOptitrack), SIGNAL(clicked()), this, SLOT(TestConnection()) ); connect( (QObject*)(m_Controls->m_resetButton), SIGNAL(clicked()), this, SLOT(ResetByUser()) ); connect( (QObject*)(m_Controls->m_finishedButton), SIGNAL(clicked()), this, SLOT(Finished()) ); connect( (QObject*)(m_Controls->m_AutoScanPolaris), SIGNAL(clicked()), this, SLOT(AutoScanPorts()) ); connect( (QObject*)(m_Controls->m_AutoScanAurora), SIGNAL(clicked()), this, SLOT(AutoScanPorts()) ); connect( (QObject*)(m_Controls->m_SetMTCalibrationFile), SIGNAL(clicked()), this, SLOT(SetMTCalibrationFileClicked()) ); connect( (QObject*)(m_Controls->m_SetOptitrackCalibrationFile), SIGNAL(clicked()), this, SLOT(SetOptitrackCalibrationFileClicked()) ); //slots for the worker thread connect(m_ScanPortsWorker, SIGNAL(PortsScanned(int,int,QString,int,int)), this, SLOT(AutoScanPortsFinished(int,int,QString,int,int)) ); connect(m_TestConnectionWorker, SIGNAL(ConnectionTested(bool,QString)), this, SLOT(TestConnectionFinished(bool,QString)) ); connect(m_ScanPortsWorkerThread,SIGNAL(started()), m_ScanPortsWorker, SLOT(ScanPortsThreadFunc()) ); connect(m_TestConnectionWorkerThread,SIGNAL(started()), m_TestConnectionWorker, SLOT(TestConnectionThreadFunc()) ); //move the worker to the thread m_ScanPortsWorker->moveToThread(m_ScanPortsWorkerThread); m_TestConnectionWorker->moveToThread(m_TestConnectionWorkerThread); //set a few UI components depending on Windows / Linux #ifdef WIN32 m_Controls->portTypeLabelPolaris->setVisible(false); m_Controls->portTypePolaris->setVisible(false); m_Controls->portTypeLabelAurora->setVisible(false); m_Controls->portTypeAurora->setVisible(false); #else m_Controls->comPortLabelAurora->setText("Port Nr:"); m_Controls->m_comPortLabelPolaris->setText("Port Nr:"); m_Controls->m_portSpinBoxAurora->setPrefix(""); m_Controls->m_portSpinBoxPolaris->setPrefix(""); #endif //disable unused UI component m_Controls->m_polarisTrackingModeBox->setVisible(false); //don't delete this component, because it is used in the MBI part of MITK } } void QmitkTrackingDeviceConfigurationWidget::TrackingDeviceChanged() { //show the correspondig widget m_Controls->m_TrackingSystemWidget->setCurrentIndex(m_Controls->m_trackingDeviceChooser->currentIndex()); //the new trackingdevice is not configurated yet m_TrackingDeviceConfigurated = false; //reset output ResetOutput(); //print output and do further initializations if (m_Controls->m_trackingDeviceChooser->currentIndex()==0)//NDI Polaris { AddOutput("
NDI Polaris selected"); } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==1) //NDI Aurora { AddOutput("
NDI Aurora selected"); } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==2) //ClaronTechnology MicronTracker 2 { AddOutput("
Microntracker selected"); if (!mitk::ClaronTrackingDevice::New()->IsDeviceInstalled()) { AddOutput("
ERROR: not installed!"); } else if (this->m_MTCalibrationFile == "") //if configuration file for MicronTracker is empty: load default { mitk::ClaronTrackingDevice::Pointer tempDevice = mitk::ClaronTrackingDevice::New(); m_MTCalibrationFile = tempDevice->GetCalibrationDir(); Poco::Path myPath = Poco::Path(m_MTCalibrationFile.c_str()); m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString(myPath.getFileName().c_str())); } } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==3) { AddOutput("
Optitrack selected"); if (!mitk::OptitrackTrackingDevice::New()->IsDeviceInstalled()) { AddOutput("
ERROR: not installed!"); } } emit TrackingDeviceSelectionChanged(); } void QmitkTrackingDeviceConfigurationWidget::EnableUserReset(bool enable) { if (enable) m_Controls->m_resetButton->setVisible(true); else m_Controls->m_resetButton->setVisible(false); } void QmitkTrackingDeviceConfigurationWidget::TestConnection() { this->setEnabled(false); //construct a tracking device: mitk::TrackingDevice::Pointer testTrackingDevice = ConstructTrackingDevice(); m_TestConnectionWorker->SetTrackingDevice(testTrackingDevice); m_TestConnectionWorkerThread->start(); emit ProgressStarted(); } void QmitkTrackingDeviceConfigurationWidget::TestConnectionFinished(bool connected, QString output) { m_TestConnectionWorkerThread->quit(); AddOutput(output.toStdString()); MITK_INFO << "Test connection: " << connected; this->setEnabled(true); emit ProgressFinished(); } void QmitkTrackingDeviceConfigurationWidget::Finished() { m_TrackingDevice = ConstructTrackingDevice(); m_Controls->m_TrackingSystemWidget->setEnabled(false); m_Controls->m_trackingDeviceChooser->setEnabled(false); m_Controls->choose_tracking_device_label->setEnabled(false); m_Controls->configuration_finished_label->setText("\n\n

Configuration finished

"); this->m_TrackingDeviceConfigurated = true; emit TrackingDeviceConfigurationFinished(); } void QmitkTrackingDeviceConfigurationWidget::Reset() { m_TrackingDevice = NULL; m_Controls->m_TrackingSystemWidget->setEnabled(true); m_Controls->m_trackingDeviceChooser->setEnabled(true); m_Controls->choose_tracking_device_label->setEnabled(true); m_Controls->configuration_finished_label->setText("\n\n

Press \"Finished\" to confirm configuration

"); this->m_TrackingDeviceConfigurated = false; emit TrackingDeviceConfigurationReseted(); } void QmitkTrackingDeviceConfigurationWidget::ResetByUser() { Reset(); } void QmitkTrackingDeviceConfigurationWidget::AutoScanPorts() { this->setEnabled(false); AddOutput("
Scanning..."); m_ScanPortsWorkerThread->start(); emit ProgressStarted(); } void QmitkTrackingDeviceConfigurationWidget::AutoScanPortsFinished(int PolarisPort, int AuroraPort, QString result, int PortTypePolaris, int PortTypeAurora) { m_ScanPortsWorkerThread->quit(); #ifdef WIN32 if((PortTypePolaris!=-1)||(PortTypeAurora!=-1)) {MITK_WARN << "Port type is specified although this should not be the case for Windows. Ignoring port type.";} #else //linux systems if (PortTypePolaris!=-1) {m_Controls->portTypePolaris->setCurrentIndex(PortTypePolaris);} if (PortTypeAurora!=-1) {m_Controls->portTypeAurora->setCurrentIndex(PortTypeAurora);} #endif m_Controls->m_portSpinBoxPolaris->setValue(PolarisPort); m_Controls->m_portSpinBoxAurora->setValue(AuroraPort); AddOutput(result.toStdString()); this->setEnabled(true); emit ProgressFinished(); } void QmitkTrackingDeviceConfigurationWidget::SetMTCalibrationFileClicked() { std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Calibration File"), "/", "*.*").toLatin1().data(); if (filename=="") {return;} else { m_MTCalibrationFile = filename; Poco::Path myPath = Poco::Path(m_MTCalibrationFile.c_str()); m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString(myPath.getFileName().c_str())); } } void QmitkTrackingDeviceConfigurationWidget::SetOptitrackCalibrationFileClicked() { std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Calibration File"), "/", "*.*").toLatin1().data(); if (filename=="") {return;} else { m_OptitrackCalibrationFile = filename; Poco::Path myPath = Poco::Path(m_OptitrackCalibrationFile.c_str()); m_Controls->m_OptitrackCalibrationFile->setText("Calibration File: " + QString(myPath.getFileName().c_str())); } } //######################### internal help methods ####################################### void QmitkTrackingDeviceConfigurationWidget::ResetOutput() { m_output.str(""); m_output <<"output:"; m_Controls->m_outputTextAurora->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextPolaris->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextMicronTracker->setHtml(QString(m_output.str().c_str())); } void QmitkTrackingDeviceConfigurationWidget::AddOutput(std::string s) { //print output m_output << s; m_Controls->m_outputTextAurora->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextPolaris->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextMicronTracker->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextOptitrack->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextPolaris->verticalScrollBar()->setValue(m_Controls->m_outputTextPolaris->verticalScrollBar()->maximum()); m_Controls->m_outputTextAurora->verticalScrollBar()->setValue(m_Controls->m_outputTextAurora->verticalScrollBar()->maximum()); m_Controls->m_outputTextMicronTracker->verticalScrollBar()->setValue(m_Controls->m_outputTextMicronTracker->verticalScrollBar()->maximum()); m_Controls->m_outputTextOptitrack->verticalScrollBar()->setValue(m_Controls->m_outputTextOptitrack->verticalScrollBar()->maximum()); repaint(); } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::ConstructTrackingDevice() { mitk::TrackingDevice::Pointer returnValue; //#### Step 1: configure tracking device: - MITK_INFO << "Current Index: " << m_Controls->m_trackingDeviceChooser->currentIndex(); if (m_Controls->m_trackingDeviceChooser->currentIndex()==0)//NDI Polaris { if(m_Controls->m_radioPolaris5D->isChecked()) //5D Tracking { //not yet in the open source part so we'll only get NULL here. returnValue = ConfigureNDI5DTrackingDevice(); } else //6D Tracking { returnValue = ConfigureNDI6DTrackingDevice(); returnValue->SetType(mitk::NDIPolaris); } } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==1)//NDI Aurora { returnValue = ConfigureNDI6DTrackingDevice(); returnValue->SetType(mitk::NDIAurora); } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==2)//ClaronTechnology MicronTracker 2 { mitk::ClaronTrackingDevice::Pointer newDevice = mitk::ClaronTrackingDevice::New(); if(this->m_MTCalibrationFile=="") AddOutput("
Warning: Calibration file is not set!"); else { //extract path from calibration file and set the calibration dir of the device std::string path = itksys::SystemTools::GetFilenamePath(m_MTCalibrationFile); newDevice->SetCalibrationDir(path); } returnValue = newDevice; } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==3) { // Create the Tracking Device this->m_OptitrackDevice = mitk::OptitrackTrackingDevice::New(); returnValue = ConfigureOptitrackTrackingDevice(); returnValue->SetType(mitk::NPOptitrack); } + else if (m_Controls->m_trackingDeviceChooser->currentIndex()==4) //Virtual Tracker + { + // Create the Virtual Tracking Device + returnValue = mitk::VirtualTrackingDevice::New(); + } return returnValue; } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::ConfigureNDI5DTrackingDevice() { return NULL; } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::ConfigureOptitrackTrackingDevice() { mitk::OptitrackTrackingDevice::Pointer tempTrackingDevice = mitk::OptitrackTrackingDevice::New(); // Set the calibration File tempTrackingDevice->SetCalibrationPath(m_OptitrackCalibrationFile); //Set the camera parameters tempTrackingDevice->SetExp(m_Controls->m_OptitrackExp->value()); tempTrackingDevice->SetLed(m_Controls->m_OptitrackLed->value()); tempTrackingDevice->SetThr(m_Controls->m_OptitrackThr->value()); mitk::TrackingDevice::Pointer returnValue = static_cast(tempTrackingDevice); return returnValue; } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::ConfigureNDI6DTrackingDevice() { mitk::NDITrackingDevice::Pointer tempTrackingDevice = mitk::NDITrackingDevice::New(); //get port int port = 0; if (m_Controls->m_trackingDeviceChooser->currentIndex()==1) port = m_Controls->m_portSpinBoxAurora->value(); else port = m_Controls->m_portSpinBoxPolaris->value(); //build prefix (depends on linux/win) QString prefix = ""; #ifdef WIN32 prefix ="COM"; tempTrackingDevice->SetPortNumber(static_cast(port)); //also set the com port for compatibility #else if (m_Controls->m_trackingDeviceChooser->currentIndex()==1) //Aurora prefix = m_Controls->portTypeAurora->currentText(); else //Polaris prefix = m_Controls->portTypePolaris->currentText(); #endif //build port name string QString portName = prefix + QString::number(port); tempTrackingDevice->SetDeviceName(portName.toStdString()); //set the port name tempTrackingDevice->SetBaudRate(mitk::SerialCommunication::BaudRate115200);//set baud rate mitk::TrackingDevice::Pointer returnValue = static_cast(tempTrackingDevice); return returnValue; } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::GetTrackingDevice() { if (!m_AdvancedUserControl) m_TrackingDevice = ConstructTrackingDevice(); if (m_TrackingDevice.IsNull() || !m_TrackingDevice->IsDeviceInstalled()) return NULL; else return this->m_TrackingDevice; } bool QmitkTrackingDeviceConfigurationWidget::GetTrackingDeviceConfigured() { return this->m_TrackingDeviceConfigurated; } void QmitkTrackingDeviceConfigurationWidget::ConfigurationFinished() { Finished(); } void QmitkTrackingDeviceConfigurationWidget::EnableAdvancedUserControl(bool enable) { m_AdvancedUserControl = enable; m_Controls->configuration_finished_label->setVisible(enable); m_Controls->m_finishedLine->setVisible(enable); m_Controls->m_resetButton->setVisible(enable); m_Controls->m_finishedButton->setVisible(enable); } void QmitkTrackingDeviceConfigurationWidget::StoreUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; int selectedDevice = m_Controls->m_trackingDeviceChooser->currentIndex(); if ( this->GetPeristenceService() ) // now save the settings using the persistence service { mitk::PropertyList::Pointer propList = this->GetPeristenceService()->GetPropertyList(id); propList->Set("PolarisPortWin",m_Controls->m_portSpinBoxPolaris->value()); propList->Set("AuroraPortWin",m_Controls->m_portSpinBoxAurora->value()); propList->Set("PortTypePolaris", m_Controls->portTypePolaris->currentIndex()); propList->Set("PortTypeAurora", m_Controls->portTypeAurora->currentIndex()); propList->Set("MTCalibrationFile",m_MTCalibrationFile); propList->Set("SelectedDevice",selectedDevice); } else // QSettings as a fallback if the persistence service is not available { QSettings settings; settings.beginGroup(QString::fromStdString(id)); settings.setValue("trackingDeviceChooser", QVariant(selectedDevice)); settings.setValue("portSpinBoxAurora", QVariant(m_Controls->m_portSpinBoxAurora->value())); settings.setValue("portSpinBoxPolaris", QVariant(m_Controls->m_portSpinBoxPolaris->value())); settings.setValue("portTypePolaris", QVariant(m_Controls->portTypePolaris->currentIndex())); settings.setValue("portTypeAurora", QVariant(m_Controls->portTypeAurora->currentIndex())); settings.setValue("mTCalibrationFile", QVariant(QString::fromStdString(m_MTCalibrationFile))); settings.endGroup(); } } void QmitkTrackingDeviceConfigurationWidget::LoadUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; int SelectedDevice = 0; if ( this->GetPeristenceService() ) { mitk::PropertyList::Pointer propList = this->GetPeristenceService()->GetPropertyList(id); if (propList.IsNull()) {MITK_ERROR << "Property list for this UI (" << id <<") is not available, could not load UI settings!"; return;} int portPolarisWin,portAuroraWin,portTypePolaris,portTypeAurora; propList->Get("PolarisPortWin",portPolarisWin); propList->Get("AuroraPortWin",portAuroraWin); propList->Get("PortTypePolaris", portTypePolaris); propList->Get("PortTypeAurora", portTypeAurora); propList->Get("MTCalibrationFile",m_MTCalibrationFile); propList->Get("SelectedDevice",SelectedDevice); if (SelectedDevice<0) { MITK_ERROR << "Loaded data from persistence service is invalid (SelectedDevice:" <m_portSpinBoxPolaris->setValue(portPolarisWin); m_Controls->m_portSpinBoxAurora->setValue(portAuroraWin); m_Controls->portTypePolaris->setCurrentIndex(portTypePolaris); m_Controls->portTypeAurora->setCurrentIndex(portTypeAurora); MITK_INFO << "Sucessfully restored UI settings"; } else { // QSettings as a fallback if the persistence service is not available QSettings settings; settings.beginGroup(QString::fromStdString(id)); SelectedDevice = settings.value("trackingDeviceChooser", 0).toInt(); m_Controls->m_portSpinBoxAurora->setValue(settings.value("portSpinBoxAurora", 0).toInt()); m_Controls->m_portSpinBoxPolaris->setValue(settings.value("portSpinBoxPolaris", 0).toInt()); m_Controls->portTypePolaris->setCurrentIndex(settings.value("portTypePolaris", 0).toInt()); m_Controls->portTypeAurora->setCurrentIndex(settings.value("portTypeAurora", 0).toInt()); m_MTCalibrationFile = settings.value("mTCalibrationFile", "").toString().toStdString(); settings.endGroup(); } //the selected device requires some checks because a device that is not installed should not be restored to avoids bugs int selectedDeviceChecked = SelectedDevice; if (SelectedDevice==2 && !mitk::ClaronTrackingDevice::New()->IsDeviceInstalled()) {selectedDeviceChecked = 0;} //0 = Polaris (default) else if (SelectedDevice==3 && !mitk::OptitrackTrackingDevice::New()->IsDeviceInstalled()) {selectedDeviceChecked = 0;} - MITK_INFO << "SelectedDeviceChecked: " << selectedDeviceChecked; m_Controls->m_TrackingSystemWidget->setCurrentIndex(selectedDeviceChecked); m_Controls->m_trackingDeviceChooser->setCurrentIndex(selectedDeviceChecked); m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString::fromStdString(m_MTCalibrationFile)); } void QmitkTrackingDeviceConfigurationWidgetConnectionWorker::TestConnectionThreadFunc() { MITK_INFO << "Testing Connection!"; QString output; bool connected = false; mitk::ProgressBar::GetInstance()->AddStepsToDo(4); try { if (!m_TrackingDevice->IsDeviceInstalled()) { output = "ERROR: Device is not installed!"; } else { //test connection and start tracking, generate output output = "
testing connection
..."; m_TrackingDevice->OpenConnection(); output += "OK"; mitk::ProgressBar::GetInstance()->Progress(); //try start/stop tracking output += "
testing tracking
..."; m_TrackingDevice->StartTracking(); mitk::ProgressBar::GetInstance()->Progress(); m_TrackingDevice->StopTracking(); mitk::ProgressBar::GetInstance()->Progress(); //try close connection m_TrackingDevice->CloseConnection(); mitk::ProgressBar::GetInstance()->Progress(); output += "OK"; connected = true; } } catch(mitk::IGTException &e) { output += "ERROR!"; MITK_WARN << "Error while testing connection / start tracking of the device: " << e.GetDescription(); } mitk::ProgressBar::GetInstance()->Progress(4); emit ConnectionTested(connected,output); } void QmitkTrackingDeviceConfigurationWidgetScanPortsWorker::ScanPortsThreadFunc() { int PolarisPort = -1; int AuroraPort = -1; int PortTypePolaris = -1; int PortTypeAurora = -1; QString result = "
Found Devices:"; int resultSize = result.size(); //remember size of result: if it stays the same no device were found #ifdef WIN32 mitk::ProgressBar::GetInstance()->AddStepsToDo(19); QString devName; for (unsigned int i = 1; i < 20; ++i) { QString statusOutput = "Scanning Port #" + QString::number(i); MITK_INFO << statusOutput.toStdString().c_str(); if (i<10) devName = QString("COM%1").arg(i); else devName = QString("\\\\.\\COM%1").arg(i); // prepend "\\.\ to COM ports >9, to be able to allow connection" mitk::TrackingDeviceType scannedPort = ScanPort(devName); switch (scannedPort) { case mitk::NDIPolaris: result += "
" + devName + ": " + "NDI Polaris"; PolarisPort = i; break; case mitk::NDIAurora: result += "
" + devName + ": " + "NDI Aurora"; AuroraPort = i; break; } mitk::ProgressBar::GetInstance()->Progress(); } #else //linux systems for(unsigned int i = 1; i < 6; ++i) { QString devName = QString("/dev/ttyS%1").arg(i); mitk::TrackingDeviceType scannedPort = ScanPort(devName); switch (scannedPort) { case mitk::NDIPolaris: result += "
" + devName + ": " + "NDI Polaris"; PolarisPort = i; PortTypePolaris = 1; break; case mitk::NDIAurora: result += "
" + devName + ": " + "NDI Aurora"; AuroraPort = i; PortTypeAurora = 1; break; } } for(unsigned int i = 0; i <7; ++i) { QString devName = QString("/dev/ttyUSB%1").arg(i); mitk::TrackingDeviceType scannedPort = ScanPort(devName); switch (scannedPort) { case mitk::NDIPolaris: result += "
" + devName + ": " + "NDI Polaris"; PolarisPort = i; PortTypePolaris = 0; break; case mitk::NDIAurora: result += "
" + devName + ": " + "NDI Aurora"; AuroraPort = i; PortTypeAurora = 0; break; } } #endif if ( result.size() == resultSize) result += "
none"; emit PortsScanned(PolarisPort,AuroraPort,result,PortTypePolaris,PortTypeAurora); } mitk::TrackingDeviceType QmitkTrackingDeviceConfigurationWidgetScanPortsWorker::ScanPort(QString port) { mitk::NDITrackingDevice::Pointer tracker = mitk::NDITrackingDevice::New(); tracker->SetDeviceName(port.toStdString()); mitk::TrackingDeviceType returnValue = mitk::TrackingSystemInvalid; try {returnValue = tracker->TestConnection();} catch (mitk::IGTException) {}//do nothing: there is simply no device on this port return returnValue; } void QmitkTrackingDeviceConfigurationWidgetConnectionWorker::SetTrackingDevice(mitk::TrackingDevice::Pointer t) { m_TrackingDevice = t; } diff --git a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui index af461195fb..23e1731ea1 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui @@ -1,1045 +1,1084 @@ QmitkTrackingDeviceConfigurationWidgetControls 0 0 - 443 - 443 + 390 + 368 0 0 Form 0 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tracking Device Configuration</span></p></body></html> Qt::Horizontal 40 20 Choose tracking device: Qt::Horizontal 128 20 0 0 Polaris Aurora MicronTracker Optitrack + + + VirtualTracker + + Qt::Horizontal true 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Polaris</span></p></body></html> Com Port: COM Auto Scan Qt::Horizontal 40 20 Port Type: /dev/ttyUSB /dev/ttyS Qt::Horizontal 40 20 0 0 Tracking Mode false 5D false 6D true Qt::Horizontal 62 20 Qt::Vertical QSizePolicy::Expanding 158 17 120 50 120 80 120 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; color:#ffffff;">NDI Polaris selected</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 Test Connection <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Aurora</span></p></body></html> Com Port: COM Auto Scan Qt::Horizontal 40 20 Port Type: /dev/ttyUSB /dev/ttyS Qt::Horizontal 40 20 Qt::Vertical 20 40 120 50 120 80 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 Test Connection <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">MicronTracker</span></p></body></html> Calibration File: <none> Set Calibration File Qt::Horizontal 40 20 Qt::Horizontal 40 20 Qt::Vertical 20 40 120 50 120 80 120 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 120 0 test connection 0 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Optitrack</span></p></body></html> Calibration File: <none> Set Calibration File Qt::Horizontal 40 20 Camera Settings: 1 480 50 Exposition 250 200 Threshold 15 15 LED Power Qt::Vertical 20 5 false 120 50 120 80 120 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 120 0 test connection + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Virtual Tracker</span></p></body></html> + + + + + + + Qt::Vertical + + + + 20 + 136 + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p align="right" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Press &quot;Finished&quot; to confirm configuration</span> </p></body></html> Qt::Vertical 20 14 Qt::Horizontal Qt::Horizontal 40 20 Reset Finished 0 Qt::Vertical 20 289 true 0 0 - 55 - 31 + 63 + 26 Qt::Vertical 20 269 16777215 0 Qt::Vertical 20 40 diff --git a/Modules/IGTUI/resources/fastbackward.png b/Modules/IGTUI/resources/fastbackward.png index cf0710f374..6aa4d21b9d 100644 Binary files a/Modules/IGTUI/resources/fastbackward.png and b/Modules/IGTUI/resources/fastbackward.png differ diff --git a/Modules/IGTUI/resources/fastforward.png b/Modules/IGTUI/resources/fastforward.png index 8e07f05b90..61780f8e05 100644 Binary files a/Modules/IGTUI/resources/fastforward.png and b/Modules/IGTUI/resources/fastforward.png differ diff --git a/Modules/IGTUI/resources/firstframe.png b/Modules/IGTUI/resources/firstframe.png index a5dc5ee9fc..a985209813 100644 Binary files a/Modules/IGTUI/resources/firstframe.png and b/Modules/IGTUI/resources/firstframe.png differ diff --git a/Modules/IGTUI/resources/lastframe.png b/Modules/IGTUI/resources/lastframe.png index 12e06af42a..89444e12d6 100644 Binary files a/Modules/IGTUI/resources/lastframe.png and b/Modules/IGTUI/resources/lastframe.png differ diff --git a/Modules/IGTUI/resources/nextframe.png b/Modules/IGTUI/resources/nextframe.png index 1793d2d291..1ccc958721 100644 Binary files a/Modules/IGTUI/resources/nextframe.png and b/Modules/IGTUI/resources/nextframe.png differ diff --git a/Modules/IGTUI/resources/play2.png b/Modules/IGTUI/resources/play2.png index 0472a46e5d..cb0502d5a4 100644 Binary files a/Modules/IGTUI/resources/play2.png and b/Modules/IGTUI/resources/play2.png differ diff --git a/Modules/IGTUI/resources/previousframe.png b/Modules/IGTUI/resources/previousframe.png index d5c6f94043..f978e4cdbf 100644 Binary files a/Modules/IGTUI/resources/previousframe.png and b/Modules/IGTUI/resources/previousframe.png differ diff --git a/Modules/IGTUI/resources/stop_recording.png b/Modules/IGTUI/resources/stop_recording.png index 46c69cf9e1..950452bc45 100644 Binary files a/Modules/IGTUI/resources/stop_recording.png and b/Modules/IGTUI/resources/stop_recording.png differ diff --git a/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp b/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp index 0470850d4e..429ee09f5f 100644 --- a/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp +++ b/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp @@ -1,196 +1,197 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIOExtObjectFactory.h" #include "mitkCoreObjectFactory.h" #include "mitkParRecFileIOFactory.h" #include "mitkObjFileIOFactory.h" #include "mitkVtkUnstructuredGridIOFactory.h" #include "mitkStlVolumeTimeSeriesIOFactory.h" #include "mitkVtkVolumeTimeSeriesIOFactory.h" #include "mitkUnstructuredGridVtkWriterFactory.h" #include "mitkUnstructuredGridVtkWriter.h" #include "mitkMeshMapper2D.h" #include "mitkMeshVtkMapper3D.h" #include "mitkMesh.h" #include "mitkGPUVolumeMapper3D.h" #include "mitkUnstructuredGridMapper2D.h" #include "mitkUnstructuredGridVtkMapper3D.h" +#include "mitkVtkGLMapperWrapper.h" #include #include #include mitk::IOExtObjectFactory::IOExtObjectFactory() : CoreObjectFactoryBase() , m_ParRecFileIOFactory(ParRecFileIOFactory::New().GetPointer()) , m_ObjFileIOFactory(ObjFileIOFactory::New().GetPointer()) , m_VtkUnstructuredGridIOFactory(VtkUnstructuredGridIOFactory::New().GetPointer()) , m_StlVolumeTimeSeriesIOFactory(StlVolumeTimeSeriesIOFactory::New().GetPointer()) , m_VtkVolumeTimeSeriesIOFactory(VtkVolumeTimeSeriesIOFactory::New().GetPointer()) , m_UnstructuredGridVtkWriterFactory(UnstructuredGridVtkWriterFactory::New().GetPointer()) { static bool alreadyDone = false; if (!alreadyDone) { MITK_DEBUG << "IOExtObjectFactory c'tor" << std::endl; itk::ObjectFactoryBase::RegisterFactory( m_ParRecFileIOFactory ); itk::ObjectFactoryBase::RegisterFactory( m_ObjFileIOFactory ); itk::ObjectFactoryBase::RegisterFactory( m_VtkUnstructuredGridIOFactory ); itk::ObjectFactoryBase::RegisterFactory( m_StlVolumeTimeSeriesIOFactory ); itk::ObjectFactoryBase::RegisterFactory( m_VtkVolumeTimeSeriesIOFactory ); itk::ObjectFactoryBase::RegisterFactory( m_UnstructuredGridVtkWriterFactory ); m_FileWriters.push_back(mitk::UnstructuredGridVtkWriter::New().GetPointer()); m_FileWriters.push_back(mitk::UnstructuredGridVtkWriter::New().GetPointer()); m_FileWriters.push_back(mitk::UnstructuredGridVtkWriter::New().GetPointer()); CreateFileExtensionsMap(); alreadyDone = true; } } mitk::IOExtObjectFactory::~IOExtObjectFactory() { itk::ObjectFactoryBase::UnRegisterFactory( m_ParRecFileIOFactory ); itk::ObjectFactoryBase::UnRegisterFactory( m_ObjFileIOFactory ); itk::ObjectFactoryBase::UnRegisterFactory( m_VtkUnstructuredGridIOFactory ); itk::ObjectFactoryBase::UnRegisterFactory( m_StlVolumeTimeSeriesIOFactory ); itk::ObjectFactoryBase::UnRegisterFactory( m_VtkVolumeTimeSeriesIOFactory ); itk::ObjectFactoryBase::UnRegisterFactory( m_UnstructuredGridVtkWriterFactory ); } mitk::Mapper::Pointer mitk::IOExtObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id) { mitk::Mapper::Pointer newMapper=NULL; mitk::BaseData *data = node->GetData(); if ( id == mitk::BaseRenderer::Standard2D ) { if((dynamic_cast(data)!=NULL)) { newMapper = mitk::MeshMapper2D::New(); newMapper->SetDataNode(node); } else if((dynamic_cast(data)!=NULL)) { - newMapper = mitk::UnstructuredGridMapper2D::New(); + newMapper = mitk::VtkGLMapperWrapper::New(mitk::UnstructuredGridMapper2D::New().GetPointer()); newMapper->SetDataNode(node); } } else if ( id == mitk::BaseRenderer::Standard3D ) { if((dynamic_cast(data) != NULL)) { newMapper = mitk::GPUVolumeMapper3D::New(); newMapper->SetDataNode(node); } else if((dynamic_cast(data)!=NULL)) { newMapper = mitk::MeshVtkMapper3D::New(); newMapper->SetDataNode(node); } else if((dynamic_cast(data)!=NULL)) { newMapper = mitk::UnstructuredGridVtkMapper3D::New(); newMapper->SetDataNode(node); } } return newMapper; } void mitk::IOExtObjectFactory::SetDefaultProperties(mitk::DataNode* node) { if(node==NULL) return; mitk::DataNode::Pointer nodePointer = node; mitk::Image::Pointer image = dynamic_cast(node->GetData()); if(image.IsNotNull() && image->IsInitialized()) { mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } if (dynamic_cast(node->GetData())) { mitk::UnstructuredGridVtkMapper3D::SetDefaultProperties(node); } } const char* mitk::IOExtObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::IOExtObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } mitk::CoreObjectFactoryBase::MultimapType mitk::IOExtObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::IOExtObjectFactory::CreateFileExtensionsMap() { m_FileExtensionsMap.insert(std::pair("*.vtu", "VTK Unstructured Grid")); m_FileExtensionsMap.insert(std::pair("*.vtk", "VTK Unstructured Grid")); m_FileExtensionsMap.insert(std::pair("*.pvtu", "VTK Unstructured Grid")); m_FileExtensionsMap.insert(std::pair("*.obj", "Surfaces")); m_SaveFileExtensionsMap.insert(std::pair("*.pvtu", "VTK Parallel XML Unstructured Grid")); m_SaveFileExtensionsMap.insert(std::pair("*.vtu", "VTK XML Unstructured Grid")); m_SaveFileExtensionsMap.insert(std::pair("*.vtk", "VTK Legacy Unstructured Grid")); } const char* mitk::IOExtObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); } struct RegisterIOExtObjectFactory { RegisterIOExtObjectFactory() : m_Factory( mitk::IOExtObjectFactory::New() ) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory ); } ~RegisterIOExtObjectFactory() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory ); } mitk::IOExtObjectFactory::Pointer m_Factory; }; static RegisterIOExtObjectFactory registerIOExtObjectFactory; diff --git a/Modules/LegacyGL/mitkVtkGLMapperWrapper.cpp b/Modules/LegacyGL/mitkVtkGLMapperWrapper.cpp index a543a1f861..d602a650e0 100644 --- a/Modules/LegacyGL/mitkVtkGLMapperWrapper.cpp +++ b/Modules/LegacyGL/mitkVtkGLMapperWrapper.cpp @@ -1,159 +1,174 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkVtkGLMapperWrapper.h" //mitk includes #include "mitkDataNode.h" #include "vtkGLMapperProp.h" #include "mitkGL.h" // constructor LocalStorage mitk::VtkGLMapperWrapper::LocalStorage::LocalStorage() { m_GLMapperProp = vtkSmartPointer::New(); } // destructor LocalStorage mitk::VtkGLMapperWrapper::LocalStorage::~LocalStorage() { } // constructor VtkGLMapperWrapper mitk::VtkGLMapperWrapper::VtkGLMapperWrapper(GLMapper::Pointer mitkGLMapper) { m_MitkGLMapper = mitkGLMapper; } // destructor mitk::VtkGLMapperWrapper::~VtkGLMapperWrapper() { } // returns propassembly vtkProp* mitk::VtkGLMapperWrapper::GetVtkProp(mitk::BaseRenderer * renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); return ls->m_GLMapperProp; } void mitk::VtkGLMapperWrapper::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { - m_MitkGLMapper->SetDataNode(GetDataNode()); LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_GLMapperProp->SetBaseRenderer(renderer); ls->m_GLMapperProp->SetWrappedGLMapper(m_MitkGLMapper); } void mitk::VtkGLMapperWrapper::ApplyColorAndOpacityProperties(mitk::BaseRenderer *renderer, vtkActor *actor) { m_MitkGLMapper->ApplyColorAndOpacityProperties(renderer,actor); } void mitk::VtkGLMapperWrapper::MitkRender(mitk::BaseRenderer *renderer, mitk::VtkPropRenderer::RenderType type) { if(type != mitk::VtkPropRenderer::Opaque) return; Enable2DOpenGL(renderer); Superclass::MitkRender(renderer,type); Disable2DOpenGL(); } +void mitk::VtkGLMapperWrapper::Update(mitk::BaseRenderer* renderer) +{ + Superclass::Update(renderer); + m_MitkGLMapper->Update(renderer); +} + +void mitk::VtkGLMapperWrapper::SetDataNode(mitk::DataNode *node) +{ + m_MitkGLMapper->SetDataNode(node); +} + +mitk::DataNode *mitk::VtkGLMapperWrapper::GetDataNode() const +{ + return m_MitkGLMapper->GetDataNode(); +} + /*! \brief Enable2DOpenGL() and Disable2DOpenGL() are used to switch between 2D rendering (orthographic projection) and 3D rendering (perspective projection) */ void mitk::VtkGLMapperWrapper::Enable2DOpenGL(mitk::BaseRenderer *renderer) { GLint iViewport[4]; // Get a copy of the viewport glGetIntegerv( GL_VIEWPORT, iViewport ); // Save a copy of the projection matrix so that we can restore it // when it's time to do 3D rendering again. glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); // Set up the orthographic projection const mitk::DisplayGeometry* displayGeometry = renderer->GetDisplayGeometry(); float displayGeometryWidth = displayGeometry->GetSizeInDisplayUnits()[0]; float displayGeometryHeight = displayGeometry->GetSizeInDisplayUnits()[1]; float viewportWidth = iViewport[2]; float viewportHeight = iViewport[3]; /* The following makes OpenGL mappers draw into the same viewport that is used by VTK when someone calls vtkRenderer::SetViewport(). The parameters of glOrtho describe what "input" coordinates (display coordinates generated by the OpenGL mappers) are transformed into the region defined by the viewport. The call has to consider that the scene is fit vertically and centered horizontally. Problem: this is a crude first step towards rendering into viewports. - mitkViewportRenderingTest demonstrates the non-interactive rendering that is now possible - interactors that measure mouse movement in pixels will probably run into problems with display-to-world transformation A proper solution should probably modify the DisplayGeometry to correctly describe the viewport. */ // iViewport is (x,y,width,height) // glOrtho expects (left,right,bottom,top,znear,zfar) glOrtho( 0 - 0.5 * (viewportWidth/viewportHeight-1.0)*displayGeometryHeight + 0.5 * (displayGeometryWidth - displayGeometryHeight) , displayGeometryWidth + 0.5 * (viewportWidth/viewportHeight-1.0)*displayGeometryHeight - 0.5 * (displayGeometryWidth - displayGeometryHeight) , 0, displayGeometryHeight, -1.0, 1.0 ); glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); // Make sure depth testing and lighting are disabled for 2D rendering until // we are finished rendering in 2D glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT ); glDisable( GL_DEPTH_TEST ); glDisable( GL_LIGHTING ); // disable the texturing here so crosshair is painted in the correct colors // vtk will reenable texturing every time it is needed glDisable( GL_TEXTURE_1D ); glDisable( GL_TEXTURE_2D ); glLineWidth(1.0); } /*! \brief Initialize the VtkPropRenderer Enable2DOpenGL() and Disable2DOpenGL() are used to switch between 2D rendering (orthographic projection) and 3D rendering (perspective projection) */ void mitk::VtkGLMapperWrapper::Disable2DOpenGL() { glPopAttrib(); glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); } diff --git a/Modules/LegacyGL/mitkVtkGLMapperWrapper.h b/Modules/LegacyGL/mitkVtkGLMapperWrapper.h index af0bd1edce..8122038e36 100644 --- a/Modules/LegacyGL/mitkVtkGLMapperWrapper.h +++ b/Modules/LegacyGL/mitkVtkGLMapperWrapper.h @@ -1,84 +1,90 @@ /*=================================================================== 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 MITKVtkGLMapperWrapper_H_HEADER #define MITKVtkGLMapperWrapper_H_HEADER #include #include "mitkVtkMapper.h" #include "mitkBaseRenderer.h" #include "mitkLocalStorageHandler.h" #include #include "mitkGLMapper.h" class vtkGLMapperProp; namespace mitk { /** * @brief Vtk-based 2D mapper for PointSet */ class MITKLEGACYGL_EXPORT VtkGLMapperWrapper : public VtkMapper { public: mitkClassMacro(VtkGLMapperWrapper, VtkMapper); mitkNewMacro1Param(Self,GLMapper::Pointer) itkCloneMacro(Self) /** \brief returns the a prop assembly */ virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); /** \brief Internal class holding the mapper, actor, etc. for each of the 3 2D render windows */ class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /* constructor */ LocalStorage(); /* destructor */ ~LocalStorage(); vtkSmartPointer m_GLMapperProp; }; virtual void ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor * actor); void MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType type); + virtual void Update(BaseRenderer *renderer); + + virtual void SetDataNode(DataNode* node); + + virtual DataNode* GetDataNode() const; + /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::LocalStorageHandler m_LSH; protected: GLMapper::Pointer m_MitkGLMapper; /* constructor */ VtkGLMapperWrapper(GLMapper::Pointer mitkGLMapper); /* destructor */ virtual ~VtkGLMapperWrapper(); void Enable2DOpenGL(mitk::BaseRenderer *renderer); void Disable2DOpenGL(); }; } // namespace mitk #endif /* MITKVtkGLMapperWrapper_H_HEADER_INCLUDED_C1902626 */ diff --git a/Modules/LegacyGL/vtkGLMapperProp.cpp b/Modules/LegacyGL/vtkGLMapperProp.cpp index 15418706b2..d02d9cc4b6 100644 --- a/Modules/LegacyGL/vtkGLMapperProp.cpp +++ b/Modules/LegacyGL/vtkGLMapperProp.cpp @@ -1,70 +1,70 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "vtkGLMapperProp.h" #include vtkStandardNewMacro(vtkGLMapperProp); vtkGLMapperProp::vtkGLMapperProp() : m_WrappedGLMapper(0), m_BaseRenderer(0) { } vtkGLMapperProp::~vtkGLMapperProp() { } int vtkGLMapperProp::RenderOpaqueGeometry(vtkViewport *) { if(!m_WrappedGLMapper || !m_BaseRenderer) return 0; this->m_WrappedGLMapper->MitkRender(m_BaseRenderer, mitk::VtkPropRenderer::Opaque); } int vtkGLMapperProp::RenderTranslucentPolygonalGeometry(vtkViewport *) { return 0; } int vtkGLMapperProp::RenderVolumetricGeometry(vtkViewport *) { return 0; } int vtkGLMapperProp::RenderOverlay(vtkViewport *) { return 0; } const mitk::GLMapper *vtkGLMapperProp::GetWrappedGLMapper() const { return m_WrappedGLMapper; } void vtkGLMapperProp::SetWrappedGLMapper(mitk::GLMapper* glMapper) { this->m_WrappedGLMapper = glMapper; } void vtkGLMapperProp::SetBaseRenderer(mitk::BaseRenderer *baseRenderer) { this->m_BaseRenderer = baseRenderer; -} \ No newline at end of file +} diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index 8cb0d831db..60a52d14a0 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,66 +1,67 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(mitk_modules Core DCMTesting RDF LegacyIO DataTypesExt Overlays LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMTesting Qt4Qt5TestModule SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction ImageStatistics LegacyAdaptors SceneSerialization GraphAlgorithms + Multilabel ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation OpenViewCore QmlItems QtWidgets QtWidgetsExt SegmentationUI DiffusionImaging GPGPU IGTBase IGT CameraCalibration RigidRegistration RigidRegistrationUI DeformableRegistration DeformableRegistrationUI OpenCL OpenCVVideoSupport QtOverlays InputDevices ToFHardware ToFProcessing ToFUI US USUI DicomUI Simulation Remeshing Python Persistence IGTUI VtkShaders DicomRT IOExt XNAT ) if(MITK_ENABLE_PIC_READER) list(APPEND mitk_modules IpPicSupportIO) endif() diff --git a/Modules/Multilabel/CMakeLists.txt b/Modules/Multilabel/CMakeLists.txt new file mode 100644 index 0000000000..5d84721ff0 --- /dev/null +++ b/Modules/Multilabel/CMakeLists.txt @@ -0,0 +1,9 @@ +MITK_CREATE_MODULE( + DEPENDS MitkCore MitkAlgorithmsExt MitkSceneSerializationBase + PACKAGE_DEPENDS PRIVATE ITK|ITKQuadEdgeMesh+ITKAntiAlias+ITKIONRRD + WARNINGS_AS_ERRORS +) + +if(BUILD_TESTING) + add_subdirectory(Testing) +endif() diff --git a/Modules/Multilabel/Testing/CMakeLists.txt b/Modules/Multilabel/Testing/CMakeLists.txt new file mode 100644 index 0000000000..153cd81e2e --- /dev/null +++ b/Modules/Multilabel/Testing/CMakeLists.txt @@ -0,0 +1 @@ +MITK_CREATE_MODULE_TESTS() diff --git a/Modules/Multilabel/Testing/files.cmake b/Modules/Multilabel/Testing/files.cmake new file mode 100644 index 0000000000..97fb1986b7 --- /dev/null +++ b/Modules/Multilabel/Testing/files.cmake @@ -0,0 +1,7 @@ +set(MODULE_TESTS + mitkLabelTest.cpp + mitkLabelSetTest.cpp + mitkLabelSetImageTest.cpp + mitkLabelSetImageIOTest.cpp +) + diff --git a/Modules/Multilabel/Testing/mitkLabelSetImageIOTest.cpp b/Modules/Multilabel/Testing/mitkLabelSetImageIOTest.cpp new file mode 100644 index 0000000000..23a8846b35 --- /dev/null +++ b/Modules/Multilabel/Testing/mitkLabelSetImageIOTest.cpp @@ -0,0 +1,121 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include + +#include +#include + +std::string pathToImage; + +class mitkLabelSetImageIOTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkLabelSetImageIOTestSuite); + MITK_TEST(TestGetWriteConfidenceLevel); + MITK_TEST(TestWriteLabelSetImage); + MITK_TEST(TestGetReadConfidenceLevel); + MITK_TEST(TestReadLabelSetImage); + CPPUNIT_TEST_SUITE_END(); + +private: + mitk::Image::Pointer regularImage; + mitk::LabelSetImage::Pointer multilabelImage; + mitk::LabelSetImageIO* lsetIO; + +public: + + void setUp() + { + regularImage = mitk::Image::New(); + unsigned int dimensions[3] = {256,256,312}; + regularImage->Initialize(mitk::MakeScalarPixelType(), 3, dimensions); + + multilabelImage = mitk::LabelSetImage::New(); + multilabelImage->Initialize(regularImage); + mitk::LabelSet::Pointer newlayer = mitk::LabelSet::New(); + newlayer->SetLayer(1); + mitk::Label::Pointer label1 = mitk::Label::New(); + label1->SetName("Label1"); + label1->SetValue(1); + + mitk::Label::Pointer label2 = mitk::Label::New(); + label2->SetName("Label2"); + label2->SetValue(200); + + newlayer->AddLabel(label1); + newlayer->AddLabel(label2); + newlayer->SetActiveLabel(200); + // TODO assert that the layer od labelset and labels is correct - TEST + + multilabelImage->AddLayer(newlayer); + + lsetIO = new mitk::LabelSetImageIO(); + } + + void tearDown() + { + regularImage = 0; + multilabelImage = 0; + delete lsetIO; + } + + void TestGetWriteConfidenceLevel() + { + dynamic_cast(lsetIO)->SetInput(regularImage); + CPPUNIT_ASSERT_MESSAGE("LabelSetImageIO returned wrong writer confidence level", lsetIO->GetWriterConfidenceLevel() == mitk::IFileIO::Unsupported); + + dynamic_cast(lsetIO)->SetInput(multilabelImage); + CPPUNIT_ASSERT_MESSAGE("LabelSetImageIO returned wrong writer confidence level", lsetIO->GetWriterConfidenceLevel() == mitk::IFileIO::Supported); + } + + void TestWriteLabelSetImage() + { + pathToImage = mitk::IOUtil::CreateTemporaryDirectory(); + pathToImage.append("/LabelSetTestImage.nrrd"); + + dynamic_cast(lsetIO)->SetInput(multilabelImage); + dynamic_cast(lsetIO)->SetOutputLocation(pathToImage); + dynamic_cast(lsetIO)->Write(); + } + + void TestGetReadConfidenceLevel() + { + dynamic_cast(lsetIO)->SetInput(GetTestDataFilePath("Pic3D.nrrd")); + CPPUNIT_ASSERT_MESSAGE("LabelSetImageIO returned wrong reader confidence level", lsetIO->GetReaderConfidenceLevel() == mitk::IFileIO::Unsupported); + + std::string path = GetTestDataFilePath("Multilabel/Pic3DAsMultilabelImage.nrrd"); + dynamic_cast(lsetIO)->SetInput(path); + CPPUNIT_ASSERT_MESSAGE("LabelSetImageIO returned wrong reader confidence level", lsetIO->GetReaderConfidenceLevel() == mitk::IFileIO::Supported); + } + + void TestReadLabelSetImage() + { + dynamic_cast(lsetIO)->SetInput(pathToImage); + std::vector data = dynamic_cast(lsetIO)->Read(); + CPPUNIT_ASSERT_MESSAGE("Too many images have been read", data.size() == 1); + mitk::LabelSetImage::Pointer loadedImage = dynamic_cast(data.at(0).GetPointer()); + + // This information is currently not serialized but also checked within the Equals function + loadedImage->SetActiveLayer(multilabelImage->GetActiveLayer()); + + CPPUNIT_ASSERT_MESSAGE("Error reading label set image", loadedImage.IsNotNull()); + CPPUNIT_ASSERT_MESSAGE("Error reading label set image", mitk::Equal(*multilabelImage, *loadedImage, 0.0001, true)); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkLabelSetImageIO) diff --git a/Modules/Multilabel/Testing/mitkLabelSetImageTest.cpp b/Modules/Multilabel/Testing/mitkLabelSetImageTest.cpp new file mode 100644 index 0000000000..22c72ee73e --- /dev/null +++ b/Modules/Multilabel/Testing/mitkLabelSetImageTest.cpp @@ -0,0 +1,414 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include +#include + +class mitkLabelSetImageTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkLabelSetImageTestSuite); + MITK_TEST(TestInitialize); + MITK_TEST(TestAddLayer); + MITK_TEST(TestGetActiveLabelSet); + MITK_TEST(TestGetActiveLabel); + MITK_TEST(TestInitializeByLabeledImage); + MITK_TEST(TestGetLabelSet); + MITK_TEST(TestGetLabel); + MITK_TEST(TestSetExteriorLabel); + MITK_TEST(TestGetTotalNumberOfLabels); + MITK_TEST(TestExistsLabel); + MITK_TEST(TestExistsLabelSet); + MITK_TEST(TestSetActiveLayer); + MITK_TEST(TestRemoveLayer); + MITK_TEST(TestRemoveLabels); + MITK_TEST(TestMergeLabel); + // TODO check it these functionalities can be moved into a process object +// MITK_TEST(TestMergeLabels); +// MITK_TEST(TestConcatenate); +// MITK_TEST(TestClearBuffer); +// MITK_TEST(TestUpdateCenterOfMass); +// MITK_TEST(TestGetVectorImage); +// MITK_TEST(TestSetVectorImage); +// MITK_TEST(TestGetLayerImage); + CPPUNIT_TEST_SUITE_END(); + +private: + mitk::LabelSetImage::Pointer m_LabelSetImage; + +public: + + void setUp() + { + // Create a new labelset image + m_LabelSetImage = mitk::LabelSetImage::New(); + mitk::Image::Pointer regularImage = mitk::Image::New(); + unsigned int dimensions[3] = {256,256,312}; + regularImage->Initialize(mitk::MakeScalarPixelType(), 3, dimensions); + m_LabelSetImage->Initialize(regularImage); + } + + void tearDown() + { + // Delete LabelSetImage + m_LabelSetImage = 0; + } + + // Reduce contours with nth point + void TestInitialize() + { + // LabelSet image should always has the pixel type mitk::Label::PixelType + CPPUNIT_ASSERT_MESSAGE("LabelSetImage has wrong pixel type", + m_LabelSetImage->GetPixelType() == mitk::MakeScalarPixelType()); + + mitk::Image::Pointer regularImage = mitk::Image::New(); + unsigned int dimensions[3] = {256,256,312}; + regularImage->Initialize(mitk::MakeScalarPixelType(), 3, dimensions); + + mitk::BaseGeometry::Pointer regularImageGeo = regularImage->GetGeometry(); + mitk::BaseGeometry::Pointer labelImageGeo = m_LabelSetImage->GetGeometry(); + MITK_ASSERT_EQUAL(labelImageGeo, regularImageGeo, "LabelSetImage has wrong geometry"); + + // By default one layer containing the exterior label should be added + CPPUNIT_ASSERT_MESSAGE("Image was not correctly initialized - number of layers is not one",m_LabelSetImage->GetNumberOfLayers() == 1); + CPPUNIT_ASSERT_MESSAGE("Image was not correctly initialized - active layer has wrong ID",m_LabelSetImage->GetActiveLayer() == 0); + + CPPUNIT_ASSERT_MESSAGE("Image was not correctly initialized - active label is not the exterior label",m_LabelSetImage->GetActiveLabel()->GetValue() == 0); + } + + void TestAddLayer() + { + CPPUNIT_ASSERT_MESSAGE("Number of layers is not zero",m_LabelSetImage->GetNumberOfLayers() == 1); + + m_LabelSetImage->AddLayer(); + CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - number of layers is not one",m_LabelSetImage->GetNumberOfLayers() == 2); + CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active layer has wrong ID", m_LabelSetImage->GetActiveLayer() == 1); + + CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active label is not the exterior label",m_LabelSetImage->GetActiveLabel()->GetValue() == 0); + + mitk::LabelSet::Pointer newlayer = mitk::LabelSet::New(); + mitk::Label::Pointer label1 = mitk::Label::New(); + label1->SetName("Label1"); + label1->SetValue(1); + + mitk::Label::Pointer label2 = mitk::Label::New(); + label2->SetName("Label2"); + label2->SetValue(200); + + newlayer->AddLabel(label1); + newlayer->AddLabel(label2); + newlayer->SetActiveLabel(200); + + unsigned int layerID = m_LabelSetImage->AddLayer(newlayer); + CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - number of layers is not two",m_LabelSetImage->GetNumberOfLayers() == 3); + CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active layer has wrong ID",m_LabelSetImage->GetActiveLayer() == layerID); + CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active label is wrong",m_LabelSetImage->GetActiveLabel(layerID)->GetValue() == 200); + } + + void TestGetActiveLabelSet() + { + mitk::LabelSet::Pointer newlayer = mitk::LabelSet::New(); + mitk::Label::Pointer label1 = mitk::Label::New(); + label1->SetName("Label1"); + label1->SetValue(1); + + mitk::Label::Pointer label2 = mitk::Label::New(); + label2->SetName("Label2"); + label2->SetValue(200); + + newlayer->AddLabel(label1); + newlayer->AddLabel(label2); + newlayer->SetActiveLabel(200); + + unsigned int layerID = m_LabelSetImage->AddLayer(newlayer); + + mitk::LabelSet::Pointer activeLayer = m_LabelSetImage->GetActiveLabelSet(); + + CPPUNIT_ASSERT_MESSAGE("Wrong layer ID was returned", layerID == 1); + CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned", mitk::Equal(*newlayer, *activeLayer, 0.00001, true)); + } + + void TestGetActiveLabel() + { + mitk::Label::Pointer label1 = mitk::Label::New(); + label1->SetName("Label1"); + mitk::Label::PixelType value1 = 1; + label1->SetValue(value1); + + mitk::Label::Pointer label2 = mitk::Label::New(); + label2->SetName("Label2"); + mitk::Label::PixelType value2 = 200; + label2->SetValue(value2); + + m_LabelSetImage->GetActiveLabelSet()->AddLabel(label1); + m_LabelSetImage->GetActiveLabelSet()->AddLabel(label2); + m_LabelSetImage->GetActiveLabelSet()->SetActiveLabel(1); + CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active label is wrong",m_LabelSetImage->GetActiveLabel()->GetValue() == value1); + m_LabelSetImage->GetActiveLabelSet()->SetActiveLabel(value2); + CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active label is wrong",m_LabelSetImage->GetActiveLabel()->GetValue() == value2); + } + + void TestInitializeByLabeledImage() + { + mitk::Image::Pointer image = mitk::IOUtil::LoadImage(GetTestDataFilePath("Multilabel/LabelSetTestInitializeImage.nrrd")); + m_LabelSetImage->InitializeByLabeledImage(image); + CPPUNIT_ASSERT_MESSAGE("Image - number of labels is not 6",m_LabelSetImage->GetNumberOfLabels() == 6); + } + + void TestGetLabelSet() + { + // Test get non existing lset + mitk::LabelSet::ConstPointer lset = m_LabelSetImage->GetLabelSet(10000); + CPPUNIT_ASSERT_MESSAGE("Non existing labelset is not NULL", lset.IsNull()); + + lset = m_LabelSetImage->GetLabelSet(0); + CPPUNIT_ASSERT_MESSAGE("Existing labelset is NULL", lset.IsNotNull()); + } + + void TestGetLabel() + { + mitk::Label::Pointer label1 = mitk::Label::New(); + label1->SetName("Label1"); + mitk::Label::PixelType value1 = 1; + label1->SetValue(value1); + + mitk::Label::Pointer label2 = mitk::Label::New(); + label2->SetName("Label2"); + mitk::Label::PixelType value2 = 200; + label2->SetValue(value2); + + m_LabelSetImage->GetActiveLabelSet()->AddLabel(label1); + m_LabelSetImage->AddLayer(); + m_LabelSetImage->GetLabelSet(1)->AddLabel(label2); + + CPPUNIT_ASSERT_MESSAGE("Wrong label retrieved for active layer", mitk::Equal(*m_LabelSetImage->GetLabel(1), *label1, 0.0001, true)); + CPPUNIT_ASSERT_MESSAGE("Wrong label retrieved for layer 1", mitk::Equal(*m_LabelSetImage->GetLabel(200, 1), *label2, 0.0001, true)); + + // Try to get a non existing label + mitk::Label* label3 = m_LabelSetImage->GetLabel(1000); + CPPUNIT_ASSERT_MESSAGE("Non existing label should be NULL", label3 == NULL); + + // Try to get a label from a non existing layer + label3 = m_LabelSetImage->GetLabel(200, 1000); + CPPUNIT_ASSERT_MESSAGE("Label from non existing layer should be NULL", label3 == NULL); + } + + void TestSetExteriorLabel() + { + mitk::Label::Pointer exteriorLabel = mitk::Label::New(); + exteriorLabel->SetName("MyExteriorSpecialLabel"); + mitk::Label::PixelType value1 = 10000; + exteriorLabel->SetValue(value1); + + m_LabelSetImage->SetExteriorLabel(exteriorLabel); + CPPUNIT_ASSERT_MESSAGE("Wrong label retrieved for layer 1", mitk::Equal(*m_LabelSetImage->GetExteriorLabel(), *exteriorLabel, 0.0001, true)); + + // Exterior label should be set automatically for each new layer + m_LabelSetImage->AddLayer(); + CPPUNIT_ASSERT_MESSAGE("Wrong label retrieved for layer 1", mitk::Equal(*m_LabelSetImage->GetLabel(10000, 1), *exteriorLabel, 0.0001, true)); + } + + void TestGetTotalNumberOfLabels() + { + mitk::Label::Pointer label1 = mitk::Label::New(); + label1->SetName("Label1"); + mitk::Label::PixelType value1 = 1; + label1->SetValue(value1); + + mitk::Label::Pointer label2 = mitk::Label::New(); + label2->SetName("Label2"); + mitk::Label::PixelType value2 = 200; + label2->SetValue(value2); + + m_LabelSetImage->GetActiveLabelSet()->AddLabel(label1); + m_LabelSetImage->AddLayer(); + m_LabelSetImage->GetLabelSet(1)->AddLabel(label2); + CPPUNIT_ASSERT_MESSAGE("Wrong total number of labels", m_LabelSetImage->GetTotalNumberOfLabels() == 4); // added 2 labels + 2 exterior default labels + } + + void TestExistsLabel() + { + mitk::Label::Pointer label = mitk::Label::New(); + label->SetName("Label2"); + mitk::Label::PixelType value = 200; + label->SetValue(value); + + m_LabelSetImage->AddLayer(); + m_LabelSetImage->GetLabelSet(1)->AddLabel(label); + m_LabelSetImage->SetActiveLayer(0); + CPPUNIT_ASSERT_MESSAGE("Existing label was not found", m_LabelSetImage->ExistLabel(value) == true); + + CPPUNIT_ASSERT_MESSAGE("Non existing label was found", m_LabelSetImage->ExistLabel(10000) == false); + } + + void TestExistsLabelSet() + { + // Cache active layer + mitk::LabelSet::ConstPointer activeLayer = m_LabelSetImage->GetActiveLabelSet(); + + // Add new layer + mitk::LabelSet::Pointer newlayer = mitk::LabelSet::New(); + mitk::Label::Pointer label1 = mitk::Label::New(); + label1->SetName("Label1"); + label1->SetValue(1); + + mitk::Label::Pointer label2 = mitk::Label::New(); + label2->SetName("Label2"); + label2->SetValue(200); + + newlayer->AddLabel(label1); + newlayer->AddLabel(label2); + newlayer->SetActiveLabel(200); + + m_LabelSetImage->AddLayer(newlayer); + + CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed",m_LabelSetImage->ExistLabelSet(0) == true); + CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed",m_LabelSetImage->ExistLabelSet(1) == true); + CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed",m_LabelSetImage->ExistLabelSet(20) == false); + } + + void TestSetActiveLayer() + { + // Cache active layer + mitk::LabelSet::ConstPointer activeLayer = m_LabelSetImage->GetActiveLabelSet(); + + // Add new layer + mitk::LabelSet::Pointer newlayer = mitk::LabelSet::New(); + mitk::Label::Pointer label1 = mitk::Label::New(); + label1->SetName("Label1"); + label1->SetValue(1); + + mitk::Label::Pointer label2 = mitk::Label::New(); + label2->SetName("Label2"); + label2->SetValue(200); + + newlayer->AddLabel(label1); + newlayer->AddLabel(label2); + newlayer->SetActiveLabel(200); + + unsigned int layerID = m_LabelSetImage->AddLayer(newlayer); + + // Set initial layer as active layer + m_LabelSetImage->SetActiveLayer(0); + CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned", mitk::Equal(*activeLayer, *m_LabelSetImage->GetActiveLabelSet(), 0.00001, true)); + + // Set previously added layer as active layer + m_LabelSetImage->SetActiveLayer(layerID); + CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned", mitk::Equal(*newlayer, *m_LabelSetImage->GetActiveLabelSet(), 0.00001, true)); + + // Set a non existing layer as active layer - nothing should change + m_LabelSetImage->SetActiveLayer(10000); + CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned", mitk::Equal(*newlayer, *m_LabelSetImage->GetActiveLabelSet(), 0.00001, true)); + } + + void TestRemoveLayer() + { + // Cache active layer + mitk::LabelSet::ConstPointer activeLayer = m_LabelSetImage->GetActiveLabelSet(); + + // Add new layers + m_LabelSetImage->AddLayer(); + + mitk::LabelSet::Pointer newlayer = mitk::LabelSet::New(); + mitk::Label::Pointer label1 = mitk::Label::New(); + label1->SetName("Label1"); + label1->SetValue(1); + + mitk::Label::Pointer label2 = mitk::Label::New(); + label2->SetName("Label2"); + label2->SetValue(200); + + newlayer->AddLabel(label1); + newlayer->AddLabel(label2); + newlayer->SetActiveLabel(200); + + m_LabelSetImage->AddLayer(newlayer); + + CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned", mitk::Equal(*newlayer, *m_LabelSetImage->GetActiveLabelSet(), 0.00001, true)); + + m_LabelSetImage->RemoveLayer(); + CPPUNIT_ASSERT_MESSAGE("Wrong number of layers, after a layer was removed", m_LabelSetImage->GetNumberOfLayers() == 2); + CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed",m_LabelSetImage->ExistLabelSet(2) == false); + CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed",m_LabelSetImage->ExistLabelSet(1) == true); + CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed",m_LabelSetImage->ExistLabelSet(0) == true); + + m_LabelSetImage->RemoveLayer(); + CPPUNIT_ASSERT_MESSAGE("Wrong number of layers, after a layer was removed", m_LabelSetImage->GetNumberOfLayers() == 1); + CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed",m_LabelSetImage->ExistLabelSet(1) == false); + CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed",m_LabelSetImage->ExistLabelSet(0) == true); + CPPUNIT_ASSERT_MESSAGE("Wrong active layer", mitk::Equal(*activeLayer, *m_LabelSetImage->GetActiveLabelSet(), 0.00001, true)); + + m_LabelSetImage->RemoveLayer(); + CPPUNIT_ASSERT_MESSAGE("Wrong number of layers, after a layer was removed", m_LabelSetImage->GetNumberOfLayers() == 0); + CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed",m_LabelSetImage->ExistLabelSet(0) == false); + CPPUNIT_ASSERT_MESSAGE("Active layers is not NULL although all layer have been removed", m_LabelSetImage->GetActiveLabelSet() == 0); + } + + void TestRemoveLabels() + { + mitk::Image::Pointer image = mitk::IOUtil::LoadImage(GetTestDataFilePath("Multilabel/LabelSetTestInitializeImage.nrrd")); + m_LabelSetImage->InitializeByLabeledImage(image); + + CPPUNIT_ASSERT_MESSAGE("Image - number of labels is not 6",m_LabelSetImage->GetNumberOfLabels() == 6); + // 2ndMin because of the exterior label = 0 + CPPUNIT_ASSERT_MESSAGE("Labels with value 1 and 3 was not remove from the image", m_LabelSetImage->GetStatistics()->GetScalarValue2ndMin() == 1); + CPPUNIT_ASSERT_MESSAGE("Label with value 7 was not remove from the image", m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 7); + + CPPUNIT_ASSERT_MESSAGE("Label with ID 3 does not exists after initialization",m_LabelSetImage->ExistLabel(3) == true); + CPPUNIT_ASSERT_MESSAGE("Label with ID 7 does not exists after initialization",m_LabelSetImage->ExistLabel(7) == true); + + std::vector labelsToBeRemoved; + labelsToBeRemoved.push_back(1); + labelsToBeRemoved.push_back(3); + labelsToBeRemoved.push_back(7); + m_LabelSetImage->RemoveLabels(labelsToBeRemoved); + + CPPUNIT_ASSERT_MESSAGE("Wrong number of labels after some have been removed", m_LabelSetImage->GetNumberOfLabels() == 3); + // Values within the image are 0, 1, 3, 5, 6, 7 - New Min/Max value should be 5 / 6 + // 2ndMin because of the exterior label = 0 + CPPUNIT_ASSERT_MESSAGE("Labels with value 1 and 3 was not remove from the image", m_LabelSetImage->GetStatistics()->GetScalarValue2ndMin() == 5); + CPPUNIT_ASSERT_MESSAGE("Label with value 7 was not remove from the image", m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 6); + } + + void TestMergeLabel() + { + mitk::Image::Pointer image = mitk::IOUtil::LoadImage(GetTestDataFilePath("Multilabel/LabelSetTestInitializeImage.nrrd")); + m_LabelSetImage = 0; + m_LabelSetImage = mitk::LabelSetImage::New(); + m_LabelSetImage->InitializeByLabeledImage(image); + + CPPUNIT_ASSERT_MESSAGE("Image - number of labels is not 6",m_LabelSetImage->GetNumberOfLabels() == 6); + + // 2ndMin because of the exterior label = 0 + CPPUNIT_ASSERT_MESSAGE("Wrong MIN value", m_LabelSetImage->GetStatistics()->GetScalarValueMin() == 0); + CPPUNIT_ASSERT_MESSAGE("Wrong MAX value", m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 7); + + m_LabelSetImage->GetActiveLabelSet()->SetActiveLabel(6); + // Merge label 7 with label 0. Result should be that label 7 is not present any more + m_LabelSetImage->MergeLabel(7); + CPPUNIT_ASSERT_MESSAGE("Label with value 7 was not remove from the image", m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 6); + m_LabelSetImage->GetStatistics()->GetScalarValue2ndMax(); + + // Count all pixels with value 7 = 823 + // Count all pixels with value 6 = 507 + // Check if merge label has 507 + 823 = 1330 pixels + CPPUNIT_ASSERT_MESSAGE("Label with value 7 was not remove from the image", m_LabelSetImage->GetStatistics()->GetCountOfMaxValuedVoxels() == 1330); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkLabelSetImage) diff --git a/Modules/Multilabel/Testing/mitkLabelSetTest.cpp b/Modules/Multilabel/Testing/mitkLabelSetTest.cpp new file mode 100644 index 0000000000..d0ae50ba89 --- /dev/null +++ b/Modules/Multilabel/Testing/mitkLabelSetTest.cpp @@ -0,0 +1,181 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include +#include + +class mitkLabelSetTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkLabelSetTestSuite); + MITK_TEST(TestSetLayer); + MITK_TEST(TestSetActiveLabel); + MITK_TEST(TestRemoveLabel); + MITK_TEST(TestAddLabel); + MITK_TEST(TestRenameLabel); + MITK_TEST(TestSetAllLabelsVisible); + MITK_TEST(TestSetAllLabelsLocked); + MITK_TEST(TestRemoveAllLabels); + CPPUNIT_TEST_SUITE_END(); + + +private: + mitk::LabelSet::Pointer m_LabelSet; + mitk::LabelSet::PixelType m_InitialNumberOfLabels; + + void AddLabels(mitk::LabelSet::PixelType numOfLabels) + { + for (mitk::Label::PixelType i = 0; i < numOfLabels; ++i) + { + mitk::Label::Pointer label = mitk::Label::New(); + std::stringstream nameStream; + nameStream << "Label_"; + nameStream << i; + label->SetName(nameStream.str()); + label->SetValue(i); + label->SetVisible( (i%20 == 0) ); + label->SetLayer( i%5); + mitk::Color color; + color.Set(0.3f, 0.25f, 1.0f); + label->SetColor(color); + + m_LabelSet->AddLabel(label); + } + } + +public: + + void setUp() + { + m_InitialNumberOfLabels = 200; + m_LabelSet = mitk::LabelSet::New(); + + this->AddLabels(m_InitialNumberOfLabels); + m_LabelSet->SetLayer(0); + m_LabelSet->SetActiveLabel(0); + } + + void tearDown() + { + // Reset label set + m_LabelSet = 0; + } + + void TestSetLayer() + { + CPPUNIT_ASSERT_MESSAGE("Wrong initial layer", m_LabelSet->GetLayer() == 0); + m_LabelSet->SetLayer(3); + CPPUNIT_ASSERT_MESSAGE("Wrong layer", m_LabelSet->GetLayer() == 3); + } + + void TestSetActiveLabel() + { + CPPUNIT_ASSERT_MESSAGE("Wrong initial active label", m_LabelSet->GetActiveLabel()->GetValue() == 0); + m_LabelSet->SetActiveLabel(145); + CPPUNIT_ASSERT_MESSAGE("Wrong layer", m_LabelSet->GetActiveLabel()->GetValue() == 145); + } + + void TestRemoveLabel() + { + CPPUNIT_ASSERT_MESSAGE("Wrong initial number of label", static_cast(m_LabelSet->GetNumberOfLabels()) == m_InitialNumberOfLabels); + + // Remove a label that is not the active label + m_LabelSet->SetActiveLabel(12); + m_LabelSet->RemoveLabel(56); + unsigned int numLabels = m_InitialNumberOfLabels-1; + CPPUNIT_ASSERT_MESSAGE("Label was not removed", m_LabelSet->ExistLabel(56) == false); + CPPUNIT_ASSERT_MESSAGE("Wrong number of label", m_LabelSet->GetNumberOfLabels() == numLabels); + CPPUNIT_ASSERT_MESSAGE("Wrong active label", m_LabelSet->GetActiveLabel()->GetValue() == 12); + + // Remove active label - now the succeeding label should be active + m_LabelSet->RemoveLabel(12); + CPPUNIT_ASSERT_MESSAGE("Wrong layer", m_LabelSet->GetActiveLabel()->GetValue() == 13); + CPPUNIT_ASSERT_MESSAGE("Label was not removed", m_LabelSet->ExistLabel(12) == false); + numLabels = m_InitialNumberOfLabels-2; + CPPUNIT_ASSERT_MESSAGE("Wrong initial number of label", m_LabelSet->GetNumberOfLabels() == numLabels); + } + + void TestAddLabel() + { + CPPUNIT_ASSERT_MESSAGE("Wrong initial number of label", m_LabelSet->GetNumberOfLabels() == m_InitialNumberOfLabels); + mitk::Label::Pointer newLabel = mitk::Label::New(); + newLabel->SetValue(199); + m_LabelSet->AddLabel(newLabel); + // Since label with value 199 already exists the new label will get the value 200 + CPPUNIT_ASSERT_MESSAGE("Wrong label value", m_LabelSet->GetActiveLabel()->GetValue() == 200); + unsigned int numLabels = m_InitialNumberOfLabels+1; + CPPUNIT_ASSERT_MESSAGE("Wrong number of label", m_LabelSet->GetNumberOfLabels() == numLabels); + + // Add new labels until the maximum number of labels is reached. + // Adding more labels should have no effect. + this->AddLabels(mitk::Label::MAX_LABEL_VALUE); + CPPUNIT_ASSERT_MESSAGE("Wrong number of label", m_LabelSet->GetNumberOfLabels() == 65536); + mitk::Label* activeLabel = m_LabelSet->GetActiveLabel(); + CPPUNIT_ASSERT_MESSAGE("Wrong value of active label", activeLabel->GetValue() == mitk::Label::MAX_LABEL_VALUE); + } + + void TestRenameLabel() + { + mitk::Color color; + color.Set(1.0f,1.0f,1.0f); + std::string name("MyAwesomeLabel"); + m_LabelSet->RenameLabel(0, name, color); + mitk::Label* label = m_LabelSet->GetLabel(0); + CPPUNIT_ASSERT_MESSAGE("Wrong label name", label->GetName().compare("MyAwesomeLabel") == 0); + mitk::Color color2 = label->GetColor(); + CPPUNIT_ASSERT_MESSAGE("Wrong color", (color2.GetBlue() == 1.0f && color2.GetGreen() == 1.0f && color2.GetRed() == 1.0f)); + } + + void TestSetAllLabelsVisible() + { + m_LabelSet->SetAllLabelsVisible(true); + for(mitk::LabelSet::PixelType i=0; i < m_LabelSet->GetNumberOfLabels(); ++i) + { + CPPUNIT_ASSERT_MESSAGE("Label not visible", m_LabelSet->GetLabel(i)->GetVisible() == true); + } + + m_LabelSet->SetAllLabelsVisible(false); + for(mitk::LabelSet::PixelType i=0; i < m_LabelSet->GetNumberOfLabels(); ++i) + { + CPPUNIT_ASSERT_MESSAGE("Label visible", m_LabelSet->GetLabel(i)->GetVisible() == false); + } + } + + void TestSetAllLabelsLocked() + { + m_LabelSet->SetAllLabelsLocked(true); + for(mitk::LabelSet::PixelType i=0; i < m_LabelSet->GetNumberOfLabels(); ++i) + { + CPPUNIT_ASSERT_MESSAGE("Label not locked", m_LabelSet->GetLabel(i)->GetLocked() == true); + } + + m_LabelSet->SetAllLabelsLocked(false); + for(mitk::LabelSet::PixelType i=0; i < m_LabelSet->GetNumberOfLabels(); ++i) + { + CPPUNIT_ASSERT_MESSAGE("Label locked", m_LabelSet->GetLabel(i)->GetLocked() == false); + } + } + + void TestRemoveAllLabels() + { + m_LabelSet->RemoveAllLabels(); + CPPUNIT_ASSERT_MESSAGE("Not all labels were removed", m_LabelSet->GetNumberOfLabels() == 0); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkLabelSet) diff --git a/Modules/Multilabel/Testing/mitkLabelTest.cpp b/Modules/Multilabel/Testing/mitkLabelTest.cpp new file mode 100644 index 0000000000..a0d862b2d3 --- /dev/null +++ b/Modules/Multilabel/Testing/mitkLabelTest.cpp @@ -0,0 +1,166 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkLabel.h" +#include "mitkStringProperty.h" +#include +#include + +class mitkLabelTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkLabelTestSuite); + MITK_TEST(TestSetLock); + MITK_TEST(TestSetVisibility); + MITK_TEST(TestSetOpacity); + MITK_TEST(TestSetName); + MITK_TEST(TestSetCenterOfMassIndex); + MITK_TEST(TestSetCenterOfMassCoordinates); + MITK_TEST(TestSetColor); + MITK_TEST(TestSetValue); + MITK_TEST(TestSetLayer); + MITK_TEST(TestSetProperty); + CPPUNIT_TEST_SUITE_END(); + +public: + + void TestSetLock() + { + mitk::Label::Pointer label = mitk::Label::New(); + CPPUNIT_ASSERT_MESSAGE("Initial label not locked", label->GetLocked() == true); + + label->SetLocked(false); + CPPUNIT_ASSERT_MESSAGE("Label should not be locked", label->GetLocked() == false); + } + + void TestSetVisibility() + { + mitk::Label::Pointer label = mitk::Label::New(); + CPPUNIT_ASSERT_MESSAGE("Initial label not visible", label->GetVisible() == true); + + label->SetVisible(false); + CPPUNIT_ASSERT_MESSAGE("Label should not be visible", label->GetVisible() == false); + } + + void TestSetOpacity() + { + mitk::Label::Pointer label = mitk::Label::New(); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong opacity", mitk::Equal(label->GetOpacity(), 0.6f)); + + label->SetOpacity(0.32f); + CPPUNIT_ASSERT_MESSAGE("Label has wrong opacity", mitk::Equal(label->GetOpacity(), 0.32f)); + } + + void TestSetName() + { + mitk::Label::Pointer label = mitk::Label::New(); + std::string initialName("noName!"); + std::string labelName = label->GetName(); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong name", initialName.compare(labelName) == 0); + + label->SetName("AwesomeLabel"); + labelName = label->GetName(); + CPPUNIT_ASSERT_MESSAGE("Label has wrong name", labelName.compare("AwesomeLabel") == 0); + } + + void TestSetCenterOfMassIndex() + { + mitk::Label::Pointer label = mitk::Label::New(); + mitk::Point3D currentIndex = label->GetCenterOfMassIndex(); + mitk::Point3D indexToBeCompared; + indexToBeCompared.Fill(0); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong center of mass index", mitk::Equal(currentIndex, indexToBeCompared)); + + indexToBeCompared.SetElement(1, 234.3f); + indexToBeCompared.SetElement(2, -53); + indexToBeCompared.SetElement(3, 120); + label->SetCenterOfMassIndex(indexToBeCompared); + currentIndex = label->GetCenterOfMassIndex(); + CPPUNIT_ASSERT_MESSAGE("Label has wrong center of mass index", mitk::Equal(currentIndex, indexToBeCompared)); + } + + void TestSetCenterOfMassCoordinates() + { + mitk::Label::Pointer label = mitk::Label::New(); + mitk::Point3D currentPoint = label->GetCenterOfMassCoordinates(); + mitk::Point3D pointToBeCompared; + pointToBeCompared.Fill(0); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong center of mass index", mitk::Equal(currentPoint, pointToBeCompared)); + + pointToBeCompared.SetElement(1, 234.3f); + pointToBeCompared.SetElement(2, -53); + pointToBeCompared.SetElement(3, 120); + label->SetCenterOfMassCoordinates(pointToBeCompared); + currentPoint = label->GetCenterOfMassCoordinates(); + CPPUNIT_ASSERT_MESSAGE("Label has wrong center of mass index", mitk::Equal(currentPoint, pointToBeCompared)); + } + + void TestSetColor() + { + mitk::Label::Pointer label = mitk::Label::New(); + mitk::Color currentColor = label->GetColor(); + mitk::Color colorToBeCompared; + colorToBeCompared.Set(0,0,0); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong color", currentColor.GetBlue() == colorToBeCompared.GetBlue()); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong color", currentColor.GetGreen() == colorToBeCompared.GetGreen()); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong color", currentColor.GetRed() == colorToBeCompared.GetRed()); + + colorToBeCompared.Set(0.4f,0.3f,1.0f); + label->SetColor(colorToBeCompared); + currentColor = label->GetColor(); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong color", currentColor.GetBlue() == colorToBeCompared.GetBlue()); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong color", currentColor.GetGreen() == colorToBeCompared.GetGreen()); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong color", currentColor.GetRed() == colorToBeCompared.GetRed()); + } + + void TestSetValue() + { + mitk::Label::Pointer label = mitk::Label::New(); + mitk::Label::PixelType initialValue(0); + mitk::Label::PixelType valueToBeCompared = label->GetValue(); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong value", initialValue == valueToBeCompared); + + label->SetValue(12345); + valueToBeCompared = 12345; + initialValue = label->GetValue(); + CPPUNIT_ASSERT_MESSAGE("Label has wrong value", initialValue == valueToBeCompared); + } + + void TestSetLayer() + { + mitk::Label::Pointer label = mitk::Label::New(); + int initialLayer(0); + int valueToBeCompared = label->GetValue(); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong layer", initialLayer == valueToBeCompared); + + label->SetLayer(2); + valueToBeCompared = 2; + initialLayer = label->GetLayer(); + CPPUNIT_ASSERT_MESSAGE("Label has wrong layer", initialLayer == valueToBeCompared); + } + + void TestSetProperty() + { + mitk::Label::Pointer label = mitk::Label::New(); + + mitk::StringProperty::Pointer prop = mitk::StringProperty::New("abc"); + label->SetProperty("cba",prop); + std::string propVal; + label->GetStringProperty("cba", propVal); + CPPUNIT_ASSERT_MESSAGE("Initial label has wrong value", propVal.compare("abc") == 0); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkLabel) diff --git a/Modules/Multilabel/files.cmake b/Modules/Multilabel/files.cmake new file mode 100644 index 0000000000..2337956310 --- /dev/null +++ b/Modules/Multilabel/files.cmake @@ -0,0 +1,17 @@ +set(CPP_FILES + mitkLabel.cpp + mitkLabelSet.cpp + mitkLabelSetImage.cpp + mitkLabelSetImageIO.cpp + mitkLabelSetImageSerializer.cpp + mitkLabelSetImageSource.cpp + mitkLabelSetImageToSurfaceFilter.cpp + mitkLabelSetImageToSurfaceThreadedFilter.cpp + mitkLabelSetImageVtkMapper2D.cpp + mitkMultilabelActivator.cpp + mitkMultilabelObjectFactory.cpp +) + +set(RESOURCE_FILES + +) diff --git a/Modules/Multilabel/mitkLabel.cpp b/Modules/Multilabel/mitkLabel.cpp new file mode 100644 index 0000000000..4ca3d4543b --- /dev/null +++ b/Modules/Multilabel/mitkLabel.cpp @@ -0,0 +1,302 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkLabel.h" + +#include "itkProcessObject.h" +#include +#include +#include "tinyxml.h" + +#include + +const mitk::Label::PixelType mitk::Label::MAX_LABEL_VALUE = std::numeric_limits::max(); + +mitk::Label::Label() : + PropertyList() +{ + if(GetProperty("locked") == NULL) SetLocked(true); + if(GetProperty("visible") == NULL) SetVisible(true); + if(GetProperty("opacity") == NULL) SetOpacity(0.6); + if(GetProperty("center.coordinates") == NULL) + { + mitk::Point3D pnt; + pnt.SetElement(0,0); + pnt.SetElement(1,0); + pnt.SetElement(2,0); + SetCenterOfMassCoordinates(pnt); + } + if(GetProperty("center.index") == NULL) + { + mitk::Point3D pnt; + pnt.SetElement(0,0); + pnt.SetElement(1,0); + pnt.SetElement(2,0); + SetCenterOfMassIndex(pnt); + } + if(GetProperty("color") == NULL) + { + mitk::Color col; + col.Set(0,0,0); + SetColor(col); + } + if(GetProperty("name") == NULL) SetName("noName!"); + if(GetProperty("value") == NULL) SetValue(0); + if(GetProperty("layer") == NULL) SetLayer(0); +} + +mitk::Label::Label(const Label& other) + : PropertyList(other) + // copyconstructer of property List handles the coping action +{ + + + mitk::PropertyList::PropertyMap * map = const_cast(this->GetMap()); + mitk::PropertyList::PropertyMap::iterator it = map->begin(); + mitk::PropertyList::PropertyMap::iterator end = map->end(); + + for(; it != end ; ++it) + { + itk::SimpleMemberCommand