diff --git a/Applications/Diffusion/CMakeLists.txt b/Applications/Diffusion/CMakeLists.txt index c0bd44220d..c1f4e5175e 100644 --- a/Applications/Diffusion/CMakeLists.txt +++ b/Applications/Diffusion/CMakeLists.txt @@ -1,102 +1,97 @@ -if(MITK_USE_Python) - project(MitkDiffusion) set(DIFFUSIONAPP_NAME MitkDiffusion) set(_app_options) if(MITK_SHOW_CONSOLE_WINDOW) list(APPEND _app_options SHOW_CONSOLE) endif() # Create a cache entry for the provisioning file which is used to export # the file name in the MITKConfig.cmake file. This will keep external projects # which rely on this file happy. set(DIFFUSIONIMAGINGAPP_PROVISIONING_FILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${DIFFUSIONAPP_NAME}.provisioning" CACHE INTERNAL "${DIFFUSIONAPP_NAME} provisioning file" FORCE) # should be identical to the list in /CMake/mitkBuildConfigurationmitkDiffusion.cmake # remember to set plugins which should be automatically toggled in target_libraries.cmake set(_plugins org.commontk.configadmin org.commontk.eventadmin org.blueberry.core.runtime org.blueberry.core.expressions org.blueberry.core.commands org.blueberry.ui.qt org.blueberry.ui.qt.log org.blueberry.ui.qt.help org.mitk.core.services org.mitk.gui.common org.mitk.planarfigure org.mitk.core.ext org.mitk.gui.qt.application org.mitk.gui.qt.ext org.mitk.gui.qt.diffusionimagingapp org.mitk.gui.qt.common org.mitk.gui.qt.stdmultiwidgeteditor - org.mitk.gui.qt.common.legacy org.mitk.gui.qt.datamanager org.mitk.gui.qt.measurementtoolbox org.mitk.gui.qt.segmentation org.mitk.gui.qt.volumevisualization org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.diffusionimaging.connectomics org.mitk.gui.qt.diffusionimaging.fiberfox org.mitk.gui.qt.diffusionimaging.fiberprocessing org.mitk.gui.qt.diffusionimaging.ivim org.mitk.gui.qt.diffusionimaging.odfpeaks org.mitk.gui.qt.diffusionimaging.preprocessing org.mitk.gui.qt.diffusionimaging.reconstruction org.mitk.gui.qt.diffusionimaging.tractography org.mitk.gui.qt.diffusionimaging.registration org.mitk.gui.qt.diffusionimaging.denoising # org.mitk.gui.qt.matchpoint.algorithm.browser # org.mitk.gui.qt.matchpoint.algorithm.control # org.mitk.gui.qt.matchpoint.mapper org.mitk.gui.qt.imagenavigator org.mitk.gui.qt.moviemaker org.mitk.gui.qt.basicimageprocessing org.mitk.gui.qt.properties org.mitk.gui.qt.viewnavigator ) # Plug-ins listed below will not be # - added as a build-time dependency to the executable # - listed in the provisioning file for the executable # - installed if they are external plug-ins set(_exclude_plugins org.blueberry.test org.blueberry.uitest org.mitk.gui.qt.coreapplication org.mitk.gui.qt.extapplication ) set(_src_files MitkDiffusion.cpp ) qt5_add_resources(_src_files splashscreen.qrc) mitkFunctionCreateBlueBerryApplication( NAME ${DIFFUSIONAPP_NAME} DESCRIPTION "MITK Diffusion" PLUGINS ${_plugins} EXCLUDE_PLUGINS ${_exclude_plugins} SOURCES ${_src_files} ${_app_options} ) mitk_use_modules(TARGET ${DIFFUSIONAPP_NAME} MODULES MitkAppUtil) # Add meta dependencies (e.g. on auto-load modules from depending modules) if(TARGET ${CMAKE_PROJECT_NAME}-autoload) add_dependencies(${DIFFUSIONAPP_NAME} ${CMAKE_PROJECT_NAME}-autoload) endif() # Add a build time dependency to legacy BlueBerry bundles. if(MITK_MODULES_ENABLED_PLUGINS) add_dependencies(${DIFFUSIONAPP_NAME} ${MITK_MODULES_ENABLED_PLUGINS}) endif() - -endif() diff --git a/Applications/Diffusion/target_libraries.cmake b/Applications/Diffusion/target_libraries.cmake index 8688809ece..d9241ad619 100644 --- a/Applications/Diffusion/target_libraries.cmake +++ b/Applications/Diffusion/target_libraries.cmake @@ -1,34 +1,33 @@ # A list of plug-in targets which should be automatically enabled # (or be available in external projects) for this application set(target_libraries org_blueberry_ui_qt org_blueberry_ui_qt_help org_mitk_planarfigure org_mitk_gui_qt_diffusionimagingapp - org_mitk_gui_qt_common_legacy org_mitk_gui_qt_ext org_mitk_gui_qt_datamanager org_mitk_gui_qt_segmentation org_mitk_gui_qt_volumevisualization org_mitk_gui_qt_diffusionimaging org_mitk_gui_qt_diffusionimaging_connectomics org_mitk_gui_qt_diffusionimaging_fiberfox org_mitk_gui_qt_diffusionimaging_fiberprocessing org_mitk_gui_qt_diffusionimaging_ivim org_mitk_gui_qt_diffusionimaging_odfpeaks org_mitk_gui_qt_diffusionimaging_preprocessing org_mitk_gui_qt_diffusionimaging_reconstruction org_mitk_gui_qt_diffusionimaging_tractography org_mitk_gui_qt_diffusionimaging_registration org_mitk_gui_qt_diffusionimaging_denoising - org_mitk_gui_qt_matchpoint_algorithm_browser - org_mitk_gui_qt_matchpoint_algorithm_control - org_mitk_gui_qt_matchpoint_mapper +# org_mitk_gui_qt_matchpoint_algorithm_browser +# org_mitk_gui_qt_matchpoint_algorithm_control +# org_mitk_gui_qt_matchpoint_mapper org_mitk_gui_qt_imagenavigator org_mitk_gui_qt_moviemaker org_mitk_gui_qt_measurementtoolbox org_mitk_gui_qt_basicimageprocessing org_mitk_gui_qt_viewnavigator ) diff --git a/CMake/BuildConfigurations/DiffusionRelease.cmake b/CMake/BuildConfigurations/DiffusionRelease.cmake index 9c7164d6da..144f7174dd 100644 --- a/CMake/BuildConfigurations/DiffusionRelease.cmake +++ b/CMake/BuildConfigurations/DiffusionRelease.cmake @@ -1,40 +1,38 @@ message(STATUS "Configuring MITK Diffusion Release Build") # Enable non-optional external dependencies set(MITK_USE_Vigra ON CACHE BOOL "MITK Use Vigra Library" FORCE) set(MITK_USE_HDF5 ON CACHE BOOL "MITK Use HDF5 Library" FORCE) set(MITK_USE_MatchPoint ON CACHE BOOL "" FORCE) set(MITK_USE_DCMTK ON CACHE BOOL "" FORCE) set(MITK_USE_DCMQI ON CACHE BOOL "" FORCE) -set(MITK_USE_Python ON CACHE BOOL "" FORCE) -set(MITK_USE_SYSTEM_PYTHON ON CACHE BOOL "" FORCE) # Disable all apps but MITK Diffusion set(MITK_BUILD_ALL_APPS OFF CACHE BOOL "Build all MITK applications" FORCE) set(MITK_BUILD_APP_CoreApp OFF CACHE BOOL "Build the MITK CoreApp" FORCE) set(MITK_BUILD_APP_Workbench OFF CACHE BOOL "Build the MITK Workbench" FORCE) set(MITK_BUILD_APP_Diffusion ON CACHE BOOL "Build MITK Diffusion" FORCE) # Activate Diffusion Mini Apps set(BUILD_DiffusionCoreCmdApps OFF CACHE BOOL "Build commandline tools for diffusion" FORCE) set(BUILD_DiffusionFiberProcessingCmdApps ON CACHE BOOL "Build commandline tools for diffusion fiber processing" FORCE) set(BUILD_DiffusionFiberfoxCmdApps ON CACHE BOOL "Build commandline tools for diffusion data simulation (Fiberfox)" FORCE) set(BUILD_DiffusionMiscCmdApps OFF CACHE BOOL "Build miscellaneous commandline tools for diffusion" FORCE) set(BUILD_DiffusionQuantificationCmdApps OFF CACHE BOOL "Build commandline tools for diffusion quantification (IVIM, ADC, ...)" FORCE) set(BUILD_DiffusionTractographyCmdApps ON CACHE BOOL "Build commandline tools for diffusion fiber tractography" FORCE) set(BUILD_DiffusionTractographyEvaluationCmdApps OFF CACHE BOOL "Build commandline tools for diffusion fiber tractography evaluation" FORCE) set(BUILD_DiffusionConnectomicsCmdApps ON CACHE BOOL "Build commandline tools for diffusion connectomics" FORCE) # Build neither all plugins nor examples set(MITK_BUILD_ALL_PLUGINS OFF CACHE BOOL "Build all MITK plugins" FORCE) set(MITK_BUILD_EXAMPLES OFF CACHE BOOL "Build the MITK examples" FORCE) set(BUILD_TESTING OFF CACHE BOOL "Build the MITK tests" FORCE) # Activate in-application help generation set(MITK_DOXYGEN_GENERATE_QCH_FILES ON CACHE BOOL "Use doxygen to generate Qt compressed help files for MITK docs" FORCE) set(BLUEBERRY_USE_QT_HELP ON CACHE BOOL "Enable support for integrating bundle documentation into Qt Help" FORCE) # Enable console window set(MITK_SHOW_CONSOLE_WINDOW ON CACHE BOOL "Use this to enable or disable the console window when starting MITK GUI Applications" FORCE) set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE) diff --git a/Modules/CommandLine/src/mitkCommandLineParser.cpp b/Modules/CommandLine/src/mitkCommandLineParser.cpp index b15a24e4b9..3e092e0ec7 100644 --- a/Modules/CommandLine/src/mitkCommandLineParser.cpp +++ b/Modules/CommandLine/src/mitkCommandLineParser.cpp @@ -1,957 +1,958 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*========================================================================= Library: CTK Copyright (c) Kitware Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.txt Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =========================================================================*/ // STL includes #include #include // MITK includes #include "mitkCommandLineParser.h" using namespace std; namespace { // -------------------------------------------------------------------------- class CommandLineParserArgumentDescription { public: CommandLineParserArgumentDescription(const string &longArg, const string &longArgPrefix, const string &shortArg, const string &shortArgPrefix, mitkCommandLineParser::Type type, const string &argHelp, const string &argLabel, const us::Any &defaultValue, bool ignoreRest, bool deprecated, bool optional, string &argGroup, string &groupDescription) : LongArg(longArg), LongArgPrefix(longArgPrefix), ShortArg(shortArg), ShortArgPrefix(shortArgPrefix), ArgHelp(argHelp), ArgLabel(argLabel), ArgGroup(argGroup), ArgGroupDescription(groupDescription), IgnoreRest(ignoreRest), NumberOfParametersToProcess(0), Deprecated(deprecated), Optional(optional), DefaultValue(defaultValue), Value(type), ValueType(type) { Value = defaultValue; switch (type) { case mitkCommandLineParser::String: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::Bool: { NumberOfParametersToProcess = 0; } break; case mitkCommandLineParser::StringList: { NumberOfParametersToProcess = -1; } break; case mitkCommandLineParser::Int: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::Float: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::OutputDirectory: case mitkCommandLineParser::InputDirectory: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::OutputFile: case mitkCommandLineParser::InputFile: { NumberOfParametersToProcess = 1; } break; case mitkCommandLineParser::InputImage: { NumberOfParametersToProcess = 1; } break; default: std::cout << "Type not supported: " << static_cast(type); } } ~CommandLineParserArgumentDescription() {} bool addParameter(const string &value); string helpText(); string LongArg; string LongArgPrefix; string ShortArg; string ShortArgPrefix; string ArgHelp; string ArgLabel; string ArgGroup; string ArgGroupDescription; bool IgnoreRest; int NumberOfParametersToProcess; bool Deprecated; bool Optional; us::Any DefaultValue; us::Any Value; mitkCommandLineParser::Type ValueType; }; // -------------------------------------------------------------------------- bool CommandLineParserArgumentDescription::addParameter(const string &value) { switch (ValueType) { case mitkCommandLineParser::String: { Value = value; } break; case mitkCommandLineParser::Bool: { if (value.compare("true") == 0) Value = true; else Value = false; } break; case mitkCommandLineParser::StringList: { try { mitkCommandLineParser::StringContainerType list = us::any_cast(Value); list.push_back(value); Value = list; } catch (...) { mitkCommandLineParser::StringContainerType list; list.push_back(value); Value = list; } } break; case mitkCommandLineParser::Int: { stringstream ss(value); int i; ss >> i; Value = i; } break; case mitkCommandLineParser::Float: { stringstream ss(value); float f; ss >> f; Value = f; } break; case mitkCommandLineParser::InputDirectory: case mitkCommandLineParser::OutputDirectory: { Value = value; } break; case mitkCommandLineParser::InputFile: case mitkCommandLineParser::InputImage: case mitkCommandLineParser::OutputFile: { Value = value; } break; default: return false; } return true; } // -------------------------------------------------------------------------- string CommandLineParserArgumentDescription::helpText() { string text; string shortAndLongArg; if (!this->ShortArg.empty()) { shortAndLongArg = " "; shortAndLongArg += this->ShortArgPrefix; shortAndLongArg += this->ShortArg; } if (!this->LongArg.empty()) { if (this->ShortArg.empty()) shortAndLongArg.append(" "); else shortAndLongArg.append(", "); shortAndLongArg += this->LongArgPrefix; shortAndLongArg += this->LongArg; } text = text + shortAndLongArg + ", " + this->ArgHelp; if (this->Optional) text += " (optional)"; if (!this->DefaultValue.Empty()) { text = text + ", (default: " + this->DefaultValue.ToString() + ")"; } text += "\n"; return text; } } // -------------------------------------------------------------------------- // ctkCommandLineParser::ctkInternal class // -------------------------------------------------------------------------- class mitkCommandLineParser::ctkInternal { public: ctkInternal() : Debug(false), FieldWidth(0), StrictMode(false) {} ~ctkInternal() {} CommandLineParserArgumentDescription *argumentDescription(const string &argument); vector ArgumentDescriptionList; map ArgNameToArgumentDescriptionMap; map> GroupToArgumentDescriptionListMap; StringContainerType UnparsedArguments; StringContainerType ProcessedArguments; string ErrorString; bool Debug; string::size_type FieldWidth; string LongPrefix; string ShortPrefix; string CurrentGroup; string DisableQSettingsLongArg; string DisableQSettingsShortArg; bool StrictMode; }; // -------------------------------------------------------------------------- // ctkCommandLineParser::ctkInternal methods // -------------------------------------------------------------------------- CommandLineParserArgumentDescription *mitkCommandLineParser::ctkInternal::argumentDescription(const string &argument) { string unprefixedArg = argument; if (!LongPrefix.empty() && argument.compare(0, LongPrefix.size(), LongPrefix) == 0) { // Case when (ShortPrefix + UnPrefixedArgument) matches LongPrefix if (argument == LongPrefix && !ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix) == 0) { unprefixedArg = argument.substr(ShortPrefix.size(), argument.size()); } else { unprefixedArg = argument.substr(LongPrefix.size(), argument.size()); } } else if (!ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix) == 0) { unprefixedArg = argument.substr(ShortPrefix.size(), argument.size()); } else if (!LongPrefix.empty() && !ShortPrefix.empty()) { return nullptr; } if (ArgNameToArgumentDescriptionMap.count(unprefixedArg)) { return this->ArgNameToArgumentDescriptionMap[unprefixedArg]; } return nullptr; } // -------------------------------------------------------------------------- // ctkCommandLineParser methods // -------------------------------------------------------------------------- mitkCommandLineParser::mitkCommandLineParser() { this->Internal = new ctkInternal(); this->Category = string(); this->Title = string(); this->Contributor = string(); this->Description = string(); this->ParameterGroupName = "Parameters"; this->ParameterGroupDescription = "Parameters"; } // -------------------------------------------------------------------------- mitkCommandLineParser::~mitkCommandLineParser() { delete this->Internal; } // -------------------------------------------------------------------------- map mitkCommandLineParser::parseArguments(const StringContainerType &arguments, bool *ok) { // Reset this->Internal->UnparsedArguments.clear(); this->Internal->ProcessedArguments.clear(); this->Internal->ErrorString.clear(); // foreach (CommandLineParserArgumentDescription* desc, this->Internal->ArgumentDescriptionList) for (unsigned int i = 0; i < Internal->ArgumentDescriptionList.size(); i++) { CommandLineParserArgumentDescription *desc = Internal->ArgumentDescriptionList.at(i); desc->Value = us::Any(desc->ValueType); if (!desc->DefaultValue.Empty()) { desc->Value = desc->DefaultValue; } } bool error = false; bool ignoreRest = false; CommandLineParserArgumentDescription *currentArgDesc = nullptr; vector parsedArgDescriptions; for (unsigned int i = 1; i < arguments.size(); ++i) { string argument = arguments.at(i); if (this->Internal->Debug) { std::cout << "Processing" << argument; } if (!argument.compare("--xml") || !argument.compare("-xml") || !argument.compare("--XML") || !argument.compare("-XML")) { this->generateXmlOutput(); return map(); } // should argument be ignored ? if (ignoreRest) { if (this->Internal->Debug) { std::cout << " Skipping: IgnoreRest flag was been set"; } this->Internal->UnparsedArguments.push_back(argument); continue; } // Skip if the argument does not start with the defined prefix if (!(argument.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix) == 0 || argument.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix) == 0)) { if (this->Internal->StrictMode) { this->Internal->ErrorString = "Unknown argument "; this->Internal->ErrorString += argument; error = true; break; } if (this->Internal->Debug) { std::cout << " Skipping: It does not start with the defined prefix"; } this->Internal->UnparsedArguments.push_back(argument); continue; } // Skip if argument has already been parsed ... bool alreadyProcessed = false; for (auto alreadyHandledArgument : Internal->ProcessedArguments) if (argument.compare(alreadyHandledArgument) == 0) { alreadyProcessed = true; break; } if (alreadyProcessed) { if (this->Internal->StrictMode) { this->Internal->ErrorString = "Argument "; this->Internal->ErrorString += argument; this->Internal->ErrorString += " already processed !"; error = true; break; } if (this->Internal->Debug) { std::cout << " Skipping: Already processed !"; } continue; } // Retrieve corresponding argument description currentArgDesc = this->Internal->argumentDescription(argument); // Is there a corresponding argument description ? if (currentArgDesc) { // If the argument is deprecated, print the help text but continue processing if (currentArgDesc->Deprecated) { std::cout << "Deprecated argument " << argument << ": " << currentArgDesc->ArgHelp; } else { parsedArgDescriptions.push_back(currentArgDesc); } this->Internal->ProcessedArguments.push_back(currentArgDesc->ShortArg); this->Internal->ProcessedArguments.push_back(currentArgDesc->LongArg); int numberOfParametersToProcess = currentArgDesc->NumberOfParametersToProcess; ignoreRest = currentArgDesc->IgnoreRest; if (this->Internal->Debug && ignoreRest) { std::cout << " IgnoreRest flag is True"; } // Is the number of parameters associated with the argument being processed known ? if (numberOfParametersToProcess == 0) { currentArgDesc->addParameter("true"); } else if (numberOfParametersToProcess > 0) { string missingParameterError = "Argument %1 has %2 value(s) associated whereas exacly %3 are expected."; for (int j = 1; j <= numberOfParametersToProcess; ++j) { if (i + j >= arguments.size()) { // this->Internal->ErrorString = // missingParameterError.arg(argument).arg(j-1).arg(numberOfParametersToProcess); // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } string parameter = arguments.at(i + j); if (this->Internal->Debug) { std::cout << " Processing parameter" << j << ", value:" << parameter; } if (this->argumentAdded(parameter)) { // this->Internal->ErrorString = // missingParameterError.arg(argument).arg(j-1).arg(numberOfParametersToProcess); // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } if (!currentArgDesc->addParameter(parameter)) { // this->Internal->ErrorString = string( // "Value(s) associated with argument %1 are incorrect. %2"). // arg(argument).arg(currentArgDesc->ExactMatchFailedMessage); // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } } // Update main loop increment i = i + numberOfParametersToProcess; } else if (numberOfParametersToProcess == -1) { if (this->Internal->Debug) { std::cout << " Proccessing StringList ..."; } int j = 1; while (j + i < arguments.size()) { if (this->argumentAdded(arguments.at(j + i))) { if (this->Internal->Debug) { std::cout << " No more parameter for" << argument; } break; } string parameter = arguments.at(j + i); if (parameter.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix) == 0 || parameter.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix) == 0) { j--; break; } if (this->Internal->Debug) { std::cout << " Processing parameter" << j << ", value:" << parameter; } if (!currentArgDesc->addParameter(parameter)) { // this->Internal->ErrorString = string( // "Value(s) associated with argument %1 are incorrect. %2"). // arg(argument).arg(currentArgDesc->ExactMatchFailedMessage); // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } j++; } // Update main loop increment i = i + j; } } else { if (this->Internal->StrictMode) { this->Internal->ErrorString = "Unknown argument "; this->Internal->ErrorString += argument; error = true; break; } if (this->Internal->Debug) { std::cout << " Skipping: Unknown argument"; } this->Internal->UnparsedArguments.push_back(argument); } } if (ok) { *ok = !error; } map parsedArguments; int obligatoryArgs = 0; vector::iterator it; for (it = Internal->ArgumentDescriptionList.begin(); it != Internal->ArgumentDescriptionList.end(); ++it) { CommandLineParserArgumentDescription *desc = *it; if (!desc->Optional) obligatoryArgs++; } int parsedObligatoryArgs = 0; for (it = parsedArgDescriptions.begin(); it != parsedArgDescriptions.end(); ++it) { CommandLineParserArgumentDescription *desc = *it; string key; if (!desc->LongArg.empty()) { key = desc->LongArg; } else { key = desc->ShortArg; } if (!desc->Optional) parsedObligatoryArgs++; std::pair elem; elem.first = key; elem.second = desc->Value; parsedArguments.insert(elem); } if (obligatoryArgs > parsedObligatoryArgs) { parsedArguments.clear(); cout << helpText(); } return parsedArguments; } // ------------------------------------------------------------------------- map mitkCommandLineParser::parseArguments(int argc, char **argv, bool *ok) { + std::cout << "Running Command Line Utility *" << Title << "*" << std::endl; StringContainerType arguments; // Create a StringContainerType of arguments for (int i = 0; i < argc; ++i) arguments.push_back(argv[i]); return this->parseArguments(arguments, ok); } // ------------------------------------------------------------------------- string mitkCommandLineParser::errorString() const { return this->Internal->ErrorString; } // ------------------------------------------------------------------------- const mitkCommandLineParser::StringContainerType &mitkCommandLineParser::unparsedArguments() const { return this->Internal->UnparsedArguments; } // -------------------------------------------------------------------------- void mitkCommandLineParser::addArgument(const string &longarg, const string &shortarg, Type type, const string &argLabel, const string &argHelp, const us::Any &defaultValue, bool optional, bool ignoreRest, bool deprecated) { if (longarg.empty() && shortarg.empty()) { return; } /* Make sure it's not already added */ bool added = (this->Internal->ArgNameToArgumentDescriptionMap.count(longarg) != 0); if (added) { return; } added = (this->Internal->ArgNameToArgumentDescriptionMap.count(shortarg) != 0); if (added) { return; } auto argDesc = new CommandLineParserArgumentDescription(longarg, this->Internal->LongPrefix, shortarg, this->Internal->ShortPrefix, type, argHelp, argLabel, defaultValue, ignoreRest, deprecated, optional, ParameterGroupName, ParameterGroupDescription); std::string::size_type argWidth = 0; if (!longarg.empty()) { this->Internal->ArgNameToArgumentDescriptionMap[longarg] = argDesc; argWidth += longarg.size() + this->Internal->LongPrefix.size(); } if (!shortarg.empty()) { this->Internal->ArgNameToArgumentDescriptionMap[shortarg] = argDesc; argWidth += shortarg.size() + this->Internal->ShortPrefix.size() + 2; } argWidth += 5; // Set the field width for the arguments if (argWidth > this->Internal->FieldWidth) { this->Internal->FieldWidth = argWidth; } this->Internal->ArgumentDescriptionList.push_back(argDesc); this->Internal->GroupToArgumentDescriptionListMap[this->Internal->CurrentGroup].push_back(argDesc); } // -------------------------------------------------------------------------- void mitkCommandLineParser::addDeprecatedArgument(const string &longarg, const string &shortarg, const string &argLabel, const string &argHelp) { addArgument(longarg, shortarg, StringList, argLabel, argHelp, us::Any(), false, true, false); } // -------------------------------------------------------------------------- std::string::size_type mitkCommandLineParser::fieldWidth() const { return this->Internal->FieldWidth; } // -------------------------------------------------------------------------- void mitkCommandLineParser::beginGroup(const string &description) { this->Internal->CurrentGroup = description; } // -------------------------------------------------------------------------- void mitkCommandLineParser::endGroup() { this->Internal->CurrentGroup.clear(); } // -------------------------------------------------------------------------- string mitkCommandLineParser::helpText() const { string text; vector deprecatedArgs; text = "Command Line Utility *" + Title + "* in Category *" + Category + "*\n"; text += Description + "\n"; text += Contributor + "\n\n"; text += "Use --xml to generate an XML description parsable as a CTK Command Line Module Plugin.\n"; // Loop over grouped argument descriptions map>::iterator it; for (it = Internal->GroupToArgumentDescriptionListMap.begin(); it != Internal->GroupToArgumentDescriptionListMap.end(); ++it) { if (!(*it).first.empty()) { text = text + "\n" + (*it).first + "\n"; } vector::iterator it2; for (it2 = (*it).second.begin(); it2 != (*it).second.end(); ++it2) { CommandLineParserArgumentDescription *argDesc = *it2; if (argDesc->Deprecated) { deprecatedArgs.push_back(argDesc); } else { text += argDesc->helpText(); } } } if (!deprecatedArgs.empty()) { text += "\nDeprecated arguments:\n"; vector::iterator it2; for (it2 = deprecatedArgs.begin(); it2 != deprecatedArgs.end(); ++it2) { CommandLineParserArgumentDescription *argDesc = *it2; text += argDesc->helpText(); } } return text; } // -------------------------------------------------------------------------- bool mitkCommandLineParser::argumentAdded(const string &argument) const { return (this->Internal->ArgNameToArgumentDescriptionMap.count(argument) != 0); } // -------------------------------------------------------------------------- bool mitkCommandLineParser::argumentParsed(const string &argument) const { for (unsigned int i = 0; i < Internal->ProcessedArguments.size(); i++) if (argument.compare(Internal->ProcessedArguments.at(i)) == 0) return true; return false; } // -------------------------------------------------------------------------- void mitkCommandLineParser::setArgumentPrefix(const string &longPrefix, const string &shortPrefix) { this->Internal->LongPrefix = longPrefix; this->Internal->ShortPrefix = shortPrefix; } // -------------------------------------------------------------------------- void mitkCommandLineParser::setStrictModeEnabled(bool strictMode) { this->Internal->StrictMode = strictMode; } void mitkCommandLineParser::generateXmlOutput() { std::stringstream xml; xml << "" << endl; xml << "" << Category << "" << endl; xml << "" << Title << "" << endl; xml << "" << Description << "" << endl; xml << "" << Contributor << "" << endl; xml << "" << endl; std::vector::iterator it; std::string lastParameterGroup = ""; for (it = this->Internal->ArgumentDescriptionList.begin(); it != this->Internal->ArgumentDescriptionList.end(); it++) { std::string type; switch ((*it)->ValueType) { case mitkCommandLineParser::String: type = "string"; break; case mitkCommandLineParser::Bool: type = "boolean"; break; case mitkCommandLineParser::StringList: type = "string-vector"; break; case mitkCommandLineParser::Int: type = "integer"; break; case mitkCommandLineParser::Float: type = "float"; break; case mitkCommandLineParser::OutputDirectory: case mitkCommandLineParser::InputDirectory: type = "directory"; break; case mitkCommandLineParser::InputImage: type = "image"; break; case mitkCommandLineParser::OutputFile: case mitkCommandLineParser::InputFile: type = "file"; break; } if (lastParameterGroup.compare((*it)->ArgGroup)) { if (it != this->Internal->ArgumentDescriptionList.begin()) { xml << "" << endl; xml << "" << endl; } xml << "" << endl; xml << "" << (*it)->ArgGroupDescription << "" << endl; lastParameterGroup = (*it)->ArgGroup; } // Skip help item, as it's no use in GUI if ((*it)->ShortArg == "h") continue; xml << "<" << type << ">" << endl; xml << "" << (*it)->LongArg << "" << endl; xml << "" << (*it)->ArgHelp << "" << endl; xml << "" << endl; if (!(*it)->DefaultValue.Empty()) xml << "" << (*it)->DefaultValue.ToString() << "" << endl; xml << "" << (*it)->LongArg << "" << endl; xml << "" << (*it)->ShortArg << "" << endl; if ((*it)->ValueType == mitkCommandLineParser::InputDirectory || (*it)->ValueType == mitkCommandLineParser::InputFile || (*it)->ValueType == mitkCommandLineParser::InputImage) { xml << "input" << endl; } else if ((*it)->ValueType == mitkCommandLineParser::OutputDirectory || (*it)->ValueType == mitkCommandLineParser::OutputFile) { xml << "output" << endl; } xml << "" << endl; } xml << "" << endl; xml << "" << endl; cout << xml.str(); } void mitkCommandLineParser::setTitle(string title) { Title = title; } void mitkCommandLineParser::setContributor(string contributor) { Contributor = contributor; } void mitkCommandLineParser::setCategory(string category) { Category = category; } void mitkCommandLineParser::setDescription(string description) { Description = description; } void mitkCommandLineParser::changeParameterGroup(string name, string tooltip) { ParameterGroupName = name; ParameterGroupDescription = tooltip; } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractClusteringFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractClusteringFilter.cpp index d85f434205..c7feec9017 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractClusteringFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractClusteringFilter.cpp @@ -1,504 +1,492 @@ /*=================================================================== 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 "itkTractClusteringFilter.h" #define _USE_MATH_DEFINES #include #include #include namespace itk{ TractClusteringFilter::TractClusteringFilter() : m_NumPoints(12) , m_InCentroids(nullptr) , m_MinClusterSize(1) , m_MaxClusters(0) , m_MergeDuplicateThreshold(-1) , m_DoResampling(true) , m_FilterMask(nullptr) , m_OverlapThreshold(0.0) { } TractClusteringFilter::~TractClusteringFilter() { for (auto m : m_Metrics) delete m; } std::vector > TractClusteringFilter::GetOutFiberIndices() const { return m_OutFiberIndices; } void TractClusteringFilter::SetMetrics(const std::vector &Metrics) { m_Metrics = Metrics; } std::vector TractClusteringFilter::GetOutClusters() const { return m_OutClusters; } std::vector TractClusteringFilter::GetOutCentroids() const { return m_OutCentroids; } std::vector TractClusteringFilter::GetOutTractograms() const { return m_OutTractograms; } void TractClusteringFilter::SetDistances(const std::vector &Distances) { m_Distances = Distances; } float TractClusteringFilter::CalcOverlap(vnl_matrix& t) { float overlap = 0; if (m_FilterMask.IsNotNull()) { for (unsigned int i=0; i p = t.get_column(i); itk::Point point; point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; itk::Index<3> idx; m_FilterMask->TransformPhysicalPointToIndex(point, idx); if (m_FilterMask->GetLargestPossibleRegion().IsInside(idx) && m_FilterMask->GetPixel(idx)>0) overlap += 1; } overlap /= m_NumPoints; } else return 1.0; return overlap; } std::vector > TractClusteringFilter::ResampleFibers(mitk::FiberBundle::Pointer tractogram) { mitk::FiberBundle::Pointer temp_fib = tractogram->GetDeepCopy(); if (m_DoResampling) temp_fib->ResampleToNumPoints(m_NumPoints); std::vector< vnl_matrix > out_fib; for (int i=0; iGetFiberPolyData()->GetNumberOfCells(); i++) { vtkCell* cell = temp_fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vnl_matrix streamline; streamline.set_size(3, m_NumPoints); streamline.fill(0.0); for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< float, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; streamline.set_column(j, candV); } out_fib.push_back(streamline); } return out_fib; } std::vector< TractClusteringFilter::Cluster > TractClusteringFilter::ClusterStep(std::vector< long > f_indices, std::vector distances) { float dist_thres = distances.back(); distances.pop_back(); std::vector< Cluster > C; int N = f_indices.size(); Cluster c1; c1.I.push_back(f_indices.at(0)); c1.h = T[f_indices.at(0)]; c1.n = 1; C.push_back(c1); if (f_indices.size()==1) return C; for (int i=1; i t = T.at(f_indices.at(i)); int min_cluster_index = -1; float min_cluster_distance = 99999; bool flip = false; for (unsigned int k=0; k v = C.at(k).h / C.at(k).n; bool f = false; float d = 0; for (auto m : m_Metrics) d += m->CalculateDistance(t, v, f); d /= m_Metrics.size(); if (d=0 && min_cluster_distance outC; -#pragma omp parallel for +//#pragma omp parallel for for (int c=0; c<(int)C.size(); c++) { std::vector< Cluster > tempC = ClusterStep(C.at(c).I, distances); AppendCluster(outC, tempC); } return outC; } else return C; } void TractClusteringFilter::AppendCluster(std::vector< Cluster >& a, std::vector< Cluster >&b) { for (auto c : b) a.push_back(c); } void TractClusteringFilter::MergeDuplicateClusters(std::vector< TractClusteringFilter::Cluster >& clusters) { if (m_MergeDuplicateThreshold<0) m_MergeDuplicateThreshold = m_Distances.at(0)/2; bool found = true; MITK_INFO << "Merging duplicate clusters with distance threshold " << m_MergeDuplicateThreshold; int start = 0; while (found && m_MergeDuplicateThreshold>mitk::eps) { std::cout << " \r"; std::cout << "Number of clusters: " << clusters.size() << '\r'; cout.flush(); found = false; for (int k1=start; k1<(int)clusters.size(); ++k1) { Cluster c1 = clusters.at(k1); vnl_matrix t = c1.h / c1.n; std::vector< int > merge_indices; std::vector< bool > flip_indices; #pragma omp parallel for for (int k2=0; k2<(int)clusters.size(); ++k2) { if (k1!=k2) { Cluster c2 = clusters.at(k2); vnl_matrix v = c2.h / c2.n; bool f = false; -// d = m_Metric->CalculateDistance(t, v, f); // alwayse use MDF? float d = 0; for (auto m : m_Metrics) d += m->CalculateDistance(t, v, f); d /= m_Metrics.size(); #pragma omp critical if (d TractClusteringFilter::AddToKnownClusters(std::vector< long > f_indices, std::vector >& centroids) { float dist_thres = m_Distances.at(0); int N = f_indices.size(); std::vector< Cluster > C; vnl_matrix zero_h; zero_h.set_size(T.at(0).rows(), T.at(0).cols()); zero_h.fill(0.0); Cluster no_fit; no_fit.h = zero_h; for (unsigned int i=0; i t = T.at(f_indices.at(i)); int min_cluster_index = -1; float min_cluster_distance = 99999; bool flip = false; if (CalcOverlap(t)>=m_OverlapThreshold) { int c_idx = 0; for (vnl_matrix centroid : centroids) { bool f = false; float d = 0; for (auto m : m_Metrics) d += m->CalculateDistance(t, centroid, f); d /= m_Metrics.size(); if (d=0 && min_cluster_distance f_indices; for (unsigned int i=0; i clusters; if (m_InCentroids.IsNull()) { MITK_INFO << "Clustering fibers"; clusters = ClusterStep(f_indices, m_Distances); -// while (clusters.size()>5000) -// { -// MITK_INFO << "Number of clusters: " << clusters.size(); -// MITK_INFO << "Increasing cluster size"; -// for (unsigned int i=0; i > centroids = ResampleFibers(m_InCentroids); if (centroids.empty()) { MITK_INFO << "No fibers in centroid tractogram!"; return; } MITK_INFO << "Clustering with input centroids"; clusters = AddToKnownClusters(f_indices, centroids); no_match = clusters.back(); clusters.pop_back(); MITK_INFO << "Number of clusters: " << clusters.size(); MergeDuplicateClusters(clusters); } MITK_INFO << "Clustering finished"; int max = clusters.size()-1; if (m_MaxClusters>0 && clusters.size()-1>m_MaxClusters) max = m_MaxClusters; for (int i=clusters.size()-1; i>=0; --i) { Cluster c = clusters.at(i); if ( c.n>=(int)m_MinClusterSize && !(m_MaxClusters>0 && clusters.size()-i>m_MaxClusters) ) { m_OutClusters.push_back(c); vtkSmartPointer weights = vtkSmartPointer::New(); vtkSmartPointer pTmp = m_Tractogram->GeneratePolyDataByIds(c.I, weights); mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(pTmp); if (max>0) fib->SetFiberWeights((float)i/max); m_OutTractograms.push_back(fib); m_OutFiberIndices.push_back(c.I); // create centroid vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); vtkSmartPointer polyData = vtkSmartPointer::New(); vtkSmartPointer container = vtkSmartPointer::New(); vnl_matrix centroid_points = c.h / c.n; for (unsigned int j=0; jInsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); polyData->SetPoints(vtkNewPoints); polyData->SetLines(vtkNewCells); mitk::FiberBundle::Pointer centroid = mitk::FiberBundle::New(polyData); centroid->SetFiberColors(255, 255, 255); m_OutCentroids.push_back(centroid); } } MITK_INFO << "Final number of clusters: " << m_OutTractograms.size(); int w = 0; for (auto fib : m_OutTractograms) { if (m_OutTractograms.size()>1) { fib->SetFiberWeights((float)w/(m_OutTractograms.size()-1)); m_OutCentroids.at(w)->SetFiberWeights((float)w/(m_OutTractograms.size()-1)); } else { fib->SetFiberWeights(1); m_OutCentroids.at(w)->SetFiberWeights(1); } fib->ColorFibersByFiberWeights(false, false); ++w; } if (no_match.n>0) { vtkSmartPointer weights = vtkSmartPointer::New(); vtkSmartPointer pTmp = m_Tractogram->GeneratePolyDataByIds(no_match.I, weights); mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(pTmp); fib->SetFiberColors(0, 0, 0); m_OutFiberIndices.push_back(no_match.I); m_OutTractograms.push_back(fib); } } } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp index a77e966134..2c8ac8ca6c 100755 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp @@ -1,2517 +1,2546 @@ /*=================================================================== 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 "mitkFiberBundle.h" #include #include #include #include "mitkImagePixelReadAccessor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const char* mitk::FiberBundle::FIBER_ID_ARRAY = "Fiber_IDs"; mitk::FiberBundle::FiberBundle( vtkPolyData* fiberPolyData ) : m_NumFibers(0) { m_FiberWeights = vtkSmartPointer::New(); m_FiberWeights->SetName("FIBER_WEIGHTS"); m_FiberPolyData = vtkSmartPointer::New(); if (fiberPolyData != nullptr) m_FiberPolyData = fiberPolyData; else { this->m_FiberPolyData->SetPoints(vtkSmartPointer::New()); this->m_FiberPolyData->SetLines(vtkSmartPointer::New()); } this->UpdateFiberGeometry(); this->GenerateFiberIds(); this->ColorFibersByOrientation(); } mitk::FiberBundle::~FiberBundle() { } mitk::FiberBundle::Pointer mitk::FiberBundle::GetDeepCopy() { mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(m_FiberPolyData); newFib->SetFiberColors(this->m_FiberColors); newFib->SetFiberWeights(this->m_FiberWeights); return newFib; } vtkSmartPointer mitk::FiberBundle::GeneratePolyDataByIds(std::vector fiberIds, vtkSmartPointer weights) { vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); vtkSmartPointer newLineSet = vtkSmartPointer::New(); vtkSmartPointer newPointSet = vtkSmartPointer::New(); weights->SetNumberOfValues(fiberIds.size()); int counter = 0; auto finIt = fiberIds.begin(); while ( finIt != fiberIds.end() ) { if (*finIt < 0 || *finIt>GetNumFibers()){ MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt; break; } vtkSmartPointer fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber); vtkSmartPointer fibPoints = fiber->GetPoints(); vtkSmartPointer newFiber = vtkSmartPointer::New(); newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() ); for(int i=0; iGetNumberOfPoints(); i++) { newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); } weights->InsertValue(counter, this->GetFiberWeight(*finIt)); newLineSet->InsertNextCell(newFiber); ++finIt; ++counter; } newFiberPolyData->SetPoints(newPointSet); newFiberPolyData->SetLines(newLineSet); return newFiberPolyData; } // merge two fiber bundles mitk::FiberBundle::Pointer mitk::FiberBundle::AddBundles(std::vector< mitk::FiberBundle::Pointer > fibs) { vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // add current fiber bundle vtkSmartPointer weights = vtkSmartPointer::New(); int num_weights = this->GetNumFibers(); for (auto fib : fibs) num_weights += fib->GetNumFibers(); weights->SetNumberOfValues(num_weights); unsigned int counter = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, this->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } for (auto fib : fibs) { // add new fiber bundle for (int i=0; iGetFiberPolyData()->GetNumberOfCells(); i++) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, fib->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } } // initialize PolyData vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData); newFib->SetFiberWeights(weights); return newFib; } // merge two fiber bundles mitk::FiberBundle::Pointer mitk::FiberBundle::AddBundle(mitk::FiberBundle* fib) { if (fib==nullptr) return this->GetDeepCopy(); MITK_INFO << "Adding fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // add current fiber bundle vtkSmartPointer weights = vtkSmartPointer::New(); weights->SetNumberOfValues(this->GetNumFibers()+fib->GetNumFibers()); unsigned int counter = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, this->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } // add new fiber bundle for (int i=0; iGetFiberPolyData()->GetNumberOfCells(); i++) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, fib->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } // initialize PolyData vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData); newFib->SetFiberWeights(weights); return newFib; } // Only retain fibers with a weight larger than the specified threshold mitk::FiberBundle::Pointer mitk::FiberBundle::FilterByWeights(float weight_thr, bool invert) { vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); std::vector weights; for (int i=0; iGetNumFibers(); i++) { if ( (invert && this->GetFiberWeight(i)>weight_thr) || (!invert && this->GetFiberWeight(i)<=weight_thr)) continue; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); weights.push_back(this->GetFiberWeight(i)); } // initialize PolyData vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData); for (unsigned int i=0; iSetFiberWeight(i, weights.at(i)); return newFib; } // Only retain a subsample of the fibers mitk::FiberBundle::Pointer mitk::FiberBundle::SubsampleFibers(float factor) { vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); int new_num_fibs = this->GetNumFibers()*factor; MITK_INFO << "Subsampling fibers with factor " << factor << "(" << new_num_fibs << "/" << this->GetNumFibers() << ")"; // add current fiber bundle vtkSmartPointer weights = vtkSmartPointer::New(); weights->SetNumberOfValues(new_num_fibs); std::vector< int > ids; for (int i=0; iGetNumFibers(); i++) ids.push_back(i); std::random_shuffle(ids.begin(), ids.end()); unsigned int counter = 0; for (int i=0; iGetCell(ids.at(i)); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, this->GetFiberWeight(ids.at(i))); vNewLines->InsertNextCell(container); counter++; } // initialize PolyData vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData); newFib->SetFiberWeights(weights); return newFib; } // subtract two fiber bundles mitk::FiberBundle::Pointer mitk::FiberBundle::SubtractBundle(mitk::FiberBundle* fib) { if (fib==nullptr) return this->GetDeepCopy(); MITK_INFO << "Subtracting fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); std::vector< std::vector< itk::Point > > points1; for( int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==nullptr || numPoints<=0) continue; itk::Point start = GetItkPoint(points->GetPoint(0)); itk::Point end = GetItkPoint(points->GetPoint(numPoints-1)); points1.push_back( {start, end} ); } std::vector< std::vector< itk::Point > > points2; for( int i=0; iGetNumFibers(); i++ ) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==nullptr || numPoints<=0) continue; itk::Point start = GetItkPoint(points->GetPoint(0)); itk::Point end = GetItkPoint(points->GetPoint(numPoints-1)); points2.push_back( {start, end} ); } // int progress = 0; std::vector< int > ids; #pragma omp parallel for for (int i=0; i<(int)points1.size(); i++) { //#pragma omp critical // { // progress++; // std::cout << (int)(100*(float)progress/points1.size()) << "%" << '\r'; // cout.flush(); // } bool match = false; for (unsigned int j=0; jGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==nullptr || numPoints<=0) continue; vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(points->GetPoint(j)); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } if(vNewLines->GetNumberOfCells()==0) return mitk::FiberBundle::New(); // initialize PolyData vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle return mitk::FiberBundle::New(vNewPolyData); } itk::Point mitk::FiberBundle::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } /* * set PolyData (additional flag to recompute fiber geometry, default = true) */ void mitk::FiberBundle::SetFiberPolyData(vtkSmartPointer fiberPD, bool updateGeometry) { if (fiberPD == nullptr) this->m_FiberPolyData = vtkSmartPointer::New(); else m_FiberPolyData->DeepCopy(fiberPD); m_NumFibers = m_FiberPolyData->GetNumberOfLines(); if (updateGeometry) UpdateFiberGeometry(); GenerateFiberIds(); ColorFibersByOrientation(); } /* * return vtkPolyData */ vtkSmartPointer mitk::FiberBundle::GetFiberPolyData() const { return m_FiberPolyData; } void mitk::FiberBundle::ColorFibersByOrientation() { //===== FOR WRITING A TEST ======================== // colorT size == tupelComponents * tupelElements // compare color results // to cover this code 100% also PolyData needed, where colorarray already exists // + one fiber with exactly 1 point // + one fiber with 0 points //================================================= vtkPoints* extrPoints = nullptr; extrPoints = m_FiberPolyData->GetPoints(); int numOfPoints = 0; if (extrPoints!=nullptr) numOfPoints = extrPoints->GetNumberOfPoints(); //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = 4; m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(numOfPoints * componentSize); m_FiberColors->SetNumberOfComponents(componentSize); m_FiberColors->SetName("FIBER_COLORS"); int numOfFibers = m_FiberPolyData->GetNumberOfLines(); if (numOfFibers < 1) return; /* extract single fibers of fiberBundle */ vtkCellArray* fiberList = m_FiberPolyData->GetLines(); fiberList->InitTraversal(); for (int fi=0; fiGetNextCell(pointsPerFiber, idList); /* single fiber checkpoints: is number of points valid */ if (pointsPerFiber > 1) { /* operate on points of single fiber */ for (int i=0; i 0) { /* The color value of the current point is influenced by the previous point and next point. */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; vnl_vector_fixed< double, 3 > diff; diff = (diff1 - diff2) / 2.0; diff.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2])); rgba[3] = (unsigned char) (255.0); } else if (i==0) { /* First point has no previous point, therefore only diff1 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; diff1.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2])); rgba[3] = (unsigned char) (255.0); } else if (i==pointsPerFiber-1) { /* Last point has no next point, therefore only diff2 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; diff2.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2])); rgba[3] = (unsigned char) (255.0); } m_FiberColors->InsertTypedTuple(idList[i], rgba); } } else if (pointsPerFiber == 1) { /* a single point does not define a fiber (use vertex mechanisms instead */ continue; } else { MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ; continue; } } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ColorFibersByCurvature(bool, bool normalize) { double window = 5; //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = 4; m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * componentSize); m_FiberColors->SetNumberOfComponents(componentSize); m_FiberColors->SetName("FIBER_COLORS"); mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(0.0, 0.8); lookupTable->Build(); mitkLookup->SetVtkLookupTable(lookupTable); mitkLookup->SetType(mitk::LookupTable::JET); std::vector< double > values; double min = 1; double max = 0; MITK_INFO << "Coloring fibers by curvature"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures for (int j=0; j > vectors; vnl_vector_fixed< float, 3 > meanV; meanV.fill(0.0); while(dist1) { double p1[3]; points->GetPoint(c-1, p1); double p2[3]; points->GetPoint(c, p2); vnl_vector_fixed< float, 3 > v; v[0] = p2[0]-p1[0]; v[1] = p2[1]-p1[1]; v[2] = p2[2]-p1[2]; dist += v.magnitude(); v.normalize(); vectors.push_back(v); if (c==j) meanV += v; c--; } c = j; dist = 0; while(distGetPoint(c, p1); double p2[3]; points->GetPoint(c+1, p2); vnl_vector_fixed< float, 3 > v; v[0] = p2[0]-p1[0]; v[1] = p2[1]-p1[1]; v[2] = p2[2]-p1[2]; dist += v.magnitude(); v.normalize(); vectors.push_back(v); if (c==j) meanV += v; c++; } meanV.normalize(); double dev = 0; for (unsigned int c=0; c1.0) angle = 1.0; if (angle<-1.0) angle = -1.0; dev += acos(angle)*180/M_PI; } if (vectors.size()>0) dev /= vectors.size(); dev = 1.0-dev/180.0; values.push_back(dev); if (devmax) max = dev; } } unsigned int count = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); for (int j=0; j1) dev = 1; lookupTable->GetColor(dev, color); rgba[0] = (unsigned char) (255.0 * color[0]); rgba[1] = (unsigned char) (255.0 * color[1]); rgba[2] = (unsigned char) (255.0 * color[2]); rgba[3] = (unsigned char) (255.0); m_FiberColors->InsertTypedTuple(cell->GetPointId(j), rgba); count++; } } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::SetFiberOpacity(vtkDoubleArray* FAValArray) { for(long i=0; iGetNumberOfTuples(); i++) { double faValue = FAValArray->GetValue(i); faValue = faValue * 255.0; m_FiberColors->SetComponent(i,3, (unsigned char) faValue ); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ResetFiberOpacity() { for(long i=0; iGetNumberOfTuples(); i++) m_FiberColors->SetComponent(i,3, 255.0 ); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ColorFibersByScalarMap(mitk::Image::Pointer FAimage, bool opacity, bool normalize) { mitkPixelTypeMultiplex3( ColorFibersByScalarMap, FAimage->GetPixelType(), FAimage, opacity, normalize ); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } template void mitk::FiberBundle::ColorFibersByScalarMap(const mitk::PixelType, mitk::Image::Pointer image, bool opacity, bool normalize) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0)); unsigned char rgba[4] = {0,0,0,0}; vtkPoints* pointSet = m_FiberPolyData->GetPoints(); mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(0.0, 0.8); lookupTable->Build(); mitkLookup->SetVtkLookupTable(lookupTable); mitkLookup->SetType(mitk::LookupTable::JET); double min = 9999999; double max = -9999999; for(long i=0; iGetNumberOfPoints(); ++i) { Point3D px; px[0] = pointSet->GetPoint(i)[0]; px[1] = pointSet->GetPoint(i)[1]; px[2] = pointSet->GetPoint(i)[2]; double pixelValue = readimage.GetPixelByWorldCoordinates(px); if (pixelValue>max) max = pixelValue; if (pixelValueGetNumberOfPoints(); ++i) { Point3D px; px[0] = pointSet->GetPoint(i)[0]; px[1] = pointSet->GetPoint(i)[1]; px[2] = pointSet->GetPoint(i)[2]; double pixelValue = readimage.GetPixelByWorldCoordinates(px); if (normalize) pixelValue = (pixelValue-min)/(max-min); else if (pixelValue>1) pixelValue = 1; double color[3]; lookupTable->GetColor(1-pixelValue, color); rgba[0] = (unsigned char) (255.0 * color[0]); rgba[1] = (unsigned char) (255.0 * color[1]); rgba[2] = (unsigned char) (255.0 * color[2]); if (opacity) rgba[3] = (unsigned char) (255.0 * pixelValue); else rgba[3] = (unsigned char) (255.0); m_FiberColors->InsertTypedTuple(i, rgba); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ColorFibersByFiberWeights(bool opacity, bool normalize) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(0.0, 0.8); lookupTable->Build(); mitkLookup->SetVtkLookupTable(lookupTable); mitkLookup->SetType(mitk::LookupTable::JET); unsigned char rgba[4] = {0,0,0,0}; unsigned int counter = 0; float max = -999999; float min = 999999; for (int i=0; iGetFiberWeight(i); if (weight>max) max = weight; if (weightGetCell(i); int numPoints = cell->GetNumberOfPoints(); double weight = this->GetFiberWeight(i); for (int j=0; j1) v = 1; double color[3]; lookupTable->GetColor(1-v, color); rgba[0] = (unsigned char) (255.0 * color[0]); rgba[1] = (unsigned char) (255.0 * color[1]); rgba[2] = (unsigned char) (255.0 * color[2]); if (opacity) rgba[3] = (unsigned char) (255.0 * v); else rgba[3] = (unsigned char) (255.0); m_FiberColors->InsertTypedTuple(counter, rgba); counter++; } } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::SetFiberColors(float r, float g, float b, float alpha) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); unsigned char rgba[4] = {0,0,0,0}; for(long i=0; iGetNumberOfPoints(); ++i) { rgba[0] = (unsigned char) r; rgba[1] = (unsigned char) g; rgba[2] = (unsigned char) b; rgba[3] = (unsigned char) alpha; m_FiberColors->InsertTypedTuple(i, rgba); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::GenerateFiberIds() { if (m_FiberPolyData == nullptr) return; vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); idFiberFilter->SetInputData(m_FiberPolyData); idFiberFilter->CellIdsOn(); // idFiberFilter->PointIdsOn(); // point id's are not needed idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); idFiberFilter->FieldDataOn(); idFiberFilter->Update(); m_FiberIdDataSet = idFiberFilter->GetOutput(); } float mitk::FiberBundle::GetOverlap(ItkUcharImgType* mask, bool do_resampling) { vtkSmartPointer PolyData = m_FiberPolyData; mitk::FiberBundle::Pointer fibCopy = this; if (do_resampling) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; fibCopy = this->GetDeepCopy(); fibCopy->ResampleLinear(minSpacing/5); PolyData = fibCopy->GetFiberPolyData(); } MITK_INFO << "Calculating overlap"; int inside = 0; int outside = 0; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetLargestPossibleRegion().IsInside(idx) && mask->GetPixel(idx) != 0 ) inside++; else outside++; } } if (inside+outside==0) outside = 1; return (float)inside/(inside+outside); } mitk::FiberBundle::Pointer mitk::FiberBundle::RemoveFibersOutside(ItkUcharImgType* mask, bool invert) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; mitk::FiberBundle::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleLinear(minSpacing/10); vtkSmartPointer PolyData =fibCopy->GetFiberPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Cutting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1) { int newNumPoints = 0; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx) != 0 && mask->GetLargestPossibleRegion().IsInside(idx) && !invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if ( (mask->GetPixel(idx) == 0 || !mask->GetLargestPossibleRegion().IsInside(idx)) && invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if (newNumPoints>0) { vtkNewCells->InsertNextCell(container); newNumPoints = 0; container = vtkSmartPointer::New(); } } if (newNumPoints>0) vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return nullptr; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(newPolyData); newFib->Compress(0.1); return newFib; } mitk::FiberBundle::Pointer mitk::FiberBundle::ExtractFiberSubset(DataNode* roi, DataStorage* storage) { if (roi==nullptr || !(dynamic_cast(roi->GetData()) || dynamic_cast(roi->GetData())) ) return nullptr; std::vector tmp = ExtractFiberIdSubset(roi, storage); if (tmp.size()<=0) return mitk::FiberBundle::New(); vtkSmartPointer weights = vtkSmartPointer::New(); vtkSmartPointer pTmp = GeneratePolyDataByIds(tmp, weights); mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(pTmp); fib->SetFiberWeights(weights); return fib; } std::vector mitk::FiberBundle::ExtractFiberIdSubset(DataNode *roi, DataStorage* storage) { std::vector result; if (roi==nullptr || roi->GetData()==nullptr) return result; mitk::PlanarFigureComposite::Pointer pfc = dynamic_cast(roi->GetData()); if (!pfc.IsNull()) // handle composite { DataStorage::SetOfObjects::ConstPointer children = storage->GetDerivations(roi); if (children->size()==0) return result; switch (pfc->getOperationType()) { case 0: // AND { MITK_INFO << "AND"; result = this->ExtractFiberIdSubset(children->ElementAt(0), storage); std::vector::iterator it; for (unsigned int i=1; iSize(); ++i) { std::vector inRoi = this->ExtractFiberIdSubset(children->ElementAt(i), storage); std::vector rest(std::min(result.size(),inRoi.size())); it = std::set_intersection(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } case 1: // OR { MITK_INFO << "OR"; result = ExtractFiberIdSubset(children->ElementAt(0), storage); std::vector::iterator it; for (unsigned int i=1; iSize(); ++i) { it = result.end(); std::vector inRoi = ExtractFiberIdSubset(children->ElementAt(i), storage); result.insert(it, inRoi.begin(), inRoi.end()); } // remove duplicates sort(result.begin(), result.end()); it = unique(result.begin(), result.end()); result.resize( it - result.begin() ); break; } case 2: // NOT { MITK_INFO << "NOT"; for(long i=0; iGetNumFibers(); i++) result.push_back(i); std::vector::iterator it; for (unsigned int i=0; iSize(); ++i) { std::vector inRoi = ExtractFiberIdSubset(children->ElementAt(i), storage); std::vector rest(result.size()-inRoi.size()); it = std::set_difference(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } } } else if ( dynamic_cast(roi->GetData()) ) // actual extraction { if ( dynamic_cast(roi->GetData()) ) { mitk::PlanarFigure::Pointer planarPoly = dynamic_cast(roi->GetData()); //create vtkPolygon using controlpoints from planarFigure polygon vtkSmartPointer polygonVtk = vtkSmartPointer::New(); for (unsigned int i=0; iGetNumberOfControlPoints(); ++i) { itk::Point p = planarPoly->GetWorldControlPoint(i); vtkIdType id = polygonVtk->GetPoints()->InsertNextPoint(p[0], p[1], p[2] ); polygonVtk->GetPointIds()->InsertNextId(id); } MITK_INFO << "Extracting with polygon"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p1); double p2[3] = {0,0,0}; points->GetPoint(j+1, p2); double tolerance = 0.001; // Outputs double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) double x[3] = {0,0,0}; // The coordinate of the intersection double pcoords[3] = {0,0,0}; int subId = 0; int iD = polygonVtk->IntersectWithLine(p1, p2, tolerance, t, x, pcoords, subId); if (iD!=0) { result.push_back(i); break; } } } } else if ( dynamic_cast(roi->GetData()) ) { mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(roi->GetData()); Vector3D planeNormal = planarFigure->GetPlaneGeometry()->GetNormal(); planeNormal.Normalize(); //calculate circle radius mitk::Point3D V1w = planarFigure->GetWorldControlPoint(0); //centerPoint mitk::Point3D V2w = planarFigure->GetWorldControlPoint(1); //radiusPoint double radius = V1w.EuclideanDistanceTo(V2w); radius *= radius; MITK_INFO << "Extracting with circle"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p1); double p2[3] = {0,0,0}; points->GetPoint(j+1, p2); // Outputs double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) double x[3] = {0,0,0}; // The coordinate of the intersection int iD = vtkPlane::IntersectWithLine(p1,p2,planeNormal.GetDataPointer(),V1w.GetDataPointer(),t,x); if (iD!=0) { double dist = (x[0]-V1w[0])*(x[0]-V1w[0])+(x[1]-V1w[1])*(x[1]-V1w[1])+(x[2]-V1w[2])*(x[2]-V1w[2]); if( dist <= radius) { result.push_back(i); break; } } } } } return result; } return result; } void mitk::FiberBundle::UpdateFiberGeometry() { vtkSmartPointer cleaner = vtkSmartPointer::New(); cleaner->SetInputData(m_FiberPolyData); cleaner->PointMergingOff(); cleaner->Update(); m_FiberPolyData = cleaner->GetOutput(); m_FiberLengths.clear(); m_MeanFiberLength = 0; m_MedianFiberLength = 0; m_LengthStDev = 0; m_NumFibers = m_FiberPolyData->GetNumberOfCells(); if (m_FiberColors==nullptr || m_FiberColors->GetNumberOfTuples()!=m_FiberPolyData->GetNumberOfPoints()) this->ColorFibersByOrientation(); if (m_FiberWeights->GetNumberOfValues()!=m_NumFibers) { m_FiberWeights = vtkSmartPointer::New(); m_FiberWeights->SetName("FIBER_WEIGHTS"); m_FiberWeights->SetNumberOfValues(m_NumFibers); this->SetFiberWeights(1); } if (m_NumFibers<=0) // no fibers present; apply default geometry { m_MinFiberLength = 0; m_MaxFiberLength = 0; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(false); float b[] = {0, 1, 0, 1, 0, 1}; geometry->SetFloatBounds(b); SetGeometry(geometry); return; } double b[6]; m_FiberPolyData->GetBounds(b); // calculate statistics for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int p = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); float length = 0; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); float dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2])); length += dist; } m_FiberLengths.push_back(length); m_MeanFiberLength += length; if (i==0) { m_MinFiberLength = length; m_MaxFiberLength = length; } else { if (lengthm_MaxFiberLength) m_MaxFiberLength = length; } } m_MeanFiberLength /= m_NumFibers; std::vector< float > sortedLengths = m_FiberLengths; std::sort(sortedLengths.begin(), sortedLengths.end()); for (int i=0; i1) m_LengthStDev /= (m_NumFibers-1); else m_LengthStDev = 0; m_LengthStDev = std::sqrt(m_LengthStDev); m_MedianFiberLength = sortedLengths.at(m_NumFibers/2); mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetFloatBounds(b); this->SetGeometry(geometry); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } float mitk::FiberBundle::GetFiberWeight(unsigned int fiber) const { return m_FiberWeights->GetValue(fiber); } void mitk::FiberBundle::SetFiberWeights(float newWeight) { for (int i=0; iGetNumberOfValues(); i++) m_FiberWeights->SetValue(i, newWeight); } void mitk::FiberBundle::SetFiberWeights(vtkSmartPointer weights) { if (m_NumFibers!=weights->GetNumberOfValues()) { MITK_INFO << "Weights array not equal to number of fibers! " << weights->GetNumberOfValues() << " vs " << m_NumFibers; return; } for (int i=0; iGetNumberOfValues(); i++) m_FiberWeights->SetValue(i, weights->GetValue(i)); m_FiberWeights->SetName("FIBER_WEIGHTS"); } void mitk::FiberBundle::SetFiberWeight(unsigned int fiber, float weight) { m_FiberWeights->SetValue(fiber, weight); } void mitk::FiberBundle::SetFiberColors(vtkSmartPointer fiberColors) { for(long i=0; iGetNumberOfPoints(); ++i) { unsigned char source[4] = {0,0,0,0}; fiberColors->GetTypedTuple(i, source); unsigned char target[4] = {0,0,0,0}; target[0] = source[0]; target[1] = source[1]; target[2] = source[2]; target[3] = source[3]; m_FiberColors->InsertTypedTuple(i, target); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } itk::Matrix< double, 3, 3 > mitk::FiberBundle::TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; m = rot*m; return m; } itk::Point mitk::FiberBundle::TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); point[0] -= center[0]; point[1] -= center[1]; point[2] -= center[2]; point = rot*point; point[0] += center[0]+tx; point[1] += center[1]+ty; point[2] += center[2]+tz; itk::Point out; out[0] = point[0]; out[1] = point[1]; out[2] = point[2]; return out; } + +void mitk::FiberBundle::TransformFibers(itk::ScalableAffineTransform< mitk::ScalarType >::Pointer transform) +{ + vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); + vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); + + for (int i=0; iGetCell(i); + int numPoints = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); + + vtkSmartPointer container = vtkSmartPointer::New(); + for (int j=0; j p = GetItkPoint(points->GetPoint(j)); + p = transform->TransformPoint(p); + vtkIdType id = vtkNewPoints->InsertNextPoint(p.GetDataPointer()); + container->GetPointIds()->InsertNextId(id); + } + vtkNewCells->InsertNextCell(container); + } + + m_FiberPolyData = vtkSmartPointer::New(); + m_FiberPolyData->SetPoints(vtkNewPoints); + m_FiberPolyData->SetLines(vtkNewCells); + this->SetFiberPolyData(m_FiberPolyData, true); +} + void mitk::FiberBundle::TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rot*dir; dir[0] += center[0]+tx; dir[1] += center[1]+ty; dir[2] += center[2]+tz; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::RotateAroundAxis(double x, double y, double z) { x = x*M_PI/180; y = y*M_PI/180; z = z*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rotZ*rotY*rotX*dir; dir[0] += center[0]; dir[1] += center[1]; dir[2] += center[2]; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::ScaleFibers(double x, double y, double z, bool subtractCenter) { MITK_INFO << "Scaling fibers"; boost::progress_display disp(m_NumFibers); mitk::BaseGeometry* geom = this->GetGeometry(); mitk::Point3D c = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); if (subtractCenter) { p[0] -= c[0]; p[1] -= c[1]; p[2] -= c[2]; } p[0] *= x; p[1] *= y; p[2] *= z; if (subtractCenter) { p[0] += c[0]; p[1] += c[1]; p[2] += c[2]; } vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::TranslateFibers(double x, double y, double z) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[0] += x; p[1] += y; p[2] += z; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::MirrorFibers(unsigned int axis) { if (axis>2) return; MITK_INFO << "Mirroring fibers"; boost::progress_display disp(m_NumFibers); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[axis] = -p[axis]; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::RemoveDir(vnl_vector_fixed dir, double threshold) { dir.normalize(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); bool discard = false; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); vnl_vector_fixed< double, 3 > v1; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; if (v1.magnitude()>0.001) { v1.normalize(); if (fabs(dot_product(v1,dir))>threshold) { discard = true; break; } } } if (!discard) { for (int j=0; jGetPoint(j, p1); vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); // UpdateColorCoding(); // UpdateFiberGeometry(); } bool mitk::FiberBundle::ApplyCurvatureThreshold(float minRadius, bool deleteFibers) { if (minRadius<0) return true; vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Applying curvature threshold"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); double p3[3]; points->GetPoint(j+2, p3); vnl_vector_fixed< float, 3 > v1, v2, v3; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; v2[0] = p3[0]-p2[0]; v2[1] = p3[1]-p2[1]; v2[2] = p3[2]-p2[2]; v3[0] = p1[0]-p3[0]; v3[1] = p1[1]-p3[1]; v3[2] = p1[2]-p3[2]; float a = v1.magnitude(); float b = v2.magnitude(); float c = v3.magnitude(); float r = a*b*c/std::sqrt((a+b+c)*(a+b-c)*(b+c-a)*(a-b+c)); // radius of triangle via Heron's formula (area of triangle) vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); if (deleteFibers && rInsertNextCell(container); container = vtkSmartPointer::New(); } else if (j==numPoints-3) { id = vtkNewPoints->InsertNextPoint(p2); container->GetPointIds()->InsertNextId(id); id = vtkNewPoints->InsertNextPoint(p3); container->GetPointIds()->InsertNextId(id); vtkNewCells->InsertNextCell(container); } } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } bool mitk::FiberBundle::RemoveShortFibers(float lengthInMM) { MITK_INFO << "Removing short fibers"; if (lengthInMM<=0 || lengthInMMm_MaxFiberLength) // can't remove all fibers { MITK_WARN << "Process aborted. No fibers would be left!"; return false; } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); float min = m_MaxFiberLength; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)>=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); if (m_FiberLengths.at(i)GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } bool mitk::FiberBundle::RemoveLongFibers(float lengthInMM) { if (lengthInMM<=0 || lengthInMM>m_MaxFiberLength) return true; if (lengthInMM vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Removing long fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)<=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } void mitk::FiberBundle::ResampleSpline(float pointDistance, double tension, double continuity, double bias ) { if (pointDistance<=0) return; vtkSmartPointer vtkSmoothPoints = vtkSmartPointer::New(); //in smoothpoints the interpolated points representing a fiber are stored. //in vtkcells all polylines are stored, actually all id's of them are stored vtkSmartPointer vtkSmoothCells = vtkSmartPointer::New(); //cellcontainer for smoothed lines MITK_INFO << "Smoothing fibers"; vtkSmartPointer newFiberWeights = vtkSmartPointer::New(); newFiberWeights->SetName("FIBER_WEIGHTS"); newFiberWeights->SetNumberOfValues(m_NumFibers); std::vector< vtkSmartPointer > resampled_streamlines; resampled_streamlines.resize(m_NumFibers); boost::progress_display disp(m_NumFibers); #pragma omp parallel for for (int i=0; i newPoints = vtkSmartPointer::New(); float length = 0; #pragma omp critical { length = m_FiberLengths.at(i); ++disp; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jInsertNextPoint(points->GetPoint(j)); } int sampling = std::ceil(length/pointDistance); vtkSmartPointer xSpline = vtkSmartPointer::New(); vtkSmartPointer ySpline = vtkSmartPointer::New(); vtkSmartPointer zSpline = vtkSmartPointer::New(); xSpline->SetDefaultBias(bias); xSpline->SetDefaultTension(tension); xSpline->SetDefaultContinuity(continuity); ySpline->SetDefaultBias(bias); ySpline->SetDefaultTension(tension); ySpline->SetDefaultContinuity(continuity); zSpline->SetDefaultBias(bias); zSpline->SetDefaultTension(tension); zSpline->SetDefaultContinuity(continuity); vtkSmartPointer spline = vtkSmartPointer::New(); spline->SetXSpline(xSpline); spline->SetYSpline(ySpline); spline->SetZSpline(zSpline); spline->SetPoints(newPoints); vtkSmartPointer functionSource = vtkSmartPointer::New(); functionSource->SetParametricFunction(spline); functionSource->SetUResolution(sampling); functionSource->SetVResolution(sampling); functionSource->SetWResolution(sampling); functionSource->Update(); vtkPolyData* outputFunction = functionSource->GetOutput(); vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber vtkSmartPointer smoothLine = vtkSmartPointer::New(); #pragma omp critical { for (int j=0; jGetNumberOfPoints(); j++) { vtkIdType id = vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j)); smoothLine->GetPointIds()->InsertNextId(id); } resampled_streamlines[i] = smoothLine; } } for (auto container : resampled_streamlines) { vtkSmoothCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkSmoothPoints); m_FiberPolyData->SetLines(vtkSmoothCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::ResampleSpline(float pointDistance) { ResampleSpline(pointDistance, 0, 0, 0 ); } unsigned long mitk::FiberBundle::GetNumberOfPoints() const { unsigned long points = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); points += cell->GetNumberOfPoints(); } return points; } void mitk::FiberBundle::Compress(float error) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Compressing fibers"; unsigned long numRemovedPoints = 0; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); vtkSmartPointer newFiberWeights = vtkSmartPointer::New(); newFiberWeights->SetName("FIBER_WEIGHTS"); newFiberWeights->SetNumberOfValues(m_NumFibers); #pragma omp parallel for for (int i=0; iGetNumberOfCells(); i++) { std::vector< vnl_vector_fixed< double, 3 > > vertices; float weight = 1; #pragma omp critical { ++disp; weight = m_FiberWeights->GetValue(i); vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< double, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; vertices.push_back(candV); } } // calculate curvatures int numPoints = vertices.size(); std::vector< int > removedPoints; removedPoints.resize(numPoints, 0); removedPoints[0]=-1; removedPoints[numPoints-1]=-1; vtkSmartPointer container = vtkSmartPointer::New(); int remCounter = 0; bool pointFound = true; while (pointFound) { pointFound = false; double minError = error; int removeIndex = -1; for (unsigned int j=0; j candV = vertices.at(j); int validP = -1; vnl_vector_fixed< double, 3 > pred; for (int k=j-1; k>=0; k--) if (removedPoints[k]<=0) { pred = vertices.at(k); validP = k; break; } int validS = -1; vnl_vector_fixed< double, 3 > succ; for (int k=j+1; k=0 && validS>=0) { double a = (candV-pred).magnitude(); double b = (candV-succ).magnitude(); double c = (pred-succ).magnitude(); double s=0.5*(a+b+c); double hc=(2.0/c)*sqrt(fabs(s*(s-a)*(s-b)*(s-c))); if (hcInsertNextPoint(vertices.at(j).data_block()); container->GetPointIds()->InsertNextId(id); } } } #pragma omp critical { newFiberWeights->SetValue(vtkNewCells->GetNumberOfCells(), weight); numRemovedPoints += remCounter; vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()>0) { MITK_INFO << "Removed points: " << numRemovedPoints; SetFiberWeights(newFiberWeights); m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } } void mitk::FiberBundle::ResampleToNumPoints(unsigned int targetPoints) { if (targetPoints<2) mitkThrow() << "Minimum two points required for resampling!"; MITK_INFO << "Resampling fibers (number of points " << targetPoints << ")"; bool unequal_fibs = true; while (unequal_fibs) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); vtkSmartPointer newFiberWeights = vtkSmartPointer::New(); newFiberWeights->SetName("FIBER_WEIGHTS"); newFiberWeights->SetNumberOfValues(m_NumFibers); unequal_fibs = false; //#pragma omp parallel for for (int i=0; iGetNumberOfCells(); i++) { std::vector< vnl_vector_fixed< double, 3 > > vertices; float weight = 1; double seg_len = 0; //#pragma omp critical { weight = m_FiberWeights->GetValue(i); vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); if ((unsigned int)numPoints!=targetPoints) seg_len = this->GetFiberLength(i)/(targetPoints-1);; vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< double, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; vertices.push_back(candV); } } vtkSmartPointer container = vtkSmartPointer::New(); vnl_vector_fixed< double, 3 > lastV = vertices.at(0); //#pragma omp critical { vtkIdType id = vtkNewPoints->InsertNextPoint(lastV.data_block()); container->GetPointIds()->InsertNextId(id); } for (unsigned int j=1; j vec = vertices.at(j) - lastV; double new_dist = vec.magnitude(); if (new_dist >= seg_len && seg_len>0) { vnl_vector_fixed< double, 3 > newV = lastV; if ( new_dist-seg_len <= mitk::eps ) { vec.normalize(); newV += vec * seg_len; } else { // intersection between sphere (radius 'pointDistance', center 'lastV') and line (direction 'd' and point 'p') vnl_vector_fixed< double, 3 > p = vertices.at(j-1); vnl_vector_fixed< double, 3 > d = vertices.at(j) - p; double a = d[0]*d[0] + d[1]*d[1] + d[2]*d[2]; double b = 2 * (d[0] * (p[0] - lastV[0]) + d[1] * (p[1] - lastV[1]) + d[2] * (p[2] - lastV[2])); double c = (p[0] - lastV[0])*(p[0] - lastV[0]) + (p[1] - lastV[1])*(p[1] - lastV[1]) + (p[2] - lastV[2])*(p[2] - lastV[2]) - seg_len*seg_len; double v1 =(-b + std::sqrt(b*b-4*a*c))/(2*a); double v2 =(-b - std::sqrt(b*b-4*a*c))/(2*a); if (v1>0) newV = p + d * v1; else if (v2>0) newV = p + d * v2; else MITK_INFO << "ERROR1 - linear resampling"; j--; } //#pragma omp critical { vtkIdType id = vtkNewPoints->InsertNextPoint(newV.data_block()); container->GetPointIds()->InsertNextId(id); } lastV = newV; } else if ( (j==vertices.size()-1 && new_dist>0.0001) || seg_len==0) { //#pragma omp critical { vtkIdType id = vtkNewPoints->InsertNextPoint(vertices.at(j).data_block()); container->GetPointIds()->InsertNextId(id); } } } //#pragma omp critical { newFiberWeights->SetValue(vtkNewCells->GetNumberOfCells(), weight); vtkNewCells->InsertNextCell(container); if (container->GetNumberOfPoints()!=targetPoints) unequal_fibs = true; } } if (vtkNewCells->GetNumberOfCells()>0) { SetFiberWeights(newFiberWeights); m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } } } void mitk::FiberBundle::ResampleLinear(double pointDistance) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Resampling fibers (linear)"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); vtkSmartPointer newFiberWeights = vtkSmartPointer::New(); newFiberWeights->SetName("FIBER_WEIGHTS"); newFiberWeights->SetNumberOfValues(m_NumFibers); std::vector< vtkSmartPointer > resampled_streamlines; resampled_streamlines.resize(m_FiberPolyData->GetNumberOfCells()); #pragma omp parallel for for (int i=0; iGetNumberOfCells(); i++) { std::vector< vnl_vector_fixed< double, 3 > > vertices; #pragma omp critical { ++disp; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< double, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; vertices.push_back(candV); } } vtkSmartPointer container = vtkSmartPointer::New(); vnl_vector_fixed< double, 3 > lastV = vertices.at(0); #pragma omp critical { vtkIdType id = vtkNewPoints->InsertNextPoint(lastV.data_block()); container->GetPointIds()->InsertNextId(id); } for (unsigned int j=1; j vec = vertices.at(j) - lastV; double new_dist = vec.magnitude(); if (new_dist >= pointDistance) { vnl_vector_fixed< double, 3 > newV = lastV; if ( new_dist-pointDistance <= mitk::eps ) { vec.normalize(); newV += vec * pointDistance; } else { // intersection between sphere (radius 'pointDistance', center 'lastV') and line (direction 'd' and point 'p') vnl_vector_fixed< double, 3 > p = vertices.at(j-1); vnl_vector_fixed< double, 3 > d = vertices.at(j) - p; double a = d[0]*d[0] + d[1]*d[1] + d[2]*d[2]; double b = 2 * (d[0] * (p[0] - lastV[0]) + d[1] * (p[1] - lastV[1]) + d[2] * (p[2] - lastV[2])); double c = (p[0] - lastV[0])*(p[0] - lastV[0]) + (p[1] - lastV[1])*(p[1] - lastV[1]) + (p[2] - lastV[2])*(p[2] - lastV[2]) - pointDistance*pointDistance; double v1 =(-b + std::sqrt(b*b-4*a*c))/(2*a); double v2 =(-b - std::sqrt(b*b-4*a*c))/(2*a); if (v1>0) newV = p + d * v1; else if (v2>0) newV = p + d * v2; else MITK_INFO << "ERROR1 - linear resampling"; j--; } #pragma omp critical { vtkIdType id = vtkNewPoints->InsertNextPoint(newV.data_block()); container->GetPointIds()->InsertNextId(id); } lastV = newV; } else if (j==vertices.size()-1 && new_dist>0.0001) { #pragma omp critical { vtkIdType id = vtkNewPoints->InsertNextPoint(vertices.at(j).data_block()); container->GetPointIds()->InsertNextId(id); } } } #pragma omp critical { resampled_streamlines[i] = container; } } for (auto container : resampled_streamlines) { vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()>0) { m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } } // reapply selected colorcoding in case PolyData structure has changed bool mitk::FiberBundle::Equals(mitk::FiberBundle* fib, double eps) { if (fib==nullptr) { MITK_INFO << "Reference bundle is nullptr!"; return false; } if (m_NumFibers!=fib->GetNumFibers()) { MITK_INFO << "Unequal number of fibers!"; MITK_INFO << m_NumFibers << " vs. " << fib->GetNumFibers(); return false; } for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cell2 = fib->GetFiberPolyData()->GetCell(i); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (numPoints2!=numPoints) { MITK_INFO << "Unequal number of points in fiber " << i << "!"; MITK_INFO << numPoints2 << " vs. " << numPoints; return false; } for (int j=0; jGetPoint(j); double* p2 = points2->GetPoint(j); if (fabs(p1[0]-p2[0])>eps || fabs(p1[1]-p2[1])>eps || fabs(p1[2]-p2[2])>eps) { MITK_INFO << "Unequal points in fiber " << i << " at position " << j << "!"; MITK_INFO << "p1: " << p1[0] << ", " << p1[1] << ", " << p1[2]; MITK_INFO << "p2: " << p2[0] << ", " << p2[1] << ", " << p2[2]; return false; } } } return true; } void mitk::FiberBundle::PrintSelf(std::ostream &os, itk::Indent indent) const { os << indent << this->GetNameOfClass() << ":\n"; os << indent << "Number of fibers: " << this->GetNumFibers() << std::endl; os << indent << "Min. fiber length: " << this->GetMinFiberLength() << std::endl; os << indent << "Max. fiber length: " << this->GetMaxFiberLength() << std::endl; os << indent << "Mean fiber length: " << this->GetMeanFiberLength() << std::endl; os << indent << "Median fiber length: " << this->GetMedianFiberLength() << std::endl; os << indent << "STDEV fiber length: " << this->GetLengthStDev() << std::endl; os << indent << "Number of points: " << this->GetNumberOfPoints() << std::endl; Superclass::PrintSelf(os, indent); } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void mitk::FiberBundle::UpdateOutputInformation() { } void mitk::FiberBundle::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::FiberBundle::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::FiberBundle::VerifyRequestedRegion() { return true; } void mitk::FiberBundle::SetRequestedRegion(const itk::DataObject* ) { } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.h index 7751e2ee65..c679aa4480 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.h @@ -1,181 +1,182 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_FiberBundle_H #define _MITK_FiberBundle_H //includes for MITK datastructure #include #include #include #include #include #include #include //includes storing fiberdata #include #include #include #include #include #include - +#include namespace mitk { /** * \brief Base Class for Fiber Bundles; */ class MITKFIBERTRACKING_EXPORT FiberBundle : public BaseData { public: typedef itk::Image ItkUcharImgType; // fiber colorcodings static const char* FIBER_ID_ARRAY; virtual void UpdateOutputInformation() override; virtual void SetRequestedRegionToLargestPossibleRegion() override; virtual bool RequestedRegionIsOutsideOfTheBufferedRegion() override; virtual bool VerifyRequestedRegion() override; virtual void SetRequestedRegion(const itk::DataObject*) override; mitkClassMacro( FiberBundle, BaseData ) itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkNewMacro1Param(Self, vtkSmartPointer) // custom constructor // colorcoding related methods void ColorFibersByFiberWeights(bool opacity, bool normalize); void ColorFibersByCurvature(bool opacity, bool normalize); void ColorFibersByScalarMap(mitk::Image::Pointer, bool opacity, bool normalize); template void ColorFibersByScalarMap(const mitk::PixelType pixelType, mitk::Image::Pointer, bool opacity, bool normalize); void ColorFibersByOrientation(); void SetFiberOpacity(vtkDoubleArray *FAValArray); void ResetFiberOpacity(); void SetFiberColors(vtkSmartPointer fiberColors); void SetFiberColors(float r, float g, float b, float alpha=255); vtkSmartPointer GetFiberColors() const { return m_FiberColors; } // fiber compression void Compress(float error = 0.0); // fiber resampling void ResampleSpline(float pointDistance=1); void ResampleSpline(float pointDistance, double tension, double continuity, double bias ); void ResampleLinear(double pointDistance=1); void ResampleToNumPoints(unsigned int targetPoints); mitk::FiberBundle::Pointer FilterByWeights(float weight_thr, bool invert=false); bool RemoveShortFibers(float lengthInMM); bool RemoveLongFibers(float lengthInMM); bool ApplyCurvatureThreshold(float minRadius, bool deleteFibers); void MirrorFibers(unsigned int axis); void RotateAroundAxis(double x, double y, double z); void TranslateFibers(double x, double y, double z); void ScaleFibers(double x, double y, double z, bool subtractCenter=true); void TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz); + void TransformFibers(itk::ScalableAffineTransform< mitk::ScalarType >::Pointer transform); void RemoveDir(vnl_vector_fixed dir, double threshold); itk::Point TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz); itk::Matrix< double, 3, 3 > TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz); // add/subtract fibers FiberBundle::Pointer AddBundle(FiberBundle* fib); mitk::FiberBundle::Pointer AddBundles(std::vector< mitk::FiberBundle::Pointer > fibs); FiberBundle::Pointer SubtractBundle(FiberBundle* fib); // fiber subset extraction FiberBundle::Pointer ExtractFiberSubset(DataNode *roi, DataStorage* storage); std::vector ExtractFiberIdSubset(DataNode* roi, DataStorage* storage); FiberBundle::Pointer RemoveFibersOutside(ItkUcharImgType* mask, bool invert=false); float GetOverlap(ItkUcharImgType* mask, bool do_resampling); mitk::FiberBundle::Pointer SubsampleFibers(float factor); // get/set data float GetFiberLength(int index) const { return m_FiberLengths.at(index); } vtkSmartPointer GetFiberWeights() const { return m_FiberWeights; } float GetFiberWeight(unsigned int fiber) const; void SetFiberWeights(float newWeight); void SetFiberWeight(unsigned int fiber, float weight); void SetFiberWeights(vtkSmartPointer weights); void SetFiberPolyData(vtkSmartPointer, bool updateGeometry = true); vtkSmartPointer GetFiberPolyData() const; itkGetConstMacro( NumFibers, int) //itkGetMacro( FiberSampling, int) itkGetConstMacro( MinFiberLength, float ) itkGetConstMacro( MaxFiberLength, float ) itkGetConstMacro( MeanFiberLength, float ) itkGetConstMacro( MedianFiberLength, float ) itkGetConstMacro( LengthStDev, float ) itkGetConstMacro( UpdateTime2D, itk::TimeStamp ) itkGetConstMacro( UpdateTime3D, itk::TimeStamp ) void RequestUpdate2D(){ m_UpdateTime2D.Modified(); } void RequestUpdate3D(){ m_UpdateTime3D.Modified(); } void RequestUpdate(){ m_UpdateTime2D.Modified(); m_UpdateTime3D.Modified(); } unsigned long GetNumberOfPoints() const; // copy fiber bundle mitk::FiberBundle::Pointer GetDeepCopy(); // compare fiber bundles bool Equals(FiberBundle* fib, double eps=0.01); itkSetMacro( ReferenceGeometry, mitk::BaseGeometry::Pointer ) itkGetConstMacro( ReferenceGeometry, mitk::BaseGeometry::Pointer ) vtkSmartPointer GeneratePolyDataByIds(std::vector fiberIds, vtkSmartPointer weights); protected: FiberBundle( vtkPolyData* fiberPolyData = nullptr ); virtual ~FiberBundle(); void GenerateFiberIds(); itk::Point GetItkPoint(double point[3]); void UpdateFiberGeometry(); virtual void PrintSelf(std::ostream &os, itk::Indent indent) const override; private: // actual fiber container vtkSmartPointer m_FiberPolyData; // contains fiber ids vtkSmartPointer m_FiberIdDataSet; int m_NumFibers; vtkSmartPointer m_FiberColors; vtkSmartPointer m_FiberWeights; std::vector< float > m_FiberLengths; float m_MinFiberLength; float m_MaxFiberLength; float m_MeanFiberLength; float m_MedianFiberLength; float m_LengthStDev; itk::TimeStamp m_UpdateTime2D; itk::TimeStamp m_UpdateTime3D; mitk::BaseGeometry::Pointer m_ReferenceGeometry; }; } // namespace mitk #endif /* _MITK_FiberBundle_H */ diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractSimilarTracts.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractSimilarTracts.cpp index fd07b7bac2..a312dd42ac 100644 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractSimilarTracts.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractSimilarTracts.cpp @@ -1,240 +1,238 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include typedef itksys::SystemTools ist; typedef itk::Image ItkFloatImgType; mitk::FiberBundle::Pointer LoadFib(std::string filename) { std::vector fibInfile = mitk::IOUtil::Load(filename); if( fibInfile.empty() ) std::cout << "File " << filename << " could not be read!"; mitk::BaseData::Pointer baseData = fibInfile.at(0); return dynamic_cast(baseData.GetPointer()); } ItkFloatImgType::Pointer LoadItkImage(const std::string& filename) { mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(filename)[0].GetPointer()); ItkFloatImgType::Pointer itkMask = ItkFloatImgType::New(); mitk::CastToItkImage(img, itkMask); return itkMask; } /*! \brief Spatially cluster fibers */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Extract Similar Tracts"); parser.setCategory("Fiber Tracking Evaluation"); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("", "i", mitkCommandLineParser::InputFile, "Input:", "input fiber bundle (.fib, .trk, .tck)", us::Any(), false); parser.addArgument("ref_tracts", "", mitkCommandLineParser::StringList, "Ref. Tracts:", "reference tracts (.fib, .trk, .tck)", us::Any(), false); parser.addArgument("ref_masks", "", mitkCommandLineParser::StringList, "Ref. Masks:", "reference bundle masks", us::Any()); parser.addArgument("", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("distance", "", mitkCommandLineParser::Int, "Distance:", "", 10); parser.addArgument("metric", "", mitkCommandLineParser::String, "Metric:", ""); parser.addArgument("subsample", "", mitkCommandLineParser::Float, "Subsampling factor:", "Only use specified fraction of input fibers", 1.0); std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; std::string in_fib = us::any_cast(parsedArgs["i"]); std::string out_root = us::any_cast(parsedArgs["o"]); mitkCommandLineParser::StringContainerType ref_bundle_files = us::any_cast(parsedArgs["ref_tracts"]); mitkCommandLineParser::StringContainerType ref_mask_files; if (parsedArgs.count("ref_masks")) ref_mask_files = us::any_cast(parsedArgs["ref_masks"]); if (ref_mask_files.size()>0 && ref_mask_files.size()!=ref_bundle_files.size()) { MITK_INFO << "If reference masks are used, there has to be one mask per reference tract."; return EXIT_FAILURE; } int distance = 10; if (parsedArgs.count("distance")) distance = us::any_cast(parsedArgs["distance"]); std::string metric = "EU_MEAN"; if (parsedArgs.count("metric")) metric = us::any_cast(parsedArgs["metric"]); float subsample = 1.0; if (parsedArgs.count("subsample")) subsample = us::any_cast(parsedArgs["subsample"]); try { mitk::FiberBundle::Pointer fib = LoadFib(in_fib); std::srand(0); if (subsample<1.0) fib = fib->SubsampleFibers(subsample); mitk::FiberBundle::Pointer resampled_fib = fib->GetDeepCopy(); resampled_fib->ResampleToNumPoints(12); std::vector< mitk::FiberBundle::Pointer > ref_fibs; std::vector< ItkFloatImgType::Pointer > ref_masks; for (std::size_t i=0; i distances; distances.push_back(distance); mitk::FiberBundle::Pointer anchor_tractogram = mitk::FiberBundle::New(nullptr); unsigned int c = 0; for (auto ref_fib : ref_fibs) { MITK_INFO << "Extracting " << ist::GetFilenameName(ref_bundle_files.at(c)); // std::streambuf *old = cout.rdbuf(); // <-- save // std::stringstream ss; // std::cout.rdbuf (ss.rdbuf()); // <-- redirect try { itk::TractClusteringFilter::Pointer segmenter = itk::TractClusteringFilter::New(); // calculate centroids from reference bundle { MITK_INFO << "TEST 1"; itk::TractClusteringFilter::Pointer clusterer = itk::TractClusteringFilter::New(); clusterer->SetDistances({10,20,30}); clusterer->SetTractogram(ref_fib); clusterer->SetMetrics({new mitk::ClusteringMetricEuclideanStd()}); clusterer->SetMergeDuplicateThreshold(0.0); clusterer->Update(); MITK_INFO << "TEST 2"; std::vector tracts = clusterer->GetOutCentroids(); ref_fib = mitk::FiberBundle::New(nullptr); ref_fib = ref_fib->AddBundles(tracts); - MITK_INFO << "TEST 3"; mitk::IOUtil::Save(ref_fib, out_root + "centroids_" + ist::GetFilenameName(ref_bundle_files.at(c))); segmenter->SetInCentroids(ref_fib); - MITK_INFO << "TEST 4"; } // segment tract segmenter->SetFilterMask(ref_masks.at(c)); segmenter->SetOverlapThreshold(0.8); segmenter->SetDistances(distances); segmenter->SetTractogram(resampled_fib); segmenter->SetMergeDuplicateThreshold(0.0); segmenter->SetDoResampling(false); if (metric=="EU_MEAN") segmenter->SetMetrics({new mitk::ClusteringMetricEuclideanMean()}); else if (metric=="EU_STD") segmenter->SetMetrics({new mitk::ClusteringMetricEuclideanStd()}); else if (metric=="EU_MAX") segmenter->SetMetrics({new mitk::ClusteringMetricEuclideanMax()}); segmenter->Update(); std::vector< std::vector< long > > clusters = segmenter->GetOutFiberIndices(); if (clusters.size()>0) { vtkSmartPointer weights = vtkSmartPointer::New(); mitk::FiberBundle::Pointer result = mitk::FiberBundle::New(nullptr); std::vector< mitk::FiberBundle::Pointer > result_fibs; for (unsigned int cluster_index=0; cluster_indexGeneratePolyDataByIds(clusters.at(cluster_index), weights))); result = result->AddBundles(result_fibs); anchor_tractogram = anchor_tractogram->AddBundle(result); mitk::IOUtil::Save(result, out_root + "anchor_" + ist::GetFilenameName(ref_bundle_files.at(c))); fib = mitk::FiberBundle::New(fib->GeneratePolyDataByIds(clusters.back(), weights)); resampled_fib = mitk::FiberBundle::New(resampled_fib->GeneratePolyDataByIds(clusters.back(), weights)); } } catch(itk::ExceptionObject& excpt) { MITK_INFO << "Exception while processing " << ist::GetFilenameName(ref_bundle_files.at(c)); MITK_INFO << excpt.GetDescription(); } catch(std::exception& excpt) { MITK_INFO << "Exception while processing " << ist::GetFilenameName(ref_bundle_files.at(c)); MITK_INFO << excpt.what(); } // std::cout.rdbuf (old); // <-- restore if (fib->GetNumFibers()==0) break; ++c; } MITK_INFO << "Streamlines in anchor tractogram: " << anchor_tractogram->GetNumFibers(); mitk::IOUtil::Save(anchor_tractogram, out_root + "anchor_tractogram.trk"); MITK_INFO << "Streamlines remaining in candidate tractogram: " << fib->GetNumFibers(); mitk::IOUtil::Save(fib, out_root + "candidate_tractogram.trk"); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/MatchPointRegistration/mitkMAPRegistrationWrapperObjectFactory.cpp b/Modules/MatchPointRegistration/mitkMAPRegistrationWrapperObjectFactory.cpp index dfe93f40fc..36dd9d4278 100644 --- a/Modules/MatchPointRegistration/mitkMAPRegistrationWrapperObjectFactory.cpp +++ b/Modules/MatchPointRegistration/mitkMAPRegistrationWrapperObjectFactory.cpp @@ -1,129 +1,127 @@ /*=================================================================== 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 "mitkMAPRegistrationWrapperObjectFactory.h" #include #include #include #include "mitkRegistrationWrapperMapper2D.h" #include "mitkRegistrationWrapperMapper3D.h" #include "mitkMAPRegistrationWrapper.h" typedef std::multimap MultimapType; mitk::MAPRegistrationWrapperObjectFactory::MAPRegistrationWrapperObjectFactory() : CoreObjectFactoryBase() { static bool alreadyDone = false; if (!alreadyDone) { - MITK_INFO << "MAPRegistrationWrapperObjectFactory c'tor" << std::endl; - alreadyDone = true; } } mitk::MAPRegistrationWrapperObjectFactory::~MAPRegistrationWrapperObjectFactory() { } mitk::Mapper::Pointer mitk::MAPRegistrationWrapperObjectFactory:: CreateMapper(mitk::DataNode* node, MapperSlotId slotId) { mitk::Mapper::Pointer newMapper=nullptr; if ( slotId == mitk::BaseRenderer::Standard2D ) { std::string classname("MAPRegistrationWrapper"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::MITKRegistrationWrapperMapper2D::New(); newMapper->SetDataNode(node); } } else if ( slotId == mitk::BaseRenderer::Standard3D ) { std::string classname("MAPRegistrationWrapper"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::MITKRegistrationWrapperMapper3D::New(); newMapper->SetDataNode(node); } } return newMapper; }; void mitk::MAPRegistrationWrapperObjectFactory::SetDefaultProperties(mitk::DataNode* node) { if(node==nullptr) return; mitk::DataNode::Pointer nodePointer = node; if(node->GetData() ==nullptr) return; if( dynamic_cast(node->GetData())!=nullptr ) { mitk::MITKRegistrationWrapperMapperBase::SetDefaultProperties(node); } } const char* mitk::MAPRegistrationWrapperObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); }; mitk::CoreObjectFactoryBase::MultimapType mitk::MAPRegistrationWrapperObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } const char* mitk::MAPRegistrationWrapperObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::MAPRegistrationWrapperObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } struct RegisterMAPRegistrationWrapperObjectFactoryHelper{ RegisterMAPRegistrationWrapperObjectFactoryHelper() : m_Factory( mitk::MAPRegistrationWrapperObjectFactory::New() ) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory ); } ~RegisterMAPRegistrationWrapperObjectFactoryHelper() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory ); } mitk::MAPRegistrationWrapperObjectFactory::Pointer m_Factory; }; static RegisterMAPRegistrationWrapperObjectFactoryHelper registerMITKRegistrationWrapperIOFactoryHelper; diff --git a/Modules/MatchPointRegistration/mitkRegEvaluationObjectFactory.cpp b/Modules/MatchPointRegistration/mitkRegEvaluationObjectFactory.cpp index 1faecb49bb..5002964542 100644 --- a/Modules/MatchPointRegistration/mitkRegEvaluationObjectFactory.cpp +++ b/Modules/MatchPointRegistration/mitkRegEvaluationObjectFactory.cpp @@ -1,109 +1,107 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRegEvaluationObjectFactory.h" #include #include #include #include "mitkRegEvaluationMapper2D.h" typedef std::multimap MultimapType; mitk::RegEvaluationObjectFactory::RegEvaluationObjectFactory() : CoreObjectFactoryBase() { static bool alreadyDone = false; if (!alreadyDone) { - MITK_INFO << "RegEvaluationObjectFactory c'tor" << std::endl; - alreadyDone = true; } } mitk::RegEvaluationObjectFactory::~RegEvaluationObjectFactory() { } mitk::Mapper::Pointer mitk::RegEvaluationObjectFactory:: CreateMapper(mitk::DataNode* node, MapperSlotId slotId) { mitk::Mapper::Pointer newMapper = nullptr; if ( slotId == mitk::BaseRenderer::Standard2D ) { std::string classname("RegEvaluationObject"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::RegEvaluationMapper2D::New(); newMapper->SetDataNode(node); } } return newMapper; }; void mitk::RegEvaluationObjectFactory::SetDefaultProperties(mitk::DataNode*) { } const char* mitk::RegEvaluationObjectFactory::GetFileExtensions() { //return empty (dummy) extension string return m_FileExtensions.c_str(); }; mitk::CoreObjectFactoryBase::MultimapType mitk::RegEvaluationObjectFactory::GetFileExtensionsMap() { return mitk::CoreObjectFactoryBase::MultimapType(); } const char* mitk::RegEvaluationObjectFactory::GetSaveFileExtensions() { //return empty (dummy) extension string return m_FileExtensions.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::RegEvaluationObjectFactory::GetSaveFileExtensionsMap() { return mitk::CoreObjectFactoryBase::MultimapType(); } void mitk::RegEvaluationObjectFactory::RegisterIOFactories() { } struct RegisterRegEvaluationObjectFactoryHelper{ RegisterRegEvaluationObjectFactoryHelper() : m_Factory( mitk::RegEvaluationObjectFactory::New() ) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory ); } ~RegisterRegEvaluationObjectFactoryHelper() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory ); } mitk::RegEvaluationObjectFactory::Pointer m_Factory; }; static RegisterRegEvaluationObjectFactoryHelper registerMITKRegistrationWrapperIOFactoryHelper; diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index eeed58f1f1..9ccec01655 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,100 +1,101 @@ # Plug-ins must be ordered according to their dependencies set(MITK_PLUGINS org.blueberry.core.runtime:ON org.blueberry.core.expressions:OFF org.blueberry.core.commands:OFF org.blueberry.core.jobs:OFF org.blueberry.ui.qt:OFF org.blueberry.ui.qt.help:ON org.blueberry.ui.qt.log:ON org.blueberry.ui.qt.objectinspector:OFF #org.blueberry.test:ON #org.blueberry.uitest:ON #Testing/org.blueberry.core.runtime.tests:ON #Testing/org.blueberry.osgi.tests:ON org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.dicominspector:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.diffusionimaging.connectomics:OFF org.mitk.gui.qt.diffusionimaging.denoising:OFF org.mitk.gui.qt.diffusionimaging.fiberfox:OFF org.mitk.gui.qt.diffusionimaging.fiberprocessing:OFF org.mitk.gui.qt.diffusionimaging.ivim:OFF org.mitk.gui.qt.diffusionimaging.odfpeaks:OFF org.mitk.gui.qt.diffusionimaging.partialvolume:OFF org.mitk.gui.qt.diffusionimaging.preprocessing:OFF org.mitk.gui.qt.diffusionimaging.reconstruction:OFF org.mitk.gui.qt.diffusionimaging.registration:OFF org.mitk.gui.qt.diffusionimaging.tbss:OFF org.mitk.gui.qt.diffusionimaging.tractography:OFF + org.mitk.gui.qt.diffusionimaging.python:OFF org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.lasercontrol:OFF org.mitk.gui.qt.openigtlink:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.renderwindowmanager:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.photoacoustics.pausviewer:OFF org.mitk.gui.qt.photoacoustics.imageprocessing:OFF org.mitk.gui.qt.photoacoustics.simulation:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF org.mitk.gui.qt.igt.app.echotrack:OFF org.mitk.gui.qt.spectrocamrecorder:OFF org.mitk.gui.qt.classificationsegmentation:OFF org.mitk.gui.qt.overlaymanager:OFF org.mitk.gui.qt.igt.app.hummelprotocolmeasurements:OFF org.mitk.gui.qt.multilabelsegmentation:OFF org.mitk.matchpoint.core.helper:OFF org.mitk.gui.qt.matchpoint.algorithm.browser:OFF org.mitk.gui.qt.matchpoint.algorithm.control:OFF org.mitk.gui.qt.matchpoint.algorithm.batch:OFF org.mitk.gui.qt.matchpoint.mapper:OFF org.mitk.gui.qt.matchpoint.framereg:OFF org.mitk.gui.qt.matchpoint.visualizer:OFF org.mitk.gui.qt.matchpoint.evaluator:OFF org.mitk.gui.qt.matchpoint.manipulator:OFF org.mitk.gui.qt.cest:OFF ) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/manifest_headers.cmake index 5b0e19249f..95d38debb1 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK Connectomics") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/manifest_headers.cmake index ccf353c8c9..cd38bf46fc 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK DWI Denoising") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/manifest_headers.cmake index 2e376675b7..75fc472cfc 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK Fiberfox") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/manifest_headers.cmake index 074d5c67ef..2f6a8b321e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK Fiber Processing") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/manifest_headers.cmake index c410e854d2..3385c26aaf 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK IVIM") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/manifest_headers.cmake index d9d2df538c..01c8d1dc61 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK ODF Peaks") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/manifest_headers.cmake index dbf79c0d1e..a7e7171515 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK Partial Volume Analysis") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/CMakeLists.txt b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/CMakeLists.txt index b80f3e0fb3..bcbe770470 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/CMakeLists.txt @@ -1,14 +1,10 @@ -if(MITK_USE_Python) - # The project name must correspond to the directory name of your plug-in # and must not contain periods. project(org_mitk_gui_qt_diffusionimaging_preprocessing) mitk_create_plugin( EXPORT_DIRECTIVE DIFFUSIONIMAGING_PREPROCESSING_EXPORT EXPORTED_INCLUDE_SUFFIXES src - MODULE_DEPENDS MitkDiffusionCore MitkPython MitkQtPython + MODULE_DEPENDS MitkDiffusionCore PACKAGE_DEPENDS Qt5|Network ) - -endif() diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/files.cmake index 61c991d6e5..0009a93c61 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/files.cmake @@ -1,45 +1,42 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkPreprocessingView.cpp - QmitkBrainExtractionView.cpp ) set(UI_FILES src/internal/QmitkPreprocessingViewControls.ui - src/internal/QmitkBrainExtractionViewControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h src/internal/QmitkPreprocessingView.h - src/internal/QmitkBrainExtractionView.h ) set(CACHED_RESOURCE_FILES plugin.xml resources/preprocessing.png resources/dwi2.png ) set(QRC_FILES ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/manifest_headers.cmake index b9885bba96..223766b673 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK Preprocessing") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/plugin.xml index c441b6d060..6fe5a3812b 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/plugin.xml @@ -1,25 +1,17 @@ - - - - diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp index aafe6330b1..baf96673ff 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp @@ -1,44 +1,42 @@ /*=================================================================== 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 "mitkPluginActivator.h" #include "src/internal/QmitkPreprocessingView.h" -#include "src/internal/QmitkBrainExtractionView.h" #include ctkPluginContext* mitk::PluginActivator::m_Context = nullptr; US_INITIALIZE_MODULE ctkPluginContext* mitk::PluginActivator::GetContext() { return m_Context; } void mitk::PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkPreprocessingView, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkBrainExtractionView, context) m_Context = context; } void mitk::PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) m_Context = nullptr; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/CMakeLists.txt b/Plugins/org.mitk.gui.qt.diffusionimaging.python/CMakeLists.txt similarity index 85% copy from Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/CMakeLists.txt copy to Plugins/org.mitk.gui.qt.diffusionimaging.python/CMakeLists.txt index b80f3e0fb3..a0feafa1d4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/CMakeLists.txt @@ -1,14 +1,14 @@ if(MITK_USE_Python) # The project name must correspond to the directory name of your plug-in # and must not contain periods. -project(org_mitk_gui_qt_diffusionimaging_preprocessing) +project(org_mitk_gui_qt_diffusionimaging_python) mitk_create_plugin( EXPORT_DIRECTIVE DIFFUSIONIMAGING_PREPROCESSING_EXPORT EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkDiffusionCore MitkPython MitkQtPython PACKAGE_DEPENDS Qt5|Network ) endif() diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.python/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..c0a9180de7 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_diffusionimaging_preprocessing org.mitk.gui.qt.diffusionimaging.preprocessing + \ingroup MITKPlugins + + \brief This is the diffusionimaging.preprocessing plugin. + +*/ + +/** + \defgroup org_mitk_gui_qt_diffusionimaging_preprocessing_internal Internal + \ingroup org_mitk_gui_qt_diffusionimaging_preprocessing + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.diffusionimaging.preprocessing plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.python/files.cmake similarity index 84% copy from Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/files.cmake copy to Plugins/org.mitk.gui.qt.diffusionimaging.python/files.cmake index 61c991d6e5..03078b8ef2 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/files.cmake @@ -1,45 +1,42 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp - QmitkPreprocessingView.cpp QmitkBrainExtractionView.cpp ) set(UI_FILES - src/internal/QmitkPreprocessingViewControls.ui src/internal/QmitkBrainExtractionViewControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h - src/internal/QmitkPreprocessingView.h src/internal/QmitkBrainExtractionView.h ) set(CACHED_RESOURCE_FILES plugin.xml resources/preprocessing.png resources/dwi2.png ) set(QRC_FILES ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.python/manifest_headers.cmake similarity index 85% copy from Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/manifest_headers.cmake copy to Plugins/org.mitk.gui.qt.diffusionimaging.python/manifest_headers.cmake index b9885bba96..223766b673 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK Preprocessing") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging.python/plugin.xml similarity index 60% copy from Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/plugin.xml copy to Plugins/org.mitk.gui.qt.diffusionimaging.python/plugin.xml index c441b6d060..69d3bf2441 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/plugin.xml @@ -1,25 +1,17 @@ - - - - diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/dwi2.png b/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/dwi2.png new file mode 100644 index 0000000000..c2087367ce Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/dwi2.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/preprocessing.png b/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/preprocessing.png new file mode 100644 index 0000000000..d7564ca333 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/preprocessing.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/preprocessing.xcf b/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/preprocessing.xcf new file mode 100644 index 0000000000..c7b840caf9 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/preprocessing.xcf differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkBrainExtractionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkBrainExtractionView.cpp rename to Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkBrainExtractionView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkBrainExtractionView.h rename to Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkBrainExtractionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionViewControls.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkBrainExtractionViewControls.ui rename to Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionViewControls.ui diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.cpp similarity index 90% copy from Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp copy to Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.cpp index aafe6330b1..c7d80cff99 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.cpp @@ -1,44 +1,42 @@ /*=================================================================== 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 "mitkPluginActivator.h" -#include "src/internal/QmitkPreprocessingView.h" #include "src/internal/QmitkBrainExtractionView.h" #include ctkPluginContext* mitk::PluginActivator::m_Context = nullptr; US_INITIALIZE_MODULE ctkPluginContext* mitk::PluginActivator::GetContext() { return m_Context; } void mitk::PluginActivator::start(ctkPluginContext* context) { - BERRY_REGISTER_EXTENSION_CLASS(QmitkPreprocessingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkBrainExtractionView, context) m_Context = context; } void mitk::PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) m_Context = nullptr; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.h new file mode 100644 index 0000000000..2867726397 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.h @@ -0,0 +1,40 @@ +/*=================================================================== + +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 MITKPLUGINACTIVATOR_H +#define MITKPLUGINACTIVATOR_H + +#include + +namespace mitk +{ + class PluginActivator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.preprocessing") + Q_INTERFACES(ctkPluginActivator) + + public: + static ctkPluginContext* GetContext(); + + void start(ctkPluginContext* context) override; + void stop(ctkPluginContext* context) override; + + private: + static ctkPluginContext* m_Context; + }; +} + +#endif diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/manifest_headers.cmake index 82ab334e31..649136a2f4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK Reconstruction") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkHeadMotionCorrection.dox similarity index 76% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkHeadMotionCorrection.dox index 90e4f6f551..0b98310a5f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkHeadMotionCorrection.dox @@ -1,5 +1,5 @@ /** -\page org_mitk_views_diffusionregistrationview Head-Motion Correction +\page org_mitk_views_headmotioncorrectionview Head-Motion Correction This view allows head-motion and eddy-current correction by affinely registering all volumes to the first unweighted volume of the complete diffusion-weighted image. The individual gradient directions are roated accordingly. */ 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 new file mode 100644 index 0000000000..50f5be7cdd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRegistration.dox @@ -0,0 +1,8 @@ +/** +\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. + +*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRigidRegistration.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRigidRegistration.dox deleted file mode 100644 index d98878e5a2..0000000000 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRigidRegistration.dox +++ /dev/null @@ -1,5 +0,0 @@ -/** -\page org_mitk_views_simplerigidregistrationview Rigid Registration - -This view enables the simple rigid 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. -*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake index b20be9d47b..88ebeda4b0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake @@ -1,46 +1,46 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp - QmitkDiffusionRegistrationView.cpp - QmitkSimpleRigidRegistrationView.cpp + QmitkHeadMotionCorrectionView.cpp + QmitkSimpleRegistrationView.cpp QmitkDwiRegistrationPerspective.cpp ) set(UI_FILES - src/internal/QmitkDiffusionRegistrationViewControls.ui - src/internal/QmitkSimpleRigidRegistrationViewControls.ui + src/internal/QmitkHeadMotionCorrectionViewControls.ui + src/internal/QmitkSimpleRegistrationViewControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h - src/internal/QmitkDiffusionRegistrationView.h - src/internal/QmitkSimpleRigidRegistrationView.h + src/internal/QmitkHeadMotionCorrectionView.h + src/internal/QmitkSimpleRegistrationView.h src/internal/QmitkDwiRegistrationPerspective.h ) set(CACHED_RESOURCE_FILES plugin.xml resources/diffusionregistration.png ) set(QRC_FILES ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/manifest_headers.cmake index d54299c5e7..226f6402e8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK dMRI Registration") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml index 3a030cdea7..c66c507de8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml @@ -1,52 +1,52 @@ - - + - - + This perspective contains views for rigid image registration and head motion correction. - - - - - - - - + + + + + + + + - + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.cpp index a5762d2bd2..ed5f3f8a56 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.cpp @@ -1,49 +1,49 @@ /*=================================================================== 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 "QmitkDwiRegistrationPerspective.h" #include "berryIViewLayout.h" void QmitkDwiRegistrationPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout) { ///////////////////////////////////////////////////// // all di-app perspectives should have the following: ///////////////////////////////////////////////////// QString editorArea = layout->GetEditorArea(); layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false); layout->AddStandaloneView("org.mitk.views.datamanager", false, berry::IPageLayout::LEFT, 0.3f, editorArea); layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview", false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager"); berry::IFolderLayout::Pointer left = layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols", berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview"); layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator", berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false); ///////////////////////////////////////////// // here goes the perspective specific stuff ///////////////////////////////////////////// - left->AddView("org.mitk.views.simplerigidregistrationview"); - left->AddView("org.mitk.views.diffusionregistrationview"); + left->AddView("org.mitk.views.simpleregistrationview"); + left->AddView("org.mitk.views.headmotioncorrectionview"); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp similarity index 81% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.cpp rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp index e004e5dd4a..322f900ba4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp @@ -1,124 +1,124 @@ /*=================================================================== 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 "QmitkDiffusionRegistrationView.h" +#include "QmitkHeadMotionCorrectionView.h" // MITK #include #include // Qt #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -const std::string QmitkDiffusionRegistrationView::VIEW_ID = "org.mitk.views.diffusionregistrationview"; +const std::string QmitkHeadMotionCorrectionView::VIEW_ID = "org.mitk.views.headmotioncorrectionview"; -QmitkDiffusionRegistrationView::QmitkDiffusionRegistrationView() +QmitkHeadMotionCorrectionView::QmitkHeadMotionCorrectionView() : QmitkAbstractView() , m_Controls( 0 ) , m_DiffusionImage( nullptr ) { } // Destructor -QmitkDiffusionRegistrationView::~QmitkDiffusionRegistrationView() +QmitkHeadMotionCorrectionView::~QmitkHeadMotionCorrectionView() { } -void QmitkDiffusionRegistrationView::CreateQtPartControl( QWidget *parent ) +void QmitkHeadMotionCorrectionView::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::QmitkDiffusionRegistrationViewControls; + m_Controls = new Ui::QmitkHeadMotionCorrectionViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_ImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) ); connect( m_Controls->m_RegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartRegistration()) ); this->m_Parent = parent; m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New(); m_Controls->m_ImageBox->SetPredicate(isImagePredicate); UpdateGUI(); } } -void QmitkDiffusionRegistrationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) +void QmitkHeadMotionCorrectionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) { } -void QmitkDiffusionRegistrationView::UpdateGUI() +void QmitkHeadMotionCorrectionView::UpdateGUI() { if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) { m_Controls->m_RegistrationStartButton->setEnabled(true); m_Controls->m_RegistrationStartButton->setToolTip("Start Registration"); } else { m_Controls->m_RegistrationStartButton->setEnabled(false); m_Controls->m_RegistrationStartButton->setToolTip("No Diffusion image selected."); } } -void QmitkDiffusionRegistrationView::SetFocus() +void QmitkHeadMotionCorrectionView::SetFocus() { UpdateGUI(); m_Controls->m_RegistrationStartButton->setFocus(); } -void QmitkDiffusionRegistrationView::StartRegistration() +void QmitkHeadMotionCorrectionView::StartRegistration() { mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode(); mitk::Image::Pointer inImage = dynamic_cast(node->GetData()); if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(inImage)) { QMessageBox::warning(nullptr, "Warning", "Input node is not a diffusion-weighted image!"); return; } DWIHeadMotionCorrectionFilterType::Pointer registerer = DWIHeadMotionCorrectionFilterType::New(); registerer->SetInput(inImage); registerer->Update(); mitk::Image::Pointer image = registerer->GetCorrectedImage(); mitk::DataNode::Pointer corrected_node = mitk::DataNode::New(); corrected_node->SetData( image ); QString name(node->GetName().c_str()); name += "_Corrected"; corrected_node->SetName(name.toStdString()); GetDataStorage()->Add(corrected_node, node); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h similarity index 88% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.h rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h index 999723a38d..d849893c05 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h @@ -1,78 +1,78 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include "ui_QmitkDiffusionRegistrationViewControls.h" +#include "ui_QmitkHeadMotionCorrectionViewControls.h" #include #include #include #include typedef short DiffusionPixelType; /*! \brief View for diffusion image registration / head motion correction */ -class QmitkDiffusionRegistrationView : public QmitkAbstractView +class QmitkHeadMotionCorrectionView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; - QmitkDiffusionRegistrationView(); - virtual ~QmitkDiffusionRegistrationView(); + QmitkHeadMotionCorrectionView(); + virtual ~QmitkHeadMotionCorrectionView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; typedef mitk::DWIHeadMotionCorrectionFilter DWIHeadMotionCorrectionFilterType; protected slots: void StartRegistration(); void UpdateGUI(); ///< update button activity etc. dpending on current datamanager selection protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; - Ui::QmitkDiffusionRegistrationViewControls* m_Controls; + Ui::QmitkHeadMotionCorrectionViewControls* m_Controls; mitk::Image::Pointer m_DiffusionImage; std::vector< mitk::DataNode::Pointer > m_SelectedDiffusionNodes; private: void UpdateRegistrationStatus(); ///< update textual status display of the Registration process // the Qt parent of our GUI (NOT of this object) QWidget* m_Parent; }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui similarity index 92% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationViewControls.ui rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui index f051e3f25c..a86cc9f1e0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui @@ -1,88 +1,88 @@ - QmitkDiffusionRegistrationViewControls - + QmitkHeadMotionCorrectionViewControls + 0 0 435 744 Form 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
+
QmitkDataStorageComboBox.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp similarity index 54% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.cpp rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp index 2954bc3839..c13e1f5199 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp @@ -1,275 +1,388 @@ /*=================================================================== 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 "QmitkSimpleRigidRegistrationView.h" +#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 QmitkSimpleRigidRegistrationView::VIEW_ID = "org.mitk.views.simplerigidregistrationview"; +const std::string QmitkSimpleRegistrationView::VIEW_ID = "org.mitk.views.simpleregistrationview"; -QmitkSimpleRigidRegistrationView::QmitkSimpleRigidRegistrationView() +QmitkSimpleRegistrationView::QmitkSimpleRegistrationView() : QmitkAbstractView() , m_Controls( 0 ) + , m_RegistrationType(0) { } // Destructor -QmitkSimpleRigidRegistrationView::~QmitkSimpleRigidRegistrationView() +QmitkSimpleRegistrationView::~QmitkSimpleRegistrationView() { } -void QmitkSimpleRigidRegistrationView::StartRegistration() +void QmitkSimpleRegistrationView::StartRegistration() { - typedef itk::Image< float, 3 > ItkFloatImageType; - mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::New(); + 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; + } - QmitkRegistrationJob* pJob = new QmitkRegistrationJob(algo); 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); -// connect(pJob, SIGNAL(AlgorithmInfo(QString)), this, SLOT(OnAlgorithmInfo(QString))); -// connect(pJob, SIGNAL(AlgorithmStatusChanged(QString)), this, SLOT(OnAlgorithmStatusChanged(QString))); -// connect(pJob, SIGNAL(AlgorithmIterated(QString, bool, unsigned long)), this, SLOT(OnAlgorithmIterated(QString, bool, unsigned long))); -// connect(pJob, SIGNAL(LevelChanged(QString, bool, unsigned long)), this, SLOT(OnLevelChanged(QString, bool, unsigned long))); - QThreadPool* threadPool = QThreadPool::globalInstance(); threadPool->start(pJob); m_Controls->m_RegistrationStartButton->setEnabled(false); m_Controls->m_RegistrationStartButton->setText("Registration in progress ..."); } -void QmitkSimpleRigidRegistrationView::OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* ) +void QmitkSimpleRegistrationView::OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* job) { mitk::Image::Pointer movingImage = dynamic_cast(m_MovingImageNode->GetData()); - mitk::Image::Pointer image = mitk::ImageMappingHelper::refineGeometry(movingImage, spResultRegistration, true); + 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(); - resultNode->SetName((name+"_registered").toStdString().c_str()); + if (m_RegistrationType==0) + resultNode->SetName((name+"_registered (rigid)").toStdString().c_str()); + else + resultNode->SetName((name+"_registered (affine)").toStdString().c_str()); } else - resultNode->SetName("Registered"); + { + 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); - GetDataStorage()->Add(resultNode); + 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 QmitkSimpleRigidRegistrationView::CreateQtPartControl( QWidget *parent ) +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::QmitkSimpleRigidRegistrationViewControls; + 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 QmitkSimpleRigidRegistrationView::FixedImageChanged() +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 QmitkSimpleRigidRegistrationView::MovingImageChanged() +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 QmitkSimpleRigidRegistrationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) +void QmitkSimpleRegistrationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) { FixedImageChanged(); MovingImageChanged(); + TractoChanged(); } -void QmitkSimpleRigidRegistrationView::SetFocus() +void QmitkSimpleRegistrationView::SetFocus() { m_Controls->m_RegistrationStartButton->setFocus(); FixedImageChanged(); MovingImageChanged(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h similarity index 78% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.h rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h index 23f278e3f4..777508b956 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h @@ -1,71 +1,75 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include "ui_QmitkSimpleRigidRegistrationViewControls.h" +#include "ui_QmitkSimpleRegistrationViewControls.h" #include #include -#include typedef short DiffusionPixelType; /*! \brief View for diffusion image registration / head motion correction */ // Forward Qt class declarations -class QmitkSimpleRigidRegistrationView : public QmitkAbstractView +class QmitkSimpleRegistrationView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: + typedef itk::Image< float, 3 > ItkFloatImageType; + typedef itk::Image ITKDiffusionVolumeType; typedef itk::VectorImage< short, 3 > ItkDwiType; static const std::string VIEW_ID; - QmitkSimpleRigidRegistrationView(); - virtual ~QmitkSimpleRigidRegistrationView(); + QmitkSimpleRegistrationView(); + virtual ~QmitkSimpleRegistrationView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; protected slots: void MovingImageChanged(); void FixedImageChanged(); + void TractoChanged(); void StartRegistration(); + void StartTractoRegistration(); void OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* pRegJob); protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; - Ui::QmitkSimpleRigidRegistrationViewControls* m_Controls; + Ui::QmitkSimpleRegistrationViewControls* m_Controls; mitk::DataNode::Pointer m_MovingImageNode; + int m_RegistrationType; private: }; 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 new file mode 100644 index 0000000000..67cb63db27 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationViewControls.ui @@ -0,0 +1,231 @@ + + + QmitkSimpleRegistrationViewControls + + + + 0 + 0 + 435 + 744 + + + + Form + + + + + + 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: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + Rigid + + + + + Affine + + + + + + + + Registration Type: + + + + + + + + + + + + + + Output Registration Object: + + + + + + + + + + false + + + + + + Start Registration + + + + + + + Tractography Registration + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Registration Object: + + + + + + + + + + Tractogram: + + + + + + + + + + + + + false + + + + + + Start Tractography Registration + + + + + + + + QmitkDataStorageComboBox + QComboBox +
QmitkDataStorageComboBox.h
+
+
+ + +
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationViewControls.ui deleted file mode 100644 index 38a25a4afe..0000000000 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationViewControls.ui +++ /dev/null @@ -1,118 +0,0 @@ - - - QmitkSimpleRigidRegistrationViewControls - - - - 0 - 0 - 435 - 744 - - - - Form - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Moving Image: - - - - - - - Fixed Image: - - - - - - - - - - false - - - Select dMRI volume used to calculate transformation. - - - - - - - false - - - Select dMRI volume used to calculate transformation. - - - - - - - - - - false - - - - - - Start Registration - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - QmitkDataStorageComboBox - QComboBox -
QmitkDataStorageComboBox.h
-
-
- - -
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp index 581c7cf5d6..ee12c7bdca 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp @@ -1,43 +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. ===================================================================*/ #include "mitkPluginActivator.h" -#include "src/internal/QmitkDiffusionRegistrationView.h" -#include "src/internal/QmitkSimpleRigidRegistrationView.h" +#include "src/internal/QmitkHeadMotionCorrectionView.h" +#include "src/internal/QmitkSimpleRegistrationView.h" #include "src/internal/QmitkDwiRegistrationPerspective.h" ctkPluginContext* mitk::PluginActivator::m_Context = nullptr; ctkPluginContext* mitk::PluginActivator::GetContext() { return m_Context; } void mitk::PluginActivator::start(ctkPluginContext* context) { - BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionRegistrationView, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkSimpleRigidRegistrationView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkHeadMotionCorrectionView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkSimpleRegistrationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDwiRegistrationPerspective, context) m_Context = context; } void mitk::PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) m_Context = nullptr; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/manifest_headers.cmake index 3e69df27ff..5c107a6272 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "MITK Tbss") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) 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 e19a991a1f..eb0ed3b82f 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,74 +1,74 @@ /** \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 StrTrackUserManualInteractive - \ref StrTrackUserManualParameters - \ref StrTrackUserManualAdvancedParameters - \ref StrTrackUserManualReferences \section StrTrackUserManualInputData Input Data Input: Select the data you want to track on in the datamanager. Supported file types are: \li One or multiple DTI images selected in the datamanager. \li One ODF image, e.g. obtained using MITK Q-ball reconstruction or MRtrix CSD (tractography similar to [6]). \li One peak image (4D float image). \li One raw diffusion-weighted image for machine learning based tractography [1]. Optional Input: \li Binary mask used to define the seed voxels. If no seed mask is specified, the whole image volume is seeded. \li Binary mask used to constrain the generated streamlines. Streamlines can not leave the mask area. \li Binary mask used to define stopping regions. Streamlines that enter the mask area are stopped immediately. \li Tissue label image needed for gray matter seeding (WM=3, GM=1). Use e.g. MRtrix 5ttgen to generate such a label image. \li 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. \li Tractography Forest: Needed for machine learning based tractography [1]. \section StrTrackUserManualInteractive Interactive Tractography Interactive tractography enables the dynamic placement of spherical seed regions simply by clicking into the image (similar to [5]). Parameters are the number of seed points and the radius of the spherical seed region. The seed points are randomly distributed inside the sphere around the selected position. By clicking and holding the left mouse button while moving the mouse around the image, the fiber connections originating from the selected region can be explored dynamically. 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 effcts that the individual parameters have on the resulting tractogram. \section StrTrackUserManualParameters Parameters \li 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. \li 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. \li Max. num. fibers: Tractography is stopped after the desired number of fibers is reached, even before all seed points are processed. \li 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. \li ODF Cutoff: Additional threshold on the ODF magnitude. This is useful in case of CSD fODF tractography. For MRtrix CSD fODF images, a typical value is 0.1. \li 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. \section StrTrackUserManualAdvancedParameters Advanced Parameters \li Step Size: The algorithm proceeds along the streamline with a fixed stepsize. Default is 0.5*minSpacing. \li 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. \li Min. Tract Length: Shorter fibers are discarded. \li 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] \li Flip directions: Internally flips progression directions. This might be necessary depending on the input data. \li Enable Trilinear Interpolation: By default the image values are interpolated. Keep in mind that in the noninterpolated case, the TEND term is only applied once per voxel. In the interpolated case the TEND term is applied at each integration step which results in much higher curvatures and has to be compensated by an according choice of f and g. \li Enable Gray Matter Seeding: Seeds are onyl placed inside of the gray matter. Needs tissue label image. -\section StrTrackUserManualAdvancedParameters Neighbourhood Sampling (for details see [1]) +\section StrTrackUserManualNeighbourhoodSampling Neighbourhood Sampling (for details see [1]) \li Neighborhood Samples: Number of neighborhood samples that are used to determine the next fiber progression direction. \li Sampling Distance: Distance of the sampling positions from the current streamline position (in voxels). \li Use Only Frontal Samples: Only neighborhood samples in front of the current streamline position are considered. \li 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 StrTrackUserManualAdvancedParameters Output and Postprocessing +\section StrTrackUserManualPostprocessing Output and Postprocessing \li 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. \li Output Probability Map: No streamline are generated. Instead, the tractography outputs a probability 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/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/manifest_headers.cmake index 72c7b12377..b2dc929af8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/manifest_headers.cmake @@ -1,6 +1,5 @@ set(Plugin-Name "MITK Tractography") set(Plugin-Version "1.0.0") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common.legacy org.mitk.gui.qt.common) -set(Plugin-ActivationPolicy "eager") +set(Require-Plugin org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox index 41cb380913..d2052b2ff2 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox @@ -1,48 +1,48 @@ /** \page org_mitk_gui_qt_diffusionimaging MITK Diffusion \tableofcontents MITK Diffusion offers a selection of image analysis methods for dMRI processing. It encompasses the research of the Division of Medical Image Computing of the German Cancer Research Center (DKFZ). \section org_mitk_gui_qt_diffusionimagingComponents Components MITK Diffusion consists of multiple components with their own documentation: \subsection sub1 Data formats, import and export \li \subpage QmitkDiffusionImagingDataImportPage \subsection sub2 Preprocessing and Reconstruction \li \subpage org_mitk_views_diffusionpreprocessing -\li \subpage org_mitk_views_simplerigidregistrationview -\li \subpage org_mitk_views_diffusionregistrationview +\li \subpage org_mitk_views_simpleregistrationview +\li \subpage org_mitk_views_headmotioncorrectionview \li \subpage org_mitk_views_denoisingview \li \subpage org_mitk_views_tensorreconstruction \li \subpage org_mitk_views_qballreconstruction \subsection sub3 Visualization and Quantification \li \subpage org_mitk_views_controlvisualizationpropertiesview \li \subpage org_mitk_views_odfdetails \li \subpage org_mitk_views_odfmaximaextraction \li \subpage org_mitk_views_partialvolumeanalysisview \li \subpage org_mitk_views_diffusionquantification \li \subpage org_mitk_views_ivim \subsection sub4 Fiber Tractography \li \subpage org_mitk_views_streamlinetracking \li \subpage org_mitk_views_gibbstracking \li \subpage org_mitk_views_mlbtview \li \subpage org_mitk_views_fiberprocessing \li \subpage org_mitk_views_fiberquantification \li \subpage org_mitk_views_fiberfit \li \subpage org_mitk_views_fiberclustering \subsection sub5 Fiberfox dMRI Simulation \li \subpage org_mitk_views_fiberfoxview \li \subpage org_mitk_views_fieldmapgenerator \subsection sub6 TBSS and Connectomics \li \subpage org_mitk_views_tractbasedspatialstatistics \li \subpage org_mitk_diffusionimagingapp_perspectives_connectomics */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging/manifest_headers.cmake index 9fa658aee6..bdff16293f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/manifest_headers.cmake @@ -1,5 +1,6 @@ set(Plugin-Name "MITK Diffusion Imaging") set(Plugin-Version "0.1") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") -set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.common) +#set(Plugin-ActivationPolicy eager)