diff --git a/CMake/MITKDashboardScript.TEMPLATE.cmake b/CMake/MITKDashboardScript.TEMPLATE.cmake index 1369eff93e..c3cb7fc55b 100644 --- a/CMake/MITKDashboardScript.TEMPLATE.cmake +++ b/CMake/MITKDashboardScript.TEMPLATE.cmake @@ -1,146 +1,147 @@ # # OS: Ubuntu 9.04 2.6.28-18-generic # Hardware: x86_64 GNU/Linux # GPU: NA # # Note: The specific version and processor type of this machine should be reported in the # header above. Indeed, this file will be send to the dashboard as a NOTE file. cmake_minimum_required(VERSION 3.10 FATAL_ERROR) # # Dashboard properties # set(MY_COMPILER "gcc-4.9.x") # For Windows, e.g. #set(MY_COMPILER "VC12.0") set(CTEST_CMAKE_COMMAND "/usr/bin/cmake") set(CTEST_CMAKE_GENERATOR "Unix Makefiles") set(CTEST_DASHBOARD_ROOT "/opt/dartclients") # For Windows, e.g. #set(CTEST_CMAKE_COMMAND "cmake") #set(CTEST_CMAKE_GENERATOR "Visual Studio 12 2013 Win64") #set(CTEST_DASHBOARD_ROOT "C:/dartclients") # The directory containing the Qt binaries set(QT5_INSTALL_PREFIX "/home/user/Qt/5.6/gcc_64") # For Windows, e.g. #set(QT5_INSTALL_PREFIX "C:/Qt/5.6/msvc2013_64") set(QT_BINARY_DIR "${QT5_INSTALL_PREFIX}/bin") # # Dashboard options # set(WITH_KWSTYLE FALSE) set(WITH_MEMCHECK FALSE) set(WITH_COVERAGE FALSE) set(WITH_DOCUMENTATION FALSE) #set(DOCUMENTATION_ARCHIVES_OUTPUT_DIRECTORY ) # for example: $ENV{HOME}/Projects/Doxygen set(CTEST_BUILD_CONFIGURATION "Release") set(CTEST_TEST_TIMEOUT 500) if(UNIX OR MINGW) set(CTEST_BUILD_FLAGS "-j4") # Use multiple CPU cores to build else() set(CTEST_BUILD_FLAGS "") endif() # experimental: # - run_ctest() macro will be called *ONE* time # - binary directory will *NOT* be cleaned # continuous: # - run_ctest() macro will be called EVERY 5 minutes ... # - binary directory will *NOT* be cleaned # - configure/build will be executed *ONLY* if the repository has been updated # nightly: # - run_ctest() macro will be called *ONE* time # - binary directory *WILL BE* cleaned set(SCRIPT_MODE "experimental") # "experimental", "continuous", "nightly" # # Project specific properties # # In order to shorten the global path length, the build directory for each DartClient # uses the following abrevation sceme: # For build configuration: # Debug -> d # Release -> r # For scripte mode: # continuous -> c # nightly -> n # experimental -> e # Example directory: /MITK-sb-d-n/ for a nightly MITK superbuild in debug mode. set(short_of_ctest_build_configuration "") set(short_of_script_mode "") string(SUBSTRING ${CTEST_BUILD_CONFIGURATION} 0 1 short_of_ctest_build_configuration) string(SUBSTRING ${SCRIPT_MODE} 0 1 short_of_script_mode) set(CTEST_SOURCE_DIRECTORY "${CTEST_DASHBOARD_ROOT}/MITK") set(CTEST_BINARY_DIRECTORY "${CTEST_DASHBOARD_ROOT}/MITK-sb-${short_of_ctest_build_configuration}-${short_of_script_mode}") # Create an initial cache file for MITK. This file is used to configure the MITK-Build. Use ADDITIONAL_CMAKECACHE_OPTION # to configure the MITK-Superbuild. The set(MITK_INITIAL_CACHE " # Example how to set a boolean variable in the MITK-Build via this script: #SET(MITK_ENABLE_TOF_HARDWARE \"TRUE\" CACHE INTERNAL \"Enable ToF Hardware\") # Example how to set a path variable in the MITK-Build via this script: #SET(MITK_PMD_LIB \"/home/kilgus/thomas/PMDSDK2/Linux_x86_64/bin/libpmdaccess2.so\" CACHE INTERNAL \"PMD lib\") ") set(ADDITIONAL_CMAKECACHE_OPTION " # Superbuild variables are not passed through to the MITK-Build (or any other build like ITK, VTK, ...) # Use the MITK_INITIAL_CACHE the pass variables to the MITK-Build. # add entries like this #MITK_USE_OpenCV:BOOL=OFF CMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH} ") # List of test that should be explicitly disabled on this machine set(TEST_TO_EXCLUDE_REGEX "") # set any extra environment variables here set(ENV{DISPLAY} ":0") find_program(CTEST_COVERAGE_COMMAND NAMES gcov) find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind) find_program(CTEST_GIT_COMMAND NAMES git) # # Git repository - Overwrite the default value provided by the driver script # # The git repository containing MITK code #set(GIT_REPOSITORY "/home/username/MITK") # The branch of the MITK git repository to check out #set(GIT_BRANCH "bug-xxx-label") ########################################## # WARNING: DO NOT EDIT BEYOND THIS POINT # ########################################## # # Convenient macro allowing to download a file # macro(downloadFile url dest) file(DOWNLOAD "${url}" "${dest}" STATUS status) list(GET status 0 error_code) list(GET status 1 error_msg) if(error_code) message(FATAL_ERROR "error: Failed to download ${url} - ${error_msg}") endif() endmacro() # # Download and include setup script # if(NOT DEFINED GIT_BRANCH OR GIT_BRANCH STREQUAL "") set(IS_PHABRICATOR_URL FALSE) set(url "https://raw.githubusercontent.com/MITK/MITK/master/CMake/MITKDashboardSetup.cmake") else() set(IS_PHABRICATOR_URL TRUE) - set(url "https://phabricator.mitk.org/source/mitk/browse/${GIT_BRANCH}/CMake/MITKDashboardSetup.cmake?view=raw") + string(REPLACE "/" "%252F" GIT_BRANCH_URL ${GIT_BRANCH}) + set(url "https://phabricator.mitk.org/source/mitk/browse/${GIT_BRANCH_URL}/CMake/MITKDashboardSetup.cmake?view=raw") endif() set(dest ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}.setup) downloadFile("${url}" "${dest}") include(${dest}) diff --git a/CMake/MITKDashboardSetup.cmake b/CMake/MITKDashboardSetup.cmake index e34d45c2a0..4bf2d289cf 100644 --- a/CMake/MITKDashboardSetup.cmake +++ b/CMake/MITKDashboardSetup.cmake @@ -1,161 +1,160 @@ # 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 if(IS_PHABRICATOR_URL) set(url "https://phabricator.mitk.org/source/mitk/browse/${GIT_BRANCH}/CMake/mitkDetectOS.sh?view=raw") else() set(url "https://raw.githubusercontent.com/MITK/MITK/master/CMake/mitkDetectOS.sh") endif() set(dest "${CTEST_SCRIPT_DIRECTORY}/mitkDetectOS.sh") downloadFile("${url}" "${dest}") execute_process(COMMAND sh "${dest}" RESULT_VARIABLE _result OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT _result) set(MY_OPERATING_SYSTEM "${_out}") endif() endif() if(NOT MY_OPERATING_SYSTEM) set(MY_OPERATING_SYSTEM "${CMAKE_HOST_SYSTEM}") # Windows 7, Linux-2.6.32, Darwin... endif() site_name(CTEST_SITE) if(NOT DEFINED MITK_USE_Qt5) set(MITK_USE_Qt5 1) endif() if(MITK_USE_Qt5) if(NOT QT_QMAKE_EXECUTABLE) find_program(QT_QMAKE_EXECUTABLE NAMES qmake qmake-qt5 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_Qt5) 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) if("${CTEST_CMAKE_GENERATOR}" MATCHES ".*Win64") set(CMAKE_LIBRARY_ARCHITECTURE x64) else() set(CMAKE_LIBRARY_ARCHITECTURE x86) endif() string(SUBSTRING "${MY_COMPILER}" 2 2 vc_version) set(OPENCV_BIN_DIR "${CTEST_BINARY_DIRECTORY}/ep/${CMAKE_LIBRARY_ARCHITECTURE}/vc${vc_version}/bin") set(BLUEBERRY_RUNTIME_DIR "${CTEST_BINARY_DIRECTORY}/MITK-build/bin/plugins/${CTEST_BUILD_CONFIGURATION}") set(PYTHON_BINARY_DIRS "${CTEST_BINARY_DIRECTORY}/ep/src/CTK-build/CMakeExternals/Install/bin") get_filename_component(_python_dir ${PYTHON_EXECUTABLE} DIRECTORY) list(APPEND PYTHON_BINARY_DIRS "${_python_dir}") set(CTEST_PATH "${CTEST_PATH};${CTEST_BINARY_DIRECTORY}/ep/bin;${QT_BINARY_DIR};${BLUEBERRY_RUNTIME_DIR};${OPENCV_BIN_DIR};${PYTHON_BINARY_DIRS}") endif() set(ENV{PATH} "${CTEST_PATH}") # If the dashscript doesn't define a GIT_REPOSITORY variable, let's define it here. if(NOT DEFINED GIT_REPOSITORY OR GIT_REPOSITORY STREQUAL "") set(GIT_REPOSITORY "https://phabricator.mitk.org/source/mitk.git") endif() # # Display build info # message("Site name: ${CTEST_SITE}") message("Build name: ${CTEST_BUILD_NAME}") message("Script Mode: ${SCRIPT_MODE}") message("Coverage: ${WITH_COVERAGE}, MemCheck: ${WITH_MEMCHECK}") # # Set initial cache options # if(CTEST_CMAKE_GENERATOR MATCHES ".*Makefiles.*") set(CTEST_USE_LAUNCHERS 1) else() set(CTEST_USE_LAUNCHERS 0) endif() set(ENV{CTEST_USE_LAUNCHERS_DEFAULT} ${CTEST_USE_LAUNCHERS}) # 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_Qt5) 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 # if(IS_PHABRICATOR_URL) - set(url "https://phabricator.mitk.org/source/mitk/browse/${GIT_BRANCH}/CMake/MITKDashboardDriverScript.cmake?view=raw") + string(REPLACE "/" "%252F" GIT_BRANCH_URL ${GIT_BRANCH}) + set(url "https://phabricator.mitk.org/source/mitk/browse/${GIT_BRANCH_URL}/CMake/MITKDashboardDriverScript.cmake?view=raw") else() set(url "https://raw.githubusercontent.com/MITK/MITK/master/CMake/MITKDashboardDriverScript.cmake") endif() set(dest ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}.driver) downloadFile("${url}" "${dest}") include(${dest}) - - diff --git a/Modules/CameraCalibration/mitkCameraIntrinsics.h b/Modules/CameraCalibration/mitkCameraIntrinsics.h index 24466803e6..45b96bfaa1 100644 --- a/Modules/CameraCalibration/mitkCameraIntrinsics.h +++ b/Modules/CameraCalibration/mitkCameraIntrinsics.h @@ -1,144 +1,145 @@ /*=================================================================== 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 mitkCameraIntrinsics_h #define mitkCameraIntrinsics_h #include #include #include #include -#include #include #include "mitkXMLSerializable.h" #include +#include "opencv2/core.hpp" + int mitkCameraIntrinsicsTest(int, char* []); namespace mitk { /// /// \brief class representing camera intrinsics and related functions /// class MITKCAMERACALIBRATION_EXPORT CameraIntrinsics: virtual public itk::Object, virtual public mitk::XMLSerializable { public: /// /// for testing purposes /// friend int mitkCameraIntrinsicsTest(int argc, char* argv[]); /// /// smartpointer typedefs /// mitkClassMacroItkParent(CameraIntrinsics, itk::Object); /// /// the static new function /// itkFactorylessNewMacro(Self); /// /// make a clone of this intrinsics /// itkCloneMacro(Self) /// /// copy information from other to this /// void Copy(const CameraIntrinsics* other); /// /// checks two intrinsics for equality /// bool Equals( const CameraIntrinsics* other ) const; /// /// \return the intrinsic parameter matrix as a 3x3 vnl matrix /// vnl_matrix_fixed GetVnlCameraMatrix() const; /// /// \return the intrinsic parameter matrix as a 3x4 vnl matrix /// (the last column only containing zeros) /// vnl_matrix_fixed GetVnlCameraMatrix3x4() const; /// /// \return true if the intrinsics are set (some plausibility checks /// may be done here) /// bool IsValid() const; void SetValid(bool valid); cv::Mat GetCameraMatrix() const; cv::Mat GetDistorsionCoeffs(); cv::Mat GetDistorsionCoeffs() const; void ToXML(TiXmlElement* elem) const override; std::string ToString() const; std::string GetString(); double GetFocalLengthX() const; double GetFocalLengthY() const; double GetPrincipalPointX() const; double GetPrincipalPointY() const; mitk::Point4D GetDistorsionCoeffsAsPoint4D() const; mitk::Point3D GetFocalPoint() const; mitk::Point3D GetPrincipalPoint() const; vnl_vector_fixed GetFocalPointAsVnlVector() const; vnl_vector_fixed GetPrincipalPointAsVnlVector() const; /// /// set a new camera matrix utilizing a vnl matrix /// void SetCameraMatrix( const vnl_matrix_fixed& _CameraMatrix ); void SetIntrinsics( const cv::Mat& _CameraMatrix , const cv::Mat& _DistorsionCoeffs); void SetFocalLength( double x, double y ); void SetPrincipalPoint( double x, double y ); void SetDistorsionCoeffs( double k1, double k2, double p1, double p2 ); void SetIntrinsics( const mitk::Point3D& focalPoint, const mitk::Point3D& principalPoint, const mitk::Point4D& distortionCoefficients); void FromXML(TiXmlElement* elem) override; void FromGMLCalibrationXML(TiXmlElement* elem); std::string ToOctaveString(const std::string& varName="CameraIntrinsics"); ~CameraIntrinsics() override; protected: CameraIntrinsics(); CameraIntrinsics(const CameraIntrinsics& other); cv::Mat m_CameraMatrix; cv::Mat m_DistorsionCoeffs; bool m_Valid; itk::FastMutexLock::Pointer m_Mutex; private: itk::LightObject::Pointer InternalClone() const override; }; } // namespace mitk MITKCAMERACALIBRATION_EXPORT std::ostream& operator<< (std::ostream& os, mitk::CameraIntrinsics::Pointer p); #endif // mitkCameraIntrinsics_h diff --git a/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h b/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h index 21b724321c..758587915d 100644 --- a/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h +++ b/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h @@ -1,88 +1,89 @@ /*=================================================================== 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 mitkCvMatFromVnlMatrix_h #define mitkCvMatFromVnlMatrix_h #include #include -#include #include #include +#include "opencv2/core.hpp" + namespace mitk { /// /// casts a random cv::Mat to a vnl Matrix /// if the columns of the first row are > 1 /// then the Matrix is filled with the values from this row /// otherwise the first elements of each row are used /// to fill the Matrix /// template class CvMatFromVnlMatrix: virtual public Algorithm { public: /// /// init default values and save references /// CvMatFromVnlMatrix( const vnl_matrix* _VnlMatrix, cv::Mat* _CvMat): m_VnlMatrix(_VnlMatrix), m_CvMat(_CvMat) { } /// /// templated function for multiplexed cv::Mat /// template static void Cast( const vnl_matrix& vnlMat, cv::Mat& cvMat ) { endodebugvar( vnlMat ) cvMat = cv::Mat(vnlMat.rows(), vnlMat.cols(), cv::DataType::type); for(unsigned int i=0; i(i,j) = static_cast( vnlMat(i,j) ); // endodebugvar( vnlMat(i,j) ) // endodebugvar( cvMat.at(i,j) ) } } } /// /// executes the Algorithm /// void Update() override { Cast( *m_VnlMatrix, *m_CvMat ); } private: /// /// CvMatFromVnlMatrix input member variable /// const vnl_matrix* m_VnlMatrix; /// /// CvMatFromVnlMatrix output member variable /// cv::Mat* m_CvMat; }; } // namespace mitk #endif // mitkCvMatFromVnlMatrix_h diff --git a/Modules/CameraCalibration/mitkStringFromCvMat.h b/Modules/CameraCalibration/mitkStringFromCvMat.h index d522d0390e..f0e0f13296 100644 --- a/Modules/CameraCalibration/mitkStringFromCvMat.h +++ b/Modules/CameraCalibration/mitkStringFromCvMat.h @@ -1,92 +1,93 @@ /*=================================================================== 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 mitkStringFromCvMat_h #define mitkStringFromCvMat_h -#include #include #include #include #include #include +#include "opencv2/core.hpp" + namespace mitk { /// /// create a vnl_matrix from a cv mat /// class StringFromCvMat: virtual public Algorithm { public: /// /// init default values and save references /// StringFromCvMat( const cv::Mat* _CvMat, std::string* _String): m_CvMat(_CvMat), m_String(_String) { } /// /// cv mat to vnl matrix with known cv type /// template void ToString( std::string& string, const cv::Mat& mat ) { std::ostringstream s; for(int i=0; i(i,j) << " "; } s << T_Delim; } string = s.str(); } void SetMatrix( const cv::Mat* _CvMat ) { m_CvMat = _CvMat; } /// /// executes the Algorithm /// void Update() override { endoAccessCvMat( ToString, '\n', (*m_String), (*m_CvMat) ); } private: /// /// StringFromCvMat input member variable /// const cv::Mat* m_CvMat; /// /// StringFromCvMat output member variable /// std::string* m_String; }; } // namespace mitk #endif // mitkStringFromCvMat_h diff --git a/Modules/Core/src/IO/mitkItkImageIO.cpp b/Modules/Core/src/IO/mitkItkImageIO.cpp index 4fc9263c56..f0f9a17054 100644 --- a/Modules/Core/src/IO/mitkItkImageIO.cpp +++ b/Modules/Core/src/IO/mitkItkImageIO.cpp @@ -1,703 +1,703 @@ /*=================================================================== 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 "mitkItkImageIO.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mitk { const char *const PROPERTY_NAME_TIMEGEOMETRY_TYPE = "org.mitk.timegeometry.type"; const char *const PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS = "org.mitk.timegeometry.timepoints"; const char *const PROPERTY_KEY_TIMEGEOMETRY_TYPE = "org_mitk_timegeometry_type"; const char *const PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS = "org_mitk_timegeometry_timepoints"; ItkImageIO::ItkImageIO(const ItkImageIO &other) : AbstractFileIO(other), m_ImageIO(dynamic_cast(other.m_ImageIO->Clone().GetPointer())) { this->InitializeDefaultMetaDataKeys(); } std::vector ItkImageIO::FixUpImageIOExtensions(const std::string &imageIOName) { std::vector extensions; // Try to fix-up some known ITK image IO classes if (imageIOName == "GiplImageIO") { extensions.push_back("gipl"); extensions.push_back("gipl.gz"); } else if (imageIOName == "GDCMImageIO") { extensions.push_back("gdcm"); extensions.push_back("dcm"); extensions.push_back("DCM"); extensions.push_back("dc3"); extensions.push_back("DC3"); extensions.push_back("ima"); extensions.push_back("img"); } else if (imageIOName == "PNGImageIO") { extensions.push_back("png"); extensions.push_back("PNG"); } else if (imageIOName == "StimulateImageIO") { extensions.push_back("spr"); } else if (imageIOName == "HDF5ImageIO") { extensions.push_back("hdf"); extensions.push_back("h4"); extensions.push_back("hdf4"); extensions.push_back("h5"); extensions.push_back("hdf5"); extensions.push_back("he4"); extensions.push_back("he5"); extensions.push_back("hd5"); } else if ("GE4ImageIO" == imageIOName || "GE5ImageIO" == imageIOName || "Bruker2dseqImageIO" == imageIOName) { extensions.push_back(""); } if (!extensions.empty()) { MITK_DEBUG << "Fixing up known extensions for " << imageIOName; } return extensions; } void ItkImageIO::FixUpCustomMimeTypeName(const std::string &imageIOName, CustomMimeType &customMimeType) { if ("GE4ImageIO" == imageIOName) { customMimeType.SetName(this->AbstractFileReader::GetMimeTypePrefix() + "ge4"); } else if ("GE5ImageIO" == imageIOName) { customMimeType.SetName(this->AbstractFileReader::GetMimeTypePrefix() + "ge5"); } else if ("Bruker2dseqImageIO" == imageIOName) { customMimeType.SetName(this->AbstractFileReader::GetMimeTypePrefix() + "bruker2dseq"); } } ItkImageIO::ItkImageIO(itk::ImageIOBase::Pointer imageIO) : AbstractFileIO(Image::GetStaticNameOfClass()), m_ImageIO(imageIO) { if (m_ImageIO.IsNull()) { mitkThrow() << "ITK ImageIOBase argument must not be nullptr"; } this->AbstractFileReader::SetMimeTypePrefix(IOMimeTypes::DEFAULT_BASE_NAME() + ".image."); this->InitializeDefaultMetaDataKeys(); std::vector readExtensions = m_ImageIO->GetSupportedReadExtensions(); if (readExtensions.empty()) { std::string imageIOName = m_ImageIO->GetNameOfClass(); MITK_DEBUG << "ITK ImageIOBase " << imageIOName << " does not provide read extensions"; readExtensions = FixUpImageIOExtensions(imageIOName); } CustomMimeType customReaderMimeType; customReaderMimeType.SetCategory("Images"); for (std::vector::const_iterator iter = readExtensions.begin(), endIter = readExtensions.end(); iter != endIter; ++iter) { std::string extension = *iter; if (!extension.empty() && extension[0] == '.') { extension.assign(iter->begin() + 1, iter->end()); } customReaderMimeType.AddExtension(extension); } auto extensions = customReaderMimeType.GetExtensions(); if (extensions.empty() || (extensions.size() == 1 && extensions[0].empty())) { std::string imageIOName = m_ImageIO->GetNameOfClass(); FixUpCustomMimeTypeName(imageIOName, customReaderMimeType); } this->AbstractFileReader::SetMimeType(customReaderMimeType); std::vector writeExtensions = imageIO->GetSupportedWriteExtensions(); if (writeExtensions.empty()) { std::string imageIOName = imageIO->GetNameOfClass(); MITK_DEBUG << "ITK ImageIOBase " << imageIOName << " does not provide write extensions"; writeExtensions = FixUpImageIOExtensions(imageIOName); } if (writeExtensions != readExtensions) { CustomMimeType customWriterMimeType; customWriterMimeType.SetCategory("Images"); for (std::vector::const_iterator iter = writeExtensions.begin(), endIter = writeExtensions.end(); iter != endIter; ++iter) { std::string extension = *iter; if (!extension.empty() && extension[0] == '.') { extension.assign(iter->begin() + 1, iter->end()); } customWriterMimeType.AddExtension(extension); } auto extensions = customWriterMimeType.GetExtensions(); if (extensions.empty() || (extensions.size() == 1 && extensions[0].empty())) { std::string imageIOName = m_ImageIO->GetNameOfClass(); FixUpCustomMimeTypeName(imageIOName, customWriterMimeType); } this->AbstractFileWriter::SetMimeType(customWriterMimeType); } std::string description = std::string("ITK ") + imageIO->GetNameOfClass(); this->SetReaderDescription(description); this->SetWriterDescription(description); this->RegisterService(); } ItkImageIO::ItkImageIO(const CustomMimeType &mimeType, itk::ImageIOBase::Pointer imageIO, int rank) : AbstractFileIO(Image::GetStaticNameOfClass(), mimeType, std::string("ITK ") + imageIO->GetNameOfClass()), m_ImageIO(imageIO) { if (m_ImageIO.IsNull()) { mitkThrow() << "ITK ImageIOBase argument must not be nullptr"; } this->AbstractFileReader::SetMimeTypePrefix(IOMimeTypes::DEFAULT_BASE_NAME() + ".image."); this->InitializeDefaultMetaDataKeys(); if (rank) { this->AbstractFileReader::SetRanking(rank); this->AbstractFileWriter::SetRanking(rank); } this->RegisterService(); } /**Helper function that converts the content of a meta data into a time point vector. * If MetaData is not valid or cannot be converted an empty vector is returned.*/ std::vector ConvertMetaDataObjectToTimePointList(const itk::MetaDataObjectBase *data) { const auto *timeGeometryTimeData = dynamic_cast *>(data); std::vector result; if (timeGeometryTimeData) { std::string dataStr = timeGeometryTimeData->GetMetaDataObjectValue(); std::stringstream stream(dataStr); TimePointType tp; while (stream >> tp) { result.push_back(tp); } } return result; }; std::vector ItkImageIO::Read() { std::vector result; mitk::LocaleSwitch localeSwitch("C"); Image::Pointer image = Image::New(); const unsigned int MINDIM = 2; const unsigned int MAXDIM = 4; const std::string path = this->GetLocalFileName(); MITK_INFO << "loading " << path << " via itk::ImageIOFactory... " << std::endl; // Check to see if we can read the file given the name or prefix if (path.empty()) { mitkThrow() << "Empty filename in mitk::ItkImageIO "; } // Got to allocate space for the image. Determine the characteristics of // the image. m_ImageIO->SetFileName(path); m_ImageIO->ReadImageInformation(); unsigned int ndim = m_ImageIO->GetNumberOfDimensions(); if (ndim < MINDIM || ndim > MAXDIM) { MITK_WARN << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim << " dimensions! Reading as 4D."; ndim = MAXDIM; } itk::ImageIORegion ioRegion(ndim); itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize(); itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex(); unsigned int dimensions[MAXDIM]; dimensions[0] = 0; dimensions[1] = 0; dimensions[2] = 0; dimensions[3] = 0; ScalarType spacing[MAXDIM]; spacing[0] = 1.0f; spacing[1] = 1.0f; spacing[2] = 1.0f; spacing[3] = 1.0f; Point3D origin; origin.Fill(0); unsigned int i; for (i = 0; i < ndim; ++i) { ioStart[i] = 0; ioSize[i] = m_ImageIO->GetDimensions(i); if (i < MAXDIM) { dimensions[i] = m_ImageIO->GetDimensions(i); spacing[i] = m_ImageIO->GetSpacing(i); if (spacing[i] <= 0) spacing[i] = 1.0f; } if (i < 3) { origin[i] = m_ImageIO->GetOrigin(i); } } ioRegion.SetSize(ioSize); ioRegion.SetIndex(ioStart); MITK_INFO << "ioRegion: " << ioRegion << std::endl; m_ImageIO->SetIORegion(ioRegion); void *buffer = new unsigned char[m_ImageIO->GetImageSizeInBytes()]; m_ImageIO->Read(buffer); image->Initialize(MakePixelType(m_ImageIO), ndim, dimensions); image->SetImportChannel(buffer, 0, Image::ManageMemory); const itk::MetaDataDictionary &dictionary = m_ImageIO->GetMetaDataDictionary(); // access direction of itk::Image and include spacing mitk::Matrix3D matrix; matrix.SetIdentity(); unsigned int j, itkDimMax3 = (ndim >= 3 ? 3 : ndim); for (i = 0; i < itkDimMax3; ++i) for (j = 0; j < itkDimMax3; ++j) matrix[i][j] = m_ImageIO->GetDirection(j)[i]; // re-initialize PlaneGeometry with origin and direction PlaneGeometry *planeGeometry = image->GetSlicedGeometry(0)->GetPlaneGeometry(0); planeGeometry->SetOrigin(origin); planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix); // re-initialize SlicedGeometry3D SlicedGeometry3D *slicedGeometry = image->GetSlicedGeometry(0); slicedGeometry->InitializeEvenlySpaced(planeGeometry, image->GetDimension(2)); slicedGeometry->SetSpacing(spacing); MITK_INFO << slicedGeometry->GetCornerPoint(false, false, false); MITK_INFO << slicedGeometry->GetCornerPoint(true, true, true); // re-initialize TimeGeometry TimeGeometry::Pointer timeGeometry; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE) || dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TYPE)) { // also check for the name because of backwards compatibility. Past code version stored with the name and not with // the key itk::MetaDataObject::ConstPointer timeGeometryTypeData = nullptr; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE)) { timeGeometryTypeData = dynamic_cast *>(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TYPE)); } else { timeGeometryTypeData = dynamic_cast *>(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TYPE)); } if (timeGeometryTypeData->GetMetaDataObjectValue() == ArbitraryTimeGeometry::GetStaticNameOfClass()) { MITK_INFO << "used time geometry: " << ArbitraryTimeGeometry::GetStaticNameOfClass() << std::endl; typedef std::vector TimePointVector; TimePointVector timePoints; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS)) { timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS)); } else if (dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS)) { timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS)); } if (timePoints.size() - 1 != image->GetDimension(3)) { MITK_ERROR << "Stored timepoints (" << timePoints.size() - 1 << ") and size of image time dimension (" << image->GetDimension(3) << ") do not match. Switch to ProportionalTimeGeometry fallback" << std::endl; } else { ArbitraryTimeGeometry::Pointer arbitraryTimeGeometry = ArbitraryTimeGeometry::New(); TimePointVector::const_iterator pos = timePoints.begin(); auto prePos = pos++; for (; pos != timePoints.end(); ++prePos, ++pos) { arbitraryTimeGeometry->AppendNewTimeStepClone(slicedGeometry, *prePos, *pos); } timeGeometry = arbitraryTimeGeometry; } } } if (timeGeometry.IsNull()) { // Fallback. If no other valid time geometry has been created, create a ProportionalTimeGeometry MITK_INFO << "used time geometry: " << ProportionalTimeGeometry::GetStaticNameOfClass() << std::endl; ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New(); propTimeGeometry->Initialize(slicedGeometry, image->GetDimension(3)); timeGeometry = propTimeGeometry; } image->SetTimeGeometry(timeGeometry); buffer = nullptr; MITK_INFO << "number of image components: " << image->GetPixelType().GetNumberOfComponents() << std::endl; for (auto iter = dictionary.Begin(), iterEnd = dictionary.End(); iter != iterEnd; ++iter) { if (iter->second->GetMetaDataObjectTypeInfo() == typeid(std::string)) { const std::string &key = iter->first; std::string assumedPropertyName = key; std::replace(assumedPropertyName.begin(), assumedPropertyName.end(), '_', '.'); std::string mimeTypeName = GetMimeType()->GetName(); // Check if there is already a info for the key and our mime type. IPropertyPersistence::InfoResultType infoList = mitk::CoreServices::GetPropertyPersistence()->GetInfoByKey(key); auto predicate = [mimeTypeName](const PropertyPersistenceInfo::ConstPointer &x) { return x.IsNotNull() && x->GetMimeTypeName() == mimeTypeName; }; auto finding = std::find_if(infoList.begin(), infoList.end(), predicate); if (finding == infoList.end()) { auto predicateWild = [](const PropertyPersistenceInfo::ConstPointer &x) { return x.IsNotNull() && x->GetMimeTypeName() == PropertyPersistenceInfo::ANY_MIMETYPE_NAME(); }; finding = std::find_if(infoList.begin(), infoList.end(), predicateWild); } PropertyPersistenceInfo::ConstPointer info; if (finding != infoList.end()) { assumedPropertyName = (*finding)->GetName(); info = *finding; } else { // we have not found anything suitable so we generate our own info PropertyPersistenceInfo::Pointer newInfo = PropertyPersistenceInfo::New(); newInfo->SetNameAndKey(assumedPropertyName, key); newInfo->SetMimeTypeName(PropertyPersistenceInfo::ANY_MIMETYPE_NAME()); info = newInfo; } std::string value = dynamic_cast *>(iter->second.GetPointer())->GetMetaDataObjectValue(); mitk::BaseProperty::Pointer loadedProp = info->GetDeserializationFunction()(value); image->SetProperty(assumedPropertyName.c_str(), loadedProp); // Read properties should be persisted unless they are default properties // which are written anyway bool isDefaultKey(false); for (const auto &defaultKey : m_DefaultMetaDataKeys) { if (defaultKey.length() <= assumedPropertyName.length()) { // does the start match the default key if (assumedPropertyName.substr(0, defaultKey.length()).find(defaultKey) != std::string::npos) { isDefaultKey = true; break; } } } if (!isDefaultKey) { mitk::CoreServices::GetPropertyPersistence()->AddInfo(info); } } } MITK_INFO << "...finished!" << std::endl; result.push_back(image.GetPointer()); return result; } AbstractFileIO::ConfidenceLevel ItkImageIO::GetReaderConfidenceLevel() const { return m_ImageIO->CanReadFile(GetLocalFileName().c_str()) ? IFileReader::Supported : IFileReader::Unsupported; } void ItkImageIO::Write() { const auto *image = dynamic_cast(this->GetInput()); if (image == nullptr) { mitkThrow() << "Cannot write non-image data"; } // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); // Clone the image geometry, because we might have to change it // for writing purposes BaseGeometry::Pointer geometry = image->GetGeometry()->Clone(); // Check if geometry information will be lost if (image->GetDimension() == 2 && !geometry->Is2DConvertable()) { MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might " "consider using Convert2Dto3DImageFilter before saving."; // set matrix to identity mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New(); affTrans->SetIdentity(); mitk::Vector3D spacing = geometry->GetSpacing(); mitk::Point3D origin = geometry->GetOrigin(); geometry->SetIndexToWorldTransform(affTrans); geometry->SetSpacing(spacing); geometry->SetOrigin(origin); } LocalFile localFile(this); const std::string path = localFile.GetFileName(); MITK_INFO << "Writing image: " << path << std::endl; try { // Implementation of writer using itkImageIO directly. This skips the use // of templated itkImageFileWriter, which saves the multiplexing on MITK side. const unsigned int dimension = image->GetDimension(); const unsigned int *const dimensions = image->GetDimensions(); const mitk::PixelType pixelType = image->GetPixelType(); const mitk::Vector3D mitkSpacing = geometry->GetSpacing(); const mitk::Point3D mitkOrigin = geometry->GetOrigin(); // Due to templating in itk, we are forced to save a 4D spacing and 4D Origin, // though they are not supported in MITK itk::Vector spacing4D; spacing4D[0] = mitkSpacing[0]; spacing4D[1] = mitkSpacing[1]; spacing4D[2] = mitkSpacing[2]; spacing4D[3] = 1; // There is no support for a 4D spacing. However, we should have a valid value here itk::Vector origin4D; origin4D[0] = mitkOrigin[0]; origin4D[1] = mitkOrigin[1]; origin4D[2] = mitkOrigin[2]; origin4D[3] = 0; // There is no support for a 4D origin. However, we should have a valid value here // Set the necessary information for imageIO m_ImageIO->SetNumberOfDimensions(dimension); m_ImageIO->SetPixelType(pixelType.GetPixelType()); m_ImageIO->SetComponentType(pixelType.GetComponentType() < PixelComponentUserType ? static_cast(pixelType.GetComponentType()) : itk::ImageIOBase::UNKNOWNCOMPONENTTYPE); m_ImageIO->SetNumberOfComponents(pixelType.GetNumberOfComponents()); itk::ImageIORegion ioRegion(dimension); for (unsigned int i = 0; i < dimension; i++) { m_ImageIO->SetDimensions(i, dimensions[i]); m_ImageIO->SetSpacing(i, spacing4D[i]); m_ImageIO->SetOrigin(i, origin4D[i]); mitk::Vector3D mitkDirection; mitkDirection.SetVnlVector(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i)); itk::Vector direction4D; direction4D[0] = mitkDirection[0]; direction4D[1] = mitkDirection[1]; direction4D[2] = mitkDirection[2]; // MITK only supports a 3x3 direction matrix. Due to templating in itk, however, we must // save a 4x4 matrix for 4D images. in this case, add an homogneous component to the matrix. if (i == 3) { direction4D[3] = 1; // homogenous component } else { direction4D[3] = 0; } vnl_vector axisDirection(dimension); for (unsigned int j = 0; j < dimension; j++) { axisDirection[j] = direction4D[j] / spacing4D[i]; } m_ImageIO->SetDirection(i, axisDirection); ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i)); ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i)); } // use compression if available m_ImageIO->UseCompressionOn(); m_ImageIO->SetIORegion(ioRegion); m_ImageIO->SetFileName(path); // Handle time geometry const auto *arbitraryTG = dynamic_cast(image->GetTimeGeometry()); if (arbitraryTG) { itk::EncapsulateMetaData(m_ImageIO->GetMetaDataDictionary(), PROPERTY_KEY_TIMEGEOMETRY_TYPE, ArbitraryTimeGeometry::GetStaticNameOfClass()); std::stringstream stream; stream << arbitraryTG->GetTimeBounds(0)[0]; for (TimeStepType pos = 0; pos < arbitraryTG->CountTimeSteps(); ++pos) { stream << " " << arbitraryTG->GetTimeBounds(pos)[1]; } std::string data = stream.str(); itk::EncapsulateMetaData( m_ImageIO->GetMetaDataDictionary(), PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS, data); } // Handle properties mitk::PropertyList::Pointer imagePropertyList = image->GetPropertyList(); for (const auto &property : *imagePropertyList->GetMap()) { IPropertyPersistence::InfoResultType infoList = mitk::CoreServices::GetPropertyPersistence()->GetInfo(property.first, GetMimeType()->GetName(), true); if (infoList.empty()) { continue; } std::string value = infoList.front()->GetSerializationFunction()(property.second); if (value == mitk::BaseProperty::VALUE_CANNOT_BE_CONVERTED_TO_STRING) { continue; } std::string key = infoList.front()->GetKey(); itk::EncapsulateMetaData(m_ImageIO->GetMetaDataDictionary(), key, value); } - ImageReadAccessor imageAccess(image); + LocaleSwitch localeSwitch2("C"); m_ImageIO->Write(imageAccess.GetData()); } catch (const std::exception &e) { mitkThrow() << e.what(); } } AbstractFileIO::ConfidenceLevel ItkImageIO::GetWriterConfidenceLevel() const { // Check if the image dimension is supported const auto *image = dynamic_cast(this->GetInput()); if (image == nullptr) { // We cannot write a null object, DUH! return IFileWriter::Unsupported; } if (!m_ImageIO->SupportsDimension(image->GetDimension())) { // okay, dimension is not supported. We have to look at a special case: // 3D-Image with one slice. We can treat that as a 2D image. if ((image->GetDimension() == 3) && (image->GetSlicedGeometry()->GetSlices() == 1)) return IFileWriter::Supported; else return IFileWriter::Unsupported; } // Check if geometry information will be lost if (image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable()) { return IFileWriter::PartiallySupported; } return IFileWriter::Supported; } ItkImageIO *ItkImageIO::IOClone() const { return new ItkImageIO(*this); } void ItkImageIO::InitializeDefaultMetaDataKeys() { this->m_DefaultMetaDataKeys.push_back("NRRD.space"); this->m_DefaultMetaDataKeys.push_back("NRRD.kinds"); this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TYPE); this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS); this->m_DefaultMetaDataKeys.push_back("ITK.InputFilterName"); } } diff --git a/Modules/DICOMReader/src/mitkDICOMTagBasedSorter.cpp b/Modules/DICOMReader/src/mitkDICOMTagBasedSorter.cpp index 08512c2a75..b82d8abdeb 100644 --- a/Modules/DICOMReader/src/mitkDICOMTagBasedSorter.cpp +++ b/Modules/DICOMReader/src/mitkDICOMTagBasedSorter.cpp @@ -1,596 +1,599 @@ /*=================================================================== 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 "mitkDICOMTagBasedSorter.h" #include #include mitk::DICOMTagBasedSorter::CutDecimalPlaces ::CutDecimalPlaces(unsigned int precision) :m_Precision(precision) { } mitk::DICOMTagBasedSorter::CutDecimalPlaces ::CutDecimalPlaces(const CutDecimalPlaces& other) :m_Precision(other.m_Precision) { } std::string mitk::DICOMTagBasedSorter::CutDecimalPlaces ::operator()(const std::string& input) const { // be a bit tolerant for tags such as image orientation orienatation, let only the first few digits matter (http://bugs.mitk.org/show_bug.cgi?id=12263) // iterate all fields, convert each to a number, cut this number as configured, then return a concatenated string with all cut-off numbers std::ostringstream resultString; resultString.str(std::string()); resultString.clear(); resultString.setf(std::ios::fixed, std::ios::floatfield); resultString.precision(m_Precision); std::stringstream ss(input); ss.str(input); ss.clear(); std::string item; double number(0); std::istringstream converter(item); while (std::getline(ss, item, '\\')) { converter.str(item); converter.clear(); if (converter >> number && converter.eof()) { // converted to double resultString << number; } else { // did not convert to double resultString << item; // just paste the unmodified string } if (!ss.eof()) { resultString << "\\"; } } return resultString.str(); } mitk::DICOMTagBasedSorter::TagValueProcessor* mitk::DICOMTagBasedSorter::CutDecimalPlaces ::Clone() const { return new CutDecimalPlaces(*this); } unsigned int mitk::DICOMTagBasedSorter::CutDecimalPlaces ::GetPrecision() const { return m_Precision; } mitk::DICOMTagBasedSorter ::DICOMTagBasedSorter() :DICOMDatasetSorter() ,m_StrictSorting(m_DefaultStrictSorting) ,m_ExpectDistanceOne(m_DefaultExpectDistanceOne) { } mitk::DICOMTagBasedSorter ::~DICOMTagBasedSorter() { for(auto ti = m_TagValueProcessor.cbegin(); ti != m_TagValueProcessor.cend(); ++ti) { delete ti->second; } } mitk::DICOMTagBasedSorter ::DICOMTagBasedSorter(const DICOMTagBasedSorter& other ) :DICOMDatasetSorter(other) ,m_DistinguishingTags( other.m_DistinguishingTags ) ,m_SortCriterion( other.m_SortCriterion ) ,m_StrictSorting( other.m_StrictSorting ) ,m_ExpectDistanceOne( other.m_ExpectDistanceOne ) { for(auto ti = other.m_TagValueProcessor.cbegin(); ti != other.m_TagValueProcessor.cend(); ++ti) { m_TagValueProcessor[ti->first] = ti->second->Clone(); } } mitk::DICOMTagBasedSorter& mitk::DICOMTagBasedSorter ::operator=(const DICOMTagBasedSorter& other) { if (this != &other) { DICOMDatasetSorter::operator=(other); m_DistinguishingTags = other.m_DistinguishingTags; m_SortCriterion = other.m_SortCriterion; m_StrictSorting = other.m_StrictSorting; m_ExpectDistanceOne = other.m_ExpectDistanceOne; for(auto ti = other.m_TagValueProcessor.cbegin(); ti != other.m_TagValueProcessor.cend(); ++ti) { m_TagValueProcessor[ti->first] = ti->second->Clone(); } } return *this; } bool mitk::DICOMTagBasedSorter ::operator==(const DICOMDatasetSorter& other) const { if (const auto* otherSelf = dynamic_cast(&other)) { if (this->m_StrictSorting != otherSelf->m_StrictSorting) return false; if (this->m_ExpectDistanceOne != otherSelf->m_ExpectDistanceOne) return false; bool allTagsPresentAndEqual(true); if (this->m_DistinguishingTags.size() != otherSelf->m_DistinguishingTags.size()) return false; for (auto myTag = this->m_DistinguishingTags.cbegin(); myTag != this->m_DistinguishingTags.cend(); ++myTag) { allTagsPresentAndEqual &= (std::find( otherSelf->m_DistinguishingTags.cbegin(), otherSelf->m_DistinguishingTags.cend(), *myTag ) != otherSelf->m_DistinguishingTags.cend()); // other contains this tags // since size is equal, we don't need to check the inverse } if (!allTagsPresentAndEqual) return false; if (this->m_SortCriterion.IsNotNull() && otherSelf->m_SortCriterion.IsNotNull()) { return *(this->m_SortCriterion) == *(otherSelf->m_SortCriterion); } else { return this->m_SortCriterion.IsNull() && otherSelf->m_SortCriterion.IsNull(); } } else { return false; } } void mitk::DICOMTagBasedSorter ::PrintConfiguration(std::ostream& os, const std::string& indent) const { os << indent << "Tag based sorting " << "(strict=" << (m_StrictSorting?"true":"false") << ", expectDistanceOne=" << (m_ExpectDistanceOne?"true":"false") << "):" << std::endl; for (auto tagIter = m_DistinguishingTags.begin(); tagIter != m_DistinguishingTags.end(); ++tagIter) { os << indent << " Split on "; tagIter->Print(os); os << std::endl; } DICOMSortCriterion::ConstPointer crit = m_SortCriterion.GetPointer(); while (crit.IsNotNull()) { os << indent << " Sort by "; crit->Print(os); os << std::endl; crit = crit->GetSecondaryCriterion(); } } void mitk::DICOMTagBasedSorter ::SetStrictSorting(bool strict) { m_StrictSorting = strict; } bool mitk::DICOMTagBasedSorter ::GetStrictSorting() const { return m_StrictSorting; } void mitk::DICOMTagBasedSorter ::SetExpectDistanceOne(bool strict) { m_ExpectDistanceOne = strict; } bool mitk::DICOMTagBasedSorter ::GetExpectDistanceOne() const { return m_ExpectDistanceOne; } mitk::DICOMTagList mitk::DICOMTagBasedSorter ::GetTagsOfInterest() { DICOMTagList allTags = m_DistinguishingTags; - const DICOMTagList sortingRelevantTags = m_SortCriterion->GetAllTagsOfInterest(); - allTags.insert( allTags.end(), sortingRelevantTags.cbegin(), sortingRelevantTags.cend() ); // append + if (m_SortCriterion.IsNotNull()) + { + const DICOMTagList sortingRelevantTags = m_SortCriterion->GetAllTagsOfInterest(); + allTags.insert( allTags.end(), sortingRelevantTags.cbegin(), sortingRelevantTags.cend() ); // append + } return allTags; } mitk::DICOMTagList mitk::DICOMTagBasedSorter ::GetDistinguishingTags() const { return m_DistinguishingTags; } const mitk::DICOMTagBasedSorter::TagValueProcessor* mitk::DICOMTagBasedSorter ::GetTagValueProcessorForDistinguishingTag(const DICOMTag& tag) const { auto loc = m_TagValueProcessor.find(tag); if (loc != m_TagValueProcessor.cend()) { return loc->second; } else { return nullptr; } } void mitk::DICOMTagBasedSorter ::AddDistinguishingTag( const DICOMTag& tag, TagValueProcessor* tagValueProcessor ) { m_DistinguishingTags.push_back(tag); m_TagValueProcessor[tag] = tagValueProcessor; } void mitk::DICOMTagBasedSorter ::SetSortCriterion( DICOMSortCriterion::ConstPointer criterion ) { m_SortCriterion = criterion; } mitk::DICOMSortCriterion::ConstPointer mitk::DICOMTagBasedSorter ::GetSortCriterion() const { return m_SortCriterion; } void mitk::DICOMTagBasedSorter ::Sort() { // 1. split // 2. sort each group GroupIDToListType groups = this->SplitInputGroups(); GroupIDToListType& sortedGroups = this->SortGroups( groups ); // 3. define output this->SetNumberOfOutputs(sortedGroups.size()); unsigned int outputIndex(0); for (auto groupIter = sortedGroups.cbegin(); groupIter != sortedGroups.cend(); ++outputIndex, ++groupIter) { this->SetOutput(outputIndex, groupIter->second); } } std::string mitk::DICOMTagBasedSorter ::BuildGroupID( DICOMDatasetAccess* dataset ) { // just concatenate all tag values assert(dataset); std::stringstream groupID; groupID << "g"; for (auto tagIter = m_DistinguishingTags.cbegin(); tagIter != m_DistinguishingTags.cend(); ++tagIter) { groupID << tagIter->GetGroup() << tagIter->GetElement(); // make group/element part of the id to cover empty tags DICOMDatasetFinding rawTagValue = dataset->GetTagValueAsString(*tagIter); std::string processedTagValue; if ( m_TagValueProcessor[*tagIter] != nullptr && rawTagValue.isValid) { processedTagValue = (*m_TagValueProcessor[*tagIter])(rawTagValue.value); } else { processedTagValue = rawTagValue.value; } groupID << processedTagValue; } // shorten ID? return groupID.str(); } mitk::DICOMTagBasedSorter::GroupIDToListType mitk::DICOMTagBasedSorter ::SplitInputGroups() { DICOMDatasetList input = GetInput(); // copy GroupIDToListType listForGroupID; for (auto dsIter = input.cbegin(); dsIter != input.cend(); ++dsIter) { DICOMDatasetAccess* dataset = *dsIter; assert(dataset); std::string groupID = this->BuildGroupID( dataset ); MITK_DEBUG << "Group ID for for " << dataset->GetFilenameIfAvailable() << ": " << groupID; listForGroupID[groupID].push_back(dataset); } MITK_DEBUG << "After tag based splitting: " << listForGroupID.size() << " groups"; return listForGroupID; } mitk::DICOMTagBasedSorter::GroupIDToListType& mitk::DICOMTagBasedSorter ::SortGroups(GroupIDToListType& groups) { if (m_SortCriterion.IsNotNull()) { /* Three steps here: 1. sort within each group - this may result in orders such as 1 2 3 4 6 7 8 10 12 13 14 2. create new groups by enforcing consecutive order within each group - resorts above example like 1 2 3 4 ; 6 7 8 ; 10 ; 12 13 14 3. sort all of the groups (not WITHIN each group) by their first frame - if earlier "distinguish" steps created groups like 6 7 8 ; 1 2 3 4 ; 10, then this step would sort them like 1 2 3 4 ; 6 7 8 ; 10 */ // Step 1: sort within the groups // for each output // sort by all configured tags, use secondary tags when equal or empty // make configurable: // - sorting order (ascending, descending) // - sort numerically // - ... ? unsigned int groupIndex(0); for (auto gIter = groups.begin(); gIter != groups.end(); ++groupIndex, ++gIter) { DICOMDatasetList& dsList = gIter->second; #ifdef MBILOG_ENABLE_DEBUG MITK_DEBUG << " --------------------------------------------------------------------------------"; MITK_DEBUG << " DICOMTagBasedSorter before sorting group : " << groupIndex; for (auto oi = dsList.begin(); oi != dsList.cend(); ++oi) { MITK_DEBUG << " INPUT : " << (*oi)->GetFilenameIfAvailable(); } #endif // #ifdef MBILOG_ENABLE_DEBUG std::sort( dsList.begin(), dsList.end(), ParameterizedDatasetSort( m_SortCriterion ) ); #ifdef MBILOG_ENABLE_DEBUG MITK_DEBUG << " --------------------------------------------------------------------------------"; MITK_DEBUG << " DICOMTagBasedSorter after sorting group : " << groupIndex; for (auto oi = dsList.cbegin(); oi != dsList.cend(); ++oi) { MITK_DEBUG << " OUTPUT : " << (*oi)->GetFilenameIfAvailable(); } MITK_DEBUG << " --------------------------------------------------------------------------------"; #endif // MBILOG_ENABLE_DEBUG } GroupIDToListType consecutiveGroups; if (m_StrictSorting) { // Step 2: create new groups by enforcing consecutive order within each group unsigned int groupIndex(0); for (auto gIter = groups.begin(); gIter != groups.end(); ++gIter) { std::stringstream groupKey; groupKey << std::setfill('0') << std::setw(6) << groupIndex++; DICOMDatasetList& dsList = gIter->second; DICOMDatasetAccess* previousDS(nullptr); unsigned int dsIndex(0); double constantDistance(0.0); bool constantDistanceInitialized(false); for (auto dataset = dsList.cbegin(); dataset != dsList.cend(); ++dsIndex, ++dataset) { if (dsIndex >0) // ignore the first dataset, we cannot check any distances yet.. { // for the second and every following dataset: // let the sorting criterion calculate a "distance" // if the distance is not 1, split off a new group! const double currentDistance = m_SortCriterion->NumericDistance(previousDS, *dataset); if (constantDistanceInitialized) { if (fabs(currentDistance - constantDistance) < fabs(constantDistance * 0.01)) // ok, deviation of up to 1% of distance is tolerated { // nothing to do, just ok MITK_DEBUG << "Checking currentDistance==" << currentDistance << ": small enough"; } //else if (currentDistance < mitk::eps) // close enough to 0 else { MITK_DEBUG << "Split consecutive group at index " << dsIndex << " (current distance " << currentDistance << ", constant distance " << constantDistance << ")"; // split! this is done by simply creating a new group (key) groupKey.str(std::string()); groupKey.clear(); groupKey << std::setfill('0') << std::setw(6) << groupIndex++; } } else { // second slice: learn about the expected distance! // heuristic: if distance is an integer, we check for a special case: // if the distance is integer and not 1/-1, then we assume // a missing slice right after the first slice // ==> split off slices // in all other cases: second dataset at this position, no need to split already, we are still learning about the images // addition to the above: when sorting by imagepositions, a distance other than 1 between the first two slices is // not unusual, actually expected... then we should not split if (m_ExpectDistanceOne) { if ((currentDistance - (int)currentDistance == 0.0) && fabs(currentDistance) != 1.0) // exact comparison. An integer should not be expressed as 1.000000000000000000000000001! { MITK_DEBUG << "Split consecutive group at index " << dsIndex << " (special case: expected distance 1 exactly)"; groupKey.str(std::string()); groupKey.clear(); groupKey << std::setfill('0') << std::setw(6) << groupIndex++; } } MITK_DEBUG << "Initialize strict distance to currentDistance=" << currentDistance; constantDistance = currentDistance; constantDistanceInitialized = true; } } consecutiveGroups[groupKey.str()].push_back(*dataset); previousDS = *dataset; } } } else { consecutiveGroups = groups; } // Step 3: sort all of the groups (not WITHIN each group) by their first frame /* build a list-1 of datasets with the first dataset one of each group sort this list-1 build a new result list-2: - iterate list-1, for each dataset - find the group that contains this dataset - add this group as the next element to list-2 return list-2 as the sorted output */ DICOMDatasetList firstSlices; for (auto gIter = consecutiveGroups.cbegin(); gIter != consecutiveGroups.cend(); ++gIter) { assert(!gIter->second.empty()); firstSlices.push_back(gIter->second.front()); } std::sort( firstSlices.begin(), firstSlices.end(), ParameterizedDatasetSort( m_SortCriterion ) ); GroupIDToListType sortedResultBlocks; unsigned int groupKeyValue(0); for (auto firstSlice = firstSlices.cbegin(); firstSlice != firstSlices.cend(); ++firstSlice) { for (auto gIter = consecutiveGroups.cbegin(); gIter != consecutiveGroups.cend(); ++groupKeyValue, ++gIter) { if (gIter->second.front() == *firstSlice) { std::stringstream groupKey; groupKey << std::setfill('0') << std::setw(6) << groupKeyValue; // try more than 999,999 groups and you are doomed (your application already is) sortedResultBlocks[groupKey.str()] = gIter->second; } } } groups = sortedResultBlocks; } #ifdef MBILOG_ENABLE_DEBUG unsigned int groupIndex( 0 ); for ( auto gIter = groups.begin(); gIter != groups.end(); ++groupIndex, ++gIter ) { DICOMDatasetList& dsList = gIter->second; MITK_DEBUG << " --------------------------------------------------------------------------------"; MITK_DEBUG << " DICOMTagBasedSorter after sorting group : " << groupIndex; for ( auto oi = dsList.begin(); oi != dsList.end(); ++oi ) { MITK_DEBUG << " OUTPUT : " << ( *oi )->GetFilenameIfAvailable(); } MITK_DEBUG << " --------------------------------------------------------------------------------"; } #endif // MBILOG_ENABLE_DEBUG return groups; } mitk::DICOMTagBasedSorter::ParameterizedDatasetSort ::ParameterizedDatasetSort(DICOMSortCriterion::ConstPointer criterion) :m_SortCriterion(criterion) { } bool mitk::DICOMTagBasedSorter::ParameterizedDatasetSort ::operator() (const mitk::DICOMDatasetAccess* left, const mitk::DICOMDatasetAccess* right) { assert(left); assert(right); assert(m_SortCriterion.IsNotNull()); return m_SortCriterion->IsLeftBeforeRight(left, right); } diff --git a/Modules/DiffusionImaging/DiffusionCore/autoload/IO/mitkDiffusionImageDicomReaderService.cpp b/Modules/DiffusionImaging/DiffusionCore/autoload/IO/mitkDiffusionImageDicomReaderService.cpp index d2ff95a095..ede4fc7775 100644 --- a/Modules/DiffusionImaging/DiffusionCore/autoload/IO/mitkDiffusionImageDicomReaderService.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/autoload/IO/mitkDiffusionImageDicomReaderService.cpp @@ -1,337 +1,326 @@ /*=================================================================== 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 __mitkDiffusionImageDicomReaderService_cpp #define __mitkDiffusionImageDicomReaderService_cpp #include "mitkDiffusionImageDicomReaderService.h" #include #include // Diffusion properties #include #include #include #include #include #include #include "itksys/SystemTools.hxx" #include "itkImageFileReader.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include "mitkCustomMimeType.h" #include "mitkDiffusionCoreIOMimeTypes.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace mitk { DiffusionImageDicomReaderService:: DiffusionImageDicomReaderService(const DiffusionImageDicomReaderService & other) : AbstractFileReader(other) { } DiffusionImageDicomReaderService* DiffusionImageDicomReaderService::Clone() const { return new DiffusionImageDicomReaderService(*this); } DiffusionImageDicomReaderService:: ~DiffusionImageDicomReaderService() {} DiffusionImageDicomReaderService:: DiffusionImageDicomReaderService() : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionCoreIOMimeTypes::DWI_DICOM_MIMETYPE() ), mitk::DiffusionCoreIOMimeTypes::DWI_DICOM_MIMETYPE_DESCRIPTION() ) { Options defaultOptions; defaultOptions["Load recursive"] = false; defaultOptions["Split mosaic"] = true; this->SetDefaultOptions(defaultOptions); m_ServiceReg = this->RegisterService(); } std::vector > DiffusionImageDicomReaderService::Read() { return InternalRead(); } std::vector > DiffusionImageDicomReaderService::InternalRead() { std::vector > result_images; OutputType::Pointer outputForCache = OutputType::New(); if ( this->GetInputLocation() == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename to be read is empty!"); } else { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, nullptr ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } try { Options options = this->GetOptions(); bool load_recursive = us::any_cast(options["Load recursive"]); bool split_mosaic = us::any_cast(options["Split mosaic"]); gdcm::Directory::FilenamesType complete_list; std::string folderName = itksys::SystemTools::GetFilenamePath( this->GetInputLocation() ); if( load_recursive ) { std::string subdir_prefix = ""; itksys::Directory rootdir; rootdir.Load( folderName.c_str() ); for( unsigned int 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) // TODO handle as real vectors! cluster with configurable errors! tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x000e) ); // Series Instance UID 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 - // gdcmReader->AddSortingElement( tagSorter ); - //mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader ); - - mitk::DICOMSortCriterion::ConstPointer sorting = - mitk::SortByImagePositionPatient::New( // Image Position (Patient) - //mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0013), // instance number - mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0012), // aqcuisition number - mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0032), // aqcuisition time - mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0018, 0x1060), // trigger time - mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0018) // SOP instance UID (last resort, not really meaningful but decides clearly) - ).GetPointer() - ).GetPointer() - ).GetPointer() - ).GetPointer() - // ).GetPointer() - ).GetPointer(); + auto tag_sop_instance_uid = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0018), nullptr ); // SOP instance UID (last resort, not really meaningful but decides clearly) + auto tag_trigger_time = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0018, 0x1060), tag_sop_instance_uid.GetPointer() ); // trigger time + auto tag_aqcuisition_time = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0032), tag_trigger_time.GetPointer()); // aqcuisition time + auto tag_aqcuisition_number = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0012), tag_aqcuisition_time.GetPointer()); // aqcuisition number + mitk::DICOMSortCriterion::ConstPointer sorting = mitk::SortByImagePositionPatient::New(tag_aqcuisition_number.GetPointer()).GetPointer(); tagSorter->SetSortCriterion( sorting ); // mosaic gdcmReader->SetResolveMosaic( split_mosaic ); gdcmReader->AddSortingElement( tagSorter ); gdcmReader->SetInputFiles( complete_list ); try { gdcmReader->AnalyzeInputFiles(); } catch( const itk::ExceptionObject &e) { MITK_ERROR << "Failed to analyze data. " << e.what(); } catch( const std::exception &se) { MITK_ERROR << "Std Exception " << se.what(); } gdcmReader->LoadImages(); for( unsigned int o = 0; o < gdcmReader->GetNumberOfOutputs(); o++ ) { mitk::Image::Pointer loaded_image = gdcmReader->GetOutput(o).GetMitkImage(); StringProperty::Pointer nameProp; if (gdcmReader->GetSeriesName(o)!="-") nameProp = StringProperty::New(gdcmReader->GetSeriesName(o)); else if (gdcmReader->GetStudyName(o)!="-") nameProp = StringProperty::New(gdcmReader->GetStudyName(o)); else nameProp = StringProperty::New(folderName); loaded_image->SetProperty("name", nameProp); std::string val = "-"; if (gdcmReader->patient_ids().size()>o) { val = gdcmReader->patient_ids().at(o); loaded_image->GetPropertyList()->SetStringProperty("DICOM.patient_id",val.c_str()); } if (gdcmReader->patient_names().size()>o) { val = gdcmReader->patient_names().at(o); loaded_image->GetPropertyList()->SetStringProperty("DICOM.patient_name",val.c_str()); } if (gdcmReader->study_instance_uids().size()>o) { val = gdcmReader->study_instance_uids().at(o); loaded_image->GetPropertyList()->SetStringProperty("DICOM.study_instance_uid",val.c_str()); } if (gdcmReader->series_instance_uids().size()>o) { val = gdcmReader->series_instance_uids().at(o); loaded_image->GetPropertyList()->SetStringProperty("DICOM.series_instance_uid",val.c_str()); } if (gdcmReader->sop_instance_uids().size()>o) { val = gdcmReader->sop_instance_uids().at(o); loaded_image->GetPropertyList()->SetStringProperty("DICOM.sop_instance_uid",val.c_str()); } if (gdcmReader->frame_of_reference_uids().size()>o) { val = gdcmReader->frame_of_reference_uids().at(o); loaded_image->GetPropertyList()->SetStringProperty("DICOM.frame_of_reference_uid",val.c_str()); } result_images.push_back(loaded_image.GetPointer()); } // 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) { try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } MITK_INFO << "Std::Exception while reading file!!"; MITK_INFO << e.what(); throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } MITK_INFO << "Exception while reading file!!"; throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!"); } } return result_images; } } //namespace MITK #endif diff --git a/Modules/IGTBase/include/mitkIGTMimeTypes.h b/Modules/IGTBase/include/mitkIGTMimeTypes.h index cef22a1141..52b5f38d47 100644 --- a/Modules/IGTBase/include/mitkIGTMimeTypes.h +++ b/Modules/IGTBase/include/mitkIGTMimeTypes.h @@ -1,34 +1,35 @@ /*=================================================================== 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 MITKIOMIMETYPE_H_HEADER_INCLUDED_ #define MITKIOMIMETYPE_H_HEADER_INCLUDED_ #include #include #include namespace mitk { class MITKIGTBASE_EXPORT IGTMimeTypes { public: static CustomMimeType NAVIGATIONDATASETXML_MIMETYPE(); static CustomMimeType NAVIGATIONDATASETCSV_MIMETYPE(); + static CustomMimeType USDEVICEINFORMATIONXML_MIMETYPE(); }; } #endif // MITKIOMIMETYPE_H_HEADER_INCLUDED_ \ No newline at end of file diff --git a/Modules/IGTBase/src/mitkIGTMimeTypes.cpp b/Modules/IGTBase/src/mitkIGTMimeTypes.cpp index f342ad8bea..a9db7c8f96 100644 --- a/Modules/IGTBase/src/mitkIGTMimeTypes.cpp +++ b/Modules/IGTBase/src/mitkIGTMimeTypes.cpp @@ -1,38 +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. ===================================================================*/ // MITK #include "mitkIGTMimeTypes.h" mitk::CustomMimeType mitk::IGTMimeTypes::NAVIGATIONDATASETXML_MIMETYPE() { mitk::CustomMimeType mimeType(IOMimeTypes::DEFAULT_BASE_NAME() + ".NavigationDataSet.xml"); std::string category = "NavigationDataSet"; mimeType.SetComment("NavigationDataSet (XML)"); mimeType.SetCategory(category); mimeType.AddExtension("xml"); return mimeType; } mitk::CustomMimeType mitk::IGTMimeTypes::NAVIGATIONDATASETCSV_MIMETYPE() { mitk::CustomMimeType mimeType(IOMimeTypes::DEFAULT_BASE_NAME() + ".NavigationDataSet.csv"); std::string category = "NavigationDataSet"; mimeType.SetComment("NavigationDataSet (csv)"); mimeType.SetCategory(category); mimeType.AddExtension("csv"); return mimeType; +} + +mitk::CustomMimeType mitk::IGTMimeTypes::USDEVICEINFORMATIONXML_MIMETYPE() +{ + mitk::CustomMimeType mimeType(IOMimeTypes::DEFAULT_BASE_NAME() + ".USDeviceInformation.xml"); + std::string category = "USDeviceInformation"; + mimeType.SetComment("USDeviceInformation (XML)"); + mimeType.SetCategory(category); + mimeType.AddExtension("xml"); + return mimeType; } \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkFiducialRegistrationWidget.ui b/Modules/IGTUI/Qmitk/QmitkFiducialRegistrationWidget.ui index 843344e01c..2fff9363fc 100755 --- a/Modules/IGTUI/Qmitk/QmitkFiducialRegistrationWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkFiducialRegistrationWidget.ui @@ -1,279 +1,307 @@ QmitkFiducialRegistrationWidget 0 0 - 569 - 402 + 580 + 525 0 0 Form - - - Fiducial Registration method - - - - - - true - - - Static - - - true - - - - - - - true - - - Hybrid Continuous - - - false - - - - - - - - - - - - Move Image Points - - - - - - - - 0 - 40 - - - - <html><head/><body><p>Find fiducial correspondences (needs 6+ fiducial pairs)</p></body></html> - - - - Find fiducial - correspondences - - - - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - Register (object is moved) - - - - - + - - - - 0 - 0 - - - - Image / object / moving fiducials - - - - - - - 0 - 0 - + + + + + Fiducial Registration method + + + + true - - - - - - - 0 - 55 - + + + 10 + 23 + 50 + 17 + - - QFrame::NoFrame + + Static - - QFrame::Raised + + true - - - - - - 0 - 0 - - - - - 0 - 35 - - - - Add image fiducial - - - - - - - - - - - - - 0 - 0 - - - - Tracker / fixed fiducials - - - - - - - 0 - 0 - + + + true - - - - - - - 0 - 55 - + + + 66 + 23 + 111 + 17 + - - QFrame::NoFrame + + Hybrid Continuous - - QFrame::Raised + + false - - - - - - 0 - 0 - - - - - 0 - 35 - - - - &Add current - instrument position - - - - - - - + + + + + + + + Move Image Points + + + + + + + + 0 + 40 + + + + <html><head/><body><p>Find fiducial correspondences (needs 6+ fiducial pairs)</p></body></html> + + + + Find fiducial + correspondences + + + + + + + + + + + 0 + 0 + + + + + 40 + 40 + + + + Register (object is moved) + + + + - - - - - - - - 0 - 0 - - - - Status: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - + + + + + + 0 + 0 + + + + + 16777215 + 400 + + + + Image / object / moving fiducials + + + + + + + 0 + 0 + + + + + + + + + 0 + 55 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + 0 + 35 + + + + Add image fiducial + + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 400 + + + + Tracker / fixed fiducials + + + + + + + 0 + 0 + + + + + + + + + 0 + 55 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + 0 + 35 + + + + &Add current + instrument position + + + + + + + + + + - - - - - - Qt::AlignCenter - - + + + + + + 0 + 0 + + + + Status: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + Qt::AlignCenter + + + + - m_RegisterFiducialsBtn - m_gbFiducialRegistration QmitkPointListWidget QListWidget
QmitkPointListWidget.h
diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui index cc0877213e..d2a2dd9051 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui @@ -1,586 +1,586 @@ QmitkNavigationToolCreationWidgetControls 0 0 618 650 Form Device Type: 150 0 150 16777215 - 0 + 2 0 0 600 - 433 + 456 Basic Information 100 0 Name: NewTool 100 0 Calibration File: none - 40 + 60 16777215 Load Qt::Vertical 20 40 0 0 600 - 433 + 456 Tool Visualization Default representation (shows tool coordinates) true Use surface from data storage 200 0 150 16777215 Qt::Horizontal 40 20 Load surface from file false - 40 + 60 16777215 Load Qt::Horizontal 40 20 Qt::Vertical 20 8 0 0 600 - 433 + 456 Tool Landmarks 0 Control Points for Registration Tool Landmarks 0 0 - 600 - 433 + 276 + 161 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 Tool Axis: Qt::Horizontal 40 20 QAbstractSpinBox::CorrectToPreviousValue -9999 9999 1 -9999 9999 -9999 9999 Qt::Horizontal Qt::Horizontal 40 20 Cancel Finished QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
1
QmitkPointListWidget QWidget
QmitkPointListWidget.h
1
diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui index b246da95c5..4964d23533 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui @@ -1,315 +1,315 @@ QmitkNavigationToolManagementWidgetControls 0 0 443 781 Form Qt::Horizontal 40 20 Whole Storage: Create New Load Save Qt::Horizontal 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:8pt; font-weight:600;">Storage Name:</span></p></body></html> <none> Qt::Horizontal 40 20 <!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:8pt; font-weight:600;">Tools:</span></p></body></html> Qt::Horizontal 40 20 - 50 + 60 16777215 Add - 50 + 60 16777215 Load <!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:8pt;">Selected:</span></p></body></html> - 50 + 60 16777215 Up - 50 + 60 16777215 Down - 50 + 60 16777215 Delete - 50 + 60 16777215 Edit - 50 + 60 16777215 Save Qt::Vertical 20 40 0 150 Qt::Vertical 20 40 QmitkNavigationToolCreationWidget QWidget
QmitkNavigationToolCreationWidget.h
1
diff --git a/Modules/OpenCVVideoSupport/Commands/mitkBasicCombinationOpenCVImageFilter.cpp b/Modules/OpenCVVideoSupport/Commands/mitkBasicCombinationOpenCVImageFilter.cpp index d5bdd9d7cb..555c6bcb1b 100644 --- a/Modules/OpenCVVideoSupport/Commands/mitkBasicCombinationOpenCVImageFilter.cpp +++ b/Modules/OpenCVVideoSupport/Commands/mitkBasicCombinationOpenCVImageFilter.cpp @@ -1,73 +1,72 @@ /*=================================================================== 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 "mitkBasicCombinationOpenCVImageFilter.h" -#include "cv.h" namespace mitk { bool BasicCombinationOpenCVImageFilter::OnFilterImage( cv::Mat& image ) { int imageId = this->GetCurrentImageId(); // go through the list of all filters for ( auto it = m_FilterList.begin(); it != m_FilterList.end(); ++it ) { // apply current filter and return false if the filter returned false if (! (*it)->FilterImage(image, imageId) ) { return false; } } return true; } void BasicCombinationOpenCVImageFilter::PushFilter( AbstractOpenCVImageFilter::Pointer filter ) { m_FilterList.push_back(filter); } AbstractOpenCVImageFilter::Pointer BasicCombinationOpenCVImageFilter::PopFilter( ) { AbstractOpenCVImageFilter::Pointer lastFilter = m_FilterList.at(m_FilterList.size()-1); m_FilterList.pop_back(); return lastFilter; } bool BasicCombinationOpenCVImageFilter::RemoveFilter( AbstractOpenCVImageFilter::Pointer filter ) { for ( auto it = m_FilterList.begin(); it != m_FilterList.end(); it++ ) { if (*it == filter) { m_FilterList.erase(it); return true; } } return false; } bool BasicCombinationOpenCVImageFilter::GetIsFilterOnTheList( AbstractOpenCVImageFilter::Pointer filter ) { return std::find(m_FilterList.begin(), m_FilterList.end(), filter) != m_FilterList.end(); } bool BasicCombinationOpenCVImageFilter::GetIsEmpty() { return m_FilterList.empty(); } } // namespace mitk diff --git a/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.h b/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.h index 848267132f..a01353983b 100644 --- a/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.h +++ b/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.h @@ -1,119 +1,120 @@ /*=================================================================== 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 QmitkOpenCVVideoControls_h #define QmitkOpenCVVideoControls_h -#include #include #include #include +#include "opencv2/core.hpp" + class QmitkRenderWindow; class QmitkVideoBackground; namespace mitk { class VideoSource; class OpenCVVideoSource; } class QmitkOpenCVVideoControlsPrivate; /// /// \brief Offers widgets to play/pause/stop a video on a certain render window with /// the use of an !initialized! QmitkVideoBackground. The QmitkVideoBackground should /// contain an OpenCVVideoSource is then owned by this widget (and deleted) /// class MITKOPENCVVIDEOSUPPORTUI_EXPORT QmitkOpenCVVideoControls : public QWidget, public mitk::PropertyListReplacedObserver { Q_OBJECT public: /// /// Construct the widget with the given render window and the given preset values /// QmitkOpenCVVideoControls(QmitkVideoBackground* _VideoBackground, QmitkRenderWindow* _RenderWindow , QWidget* parent = nullptr, Qt::WindowFlags f = nullptr); /// /// call reset if video playback is enabled here /// ~QmitkOpenCVVideoControls() override; /// /// sets the render window for this video player /// void SetRenderWindow(QmitkRenderWindow* _RenderWindow); /// /// returns the current render window /// QmitkRenderWindow* GetRenderWindow() const; /// /// sets the qmitkvideobackground for this /// void SetVideoBackground(QmitkVideoBackground* _VideoBackground); /// /// returns the current QmitkVideoBackground /// QmitkVideoBackground* GetVideoBackground() const; /// /// calls FromPropertyList /// void AfterPropertyListReplaced(const std::string& id, mitk::PropertyList* propertyList) override; signals: /// /// When playback is started this informs when a new frame was grabbed /// void NewOpenCVFrameAvailable(const IplImage*); protected slots: void on_UseGrabbingDeviceButton_clicked(bool checked = false); void on_UseVideoFileButton_clicked(bool checked = false); void on_VideoProgressSlider_sliderPressed(); void on_VideoProgressSlider_sliderReleased(); void on_VideoProgressSlider_valueChanged(int value); void on_RepeatVideoButton_clicked(bool checked = false); void on_PlayButton_clicked(bool checked = false); void on_StopButton_clicked(bool checked = false); void Play(); void Stop(); void Reset(); void IsPlaying(bool paused); void QObjectDestroyed(QObject * obj = nullptr); void NewFrameAvailable(mitk::VideoSource* videoSource); void EndOfVideoSourceReached(mitk::VideoSource* videoSource); protected: QmitkVideoBackground* m_VideoBackground; QmitkRenderWindow* m_RenderWindow; mitk::OpenCVVideoSource* m_VideoSource; Ui::QmitkOpenCVVideoControls* m_Controls; bool m_SliderCurrentlyMoved; private: friend class QmitkOpenCVVideoControlsPrivate; QScopedPointer d; }; #endif diff --git a/Modules/OpenCVVideoSupport/mitkOpenCVImageSource.h b/Modules/OpenCVVideoSupport/mitkOpenCVImageSource.h index 25ef0e9d91..eaeb509dae 100644 --- a/Modules/OpenCVVideoSupport/mitkOpenCVImageSource.h +++ b/Modules/OpenCVVideoSupport/mitkOpenCVImageSource.h @@ -1,42 +1,43 @@ /*=================================================================== 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 MITKOPENCVIMAGESOURCE_H #define MITKOPENCVIMAGESOURCE_H -#include #include +#include "opencv2/core.hpp" + namespace mitk { /// /// interface for a class providing opencv images /// class OpenCVImageSource: virtual public itk::Object { public: /// /// provide smart pointer defs /// mitkClassMacroItkParent( OpenCVImageSource, itk::Object ); /// /// \return a image as opencv 2 Mat /// virtual cv::Mat GetImage() = 0; }; } #endif // MITKOPENCVIMAGESOURCE_H diff --git a/Modules/OpenCVVideoSupport/mitkUndistortCameraImage.h b/Modules/OpenCVVideoSupport/mitkUndistortCameraImage.h index e9561d8d62..bb709aad58 100644 --- a/Modules/OpenCVVideoSupport/mitkUndistortCameraImage.h +++ b/Modules/OpenCVVideoSupport/mitkUndistortCameraImage.h @@ -1,128 +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. ===================================================================*/ #ifndef __mitkUndistortCameraImage_h #define __mitkUndistortCameraImage_h #include "mitkCommon.h" #include #include "itkObject.h" #include "mitkPoint.h" -#include "cv.h" + +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" /*! \brief UndistortCameraImage This class is used to undistort camera images. Before any undistortion the class has to be initialized using the functions: SetFocalLength(),SetPrinzipalPoint() and SetCameraDistortion(). After this you can either use UndistortPixel() to undistort a single pixel's coordinates or UndistortImage() to undistort an OpenCV image. A faster version of UndistortImage() is UndistortImageFast(), however, it has to be initialized once with SetUndistortImageFastInfo() instead of the Set... methods before use. \sa QmitkFunctionality \ingroup Functionalities */ namespace mitk { class MITKOPENCVVIDEOSUPPORT_EXPORT UndistortCameraImage : public itk::Object { public: mitkClassMacroItkParent(UndistortCameraImage,itk::Object); itkFactorylessNewMacro(Self) itkCloneMacro(Self) /// Initialization /// /* * Set the camera's intrinsic focal length */ void SetFocalLength(float fc_x, float fc_y) { m_fcX = fc_x; m_fcY = fc_y; } /* * Set the camera's intrinsic principal point */ void SetPrincipalPoint(float cc_x, float cc_y) { m_ccX = cc_x; m_ccY = cc_y; } /* * Set the camera's intrinsic distortion parameters */ void SetCameraDistortion(float kc1, float kc2, float kc3, float kc4) { m_distortionMatrixData[0] = kc1; m_distortionMatrixData[1] = kc2; m_distortionMatrixData[2] = kc3; m_distortionMatrixData[3] = kc4; } /* * Pre-Calculates matrices for the later use of UndistortImageFast() */ void InitRemapUndistortion(int sizeX, int sizeY); /// USAGE /// /* * Undistort a single pixel, returns undistorted pixel */ mitk::Point2D UndistortPixel(const mitk::Point2D& src); /* * Complete undistortion of an OpenCV image, including all calculations */ void UndistortImage(IplImage* src, IplImage* dst); /* * Complete undistortion of an OpenCV image, using pre-calculated matrices from SetUndistortImageFastInfo() * The use of only a source parameter will cause the source to be overwritten. * NOTE: Using the Fast undistortion methods does not require a initialization via the Set... methods. */ void UndistortImageFast( IplImage * src, IplImage* dst = nullptr ); void SetUndistortImageFastInfo(float in_dF1, float in_dF2, float in_dPrincipalX, float in_dPrincipalY, float in_Dist[4], float ImageSizeX, float ImageSizeY); UndistortCameraImage(); ~UndistortCameraImage() override; protected: // principal point and focal length parameters float m_ccX, m_ccY, m_fcX, m_fcY; // undistortion parameters float m_distortionMatrixData[4]; // intrinsic camera parameters float m_intrinsicMatrixData[9]; // precalculated matrices for fast image undistortion with UndistortImageFast() CvMat * m_mapX, * m_mapY; // intrinsic and undistortion camera matrices CvMat m_intrinsicMatrix, m_distortionMatrix; // temp image IplImage * m_tempImage; CvMat *m_DistortionCoeffs; CvMat *m_CameraMatrix; }; } #endif diff --git a/Modules/OpenCVVideoSupport/mitkVideoInputSource.h b/Modules/OpenCVVideoSupport/mitkVideoInputSource.h index 3fc2186dcb..7ec84293fb 100644 --- a/Modules/OpenCVVideoSupport/mitkVideoInputSource.h +++ b/Modules/OpenCVVideoSupport/mitkVideoInputSource.h @@ -1,78 +1,77 @@ /*=================================================================== 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_VideoInput_Source_h_ #define _mitk_VideoInput_Source_h_ #include "mitkConfig.h" #include "mitkOpenCVVideoSource.h" #include "mitkUndistortCameraImage.h" #include -#include "cv.h" // open CV class videoInput; namespace mitk { class MITKOPENCVVIDEOSUPPORT_EXPORT VideoInputSource : public OpenCVVideoSource { public: mitkClassMacro( VideoInputSource, OpenCVVideoSource ); itkFactorylessNewMacro(Self) itkCloneMacro(Self) ////##Documentation ////## @brief All functions behave like OpenCVVideoSource to the outside. //void GetCurrentFrameAsOpenCVImage(IplImage * image); void FetchFrame(); ////##Documentation ////## @brief returns a pointer to the image data array for opengl rendering. //unsigned char * GetVideoTexture(); void StartCapturing(); void StopCapturing(); void SetVideoCameraInput(int cameraindex, bool useCVCAMLib); void SetVideoFileInput(const char * filename, bool repeatVideo, bool useCVCAMLib); itkGetConstMacro(ShowSettingsWindow, bool); itkSetMacro(ShowSettingsWindow, bool); itkGetMacro(VideoInput, bool); protected: VideoInputSource(); virtual ~VideoInputSource(); videoInput* m_VideoInput; int m_DeviceNumber; int m_CaptureSize; // current Video image unsigned char* m_CurrentVideoTexture; /// /// Show vendor specific settings window? /// bool m_ShowSettingsWindow; }; } #endif // Header diff --git a/Modules/ToFProcessing/mitkToFCompositeFilter.cpp b/Modules/ToFProcessing/mitkToFCompositeFilter.cpp index c336ba8c3a..94a632b937 100644 --- a/Modules/ToFProcessing/mitkToFCompositeFilter.cpp +++ b/Modules/ToFProcessing/mitkToFCompositeFilter.cpp @@ -1,400 +1,402 @@ /*=================================================================== 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 "mitkImageReadAccessor.h" #include +#include "opencv2/imgproc.hpp" + mitk::ToFCompositeFilter::ToFCompositeFilter() : m_SegmentationMask(nullptr), m_ImageWidth(0), m_ImageHeight(0), m_ImageSize(0), m_IplDistanceImage(nullptr), m_IplOutputImage(nullptr), m_ItkInputImage(nullptr), m_ApplyTemporalMedianFilter(false), m_ApplyAverageFilter(false), m_ApplyMedianFilter(false), m_ApplyThresholdFilter(false), m_ApplyMaskSegmentation(false), m_ApplyBilateralFilter(false), m_DataBuffer(nullptr), m_DataBufferCurrentIndex(0), m_DataBufferMaxSize(0), m_TemporalMedianFilterNumOfFrames(10), m_ThresholdFilterMin(1), m_ThresholdFilterMax(7000), m_BilateralFilterDomainSigma(2), m_BilateralFilterRangeSigma(60), m_BilateralFilterKernelRadius(0) { } mitk::ToFCompositeFilter::~ToFCompositeFilter() { cvReleaseImage(&(this->m_IplDistanceImage)); cvReleaseImage(&(this->m_IplOutputImage)); if (m_DataBuffer!=nullptr) { delete [] m_DataBuffer; } } void mitk::ToFCompositeFilter::SetInput( const InputImageType* distanceImage ) { this->SetInput(0, distanceImage); } void mitk::ToFCompositeFilter::SetInput( unsigned int idx, const InputImageType* distanceImage ) { if ((distanceImage == nullptr) && (idx == this->GetNumberOfInputs() - 1)) // if the last input is set to nullptr, reduce the number of inputs by one { this->SetNumberOfIndexedInputs(this->GetNumberOfInputs() - 1); } else { if (idx==0) //create IPL image holding distance data { if (!distanceImage->IsEmpty()) { this->m_ImageWidth = distanceImage->GetDimension(0); this->m_ImageHeight = distanceImage->GetDimension(1); this->m_ImageSize = this->m_ImageWidth * this->m_ImageHeight * sizeof(float); if (this->m_IplDistanceImage != nullptr) { cvReleaseImage(&(this->m_IplDistanceImage)); } ImageReadAccessor distImgAcc(distanceImage, distanceImage->GetSliceData(0,0,0)); float* distanceFloatData = (float*) distImgAcc.GetData(); this->m_IplDistanceImage = cvCreateImage(cvSize(this->m_ImageWidth, this->m_ImageHeight), IPL_DEPTH_32F, 1); memcpy(this->m_IplDistanceImage->imageData, (void*)distanceFloatData, this->m_ImageSize); if (this->m_IplOutputImage != nullptr) { cvReleaseImage(&(this->m_IplOutputImage)); } this->m_IplOutputImage = cvCreateImage(cvSize(this->m_ImageWidth, this->m_ImageHeight), IPL_DEPTH_32F, 1); CreateItkImage(this->m_ItkInputImage); } } this->ProcessObject::SetNthInput(idx, const_cast(distanceImage)); // Process object is not const-correct so the const_cast is required here } this->CreateOutputsForAllInputs(); } mitk::Image* mitk::ToFCompositeFilter::GetInput() { return this->GetInput(0); } mitk::Image* mitk::ToFCompositeFilter::GetInput( unsigned int idx ) { if (this->GetNumberOfInputs() < 1) return nullptr; //TODO: geeignete exception werfen return static_cast< mitk::Image*>(this->ProcessObject::GetInput(idx)); } void mitk::ToFCompositeFilter::GenerateData() { // copy input 1...n to output 1...n for (unsigned int idx=0; idxGetNumberOfOutputs(); idx++) { mitk::Image::Pointer outputImage = this->GetOutput(idx); mitk::Image::Pointer inputImage = this->GetInput(idx); if (outputImage.IsNotNull()&&inputImage.IsNotNull()) { ImageReadAccessor inputAcc(inputImage, inputImage->GetSliceData()); outputImage->CopyInformation(inputImage); outputImage->Initialize(inputImage->GetPixelType(),inputImage->GetDimension(),inputImage->GetDimensions()); outputImage->SetSlice(inputAcc.GetData()); } } //mitk::Image::Pointer outputDistanceImage = this->GetOutput(); ImageReadAccessor outputAcc(this->GetOutput(), this->GetOutput()->GetSliceData(0, 0, 0) ); float* outputDistanceFloatData = (float*) outputAcc.GetData(); //mitk::Image::Pointer inputDistanceImage = this->GetInput(); ImageReadAccessor inputAcc(this->GetInput(), this->GetInput()->GetSliceData(0, 0, 0) ); // copy initial distance image to ipl image float* distanceFloatData = (float*)inputAcc.GetData(); memcpy(this->m_IplDistanceImage->imageData, (void*)distanceFloatData, this->m_ImageSize); if (m_ApplyThresholdFilter||m_ApplyMaskSegmentation) { ProcessSegmentation(this->m_IplDistanceImage); } if (this->m_ApplyTemporalMedianFilter||this->m_ApplyAverageFilter) { ProcessStreamedQuickSelectMedianImageFilter(this->m_IplDistanceImage); } if (this->m_ApplyMedianFilter) { ProcessCVMedianFilter(this->m_IplDistanceImage, this->m_IplOutputImage); memcpy( this->m_IplDistanceImage->imageData, this->m_IplOutputImage->imageData, this->m_ImageSize ); } if (this->m_ApplyBilateralFilter) { float* itkFloatData = this->m_ItkInputImage->GetBufferPointer(); memcpy(itkFloatData, this->m_IplDistanceImage->imageData, this->m_ImageSize ); ItkImageType2D::Pointer itkOutputImage = ProcessItkBilateralFilter(this->m_ItkInputImage); memcpy( this->m_IplDistanceImage->imageData, itkOutputImage->GetBufferPointer(), this->m_ImageSize ); //ProcessCVBilateralFilter(this->m_IplDistanceImage, this->m_OutputIplImage, domainSigma, rangeSigma, kernelRadius); //memcpy( distanceFloatData, this->m_OutputIplImage->imageData, distanceImageSize ); } memcpy( outputDistanceFloatData, this->m_IplDistanceImage->imageData, this->m_ImageSize ); } void mitk::ToFCompositeFilter::CreateOutputsForAllInputs() { this->SetNumberOfIndexedOutputs(this->GetNumberOfInputs()); // create outputs for all inputs for (unsigned int idx = 0; idx < this->GetNumberOfIndexedInputs(); ++idx) { if (this->GetOutput(idx) == nullptr) { DataObjectPointer newOutput = this->MakeOutput(idx); this->SetNthOutput(idx, newOutput); } } this->Modified(); } void mitk::ToFCompositeFilter::GenerateOutputInformation() { mitk::Image::ConstPointer input = this->GetInput(); mitk::Image::Pointer output = this->GetOutput(); if (output->IsInitialized()) return; itkDebugMacro(<<"GenerateOutputInformation()"); output->Initialize(input->GetPixelType(), *input->GetTimeGeometry()); output->SetPropertyList(input->GetPropertyList()->Clone()); } void mitk::ToFCompositeFilter::ProcessSegmentation(IplImage* inputIplImage) { char* segmentationMask; if (m_SegmentationMask.IsNotNull()) { ImageReadAccessor segMaskAcc(m_SegmentationMask, m_SegmentationMask->GetSliceData(0,0,0)); segmentationMask = (char*)segMaskAcc.GetData(); } else { segmentationMask = nullptr; } float *f = (float*)inputIplImage->imageData; for(int i=0; im_ImageWidth*this->m_ImageHeight; i++) { if (this->m_ApplyThresholdFilter) { if (f[i]<=m_ThresholdFilterMin) { f[i] = 0.0; } else if (f[i]>=m_ThresholdFilterMax) { f[i] = 0.0; } } if (this->m_ApplyMaskSegmentation) { if (segmentationMask) { if (segmentationMask[i]==0) { f[i] = 0.0; } } } } } ItkImageType2D::Pointer mitk::ToFCompositeFilter::ProcessItkBilateralFilter(ItkImageType2D::Pointer inputItkImage) { ItkImageType2D::Pointer outputItkImage; BilateralFilterType::Pointer bilateralFilter = BilateralFilterType::New(); bilateralFilter->SetInput(inputItkImage); bilateralFilter->SetDomainSigma(m_BilateralFilterDomainSigma); bilateralFilter->SetRangeSigma(m_BilateralFilterRangeSigma); //bilateralFilter->SetRadius(m_BilateralFilterKernelRadius); outputItkImage = bilateralFilter->GetOutput(); outputItkImage->Update(); return outputItkImage; } void mitk::ToFCompositeFilter::ProcessCVBilateralFilter(IplImage* inputIplImage, IplImage* outputIplImage) { int diameter = m_BilateralFilterKernelRadius; double sigmaColor = m_BilateralFilterRangeSigma; double sigmaSpace = m_BilateralFilterDomainSigma; cvSmooth(inputIplImage, outputIplImage, CV_BILATERAL, diameter, 0, sigmaColor, sigmaSpace); } void mitk::ToFCompositeFilter::ProcessCVMedianFilter(IplImage* inputIplImage, IplImage* outputIplImage, int radius) { cvSmooth(inputIplImage, outputIplImage, CV_MEDIAN, radius, 0, 0, 0); } void mitk::ToFCompositeFilter::ProcessStreamedQuickSelectMedianImageFilter(IplImage* inputIplImage) { float* data = (float*)inputIplImage->imageData; int imageSize = inputIplImage->width * inputIplImage->height; float* tmpArray; if (this->m_TemporalMedianFilterNumOfFrames == 0) { return; } if (m_TemporalMedianFilterNumOfFrames != this->m_DataBufferMaxSize) // reset { //delete current buffer for( int i=0; im_DataBufferMaxSize; i++ ) { delete[] this->m_DataBuffer[i]; } if (this->m_DataBuffer != nullptr) { delete[] this->m_DataBuffer; } this->m_DataBufferMaxSize = m_TemporalMedianFilterNumOfFrames; // create new buffer with current size this->m_DataBuffer = new float*[this->m_DataBufferMaxSize]; for(int i=0; im_DataBufferMaxSize; i++) { this->m_DataBuffer[i] = nullptr; } this->m_DataBufferCurrentIndex = 0; } int currentBufferSize = this->m_DataBufferMaxSize; tmpArray = new float[this->m_DataBufferMaxSize]; // copy data to buffer if (this->m_DataBuffer[this->m_DataBufferCurrentIndex] == nullptr) { this->m_DataBuffer[this->m_DataBufferCurrentIndex] = new float[imageSize]; currentBufferSize = this->m_DataBufferCurrentIndex + 1; } for(int j=0; jm_DataBuffer[this->m_DataBufferCurrentIndex][j] = data[j]; } float tmpValue = 0.0f; for(int i=0; im_DataBuffer[j][i]; } data[i] = tmpValue/currentBufferSize; } else if (m_ApplyTemporalMedianFilter) { for(int j=0; jm_DataBuffer[j][i]; } data[i] = quick_select(tmpArray, currentBufferSize); } } this->m_DataBufferCurrentIndex = (this->m_DataBufferCurrentIndex + 1) % this->m_DataBufferMaxSize; delete[] tmpArray; } #define ELEM_SWAP(a,b) { register float t=(a);(a)=(b);(b)=t; } float mitk::ToFCompositeFilter::quick_select(float arr[], int n) { int low = 0; int high = n-1; int median = (low + high)/2; int middle = 0; int ll = 0; int hh = 0; for (;;) { if (high <= low) /* One element only */ return arr[median] ; if (high == low + 1) { /* Two elements only */ if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; return arr[median] ; } /* Find median of low, middle and high items; swap into position low */ middle = (low + high) / 2; if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; /* Swap low item (now in position middle) into position (low+1) */ ELEM_SWAP(arr[middle], arr[low+1]) ; /* Nibble from each end towards middle, swapping items when stuck */ ll = low + 1; hh = high; for (;;) { do ll++; while (arr[low] > arr[ll]) ; do hh--; while (arr[hh] > arr[low]) ; if (hh < ll) break; ELEM_SWAP(arr[ll], arr[hh]) ; } /* Swap middle item (in position low) back into correct position */ ELEM_SWAP(arr[low], arr[hh]) ; /* Re-set active partition */ if (hh <= median) low = ll; if (hh >= median) high = hh - 1; } } #undef ELEM_SWAP void mitk::ToFCompositeFilter::SetTemporalMedianFilterParameter(int tmporalMedianFilterNumOfFrames) { this->m_TemporalMedianFilterNumOfFrames = tmporalMedianFilterNumOfFrames; } void mitk::ToFCompositeFilter::SetThresholdFilterParameter(int min, int max) { if (min > max) { min = max; } this->m_ThresholdFilterMin = min; this->m_ThresholdFilterMax = max; } void mitk::ToFCompositeFilter::SetBilateralFilterParameter(double domainSigma, double rangeSigma, int kernelRadius = 0) { this->m_BilateralFilterDomainSigma = domainSigma; this->m_BilateralFilterRangeSigma = rangeSigma; this->m_BilateralFilterKernelRadius = kernelRadius; } void mitk::ToFCompositeFilter::CreateItkImage(ItkImageType2D::Pointer &itkInputImage) { itkInputImage = ItkImageType2D::New(); ItkImageType2D::IndexType startIndex; startIndex[0] = 0; // first index on X startIndex[1] = 0; // first index on Y ItkImageType2D::SizeType size; size[0] = this->m_ImageWidth; // size along X size[1] = this->m_ImageHeight; // size along Y ItkImageType2D::RegionType region; region.SetSize( size ); region.SetIndex( startIndex ); itkInputImage->SetRegions( region ); itkInputImage->Allocate(); } diff --git a/Modules/ToFProcessing/mitkToFCompositeFilter.h b/Modules/ToFProcessing/mitkToFCompositeFilter.h index e520b96280..cbdc1686cb 100644 --- a/Modules/ToFProcessing/mitkToFCompositeFilter.h +++ b/Modules/ToFProcessing/mitkToFCompositeFilter.h @@ -1,201 +1,201 @@ /*=================================================================== 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 __mitkToFCompositeFilter_h #define __mitkToFCompositeFilter_h #include #include "mitkImageToImageFilter.h" #include -#include #include +#include "opencv2/core.hpp" typedef itk::Image ItkImageType2D; typedef itk::Image ItkImageType3D; typedef itk::BilateralImageFilter BilateralFilterType; namespace mitk { /** * @brief Applies a common filter-pipeline to the first input of this filter * * This class intends to allow quick preprocessing of (ToF) range data. Input 0 of this filter, holding the range image, * is processed using the following image processing filters: * - threshold filter * - mask segmentation * - temporal median filter * - spatial median filter * - bilateral filter * * @ingroup ToFProcessing */ class MITKTOFPROCESSING_EXPORT ToFCompositeFilter : public ImageToImageFilter { public: mitkClassMacro( ToFCompositeFilter , ImageToImageFilter ); itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkSetMacro(SegmentationMask,mitk::Image::Pointer); itkSetMacro(ApplyTemporalMedianFilter,bool); itkGetConstMacro(ApplyTemporalMedianFilter,bool); itkSetMacro(ApplyAverageFilter,bool); itkGetConstMacro(ApplyAverageFilter,bool); itkSetMacro(ApplyMedianFilter,bool); itkGetConstMacro(ApplyMedianFilter,bool); itkSetMacro(ApplyThresholdFilter,bool); itkGetConstMacro(ApplyThresholdFilter,bool); itkSetMacro(ApplyMaskSegmentation,bool); itkGetConstMacro(ApplyMaskSegmentation,bool); itkSetMacro(ApplyBilateralFilter,bool); itkGetConstMacro(ApplyBilateralFilter,bool); using itk::ProcessObject::SetInput; /*! \brief sets the input of this filter \param distanceImage input is the distance image of e.g. a ToF camera */ void SetInput( const InputImageType* distanceImage) override; /*! \brief sets the input of this filter at idx \param idx number of the current input \param distanceImage input is the distance image of e.g. a ToF camera */ void SetInput(unsigned int idx, const InputImageType* distanceImage) override; /*! \brief returns the input of this filter */ Image* GetInput(); /*! \brief returns the input with id idx of this filter */ Image* GetInput(unsigned int idx); /*! \brief Sets the parameter of the temporal median filter \param tmporalMedianFilterNumOfFrames number of frames to be considered for calulating the temporal median */ void SetTemporalMedianFilterParameter(int tmporalMedianFilterNumOfFrames); /*! \brief Sets the parameters (lower, upper threshold) of the threshold filter \param min lower threshold of the threshold filter \param max upper threshold of the threshold filter */ void SetThresholdFilterParameter(int min, int max); /*! \brief Sets the parameters (domain sigma, range sigma, kernel radius) of the bilateral filter \param domainSigma Parameter controlling the smoothing effect of the bilateral filter. Default value: 2 \param rangeSigma Parameter controlling the edge preserving effect of the bilateral filter. Default value: 60 \param kernelRadius radius of the filter mask of the bilateral filter */ void SetBilateralFilterParameter(double domainSigma, double rangeSigma, int kernelRadius); protected: /*! \brief standard constructor */ ToFCompositeFilter(); /*! \brief standard destructor */ ~ToFCompositeFilter() override; void GenerateOutputInformation() override; /*! \brief method generating the output of this filter. Called in the updated process of the pipeline. This method generates the output of the ToFSurfaceSource: The generated surface of the 3d points */ void GenerateData() override; /** * \brief Create an output for each input * * This Method sets the number of outputs to the number of inputs * and creates missing outputs objects. * \warning any additional outputs that exist before the method is called are deleted */ void CreateOutputsForAllInputs(); /*! \brief Applies a mask and/or threshold segmentation to the input image. All pixels with values outside the mask, below the lower threshold (min) and above the upper threshold (max) are assigned the pixel value 0 */ void ProcessSegmentation(IplImage* inputIplImage); /*! \brief Applies the ITK bilateral filter to the input image See http://www.itk.org/Doxygen320/html/classitk_1_1BilateralImageFilter.html for more details. */ ItkImageType2D::Pointer ProcessItkBilateralFilter(ItkImageType2D::Pointer inputItkImage); /*! \brief Applies the OpenCV bilateral filter to the input image. See http://opencv.willowgarage.com/documentation/c/image_filtering.html#smooth for more details */ void ProcessCVBilateralFilter(IplImage* inputIplImage, IplImage* outputIplImage); /*! \brief Applies the OpenCV median filter to the input image. See http://opencv.willowgarage.com/documentation/c/image_filtering.html#smooth for more details */ void ProcessCVMedianFilter(IplImage* inputIplImage, IplImage* outputIplImage, int radius = 3); /*! \brief Performs temporal median filter on an image given the number of frames to be considered */ void ProcessStreamedQuickSelectMedianImageFilter(IplImage* inputIplImage); /*! \brief Quickselect algorithm * This Quickselect routine is based on the algorithm described in * "Numerical recipes in C", Second Edition, * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 * This code by Nicolas Devillard - 1998. Public domain. */ float quick_select(float arr[], int n); /*! \brief Initialize and allocate a 2D ITK image of dimension m_ImageWidth*m_ImageHeight */ void CreateItkImage(ItkImageType2D::Pointer &itkInputImage); mitk::Image::Pointer m_SegmentationMask; ///< mask image used for segmenting the image int m_ImageWidth; ///< x-dimension of the image int m_ImageHeight; ///< y-dimension of the image int m_ImageSize; ///< size of the image in bytes IplImage* m_IplDistanceImage; ///< OpenCV-representation of the distance image IplImage* m_IplOutputImage; ///< OpenCV-representation of the output image ItkImageType2D::Pointer m_ItkInputImage; ///< ITK representation of the distance image bool m_ApplyTemporalMedianFilter; ///< Flag indicating if the temporal median filter is currently active for processing the distance image bool m_ApplyAverageFilter; ///< Flag indicating if the average filter is currently active for processing the distance image bool m_ApplyMedianFilter; ///< Flag indicating if the spatial median filter is currently active for processing the distance image bool m_ApplyThresholdFilter; ///< Flag indicating if the threshold filter is currently active for processing the distance image bool m_ApplyMaskSegmentation; ///< Flag indicating if a mask segmentation is performed bool m_ApplyBilateralFilter; ///< Flag indicating if the bilateral filter is currently active for processing the distance image float** m_DataBuffer; ///< Buffer used for calculating the pixel-wise median over the last n (m_TemporalMedianFilterNumOfFrames) number of frames int m_DataBufferCurrentIndex; ///< Current index in the buffer of the temporal median filter int m_DataBufferMaxSize; ///< Maximal size for the buffer of the temporal median filter (m_DataBuffer) int m_TemporalMedianFilterNumOfFrames; ///< Number of frames to be used in the calculation of the temporal median int m_ThresholdFilterMin; ///< Lower threshold of the threshold filter. Pixels with values below will be assigned value 0 when applying the threshold filter int m_ThresholdFilterMax; ///< Lower threshold of the threshold filter. Pixels with values above will be assigned value 0 when applying the threshold filter double m_BilateralFilterDomainSigma; ///< Parameter of the bilateral filter controlling the smoothing effect of the filter. Default value: 2 double m_BilateralFilterRangeSigma; ///< Parameter of the bilateral filter controlling the edge preserving effect of the filter. Default value: 60 int m_BilateralFilterKernelRadius; ///< Kernel radius of the bilateral filter mask }; } //END mitk namespace #endif diff --git a/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.h b/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.h index 5ef5de41d2..74ef246548 100644 --- a/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.h +++ b/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.h @@ -1,196 +1,195 @@ /*=================================================================== 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 __mitkToFDistanceImageToSurfaceFilter_h #define __mitkToFDistanceImageToSurfaceFilter_h #include #include #include #include #include #include "mitkCameraIntrinsics.h" #include -#include #include #include namespace mitk { /** * @brief Converts a Time-of-Flight (ToF) distance image to a 3D surface using the pinhole camera model for coordinate computation. * The intrinsic parameters of the camera (FocalLength, PrincipalPoint, InterPixelDistance) are set via SetCameraIntrinsics(). The * measured distance for each pixel corresponds to the distance between the object point and the corresponding image point on the * image plane. * * The coordinate conversion follows the model of a common pinhole camera where the origin of the camera * coordinate system (world coordinates) is at the pinhole * \image html ../Modules/ToFProcessing/Documentation/PinholeCameraModel.png * The definition of the image plane and its coordinate systems (pixel and mm) is depicted in the following image * \image html ../Modules/ToFProcessing/Documentation/ImagePlane.png * * @ingroup SurfaceFilters * @ingroup ToFProcessing */ class MITKTOFPROCESSING_EXPORT ToFDistanceImageToSurfaceFilter : public SurfaceSource { public: mitkClassMacro( ToFDistanceImageToSurfaceFilter , SurfaceSource ); itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkSetMacro(CameraIntrinsics, mitk::CameraIntrinsics::Pointer); itkGetMacro(CameraIntrinsics, mitk::CameraIntrinsics::Pointer); itkSetMacro(InterPixelDistance,ToFProcessingCommon::ToFPoint2D); itkGetMacro(InterPixelDistance,ToFProcessingCommon::ToFPoint2D); itkSetMacro(TextureIndex,int); /** * @brief SetTriangulationThreshold Sets a triangulation threshold in order * to remove unusually huge faces from the surface. If this value is set, * the filter will check whether the distance between two neighboring vertices * exceeds the triangulation threshold. If yes, there vertices will not be * triangulated (connected with lines). The vertices will still be added to * the surface, but only as single point (if they have no other neighbors). * @param triangulationThreshold The triangulationThreshold in mm. (not mm*mm!) * @note vtkMath::Distance2BetweenPoints returns the squared distance * between two points and hence we square m_TriangulationThreshold in * order to save run-time. */ void SetTriangulationThreshold( double triangulationThreshold ); itkGetMacro(TriangulationThreshold, double); itkSetMacro(VertexIdList, vtkSmartPointer); itkGetMacro(VertexIdList, vtkSmartPointer); itkSetMacro(GenerateTriangularMesh,bool); itkGetMacro(GenerateTriangularMesh,bool); /** * @brief The ReconstructionModeType enum: Defines the reconstruction mode, if using no interpixeldistances and focal lenghts in pixel units or interpixeldistances and focal length in mm. The Kinect option defines a special reconstruction mode for the kinect. */ enum ReconstructionModeType{ WithOutInterPixelDistance = 1, WithInterPixelDistance = 2, Kinect = 3}; itkSetEnumMacro(ReconstructionMode,ReconstructionModeType); itkGetEnumMacro(ReconstructionMode,ReconstructionModeType); /*! \brief Set scalar image used as texture of the surface. \param iplScalarImage OpenCV image for texturing */ void SetScalarImage(IplImage* iplScalarImage); /*! \brief Set scalar image used as texture of the surface. \return OpenCV image for texturing */ IplImage* GetScalarImage(); /*! \brief Set width of the scalar image used for texturing the surface \param width width (x-dimension) of the texture image */ void SetTextureImageWidth(int width); /*! \brief Set height of the scalar image used for texturing the surface \param height height (y-dimension) of the texture image */ void SetTextureImageHeight(int height); using itk::ProcessObject::SetInput; /*! \brief Sets the input of this filter \param distanceImage input is the distance image of e.g. a ToF camera */ virtual void SetInput( Image* distanceImage); /*! \brief Sets the input of this filter and the intrinsic parameters \param distanceImage input is the distance image of e.g. a ToF camera */ virtual void SetInput( Image* distanceImage, mitk::CameraIntrinsics::Pointer cameraIntrinsics ); /*! \brief Sets the input of this filter at idx \param idx number of the current input \param distanceImage input is the distance image of e.g. a ToF camera */ virtual void SetInput(unsigned int idx, Image* distanceImage); /*! \brief Sets the input of this filter at idx and the intrinsic parameters \param idx number of the current input \param distanceImage input is the distance image of e.g. a ToF camera \param cameraIntrinsics This is the camera model which holds parameters like focal length, pixel size, etc. which are needed for the reconstruction of the surface. */ virtual void SetInput( unsigned int idx, Image* distanceImage, mitk::CameraIntrinsics::Pointer cameraIntrinsics ); /*! \brief Returns the input of this filter */ Image* GetInput(); /*! \brief Returns the input with id idx of this filter */ Image* GetInput(unsigned int idx); protected: /*! \brief Standard constructor */ ToFDistanceImageToSurfaceFilter(); /*! \brief Standard destructor */ ~ToFDistanceImageToSurfaceFilter() override; void GenerateOutputInformation() override; /*! \brief Method generating the output of this filter. Called in the updated process of the pipeline. This method generates the output of the ToFSurfaceSource: The generated surface of the 3d points */ void GenerateData() override; /** * \brief Create an output for each input * * This Method sets the number of outputs to the number of inputs * and creates missing outputs objects. * \warning any additional outputs that exist before the method is called are deleted */ void CreateOutputsForAllInputs(); IplImage* m_IplScalarImage; ///< Scalar image used for surface texturing mitk::CameraIntrinsics::Pointer m_CameraIntrinsics; ///< Specifies the intrinsic parameters int m_TextureImageWidth; ///< Width (x-dimension) of the texture image int m_TextureImageHeight; ///< Height (y-dimension) of the texture image ToFProcessingCommon::ToFPoint2D m_InterPixelDistance; ///< distance in mm between two adjacent pixels on the ToF camera chip int m_TextureIndex; ///< Index of the input used as texture image when no scalar image was set via SetIplScalarImage(). 0 = Distance, 1 = Amplitude, 2 = Intensity bool m_GenerateTriangularMesh; ReconstructionModeType m_ReconstructionMode; ///< The ReconstructionModeType enum: Defines the reconstruction mode, if using no interpixeldistances and focal lenghts in pixel units or interpixeldistances and focal length in mm. The Kinect option defines a special reconstruction mode for the kinect. vtkSmartPointer m_VertexIdList; ///< Make a vtkIdList to save the ID's of the polyData corresponding to the image pixel ID's. This can be accessed after generate data to obtain the mapping. double m_TriangulationThreshold; }; } //END mitk namespace #endif diff --git a/Modules/US/USFilters/mitkUSImageSource.h b/Modules/US/USFilters/mitkUSImageSource.h index b5a224a20d..2866092a67 100644 --- a/Modules/US/USFilters/mitkUSImageSource.h +++ b/Modules/US/USFilters/mitkUSImageSource.h @@ -1,105 +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 MITKUSImageSource_H_HEADER_INCLUDED_ #define MITKUSImageSource_H_HEADER_INCLUDED_ // ITK #include #include // MITK #include #include #include "mitkBasicCombinationOpenCVImageFilter.h" #include "mitkOpenCVToMitkImageFilter.h" #include "mitkImageToOpenCVImageFilter.h" -// OpenCV -#include "cv.h" - namespace mitk { /** * \brief This is an abstract superclass for delivering USImages. * Each subclass must implement the method mitk::USImageSource::GetNextRawImage(). * The public method mitk::USImageSource::GetNextImage() can the be used to * get the next image from the image source. This image will be filtered by * the filter set with mitk::USImageSource::SetImageFilter(). * * \ingroup US */ class MITKUS_EXPORT USImageSource : public itk::Object { public: static const char* IMAGE_PROPERTY_IDENTIFIER; mitkClassMacroItkParent(USImageSource, itk::Object); itkGetMacro(ImageFilter, mitk::BasicCombinationOpenCVImageFilter::Pointer); void PushFilter(AbstractOpenCVImageFilter::Pointer filter); bool RemoveFilter(AbstractOpenCVImageFilter::Pointer filter); bool GetIsFilterInThePipeline(AbstractOpenCVImageFilter::Pointer filter); /** * \brief Retrieves the next frame. This will typically be the next frame * in a file or the last cached file in a device. The image is filtered if * a filter was set by mitk::USImageSource::SetImageFilter(). * * \return pointer to the next USImage (filtered if set) */ std::vector GetNextImage(); protected: USImageSource(); ~USImageSource() override; /** * \brief Set the given OpenCV image matrix to the next image received * from the device or file. * * The standard implementation calls the overloaded function with an * mitk::Image and converts this image to OpenCV then. One should reimplement * this method for a better performance if an image filter is set. */ virtual void GetNextRawImage(std::vector&); /** * \brief Set mitk::Image to the next image received from the device or file. * This method must be implemented in every subclass. */ virtual void GetNextRawImage(std::vector&) = 0; /** * \brief Used to convert from OpenCV Images to MITK Images. */ mitk::OpenCVToMitkImageFilter::Pointer m_OpenCVToMitkFilter; /** * \brief Used to convert from MITK Images to OpenCV Images. */ mitk::ImageToOpenCVImageFilter::Pointer m_MitkToOpenCVFilter; private: /** * \brief Filter is executed during mitk::USImageVideoSource::GetNextImage(). */ BasicCombinationOpenCVImageFilter::Pointer m_ImageFilter; int m_CurrentImageId; itk::FastMutexLock::Pointer m_ImageFilterMutex; }; } // namespace mitk #endif /* MITKUSImageSource_H_HEADER_INCLUDED_ */ diff --git a/Modules/US/USFilters/mitkUSImageVideoSource.cpp b/Modules/US/USFilters/mitkUSImageVideoSource.cpp index 0c5597bffb..7db00a5a14 100644 --- a/Modules/US/USFilters/mitkUSImageVideoSource.cpp +++ b/Modules/US/USFilters/mitkUSImageVideoSource.cpp @@ -1,233 +1,230 @@ /*=================================================================== 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 HEADER #include "mitkUSImageVideoSource.h" #include "mitkImage.h" -//OpenCV HEADER -#include -#include - //Other #include +#include mitk::USImageVideoSource::USImageVideoSource() : m_VideoCapture(new cv::VideoCapture()), m_IsVideoReady(false), m_IsGreyscale(false), m_IsCropped(false), m_ResolutionOverrideWidth(0), m_ResolutionOverrideHeight(0), m_ResolutionOverride(false), m_GrayscaleFilter(mitk::ConvertGrayscaleOpenCVImageFilter::New()), m_CropFilter(mitk::CropOpenCVImageFilter::New()) { } mitk::USImageVideoSource::~USImageVideoSource() { m_VideoCapture->release(); delete m_VideoCapture; } void mitk::USImageVideoSource::SetVideoFileInput(std::string path) { m_VideoCapture->open(path.c_str()); // check if we succeeded if(!m_VideoCapture->isOpened()) { m_IsVideoReady = false; } else { m_IsVideoReady = true; } // if Override is enabled, use it if (m_ResolutionOverride) { m_VideoCapture->set(CV_CAP_PROP_FRAME_WIDTH, this->m_ResolutionOverrideWidth); m_VideoCapture->set(CV_CAP_PROP_FRAME_HEIGHT, this->m_ResolutionOverrideHeight); } } void mitk::USImageVideoSource::SetCameraInput(int deviceID) { m_VideoCapture->open(deviceID); if(!m_VideoCapture->isOpened()) // check if we succeeded m_IsVideoReady = false; else m_IsVideoReady = true; // if Override is enabled, use it if (m_ResolutionOverride) { m_VideoCapture->set(CV_CAP_PROP_FRAME_WIDTH, this->m_ResolutionOverrideWidth); m_VideoCapture->set(CV_CAP_PROP_FRAME_HEIGHT, this->m_ResolutionOverrideHeight); } } void mitk::USImageVideoSource::ReleaseInput() { m_VideoCapture->release(); delete m_VideoCapture; m_VideoCapture = new cv::VideoCapture(); } void mitk::USImageVideoSource::SetColorOutput(bool isColor){ if ( ! isColor && ! m_IsGreyscale ) { this->PushFilter(m_GrayscaleFilter.GetPointer()); } else if ( isColor && m_IsGreyscale ) { this->RemoveFilter(m_GrayscaleFilter.GetPointer()); } m_IsGreyscale = !isColor; } int mitk::USImageVideoSource::GetImageHeight() { if (m_VideoCapture) { return m_VideoCapture->get(CV_CAP_PROP_FRAME_HEIGHT); } else { return 0; } } int mitk::USImageVideoSource::GetImageWidth() { if (m_VideoCapture) { return m_VideoCapture->get(CV_CAP_PROP_FRAME_WIDTH); } else { return 0; } } bool mitk::USImageVideoSource::GetIsReady() { if (!m_VideoCapture) { return false; } return m_VideoCapture->isOpened(); } void mitk::USImageVideoSource::SetRegionOfInterest(int topLeftX, int topLeftY, int bottomRightX, int bottomRightY) { m_CropFilter->SetCropRegion(topLeftX, topLeftY, bottomRightX, bottomRightY); if (! m_IsCropped && ! m_CropFilter->GetIsCropRegionEmpty()) { this->PushFilter(m_CropFilter.GetPointer()); m_IsCropped = true; } } void mitk::USImageVideoSource::SetRegionOfInterest(USImageRoi roi) { this->SetRegionOfInterest(roi.topLeftX, roi.topLeftY, roi.bottomRightX, roi.bottomRightY); } void mitk::USImageVideoSource::SetCropping(USImageCropping cropping) { int width = this->GetImageWidth(); int height = this->GetImageHeight(); this->SetRegionOfInterest(cropping.left, cropping.top, width - cropping.right, height - cropping.bottom); } mitk::USImageVideoSource::USImageCropping mitk::USImageVideoSource::GetCropping() { cv::Rect cropRect = m_CropFilter->GetCropRegion(); USImageCropping cropping; cropping.left = cropRect.x; cropping.top = cropRect.y; if ( cropRect.height == 0 ) { cropping.bottom = 0; } else { cropping.bottom = this->GetImageHeight() - (cropRect.y + cropRect.height); } if ( cropRect.width == 0 ) { cropping.right = 0; } else { cropping.right = this->GetImageWidth() - (cropRect.x + cropRect.width); } return cropping; } mitk::USImageVideoSource::USImageRoi mitk::USImageVideoSource::GetRegionOfInterest() { cv::Rect cropRect = m_CropFilter->GetCropRegion(); return USImageRoi(cropRect.x, cropRect.y, cropRect.x + cropRect.width, cropRect.y + cropRect.height); } void mitk::USImageVideoSource::RemoveRegionOfInterest() { this->RemoveFilter(m_CropFilter.GetPointer()); m_IsCropped = false; } void mitk::USImageVideoSource::GetNextRawImage(std::vector& image ) { // loop video if necessary //Commented out because setting and getting of these properties is not supported. Therefore on Linux //you'll always get some Highgui errors from OpenCV /*if (m_VideoCapture->get(CV_CAP_PROP_POS_FRAMES) == m_VideoCapture->get(CV_CAP_PROP_FRAME_COUNT)) { m_VideoCapture->set(CV_CAP_PROP_POS_FRAMES, 0); }*/ if (image.size() != 1) image.resize(1); // retrieve image *m_VideoCapture >> image[0]; // get a new frame from camera } void mitk::USImageVideoSource::GetNextRawImage(std::vector& image ) { if (image.size() != 1) image.resize(1); std::vector cv_img; this->GetNextRawImage(cv_img); // convert to MITK-Image IplImage ipl_img = cv_img[0]; this->m_OpenCVToMitkFilter->SetOpenCVImage(&ipl_img); this->m_OpenCVToMitkFilter->Update(); // OpenCVToMitkImageFilter returns a standard mitk::image. We then transform it into an USImage image[0] = this->m_OpenCVToMitkFilter->GetOutput(); // clean up cv_img[0].release(); } void mitk::USImageVideoSource::OverrideResolution(int width, int height) { this->m_ResolutionOverrideHeight = height; this->m_ResolutionOverrideWidth = width; if (m_VideoCapture != nullptr) { m_VideoCapture->set(CV_CAP_PROP_FRAME_WIDTH, width); m_VideoCapture->set(CV_CAP_PROP_FRAME_HEIGHT, height); } } diff --git a/Modules/US/USModel/mitkUSDevice.cpp b/Modules/US/USModel/mitkUSDevice.cpp index 029fdada96..8e80410b82 100644 --- a/Modules/US/USModel/mitkUSDevice.cpp +++ b/Modules/US/USModel/mitkUSDevice.cpp @@ -1,670 +1,692 @@ /*=================================================================== 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 "mitkUSDevice.h" #include "mitkImageReadAccessor.h" // US Control Interfaces #include "mitkUSControlInterfaceProbes.h" #include "mitkUSControlInterfaceBMode.h" #include "mitkUSControlInterfaceDoppler.h" // Microservices #include #include #include #include mitk::USDevice::PropertyKeys mitk::USDevice::GetPropertyKeys() { static mitk::USDevice::PropertyKeys propertyKeys; return propertyKeys; } mitk::USDevice::USImageCropArea mitk::USDevice::GetCropArea() { MITK_INFO << "Return Crop Area L:" << m_CropArea.cropLeft << " R:" << m_CropArea.cropRight << " T:" << m_CropArea.cropTop << " B:" << m_CropArea.cropBottom; return m_CropArea; } mitk::USDevice::USDevice(std::string manufacturer, std::string model) : mitk::ImageSource(), m_IsFreezed(false), m_DeviceState(State_NoState), m_NumberOfOutputs(1), m_Manufacturer(manufacturer), m_Name(model), m_SpawnAcquireThread(true), m_MultiThreader(itk::MultiThreader::New()), m_ImageMutex(itk::FastMutexLock::New()), m_ThreadID(-1), m_UnregisteringStarted(false) { USImageCropArea empty; empty.cropBottom = 0; empty.cropTop = 0; empty.cropLeft = 0; empty.cropRight = 0; this->m_CropArea = empty; // set number of outputs this->SetNumberOfIndexedOutputs(m_NumberOfOutputs); // create a new output mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); } mitk::USDevice::USDevice(mitk::USImageMetadata::Pointer metadata) : mitk::ImageSource(), m_IsFreezed(false), m_DeviceState(State_NoState), m_SpawnAcquireThread(true), m_MultiThreader(itk::MultiThreader::New()), m_ImageMutex(itk::FastMutexLock::New()), m_ThreadID(-1), m_UnregisteringStarted(false) { m_Manufacturer = metadata->GetDeviceManufacturer(); m_Name = metadata->GetDeviceModel(); m_Comment = metadata->GetDeviceComment(); USImageCropArea empty; empty.cropBottom = 0; empty.cropTop = 0; empty.cropLeft = 0; empty.cropRight = 0; this->m_CropArea = empty; // set number of outputs this->SetNumberOfIndexedOutputs(1); // create a new output mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); } mitk::USDevice::~USDevice() { if (m_ThreadID >= 0) { m_MultiThreader->TerminateThread(m_ThreadID); } // make sure that the us device is not registered at the micro service // anymore after it is destructed this->UnregisterOnService(); } mitk::USAbstractControlInterface::Pointer mitk::USDevice::GetControlInterfaceCustom() { MITK_INFO << "Custom control interface does not exist for this object."; return nullptr; } mitk::USControlInterfaceBMode::Pointer mitk::USDevice::GetControlInterfaceBMode() { MITK_INFO << "Control interface BMode does not exist for this object."; return nullptr; } mitk::USControlInterfaceProbes::Pointer mitk::USDevice::GetControlInterfaceProbes() { MITK_INFO << "Control interface Probes does not exist for this object."; return nullptr; } mitk::USControlInterfaceDoppler::Pointer mitk::USDevice::GetControlInterfaceDoppler() { MITK_INFO << "Control interface Doppler does not exist for this object."; return nullptr; } void mitk::USDevice::SetManufacturer(std::string manufacturer) { m_Manufacturer = manufacturer; if (m_DeviceState >= State_Initialized) { this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_MANUFACTURER, manufacturer); } } void mitk::USDevice::SetName(std::string name) { m_Name = name; if (m_DeviceState >= State_Initialized) { this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_NAME, name); } } void mitk::USDevice::SetComment(std::string comment) { m_Comment = comment; if (m_DeviceState >= State_Initialized) { this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_COMMENT, comment); } } us::ServiceProperties mitk::USDevice::ConstructServiceProperties() { mitk::USDevice::PropertyKeys propertyKeys = mitk::USDevice::GetPropertyKeys(); us::ServiceProperties props; props[propertyKeys.US_PROPKEY_ISCONNECTED] = this->GetIsConnected() ? "true" : "false"; props[propertyKeys.US_PROPKEY_ISACTIVE] = this->GetIsActive() ? "true" : "false"; props[propertyKeys.US_PROPKEY_LABEL] = this->GetServicePropertyLabel(); // get identifier of selected probe if there is one selected mitk::USControlInterfaceProbes::Pointer probesControls = this->GetControlInterfaceProbes(); if (probesControls.IsNotNull() && probesControls->GetIsActive()) { mitk::USProbe::Pointer probe = probesControls->GetSelectedProbe(); if (probe.IsNotNull()) { props[propertyKeys.US_PROPKEY_PROBES_SELECTED] = probe->GetName(); } } props[propertyKeys.US_PROPKEY_CLASS] = GetDeviceClass(); props[propertyKeys.US_PROPKEY_MANUFACTURER] = m_Manufacturer; props[propertyKeys.US_PROPKEY_NAME] = m_Name; props[propertyKeys.US_PROPKEY_COMMENT] = m_Comment; m_ServiceProperties = props; return props; } void mitk::USDevice::UnregisterOnService() { // unregister on micro service if (m_ServiceRegistration && !m_UnregisteringStarted) { // make sure that unregister is not started a second // time due to a callback during unregister for example m_UnregisteringStarted = true; m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } } bool mitk::USDevice::Initialize() { if (!this->OnInitialization()) { return false; } m_DeviceState = State_Initialized; // Get Context and Module us::ModuleContext* context = us::GetModuleContext(); us::ServiceProperties props = this->ConstructServiceProperties(); m_ServiceRegistration = context->RegisterService(this, props); return true; } bool mitk::USDevice::Connect() { MITK_DEBUG << "mitk::USDevice::Connect() called"; if (this->GetIsConnected()) { MITK_INFO("mitkUSDevice") << "Tried to connect an ultrasound device that " "was already connected. Ignoring call..."; return true; } if (!this->GetIsInitialized()) { MITK_ERROR("mitkUSDevice") << "Cannot connect device if it is not in initialized state."; return false; } // Prepare connection, fail if this fails. if (!this->OnConnection()) { return false; } // Update state m_DeviceState = State_Connected; this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISCONNECTED, true); return true; } void mitk::USDevice::ConnectAsynchron() { this->m_MultiThreader->SpawnThread(this->ConnectThread, this); } bool mitk::USDevice::Disconnect() { if (!GetIsConnected()) { MITK_WARN << "Tried to disconnect an ultrasound device that was not " "connected. Ignoring call..."; return false; } // Prepare connection, fail if this fails. if (!this->OnDisconnection()) return false; // Update state m_DeviceState = State_Initialized; this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISCONNECTED, false); return true; } bool mitk::USDevice::Activate() { if (!this->GetIsConnected()) { MITK_INFO("mitkUSDevice") << "Cannot activate device if it is not in connected state."; return true; } if (OnActivation()) { m_DeviceState = State_Activated; m_FreezeBarrier = itk::ConditionVariable::New(); // spawn thread for aquire images if us device is active if (m_SpawnAcquireThread) { this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); } this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE, true); this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, this->GetServicePropertyLabel()); // initialize the b mode control properties of the micro service mitk::USControlInterfaceBMode::Pointer bmodeControls = this->GetControlInterfaceBMode(); if (bmodeControls.IsNotNull()) { bmodeControls->Initialize(); } } this->ProvideViaOIGTL(); return m_DeviceState == State_Activated; } void mitk::USDevice::ProvideViaOIGTL() { // create a new OpenIGTLink Server if (m_IGTLServer.IsNull()) m_IGTLServer = mitk::IGTLServer::New(true); m_IGTLServer->SetName(this->GetName()); // create a new OpenIGTLink Device source if (m_IGTLMessageProvider.IsNull()) m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); // set the OpenIGTLink server as the source for the device source m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); // register the provider so that it can be configured with the IGTL manager // plugin. This could be hardcoded but now I already have the fancy plugin. m_IGTLMessageProvider->RegisterAsMicroservice(); m_ImageToIGTLMsgFilter = mitk::ImageToIGTLMessageFilter::New(); m_ImageToIGTLMsgFilter->ConnectTo(this); // set the name of this filter to identify it easier m_ImageToIGTLMsgFilter->SetName(this->GetName()); // register this filter as micro service. The message provider looks for // provided IGTLMessageSources, once it found this microservice and someone // requested this data type then the provider will connect with this filter // automatically. m_ImageToIGTLMsgFilter->RegisterAsMicroservice(); } void mitk::USDevice::Deactivate() { if (!this->GetIsActive()) { MITK_WARN("mitkUSDevice") - << "Cannot deactivate a device which is not active."; + << "Cannot deactivate a device which is not activae."; return; } if (!OnDeactivation()) { return; } DisableOIGTL(); m_DeviceState = State_Connected; this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE, false); this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, this->GetServicePropertyLabel()); } void mitk::USDevice::DisableOIGTL() { // TODO: This seems not to be enough cleanup to catch all cases. For example, if the device is disconnected // from the OIGTL GUI, this won't get cleaned up correctly. m_IGTLServer->CloseConnection(); m_IGTLMessageProvider->UnRegisterMicroservice(); m_ImageToIGTLMsgFilter->UnRegisterMicroservice(); } void mitk::USDevice::SetIsFreezed(bool freeze) { if (!this->GetIsActive()) { MITK_WARN("mitkUSDevice") << "Cannot freeze or unfreeze if device is not active."; return; } this->OnFreeze(freeze); if (freeze) { m_IsFreezed = true; } else { m_IsFreezed = false; // wake up the image acquisition thread m_FreezeBarrier->Signal(); } } bool mitk::USDevice::GetIsFreezed() { + /* if (!this->GetIsActive()) { MITK_WARN("mitkUSDevice")("mitkUSTelemedDevice") << "Cannot get freeze state if the hardware interface is not ready. " "Returning false..."; return false; - } + }*/ return m_IsFreezed; } void mitk::USDevice::PushFilter(AbstractOpenCVImageFilter::Pointer filter) { mitk::USImageSource::Pointer imageSource = this->GetUSImageSource(); if (imageSource.IsNull()) { MITK_ERROR << "ImageSource must not be null when pushing a filter."; mitkThrow() << "ImageSource must not be null when pushing a filter."; } imageSource->PushFilter(filter); } void mitk::USDevice::PushFilterIfNotPushedBefore( AbstractOpenCVImageFilter::Pointer filter) { mitk::USImageSource::Pointer imageSource = this->GetUSImageSource(); if (imageSource.IsNull()) { MITK_ERROR << "ImageSource must not be null when pushing a filter."; mitkThrow() << "ImageSource must not be null when pushing a filter."; } if (!imageSource->GetIsFilterInThePipeline(filter)) { imageSource->PushFilter(filter); } } bool mitk::USDevice::RemoveFilter(AbstractOpenCVImageFilter::Pointer filter) { mitk::USImageSource::Pointer imageSource = this->GetUSImageSource(); if (imageSource.IsNull()) { MITK_ERROR << "ImageSource must not be null when pushing a filter."; mitkThrow() << "ImageSource must not be null when removing a filter."; } return imageSource->RemoveFilter(filter); } void mitk::USDevice::UpdateServiceProperty(std::string key, std::string value) { m_ServiceProperties[key] = value; m_ServiceRegistration.SetProperties(m_ServiceProperties); // send event to notify listeners about the changed property m_PropertyChangedMessage(key, value); } void mitk::USDevice::UpdateServiceProperty(std::string key, double value) { std::stringstream stream; stream << value; this->UpdateServiceProperty(key, stream.str()); } void mitk::USDevice::UpdateServiceProperty(std::string key, bool value) { this->UpdateServiceProperty( key, value ? std::string("true") : std::string("false")); } /** mitk::Image* mitk::USDevice::GetOutput() { if (this->GetNumberOfOutputs() < 1) return nullptr; return static_cast(this->ProcessObject::GetPrimaryOutput()); } mitk::Image* mitk::USDevice::GetOutput(unsigned int idx) { if (this->GetNumberOfOutputs() < 1) return nullptr; return static_cast(this->ProcessObject::GetOutput(idx)); } void mitk::USDevice::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::USDevice::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter only has " << this->GetNumberOfOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a nullptr pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a nullptr pointer" ); } // Call Graft on USImage to copy member data output->Graft( graft ); } */ void mitk::USDevice::GrabImage() { std::vector image = this->GetUSImageSource()->GetNextImage(); m_ImageMutex->Lock(); this->SetImageVector(image); m_ImageMutex->Unlock(); } //########### GETTER & SETTER ##################// bool mitk::USDevice::GetIsInitialized() { return m_DeviceState == State_Initialized; } bool mitk::USDevice::GetIsActive() { return m_DeviceState == State_Activated; } bool mitk::USDevice::GetIsConnected() { return m_DeviceState == State_Connected; } std::string mitk::USDevice::GetDeviceManufacturer() { return m_Manufacturer; } std::string mitk::USDevice::GetDeviceModel() { return m_Name; } std::string mitk::USDevice::GetDeviceComment() { return m_Comment; } +void mitk::USDevice::SetSpacing(double xSpacing, double ySpacing) +{ + m_Spacing[0] = xSpacing; + m_Spacing[1] = ySpacing; + m_Spacing[2] = 1; + + + if( m_ImageVector.size() > 0 ) + { + for( size_t index = 0; index < m_ImageVector.size(); ++index ) + { + auto& image = m_ImageVector[index]; + if( image.IsNotNull() && image->IsInitialized() ) + { + image->GetGeometry()->SetSpacing(m_Spacing); + } + } + this->Modified(); + } + MITK_INFO << "Spacing: " << m_Spacing; +} + void mitk::USDevice::GenerateData() { m_ImageMutex->Lock(); for (unsigned int i = 0; i < m_ImageVector.size() && i < this->GetNumberOfIndexedOutputs(); ++i) { auto& image = m_ImageVector[i]; if (image.IsNull() || !image->IsInitialized()) { // skip image } else { mitk::Image::Pointer output = this->GetOutput(i); if (!output->IsInitialized() || output->GetDimension(0) != image->GetDimension(0) || output->GetDimension(1) != image->GetDimension(1) || output->GetDimension(2) != image->GetDimension(2) || output->GetPixelType() != image->GetPixelType()) { output->Initialize(image->GetPixelType(), image->GetDimension(), image->GetDimensions()); } // copy contents of the given image into the member variable mitk::ImageReadAccessor inputReadAccessor(image); output->SetImportVolume(inputReadAccessor.GetData()); - output->SetGeometry(image->GetGeometry()); } - } + } m_ImageMutex->Unlock(); }; std::string mitk::USDevice::GetServicePropertyLabel() { std::string isActive; if (this->GetIsActive()) { isActive = " (Active)"; } else { isActive = " (Inactive)"; } // e.g.: Zonare MyLab5 (Active) return m_Manufacturer + " " + m_Name + isActive; } ITK_THREAD_RETURN_TYPE mitk::USDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct* pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; mitk::USDevice* device = (mitk::USDevice*)pInfo->UserData; while (device->GetIsActive()) { // lock this thread when ultrasound device is freezed if (device->m_IsFreezed) { itk::SimpleMutexLock* mutex = &(device->m_FreezeMutex); mutex->Lock(); if (device->m_FreezeBarrier.IsNotNull()) { device->m_FreezeBarrier->Wait(mutex); } } device->GrabImage(); } return ITK_THREAD_RETURN_VALUE; } ITK_THREAD_RETURN_TYPE mitk::USDevice::ConnectThread(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct* pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; mitk::USDevice* device = (mitk::USDevice*)pInfo->UserData; device->Connect(); return ITK_THREAD_RETURN_VALUE; } void mitk::USDevice::ProbeChanged(std::string probename) { this->UpdateServiceProperty(mitk::USDevice::GetPropertyKeys().US_PROPKEY_PROBES_SELECTED, probename); } void mitk::USDevice::DepthChanged(double depth) { this->UpdateServiceProperty(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH, depth); } diff --git a/Modules/US/USModel/mitkUSDevice.h b/Modules/US/USModel/mitkUSDevice.h index f84656d143..b54f67c583 100644 --- a/Modules/US/USModel/mitkUSDevice.h +++ b/Modules/US/USModel/mitkUSDevice.h @@ -1,479 +1,490 @@ /*=================================================================== 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 MITKUSDevice_H_HEADER_INCLUDED_ #define MITKUSDevice_H_HEADER_INCLUDED_ // STL #include // MitkUS #include "mitkUSProbe.h" #include #include "mitkUSImageSource.h" // MitkIGTL #include "mitkIGTLMessageProvider.h" #include "mitkIGTLServer.h" #include "mitkIGTLDeviceSource.h" #include "mitkImageToIGTLMessageFilter.h" // MITK #include #include #include // ITK #include #include // Microservices #include #include #include // DEPRECATED #include "mitkUSImageMetadata.h" namespace itk { template class SmartPointer; } namespace mitk { class USAbstractControlInterface; class USControlInterfaceBMode; class USControlInterfaceProbes; class USControlInterfaceDoppler; /** * \brief A device holds information about it's model, make and the connected probes. It is the * common super class for all devices and acts as an image source for mitkUSImages. It is the base class * for all US Devices, and every new device should extend it. * * US Devices support output of calibrated images, i.e. images that include a specific geometry. * To achieve this, call SetCalibration, and make sure that the subclass also calls apply * transformation at some point (The USDevice does not automatically apply the transformation to the image) * * Note that USDevices will be removed from micro servive when their * destructor is called. Registering into micro service is done when * mitk::USDevice::Initialize() is called. * * \ingroup US */ class MITKUS_EXPORT USDevice : public mitk::ImageSource { public: enum DeviceStates { State_NoState, State_Initialized, State_Connected, State_Activated }; mitkClassMacro(USDevice, mitk::ImageSource); + itkSetMacro(SpawnAcquireThread, bool); + itkGetMacro(SpawnAcquireThread, bool); struct USImageCropArea { int cropLeft; int cropRight; int cropBottom; int cropTop; }; /** * \brief These constants are used in conjunction with Microservices. * The constants aren't defined as static member attributes to avoid the * "static initialization order fiasco", which would occur when objects of * this class are used in module activators (for restoring stored device, * for example). */ struct PropertyKeys { const std::string US_INTERFACE_NAME; // Common Interface name of all US Devices. Used to refer to this device via Microservices const std::string US_PROPKEY_MANUFACTURER; const std::string US_PROPKEY_NAME; const std::string US_PROPKEY_COMMENT; const std::string US_PROPKEY_LABEL; // Human readable text represntation of this device const std::string US_PROPKEY_ISCONNECTED; // Whether this device is connected or not. const std::string US_PROPKEY_ISACTIVE; // Whether this device is active or not. const std::string US_PROPKEY_CLASS; // Class Name of this Object const std::string US_PROPKEY_PROBES_SELECTED; const std::string US_PROPKEY_BMODE_FREQUENCY; const std::string US_PROPKEY_BMODE_POWER; const std::string US_PROPKEY_BMODE_DEPTH; const std::string US_PROPKEY_BMODE_GAIN; const std::string US_PROPKEY_BMODE_REJECTION; const std::string US_PROPKEY_BMODE_DYNAMIC_RANGE; PropertyKeys() : US_INTERFACE_NAME("org.mitk.services.UltrasoundDevice"), US_PROPKEY_MANUFACTURER(US_INTERFACE_NAME + ".manufacturer"), US_PROPKEY_NAME(US_INTERFACE_NAME + ".name"), US_PROPKEY_COMMENT(US_INTERFACE_NAME + ".comment"), US_PROPKEY_LABEL(US_INTERFACE_NAME + ".label"), US_PROPKEY_ISCONNECTED(US_INTERFACE_NAME + ".isConnected"), US_PROPKEY_ISACTIVE(US_INTERFACE_NAME + ".isActive"), US_PROPKEY_CLASS(US_INTERFACE_NAME + ".class"), US_PROPKEY_PROBES_SELECTED(US_INTERFACE_NAME + ".probes.selected"), US_PROPKEY_BMODE_FREQUENCY(US_INTERFACE_NAME + ".bmode.frequency"), US_PROPKEY_BMODE_POWER(US_INTERFACE_NAME + ".bmode.power"), US_PROPKEY_BMODE_DEPTH(US_INTERFACE_NAME + ".bmode.depth"), US_PROPKEY_BMODE_GAIN(US_INTERFACE_NAME + ".bmode.gain"), US_PROPKEY_BMODE_REJECTION(US_INTERFACE_NAME + ".bmode.rejection"), US_PROPKEY_BMODE_DYNAMIC_RANGE(US_INTERFACE_NAME + ".bmode.dynamicRange") {} }; /** * \brief Event for being notified about changes of the micro service properties. * This event can be used if no micro service context is available. */ mitkNewMessage2Macro(PropertyChanged, const std::string&, const std::string&) /** * \return keys for the microservice properties of ultrasound devices */ static mitk::USDevice::PropertyKeys GetPropertyKeys(); /** * \brief Default getter for the custom control interface. * Has to be implemented in a subclass if a custom control interface is * available. Default implementation returns null. * * \return null pointer */ virtual itk::SmartPointer GetControlInterfaceCustom(); /** * \brief Default getter for the b mode control interface. * Has to be implemented in a subclass if a b mode control interface is * available. Default implementation returns null. * * \return null pointer */ virtual itk::SmartPointer GetControlInterfaceBMode(); /** * \brief Default getter for the probes control interface. * Has to be implemented in a subclass if a probes control interface is * available. Default implementation returns null. * * \return null pointer */ virtual itk::SmartPointer GetControlInterfaceProbes(); /** * \brief Default getter for the doppler control interface. * Has to be implemented in a subclass if a doppler control interface is * available. Default implementation returns null. * * \return null pointer */ virtual itk::SmartPointer GetControlInterfaceDoppler(); /** * \brief Changes device state to mitk::USDevice::State_Initialized. * During initialization the virtual method * mitk::USDevice::OnInitialization will be called. If this method * returns false the initialization process will be canceled. Otherwise * the mitk::USDevice is registered in a micro service. */ bool Initialize(); /** * \brief Connects this device. A connected device is ready to deliver images (i.e. be Activated). A Connected Device can be active. A disconnected Device cannot be active. * Internally calls onConnect and then registers the device with the service. A device usually should * override the OnConnection() method, but never the Connect() method, since this will possibly exclude the device * from normal service management. The exact flow of events is: * 0. Check if the device is already connected. If yes, return true anyway, but don't do anything. * 1. Call OnConnection() Here, a device should establish it's connection with the hardware Afterwards, it should be ready to start transmitting images at any time. * 2. If OnConnection() returns true ("successful"), then the device is registered with the service. * 3. if not, it the method itself returns false or may throw an expection, depeneding on the device implementation. * */ bool Connect(); void ConnectAsynchron(); /** * \brief Works analogously to mitk::USDevice::Connect(). Don't override this Method, but onDisconnection instead. */ bool Disconnect(); /** * \brief Activates this device. * After the activation process, the device will start to produce images. * This Method will fail, if the device is not connected. */ bool Activate(); /** * \brief Deactivates this device. * After the deactivation process, the device will no longer produce * images, but still be connected. */ void Deactivate(); /** * \brief Can toggle if ultrasound image is currently updated or freezed. * * \param freeze true to stop updating the ultrasound image, false to start updating again */ virtual void SetIsFreezed(bool freeze); /** * \return true if device is currently freezed (no image update is done), false otherwise */ virtual bool GetIsFreezed(); void PushFilter(AbstractOpenCVImageFilter::Pointer filter); void PushFilterIfNotPushedBefore(AbstractOpenCVImageFilter::Pointer filter); bool RemoveFilter(AbstractOpenCVImageFilter::Pointer filter); /** * @brief To be called when the used probe changed. Will update the service properties * @param probename of the now used probe */ void ProbeChanged(std::string probename); /** * @brief To be called when the scanning depth of the probe changed. Will update the service properties * @param depth that is now used */ void DepthChanged(double depth); /** * \brief Given property is updated in the device micro service. * This method is mainly for being used by the control interface * superclasses. You do not need to call it by yoursefs in your * concrete control interface classes. */ void UpdateServiceProperty(std::string key, std::string value); void UpdateServiceProperty(std::string key, double value); void UpdateServiceProperty(std::string key, bool value); //########### GETTER & SETTER ##################// /** * \brief Returns the Class of the Device. This Method must be reimplemented by every Inheriting Class. */ virtual std::string GetDeviceClass() = 0; /** * \brief True, if the device object is created and initialized, false otherwise. */ bool GetIsInitialized(); /** * \brief True, if the device is currently generating image data, false otherwise. */ bool GetIsActive(); /** * \brief True, if the device is currently ready to start transmitting image data or is already * transmitting image data. A disconnected device cannot be activated. */ bool GetIsConnected(); /* @return Returns the area that will be cropped from the US image. Is disabled / [0,0,0,0] by default. */ mitk::USDevice::USImageCropArea GetCropArea(); + /* @return Returns the size of the m_ImageVector of the ultrasound device.*/ + unsigned int GetSizeOfImageVector(); + /** @return Returns the current image source of this device. */ virtual USImageSource::Pointer GetUSImageSource() = 0; /** \brief Deprecated -> use GetManufacturer() instead */ DEPRECATED(std::string GetDeviceManufacturer()); /** \brief Deprecated -> use GetName() instead */ DEPRECATED(std::string GetDeviceModel()); /** \brief Deprecated -> use GetCommend() instead */ DEPRECATED(std::string GetDeviceComment()); itkGetMacro(Manufacturer, std::string); itkGetMacro(Name, std::string); itkGetMacro(Comment, std::string); void SetManufacturer(std::string manufacturer); void SetName(std::string name); void SetComment(std::string comment); itkGetMacro(DeviceState, DeviceStates) itkGetMacro(ServiceProperties, us::ServiceProperties) void GrabImage(); + virtual void SetSpacing(double xSpacing, double ySpacing); + + protected: + + // Threading-Related + itk::ConditionVariable::Pointer m_FreezeBarrier; + itk::SimpleMutexLock m_FreezeMutex; + itk::MultiThreader::Pointer m_MultiThreader; ///< itk::MultiThreader used for thread handling + itk::FastMutexLock::Pointer m_ImageMutex; ///< mutex for images provided by the image source + int m_ThreadID; ///< ID of the started thread + virtual void SetImageVector(std::vector vec) { if (this->m_ImageVector != vec) { this->m_ImageVector = vec; this->Modified(); } } - itkSetMacro(SpawnAcquireThread, bool); - itkGetMacro(SpawnAcquireThread, bool); static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); static ITK_THREAD_RETURN_TYPE ConnectThread(void* pInfoStruct); std::vector m_ImageVector; //mitk::Image::Pointer m_OutputImage; + // Variables to determine if spacing was calibrated and needs to be applied to the incoming images + mitk::Vector3D m_Spacing; + /** * \brief Registers an OpenIGTLink device as a microservice so that we can send the images of * this device via the network. */ void ProvideViaOIGTL(); /** * \brief Deregisters the microservices for OpenIGTLink. */ void DisableOIGTL(); mitk::IGTLServer::Pointer m_IGTLServer; mitk::IGTLMessageProvider::Pointer m_IGTLMessageProvider; mitk::ImageToIGTLMessageFilter::Pointer m_ImageToIGTLMsgFilter; bool m_IsFreezed; DeviceStates m_DeviceState; /* @brief defines the area that should be cropped from the US image */ USImageCropArea m_CropArea; /** * \brief This Method constructs the service properties which can later be used to * register the object with the Microservices * Return service properties */ us::ServiceProperties ConstructServiceProperties(); /** * \brief Remove this device from the micro service. */ void UnregisterOnService(); /** * \brief Is called during the initialization process. * Override this method in a subclass to handle the actual initialization. * If it returns false, the initialization process will be canceled. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnInitialization() = 0; /** * \brief Is called during the connection process. * Override this method in a subclass to handle the actual connection. * If it returns false, the connection process will be canceled. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnConnection() = 0; /** * \brief Is called during the disconnection process. * Override this method in a subclass to handle the actual disconnection. * If it returns false, the disconnection process will be canceled. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnDisconnection() = 0; /** * \brief Is called during the activation process. * After this method is finished, the device should be generating images. * If it returns false, the activation process will be canceled. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnActivation() = 0; /** * \brief Is called during the deactivation process. * After a call to this method the device should still be connected, * but not producing images anymore. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnDeactivation() = 0; /** * \brief Called when mitk::USDevice::SetIsFreezed() is called. * Subclasses can overwrite this method to do additional actions. Default * implementation does noting. */ virtual void OnFreeze(bool) { } /** * \brief Enforces minimal Metadata to be set. */ USDevice(std::string manufacturer, std::string model); /** * \brief Constructs a device with the given Metadata. Make sure the Metadata contains meaningful content! * \deprecated Use USDevice(std::string manufacturer, std::string model) instead. */ USDevice(mitk::USImageMetadata::Pointer metadata); ~USDevice() override; /** * \brief Grabs the next frame from the Video input. * This method is called internally, whenever Update() is invoked by an Output. */ void GenerateData() override; std::string GetServicePropertyLabel(); unsigned int m_NumberOfOutputs; + /** + * \brief Properties of the device's Microservice. + */ + us::ServiceProperties m_ServiceProperties; + + /** + * \brief The device's ServiceRegistration object that allows to modify it's Microservice registraton details. + */ + us::ServiceRegistration m_ServiceRegistration; + + private: std::string m_Manufacturer; std::string m_Name; std::string m_Comment; bool m_SpawnAcquireThread; - /** - * \brief The device's ServiceRegistration object that allows to modify it's Microservice registraton details. - */ - us::ServiceRegistration m_ServiceRegistration; - - /** - * \brief Properties of the device's Microservice. - */ - us::ServiceProperties m_ServiceProperties; - - // Threading-Related - itk::ConditionVariable::Pointer m_FreezeBarrier; - itk::SimpleMutexLock m_FreezeMutex; - itk::MultiThreader::Pointer m_MultiThreader; ///< itk::MultiThreader used for thread handling - itk::FastMutexLock::Pointer m_ImageMutex; ///< mutex for images provided by the image source - int m_ThreadID; ///< ID of the started thread - bool m_UnregisteringStarted; }; } // namespace mitk // This is the microservice declaration. Do not meddle! MITK_DECLARE_SERVICE_INTERFACE(mitk::USDevice, "org.mitk.services.UltrasoundDevice") #endif // MITKUSDevice_H_HEADER_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSDeviceReaderWriterConstants.h b/Modules/US/USModel/mitkUSDeviceReaderWriterConstants.h new file mode 100644 index 0000000000..5535469911 --- /dev/null +++ b/Modules/US/USModel/mitkUSDeviceReaderWriterConstants.h @@ -0,0 +1,53 @@ +/*=================================================================== + +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 mitkUSDeviceReaderWriterConstants_H_HEADER_INCLUDED_ +#define mitkUSDeviceReaderWriterConstants_H_HEADER_INCLUDED_ + +const static char* TAG_ULTRASOUNDDEVICE = "ULTRASOUNDDEVICE"; +const static char* TAG_GENERALSETTINGS = "GENERALSETTINGS"; +const static char* TAG_PROBES = "PROBES"; +const static char* TAG_PROBE = "PROBE"; +const static char* TAG_DEPTHS = "DEPTHS"; +const static char* TAG_DEPTH = "DEPTH"; +const static char* TAG_SPACING = "SPACING"; +const static char* TAG_CROPPING = "CROPPING"; + +const static char* ATTR_FILEVERS = "filevers"; +const static char* ATTR_TYPE = "type"; +const static char* ATTR_NAME = "name"; +const static char* ATTR_MANUFACTURER = "manufacturer"; +const static char* ATTR_MODEL = "model"; +const static char* ATTR_COMMENT = "comment"; +const static char* ATTR_IMAGESTREAMS = "imagestreams"; +const static char* ATTR_GREYSCALE = "greyscale"; +const static char* ATTR_RESOLUTIONOVERRIDE = "resolutionOverride"; +const static char* ATTR_RESOLUTIONWIDTH = "resolutionWidth"; +const static char* ATTR_RESOLUTIONHEIGHT = "resolutionHeight"; +const static char* ATTR_SOURCEID = "sourceID"; +const static char* ATTR_FILEPATH = "filepath"; +const static char* ATTR_OPENCVPORT = "opencvPort"; +const static char* ATTR_DEPTH = "depth"; +const static char* ATTR_X = "x"; +const static char* ATTR_Y = "y"; +const static char* ATTR_TOP = "top"; +const static char* ATTR_BOTTOM = "bottom"; +const static char* ATTR_LEFT = "left"; +const static char* ATTR_RIGHT = "right"; + + +#endif // mitkUSDeviceReaderWriterConstants_H_HEADER_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSDeviceReaderXML.cpp b/Modules/US/USModel/mitkUSDeviceReaderXML.cpp new file mode 100644 index 0000000000..7e7aed1530 --- /dev/null +++ b/Modules/US/USModel/mitkUSDeviceReaderXML.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. + +===================================================================*/ + +// MITK +#include "mitkUSDeviceReaderWriterConstants.h" +#include "mitkUSDeviceReaderXML.h" +#include +#include + +#include + +// Third Party +#include +#include +#include + +mitk::USDeviceReaderXML::USDeviceReaderXML() : AbstractFileReader( + mitk::IGTMimeTypes::USDEVICEINFORMATIONXML_MIMETYPE(), + "MITK USDevice Reader (XML)"), m_Filename("") +{ + RegisterService(); +} + +mitk::USDeviceReaderXML::~USDeviceReaderXML() +{ +} + +mitk::USDeviceReaderXML::USVideoDeviceConfigData &mitk::USDeviceReaderXML::GetUSVideoDeviceConfigData() +{ + return m_DeviceConfig; +} + +mitk::USDeviceReaderXML::USDeviceReaderXML(const mitk::USDeviceReaderXML& other) : AbstractFileReader(other) +{ +} + +mitk::USDeviceReaderXML* mitk::USDeviceReaderXML::Clone() const +{ + return new USDeviceReaderXML(*this); +} + + + + +std::vector> mitk::USDeviceReaderXML::Read() +{ + MITK_WARN << "This method is not implemented. \ + Please use the method ReadUltrasoundDeviceConfiguration() instead."; + std::vector result; + return result; +} + +bool mitk::USDeviceReaderXML::ReadUltrasoundDeviceConfiguration() +{ + MITK_INFO << "Try to start reading xml device configuration..."; + if (m_Filename == "") + { + MITK_WARN << "Cannot read file - empty filename!"; + return false; + } + + TiXmlDocument document(m_Filename); + if (!document.LoadFile()) + { + MITK_ERROR << "Error when opening and reading file :" << m_Filename; + return false; + } + + TiXmlHandle documentHandle(&document); + TiXmlElement* ultrasoundDeviceTag = documentHandle.FirstChildElement(TAG_ULTRASOUNDDEVICE).ToElement(); + if (ultrasoundDeviceTag == nullptr) + { + MITK_ERROR << "Error parsing the file :" << m_Filename << std::endl << "Wrong xml format structure."; + return false; + } + + //Extract attribute information of the ULTRASOUNDDEVICE-Tag: + this->ExtractAttributeInformationOfUltrasoundDeviceTag(ultrasoundDeviceTag); + + TiXmlElement* generalSettingsTag = documentHandle.FirstChildElement(TAG_ULTRASOUNDDEVICE).FirstChildElement(TAG_GENERALSETTINGS).ToElement(); + if (generalSettingsTag == nullptr) + { + MITK_ERROR << "Error parsing the GENERALSETTINGS-Tag in the file :" << m_Filename; + return false; + } + + //Extract attribute information of the GENERALSETTINGS-Tag: + this->ExtractAttributeInformationOfGeneralSettingsTag(generalSettingsTag); + + TiXmlElement* probesTag = documentHandle.FirstChildElement(TAG_ULTRASOUNDDEVICE).FirstChildElement(TAG_PROBES).ToElement(); + if (probesTag == nullptr) + { + MITK_ERROR << "Error: PROBES-Tag was not found in the file :" << m_Filename << "Therefore, creating default probe."; + //Create default ultrasound probe: + mitk::USProbe::Pointer ultrasoundProbeDefault = mitk::USProbe::New(); + ultrasoundProbeDefault->SetName("default"); + ultrasoundProbeDefault->SetDepth(0); + m_DeviceConfig.probes.push_back(ultrasoundProbeDefault); + return true; + } + + //Extract all saved and configured probes of the USDevice: + for (TiXmlElement* probeTag = probesTag->FirstChildElement(TAG_PROBE); + probeTag != nullptr; probeTag = probeTag->NextSiblingElement()) + { + this->ExtractProbe(probeTag); + } + return true; +} + +void mitk::USDeviceReaderXML::SetFilename(std::string filename) +{ + m_Filename = filename; +} + +void mitk::USDeviceReaderXML::ExtractAttributeInformationOfUltrasoundDeviceTag(TiXmlElement *ultrasoundTag) +{ + ultrasoundTag->QueryDoubleAttribute(ATTR_FILEVERS, &m_DeviceConfig.fileversion); + ultrasoundTag->QueryStringAttribute(ATTR_TYPE, &m_DeviceConfig.deviceType); + ultrasoundTag->QueryStringAttribute(ATTR_NAME, &m_DeviceConfig.deviceName); + ultrasoundTag->QueryStringAttribute(ATTR_MANUFACTURER, &m_DeviceConfig.manufacturer); + ultrasoundTag->QueryStringAttribute(ATTR_MODEL, &m_DeviceConfig.model); + ultrasoundTag->QueryStringAttribute(ATTR_COMMENT, &m_DeviceConfig.comment); + ultrasoundTag->QueryIntAttribute(ATTR_IMAGESTREAMS, &m_DeviceConfig.numberOfImageStreams); +} + +void mitk::USDeviceReaderXML::ExtractAttributeInformationOfGeneralSettingsTag(TiXmlElement *generalSettingsTag) +{ + generalSettingsTag->QueryBoolAttribute(ATTR_GREYSCALE, &m_DeviceConfig.useGreyscale); + generalSettingsTag->QueryBoolAttribute(ATTR_RESOLUTIONOVERRIDE, &m_DeviceConfig.useResolutionOverride); + generalSettingsTag->QueryIntAttribute(ATTR_RESOLUTIONHEIGHT, &m_DeviceConfig.resolutionHeight); + generalSettingsTag->QueryIntAttribute(ATTR_RESOLUTIONWIDTH, &m_DeviceConfig.resolutionWidth); + generalSettingsTag->QueryIntAttribute(ATTR_SOURCEID, &m_DeviceConfig.sourceID); + generalSettingsTag->QueryStringAttribute(ATTR_FILEPATH, &m_DeviceConfig.filepathVideoSource); + generalSettingsTag->QueryIntAttribute(ATTR_OPENCVPORT, &m_DeviceConfig.opencvPort); +} + +void mitk::USDeviceReaderXML::ExtractProbe(TiXmlElement *probeTag) +{ + mitk::USProbe::Pointer ultrasoundProbe = mitk::USProbe::New(); + std::string probeName; + probeTag->QueryStringAttribute(ATTR_NAME, &probeName); + ultrasoundProbe->SetName(probeName); + + TiXmlElement* depthsTag = probeTag->FirstChildElement(TAG_DEPTHS); + if (depthsTag != nullptr) + { + for (TiXmlElement* depthTag = depthsTag->FirstChildElement(TAG_DEPTH); + depthTag != nullptr; depthTag = depthTag->NextSiblingElement()) + { + int depth = 0; + mitk::Vector3D spacing; + spacing[0] = 1; + spacing[1] = 1; + spacing[2] = 1; + + depthTag->QueryIntAttribute(ATTR_DEPTH, &depth); + + TiXmlElement* spacingTag = depthTag->FirstChildElement(TAG_SPACING); + if (spacingTag != nullptr) + { + spacingTag->QueryDoubleAttribute(ATTR_X, &spacing[0]); + spacingTag->QueryDoubleAttribute(ATTR_Y, &spacing[1]); + } + + ultrasoundProbe->SetDepthAndSpacing(depth, spacing); + } + } + else + { + MITK_ERROR << "Error: DEPTHS-Tag was not found in the file :" << m_Filename + << "Therefore, creating default depth [0] and spacing [1,1,1] for the probe."; + ultrasoundProbe->SetDepth(0); + } + + unsigned int croppingTop = 0; + unsigned int croppingBottom = 0; + unsigned int croppingLeft = 0; + unsigned int croppingRight = 0; + + TiXmlElement* croppingTag = probeTag->FirstChildElement(TAG_CROPPING); + if (croppingTag != nullptr) + { + croppingTag->QueryUnsignedAttribute(ATTR_TOP, &croppingTop); + croppingTag->QueryUnsignedAttribute(ATTR_BOTTOM, &croppingBottom); + croppingTag->QueryUnsignedAttribute(ATTR_LEFT, &croppingLeft); + croppingTag->QueryUnsignedAttribute(ATTR_RIGHT, &croppingRight); + } + + ultrasoundProbe->SetProbeCropping(croppingTop, croppingBottom, croppingLeft, croppingRight); + m_DeviceConfig.probes.push_back(ultrasoundProbe); +} diff --git a/Modules/US/USModel/mitkUSDeviceReaderXML.h b/Modules/US/USModel/mitkUSDeviceReaderXML.h new file mode 100644 index 0000000000..2b6c0a4fde --- /dev/null +++ b/Modules/US/USModel/mitkUSDeviceReaderXML.h @@ -0,0 +1,101 @@ +/*=================================================================== + +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 mitkUSDeviceReaderXML_H_HEADER_INCLUDED_ +#define mitkUSDeviceReaderXML_H_HEADER_INCLUDED_ + +#include + +#include +#include + +class TiXmlElement; +class TiXmlNode; + +namespace mitk { + + class MITKUS_EXPORT USDeviceReaderXML : public AbstractFileReader + { + public: + USDeviceReaderXML(); + ~USDeviceReaderXML() override; + + using AbstractFileReader::Read; + std::vector> Read() override; + bool ReadUltrasoundDeviceConfiguration(); + + void SetFilename(std::string filename); + + typedef struct USVideoDeviceConfigData_ + { + double fileversion; + std::string deviceType; + std::string deviceName; + std::string manufacturer; + std::string model; + std::string comment; + int numberOfImageStreams; + + bool useGreyscale; + bool useResolutionOverride; + int resolutionWidth; + int resolutionHeight; + int sourceID; + std::string filepathVideoSource; + int opencvPort; + + std::vector probes; + + USVideoDeviceConfigData_() + : fileversion(0), deviceType("Unknown"), deviceName("Unknown"), + manufacturer("Unknown"), comment(""), numberOfImageStreams(1), + useGreyscale(true), useResolutionOverride(true), + resolutionWidth(640), resolutionHeight(480), sourceID(0), + filepathVideoSource(""), opencvPort(0) + { }; + + }USVideoDeviceConfigData; + + USVideoDeviceConfigData &GetUSVideoDeviceConfigData(); + + protected: + USDeviceReaderXML(const USDeviceReaderXML& other); + mitk::USDeviceReaderXML* Clone() const override; + + /** + * \brief Extracts all stored attribute information of the ULTRASOUNDDEVICE-Tag. + */ + void ExtractAttributeInformationOfUltrasoundDeviceTag(TiXmlElement *element); + + /** + * \brief Extracts all stored attribute information of the GENERALSETTINGS-Tag. + */ + void ExtractAttributeInformationOfGeneralSettingsTag(TiXmlElement *element); + + /** + * \brief Extracts all stored information of a single ultrasound probe. + */ + void ExtractProbe(TiXmlElement *element); + + private: + std::string m_Filename; + USVideoDeviceConfigData m_DeviceConfig; + }; + +} // namespace mitk + +#endif // mitkUSDeviceReaderXML_H_HEADER_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSDeviceWriterXML.cpp b/Modules/US/USModel/mitkUSDeviceWriterXML.cpp new file mode 100644 index 0000000000..3a05ddb3d8 --- /dev/null +++ b/Modules/US/USModel/mitkUSDeviceWriterXML.cpp @@ -0,0 +1,157 @@ +/*=================================================================== + +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 "mitkUSDeviceReaderWriterConstants.h" +#include "mitkUSDeviceWriterXML.h" +#include +#include +#include + +// Third Party +#include +#include +#include +#include + +mitk::USDeviceWriterXML::USDeviceWriterXML() : AbstractFileWriter(USDevice::GetStaticNameOfClass(), + mitk::IGTMimeTypes::USDEVICEINFORMATIONXML_MIMETYPE(), + "MITK USDevice Writer (XML)"), m_Filename("") +{ + RegisterService(); +} + +mitk::USDeviceWriterXML::USDeviceWriterXML(const mitk::USDeviceWriterXML& other) : AbstractFileWriter(other) +{ +} + +mitk::USDeviceWriterXML::~USDeviceWriterXML() +{ +} + +mitk::USDeviceWriterXML* mitk::USDeviceWriterXML::Clone() const +{ + return new USDeviceWriterXML(*this); +} + +void mitk::USDeviceWriterXML::Write() +{ + if (m_Filename == "") + { + MITK_WARN << "Cannot write to file - empty filename!"; + return; + } +} + +void mitk::USDeviceWriterXML::SetFilename(std::string filename) +{ + m_Filename = filename; +} + +bool mitk::USDeviceWriterXML::WriteUltrasoundVideoDeviceConfiguration(mitk::USDeviceReaderXML::USVideoDeviceConfigData & config) +{ + TiXmlDocument document; + TiXmlDeclaration* xmlDeclaration = new TiXmlDeclaration("1.0", "", ""); + document.LinkEndChild(xmlDeclaration); + + + //Create the xml information of the ULTRASOUNDDEVICE-Tag: + TiXmlElement *ultrasoundDeviceTag = new TiXmlElement(TAG_ULTRASOUNDDEVICE); + this->CreateXmlInformationOfUltrasoundDeviceTag(document, ultrasoundDeviceTag, config); + + + //Create the xml information of the GENERALSETTINGS-Tag: + TiXmlElement *generalSettingsTag = new TiXmlElement(TAG_GENERALSETTINGS); + this->CreateXmlInformationOfGeneralSettingsTag(ultrasoundDeviceTag, generalSettingsTag, config); + + //Create the xml information of the PROBES-Tag: + this->CreateXmlInformationOfProbesTag(ultrasoundDeviceTag, config); + + return document.SaveFile(m_Filename); +} + +void mitk::USDeviceWriterXML::CreateXmlInformationOfUltrasoundDeviceTag( + TiXmlDocument &document, TiXmlElement * ultrasoundDeviceTag, + mitk::USDeviceReaderXML::USVideoDeviceConfigData &config) +{ + ultrasoundDeviceTag->SetAttribute(ATTR_FILEVERS, config.fileversion); + ultrasoundDeviceTag->SetAttribute(ATTR_TYPE, config.deviceType); + ultrasoundDeviceTag->SetAttribute(ATTR_NAME, config.deviceName); + ultrasoundDeviceTag->SetAttribute(ATTR_MANUFACTURER, config.manufacturer); + ultrasoundDeviceTag->SetAttribute(ATTR_MODEL, config.model); + ultrasoundDeviceTag->SetAttribute(ATTR_COMMENT, config.comment); + ultrasoundDeviceTag->SetAttribute(ATTR_IMAGESTREAMS, config.numberOfImageStreams); + + document.LinkEndChild(ultrasoundDeviceTag); +} + +void mitk::USDeviceWriterXML::CreateXmlInformationOfGeneralSettingsTag(TiXmlElement *parentTag, TiXmlElement *generalSettingsTag, mitk::USDeviceReaderXML::USVideoDeviceConfigData & config) +{ + std::string value = config.useGreyscale ? "true" : "false"; + generalSettingsTag->SetAttribute(ATTR_GREYSCALE, value); + value = config.useResolutionOverride ? "true" : "false"; + generalSettingsTag->SetAttribute(ATTR_RESOLUTIONOVERRIDE, value); + generalSettingsTag->SetAttribute(ATTR_RESOLUTIONWIDTH, config.resolutionWidth); + generalSettingsTag->SetAttribute(ATTR_RESOLUTIONHEIGHT, config.resolutionHeight); + + generalSettingsTag->SetAttribute(ATTR_SOURCEID, config.sourceID); + generalSettingsTag->SetAttribute(ATTR_FILEPATH, config.filepathVideoSource); + generalSettingsTag->SetAttribute(ATTR_OPENCVPORT, config.opencvPort); + + parentTag->LinkEndChild(generalSettingsTag); +} + +void mitk::USDeviceWriterXML::CreateXmlInformationOfProbesTag(TiXmlElement * parentTag, mitk::USDeviceReaderXML::USVideoDeviceConfigData & config) +{ + if (config.probes.size() != 0) + { + TiXmlElement *probesTag = new TiXmlElement(TAG_PROBES); + parentTag->LinkEndChild(probesTag); + + for (size_t index = 0; index < config.probes.size(); ++index) + { + TiXmlElement *probeTag = new TiXmlElement(TAG_PROBE); + probesTag->LinkEndChild(probeTag); + + mitk::USProbe::Pointer probe = config.probes.at(index); + probeTag->SetAttribute(ATTR_NAME, probe->GetName()); + std::map depthsAndSpacing = probe->GetDepthsAndSpacing(); + if (depthsAndSpacing.size() != 0) + { + TiXmlElement *depthsTag = new TiXmlElement(TAG_DEPTHS); + probeTag->LinkEndChild(depthsTag); + for (std::map::iterator it = depthsAndSpacing.begin(); it != depthsAndSpacing.end(); it++) + { + TiXmlElement *depthTag = new TiXmlElement(TAG_DEPTH); + depthTag->SetAttribute(ATTR_DEPTH, it->first); + depthsTag->LinkEndChild(depthTag); + + TiXmlElement *spacingTag = new TiXmlElement(TAG_SPACING); + spacingTag->SetDoubleAttribute(ATTR_X, it->second[0], 6); + spacingTag->SetDoubleAttribute(ATTR_Y, it->second[1], 6); + depthTag->LinkEndChild(spacingTag); + } + + TiXmlElement *croppingTag = new TiXmlElement(TAG_CROPPING); + probeTag->LinkEndChild(croppingTag); + croppingTag->SetAttribute(ATTR_TOP, probe->GetProbeCropping().top); + croppingTag->SetAttribute(ATTR_BOTTOM, probe->GetProbeCropping().bottom); + croppingTag->SetAttribute(ATTR_LEFT, probe->GetProbeCropping().left); + croppingTag->SetAttribute(ATTR_RIGHT, probe->GetProbeCropping().right); + } + } + } +} diff --git a/Modules/US/USModel/mitkUSDeviceWriterXML.h b/Modules/US/USModel/mitkUSDeviceWriterXML.h new file mode 100644 index 0000000000..027733c578 --- /dev/null +++ b/Modules/US/USModel/mitkUSDeviceWriterXML.h @@ -0,0 +1,92 @@ +/*=================================================================== + +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 mitkUSDeviceWriterXML_H_Header_INCLUDED_ +#define mitkUSDeviceWriterXML_H_Header_INCLUDED_ + +#include + +#include +#include + +class TiXmlDocument; +class TiXmlElement; + +namespace mitk { + class MITKUS_EXPORT USDeviceWriterXML : public AbstractFileWriter + { + public: + + USDeviceWriterXML(); + ~USDeviceWriterXML() override; + + using AbstractFileWriter::Write; + void Write() override; + + /** + * \brief Sets the filename of the ultrasound device configuration file which should be created. + */ + void SetFilename(std::string filename); + + /** + * \brief Writes the configuration settings of an ultrasound device to a xml-file. + * \param config The struct containing all information of the ultrasound device. + */ + bool WriteUltrasoundVideoDeviceConfiguration(mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + + protected: + USDeviceWriterXML(const USDeviceWriterXML& other); + mitk::USDeviceWriterXML* Clone() const override; + + /** + * \brief Creates the xml ULTRASOUNDDEVICE-Tag entry of the ultrasound video device configuration file. + * \param document A reference to the xml document. + * \param ultrasoundDeviceTag The ULTRASOUNDDEVICETAG which should be created. + * \param config The struct containing all information of the ultrasound device. + */ + void CreateXmlInformationOfUltrasoundDeviceTag( TiXmlDocument &document, + TiXmlElement *ultrasoundDeviceTag, + mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + + /** + * \brief Creates the xml GENERALSETTINGS-Tag entry of the ultrasound video device configuration file. + * \param parentTag The xml parent tag of the GENERALSETTINGS-Tag. This is the ULTRASOUNDDEVICE-Tag. + * \param generalSettingsTag The GENERALSETTINGS-Tag which should be created. + * \param config The struct containing all information of the ultrasound device. + */ + void CreateXmlInformationOfGeneralSettingsTag( TiXmlElement *parentTag, + TiXmlElement *generalSettingsTag, + mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + + /** + * \brief Creates the xml PROBES-Tag entry of the ultrasound video device configuration file. All information + * of all configured probes is extracted and then stored in the xml file. + * \param parentTag The xml parent tag of the GENERALSETTINGS-Tag. This is the ULTRASOUNDDEVICE-Tag. + * \param config The struct containing all information of the ultrasound device. + */ + void CreateXmlInformationOfProbesTag( TiXmlElement *parentTag, + mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + private: + /** + * \brief The filename of the ultrasound device configuration file which should be created. + */ + std::string m_Filename; + + + }; +} + +#endif // mitkUSDeviceWriterXML_H_Header_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSProbe.cpp b/Modules/US/USModel/mitkUSProbe.cpp index d1d0f7abe5..fd8fef5ac7 100644 --- a/Modules/US/USModel/mitkUSProbe.cpp +++ b/Modules/US/USModel/mitkUSProbe.cpp @@ -1,88 +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 "mitkUSProbe.h" #include -mitk::USProbe::USProbe() : itk::Object() +mitk::USProbe::USProbe() : itk::Object(), m_CurrentDepth(0) { } mitk::USProbe::USProbe(std::string identifier) - : m_Name(identifier) + : m_Name(identifier), m_CurrentDepth(0) { } mitk::USProbe::~USProbe() { } +void mitk::USProbe::SetProbeCropping(unsigned int top, unsigned int bottom, unsigned int left, unsigned int right) +{ + m_Cropping.top = top; + m_Cropping.bottom = bottom; + m_Cropping.left = left; + m_Cropping.right = right; +} + +mitk::USProbe::USProbeCropping mitk::USProbe::GetProbeCropping() +{ + return m_Cropping; +} + bool mitk::USProbe::IsEqualToProbe(mitk::USProbe::Pointer probe) { if (m_Name.compare(probe->GetName()) == 0) return true; else return false; } void mitk::USProbe::SetDepthAndSpacing(int depth, mitk::Vector3D spacing) { m_DepthsAndSpacings.insert(std::pair(depth, spacing)); } std::map mitk::USProbe::GetDepthsAndSpacing() { return m_DepthsAndSpacings; } void mitk::USProbe::SetDepth(int depth) { mitk::Vector3D defaultSpacing; defaultSpacing[0] = 1; defaultSpacing[1] = 1; - defaultSpacing[2] = 0; + defaultSpacing[2] = 1; m_DepthsAndSpacings.insert(std::pair(depth, defaultSpacing)); } void mitk::USProbe::RemoveDepth(int depthToRemove) { m_DepthsAndSpacings.erase(depthToRemove); } void mitk::USProbe::SetSpacingForGivenDepth(int givenDepth, Vector3D spacing) { m_DepthsAndSpacings[givenDepth][0] = spacing[0]; m_DepthsAndSpacings[givenDepth][1] = spacing[1]; m_DepthsAndSpacings[givenDepth][2] = spacing[2]; } mitk::Vector3D mitk::USProbe::GetSpacingForGivenDepth(int givenDepth) { mitk::Vector3D spacing; std::map::iterator it = m_DepthsAndSpacings.find(givenDepth); if (it != m_DepthsAndSpacings.end()) //check if given depth really exists { spacing[0] = it->second[0]; spacing[1] = it->second[1]; spacing[2] = it->second[2]; } else - { //spacing does not exist, so set default spacing (1,1,0) + { //spacing does not exist, so set default spacing (1,1,1) spacing[0] = 1; spacing[1] = 1; - spacing[2] = 0; + spacing[2] = 1; } return spacing; } + +bool mitk::USProbe::IsDepthAndSpacingEmpty() +{ + if( m_DepthsAndSpacings.size() == 0 ) + { + return true; + } + + return false; +} diff --git a/Modules/US/USModel/mitkUSProbe.h b/Modules/US/USModel/mitkUSProbe.h index 8544e93d84..2ca2f931ed 100644 --- a/Modules/US/USModel/mitkUSProbe.h +++ b/Modules/US/USModel/mitkUSProbe.h @@ -1,96 +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. ===================================================================*/ #ifndef MITKUSProbe_H_HEADER_INCLUDED_ #define MITKUSProbe_H_HEADER_INCLUDED_ #include #include #include #include #include namespace mitk { /**Documentation * \brief Right now, the US Probe is only a fancy name for a string. Later, it could handle probe specific parameters * like the current frequency etc. It is able to compare itself to other probes for device managment though. * * \ingroup US */ //Be sure to check the isEqualTo() method if you expand this class to see if it needs work! class MITKUS_EXPORT USProbe : public itk::Object { public: mitkClassMacroItkParent(USProbe, itk::Object); itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkNewMacro1Param(Self, std::string); + /** + * \brief Struct to define a probe specific ultrasound image cropping. + */ + typedef struct USProbeCropping_ + { + unsigned int top; + unsigned int bottom; + unsigned int left; + unsigned int right; + + USProbeCropping_() + : top(0), bottom(0), left(0), right(0) { }; + + USProbeCropping_(unsigned int top, unsigned int bottom, unsigned int left, unsigned int right) + : top(top), bottom(bottom), left(left), right(right) { }; + }USProbeCropping; + + /** + * \brief Sets the probe cropping. + */ + void SetProbeCropping(unsigned int top, unsigned int bottom, unsigned int left, unsigned int right); + USProbeCropping GetProbeCropping(); + /** * \brief Compares this probe to another probe and returns true if they are equal in terms of name AND NAME ONLY * be sure to sufficiently extend this method along with further capabilities probes. */ bool IsEqualToProbe(mitk::USProbe::Pointer probe); /** * \brief Sets a scanning depth of the probe and the associated spacing */ void SetDepthAndSpacing(int depth, Vector3D spacing); /** * \brief Gets all scanning depths and the associates spacings of the probe as an std::map with depth as key (represented by an int) and *spacing as value (represented by a Vector3D) */ std::map GetDepthsAndSpacing(); /** - * \brief Sets a scanning depth of the probe with the default spacing (1,1,0). Exact spacing needs to be calibrated. + * \brief Sets a scanning depth of the probe with the default spacing (1,1,1). Exact spacing needs to be calibrated. */ void SetDepth(int depth); /** * \brief Removes the given depth of the probe, if it exists */ void RemoveDepth(int depthToRemove); /** * \ brief Sets the spacing associated to the given depth of the probe. Spacing needs to be calibrated. */ void SetSpacingForGivenDepth(int givenDepth, Vector3D spacing); /** * \brief Returns the spacing that is associated to the given depth of the probe. - *If spacing was not calibrated or if depth does not exist for this probe the default spacing (1,1,0) is returned. + *If spacing was not calibrated or if depth does not exist for this probe the default spacing (1,1,1) is returned. */ Vector3D GetSpacingForGivenDepth(int givenDepth); + /** + * \brief Checks, whether the std::map m_DepthAndSpacings contains at least one depth element or not. + * \return True, if the the std::map m_DepthAndSpacings does not contain at least one depth element, else false. + */ + bool IsDepthAndSpacingEmpty(); + //## getter and setter ## itkGetMacro(Name, std::string); itkSetMacro(Name, std::string); + itkGetMacro(CurrentDepth, double); + itkSetMacro(CurrentDepth, double); protected: USProbe(); USProbe(std::string identifier); ~USProbe() override; std::string m_Name; + double m_CurrentDepth; // Map containing the depths and the associated spacings as an std::vector with depth as key and spacing as value std::map m_DepthsAndSpacings; + + USProbeCropping m_Cropping; }; } // namespace mitk #endif diff --git a/Modules/US/USModel/mitkUSVideoDevice.cpp b/Modules/US/USModel/mitkUSVideoDevice.cpp index 5c42355452..6d216e8296 100644 --- a/Modules/US/USModel/mitkUSVideoDevice.cpp +++ b/Modules/US/USModel/mitkUSVideoDevice.cpp @@ -1,195 +1,258 @@ /*=================================================================== 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 "mitkUSVideoDevice.h" #include "mitkUSVideoDeviceCustomControls.h" mitk::USVideoDevice::USVideoDevice(int videoDeviceNumber, std::string manufacturer, std::string model) : mitk::USDevice(manufacturer, model) { Init(); m_SourceIsFile = false; m_DeviceID = videoDeviceNumber; m_FilePath = ""; } mitk::USVideoDevice::USVideoDevice(std::string videoFilePath, std::string manufacturer, std::string model) : mitk::USDevice(manufacturer, model) { Init(); m_SourceIsFile = true; m_FilePath = videoFilePath; } mitk::USVideoDevice::USVideoDevice(int videoDeviceNumber, mitk::USImageMetadata::Pointer metadata) : mitk::USDevice(metadata) { Init(); m_SourceIsFile = false; m_DeviceID = videoDeviceNumber; m_FilePath = ""; } mitk::USVideoDevice::USVideoDevice(std::string videoFilePath, mitk::USImageMetadata::Pointer metadata) : mitk::USDevice(metadata) { Init(); m_SourceIsFile = true; m_FilePath = videoFilePath; } mitk::USVideoDevice::~USVideoDevice() { //m_Source->UnRegister(); m_Source = nullptr; } void mitk::USVideoDevice::Init() { m_Source = mitk::USImageVideoSource::New(); m_ControlInterfaceCustom = mitk::USVideoDeviceCustomControls::New(this); //this->SetNumberOfInputs(1); this->SetNumberOfIndexedOutputs(1); // mitk::USImage::Pointer output = mitk::USImage::New(); // output->Initialize(); this->SetNthOutput(0, this->MakeOutput(0)); } std::string mitk::USVideoDevice::GetDeviceClass() { return mitk::USVideoDevice::GetDeviceClassStatic(); } std::string mitk::USVideoDevice::GetDeviceClassStatic() { return "org.mitk.modules.us.USVideoDevice"; } mitk::USAbstractControlInterface::Pointer mitk::USVideoDevice::GetControlInterfaceCustom() { return m_ControlInterfaceCustom.GetPointer(); } bool mitk::USVideoDevice::OnInitialization() { // nothing to do at initialization of video device return true; } bool mitk::USVideoDevice::OnConnection() { if (m_SourceIsFile){ m_Source->SetVideoFileInput(m_FilePath); } else { m_Source->SetCameraInput(m_DeviceID); } //SetSourceCropArea(); return true; } bool mitk::USVideoDevice::OnDisconnection() { if (m_DeviceState == State_Activated) this->Deactivate(); m_Source->ReleaseInput(); return true; } bool mitk::USVideoDevice::OnActivation() { // make sure that video device is ready before aquiring images if (!m_Source->GetIsReady()) { MITK_WARN("mitkUSDevice")("mitkUSVideoDevice") << "Could not activate us video device. Check if video grabber is configured correctly."; return false; } MITK_INFO << "Activated UsVideoDevice!"; return true; } bool mitk::USVideoDevice::OnDeactivation() { // happens automatically when m_Active is set to false return true; } +void mitk::USVideoDevice::GenerateData() +{ + Superclass::GenerateData(); + + if( m_ImageVector.size() == 0 || this->GetNumberOfIndexedOutputs() == 0 ) + { + return; + } + + m_ImageMutex->Lock(); + auto& image = m_ImageVector[0]; + if( image.IsNotNull() && image->IsInitialized() && m_CurrentProbe.IsNotNull() ) + { + //MITK_INFO << "Spacing CurrentProbe: " << m_CurrentProbe->GetSpacingForGivenDepth(m_CurrentProbe->GetCurrentDepth()); + image->GetGeometry()->SetSpacing(m_CurrentProbe->GetSpacingForGivenDepth(m_CurrentProbe->GetCurrentDepth())); + this->GetOutput(0)->SetGeometry(image->GetGeometry()); + } + m_ImageMutex->Unlock(); +} + void mitk::USVideoDevice::UnregisterOnService() { if (m_DeviceState == State_Activated) { this->Deactivate(); } if (m_DeviceState == State_Connected) { this->Disconnect(); } mitk::USDevice::UnregisterOnService(); } mitk::USImageSource::Pointer mitk::USVideoDevice::GetUSImageSource() { return m_Source.GetPointer(); } std::vector mitk::USVideoDevice::GetAllProbes() { if (m_Probes.empty()) { MITK_INFO << "No probes exist for this USVideDevice. Empty vector is returned"; } return m_Probes; } +void mitk::USVideoDevice::DeleteAllProbes() +{ + m_Probes.clear(); +} + mitk::USProbe::Pointer mitk::USVideoDevice::GetCurrentProbe() { if (m_CurrentProbe.IsNotNull()) { return m_CurrentProbe; } else { return nullptr; } } mitk::USProbe::Pointer mitk::USVideoDevice::GetProbeByName(std::string name) { for (std::vector::iterator it = m_Probes.begin(); it != m_Probes.end(); it++) { if (name.compare((*it)->GetName()) == 0) return (*it); } MITK_INFO << "No probe with given name " << name << " was found."; return nullptr; //no matching probe was found so 0 is returned } void mitk::USVideoDevice::RemoveProbeByName(std::string name) { for (std::vector::iterator it = m_Probes.begin(); it != m_Probes.end(); it++) { if (name.compare((*it)->GetName()) == 0) { m_Probes.erase(it); return; } } MITK_INFO << "No Probe with given name " << name << " was found"; } void mitk::USVideoDevice::AddNewProbe(mitk::USProbe::Pointer probe) { m_Probes.push_back(probe); } bool mitk::USVideoDevice::GetIsSourceFile() { return m_SourceIsFile; } + +void mitk::USVideoDevice::SetDefaultProbeAsCurrentProbe() +{ + if( m_Probes.size() == 0 ) + { + std::string name = "default"; + mitk::USProbe::Pointer defaultProbe = mitk::USProbe::New( name ); + m_Probes.push_back( defaultProbe ); + } + + m_CurrentProbe = m_Probes.at(0); + MITK_INFO << "SetDefaultProbeAsCurrentProbe()"; + this->ProbeChanged( m_CurrentProbe->GetName() ); +} + +void mitk::USVideoDevice::SetCurrentProbe(std::string probename) +{ + m_CurrentProbe = this->GetProbeByName( probename ); + MITK_INFO << "SetCurrentProbe() " << probename; +} + +void mitk::USVideoDevice::SetSpacing(double xSpacing, double ySpacing) +{ + mitk::Vector3D spacing; + spacing[0] = xSpacing; + spacing[1] = ySpacing; + spacing[2] = 1; + MITK_INFO << "Spacing: " << spacing; + + if( m_CurrentProbe.IsNotNull() ) + { + m_CurrentProbe->SetSpacingForGivenDepth(m_CurrentProbe->GetCurrentDepth(), spacing); + } + else + { + MITK_WARN << "Cannot set spacing. Current ultrasound probe not set."; + } +} diff --git a/Modules/US/USModel/mitkUSVideoDevice.h b/Modules/US/USModel/mitkUSVideoDevice.h index 00790af550..df205dd6c0 100644 --- a/Modules/US/USModel/mitkUSVideoDevice.h +++ b/Modules/US/USModel/mitkUSVideoDevice.h @@ -1,225 +1,252 @@ /*=================================================================== 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 MITKUSVideoDevice_H_HEADER_INCLUDED_ #define MITKUSVideoDevice_H_HEADER_INCLUDED_ #include #include #include "mitkUSDevice.h" #include "mitkUSImageVideoSource.h" #include "mitkUSProbe.h" #include namespace itk { template class SmartPointer; } namespace mitk { class USVideoDeviceCustomControls; class USAbstractControlInterface; /** * \brief A mitk::USVideoDevice is the common class for video only devices. * They capture video input either from a file or from a device and * transform the output into an mitk::USImage with attached metadata. * This simple implementation does only capture and display 2d images without * registration for example. * * \ingroup US */ class MITKUS_EXPORT USVideoDevice : public mitk::USDevice { public: mitkClassMacro(USVideoDevice, mitk::USDevice); // To open a device (DeviceID, Manufacturer, Model) mitkNewMacro3Param(Self, int, std::string, std::string); // To open A VideoFile (Path, Manufacturer, Model) mitkNewMacro3Param(Self, std::string, std::string, std::string); // To open a device (DeviceID, Metadata) mitkNewMacro2Param(Self, int, mitk::USImageMetadata::Pointer); // To open A VideoFile (Path, Metadata) mitkNewMacro2Param(Self, std::string, mitk::USImageMetadata::Pointer); /** * \return the qualified name of this class (as returned by GetDeviceClassStatic()) */ std::string GetDeviceClass() override; /** * This methode is necessary instead of a static member attribute to avoid * "static initialization order fiasco" when an instance of this class is * used in a module activator. * * \return the qualified name of this class */ static std::string GetDeviceClassStatic(); /** * Getter for the custom control interface which was created during the * construction process of mitk::USVideoDevice. * * \return custom control interface of the video device */ itk::SmartPointer GetControlInterfaceCustom() override; /** * \brief Remove this device from the micro service. * This method is public for mitk::USVideoDevice, because this devices * can be completly removed. This is not possible for API devices, which * should be available while their sub module is loaded. */ void UnregisterOnService(); /** * \return mitk::USImageSource connected to this device */ USImageSource::Pointer GetUSImageSource() override; /** * \brief Return all probes for this USVideoDevice or an empty vector it no probes were set * Returns a std::vector of all probes that exist for this USVideoDevice if there were probes set while creating or modifying this USVideoDevice. * Otherwise it returns an empty vector. Therefore always check if vector is filled, before using it! */ std::vector GetAllProbes(); + /** + * \brief Cleans the std::vector containing all configured probes. + */ + void DeleteAllProbes(); + /** * \brief Return current active probe for this USVideoDevice * Returns a pointer to the probe that is currently in use. If there were probes set while creating or modifying this USVideoDevice. * Returns null otherwise */ mitk::USProbe::Pointer GetCurrentProbe(); /** \brief adds a new probe to the device */ void AddNewProbe(mitk::USProbe::Pointer probe); /** * \brief get the probe by its name * Returns a pointer to the probe identified by the given name. If no probe of given name exists for this Device 0 is returned. */ mitk::USProbe::Pointer GetProbeByName(std::string name); /** * \brief Removes the Probe with the given name */ void RemoveProbeByName(std::string name); /** \brief True, if this Device plays back a file, false if it recieves data from a device */ bool GetIsSourceFile(); + /** + * \brief Sets the first existing probe or the default probe of the video device + * as the current probe of it. + */ + void SetDefaultProbeAsCurrentProbe(); + + /** + * \brief Sets the probe with the given name as current probe if the named probe exists. + */ + void SetCurrentProbe( std::string probename ); + + /** + * \brief Sets the given spacing of the current depth of the current probe. + */ + void SetSpacing( double xSpacing, double ySpacing ) override; + itkGetMacro(ImageVector, std::vector); itkGetMacro(DeviceID, int); itkGetMacro(FilePath, std::string); protected: /** * \brief Creates a new device that will deliver USImages taken from a video device. * under windows, try -1 for device number, which will grab the first available one * (Open CV functionality) */ USVideoDevice(int videoDeviceNumber, std::string manufacturer, std::string model); /** * \brief Creates a new device that will deliver USImages taken from a video file. */ USVideoDevice(std::string videoFilePath, std::string manufacturer, std::string model); /** * \brief Creates a new device that will deliver USImages taken from a video device. * under windows, try -1 for device number, which will grab the first available one * (Open CV functionality) */ USVideoDevice(int videoDeviceNumber, mitk::USImageMetadata::Pointer metadata); /** * \brief Creates a new device that will deliver USImages taken from a video file. */ USVideoDevice(std::string videoFilePath, mitk::USImageMetadata::Pointer metadata); ~USVideoDevice() override; /** * \brief Initializes common properties for all constructors. */ void Init(); /** * \brief Is called during the initialization process. * Returns true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ bool OnInitialization() override; /** * \brief Is called during the connection process. * Returns true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ bool OnConnection() override; /** * \brief Is called during the disconnection process. * Returns true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ bool OnDisconnection() override; /** * \brief Is called during the activation process. After this method is finsihed, the device should be generating images */ bool OnActivation() override; /** * \brief Is called during the deactivation process. After a call to this method the device should still be connected, but not producing images anymore. */ bool OnDeactivation() override; + /** + * \brief Grabs the next frame from the Video input. + * This method is called internally, whenever Update() is invoked by an Output. + */ + virtual void GenerateData() override; + /** * \brief The image source that we use to aquire data */ mitk::USImageVideoSource::Pointer m_Source; /** * \brief True, if this source plays back a file, false if it recieves data from a device */ bool m_SourceIsFile; /** * \brief The device id to connect to. Undefined, if m_SourceIsFile == true; */ int m_DeviceID; /** * \brief The Filepath id to connect to. Undefined, if m_SourceIsFile == false; */ std::string m_FilePath; /** * \brief custom control interface for us video device */ itk::SmartPointer m_ControlInterfaceCustom; /** * \brief probes for this USVideoDevice */ std::vector < mitk::USProbe::Pointer > m_Probes; /** \brief probe that is currently in use */ mitk::USProbe::Pointer m_CurrentProbe; }; } // namespace mitk #endif // MITKUSVideoDevice_H_HEADER_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSVideoDeviceCustomControls.cpp b/Modules/US/USModel/mitkUSVideoDeviceCustomControls.cpp index 58a1f664b4..bf6ab39efc 100644 --- a/Modules/US/USModel/mitkUSVideoDeviceCustomControls.cpp +++ b/Modules/US/USModel/mitkUSVideoDeviceCustomControls.cpp @@ -1,96 +1,116 @@ /*=================================================================== 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 "mitkUSVideoDeviceCustomControls.h" mitk::USVideoDeviceCustomControls::USVideoDeviceCustomControls(itk::SmartPointer device) : mitk::USAbstractControlInterface(device.GetPointer()), m_IsActive(false) { m_ImageSource = dynamic_cast(m_Device->GetUSImageSource().GetPointer()); } mitk::USVideoDeviceCustomControls::~USVideoDeviceCustomControls() { } void mitk::USVideoDeviceCustomControls::SetIsActive(bool isActive) { m_IsActive = isActive; } bool mitk::USVideoDeviceCustomControls::GetIsActive() { return m_IsActive; } void mitk::USVideoDeviceCustomControls::SetCropArea(mitk::USImageVideoSource::USImageCropping newArea) { MITK_INFO << "Set Crop Area L:" << newArea.left << " R:" << newArea.right << " T:" << newArea.top << " B:" << newArea.bottom; if (m_ImageSource.IsNotNull()) { // if area is empty, remove region if ((newArea.bottom == 0) && (newArea.top == 0) && (newArea.left == 0) && (newArea.right == 0)) { m_ImageSource->RemoveRegionOfInterest(); } else { m_ImageSource->SetCropping(newArea); } } else { MITK_WARN << "Cannot set crop are, source is not initialized!"; } } void mitk::USVideoDeviceCustomControls::SetNewDepth(double depth) { + mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); + if (device.IsNotNull()) + { + if( device->GetCurrentProbe().IsNotNull() ) + { + device->GetCurrentProbe()->SetCurrentDepth(depth); + MITK_INFO << "SetCurrentDepth of currentProbe: " << depth; + } + } m_Device->DepthChanged(depth); } void mitk::USVideoDeviceCustomControls::SetNewProbeIdentifier(std::string probename) { + mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); + if( device.IsNotNull() ) + { + device->SetCurrentProbe(probename); + } m_Device->ProbeChanged(probename); } mitk::USImageVideoSource::USImageCropping mitk::USVideoDeviceCustomControls::GetCropArea() { // just return the crop area set at the image source return m_ImageSource->GetCropping(); } std::vector mitk::USVideoDeviceCustomControls::GetProbes() { mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); return device->GetAllProbes(); } std::vector mitk::USVideoDeviceCustomControls::GetDepthsForProbe(std::string name) { mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); mitk::USProbe::Pointer probe = device->GetProbeByName(name); std::map depthsAndSpacings = probe->GetDepthsAndSpacing(); std::vector depths; for (std::map::iterator it = depthsAndSpacings.begin(); it != depthsAndSpacings.end(); it++) { depths.push_back((it->first)); } return depths; } + +void mitk::USVideoDeviceCustomControls::SetDefaultProbeAsCurrentProbe() +{ + mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); + device->SetDefaultProbeAsCurrentProbe(); +} diff --git a/Modules/US/USModel/mitkUSVideoDeviceCustomControls.h b/Modules/US/USModel/mitkUSVideoDeviceCustomControls.h index 11e94f0d7f..ce90da24b1 100644 --- a/Modules/US/USModel/mitkUSVideoDeviceCustomControls.h +++ b/Modules/US/USModel/mitkUSVideoDeviceCustomControls.h @@ -1,95 +1,101 @@ /*=================================================================== 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 MITKUSVideoDeviceCustomControls_H_HEADER_INCLUDED_ #define MITKUSVideoDeviceCustomControls_H_HEADER_INCLUDED_ #include "mitkUSAbstractControlInterface.h" #include "mitkUSImageVideoSource.h" #include "mitkUSVideoDevice.h" #include namespace mitk { /** * \brief Custom controls for mitk::USVideoDevice. * Controls image cropping of the corresponding mitk::USImageVideoSource. */ class MITKUS_EXPORT USVideoDeviceCustomControls : public USAbstractControlInterface { public: mitkClassMacro(USVideoDeviceCustomControls, USAbstractControlInterface); mitkNewMacro1Param(Self, itk::SmartPointer); /** * Activate or deactivate the custom controls. This is just for handling * widget visibility in a GUI for example. Cropping will not be deactivated * if this method is called with false. Use * mitk::USVideoDeviceCustomControls::SetCropArea() with an empty are * instead. */ void SetIsActive(bool isActive) override; /** * \return if this custom controls are currently activated */ bool GetIsActive() override; /** * \brief Sets the area that will be cropped from the US image. * Set [0,0,0,0] to disable it, which is also default. */ void SetCropArea(USImageVideoSource::USImageCropping newArea); /** * \return area currently set for image cropping */ mitk::USImageVideoSource::USImageCropping GetCropArea(); /** - * \brief Sets new depth value + * \brief Sets a new depth value to the current probe. */ void SetNewDepth(double depth); /** * \ brief Sets new probe identifier */ void SetNewProbeIdentifier(std::string probename); /** *\brief Get all the probes for the current device */ std::vector GetProbes(); /** * \brief Get the scanning dephts of the given probe */ std::vector GetDepthsForProbe(std::string name); + /** + * \brief Sets the first existing probe or the default probe of a USVideoDevice + * as the current probe of the USVideoDevice. + */ + void SetDefaultProbeAsCurrentProbe(); + protected: /** * Class needs an mitk::USImageVideoSource object for beeing constructed. * This object will be manipulated by the custom controls methods. */ USVideoDeviceCustomControls(itk::SmartPointer device); ~USVideoDeviceCustomControls() override; bool m_IsActive; USImageVideoSource::Pointer m_ImageSource; }; } // namespace mitk #endif // MITKUSVideoDeviceCustomControls_H_HEADER_INCLUDED_ \ No newline at end of file diff --git a/Modules/US/USNavigation/mitkUSCombinedModality.cpp b/Modules/US/USNavigation/mitkUSCombinedModality.cpp index 542fb985ec..7c1baf9f71 100644 --- a/Modules/US/USNavigation/mitkUSCombinedModality.cpp +++ b/Modules/US/USNavigation/mitkUSCombinedModality.cpp @@ -1,581 +1,576 @@ /*=================================================================== 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 "mitkUSCombinedModality.h" #include "mitkUSDevice.h" #include "mitkNavigationDataSource.h" #include "mitkImageReadAccessor.h" #include #include #include "mitkTrackingDeviceSource.h" // US Control Interfaces #include "mitkUSControlInterfaceProbes.h" #include "mitkUSControlInterfaceBMode.h" #include "mitkUSControlInterfaceDoppler.h" //Microservices #include #include #include #include #include //TempIncludes #include const std::string mitk::USCombinedModality::DeviceClassIdentifier = "org.mitk.modules.us.USCombinedModality"; const char* mitk::USCombinedModality::DefaultProbeIdentifier = "default"; const char* mitk::USCombinedModality::ProbeAndDepthSeperator = "_"; const std::string mitk::USCombinedModality::US_INTERFACE_NAME = "org.mitk.services.USCombinedModality"; const std::string mitk::USCombinedModality::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; const std::string mitk::USCombinedModality::US_PROPKEY_CLASS = US_INTERFACE_NAME + ".class"; const std::string mitk::USCombinedModality::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; mitk::USCombinedModality::USCombinedModality(USDevice::Pointer usDevice, NavigationDataSource::Pointer trackingDevice, std::string manufacturer, std::string model) : mitk::USDevice(manufacturer, model), m_UltrasoundDevice(usDevice), m_TrackingDevice(trackingDevice), m_SmoothingFilter(mitk::NavigationDataSmoothingFilter::New()), m_DelayFilter(mitk::NavigationDataDelayFilter::New(0)), m_NumberOfSmoothingValues(0), m_DelayCount(0) { this->RebuildFilterPipeline(); //create a new output (for the image data) mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); // Combined Modality should not spawn an own acquire thread, because // image acquiring is done by the included us device this->SetSpawnAcquireThread(false); } mitk::USCombinedModality::~USCombinedModality() { - if (m_ServiceRegistration != nullptr) - m_ServiceRegistration.Unregister(); - m_ServiceRegistration = 0; } std::string mitk::USCombinedModality::GetDeviceClass() { return DeviceClassIdentifier; } mitk::USImageSource::Pointer mitk::USCombinedModality::GetUSImageSource() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetUSImageSource(); } mitk::USAbstractControlInterface::Pointer mitk::USCombinedModality::GetControlInterfaceCustom() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetControlInterfaceCustom(); } mitk::USControlInterfaceBMode::Pointer mitk::USCombinedModality::GetControlInterfaceBMode() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetControlInterfaceBMode(); } mitk::USControlInterfaceProbes::Pointer mitk::USCombinedModality::GetControlInterfaceProbes() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetControlInterfaceProbes(); } mitk::USControlInterfaceDoppler::Pointer mitk::USCombinedModality::GetControlInterfaceDoppler() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetControlInterfaceDoppler(); } void mitk::USCombinedModality::UnregisterOnService() { if (m_DeviceState == State_Activated) { this->Deactivate(); } if (m_DeviceState == State_Connected) { this->Disconnect(); } - if (m_ServiceRegistration != nullptr) - m_ServiceRegistration.Unregister(); - m_ServiceRegistration = 0; + mitk::USDevice::UnregisterOnService(); } mitk::AffineTransform3D::Pointer mitk::USCombinedModality::GetCalibration() { return this->GetCalibration(this->GetCurrentDepthValue(), this->GetIdentifierForCurrentProbe()); } mitk::AffineTransform3D::Pointer mitk::USCombinedModality::GetCalibration(std::string depth) { return this->GetCalibration(depth, this->GetIdentifierForCurrentProbe()); } mitk::AffineTransform3D::Pointer mitk::USCombinedModality::GetCalibration(std::string depth, std::string probe) { // make sure that there is no '/' which would cause problems for TinyXML std::replace(probe.begin(), probe.end(), '/', '-'); // create identifier for calibration from probe and depth std::string calibrationKey = probe + mitk::USCombinedModality::ProbeAndDepthSeperator + depth; // find calibration for combination of probe identifier and depth std::map::iterator calibrationIterator = m_Calibrations.find(calibrationKey); if (calibrationIterator == m_Calibrations.end()) { return nullptr; } return calibrationIterator->second; } void mitk::USCombinedModality::SetCalibration(mitk::AffineTransform3D::Pointer calibration) { if (calibration.IsNull()) { MITK_WARN << "Null pointer passed to SetCalibration of mitk::USDevice. Ignoring call."; return; } std::string calibrationKey = this->GetIdentifierForCurrentCalibration(); if (calibrationKey.empty()) { MITK_WARN << "Could not get a key for the calibration -> Calibration cannot be set."; return; } m_Calibrations[calibrationKey] = calibration; } bool mitk::USCombinedModality::RemoveCalibration() { return this->RemoveCalibration(this->GetCurrentDepthValue(), this->GetIdentifierForCurrentProbe()); } bool mitk::USCombinedModality::RemoveCalibration(std::string depth) { return this->RemoveCalibration(depth, this->GetIdentifierForCurrentProbe()); } bool mitk::USCombinedModality::RemoveCalibration(std::string depth, std::string probe) { // make sure that there is no '/' which would cause problems for TinyXML std::replace(probe.begin(), probe.end(), '/', '-'); // create identifier for calibration from probe and depth std::string calibrationKey = probe + mitk::USCombinedModality::ProbeAndDepthSeperator + depth; return m_Calibrations.erase(calibrationKey) > 0; } void mitk::USCombinedModality::SetNumberOfSmoothingValues(unsigned int numberOfSmoothingValues) { unsigned int oldNumber = m_NumberOfSmoothingValues; m_NumberOfSmoothingValues = numberOfSmoothingValues; // if filter should be activated or deactivated if ((oldNumber == 0 && numberOfSmoothingValues != 0) || (oldNumber != 0 && numberOfSmoothingValues == 0)) { this->RebuildFilterPipeline(); } m_SmoothingFilter->SetNumerOfValues(numberOfSmoothingValues); } void mitk::USCombinedModality::SetDelayCount(unsigned int delayCount) { unsigned int oldCount = m_DelayCount; m_DelayCount = delayCount; // if filter should be activated or deactivated if ((oldCount == 0 && delayCount != 0) || (oldCount != 0 && delayCount == 0)) { this->RebuildFilterPipeline(); } m_DelayFilter->SetDelay(delayCount); } bool mitk::USCombinedModality::OnInitialization() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } if (m_UltrasoundDevice->GetDeviceState() < mitk::USDevice::State_Initialized) { return m_UltrasoundDevice->Initialize(); } else { return true; } } bool mitk::USCombinedModality::OnConnection() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } // connect ultrasound device only if it is not already connected if (m_UltrasoundDevice->GetDeviceState() >= mitk::USDevice::State_Connected) { return true; } else { return m_UltrasoundDevice->Connect(); } } bool mitk::USCombinedModality::OnDisconnection() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->Disconnect(); } bool mitk::USCombinedModality::OnActivation() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } mitk::TrackingDeviceSource::Pointer trackingDeviceSource = dynamic_cast(m_TrackingDevice.GetPointer()); if (trackingDeviceSource.IsNull()) { MITK_WARN("USCombinedModality")("USDevice") << "Cannot start tracking as TrackingDeviceSource is null."; } trackingDeviceSource->StartTracking(); // activate ultrasound device only if it is not already activated if (m_UltrasoundDevice->GetDeviceState() >= mitk::USDevice::State_Activated) { return true; } else { return m_UltrasoundDevice->Activate(); } } bool mitk::USCombinedModality::OnDeactivation() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } mitk::TrackingDeviceSource::Pointer trackingDeviceSource = dynamic_cast(m_TrackingDevice.GetPointer()); if (trackingDeviceSource.IsNull()) { MITK_WARN("USCombinedModality")("USDevice") << "Cannot stop tracking as TrackingDeviceSource is null."; } trackingDeviceSource->StopTracking(); m_UltrasoundDevice->Deactivate(); return m_UltrasoundDevice->GetIsConnected(); } void mitk::USCombinedModality::OnFreeze(bool freeze) { mitk::TrackingDeviceSource::Pointer trackingDeviceSource = dynamic_cast(m_TrackingDevice.GetPointer()); if (trackingDeviceSource.IsNull()) { MITK_WARN("USCombinedModality")("USDevice") << "Cannot freeze tracking."; } else { if (freeze) { trackingDeviceSource->Freeze(); } else { trackingDeviceSource->UnFreeze(); } } if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } m_UltrasoundDevice->SetIsFreezed(freeze); } mitk::NavigationDataSource::Pointer mitk::USCombinedModality::GetNavigationDataSource() { return m_LastFilter.GetPointer(); } bool mitk::USCombinedModality::GetIsCalibratedForCurrentStatus() { return m_Calibrations.find(this->GetIdentifierForCurrentCalibration()) != m_Calibrations.end(); } bool mitk::USCombinedModality::GetContainsAtLeastOneCalibration() { return !m_Calibrations.empty(); } void mitk::USCombinedModality::GenerateData() { if (m_UltrasoundDevice->GetIsFreezed()) { return; } //if the image is freezed: do nothing //get next image from ultrasound image source mitk::Image::Pointer image = m_UltrasoundDevice->GetUSImageSource()->GetNextImage()[0]; if (image.IsNull() || !image->IsInitialized()) //check the image { MITK_WARN << "Invalid image in USCombinedModality, aborting!"; return; } //get output and initialize it if it wasn't initialized before mitk::Image::Pointer output = this->GetOutput(); if (!output->IsInitialized()) { output->Initialize(image); } //now update image data mitk::ImageReadAccessor inputReadAccessor(image, image->GetSliceData(0, 0, 0)); output->SetSlice(inputReadAccessor.GetData()); //copy image data output->GetGeometry()->SetSpacing(image->GetGeometry()->GetSpacing()); //copy spacing because this might also change //and update calibration (= transformation of the image) std::string calibrationKey = this->GetIdentifierForCurrentCalibration(); if (!calibrationKey.empty()) { std::map::iterator calibrationIterator = m_Calibrations.find(calibrationKey); if (calibrationIterator != m_Calibrations.end()) { // transform image according to callibration if one is set // for current configuration of probe and depth this->GetOutput()->GetGeometry()->SetIndexToWorldTransform(calibrationIterator->second); } } } std::string mitk::USCombinedModality::SerializeCalibration() { std::stringstream result; result << "" << std::endl; // For each calibration in the set for (std::map::iterator it = m_Calibrations.begin(); it != m_Calibrations.end(); it++) { mitk::AffineTransform3D::MatrixType matrix = it->second->GetMatrix(); mitk::AffineTransform3D::TranslationType translation = it->second->GetTranslation(); TiXmlElement elem(it->first); // Serialize Matrix elem.SetDoubleAttribute("M00", matrix[0][0]); elem.SetDoubleAttribute("M01", matrix[0][1]); elem.SetDoubleAttribute("M02", matrix[0][2]); elem.SetDoubleAttribute("M10", matrix[1][0]); elem.SetDoubleAttribute("M11", matrix[1][1]); elem.SetDoubleAttribute("M12", matrix[1][2]); elem.SetDoubleAttribute("M20", matrix[2][0]); elem.SetDoubleAttribute("M21", matrix[2][1]); elem.SetDoubleAttribute("M22", matrix[2][2]); // Serialize Offset elem.SetDoubleAttribute("T0", translation[0]); elem.SetDoubleAttribute("T1", translation[1]); elem.SetDoubleAttribute("T2", translation[2]); result << elem << std::endl; } result << "" << std::endl; return result.str(); } void mitk::USCombinedModality::DeserializeCalibration(const std::string& xmlString, bool clearPreviousCalibrations) { // Sanitize Input if (xmlString == "") { MITK_ERROR << "Empty string passed to Deserialize() method of CombinedModality. Aborting..."; mitkThrow() << "Empty string passed to Deserialize() method of CombinedModality. Aborting..."; return; } // Clear previous calibrations if necessary if (clearPreviousCalibrations) m_Calibrations.clear(); // Parse Input TiXmlDocument doc; if (!doc.Parse(xmlString.c_str())) { MITK_ERROR << "Unable to deserialize calibrations in CombinedModality. Error was: " << doc.ErrorDesc(); mitkThrow() << "Unable to deserialize calibrations in CombinedModality. Error was: " << doc.ErrorDesc(); return; } TiXmlElement* root = doc.FirstChildElement(); if (root == nullptr) { MITK_ERROR << "Unable to deserialize calibrations in CombinedModality. String contained no root element."; mitkThrow() << "Unable to deserialize calibrations in CombinedModality. String contained no root element."; return; } // Read Calibrations for (TiXmlElement* elem = root->FirstChildElement(); elem != nullptr; elem = elem->NextSiblingElement()) { mitk::AffineTransform3D::MatrixType matrix; mitk::AffineTransform3D::OffsetType translation; std::string calibName = elem->Value(); // Deserialize Matrix elem->QueryDoubleAttribute("M00", &matrix[0][0]); elem->QueryDoubleAttribute("M01", &matrix[0][1]); elem->QueryDoubleAttribute("M02", &matrix[0][2]); elem->QueryDoubleAttribute("M10", &matrix[1][0]); elem->QueryDoubleAttribute("M11", &matrix[1][1]); elem->QueryDoubleAttribute("M12", &matrix[1][2]); elem->QueryDoubleAttribute("M20", &matrix[2][0]); elem->QueryDoubleAttribute("M21", &matrix[2][1]); elem->QueryDoubleAttribute("M22", &matrix[2][2]); // Deserialize Offset elem->QueryDoubleAttribute("T0", &translation[0]); elem->QueryDoubleAttribute("T1", &translation[1]); elem->QueryDoubleAttribute("T2", &translation[2]); mitk::AffineTransform3D::Pointer calibration = mitk::AffineTransform3D::New(); calibration->SetMatrix(matrix); calibration->SetTranslation(translation); m_Calibrations[calibName] = calibration; } } std::string mitk::USCombinedModality::GetIdentifierForCurrentCalibration() { return this->GetIdentifierForCurrentProbe() + mitk::USCombinedModality::ProbeAndDepthSeperator + this->GetCurrentDepthValue(); } std::string mitk::USCombinedModality::GetIdentifierForCurrentProbe() { us::ServiceProperties usdeviceProperties = m_UltrasoundDevice->GetServiceProperties(); us::ServiceProperties::const_iterator probeIt = usdeviceProperties.find( mitk::USCombinedModality::GetPropertyKeys().US_PROPKEY_PROBES_SELECTED); // get probe identifier from control interface for probes std::string probeName = mitk::USCombinedModality::DefaultProbeIdentifier; if (probeIt != usdeviceProperties.end()) { probeName = (probeIt->second).ToString(); } // make sure that there is no '/' which would cause problems for TinyXML std::replace(probeName.begin(), probeName.end(), '/', '-'); return probeName; } std::string mitk::USCombinedModality::GetCurrentDepthValue() { us::ServiceProperties usdeviceProperties = m_UltrasoundDevice->GetServiceProperties(); // get string for depth value from the micro service properties std::string depth; us::ServiceProperties::iterator depthIterator = usdeviceProperties.find( mitk::USCombinedModality::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH); if (depthIterator != usdeviceProperties.end()) { depth = depthIterator->second.ToString(); } else { depth = "0"; } return depth; } void mitk::USCombinedModality::RebuildFilterPipeline() { m_LastFilter = m_TrackingDevice; if (m_NumberOfSmoothingValues > 0) { for (unsigned int i = 0; i < m_TrackingDevice->GetNumberOfOutputs(); i++) { m_SmoothingFilter->SetInput(i, m_LastFilter->GetOutput(i)); } m_LastFilter = m_SmoothingFilter; } if (m_DelayCount > 0) { for (unsigned int i = 0; i < m_TrackingDevice->GetNumberOfOutputs(); i++) { m_DelayFilter->SetInput(i, m_LastFilter->GetOutput(i)); } m_LastFilter = m_DelayFilter; } } void mitk::USCombinedModality::RegisterAsMicroservice() { //Get Context us::ModuleContext* context = us::GetModuleContext(); //Define ServiceProps us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator("org.mitk.services.USCombinedModality", 16); props[US_PROPKEY_ID] = uidGen.GetUID(); props[US_PROPKEY_DEVICENAME] = this->GetName(); props[US_PROPKEY_CLASS] = this->GetDeviceClass(); m_ServiceProperties = props; m_ServiceRegistration = context->RegisterService(this, props); } diff --git a/Modules/US/USNavigation/mitkUSCombinedModality.h b/Modules/US/USNavigation/mitkUSCombinedModality.h index e632142538..a549299f54 100644 --- a/Modules/US/USNavigation/mitkUSCombinedModality.h +++ b/Modules/US/USNavigation/mitkUSCombinedModality.h @@ -1,270 +1,256 @@ /*=================================================================== 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 MITKUSCombinedModality_H_HEADER_INCLUDED_ #define MITKUSCombinedModality_H_HEADER_INCLUDED_ #include #include "mitkUSDevice.h" #include "mitkNavigationDataSource.h" -// Microservices -#include -#include - namespace itk { template class SmartPointer; } namespace mitk { class NavigationDataSmoothingFilter; class NavigationDataDelayFilter; class USControlInterfaceBMode; class USControlInterfaceProbes; class USControlInterfaceDoppler; /** * \brief Combination of USDevice and NavigationDataSource. * This class can be used as any USDevice subclass. Additionally tracking data be * retrieved from the NavigationDataSource returned by GetTrackingDevice(). * * A calibration of the ultrasound image stream to the navigation datas can be set * for the currently active zoom level (of the ultrasound device) by SetCalibration(). * The ultrasound images are transformed according to this calibration in the * GenerateData() method. */ class MITKUSNAVIGATION_EXPORT USCombinedModality : public USDevice { public: static const std::string DeviceClassIdentifier; static const char* DefaultProbeIdentifier; static const char* ProbeAndDepthSeperator; mitkClassMacro(USCombinedModality, USDevice); mitkNewMacro4Param(USCombinedModality, USDevice::Pointer, itk::SmartPointer, std::string, std::string); itkGetMacro(UltrasoundDevice, itk::SmartPointer); itkSetMacro(UltrasoundDevice, itk::SmartPointer); itkGetMacro(TrackingDevice, itk::SmartPointer); itkSetMacro(TrackingDevice, itk::SmartPointer); /** * \brief Getter for calibration data of the currently active depth and probe. * * \return Transformation for calibration or null if no calibration is available. */ AffineTransform3D::Pointer GetCalibration(); /** * \brief Getter for calibration data of the given depth and the currently active probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be returned * \return Transformation for calibration or null if no calibration is available. */ AffineTransform3D::Pointer GetCalibration(std::string depth); /** * \brief Getter for calibration data of the given depth and probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be returned * \param probe probe of the ultrasound device for which the calibration should be returned * \return Transformation for calibration or null if no calibration is available. */ AffineTransform3D::Pointer GetCalibration(std::string depth, std::string probe); /** * \brief Sets a transformation as calibration data. * Calibration data is set for the currently activated probe and their current * zoom factor. It also marks the device as calibrated. */ void SetCalibration(AffineTransform3D::Pointer calibration); /** * \brief Removes the calibration data of the currently active depth and probe. * \return true on success, false if there was no calibration */ bool RemoveCalibration(); /** * \brief Removes the calibration data of the given depth and the currently active probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be removed * \return true on success, false if there was no calibration */ bool RemoveCalibration(std::string depth); /** * \brief Removes the calibration data of the given depth and probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be removed * \param probe probe of the ultrasound device for which the calibration should be removed * \return true on success, false if there was no calibration */ bool RemoveCalibration(std::string depth, std::string probe); /** * \brief Returns the Class of the Device. */ std::string GetDeviceClass() override; /** * \brief Wrapper for returning USImageSource of the UltrasoundDevice. */ USImageSource::Pointer GetUSImageSource() override; /** * \brief Wrapper for returning custom control interface of the UltrasoundDevice. */ itk::SmartPointer GetControlInterfaceCustom() override; /** * \brief Wrapper for returning B mode control interface of the UltrasoundDevice. */ itk::SmartPointer GetControlInterfaceBMode() override; /** * \brief Wrapper for returning probes control interface of the UltrasoundDevice. */ itk::SmartPointer GetControlInterfaceProbes() override; /** * \brief Wrapper for returning doppler control interface of the UltrasoundDevice. */ itk::SmartPointer GetControlInterfaceDoppler() override; virtual itk::SmartPointer GetNavigationDataSource(); /** * \return true if the device is calibrated for the currently selected probe with the current zoom level */ bool GetIsCalibratedForCurrentStatus(); /** * \return true if a calibration was loaded for at least one probe and depth */ bool GetContainsAtLeastOneCalibration(); /** * \brief Remove this device from the micro service. * This method is public for mitk::USCombinedModality, because this devices * can be completly removed. This is not possible for API devices, which * should be available while their sub module is loaded. */ void UnregisterOnService(); /** * \brief Serializes all contained calibrations into an xml fragment. * * The returned string contains one parent node named "calibrations" and several * subnodes, one for each calibration that is present. */ std::string SerializeCalibration(); /** * \brief Deserializes a string provided by a prior call to Serialize(). * If the bool flag is true, all prior calibrations will be deleted. * If the flag is set to false, prior calibrations will be retained, but overwritten * if one of equal name is present. * * \throws mitk::Exception if the given string could not be parsed correctly. */ void DeserializeCalibration(const std::string &xmlString, bool clearPreviousCalibrations = true); void SetNumberOfSmoothingValues(unsigned int numberOfSmoothingValues); void SetDelayCount(unsigned int delayCount); void RegisterAsMicroservice(); /** *\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_CLASS; static const std::string US_PROPKEY_ID; protected: USCombinedModality(USDevice::Pointer usDevice, itk::SmartPointer trackingDevice, std::string manufacturer = "", std::string model = ""); ~USCombinedModality() override; /** * \brief Initializes UltrasoundDevice. */ bool OnInitialization() override; /** * \brief Connects UltrasoundDevice. */ bool OnConnection() override; /** * \brief Disconnects UltrasoundDevice. */ bool OnDisconnection() override; /** * \brief Activates UltrasoundDevice. */ bool OnActivation() override; /** * \brief Deactivates UltrasoundDevice. */ bool OnDeactivation() override; /** * \brief Freezes or unfreezes UltrasoundDevice. */ void OnFreeze(bool) override; /** * \brief Grabs the next frame from the input. * This method is called internally, whenever Update() is invoked by an Output. */ void GenerateData() override; std::string GetIdentifierForCurrentCalibration(); std::string GetIdentifierForCurrentProbe(); std::string GetCurrentDepthValue(); void RebuildFilterPipeline(); USDevice::Pointer m_UltrasoundDevice; itk::SmartPointer m_TrackingDevice; std::map m_Calibrations; itk::SmartPointer m_SmoothingFilter; itk::SmartPointer m_DelayFilter; itk::SmartPointer m_LastFilter; unsigned int m_NumberOfSmoothingValues; unsigned int m_DelayCount; - private: - /** - * \brief The device's ServiceRegistration object that allows to modify it's Microservice registraton details. - */ - us::ServiceRegistration m_ServiceRegistration; - - /** - * \brief Properties of the device's Microservice. - */ - us::ServiceProperties m_ServiceProperties; }; } // namespace mitk -MITK_DECLARE_SERVICE_INTERFACE(mitk::USCombinedModality, "org.mitk.services.USCombinedModality") +//MITK_DECLARE_SERVICE_INTERFACE(mitk::USCombinedModality, "org.mitk.services.USCombinedModality") #endif // MITKUSCombinedModality_H_HEADER_INCLUDED_ diff --git a/Modules/US/files.cmake b/Modules/US/files.cmake index 93bf7bcfb2..42c099ed21 100644 --- a/Modules/US/files.cmake +++ b/Modules/US/files.cmake @@ -1,34 +1,36 @@ SET(CPP_FILES ## Module Activator mitkUSActivator.cpp ## Model Classes USModel/mitkUSImage.cpp USModel/mitkUSImageMetadata.cpp USModel/mitkUSDevice.cpp USModel/mitkUSIGTLDevice.cpp USModel/mitkUSVideoDevice.cpp USModel/mitkUSVideoDeviceCustomControls.cpp USModel/mitkUSProbe.cpp USModel/mitkUSDevicePersistence.cpp +USModel/mitkUSDeviceReaderXML.cpp +USModel/mitkUSDeviceWriterXML.cpp ## Filters and Sources USFilters/mitkUSImageLoggingFilter.cpp USFilters/mitkUSImageSource.cpp USFilters/mitkUSImageVideoSource.cpp USFilters/mitkIGTLMessageToUSImageFilter.cpp ## Control Interfaces USControlInterfaces/mitkUSAbstractControlInterface.cpp USControlInterfaces/mitkUSControlInterfaceBMode.cpp USControlInterfaces/mitkUSControlInterfaceProbes.cpp USControlInterfaces/mitkUSControlInterfaceDoppler.cpp USControlInterfaces/mitkUSDiPhASDeviceCustomControls.cpp ) set(RESOURCE_FILES Interactions/USPointMarkInteractions.xml Interactions/USZoneInteractions.xml Interactions/USZoneInteractionsHold.xml ) diff --git a/Modules/USUI/Qmitk/QmitkUSControlsBModeWidget.cpp b/Modules/USUI/Qmitk/QmitkUSControlsBModeWidget.cpp index de86ddea54..e4a7e569b4 100644 --- a/Modules/USUI/Qmitk/QmitkUSControlsBModeWidget.cpp +++ b/Modules/USUI/Qmitk/QmitkUSControlsBModeWidget.cpp @@ -1,124 +1,129 @@ /*=================================================================== 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 "QmitkUSControlsBModeWidget.h" #include "ui_QmitkUSControlsBModeWidget.h" QmitkUSControlsBModeWidget::QmitkUSControlsBModeWidget(mitk::USControlInterfaceBMode::Pointer controlInterface, QWidget *parent) : QWidget(parent), ui(new Ui::QmitkUSControlsBModeWidget), m_ControlInterface(controlInterface) { ui->setupUi(this); if ( ! m_ControlInterface ) { this->setDisabled(true); /*ui->scanningDepthComboBox->setEnabled(false); ui->scanningGainSlider->setEnabled(false); ui->scanningRejectionSlider->setEnabled(false);*/ return; } if ( ! m_ControlInterface->GetIsActive() ) { m_ControlInterface->SetIsActive(true); } // get possible scanning depth values and set combo box values according to them std::vector scanningDepths = m_ControlInterface->GetScanningDepthValues(); double curDepthValue = m_ControlInterface->GetScanningDepth(); for (auto it = scanningDepths.begin(); it != scanningDepths.end(); it++) { ui->scanningDepthComboBox->addItem(QString::number(*it, 'f', 2)); // set current index to last inserted element if this element is equal // to the current depth value got from the interface if (curDepthValue == *it) ui->scanningDepthComboBox->setCurrentIndex(ui->scanningDepthComboBox->count()-1); } // get possible scanning frequency values and set combo box values according to them std::vector scanningFrequencies = m_ControlInterface->GetScanningFrequencyValues(); double curFrequencyValue = m_ControlInterface->GetScanningFrequency(); for (auto it = scanningFrequencies.begin(); it != scanningFrequencies.end(); it++) { ui->scanningFrequencyComboBox->addItem(QString::number(*it, 'f', 2) + QString(" MHz")); // set current index to last inserted element if this element is equal // to the current depth value got from the interface if (curFrequencyValue == *it) ui->scanningFrequencyComboBox->setCurrentIndex(ui->scanningFrequencyComboBox->count()-1); } - + ui->scanningPowerSlider->setMinimum(m_ControlInterface->GetScanningPowerMin()); ui->scanningPowerSlider->setMaximum(m_ControlInterface->GetScanningPowerMax()); ui->scanningPowerSlider->setTickInterval(m_ControlInterface->GetScanningPowerTick()); ui->scanningPowerSlider->setValue(m_ControlInterface->GetScanningPower()); ui->scanningGainSlider->setMinimum(m_ControlInterface->GetScanningGainMin()); ui->scanningGainSlider->setMaximum(m_ControlInterface->GetScanningGainMax()); ui->scanningGainSlider->setTickInterval(m_ControlInterface->GetScanningGainTick()); ui->scanningGainSlider->setValue(m_ControlInterface->GetScanningGain()); ui->scanningRejectionSlider->setMinimum(m_ControlInterface->GetScanningRejectionMin()); ui->scanningRejectionSlider->setMaximum(m_ControlInterface->GetScanningRejectionMax()); ui->scanningRejectionSlider->setTickInterval(m_ControlInterface->GetScanningRejectionTick()); ui->scanningRejectionSlider->setValue(m_ControlInterface->GetScanningRejection()); ui->scanningDynamicRangeSlider->setMinimum(m_ControlInterface->GetScanningDynamicRangeMin()); ui->scanningDynamicRangeSlider->setMaximum(m_ControlInterface->GetScanningDynamicRangeMax()); ui->scanningDynamicRangeSlider->setTickInterval(m_ControlInterface->GetScanningDynamicRangeTick()); ui->scanningDynamicRangeSlider->setValue(m_ControlInterface->GetScanningDynamicRange()); connect( ui->scanningFrequencyComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFrequencyControlIndexChanged(int)) ); connect( ui->scanningDepthComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnDepthControlActivated(int)) ); connect( ui->scanningPowerSlider, SIGNAL(valueChanged(int)), this, SLOT(OnPowerControlValueChanged(int)) ); connect( ui->scanningGainSlider, SIGNAL(valueChanged(int)), this, SLOT(OnGainControlValueChanged(int)) ); connect( ui->scanningRejectionSlider, SIGNAL(valueChanged(int)), this, SLOT(OnRejectionControlValueChanged(int)) ); connect( ui->scanningDynamicRangeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnDynamicRangeControlValueChanged(int)) ); } QmitkUSControlsBModeWidget::~QmitkUSControlsBModeWidget() { delete ui; } // slots void QmitkUSControlsBModeWidget::OnFrequencyControlIndexChanged(int) { QString currentText = ui->scanningFrequencyComboBox->currentText(); m_ControlInterface->SetScanningFrequency((currentText.left(currentText.size()-5)).toDouble()); } void QmitkUSControlsBModeWidget::OnDepthControlActivated(int) { m_ControlInterface->SetScanningDepth(ui->scanningDepthComboBox->currentText().toDouble()); } void QmitkUSControlsBModeWidget::OnPowerControlValueChanged(int value) { m_ControlInterface->SetScanningPower(static_cast(value)); + ui->scanningPowerLabel_value->setText(QString::number(value) +"%"); + } void QmitkUSControlsBModeWidget::OnGainControlValueChanged(int value) { m_ControlInterface->SetScanningGain(static_cast(value)); + ui->scanningGainLabel_value->setText(QString::number(value) + "%"); } void QmitkUSControlsBModeWidget::OnRejectionControlValueChanged(int value) { m_ControlInterface->SetScanningRejection(static_cast(value)); + ui->scanningRejectionLabel_value->setText(QString::number(value)); } void QmitkUSControlsBModeWidget::OnDynamicRangeControlValueChanged(int value) { m_ControlInterface->SetScanningDynamicRange(static_cast(value)); + ui->scanningDynamicRangeLabel_value->setText(QString::number(value) + "dB"); } \ No newline at end of file diff --git a/Modules/USUI/Qmitk/QmitkUSControlsBModeWidget.ui b/Modules/USUI/Qmitk/QmitkUSControlsBModeWidget.ui index 5de348c171..fdeae33882 100644 --- a/Modules/USUI/Qmitk/QmitkUSControlsBModeWidget.ui +++ b/Modules/USUI/Qmitk/QmitkUSControlsBModeWidget.ui @@ -1,593 +1,689 @@ QmitkUSControlsBModeWidget 0 0 372 394 Form - - + + Depth Control - + - :/USUI/zoom-out.png:/USUI/zoom-out.png 0 0 + :/USUI/zoom-in.png:/USUI/zoom-in.png - + Frequency Control - + - :/USUI/zoom-out.png:/USUI/zoom-out.png + :/USUI/zoom-in.png:/USUI/zoom-in.png - - - - Power Control - - + + + + + + Power Control : + + + + + + + 100 % + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - + 0 15 true Qt::Horizontal false false QSlider::NoTicks - + 16777215 10 6 0% 16777215 10 Qt::Horizontal 40 20 16777215 10 6 100% - - - - Gain Control - - + + + + + + Gain Control : + + + + + + + 100 % + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - + 0 15 Qt::Horizontal QSlider::NoTicks - + 16777215 10 6 0% 16777215 10 Qt::Horizontal 40 20 16777215 10 6 100% - - - - Dynamic Range Control - - + + + + + + Dynamic Range Control : + + + + + + + 80 dB + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - + 0 15 Qt::Horizontal QSlider::NoTicks - + 16777215 10 6 20 dB 16777215 10 Qt::Horizontal 40 20 16777215 10 6 80 dB - - - - Rejection Control - - + + + + + + Rejection Control : + + + + + + + 0 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - + 0 15 Qt::Horizontal QSlider::NoTicks - + 16777215 10 6 0 16777215 10 Qt::Horizontal 40 20 16777215 10 6 32 - + Qt::Vertical 20 40 QmitkComboBoxStepThrough QComboBox
QmitkComboBoxStepThrough.h
SignalReachedBegin(bool) SignalReachedEnd(bool) OnSetPreviousIndex() OnSetNextIndex()
scanningDepthNext clicked() scanningDepthComboBox OnSetNextIndex() 197 36 107 35 scanningDepthPrev clicked() scanningDepthComboBox OnSetPreviousIndex() 17 36 107 35 scanningDepthComboBox SignalReachedBegin(bool) scanningDepthPrev setDisabled(bool) 107 35 17 36 scanningDepthComboBox SignalReachedEnd(bool) scanningDepthNext setDisabled(bool) 107 35 197 36 scanningFrequencyNext clicked() scanningFrequencyComboBox OnSetNextIndex() 50 39 136 39 scanningFrequencyPrev clicked() scanningFrequencyComboBox OnSetPreviousIndex() 21 39 136 39 scanningFrequencyComboBox SignalReachedBegin(bool) scanningFrequencyPrev setDisabled(bool) 136 39 21 39 scanningFrequencyComboBox SignalReachedEnd(bool) scanningFrequencyNext setDisabled(bool) 136 39 50 39
diff --git a/Modules/USUI/Qmitk/QmitkUSControlsCustomVideoDeviceWidget.cpp b/Modules/USUI/Qmitk/QmitkUSControlsCustomVideoDeviceWidget.cpp index e997ecfd79..6785955e4a 100644 --- a/Modules/USUI/Qmitk/QmitkUSControlsCustomVideoDeviceWidget.cpp +++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomVideoDeviceWidget.cpp @@ -1,165 +1,172 @@ /*=================================================================== 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 "QmitkUSControlsCustomVideoDeviceWidget.h" #include "ui_QmitkUSControlsCustomVideoDeviceWidget.h" #include #include QmitkUSControlsCustomVideoDeviceWidget::QmitkUSControlsCustomVideoDeviceWidget() : ui(new Ui::QmitkUSControlsCustomVideoDeviceWidget) { } QmitkUSControlsCustomVideoDeviceWidget::QmitkUSControlsCustomVideoDeviceWidget(QWidget *parent) : QmitkUSAbstractCustomWidget(parent), ui(new Ui::QmitkUSControlsCustomVideoDeviceWidget) { m_Cropping.left = 0; m_Cropping.top = 0; m_Cropping.right = 0; m_Cropping.bottom = 0; } QmitkUSControlsCustomVideoDeviceWidget::~QmitkUSControlsCustomVideoDeviceWidget() { delete ui; } std::string QmitkUSControlsCustomVideoDeviceWidget::GetDeviceClass() const { return mitk::USVideoDevice::GetDeviceClassStatic(); } QmitkUSAbstractCustomWidget* QmitkUSControlsCustomVideoDeviceWidget::Clone(QWidget* parent) const { QmitkUSAbstractCustomWidget* clonedWidget = new QmitkUSControlsCustomVideoDeviceWidget(parent); clonedWidget->SetDevice(this->GetDevice()); return clonedWidget; } void QmitkUSControlsCustomVideoDeviceWidget::OnDeviceSet() { m_ControlInterface = dynamic_cast (this->GetDevice()->GetControlInterfaceCustom().GetPointer()); if (m_ControlInterface.IsNotNull()) { mitk::USImageVideoSource::USImageCropping cropping = m_ControlInterface->GetCropArea(); ui->crop_left->setValue(cropping.left); ui->crop_right->setValue(cropping.right); ui->crop_bot->setValue(cropping.bottom); ui->crop_top->setValue(cropping.top); //get all probes and put their names into a combobox std::vector probes = m_ControlInterface->GetProbes(); for (std::vector::iterator it = probes.begin(); it != probes.end(); it++) { std::string probeName = (*it)->GetName(); ui->m_ProbeIdentifier->addItem(QString::fromUtf8(probeName.data(), probeName.size())); } + + m_ControlInterface->SetDefaultProbeAsCurrentProbe(); + + SetDepthsForProbe( ui->m_ProbeIdentifier->currentText().toStdString() ); + m_ControlInterface->SetNewDepth( ui->m_UsDepth->currentText().toDouble() ); + connect(ui->m_UsDepth, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnDepthChanged())); connect(ui->m_ProbeIdentifier, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnProbeChanged())); } else { MITK_WARN("QmitkUSAbstractCustomWidget")("QmitkUSControlsCustomVideoDeviceWidget") << "Did not get a custom video device control interface."; } ui->crop_left->setEnabled(m_ControlInterface.IsNotNull()); ui->crop_right->setEnabled(m_ControlInterface.IsNotNull()); ui->crop_bot->setEnabled(m_ControlInterface.IsNotNull()); ui->crop_top->setEnabled(m_ControlInterface.IsNotNull()); } void QmitkUSControlsCustomVideoDeviceWidget::Initialize() { ui->setupUi(this); connect(ui->crop_left, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged())); connect(ui->crop_right, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged())); connect(ui->crop_top, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged())); connect(ui->crop_bot, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged())); } void QmitkUSControlsCustomVideoDeviceWidget::OnCropAreaChanged() { if (m_ControlInterface.IsNull()) { return; } mitk::USImageVideoSource::USImageCropping cropping; cropping.left = ui->crop_left->value(); cropping.top = ui->crop_top->value(); cropping.right = ui->crop_right->value(); cropping.bottom = ui->crop_bot->value(); try { m_ControlInterface->SetCropArea(cropping); m_Cropping = cropping; } catch (mitk::Exception e) { m_ControlInterface->SetCropArea(m_Cropping); // reset to last valid crop //reset values BlockSignalAndSetValue(ui->crop_left, m_Cropping.left); BlockSignalAndSetValue(ui->crop_right, m_Cropping.right); BlockSignalAndSetValue(ui->crop_top, m_Cropping.top); BlockSignalAndSetValue(ui->crop_bot, m_Cropping.bottom); // inform user QMessageBox msgBox; msgBox.setInformativeText("The crop area you specified is invalid.\nPlease make sure that no more pixels are cropped than are available."); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); MITK_WARN << "User tried to crop beyond limits of the image"; } } void QmitkUSControlsCustomVideoDeviceWidget::OnDepthChanged() { double depth = ui->m_UsDepth->currentText().toDouble(); + MITK_INFO << "OnDepthChanged() " << depth; m_ControlInterface->SetNewDepth(depth); } void QmitkUSControlsCustomVideoDeviceWidget::OnProbeChanged() { std::string probename = ui->m_ProbeIdentifier->currentText().toStdString(); m_ControlInterface->SetNewProbeIdentifier(probename); SetDepthsForProbe(probename); } void QmitkUSControlsCustomVideoDeviceWidget::BlockSignalAndSetValue(QSpinBox* target, int value) { bool oldState = target->blockSignals(true); target->setValue(value); target->blockSignals(oldState); } void QmitkUSControlsCustomVideoDeviceWidget::SetDepthsForProbe(std::string probename) { ui->m_UsDepth->clear(); std::vector depths = m_ControlInterface->GetDepthsForProbe(probename); for (std::vector::iterator it = depths.begin(); it != depths.end(); it++) { ui->m_UsDepth->addItem(QString::number(*it)); } } diff --git a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp index 4912d53cad..8b72ad79a4 100644 --- a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp +++ b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp @@ -1,405 +1,811 @@ /*=================================================================== 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 // QT headers #include +#include // mitk headers // itk headers +#include +#include + const std::string QmitkUSNewVideoDeviceWidget::VIEW_ID = "org.mitk.views.QmitkUSNewVideoDeviceWidget"; QmitkUSNewVideoDeviceWidget::QmitkUSNewVideoDeviceWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; CreateQtPartControl(this); } QmitkUSNewVideoDeviceWidget::~QmitkUSNewVideoDeviceWidget() {} //////////////////// INITIALIZATION ///////////////////// void QmitkUSNewVideoDeviceWidget::CreateQtPartControl(QWidget* parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkUSNewVideoDeviceWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); } } void QmitkUSNewVideoDeviceWidget::CreateConnections() { if (m_Controls) { // connect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, // SLOT(OnClickedDone())); connect(m_Controls->m_BtnCancel, SIGNAL(clicked()), this, SLOT(OnClickedCancel())); connect(m_Controls->m_RadioDeviceSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection())); connect(m_Controls->m_RadioFileSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection())); connect(m_Controls->m_RadioOIGTLClientSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection())); connect(m_Controls->m_RadioOIGTLServerSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection())); connect(m_Controls->m_OpenFileButton, SIGNAL(clicked()), this, SLOT(OnOpenFileButtonClicked())); + connect(m_Controls->m_BtnSave, SIGNAL(clicked()), this, + SLOT(OnSaveButtonClicked())); + connect(m_Controls->m_BtnLoadConfiguration, SIGNAL(clicked()), this, + SLOT(OnLoadConfigurationButtonClicked())); + //Connect buttons and functions for editing of probes + connect(m_Controls->m_AddNewProbePushButton, SIGNAL(clicked()), this, SLOT(OnAddNewProbeClicked())); connect(m_Controls->m_BtnRemoveProbe, SIGNAL(clicked()), this, SLOT(OnClickedRemoveProbe())); connect(m_Controls->m_BtnRemoveDepth, SIGNAL(clicked()), this, SLOT(OnClickedRemoveDepth())); connect(m_Controls->m_BtnAddDepths, SIGNAL(clicked()), this, SLOT(OnClickedAddDepths())); connect(m_Controls->m_Probes, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnProbeChanged(const QString &))); + connect(m_Controls->m_Depths, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnDepthChanged(const QString &))); + + connect(m_Controls->m_XSpacingSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnXSpacingSpinBoxChanged(double))); + connect(m_Controls->m_YSpacingSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnYSpacingSpinBoxChanged(double))); + connect(m_Controls->m_CroppingTopSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnCroppingTopSpinBoxChanged(int))); + connect(m_Controls->m_CroppingRightSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnCroppingRightSpinBoxChanged(int))); + connect(m_Controls->m_CroppingBottomSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnCroppingBottomSpinBoxChanged(int))); + connect(m_Controls->m_CroppingLeftSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnCroppingLeftSpinBoxChanged(int))); } } ///////////// Methods & Slots Handling Direct Interaction ///////////////// void QmitkUSNewVideoDeviceWidget::OnClickedDone() { m_Active = false; // Create Device mitk::USVideoDevice::Pointer newDevice; if (m_Controls->m_RadioDeviceSource->isChecked()) { newDevice = mitk::USVideoDevice::New( m_Controls->m_DeviceSelector->value(), m_Controls->m_Manufacturer->text().toStdString(), m_Controls->m_Model->text().toStdString()); newDevice->SetComment(m_Controls->m_Comment->text().toStdString()); } else if (m_Controls->m_RadioFileSource->isChecked()) { newDevice = mitk::USVideoDevice::New( m_Controls->m_FilePathSelector->text().toStdString(), m_Controls->m_Manufacturer->text().toStdString(), m_Controls->m_Model->text().toStdString()); newDevice->SetComment(m_Controls->m_Comment->text().toStdString()); } else if (m_Controls->m_RadioOIGTLClientSource->isChecked()) { std::string host = m_Controls->m_OIGTLClientHost->text().toStdString(); int port = m_Controls->m_OIGTLClientPort->value(); // Create a new USIGTLDevice. The last parameter tells the device that it should be a client. mitk::USIGTLDevice::Pointer device = mitk::USIGTLDevice::New(m_Controls->m_Manufacturer->text().toStdString(), m_Controls->m_Model->text().toStdString(), host, port, false); device->Initialize(); emit Finished(); // The rest of this method does stuff that is specific to USVideoDevices, // which we don't need. So we return directly. return; } else { std::string host = m_Controls->m_OIGTLServerHost->text().toStdString(); int port = m_Controls->m_OIGTLServerPort->value(); // Create a new USIGTLDevice. The last parameter tells the device that it should be a server. mitk::USIGTLDevice::Pointer device = mitk::USIGTLDevice::New(m_Controls->m_Manufacturer->text().toStdString(), m_Controls->m_Model->text().toStdString(), host, port, true); device->Initialize(); emit Finished(); // The rest of this method does stuff that is specific to USVideoDevices, // which we don't need. So we return directly. return; } // get USImageVideoSource from new device mitk::USImageVideoSource::Pointer imageSource = dynamic_cast( newDevice->GetUSImageSource().GetPointer()); if (!imageSource) { MITK_ERROR << "There is no USImageVideoSource at the current device."; mitkThrow() << "There is no USImageVideoSource at the current device."; } // Set Video Options imageSource->SetColorOutput(!m_Controls->m_CheckGreyscale->isChecked()); // If Resolution override is activated, apply it if (m_Controls->m_CheckResolutionOverride->isChecked()) { int width = m_Controls->m_ResolutionWidth->value(); int height = m_Controls->m_ResolutionHeight->value(); imageSource->OverrideResolution(width, height); imageSource->SetResolutionOverride(true); } - if (!m_Controls->m_ProbesInformation->text().isEmpty()) //there are informations about the probes of the device, so create the probes + if (m_Controls->m_Probes->count() != 0 ) //there are informations about the probes of the device, so create the probes { - AddProbesToDevice(newDevice); + this->AddProbesToDevice(newDevice); } else //no information about the probes of the device, so set default value { mitk::USProbe::Pointer probe = mitk::USProbe::New("default"); probe->SetDepth(0); + newDevice->DeleteAllProbes(); newDevice->AddNewProbe(probe); } newDevice->Initialize(); CleanUpAfterCreatingNewDevice(); emit Finished(); } void QmitkUSNewVideoDeviceWidget::OnClickedFinishedEditing() { m_Active = false; m_TargetDevice->SetManufacturer(m_Controls->m_Manufacturer->text().toStdString()); m_TargetDevice->SetName(m_Controls->m_Model->text().toStdString()); m_TargetDevice->SetComment(m_Controls->m_Comment->text().toStdString()); - if (!m_Controls->m_ProbesInformation->text().isEmpty()){ //there is information about probes to add, so add them - AddProbesToDevice(m_TargetDevice); + if (m_Controls->m_Probes->count() != 0) //there are informations about the probes of the device, so create the probes + { + this->AddProbesToDevice(m_TargetDevice); + } + else //no information about the probes of the device, so set default value + { + mitk::USProbe::Pointer probe = mitk::USProbe::New("default"); + probe->SetDepth(0); + m_TargetDevice->DeleteAllProbes(); + m_TargetDevice->AddNewProbe(probe); } + mitk::USImageVideoSource::Pointer imageSource = dynamic_cast( m_TargetDevice->GetUSImageSource().GetPointer()); if (!imageSource) { MITK_ERROR << "There is no USImageVideoSource at the current device."; mitkThrow() << "There is no USImageVideoSource at the current device."; } // Set Video Options imageSource->SetColorOutput(!m_Controls->m_CheckGreyscale->isChecked()); // If Resolution override is activated, apply it if (m_Controls->m_CheckResolutionOverride->isChecked()) { int width = m_Controls->m_ResolutionWidth->value(); int height = m_Controls->m_ResolutionHeight->value(); imageSource->OverrideResolution(width, height); imageSource->SetResolutionOverride(true); } CleanUpAfterEditingOfDevice(); MITK_INFO << "Finished Editing"; emit Finished(); } void QmitkUSNewVideoDeviceWidget::OnClickedCancel() { m_TargetDevice = nullptr; m_Active = false; CleanUpAfterCreatingNewDevice(); CleanUpAfterEditingOfDevice(); emit Finished(); } void QmitkUSNewVideoDeviceWidget::OnDeviceTypeSelection() { m_Controls->m_FilePathSelector->setEnabled( m_Controls->m_RadioFileSource->isChecked()); m_Controls->m_DeviceSelector->setEnabled( m_Controls->m_RadioDeviceSource->isChecked()); m_Controls->m_OIGTLClientHost->setEnabled( m_Controls->m_RadioOIGTLClientSource->isChecked()); m_Controls->m_OIGTLClientPort->setEnabled( m_Controls->m_RadioOIGTLClientSource->isChecked()); m_Controls->m_OIGTLServerHost->setEnabled( m_Controls->m_RadioOIGTLServerSource->isChecked()); m_Controls->m_OIGTLServerPort->setEnabled( m_Controls->m_RadioOIGTLServerSource->isChecked()); } void QmitkUSNewVideoDeviceWidget::OnOpenFileButtonClicked() { QString fileName = QFileDialog::getOpenFileName(nullptr, "Open Video File"); if (fileName.isNull()) { return; } // user pressed cancel m_Controls->m_FilePathSelector->setText(fileName); m_Controls->m_RadioFileSource->setChecked(true); this->OnDeviceTypeSelection(); } ///////////////// Methods & Slots Handling Logic ////////////////////////// void QmitkUSNewVideoDeviceWidget::EditDevice(mitk::USDevice::Pointer device) { // If no VideoDevice is given, throw an exception - if (device.IsNull()) - { - mitkThrow() << "No device selected"; - } - else if (device->GetDeviceClass().compare("org.mitk.modules.us.USVideoDevice") != + if (device->GetDeviceClass().compare("org.mitk.modules.us.USVideoDevice") != 0) { // TODO Alert if bad path mitkThrow() << "NewVideoDeviceWidget recieved an incompatible device type " "to edit. Type was: " << device->GetDeviceClass(); } m_TargetDevice = static_cast(device.GetPointer()); m_Active = true; - + m_ConfigProbes.clear(); + m_ConfigProbes = m_TargetDevice->GetAllProbes(); ChangeUIEditingUSVideoDevice(); } void QmitkUSNewVideoDeviceWidget::CreateNewDevice() { - //When new device is created there are no probes to edit, therefore disable the Groupbox - m_Controls->m_GroupBoxEditProbes->setEnabled(false); - //Toggle functionality of Btn_Done connect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedDone())); m_Controls->m_BtnDone->setText("Add Video Device"); //Fill Metadata with default information m_Controls->m_Manufacturer->setText("Unknown Manufacturer"); m_Controls->m_Model->setText("Unknown Model"); m_Controls->m_Comment->setText("None"); m_TargetDevice = nullptr; + m_ConfigProbes.clear(); m_Active = true; } /////////////////////// HOUSEHOLDING CODE /////////////////////////////// QListWidgetItem* QmitkUSNewVideoDeviceWidget::ConstructItemFromDevice( mitk::USDevice::Pointer device) { QListWidgetItem* result = new QListWidgetItem; std::string text = device->GetManufacturer() + "|" + device->GetName(); result->setText(text.c_str()); return result; } void QmitkUSNewVideoDeviceWidget::ChangeUIEditingUSVideoDevice() { - //activate the groupbox contaning the options to edit the probes of the device and fill it with information - m_Controls->m_GroupBoxEditProbes->setEnabled(true); - std::vector probes = m_TargetDevice->GetAllProbes(); - for (std::vector::iterator it = probes.begin(); it != probes.end(); it++) + for (std::vector::iterator it = m_ConfigProbes.begin(); it != m_ConfigProbes.end(); it++) { std::string probeName = (*it)->GetName(); m_Controls->m_Probes->addItem(QString::fromUtf8(probeName.data(), probeName.size())); } OnProbeChanged(m_Controls->m_Probes->currentText()); //Toggle functionality of Btn_Done - m_Controls->m_BtnDone->setText("Save Changes"); + m_Controls->m_BtnDone->setText("Apply Changes"); connect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedFinishedEditing())); //Fill Metadata with Information provided by the Device selected to edit m_Controls->m_Manufacturer->setText(m_TargetDevice->GetManufacturer().c_str()); m_Controls->m_Model->setText(m_TargetDevice->GetName().c_str()); m_Controls->m_Comment->setText(m_TargetDevice->GetComment().c_str()); } void QmitkUSNewVideoDeviceWidget::OnClickedAddDepths() { if (!m_Controls->m_Probes->currentText().isEmpty()) { - std::string probename = m_Controls->m_Probes->currentText().toStdString(); - mitk::USProbe::Pointer currentProbe = m_TargetDevice->GetProbeByName(probename); QString depths = m_Controls->m_AddDepths->text(); + if( depths.isEmpty() ) + return; + + std::string probename = m_Controls->m_Probes->currentText().toStdString(); + mitk::USProbe::Pointer currentProbe = this->CheckIfProbeExistsAlready(probename); + QStringList singleDepths = depths.split(','); for (int i = 0; i < singleDepths.size(); i++) { currentProbe->SetDepth(singleDepths.at(i).toInt()); } m_Controls->m_AddDepths->clear(); + m_Controls->m_Depths->setEnabled(true); + m_Controls->m_BtnRemoveDepth->setEnabled(true); OnProbeChanged(m_Controls->m_Probes->currentText()); } } void QmitkUSNewVideoDeviceWidget::OnClickedRemoveDepth() { if (!m_Controls->m_Probes->currentText().isEmpty() && !m_Controls->m_Depths->currentText().isEmpty()) { std::string probename = m_Controls->m_Probes->currentText().toStdString(); int indexOfDepthToRemove = m_Controls->m_Depths->currentIndex(); - mitk::USProbe::Pointer currentProbe = m_TargetDevice->GetProbeByName(probename); + mitk::USProbe::Pointer currentProbe = this->CheckIfProbeExistsAlready(probename); currentProbe->RemoveDepth(m_Controls->m_Depths->currentText().toInt()); m_Controls->m_Depths->removeItem(indexOfDepthToRemove); + + if (m_Controls->m_Depths->count() == 0) + { + m_Controls->m_Depths->setEnabled(false); + m_Controls->m_BtnRemoveDepth->setEnabled(false); + + this->EnableDisableSpacingAndCropping(false); + } } } void QmitkUSNewVideoDeviceWidget::OnClickedRemoveProbe() { if (!m_Controls->m_Probes->currentText().isEmpty()) { std::string probename = m_Controls->m_Probes->currentText().toStdString(); int indexOfProbeToRemove = m_Controls->m_Probes->currentIndex(); - m_TargetDevice->RemoveProbeByName(probename); + m_ConfigProbes.erase(m_ConfigProbes.begin() + indexOfProbeToRemove); m_Controls->m_Probes->removeItem(indexOfProbeToRemove); + if( m_Controls->m_Probes->count() == 0 ) + { + m_Controls->m_Probes->setEnabled(false); + m_Controls->m_BtnRemoveProbe->setEnabled(false); + m_Controls->m_BtnAddDepths->setEnabled(false); + m_Controls->m_AddDepths->setEnabled(false); + m_Controls->m_Depths->setEnabled(false); + m_Controls->m_BtnRemoveDepth->setEnabled(false); + + this->EnableDisableSpacingAndCropping(false); + } } } void QmitkUSNewVideoDeviceWidget::OnProbeChanged(const QString & probename) { if (!probename.isEmpty()) { std::string name = probename.toStdString(); - mitk::USProbe::Pointer probe = m_TargetDevice->GetProbeByName(name); - std::map depths = probe->GetDepthsAndSpacing(); + mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(name); + if( probe.IsNotNull() ) + { + std::map depths = probe->GetDepthsAndSpacing(); + m_Controls->m_Depths->clear(); + for (std::map::iterator it = depths.begin(); it != depths.end(); it++) + { + m_Controls->m_Depths->addItem(QString::number(it->first)); + } + + this->OnDepthChanged(m_Controls->m_Depths->currentText().toInt(), probe); + } + } + else + { m_Controls->m_Depths->clear(); - for (std::map::iterator it = depths.begin(); it != depths.end(); it++) + m_Controls->m_Depths->setEnabled(false); + m_Controls->m_BtnRemoveDepth->setEnabled(false); + } +} + +void QmitkUSNewVideoDeviceWidget::OnDepthChanged(int depth, mitk::USProbe* probe) +{ + if (m_Controls->m_Depths->count() == 0) + { + m_Controls->m_Depths->setEnabled(false); + m_Controls->m_BtnRemoveDepth->setEnabled(false); + + this->EnableDisableSpacingAndCropping(false); + return; + } + + if (probe != nullptr) + { + mitk::Vector3D spacing = probe->GetSpacingForGivenDepth(depth); + m_Controls->m_XSpacingSpinBox->setValue(spacing[0]); + m_Controls->m_YSpacingSpinBox->setValue(spacing[1]); + + mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); + m_Controls->m_CroppingTopSpinBox->setValue(cropping.top); + m_Controls->m_CroppingRightSpinBox->setValue(cropping.right); + m_Controls->m_CroppingBottomSpinBox->setValue(cropping.bottom); + m_Controls->m_CroppingLeftSpinBox->setValue(cropping.left); + + this->EnableDisableSpacingAndCropping(true); + + m_Controls->m_Depths->setEnabled(true); + m_Controls->m_BtnRemoveDepth->setEnabled(true); + m_Controls->m_AddDepths->setEnabled(true); + m_Controls->m_BtnAddDepths->setEnabled(true); + m_Controls->m_Probes->setEnabled(true); + m_Controls->m_BtnRemoveProbe->setEnabled(true); + } +} + +void QmitkUSNewVideoDeviceWidget::OnDepthChanged(const QString &depth) +{ + MITK_INFO << "OnDepthChanged(int, mitk::USProbe)"; + if( depth.isEmpty() ) + { + this->EnableDisableSpacingAndCropping(false); + return; + } + QString probeName = m_Controls->m_Probes->currentText(); + + this->OnDepthChanged(depth.toInt(), this->CheckIfProbeExistsAlready(probeName.toStdString()) ); +} + +void QmitkUSNewVideoDeviceWidget::OnSaveButtonClicked() +{ + QString fileName = QFileDialog::getSaveFileName(nullptr, "Save Configuration ...", "", "XML files (*.xml)"); + if( fileName.isNull() ) + { + return; + } // user pressed cancel + + mitk::USDeviceWriterXML deviceWriter; + deviceWriter.SetFilename(fileName.toStdString()); + + mitk::USDeviceReaderXML::USVideoDeviceConfigData config; + this->CollectUltrasoundVideoDeviceConfigInformation(config); + + if (!deviceWriter.WriteUltrasoundVideoDeviceConfiguration(config)) + { + QMessageBox msgBox; + msgBox.setText("Error when writing the configuration to the selected file. Could not write device information."); + msgBox.exec(); + return; + } + +} + +void QmitkUSNewVideoDeviceWidget::OnLoadConfigurationButtonClicked() +{ + QString fileName = QFileDialog::getOpenFileName(this, "Open ultrasound device configuration ..."); + if (fileName.isNull()) + { + return; + } // user pressed cancel + + mitk::USDeviceReaderXML deviceReader; + deviceReader.SetFilename(fileName.toStdString()); + if (!deviceReader.ReadUltrasoundDeviceConfiguration()) + { + QMessageBox msgBox; + msgBox.setText("Error when parsing the selected file. Could not load stored device information."); + msgBox.exec(); + return; + } + mitk::USDeviceReaderXML::USVideoDeviceConfigData config = deviceReader.GetUSVideoDeviceConfigData(); + + if( config.fileversion == 1.0 ) + { + if (config.deviceType.compare("video") == 0) + { + //Fill info in metadata groupbox: + m_Controls->m_DeviceName->setText(QString::fromStdString(config.deviceName)); + m_Controls->m_Manufacturer->setText(QString::fromStdString(config.manufacturer)); + m_Controls->m_Model->setText(QString::fromStdString(config.model)); + m_Controls->m_Comment->setText(QString::fromStdString(config.comment)); + + //Fill info about video source: + m_Controls->m_DeviceSelector->setValue(config.sourceID); + m_Controls->m_FilePathSelector->setText(QString::fromStdString(config.filepathVideoSource)); + + //Fill video options: + m_Controls->m_CheckGreyscale->setChecked(config.useGreyscale); + + //Fill override options: + m_Controls->m_CheckResolutionOverride->setChecked(config.useResolutionOverride); + m_Controls->m_ResolutionWidth->setValue(config.resolutionWidth); + m_Controls->m_ResolutionHeight->setValue(config.resolutionHeight); + + //Fill information about probes: + m_ConfigProbes.clear(); + m_ConfigProbes = config.probes; + + m_Controls->m_Probes->clear(); + m_Controls->m_ProbeNameLineEdit->clear(); + m_Controls->m_AddDepths->clear(); + m_Controls->m_Depths->clear(); + + for( size_t index = 0; index < m_ConfigProbes.size(); ++index) + { + m_Controls->m_Probes->addItem(QString::fromStdString(config.probes.at(index)->GetName())); + } + this->OnProbeChanged(m_Controls->m_Probes->currentText()); + + } + else { - m_Controls->m_Depths->addItem(QString::number(it->first)); + MITK_WARN << "Unknown device type detected. The device type must be of type |video|"; } } + else + { + MITK_WARN << "Unknown fileversion. Only fileversion 1.0 is known to the system."; + } +} + +void QmitkUSNewVideoDeviceWidget::OnAddNewProbeClicked() +{ + QString probeName = m_Controls->m_ProbeNameLineEdit->text(); + probeName = probeName.trimmed(); + if (probeName.isEmpty()) + { + m_Controls->m_ProbeNameLineEdit->clear(); + return; + } + + if( this->CheckIfProbeExistsAlready(probeName.toStdString() ) != nullptr ) + { + QMessageBox msgBox; + msgBox.setText("Probe name already exists. Please choose another name for the probe."); + msgBox.exec(); + m_Controls->m_ProbeNameLineEdit->clear(); + } + else + { + mitk::USProbe::Pointer newProbe = mitk::USProbe::New(probeName.toStdString()); + m_ConfigProbes.push_back(newProbe); + m_Controls->m_Probes->addItem(QString::fromStdString(probeName.toStdString())); + + m_Controls->m_Probes->setEnabled(true); + m_Controls->m_BtnRemoveProbe->setEnabled(true); + m_Controls->m_BtnAddDepths->setEnabled(true); + m_Controls->m_AddDepths->setEnabled(true); + m_Controls->m_ProbeNameLineEdit->clear(); + } +} + +void QmitkUSNewVideoDeviceWidget::OnXSpacingSpinBoxChanged(double value) +{ + MITK_INFO << "Changing x-spacing to: " << value; + QString probeName = m_Controls->m_Probes->currentText(); + int depth = m_Controls->m_Depths->currentText().toInt(); + + mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); + if (probe.IsNull()) + { + QMessageBox msgBox; + msgBox.setText("An error occurred when changing the spacing. \ + The specified probe does not exist. \ + Please restart the configuration process."); + msgBox.exec(); + return; + } + + mitk::Vector3D spacing = probe->GetSpacingForGivenDepth(depth); + spacing[0] = value; + probe->SetSpacingForGivenDepth(depth, spacing); +} + +void QmitkUSNewVideoDeviceWidget::OnYSpacingSpinBoxChanged(double value) +{ + MITK_INFO << "Changing y-spacing to: " << value; + QString probeName = m_Controls->m_Probes->currentText(); + int depth = m_Controls->m_Depths->currentText().toInt(); + + mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); + if (probe.IsNull()) + { + QMessageBox msgBox; + msgBox.setText("An error occurred when changing the spacing. \ + The specified probe does not exist. \ + Please restart the configuration process."); + msgBox.exec(); + return; + } + + mitk::Vector3D spacing = probe->GetSpacingForGivenDepth(depth); + spacing[1] = value; + probe->SetSpacingForGivenDepth(depth, spacing); +} + +void QmitkUSNewVideoDeviceWidget::OnCroppingTopSpinBoxChanged(int value) +{ + MITK_INFO << "Changing cropping top to: " << value; + QString probeName = m_Controls->m_Probes->currentText(); + + mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); + if (probe.IsNull()) + { + QMessageBox msgBox; + msgBox.setText("An error occurred when changing the probe cropping. \ + The specified probe does not exist. \ + Please restart the configuration process."); + msgBox.exec(); + return; + } + + mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); + probe->SetProbeCropping(value, cropping.bottom, cropping.left, cropping.right); +} + +void QmitkUSNewVideoDeviceWidget::OnCroppingRightSpinBoxChanged(int value) +{ + MITK_INFO << "Changing cropping right to: " << value; + QString probeName = m_Controls->m_Probes->currentText(); + + mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); + if (probe.IsNull()) + { + QMessageBox msgBox; + msgBox.setText("An error occurred when changing the probe cropping. \ + The specified probe does not exist. \ + Please restart the configuration process."); + msgBox.exec(); + return; + } + + mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); + probe->SetProbeCropping(cropping.top, cropping.bottom, cropping.left, value); +} + +void QmitkUSNewVideoDeviceWidget::OnCroppingBottomSpinBoxChanged(int value) +{ + MITK_INFO << "Changing cropping bottom to: " << value; + QString probeName = m_Controls->m_Probes->currentText(); + + mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); + if (probe.IsNull()) + { + QMessageBox msgBox; + msgBox.setText("An error occurred when changing the probe cropping. \ + The specified probe does not exist. \ + Please restart the configuration process."); + msgBox.exec(); + return; + } + + mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); + probe->SetProbeCropping(cropping.top, value, cropping.left, cropping.right); +} + +void QmitkUSNewVideoDeviceWidget::OnCroppingLeftSpinBoxChanged(int value) +{ + MITK_INFO << "Changing cropping left to: " << value; + QString probeName = m_Controls->m_Probes->currentText(); + + mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); + if (probe.IsNull()) + { + QMessageBox msgBox; + msgBox.setText("An error occurred when changing the probe cropping. \ + The specified probe does not exist. \ + Please restart the configuration process."); + msgBox.exec(); + return; + } + + mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); + probe->SetProbeCropping(cropping.top, cropping.bottom, value, cropping.right); } void QmitkUSNewVideoDeviceWidget::CleanUpAfterCreatingNewDevice() { disconnect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedDone())); - m_Controls->m_ProbesInformation->clear(); + m_Controls->m_Probes->clear(); + m_Controls->m_Depths->clear(); + m_Controls->m_AddDepths->clear(); + m_Controls->m_ProbeNameLineEdit->clear(); + m_ConfigProbes.clear(); } void QmitkUSNewVideoDeviceWidget::CleanUpAfterEditingOfDevice() { disconnect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedFinishedEditing())); m_Controls->m_Probes->clear(); m_Controls->m_Depths->clear(); m_Controls->m_AddDepths->clear(); - m_Controls->m_ProbesInformation->clear(); + m_ConfigProbes.clear(); } void QmitkUSNewVideoDeviceWidget::AddProbesToDevice(mitk::USVideoDevice::Pointer device) { - QString probesInformation = m_Controls->m_ProbesInformation->text(); - QStringList probes = probesInformation.split(';'); //split the different probes - for (int i = 0; i < probes.size(); i++) + device->DeleteAllProbes(); + for( std::vector::iterator it = m_ConfigProbes.begin(); + it != m_ConfigProbes.end(); it++) { - QStringList depths = probes.at(i).split(','); //now for every probe split the probe name and the different depths - mitk::USProbe::Pointer probe = mitk::USProbe::New(); - probe->SetName(depths.at(0).toStdString()); //first element is the probe name - for (int i = 1; i < depths.size(); i++) //all the other elements are the depths for the specific probe so add them to the probe + if ((*it)->IsDepthAndSpacingEmpty()) { - probe->SetDepth(depths.at(i).toInt()); + (*it)->SetDepth(0); } - device->AddNewProbe(probe); + device->AddNewProbe((*it)); + } +} + +mitk::USProbe::Pointer QmitkUSNewVideoDeviceWidget::CheckIfProbeExistsAlready(std::string &probeName) +{ + for( std::vector::iterator it = m_ConfigProbes.begin(); + it != m_ConfigProbes.end(); it++ ) + { + if( probeName.compare((*it)->GetName()) == 0) + return (*it); } + return nullptr; //no matching probe was found so nullptr is returned +} + +void QmitkUSNewVideoDeviceWidget::CollectUltrasoundVideoDeviceConfigInformation(mitk::USDeviceReaderXML::USVideoDeviceConfigData &config) +{ + config.fileversion = 1.0; + config.deviceType = "video"; + + //Fill info in metadata groupbox: + config.deviceName = m_Controls->m_DeviceName->text().toStdString(); + config.manufacturer = m_Controls->m_Manufacturer->text().toStdString(); + config.model = m_Controls->m_Model->text().toStdString(); + config.comment = m_Controls->m_Comment->text().toStdString(); + + //Fill info about video source: + config.sourceID = m_Controls->m_DeviceSelector->value(); + config.filepathVideoSource = m_Controls->m_FilePathSelector->text().toStdString(); + + //Fill video options: + config.useGreyscale = m_Controls->m_CheckGreyscale->isChecked(); + + //Fill override options: + config.useResolutionOverride = m_Controls->m_CheckResolutionOverride->isChecked(); + config.resolutionWidth = m_Controls->m_ResolutionWidth->value(); + config.resolutionHeight = m_Controls->m_ResolutionHeight->value(); + + //Fill information about probes: + config.probes = m_ConfigProbes; +} + +void QmitkUSNewVideoDeviceWidget::EnableDisableSpacingAndCropping(bool enable) +{ + m_Controls->m_XSpacingSpinBox->setEnabled(enable); + m_Controls->m_YSpacingSpinBox->setEnabled(enable); + m_Controls->m_XSpacingLabel->setEnabled(enable); + m_Controls->m_YSpacingLabel->setEnabled(enable); + + m_Controls->m_CroppingTopSpinBox->setEnabled(enable); + m_Controls->m_CroppingRightSpinBox->setEnabled(enable); + m_Controls->m_CroppingBottomSpinBox->setEnabled(enable); + m_Controls->m_CroppingLeftSpinBox->setEnabled(enable); + m_Controls->m_CroppingTopLabel->setEnabled(enable); + m_Controls->m_CroppingBottomLabel->setEnabled(enable); + m_Controls->m_CroppingLeftLabel->setEnabled(enable); + m_Controls->m_CroppingRightLabel->setEnabled(enable); } diff --git a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.h b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.h index be811eb4ed..531d3a342b 100644 --- a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.h +++ b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.h @@ -1,130 +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. ===================================================================*/ #ifndef _QmitkUSNewVideoDeviceWidget_H_INCLUDED #define _QmitkUSNewVideoDeviceWidget_H_INCLUDED #include "MitkUSUIExports.h" #include "ui_QmitkUSNewVideoDeviceWidgetControls.h" #include "mitkUSVideoDevice.h" #include "mitkUSIGTLDevice.h" +#include "mitkUSDeviceReaderXML.h" //QT headers #include #include //mitk header /** * @brief This Widget enables the USer to create and connect Video Devices. * * @ingroup USUI */ class MITKUSUI_EXPORT QmitkUSNewVideoDeviceWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkUSNewVideoDeviceWidget(QWidget* p = nullptr, Qt::WindowFlags f1 = nullptr); ~QmitkUSNewVideoDeviceWidget() override; /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); signals: void Finished(); public slots: /* \brief Activates the widget and displays the given device's Data to edit. */ void EditDevice(mitk::USDevice::Pointer device); /* \brief Activates the widget with fields empty. */ void CreateNewDevice(); protected slots: /* \brief Called, when the the user clicks the "Done" button (Labeled either "Add Device" or "Edit Device", depending on the situation. */ void OnClickedDone(); void OnClickedFinishedEditing(); /* \brief Called, when the button "Cancel" was clicked */ void OnClickedCancel(); /* \brief Called, when the Use selects one of the Radiobuttons */ void OnDeviceTypeSelection(); void OnOpenFileButtonClicked(); void OnClickedRemoveProbe(); void OnClickedRemoveDepth(); void OnClickedAddDepths(); void OnProbeChanged(const QString & probename); + void OnDepthChanged(int depth, mitk::USProbe* probe); + + void OnDepthChanged(const QString &depth); + + void OnSaveButtonClicked(); + + void OnLoadConfigurationButtonClicked(); + + void OnAddNewProbeClicked(); + + void OnXSpacingSpinBoxChanged(double value); + + void OnYSpacingSpinBoxChanged(double value); + + void OnCroppingTopSpinBoxChanged(int value); + + void OnCroppingRightSpinBoxChanged(int value); + + void OnCroppingBottomSpinBoxChanged(int value); + + void OnCroppingLeftSpinBoxChanged(int value); + protected: Ui::QmitkUSNewVideoDeviceWidgetControls* m_Controls; ///< member holding the UI elements of this widget /* \brief Constructs a ListItem from the given device for display in the list of active devices */ QListWidgetItem* ConstructItemFromDevice(mitk::USDevice::Pointer device); void ChangeUIEditingUSVideoDevice(); void CleanUpAfterEditingOfDevice(); void CleanUpAfterCreatingNewDevice(); void AddProbesToDevice(mitk::USVideoDevice::Pointer device); + mitk::USProbe::Pointer CheckIfProbeExistsAlready(std::string &probe); + + void CollectUltrasoundVideoDeviceConfigInformation(mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + + /** + * \brief Enables or disables the GUI elements of the spacing and cropping options. + * \param enable If true: the GUI elements are enabled. If false: elements are disabled. + */ + void EnableDisableSpacingAndCropping(bool enable); + /* \brief Displays whether this widget is active or not. It gets activated by either sending a Signal to * the "CreateNewDevice" Slot or to the "EditDevice" Slot. If the user finishes editing the device, a * "EditingComplete" Signal is sent, and the widget is set to inactive again. Clicking Cancel also * deactivates it. */ bool m_Active; /** * \brief This is the device to edit. It is either the device transmitted in the "EditDevice" signal, or a new one * if the "CreateNewDevice slot was called. */ mitk::USVideoDevice::Pointer m_TargetDevice; + + /** + * \brief The config probes are used to have a possibility to configure ultrasound probes without having an existing + * created USVideoDevice yet. + */ + std::vector m_ConfigProbes; }; #endif // _QmitkUSNewVideoDeviceWidget_H_INCLUDED diff --git a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui index 33f618298a..44e004599b 100644 --- a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui +++ b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui @@ -1,543 +1,710 @@ QmitkUSNewVideoDeviceWidgetControls 0 0 - 333 + 332 972 0 0 QmitkUSNewVideoDeviceWidget - + QLayout::SetDefaultConstraint - - QFormLayout::AllNonFixedFieldsGrow - 0 - 0 + 10 0 0 - + + + + + + Add Video Device + + + + :/USUI/accept.png:/USUI/accept.png + + + + + + + Cancel + + + + :/USUI/restart.png:/USUI/restart.png + + + + + + + + + 0 + + + + + Load Device Configuration + + + + + + + Save->File + + + + :/USUI/accept.png:/USUI/accept.png + + + + + + + + + Metadata: + + + + + + Unknown Manufacturer + + + + + + + Model + + + + + + + + 50 + false + true + + + + Device Information: + + + + + + + Comment + + + + + + + Manufacturer + + + + + + + Unknown Model + + + + + + + None + + + + + + + Name + + + + + + + USVideoDevice + + + + + + + Video Source: From Device: true 0 10 0 From File: false ... OIGTL Server false localhost false 1 65535 18944 OIGTL Client false localhost false 1 65535 18944 - - - - Video Options: - - - - - - Greyscale Image (Significantly faster) - - - true - - - - - - - - - - - - Add Video Device - - - - :/USUI/accept.png:/USUI/accept.png - - - - - - - Cancel - - - - :/USUI/restart.png:/USUI/restart.png - - - - - - - - - - 0 - 0 - + + + + true - 50 - 130 + 0 + 180 - Add Probes - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Edit Probes - - - - - Enter the names of the probes of the VideoDevice and, separated by commas, its scanning depths. If you want to add several probes separate the probes and their informations by semicolons E.g. ACV,100,120,150;BDW,90,100;CSV,120,150,180 + + + + + false - - Qt::AutoText + + 6 - - true + + 0.000001000000000 - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + 1.000000000000000 - - true + + 0.010000000000000 - - -2 + + 1.000000000000000 - - + + + + false + + + Qt::WheelFocus + + + Enter a depth to add to the chosen probe + + - - - - - - - Override: - - - - + + + + true + - Width: + Probes - - - - - 0 - 0 - + + + + false - - 10 + + Qt::WheelFocus - - 2048 + + Add Depth - - 10 + + + + + + false - - 480 + + Cropping Right - - + + + + false + - Height: + Cropping Top - - - - - 0 - 0 - - - - 10 + + + + false - - 2048 + + Cropping Bottom - - 10 + + + + + + - - 640 + + Enter the name of the probe - - + + - Enable Resolution Override + Add New Probe - - - - If you encounter problems with devices (e.g. Images of uniform color and error messages in the log window), then try to set the resolution externally using the device's driver panel and then enter the same resolution here. + + + + false - - true + + Spacing Y-direction - - - - - - - false - - - - 0 - 180 - - - - Edit Probes - - - - + + + + false + - Probes + Spacing X-direction - - - - - 0 - 0 - + + + + false + + + 6 + + + 0.000001000000000 + + + 1.000000000000000 + + + 0.010000000000000 + + + 1.000000000000000 - + + + false + 0 0 Qt::WheelFocus Remove this Probe - - - - Scanning Depths for chosen Probe + + + + false + + + + 0 + 0 + - + + + false + 0 0 - + + + false + 0 0 Qt::WheelFocus Remove this Depth - + + + false + - Enter Scanning Depths you want to add to chosen Probe. -Seperate them by commas. E.g. 120,150,180 + Scanning depths for chosen probe - - - - Qt::WheelFocus + + + + false + + + 400 - - - - Qt::WheelFocus + + + + false + + + 400 + + + + + + + false - Add Depths + Cropping Left + + + + + + + false + + + 400 + + + + + + + false + + + 400 - - + + - Metadata: + Video Options: - - - + + + - Comment + Greyscale Image (Significantly faster) + + + true - - - - - 50 - false - true - - + + + + + + + Override: + + + + - Device Information: + Width: - - - - Manufacturer + + + + + 0 + 0 + + + + 10 + + + 2048 + + + 10 + + + 480 - - + + - Unknown Manufacturer + Height: - - - - Model + + + + + 0 + 0 + + + + 10 + + + 2048 + + + 10 + + + 640 - - + + - Unknown Model + Enable Resolution Override - - + + - None + If you encounter problems with devices (e.g. Images of uniform color and error messages in the log window), then try to set the resolution externally using the device's driver panel and then enter the same resolution here. + + + true m_Manufacturer m_Model m_Comment m_RadioDeviceSource m_DeviceSelector m_RadioFileSource m_CheckResolutionOverride diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataViewControls.ui index 575ec4f153..e7196a043c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataViewControls.ui @@ -1,306 +1,299 @@ QmitkConnectomicsDataViewControls 0 0 286 639 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 Input Data 6 6 6 6 QLabel { color: rgb(255, 0, 0) } Select a parcellation and a tractogram! Image 1: - Image 2: - Network Creation Options 6 6 6 6 Create a network from a parcellation and a fiber image Networkify Create Correlation Matrix true Synthetic Network Options 6 6 6 6 Parameter 2 false 3 999.899999999999977 Parameter 1 false 9999 Create Synthetic Networks 0 0 Anatomical labeling 6 6 6 6 Qt::Vertical 20 40 QmitkFreeSurferParcellationWidget QWidget
QmitkFreeSurferParcellationWidget.h
1
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsViewControls.ui index 5eba3ef537..50883169d6 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsViewControls.ui @@ -1,313 +1,306 @@ QmitkConnectomicsNetworkOperationsViewControls 0 0 283 639 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 Data 6 6 6 6 QLabel { color: rgb(255, 0, 0) } Select a network or a parcellation! Image 1: - Convert the selected image to RGBA format Turn Into RGBA Image Assign FreeSurfer Colors Divide in Modules Connectivity Matrix Image Options 6 6 6 6 Create Connectivity Matrix Image Rescale Binary Prune Options 6 6 6 6 Prune Network Target Density 1.000000000000000 0.010000000000000 Target Threshold Threshold weight Threshold Below Density Random Removal Threshold Qt::Vertical 20 40 \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsViewControls.ui index 7e3b0384ed..1610d78f61 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsViewControls.ui @@ -1,324 +1,317 @@ QmitkConnectomicsStatisticsViewControls 0 0 557 1218 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 Input Data 6 6 6 6 Network: Network Statistics 6 6 6 6 true 0 0 true Informational Balloons. 6 6 6 6 false PointingHandCursor Qt::RightToLeft true false false -1 12 QComboBox::InsertAlphabetically 0 0 MS Shell Dlg 2 8 IBeamCursor false true Histograms 6 6 6 6 0 0 50 150 50 150 50 150 Qt::Vertical 20 40 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkNetworkHistogramCanvas QWidget
internal/QmitkNetworkHistogramCanvas.h
1
networkBalloonsNodeLabelsComboBox currentIndexChanged(int) networkBalloonsNodeLabelsComboBox setCurrentIndex(int) 360 409 360 409
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationViewControls.ui index 832419054d..0078a5b273 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationViewControls.ui @@ -1,350 +1,343 @@ QmitkRandomParcellationViewControls true 0 0 327 591 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 QLabel { color: rgb(255, 0, 0) } Please select an image! true Nodes false 6 6 6 6 true Choose the number of nodes: 2 5000 true Merging 6 6 6 6 Merging on false QFrame::NoFrame QFrame::Raised 0 0 0 0 According to the number of parcels false QFrame::StyledPanel QFrame::Raised 0 0 0 Number of Parcels: 1 5000 According to the size of parcels false QFrame::StyledPanel QFrame::Raised 0 0 0 Size of the smallest parcel: 2 100000 Just merge small parcels false Do image processing Select random nodes Qt::Vertical 20 40 Counting 6 6 6 6 Number of voxels with value 1: Number of nodes: \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingViewControls.ui index bfb9603eb8..7f732f0e06 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingViewControls.ui @@ -1,382 +1,375 @@ QmitkDenoisingViewControls 0 0 351 734 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 9 9 9 9 25 QFrame::NoFrame QFrame::Raised 0 0 0 0 Input Image: Total-variation Discrete Gaussian Non-local means Filter: Parameters 6 6 6 6 Lambda: 4 0.000000000000000 1.000000000000000 0.100000000000000 0.100000000000000 Iterations: 1 999 1 Parameters 6 6 6 6 Sampling Radius: 1 999 10 1 999 4 1 999 4 Num. Patches: 1 50 1 Iterations: Patch Size: Parameters 6 6 6 6 4 1.000000000000000 99999.000000000000000 0.100000000000000 1.000000000000000 Variance: Start Qt::Vertical 20 40 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxViewControls.ui index d00a61791e..9228e80e1e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxViewControls.ui @@ -1,3615 +1,3608 @@ QmitkFiberfoxViewControls 0 0 463 875 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } Load Parameters :/QmitkDiffusionImaging/general_icons/upload.ico :/QmitkDiffusionImaging/general_icons/upload.ico Save Parameters :/QmitkDiffusionImaging/general_icons/download.ico :/QmitkDiffusionImaging/general_icons/download.ico Signal Generation 25 QFrame::NoFrame QFrame::Raised 0 0 0 0 true <html><head/><body><p>Start DWI generation from selected fiber bundle.</p><p>If no fiber bundle but an existing diffusion weighted image is selected, the enabled artifacts are added to this image.</p><p>If neither a fiber bundle nor a diffusion weighted image is selected, a grayscale image containing a simple gradient is generated.</p></body></html> Start Simulation :/QmitkDiffusionImaging/general_icons/right.ico :/QmitkDiffusionImaging/general_icons/right.ico Input Data 6 6 6 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 - ... <html><head/><body><p>Select a binary image to define the area of signal generation. Outside of the mask image only noise will be actively generated.</p></body></html> QComboBox::AdjustToMinimumContentsLength Fiber Bundle: false Save path: false Tissue Mask: false <html><head/><body><p>Select a fiber bundle to generate the white matter signal from. You can either use the fiber definition tab to manually define an input fiber bundle or you can also use any existing bundle, e.g. yielded by a tractography algorithm.</p></body></html> QComboBox::AdjustToMinimumContentsLength Template Image: false <html><head/><body><p>The parameters for the simulation (e.g. spacing, size, diffuison-weighted gradients, b-value) are adopted from this image.</p></body></html> QComboBox::AdjustToMinimumContentsLength true Stop current simulation. Abort Simulation :/QmitkDiffusionImaging/general_icons/abort.ico :/QmitkDiffusionImaging/general_icons/abort.ico Courier 7 true Extra-axonal Compartments 6 6 6 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 Volume Fraction: Select signal model for extra-axonal compartment. Ball Model Astrosticks Model Dot Model Prototype Signal Qt::Horizontal QFrame::NoFrame QFrame::Raised 0 0 0 0 Volume Fraction: Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. Select signal model for extra-axonal compartment. -- Ball Model Astrosticks Model Dot Model Prototype Signal Intra-axonal Compartment 6 6 6 6 Select signal model for intra-axonal compartment. Stick Model Zeppelin Model Tensor Model Prototype Signal QFrame::NoFrame QFrame::Raised 0 0 0 0 Volume Fraction: Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. Image Settings 6 6 6 6 Advanced Options QFrame::NoFrame QFrame::Raised 0 0 0 0 6 Gradient Directions: Number of gradient directions distributed over the half sphere. 0 10000 1 30 <html><head/><body><p>b-Value<span style=" font-style:italic;"> [s/mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">]</span>:</p></body></html> false b-value in s/mm² 0 10000 100 1000 color: rgb(255, 0, 0); Using geometry of selected image! color: rgb(255, 0, 0); Using gradients of selected DWI! QFrame::NoFrame QFrame::Raised 0 0 0 0 6 <html><head/><body><p>Number of Channels:</p></body></html> false TR in milliseconds 1 999999999 1 4000 Output one image per compartment containing the corresponding volume fractions per voxel. Reverse Phase Encoding Direction false Signal Scale: Dwell time (time to read one line in k-space) in ms. 100.000000000000000 0.100000000000000 1.000000000000000 TE in milliseconds 1 999999999 1 100 Fiber Radius: Partial Fourier: false Disable partial volume. Treat voxel content as fiber-only if at least one fiber is present. Disable Partial Volume Effects false <html><head/><body><p>Coil Sensitivity:</p></body></html> false Partial fourier factor (0.5-1) 3 0.500000000000000 1.000000000000000 0.100000000000000 1.000000000000000 Output phase image and volume fraction maps. Output Additional Images false Relaxation time due to magnetic field inhomogeneities (T2', in milliseconds). 1 10000 1 50 <html><head/><body><p>Repetition Time <span style=" font-style:italic;">TR</span>: </p></body></html> false Constant Linear Exponential Dwell Time: false <html><head/><body><p><span style=" font-style:italic;">T</span><span style=" font-style:italic; vertical-align:sub;">inhom</span> Relaxation: </p></body></html> false <html><head/><body><p><span style=" font-style:italic;">TE</span>, <span style=" font-style:italic;">T</span><span style=" font-style:italic; vertical-align:sub;">inhom</span> and <span style=" font-style:italic;">T2</span> will have no effect if unchecked.</p></body></html> Simulate Signal Relaxation true <html><head/><body><p>Echo Time <span style=" font-style:italic;">TE</span>: </p></body></html> false TE in milliseconds 1 10000 1 100 Number of coil elements used for the acquisiton. 1 128 1 1 Acquisition Type: Single Shot EPI Spin Echo Fiber radius used to calculate volume fractions (in µm). Set to 0 for automatic radius estimation. 9999.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 3 0.100000000000000 50.000000000000000 0.100000000000000 2.000000000000000 Image Spacing: 3 0.100000000000000 50.000000000000000 0.100000000000000 2.000000000000000 3 0.100000000000000 50.000000000000000 0.100000000000000 2.000000000000000 Image Dimensions: Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 1000 1 20 Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 1000 1 20 Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 1000 1 3 Inter-axonal Compartment 6 6 6 6 Select signal model for intra-axonal compartment. -- Stick Model Zeppelin Model Tensor Model QFrame::NoFrame QFrame::Raised 0 0 0 0 Volume Fraction: Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. Noise and other Artifacts 6 6 6 6 Add Distortions false Add Spikes false true QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 0 0 0 0 Gradient: false Eddy current induced magnetic field gradient (in mT/m). 4 1000.000000000000000 0.001000000000000 0.010000000000000 Add Motion Artifacts false Qt::Horizontal true QFrame::NoFrame QFrame::Raised 6 0 0 0 0 K-Space Line Offset: false A larger offset increases the inensity of the ghost image. 3 1.000000000000000 0.010000000000000 0.250000000000000 Add Noise false QFrame::NoFrame QFrame::Raised 0 0 0 0 Num. Spikes: The number of randomly occurring signal spikes. 1 Spike amplitude relative to the largest signal amplitude of the corresponding k-space slice. 0.100000000000000 0.100000000000000 Scale: true QFrame::NoFrame QFrame::Raised 0 6 0 0 6 Toggle between random movement and linear movement. Randomize motion true Rotation 6 9 6 6 Degree: false x false Axis: false Maximum rotation around x-axis. 1 -360.000000000000000 360.000000000000000 1.000000000000000 0.000000000000000 Maximum rotation around z-axis. 1 -360.000000000000000 360.000000000000000 1.000000000000000 15.000000000000000 y false z false Maximum rotation around y-axis. 1 -360.000000000000000 360.000000000000000 1.000000000000000 0.000000000000000 Translation 6 6 6 Distance: false x false y false Axis: false z false Maximum translation along x-axis. 1 -1000.000000000000000 1000.000000000000000 1.000000000000000 0.000000000000000 Maximum translation along y-axis. 1 -1000.000000000000000 1000.000000000000000 1.000000000000000 0.000000000000000 Maximum translation along z-axis. 1 -1000.000000000000000 1000.000000000000000 1.000000000000000 0.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 Motion volumes: Type in the volume indices that should be affected by motion (e.g. "0 3 7" whithout quotation marks). Leave blank for motion in all volumes. Type in "random" to randomly select volumes for motion. A list of negative numbers (e.g. -1 -2 -3) excludes volumes (e.g. 1 2 3) selects all remaining volumes. random Add ringing artifacts occuring at strong edges in the image. Add Gibbs Ringing false Qt::Horizontal Qt::Horizontal Qt::Horizontal Qt::Horizontal Add N/2 Ghosts false Add Aliasing false Qt::Horizontal Qt::Horizontal Add Eddy Current Effects false true QFrame::NoFrame QFrame::Raised 6 0 0 0 0 Shrink FOV (%): false Shrink FOV by this percentage. 1 0.000000000000000 90.000000000000000 0.100000000000000 25.000000000000000 true QFrame::NoFrame QFrame::Raised 6 0 0 0 0 Frequency Map: false Select image specifying the frequency inhomogeneities (in Hz). QFrame::NoFrame QFrame::Raised 0 0 0 0 Variance: Variance of selected noise distribution. 10 0.000000000000000 999999999.000000000000000 0.001000000000000 50.000000000000000 Distribution: Noise distribution Complex Gaussian Rician Fiber Definition 25 Qt::Vertical 20 40 color: rgb(255, 0, 0); Please select an image or an existing fiber bundle to draw the fiber fiducials. If you can't provide a suitable image, generate one using the "Signal Generation" tab. Qt::AutoText Qt::AlignJustify|Qt::AlignVCenter true Fiducial Options 6 6 6 6 All fiducials are treated as circles with the same radius as the first fiducial. Use Constant Fiducial Radius false false Align selected fiducials with voxel grid. Shifts selected fiducials to nearest voxel center. Align With Grid :/QmitkDiffusionImaging/general_icons/right.ico :/QmitkDiffusionImaging/general_icons/right.ico Operations 6 6 6 6 false Join Bundles :/QmitkDiffusionImaging/general_icons/plus.ico :/QmitkDiffusionImaging/general_icons/plus.ico QFrame::NoFrame QFrame::Raised 0 0 0 0 Y false Rotation angle (in degree) around x-axis. 3 -360.000000000000000 360.000000000000000 0.100000000000000 Axis: false Rotation angle (in degree) around y-axis. 3 -360.000000000000000 360.000000000000000 0.100000000000000 Translation: false Translation (in mm) in direction of the z-axis. 3 -1000.000000000000000 1000.000000000000000 0.100000000000000 Translation (in mm) in direction of the y-axis. 3 -1000.000000000000000 1000.000000000000000 0.100000000000000 X false Rotation: false Z false Rotation angle (in degree) around z-axis. 3 -360.000000000000000 360.000000000000000 0.100000000000000 Translation (in mm) in direction of the x-axis. 3 -1000.000000000000000 1000.000000000000000 0.100000000000000 Scaling: false Scaling factor for selected fiber bundle along the x-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the y-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the z-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 false Copy Bundles :/QmitkDiffusionImaging/general_icons/copy2.ico :/QmitkDiffusionImaging/general_icons/copy2.ico false Transform Selection :/QmitkDiffusionImaging/general_icons/refresh.ico :/QmitkDiffusionImaging/general_icons/refresh.ico If checked, the fiducials belonging to the modified bundle are also modified. Include Fiducials true Fiber Options 6 6 6 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Tension: false Fiber Sampling: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Bias: false Continuity: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Distance of fiber sampling points (in mm) 1 0.100000000000000 0.100000000000000 1.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 #Fibers: false Specify number of fibers to generate for the selected bundle. 1 1000000 100 100 false Generate Fibers :/QmitkDiffusionImaging/general_icons/right.ico :/QmitkDiffusionImaging/general_icons/right.ico QFrame::NoFrame QFrame::Raised 0 0 0 0 Select fiber distribution inside of the fiducials. Uniform Gaussian Fiber Distribution: false Variance of the gaussian 3 0.001000000000000 10.000000000000000 0.010000000000000 0.100000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 Disable to only generate fibers if "Generate Fibers" button is pressed. Real Time Fibers true Disable to only generate fibers if "Generate Fibers" button is pressed. Advanced Options false QFrame::NoFrame QFrame::Raised 0 0 0 0 false 30 30 Draw elliptical fiducial. :/QmitkDiffusionImaging/circle.png :/QmitkDiffusionImaging/circle.png 32 32 false true false 30 30 Flip fiber waypoints of selcted fiducial around one axis. :/QmitkDiffusionImaging/general_icons/refresh.ico :/QmitkDiffusionImaging/general_icons/refresh.ico 32 32 false true Qt::Horizontal 40 20 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
QmitkTensorModelParametersWidget QWidget
QmitkTensorModelParametersWidget.h
1
QmitkStickModelParametersWidget QWidget
QmitkStickModelParametersWidget.h
1
QmitkZeppelinModelParametersWidget QWidget
QmitkZeppelinModelParametersWidget.h
1
QmitkBallModelParametersWidget QWidget
QmitkBallModelParametersWidget.h
1
QmitkAstrosticksModelParametersWidget QWidget
QmitkAstrosticksModelParametersWidget.h
1
QmitkDotModelParametersWidget QWidget
QmitkDotModelParametersWidget.h
1
QmitkPrototypeSignalParametersWidget QWidget
QmitkPrototypeSignalParametersWidget.h
1
m_CircleButton m_FlipButton m_RealTimeFibers m_AdvancedOptionsBox m_DistributionBox m_VarianceBox m_FiberDensityBox m_FiberSamplingBox m_TensionBox m_ContinuityBox m_BiasBox m_GenerateFibersButton m_ConstantRadiusBox m_AlignOnGrid m_XrotBox m_YrotBox m_ZrotBox m_XtransBox m_YtransBox m_ZtransBox m_XscaleBox m_YscaleBox m_ZscaleBox m_TransformBundlesButton m_CopyBundlesButton m_JoinBundlesButton m_IncludeFiducials m_FiberBundleComboBox m_MaskComboBox m_TemplateComboBox m_SavePathEdit m_OutputPathButton m_SizeX m_SizeY m_SizeZ m_SpacingX m_SpacingY m_SpacingZ m_NumGradientsBox m_BvalueBox m_AdvancedOptionsBox_2 m_SignalScaleBox m_TEbox m_TRbox m_LineReadoutTimeBox m_PartialFourier m_T2starBox m_FiberRadius m_ReversePhaseBox m_RelaxationBox m_EnforcePureFiberVoxelsBox m_VolumeFractionsBox m_Compartment1Box m_Comp1VolumeFraction m_Compartment2Box m_Comp2VolumeFraction m_Compartment3Box m_Comp3VolumeFraction m_Compartment4Box m_Comp4VolumeFraction m_AddNoise m_NoiseDistributionBox m_NoiseLevel m_AddSpikes m_SpikeNumBox m_SpikeScaleBox m_AddGhosts m_kOffsetBox m_AddAliasing m_WrapBox m_AddDistortions m_FrequencyMapBox m_AddMotion m_RandomMotion m_MaxRotationBoxX m_MaxRotationBoxY m_MaxRotationBoxZ m_MaxTranslationBoxX m_MaxTranslationBoxY m_MaxTranslationBoxZ m_AddEddy m_EddyGradientStrength m_AddGibbsRinging m_SaveParametersButton m_LoadParametersButton toolBox
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorViewControls.ui index b0d6ed02b3..58600b9fab 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorViewControls.ui @@ -1,414 +1,407 @@ QmitkFieldmapGeneratorViewControls 0 0 358 536 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 9 9 9 9 25 QFrame::NoFrame QFrame::Raised 0 0 0 0 Place Field Source QFrame::NoFrame QFrame::Raised 0 0 0 0 World Coordinates: - Index: - Generate Fieldmap Please Select Reference Image 6 6 6 6 Add Gradient 6 6 6 6 Gradient x: z: 4 -1000.000000000000000 1000.000000000000000 4 -1000.000000000000000 1000.000000000000000 y: 4 -1000.000000000000000 1000.000000000000000 Offset 4 -1000.000000000000000 1000.000000000000000 4 -1000.000000000000000 1000.000000000000000 4 -1000.000000000000000 1000.000000000000000 Qt::Vertical QSizePolicy::Expanding 20 220 Edit Selected Source 6 6 6 6 Name: Height: Variance: - 999999.000000000000000 999999.000000000000000 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui index 142f9b6f4b..83c5746932 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui @@ -1,552 +1,545 @@ QmitkFiberClusteringViewControls 0 0 474 683 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 Qt::Vertical 20 40 Metrics 6 6 6 6 Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Euclidean true Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Euclidean STDEV Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Euclidean Maximum Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Inner Angles Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 Distance is based on the selected parcellation. Anatomical Distance is based on the selected parcellation. Weighting factor for metric values. 1 999.000000000000000 30.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 Distance is based on the scalar map values along the tract. Scalar Map Distance is based on the scalar map values along the tract. Streamline Length Input Data 6 6 6 6 Input Centroids: If set, the input tractogram is clustered around the input centroids and no new clusters are created. false 0 0 200 16777215 11 Start Tractogram: Parameters Only output clusters with ate least the specified number of fibers. 1 9999999 50 Only output the N largest clusters. Zero means no limit. 99999999 10 Min. Fibers per Cluster: Max. Clusters: Fiber Points: Merge duplicate clusters withthe specified distance threshold. If threshold is < 0, the threshold is set to half of the specified cluster size. -1.000000000000000 99999.000000000000000 0.000000000000000 Cluster Size: Cluster size in mm. 1 9999999 20 Fibers are resampled to the desired number of points for clustering. Smaller is faster but less accurate. 2 9999999 12 Merge Duplicate Clusters: Output Centroids: QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitViewControls.ui index eada3d492a..1712aaae56 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitViewControls.ui @@ -1,252 +1,245 @@ QmitkFiberFitViewControls 0 0 484 574 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } QFrame::NoFrame QFrame::Raised 0 0 0 0 6 false Output Residuals: Weight for regularization. 999999.000000000000000 0.100000000000000 0.100000000000000 Tractogram: false 0 0 200 16777215 11 Start λ: Image: false Suppress Outliers: Regularization: Voxel-wise Variance Variance Mean Squared Magnitude Lasso None Qt::Vertical 20 40 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingViewControls.ui index 9a8a405915..e155a9b83e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingViewControls.ui @@ -1,1625 +1,1620 @@ - + QmitkFiberProcessingViewControls 0 0 385 684 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 9 9 9 9 0 5 0 0 353 441 Fiber Extraction Extract a fiber subset from the selected fiber bundle using manually placed planar figures as waypoints or binary regions of interest. false 0 0 200 16777215 11 Extract fibers passing through selected ROI or composite ROI. Select ROI and fiber bundle to execute. Extract Qt::Vertical 20 40 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 Interactive Extraction 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 0 0 0 30 30 Draw circular ROI. Select reference fiber bundle to execute. - + - :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png + :/QmitkDiffusionImaging/circle.png +:/QmitkDiffusionImaging/circle.png 32 32 false true Qt::Horizontal 40 20 30 30 Draw polygonal ROI. Select reference fiber bundle to execute. - + - :/QmitkDiffusionImaging/polygon.png:/QmitkDiffusionImaging/polygon.png + :/QmitkDiffusionImaging/polygon.png +:/QmitkDiffusionImaging/polygon.png 32 32 true true 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 0 0 0 false 60 16777215 Create NOT composition from selected ROI. NOT false 60 16777215 Create OR composition with selected ROIs. OR Qt::Horizontal 40 20 false 60 16777215 Create AND composition with selected ROIs. AND false 0 0 16777215 16777215 11 Generate a binary image containing all selected ROIs. Select at least one ROI (planar figure) and a reference fiber bundle or image. Generate ROI Image 0 0 Extract using planar figures Extract using ROI image QFrame::NoFrame QFrame::Raised 0 0 0 0 Min. overlap: Extract fibers: Both ends true - Minimum overlap of streamlines and ROI in terms of streamline length. Zero means that one streamline point inside the ROI is enough to be considered as "overlapping". + Minimum overlap of streamlines and ROI in terms of streamline length. Zero means that one streamline point inside the ROI is enough to be considered as "overlapping". 3 1.000000000000000 0.100000000000000 0 0 Ending in ROI Not ending in ROI Passing ROI Not passing ROI Interpolate ROI true Threshold: Threshold on ROI image for positions to be considered as positive. 3 9999.000000000000000 0.100000000000000 0.500000000000000 0 0 367 408 Fiber Removal Remove fibers that satisfy certain criteria from the selected bundle. QFrame::NoFrame QFrame::Raised 0 0 0 0 If unchecked, the fiber exceeding the threshold will be split in two instead of removed. Remove Fiber false QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Max. Angular Deviation: Qt::Horizontal 40 20 Maximum angular deviation in degree 180.000000000000000 0.100000000000000 30.000000000000000 Distance: Distance in mm 1 999.000000000000000 1.000000000000000 10.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 X: Y: - + - + Z: - + Angle: Angular deviation threshold in degree 1 90.000000000000000 1.000000000000000 25.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 Qt::Horizontal 40 20 Minimum fiber length in mm 0 999999999 20 Max. Length: Min. Length: Maximum fiber length in mm 0 999999999 300 false 0 0 200 16777215 11 - + Remove Qt::Vertical 20 40 0 0 Remove fibers in direction Remove fibers by length Remove fibers by curvature Remove fiber parts outside mask Remove fiber parts inside mask Remove fibers by weight QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Weight threshold: Only fibers with weight larger than this threshold are kept. 5 99999.000000000000000 0.100000000000000 0 0 367 408 Bundle Modification Modify the selected bundle with operations such as fiber resampling, FA coloring, etc. QFrame::NoFrame QFrame::Raised 0 0 0 0 0 6 Error threshold in mm: 999999999.000000000000000 0.100000000000000 0.100000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 6 Sagittal Coronal Axial Select direction: QFrame::NoFrame QFrame::Raised 0 0 0 0 0 6 If checked, the image values are not only used to color the fibers but are also used as opaxity values. Values as opacity false - + Scalar map: The values used to color the fibers are min-max normalized. If not checked, the values should be between 0 and 1. Normalize values true 0 0 Resample fibers (spline) Resample fibers (linear) Compress fibers Color fibers by scalar map (e.g. FA) Mirror fibers Weight bundle Color fibers by curvature Color fibers by fiber weights Color fibers by length QFrame::NoFrame QFrame::Raised 0 0 0 0 0 6 0.010000000000000 999999999.000000000000000 0.100000000000000 1.000000000000000 Point distance in mm: Qt::Vertical 20 40 false 0 0 200 16777215 11 - + Execute QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Weight: 7 999999999.000000000000000 0.100000000000000 1.000000000000000 0 0 367 172 Bundle Operations Join, subtract or copy bundles. false 0 0 200 16777215 11 Returns all fibers contained in bundle X that are not contained in bundle Y (not commutative!). Select at least two fiber bundles to execute. Substract Qt::Vertical 20 40 false 0 0 200 16777215 11 Merge selected fiber bundles. Select at least two fiber bundles to execute. Join false 0 0 200 16777215 11 Merge selected fiber bundles. Select at least two fiber bundles to execute. Copy Please Select Input Data 6 6 6 6 - <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> + <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true - <html><head/><body><p><span style=" color:#969696;">needed for extraction</span></p></body></html> + <html><head/><body><p><span style=" color:#969696;">needed for extraction</span></p></body></html> true Input DTI Fiber Bundle: Binary seed ROI. If not specified, the whole image area is seeded. ROI: Qt::Vertical 20 40 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
- - + + - -
+ + \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationViewControls.ui index 68b0065306..bd45e43f55 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationViewControls.ui @@ -1,448 +1,441 @@ QmitkFiberQuantificationViewControls 0 0 365 581 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 Fiber-derived images 6 6 6 6 false 0 0 200 16777215 11 Perform selected operation on all selected fiber bundles. Generate Image 0 0 Upsampling factor 1 0.100000000000000 10.000000000000000 0.100000000000000 1.000000000000000 0 0 Tract Density Image (TDI) Normalized TDI Binary Envelope Fiber Bundle Image Fiber Endings Image Fiber Endings Pointset Principal Fiber Directions 6 6 6 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 Fiber directions with an angle smaller than the defined threshold are clustered. 2 0.000000000000000 90.000000000000000 1.000000000000000 30.000000000000000 0 0 <html><head/><body><p>Directions shorter than the defined threshold are discarded.</p></body></html> 3 1.000000000000000 0.100000000000000 0.300000000000000 Angular Threshold: Max. Peaks: Size Threshold: 0 0 Maximum number of fiber directions per voxel. 100 3 Normalization: 0 0 0 Global maximum Single vector Voxel-wise maximum 0 0 Image containing the number of distinct fiber clusters per voxel. Output #Directions per Voxel false false Generate Directions Input Data 6 6 6 6 Tractogram: Reference Image: Qt::Vertical 20 40 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryViewControls.ui index 0706ec6ad1..fe454057d0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryViewControls.ui @@ -1,164 +1,157 @@ QmitkTractometryViewControls 0 0 484 574 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } QFrame::NoFrame QFrame::Raised 0 0 0 0 6 Input Image: 3 99999 100 Sampling Points: Qt::Vertical 20 40 0 100 Show STDEV true QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkChartWidget QWidget
QmitkChartWidget.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMViewControls.ui index 02febef950..b83e5d07d1 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMViewControls.ui @@ -1,1215 +1,1208 @@ QmitkIVIMViewControls 0 0 423 1563 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 9 9 9 9 9 Intra Voxel Incoherent Motion Estimation 6 9 6 6 Input Data 6 6 6 6 Optional ROI image ROI: DWI to analyze Raw DWI: QFrame::NoFrame QFrame::Raised 0 0 0 0 warning display Qt::RichText true 0 0 16 16 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 16 16 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 16 16 QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::StyledPanel QFrame::Raised 0 0 0 0 0 0 0 IVIM Parameters 9 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 80 16777215 D* 100 60 Qt::Horizontal 51 16777215 200 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter QFrame::NoFrame QFrame::Raised 0 0 0 0 0 80 16777215 neglect b< 250 34 Qt::Horizontal 51 16777215 46.5 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter QFrame::NoFrame QFrame::Raised 0 0 0 0 0 80 16777215 #iterations 100 10 Qt::Horizontal 30 16777215 TextLabel Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter QFrame::NoFrame QFrame::Raised 0 0 0 0 0 80 16777215 lambda 1000 10 Qt::Horizontal 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 0 30 16777215 TextLabel Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 15 16777215 Calculate threshold from histogram * QFrame::NoFrame QFrame::Plain 0 0 0 0 0 80 16777215 neglect Si< 100 0 Qt::Horizontal 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 0 30 16777215 TextLabel Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 15 16777215 Calculate threshold from histogram * QFrame::NoFrame QFrame::Raised 0 0 0 0 80 0 Output Images f true D false D* false true 0 0 0 400 Choose Method 2 3 Param. Fit Fit D & f with fixed D* value Fit D & f (high b), then fit D* Linearly fit D & f (high b), then fit D* Regularized Kurtosis QFrame::StyledPanel QFrame::Raised 2 2 2 2 2 Smoothing sigma Select Fit Type Omit b=0 Measurement 80 0 Output Images Force the fitting of K to remain within the given boundaries Boundaries for K Select if the data is fitted directly (straight) or the logarithmic equation is used Straight Fit Logarithmic Fit 2 QLayout::SetMaximumSize D false K true Signa for gaussian smoothing applied prior to map computation 0.000000000000000 5.000000000000000 0.100000000000000 On 0 0 0 400 Generate Output Images QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Datapoints to Clipboard Parameters to Clipboard QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
QmitkIVIMWidget QWidget
QmitkIVIMWidget.h
1
QmitkKurtosisWidget QWidget
QmitkKurtosisWidget.h
1
ctkRangeWidget QWidget
ctkRangeWidget.h
1
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionViewControls.ui index 56cfad412f..dc363b8334 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionViewControls.ui @@ -1,504 +1,497 @@ QmitkOdfMaximaExtractionViewControls 0 0 397 848 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 QFrame::NoFrame QFrame::Raised 0 0 0 0 true Generate ODF image and MITK compatible SH coefficient from other toolkits. Start SH Coefficient Import true Extract ODF peaks using finite differences on the densely sampled ODF surface. Start Peak Extraction Please Select Input Data 6 6 6 6 Select a tensor image or a SH coefficient image (generate using Q-Ball reconstruction view). ShCoeff/DTI: Mask Image: Additional Output QFormLayout::AllNonFixedFieldsGrow 6 6 6 6 Output unsigned char image containing the number of directions per voxel. #Peaks per Voxel false Parameters 6 6 6 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 Vector Normalization: <html><head/><body><p>The vector fields are always coorected for image spacing and using the lagest eigenvalue in case of the tensor peak extraction. This is done for visualizytion purposes. The output direction images are not affected.</p></body></html> 1 No Normalization MAX Normalize Single Vec Normalization true QFrame::NoFrame QFrame::Raised 0 0 0 0 6 true Max. Peaks: Relative Threshold: true Peak threshold relative to the largest peak per voxel. 3 0.000000000000000 1.000000000000000 0.100000000000000 0.500000000000000 true Absolute peak threshold (only used for the finite differences method). The value is additionally scaled by 1/GFA. 3 0.000000000000000 1.000000000000000 0.010000000000000 0.030000000000000 true Maximum number of peaks to extract. 1 1000 3 Clustering Angle: Cluster close directions. Define "close" here. 90 30 Absolute Threshold: Angular Threshold: Discard smaller peaks in the defined angle around the maximum peaks that were too far away to be clustered. 0 90 0 Qt::Vertical 20 259 Spherical Harmonic Convention 6 6 6 6 Define SH coefficient convention (depends on toolkit) 0 MITK/MRtrix FSL QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisViewControls.ui index 0cb2586b38..baec9ccaa4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisViewControls.ui @@ -1,886 +1,879 @@ QmitkPartialVolumeAnalysisViewControls true 0 0 360 565 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 0 9 3 9 3 Data 0 0 Tensor/Scalar Image: 0 0 Mask Image: <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> Parameters QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised 0 0 false QFrame::NoFrame QFrame::Raised 0 30 30 Draw circular ROI :/QmitkDiffusionImaging/circle.png :/QmitkDiffusionImaging/circle.png 32 32 true true 30 30 Draw quadratic ROI :/QmitkDiffusionImaging/rectangle.png :/QmitkDiffusionImaging/rectangle.png 32 32 true true 30 30 Draw polygonal ROI :/QmitkDiffusionImaging/polygon.png :/QmitkDiffusionImaging/polygon.png 32 32 true true Qt::Horizontal 40 20 true QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 0 Upsampling QFrame::NoFrame QFrame::Raised 0 1 50 1 25 Qt::Horizontal 50 0 2.5 Similar angles QFrame::NoFrame 0 90 0 Qt::Horizontal QSlider::NoTicks 50 0 90° QFrame::NoFrame QFrame::Raised 0 0 display histogram true 0 0 QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised 0 20 20 true true Green Partial Volume Partial Volume Partial Volume Partial Volume PV Red true All Export clustering result as float image. ... :/org.mitk.gui.qt.diffusionimaging/resources/arrow.png :/org.mitk.gui.qt.diffusionimaging/resources/arrow.png QFrame::NoFrame 0 Opacity 10 5 Qt::Horizontal QSlider::TicksBelow Qt::Vertical QSizePolicy::Fixed 20 10 The computed class values (median, variance of the gaussians) are automatically copied to clipboard. Qt::AutoText true Qt::Vertical QSizePolicy::Fixed 20 10 Histogram to Clipboard Advanced Qt::Vertical QSizePolicy::Preferred 10 1 QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 0 Blurring QFrame::NoFrame QFrame::Raised 0 200 1 0 Qt::Horizontal 50 0 0.0 # Bins QFrame::NoFrame 0 1 100 10 Qt::Horizontal QSlider::NoTicks 50 0 50 quantiles QFrame::StyledPanel QFrame::Raised 0 1.000000000000000 0.010000000000000 0.250000000000000 1.000000000000000 0.010000000000000 0.750000000000000 Estimate circle from binary image "Thick" PFs Qt::Vertical 20 40 QmitkPartialVolumeAnalysisWidget QWidget
QmitkPartialVolumeAnalysisWidget.h
1
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingViewControls.ui index dfd044558f..6120fc9c5f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingViewControls.ui @@ -1,1766 +1,1759 @@ QmitkPreprocessingViewControls 0 0 503 813 0 0 false QmitkPreprocessingViewControls true QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 Please Select Input Data 6 6 6 6 Image: QComboBox::AdjustToMinimumContentsLength 0 Gradients 25 Qt::Vertical 20 40 0 0 Qt::ScrollBarAsNeeded Qt::ScrollBarAlwaysOff true 100 true false true b-Value Number of gradients QFrame::NoFrame QFrame::Raised 0 0 0 0 6 <html><head/><body><p>Define the sampling frame the b-Values are rounded with.</p></body></html> Sampling frame: false <html><head/><body><p>Round b-values to nearest multiple of this value (click &quot;Round b-value&quot; to create new image with these values).</p></body></html> QAbstractSpinBox::CorrectToNearestValue 1 10000 10 false Sometimes the gradient directions are not located on one half sphere. Mirror gradients to half sphere false Generate pointset displaying the gradient vectors (applied measurement frame). Show gradients false Generate pointset displaying the gradient vectors (applied measurement frame). Flip gradients false Retain only the specified number of gradient directions and according image volumes. The retained directions are spread equally over the half sphere using an iterative energy repulsion strategy. Reduce number of gradients QFrame::NoFrame QFrame::Plain 0 0 0 0 0 x y z false Round b-values false By default, the image matrix is applied to the image gradients. This button removes this additional rotation. Clear rotation of gradients Remove or extract gradient volumes 6 6 6 6 6 6 false Remove gradient volume false Extract gradient volume Image Values 25 Qt::Vertical 20 40 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. 6 2.000000000000000 0.000100000000000 0.001000000000000 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Merge radius false Merges selected DWIs of same dimension. If several b-values are present, the resulting image will contain multiple b-shells. Merge selected DWIs false Normalizes the diffusion-weighted image values across all weighted volumes to the given mean and standard deviation. Normalize image values QFrame::NoFrame QFrame::Raised 0 0 0 0 0 false Target b-value 100000 500 Select projection method. QComboBox::AdjustToMinimumContentsLength ADC Average AKC Bi-Exponential false Multiple acquistions of one gradient direction can be averaged. Due to rounding errors, similar gradients often differ in the last decimal positions. The Merge radius allows to average them by taking all directions within a certain radius into account. Average repetitions false Project image values onto one b-shell. Project onto shell QFrame::NoFrame QFrame::Raised 0 0 0 0 0 true New stdev 100000 100 500 Select binary mask image. The mask is used to calculate the old mean and standard deviation. QComboBox::AdjustToMinimumContentsLength true New mean value 100000 100 1000 false Merges selected DWIs of same dimension. If several b-values are present, the resulting image will contain multiple b-shells. Flip axis QFrame::NoFrame QFrame::Raised 0 0 0 0 Y Qt::Horizontal 40 20 X Z Axis: QComboBox::AdjustToMinimumContentsLength Resample image 6 6 6 6 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0.010000000000000 2.000000000000000 0.010000000000000 2.000000000000000 0.010000000000000 2.000000000000000 Sampling factor New image spacing New image size QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Interpolator: Nearest neighbour Linear B-spline Windowed sinc false Resample image QFrame::NoFrame QFrame::Raised 0 0 0 0 0 1 10000 1 10000 1 10000 Crop Image 6 6 6 6 6 x: y: z: Crop Image Header 25 Voxel size 6 6 6 6 4 0.000000000000000 99.989999999999995 4 4 false Apply new header information Direction matrix 6 6 6 6 false 0 0 0 0 IBeamCursor true Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff true false false true true 0 false true true New Row New Row New Row New Column New Column New Column Qt::Horizontal 40 20 0 0 Measurment frame 6 6 6 6 false 0 0 0 0 IBeamCursor true Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff true false false true true 0 false true true New Row New Row New Row New Column New Column New Column Qt::Horizontal 40 20 Qt::Vertical 20 40 Origin 6 6 6 6 4 -999999999.000000000000000 999999999.000000000000000 4 -99999999.000000000000000 999999999.000000000000000 4 -999999999.000000000000000 999999999.000000000000000 Align origins 6 6 6 6 QComboBox::AdjustToMinimumContentsLength Align to Other false If multiple baseline acquisitions are present, the default behaviour is to output an averaged image. Estimate binary brain mask Maximum number of iterations. 10000 10000 Qt::Vertical 20 40 false If multiple baseline acquisitions are present, the default behaviour is to output an averaged image. Extract baseline image Create a 3D+t data set containing all b0 images as timesteps Disable averaging QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
m_SelctedImageComboBox tabWidget m_B_ValueMap_TableWidget m_CreateLengthCorrectedDwi m_B_ValueMap_Rounder_SpinBox m_FlipGradientsButton m_FlipGradBoxX m_FlipGradBoxY m_FlipGradBoxZ m_ShowGradientsButton m_MirrorGradientToHalfSphereButton m_ReduceGradientsButton m_ClearRotationButton m_RemoveGradientButton m_RemoveGradientBox m_ExtractGradientButton m_ExtractGradientBox m_ButtonAverageGradients m_Blur m_ProjectSignalButton m_targetBValueSpinBox m_ProjectionMethodBox m_NormalizeImageValuesButton m_NewMean m_NewStdev m_NormalizationMaskBox m_FlipAxis m_FlipX m_FlipY m_FlipZ m_MergeDwisButton m_MergeDwiBox m_ResampleTypeBox m_ResampleDoubleX m_ResampleDoubleY m_ResampleDoubleZ m_ResampleIntX m_ResampleIntY m_ResampleIntZ m_InterpolatorBox m_ResampleImageButton m_XstartBox m_XendBox m_YstartBox m_YendBox m_ZstartBox m_ZendBox m_CropImageButton m_ModifyHeader m_HeaderOriginX m_HeaderOriginY m_HeaderOriginZ m_HeaderSpacingX m_HeaderSpacingY m_HeaderSpacingZ m_DirectionMatrixTable m_MeasurementFrameTable m_ButtonExtractB0 m_CheckExtractAll m_ExtractBrainMask m_BrainMaskIterationsBox
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionViewControls.ui index 01a01e31c5..3671293c44 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionViewControls.ui @@ -1,125 +1,118 @@ QmitkBrainExtractionViewControls 0 0 435 744 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } false Start Brain Extraction Qt::Vertical 20 40 QFrame::NoFrame QFrame::Raised 0 0 0 0 Input Image: QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationViewControls.ui index efcc1114a2..6002ee62c4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationViewControls.ui @@ -1,458 +1,451 @@ QmitkDiffusionQuantificationViewControls 0 0 343 888 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 Input Data 6 6 6 6 Image Scale Image Values: 9999999.000000000000000 1.000000000000000 Raw diffusion-weighted image 6 6 6 6 false ADC false MD false Ball-Stick false Multi-Tensor Fit ODF image 6 6 6 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 Generalized GFA QFrame::NoFrame QFrame::Raised 0 0 0 0 true k true true p true false GFA QFrame::NoFrame QFrame::Raised 0 0 0 0 Min. angle Max. angle false Curvature Tensor image 6 6 6 6 false FA (Fractional Anisotropy) false RA (Relative Anisotropy) false AD (Axial Diffusivity) false RD (Radial Diffusivity) false MD (Mean Diffusivity) false 1-(λ2+λ3)/(2*λ1) Qt::Vertical QSizePolicy::Expanding 20 220 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBox.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsViewControls.ui index 01204eabad..bad0fc4932 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsViewControls.ui @@ -1,287 +1,280 @@ QmitkODFDetailsViewControls 0 0 351 734 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 6 9 9 9 9 Please Select Input Data 6 6 6 6 DTI/ODF: <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true Overview 6 6 6 6 0 0 0 0 true 0 0 200 200 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 ODF Values 6 6 6 6 true 0 0 0 200 Qt::Vertical QSizePolicy::Expanding 20 220 QmitkODFDetailsWidget QWidget
QmitkODFDetailsWidget.h
1
QmitkODFRenderWidget QWidget
QmitkODFRenderWidget.h
1
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionViewControls.ui index 5d8166f03f..bb4d30e9be 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionViewControls.ui @@ -1,457 +1,450 @@ QmitkQBallReconstructionViewControls 0 0 372 844 0 0 true QmitkQBallReconstructionViewControls QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 Parameters 6 6 6 6 2 Numerical Standard Solid Angle Constraint Solid Angle ADC-Profile only Raw Signal only Multi-Shell TextLabel QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 true Regularization Parameter Lambda: false Regularization factor 3 1.000000000000000 0.001000000000000 0.006000000000000 true SH-Order: false true -1 true B0 Threshold false 10000 Output SH-Coefficient Image false false Start Reconstruction Input Data 6 6 6 6 Input for Q-Ball reconstruction. Raw DWI: true Qt::LeftToRight false Multi-Shell Reconstruction 6 6 6 6 Qt::Vertical 20 0 Convert SH to sampled ODF image 6 6 6 6 false Convert QFrame::NoFrame QFrame::Raised 0 0 0 0 Input for Q-Ball reconstruction. SH Image: QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionViewControls.ui index b32a923947..a7512461be 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionViewControls.ui @@ -1,785 +1,778 @@ QmitkTensorReconstructionViewControls 0 0 368 1019 0 0 true QmitkTensorReconstructionViewControls QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 ODF Image from Tensors 6 6 6 6 false Calculate ODF value as tensor value in the according direction Start QFrame::NoFrame QFrame::Raised 0 0 0 0 Tensor Image: Diffusion-weighted Image from Tensors 6 6 6 6 false Estimates the original diffusion weighted image based on a reconstructed tensor image. Estimate DWI based on Tensor Image QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 6 0 0 0 0 how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: "0" how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: "0" how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: "0" B-Value false #Gradient Directions 3 12 42 92 162 252 362 492 642 812 1002 10000 100 1000 QFrame::NoFrame QFrame::Raised 0 0 0 0 Tensor Image: Calculate Residuals false false 6 6 6 6 6 false percentages of error 0 Per volume 200 300 Per slice outliers per slice QFrame::NoFrame QFrame::Raised 0 0 0 0 300 400 QFrame::NoFrame QFrame::Raised 0 0 0 0 20 255 Volume: .., Slice:.. false Calculate the residual from a dti and a dwi image Start QFrame::NoFrame QFrame::Raised 0 0 0 0 Diffusion-weighted Image: Tensor Image: Qt::Vertical 20 40 Tensor Reconstruction 6 6 6 6 Advanced Settings false false Select raw DWI! Start Reconstruction QFrame::StyledPanel QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 B0 Threshold false 10000 Only influences WLS reconstruction Ignore voxels with negative eigenvalues 0 ITK Linear Least Squares With correction for negative eigenvalues QFrame::NoFrame QFrame::Raised 0 0 0 0 Diffusion-weighted Image: QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkResidualAnalysisWidget QWidget
QmitkResidualAnalysisWidget.h
1
QmitkResidualViewWidget QGraphicsView
QmitkResidualViewWidget.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRegistration.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRegistration.dox index 50f5be7cdd..b6fc0bb470 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRegistration.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRegistration.dox @@ -1,8 +1,6 @@ /** \page org_mitk_views_simpleregistrationview Registration -This view enables the simple rigid or affine registration of two images. The registered image will be displayed in transparent blue color overlayed over the fixed image. To regain normal coloring, right-click on the data node and adjust the corresponding settings. - -It is also possible to transform a tractogram with a registration object obtained from a previous registration of two images. +This view enables the simple rigid or affine registration of two images. It is also possible to transform a tractogram with a registration object obtained from a previous registration of two images. */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui index c48527cac1..c73acb1a3a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui @@ -1,125 +1,118 @@ QmitkHeadMotionCorrectionViewControls 0 0 435 744 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } false Start DWI registration/Head Motion Correction Start Head Motion Correction Qt::Vertical 20 40 QFrame::NoFrame QFrame::Raised 0 0 0 0 Input Image: QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp index 7905469296..dfb58a2792 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp @@ -1,392 +1,392 @@ /*=================================================================== 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. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include // Blueberry #include #include // Qmitk #include "QmitkSimpleRegistrationView.h" // MITK #include #include #include #include #include #include #include #include #include #include #include // Qt #include #define _USE_MATH_DEFINES #include const std::string QmitkSimpleRegistrationView::VIEW_ID = "org.mitk.views.simpleregistrationview"; QmitkSimpleRegistrationView::QmitkSimpleRegistrationView() : QmitkAbstractView() , m_Controls( 0 ) , m_RegistrationType(0) { } // Destructor QmitkSimpleRegistrationView::~QmitkSimpleRegistrationView() { } void QmitkSimpleRegistrationView::StartRegistration() { QmitkRegistrationJob* pJob; if (m_Controls->m_RegBox->currentIndex()==0) { mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::New(); pJob = new QmitkRegistrationJob(algo); m_RegistrationType = 0; } else { mitk::MultiModalAffineDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalAffineDefaultRegistrationAlgorithm< ItkFloatImageType >::New(); pJob = new QmitkRegistrationJob(algo); m_RegistrationType = 1; } pJob->setAutoDelete(true); m_MovingImageNode = m_Controls->m_MovingImageBox->GetSelectedNode(); mitk::Image::Pointer movingImage = dynamic_cast(m_MovingImageNode->GetData()); if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(movingImage)) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(movingImage, itkVectorImagePointer); itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New(); filter->SetInput( itkVectorImagePointer); filter->SetChannelIndex(m_Controls->m_MovingChannelBox->value()); filter->Update(); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( filter->GetOutput() ); newImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); pJob->m_spMovingData = newImage; } else pJob->m_spMovingData = movingImage; mitk::Image::Pointer fixedImage = dynamic_cast(m_Controls->m_FixedImageBox->GetSelectedNode()->GetData()); if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(fixedImage)) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(fixedImage, itkVectorImagePointer); itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New(); filter->SetInput( itkVectorImagePointer); filter->SetChannelIndex(m_Controls->m_MovingChannelBox->value()); filter->Update(); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( filter->GetOutput() ); newImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); pJob->m_spTargetData = newImage; } else pJob->m_spTargetData = fixedImage; pJob->m_TargetDataUID = mitk::EnsureUID(m_Controls->m_FixedImageBox->GetSelectedNode()->GetData()); pJob->m_MovingDataUID = mitk::EnsureUID(m_Controls->m_MovingImageBox->GetSelectedNode()->GetData()); connect(pJob, SIGNAL(RegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer, const QmitkRegistrationJob*)), this, SLOT(OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer, const QmitkRegistrationJob*)), Qt::BlockingQueuedConnection); QThreadPool* threadPool = QThreadPool::globalInstance(); threadPool->start(pJob); m_Controls->m_RegistrationStartButton->setEnabled(false); m_Controls->m_RegistrationStartButton->setText("Registration in progress ..."); } void QmitkSimpleRegistrationView::OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* job) { mitk::Image::Pointer movingImage = dynamic_cast(m_MovingImageNode->GetData()); mitk::Image::Pointer image; if (m_RegistrationType==0) { image = mitk::ImageMappingHelper::refineGeometry(movingImage, spResultRegistration, true); } else { if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(movingImage)) { image = mitk::ImageMappingHelper::map(movingImage, spResultRegistration, false, 0, job->m_spTargetData->GetGeometry(), false, 0, mitk::ImageMappingInterpolator::BSpline_3); } else { typedef itk::ComposeImageFilter < ITKDiffusionVolumeType > ComposeFilterType; ComposeFilterType::Pointer composer = ComposeFilterType::New(); ItkDwiType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(movingImage); for (unsigned int i=0; iGetVectorLength(); ++i) { itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New(); filter->SetInput( itkVectorImagePointer); filter->SetChannelIndex(i); filter->Update(); mitk::Image::Pointer gradientVolume = mitk::Image::New(); gradientVolume->InitializeByItk( filter->GetOutput() ); gradientVolume->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); mitk::Image::Pointer registered_mitk_image = mitk::ImageMappingHelper::map(gradientVolume, spResultRegistration, false, 0, job->m_spTargetData->GetGeometry(), false, 0, mitk::ImageMappingInterpolator::BSpline_3); ITKDiffusionVolumeType::Pointer registered_itk_image = ITKDiffusionVolumeType::New(); mitk::CastToItkImage(registered_mitk_image, registered_itk_image); composer->SetInput(i, registered_itk_image); } composer->Update(); image = mitk::GrabItkImageMemory( composer->GetOutput() ); mitk::DiffusionPropertyHelper::CopyProperties(movingImage, image, true); } } if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image)) { mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); } mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); resultNode->SetData(image); if (m_MovingImageNode.IsNotNull()) { m_MovingImageNode->SetVisibility(false); QString name = m_MovingImageNode->GetName().c_str(); if (m_RegistrationType==0) resultNode->SetName((name+"_registered (rigid)").toStdString().c_str()); else resultNode->SetName((name+"_registered (affine)").toStdString().c_str()); } else { if (m_RegistrationType==0) resultNode->SetName("Registered (rigid)"); else resultNode->SetName("Registered (affine)"); } - resultNode->SetOpacity(0.6); - resultNode->SetColor(0.0, 0.0, 1.0); +// resultNode->SetOpacity(0.6); +// resultNode->SetColor(0.0, 0.0, 1.0); GetDataStorage()->Add(resultNode); mitk::RenderingManager::GetInstance()->InitializeViews( resultNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); if (m_Controls->m_RegOutputBox->isChecked()) { mitk::DataNode::Pointer registration_node = mitk::DataNode::New(); registration_node->SetData(spResultRegistration); if (m_RegistrationType==0) registration_node->SetName("Registration Object (rigid)"); else registration_node->SetName("Registration Object (affine)"); GetDataStorage()->Add(registration_node, resultNode); } this->GetRenderWindowPart()->RequestUpdate(); m_Controls->m_RegistrationStartButton->setEnabled(true); m_Controls->m_RegistrationStartButton->setText("Start Registration"); m_MovingImageNode = nullptr; TractoChanged(); } void QmitkSimpleRegistrationView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkSimpleRegistrationViewControls; m_Controls->setupUi( parent ); m_Controls->m_FixedImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_MovingImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New(); m_Controls->m_FixedImageBox->SetPredicate(isImagePredicate); m_Controls->m_MovingImageBox->SetPredicate(isImagePredicate); mitk::TNodePredicateDataType::Pointer isFib = mitk::TNodePredicateDataType::New(); mitk::TNodePredicateDataType::Pointer isReg = mitk::TNodePredicateDataType::New(); m_Controls->m_TractoBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_RegObjectBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TractoBox->SetPredicate(isFib); m_Controls->m_RegObjectBox->SetPredicate(isReg); connect( m_Controls->m_FixedImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(FixedImageChanged()) ); connect( m_Controls->m_MovingImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(MovingImageChanged()) ); connect( m_Controls->m_TractoBox, SIGNAL(currentIndexChanged(int)), this, SLOT(TractoChanged()) ); connect( m_Controls->m_RegObjectBox, SIGNAL(currentIndexChanged(int)), this, SLOT(TractoChanged()) ); connect( m_Controls->m_RegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartRegistration()) ); connect( m_Controls->m_TractoRegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartTractoRegistration()) ); FixedImageChanged(); MovingImageChanged(); TractoChanged(); } } void QmitkSimpleRegistrationView::StartTractoRegistration() { mitk::FiberBundle::Pointer fib = dynamic_cast(m_Controls->m_TractoBox->GetSelectedNode()->GetData()); mitk::MAPRegistrationWrapper::Pointer reg = dynamic_cast(m_Controls->m_RegObjectBox->GetSelectedNode()->GetData()); mitk::MITKRegistrationHelper::Affine3DTransformType::Pointer affine = mitk::MITKRegistrationHelper::getAffineMatrix(reg, false); mitk::FiberBundle::Pointer fib_copy = fib->GetDeepCopy(); fib_copy->TransformFibers(affine); mitk::DataNode::Pointer registration_node = mitk::DataNode::New(); registration_node->SetData(fib_copy); QString name = m_Controls->m_TractoBox->GetSelectedNode()->GetName().c_str(); registration_node->SetName((name+"_registered").toStdString().c_str()); GetDataStorage()->Add(registration_node, m_Controls->m_TractoBox->GetSelectedNode()); } void QmitkSimpleRegistrationView::TractoChanged() { if (m_Controls->m_RegObjectBox->GetSelectedNode().IsNotNull() && m_Controls->m_TractoBox->GetSelectedNode().IsNotNull()) m_Controls->m_TractoRegistrationStartButton->setEnabled(true); else m_Controls->m_TractoRegistrationStartButton->setEnabled(false); } void QmitkSimpleRegistrationView::FixedImageChanged() { if (m_Controls->m_FixedImageBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer image = dynamic_cast(m_Controls->m_FixedImageBox->GetSelectedNode()->GetData()); int channels = image->GetNumberOfChannels(); int dims = image->GetDimension(); int fourth_dim_size = image->GetTimeSteps(); bool isdiff = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image); if (dims==4 || channels>1) { m_Controls->m_FixedChannelBox->setEnabled(false); m_Controls->m_RegistrationStartButton->setEnabled(false); } if (isdiff) { m_Controls->m_FixedChannelBox->setEnabled(true); if (fourth_dim_size>1) m_Controls->m_FixedChannelBox->setMaximum(fourth_dim_size-1); else if (isdiff) m_Controls->m_FixedChannelBox->setMaximum(mitk::DiffusionPropertyHelper::GetGradientContainer(image)->Size()-1); } else { m_Controls->m_FixedChannelBox->setEnabled(false); } m_Controls->m_RegistrationStartButton->setEnabled(true); } else { m_Controls->m_FixedChannelBox->setEnabled(false); m_Controls->m_RegistrationStartButton->setEnabled(false); } } void QmitkSimpleRegistrationView::MovingImageChanged() { if (m_Controls->m_MovingImageBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer image = dynamic_cast(m_Controls->m_MovingImageBox->GetSelectedNode()->GetData()); int channels = image->GetNumberOfChannels(); int dims = image->GetDimension(); int fourth_dim_size = image->GetTimeSteps(); bool isdiff = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image); if (dims==4 || channels>1) { m_Controls->m_MovingChannelBox->setEnabled(false); m_Controls->m_RegistrationStartButton->setEnabled(false); } if (isdiff) { m_Controls->m_MovingChannelBox->setEnabled(true); if (fourth_dim_size>1) m_Controls->m_MovingChannelBox->setMaximum(fourth_dim_size-1); else if (isdiff) m_Controls->m_MovingChannelBox->setMaximum(mitk::DiffusionPropertyHelper::GetGradientContainer(image)->Size()-1); } else { m_Controls->m_MovingChannelBox->setEnabled(false); } m_Controls->m_RegistrationStartButton->setEnabled(true); } else { m_Controls->m_MovingChannelBox->setEnabled(false); m_Controls->m_RegistrationStartButton->setEnabled(false); } } void QmitkSimpleRegistrationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) { FixedImageChanged(); MovingImageChanged(); TractoChanged(); } void QmitkSimpleRegistrationView::SetFocus() { m_Controls->m_RegistrationStartButton->setFocus(); FixedImageChanged(); MovingImageChanged(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationViewControls.ui index b413b63e85..1073648dd4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationViewControls.ui @@ -1,316 +1,309 @@ QmitkSimpleRegistrationViewControls 0 0 435 744 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 25 Qt::Vertical 20 40 Image Registration 6 6 6 6 false Start Registration QFrame::NoFrame QFrame::Raised 0 0 0 0 Rigid Affine Registration Type: Output Registration Object: QFrame::NoFrame QFrame::Raised 0 0 0 0 Moving Image: false Select dMRI volume used to calculate transformation. false Select dMRI volume used to calculate transformation. Fixed Image: QFrame::NoFrame QFrame::Raised 0 0 0 0 false Start Tractography Registration Tractography Registration 6 6 6 6 Registration Object: Tractogram: QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationViewControls.ui index d213dba93f..3edd0a05a2 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationViewControls.ui @@ -1,165 +1,158 @@ QmitkTbssSkeletonizationViewControls 0 0 431 811 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 0 0 0 80 QFrame::StyledPanel QFrame::Raised false Mean: false Patient Data: false Tubular Structure Mask: false Skeletonize false Skeletonize and Project false Output binary mask true false Output distance map true \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui index 2628034274..fc056a2cfa 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui @@ -1,502 +1,495 @@ QmitkTractbasedSpatialStatisticsViewControls 0 0 265 811 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 0 0 FSL import Subject Data false false QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised Group information QAbstractItemView::SelectRows 0 0 110 100 QFrame::NoFrame QFrame::Raised 0 0 Add group entry. After that give the group a name and the correct number Add 0 0 Remove selected entries Remove false 0 0 Import a 4D image containing group data after group information has been set Import data 0 0 QFrame::StyledPanel QFrame::Raised 0 0 Measure Measurement in the to be imported 4D image FA 0 0 Tract-specific analysis true To create a roi first load a tbss meta image into the datamanager 0 ROIs 0 0 Points on Roi 100 100 0 100 Use this widget to create points on the ROI by shift-leftclick on the right positions on the skeleton. Then click Create Roi. The Roi that will be created will pass through the points in the order of occurence in this list false 0 0 No suitable tbss meta image selected yet. The meta image needs to contain a mean FA skeleton and a skeleton mask Create ROI 0 0 Points on the ROI 0 0 Name Give a name to the region of interest roiname 0 0 Structure info On what anatomical structure lies the ROI? Structure 0 0 current selection mean FA skeleton: Qt::Horizontal 253 20 Measuring 16777215 50 false #segments false 100 25 false Average false Cut To plot, load a tbss image with subject information and a region of interest corresponding to the study and select them both Copy to clipboard QmitkPointListWidget QWidget
QmitkPointListWidget.h
QmitkTbssRoiAnalysisWidget QWidget
QmitkTbssRoiAnalysisWidget.h
1
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/documentation/UserManual/QmitkGibbsTrackingViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/documentation/UserManual/QmitkGibbsTrackingViewUserManual.dox index 7f2d3dfca3..802ad0d4d5 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/documentation/UserManual/QmitkGibbsTrackingViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/documentation/UserManual/QmitkGibbsTrackingViewUserManual.dox @@ -1,38 +1,38 @@ /** \page org_mitk_views_gibbstracking Global Gibbs Tractography This view provides the user interface for the global Gibbs tractography algorithm, a global fiber tracking algorithm, originally proposed by Reisert et.al. [1]. The corresponding comman line application is named "MitkGlobalTractography". \tableofcontents \section QmitkGibbsTrackingUserManualInputData Input Data Mandatory Input: \li One ODF or tensor image selected in the datamanager Optional Input: \li Mask Image: White matter probability mask. Corresponds to the probability to generate fiber segments in the respective voxel. -\section QmitkGibbsTrackingUserManualParameters ODF Reconstruction +\section QmitkGibbsTrackingUserManualParameters Parameters \li Number of iterations: More iterations causes the algorithm to be more stable but also to take longer to finish the tracking. Recommended: minimum 10^8 iterations for full brain tractography. \li Particle length/width/weight controlling the contribution of each particle to the model M \li Start and end temperature controlling how fast the process reaches a stable state. (usually no change needed) \li Weighting between the internal (affinity of the model to long and straigt fibers) and external energy (affinity of the model towards the data). (usually no change needed). \li Minimum fiber length constraint (in mm). Shorter fibers are discarded after the tracking. The automatic selection of parameters for the particle length/width and weight are determined directly from the input image using information about the image spacing and GFA. \section QmitkGibbsTrackingUserManualTrackingSurveillance Surveilance of the tracking process Once started, the tracking can be monitored via the textual output that informs about the tracking progress and several stats of the current state of the algorithm. If enabled, the intermediate tracking results are displayed in the renderwindows each second. This live visualization should usually be disabled for performance reasons. It can be turned on and off during the tracking process via the according checkbox. The button next to this checkbox allows the visualization of only the next iteration step. \section QmitkGibbsTrackingUserManualReferences References [1] Reisert, M., Mader, I., Anastasopoulos, C., Weigel, M., Schnell, S., Kiselev, V.: Global fiber reconstruction becomes practical. Neuroimage 54 (2011) 955-962 */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/documentation/UserManual/QmitkStreamlineTrackingViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/documentation/UserManual/QmitkStreamlineTrackingViewUserManual.dox index 677c6f915b..8c9322383e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/documentation/UserManual/QmitkStreamlineTrackingViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/documentation/UserManual/QmitkStreamlineTrackingViewUserManual.dox @@ -1,96 +1,102 @@ /** \page org_mitk_views_streamlinetracking Streamline Tractography This view enables streamline tractography on various input data. The corresponding command line application is named "MitkStreamlineTractography". Available sections: - \ref StrTrackUserManualInputData - \ref StrTrackUserManualSeeding - \ref StrTrackUserManualConstraints - \ref StrTrackUserManualParameters - \ref StrTrackUserManualNeighbourhoodSampling - \ref StrTrackUserManualDataHandling - \ref StrTrackUserManualPostprocessing - \ref StrTrackUserManualReferences \section StrTrackUserManualInputData Input Data Select the data you want to track on in the datamanager. Supported file types are: - One or multiple DTI images selected in the datamanager. - One ODF image, e.g. obtained using MITK Q-ball reconstruction or MRtrix CSD (tractography similar to [6]). - One peak image (4D float image). - One raw diffusion-weighted image for machine learning based tractography [1]. -- Tractography Forest: Needed for machine learning based tractography [1]. \section StrTrackUserManualSeeding Seeding Specify how, where and how many tractography seed points are placed. This can be either done statically using a seed image or in an interactive fashion. Interactive tractography enables the dynamic placement of spherical seed regions simply by clicking into the image (similar to [5]). Image based seeding: - Seed Image: ROI image used to define the seed voxels. If no seed mask is specified, the whole image volume is seeded. - Seeds per voxel: If set to 1, the seed is defined as the voxel center. If > 1 the seeds are distributet randomly inside the voxel. Interactive seeding: - Update on Parameter Change: When "Update on Parameter Change" is checked, each parameter change causes an instant retracking with the new parameters. This enables an intuitive exploration of the effects that the other tractography parameters have on the resulting tractogram. - Radius: Radius of the manually placed spherical seed region. - Num.Seeds: Number of seeds placed randomly inside the spherical seed region. Parameters for both seeding modes: - Trials Per Seed: Try each seed N times until a valid streamline is obtained (only for probabilistic tractography). - Max. Num. Fibers: Tractography is stopped after the desired number of fibers is reached, even before all seed points are processed. \section StrTrackUserManualConstraints ROI Constraints Specify various ROI and mask images to constrain the tractography process. - Mask Image: ROI image used to constrain the generated streamlines, typically a brain mask. Streamlines that leave the regions defined in this image will stop immediately. - Stop ROI Image: ROI image used to define stopping regions. Streamlines that enter the regions defined in this image will stop immediately. - Exclusion ROI Image: Fibers that enter a region defined in this image will be discarded. - Endpoint Constraints: Determines which fibers are accepted based on their endpoint location. Options are: - No constraints on endpoint locations (command line option NONE) - Both EPs are required to be located in the target image (command line option EPS_IN_TARGET) - Both EPs are required to be located in the target image and the image values at the respective position needs to be distinct (command line option EPS_IN_TARGET_LABELDIFF) - One EP is required to be located in the seed image and one in the target image (command line option EPS_IN_SEED_AND_TARGET) - At least one EP is required to be located in the target image (command line option MIN_ONE_EP_IN_TARGET) - Exactly one EP is required to be located in the target image (command line option ONE_EP_IN_TARGET) - No EP is allowed to be located in the target image (command line option NO_EP_IN_TARGET) - Target Image: ROI image needed for endpoint constraints. \section StrTrackUserManualParameters Tractography Parameters - Mode: Toggle between deterministic and probabilistic tractography. Peak tracking only supports deterministic mode. The probabilistic method simply samples the output direction from the discrete probability ditribution provided by the discretized ODF. - Sharpen ODFs: If you are using dODF images as input, it is advisable to sharpen the ODFs (min-max normalize and raise to the power of 4). This is not necessary (and not recommended) for CSD fODFs, since they are naturally much sharper. - Cutoff: If the streamline reaches a position with an FA value or peak magnitude lower than the speciefied threshold, tracking is terminated. Typical values are 0.2 for FA/GFA and 0.1 for CSD peaks. - FA/GFA image used to determine streamline termination. If no image is specified, the FA/GFA image is automatically calculated from the input image. If multiple tensor images are used as input, it is recommended to provide such an image since the FA maps calculated from the individual input tensor images can not provide a suitable termination criterion. - ODF Cutoff: Additional threshold on the ODF magnitude. This is useful in case of CSD fODF tractography. For fODFs a good default value is 0.1, for normalized dODFs, e.g. Q-ball ODFs, this threshold should be very low (0.00025) or 0. - Step Size: The algorithm proceeds along the streamline with a fixed stepsize. Default is 0.5*minSpacing. - Min. Tract Length: Shorter fibers are discarded. - Angular threshold: Maximum angle between two successive steps (in degree). Default is 90° * step_size. For probabilistic tractography, candidate directions exceeding this threshold have probability 0, i.e. the respective ODF value is set to zero. The probabilities of the valid directions are normalized to sum to 1. - Loop Check: Stop streamline if the threshold on the angular stdev over the last 4 voxel lengths is exceeded. -1 = no loop check. - f and g values to balance between FACT [2] and TEND [3,4] tracking (only for tensor based tractography). For further information please refer to [2,3] +\section StrTrackUserManualTractographyPrior Tractography Prior +It is possible to use a peak image as prior for tractography on arbitrary other input images. The local progression direction is determined as the weighted average between the direction obtained from the prior and the input data. +- Weight: Weighting factor between prior and input data directions. A weight of zero means that no prior iformation is used. With a weight of one, tractography is performed directly on the prior directions itself. +- Restrict to Prior: The prior image is used as tractography mask. Voxels without prior peaks are excluded. +- New Directions from Prior: By default, the prior is used even if there is no valid direction found in the data. If unchecked, the prior cannot create directions where there are none in the data. + \section StrTrackUserManualDataHandling Data Handling - Flip directions: Internally flips progression directions. This might be necessary depending on the input data. - Interpolate Tractography Data: Trilinearly interpolate the input image used for tractography. - Interpolate ROI Images: Trilinearly interpolate the ROI images used to constrain the tractography. \section StrTrackUserManualNeighbourhoodSampling Neighbourhood Sampling (for details see [1]) - Neighborhood Samples: Number of neighborhood samples that are used to determine the next fiber progression direction. - Sampling Distance: Distance of the sampling positions from the current streamline position (in voxels). - Use Only Frontal Samples: Only neighborhood samples in front of the current streamline position are considered. - Use Stop-Votes: If checked, the majority of sampling points has to place a stop-vote for the streamline to terminate. If not checked, all sampling positions have to vote for a streamline termination. \section StrTrackUserManualPostprocessing Output and Postprocessing - Compress Fibers: Whole brain tractograms obtained with a small step size can contain billions of points. The tractograms can be compressed by removing points that do not really contribute to the fiber shape, such as many points on a straight line. An error threshold (in mm) can be defined to specify which points should be removed and which not. - Output Probability Map: No streamline are generated. Instead, the tractography outputs a visitation-count map that indicates the probability of a fiber to reach a voxel from the selected seed region. For this measure to be sensible, the number of seeds per voxel needs to be rather large. \section StrTrackUserManualReferences References [1] Neher, Peter F., Marc-Alexandre Côté, Jean-Christophe Houde, Maxime Descoteaux, and Klaus H. Maier-Hein. “Fiber Tractography Using Machine Learning.” NeuroImage. Accessed July 19, 2017. doi:10.1016/j.neuroimage.2017.07.028.\n [2] Mori, Susumu, Walter E. Kaufmann, Godfrey D. Pearlson, Barbara J. Crain, Bram Stieltjes, Meiyappan Solaiyappan, and Peter C. M. Van Zijl. “In Vivo Visualization of Human Neural Pathways by Magnetic Resonance Imaging.” Annals of Neurology 47 (2000): 412–414.\n [3] Weinstein, David, Gordon Kindlmann, and Eric Lundberg. “Tensorlines: Advection-Diffusion Based Propagation through Diffusion Tensor Fields.” In Proceedings of the Conference on Visualization’99: Celebrating Ten Years, 249–253, n.d.\n [4] Lazar, Mariana, David M. Weinstein, Jay S. Tsuruda, Khader M. Hasan, Konstantinos Arfanakis, M. Elizabeth Meyerand, Benham Badie, et al. “White Matter Tractography Using Diffusion Tensor Deflection.” Human Brain Mapping 18, no. 4 (2003): 306–321.\n [5] Chamberland, M., K. Whittingstall, D. Fortin, D. Mathieu, and M. Descoteaux. “Real-Time Multi-Peak Tractography for Instantaneous Connectivity Display.” Front Neuroinform 8 (2014): 59. doi:10.3389/fninf.2014.00059.\n [6] Tournier, J-Donald, Fernando Calamante, and Alan Connelly. “MRtrix: Diffusion Tractography in Crossing Fiber Regions.” International Journal of Imaging Systems and Technology 22, no. 1 (March 2012): 53–66. doi:10.1002/ima.22005. */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingViewControls.ui index dd1813e50f..ea598ceab8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingViewControls.ui @@ -1,1206 +1,1199 @@ QmitkGibbsTrackingViewControls 0 0 463 1011 0 0 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } QFormLayout::AllNonFixedFieldsGrow QFrame::NoFrame QFrame::Plain 0 0 0 0 0 6 false No ODF/tensor image selected. Qt::LeftToRight Start Tractography :/QtWidgetsExt/play.xpm :/QtWidgetsExt/play.xpm false Qt::LeftToRight Stop Tractography :/QtWidgetsExt/stop.xpm :/QtWidgetsExt/stop.xpm Parameters 6 6 6 6 Output File: Advanced Settings true Activate continuous visualization of intermediate results. Visualize Tractography true QFrame::NoFrame QFrame::Plain 0 0 0 0 0 0 Select output file name and folder. ... N/A true Visualize intermediate result. :/QmitkDiffusionImaging/Refresh_48.png :/QmitkDiffusionImaging/Refresh_48.png true Iterations: 1e9 true QFrame::StyledPanel QFrame::Raised 0 0 0 0 6 Particle Width: 0 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 0.1 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Particle Weight: 1 99 1 10 Qt::Horizontal QSlider::NoTicks Start Temperature: automatic estimation from gfa map and ODF data. 0 1000 1 0 Qt::Horizontal true QSlider::NoTicks IE Bias < 0 < EE Bias -50 50 1 Qt::Horizontal QSlider::NoTicks 0.001 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Curvature Threshold: Balance In/Ex Energy: 45° Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter auto = 0.5 * min. spacing; sigma 100 1 Qt::Horizontal QSlider::NoTicks Particle Length: auto Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Min. Fiber Length: Only fibers longer than specified are accepted. 500 1 20 Qt::Horizontal QSlider::NoTicks Allow only fiber curvature values smaller than the selected threshold. 180 1 45 Qt::Horizontal QSlider::NoTicks End Temperature: 20mm Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter auto Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 1 100 1 10 Qt::Horizontal false false QSlider::NoTicks auto Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter auto = 1.5 * min. spacing; l 100 1 Qt::Horizontal QSlider::NoTicks Random Seed auto Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter auto = 1.5 * min. spacing; l -1 100 1 -1 Qt::Horizontal QSlider::NoTicks QFrame::NoFrame QFrame::Plain 0 0 0 0 0 6 true Save current parameters as xml (.gtp) Qt::LeftToRight Save Parameters :/QmitkDiffusionImaging/general_icons/download.ico :/QmitkDiffusionImaging/general_icons/download.ico true Load parameters from xml file (.gtp) Qt::LeftToRight Load Parameters :/QmitkDiffusionImaging/general_icons/upload.ico :/QmitkDiffusionImaging/general_icons/upload.ico Qt::Vertical QSizePolicy::Expanding 0 0 0 0 Input Data 6 6 6 6 0 0 ODF/Tensor Image: Mask Image: 0 0 0 0 0 0 Monitor 6 6 6 6 6 Progress: - Will only be updated if tracking is visualized Will only be updated if tracking is visualized Accepted Fibers: Connections: Particles: Proposal Acceptance Rate: Tracking Time: Will only be updated if tracking is visualized - - - - - QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkMLBTViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkMLBTViewControls.ui index f42e1f2b6b..cc06db5811 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkMLBTViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkMLBTViewControls.ui @@ -1,472 +1,465 @@ QmitkMLBTViewControls 0 0 476 548 Form QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Remove training data pair ... :/org_mitk_icons/icons/tango/scalable/actions/list-remove.svg :/org_mitk_icons/icons/tango/scalable/actions/list-remove.svg Add additional training data pair ... :/org_mitk_icons/icons/tango/scalable/actions/list-add.svg :/org_mitk_icons/icons/tango/scalable/actions/list-add.svg <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">It is recommended to use the command line application 'RfTraining' instead of this graphical user interface for the training process. Additional feature images are not supported here.</span></p><p><span style=" font-weight:600; color:#ff0000;">The GUI is intended for testing using small examples.</span></p></body></html> Qt::RichText Qt::AlignCenter true 5 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Input DWI: Qt::AlignCenter Reference Tractogram: Qt::AlignCenter Mask: Qt::AlignCenter WM: Qt::AlignCenter QFrame::NoFrame QFrame::Raised 0 0 0 0 Fraction of samples used to train each tree. 3 1.000000000000000 0.100000000000000 0.700000000000000 Num. Trees: Sample Fraction: Max. Depth: Fiber sampling in mm. Determines the number of white-matter samples (-1 = auto). 3 -1.000000000000000 999.000000000000000 0.100000000000000 -1.000000000000000 Number of tress in the final random forest. 1 999999999 30 Non-WM Sampling Points: Fiber Sampling: Maximum tree depth. 1 999999999 25 Number of sampling points outside of the white-matter (-1 = automatic estimation). -1 999999999 -1 Num. previous directions: Number of previous fiber directions used as features. 0 50 1 dMRI Features: Spherical Harmonics Coefficients Raw Data Start Training. This can take up to a couple of hours. Start Training Qt::Vertical 20 40 \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui index e8d893c49c..32fc1145d5 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui @@ -1,1597 +1,1590 @@ QmitkStreamlineTrackingViewControls 0 0 453 859 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 3 3 0 40 QFrame::NoFrame QFrame::Raised 0 15 0 0 6 15 true 0 0 true QFrame::NoFrame QFrame::Raised 0 0 0 0 Input Image. ODF, tensor and peak images are currently supported. Input Image: Input Image. ODF, tensor, peak, and, in case of ML tractography, raw diffusion-weighted images are currently supported. <html><head/><body><p><span style=" color:#ff0000;">select image in data-manager</span></p></body></html> true Tractography Forest: Random forest for machine learning based tractography. QComboBox::AdjustToMinimumContentsLength - true Stop tractography and return all fibers reconstructed until now. Stop Tractography false Start Tractography 0 0 0 0 0 0 0 421 - 267 + 262 Seeding Specify how, where and how many tractography seed points are placed. QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Number of seed points equally distributed around selected position. 1 9999999 50 Radius: Seedpoints are equally distributed within a sphere centered at the selected position with the specified radius (in mm). 2 50.000000000000000 0.100000000000000 2.000000000000000 Num. Seeds: true When checked, parameter changes cause instant retracking while in interactive mode. Update on Parameter Change true QFrame::NoFrame QFrame::Raised 0 0 0 0 Try each seed N times until a valid streamline is obtained (only for probabilistic tractography). Minimum fiber length (in mm) 1 999 10 Trials Per Seed: Max. Num. Fibers: Tractography is stopped after the desired number of fibers is reached, even before all seed points are processed (-1 means no limit). -1 999999999 -1 QFrame::NoFrame QFrame::Raised 0 0 0 0 Number of seed points placed in each voxel. 1 9999999 Seeds per Voxel: Seed points are only placed inside the regions defined in the seed image. If no seed image is selected, the whole image is seeded. QComboBox::AdjustToMinimumContentsLength - Seed Image: true Dynamically pick a seed location by click into image. Enable Interactive Tractography Qt::Vertical 20 40 0 0 435 224 ROI Constraints Specify various ROI and mask images to constrain the tractography process. Mask Image: Fibers that enter a region defined in this image will stop immediately. QComboBox::AdjustToMinimumContentsLength - Select which fibers should be accepted or rejected based on the location of their endpoints. QComboBox::AdjustToMinimumContentsLength No Constraints on EP locations Both EPs in Target Image Both EPs in Target Image But Different Label One EP in Seed Image and One EP in Target Image At Least One EP in Target Image Exactly One EP in Target Image No EP in Target Image Endpoint Constraints: Stop ROI Image: The target image is used for the endpoint constraint strategy defined above. QComboBox::AdjustToMinimumContentsLength - Exclusion ROI Image: Fibers that leave the regions defined in this image will stop immediately. QComboBox::AdjustToMinimumContentsLength - Target ROI Image: Fibers that enter a region defined in this image will be discarded. QComboBox::AdjustToMinimumContentsLength - Qt::Vertical 20 40 0 0 421 - 359 + 351 Tractography Parameters Specify the behavior of the tractography at each streamline integration step (step size, deterministic/probabilistic, ...). Qt::Vertical 20 40 f=1 + g=0 means FACT (depending on the chosen interpolation). f=0 and g=1 means TEND (disable interpolation for this mode!). 2 1.000000000000000 0.100000000000000 0.000000000000000 Toggle between deterministic and probabilistic tractography. Some modes might not be available for all types of tractography. Deterministic Probabilistic Cutoff: FA/GFA Image: Mode: Angular Threshold: Step size (in voxels) 2 0.010000000000000 10.000000000000000 0.100000000000000 0.500000000000000 Maximum allowed angular SDTEV over 4 voxel lengths. Default: no loop check. -1 180 -1 If an image is selected, the stopping criterion is not calculated from the input image but instead the selected image is used. QComboBox::AdjustToMinimumContentsLength - Step Size: Additional threshold on the ODF magnitude. This is useful in case of CSD fODF tractography. For fODFs a good default value is 0.1, for normalized dODFs, e.g. Q-ball ODFs, this threshold should be very low (0.00025) or 0. 5 1.000000000000000 0.100000000000000 0.000250000000000 f=1 + g=0 means FACT (depending on the chosen interpolation). f=0 and g=1 means TEND (disable interpolation for this mode!). 2 1.000000000000000 0.100000000000000 1.000000000000000 If you are using dODF images as input, it is advisable to sharpen the ODFs (min-max normalize and raise to the power of 4). This is not necessary for CSD fODFs, since they are naturally much sharper. f parameter of tensor tractography. f=1 + g=0 means FACT (depending on the chosen interpolation). f=0 and g=1 means TEND (disable interpolation for this mode!). f: Min. Tract Length: Threshold on peak magnitude, FA, GFA, ... 5 1.000000000000000 0.100000000000000 0.100000000000000 ODF Cutoff: Minimum tract length in mm. Shorter fibers are discarded. Minimum fiber length (in mm) 1 999.000000000000000 1.000000000000000 20.000000000000000 Loop Check: Angular threshold between two steps (in degree). Default: 90° * step_size -1 90 1 -1 g: Sharpen ODFs: 0 0 435 224 Tractography Prior Restrict to Prior: Weight: Peak Image: Weighting factor between prior and data. 1.000000000000000 0.100000000000000 0.500000000000000 Restrict tractography to regions where the prior is valid. true Qt::Vertical 20 40 - New Directions From Prior: + New Directions from Prior: If unchecked, the prior cannot create directions where there are none in the data. - false + true 0 0 435 224 Neighborhood Sampling Specify if and how information about the current streamline neighborhood should be used. Only neighborhood samples in front of the current streamline position are considered. Use Only Frontal Samples false If checked, the majority of sampling points has to place a stop-vote for the streamline to terminate. If not checked, all sampling positions have to vote for a streamline termination. Use Stop-Votes false QFrame::NoFrame QFrame::Raised 0 0 0 0 Num. Samples: Number of neighborhood samples that are used to determine the next fiber progression direction. 50 Sampling Distance: Sampling distance (in voxels) 2 10.000000000000000 0.100000000000000 0.250000000000000 Qt::Vertical 20 40 0 0 435 224 Data Handling Specify interpolation and direction flips. QFrame::NoFrame QFrame::Raised 0 0 0 0 Trilinearly interpolate the input image used for tractography. Interpolate Tractography Data true Trilinearly interpolate the ROI images used to constrain the tractography. Interpolate ROI Images true QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Internally flips progression directions. This might be necessary depending on the input data. x Internally flips progression directions. This might be necessary depending on the input data. y Internally flips progression directions. This might be necessary depending on the input data. z Flip directions: Qt::Vertical 20 40 0 0 435 224 Output and Postprocessing Specify the tractography output (streamlines or probability maps) and postprocessing steps. QFrame::NoFrame QFrame::Raised 0 0 0 0 Compress fibers using the specified error constraint. Compress Fibers true Qt::StrongFocus Lossy fiber compression. Recommended for large tractograms. Maximum error in mm. 3 10.000000000000000 0.010000000000000 0.100000000000000 Output map with voxel-wise visitation counts instead of streamlines. Output Probability Map false Qt::Vertical 20 40 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui index 670cecafb9..9d779a6a02 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui @@ -1,1037 +1,1030 @@ QmitkControlVisualizationPropertiesViewControls 0 0 567 619 0 100 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Multislice Projection MIP QToolButton::MenuButtonPopup Qt::NoArrow QFrame::NoFrame QFrame::Plain 0 0 0 0 Toggle visibility of ODF glyphs (axial) :/QmitkDiffusionImaging/glyphsoff_T.png :/QmitkDiffusionImaging/glyphson_T.png :/QmitkDiffusionImaging/glyphsoff_T.png true false Toggle visibility of ODF glyphs (sagittal) :/QmitkDiffusionImaging/glyphsoff_S.png :/QmitkDiffusionImaging/glyphson_S.png :/QmitkDiffusionImaging/glyphsoff_S.png true false Toggle visibility of ODF glyphs (coronal) :/QmitkDiffusionImaging/glyphsoff_C.png :/QmitkDiffusionImaging/glyphson_C.png :/QmitkDiffusionImaging/glyphsoff_C.png true false #Glyphs 9999 Qt::Horizontal 20 20 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Plain 0 0 0 0 ODF normalization false Min-Max Max None ODF Normalization: ODF normalization false ODF Value Principal Direction Color ODFs/Tensors by: QFrame::NoFrame QFrame::Plain 0 0 0 0 ODF Scale: false None FA/GFA * Additional scaling factor 3 999999999.000000000000000 0.100000000000000 1.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Reset to Default Coloring :/QmitkDiffusionImaging/color64.gif :/QmitkDiffusionImaging/color64.gif Reset to Default Coloring :/QmitkDiffusionImaging/reset.png :/QmitkDiffusionImaging/reset.png Position Crosshair by 3D-Click :/QmitkDiffusionImaging/crosshair.png :/QmitkDiffusionImaging/crosshair.png true false 2D Fiberfading on/off Qt::Horizontal 40 20 QFrame::NoFrame QFrame::Raised 0 0 0 0 2D Clipping 100 10 10 10 Qt::Horizontal 90 0 10000 16777215 Range QFrame::NoFrame QFrame::Raised 0 0 0 0 Tube Radius 3 0.100000000000000 Ribbon Width 3 0.100000000000000 50 false false <!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:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#ff0000;">One or more slices are rotated. ODF Visualisation is not possible in rotated planes. Use 'Reinit' on the image node to reset. </span></p></body></html> Qt::AutoText true QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 y z x 0 0 Flip Peaks QFrame::NoFrame QFrame::Raised 0 0 0 0 Reset to Default Coloring :/QmitkDiffusionImaging/reset.png :/QmitkDiffusionImaging/reset.png Reset to Default Coloring :/QmitkDiffusionImaging/color64.gif :/QmitkDiffusionImaging/color64.gif Qt::Horizontal 40 20 Line Width 1 1.000000000000000 0.100000000000000 1.000000000000000 3D Clipping 6 6 6 6 0 Coronal Axial No clipping true Sagittal Flipp Clipping Direction Enable 3D Rendering Qt::Vertical 20 40 QmitkDataStorageComboBox.h \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorViewControls.ui index f80e09d34d..5c160ad17e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorViewControls.ui @@ -1,193 +1,186 @@ QmitkDicomTractogramTagEditorViewControls 0 0 397 366 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 3 3 0 QFrame::NoFrame QFrame::Raised 0 0 0 9 Tractogram: Seed points are only placed inside the mask image. If no seed mask is selected, the whole image is seeded. QComboBox::AdjustToMinimumContentsLength - Tractography DICOM Tags 6 6 6 6 0 QFrame::NoFrame Qt::ScrollBarAlwaysOff QAbstractScrollArea::AdjustToContents Qt::Vertical QSizePolicy::Expanding 20 220 Copies the DICOM properties of the tractogram selected in this view to the one selected in the datamanager. Copy Properties From Image QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
\ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportViewControls.ui index 736bf50aa2..336dc2fbac 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportViewControls.ui @@ -1,408 +1,401 @@ QmitkDiffusionDicomImportControls 0 0 374 603 0 0 true QmitkDiffusionDicomImport QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 16777215 70 QFrame::NoFrame QFrame::Plain 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:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;"> <tr> <td style="border: none;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:10pt;">Each input folder must only contain DICOM-images that can be combined into one vector-valued 3D output volume. Different patients must be loaded from different input-folders. The folders must not contain other acquisitions (e.g. T1,T2,localizer).</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></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-family:'Sans'; font-size:10pt;">In case many imports are performed at once, it is recommended to set the the optional output folder argument. This prevents the images from being kept in memory.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></p></td></tr></table></body></html> 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Add Input Folders Remove Clear 0 0 0 70 QFrame::Box QFrame::Plain 1 0 Qt::ScrollBarAsNeeded Qt::ScrollBarAlwaysOn QListView::Adjust true QFrame::StyledPanel QFrame::Raised Recursive 8 QLayout::SetNoConstraint Set Prefix Reset Multiple acquistions of one gradient direction can be averaged. Due to rounding errors, similar gradients often differ in the last decimal positions. The Merge radius allows to average them anyway by taking into account all directions within a certain radius. QFrame::NoFrame QFrame::Raised 0 0 0 0 Merge duplicate gradients: false 4 2.000000000000000 0.000100000000000 0.001000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 40 25 30 16777215 Files are automaticall saved to disc. If the files can not be written, they are added to the data manager. Set ... optional out-folder ... false true 50 25 30 16777215 Clear Override existing files Split Mosaic Import DICOM as *.dwi Qt::Vertical 20 40 \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkWelcomeScreenViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkWelcomeScreenViewControls.ui index 536be45e1e..e567f646f8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkWelcomeScreenViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkWelcomeScreenViewControls.ui @@ -1,71 +1,64 @@ QmitkWelcomeScreenViewControls 0 0 458 398 0 0 QmitkTemplate QCommandLinkButton { - font-weight: normal; + font-weight: lighter; } QCommandLinkButton:disabled { border: none; font-weight: lighter; } QToolBox::tab { - border: 1px solid #434346; font-weight: bold; } QToolBox::tab:hover { - background-color: #434346; font-weight: bold; } QToolBox::tab:selected { - background-color: #1c97ea; - border: 1px solid #1c97ea; font-weight: bold; } QGroupBox { - border: 1px solid #434346; - background-color: #2d2d30; - margin-top: 8px; - padding-top: 8px; + background-color: transparent; } QGroupBox, QGroupBox:disabled { - background-color: #2d2d30; + background-color: transparent; } 0 \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp index bd6d29d4c9..db3c0c8b0c 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp @@ -1,428 +1,427 @@ /*=================================================================== 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 "QmitkUSNavigationStepTumourSelection.h" #include "ui_QmitkUSNavigationStepTumourSelection.h" #include "usModuleRegistry.h" #include "mitkDataNode.h" #include "mitkSurface.h" #include "mitkUSCombinedModality.h" #include "../Interactors/mitkUSZonesInteractor.h" #include "mitkNodeDisplacementFilter.h" #include "QmitkUSNavigationStepCombinedModality.h" #include "../QmitkUSNavigationMarkerPlacement.h" #include "mitkIOUtil.h" #include "vtkSmartPointer.h" #include "vtkDoubleArray.h" #include "vtkPolyData.h" #include "vtkPointData.h" #include "vtkWarpScalar.h" QmitkUSNavigationStepTumourSelection::QmitkUSNavigationStepTumourSelection(QWidget* parent) : QmitkUSAbstractNavigationStep(parent), m_targetSelectionOptional(false), m_SecurityDistance(0), m_Interactor(mitk::USZonesInteractor::New()), m_NodeDisplacementFilter(mitk::NodeDisplacementFilter::New()), m_StateMachineFilename("USZoneInteractions.xml"), m_ReferenceSensorIndex(1), m_ListenerChangeNode(this, &QmitkUSNavigationStepTumourSelection::TumourNodeChanged), ui(new Ui::QmitkUSNavigationStepTumourSelection) { ui->setupUi(this); connect(ui->freezeImageButton, SIGNAL(SignalFreezed(bool)), this, SLOT(OnFreeze(bool))); connect(ui->tumourSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnTumourSizeChanged(int))); connect(ui->deleteTumourButton, SIGNAL(clicked()), this, SLOT(OnDeleteButtonClicked())); m_SphereColor = mitk::Color(); //default color: green m_SphereColor[0] = 0; m_SphereColor[1] = 255; m_SphereColor[2] = 0; } void QmitkUSNavigationStepTumourSelection::SetTumorColor(mitk::Color c) { m_SphereColor = c; } void QmitkUSNavigationStepTumourSelection::SetTargetSelectionOptional(bool t) { m_targetSelectionOptional = t; } QmitkUSNavigationStepTumourSelection::~QmitkUSNavigationStepTumourSelection() { delete ui; } bool QmitkUSNavigationStepTumourSelection::OnStartStep() { m_TumourNode = this->GetNamedDerivedNodeAndCreate( QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); m_TumourNode->SetColor(m_SphereColor[0], m_SphereColor[1], m_SphereColor[2]); // load state machine and event config for data interactor m_Interactor->LoadStateMachine(m_StateMachineFilename, us::ModuleRegistry::GetModule("MitkUS")); m_Interactor->SetEventConfig("globalConfig.xml"); this->GetDataStorage()->ChangedNodeEvent.AddListener(m_ListenerChangeNode); m_TargetSurfaceNode = this->GetNamedDerivedNodeAndCreate( QmitkUSNavigationMarkerPlacement::DATANAME_TARGETSURFACE, QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR); // do not show the surface until this is requested m_TargetSurfaceNode->SetBoolProperty("visible", false); // make sure that scalars will be renderer on the surface m_TargetSurfaceNode->SetBoolProperty("scalar visibility", true); m_TargetSurfaceNode->SetBoolProperty("color mode", true); m_TargetSurfaceNode->SetBoolProperty("Backface Culling", true); return true; } bool QmitkUSNavigationStepTumourSelection::OnStopStep() { // make sure that imaging isn't freezed anymore ui->freezeImageButton->Unfreeze(); m_NodeDisplacementFilter->ResetNodes(); mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(false); if (dataStorage.IsNotNull()) { // remove target surface node from data storage, if available there if (m_TargetSurfaceNode.IsNotNull()) { dataStorage->Remove(m_TargetSurfaceNode); } dataStorage->ChangedNodeEvent.RemoveListener(m_ListenerChangeNode); dataStorage->Remove(m_TumourNode); m_TumourNode = 0; } MITK_INFO("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection") << "Removing tumour."; return true; } bool QmitkUSNavigationStepTumourSelection::OnRestartStep() { ui->tumourSizeExplanationLabel->setEnabled(false); ui->tumourSizeLabel->setEnabled(false); ui->tumourSizeSlider->setEnabled(false); ui->deleteTumourButton->setEnabled(false); ui->tumourSizeSlider->blockSignals(true); ui->tumourSizeSlider->setValue(0); ui->tumourSizeSlider->blockSignals(false); - emit SignalNoLongerReadyForNextStep(); return QmitkUSAbstractNavigationStep::OnRestartStep(); } bool QmitkUSNavigationStepTumourSelection::OnFinishStep() { // make sure that the surface has the right extent (in case the // tumor size was changed since the initial surface creation) m_TargetSurfaceNode->SetData(this->CreateTargetSurface()); return true; } bool QmitkUSNavigationStepTumourSelection::OnActivateStep() { m_Interactor = mitk::USZonesInteractor::New(); m_Interactor->LoadStateMachine(m_StateMachineFilename, us::ModuleRegistry::GetModule("MitkUS")); m_Interactor->SetEventConfig("globalConfig.xml"); m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); //target selection is optional if (m_targetSelectionOptional) { emit SignalReadyForNextStep(); } return true; } bool QmitkUSNavigationStepTumourSelection::OnDeactivateStep() { m_Interactor->SetDataNode(0); bool value; if (m_TumourNode.IsNotNull() && !(m_TumourNode->GetBoolProperty("zone.created", value) && value)) { m_TumourNode->SetData(0); } // make sure that imaging isn't freezed anymore ui->freezeImageButton->Unfreeze(); return true; } void QmitkUSNavigationStepTumourSelection::OnUpdate() { if (m_NavigationDataSource.IsNull()) { return; } m_NavigationDataSource->Update(); bool valid = m_NavigationDataSource->GetOutput(m_ReferenceSensorIndex)->IsDataValid(); if (valid) { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume."); } else { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume."); } ui->freezeImageButton->setEnabled(valid); bool created; if (m_TumourNode.IsNull() || !m_TumourNode->GetBoolProperty("zone.created", created) || !created) { ui->tumourSearchExplanationLabel->setEnabled(valid); } } void QmitkUSNavigationStepTumourSelection::OnSettingsChanged(const itk::SmartPointer settingsNode) { if (settingsNode.IsNull()) { return; } float securityDistance; if (settingsNode->GetFloatProperty("settings.security-distance", securityDistance)) { m_SecurityDistance = securityDistance; } std::string stateMachineFilename; if (settingsNode->GetStringProperty("settings.interaction-concept", stateMachineFilename) && stateMachineFilename != m_StateMachineFilename) { m_StateMachineFilename = stateMachineFilename; m_Interactor->LoadStateMachine(stateMachineFilename, us::ModuleRegistry::GetModule("MitkUS")); } std::string referenceSensorName; if (settingsNode->GetStringProperty("settings.reference-name-selected", referenceSensorName)) { m_ReferenceSensorName = referenceSensorName; } this->UpdateReferenceSensorName(); } QString QmitkUSNavigationStepTumourSelection::GetTitle() { return "Localisation of Tumour Position"; } QmitkUSAbstractNavigationStep::FilterVector QmitkUSNavigationStepTumourSelection::GetFilter() { return FilterVector(1, m_NodeDisplacementFilter.GetPointer()); } void QmitkUSNavigationStepTumourSelection::OnFreeze(bool freezed) { if (freezed) this->GetCombinedModality()->SetIsFreezed(true); ui->tumourSelectionExplanation1Label->setEnabled(freezed); ui->tumourSelectionExplanation2Label->setEnabled(freezed); if (freezed) { if (!m_TumourNode->GetData()) { // load state machine and event config for data interactor m_Interactor->LoadStateMachine(m_StateMachineFilename, us::ModuleRegistry::GetModule("MitkUS")); m_Interactor->SetEventConfig("globalConfig.xml"); m_Interactor->SetDataNode(m_TumourNode); // feed reference pose to node displacement filter m_NodeDisplacementFilter->SetInitialReferencePose(this->GetCombinedModality()->GetNavigationDataSource()->GetOutput(m_ReferenceSensorIndex)->Clone()); } } else { bool value; if (m_TumourNode->GetBoolProperty("zone.created", value) && value) { ui->freezeImageButton->setEnabled(false); ui->tumourSearchExplanationLabel->setEnabled(false); } } if (!freezed) this->GetCombinedModality()->SetIsFreezed(false); } void QmitkUSNavigationStepTumourSelection::OnSetCombinedModality() { mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNotNull()) { m_NavigationDataSource = combinedModality->GetNavigationDataSource(); } else { m_NavigationDataSource = 0; } ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex); this->UpdateReferenceSensorName(); } void QmitkUSNavigationStepTumourSelection::OnTumourSizeChanged(int size) { m_TumourNode->SetFloatProperty("zone.size", static_cast(size)); mitk::USZonesInteractor::UpdateSurface(m_TumourNode); MITK_INFO("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection") << "Changing tumour radius to " << size << "."; } void QmitkUSNavigationStepTumourSelection::OnDeleteButtonClicked() { this->OnRestartStep(); } void QmitkUSNavigationStepTumourSelection::TumourNodeChanged(const mitk::DataNode* dataNode) { // only changes of tumour node are of interest if (dataNode != m_TumourNode) { return; } float size; dataNode->GetFloatProperty("zone.size", size); ui->tumourSizeSlider->setValue(static_cast(size)); bool created; if (dataNode->GetBoolProperty("zone.created", created) && created) { if (ui->freezeImageButton->isChecked()) { m_NodeDisplacementFilter->AddNode(const_cast(dataNode)); m_TargetSurfaceNode->SetData(this->CreateTargetSurface()); m_NodeDisplacementFilter->AddNode(m_TargetSurfaceNode); MITK_INFO("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection") << "Tumour created with center " << dataNode->GetData()->GetGeometry()->GetOrigin() << " and radius " << size << "."; mitk::DataNode::Pointer tumourResultNode = mitk::DataNode::New(); tumourResultNode->SetName("TumourResult"); tumourResultNode->SetProperty("USNavigation::TumourCenter", mitk::Point3dProperty::New(dataNode->GetData()->GetGeometry()->GetOrigin())); tumourResultNode->SetProperty("USNavigation::TumourRadius", mitk::DoubleProperty::New(size)); emit SignalIntermediateResult(tumourResultNode); ui->freezeImageButton->Unfreeze(); } ui->tumourSearchExplanationLabel->setEnabled(false); ui->tumourSizeExplanationLabel->setEnabled(true); ui->tumourSizeLabel->setEnabled(true); ui->tumourSizeSlider->setEnabled(true); ui->deleteTumourButton->setEnabled(true); emit SignalReadyForNextStep(); } } mitk::Surface::Pointer QmitkUSNavigationStepTumourSelection::CreateTargetSurface() { mitk::Surface::Pointer tumourSurface = dynamic_cast(m_TumourNode->GetData()); if (tumourSurface.IsNull()) { MITK_WARN << "No target selected, cannot create surface!"; return mitk::Surface::New(); //return a empty surface in this case... } // make a deep copy of the tumour surface polydata vtkSmartPointer tumourSurfaceVtk = vtkSmartPointer::New(); tumourSurfaceVtk->DeepCopy(tumourSurface->GetVtkPolyData()); // create scalars for moving every point the same size onto its normal vector vtkSmartPointer scalars = vtkSmartPointer::New(); int numberOfPoints = tumourSurfaceVtk->GetNumberOfPoints(); scalars->SetNumberOfTuples(numberOfPoints); // set scalars for warp filter for (vtkIdType i = 0; i < numberOfPoints; ++i) { scalars->SetTuple1(i, m_SecurityDistance * 10); } tumourSurfaceVtk->GetPointData()->SetScalars(scalars); vtkSmartPointer warpScalar = vtkSmartPointer::New(); warpScalar->SetInputData(tumourSurfaceVtk); warpScalar->SetScaleFactor(1); // use the scalars themselves warpScalar->Update(); vtkSmartPointer targetSurfaceVtk = warpScalar->GetPolyDataOutput(); // set the moved points to the deep copied tumour surface; this is // necessary as setting the targetSurfaceVtk as polydata for the // targetSurface would result in flat shading for the surface (seems // to be a bug in MITK or VTK) tumourSurfaceVtk->SetPoints(targetSurfaceVtk->GetPoints()); mitk::Surface::Pointer targetSurface = mitk::Surface::New(); targetSurface->SetVtkPolyData(tumourSurfaceVtk); targetSurface->GetGeometry()->SetOrigin(tumourSurface->GetGeometry()->GetOrigin()); return targetSurface; } itk::SmartPointer QmitkUSNavigationStepTumourSelection::GetTumourNodeDisplacementFilter() { return m_NodeDisplacementFilter; } void QmitkUSNavigationStepTumourSelection::UpdateReferenceSensorName() { if (m_NavigationDataSource.IsNull()) { return; } if (!m_ReferenceSensorName.empty()) { try { m_ReferenceSensorIndex = m_NavigationDataSource->GetOutputIndex(m_ReferenceSensorName); } catch (const std::exception &e) { MITK_WARN("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection") << "Cannot get index for reference sensor name: " << e.what(); } } if (this->GetNavigationStepState() >= QmitkUSAbstractNavigationStep::State_Active) { m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); } ui->freezeImageButton->SetCombinedModality(this->GetCombinedModality(false), m_ReferenceSensorIndex); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp index fc4c1fa540..e817742768 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp @@ -1,1140 +1,1155 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkUltrasoundCalibration.h" #include // Qt #include #include #include #include // MITK #include //#include #include #include #include #include #include #include "mitkIRenderingManager.h" // us #include //VTK #include #include #include #include #include #include #include "internal/org_mbi_gui_qt_usnavigation_Activator.h" //sleep headers #include #include const std::string QmitkUltrasoundCalibration::VIEW_ID = "org.mitk.views.ultrasoundcalibration"; QmitkUltrasoundCalibration::QmitkUltrasoundCalibration() : m_USDeviceChanged(this, &QmitkUltrasoundCalibration::OnUSDepthChanged) { ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if (pluginContext) { // to be notified about service event of an USDevice pluginContext->connectServiceListener(this, "OnDeviceServiceEvent", QString::fromStdString("(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid() + ")")); } } QmitkUltrasoundCalibration::~QmitkUltrasoundCalibration() { m_Controls.m_CombinedModalityManagerWidget->blockSignals(true); mitk::USCombinedModality::Pointer combinedModality; combinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { combinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_USDeviceChanged); } m_Timer->stop(); // Sleep(500); //This might be problematic... seems like sometimes some ressources are still in use at calling time. this->OnStopCalibrationProcess(); this->OnStopPlusCalibration(); /*mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Tool Calibration Points"); if (node.IsNotNull())this->GetDataStorage()->Remove(node); node = this->GetDataStorage()->GetNamedNode("Image Calibration Points"); if (node.IsNotNull())this->GetDataStorage()->Remove(node); node = this->GetDataStorage()->GetNamedNode("US Image Stream"); if (node.IsNotNull())this->GetDataStorage()->Remove(node);*/ mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Needle Path"); if (node.IsNotNull())this->GetDataStorage()->Remove(node); this->GetDataStorage()->Remove(m_VerificationReferencePointsDataNode); delete m_Timer; } void QmitkUltrasoundCalibration::SetFocus() { m_Controls.m_ToolBox->setFocus(); } void QmitkUltrasoundCalibration::CreateQtPartControl(QWidget *parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); m_Controls.m_CombinedModalityManagerWidget->SetCalibrationLoadedNecessary(false); m_Timer = new QTimer(this); m_StreamingTimer = new QTimer(this); m_Controls.m_SpacingBtnFreeze->setEnabled(true); m_Controls.m_SpacingAddPoint->setEnabled(false); m_Controls.m_CalculateSpacing->setEnabled(false); m_SpacingPointsCount = 0; m_SpacingPoints = mitk::PointSet::New(); m_SpacingNode = mitk::DataNode::New(); m_SpacingNode->SetName("Spacing Points"); m_SpacingNode->SetData(this->m_SpacingPoints); this->GetDataStorage()->Add(m_SpacingNode); // Pointset for Calibration Points m_CalibPointsTool = mitk::PointSet::New(); // Pointset for Worldpoints m_CalibPointsImage = mitk::PointSet::New(); m_CalibPointsCount = 0; // Evaluation Pointsets (Non-Visualized) m_EvalPointsImage = mitk::PointSet::New(); m_EvalPointsTool = mitk::PointSet::New(); m_EvalPointsProjected = mitk::PointSet::New(); // Neelde Projection Filter m_NeedleProjectionFilter = mitk::NeedleProjectionFilter::New(); // Tracking Status Widgets m_Controls.m_CalibTrackingStatus->ShowStatusLabels(); m_Controls.m_EvalTrackingStatus->ShowStatusLabels(); m_OverrideSpacing = false; // General & Device Selection connect(m_Timer, SIGNAL(timeout()), this, SLOT(Update())); //connect(m_Controls.m_ToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabSwitch(int))); // Calibration connect(m_Controls.m_CalibBtnFreeze, SIGNAL(clicked()), this, SLOT(SwitchFreeze())); // Freeze connect(m_Controls.m_CalibBtnAddPoint, SIGNAL(clicked()), this, SLOT(OnAddCalibPoint())); // Tracking & Image Points (Calibration) connect(m_Controls.m_CalibBtnCalibrate, SIGNAL(clicked()), this, SLOT(OnCalibration())); // Perform Calibration // Evaluation connect(m_Controls.m_EvalBtnStep1, SIGNAL(clicked()), this, SLOT(OnAddEvalProjectedPoint())); // Needle Projection connect(m_Controls.m_EvalBtnStep2, SIGNAL(clicked()), this, SLOT(SwitchFreeze())); // Freeze connect(m_Controls.m_EvalBtnStep3, SIGNAL(clicked()), this, SLOT(OnAddEvalTargetPoint())); // Tracking & Image Points (Evaluation) connect(m_Controls.m_EvalBtnSave, SIGNAL(clicked()), this, SLOT(OnSaveEvaluation())); // Save Evaluation Results connect(m_Controls.m_CalibBtnSaveCalibration, SIGNAL(clicked()), this, SLOT(OnSaveCalibration())); // Save Evaluation Results connect(m_Controls.m_BtnReset, SIGNAL(clicked()), this, SLOT(OnReset())); // Reset Pointsets // PLUS Calibration connect(m_Controls.m_GetCalibrationFromPLUS, SIGNAL(clicked()), this, SLOT(OnGetPlusCalibration())); connect(m_Controls.m_StartStreaming, SIGNAL(clicked()), this, SLOT(OnStartStreaming())); connect(m_StreamingTimer, SIGNAL(timeout()), this, SLOT(OnStreamingTimerTimeout())); connect(m_Controls.m_StopPlusCalibration, SIGNAL(clicked()), this, SLOT(OnStopPlusCalibration())); connect(m_Controls.m_SavePlusCalibration, SIGNAL(clicked()), this, SLOT(OnSaveCalibration())); connect(this, SIGNAL(NewConnectionSignal()), this, SLOT(OnNewConnection())); //Determine Spacing for Calibration of USVideoDevice connect(m_Controls.m_SpacingBtnFreeze, SIGNAL(clicked()), this, SLOT(OnFreezeClicked())); connect(m_Controls.m_SpacingAddPoint, SIGNAL(clicked()), this, SLOT(OnAddSpacingPoint())); connect(m_Controls.m_CalculateSpacing, SIGNAL(clicked()), this, SLOT(OnCalculateSpacing())); //connect( m_Controls.m_CombinedModalityManagerWidget, SIGNAL(SignalCombinedModalitySelected(mitk::USCombinedModality::Pointer)), // this, SLOT(OnSelectDevice(mitk::USCombinedModality::Pointer)) ); connect(m_Controls.m_CombinedModalityManagerWidget, SIGNAL(SignalReadyForNextStep()), this, SLOT(OnDeviceSelected())); connect(m_Controls.m_CombinedModalityManagerWidget, SIGNAL(SignalNoLongerReadyForNextStep()), this, SLOT(OnDeviceDeselected())); connect(m_Controls.m_StartCalibrationButton, SIGNAL(clicked()), this, SLOT(OnStartCalibrationProcess())); connect(m_Controls.m_StartPlusCalibrationButton, SIGNAL(clicked()), this, SLOT(OnStartPlusCalibration())); connect(m_Controls.m_CalibBtnRestartCalibration, SIGNAL(clicked()), this, SLOT(OnReset())); connect(m_Controls.m_CalibBtnStopCalibration, SIGNAL(clicked()), this, SLOT(OnStopCalibrationProcess())); connect(m_Controls.m_AddReferencePoints, SIGNAL(clicked()), this, SLOT(OnAddCurrentTipPositionToReferencePoints())); connect(m_Controls.m_AddCurrentPointerTipForVerification, SIGNAL(clicked()), this, SLOT(OnAddCurrentTipPositionForVerification())); connect(m_Controls.m_StartVerification, SIGNAL(clicked()), this, SLOT(OnStartVerification())); //initialize data storage combo box m_Controls.m_ReferencePointsComboBox->SetDataStorage(this->GetDataStorage()); m_Controls.m_ReferencePointsComboBox->SetAutoSelectNewItems(true); m_Controls.m_ReferencePointsComboBox->SetPredicate(mitk::NodePredicateDataType::New("PointSet")); //initialize point list widget if (m_VerificationReferencePoints.IsNull()) { m_VerificationReferencePoints = mitk::PointSet::New(); } if (m_VerificationReferencePointsDataNode.IsNull()) { m_VerificationReferencePointsDataNode = mitk::DataNode::New(); m_VerificationReferencePointsDataNode->SetName("US Verification Reference Points"); m_VerificationReferencePointsDataNode->SetData(m_VerificationReferencePoints); this->GetDataStorage()->Add(m_VerificationReferencePointsDataNode); } m_Controls.m_ReferencePointsPointListWidget->SetPointSetNode(m_VerificationReferencePointsDataNode); m_Controls.m_ToolBox->setCurrentIndex(0); } void QmitkUltrasoundCalibration::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, const QList& /*nodes*/) { } void QmitkUltrasoundCalibration::OnTabSwitch(int index) { switch (index) { case 0: if (m_Controls.m_ToolBox->isItemEnabled(1) || m_Controls.m_ToolBox->isItemEnabled(2)) { this->OnStopCalibrationProcess(); } break; default: ; } } //void QmitkUltrasoundCalibration::OnSelectDevice(mitk::USCombinedModality::Pointer combinedModality) void QmitkUltrasoundCalibration::OnDeviceSelected() { mitk::USCombinedModality::Pointer combinedModality; combinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { //m_Tracker = m_CombinedModality->GetNavigationDataSource(); // Construct Pipeline //this->m_NeedleProjectionFilter->SetInput(0, m_Tracker->GetOutput(0)); combinedModality->GetUltrasoundDevice()->AddPropertyChangedListener(m_USDeviceChanged); m_Controls.m_StartCalibrationButton->setEnabled(true); m_Controls.m_StartPlusCalibrationButton->setEnabled(true); m_Controls.m_ToolBox->setItemEnabled(1, true); m_Controls.m_ToolBox->setItemEnabled(2, true); } } void QmitkUltrasoundCalibration::OnDeviceDeselected() { mitk::USCombinedModality::Pointer combinedModality; combinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { combinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_USDeviceChanged); } m_Controls.m_StartCalibrationButton->setEnabled(false); m_Controls.m_StartPlusCalibrationButton->setEnabled(false); m_Controls.m_ToolBox->setCurrentIndex(0); m_Controls.m_ToolBox->setItemEnabled(1, false); m_Controls.m_ToolBox->setItemEnabled(2, false); } void QmitkUltrasoundCalibration::OnAddCurrentTipPositionToReferencePoints() { if (m_Controls.m_VerificationPointerChoser->GetSelectedNavigationDataSource().IsNull() || (m_Controls.m_VerificationPointerChoser->GetSelectedToolID() == -1)) { MITK_WARN << "No tool selected, aborting"; return; } mitk::NavigationData::Pointer currentPointerData = m_Controls.m_VerificationPointerChoser->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_VerificationPointerChoser->GetSelectedToolID()); mitk::Point3D currentTipPosition = currentPointerData->GetPosition(); m_VerificationReferencePoints->InsertPoint(m_VerificationReferencePoints->GetSize(), currentTipPosition); } void QmitkUltrasoundCalibration::OnStartVerification() { m_currentPoint = 0; mitk::PointSet::Pointer selectedPointSet = dynamic_cast(m_Controls.m_ReferencePointsComboBox->GetSelectedNode()->GetData()); m_Controls.m_CurrentPointLabel->setText("Point " + QString::number(m_currentPoint) + " of " + QString::number(selectedPointSet->GetSize())); m_allErrors = std::vector(); m_allReferencePoints = std::vector(); for (int i = 0; i < selectedPointSet->GetSize(); i++) { m_allReferencePoints.push_back(selectedPointSet->GetPoint(i)); } } void QmitkUltrasoundCalibration::OnAddCurrentTipPositionForVerification() { if (m_currentPoint == -1) { MITK_WARN << "Cannot add point"; return; } if (m_Controls.m_VerificationPointerChoser->GetSelectedNavigationDataSource().IsNull() || (m_Controls.m_VerificationPointerChoser->GetSelectedToolID() == -1)) { MITK_WARN << "No tool selected, aborting"; return; } mitk::NavigationData::Pointer currentPointerData = m_Controls.m_VerificationPointerChoser->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_VerificationPointerChoser->GetSelectedToolID()); mitk::Point3D currentTipPosition = currentPointerData->GetPosition(); double currentError = m_allReferencePoints.at(m_currentPoint).EuclideanDistanceTo(currentTipPosition); MITK_INFO << "Current Error: " << currentError << " mm"; m_allErrors.push_back(currentError); if (++m_currentPoint < static_cast(m_allReferencePoints.size())) { m_Controls.m_CurrentPointLabel->setText("Point " + QString::number(m_currentPoint) + " of " + QString::number(m_allReferencePoints.size())); } else { m_currentPoint = -1; double meanError = 0; for (std::size_t i = 0; i < m_allErrors.size(); ++i) { meanError += m_allErrors[i]; } meanError /= m_allErrors.size(); QString result = "Finished verification! \n Verification of " + QString::number(m_allErrors.size()) + " points, mean error: " + QString::number(meanError) + " mm"; m_Controls.m_ResultsTextEdit->setText(result); MITK_INFO << result.toStdString(); } } void QmitkUltrasoundCalibration::OnStartCalibrationProcess() { // US Image Stream m_Node = mitk::DataNode::New(); m_Node->SetName("US Calibration Viewing Stream"); //create a dummy image (gray values 0..255) for correct initialization of level window, etc. mitk::Image::Pointer dummyImage = mitk::ImageGenerator::GenerateRandomImage(100, 100, 1, 1, 1, 1, 1, 255, 0); m_Node->SetData(dummyImage); this->GetDataStorage()->Add(m_Node); // data node for calibration point set m_CalibNode = mitk::DataNode::New(); m_CalibNode->SetName("Tool Calibration Points"); m_CalibNode->SetData(this->m_CalibPointsImage); this->GetDataStorage()->Add(m_CalibNode); // data node for world point set m_WorldNode = mitk::DataNode::New(); m_WorldNode->SetName("Image Calibration Points"); m_WorldNode->SetData(this->m_CalibPointsTool); this->GetDataStorage()->Add(m_WorldNode); m_CombinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (m_CombinedModality.IsNull()) { return; } m_Tracker = m_CombinedModality->GetNavigationDataSource(); //QString curDepth = service.getProperty(QString::fromStdString(mitk::USDevice::US_PROPKEY_BMODE_DEPTH)).toString(); // Construct Pipeline this->m_NeedleProjectionFilter->SetInput(0, m_Tracker->GetOutput(0)); QApplication::setOverrideCursor(Qt::WaitCursor); // make sure that the combined modality is in connected state before using it if (m_CombinedModality->GetDeviceState() < mitk::USDevice::State_Connected) { m_CombinedModality->Connect(); } if (m_CombinedModality->GetDeviceState() < mitk::USDevice::State_Activated) { m_CombinedModality->Activate(); } QApplication::restoreOverrideCursor(); this->SwitchFreeze(); // Todo: Maybe display this elsewhere this->ShowNeedlePath(); // Switch active tab to Calibration page m_Controls.m_ToolBox->setItemEnabled(1, true); m_Controls.m_ToolBox->setCurrentIndex(1); } void QmitkUltrasoundCalibration::OnStartPlusCalibration() { if (m_CombinedModality.IsNull()){ m_CombinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (m_CombinedModality.IsNull()) { return; } //something went wrong, there is no combined modality } //setup server to send UltrasoundImages to PLUS mitk::IGTLServer::Pointer m_USServer = mitk::IGTLServer::New(true); m_USServer->SetName("EchoTrack Image Source"); m_USServer->SetHostname("127.0.0.1"); m_USServer->SetPortNumber(18944); m_USMessageProvider = mitk::IGTLMessageProvider::New(); m_USMessageProvider->SetIGTLDevice(m_USServer); m_USMessageProvider->SetFPS(5); m_USImageToIGTLMessageFilter = mitk::ImageToIGTLMessageFilter::New(); m_USImageToIGTLMessageFilter->ConnectTo(m_CombinedModality->GetUltrasoundDevice()); m_USImageToIGTLMessageFilter->SetName("USImage Filter"); //setup server to send TrackingData to PLUS m_TrackingServer = mitk::IGTLServer::New(true); m_TrackingServer->SetName("EchoTrack Tracking Source"); m_TrackingServer->SetHostname("127.0.0.1"); m_TrackingServer->SetPortNumber(18945); m_TrackingMessageProvider = mitk::IGTLMessageProvider::New(); m_TrackingMessageProvider->SetIGTLDevice(m_TrackingServer); m_TrackingMessageProvider->SetFPS(5); m_TrackingToIGTLMessageFilter = mitk::NavigationDataToIGTLMessageFilter::New(); m_TrackingToIGTLMessageFilter->ConnectTo(m_CombinedModality->GetTrackingDevice()); m_TrackingToIGTLMessageFilter->SetName("Tracker Filter"); typedef itk::SimpleMemberCommand< QmitkUltrasoundCalibration > CurCommandType; CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); newConnectionCommand->SetCallbackFunction( this, &QmitkUltrasoundCalibration::OnPlusConnected); this->m_NewConnectionObserverTag = this->m_TrackingServer->AddObserver( mitk::NewClientConnectionEvent(), newConnectionCommand); //Open connections of both servers if (m_USServer->OpenConnection()) { MITK_INFO << "US Server opened its connection successfully"; m_USServer->StartCommunication(); } else { MITK_INFO << "US Server could not open its connection"; } if (m_TrackingServer->OpenConnection()) { MITK_INFO << "Tracking Server opened its connection successfully"; m_TrackingServer->StartCommunication(); } else { MITK_INFO << "Tracking Server could not open its connection"; } if (m_USMessageProvider->IsCommunicating() && m_TrackingMessageProvider->IsCommunicating()) { m_Controls.m_StartPlusCalibrationButton->setEnabled(false); m_Controls.m_GetCalibrationFromPLUS->setEnabled(true); m_Controls.m_StartStreaming->setEnabled(false); m_Controls.m_SavePlusCalibration->setEnabled(false); m_Controls.m_SetupStatus->setStyleSheet("QLabel { color : green; }"); m_Controls.m_SetupStatus->setText("Setup successfull you can now connect PLUS"); } else { m_Controls.m_SetupStatus->setStyleSheet("QLabel { color : red; }"); m_Controls.m_SetupStatus->setText("Something went wrong. Please try again"); } } void QmitkUltrasoundCalibration::OnStopPlusCalibration() { //closing all server and clients when PlusCalibration is finished if (m_USMessageProvider.IsNotNull()) { if (m_USMessageProvider->IsStreaming()) { m_USMessageProvider->StopStreamingOfSource(m_USImageToIGTLMessageFilter); } } if (m_TrackingMessageProvider.IsNotNull()) { if (m_TrackingMessageProvider->IsStreaming()) { m_TrackingMessageProvider->StopStreamingOfSource(m_TrackingToIGTLMessageFilter); } } if (m_USServer.IsNotNull()) { m_USServer->CloseConnection(); } if (m_TrackingServer.IsNotNull()) { m_TrackingServer->CloseConnection(); } if (m_TransformClient.IsNotNull()) { m_TransformClient->CloseConnection(); } m_Controls.m_GotCalibrationLabel->setText(""); m_Controls.m_ConnectionStatus->setText(""); m_Controls.m_SetupStatus->setText(""); m_Controls.m_StartPlusCalibrationButton->setEnabled(true); m_StreamingTimer->stop(); delete m_StreamingTimer; } void QmitkUltrasoundCalibration::OnPlusConnected() { emit NewConnectionSignal(); } void QmitkUltrasoundCalibration::OnNewConnection() { m_Controls.m_StartStreaming->setEnabled(true); m_Controls.m_ConnectionStatus->setStyleSheet("QLabel { color : green; }"); m_Controls.m_ConnectionStatus->setText("Connection successfull you can now start streaming"); } void QmitkUltrasoundCalibration::OnStreamingTimerTimeout() { m_USMessageProvider->Update(); m_TrackingMessageProvider->Update(); } void QmitkUltrasoundCalibration::OnStartStreaming() { m_USMessageProvider->StartStreamingOfSource(m_USImageToIGTLMessageFilter, 5); m_TrackingMessageProvider->StartStreamingOfSource(m_TrackingToIGTLMessageFilter, 5); m_Controls.m_StartStreaming->setEnabled(false); m_Controls.m_ConnectionStatus->setText(""); m_StreamingTimer->start((1.0 / 5.0 * 1000.0)); } void QmitkUltrasoundCalibration::OnGetPlusCalibration() { m_TransformClient = mitk::IGTLClient::New(true); m_TransformClient->SetHostname("127.0.0.1"); m_TransformClient->SetPortNumber(18946); m_TransformDeviceSource = mitk::IGTLDeviceSource::New(); m_TransformDeviceSource->SetIGTLDevice(m_TransformClient); m_TransformDeviceSource->Connect(); if (m_TransformDeviceSource->IsConnected()) { MITK_INFO << "successfully connected"; m_TransformDeviceSource->StartCommunication(); if (m_TransformDeviceSource->IsCommunicating()) { MITK_INFO << "communication started"; mitk::IGTLMessage::Pointer receivedMessage; bool condition = false; igtl::Matrix4x4 transformPLUS; while (!(receivedMessage.IsNotNull() && receivedMessage->IsDataValid())) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); m_TransformDeviceSource->Update(); receivedMessage = m_TransformDeviceSource->GetOutput(); igtl::TransformMessage::Pointer msg = dynamic_cast(m_TransformDeviceSource->GetOutput()->GetMessage().GetPointer()); if (msg == nullptr || msg.IsNull()) { MITK_INFO << "Received message could not be casted to TransformMessage. Skipping.."; continue; } else { if (std::strcmp(msg->GetDeviceName(), "ImageToTracker") != 0) { MITK_INFO << "Was not Image to Tracker Transform. Skipping..."; continue; } else { msg->GetMatrix(transformPLUS); condition = true; break; } } } if (condition) { this->ProcessPlusCalibration(transformPLUS); } else { m_Controls.m_GotCalibrationLabel->setStyleSheet("QLabel { color : red; }"); m_Controls.m_GotCalibrationLabel->setText("Something went wrong. Please try again"); } } else { MITK_INFO << " no connection"; m_Controls.m_GotCalibrationLabel->setStyleSheet("QLabel { color : red; }"); m_Controls.m_GotCalibrationLabel->setText("Something went wrong. Please try again"); } } else { m_Controls.m_GotCalibrationLabel->setStyleSheet("QLabel { color : red; }"); m_Controls.m_GotCalibrationLabel->setText("Something went wrong. Please try again"); } } void QmitkUltrasoundCalibration::ProcessPlusCalibration(igtl::Matrix4x4& imageToTracker) { mitk::AffineTransform3D::Pointer imageToTrackerTransform = mitk::AffineTransform3D::New(); itk::Matrix rotationFloat = itk::Matrix(); itk::Vector translationFloat = itk::Vector(); rotationFloat[0][0] = imageToTracker[0][0]; rotationFloat[0][1] = imageToTracker[0][1]; rotationFloat[0][2] = imageToTracker[0][2]; rotationFloat[1][0] = imageToTracker[1][0]; rotationFloat[1][1] = imageToTracker[1][1]; rotationFloat[1][2] = imageToTracker[1][2]; rotationFloat[2][0] = imageToTracker[2][0]; rotationFloat[2][1] = imageToTracker[2][1]; rotationFloat[2][2] = imageToTracker[2][2]; translationFloat[0] = imageToTracker[0][3]; translationFloat[1] = imageToTracker[1][3]; translationFloat[2] = imageToTracker[2][3]; imageToTrackerTransform->SetTranslation(translationFloat); imageToTrackerTransform->SetMatrix(rotationFloat); m_CombinedModality->SetCalibration(imageToTrackerTransform); m_Controls.m_ToolBox->setItemEnabled(2, true); m_Controls.m_SavePlusCalibration->setEnabled(true); m_Controls.m_GotCalibrationLabel->setStyleSheet("QLabel { color : green; }"); m_Controls.m_GotCalibrationLabel->setText("Recieved Calibration from PLUS you can now save it"); } void QmitkUltrasoundCalibration::OnStopCalibrationProcess() { this->ClearTemporaryMembers(); m_Timer->stop(); this->GetDataStorage()->Remove(m_Node); m_Node = 0; this->GetDataStorage()->Remove(m_CalibNode); m_CalibNode = 0; this->GetDataStorage()->Remove(m_WorldNode); m_WorldNode = 0; m_Controls.m_ToolBox->setCurrentIndex(0); } void QmitkUltrasoundCalibration::OnDeviceServiceEvent(const ctkServiceEvent event) { if (m_CombinedModality.IsNull() || event.getType() != ctkServiceEvent::MODIFIED) { return; } ctkServiceReference service = event.getServiceReference(); QString curDepth = service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH)).toString(); if (m_CurrentDepth != curDepth) { m_CurrentDepth = curDepth; this->OnReset(); } } void QmitkUltrasoundCalibration::OnAddCalibPoint() { mitk::Point3D world = this->GetRenderWindowPart()->GetSelectedPosition(); this->m_CalibPointsImage->InsertPoint(m_CalibPointsCount, world); this->m_CalibPointsTool->InsertPoint(m_CalibPointsCount, this->m_FreezePoint); QString text = text.number(m_CalibPointsCount + 1); text = "Point " + text; this->m_Controls.m_CalibPointList->addItem(text); m_CalibPointsCount++; SwitchFreeze(); } void QmitkUltrasoundCalibration::OnCalibration() { // Compute transformation vtkSmartPointer transform = vtkSmartPointer::New(); transform->SetSourceLandmarks(this->ConvertPointSetToVtkPolyData(m_CalibPointsImage)->GetPoints()); transform->SetTargetLandmarks(this->ConvertPointSetToVtkPolyData(m_CalibPointsTool)->GetPoints()); if (m_Controls.m_ScaleTransform->isChecked()) { transform->SetModeToSimilarity(); } //use affine transform else { transform->SetModeToRigidBody(); } //use similarity transform: scaling is not touched transform->Modified(); transform->Update(); // Convert from vtk to itk data types itk::Matrix rotationFloat = itk::Matrix(); itk::Vector translationFloat = itk::Vector(); vtkSmartPointer m = transform->GetMatrix(); rotationFloat[0][0] = m->GetElement(0, 0); rotationFloat[0][1] = m->GetElement(0, 1); rotationFloat[0][2] = m->GetElement(0, 2); rotationFloat[1][0] = m->GetElement(1, 0); rotationFloat[1][1] = m->GetElement(1, 1); rotationFloat[1][2] = m->GetElement(1, 2); rotationFloat[2][0] = m->GetElement(2, 0); rotationFloat[2][1] = m->GetElement(2, 1); rotationFloat[2][2] = m->GetElement(2, 2); translationFloat[0] = m->GetElement(0, 3); translationFloat[1] = m->GetElement(1, 3); translationFloat[2] = m->GetElement(2, 3); mitk::DataNode::Pointer CalibPointsImage = mitk::DataNode::New(); CalibPointsImage->SetName("Calibration Points Image"); CalibPointsImage->SetData(m_CalibPointsImage); this->GetDataStorage()->Add(CalibPointsImage); mitk::DataNode::Pointer CalibPointsTracking = mitk::DataNode::New(); CalibPointsTracking->SetName("Calibration Points Tracking"); CalibPointsTracking->SetData(m_CalibPointsTool); this->GetDataStorage()->Add(CalibPointsTracking); mitk::PointSet::Pointer ImagePointsTransformed = m_CalibPointsImage->Clone(); this->ApplyTransformToPointSet(ImagePointsTransformed, transform); mitk::DataNode::Pointer CalibPointsImageTransformed = mitk::DataNode::New(); CalibPointsImageTransformed->SetName("Calibration Points Image (Transformed)"); CalibPointsImageTransformed->SetData(ImagePointsTransformed); this->GetDataStorage()->Add(CalibPointsImageTransformed); // Set output variable mitk::AffineTransform3D::Pointer oldUSImageTransform = m_Image->GetGeometry()->GetIndexToWorldTransform(); //including spacing! MITK_INFO << "Old US Image transform: " << oldUSImageTransform; mitk::AffineTransform3D::Pointer calibTransform = mitk::AffineTransform3D::New(); calibTransform->SetTranslation(translationFloat); calibTransform->SetMatrix(rotationFloat); MITK_INFO << "Calibration transform: " << calibTransform; m_Transformation = mitk::AffineTransform3D::New(); if (!m_Controls.m_ScaleTransform->isChecked()) { m_Transformation->Compose(oldUSImageTransform); } m_Transformation->Compose(calibTransform); MITK_INFO << "New combined transform: " << m_Transformation; mitk::SlicedGeometry3D::Pointer sliced3d = dynamic_cast (m_Node->GetData()->GetGeometry()); mitk::PlaneGeometry::Pointer plane = const_cast (sliced3d->GetPlaneGeometry(0)); plane->SetIndexToWorldTransform(m_Transformation); // Save to US-Device m_CombinedModality->SetCalibration(m_Transformation); m_Controls.m_ToolBox->setItemEnabled(2, true); // Save to NeedleProjectionFilter m_NeedleProjectionFilter->SetTargetPlane(m_Transformation); // Update Calibration FRE m_CalibrationStatistics = mitk::PointSetDifferenceStatisticsCalculator::New(); mitk::PointSet::Pointer p1 = this->m_CalibPointsTool->Clone(); // We use clones to calculate statistics to avoid concurrency Problems // Create point set with transformed image calibration points for // calculating the difference of image calibration and tool // calibration points in one geometry space mitk::PointSet::Pointer p2 = mitk::PointSet::New(); int n = 0; for (mitk::PointSet::PointsConstIterator it = m_CalibPointsImage->Begin(); it != m_CalibPointsImage->End(); ++it, ++n) { p2->InsertPoint(n, m_Transformation->TransformPoint(it->Value())); } m_CalibrationStatistics->SetPointSets(p1, p2); //QString text = text.number(m_CalibrationStatistics->GetRMS()); QString text = QString::number(ComputeFRE(m_CalibPointsImage, m_CalibPointsTool, transform)); MITK_INFO << "Calibration FRE: " << text.toStdString().c_str(); m_Controls.m_EvalLblCalibrationFRE->setText(text); m_Node->SetStringProperty("Calibration FRE", text.toStdString().c_str()); // Enable Button to save Calibration m_Controls.m_CalibBtnSaveCalibration->setEnabled(true); } void QmitkUltrasoundCalibration::OnAddEvalTargetPoint() { mitk::Point3D world = this->GetRenderWindowPart()->GetSelectedPosition(); this->m_EvalPointsImage->InsertPoint(m_EvalPointsImage->GetSize(), world); this->m_EvalPointsTool->InsertPoint(m_EvalPointsTool->GetSize(), this->m_FreezePoint); QString text = text.number(this->m_EvalPointsTool->GetSize()); this->m_Controls.m_EvalLblNumTargetPoints->setText(text); // Update FREs // Update Evaluation FRE, but only if it contains more than one point (will crash otherwise) if ((m_EvalPointsProjected->GetSize() > 1) && (m_EvalPointsTool->GetSize() > 1)) { m_EvaluationStatistics = mitk::PointSetDifferenceStatisticsCalculator::New(); m_ProjectionStatistics = mitk::PointSetDifferenceStatisticsCalculator::New(); mitk::PointSet::Pointer p1 = this->m_EvalPointsTool->Clone(); // We use clones to calculate statistics to avoid concurrency Problems mitk::PointSet::Pointer p2 = this->m_EvalPointsImage->Clone(); mitk::PointSet::Pointer p3 = this->m_EvalPointsProjected->Clone(); m_EvaluationStatistics->SetPointSets(p1, p2); m_ProjectionStatistics->SetPointSets(p1, p3); QString evalText = evalText.number(m_EvaluationStatistics->GetRMS()); QString projText = projText.number(m_ProjectionStatistics->GetRMS()); m_Controls.m_EvalLblEvaluationFRE->setText(evalText); m_Controls.m_EvalLblProjectionFRE->setText(projText); } SwitchFreeze(); } void QmitkUltrasoundCalibration::OnAddEvalProjectedPoint() { MITK_WARN << "Projection Evaluation may currently be inaccurate."; // TODO: Verify correct Evaluation. Is the Point that is added really current? mitk::Point3D projection = this->m_NeedleProjectionFilter->GetProjection()->GetPoint(1); m_EvalPointsProjected->InsertPoint(m_EvalPointsProjected->GetSize(), projection); QString text = text.number(this->m_EvalPointsProjected->GetSize()); this->m_Controls.m_EvalLblNumProjectionPoints->setText(text); } void QmitkUltrasoundCalibration::OnSaveEvaluation() { //Filename without suffix QString filename = m_Controls.m_EvalFilePath->text() + "//" + m_Controls.m_EvalFilePrefix->text(); MITK_WARN << "CANNOT SAVE, ABORTING!"; /* not working any more TODO! mitk::PointSetWriter::Pointer psWriter = mitk::PointSetWriter::New(); psWriter->SetInput(0, m_CalibPointsImage); psWriter->SetInput(1, m_CalibPointsTool); psWriter->SetInput(2, m_EvalPointsImage); psWriter->SetInput(3, m_EvalPointsTool); psWriter->SetInput(4, m_EvalPointsProjected); psWriter->SetFileName(filename.toStdString() + ".xml"); psWriter->Write(); */ // TODO: New writer for transformations must be implemented. /* mitk::TransformationFileWriter::Pointer tWriter = mitk::TransformationFileWriter::New(); tWriter->SetInput(0, m_CalibPointsImage); tWriter->SetInput(1, m_CalibPointsTool); tWriter->SetInput(2, m_EvalPointsImage); tWriter->SetInput(3, m_EvalPointsTool); tWriter->SetInput(4, m_EvalPointsProjected); tWriter->SetOutputFilename(filename.toStdString() + ".txt"); tWriter->DoWrite(this->m_Transformation); */ } void QmitkUltrasoundCalibration::OnSaveCalibration() { m_Controls.m_GotCalibrationLabel->setText(""); QString filename = QFileDialog::getSaveFileName(QApplication::activeWindow(), "Save Calibration", "", "Calibration files *.cal"); QFile file(filename); if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { MITK_WARN << "Cannot open file '" << filename.toStdString() << "' for writing."; return; } std::string calibrationSerialization = m_CombinedModality->SerializeCalibration(); QTextStream outStream(&file); outStream << QString::fromStdString(calibrationSerialization); //save additional information if (m_Controls.m_saveAdditionalCalibrationLog->isChecked()) { mitk::SceneIO::Pointer mySceneIO = mitk::SceneIO::New(); QString filenameScene = filename + "_mitkScene.mitk"; mitk::NodePredicateNot::Pointer isNotHelperObject = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); mitk::DataStorage::SetOfObjects::ConstPointer nodesToBeSaved = this->GetDataStorage()->GetSubset(isNotHelperObject); mySceneIO->SaveScene(nodesToBeSaved, this->GetDataStorage(), filenameScene.toStdString().c_str()); } } void QmitkUltrasoundCalibration::OnReset() { this->ClearTemporaryMembers(); if (m_Transformation.IsNull()) { m_Transformation = mitk::AffineTransform3D::New(); } m_Transformation->SetIdentity(); if (m_Node.IsNotNull() && (m_Node->GetData() != nullptr) && (m_Node->GetData()->GetGeometry() != nullptr)) { mitk::SlicedGeometry3D::Pointer sliced3d = dynamic_cast (m_Node->GetData()->GetGeometry()); mitk::PlaneGeometry::Pointer plane = const_cast (sliced3d->GetPlaneGeometry(0)); plane->SetIndexToWorldTransform(m_Transformation); } QString text1 = text1.number(this->m_EvalPointsTool->GetSize()); this->m_Controls.m_EvalLblNumTargetPoints->setText(text1); QString text2 = text2.number(this->m_EvalPointsProjected->GetSize()); this->m_Controls.m_EvalLblNumProjectionPoints->setText(text2); } void QmitkUltrasoundCalibration::Update() { //QList nodes = this->GetDataManagerSelection(); // if (nodes.empty()) return; // Update Tracking Data std::vector* datas = new std::vector(); datas->push_back(m_Tracker->GetOutput()); m_Controls.m_CalibTrackingStatus->SetNavigationDatas(datas); m_Controls.m_CalibTrackingStatus->Refresh(); m_Controls.m_EvalTrackingStatus->SetNavigationDatas(datas); m_Controls.m_EvalTrackingStatus->Refresh(); // Update US Image m_CombinedModality->Modified(); m_CombinedModality->Update(); mitk::Image::Pointer m_Image = m_CombinedModality->GetOutput(); if (m_Image.IsNotNull() && m_Image->IsInitialized()) { if (m_OverrideSpacing) { m_Image->GetGeometry()->SetSpacing(m_Spacing); } if (m_Image.IsNotNull() && m_Image->IsInitialized()) { m_Node->SetData(m_Image); } } // Update Needle Projection m_NeedleProjectionFilter->Update(); //only update 2d window because it is faster //this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); } void QmitkUltrasoundCalibration::SwitchFreeze() { m_Controls.m_CalibBtnAddPoint->setEnabled(false); // generally deactivate // We use the activity state of the timer to determine whether we are currently viewing images if (!m_Timer->isActive()) // Activate Imaging { // if (m_Node) m_Node->ReleaseData(); if (m_CombinedModality.IsNull()){ m_Timer->stop(); return; } m_CombinedModality->Update(); - m_Image = m_CombinedModality->GetOutput(); + m_Image = m_CombinedModality->GetOutput(); if (m_Image.IsNotNull() && m_Image->IsInitialized()) { m_Node->SetData(m_Image); } std::vector datas; datas.push_back(m_Tracker->GetOutput()); m_Controls.m_CalibTrackingStatus->SetNavigationDatas(&datas); m_Controls.m_CalibTrackingStatus->ShowStatusLabels(); m_Controls.m_CalibTrackingStatus->Refresh(); m_Controls.m_EvalTrackingStatus->SetNavigationDatas(&datas); m_Controls.m_EvalTrackingStatus->ShowStatusLabels(); m_Controls.m_EvalTrackingStatus->Refresh(); int interval = 40; m_Timer->setInterval(interval); m_Timer->start(); m_CombinedModality->SetIsFreezed(false); } else if (this->m_Tracker->GetOutput(0)->IsDataValid()) { //deactivate Imaging m_Timer->stop(); // Remember last tracking coordinates m_FreezePoint = this->m_Tracker->GetOutput(0)->GetPosition(); m_Controls.m_CalibBtnAddPoint->setEnabled(true); // activate only, if valid point is set m_CombinedModality->SetIsFreezed(true); } } void QmitkUltrasoundCalibration::ShowNeedlePath() { // Init Filter this->m_NeedleProjectionFilter->SelectInput(0); // Create Node for Pointset mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Needle Path"); if (node.IsNull()) { node = mitk::DataNode::New(); node->SetName("Needle Path"); node->SetData(m_NeedleProjectionFilter->GetProjection()); node->SetBoolProperty("show contour", true); this->GetDataStorage()->Add(node); } } void QmitkUltrasoundCalibration::ClearTemporaryMembers() { m_CalibPointsTool->Clear(); m_CalibPointsImage->Clear(); m_CalibPointsCount = 0; m_EvalPointsImage->Clear(); m_EvalPointsTool->Clear(); m_EvalPointsProjected->Clear(); this->m_Controls.m_CalibPointList->clear(); m_SpacingPoints->Clear(); m_Controls.m_SpacingPointsList->clear(); m_SpacingPointsCount = 0; } vtkSmartPointer QmitkUltrasoundCalibration::ConvertPointSetToVtkPolyData(mitk::PointSet::Pointer PointSet) { vtkSmartPointer returnValue = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); for (int i = 0; i < PointSet->GetSize(); i++) { double point[3] = { PointSet->GetPoint(i)[0], PointSet->GetPoint(i)[1], PointSet->GetPoint(i)[2] }; points->InsertNextPoint(point); } vtkSmartPointer temp = vtkSmartPointer::New(); temp->SetPoints(points); vtkSmartPointer vertexFilter = vtkSmartPointer::New(); vertexFilter->SetInputData(temp); vertexFilter->Update(); returnValue->ShallowCopy(vertexFilter->GetOutput()); return returnValue; } double QmitkUltrasoundCalibration::ComputeFRE(mitk::PointSet::Pointer imageFiducials, mitk::PointSet::Pointer realWorldFiducials, vtkSmartPointer transform) { if (imageFiducials->GetSize() != realWorldFiducials->GetSize()) return -1; double FRE = 0; for (int i = 0; i < imageFiducials->GetSize(); ++i) { itk::Point current_image_fiducial_point = imageFiducials->GetPoint(i); if (transform != nullptr) { current_image_fiducial_point = transform->TransformPoint(imageFiducials->GetPoint(i)[0], imageFiducials->GetPoint(i)[1], imageFiducials->GetPoint(i)[2]); } double cur_error_squared = current_image_fiducial_point.SquaredEuclideanDistanceTo(realWorldFiducials->GetPoint(i)); FRE += cur_error_squared; } FRE = sqrt(FRE / (double)imageFiducials->GetSize()); return FRE; } void QmitkUltrasoundCalibration::ApplyTransformToPointSet(mitk::PointSet::Pointer pointSet, vtkSmartPointer transform) { for (int i = 0; i < pointSet->GetSize(); ++i) { itk::Point current_point_transformed = itk::Point(); current_point_transformed = transform->TransformPoint(pointSet->GetPoint(i)[0], pointSet->GetPoint(i)[1], pointSet->GetPoint(i)[2]); pointSet->SetPoint(i, current_point_transformed); } } void QmitkUltrasoundCalibration::OnFreezeClicked() { if (m_CombinedModality->GetIsFreezed()) - { //device was already frozen so we need to delete all Spacing points because they need to be collected all at once + { + if (!m_Timer->isActive()) // Activate Imaging + { + // if (m_Node) m_Node->ReleaseData(); + if (m_CombinedModality.IsNull()) { + m_Timer->stop(); + return; + } + m_Timer->start(); + } + + //device was already frozen so we need to delete all Spacing points because they need to be collected all at once // no need to check if all four points are already collected, because if thats the case you can no longer click the Freeze Button m_SpacingPoints->Clear(); m_Controls.m_SpacingPointsList->clear(); m_SpacingPointsCount = 0; m_Controls.m_SpacingAddPoint->setEnabled(false); m_CombinedModality->SetIsFreezed(false); + } else { + //deactivate Imaging + m_Timer->stop(); m_CombinedModality->SetIsFreezed(true); m_Controls.m_SpacingAddPoint->setEnabled(true); } //SwitchFreeze(); } void QmitkUltrasoundCalibration::OnAddSpacingPoint() { mitk::Point3D point = this->GetRenderWindowPart()->GetSelectedPosition(); this->m_SpacingPoints->InsertPoint(m_SpacingPointsCount, point); QString text = text.number(m_SpacingPointsCount + 1); text = "Point " + text; this->m_Controls.m_SpacingPointsList->addItem(text); m_SpacingPointsCount++; if (m_SpacingPointsCount == 4) //now we have all 4 points needed { m_Controls.m_SpacingAddPoint->setEnabled(false); m_Controls.m_CalculateSpacing->setEnabled(true); m_Controls.m_SpacingBtnFreeze->setEnabled(false); } } void QmitkUltrasoundCalibration::OnCalculateSpacing() { mitk::Point3D horizontalOne = m_SpacingPoints->GetPoint(0); mitk::Point3D horizontalTwo = m_SpacingPoints->GetPoint(1); mitk::Point3D verticalOne = m_SpacingPoints->GetPoint(2); mitk::Point3D verticalTwo = m_SpacingPoints->GetPoint(3); //Get the distances between the points in the image double xDistance = horizontalOne.EuclideanDistanceTo(horizontalTwo); double yDistance = verticalOne.EuclideanDistanceTo(verticalTwo); //Calculate the spacing of the image and fill a vector with it double xSpacing = 30 / xDistance; double ySpacing = 20 / yDistance; m_Spacing[0] = xSpacing; m_Spacing[1] = ySpacing; m_Spacing[2] = 1; MITK_INFO << m_Spacing; //Make sure the new spacing is applied to the USVideoDeviceImages m_OverrideSpacing = true; //Now that the spacing is set clear all stuff and return to Calibration m_SpacingPoints->Clear(); m_Controls.m_SpacingPointsList->clear(); m_SpacingPointsCount = 0; m_CombinedModality->SetIsFreezed(false); } void QmitkUltrasoundCalibration::OnUSDepthChanged(const std::string& key, const std::string&) { //whenever depth of USImage is changed the spacing should no longer be overwritten if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) { + m_OverrideSpacing = false; } } diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkIGTFiducialRegistrationControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkIGTFiducialRegistrationControls.ui index 3e320044a8..931b1781bb 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkIGTFiducialRegistrationControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkIGTFiducialRegistrationControls.ui @@ -1,178 +1,166 @@ IGTFiducialRegistrationControls 0 0 - 392 - 753 + 454 + 625 0 0 QmitkTemplate - - - 2 - - - 2 - - - 2 - - - 2 - - + + Configuration - - + + <html><head/><body><p><span style=" font-weight:600;">Choose Tracking Pointer:</span></p></body></html> - + - + Choose Selected Qt::Horizontal 40 20 <none> - + Qt::Horizontal - + <html><head/><body><p><span style=" font-weight:600;">Choose Image or Surface:</span></p></body></html> - + - + Choose Selected Qt::Horizontal 40 20 <none> - + Point Based Registration - - + + 16777215 900 QmitkNavigationDataSourceSelectionWidget QWidget
QmitkNavigationDataSourceSelectionWidget.h
1
QmitkFiducialRegistrationWidget QTextBrowser
QmitkFiducialRegistrationWidget.h
QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
1