diff --git a/Applications/Diffusion/CMakeLists.txt b/Applications/Diffusion/CMakeLists.txt index 903b7d2193..594bbfb70e 100644 --- a/Applications/Diffusion/CMakeLists.txt +++ b/Applications/Diffusion/CMakeLists.txt @@ -1,95 +1,97 @@ 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.matchpoint.algorithm.browser - org.mitk.gui.qt.matchpoint.algorithm.control + org.mitk.gui.qt.diffusionimaging.registration +# 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() diff --git a/Applications/Diffusion/target_libraries.cmake b/Applications/Diffusion/target_libraries.cmake index a6496917be..fa0fefc01e 100644 --- a/Applications/Diffusion/target_libraries.cmake +++ b/Applications/Diffusion/target_libraries.cmake @@ -1,29 +1,33 @@ # A list of plug-in targets which should be automatically enabled -# (or be available in external projects) for this application. +# (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_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/mitkDiffusion.cmake b/CMake/BuildConfigurations/DiffusionAll.cmake similarity index 94% rename from CMake/BuildConfigurations/mitkDiffusion.cmake rename to CMake/BuildConfigurations/DiffusionAll.cmake index 5e00e6b54b..26f661e2c9 100644 --- a/CMake/BuildConfigurations/mitkDiffusion.cmake +++ b/CMake/BuildConfigurations/DiffusionAll.cmake @@ -1,35 +1,34 @@ -message(STATUS "Configuring MITK Diffusion Release Build") +message(STATUS "Configuring MITK Diffusion with all Plugins") # 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_DCMQI ON CACHE BOOL "" FORCE) set(MITK_USE_MatchPoint 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 ON 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 ON CACHE BOOL "Build miscellaneous commandline tools for diffusion" FORCE) set(BUILD_DiffusionQuantificationCmdApps ON 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 ON 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 ON 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) # Disable 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) diff --git a/CMakeExternals/ITK-4.11.0.patch b/CMakeExternals/ITK-4.11.0.patch deleted file mode 100644 index 9a285c0804..0000000000 --- a/CMakeExternals/ITK-4.11.0.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/Modules/ThirdParty/GDCM/CMakeLists.txt b/Modules/ThirdParty/GDCM/CMakeLists.txt -index bf2d27d..e321215 100644 ---- a/Modules/ThirdParty/GDCM/CMakeLists.txt -+++ b/Modules/ThirdParty/GDCM/CMakeLists.txt -@@ -4,7 +4,7 @@ set(ITKGDCM_THIRD_PARTY 1) - if(ITK_USE_SYSTEM_GDCM) - set(ITKGDCM_SYSTEM_INCLUDE_DIRS ${GDCM_INCLUDE_DIRS}) - set(ITKGDCM_SYSTEM_LIBRARY_DIRS ${GDCM_LIBRARY_DIRS}) -- set(ITKGDCM_LIBRARIES gdcmDICT gdcmMSFF) -+ set(ITKGDCM_LIBRARIES gdcmDICT gdcmMSFF gdcmDSED) - set(ITKGDCM_NO_SRC 1) - - # When this module is loaded by an app, load GDCM too. -@@ -42,7 +42,7 @@ else() - endif() - endif() - endif() -- set(ITKGDCM_LIBRARIES gdcmDICT gdcmMSFF ) -+ set(ITKGDCM_LIBRARIES gdcmDICT gdcmMSFF gdcmDSED) - endif() - - itk_module_impl() diff --git a/CMakeExternals/ITK.cmake b/CMakeExternals/ITK.cmake index de97277bce..30e2acaf73 100644 --- a/CMakeExternals/ITK.cmake +++ b/CMakeExternals/ITK.cmake @@ -1,86 +1,86 @@ #----------------------------------------------------------------------------- # ITK #----------------------------------------------------------------------------- # Sanity checks if(DEFINED ITK_DIR AND NOT EXISTS ${ITK_DIR}) message(FATAL_ERROR "ITK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj ITK) set(proj_DEPENDENCIES GDCM) if(MITK_USE_OpenCV) list(APPEND proj_DEPENDENCIES OpenCV) endif() if(MITK_USE_HDF5) list(APPEND proj_DEPENDENCIES HDF5) endif() set(ITK_DEPENDS ${proj}) if(NOT DEFINED ITK_DIR) set(additional_cmake_args ) if(MINGW) set(additional_cmake_args -DCMAKE_USE_WIN32_THREADS:BOOL=ON -DCMAKE_USE_PTHREADS:BOOL=OFF) endif() list(APPEND additional_cmake_args -DUSE_WRAP_ITK:BOOL=OFF ) if(MITK_USE_OpenCV) list(APPEND additional_cmake_args -DModule_ITKVideoBridgeOpenCV:BOOL=ON -DOpenCV_DIR:PATH=${OpenCV_DIR} ) endif() # Keep the behaviour of ITK 4.3 which by default turned on ITK Review # see MITK bug #17338 list(APPEND additional_cmake_args -DModule_ITKReview:BOOL=ON # for 4.7, the OpenJPEG is needed by review but the variable must be set -DModule_ITKOpenJPEG:BOOL=ON ) if(CTEST_USE_LAUNCHERS) list(APPEND additional_cmake_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} - URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/InsightToolkit-4.11.0.tar.gz - URL_MD5 1a71ae9d2f7b3140ac17e8bbb0602c8a + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/InsightToolkit-4.12.2.tar.xz + URL_MD5 cee6436c1341db3813a85955c281e6a9 # work with external GDCM - PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/ITK-4.11.0.patch + # PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/ITK-4.11.0.patch CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} ${additional_cmake_args} -DBUILD_EXAMPLES:BOOL=OFF -DITK_USE_SYSTEM_GDCM:BOOL=ON -DGDCM_DIR:PATH=${GDCM_DIR} -DITK_USE_SYSTEM_HDF5:BOOL=ON -DHDF5_DIR:PATH=${HDF5_DIR} CMAKE_CACHE_ARGS ${ep_common_cache_args} CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${proj_DEPENDENCIES} ) set(ITK_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/Modules/Chart/include/QmitkChartData.h b/Modules/Chart/include/QmitkChartData.h index 535c4e2a0e..6229304e36 100644 --- a/Modules/Chart/include/QmitkChartData.h +++ b/Modules/Chart/include/QmitkChartData.h @@ -1,86 +1,92 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkC3Data_h #define QmitkC3Data_h #include #include /** \brief This class holds the relevant properties for the chart generation with C3 such as labels and diagram type. * It is derived from QObject, because we need Q_PROPERTIES to send Data via QWebChannel to JavaScript. * \sa The actual data for the chart generation is in QmitkC3xyData! */ class QmitkChartData : public QObject { Q_OBJECT Q_PROPERTY(QVariant m_xAxisLabel READ GetXAxisLabel WRITE SetXAxisLabel NOTIFY SignalXAxisLabelChanged); Q_PROPERTY(QVariant m_yAxisLabel READ GetYAxisLabel WRITE SetYAxisLabel NOTIFY SignalYAxisLabelChanged); Q_PROPERTY(QVariant m_diagramTitle READ GetDiagramTitle WRITE SetDiagramTitle NOTIFY SignalDiagramTitleChanged); Q_PROPERTY(QVariant m_LegendPosition READ GetLegendPosition WRITE SetLegendPosition NOTIFY SignalLegendPositionChanged); Q_PROPERTY(QVariant m_YAxisScale READ GetYAxisScale WRITE SetYAxisScale NOTIFY SignalYAxisScaleChanged); Q_PROPERTY(QVariant m_ShowSubchart READ GetShowSubchart WRITE SetShowSubchart NOTIFY SignalShowSubchartChanged); Q_PROPERTY(QVariant m_UsePercentageInPieChart READ GetUsePercentageInPieChart WRITE SetUsePercentageInPieChart NOTIFY SignalUsePercentageInPieChartChanged); + Q_PROPERTY(QVariant m_DataPointSize READ GetDataPointSize WRITE SetDataPointSize NOTIFY SignalDataPointSizeChanged); public: QmitkChartData(); void SetAppearance(bool showSubChart = true, bool usePercentageInPieChart = false); Q_INVOKABLE QVariant GetXAxisLabel() const { return m_xAxisLabel; }; Q_INVOKABLE void SetXAxisLabel(const QVariant& label) { m_xAxisLabel = label; emit SignalXAxisLabelChanged(label); }; Q_INVOKABLE QVariant GetYAxisLabel() const { return m_yAxisLabel; }; Q_INVOKABLE void SetYAxisLabel(const QVariant& label) { m_yAxisLabel = label; emit SignalYAxisLabelChanged(label); }; Q_INVOKABLE QVariant GetDiagramTitle() const { return m_diagramTitle; }; Q_INVOKABLE void SetDiagramTitle(const QVariant& title) { m_diagramTitle = title; emit SignalDiagramTitleChanged(title); }; Q_INVOKABLE QVariant GetLegendPosition() const { return m_LegendPosition; }; Q_INVOKABLE void SetLegendPosition(const QVariant& legendPosition) { m_LegendPosition = legendPosition; emit SignalLegendPositionChanged(legendPosition); }; Q_INVOKABLE QVariant GetYAxisScale() const { return m_YAxisScale; }; Q_INVOKABLE void SetYAxisScale(const QVariant& YAxisScale) { m_YAxisScale = YAxisScale; emit SignalYAxisScaleChanged(YAxisScale); }; Q_INVOKABLE QVariant GetShowSubchart() const { return m_ShowSubchart; }; Q_INVOKABLE void SetShowSubchart(const QVariant& showSubchart) { m_ShowSubchart = showSubchart; emit SignalShowSubchartChanged(showSubchart); }; Q_INVOKABLE QVariant GetUsePercentageInPieChart() const { return m_UsePercentageInPieChart; }; Q_INVOKABLE void SetUsePercentageInPieChart(const QVariant& usePercentageInPieChart) { m_UsePercentageInPieChart = usePercentageInPieChart; emit SignalUsePercentageInPieChartChanged(usePercentageInPieChart); }; + Q_INVOKABLE QVariant GetDataPointSize() const { return m_DataPointSize; }; + Q_INVOKABLE void SetDataPointSize(const QVariant& showDataPoints) {if (showDataPoints > 0 ) { m_DataPointSize = 3; } else { m_DataPointSize = 0; } emit SignalDataPointSizeChanged(showDataPoints); }; + signals: void SignalYAxisLabelChanged(const QVariant label); void SignalXAxisLabelChanged(const QVariant label); void SignalLegendPositionChanged(const QVariant legendPosition); void SignalYAxisScaleChanged(const QVariant YAxisScale); void SignalDiagramTitleChanged(const QVariant title); void SignalShowSubchartChanged(const QVariant showSubchart); void SignalUsePercentageInPieChartChanged(const QVariant usePercentageInPieChart); + void SignalDataPointSizeChanged(const QVariant showDataPoints); private: QVariant m_xAxisLabel; QVariant m_yAxisLabel; QVariant m_diagramTitle; QVariant m_LegendPosition; QVariant m_YAxisScale; QVariant m_ShowSubchart; QVariant m_UsePercentageInPieChart; QVariant m_numberDatasets; + QVariant m_DataPointSize = 0; }; #endif //QmitkC3Data_h \ No newline at end of file diff --git a/Modules/Chart/include/QmitkChartWidget.h b/Modules/Chart/include/QmitkChartWidget.h index 1cdae949e7..8b40212ef8 100644 --- a/Modules/Chart/include/QmitkChartWidget.h +++ b/Modules/Chart/include/QmitkChartWidget.h @@ -1,189 +1,196 @@ /*=================================================================== 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 QmitkC3jsWidget_h #define QmitkC3jsWidget_h #include #include #include /*! \brief QmitkChartWidget is a widget to display various charts based on the javascript chart library C3js. Currently, bar charts, line charts and pie charts are supported. * \details Data is added via AddData1D() or AddData2D().\n * There can be multiple charts (of the same type) created by calling AddData1D or AddData2D multiple times.\n\n * The following chart types are supported: * * line chart: http://c3js.org/samples/simple_multiple.html * * bar chart: http://c3js.org/samples/chart_bar.html * * spline chart: http://c3js.org/samples/chart_spline.html * * pie chart: http://c3js.org/samples/chart_pie.html * \n Technical details: The javascript code is embedded in a QWebEngineView. The actual js code is implemented in resource\Chart.js. * \sa http://c3js.org for further information about the used javaScript library. * \warning Pie is significantly different than the other types. Here, the data given by AddData1D is summed. Each entry represents a different category. * \ingroup Modules/Chart */ class MITKCHART_EXPORT QmitkChartWidget : public QWidget { Q_OBJECT public: /*! * \brief enum of diagram types. Supported are bar, line, spline (a smoothed line) and pie. */ enum class ChartType { bar, /*!< bar chart, see http://c3js.org/samples/chart_bar.html */ line, /*!< line chart, see http://c3js.org/samples/simple_multiple.html */ spline, /*!< spline chart (smoothed line chart), see http://c3js.org/samples/chart_spline.html */ pie, /*!< pie chart, see http://c3js.org/samples/chart_pie.html*/ area, /*!< area chart, see http://c3js.org/samples/chart_area.html*/ area_spline /*!< area-spline chart, see http://c3js.org/samples/chart_area.html*/ }; enum class ChartStyle { defaultstyle, darkstyle }; enum class LineStyle { solid, dashed }; enum class AxisScale { linear, log }; /*! * \brief enum of legend position. Supported are bottom, right, inset. * See http://c3js.org/reference.html#legend-position */ enum class LegendPosition { bottom, right, inset }; explicit QmitkChartWidget(QWidget* parent = nullptr); virtual ~QmitkChartWidget(); /*! * \brief Adds 1D data to the widget * \details internally, the list is converted to a map with increasing integers keys starting at 0. * \param label the name of the data that is also used as identifier. * \param type the chart type that should be used for this data entry * \note the data can be cleared with ClearDiagram() * \note If the label name already exists, the name is replaced with a unique one by concatenating numbers to it. */ void AddData1D(const std::vector& data1D, const std::string& label, ChartType type = ChartType::bar); /*! * \brief Adds 2D data to the widget. Call repeatedly for displaying multiple charts. * \details each entry represents a data point: key: value --> x-value: y-value. * \param label the name of the data that is also used as identifier. * \param type the chart type that should be used for this data entry * \note the data can be cleared with ClearDiagram() * \note If the label name already exists, the name is replaced with a unique one by concatenating numbers to it. */ void AddData2D(const std::map& data2D, const std::string& label, ChartType type = ChartType::bar); /*! * \brief Removes data from the widget, works for 1D and 2D Data * \param label the name of the data that is also used as identifier. * \note the data can be cleared with ClearDiagram() * \throws Invalid Argument Exception when the label cannot be found */ void RemoveData(const std::string& label); /*! * \brief sets the color of one data entry (identifier is previously assigned label) * \details the color name can be "red" or a hex number (#FF0000). * Either define all data entries with a color or none. If a mixed approach is used, different data entries could have the same color. * If an unknown label is given, nothing happens. * \sa https://www.w3schools.com/cssref/css_colors.asp */ void SetColor(const std::string& label, const std::string& colorName); /*! * \brief sets the line style of one data entry (identifier is previously assigned label) * \details two line styles are possible: LineStyle::solid and LineStyle::dashed. * The default linestyle is solid. * If an unknown label is given, nothing happens. * \warning only sets the line style if the current chart type is ChartType::line. However, the line style remains also if the chart changes (e.g. new chart type) */ void SetLineStyle(const std::string& label, LineStyle style); void SetYAxisScale(AxisScale scale); void SetXAxisLabel(const std::string& label); std::string GetXAxisLabel() const; void SetYAxisLabel(const std::string& label); std::string GetYAxisLabel() const; void SetDiagramTitle(const std::string &title); std::string GetDiagramTitle() const; /*! * \brief sets the chart type for a data entry * \details for available types, see ChartType * If an unknown label is given, nothing happens. * \sa DiagramType for available types */ void SetChartType(const std::string& label, ChartType type); void SetLegendPosition(LegendPosition position); LegendPosition GetLegendPosition() const; /*! * \brief Changes the chart type for all data entries and reloads the chart */ void SetChartTypeForAllDataAndReload(ChartType type); /*! * \brief Displays the chart in the widget * \param showSubChart if a subchart is displayed inside the widget or not (see http://c3js.org/samples/options_subchart.html). * \exception if no data has been provided (\sa AddData1D AddData2D) */ void Show(bool showSubChart=false); + /*! + * \brief Displays the dataPoints or not + * \param showDataPoints if dataPoints are displayed inside the widget or not. + */ + void SetShowDataPoints(bool showDataPoints); + bool GetShowDataPoints() const; + /*! * \brief Clears all data inside and resets the widget. */ void Clear(); /*! * \brief Changes the theme of the widget. */ void SetTheme(ChartStyle themeEnabled); /*! * \brief Reloads the chart in the widget * \details reloading may be needed to display added data in an existing chart * \param showSubChart if a subchart is displayed inside the widget or not. */ void Reload(bool showSubChart); private: class Impl; Impl* m_Impl; public slots: void OnLoadFinished(bool isLoadSuccessfull); signals: void PageSuccessfullyLoaded(); }; #endif diff --git a/Modules/Chart/resource/Chart.js b/Modules/Chart/resource/Chart.js index c35b3a2ddc..07f04e2454 100644 --- a/Modules/Chart/resource/Chart.js +++ b/Modules/Chart/resource/Chart.js @@ -1,236 +1,236 @@ //Based on C3.js (http://c3js.org). See Website for examples! document.body.style.backgroundColor = 'rgb(240, 240, 240)'; var minHeight = 255; var chart; GenerateChart('bar', false, false) var chartData; var xValues=[]; var yValues=[]; var xs = {}; var dataColors = {}; var chartTypes = {}; var lineStyle = {}; //Is executed when js is loaded first. //Extracts relevant information from chartData in variables window.onload = function() { new QWebChannel(qt.webChannelTransport, function(channel) { chartData = channel.objects.chartData; var count = 0; for(var propertyName in channel.objects) { if (propertyName != 'chartData'){ var xDataTemp = channel.objects[propertyName].m_XData var yDataTemp = channel.objects[propertyName].m_YData var dataLabelsTemp; //add label to x array xDataTemp.unshift('x'+count.toString()) dataLabelsTemp = channel.objects[propertyName].m_Label xs[dataLabelsTemp] = 'x'+count.toString() xDataTemp.push(null); //append null value, to make sure the last tick on x-axis is displayed correctly yDataTemp.unshift(dataLabelsTemp) yDataTemp.push(null); //append null value, to make sure the last tick on y-axis is displayed correctly xValues[count] = xDataTemp yValues[count] = yDataTemp dataColors[dataLabelsTemp] = channel.objects[propertyName].m_Color chartTypes[dataLabelsTemp] = channel.objects[propertyName].m_ChartType if (channel.objects[propertyName].m_LineStyleName=="solid"){ lineStyle[dataLabelsTemp]= '' } else { lineStyle[dataLabelsTemp]= [{'style':'dashed'}] } count++; } } setupChart(chartData) }); } //This is necessary to resize the chart, after the size of the parent changed window.onresize = function () { var size = window.innerHeight-(window.innerHeight/100*10); //subtract 5% of height to hide vertical scrool bar if (size < minHeight) { size = minHeight; } chart.resize({ height: size, }); } function ReloadChart(showSubchart) { chartData.m_ShowSubchart = showSubchart; setupChart(chartData); } function setupChart(chartData) { window.onresize(); GenerateChart(chartData.m_DiagramTypeName, chartData.m_ShowSubchart, chartData.m_UsePercentageInPieChart, - chartData.m_xAxisLabel, chartData.m_yAxisLabel, chartData.m_diagramTitle, chartData.m_LegendPosition, chartData.m_YAxisScale) + chartData.m_xAxisLabel, chartData.m_yAxisLabel, chartData.m_diagramTitle, chartData.m_LegendPosition, chartData.m_DataPointSize, chartData.m_YAxisScale) chart.unload(); //unload data before loading new data //for multiple xy line chart, see http://c3js.org/samples/simple_xy_multiple.html var columns = []; for (var i in xValues){ columns.push(xValues[i]) } for (var i in yValues){ columns.push(yValues[i]) } chart.load({ xs: xs, columns: columns }); } //Transformation between different chart types //takes the name of the chart type as a parameter //called by QmitkC3jsWidget function transformView(TransformTo) { chart.transform(TransformTo); }; function changeTheme(color) { link = document.getElementsByTagName("link")[0]; if (color == 'dark') { link.href = "Chart_dark.css"; } else { link.href = "Chart.css"; } }; //Here, the chart magic takes place. C3js is called //chartType: either bar, line or pie //showSubchart: see http://c3js.org/samples/options_subchart.html //usePercentageInPieChart: percentage labels (only for pie chart) -function GenerateChart(chartType, showSubchart, usePercentageInPieChart, xAxisLabel, yAxisLabel, title, legendPosition, YAxisScale) +function GenerateChart(chartType, showSubchart, usePercentageInPieChart, xAxisLabel, yAxisLabel, title, legendPosition, dataPointSize, YAxisScale) { //adaption for bar ratio indepenend of amount of data points //otherwise, bars could be covered. var barRatio; try { barRatio = 0.8*Math.exp(-0.015*xValues[0].length); } catch (err){ barRatio=0.42 } var formatCharacter; if (usePercentageInPieChart==true){ formatCharacter = '%' } else{ formatCharacter = '.1f' } chart = c3.generate({ title:{ text: title, position: 'top-center' }, data: { xs: {}, //use first "column" as x axis values columns: [], //initialize empty. Data will be loaded in function setupChart(chartData) types: chartTypes, selection: { enabled: false, multiple: false, }, colors: dataColors, regions: lineStyle, }, legend: { position: legendPosition, show: true }, grid: { y: { lines: [{value:0}] //Draws a horizontal line at y=0 } }, bar: { width: { ratio: barRatio } }, pie:{ label: { format: function (value, ratio, id) { if (usePercentageInPieChart==true){ return d3.format('%') (ratio); } else{ return value; } } } }, zoom: { enabled: true, }, subchart: { show: showSubchart //Shows a subchart that shows the region the primary chart is zoomed in to by overlay. }, axis: { x: { tick: { multiline: false, fit: false, //to make more x labels appear on zoom centered: true, format: d3.format(".1f"), }, label: { text: xAxisLabel, position: 'outer-center' } }, y: { tick: { format: d3.format(formatCharacter) }, label: { text: yAxisLabel, position: 'outer-middle' }, scale: { name: YAxisScale } } }, tooltip: { format: { title: function (x) { return xAxisLabel + ': ' + d3.format(".2f")(x)} }, }, //Style data points in linegraph point: { - r: 0.2, + r: dataPointSize, focus: { expand: { - r: 4 + r: dataPointSize + 2 } } }, }); } diff --git a/Modules/Chart/src/QmitkChartWidget.cpp b/Modules/Chart/src/QmitkChartWidget.cpp index 0cad36b06d..c391d9b3fd 100644 --- a/Modules/Chart/src/QmitkChartWidget.cpp +++ b/Modules/Chart/src/QmitkChartWidget.cpp @@ -1,469 +1,499 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include "mitkExceptionMacro.h" class QmitkChartWidget::Impl final { public: explicit Impl(QWidget* parent); ~Impl(); Impl(const Impl&) = delete; Impl& operator=(const Impl&) = delete; void AddData1D(const std::vector& data1D, const std::string& label, QmitkChartWidget::ChartType diagramType); void AddData2D(const std::map& data2D, const std::string& label, QmitkChartWidget::ChartType diagramType); void RemoveData(const std::string& label); void ClearData(); void SetColor(const std::string& label, const std::string& colorName); void SetLineStyle(const std::string& label, LineStyle style); void SetYAxisScale(AxisScale scale); void SetXAxisLabel(const std::string& label); std::string GetXAxisLabel() const; void SetYAxisLabel(const std::string& label); std::string GetYAxisLabel() const; void SetDiagramTitle(const std::string &title); std::string GetDiagramTitle() const; void SetLegendPosition(LegendPosition position); LegendPosition GetLegendPosition() const; std::string GetLegendPositionAsString() const; + void SetShowDataPoints(bool showDataPoints = false); + bool GetShowDataPoints() const; + void SetChartType(const std::string& label, QmitkChartWidget::ChartType diagramType); std::string ConvertChartTypeToString(QmitkChartWidget::ChartType diagramType) const; void ClearJavaScriptChart(); void InitializeJavaScriptChart(); void CallJavaScriptFuntion(const QString& command); QmitkChartData* GetC3Data() const; std::vector* GetC3xyData() const; private: std::string GetUniqueLabelName(const QList& labelList, const std::string& label) const; QmitkChartxyData* GetElementByLabel(const std::vector* c3xyData, const std::string& label) const; QList GetDataLabels(const std::vector* c3xyData) const; QWebChannel* m_WebChannel; QWebEngineView* m_WebEngineView; QmitkChartData * m_C3Data; std::vector * m_C3xyData; std::map m_DiagramTypeToName; std::map m_LegendPositionToName; std::map m_LineStyleToName; std::map m_AxisScaleToName; }; QmitkChartWidget::Impl::Impl(QWidget* parent) : m_WebChannel(new QWebChannel(parent)), m_WebEngineView(new QWebEngineView(parent)) { //disable context menu for QWebEngineView m_WebEngineView->setContextMenuPolicy(Qt::NoContextMenu); //Set the webengineview to an initial empty page. The actual chart will be loaded once the data is calculated. m_WebEngineView->setUrl(QUrl(QStringLiteral("qrc:///C3js/empty.html"))); m_WebEngineView->page()->setWebChannel(m_WebChannel); connect(m_WebEngineView, SIGNAL(loadFinished(bool)), parent, SLOT(OnLoadFinished(bool))); auto layout = new QGridLayout(parent); layout->setMargin(0); layout->addWidget(m_WebEngineView); parent->setLayout(layout); m_DiagramTypeToName.emplace(ChartType::bar, "bar"); m_DiagramTypeToName.emplace(ChartType::line, "line"); m_DiagramTypeToName.emplace(ChartType::spline, "spline"); m_DiagramTypeToName.emplace(ChartType::pie, "pie"); m_DiagramTypeToName.emplace(ChartType::area, "area"); m_DiagramTypeToName.emplace(ChartType::area_spline , "area-spline"); m_LegendPositionToName.emplace(LegendPosition::bottom, "bottom"); m_LegendPositionToName.emplace(LegendPosition::right, "right"); m_LegendPositionToName.emplace(LegendPosition::inset, "inset"); m_LineStyleToName.emplace(LineStyle::solid, "solid"); m_LineStyleToName.emplace(LineStyle::dashed, "dashed"); m_AxisScaleToName.emplace(AxisScale::linear, ""); m_AxisScaleToName.emplace(AxisScale::log, "log"); m_C3Data = new QmitkChartData(); m_C3xyData = new std::vector(); } QmitkChartWidget::Impl::~Impl() { delete m_C3Data; delete m_C3xyData; } std::string QmitkChartWidget::Impl::GetUniqueLabelName(const QList& labelList, const std::string& label) const { QString currentLabel = QString::fromStdString(label); int counter = 0; while (labelList.contains(currentLabel)) { currentLabel = QString::fromStdString(label + std::to_string(counter)); counter++; } return currentLabel.toStdString(); } void QmitkChartWidget::Impl::AddData1D(const std::vector& data1D, const std::string& label, QmitkChartWidget::ChartType type) { QList data1DConverted; for (const auto& aValue : data1D) { data1DConverted.append(aValue); } const std::string diagramTypeName(m_DiagramTypeToName.at(type)); auto definedLabels = GetDataLabels(GetC3xyData()); auto uniqueLabel = GetUniqueLabelName(definedLabels, label); GetC3xyData()->push_back(new QmitkChartxyData(data1DConverted, QVariant(QString::fromStdString(uniqueLabel)), QVariant(QString::fromStdString(diagramTypeName)))); } void QmitkChartWidget::Impl::RemoveData(const std::string& label) { std::vector::iterator iter_temp = GetC3xyData()->end(); for (std::vector::iterator iter = GetC3xyData()->begin(); iter != GetC3xyData()->end(); ++iter) { const auto &temp = *iter; if (temp->GetLabel().toString().toStdString() == label) { iter_temp = iter; break; } } if (iter_temp == GetC3xyData()->end()) { throw std::invalid_argument("Cannot Remove Data because the label does not exist."); } else { GetC3xyData()->erase(iter_temp); } } void QmitkChartWidget::Impl::AddData2D(const std::map& data2D, const std::string& label, QmitkChartWidget::ChartType type) { QMap data2DConverted; for (const auto& aValue : data2D) { data2DConverted.insert(aValue.first, aValue.second); } const std::string diagramTypeName(m_DiagramTypeToName.at(type)); auto definedLabels = GetDataLabels(GetC3xyData()); auto uniqueLabel = GetUniqueLabelName(definedLabels, label); GetC3xyData()->push_back(new QmitkChartxyData(data2DConverted, QVariant(QString::fromStdString(uniqueLabel)), QVariant(QString::fromStdString(diagramTypeName)))); } void QmitkChartWidget::Impl::SetColor(const std::string& label, const std::string& colorName) { auto element = GetElementByLabel(GetC3xyData(), label); if (element) { element->SetColor(QVariant(QString::fromStdString(colorName))); } } void QmitkChartWidget::Impl::SetLineStyle(const std::string& label, LineStyle style) { auto element = GetElementByLabel(GetC3xyData(), label); //only has effect with chart type line if (element && element->GetChartType()==QVariant(QString::fromStdString(ConvertChartTypeToString(ChartType::line)))) { const std::string lineStyleName(m_LineStyleToName.at(style)); element->SetLineStyle(QVariant(QString::fromStdString(lineStyleName))); } } void QmitkChartWidget::Impl::SetYAxisScale(AxisScale scale) { const std::string axisScaleName(m_AxisScaleToName.at(scale)); GetC3Data()->SetYAxisScale(QString::fromStdString(axisScaleName)); } QmitkChartxyData* QmitkChartWidget::Impl::GetElementByLabel(const std::vector* c3xyData, const std::string& label) const { for (auto element = c3xyData->begin(); element != c3xyData->end(); ++element) { if ((*element)->GetLabel().toString().toStdString() == label) { return *element; } } MITK_WARN << "label " << label << " not found in QmitkChartWidget"; return nullptr; } QList QmitkChartWidget::Impl::GetDataLabels(const std::vector* c3xyData) const { QList dataLabels; for (auto element = c3xyData->begin(); element != c3xyData->end(); ++element) { dataLabels.push_back((*element)->GetLabel()); } return dataLabels; } void QmitkChartWidget::Impl::SetXAxisLabel(const std::string& label) { GetC3Data()->SetXAxisLabel(QString::fromStdString(label)); } std::string QmitkChartWidget::Impl::GetXAxisLabel() const { return GetC3Data()->GetXAxisLabel().toString().toStdString(); } void QmitkChartWidget::Impl::SetYAxisLabel(const std::string& label) { GetC3Data()->SetYAxisLabel(QString::fromStdString(label)); } std::string QmitkChartWidget::Impl::GetYAxisLabel() const { return GetC3Data()->GetYAxisLabel().toString().toStdString(); } void QmitkChartWidget::Impl::SetDiagramTitle(const std::string& title) { GetC3Data()->SetDiagramTitle(QString::fromStdString(title)); } std::string QmitkChartWidget::Impl::GetDiagramTitle() const { return GetC3Data()->GetDiagramTitle().toString().toStdString(); } void QmitkChartWidget::Impl::SetLegendPosition(QmitkChartWidget::LegendPosition legendPosition) { const std::string legendPositionName(m_LegendPositionToName.at(legendPosition)); GetC3Data()->SetLegendPosition(QString::fromStdString(legendPositionName)); } QmitkChartWidget::LegendPosition QmitkChartWidget::Impl::GetLegendPosition() const { for (const auto& aLegendPosition : m_LegendPositionToName) { if (aLegendPosition.second == GetLegendPositionAsString()) { return aLegendPosition.first; } } mitkThrow() << "can't find legend position!"; } std::string QmitkChartWidget::Impl::GetLegendPositionAsString() const { return GetC3Data()->GetLegendPosition().toString().toStdString(); } +void QmitkChartWidget::Impl::SetShowDataPoints(bool showDataPoints) { + if (showDataPoints == true) { + GetC3Data()->SetDataPointSize(3); + } + else { + GetC3Data()->SetDataPointSize(0); + } +} + +bool QmitkChartWidget::Impl::GetShowDataPoints() const{ + int value = GetC3Data()->GetDataPointSize().toInt(); + if (value > 0) { + return true; + } + else { + return false; + } +} void QmitkChartWidget::Impl::SetChartType(const std::string& label, QmitkChartWidget::ChartType chartType) { auto element = GetElementByLabel(GetC3xyData(), label); if (element) { const std::string chartTypeName(m_DiagramTypeToName.at(chartType)); element->SetChartType(QVariant(QString::fromStdString(chartTypeName))); } } std::string QmitkChartWidget::Impl::ConvertChartTypeToString(QmitkChartWidget::ChartType diagramType) const { return m_DiagramTypeToName.at(diagramType); } QmitkChartData* QmitkChartWidget::Impl::GetC3Data() const { return m_C3Data; } std::vector* QmitkChartWidget::Impl::GetC3xyData() const { return m_C3xyData; } void QmitkChartWidget::Impl::ClearData() { for (auto& xyData : *m_C3xyData) { m_WebChannel->deregisterObject(xyData); } GetC3xyData()->clear(); } QmitkChartWidget::QmitkChartWidget(QWidget* parent) : QWidget(parent), m_Impl(new Impl(this)) { } void QmitkChartWidget::Impl::CallJavaScriptFuntion(const QString& command) { m_WebEngineView->page()->runJavaScript(command); } void QmitkChartWidget::Impl::ClearJavaScriptChart() { m_WebEngineView->setUrl(QUrl(QStringLiteral("qrc:///C3js/empty.html"))); } void QmitkChartWidget::Impl::InitializeJavaScriptChart() { m_WebChannel->registerObject(QStringLiteral("chartData"), m_C3Data); unsigned count = 0; for (auto& xyData : *m_C3xyData) { QString variableName = "xyData" + QString::number(count); m_WebChannel->registerObject(variableName, xyData); count++; } m_WebEngineView->load(QUrl(QStringLiteral("qrc:///C3js/QmitkChartWidget.html"))); } QmitkChartWidget::~QmitkChartWidget() { delete m_Impl; } void QmitkChartWidget::AddData2D(const std::map& data2D, const std::string& label, ChartType type) { m_Impl->AddData2D(data2D, label, type); } void QmitkChartWidget::SetColor(const std::string& label, const std::string& colorName) { m_Impl->SetColor(label, colorName); } void QmitkChartWidget::SetLineStyle(const std::string& label, LineStyle style) { m_Impl->SetLineStyle(label, style); } void QmitkChartWidget::SetYAxisScale(AxisScale scale) { m_Impl->SetYAxisScale(scale); } void QmitkChartWidget::AddData1D(const std::vector& data1D, const std::string& label, ChartType type) { m_Impl->AddData1D(data1D, label, type); } void QmitkChartWidget::RemoveData(const std::string& label) { m_Impl->RemoveData(label); } void QmitkChartWidget::SetXAxisLabel(const std::string & label) { m_Impl->SetXAxisLabel(label); } std::string QmitkChartWidget::GetXAxisLabel() const { return m_Impl->GetXAxisLabel(); } void QmitkChartWidget::SetYAxisLabel(const std::string & label) { m_Impl->SetYAxisLabel(label); } std::string QmitkChartWidget::GetYAxisLabel() const { return m_Impl->GetYAxisLabel(); } void QmitkChartWidget::SetDiagramTitle(const std::string & title) { m_Impl->SetDiagramTitle(title); } std::string QmitkChartWidget::GetDiagramTitle() const { return m_Impl->GetDiagramTitle(); } +void QmitkChartWidget::SetShowDataPoints(bool showDataPoints) +{ + m_Impl->SetShowDataPoints(showDataPoints); +} +bool QmitkChartWidget::GetShowDataPoints() const +{ + return m_Impl->GetShowDataPoints(); +} + void QmitkChartWidget::SetChartType(const std::string& label, ChartType type) { m_Impl->SetChartType(label, type); } void QmitkChartWidget::SetLegendPosition(LegendPosition position) { m_Impl->SetLegendPosition(position); } QmitkChartWidget::LegendPosition QmitkChartWidget::GetLegendPosition() const { return m_Impl->GetLegendPosition(); } void QmitkChartWidget::Show(bool showSubChart) { if (m_Impl->GetC3xyData()->empty()) { mitkThrow() << "no data available for display in chart"; } this->m_Impl->GetC3Data()->SetAppearance(showSubChart, m_Impl->GetC3xyData()->front()->GetChartType()== QVariant("pie")); m_Impl->InitializeJavaScriptChart(); } void QmitkChartWidget::Clear() { m_Impl->ClearData(); m_Impl->ClearJavaScriptChart(); } void QmitkChartWidget::OnLoadFinished(bool isLoadSuccessfull) { if(isLoadSuccessfull) { emit PageSuccessfullyLoaded(); } } void QmitkChartWidget::SetChartTypeForAllDataAndReload(ChartType type) { auto allData = this->m_Impl->GetC3xyData(); for (auto iterator = allData->begin(); iterator != allData->end(); ++iterator) { SetChartType((*iterator)->GetLabel().toString().toStdString(), type); } auto diagramTypeName = m_Impl->ConvertChartTypeToString(type); const QString command = QString::fromStdString("transformView('" + diagramTypeName + "')"); m_Impl->CallJavaScriptFuntion(command); } void QmitkChartWidget::SetTheme(ChartStyle themeEnabled) { QString command; if (themeEnabled == ChartStyle::darkstyle) { command = QString("changeTheme('dark')"); } else { command = QString("changeTheme('default')"); } m_Impl->CallJavaScriptFuntion(command); } void QmitkChartWidget::Reload(bool showSubChart) { QString subChartString; if (showSubChart) { subChartString = "true"; } else { subChartString = "false"; } const QString command = QString("ReloadChart(" + subChartString + ")"); m_Impl->CallJavaScriptFuntion(command); } diff --git a/Modules/DICOMReader/files.cmake b/Modules/DICOMReader/files.cmake index 07c291c856..b2e1395c9b 100644 --- a/Modules/DICOMReader/files.cmake +++ b/Modules/DICOMReader/files.cmake @@ -1,52 +1,53 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkBaseDICOMReaderService.cpp mitkDICOMFileReader.cpp mitkDICOMTagScanner.cpp mitkDICOMGDCMTagScanner.cpp mitkDICOMDCMTKTagScanner.cpp mitkDICOMImageBlockDescriptor.cpp mitkDICOMITKSeriesGDCMReader.cpp mitkDICOMDatasetSorter.cpp mitkDICOMTagBasedSorter.cpp mitkDICOMGDCMImageFrameInfo.cpp mitkDICOMImageFrameInfo.cpp mitkDICOMIOHelper.cpp mitkDICOMGenericImageFrameInfo.cpp mitkDICOMDatasetAccessingImageFrameInfo.cpp mitkDICOMSortCriterion.cpp mitkDICOMSortByTag.cpp mitkITKDICOMSeriesReaderHelper.cpp mitkEquiDistantBlocksSorter.cpp mitkNormalDirectionConsistencySorter.cpp mitkSortByImagePositionPatient.cpp mitkGantryTiltInformation.cpp mitkClassicDICOMSeriesReader.cpp mitkThreeDnTDICOMSeriesReader.cpp mitkDICOMTag.cpp mitkDICOMTagsOfInterestHelper.cpp mitkDICOMTagCache.cpp mitkDICOMGDCMTagCache.cpp mitkDICOMGenericTagCache.cpp mitkDICOMEnums.cpp mitkDICOMReaderConfigurator.cpp mitkDICOMFileReaderSelector.cpp mitkIDICOMTagsOfInterest.cpp mitkDICOMTagPath.cpp mitkDICOMProperty.cpp mitkDICOMFilesHelper.cpp ) set(RESOURCE_FILES configurations/3D/classicreader.xml configurations/3D/imageposition.xml configurations/3D/imageposition_byacquisition.xml configurations/3D/instancenumber.xml configurations/3D/instancenumber_soft.xml configurations/3D/slicelocation.xml + configurations/3D/simpleinstancenumber_soft.xml configurations/3DnT/classicreader.xml configurations/3DnT/imageposition_byacquisition.xml configurations/3DnT/imageposition_bytriggertime.xml ) diff --git a/Modules/DICOMReader/include/mitkDICOMITKSeriesGDCMReader.h b/Modules/DICOMReader/include/mitkDICOMITKSeriesGDCMReader.h index 6bfd9735a4..2b847a5edb 100644 --- a/Modules/DICOMReader/include/mitkDICOMITKSeriesGDCMReader.h +++ b/Modules/DICOMReader/include/mitkDICOMITKSeriesGDCMReader.h @@ -1,343 +1,369 @@ /*=================================================================== 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 mitkDICOMITKSeriesGDCMReader_h #define mitkDICOMITKSeriesGDCMReader_h #include #include "itkMutexLock.h" #include "mitkDICOMFileReader.h" #include "mitkDICOMDatasetSorter.h" #include "mitkDICOMGDCMImageFrameInfo.h" #include "mitkEquiDistantBlocksSorter.h" #include "mitkNormalDirectionConsistencySorter.h" #include "MitkDICOMReaderExports.h" namespace itk { class TimeProbesCollectorBase; } namespace mitk { /** \ingroup DICOMReaderModule \brief Flexible reader based on itk::ImageSeriesReader and GDCM, for single-slice modalities like CT, MR, PET, CR, etc. Implements the loading processed as structured by DICOMFileReader offers configuration of its loading strategy. Documentation sections: - \ref DICOMITKSeriesGDCMReader_LoadingStrategy - \ref DICOMITKSeriesGDCMReader_ForcedConfiguration - \ref DICOMITKSeriesGDCMReader_UserConfiguration - \ref DICOMITKSeriesGDCMReader_GantryTilt - \ref DICOMITKSeriesGDCMReader_Testing - \ref DICOMITKSeriesGDCMReader_Internals - \ref DICOMITKSeriesGDCMReader_RelatedClasses - \ref DICOMITKSeriesGDCMReader_TiltInternals - \ref DICOMITKSeriesGDCMReader_Condensing \section DICOMITKSeriesGDCMReader_LoadingStrategy Loading strategy The set of input files is processed by a number of DICOMDatasetSorter objects which may do two sort of things: 1. split a list of input frames into multiple lists, based on DICOM tags such as "Rows", "Columns", which cannot be mixed within a single mitk::Image 2. sort the frames within the input lists, based on the values of DICOM tags such as "Image Position Patient" When the DICOMITKSeriesGDCMReader is configured with DICOMDatasetSorter%s, the list of input files is processed as follows: 1. build an initial set of output groups, simply by grouping all input files. 2. for each configured DICOMDatasetSorter, process: - for each output group: 1. set this group's files as input to the sorter 2. let the sorter sort (and split) 3. integrate the sorter's output groups with our own output groups \section DICOMITKSeriesGDCMReader_ForcedConfiguration Forced Configuration In all cases, the reader will add two DICOMDatasetSorter objects that are required to load mitk::Images properly via itk::ImageSeriesReader: 1. As a \b first step, the input files will be split into groups that are not compatible because they differ in essential aspects: - (0028,0010) Number of Rows - (0028,0011) Number of Columns - (0028,0030) Pixel Spacing - (0018,1164) Imager Pixel Spacing - (0020,0037) %Image Orientation (Patient) - (0018,0050) Slice Thickness - (0028,0008) Number of Frames 2. As are two forced \b last steps: 1. There will always be an instance of EquiDistantBlocksSorter, which ensures that there is an equal distance between all the frames of an Image. This is required to achieve correct geometrical positions in the mitk::Image, i.e. it is essential to be able to make measurements in images. - whether or not the distance is required to be orthogonal to the image planes is configured by SetFixTiltByShearing(). - during this check, we need to tolerate some minor errors in documented vs. calculated image origins. The amount of tolerance can be adjusted by SetToleratedOriginOffset() and SetToleratedOriginOffsetToAdaptive(). Please see EquiDistantBlocksSorter for more details. The default should be good for most cases. 2. There is always an instance of NormalDirectionConsistencySorter, which makes the order of images go along the image normals (see NormalDirectionConsistencySorter) \section DICOMITKSeriesGDCMReader_UserConfiguration User Configuration The user of this class can add more sorting steps (similar to the one described in above section) by calling AddSortingElement(). Usually, an application will add sorting by "Image Position Patient", by "Instance Number", and by other relevant tags here. \section DICOMITKSeriesGDCMReader_GantryTilt Gantry tilt handling When CT gantry tilt is used, the gantry plane (= X-Ray source and detector ring) and the vertical plane do not align anymore. This scanner feature is used for example to reduce metal artifacs (e.g. Lee C , Evaluation of Using CT Gantry Tilt Scan on Head and Neck Cancer Patients with Dental Structure: Scans Show Less Metal Artifacts. Presented at: Radiological Society of North America 2011 Scientific Assembly and Annual Meeting; November 27- December 2, 2011 Chicago IL.). The acquired planes of such CT series do not match the expectations of a orthogonal geometry in mitk::Image: if you stack the slices, they show a small shift along the Y axis: \verbatim without tilt with tilt |||||| ////// |||||| ////// -- |||||| --------- ////// -------- table orientation |||||| ////// |||||| ////// Stacked slices: without tilt with tilt -------------- -------------- -------------- -------------- -------------- -------------- -------------- -------------- -------------- -------------- \endverbatim As such gemetries do not "work" in conjunction with mitk::Image, DICOMITKSeriesGDCMReader is able to perform a correction for such series. Whether or not such correction should be attempted is controlled by SetFixTiltByShearing(), the default being correction. For details, see "Internals" below. \section DICOMITKSeriesGDCMReader_Testing Testing A number of tests is implemented in module DICOMTesting, which is documented at \ref DICOMTesting. \section DICOMITKSeriesGDCMReader_Internals Class internals Internally, the class is based on GDCM and it depends heavily on the gdcm::Scanner class. Since the sorting elements (see DICOMDatasetSorter and DICOMSortCriterion) can access tags only via the DICOMDatasetAccess interface, BUT DICOMITKSeriesGDCMReader holds a list of more specific classes DICOMGDCMImageFrameInfo, we must convert between the two types sometimes. This explains the methods ToDICOMDatasetList(), FromDICOMDatasetList(). The intermediate result of all the sorting efforts is held in m_SortingResultInProgress, which is modified through InternalExecuteSortingStep(). \subsection DICOMITKSeriesGDCMReader_RelatedClasses Overview of related classes The following diagram gives an overview of the related classes: \image html implementeditkseriesgdcmreader.jpg \subsection DICOMITKSeriesGDCMReader_TiltInternals Details about the tilt correction The gantry tilt "correction" algorithm fixes two errors introduced by ITK's ImageSeriesReader: - the plane shift that is ignored by ITK's reader is recreated by applying a shearing transformation using itk::ResampleFilter. - the spacing is corrected (it is calculated by ITK's reader from the distance between two origins, which is NOT the slice distance in this special case) Both errors are introduced in itkImageSeriesReader.txx (ImageSeriesReader::GenerateOutputInformation(void)), lines 176 to 245 (as of ITK 3.20) For the correction, we examine two consecutive slices of a series, both described as a pair (origin/orientation): - we calculate if the first origin is on a line along the normal of the second slice - if this is not the case, the geometry will not fit a normal mitk::Image/mitk::Geometry3D - we then project the second origin into the first slice's coordinate system to quantify the shift - both is done in class GantryTiltInformation with quite some comments. The geometry of image stacks with tilted geometries is illustrated below: - green: the DICOM images as described by their tags: origin as a point with the line indicating the orientation - red: the output of ITK ImageSeriesReader: wrong, larger spacing, no tilt - blue: how much a shear must correct \image html tilt-correction.jpg \subsection DICOMITKSeriesGDCMReader_Condensing Sub-classes can condense multiple blocks into a single larger block The sorting/splitting process described above is helpful for at least two more DICOM readers, which either try to load 3D+t images or which load diffusion data. In both cases, a single pixel of the mitk::Image is made up of multiple values, in one case values over time, in the other case multiple measurements of a single point. The specialized readers for these cases (e.g. ThreeDnTDICOMSeriesReader) can reuse most of the methods in DICOMITKSeriesGDCMReader, except that they need an extra step after the usual sorting, in which they can merge already grouped 3D blocks. What blocks are merged depends on the specialized reader's understanding of these images. To allow for such merging, a method Condense3DBlocks() is called as an absolute last step of AnalyzeInputFiles(). Given this, a sub-class could implement only LoadImages() and Condense3DBlocks() instead repeating most of AnalyzeInputFiles(). */ class MITKDICOMREADER_EXPORT DICOMITKSeriesGDCMReader : public DICOMFileReader { public: mitkClassMacro( DICOMITKSeriesGDCMReader, DICOMFileReader ); mitkCloneMacro( DICOMITKSeriesGDCMReader ); itkFactorylessNewMacro( DICOMITKSeriesGDCMReader ); mitkNewMacro1Param( DICOMITKSeriesGDCMReader, unsigned int ); + mitkNewMacro2Param( DICOMITKSeriesGDCMReader, unsigned int, bool ); /** \brief Runs the sorting / splitting process described in \ref DICOMITKSeriesGDCMReader_LoadingStrategy. Method required by DICOMFileReader. */ virtual void AnalyzeInputFiles() override; // void AllocateOutputImages(); /** \brief Loads images using itk::ImageSeriesReader, potentially applies shearing to correct gantry tilt. */ virtual bool LoadImages() override; // re-implemented from super-class virtual bool CanHandleFile(const std::string& filename) override; /** \brief Add an element to the sorting procedure described in \ref DICOMITKSeriesGDCMReader_LoadingStrategy. */ virtual void AddSortingElement(DICOMDatasetSorter* sorter, bool atFront = false); typedef const std::list ConstSorterList; ConstSorterList GetFreelyConfiguredSortingElements() const; /** \brief Controls whether to "fix" tilted acquisitions by shearing the output (see \ref DICOMITKSeriesGDCMReader_GantryTilt). */ void SetFixTiltByShearing(bool on); bool GetFixTiltByShearing() const; /** \brief Controls whether groups of only two images are accepted when ensuring consecutive slices via EquiDistantBlocksSorter. */ void SetAcceptTwoSlicesGroups(bool accept) const; bool GetAcceptTwoSlicesGroups() const; /** \brief See \ref DICOMITKSeriesGDCMReader_ForcedConfiguration. */ void SetToleratedOriginOffsetToAdaptive(double fractionOfInterSliceDistanct = 0.3) const; /** \brief See \ref DICOMITKSeriesGDCMReader_ForcedConfiguration. */ void SetToleratedOriginOffset(double millimeters = 0.005) const; + /** + \brief Ignore all dicom tags that are non-essential for simple 3D volume import. + */ + void SetSimpleVolumeReading(bool read) + { + m_SimpleVolumeReading = read; + }; + + /** + \brief Ignore all dicom tags that are non-essential for simple 3D volume import. + */ + bool GetSimpleVolumeReading() + { + return m_SimpleVolumeReading; + }; + double GetToleratedOriginError() const; bool IsToleratedOriginOffsetAbsolute() const; double GetDecimalPlacesForOrientation() const; virtual bool operator==(const DICOMFileReader& other) const override; virtual DICOMTagPathList GetTagsOfInterest() const override; + static int GetDefaultDecimalPlacesForOrientation() + { + return m_DefaultDecimalPlacesForOrientation; + } + protected: virtual void InternalPrintConfiguration(std::ostream& os) const override; /// \brief Return active C locale static std::string GetActiveLocale(); /** \brief Remember current locale on stack, activate "C" locale. "C" locale is required for correct parsing of numbers by itk::ImageSeriesReader */ void PushLocale() const; /** \brief Activate last remembered locale from locale stack "C" locale is required for correct parsing of numbers by itk::ImageSeriesReader */ void PopLocale() const; - DICOMITKSeriesGDCMReader(unsigned int decimalPlacesForOrientation = 5); + const static int m_DefaultDecimalPlacesForOrientation = 5; + + DICOMITKSeriesGDCMReader(unsigned int decimalPlacesForOrientation = m_DefaultDecimalPlacesForOrientation, bool simpleVolumeImport = false); virtual ~DICOMITKSeriesGDCMReader(); DICOMITKSeriesGDCMReader(const DICOMITKSeriesGDCMReader& other); DICOMITKSeriesGDCMReader& operator=(const DICOMITKSeriesGDCMReader& other); typedef std::vector SortingBlockList; /** \brief "Hook" for sub-classes, see \ref DICOMITKSeriesGDCMReader_Condensing \return REMAINING blocks */ virtual SortingBlockList Condense3DBlocks(SortingBlockList& resultOf3DGrouping); virtual DICOMTagCache::Pointer GetTagCache() const; void SetTagCache( const DICOMTagCache::Pointer& ) override; /// \brief Sorting step as described in \ref DICOMITKSeriesGDCMReader_LoadingStrategy static SortingBlockList InternalExecuteSortingStep( unsigned int sortingStepIndex, const DICOMDatasetSorter::Pointer& sorter, const SortingBlockList& input); /// \brief Loads the mitk::Image by means of an itk::ImageSeriesReader virtual bool LoadMitkImageForOutput(unsigned int o); virtual bool LoadMitkImageForImageBlockDescriptor(DICOMImageBlockDescriptor& block) const; /// \brief Describe this reader's confidence for given SOP class UID static ReaderImplementationLevel GetReaderImplementationLevel(const std::string sopClassUID); private: /// \brief Creates the required sorting steps described in \ref DICOMITKSeriesGDCMReader_ForcedConfiguration - void EnsureMandatorySortersArePresent(unsigned int decimalPlacesForOrientation); + void EnsureMandatorySortersArePresent(unsigned int decimalPlacesForOrientation, bool simpleVolumeImport = false); protected: // NOT nice, made available to ThreeDnTDICOMSeriesReader due to lack of time bool m_FixTiltByShearing; // could be removed by ITKDICOMSeriesReader NOT flagging tilt unless requested to fix it! + bool m_SimpleVolumeReading; + private: SortingBlockList m_SortingResultInProgress; typedef std::list SorterList; SorterList m_Sorter; protected: // NOT nice, made available to ThreeDnTDICOMSeriesReader and ClassicDICOMSeriesReader due to lack of time mitk::EquiDistantBlocksSorter::Pointer m_EquiDistantBlocksSorter; mitk::NormalDirectionConsistencySorter::Pointer m_NormalDirectionConsistencySorter; private: static itk::MutexLock::Pointer s_LocaleMutex; mutable std::stack m_ReplacedCLocales; mutable std::stack m_ReplacedCinLocales; double m_DecimalPlacesForOrientation; DICOMTagCache::Pointer m_TagCache; bool m_ExternalCache; }; } #endif diff --git a/Modules/DICOMReader/resource/configurations/3D/simpleinstancenumber_soft.xml b/Modules/DICOMReader/resource/configurations/3D/simpleinstancenumber_soft.xml new file mode 100644 index 0000000000..32c6396cfa --- /dev/null +++ b/Modules/DICOMReader/resource/configurations/3D/simpleinstancenumber_soft.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Modules/DICOMReader/src/mitkDICOMITKSeriesGDCMReader.cpp b/Modules/DICOMReader/src/mitkDICOMITKSeriesGDCMReader.cpp index 7f71f51123..2961b9cb2b 100644 --- a/Modules/DICOMReader/src/mitkDICOMITKSeriesGDCMReader.cpp +++ b/Modules/DICOMReader/src/mitkDICOMITKSeriesGDCMReader.cpp @@ -1,614 +1,622 @@ /*=================================================================== 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 MBILOG_ENABLE_DEBUG #define ENABLE_TIMING #include #include #include "mitkDICOMITKSeriesGDCMReader.h" #include "mitkITKDICOMSeriesReaderHelper.h" #include "mitkGantryTiltInformation.h" #include "mitkDICOMTagBasedSorter.h" #include "mitkDICOMGDCMTagScanner.h" itk::MutexLock::Pointer mitk::DICOMITKSeriesGDCMReader::s_LocaleMutex = itk::MutexLock::New(); -mitk::DICOMITKSeriesGDCMReader::DICOMITKSeriesGDCMReader( unsigned int decimalPlacesForOrientation ) +mitk::DICOMITKSeriesGDCMReader::DICOMITKSeriesGDCMReader( unsigned int decimalPlacesForOrientation, bool simpleVolumeImport ) : DICOMFileReader() , m_FixTiltByShearing( true ) +, m_SimpleVolumeReading( simpleVolumeImport ) , m_DecimalPlacesForOrientation( decimalPlacesForOrientation ) , m_ExternalCache(false) { - this->EnsureMandatorySortersArePresent( decimalPlacesForOrientation ); + this->EnsureMandatorySortersArePresent( decimalPlacesForOrientation, simpleVolumeImport ); } mitk::DICOMITKSeriesGDCMReader::DICOMITKSeriesGDCMReader( const DICOMITKSeriesGDCMReader& other ) : DICOMFileReader( other ) , m_FixTiltByShearing( false ) , m_SortingResultInProgress( other.m_SortingResultInProgress ) , m_Sorter( other.m_Sorter ) , m_EquiDistantBlocksSorter( other.m_EquiDistantBlocksSorter->Clone() ) , m_NormalDirectionConsistencySorter( other.m_NormalDirectionConsistencySorter->Clone() ) , m_ReplacedCLocales( other.m_ReplacedCLocales ) , m_ReplacedCinLocales( other.m_ReplacedCinLocales ) , m_DecimalPlacesForOrientation( other.m_DecimalPlacesForOrientation ) , m_TagCache( other.m_TagCache ) , m_ExternalCache(other.m_ExternalCache) { } mitk::DICOMITKSeriesGDCMReader::~DICOMITKSeriesGDCMReader() { } mitk::DICOMITKSeriesGDCMReader& mitk::DICOMITKSeriesGDCMReader:: operator=( const DICOMITKSeriesGDCMReader& other ) { if ( this != &other ) { DICOMFileReader::operator =( other ); this->m_FixTiltByShearing = other.m_FixTiltByShearing; this->m_SortingResultInProgress = other.m_SortingResultInProgress; this->m_Sorter = other.m_Sorter; // TODO should clone the list items this->m_EquiDistantBlocksSorter = other.m_EquiDistantBlocksSorter->Clone(); this->m_NormalDirectionConsistencySorter = other.m_NormalDirectionConsistencySorter->Clone(); this->m_ReplacedCLocales = other.m_ReplacedCLocales; this->m_ReplacedCinLocales = other.m_ReplacedCinLocales; this->m_DecimalPlacesForOrientation = other.m_DecimalPlacesForOrientation; this->m_TagCache = other.m_TagCache; } return *this; } bool mitk::DICOMITKSeriesGDCMReader::operator==( const DICOMFileReader& other ) const { if ( const Self* otherSelf = dynamic_cast( &other ) ) { if ( this->m_FixTiltByShearing == otherSelf->m_FixTiltByShearing && *( this->m_EquiDistantBlocksSorter ) == *( otherSelf->m_EquiDistantBlocksSorter ) && ( fabs( this->m_DecimalPlacesForOrientation - otherSelf->m_DecimalPlacesForOrientation ) < eps ) ) { // test sorters for equality if ( this->m_Sorter.size() != otherSelf->m_Sorter.size() ) return false; auto mySorterIter = this->m_Sorter.cbegin(); auto oSorterIter = otherSelf->m_Sorter.cbegin(); for ( ; mySorterIter != this->m_Sorter.cend() && oSorterIter != otherSelf->m_Sorter.cend(); ++mySorterIter, ++oSorterIter ) { if ( !( **mySorterIter == **oSorterIter ) ) return false; // this sorter differs } // nothing differs ==> all is equal return true; } else { return false; } } else { return false; } } void mitk::DICOMITKSeriesGDCMReader::SetFixTiltByShearing( bool on ) { this->Modified(); m_FixTiltByShearing = on; } bool mitk::DICOMITKSeriesGDCMReader::GetFixTiltByShearing() const { return m_FixTiltByShearing; } void mitk::DICOMITKSeriesGDCMReader::SetAcceptTwoSlicesGroups( bool accept ) const { this->Modified(); m_EquiDistantBlocksSorter->SetAcceptTwoSlicesGroups( accept ); } bool mitk::DICOMITKSeriesGDCMReader::GetAcceptTwoSlicesGroups() const { return m_EquiDistantBlocksSorter->GetAcceptTwoSlicesGroups(); } void mitk::DICOMITKSeriesGDCMReader::InternalPrintConfiguration( std::ostream& os ) const { unsigned int sortIndex( 1 ); for ( auto sorterIter = m_Sorter.cbegin(); sorterIter != m_Sorter.cend(); ++sortIndex, ++sorterIter ) { os << "Sorting step " << sortIndex << ":" << std::endl; ( *sorterIter )->PrintConfiguration( os, " " ); } os << "Sorting step " << sortIndex << ":" << std::endl; m_EquiDistantBlocksSorter->PrintConfiguration( os, " " ); } std::string mitk::DICOMITKSeriesGDCMReader::GetActiveLocale() { return setlocale( LC_NUMERIC, nullptr ); } void mitk::DICOMITKSeriesGDCMReader::PushLocale() const { s_LocaleMutex->Lock(); std::string currentCLocale = setlocale( LC_NUMERIC, nullptr ); m_ReplacedCLocales.push( currentCLocale ); setlocale( LC_NUMERIC, "C" ); std::locale currentCinLocale( std::cin.getloc() ); m_ReplacedCinLocales.push( currentCinLocale ); std::locale l( "C" ); std::cin.imbue( l ); s_LocaleMutex->Unlock(); } void mitk::DICOMITKSeriesGDCMReader::PopLocale() const { s_LocaleMutex->Lock(); if ( !m_ReplacedCLocales.empty() ) { setlocale( LC_NUMERIC, m_ReplacedCLocales.top().c_str() ); m_ReplacedCLocales.pop(); } else { MITK_WARN << "Mismatched PopLocale on DICOMITKSeriesGDCMReader."; } if ( !m_ReplacedCinLocales.empty() ) { std::cin.imbue( m_ReplacedCinLocales.top() ); m_ReplacedCinLocales.pop(); } else { MITK_WARN << "Mismatched PopLocale on DICOMITKSeriesGDCMReader."; } s_LocaleMutex->Unlock(); } mitk::DICOMITKSeriesGDCMReader::SortingBlockList mitk::DICOMITKSeriesGDCMReader::Condense3DBlocks( SortingBlockList& input ) { return input; // to be implemented differently by sub-classes } #if defined( MBILOG_ENABLE_DEBUG ) || defined( ENABLE_TIMING ) #define timeStart( part ) timer.Start( part ); #define timeStop( part ) timer.Stop( part ); #else #define timeStart( part ) #define timeStop( part ) #endif void mitk::DICOMITKSeriesGDCMReader::AnalyzeInputFiles() { itk::TimeProbesCollectorBase timer; timeStart( "Reset" ); this->ClearOutputs(); timeStop( "Reset" ); // prepare initial sorting (== list of input files) const StringList inputFilenames = this->GetInputFiles(); timeStart( "Check input for DCM" ); if ( inputFilenames.empty() || !this->CanHandleFile( inputFilenames.front() ) // first || !this->CanHandleFile( inputFilenames.back() ) // last || !this->CanHandleFile( inputFilenames[inputFilenames.size() / 2] ) // roughly central file ) { // TODO a read-as-many-as-possible fallback could be implemented here MITK_DEBUG << "Reader unable to process files.."; return; } timeStop( "Check input for DCM" ); // scan files for sorting-relevant tags if ( m_TagCache.IsNull() || ( m_TagCache->GetMTime()GetMTime() && !m_ExternalCache )) { timeStart( "Tag scanning" ); DICOMGDCMTagScanner::Pointer filescanner = DICOMGDCMTagScanner::New(); filescanner->SetInputFiles( inputFilenames ); filescanner->AddTagPaths( this->GetTagsOfInterest() ); PushLocale(); filescanner->Scan(); PopLocale(); m_TagCache = filescanner->GetScanCache(); // keep alive and make accessible to sub-classes timeStop("Tag scanning"); } else { // ensure that the tag cache contains our required tags AND files and has scanned! } m_SortingResultInProgress.clear(); m_SortingResultInProgress.push_back(m_TagCache->GetFrameInfoList()); // sort and split blocks as configured timeStart( "Sorting frames" ); unsigned int sorterIndex = 0; for ( auto sorterIter = m_Sorter.cbegin(); sorterIter != m_Sorter.cend(); ++sorterIndex, ++sorterIter ) { std::stringstream ss; ss << "Sorting step " << sorterIndex; timeStart( ss.str().c_str() ); m_SortingResultInProgress = this->InternalExecuteSortingStep( sorterIndex, *sorterIter, m_SortingResultInProgress ); timeStop( ss.str().c_str() ); } - // a last extra-sorting step: ensure equidistant slices - timeStart( "EquiDistantBlocksSorter" ); - m_SortingResultInProgress = this->InternalExecuteSortingStep( - sorterIndex++, m_EquiDistantBlocksSorter.GetPointer(), m_SortingResultInProgress ); - timeStop( "EquiDistantBlocksSorter" ); + if ( !m_SimpleVolumeReading ) + { + // a last extra-sorting step: ensure equidistant slices + timeStart( "EquiDistantBlocksSorter" ); + m_SortingResultInProgress = this->InternalExecuteSortingStep( + sorterIndex++, m_EquiDistantBlocksSorter.GetPointer(), m_SortingResultInProgress ); + timeStop( "EquiDistantBlocksSorter" ); + } timeStop( "Sorting frames" ); timeStart( "Condensing 3D blocks" ); m_SortingResultInProgress = this->Condense3DBlocks( m_SortingResultInProgress ); timeStop( "Condensing 3D blocks" ); // provide final result as output timeStart( "Output" ); unsigned int o = this->GetNumberOfOutputs(); this->SetNumberOfOutputs( o + m_SortingResultInProgress.size() ); // Condense3DBlocks may already have added outputs! for ( auto blockIter = m_SortingResultInProgress.cbegin(); blockIter != m_SortingResultInProgress.cend(); ++o, ++blockIter ) { const DICOMDatasetAccessingImageFrameList& gdcmFrameInfoList = *blockIter; assert( !gdcmFrameInfoList.empty() ); // reverse frames if necessary // update tilt information from absolute last sorting const DICOMDatasetList datasetList = ConvertToDICOMDatasetList( gdcmFrameInfoList ); m_NormalDirectionConsistencySorter->SetInput( datasetList ); m_NormalDirectionConsistencySorter->Sort(); const DICOMDatasetAccessingImageFrameList sortedGdcmInfoFrameList = ConvertToDICOMDatasetAccessingImageFrameList( m_NormalDirectionConsistencySorter->GetOutput( 0 ) ); const GantryTiltInformation& tiltInfo = m_NormalDirectionConsistencySorter->GetTiltInformation(); // set frame list for current block const DICOMImageFrameList frameList = ConvertToDICOMImageFrameList( sortedGdcmInfoFrameList ); assert( !frameList.empty() ); DICOMImageBlockDescriptor block; block.SetTagCache( this->GetTagCache() ); // important: this must be before SetImageFrameList(), because // SetImageFrameList will trigger reading of lots of interesting // tags! block.SetAdditionalTagsOfInterest( GetAdditionalTagsOfInterest() ); block.SetTagLookupTableToPropertyFunctor( GetTagLookupTableToPropertyFunctor() ); block.SetImageFrameList( frameList ); block.SetTiltInformation( tiltInfo ); block.SetReaderImplementationLevel( this->GetReaderImplementationLevel( block.GetSOPClassUID() ) ); this->SetOutput( o, block ); } timeStop( "Output" ); #if defined( MBILOG_ENABLE_DEBUG ) || defined( ENABLE_TIMING ) std::cout << "---------------------------------------------------------------" << std::endl; timer.Report( std::cout ); std::cout << "---------------------------------------------------------------" << std::endl; #endif } mitk::DICOMITKSeriesGDCMReader::SortingBlockList mitk::DICOMITKSeriesGDCMReader::InternalExecuteSortingStep( unsigned int sortingStepIndex, const DICOMDatasetSorter::Pointer& sorter, const SortingBlockList& input ) { SortingBlockList nextStepSorting; // we should not modify our input list while processing it std::stringstream ss; ss << "Sorting step " << sortingStepIndex << " '"; #if defined( MBILOG_ENABLE_DEBUG ) sorter->PrintConfiguration( ss ); #endif ss << "'"; nextStepSorting.clear(); MITK_DEBUG << "================================================================================"; MITK_DEBUG << "DICOMITKSeriesGDCMReader: " << ss.str() << ": " << input.size() << " groups input"; unsigned int groupIndex = 0; for ( auto blockIter = input.cbegin(); blockIter != input.cend(); ++groupIndex, ++blockIter ) { const DICOMDatasetAccessingImageFrameList& gdcmInfoFrameList = *blockIter; const DICOMDatasetList datasetList = ConvertToDICOMDatasetList( gdcmInfoFrameList ); #if defined( MBILOG_ENABLE_DEBUG ) MITK_DEBUG << "--------------------------------------------------------------------------------"; MITK_DEBUG << "DICOMITKSeriesGDCMReader: " << ss.str() << ", dataset group " << groupIndex << " (" << datasetList.size() << " datasets): "; for ( auto oi = datasetList.cbegin(); oi != datasetList.cend(); ++oi ) { MITK_DEBUG << " INPUT : " << ( *oi )->GetFilenameIfAvailable(); } #endif sorter->SetInput( datasetList ); sorter->Sort(); unsigned int numberOfResultingBlocks = sorter->GetNumberOfOutputs(); for ( unsigned int b = 0; b < numberOfResultingBlocks; ++b ) { const DICOMDatasetList blockResult = sorter->GetOutput( b ); for ( auto oi = blockResult.cbegin(); oi != blockResult.cend(); ++oi ) { MITK_DEBUG << " OUTPUT(" << b << ") :" << ( *oi )->GetFilenameIfAvailable(); } DICOMDatasetAccessingImageFrameList sortedGdcmInfoFrameList = ConvertToDICOMDatasetAccessingImageFrameList( blockResult ); nextStepSorting.push_back( sortedGdcmInfoFrameList ); } } return nextStepSorting; } mitk::ReaderImplementationLevel mitk::DICOMITKSeriesGDCMReader::GetReaderImplementationLevel( const std::string sopClassUID ) { if ( sopClassUID.empty() ) { return SOPClassUnknown; } gdcm::UIDs uidKnowledge; uidKnowledge.SetFromUID( sopClassUID.c_str() ); gdcm::UIDs::TSType gdcmType = uidKnowledge; switch ( gdcmType ) { case gdcm::UIDs::CTImageStorage: case gdcm::UIDs::MRImageStorage: case gdcm::UIDs::PositronEmissionTomographyImageStorage: case gdcm::UIDs::ComputedRadiographyImageStorage: case gdcm::UIDs::DigitalXRayImageStorageForPresentation: case gdcm::UIDs::DigitalXRayImageStorageForProcessing: return SOPClassSupported; case gdcm::UIDs::NuclearMedicineImageStorage: return SOPClassPartlySupported; case gdcm::UIDs::SecondaryCaptureImageStorage: return SOPClassImplemented; default: return SOPClassUnsupported; } } // void AllocateOutputImages(); bool mitk::DICOMITKSeriesGDCMReader::LoadImages() { bool success = true; unsigned int numberOfOutputs = this->GetNumberOfOutputs(); for ( unsigned int o = 0; o < numberOfOutputs; ++o ) { success &= this->LoadMitkImageForOutput( o ); } return success; } bool mitk::DICOMITKSeriesGDCMReader::LoadMitkImageForImageBlockDescriptor( DICOMImageBlockDescriptor& block ) const { PushLocale(); const DICOMImageFrameList& frames = block.GetImageFrameList(); const GantryTiltInformation tiltInfo = block.GetTiltInformation(); bool hasTilt = tiltInfo.IsRegularGantryTilt(); ITKDICOMSeriesReaderHelper::StringContainer filenames; filenames.reserve( frames.size() ); for ( auto frameIter = frames.cbegin(); frameIter != frames.cend(); ++frameIter ) { filenames.push_back( ( *frameIter )->Filename ); } mitk::ITKDICOMSeriesReaderHelper helper; bool success( true ); try { mitk::Image::Pointer mitkImage = helper.Load( filenames, m_FixTiltByShearing && hasTilt, tiltInfo ); block.SetMitkImage( mitkImage ); } catch ( const std::exception& e ) { success = false; MITK_ERROR << "Exception during image loading: " << e.what(); } PopLocale(); return success; } bool mitk::DICOMITKSeriesGDCMReader::LoadMitkImageForOutput( unsigned int o ) { DICOMImageBlockDescriptor& block = this->InternalGetOutput( o ); return this->LoadMitkImageForImageBlockDescriptor( block ); } bool mitk::DICOMITKSeriesGDCMReader::CanHandleFile( const std::string& filename ) { return ITKDICOMSeriesReaderHelper::CanHandleFile( filename ); } void mitk::DICOMITKSeriesGDCMReader::AddSortingElement( DICOMDatasetSorter* sorter, bool atFront ) { assert( sorter ); if ( atFront ) { m_Sorter.push_front( sorter ); } else { m_Sorter.push_back( sorter ); } this->Modified(); } mitk::DICOMITKSeriesGDCMReader::ConstSorterList mitk::DICOMITKSeriesGDCMReader::GetFreelyConfiguredSortingElements() const { std::list result; unsigned int sortIndex( 0 ); for ( auto sorterIter = m_Sorter.begin(); sorterIter != m_Sorter.end(); ++sortIndex, ++sorterIter ) { if ( sortIndex > 0 ) // ignore first element (see EnsureMandatorySortersArePresent) { result.push_back( ( *sorterIter ).GetPointer() ); } } return result; } void mitk::DICOMITKSeriesGDCMReader::EnsureMandatorySortersArePresent( - unsigned int decimalPlacesForOrientation ) + unsigned int decimalPlacesForOrientation, bool simpleVolumeImport ) { DICOMTagBasedSorter::Pointer splitter = DICOMTagBasedSorter::New(); splitter->AddDistinguishingTag( DICOMTag(0x0028, 0x0010) ); // Number of Rows splitter->AddDistinguishingTag( DICOMTag(0x0028, 0x0011) ); // Number of Columns splitter->AddDistinguishingTag( DICOMTag(0x0028, 0x0030) ); // Pixel Spacing splitter->AddDistinguishingTag( DICOMTag(0x0018, 0x1164) ); // Imager Pixel Spacing splitter->AddDistinguishingTag( DICOMTag(0x0020, 0x0037), new mitk::DICOMTagBasedSorter::CutDecimalPlaces(decimalPlacesForOrientation) ); // Image Orientation (Patient) splitter->AddDistinguishingTag( DICOMTag(0x0018, 0x0050) ); // Slice Thickness - splitter->AddDistinguishingTag( DICOMTag(0x0028, 0x0008) ); // Number of Frames + if ( !simpleVolumeImport ) + { + std::cout << "Simple volume reading: ignoring number of frames" << std::endl; + splitter->AddDistinguishingTag( DICOMTag(0x0028, 0x0008) ); // Number of Frames + } this->AddSortingElement( splitter, true ); // true = at front if ( m_EquiDistantBlocksSorter.IsNull() ) { m_EquiDistantBlocksSorter = mitk::EquiDistantBlocksSorter::New(); } m_EquiDistantBlocksSorter->SetAcceptTilt( m_FixTiltByShearing ); if ( m_NormalDirectionConsistencySorter.IsNull() ) { m_NormalDirectionConsistencySorter = mitk::NormalDirectionConsistencySorter::New(); } } void mitk::DICOMITKSeriesGDCMReader::SetToleratedOriginOffsetToAdaptive( double fractionOfInterSliceDistance ) const { assert( m_EquiDistantBlocksSorter.IsNotNull() ); m_EquiDistantBlocksSorter->SetToleratedOriginOffsetToAdaptive( fractionOfInterSliceDistance ); this->Modified(); } void mitk::DICOMITKSeriesGDCMReader::SetToleratedOriginOffset( double millimeters ) const { assert( m_EquiDistantBlocksSorter.IsNotNull() ); m_EquiDistantBlocksSorter->SetToleratedOriginOffset( millimeters ); this->Modified(); } double mitk::DICOMITKSeriesGDCMReader::GetToleratedOriginError() const { assert( m_EquiDistantBlocksSorter.IsNotNull() ); return m_EquiDistantBlocksSorter->GetToleratedOriginOffset(); } bool mitk::DICOMITKSeriesGDCMReader::IsToleratedOriginOffsetAbsolute() const { assert( m_EquiDistantBlocksSorter.IsNotNull() ); return m_EquiDistantBlocksSorter->IsToleratedOriginOffsetAbsolute(); } double mitk::DICOMITKSeriesGDCMReader::GetDecimalPlacesForOrientation() const { return m_DecimalPlacesForOrientation; } mitk::DICOMTagCache::Pointer mitk::DICOMITKSeriesGDCMReader::GetTagCache() const { return m_TagCache; } void mitk::DICOMITKSeriesGDCMReader::SetTagCache( const DICOMTagCache::Pointer& tagCache ) { m_TagCache = tagCache; m_ExternalCache = tagCache.IsNotNull(); } mitk::DICOMTagPathList mitk::DICOMITKSeriesGDCMReader::GetTagsOfInterest() const { DICOMTagPathList completeList; // check all configured sorters for ( auto sorterIter = m_Sorter.cbegin(); sorterIter != m_Sorter.cend(); ++sorterIter ) { assert( sorterIter->IsNotNull() ); const DICOMTagList tags = ( *sorterIter )->GetTagsOfInterest(); completeList.insert( completeList.end(), tags.cbegin(), tags.cend() ); } // check our own forced sorters DICOMTagList tags = m_EquiDistantBlocksSorter->GetTagsOfInterest(); completeList.insert( completeList.end(), tags.cbegin(), tags.cend() ); tags = m_NormalDirectionConsistencySorter->GetTagsOfInterest(); completeList.insert( completeList.end(), tags.cbegin(), tags.cend() ); // add the tags for DICOMImageBlockDescriptor tags = DICOMImageBlockDescriptor::GetTagsOfInterest(); completeList.insert( completeList.end(), tags.cbegin(), tags.cend() ); const AdditionalTagsMapType tagList = GetAdditionalTagsOfInterest(); for ( auto iter = tagList.cbegin(); iter != tagList.cend(); ++iter ) { completeList.push_back( iter->first ) ; } return completeList; } diff --git a/Modules/DICOMReader/src/mitkDICOMReaderConfigurator.cpp b/Modules/DICOMReader/src/mitkDICOMReaderConfigurator.cpp index ab885de7c2..c460533882 100644 --- a/Modules/DICOMReader/src/mitkDICOMReaderConfigurator.cpp +++ b/Modules/DICOMReader/src/mitkDICOMReaderConfigurator.cpp @@ -1,688 +1,693 @@ /*=================================================================== 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 "mitkDICOMReaderConfigurator.h" #include "mitkDICOMSortByTag.h" #include "mitkSortByImagePositionPatient.h" mitk::DICOMReaderConfigurator ::DICOMReaderConfigurator() { } mitk::DICOMReaderConfigurator ::~DICOMReaderConfigurator() { } mitk::DICOMFileReader::Pointer mitk::DICOMReaderConfigurator ::CreateFromConfigFile(const std::string& filename) const { TiXmlDocument doc (filename); if (doc.LoadFile()) { return this->CreateFromTiXmlDocument( doc ); } else { MITK_ERROR << "Unable to load file at '" << filename <<"'"; return DICOMFileReader::Pointer(); } } mitk::DICOMFileReader::Pointer mitk::DICOMReaderConfigurator ::CreateFromUTF8ConfigString(const std::string& xmlContents) const { TiXmlDocument doc; doc.Parse(xmlContents.c_str(), nullptr, TIXML_ENCODING_UTF8); return this->CreateFromTiXmlDocument( doc ); } mitk::DICOMFileReader::Pointer mitk::DICOMReaderConfigurator ::CreateFromTiXmlDocument(TiXmlDocument& doc) const { TiXmlHandle root(doc.RootElement()); if (TiXmlElement* rootElement = root.ToElement()) { if (strcmp(rootElement->Value(), "DICOMFileReader")) // :-( no std::string methods { MITK_ERROR << "File should contain a tag at top-level! Found '" << (rootElement->Value() ? std::string(rootElement->Value()) : std::string("!nothing!")) << "' instead"; return nullptr; } const char* classnameC = rootElement->Attribute("class"); if (!classnameC) { MITK_ERROR << "File should name a reader class in the class attribute: . Found nothing instead"; return nullptr; } int version(1); if ( rootElement->QueryIntAttribute("version", &version) == TIXML_SUCCESS) { if (version != 1) { MITK_WARN << "This reader is only capable of creating DICOMFileReaders of version 1. " << "Will not continue, because given configuration is meant for version " << version << "."; return nullptr; } } else { MITK_ERROR << "File should name the version of the reader class in the version attribute: ." << " Found nothing instead, assuming version 1!"; version = 1; } std::string classname(classnameC); double decimalPlacesForOrientation(5); bool useDecimalPlacesForOrientation(false); useDecimalPlacesForOrientation = rootElement->QueryDoubleAttribute("decimalPlacesForOrientation", &decimalPlacesForOrientation) == TIXML_SUCCESS; // attribute present and a double value if (classname == "ClassicDICOMSeriesReader") { mitk::ClassicDICOMSeriesReader::Pointer reader = mitk::ClassicDICOMSeriesReader::New(); this->ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(reader.GetPointer(), rootElement); this->ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(reader.GetPointer(), rootElement); return reader.GetPointer(); } if (classname == "ThreeDnTDICOMSeriesReader") { mitk::ThreeDnTDICOMSeriesReader::Pointer reader; if (useDecimalPlacesForOrientation) reader = mitk::ThreeDnTDICOMSeriesReader::New(decimalPlacesForOrientation); else reader = mitk::ThreeDnTDICOMSeriesReader::New(); return ConfigureThreeDnTDICOMSeriesReader(reader, rootElement).GetPointer(); } else if (classname == "DICOMITKSeriesGDCMReader") { + const char* simpleVolumeImportC = rootElement->Attribute("simpleVolumeImport"); + bool simpleVolumeImport = simpleVolumeImportC ? true : false; + mitk::DICOMITKSeriesGDCMReader::Pointer reader; if (useDecimalPlacesForOrientation) - reader = mitk::DICOMITKSeriesGDCMReader::New(decimalPlacesForOrientation); + reader = mitk::DICOMITKSeriesGDCMReader::New( decimalPlacesForOrientation, simpleVolumeImport ); else - reader = mitk::DICOMITKSeriesGDCMReader::New(); + reader = mitk::DICOMITKSeriesGDCMReader::New( mitk::DICOMITKSeriesGDCMReader::GetDefaultDecimalPlacesForOrientation(), simpleVolumeImport ); + + // simple volume import that ignores number of frames and inter slice distance return ConfigureDICOMITKSeriesGDCMReader(reader, rootElement).GetPointer(); } else { MITK_ERROR << "DICOMFileReader tag names unknown class '" << classname << "'"; return nullptr; } } else { MITK_ERROR << "Great confusion: no root element in XML document. Expecting a DICOMFileReader tag at top-level."; return nullptr; } } #define boolStringTrue(s) \ ( s == "true" || s == "on" || s == "1" \ || s == "TRUE" || s == "ON") void mitk::DICOMReaderConfigurator ::ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, TiXmlElement* element) const { // add the "group3DnT" flag bool group3DnT(true); const char* group3DnTC = element->Attribute("group3DnT"); if (group3DnTC) { std::string group3DnTS(group3DnTC); group3DnT = boolStringTrue(group3DnTS); } reader->SetGroup3DandT( group3DnT ); } mitk::ThreeDnTDICOMSeriesReader::Pointer mitk::DICOMReaderConfigurator ::ConfigureThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, TiXmlElement* element) const { assert(element); // use all the base class configuration if (this->ConfigureDICOMITKSeriesGDCMReader( reader.GetPointer(), element ).IsNull()) { return nullptr; } this->ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(reader,element); return reader; } void mitk::DICOMReaderConfigurator ::ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement* element) const { assert(element); const char* configLabelC = element->Attribute("label"); if (configLabelC) { std::string configLabel(configLabelC); reader->SetConfigurationLabel(configLabel); } const char* configDescriptionC = element->Attribute("description"); if (configDescriptionC) { reader->SetConfigurationDescription(configDescriptionC); } // "fixTiltByShearing" flag bool fixTiltByShearing(false); const char* fixTiltByShearingC = element->Attribute("fixTiltByShearing"); if (fixTiltByShearingC) { std::string fixTiltByShearingS(fixTiltByShearingC); fixTiltByShearing = boolStringTrue(fixTiltByShearingS); } reader->SetFixTiltByShearing( fixTiltByShearing ); } mitk::DICOMITKSeriesGDCMReader::Pointer mitk::DICOMReaderConfigurator ::ConfigureDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement* element) const { assert(element); this->ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(reader, element); // "acceptTwoSlicesGroups" flag bool acceptTwoSlicesGroups(true); const char* acceptTwoSlicesGroupsC = element->Attribute("acceptTwoSlicesGroups"); if (acceptTwoSlicesGroupsC) { std::string acceptTwoSlicesGroupsS(acceptTwoSlicesGroupsC); acceptTwoSlicesGroups = boolStringTrue(acceptTwoSlicesGroupsS); } reader->SetAcceptTwoSlicesGroups( acceptTwoSlicesGroups ); // "toleratedOriginError" attribute (double) bool toleratedOriginErrorIsAbsolute(false); const char* toleratedOriginErrorIsAbsoluteC = element->Attribute("toleratedOriginErrorIsAbsolute"); if (toleratedOriginErrorIsAbsoluteC) { std::string toleratedOriginErrorIsAbsoluteS(toleratedOriginErrorIsAbsoluteC); toleratedOriginErrorIsAbsolute = boolStringTrue(toleratedOriginErrorIsAbsoluteS); } double toleratedOriginError(0.3); if (element->QueryDoubleAttribute("toleratedOriginError", &toleratedOriginError) == TIXML_SUCCESS) // attribute present and a double value { if (toleratedOriginErrorIsAbsolute) { reader->SetToleratedOriginOffset( toleratedOriginError ); } else { reader->SetToleratedOriginOffsetToAdaptive( toleratedOriginError ); } } // DICOMTagBasedSorters are the only thing we create at this point // TODO for-loop over all child elements of type DICOMTagBasedSorter, BUT actually a single sorter of this type is enough. TiXmlElement* dElement = element->FirstChildElement("DICOMDatasetSorter"); if (dElement) { const char* classnameC = dElement->Attribute("class"); if (!classnameC) { MITK_ERROR << "File should name a DICOMDatasetSorter class in the class attribute of . Found nothing instead"; return nullptr; } std::string classname(classnameC); if (classname == "DICOMTagBasedSorter") { DICOMTagBasedSorter::Pointer tagSorter = CreateDICOMTagBasedSorter(dElement); if (tagSorter.IsNotNull()) { reader->AddSortingElement( tagSorter ); } } else { MITK_ERROR << "DICOMDatasetSorter tag names unknown class '" << classname << "'"; return nullptr; } } return reader; } mitk::DICOMTagBasedSorter::Pointer mitk::DICOMReaderConfigurator ::CreateDICOMTagBasedSorter(TiXmlElement* element) const { mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New(); // "strictSorting" parameter! bool strictSorting(true); const char* strictSortingC = element->Attribute("strictSorting"); if (strictSortingC) { std::string strictSortingS(strictSortingC); strictSorting = boolStringTrue(strictSortingS); } tagSorter->SetStrictSorting(strictSorting); // "strictSorting" parameter! bool expectDistanceOne(true); const char* expectDistanceOneC = element->Attribute("expectDistanceOne"); if (expectDistanceOneC) { std::string expectDistanceOneS(expectDistanceOneC); expectDistanceOne = boolStringTrue(expectDistanceOneS); } tagSorter->SetExpectDistanceOne(expectDistanceOne); TiXmlElement* dElement = element->FirstChildElement("Distinguishing"); if (dElement) { for ( TiXmlElement* tChild = dElement->FirstChildElement(); tChild != nullptr; tChild = tChild->NextSiblingElement() ) { try { mitk::DICOMTag tag = tagFromXMLElement(tChild); int i(5); if (tChild->QueryIntAttribute("cutDecimalPlaces", &i) == TIXML_SUCCESS) { tagSorter->AddDistinguishingTag( tag, new mitk::DICOMTagBasedSorter::CutDecimalPlaces(i) ); } else { tagSorter->AddDistinguishingTag( tag ); } } catch(...) { return nullptr; } } } // "sorting tags" TiXmlElement* sElement = element->FirstChildElement("Sorting"); if (sElement) { DICOMSortCriterion::Pointer previousCriterion; DICOMSortCriterion::Pointer currentCriterion; for ( TiXmlNode* tChildNode = sElement->LastChild(); tChildNode != nullptr; tChildNode = tChildNode->PreviousSibling() ) { TiXmlElement* tChild = tChildNode->ToElement(); if (!tChild) continue; if (!strcmp(tChild->Value(), "Tag")) { try { currentCriterion = this->CreateDICOMSortByTag(tChild, previousCriterion); } catch(...) { std::stringstream ss; ss << "Could not parse element at (input line " << tChild->Row() << ", col. " << tChild->Column() << ")!"; MITK_ERROR << ss.str(); return nullptr; } } else if (!strcmp(tChild->Value(), "ImagePositionPatient")) { try { currentCriterion = this->CreateSortByImagePositionPatient(tChild, previousCriterion); } catch(...) { std::stringstream ss; ss << "Could not parse element at (input line " << tChild->Row() << ", col. " << tChild->Column() << ")!"; MITK_ERROR << ss.str(); return nullptr; } } else { MITK_ERROR << "File contain unknown tag <" << tChild->Value() << "> tag as child to ! Cannot interpret..."; } previousCriterion = currentCriterion; } tagSorter->SetSortCriterion( currentCriterion.GetPointer() ); } return tagSorter; } std::string mitk::DICOMReaderConfigurator ::requiredStringAttribute(TiXmlElement* xmlElement, const std::string& key) const { assert(xmlElement); const char* gC = xmlElement->Attribute(key.c_str()); if (gC) { std::string gS(gC); return gS; } else { std::stringstream ss; ss << "Expected an attribute '" << key << "' at this position " "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!"; MITK_ERROR << ss.str(); throw std::invalid_argument( ss.str() ); } } unsigned int mitk::DICOMReaderConfigurator ::hexStringToUInt(const std::string& s) const { std::stringstream converter(s); unsigned int ui; converter >> std::hex >> ui; MITK_DEBUG << "Converted string '" << s << "' to unsigned int " << ui; return ui; } mitk::DICOMTag mitk::DICOMReaderConfigurator ::tagFromXMLElement(TiXmlElement* xmlElement) const { assert(xmlElement); if (strcmp(xmlElement->Value(), "Tag")) // :-( no std::string methods { std::stringstream ss; ss << "Expected a tag at this position " "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!"; MITK_ERROR << ss.str(); throw std::invalid_argument( ss.str() ); } std::string groupS = requiredStringAttribute(xmlElement, "group"); std::string elementS = requiredStringAttribute(xmlElement, "element"); try { // convert string to int (assuming string is in hex format with leading "0x" like "0x0020") unsigned int group = hexStringToUInt(groupS); unsigned int element = hexStringToUInt(elementS); return DICOMTag(group, element); } catch(...) { std::stringstream ss; ss << "Expected group and element values in to be hexadecimal with leading 0x, e.g. '0x0020'" "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!"; MITK_ERROR << ss.str(); throw std::invalid_argument( ss.str() ); } } mitk::DICOMSortCriterion::Pointer mitk::DICOMReaderConfigurator ::CreateDICOMSortByTag(TiXmlElement* xmlElement, DICOMSortCriterion::Pointer secondaryCriterion) const { mitk::DICOMTag tag = tagFromXMLElement(xmlElement); return DICOMSortByTag::New(tag, secondaryCriterion).GetPointer(); } mitk::DICOMSortCriterion::Pointer mitk::DICOMReaderConfigurator ::CreateSortByImagePositionPatient(TiXmlElement*, DICOMSortCriterion::Pointer secondaryCriterion) const { return SortByImagePositionPatient::New(secondaryCriterion).GetPointer(); } std::string mitk::DICOMReaderConfigurator ::CreateConfigStringFromReader(DICOMFileReader::ConstPointer reader) const { // check possible sub-classes from the most-specific one up to the most generic one const DICOMFileReader* cPointer = reader; TiXmlElement* root; if (const ClassicDICOMSeriesReader* specificReader = dynamic_cast(cPointer)) { root = this->CreateConfigStringFromReader(specificReader); } else if (const ThreeDnTDICOMSeriesReader* specificReader = dynamic_cast(cPointer)) { root = this->CreateConfigStringFromReader(specificReader); } else if (const DICOMITKSeriesGDCMReader* specificReader = dynamic_cast(cPointer)) { root = this->CreateConfigStringFromReader(specificReader); } else { MITK_WARN << "Unknown reader class passed to DICOMReaderConfigurator::CreateConfigStringFromReader(). Cannot serialize."; return ""; // no serialization, what a pity } if (root) { TiXmlDocument document; document.LinkEndChild( root ); TiXmlPrinter printer; printer.SetIndent( " " ); document.Accept( &printer ); std::string xmltext = printer.CStr(); return xmltext; } else { MITK_WARN << "DICOMReaderConfigurator::CreateConfigStringFromReader() created empty serialization. Problem?"; return ""; } } TiXmlElement* mitk::DICOMReaderConfigurator ::CreateConfigStringFromReader(const DICOMITKSeriesGDCMReader* reader) const { TiXmlElement* root = this->CreateDICOMFileReaderTag(reader); assert(root); root->SetAttribute("fixTiltByShearing", toString(reader->GetFixTiltByShearing())); root->SetAttribute("acceptTwoSlicesGroups", toString(reader->GetAcceptTwoSlicesGroups())); root->SetDoubleAttribute("toleratedOriginError", reader->GetToleratedOriginError()); root->SetAttribute("toleratedOriginErrorIsAbsolute", toString(reader->IsToleratedOriginOffsetAbsolute())); root->SetDoubleAttribute("decimalPlacesForOrientation", reader->GetDecimalPlacesForOrientation()); // iterate DICOMDatasetSorter objects DICOMITKSeriesGDCMReader::ConstSorterList sorterList = reader->GetFreelyConfiguredSortingElements(); for(auto sorterIter = sorterList.begin(); sorterIter != sorterList.end(); ++sorterIter) { const DICOMDatasetSorter* sorter = *sorterIter; if (const DICOMTagBasedSorter* specificSorter = dynamic_cast(sorter)) { TiXmlElement* sorterTag = this->CreateConfigStringFromDICOMDatasetSorter(specificSorter); root->LinkEndChild(sorterTag); } else { MITK_WARN << "Unknown DICOMDatasetSorter class passed to DICOMReaderConfigurator::CreateConfigStringFromReader(). Cannot serialize."; return nullptr; } } return root; } TiXmlElement* mitk::DICOMReaderConfigurator ::CreateConfigStringFromDICOMDatasetSorter(const DICOMTagBasedSorter* sorter) const { assert(sorter); auto sorterTag = new TiXmlElement("DICOMDatasetSorter"); sorterTag->SetAttribute("class", sorter->GetNameOfClass()); sorterTag->SetAttribute("strictSorting", toString(sorter->GetStrictSorting())); sorterTag->SetAttribute("expectDistanceOne", toString(sorter->GetExpectDistanceOne())); auto distinguishingTagsElement = new TiXmlElement("Distinguishing"); sorterTag->LinkEndChild(distinguishingTagsElement); mitk::DICOMTagList distinguishingTags = sorter->GetDistinguishingTags(); for (auto tagIter = distinguishingTags.begin(); tagIter != distinguishingTags.end(); ++tagIter) { TiXmlElement* tag = this->CreateConfigStringFromDICOMTag(*tagIter); distinguishingTagsElement->LinkEndChild(tag); const DICOMTagBasedSorter::TagValueProcessor* processor = sorter->GetTagValueProcessorForDistinguishingTag(*tagIter); if (const DICOMTagBasedSorter::CutDecimalPlaces* specificProcessor = dynamic_cast(processor)) { tag->SetDoubleAttribute("cutDecimalPlaces", specificProcessor->GetPrecision()); } } auto sortingElement = new TiXmlElement("Sorting"); sorterTag->LinkEndChild(sortingElement); mitk::DICOMSortCriterion::ConstPointer sortCriterion = sorter->GetSortCriterion(); while (sortCriterion.IsNotNull()) { std::string classname = sortCriterion->GetNameOfClass(); if (classname == "SortByImagePositionPatient") { sortingElement->LinkEndChild( new TiXmlElement("ImagePositionPatient") ); // no parameters } else if (classname == "DICOMSortByTag") { DICOMTagList pseudoTagList = sortCriterion->GetTagsOfInterest(); if (pseudoTagList.size() == 1) { DICOMTag firstTag = pseudoTagList.front(); TiXmlElement* tagElement = this->CreateConfigStringFromDICOMTag(firstTag); sortingElement->LinkEndChild( tagElement ); } else { MITK_ERROR << "Encountered SortByTag class with MULTIPLE tag in CreateConfigStringFromDICOMDatasetSorter. Cannot serialize."; return nullptr; } } else { MITK_ERROR << "Encountered unknown class '" << classname << "' in CreateConfigStringFromDICOMDatasetSorter. Cannot serialize."; return nullptr; } sortCriterion = sortCriterion->GetSecondaryCriterion(); } return sorterTag; } TiXmlElement* mitk::DICOMReaderConfigurator ::CreateConfigStringFromDICOMTag(const DICOMTag& tag) const { auto tagElement = new TiXmlElement("Tag"); // name group element tagElement->SetAttribute("name", tag.GetName().c_str()); tagElement->SetAttribute("group", toHexString(tag.GetGroup())); tagElement->SetAttribute("element", toHexString(tag.GetElement())); return tagElement; } std::string mitk::DICOMReaderConfigurator ::toHexString(unsigned int i) const { std::stringstream ss; ss << "0x" << std::setfill ('0') << std::setw(4) << std::hex << i; return ss.str(); } TiXmlElement* mitk::DICOMReaderConfigurator ::CreateConfigStringFromReader(const ThreeDnTDICOMSeriesReader* reader) const { TiXmlElement* root = this->CreateConfigStringFromReader(static_cast(reader)); assert(root); root->SetAttribute("group3DnT", toString(reader->GetGroup3DandT())); return root; } const char* mitk::DICOMReaderConfigurator ::toString(bool b) const { return b ? "true" : "false"; } TiXmlElement* mitk::DICOMReaderConfigurator ::CreateConfigStringFromReader(const ClassicDICOMSeriesReader* reader) const { return this->CreateDICOMFileReaderTag(reader); } TiXmlElement* mitk::DICOMReaderConfigurator ::CreateDICOMFileReaderTag(const DICOMFileReader* reader) const { auto readerTag = new TiXmlElement("DICOMFileReader"); readerTag->SetAttribute("class", reader->GetNameOfClass()); readerTag->SetAttribute("label", reader->GetConfigurationLabel().c_str()); readerTag->SetAttribute("description", reader->GetConfigurationDescription().c_str()); readerTag->SetAttribute("version", "1"); return readerTag; } diff --git a/Modules/DICOMReader/test/CMakeLists.txt b/Modules/DICOMReader/test/CMakeLists.txt index 559920cb95..01b228e186 100644 --- a/Modules/DICOMReader/test/CMakeLists.txt +++ b/Modules/DICOMReader/test/CMakeLists.txt @@ -1,10 +1,12 @@ MITK_CREATE_MODULE_TESTS() file(GLOB_RECURSE tinyCTSlices ${MITK_DATA_DIR}/TinyCTAbdomen/1??) +file(GLOB_RECURSE sloppyDICOMfiles ${MITK_DATA_DIR}/SloppyDICOMFiles/1*) -#foreach(f ${tinyCTSlices}) +#foreach(f ${sloppyDICOMfiles}) # message(" ${f}") #endforeach() mitkAddCustomModuleTest(mitkDICOMFileReaderTest_Basics mitkDICOMFileReaderTest ${tinyCTSlices}) mitkAddCustomModuleTest(mitkDICOMITKSeriesGDCMReaderBasicsTest_Basics mitkDICOMITKSeriesGDCMReaderBasicsTest ${tinyCTSlices}) +mitkAddCustomModuleTest(mitkDICOMSimpleVolumeImportTest_Basics mitkDICOMSimpleVolumeImportTest ${sloppyDICOMfiles}) diff --git a/Modules/DICOMReader/test/files.cmake b/Modules/DICOMReader/test/files.cmake index 94f0d1df07..255fd1fe7f 100644 --- a/Modules/DICOMReader/test/files.cmake +++ b/Modules/DICOMReader/test/files.cmake @@ -1,16 +1,17 @@ set(MODULE_TESTS mitkDICOMReaderConfiguratorTest.cpp mitkDICOMDCMTKTagScannerTest.cpp + mitkDICOMSimpleVolumeImportTest.cpp mitkDICOMTagPathTest.cpp mitkDICOMPropertyTest.cpp ) set(MODULE_CUSTOM_TESTS mitkDICOMFileReaderTest.cpp mitkDICOMITKSeriesGDCMReaderBasicsTest.cpp ) set(CPP_FILES mitkDICOMNullFileReader.cpp mitkDICOMFilenameSorter.cpp ) diff --git a/Modules/DICOMReader/test/mitkDICOMFileReaderTestHelper.h b/Modules/DICOMReader/test/mitkDICOMFileReaderTestHelper.h index 2e1f966c2c..b0dd8d72e6 100644 --- a/Modules/DICOMReader/test/mitkDICOMFileReaderTestHelper.h +++ b/Modules/DICOMReader/test/mitkDICOMFileReaderTestHelper.h @@ -1,176 +1,188 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkDICOMFileReaderTestHelper_h #define mitkDICOMFileReaderTestHelper_h #include "mitkDICOMFileReader.h" #include "mitkDICOMEnums.h" #include "mitkTestingMacros.h" namespace mitk { class DICOMFileReaderTestHelper { public: static StringList& GetInputFilenames() { static StringList inputs; return inputs; } static void SetTestInputFilenames(int argc, char* argv[]) { mitk::StringList inputFiles; for (int a = 1; a < argc; ++a) { inputFiles.push_back( argv[a] ); } GetInputFilenames() = inputFiles; } static void SetTestInputFilenames(const StringList& filenames) { GetInputFilenames() = filenames; } static void TestInputFilenames(DICOMFileReader* reader) { StringList inputFiles = GetInputFilenames(); reader->SetInputFiles( inputFiles ); const StringList& inputFilesReturned = reader->GetInputFiles(); MITK_TEST_CONDITION( inputFilesReturned.size() == inputFiles.size(), "Input file list is received") MITK_TEST_CONDITION( reader->GetNumberOfOutputs() == 0, "No outputs without analysis") } static void TestOutputsContainInputs(DICOMFileReader* reader) { StringList inputFiles = GetInputFilenames(); reader->SetInputFiles( inputFiles ); reader->AnalyzeInputFiles(); StringList allSortedInputsFiles; unsigned int numberOfOutputs = reader->GetNumberOfOutputs(); for (unsigned int o = 0; o < numberOfOutputs; ++o) { const DICOMImageBlockDescriptor block = reader->GetOutput(o); const DICOMImageFrameList& outputFiles = block.GetImageFrameList(); for(auto iter = outputFiles.cbegin(); iter != outputFiles.cend(); ++iter) { // check that output is part of input auto inputPositionOfCurrentOutput = std::find( inputFiles.cbegin(), inputFiles.cend(), (*iter)->Filename ); if (inputPositionOfCurrentOutput != inputFiles.cend()) { // check that output is only part of ONE output auto outputPositionOfCurrentOutput = std::find( allSortedInputsFiles.cbegin(), allSortedInputsFiles.cend(), (*iter)->Filename ); if (outputPositionOfCurrentOutput == allSortedInputsFiles.cend()) { // was not in list before allSortedInputsFiles.push_back( *inputPositionOfCurrentOutput ); } else { reader->PrintOutputs(std::cout); MITK_TEST_CONDITION_REQUIRED(false, "File '" << (*iter)->Filename << "' appears in TWO outputs. Readers are expected to use each frame only once." ) } } else { reader->PrintOutputs(std::cout); MITK_TEST_CONDITION_REQUIRED(false, "File '" << (*iter)->Filename << "' appears in output, but it was never part of the input list." ) } } } MITK_TEST_CONDITION( allSortedInputsFiles.size() == inputFiles.size(), "Output list size (" << allSortedInputsFiles.size() << ") equals input list size (" << inputFiles.size() << ")" ) try { const DICOMImageBlockDescriptor block = reader->GetOutput( inputFiles.size() ); MITK_TEST_CONDITION(false, "Invalid indices for GetOutput() should throw exception") } catch( std::invalid_argument& ) { MITK_TEST_CONDITION(true, "Invalid indices for GetOutput() should throw exception") } } static void TestMitkImagesAreLoaded( DICOMFileReader* reader, const DICOMFileReader::AdditionalTagsMapType& requestedTags, const std::unordered_map& expectedProperties ) { StringList inputFiles = GetInputFilenames(); reader->SetInputFiles( inputFiles ); reader->AnalyzeInputFiles(); reader->LoadImages(); unsigned int numberOfOutputs = reader->GetNumberOfOutputs(); for (unsigned int o = 0; o < numberOfOutputs; ++o) { const DICOMImageBlockDescriptor block = reader->GetOutput(o); const DICOMImageFrameList& outputFiles = block.GetImageFrameList(); const mitk::Image::Pointer mitkImage = block.GetMitkImage(); for ( auto iter = requestedTags.cbegin(); iter != requestedTags.cend(); ++iter) { mitk::BaseProperty* property = mitkImage->GetProperty( iter->second.c_str() ).GetPointer(); MITK_TEST_CONDITION( property != nullptr, "Requested Tag is available as Property in Image" ); if (property) { MITK_INFO << iter->first.ToStr() << " / " << property->GetNameOfClass(); auto expectfinding = expectedProperties.find(iter->second); if (expectfinding != expectedProperties.end()) { MITK_TEST_CONDITION(std::string(property->GetNameOfClass()) == expectfinding->second, "Property type is as expected"); } } } MITK_DEBUG << "-------------------------------------------"; MITK_DEBUG << "Output " << o << " at " << (void*) mitkImage.GetPointer(); MITK_DEBUG << " Number of files: " << outputFiles.size(); MITK_DEBUG << " Dimensions: " << mitkImage->GetDimension(0) << " " << mitkImage->GetDimension(1) << " " << mitkImage->GetDimension(2); } } +static void TestSingleBlockIsRead( DICOMFileReader* reader ) +{ + StringList inputFiles = GetInputFilenames(); + reader->SetInputFiles( inputFiles ); + reader->AnalyzeInputFiles(); + reader->LoadImages(); + + unsigned int numberOfOutputs = reader->GetNumberOfOutputs(); + + MITK_TEST_CONDITION_REQUIRED( numberOfOutputs == 1, "Single block is read from input files."); +} + static mitk::BaseProperty::Pointer DummyTagToPropertyFunctor( const mitk::StringLookupTable& ) { return mitk::BaseProperty::Pointer(); } }; // end test class } // namespace #endif diff --git a/Modules/DICOMReader/test/mitkDICOMSimpleVolumeImportTest.cpp b/Modules/DICOMReader/test/mitkDICOMSimpleVolumeImportTest.cpp new file mode 100644 index 0000000000..a3bd311f8d --- /dev/null +++ b/Modules/DICOMReader/test/mitkDICOMSimpleVolumeImportTest.cpp @@ -0,0 +1,110 @@ +/*=================================================================== + +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 "mitkDICOMFileReaderSelector.h" +#include "mitkDICOMFileReaderTestHelper.h" + +#include +#include +#include +#include +#include +#include + +#include "mitkImageToItk.h" +#include "itkImageRegionConstIteratorWithIndex.h" + +#include "mitkTestingMacros.h" + +/** + \brief Verify single block reading of SimpleDICOMvolumeImport for sloppily tagged data. +*/ +int mitkDICOMSimpleVolumeImportTest(int argc, char* argv[]) +{ + typedef mitk::DICOMFileReaderSelector::ReaderList ReaderList; + typedef itk::Image< short, 3 > ImageType; + typedef itk::ImageRegionConstIteratorWithIndex< ImageType > IteratorType; + + MITK_TEST_BEGIN("mitkDICOMSimpleVolumeImportTest"); + + us::ModuleResource resource = + us::ModuleRegistry::GetModule("MitkDICOMReader")->GetResource("configurations/3D/simpleinstancenumber_soft.xml"); + + std::string descr; + if ( resource.IsValid() ) + { + us::ModuleResourceStream stream(resource); + + stream.seekg(0, std::ios::end); + descr.reserve(stream.tellg()); + stream.seekg(0, std::ios::beg); + + descr.assign((std::istreambuf_iterator(stream)), + std::istreambuf_iterator()); + } + mitk::DICOMFileReaderSelector::Pointer readerSelector = mitk::DICOMFileReaderSelector::New(); + + readerSelector->AddConfig( descr ); + ReaderList readers = readerSelector->GetAllConfiguredReaders(); + + mitk::DICOMFileReader::Pointer simpleReader; + for ( ReaderList::const_iterator it = readers.begin(); it != readers.end(); ++it ) + { + mitk::DICOMFileReader::Pointer reader = *it; + std::string configLabel = reader->GetConfigurationLabel(); + if ( configLabel == "Instance Number, non-consecutive, simple import" ) + { + simpleReader = reader; + } + } + + MITK_TEST_CONDITION_REQUIRED( simpleReader.IsNotNull(), "DICOMFileReaderSelector is able to create simple reader from XML"); + + if ( argc > 1 ) + { + mitk::DICOMFileReaderTestHelper::SetTestInputFilenames( argc,argv ); + + mitk::DICOMFileReaderTestHelper::TestInputFilenames( simpleReader ); + mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( simpleReader ); + mitk::DICOMFileReaderTestHelper::TestSingleBlockIsRead( simpleReader ); + + const mitk::DICOMImageBlockDescriptor block = simpleReader->GetOutput( 0 ); + const mitk::Image::Pointer mitkImage = block.GetMitkImage(); + + ImageType::Pointer itkImage = mitk::ImageToItkImage( mitkImage ); + + IteratorType it( itkImage, itkImage->GetLargestPossibleRegion() ); + bool success = true; + while ( !it.IsAtEnd() ) + { + ImageType::PixelType val = it.Get(); + ImageType::IndexType ind = it.GetIndex(); + + if ( !(val == ind[2]) ) + { + success = false; + break; + } + + ++it; + } + + MITK_TEST_CONDITION( success, "Single block image composed as expected."); + } + + MITK_TEST_END(); +} + diff --git a/Modules/DICOMReaderServices/files.cmake b/Modules/DICOMReaderServices/files.cmake index be2e245088..b0f9199daa 100644 --- a/Modules/DICOMReaderServices/files.cmake +++ b/Modules/DICOMReaderServices/files.cmake @@ -1,8 +1,9 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkAutoSelectingDICOMReaderService.cpp mitkClassicDICOMSeriesReaderService.cpp mitkDICOMReaderServicesActivator.cpp mitkDICOMTagsOfInterestService.cpp + mitkSimpleVolumeDICOMSeriesReaderService.cpp ) diff --git a/Modules/DICOMReaderServices/include/mitkSimpleVolumeDICOMSeriesReaderService.h b/Modules/DICOMReaderServices/include/mitkSimpleVolumeDICOMSeriesReaderService.h new file mode 100644 index 0000000000..c8566e35f1 --- /dev/null +++ b/Modules/DICOMReaderServices/include/mitkSimpleVolumeDICOMSeriesReaderService.h @@ -0,0 +1,44 @@ +/*=================================================================== + +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 MITKSIMPLEVOLUMEDICOMSERIESREADERSERVICE_H +#define MITKSIMPLEVOLUMEDICOMSERIESREADERSERVICE_H + +#include + +namespace mitk { + + /** + Service wrapper that selects a DICOMITKSeriesGDCMReader configured for a simple and non-restrictive 3D volume import. + */ +class SimpleVolumeDICOMSeriesReaderService : public BaseDICOMReaderService +{ +public: + SimpleVolumeDICOMSeriesReaderService(); + +protected: + /** Returns the reader instance that should be used. The descission may be based + * one the passed relevant file list.*/ + virtual mitk::DICOMFileReader::Pointer GetReader(const mitk::StringList& relevantFiles) const override; + +private: + virtual SimpleVolumeDICOMSeriesReaderService* Clone() const override; + +}; + +} + +#endif // MITKSIMPLEVOLUMEDICOMSERIESREADERSERVICE_H diff --git a/Modules/DICOMReaderServices/src/mitkDICOMReaderServicesActivator.cpp b/Modules/DICOMReaderServices/src/mitkDICOMReaderServicesActivator.cpp index 6597bda813..76982088ab 100644 --- a/Modules/DICOMReaderServices/src/mitkDICOMReaderServicesActivator.cpp +++ b/Modules/DICOMReaderServices/src/mitkDICOMReaderServicesActivator.cpp @@ -1,48 +1,50 @@ /*=================================================================== 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 "mitkDICOMReaderServicesActivator.h" #include "mitkAutoSelectingDICOMReaderService.h" #include "mitkClassicDICOMSeriesReaderService.h" #include "mitkDICOMTagsOfInterestService.h" +#include "mitkSimpleVolumeDICOMSeriesReaderService.h" #include namespace mitk { void DICOMReaderServicesActivator::Load(us::ModuleContext* context) { m_AutoSelectingDICOMReader.reset(new AutoSelectingDICOMReaderService()); m_ClassicDICOMSeriesReader.reset(new ClassicDICOMSeriesReaderService()); + m_SimpleVolumeDICOMSeriesReader.reset(new SimpleVolumeDICOMSeriesReaderService()); m_DICOMTagsOfInterestService.reset(new DICOMTagsOfInterestService()); context->RegisterService(m_DICOMTagsOfInterestService.get()); DICOMTagPathMapType tagmap = GetDefaultDICOMTagsOfInterest(); for (auto tag : tagmap) { m_DICOMTagsOfInterestService->AddTagOfInterest(tag.first); } } void DICOMReaderServicesActivator::Unload(us::ModuleContext*) { } } US_EXPORT_MODULE_ACTIVATOR(mitk::DICOMReaderServicesActivator) diff --git a/Modules/DICOMReaderServices/src/mitkDICOMReaderServicesActivator.h b/Modules/DICOMReaderServices/src/mitkDICOMReaderServicesActivator.h index 175c0158fa..f095c7a995 100644 --- a/Modules/DICOMReaderServices/src/mitkDICOMReaderServicesActivator.h +++ b/Modules/DICOMReaderServices/src/mitkDICOMReaderServicesActivator.h @@ -1,51 +1,52 @@ /*=================================================================== 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 MITKDICOMREADERSERVICESACTIVATOR_H #define MITKDICOMREADERSERVICESACTIVATOR_H #include #include #include namespace mitk { struct IFileReader; class IDICOMTagsOfInterest; class DICOMReaderServicesActivator : public us::ModuleActivator { public: void Load(us::ModuleContext* context) override; void Unload(us::ModuleContext* context) override; void AliasServiceChanged(const us::ServiceEvent event); private: std::unique_ptr m_AutoSelectingDICOMReader; std::unique_ptr m_ClassicDICOMSeriesReader; + std::unique_ptr m_SimpleVolumeDICOMSeriesReader; std::unique_ptr m_DICOMTagsOfInterestService; us::ModuleContext* mitkContext; }; } #endif // MITKDICOMREADERSERVICESACTIVATOR_H diff --git a/Modules/DICOMReaderServices/src/mitkSimpleVolumeDICOMSeriesReaderService.cpp b/Modules/DICOMReaderServices/src/mitkSimpleVolumeDICOMSeriesReaderService.cpp new file mode 100644 index 0000000000..53925edcd8 --- /dev/null +++ b/Modules/DICOMReaderServices/src/mitkSimpleVolumeDICOMSeriesReaderService.cpp @@ -0,0 +1,68 @@ +/*=================================================================== + +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 "mitkSimpleVolumeDICOMSeriesReaderService.h" +#include "mitkDICOMReaderConfigurator.h" +#include + +#include +#include +#include +#include +#include +#include + +namespace mitk { + + SimpleVolumeDICOMSeriesReaderService::SimpleVolumeDICOMSeriesReaderService() + : BaseDICOMReaderService("MITK Simple Volume Importer") +{ + this->RegisterService(); +} + +DICOMFileReader::Pointer SimpleVolumeDICOMSeriesReaderService::GetReader(const mitk::StringList& relevantFiles) const +{ + mitk::StringList files = relevantFiles; + std::string descr; + + us::ModuleResource resource = + us::ModuleRegistry::GetModule("MitkDICOMReader")->GetResource("configurations/3D/simpleinstancenumber_soft.xml"); + + if ( resource.IsValid() ) + { + us::ModuleResourceStream stream(resource); + + stream.seekg(0, std::ios::end); + descr.reserve(stream.tellg()); + stream.seekg(0, std::ios::beg); + + descr.assign((std::istreambuf_iterator(stream)), + std::istreambuf_iterator()); + } + + DICOMReaderConfigurator::Pointer configurator = DICOMReaderConfigurator::New(); + DICOMFileReader::Pointer reader = configurator->CreateFromUTF8ConfigString(descr); + + return reader.GetPointer(); +}; + + + SimpleVolumeDICOMSeriesReaderService* SimpleVolumeDICOMSeriesReaderService::Clone() const + { + return new SimpleVolumeDICOMSeriesReaderService(*this); + } + +} diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp index 248009363d..68b7e3656c 100644 --- a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp @@ -1,3920 +1,3919 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "mitkFreeSurferParcellationTranslator.h" -using namespace mitk; -using namespace std; +using namespace mitk; /*########### Static Members ###########*/ LookupTable::Pointer FreeSurferParcellationTranslator::m_LookupTable = FreeSurferParcellationTranslator::CreateLookupTable(); const FreeSurferParcellationTranslator::NameTable FreeSurferParcellationTranslator::m_NameTable = FreeSurferParcellationTranslator::CreateNameTable(); TransferFunction::Pointer FreeSurferParcellationTranslator::m_TransferFunction = FreeSurferParcellationTranslator::CreateTransferFunction(); /*########### Constructors ###########*/ FreeSurferParcellationTranslator::FreeSurferParcellationTranslator() { } FreeSurferParcellationTranslator::~FreeSurferParcellationTranslator() { } /*########### Methods ###########*/ // Assign the lookup table to the given node void FreeSurferParcellationTranslator::AssignLookupTable(DataNode::Pointer node) const { LookupTableProperty::Pointer lookupTableProp = LookupTableProperty::New( this->GetLookupTable() ); node->SetProperty( "LookupTable", lookupTableProp ); } // Assign the color transfer function to the given node void FreeSurferParcellationTranslator::AssignTransferFunction(DataNode::Pointer node) const { TransferFunctionProperty::Pointer transferFunctionProp = TransferFunctionProperty::New( this->GetTransferFunction() ); node->SetProperty( "Image Rendering.Transfer Function", transferFunctionProp ); } // Get the label assigned to the given name -const string FreeSurferParcellationTranslator::GetLabel(const string& name) const +const std::string FreeSurferParcellationTranslator::GetLabel(const std::string& name) const { NameTable::const_iterator iter; for( iter = m_NameTable.begin(); iter != m_NameTable.end(); ++iter ) { if( iter->second == name ) return iter->first; } return "0"; } // Get the label assigned to the given name as integer -int FreeSurferParcellationTranslator::GetLabelAsNumber(const string &name) const +int FreeSurferParcellationTranslator::GetLabelAsNumber(const std::string &name) const { return std::atoi(this->GetLabel( name ).c_str()) ; } // Return the lookup table LookupTable::Pointer FreeSurferParcellationTranslator::GetLookupTable() const { return m_LookupTable; } // Get the name assigned to the given label -const string FreeSurferParcellationTranslator::GetName(const string & label) const +const std::string FreeSurferParcellationTranslator::GetName(const std::string & label) const { auto endIter = this->m_NameTable.end(); auto iter = this->m_NameTable.find( label ); if( iter != endIter ) { return iter->second; } else { return "Unknown area or outside the cerebrum."; } } // Get the name assigned to the given label -const string FreeSurferParcellationTranslator::GetName(int label) const +const std::string FreeSurferParcellationTranslator::GetName(int label) const { - stringstream ss;//create a stringstream + std::stringstream ss;//create a stringstream ss << label;//add number to the stream return this->GetName( ss.str() ); } // Get the transfer function TransferFunction::Pointer FreeSurferParcellationTranslator::GetTransferFunction() const { return m_TransferFunction; } LookupTable::Pointer FreeSurferParcellationTranslator::CreateLookupTable() { vtkSmartPointer table = vtkSmartPointer::New(); table->SetRange(0.0, 14175.0); table->SetNumberOfTableValues( 14176.0 ); // Count of the overall range (0 - 14175) table->Build(); table->SetTableValue( 0.0, 0, 0, 0, 0); table->SetTableValue( 1.0, 0.27451, 0.509804, 0.705882 ); table->SetTableValue( 2.0, 0.960784, 0.960784, 0.960784 ); table->SetTableValue( 3.0, 0.803922, 0.243137, 0.305882 ); table->SetTableValue( 4.0, 0.470588, 0.0705882, 0.52549 ); table->SetTableValue( 5.0, 0.768627, 0.227451, 0.980392 ); table->SetTableValue( 6.0, 0, 0.580392, 0 ); table->SetTableValue( 7.0, 0.862745, 0.972549, 0.643137 ); table->SetTableValue( 8.0, 0.901961, 0.580392, 0.133333 ); table->SetTableValue( 9.0, 0, 0.462745, 0.054902 ); table->SetTableValue( 10.0, 0, 0.462745, 0.054902 ); table->SetTableValue( 11.0, 0.478431, 0.729412, 0.862745 ); table->SetTableValue( 12.0, 0.92549, 0.0509804, 0.690196 ); table->SetTableValue( 13.0, 0.0470588, 0.188235, 1 ); table->SetTableValue( 14.0, 0.8, 0.713725, 0.556863 ); table->SetTableValue( 15.0, 0.164706, 0.8, 0.643137 ); table->SetTableValue( 16.0, 0.466667, 0.623529, 0.690196 ); table->SetTableValue( 17.0, 0.862745, 0.847059, 0.0784314 ); table->SetTableValue( 18.0, 0.403922, 1, 1 ); table->SetTableValue( 19.0, 0.313725, 0.768627, 0.384314 ); table->SetTableValue( 20.0, 0.235294, 0.227451, 0.823529 ); table->SetTableValue( 21.0, 0.235294, 0.227451, 0.823529 ); table->SetTableValue( 22.0, 0.235294, 0.227451, 0.823529 ); table->SetTableValue( 23.0, 0.235294, 0.227451, 0.823529 ); table->SetTableValue( 24.0, 0.235294, 0.235294, 0.235294 ); table->SetTableValue( 25.0, 1, 0.647059, 0 ); table->SetTableValue( 26.0, 1, 0.647059, 0 ); table->SetTableValue( 27.0, 0, 1, 0.498039 ); table->SetTableValue( 28.0, 0.647059, 0.164706, 0.164706 ); table->SetTableValue( 29.0, 0.529412, 0.807843, 0.921569 ); table->SetTableValue( 30.0, 0.627451, 0.12549, 0.941176 ); table->SetTableValue( 31.0, 0, 0.784314, 0.784314 ); table->SetTableValue( 32.0, 0.392157, 0.196078, 0.392157 ); table->SetTableValue( 33.0, 0.529412, 0.196078, 0.290196 ); table->SetTableValue( 34.0, 0.478431, 0.529412, 0.196078 ); table->SetTableValue( 35.0, 0.2, 0.196078, 0.529412 ); table->SetTableValue( 36.0, 0.290196, 0.607843, 0.235294 ); table->SetTableValue( 37.0, 0.470588, 0.243137, 0.168627 ); table->SetTableValue( 38.0, 0.290196, 0.607843, 0.235294 ); table->SetTableValue( 39.0, 0.478431, 0.529412, 0.196078 ); table->SetTableValue( 40.0, 0.27451, 0.509804, 0.705882 ); table->SetTableValue( 41.0, 0, 0.882353, 0 ); table->SetTableValue( 42.0, 0.803922, 0.243137, 0.305882 ); table->SetTableValue( 43.0, 0.470588, 0.0705882, 0.52549 ); table->SetTableValue( 44.0, 0.768627, 0.227451, 0.980392 ); table->SetTableValue( 45.0, 0, 0.580392, 0 ); table->SetTableValue( 46.0, 0.862745, 0.972549, 0.643137 ); table->SetTableValue( 47.0, 0.901961, 0.580392, 0.133333 ); table->SetTableValue( 48.0, 0, 0.462745, 0.054902 ); table->SetTableValue( 49.0, 0, 0.462745, 0.054902 ); table->SetTableValue( 50.0, 0.478431, 0.729412, 0.862745 ); table->SetTableValue( 51.0, 0.92549, 0.0509804, 0.690196 ); table->SetTableValue( 52.0, 0.0509804, 0.188235, 1 ); table->SetTableValue( 53.0, 0.862745, 0.847059, 0.0784314 ); table->SetTableValue( 54.0, 0.403922, 1, 1 ); table->SetTableValue( 55.0, 0.313725, 0.768627, 0.384314 ); table->SetTableValue( 56.0, 0.235294, 0.227451, 0.823529 ); table->SetTableValue( 57.0, 1, 0.647059, 0 ); table->SetTableValue( 58.0, 1, 0.647059, 0 ); table->SetTableValue( 59.0, 0, 1, 0.498039 ); table->SetTableValue( 60.0, 0.647059, 0.164706, 0.164706 ); table->SetTableValue( 61.0, 0.529412, 0.807843, 0.921569 ); table->SetTableValue( 62.0, 0.627451, 0.12549, 0.941176 ); table->SetTableValue( 63.0, 0, 0.784314, 0.866667 ); table->SetTableValue( 64.0, 0.392157, 0.196078, 0.392157 ); table->SetTableValue( 65.0, 0.529412, 0.196078, 0.290196 ); table->SetTableValue( 66.0, 0.478431, 0.529412, 0.196078 ); table->SetTableValue( 67.0, 0.2, 0.196078, 0.529412 ); table->SetTableValue( 68.0, 0.290196, 0.607843, 0.235294 ); table->SetTableValue( 69.0, 0.470588, 0.243137, 0.168627 ); table->SetTableValue( 70.0, 0.290196, 0.607843, 0.235294 ); table->SetTableValue( 71.0, 0.478431, 0.529412, 0.196078 ); table->SetTableValue( 72.0, 0.470588, 0.745098, 0.588235 ); table->SetTableValue( 73.0, 0.478431, 0.529412, 0.196078 ); table->SetTableValue( 74.0, 0.478431, 0.529412, 0.196078 ); table->SetTableValue( 77.0, 0.784314, 0.27451, 1 ); table->SetTableValue( 78.0, 1, 0.580392, 0.0392157 ); table->SetTableValue( 79.0, 1, 0.580392, 0.0392157 ); table->SetTableValue( 80.0, 0.643137, 0.423529, 0.886275 ); table->SetTableValue( 81.0, 0.643137, 0.423529, 0.886275 ); table->SetTableValue( 82.0, 0.643137, 0.423529, 0.886275 ); table->SetTableValue( 83.0, 1, 0.854902, 0.72549 ); table->SetTableValue( 84.0, 1, 0.854902, 0.72549 ); table->SetTableValue( 85.0, 0.917647, 0.662745, 0.117647 ); table->SetTableValue( 192.0, 0.980392, 1, 0.196078 ); table->SetTableValue( 86.0, 0.784314, 0.470588, 1 ); table->SetTableValue( 87.0, 0.784314, 0.47451, 1 ); table->SetTableValue( 88.0, 0.784314, 0.478431, 1 ); table->SetTableValue( 96.0, 0.803922, 0.0392157, 0.490196 ); table->SetTableValue( 97.0, 0.803922, 0.0392157, 0.490196 ); table->SetTableValue( 98.0, 0.627451, 0.12549, 0.941176 ); table->SetTableValue( 100.0, 0.486275, 0.54902, 0.698039 ); table->SetTableValue( 101.0, 0.490196, 0.54902, 0.698039 ); table->SetTableValue( 102.0, 0.494118, 0.54902, 0.698039 ); table->SetTableValue( 103.0, 0.498039, 0.54902, 0.698039 ); table->SetTableValue( 104.0, 0.486275, 0.552941, 0.698039 ); table->SetTableValue( 105.0, 0.486275, 0.556863, 0.698039 ); table->SetTableValue( 106.0, 0.486275, 0.560784, 0.698039 ); table->SetTableValue( 107.0, 0.486275, 0.564706, 0.698039 ); table->SetTableValue( 108.0, 0.486275, 0.54902, 0.701961 ); table->SetTableValue( 109.0, 0.486275, 0.54902, 0.698039 ); table->SetTableValue( 110.0, 0.490196, 0.54902, 0.698039 ); table->SetTableValue( 111.0, 0.494118, 0.54902, 0.698039 ); table->SetTableValue( 112.0, 0.498039, 0.54902, 0.698039 ); table->SetTableValue( 113.0, 0.486275, 0.552941, 0.698039 ); table->SetTableValue( 114.0, 0.486275, 0.556863, 0.698039 ); table->SetTableValue( 115.0, 0.486275, 0.560784, 0.698039 ); table->SetTableValue( 116.0, 0.486275, 0.564706, 0.698039 ); table->SetTableValue( 117.0, 0.486275, 0.54902, 0.701961 ); table->SetTableValue( 118.0, 1, 0.0784314, 0.576471 ); table->SetTableValue( 119.0, 0.803922, 0.701961, 0.545098 ); table->SetTableValue( 120.0, 0.933333, 0.933333, 0.819608 ); table->SetTableValue( 121.0, 0.784314, 0.784314, 0.784314 ); table->SetTableValue( 122.0, 0.290196, 1, 0.290196 ); table->SetTableValue( 123.0, 0.933333, 0, 0 ); table->SetTableValue( 124.0, 0, 0, 0.545098 ); table->SetTableValue( 125.0, 0.678431, 1, 0.184314 ); table->SetTableValue( 126.0, 0.521569, 0.796078, 0.898039 ); table->SetTableValue( 127.0, 0.101961, 0.929412, 0.223529 ); table->SetTableValue( 128.0, 0.133333, 0.545098, 0.133333 ); table->SetTableValue( 129.0, 0.117647, 0.564706, 1 ); table->SetTableValue( 130.0, 0.576471, 0.0745098, 0.678431 ); table->SetTableValue( 131.0, 0.933333, 0.231373, 0.231373 ); table->SetTableValue( 132.0, 0.866667, 0.152941, 0.784314 ); table->SetTableValue( 133.0, 0.933333, 0.682353, 0.933333 ); table->SetTableValue( 134.0, 1, 0, 0 ); table->SetTableValue( 135.0, 0.282353, 0.239216, 0.545098 ); table->SetTableValue( 136.0, 0.0823529, 0.152941, 0.517647 ); table->SetTableValue( 137.0, 0.0823529, 0.152941, 0.517647 ); table->SetTableValue( 138.0, 0.254902, 0.529412, 0.0784314 ); table->SetTableValue( 139.0, 0.254902, 0.529412, 0.0784314 ); table->SetTableValue( 140.0, 0.52549, 0.0156863, 0.627451 ); table->SetTableValue( 142.0, 0.866667, 0.886275, 0.266667 ); table->SetTableValue( 143.0, 1, 1, 0.996078 ); table->SetTableValue( 144.0, 0.203922, 0.819608, 0.886275 ); table->SetTableValue( 145.0, 0.937255, 0.627451, 0.87451 ); table->SetTableValue( 146.0, 0.27451, 0.509804, 0.705882 ); table->SetTableValue( 147.0, 0.27451, 0.509804, 0.709804 ); table->SetTableValue( 148.0, 0.545098, 0.47451, 0.368627 ); table->SetTableValue( 149.0, 0.878431, 0.878431, 0.878431 ); table->SetTableValue( 150.0, 1, 0, 0 ); table->SetTableValue( 151.0, 0.803922, 0.803922, 0 ); table->SetTableValue( 152.0, 0.933333, 0.933333, 0.819608 ); table->SetTableValue( 153.0, 0.545098, 0.47451, 0.368627 ); table->SetTableValue( 154.0, 0.933333, 0.231373, 0.231373 ); table->SetTableValue( 155.0, 0.933333, 0.231373, 0.231373 ); table->SetTableValue( 156.0, 0.933333, 0.231373, 0.231373 ); table->SetTableValue( 157.0, 0.243137, 0.0392157, 0.803922 ); table->SetTableValue( 158.0, 0.243137, 0.0392157, 0.803922 ); table->SetTableValue( 159.0, 0, 0.462745, 0.054902 ); table->SetTableValue( 160.0, 0, 0.462745, 0.054902 ); table->SetTableValue( 161.0, 0.862745, 0.847059, 0.0823529 ); table->SetTableValue( 162.0, 0.862745, 0.847059, 0.0823529 ); table->SetTableValue( 163.0, 0.478431, 0.729412, 0.862745 ); table->SetTableValue( 164.0, 0.478431, 0.729412, 0.862745 ); table->SetTableValue( 165.0, 1, 0.647059, 0 ); table->SetTableValue( 166.0, 0.054902, 0.188235, 1 ); table->SetTableValue( 167.0, 0.65098, 0.164706, 0.164706 ); table->SetTableValue( 168.0, 0.47451, 0.0705882, 0.52549 ); table->SetTableValue( 169.0, 0.92549, 0.0509804, 0.498039 ); table->SetTableValue( 176.0, 0.92549, 0.0509804, 0.494118 ); table->SetTableValue( 170.0, 0.466667, 0.623529, 0.690196 ); table->SetTableValue( 171.0, 0.466667, 0, 0.690196 ); table->SetTableValue( 172.0, 0.466667, 0.392157, 0.690196 ); table->SetTableValue( 173.0, 0.466667, 0.784314, 0.690196 ); table->SetTableValue( 174.0, 0.466667, 0.623529, 0.392157 ); table->SetTableValue( 175.0, 0.466667, 0.623529, 0.784314 ); table->SetTableValue( 180.0, 0.286275, 0.239216, 0.545098 ); table->SetTableValue( 181.0, 0.286275, 0.243137, 0.545098 ); table->SetTableValue( 193.0, 0, 0.768627, 1 ); table->SetTableValue( 194.0, 1, 0.643137, 0.643137 ); table->SetTableValue( 195.0, 0.768627, 0.768627, 0 ); table->SetTableValue( 196.0, 0, 0.392157, 1 ); table->SetTableValue( 197.0, 0.501961, 0.768627, 0.643137 ); table->SetTableValue( 198.0, 0, 0.494118, 0.294118 ); table->SetTableValue( 199.0, 0.501961, 0.376471, 0.25098 ); table->SetTableValue( 200.0, 0, 0.196078, 0.501961 ); table->SetTableValue( 201.0, 1, 0.8, 0.6 ); table->SetTableValue( 202.0, 1, 0.501961, 0.501961 ); table->SetTableValue( 203.0, 1, 1, 0 ); table->SetTableValue( 204.0, 0.25098, 0, 0.25098 ); table->SetTableValue( 205.0, 0, 0, 1 ); table->SetTableValue( 206.0, 1, 0, 0 ); table->SetTableValue( 207.0, 0.501961, 0.501961, 1 ); table->SetTableValue( 208.0, 0, 0.501961, 0 ); table->SetTableValue( 209.0, 0.768627, 0.627451, 0.501961 ); table->SetTableValue( 210.0, 0.12549, 0.784314, 1 ); table->SetTableValue( 211.0, 0.501961, 1, 0.501961 ); table->SetTableValue( 212.0, 0.8, 0.6, 0.8 ); table->SetTableValue( 213.0, 0.47451, 0.0666667, 0.533333 ); table->SetTableValue( 214.0, 0.501961, 0, 0 ); table->SetTableValue( 215.0, 0.501961, 0.12549, 1 ); table->SetTableValue( 216.0, 1, 0.8, 0.4 ); table->SetTableValue( 217.0, 0.501961, 0.501961, 0.501961 ); table->SetTableValue( 218.0, 0.407843, 1, 1 ); table->SetTableValue( 219.0, 0, 0.886275, 0 ); table->SetTableValue( 220.0, 0.803922, 0.247059, 0.305882 ); table->SetTableValue( 221.0, 0.772549, 0.227451, 0.980392 ); table->SetTableValue( 222.0, 0.129412, 0.588235, 0.980392 ); table->SetTableValue( 223.0, 0.886275, 0, 0 ); table->SetTableValue( 224.0, 0.392157, 0.392157, 0.392157 ); table->SetTableValue( 225.0, 0.772549, 0.588235, 0.980392 ); table->SetTableValue( 226.0, 0.666667, 0.666667, 1 ); table->SetTableValue( 250.0, 1, 0, 0 ); table->SetTableValue( 251.0, 0, 0, 0.25098 ); table->SetTableValue( 252.0, 0, 0, 0.439216 ); table->SetTableValue( 253.0, 0, 0, 0.627451 ); table->SetTableValue( 254.0, 0, 0, 0.815686 ); table->SetTableValue( 255.0, 0, 0, 1 ); table->SetTableValue( 256.0, 0, 0, 0, 0); table->SetTableValue( 331.0, 1, 0, 0 ); table->SetTableValue( 332.0, 1, 0.313725, 0 ); table->SetTableValue( 333.0, 1, 0.627451, 0 ); table->SetTableValue( 334.0, 1, 1, 0 ); table->SetTableValue( 335.0, 0, 1, 0 ); table->SetTableValue( 336.0, 1, 0, 0.627451 ); table->SetTableValue( 337.0, 1, 0, 1 ); table->SetTableValue( 338.0, 1, 0.196078, 0.313725 ); table->SetTableValue( 339.0, 0.313725, 1, 0.196078 ); table->SetTableValue( 340.0, 0.627451, 1, 0.196078 ); table->SetTableValue( 341.0, 0.627451, 0.784314, 1 ); table->SetTableValue( 342.0, 0, 1, 0.627451 ); table->SetTableValue( 343.0, 0, 0, 1 ); table->SetTableValue( 344.0, 0.313725, 0.196078, 1 ); table->SetTableValue( 345.0, 0.627451, 0, 1 ); table->SetTableValue( 346.0, 1, 0.823529, 0 ); table->SetTableValue( 347.0, 0, 0.627451, 1 ); table->SetTableValue( 348.0, 1, 0.784314, 0.313725 ); table->SetTableValue( 349.0, 1, 0.784314, 0.627451 ); table->SetTableValue( 350.0, 1, 0.313725, 0.784314 ); table->SetTableValue( 351.0, 1, 0.627451, 0.784314 ); table->SetTableValue( 352.0, 0.117647, 1, 0.313725 ); table->SetTableValue( 353.0, 0.313725, 0.784314, 1 ); table->SetTableValue( 354.0, 0.313725, 1, 0.784314 ); table->SetTableValue( 355.0, 0.764706, 1, 0.784314 ); table->SetTableValue( 356.0, 0.470588, 0.784314, 0.0784314 ); table->SetTableValue( 357.0, 0.666667, 0.0392157, 0.784314 ); table->SetTableValue( 358.0, 0.0784314, 0.509804, 0.705882 ); table->SetTableValue( 359.0, 0.0784314, 0.705882, 0.509804 ); table->SetTableValue( 400.0, 0.807843, 0.243137, 0.305882 ); table->SetTableValue( 401.0, 0.47451, 0.0705882, 0.52549 ); table->SetTableValue( 402.0, 0.780392, 0.227451, 0.980392 ); table->SetTableValue( 403.0, 0.00392157, 0.580392, 0 ); table->SetTableValue( 404.0, 0.866667, 0.972549, 0.643137 ); table->SetTableValue( 405.0, 0.905882, 0.580392, 0.133333 ); table->SetTableValue( 406.0, 0.00392157, 0.462745, 0.054902 ); table->SetTableValue( 407.0, 0.470588, 0.462745, 0.054902 ); table->SetTableValue( 408.0, 0.482353, 0.729412, 0.866667 ); table->SetTableValue( 409.0, 0.933333, 0.0509804, 0.694118 ); table->SetTableValue( 410.0, 0.482353, 0.729412, 0.862745 ); table->SetTableValue( 411.0, 0.541176, 0.0509804, 0.807843 ); table->SetTableValue( 412.0, 0.933333, 0.509804, 0.690196 ); table->SetTableValue( 413.0, 0.854902, 0.901961, 0.298039 ); table->SetTableValue( 414.0, 0.14902, 0.835294, 0.690196 ); table->SetTableValue( 415.0, 0.00392157, 0.882353, 0.690196 ); table->SetTableValue( 416.0, 0.00392157, 0.882353, 0.690196 ); table->SetTableValue( 417.0, 0.784314, 0.00784314, 0.392157 ); table->SetTableValue( 418.0, 0.784314, 0.00784314, 0.392157 ); table->SetTableValue( 419.0, 0.0196078, 0.784314, 0.352941 ); table->SetTableValue( 420.0, 0.0196078, 0.784314, 0.352941 ); table->SetTableValue( 421.0, 0.392157, 0.0196078, 0.784314 ); table->SetTableValue( 422.0, 0.0980392, 1, 0.392157 ); table->SetTableValue( 423.0, 0.0980392, 1, 0.392157 ); table->SetTableValue( 424.0, 0.901961, 0.027451, 0.392157 ); table->SetTableValue( 425.0, 0.901961, 0.027451, 0.392157 ); table->SetTableValue( 426.0, 0.392157, 0.0196078, 0.784314 ); table->SetTableValue( 427.0, 0.588235, 0.0392157, 0.784314 ); table->SetTableValue( 428.0, 0.588235, 0.0392157, 0.784314 ); table->SetTableValue( 429.0, 0.686275, 0.0392157, 0.690196 ); table->SetTableValue( 430.0, 0.686275, 0.0392157, 0.690196 ); table->SetTableValue( 431.0, 0.0392157, 0.392157, 1 ); table->SetTableValue( 432.0, 0.0392157, 0.392157, 1 ); table->SetTableValue( 433.0, 0.588235, 0.176471, 0.27451 ); table->SetTableValue( 434.0, 0.588235, 0.176471, 0.27451 ); table->SetTableValue( 435.0, 0.176471, 0.784314, 0.0588235 ); table->SetTableValue( 436.0, 0.176471, 0.784314, 0.0588235 ); table->SetTableValue( 437.0, 0.890196, 0.176471, 0.392157 ); table->SetTableValue( 438.0, 0.890196, 0.176471, 0.392157 ); table->SetTableValue( 439.0, 0.890196, 0.176471, 0.392157 ); table->SetTableValue( 498.0, 0.560784, 0.737255, 0.560784 ); table->SetTableValue( 499.0, 1, 0.972549, 0.862745 ); table->SetTableValue( 500.0, 0.0666667, 0.333333, 0.533333 ); table->SetTableValue( 501.0, 0.466667, 0.733333, 0.4 ); table->SetTableValue( 502.0, 0.8, 0.266667, 0.133333 ); table->SetTableValue( 503.0, 0.8, 0, 1 ); table->SetTableValue( 504.0, 0.866667, 0.733333, 0.0666667 ); table->SetTableValue( 505.0, 0.6, 0.866667, 0.933333 ); table->SetTableValue( 506.0, 0.2, 0.0666667, 0.0666667 ); table->SetTableValue( 507.0, 0, 0.466667, 0.333333 ); table->SetTableValue( 508.0, 0.0784314, 0.392157, 0.784314 ); table->SetTableValue( 550.0, 0.0666667, 0.333333, 0.537255 ); table->SetTableValue( 551.0, 0.466667, 0.733333, 0.403922 ); table->SetTableValue( 552.0, 0.8, 0.266667, 0.137255 ); table->SetTableValue( 553.0, 0.8, 0, 0.996078 ); table->SetTableValue( 554.0, 0.866667, 0.733333, 0.0627451 ); table->SetTableValue( 555.0, 0.6, 0.866667, 0.937255 ); table->SetTableValue( 556.0, 0.2, 0.0666667, 0.0705882 ); table->SetTableValue( 557.0, 0, 0.466667, 0.337255 ); table->SetTableValue( 558.0, 0.0784314, 0.392157, 0.788235 ); table->SetTableValue( 600.0, 0.996078, 0.996078, 0.996078 ); table->SetTableValue( 601.0, 0.27451, 0.509804, 0.705882 ); table->SetTableValue( 602.0, 0.960784, 0.960784, 0.960784 ); table->SetTableValue( 603.0, 0.803922, 0.243137, 0.305882 ); table->SetTableValue( 604.0, 0.470588, 0.0705882, 0.52549 ); table->SetTableValue( 605.0, 0.768627, 0.227451, 0.980392 ); table->SetTableValue( 606.0, 0, 0.580392, 0 ); table->SetTableValue( 607.0, 0.862745, 0.972549, 0.643137 ); table->SetTableValue( 608.0, 0.901961, 0.580392, 0.133333 ); table->SetTableValue( 609.0, 0, 0.462745, 0.054902 ); table->SetTableValue( 610.0, 0, 0.462745, 0.054902 ); table->SetTableValue( 611.0, 0.478431, 0.729412, 0.862745 ); table->SetTableValue( 612.0, 0.92549, 0.0509804, 0.690196 ); table->SetTableValue( 613.0, 0.0470588, 0.188235, 1 ); table->SetTableValue( 614.0, 0.8, 0.713725, 0.556863 ); table->SetTableValue( 615.0, 0.164706, 0.8, 0.643137 ); table->SetTableValue( 616.0, 0.466667, 0.623529, 0.690196 ); table->SetTableValue( 617.0, 0.862745, 0.847059, 0.0784314 ); table->SetTableValue( 618.0, 0.403922, 1, 1 ); table->SetTableValue( 619.0, 0.313725, 0.768627, 0.384314 ); table->SetTableValue( 620.0, 0.235294, 0.227451, 0.823529 ); table->SetTableValue( 621.0, 0.235294, 0.227451, 0.823529 ); table->SetTableValue( 622.0, 0.235294, 0.227451, 0.823529 ); table->SetTableValue( 623.0, 0.235294, 0.227451, 0.823529 ); table->SetTableValue( 624.0, 0.235294, 0.235294, 0.235294 ); table->SetTableValue( 625.0, 1, 0.647059, 0 ); table->SetTableValue( 626.0, 1, 0.647059, 0 ); table->SetTableValue( 627.0, 0, 1, 0.498039 ); table->SetTableValue( 628.0, 0.647059, 0.164706, 0.164706 ); table->SetTableValue( 640.0, 0.8, 0, 0 ); table->SetTableValue( 641.0, 1, 0, 0 ); table->SetTableValue( 642.0, 0, 0, 1 ); table->SetTableValue( 643.0, 0.117647, 0.564706, 1 ); table->SetTableValue( 644.0, 0.392157, 0.831373, 0.929412 ); table->SetTableValue( 645.0, 0.854902, 0.647059, 0.12549 ); table->SetTableValue( 646.0, 1, 0.843137, 0 ); table->SetTableValue( 647.0, 1, 1, 0.65098 ); table->SetTableValue( 648.0, 0.6, 0, 0.8 ); table->SetTableValue( 649.0, 0.6, 0.552941, 0.819608 ); table->SetTableValue( 650.0, 0.8, 0.8, 1 ); table->SetTableValue( 651.0, 0.121569, 0.831373, 0.760784 ); table->SetTableValue( 652.0, 0.0117647, 1, 0.929412 ); table->SetTableValue( 653.0, 0.8, 1, 1 ); table->SetTableValue( 654.0, 0.337255, 0.290196, 0.576471 ); table->SetTableValue( 655.0, 0.447059, 0.447059, 0.745098 ); table->SetTableValue( 656.0, 0.721569, 0.698039, 1 ); table->SetTableValue( 657.0, 0.494118, 0.541176, 0.145098 ); table->SetTableValue( 658.0, 0.741176, 0.772549, 0.458824 ); table->SetTableValue( 659.0, 0.941176, 0.901961, 0.54902 ); table->SetTableValue( 660.0, 0.8, 0, 0 ); table->SetTableValue( 661.0, 1, 0, 0 ); table->SetTableValue( 662.0, 0, 0, 1 ); table->SetTableValue( 663.0, 0.117647, 0.564706, 1 ); table->SetTableValue( 664.0, 0.392157, 0.831373, 0.929412 ); table->SetTableValue( 665.0, 0.854902, 0.647059, 0.12549 ); table->SetTableValue( 666.0, 1, 0.843137, 0 ); table->SetTableValue( 667.0, 1, 1, 0.65098 ); table->SetTableValue( 668.0, 0.6, 0, 0.8 ); table->SetTableValue( 669.0, 0.6, 0.552941, 0.819608 ); table->SetTableValue( 670.0, 0.8, 0.8, 1 ); table->SetTableValue( 671.0, 0.121569, 0.831373, 0.760784 ); table->SetTableValue( 672.0, 0.0117647, 1, 0.929412 ); table->SetTableValue( 673.0, 0.8, 1, 1 ); table->SetTableValue( 674.0, 0.337255, 0.290196, 0.576471 ); table->SetTableValue( 675.0, 0.447059, 0.447059, 0.745098 ); table->SetTableValue( 676.0, 0.721569, 0.698039, 1 ); table->SetTableValue( 677.0, 0.494118, 0.541176, 0.145098 ); table->SetTableValue( 678.0, 0.741176, 0.772549, 0.458824 ); table->SetTableValue( 679.0, 0.941176, 0.901961, 0.54902 ); table->SetTableValue( 701.0, 0.470588, 0.0705882, 0.52549 ); table->SetTableValue( 702.0, 0.803922, 0.243137, 0.305882 ); table->SetTableValue( 703.0, 0, 0.882353, 0 ); table->SetTableValue( 999.0, 1, 0.392157, 0.392157 ); table->SetTableValue( 1000.0, 0.0980392, 0.0196078, 0.0980392 ); table->SetTableValue( 1001.0, 0.0980392, 0.392157, 0.156863 ); table->SetTableValue( 1002.0, 0.490196, 0.392157, 0.627451 ); table->SetTableValue( 1003.0, 0.392157, 0.0980392, 0 ); table->SetTableValue( 1004.0, 0.470588, 0.27451, 0.196078 ); table->SetTableValue( 1005.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 1006.0, 0.862745, 0.0784314, 0.0392157 ); table->SetTableValue( 1007.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 1008.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 1009.0, 0.705882, 0.156863, 0.470588 ); table->SetTableValue( 1010.0, 0.54902, 0.0784314, 0.54902 ); table->SetTableValue( 1011.0, 0.0784314, 0.117647, 0.54902 ); table->SetTableValue( 1012.0, 0.137255, 0.294118, 0.196078 ); table->SetTableValue( 1013.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 1014.0, 0.784314, 0.137255, 0.294118 ); table->SetTableValue( 1015.0, 0.627451, 0.392157, 0.196078 ); table->SetTableValue( 1016.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 1017.0, 0.235294, 0.862745, 0.235294 ); table->SetTableValue( 1018.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 1019.0, 0.0784314, 0.392157, 0.196078 ); table->SetTableValue( 1020.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 1021.0, 0.470588, 0.392157, 0.235294 ); table->SetTableValue( 1022.0, 0.862745, 0.0784314, 0.0784314 ); table->SetTableValue( 1023.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 1024.0, 0.235294, 0.0784314, 0.862745 ); table->SetTableValue( 1025.0, 0.627451, 0.54902, 0.705882 ); table->SetTableValue( 1026.0, 0.313725, 0.0784314, 0.54902 ); table->SetTableValue( 1027.0, 0.294118, 0.196078, 0.490196 ); table->SetTableValue( 1028.0, 0.0784314, 0.862745, 0.627451 ); table->SetTableValue( 1029.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 1030.0, 0.54902, 0.862745, 0.862745 ); table->SetTableValue( 1031.0, 0.313725, 0.627451, 0.0784314 ); table->SetTableValue( 1032.0, 0.392157, 0, 0.392157 ); table->SetTableValue( 1033.0, 0.27451, 0.27451, 0.27451 ); table->SetTableValue( 1034.0, 0.588235, 0.588235, 0.784314 ); table->SetTableValue( 1035.0, 1, 0.752941, 0.12549 ); table->SetTableValue( 2000.0, 0.0980392, 0.0196078, 0.0980392 ); table->SetTableValue( 2001.0, 0.0980392, 0.392157, 0.156863 ); table->SetTableValue( 2002.0, 0.490196, 0.392157, 0.627451 ); table->SetTableValue( 2003.0, 0.392157, 0.0980392, 0 ); table->SetTableValue( 2004.0, 0.470588, 0.27451, 0.196078 ); table->SetTableValue( 2005.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 2006.0, 0.862745, 0.0784314, 0.0392157 ); table->SetTableValue( 2007.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 2008.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 2009.0, 0.705882, 0.156863, 0.470588 ); table->SetTableValue( 2010.0, 0.54902, 0.0784314, 0.54902 ); table->SetTableValue( 2011.0, 0.0784314, 0.117647, 0.54902 ); table->SetTableValue( 2012.0, 0.137255, 0.294118, 0.196078 ); table->SetTableValue( 2013.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 2014.0, 0.784314, 0.137255, 0.294118 ); table->SetTableValue( 2015.0, 0.627451, 0.392157, 0.196078 ); table->SetTableValue( 2016.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 2017.0, 0.235294, 0.862745, 0.235294 ); table->SetTableValue( 2018.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 2019.0, 0.0784314, 0.392157, 0.196078 ); table->SetTableValue( 2020.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 2021.0, 0.470588, 0.392157, 0.235294 ); table->SetTableValue( 2022.0, 0.862745, 0.0784314, 0.0784314 ); table->SetTableValue( 2023.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 2024.0, 0.235294, 0.0784314, 0.862745 ); table->SetTableValue( 2025.0, 0.627451, 0.54902, 0.705882 ); table->SetTableValue( 2026.0, 0.313725, 0.0784314, 0.54902 ); table->SetTableValue( 2027.0, 0.294118, 0.196078, 0.490196 ); table->SetTableValue( 2028.0, 0.0784314, 0.862745, 0.627451 ); table->SetTableValue( 2029.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 2030.0, 0.54902, 0.862745, 0.862745 ); table->SetTableValue( 2031.0, 0.313725, 0.627451, 0.0784314 ); table->SetTableValue( 2032.0, 0.392157, 0, 0.392157 ); table->SetTableValue( 2033.0, 0.27451, 0.27451, 0.27451 ); table->SetTableValue( 2034.0, 0.588235, 0.588235, 0.784314 ); table->SetTableValue( 2035.0, 1, 0.752941, 0.12549 ); table->SetTableValue( 3000.0, 0.901961, 0.980392, 0.901961 ); table->SetTableValue( 3001.0, 0.901961, 0.607843, 0.843137 ); table->SetTableValue( 3002.0, 0.509804, 0.607843, 0.372549 ); table->SetTableValue( 3003.0, 0.607843, 0.901961, 1 ); table->SetTableValue( 3004.0, 0.529412, 0.72549, 0.803922 ); table->SetTableValue( 3005.0, 0.137255, 0.921569, 0.607843 ); table->SetTableValue( 3006.0, 0.137255, 0.921569, 0.960784 ); table->SetTableValue( 3007.0, 0.294118, 0.137255, 0.45098 ); table->SetTableValue( 3008.0, 0.137255, 0.764706, 0.137255 ); table->SetTableValue( 3009.0, 0.294118, 0.843137, 0.529412 ); table->SetTableValue( 3010.0, 0.45098, 0.921569, 0.45098 ); table->SetTableValue( 3011.0, 0.921569, 0.882353, 0.45098 ); table->SetTableValue( 3012.0, 0.862745, 0.705882, 0.803922 ); table->SetTableValue( 3013.0, 0.117647, 0.45098, 0.45098 ); table->SetTableValue( 3014.0, 0.215686, 0.862745, 0.705882 ); table->SetTableValue( 3015.0, 0.372549, 0.607843, 0.803922 ); table->SetTableValue( 3016.0, 0.921569, 0.137255, 0.764706 ); table->SetTableValue( 3017.0, 0.764706, 0.137255, 0.764706 ); table->SetTableValue( 3018.0, 0.137255, 0.294118, 0.45098 ); table->SetTableValue( 3019.0, 0.921569, 0.607843, 0.803922 ); table->SetTableValue( 3020.0, 0.137255, 0.764706, 0.921569 ); table->SetTableValue( 3021.0, 0.529412, 0.607843, 0.764706 ); table->SetTableValue( 3022.0, 0.137255, 0.921569, 0.921569 ); table->SetTableValue( 3023.0, 0.137255, 0.294118, 0.137255 ); table->SetTableValue( 3024.0, 0.764706, 0.921569, 0.137255 ); table->SetTableValue( 3025.0, 0.372549, 0.45098, 0.294118 ); table->SetTableValue( 3026.0, 0.686275, 0.921569, 0.45098 ); table->SetTableValue( 3027.0, 0.705882, 0.803922, 0.509804 ); table->SetTableValue( 3028.0, 0.921569, 0.137255, 0.372549 ); table->SetTableValue( 3029.0, 0.921569, 0.294118, 0.45098 ); table->SetTableValue( 3030.0, 0.45098, 0.137255, 0.137255 ); table->SetTableValue( 3031.0, 0.686275, 0.372549, 0.921569 ); table->SetTableValue( 3032.0, 0.607843, 1, 0.607843 ); table->SetTableValue( 3033.0, 0.72549, 0.72549, 0.72549 ); table->SetTableValue( 3034.0, 0.411765, 0.411765, 0.215686 ); table->SetTableValue( 3035.0, 0.996078, 0.74902, 0.121569 ); table->SetTableValue( 4000.0, 0.901961, 0.980392, 0.901961 ); table->SetTableValue( 4001.0, 0.901961, 0.607843, 0.843137 ); table->SetTableValue( 4002.0, 0.509804, 0.607843, 0.372549 ); table->SetTableValue( 4003.0, 0.607843, 0.901961, 1 ); table->SetTableValue( 4004.0, 0.529412, 0.72549, 0.803922 ); table->SetTableValue( 4005.0, 0.137255, 0.921569, 0.607843 ); table->SetTableValue( 4006.0, 0.137255, 0.921569, 0.960784 ); table->SetTableValue( 4007.0, 0.294118, 0.137255, 0.45098 ); table->SetTableValue( 4008.0, 0.137255, 0.764706, 0.137255 ); table->SetTableValue( 4009.0, 0.294118, 0.843137, 0.529412 ); table->SetTableValue( 4010.0, 0.45098, 0.921569, 0.45098 ); table->SetTableValue( 4011.0, 0.921569, 0.882353, 0.45098 ); table->SetTableValue( 4012.0, 0.862745, 0.705882, 0.803922 ); table->SetTableValue( 4013.0, 0.117647, 0.45098, 0.45098 ); table->SetTableValue( 4014.0, 0.215686, 0.862745, 0.705882 ); table->SetTableValue( 4015.0, 0.372549, 0.607843, 0.803922 ); table->SetTableValue( 4016.0, 0.921569, 0.137255, 0.764706 ); table->SetTableValue( 4017.0, 0.764706, 0.137255, 0.764706 ); table->SetTableValue( 4018.0, 0.137255, 0.294118, 0.45098 ); table->SetTableValue( 4019.0, 0.921569, 0.607843, 0.803922 ); table->SetTableValue( 4020.0, 0.137255, 0.764706, 0.921569 ); table->SetTableValue( 4021.0, 0.529412, 0.607843, 0.764706 ); table->SetTableValue( 4022.0, 0.137255, 0.921569, 0.921569 ); table->SetTableValue( 4023.0, 0.137255, 0.294118, 0.137255 ); table->SetTableValue( 4024.0, 0.764706, 0.921569, 0.137255 ); table->SetTableValue( 4025.0, 0.372549, 0.45098, 0.294118 ); table->SetTableValue( 4026.0, 0.686275, 0.921569, 0.45098 ); table->SetTableValue( 4027.0, 0.705882, 0.803922, 0.509804 ); table->SetTableValue( 4028.0, 0.921569, 0.137255, 0.372549 ); table->SetTableValue( 4029.0, 0.921569, 0.294118, 0.45098 ); table->SetTableValue( 4030.0, 0.45098, 0.137255, 0.137255 ); table->SetTableValue( 4031.0, 0.686275, 0.372549, 0.921569 ); table->SetTableValue( 4032.0, 0.607843, 1, 0.607843 ); table->SetTableValue( 4033.0, 0.72549, 0.72549, 0.72549 ); table->SetTableValue( 4034.0, 0.411765, 0.411765, 0.215686 ); table->SetTableValue( 4035.0, 0.996078, 0.74902, 0.121569 ); table->SetTableValue( 1100.0, 0, 0, 0, 0); table->SetTableValue( 1101.0, 0.196078, 0.196078, 0.196078 ); table->SetTableValue( 1102.0, 0.705882, 0.0784314, 0.117647 ); table->SetTableValue( 1103.0, 0.235294, 0.0980392, 0.0980392 ); table->SetTableValue( 1104.0, 0.0980392, 0.235294, 0.235294 ); table->SetTableValue( 1200.0, 0.0980392, 0.235294, 0.239216 ); table->SetTableValue( 1201.0, 0.0980392, 0.352941, 0.235294 ); table->SetTableValue( 1202.0, 0.0980392, 0.470588, 0.235294 ); table->SetTableValue( 1205.0, 0.0980392, 0.588235, 0.235294 ); table->SetTableValue( 1206.0, 0.0980392, 0.705882, 0.235294 ); table->SetTableValue( 1207.0, 0.0980392, 0.823529, 0.235294 ); table->SetTableValue( 1210.0, 0.0980392, 0.588235, 0.352941 ); table->SetTableValue( 1211.0, 0.0980392, 0.705882, 0.352941 ); table->SetTableValue( 1212.0, 0.0980392, 0.823529, 0.352941 ); table->SetTableValue( 1105.0, 0.705882, 0.0784314, 0.0784314 ); table->SetTableValue( 1106.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 1107.0, 0.54902, 0.235294, 0.235294 ); table->SetTableValue( 1108.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 1109.0, 0.54902, 0.392157, 0.705882 ); table->SetTableValue( 1110.0, 0.705882, 0.0784314, 0.54902 ); table->SetTableValue( 1111.0, 0.54902, 0.0784314, 0.54902 ); table->SetTableValue( 1112.0, 0.0823529, 0.0392157, 0.0392157 ); table->SetTableValue( 1113.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 1114.0, 0.0901961, 0.235294, 0.705882 ); table->SetTableValue( 1115.0, 0.705882, 0.235294, 0.705882 ); table->SetTableValue( 1116.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 1117.0, 0.235294, 0.0784314, 0.54902 ); table->SetTableValue( 1118.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 1119.0, 0.254902, 0.392157, 0.0784314 ); table->SetTableValue( 1120.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 1121.0, 0.235294, 0.392157, 0.235294 ); table->SetTableValue( 1122.0, 0.0784314, 0.235294, 0.862745 ); table->SetTableValue( 1123.0, 0.392157, 0.392157, 0.235294 ); table->SetTableValue( 1124.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 1125.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 1126.0, 0.235294, 0.54902, 0.705882 ); table->SetTableValue( 1127.0, 0.0980392, 0.0784314, 0.54902 ); table->SetTableValue( 1128.0, 0.0784314, 0.235294, 0.392157 ); table->SetTableValue( 1129.0, 0.235294, 0.862745, 0.0784314 ); table->SetTableValue( 1130.0, 0.235294, 0.0784314, 0.862745 ); table->SetTableValue( 1131.0, 0.862745, 0.862745, 0.392157 ); table->SetTableValue( 1132.0, 0.705882, 0.235294, 0.235294 ); table->SetTableValue( 1133.0, 0.235294, 0.235294, 0.862745 ); table->SetTableValue( 1134.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 1135.0, 0.254902, 0.862745, 0.235294 ); table->SetTableValue( 1136.0, 0.0980392, 0.54902, 0.0784314 ); table->SetTableValue( 1137.0, 0.0509804, 0, 0.980392 ); table->SetTableValue( 1138.0, 0.239216, 0.0784314, 0.862745 ); table->SetTableValue( 1139.0, 0.239216, 0.0784314, 0.235294 ); table->SetTableValue( 1140.0, 0.239216, 0.235294, 0.392157 ); table->SetTableValue( 1141.0, 0.0980392, 0.0980392, 0.0980392 ); table->SetTableValue( 1142.0, 0.54902, 0.0784314, 0.235294 ); table->SetTableValue( 1143.0, 0.862745, 0.705882, 0.0784314 ); table->SetTableValue( 1144.0, 0.247059, 0.705882, 0.705882 ); table->SetTableValue( 1145.0, 0.866667, 0.0784314, 0.0392157 ); table->SetTableValue( 1146.0, 0.0823529, 0.862745, 0.0784314 ); table->SetTableValue( 1147.0, 0.717647, 0.392157, 0.0784314 ); table->SetTableValue( 1148.0, 0.866667, 0.0784314, 0.392157 ); table->SetTableValue( 1149.0, 0.866667, 0.235294, 0.54902 ); table->SetTableValue( 1150.0, 0.866667, 0.0784314, 0.862745 ); table->SetTableValue( 1151.0, 0.239216, 0.862745, 0.862745 ); table->SetTableValue( 1152.0, 0.392157, 0.784314, 0.784314 ); table->SetTableValue( 1153.0, 0.0392157, 0.784314, 0.784314 ); table->SetTableValue( 1154.0, 0.866667, 0.862745, 0.0784314 ); table->SetTableValue( 1155.0, 0.552941, 0.0784314, 0.392157 ); table->SetTableValue( 1156.0, 0.239216, 0.862745, 0.392157 ); table->SetTableValue( 1157.0, 0.0823529, 0.862745, 0.235294 ); table->SetTableValue( 1158.0, 0.552941, 0.235294, 0.0784314 ); table->SetTableValue( 1159.0, 0.560784, 0.0784314, 0.862745 ); table->SetTableValue( 1160.0, 0.239216, 0.0784314, 0.705882 ); table->SetTableValue( 1161.0, 0.396078, 0.235294, 0.862745 ); table->SetTableValue( 1162.0, 0.0823529, 0.0784314, 0.54902 ); table->SetTableValue( 1163.0, 0.866667, 0.54902, 0.0784314 ); table->SetTableValue( 1164.0, 0.552941, 0.392157, 0.862745 ); table->SetTableValue( 1165.0, 0.396078, 0.0784314, 0.0784314 ); table->SetTableValue( 1166.0, 0.866667, 0.392157, 0.0784314 ); table->SetTableValue( 1167.0, 0.709804, 0.784314, 0.0784314 ); table->SetTableValue( 1168.0, 0.0823529, 0.705882, 0.54902 ); table->SetTableValue( 1169.0, 0.396078, 0.392157, 0.705882 ); table->SetTableValue( 1170.0, 0.709804, 0.862745, 0.0784314 ); table->SetTableValue( 1171.0, 0.0823529, 0.54902, 0.784314 ); table->SetTableValue( 1172.0, 0.0823529, 0.0784314, 0.941176 ); table->SetTableValue( 1173.0, 0.0823529, 0.0784314, 0.784314 ); table->SetTableValue( 1174.0, 0.239216, 0.705882, 0.235294 ); table->SetTableValue( 1175.0, 0.239216, 0.705882, 0.980392 ); table->SetTableValue( 1176.0, 0.0823529, 0.0784314, 0.235294 ); table->SetTableValue( 1177.0, 0.396078, 0.235294, 0.235294 ); table->SetTableValue( 1178.0, 0.0823529, 0.862745, 0.862745 ); table->SetTableValue( 1179.0, 0.0823529, 0.705882, 0.705882 ); table->SetTableValue( 1180.0, 0.87451, 0.862745, 0.235294 ); table->SetTableValue( 1181.0, 0.866667, 0.235294, 0.235294 ); table->SetTableValue( 2100.0, 0, 0, 0, 0); table->SetTableValue( 2101.0, 0.196078, 0.196078, 0.196078 ); table->SetTableValue( 2102.0, 0.705882, 0.0784314, 0.117647 ); table->SetTableValue( 2103.0, 0.235294, 0.0980392, 0.0980392 ); table->SetTableValue( 2104.0, 0.0980392, 0.235294, 0.235294 ); table->SetTableValue( 2105.0, 0.705882, 0.0784314, 0.0784314 ); table->SetTableValue( 2106.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 2107.0, 0.54902, 0.235294, 0.235294 ); table->SetTableValue( 2108.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 2109.0, 0.54902, 0.392157, 0.705882 ); table->SetTableValue( 2110.0, 0.705882, 0.0784314, 0.54902 ); table->SetTableValue( 2111.0, 0.54902, 0.0784314, 0.54902 ); table->SetTableValue( 2112.0, 0.0823529, 0.0392157, 0.0392157 ); table->SetTableValue( 2113.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 2114.0, 0.0901961, 0.235294, 0.705882 ); table->SetTableValue( 2115.0, 0.705882, 0.235294, 0.705882 ); table->SetTableValue( 2116.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 2117.0, 0.235294, 0.0784314, 0.54902 ); table->SetTableValue( 2118.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 2119.0, 0.254902, 0.392157, 0.0784314 ); table->SetTableValue( 2120.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 2121.0, 0.235294, 0.392157, 0.235294 ); table->SetTableValue( 2122.0, 0.0784314, 0.235294, 0.862745 ); table->SetTableValue( 2123.0, 0.392157, 0.392157, 0.235294 ); table->SetTableValue( 2124.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 2125.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 2126.0, 0.235294, 0.54902, 0.705882 ); table->SetTableValue( 2127.0, 0.0980392, 0.0784314, 0.54902 ); table->SetTableValue( 2128.0, 0.0784314, 0.235294, 0.392157 ); table->SetTableValue( 2129.0, 0.235294, 0.862745, 0.0784314 ); table->SetTableValue( 2130.0, 0.235294, 0.0784314, 0.862745 ); table->SetTableValue( 2131.0, 0.862745, 0.862745, 0.392157 ); table->SetTableValue( 2132.0, 0.705882, 0.235294, 0.235294 ); table->SetTableValue( 2133.0, 0.235294, 0.235294, 0.862745 ); table->SetTableValue( 2134.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 2135.0, 0.254902, 0.862745, 0.235294 ); table->SetTableValue( 2136.0, 0.0980392, 0.54902, 0.0784314 ); table->SetTableValue( 2137.0, 0.0509804, 0, 0.980392 ); table->SetTableValue( 2138.0, 0.239216, 0.0784314, 0.862745 ); table->SetTableValue( 2139.0, 0.239216, 0.0784314, 0.235294 ); table->SetTableValue( 2140.0, 0.239216, 0.235294, 0.392157 ); table->SetTableValue( 2141.0, 0.0980392, 0.0980392, 0.0980392 ); table->SetTableValue( 2142.0, 0.54902, 0.0784314, 0.235294 ); table->SetTableValue( 2143.0, 0.862745, 0.705882, 0.0784314 ); table->SetTableValue( 2144.0, 0.247059, 0.705882, 0.705882 ); table->SetTableValue( 2145.0, 0.866667, 0.0784314, 0.0392157 ); table->SetTableValue( 2146.0, 0.0823529, 0.862745, 0.0784314 ); table->SetTableValue( 2147.0, 0.717647, 0.392157, 0.0784314 ); table->SetTableValue( 2148.0, 0.866667, 0.0784314, 0.392157 ); table->SetTableValue( 2149.0, 0.866667, 0.235294, 0.54902 ); table->SetTableValue( 2150.0, 0.866667, 0.0784314, 0.862745 ); table->SetTableValue( 2151.0, 0.239216, 0.862745, 0.862745 ); table->SetTableValue( 2152.0, 0.392157, 0.784314, 0.784314 ); table->SetTableValue( 2153.0, 0.0392157, 0.784314, 0.784314 ); table->SetTableValue( 2154.0, 0.866667, 0.862745, 0.0784314 ); table->SetTableValue( 2155.0, 0.552941, 0.0784314, 0.392157 ); table->SetTableValue( 2156.0, 0.239216, 0.862745, 0.392157 ); table->SetTableValue( 2157.0, 0.0823529, 0.862745, 0.235294 ); table->SetTableValue( 2158.0, 0.552941, 0.235294, 0.0784314 ); table->SetTableValue( 2159.0, 0.560784, 0.0784314, 0.862745 ); table->SetTableValue( 2160.0, 0.239216, 0.0784314, 0.705882 ); table->SetTableValue( 2161.0, 0.396078, 0.235294, 0.862745 ); table->SetTableValue( 2162.0, 0.0823529, 0.0784314, 0.54902 ); table->SetTableValue( 2163.0, 0.866667, 0.54902, 0.0784314 ); table->SetTableValue( 2164.0, 0.552941, 0.392157, 0.862745 ); table->SetTableValue( 2165.0, 0.396078, 0.0784314, 0.0784314 ); table->SetTableValue( 2166.0, 0.866667, 0.392157, 0.0784314 ); table->SetTableValue( 2167.0, 0.709804, 0.784314, 0.0784314 ); table->SetTableValue( 2168.0, 0.0823529, 0.705882, 0.54902 ); table->SetTableValue( 2169.0, 0.396078, 0.392157, 0.705882 ); table->SetTableValue( 2170.0, 0.709804, 0.862745, 0.0784314 ); table->SetTableValue( 2171.0, 0.0823529, 0.54902, 0.784314 ); table->SetTableValue( 2172.0, 0.0823529, 0.0784314, 0.941176 ); table->SetTableValue( 2173.0, 0.0823529, 0.0784314, 0.784314 ); table->SetTableValue( 2174.0, 0.239216, 0.705882, 0.235294 ); table->SetTableValue( 2175.0, 0.239216, 0.705882, 0.980392 ); table->SetTableValue( 2176.0, 0.0823529, 0.0784314, 0.235294 ); table->SetTableValue( 2177.0, 0.396078, 0.235294, 0.235294 ); table->SetTableValue( 2178.0, 0.0823529, 0.862745, 0.862745 ); table->SetTableValue( 2179.0, 0.0823529, 0.705882, 0.705882 ); table->SetTableValue( 2180.0, 0.87451, 0.862745, 0.235294 ); table->SetTableValue( 2181.0, 0.866667, 0.235294, 0.235294 ); table->SetTableValue( 2200.0, 0.0980392, 0.235294, 0.239216 ); table->SetTableValue( 2201.0, 0.0980392, 0.352941, 0.235294 ); table->SetTableValue( 2202.0, 0.0980392, 0.470588, 0.235294 ); table->SetTableValue( 2205.0, 0.0980392, 0.588235, 0.235294 ); table->SetTableValue( 2206.0, 0.0980392, 0.705882, 0.235294 ); table->SetTableValue( 2207.0, 0.0980392, 0.823529, 0.235294 ); table->SetTableValue( 2210.0, 0.0980392, 0.588235, 0.352941 ); table->SetTableValue( 2211.0, 0.0980392, 0.705882, 0.352941 ); table->SetTableValue( 2212.0, 0.0980392, 0.823529, 0.352941 ); table->SetTableValue( 3100.0, 0, 0, 0, 0); table->SetTableValue( 3101.0, 0.196078, 0.196078, 0.196078 ); table->SetTableValue( 3102.0, 0.705882, 0.0784314, 0.117647 ); table->SetTableValue( 3103.0, 0.235294, 0.0980392, 0.0980392 ); table->SetTableValue( 3104.0, 0.0980392, 0.235294, 0.235294 ); table->SetTableValue( 3105.0, 0.705882, 0.0784314, 0.0784314 ); table->SetTableValue( 3106.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 3107.0, 0.54902, 0.235294, 0.235294 ); table->SetTableValue( 3108.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 3109.0, 0.54902, 0.392157, 0.705882 ); table->SetTableValue( 3110.0, 0.705882, 0.0784314, 0.54902 ); table->SetTableValue( 3111.0, 0.54902, 0.0784314, 0.54902 ); table->SetTableValue( 3112.0, 0.0823529, 0.0392157, 0.0392157 ); table->SetTableValue( 3113.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 3114.0, 0.0901961, 0.235294, 0.705882 ); table->SetTableValue( 3115.0, 0.705882, 0.235294, 0.705882 ); table->SetTableValue( 3116.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 3117.0, 0.235294, 0.0784314, 0.54902 ); table->SetTableValue( 3118.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 3119.0, 0.254902, 0.392157, 0.0784314 ); table->SetTableValue( 3120.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 3121.0, 0.235294, 0.392157, 0.235294 ); table->SetTableValue( 3122.0, 0.0784314, 0.235294, 0.862745 ); table->SetTableValue( 3123.0, 0.392157, 0.392157, 0.235294 ); table->SetTableValue( 3124.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 3125.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 3126.0, 0.235294, 0.54902, 0.705882 ); table->SetTableValue( 3127.0, 0.0980392, 0.0784314, 0.54902 ); table->SetTableValue( 3128.0, 0.0784314, 0.235294, 0.392157 ); table->SetTableValue( 3129.0, 0.235294, 0.862745, 0.0784314 ); table->SetTableValue( 3130.0, 0.235294, 0.0784314, 0.862745 ); table->SetTableValue( 3131.0, 0.862745, 0.862745, 0.392157 ); table->SetTableValue( 3132.0, 0.705882, 0.235294, 0.235294 ); table->SetTableValue( 3133.0, 0.235294, 0.235294, 0.862745 ); table->SetTableValue( 3134.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 3135.0, 0.254902, 0.862745, 0.235294 ); table->SetTableValue( 3136.0, 0.0980392, 0.54902, 0.0784314 ); table->SetTableValue( 3137.0, 0.0509804, 0, 0.980392 ); table->SetTableValue( 3138.0, 0.239216, 0.0784314, 0.862745 ); table->SetTableValue( 3139.0, 0.239216, 0.0784314, 0.235294 ); table->SetTableValue( 3140.0, 0.239216, 0.235294, 0.392157 ); table->SetTableValue( 3141.0, 0.0980392, 0.0980392, 0.0980392 ); table->SetTableValue( 3142.0, 0.54902, 0.0784314, 0.235294 ); table->SetTableValue( 3143.0, 0.862745, 0.705882, 0.0784314 ); table->SetTableValue( 3144.0, 0.247059, 0.705882, 0.705882 ); table->SetTableValue( 3145.0, 0.866667, 0.0784314, 0.0392157 ); table->SetTableValue( 3146.0, 0.0823529, 0.862745, 0.0784314 ); table->SetTableValue( 3147.0, 0.717647, 0.392157, 0.0784314 ); table->SetTableValue( 3148.0, 0.866667, 0.0784314, 0.392157 ); table->SetTableValue( 3149.0, 0.866667, 0.235294, 0.54902 ); table->SetTableValue( 3150.0, 0.866667, 0.0784314, 0.862745 ); table->SetTableValue( 3151.0, 0.239216, 0.862745, 0.862745 ); table->SetTableValue( 3152.0, 0.392157, 0.784314, 0.784314 ); table->SetTableValue( 3153.0, 0.0392157, 0.784314, 0.784314 ); table->SetTableValue( 3154.0, 0.866667, 0.862745, 0.0784314 ); table->SetTableValue( 3155.0, 0.552941, 0.0784314, 0.392157 ); table->SetTableValue( 3156.0, 0.239216, 0.862745, 0.392157 ); table->SetTableValue( 3157.0, 0.0823529, 0.862745, 0.235294 ); table->SetTableValue( 3158.0, 0.552941, 0.235294, 0.0784314 ); table->SetTableValue( 3159.0, 0.560784, 0.0784314, 0.862745 ); table->SetTableValue( 3160.0, 0.239216, 0.0784314, 0.705882 ); table->SetTableValue( 3161.0, 0.396078, 0.235294, 0.862745 ); table->SetTableValue( 3162.0, 0.0823529, 0.0784314, 0.54902 ); table->SetTableValue( 3163.0, 0.866667, 0.54902, 0.0784314 ); table->SetTableValue( 3164.0, 0.552941, 0.392157, 0.862745 ); table->SetTableValue( 3165.0, 0.396078, 0.0784314, 0.0784314 ); table->SetTableValue( 3166.0, 0.866667, 0.392157, 0.0784314 ); table->SetTableValue( 3167.0, 0.709804, 0.784314, 0.0784314 ); table->SetTableValue( 3168.0, 0.0823529, 0.705882, 0.54902 ); table->SetTableValue( 3169.0, 0.396078, 0.392157, 0.705882 ); table->SetTableValue( 3170.0, 0.709804, 0.862745, 0.0784314 ); table->SetTableValue( 3171.0, 0.0823529, 0.54902, 0.784314 ); table->SetTableValue( 3172.0, 0.0823529, 0.0784314, 0.941176 ); table->SetTableValue( 3173.0, 0.0823529, 0.0784314, 0.784314 ); table->SetTableValue( 3174.0, 0.239216, 0.705882, 0.235294 ); table->SetTableValue( 3175.0, 0.239216, 0.705882, 0.980392 ); table->SetTableValue( 3176.0, 0.0823529, 0.0784314, 0.235294 ); table->SetTableValue( 3177.0, 0.396078, 0.235294, 0.235294 ); table->SetTableValue( 3178.0, 0.0823529, 0.862745, 0.862745 ); table->SetTableValue( 3179.0, 0.0823529, 0.705882, 0.705882 ); table->SetTableValue( 3180.0, 0.87451, 0.862745, 0.235294 ); table->SetTableValue( 3181.0, 0.866667, 0.235294, 0.235294 ); table->SetTableValue( 4100.0, 0, 0, 0, 0); table->SetTableValue( 4101.0, 0.196078, 0.196078, 0.196078 ); table->SetTableValue( 4102.0, 0.705882, 0.0784314, 0.117647 ); table->SetTableValue( 4103.0, 0.235294, 0.0980392, 0.0980392 ); table->SetTableValue( 4104.0, 0.0980392, 0.235294, 0.235294 ); table->SetTableValue( 4105.0, 0.705882, 0.0784314, 0.0784314 ); table->SetTableValue( 4106.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 4107.0, 0.54902, 0.235294, 0.235294 ); table->SetTableValue( 4108.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 4109.0, 0.54902, 0.392157, 0.705882 ); table->SetTableValue( 4110.0, 0.705882, 0.0784314, 0.54902 ); table->SetTableValue( 4111.0, 0.54902, 0.0784314, 0.54902 ); table->SetTableValue( 4112.0, 0.0823529, 0.0392157, 0.0392157 ); table->SetTableValue( 4113.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 4114.0, 0.0901961, 0.235294, 0.705882 ); table->SetTableValue( 4115.0, 0.705882, 0.235294, 0.705882 ); table->SetTableValue( 4116.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 4117.0, 0.235294, 0.0784314, 0.54902 ); table->SetTableValue( 4118.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 4119.0, 0.254902, 0.392157, 0.0784314 ); table->SetTableValue( 4120.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 4121.0, 0.235294, 0.392157, 0.235294 ); table->SetTableValue( 4122.0, 0.0784314, 0.235294, 0.862745 ); table->SetTableValue( 4123.0, 0.392157, 0.392157, 0.235294 ); table->SetTableValue( 4124.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 4125.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 4126.0, 0.235294, 0.54902, 0.705882 ); table->SetTableValue( 4127.0, 0.0980392, 0.0784314, 0.54902 ); table->SetTableValue( 4128.0, 0.0784314, 0.235294, 0.392157 ); table->SetTableValue( 4129.0, 0.235294, 0.862745, 0.0784314 ); table->SetTableValue( 4130.0, 0.235294, 0.0784314, 0.862745 ); table->SetTableValue( 4131.0, 0.862745, 0.862745, 0.392157 ); table->SetTableValue( 4132.0, 0.705882, 0.235294, 0.235294 ); table->SetTableValue( 4133.0, 0.235294, 0.235294, 0.862745 ); table->SetTableValue( 4134.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 4135.0, 0.254902, 0.862745, 0.235294 ); table->SetTableValue( 4136.0, 0.0980392, 0.54902, 0.0784314 ); table->SetTableValue( 4137.0, 0.0509804, 0, 0.980392 ); table->SetTableValue( 4138.0, 0.239216, 0.0784314, 0.862745 ); table->SetTableValue( 4139.0, 0.239216, 0.0784314, 0.235294 ); table->SetTableValue( 4140.0, 0.239216, 0.235294, 0.392157 ); table->SetTableValue( 4141.0, 0.0980392, 0.0980392, 0.0980392 ); table->SetTableValue( 4142.0, 0.54902, 0.0784314, 0.235294 ); table->SetTableValue( 4143.0, 0.862745, 0.705882, 0.0784314 ); table->SetTableValue( 4144.0, 0.247059, 0.705882, 0.705882 ); table->SetTableValue( 4145.0, 0.866667, 0.0784314, 0.0392157 ); table->SetTableValue( 4146.0, 0.0823529, 0.862745, 0.0784314 ); table->SetTableValue( 4147.0, 0.717647, 0.392157, 0.0784314 ); table->SetTableValue( 4148.0, 0.866667, 0.0784314, 0.392157 ); table->SetTableValue( 4149.0, 0.866667, 0.235294, 0.54902 ); table->SetTableValue( 4150.0, 0.866667, 0.0784314, 0.862745 ); table->SetTableValue( 4151.0, 0.239216, 0.862745, 0.862745 ); table->SetTableValue( 4152.0, 0.392157, 0.784314, 0.784314 ); table->SetTableValue( 4153.0, 0.0392157, 0.784314, 0.784314 ); table->SetTableValue( 4154.0, 0.866667, 0.862745, 0.0784314 ); table->SetTableValue( 4155.0, 0.552941, 0.0784314, 0.392157 ); table->SetTableValue( 4156.0, 0.239216, 0.862745, 0.392157 ); table->SetTableValue( 4157.0, 0.0823529, 0.862745, 0.235294 ); table->SetTableValue( 4158.0, 0.552941, 0.235294, 0.0784314 ); table->SetTableValue( 4159.0, 0.560784, 0.0784314, 0.862745 ); table->SetTableValue( 4160.0, 0.239216, 0.0784314, 0.705882 ); table->SetTableValue( 4161.0, 0.396078, 0.235294, 0.862745 ); table->SetTableValue( 4162.0, 0.0823529, 0.0784314, 0.54902 ); table->SetTableValue( 4163.0, 0.866667, 0.54902, 0.0784314 ); table->SetTableValue( 4164.0, 0.552941, 0.392157, 0.862745 ); table->SetTableValue( 4165.0, 0.396078, 0.0784314, 0.0784314 ); table->SetTableValue( 4166.0, 0.866667, 0.392157, 0.0784314 ); table->SetTableValue( 4167.0, 0.709804, 0.784314, 0.0784314 ); table->SetTableValue( 4168.0, 0.0823529, 0.705882, 0.54902 ); table->SetTableValue( 4169.0, 0.396078, 0.392157, 0.705882 ); table->SetTableValue( 4170.0, 0.709804, 0.862745, 0.0784314 ); table->SetTableValue( 4171.0, 0.0823529, 0.54902, 0.784314 ); table->SetTableValue( 4172.0, 0.0823529, 0.0784314, 0.941176 ); table->SetTableValue( 4173.0, 0.0823529, 0.0784314, 0.784314 ); table->SetTableValue( 4174.0, 0.239216, 0.705882, 0.235294 ); table->SetTableValue( 4175.0, 0.239216, 0.705882, 0.980392 ); table->SetTableValue( 4176.0, 0.0823529, 0.0784314, 0.235294 ); table->SetTableValue( 4177.0, 0.396078, 0.235294, 0.235294 ); table->SetTableValue( 4178.0, 0.0823529, 0.862745, 0.862745 ); table->SetTableValue( 4179.0, 0.0823529, 0.705882, 0.705882 ); table->SetTableValue( 4180.0, 0.87451, 0.862745, 0.235294 ); table->SetTableValue( 4181.0, 0.866667, 0.235294, 0.235294 ); table->SetTableValue( 5001.0, 0.0784314, 0.117647, 0.156863 ); table->SetTableValue( 5002.0, 0.0784314, 0.117647, 0.156863 ); table->SetTableValue( 5100.0, 0.8, 0.4, 0.4 ); table->SetTableValue( 5101.0, 0.8, 0.4, 0.4 ); table->SetTableValue( 5102.0, 1, 1, 0.4 ); table->SetTableValue( 5103.0, 0.6, 0.8, 0 ); table->SetTableValue( 5104.0, 0, 0.6, 0.6 ); table->SetTableValue( 5105.0, 0.8, 0.6, 1 ); table->SetTableValue( 5106.0, 1, 0.6, 0.2 ); table->SetTableValue( 5107.0, 0.8, 0.8, 0.8 ); table->SetTableValue( 5108.0, 0.6, 1, 1 ); table->SetTableValue( 5109.0, 0.4, 0.6, 1 ); table->SetTableValue( 5110.0, 1, 1, 0.4 ); table->SetTableValue( 5111.0, 0.6, 0.8, 0 ); table->SetTableValue( 5112.0, 0, 0.6, 0.6 ); table->SetTableValue( 5113.0, 0.8, 0.6, 1 ); table->SetTableValue( 5114.0, 1, 0.6, 0.2 ); table->SetTableValue( 5115.0, 0.8, 0.8, 0.8 ); table->SetTableValue( 5116.0, 0.6, 1, 1 ); table->SetTableValue( 5117.0, 0.4, 0.6, 1 ); table->SetTableValue( 5200.0, 0.8, 0.4, 0.4 ); table->SetTableValue( 5201.0, 0.8, 0.4, 0.4 ); table->SetTableValue( 5202.0, 1, 1, 0.4 ); table->SetTableValue( 5203.0, 0.6, 0.8, 0 ); table->SetTableValue( 5204.0, 0, 0.6, 0.6 ); table->SetTableValue( 5205.0, 0.8, 0.6, 1 ); table->SetTableValue( 5206.0, 1, 0.6, 0.2 ); table->SetTableValue( 5207.0, 0.8, 0.8, 0.8 ); table->SetTableValue( 5208.0, 0.6, 1, 1 ); table->SetTableValue( 5209.0, 0.4, 0.6, 1 ); table->SetTableValue( 5210.0, 1, 1, 0.4 ); table->SetTableValue( 5211.0, 0.6, 0.8, 0 ); table->SetTableValue( 5212.0, 0, 0.6, 0.6 ); table->SetTableValue( 5213.0, 0.8, 0.6, 1 ); table->SetTableValue( 5214.0, 1, 0.6, 0.2 ); table->SetTableValue( 5215.0, 0.8, 0.8, 0.8 ); table->SetTableValue( 5216.0, 0.6, 1, 1 ); table->SetTableValue( 5217.0, 0.4, 0.6, 1 ); table->SetTableValue( 6000.0, 0, 1, 0 ); table->SetTableValue( 6001.0, 1, 1, 0 ); table->SetTableValue( 6002.0, 0, 1, 1 ); table->SetTableValue( 6003.0, 0, 0, 1 ); table->SetTableValue( 6010.0, 0.92549, 0.0627451, 0.905882 ); table->SetTableValue( 6020.0, 0.929412, 0.0705882, 0.909804 ); table->SetTableValue( 6030.0, 0.92549, 0.0509804, 0.890196 ); table->SetTableValue( 6040.0, 0.92549, 0.0666667, 0.894118 ); table->SetTableValue( 6050.0, 0.00392157, 1, 0.00392157 ); table->SetTableValue( 6060.0, 0.00784314, 1, 0.00392157 ); table->SetTableValue( 6070.0, 0.92549, 0.054902, 0.901961 ); table->SetTableValue( 6080.0, 0.929412, 0.054902, 0.901961 ); table->SetTableValue( 7001.0, 0.282353, 0.517647, 0.709804 ); table->SetTableValue( 7002.0, 0.952941, 0.952941, 0.952941 ); table->SetTableValue( 7003.0, 0.811765, 0.247059, 0.309804 ); table->SetTableValue( 7004.0, 0.47451, 0.0784314, 0.529412 ); table->SetTableValue( 7005.0, 0.772549, 0.235294, 0.972549 ); table->SetTableValue( 7006.0, 0.00784314, 0.584314, 0.00784314 ); table->SetTableValue( 7007.0, 0.866667, 0.976471, 0.65098 ); table->SetTableValue( 7008.0, 0.909804, 0.572549, 0.137255 ); table->SetTableValue( 7009.0, 0.0784314, 0.235294, 0.470588 ); table->SetTableValue( 7010.0, 0.980392, 0.980392, 0 ); table->SetTableValue( 7011.0, 0.478431, 0.733333, 0.870588 ); table->SetTableValue( 7012.0, 0.929412, 0.0470588, 0.694118 ); table->SetTableValue( 7013.0, 0.0392157, 0.192157, 1 ); table->SetTableValue( 7014.0, 0.803922, 0.721569, 0.564706 ); table->SetTableValue( 7015.0, 0.176471, 0.803922, 0.647059 ); table->SetTableValue( 7016.0, 0.458824, 0.627451, 0.686275 ); table->SetTableValue( 7017.0, 0.866667, 0.85098, 0.0823529 ); table->SetTableValue( 7018.0, 0.0784314, 0.235294, 0.470588 ); table->SetTableValue( 7019.0, 0.552941, 0.0823529, 0.392157 ); table->SetTableValue( 7020.0, 0.882353, 0.54902, 0.552941 ); table->SetTableValue( 7100.0, 0.164706, 0.788235, 0.658824 ); table->SetTableValue( 7101.0, 0.658824, 0.407843, 0.635294 ); table->SetTableValue( 8001.0, 0.290196, 0.509804, 0.709804 ); table->SetTableValue( 8002.0, 0.94902, 0.945098, 0.941176 ); table->SetTableValue( 8003.0, 0.807843, 0.254902, 0.305882 ); table->SetTableValue( 8004.0, 0.470588, 0.0823529, 0.521569 ); table->SetTableValue( 8005.0, 0.764706, 0.239216, 0.964706 ); table->SetTableValue( 8006.0, 0.0117647, 0.576471, 0.0235294 ); table->SetTableValue( 8007.0, 0.862745, 0.984314, 0.639216 ); table->SetTableValue( 8008.0, 0.909804, 0.572549, 0.129412 ); table->SetTableValue( 8009.0, 0.0156863, 0.447059, 0.054902 ); table->SetTableValue( 8010.0, 0.47451, 0.721569, 0.862745 ); table->SetTableValue( 8011.0, 0.921569, 0.0431373, 0.686275 ); table->SetTableValue( 8012.0, 0.0470588, 0.180392, 0.980392 ); table->SetTableValue( 8013.0, 0.796078, 0.713725, 0.560784 ); table->SetTableValue( 8014.0, 0.164706, 0.8, 0.654902 ); table->SetTableValue( 9000.0, 0.117647, 0.0196078, 0.117647 ); table->SetTableValue( 9001.0, 0.117647, 0.392157, 0.176471 ); table->SetTableValue( 9002.0, 0.509804, 0.392157, 0.647059 ); table->SetTableValue( 9003.0, 0.411765, 0.0980392, 0.0196078 ); table->SetTableValue( 9004.0, 0.490196, 0.27451, 0.215686 ); table->SetTableValue( 9005.0, 0.882353, 0.0784314, 0.411765 ); table->SetTableValue( 9006.0, 0.882353, 0.0784314, 0.0588235 ); table->SetTableValue( 9500.0, 0.117647, 0.215686, 0.117647 ); table->SetTableValue( 9501.0, 0.117647, 0.588235, 0.176471 ); table->SetTableValue( 9502.0, 0.509804, 0.588235, 0.647059 ); table->SetTableValue( 9503.0, 0.411765, 0.294118, 0.0196078 ); table->SetTableValue( 9504.0, 0.490196, 0.470588, 0.215686 ); table->SetTableValue( 9505.0, 0.882353, 0.27451, 0.411765 ); table->SetTableValue( 9506.0, 0.882353, 0.27451, 0.0588235 ); table->SetTableValue( 11100.0, 0, 0, 0, 0); table->SetTableValue( 11101.0, 0.0901961, 0.862745, 0.235294 ); table->SetTableValue( 11102.0, 0.0901961, 0.235294, 0.705882 ); table->SetTableValue( 11103.0, 0.247059, 0.392157, 0.235294 ); table->SetTableValue( 11104.0, 0.247059, 0.0784314, 0.862745 ); table->SetTableValue( 11105.0, 0.0509804, 0, 0.980392 ); table->SetTableValue( 11106.0, 0.101961, 0.235294, 0 ); table->SetTableValue( 11107.0, 0.101961, 0.235294, 0.294118 ); table->SetTableValue( 11108.0, 0.101961, 0.235294, 0.588235 ); table->SetTableValue( 11109.0, 0.0980392, 0.235294, 0.980392 ); table->SetTableValue( 11110.0, 0.235294, 0.0980392, 0.0980392 ); table->SetTableValue( 11111.0, 0.705882, 0.0784314, 0.0784314 ); table->SetTableValue( 11112.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 11113.0, 0.54902, 0.235294, 0.235294 ); table->SetTableValue( 11114.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 11115.0, 0.54902, 0.392157, 0.705882 ); table->SetTableValue( 11116.0, 0.705882, 0.0784314, 0.54902 ); table->SetTableValue( 11117.0, 0.0901961, 0.0392157, 0.0392157 ); table->SetTableValue( 11118.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 11119.0, 0.705882, 0.235294, 0.705882 ); table->SetTableValue( 11120.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 11121.0, 0.235294, 0.0784314, 0.54902 ); table->SetTableValue( 11122.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 11123.0, 0.254902, 0.392157, 0.0784314 ); table->SetTableValue( 11124.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 11125.0, 0.0784314, 0.235294, 0.862745 ); table->SetTableValue( 11126.0, 0.392157, 0.392157, 0.235294 ); table->SetTableValue( 11127.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 11128.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 11129.0, 0.235294, 0.54902, 0.705882 ); table->SetTableValue( 11130.0, 0.0980392, 0.0784314, 0.54902 ); table->SetTableValue( 11131.0, 0.0784314, 0.235294, 0.392157 ); table->SetTableValue( 11132.0, 0.235294, 0.862745, 0.0784314 ); table->SetTableValue( 11133.0, 0.235294, 0.235294, 0.862745 ); table->SetTableValue( 11134.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 11135.0, 0.254902, 0.862745, 0.235294 ); table->SetTableValue( 11136.0, 0.0980392, 0.54902, 0.0784314 ); table->SetTableValue( 11137.0, 0.862745, 0.862745, 0.392157 ); table->SetTableValue( 11138.0, 0.705882, 0.235294, 0.235294 ); table->SetTableValue( 11139.0, 0.239216, 0.0784314, 0.862745 ); table->SetTableValue( 11140.0, 0.239216, 0.0784314, 0.235294 ); table->SetTableValue( 11141.0, 0.239216, 0.235294, 0.392157 ); table->SetTableValue( 11142.0, 0.0980392, 0.0980392, 0.0980392 ); table->SetTableValue( 11143.0, 0.54902, 0.0784314, 0.235294 ); table->SetTableValue( 11144.0, 0.862745, 0.705882, 0.0784314 ); table->SetTableValue( 11145.0, 0.247059, 0.705882, 0.705882 ); table->SetTableValue( 11146.0, 0.866667, 0.0784314, 0.0392157 ); table->SetTableValue( 11147.0, 0.866667, 0.0784314, 0.392157 ); table->SetTableValue( 11148.0, 0.866667, 0.235294, 0.54902 ); table->SetTableValue( 11149.0, 0.866667, 0.0784314, 0.862745 ); table->SetTableValue( 11150.0, 0.239216, 0.862745, 0.862745 ); table->SetTableValue( 11151.0, 0.392157, 0.784314, 0.784314 ); table->SetTableValue( 11152.0, 0.0392157, 0.784314, 0.784314 ); table->SetTableValue( 11153.0, 0.866667, 0.862745, 0.0784314 ); table->SetTableValue( 11154.0, 0.552941, 0.0784314, 0.392157 ); table->SetTableValue( 11155.0, 0.239216, 0.862745, 0.392157 ); table->SetTableValue( 11156.0, 0.552941, 0.235294, 0.0784314 ); table->SetTableValue( 11157.0, 0.560784, 0.0784314, 0.862745 ); table->SetTableValue( 11158.0, 0.396078, 0.235294, 0.862745 ); table->SetTableValue( 11159.0, 0.0823529, 0.0784314, 0.54902 ); table->SetTableValue( 11160.0, 0.239216, 0.0784314, 0.705882 ); table->SetTableValue( 11161.0, 0.866667, 0.54902, 0.0784314 ); table->SetTableValue( 11162.0, 0.552941, 0.392157, 0.862745 ); table->SetTableValue( 11163.0, 0.866667, 0.392157, 0.0784314 ); table->SetTableValue( 11164.0, 0.709804, 0.784314, 0.0784314 ); table->SetTableValue( 11165.0, 0.396078, 0.0784314, 0.0784314 ); table->SetTableValue( 11166.0, 0.396078, 0.392157, 0.705882 ); table->SetTableValue( 11167.0, 0.709804, 0.862745, 0.0784314 ); table->SetTableValue( 11168.0, 0.0823529, 0.54902, 0.784314 ); table->SetTableValue( 11169.0, 0.0823529, 0.0784314, 0.941176 ); table->SetTableValue( 11170.0, 0.0823529, 0.0784314, 0.784314 ); table->SetTableValue( 11171.0, 0.0823529, 0.0784314, 0.235294 ); table->SetTableValue( 11172.0, 0.396078, 0.235294, 0.235294 ); table->SetTableValue( 11173.0, 0.0823529, 0.705882, 0.705882 ); table->SetTableValue( 11174.0, 0.87451, 0.862745, 0.235294 ); table->SetTableValue( 11175.0, 0.866667, 0.235294, 0.235294 ); table->SetTableValue( 12100.0, 0, 0, 0, 0); table->SetTableValue( 12101.0, 0.0901961, 0.862745, 0.235294 ); table->SetTableValue( 12102.0, 0.0901961, 0.235294, 0.705882 ); table->SetTableValue( 12103.0, 0.247059, 0.392157, 0.235294 ); table->SetTableValue( 12104.0, 0.247059, 0.0784314, 0.862745 ); table->SetTableValue( 12105.0, 0.0509804, 0, 0.980392 ); table->SetTableValue( 12106.0, 0.101961, 0.235294, 0 ); table->SetTableValue( 12107.0, 0.101961, 0.235294, 0.294118 ); table->SetTableValue( 12108.0, 0.101961, 0.235294, 0.588235 ); table->SetTableValue( 12109.0, 0.0980392, 0.235294, 0.980392 ); table->SetTableValue( 12110.0, 0.235294, 0.0980392, 0.0980392 ); table->SetTableValue( 12111.0, 0.705882, 0.0784314, 0.0784314 ); table->SetTableValue( 12112.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 12113.0, 0.54902, 0.235294, 0.235294 ); table->SetTableValue( 12114.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 12115.0, 0.54902, 0.392157, 0.705882 ); table->SetTableValue( 12116.0, 0.705882, 0.0784314, 0.54902 ); table->SetTableValue( 12117.0, 0.0901961, 0.0392157, 0.0392157 ); table->SetTableValue( 12118.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 12119.0, 0.705882, 0.235294, 0.705882 ); table->SetTableValue( 12120.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 12121.0, 0.235294, 0.0784314, 0.54902 ); table->SetTableValue( 12122.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 12123.0, 0.254902, 0.392157, 0.0784314 ); table->SetTableValue( 12124.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 12125.0, 0.0784314, 0.235294, 0.862745 ); table->SetTableValue( 12126.0, 0.392157, 0.392157, 0.235294 ); table->SetTableValue( 12127.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 12128.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 12129.0, 0.235294, 0.54902, 0.705882 ); table->SetTableValue( 12130.0, 0.0980392, 0.0784314, 0.54902 ); table->SetTableValue( 12131.0, 0.0784314, 0.235294, 0.392157 ); table->SetTableValue( 12132.0, 0.235294, 0.862745, 0.0784314 ); table->SetTableValue( 12133.0, 0.235294, 0.235294, 0.862745 ); table->SetTableValue( 12134.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 12135.0, 0.254902, 0.862745, 0.235294 ); table->SetTableValue( 12136.0, 0.0980392, 0.54902, 0.0784314 ); table->SetTableValue( 12137.0, 0.862745, 0.862745, 0.392157 ); table->SetTableValue( 12138.0, 0.705882, 0.235294, 0.235294 ); table->SetTableValue( 12139.0, 0.239216, 0.0784314, 0.862745 ); table->SetTableValue( 12140.0, 0.239216, 0.0784314, 0.235294 ); table->SetTableValue( 12141.0, 0.239216, 0.235294, 0.392157 ); table->SetTableValue( 12142.0, 0.0980392, 0.0980392, 0.0980392 ); table->SetTableValue( 12143.0, 0.54902, 0.0784314, 0.235294 ); table->SetTableValue( 12144.0, 0.862745, 0.705882, 0.0784314 ); table->SetTableValue( 12145.0, 0.247059, 0.705882, 0.705882 ); table->SetTableValue( 12146.0, 0.866667, 0.0784314, 0.0392157 ); table->SetTableValue( 12147.0, 0.866667, 0.0784314, 0.392157 ); table->SetTableValue( 12148.0, 0.866667, 0.235294, 0.54902 ); table->SetTableValue( 12149.0, 0.866667, 0.0784314, 0.862745 ); table->SetTableValue( 12150.0, 0.239216, 0.862745, 0.862745 ); table->SetTableValue( 12151.0, 0.392157, 0.784314, 0.784314 ); table->SetTableValue( 12152.0, 0.0392157, 0.784314, 0.784314 ); table->SetTableValue( 12153.0, 0.866667, 0.862745, 0.0784314 ); table->SetTableValue( 12154.0, 0.552941, 0.0784314, 0.392157 ); table->SetTableValue( 12155.0, 0.239216, 0.862745, 0.392157 ); table->SetTableValue( 12156.0, 0.552941, 0.235294, 0.0784314 ); table->SetTableValue( 12157.0, 0.560784, 0.0784314, 0.862745 ); table->SetTableValue( 12158.0, 0.396078, 0.235294, 0.862745 ); table->SetTableValue( 12159.0, 0.0823529, 0.0784314, 0.54902 ); table->SetTableValue( 12160.0, 0.239216, 0.0784314, 0.705882 ); table->SetTableValue( 12161.0, 0.866667, 0.54902, 0.0784314 ); table->SetTableValue( 12162.0, 0.552941, 0.392157, 0.862745 ); table->SetTableValue( 12163.0, 0.866667, 0.392157, 0.0784314 ); table->SetTableValue( 12164.0, 0.709804, 0.784314, 0.0784314 ); table->SetTableValue( 12165.0, 0.396078, 0.0784314, 0.0784314 ); table->SetTableValue( 12166.0, 0.396078, 0.392157, 0.705882 ); table->SetTableValue( 12167.0, 0.709804, 0.862745, 0.0784314 ); table->SetTableValue( 12168.0, 0.0823529, 0.54902, 0.784314 ); table->SetTableValue( 12169.0, 0.0823529, 0.0784314, 0.941176 ); table->SetTableValue( 12170.0, 0.0823529, 0.0784314, 0.784314 ); table->SetTableValue( 12171.0, 0.0823529, 0.0784314, 0.235294 ); table->SetTableValue( 12172.0, 0.396078, 0.235294, 0.235294 ); table->SetTableValue( 12173.0, 0.0823529, 0.705882, 0.705882 ); table->SetTableValue( 12174.0, 0.87451, 0.862745, 0.235294 ); table->SetTableValue( 12175.0, 0.866667, 0.235294, 0.235294 ); table->SetTableValue( 13100.0, 0, 0, 0, 0); table->SetTableValue( 13101.0, 0.0901961, 0.862745, 0.235294 ); table->SetTableValue( 13102.0, 0.0901961, 0.235294, 0.705882 ); table->SetTableValue( 13103.0, 0.247059, 0.392157, 0.235294 ); table->SetTableValue( 13104.0, 0.247059, 0.0784314, 0.862745 ); table->SetTableValue( 13105.0, 0.0509804, 0, 0.980392 ); table->SetTableValue( 13106.0, 0.101961, 0.235294, 0 ); table->SetTableValue( 13107.0, 0.101961, 0.235294, 0.294118 ); table->SetTableValue( 13108.0, 0.101961, 0.235294, 0.588235 ); table->SetTableValue( 13109.0, 0.0980392, 0.235294, 0.980392 ); table->SetTableValue( 13110.0, 0.235294, 0.0980392, 0.0980392 ); table->SetTableValue( 13111.0, 0.705882, 0.0784314, 0.0784314 ); table->SetTableValue( 13112.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 13113.0, 0.54902, 0.235294, 0.235294 ); table->SetTableValue( 13114.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 13115.0, 0.54902, 0.392157, 0.705882 ); table->SetTableValue( 13116.0, 0.705882, 0.0784314, 0.54902 ); table->SetTableValue( 13117.0, 0.0901961, 0.0392157, 0.0392157 ); table->SetTableValue( 13118.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 13119.0, 0.705882, 0.235294, 0.705882 ); table->SetTableValue( 13120.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 13121.0, 0.235294, 0.0784314, 0.54902 ); table->SetTableValue( 13122.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 13123.0, 0.254902, 0.392157, 0.0784314 ); table->SetTableValue( 13124.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 13125.0, 0.0784314, 0.235294, 0.862745 ); table->SetTableValue( 13126.0, 0.392157, 0.392157, 0.235294 ); table->SetTableValue( 13127.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 13128.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 13129.0, 0.235294, 0.54902, 0.705882 ); table->SetTableValue( 13130.0, 0.0980392, 0.0784314, 0.54902 ); table->SetTableValue( 13131.0, 0.0784314, 0.235294, 0.392157 ); table->SetTableValue( 13132.0, 0.235294, 0.862745, 0.0784314 ); table->SetTableValue( 13133.0, 0.235294, 0.235294, 0.862745 ); table->SetTableValue( 13134.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 13135.0, 0.254902, 0.862745, 0.235294 ); table->SetTableValue( 13136.0, 0.0980392, 0.54902, 0.0784314 ); table->SetTableValue( 13137.0, 0.862745, 0.862745, 0.392157 ); table->SetTableValue( 13138.0, 0.705882, 0.235294, 0.235294 ); table->SetTableValue( 13139.0, 0.239216, 0.0784314, 0.862745 ); table->SetTableValue( 13140.0, 0.239216, 0.0784314, 0.235294 ); table->SetTableValue( 13141.0, 0.239216, 0.235294, 0.392157 ); table->SetTableValue( 13142.0, 0.0980392, 0.0980392, 0.0980392 ); table->SetTableValue( 13143.0, 0.54902, 0.0784314, 0.235294 ); table->SetTableValue( 13144.0, 0.862745, 0.705882, 0.0784314 ); table->SetTableValue( 13145.0, 0.247059, 0.705882, 0.705882 ); table->SetTableValue( 13146.0, 0.866667, 0.0784314, 0.0392157 ); table->SetTableValue( 13147.0, 0.866667, 0.0784314, 0.392157 ); table->SetTableValue( 13148.0, 0.866667, 0.235294, 0.54902 ); table->SetTableValue( 13149.0, 0.866667, 0.0784314, 0.862745 ); table->SetTableValue( 13150.0, 0.239216, 0.862745, 0.862745 ); table->SetTableValue( 13151.0, 0.392157, 0.784314, 0.784314 ); table->SetTableValue( 13152.0, 0.0392157, 0.784314, 0.784314 ); table->SetTableValue( 13153.0, 0.866667, 0.862745, 0.0784314 ); table->SetTableValue( 13154.0, 0.552941, 0.0784314, 0.392157 ); table->SetTableValue( 13155.0, 0.239216, 0.862745, 0.392157 ); table->SetTableValue( 13156.0, 0.552941, 0.235294, 0.0784314 ); table->SetTableValue( 13157.0, 0.560784, 0.0784314, 0.862745 ); table->SetTableValue( 13158.0, 0.396078, 0.235294, 0.862745 ); table->SetTableValue( 13159.0, 0.0823529, 0.0784314, 0.54902 ); table->SetTableValue( 13160.0, 0.239216, 0.0784314, 0.705882 ); table->SetTableValue( 13161.0, 0.866667, 0.54902, 0.0784314 ); table->SetTableValue( 13162.0, 0.552941, 0.392157, 0.862745 ); table->SetTableValue( 13163.0, 0.866667, 0.392157, 0.0784314 ); table->SetTableValue( 13164.0, 0.709804, 0.784314, 0.0784314 ); table->SetTableValue( 13165.0, 0.396078, 0.0784314, 0.0784314 ); table->SetTableValue( 13166.0, 0.396078, 0.392157, 0.705882 ); table->SetTableValue( 13167.0, 0.709804, 0.862745, 0.0784314 ); table->SetTableValue( 13168.0, 0.0823529, 0.54902, 0.784314 ); table->SetTableValue( 13169.0, 0.0823529, 0.0784314, 0.941176 ); table->SetTableValue( 13170.0, 0.0823529, 0.0784314, 0.784314 ); table->SetTableValue( 13171.0, 0.0823529, 0.0784314, 0.235294 ); table->SetTableValue( 13172.0, 0.396078, 0.235294, 0.235294 ); table->SetTableValue( 13173.0, 0.0823529, 0.705882, 0.705882 ); table->SetTableValue( 13174.0, 0.87451, 0.862745, 0.235294 ); table->SetTableValue( 13175.0, 0.866667, 0.235294, 0.235294 ); table->SetTableValue( 14100.0, 0, 0, 0, 0); table->SetTableValue( 14101.0, 0.0901961, 0.862745, 0.235294 ); table->SetTableValue( 14102.0, 0.0901961, 0.235294, 0.705882 ); table->SetTableValue( 14103.0, 0.247059, 0.392157, 0.235294 ); table->SetTableValue( 14104.0, 0.247059, 0.0784314, 0.862745 ); table->SetTableValue( 14105.0, 0.0509804, 0, 0.980392 ); table->SetTableValue( 14106.0, 0.101961, 0.235294, 0 ); table->SetTableValue( 14107.0, 0.101961, 0.235294, 0.294118 ); table->SetTableValue( 14108.0, 0.101961, 0.235294, 0.588235 ); table->SetTableValue( 14109.0, 0.0980392, 0.235294, 0.980392 ); table->SetTableValue( 14110.0, 0.235294, 0.0980392, 0.0980392 ); table->SetTableValue( 14111.0, 0.705882, 0.0784314, 0.0784314 ); table->SetTableValue( 14112.0, 0.862745, 0.0784314, 0.392157 ); table->SetTableValue( 14113.0, 0.54902, 0.235294, 0.235294 ); table->SetTableValue( 14114.0, 0.705882, 0.862745, 0.54902 ); table->SetTableValue( 14115.0, 0.54902, 0.392157, 0.705882 ); table->SetTableValue( 14116.0, 0.705882, 0.0784314, 0.54902 ); table->SetTableValue( 14117.0, 0.0901961, 0.0392157, 0.0392157 ); table->SetTableValue( 14118.0, 0.882353, 0.54902, 0.54902 ); table->SetTableValue( 14119.0, 0.705882, 0.235294, 0.705882 ); table->SetTableValue( 14120.0, 0.0784314, 0.862745, 0.235294 ); table->SetTableValue( 14121.0, 0.235294, 0.0784314, 0.54902 ); table->SetTableValue( 14122.0, 0.862745, 0.705882, 0.54902 ); table->SetTableValue( 14123.0, 0.254902, 0.392157, 0.0784314 ); table->SetTableValue( 14124.0, 0.862745, 0.235294, 0.0784314 ); table->SetTableValue( 14125.0, 0.0784314, 0.235294, 0.862745 ); table->SetTableValue( 14126.0, 0.392157, 0.392157, 0.235294 ); table->SetTableValue( 14127.0, 0.862745, 0.705882, 0.862745 ); table->SetTableValue( 14128.0, 0.0784314, 0.705882, 0.54902 ); table->SetTableValue( 14129.0, 0.235294, 0.54902, 0.705882 ); table->SetTableValue( 14130.0, 0.0980392, 0.0784314, 0.54902 ); table->SetTableValue( 14131.0, 0.0784314, 0.235294, 0.392157 ); table->SetTableValue( 14132.0, 0.235294, 0.862745, 0.0784314 ); table->SetTableValue( 14133.0, 0.235294, 0.235294, 0.862745 ); table->SetTableValue( 14134.0, 0.862745, 0.235294, 0.862745 ); table->SetTableValue( 14135.0, 0.254902, 0.862745, 0.235294 ); table->SetTableValue( 14136.0, 0.0980392, 0.54902, 0.0784314 ); table->SetTableValue( 14137.0, 0.862745, 0.862745, 0.392157 ); table->SetTableValue( 14138.0, 0.705882, 0.235294, 0.235294 ); table->SetTableValue( 14139.0, 0.239216, 0.0784314, 0.862745 ); table->SetTableValue( 14140.0, 0.239216, 0.0784314, 0.235294 ); table->SetTableValue( 14141.0, 0.239216, 0.235294, 0.392157 ); table->SetTableValue( 14142.0, 0.0980392, 0.0980392, 0.0980392 ); table->SetTableValue( 14143.0, 0.54902, 0.0784314, 0.235294 ); table->SetTableValue( 14144.0, 0.862745, 0.705882, 0.0784314 ); table->SetTableValue( 14145.0, 0.247059, 0.705882, 0.705882 ); table->SetTableValue( 14146.0, 0.866667, 0.0784314, 0.0392157 ); table->SetTableValue( 14147.0, 0.866667, 0.0784314, 0.392157 ); table->SetTableValue( 14148.0, 0.866667, 0.235294, 0.54902 ); table->SetTableValue( 14149.0, 0.866667, 0.0784314, 0.862745 ); table->SetTableValue( 14150.0, 0.239216, 0.862745, 0.862745 ); table->SetTableValue( 14151.0, 0.392157, 0.784314, 0.784314 ); table->SetTableValue( 14152.0, 0.0392157, 0.784314, 0.784314 ); table->SetTableValue( 14153.0, 0.866667, 0.862745, 0.0784314 ); table->SetTableValue( 14154.0, 0.552941, 0.0784314, 0.392157 ); table->SetTableValue( 14155.0, 0.239216, 0.862745, 0.392157 ); table->SetTableValue( 14156.0, 0.552941, 0.235294, 0.0784314 ); table->SetTableValue( 14157.0, 0.560784, 0.0784314, 0.862745 ); table->SetTableValue( 14158.0, 0.396078, 0.235294, 0.862745 ); table->SetTableValue( 14159.0, 0.0823529, 0.0784314, 0.54902 ); table->SetTableValue( 14160.0, 0.239216, 0.0784314, 0.705882 ); table->SetTableValue( 14161.0, 0.866667, 0.54902, 0.0784314 ); table->SetTableValue( 14162.0, 0.552941, 0.392157, 0.862745 ); table->SetTableValue( 14163.0, 0.866667, 0.392157, 0.0784314 ); table->SetTableValue( 14164.0, 0.709804, 0.784314, 0.0784314 ); table->SetTableValue( 14165.0, 0.396078, 0.0784314, 0.0784314 ); table->SetTableValue( 14166.0, 0.396078, 0.392157, 0.705882 ); table->SetTableValue( 14167.0, 0.709804, 0.862745, 0.0784314 ); table->SetTableValue( 14168.0, 0.0823529, 0.54902, 0.784314 ); table->SetTableValue( 14169.0, 0.0823529, 0.0784314, 0.941176 ); table->SetTableValue( 14170.0, 0.0823529, 0.0784314, 0.784314 ); table->SetTableValue( 14171.0, 0.0823529, 0.0784314, 0.235294 ); table->SetTableValue( 14172.0, 0.396078, 0.235294, 0.235294 ); table->SetTableValue( 14173.0, 0.0823529, 0.705882, 0.705882 ); table->SetTableValue( 14174.0, 0.87451, 0.862745, 0.235294 ); table->SetTableValue( 14175.0, 0.866667, 0.235294, 0.235294 ); mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); lookupTable->SetVtkLookupTable( table ); return lookupTable; } TransferFunction::Pointer FreeSurferParcellationTranslator::CreateTransferFunction() { mitk::TransferFunction::Pointer transferFunction = mitk::TransferFunction::New(); transferFunction->AddRGBPoint( 1.0, 0.27451, 0.509804, 0.705882 ); transferFunction->AddRGBPoint( 2.0, 0.960784, 0.960784, 0.960784 ); transferFunction->AddRGBPoint( 3.0, 0.803922, 0.243137, 0.305882 ); transferFunction->AddRGBPoint( 4.0, 0.470588, 0.0705882, 0.52549 ); transferFunction->AddRGBPoint( 5.0, 0.768627, 0.227451, 0.980392 ); transferFunction->AddRGBPoint( 6.0, 0, 0.580392, 0 ); transferFunction->AddRGBPoint( 7.0, 0.862745, 0.972549, 0.643137 ); transferFunction->AddRGBPoint( 8.0, 0.901961, 0.580392, 0.133333 ); transferFunction->AddRGBPoint( 9.0, 0, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 10.0, 0, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 11.0, 0.478431, 0.729412, 0.862745 ); transferFunction->AddRGBPoint( 12.0, 0.92549, 0.0509804, 0.690196 ); transferFunction->AddRGBPoint( 13.0, 0.0470588, 0.188235, 1 ); transferFunction->AddRGBPoint( 14.0, 0.8, 0.713725, 0.556863 ); transferFunction->AddRGBPoint( 15.0, 0.164706, 0.8, 0.643137 ); transferFunction->AddRGBPoint( 16.0, 0.466667, 0.623529, 0.690196 ); transferFunction->AddRGBPoint( 17.0, 0.862745, 0.847059, 0.0784314 ); transferFunction->AddRGBPoint( 18.0, 0.403922, 1, 1 ); transferFunction->AddRGBPoint( 19.0, 0.313725, 0.768627, 0.384314 ); transferFunction->AddRGBPoint( 20.0, 0.235294, 0.227451, 0.823529 ); transferFunction->AddRGBPoint( 21.0, 0.235294, 0.227451, 0.823529 ); transferFunction->AddRGBPoint( 22.0, 0.235294, 0.227451, 0.823529 ); transferFunction->AddRGBPoint( 23.0, 0.235294, 0.227451, 0.823529 ); transferFunction->AddRGBPoint( 24.0, 0.235294, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 25.0, 1, 0.647059, 0 ); transferFunction->AddRGBPoint( 26.0, 1, 0.647059, 0 ); transferFunction->AddRGBPoint( 27.0, 0, 1, 0.498039 ); transferFunction->AddRGBPoint( 28.0, 0.647059, 0.164706, 0.164706 ); transferFunction->AddRGBPoint( 29.0, 0.529412, 0.807843, 0.921569 ); transferFunction->AddRGBPoint( 30.0, 0.627451, 0.12549, 0.941176 ); transferFunction->AddRGBPoint( 31.0, 0, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 32.0, 0.392157, 0.196078, 0.392157 ); transferFunction->AddRGBPoint( 33.0, 0.529412, 0.196078, 0.290196 ); transferFunction->AddRGBPoint( 34.0, 0.478431, 0.529412, 0.196078 ); transferFunction->AddRGBPoint( 35.0, 0.2, 0.196078, 0.529412 ); transferFunction->AddRGBPoint( 36.0, 0.290196, 0.607843, 0.235294 ); transferFunction->AddRGBPoint( 37.0, 0.470588, 0.243137, 0.168627 ); transferFunction->AddRGBPoint( 38.0, 0.290196, 0.607843, 0.235294 ); transferFunction->AddRGBPoint( 39.0, 0.478431, 0.529412, 0.196078 ); transferFunction->AddRGBPoint( 40.0, 0.27451, 0.509804, 0.705882 ); transferFunction->AddRGBPoint( 41.0, 0, 0.882353, 0 ); transferFunction->AddRGBPoint( 42.0, 0.803922, 0.243137, 0.305882 ); transferFunction->AddRGBPoint( 43.0, 0.470588, 0.0705882, 0.52549 ); transferFunction->AddRGBPoint( 44.0, 0.768627, 0.227451, 0.980392 ); transferFunction->AddRGBPoint( 45.0, 0, 0.580392, 0 ); transferFunction->AddRGBPoint( 46.0, 0.862745, 0.972549, 0.643137 ); transferFunction->AddRGBPoint( 47.0, 0.901961, 0.580392, 0.133333 ); transferFunction->AddRGBPoint( 48.0, 0, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 49.0, 0, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 50.0, 0.478431, 0.729412, 0.862745 ); transferFunction->AddRGBPoint( 51.0, 0.92549, 0.0509804, 0.690196 ); transferFunction->AddRGBPoint( 52.0, 0.0509804, 0.188235, 1 ); transferFunction->AddRGBPoint( 53.0, 0.862745, 0.847059, 0.0784314 ); transferFunction->AddRGBPoint( 54.0, 0.403922, 1, 1 ); transferFunction->AddRGBPoint( 55.0, 0.313725, 0.768627, 0.384314 ); transferFunction->AddRGBPoint( 56.0, 0.235294, 0.227451, 0.823529 ); transferFunction->AddRGBPoint( 57.0, 1, 0.647059, 0 ); transferFunction->AddRGBPoint( 58.0, 1, 0.647059, 0 ); transferFunction->AddRGBPoint( 59.0, 0, 1, 0.498039 ); transferFunction->AddRGBPoint( 60.0, 0.647059, 0.164706, 0.164706 ); transferFunction->AddRGBPoint( 61.0, 0.529412, 0.807843, 0.921569 ); transferFunction->AddRGBPoint( 62.0, 0.627451, 0.12549, 0.941176 ); transferFunction->AddRGBPoint( 63.0, 0, 0.784314, 0.866667 ); transferFunction->AddRGBPoint( 64.0, 0.392157, 0.196078, 0.392157 ); transferFunction->AddRGBPoint( 65.0, 0.529412, 0.196078, 0.290196 ); transferFunction->AddRGBPoint( 66.0, 0.478431, 0.529412, 0.196078 ); transferFunction->AddRGBPoint( 67.0, 0.2, 0.196078, 0.529412 ); transferFunction->AddRGBPoint( 68.0, 0.290196, 0.607843, 0.235294 ); transferFunction->AddRGBPoint( 69.0, 0.470588, 0.243137, 0.168627 ); transferFunction->AddRGBPoint( 70.0, 0.290196, 0.607843, 0.235294 ); transferFunction->AddRGBPoint( 71.0, 0.478431, 0.529412, 0.196078 ); transferFunction->AddRGBPoint( 72.0, 0.470588, 0.745098, 0.588235 ); transferFunction->AddRGBPoint( 73.0, 0.478431, 0.529412, 0.196078 ); transferFunction->AddRGBPoint( 74.0, 0.478431, 0.529412, 0.196078 ); transferFunction->AddRGBPoint( 77.0, 0.784314, 0.27451, 1 ); transferFunction->AddRGBPoint( 78.0, 1, 0.580392, 0.0392157 ); transferFunction->AddRGBPoint( 79.0, 1, 0.580392, 0.0392157 ); transferFunction->AddRGBPoint( 80.0, 0.643137, 0.423529, 0.886275 ); transferFunction->AddRGBPoint( 81.0, 0.643137, 0.423529, 0.886275 ); transferFunction->AddRGBPoint( 82.0, 0.643137, 0.423529, 0.886275 ); transferFunction->AddRGBPoint( 83.0, 1, 0.854902, 0.72549 ); transferFunction->AddRGBPoint( 84.0, 1, 0.854902, 0.72549 ); transferFunction->AddRGBPoint( 85.0, 0.917647, 0.662745, 0.117647 ); transferFunction->AddRGBPoint( 192.0, 0.980392, 1, 0.196078 ); transferFunction->AddRGBPoint( 86.0, 0.784314, 0.470588, 1 ); transferFunction->AddRGBPoint( 87.0, 0.784314, 0.47451, 1 ); transferFunction->AddRGBPoint( 88.0, 0.784314, 0.478431, 1 ); transferFunction->AddRGBPoint( 96.0, 0.803922, 0.0392157, 0.490196 ); transferFunction->AddRGBPoint( 97.0, 0.803922, 0.0392157, 0.490196 ); transferFunction->AddRGBPoint( 98.0, 0.627451, 0.12549, 0.941176 ); transferFunction->AddRGBPoint( 100.0, 0.486275, 0.54902, 0.698039 ); transferFunction->AddRGBPoint( 101.0, 0.490196, 0.54902, 0.698039 ); transferFunction->AddRGBPoint( 102.0, 0.494118, 0.54902, 0.698039 ); transferFunction->AddRGBPoint( 103.0, 0.498039, 0.54902, 0.698039 ); transferFunction->AddRGBPoint( 104.0, 0.486275, 0.552941, 0.698039 ); transferFunction->AddRGBPoint( 105.0, 0.486275, 0.556863, 0.698039 ); transferFunction->AddRGBPoint( 106.0, 0.486275, 0.560784, 0.698039 ); transferFunction->AddRGBPoint( 107.0, 0.486275, 0.564706, 0.698039 ); transferFunction->AddRGBPoint( 108.0, 0.486275, 0.54902, 0.701961 ); transferFunction->AddRGBPoint( 109.0, 0.486275, 0.54902, 0.698039 ); transferFunction->AddRGBPoint( 110.0, 0.490196, 0.54902, 0.698039 ); transferFunction->AddRGBPoint( 111.0, 0.494118, 0.54902, 0.698039 ); transferFunction->AddRGBPoint( 112.0, 0.498039, 0.54902, 0.698039 ); transferFunction->AddRGBPoint( 113.0, 0.486275, 0.552941, 0.698039 ); transferFunction->AddRGBPoint( 114.0, 0.486275, 0.556863, 0.698039 ); transferFunction->AddRGBPoint( 115.0, 0.486275, 0.560784, 0.698039 ); transferFunction->AddRGBPoint( 116.0, 0.486275, 0.564706, 0.698039 ); transferFunction->AddRGBPoint( 117.0, 0.486275, 0.54902, 0.701961 ); transferFunction->AddRGBPoint( 118.0, 1, 0.0784314, 0.576471 ); transferFunction->AddRGBPoint( 119.0, 0.803922, 0.701961, 0.545098 ); transferFunction->AddRGBPoint( 120.0, 0.933333, 0.933333, 0.819608 ); transferFunction->AddRGBPoint( 121.0, 0.784314, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 122.0, 0.290196, 1, 0.290196 ); transferFunction->AddRGBPoint( 123.0, 0.933333, 0, 0 ); transferFunction->AddRGBPoint( 124.0, 0, 0, 0.545098 ); transferFunction->AddRGBPoint( 125.0, 0.678431, 1, 0.184314 ); transferFunction->AddRGBPoint( 126.0, 0.521569, 0.796078, 0.898039 ); transferFunction->AddRGBPoint( 127.0, 0.101961, 0.929412, 0.223529 ); transferFunction->AddRGBPoint( 128.0, 0.133333, 0.545098, 0.133333 ); transferFunction->AddRGBPoint( 129.0, 0.117647, 0.564706, 1 ); transferFunction->AddRGBPoint( 130.0, 0.576471, 0.0745098, 0.678431 ); transferFunction->AddRGBPoint( 131.0, 0.933333, 0.231373, 0.231373 ); transferFunction->AddRGBPoint( 132.0, 0.866667, 0.152941, 0.784314 ); transferFunction->AddRGBPoint( 133.0, 0.933333, 0.682353, 0.933333 ); transferFunction->AddRGBPoint( 134.0, 1, 0, 0 ); transferFunction->AddRGBPoint( 135.0, 0.282353, 0.239216, 0.545098 ); transferFunction->AddRGBPoint( 136.0, 0.0823529, 0.152941, 0.517647 ); transferFunction->AddRGBPoint( 137.0, 0.0823529, 0.152941, 0.517647 ); transferFunction->AddRGBPoint( 138.0, 0.254902, 0.529412, 0.0784314 ); transferFunction->AddRGBPoint( 139.0, 0.254902, 0.529412, 0.0784314 ); transferFunction->AddRGBPoint( 140.0, 0.52549, 0.0156863, 0.627451 ); transferFunction->AddRGBPoint( 142.0, 0.866667, 0.886275, 0.266667 ); transferFunction->AddRGBPoint( 143.0, 1, 1, 0.996078 ); transferFunction->AddRGBPoint( 144.0, 0.203922, 0.819608, 0.886275 ); transferFunction->AddRGBPoint( 145.0, 0.937255, 0.627451, 0.87451 ); transferFunction->AddRGBPoint( 146.0, 0.27451, 0.509804, 0.705882 ); transferFunction->AddRGBPoint( 147.0, 0.27451, 0.509804, 0.709804 ); transferFunction->AddRGBPoint( 148.0, 0.545098, 0.47451, 0.368627 ); transferFunction->AddRGBPoint( 149.0, 0.878431, 0.878431, 0.878431 ); transferFunction->AddRGBPoint( 150.0, 1, 0, 0 ); transferFunction->AddRGBPoint( 151.0, 0.803922, 0.803922, 0 ); transferFunction->AddRGBPoint( 152.0, 0.933333, 0.933333, 0.819608 ); transferFunction->AddRGBPoint( 153.0, 0.545098, 0.47451, 0.368627 ); transferFunction->AddRGBPoint( 154.0, 0.933333, 0.231373, 0.231373 ); transferFunction->AddRGBPoint( 155.0, 0.933333, 0.231373, 0.231373 ); transferFunction->AddRGBPoint( 156.0, 0.933333, 0.231373, 0.231373 ); transferFunction->AddRGBPoint( 157.0, 0.243137, 0.0392157, 0.803922 ); transferFunction->AddRGBPoint( 158.0, 0.243137, 0.0392157, 0.803922 ); transferFunction->AddRGBPoint( 159.0, 0, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 160.0, 0, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 161.0, 0.862745, 0.847059, 0.0823529 ); transferFunction->AddRGBPoint( 162.0, 0.862745, 0.847059, 0.0823529 ); transferFunction->AddRGBPoint( 163.0, 0.478431, 0.729412, 0.862745 ); transferFunction->AddRGBPoint( 164.0, 0.478431, 0.729412, 0.862745 ); transferFunction->AddRGBPoint( 165.0, 1, 0.647059, 0 ); transferFunction->AddRGBPoint( 166.0, 0.054902, 0.188235, 1 ); transferFunction->AddRGBPoint( 167.0, 0.65098, 0.164706, 0.164706 ); transferFunction->AddRGBPoint( 168.0, 0.47451, 0.0705882, 0.52549 ); transferFunction->AddRGBPoint( 169.0, 0.92549, 0.0509804, 0.498039 ); transferFunction->AddRGBPoint( 176.0, 0.92549, 0.0509804, 0.494118 ); transferFunction->AddRGBPoint( 170.0, 0.466667, 0.623529, 0.690196 ); transferFunction->AddRGBPoint( 171.0, 0.466667, 0, 0.690196 ); transferFunction->AddRGBPoint( 172.0, 0.466667, 0.392157, 0.690196 ); transferFunction->AddRGBPoint( 173.0, 0.466667, 0.784314, 0.690196 ); transferFunction->AddRGBPoint( 174.0, 0.466667, 0.623529, 0.392157 ); transferFunction->AddRGBPoint( 175.0, 0.466667, 0.623529, 0.784314 ); transferFunction->AddRGBPoint( 180.0, 0.286275, 0.239216, 0.545098 ); transferFunction->AddRGBPoint( 181.0, 0.286275, 0.243137, 0.545098 ); transferFunction->AddRGBPoint( 193.0, 0, 0.768627, 1 ); transferFunction->AddRGBPoint( 194.0, 1, 0.643137, 0.643137 ); transferFunction->AddRGBPoint( 195.0, 0.768627, 0.768627, 0 ); transferFunction->AddRGBPoint( 196.0, 0, 0.392157, 1 ); transferFunction->AddRGBPoint( 197.0, 0.501961, 0.768627, 0.643137 ); transferFunction->AddRGBPoint( 198.0, 0, 0.494118, 0.294118 ); transferFunction->AddRGBPoint( 199.0, 0.501961, 0.376471, 0.25098 ); transferFunction->AddRGBPoint( 200.0, 0, 0.196078, 0.501961 ); transferFunction->AddRGBPoint( 201.0, 1, 0.8, 0.6 ); transferFunction->AddRGBPoint( 202.0, 1, 0.501961, 0.501961 ); transferFunction->AddRGBPoint( 203.0, 1, 1, 0 ); transferFunction->AddRGBPoint( 204.0, 0.25098, 0, 0.25098 ); transferFunction->AddRGBPoint( 205.0, 0, 0, 1 ); transferFunction->AddRGBPoint( 206.0, 1, 0, 0 ); transferFunction->AddRGBPoint( 207.0, 0.501961, 0.501961, 1 ); transferFunction->AddRGBPoint( 208.0, 0, 0.501961, 0 ); transferFunction->AddRGBPoint( 209.0, 0.768627, 0.627451, 0.501961 ); transferFunction->AddRGBPoint( 210.0, 0.12549, 0.784314, 1 ); transferFunction->AddRGBPoint( 211.0, 0.501961, 1, 0.501961 ); transferFunction->AddRGBPoint( 212.0, 0.8, 0.6, 0.8 ); transferFunction->AddRGBPoint( 213.0, 0.47451, 0.0666667, 0.533333 ); transferFunction->AddRGBPoint( 214.0, 0.501961, 0, 0 ); transferFunction->AddRGBPoint( 215.0, 0.501961, 0.12549, 1 ); transferFunction->AddRGBPoint( 216.0, 1, 0.8, 0.4 ); transferFunction->AddRGBPoint( 217.0, 0.501961, 0.501961, 0.501961 ); transferFunction->AddRGBPoint( 218.0, 0.407843, 1, 1 ); transferFunction->AddRGBPoint( 219.0, 0, 0.886275, 0 ); transferFunction->AddRGBPoint( 220.0, 0.803922, 0.247059, 0.305882 ); transferFunction->AddRGBPoint( 221.0, 0.772549, 0.227451, 0.980392 ); transferFunction->AddRGBPoint( 222.0, 0.129412, 0.588235, 0.980392 ); transferFunction->AddRGBPoint( 223.0, 0.886275, 0, 0 ); transferFunction->AddRGBPoint( 224.0, 0.392157, 0.392157, 0.392157 ); transferFunction->AddRGBPoint( 225.0, 0.772549, 0.588235, 0.980392 ); transferFunction->AddRGBPoint( 226.0, 0.666667, 0.666667, 1 ); transferFunction->AddRGBPoint( 250.0, 1, 0, 0 ); transferFunction->AddRGBPoint( 251.0, 0, 0, 0.25098 ); transferFunction->AddRGBPoint( 252.0, 0, 0, 0.439216 ); transferFunction->AddRGBPoint( 253.0, 0, 0, 0.627451 ); transferFunction->AddRGBPoint( 254.0, 0, 0, 0.815686 ); transferFunction->AddRGBPoint( 255.0, 0, 0, 1 ); transferFunction->AddRGBPoint( 331.0, 1, 0, 0 ); transferFunction->AddRGBPoint( 332.0, 1, 0.313725, 0 ); transferFunction->AddRGBPoint( 333.0, 1, 0.627451, 0 ); transferFunction->AddRGBPoint( 334.0, 1, 1, 0 ); transferFunction->AddRGBPoint( 335.0, 0, 1, 0 ); transferFunction->AddRGBPoint( 336.0, 1, 0, 0.627451 ); transferFunction->AddRGBPoint( 337.0, 1, 0, 1 ); transferFunction->AddRGBPoint( 338.0, 1, 0.196078, 0.313725 ); transferFunction->AddRGBPoint( 339.0, 0.313725, 1, 0.196078 ); transferFunction->AddRGBPoint( 340.0, 0.627451, 1, 0.196078 ); transferFunction->AddRGBPoint( 341.0, 0.627451, 0.784314, 1 ); transferFunction->AddRGBPoint( 342.0, 0, 1, 0.627451 ); transferFunction->AddRGBPoint( 343.0, 0, 0, 1 ); transferFunction->AddRGBPoint( 344.0, 0.313725, 0.196078, 1 ); transferFunction->AddRGBPoint( 345.0, 0.627451, 0, 1 ); transferFunction->AddRGBPoint( 346.0, 1, 0.823529, 0 ); transferFunction->AddRGBPoint( 347.0, 0, 0.627451, 1 ); transferFunction->AddRGBPoint( 348.0, 1, 0.784314, 0.313725 ); transferFunction->AddRGBPoint( 349.0, 1, 0.784314, 0.627451 ); transferFunction->AddRGBPoint( 350.0, 1, 0.313725, 0.784314 ); transferFunction->AddRGBPoint( 351.0, 1, 0.627451, 0.784314 ); transferFunction->AddRGBPoint( 352.0, 0.117647, 1, 0.313725 ); transferFunction->AddRGBPoint( 353.0, 0.313725, 0.784314, 1 ); transferFunction->AddRGBPoint( 354.0, 0.313725, 1, 0.784314 ); transferFunction->AddRGBPoint( 355.0, 0.764706, 1, 0.784314 ); transferFunction->AddRGBPoint( 356.0, 0.470588, 0.784314, 0.0784314 ); transferFunction->AddRGBPoint( 357.0, 0.666667, 0.0392157, 0.784314 ); transferFunction->AddRGBPoint( 358.0, 0.0784314, 0.509804, 0.705882 ); transferFunction->AddRGBPoint( 359.0, 0.0784314, 0.705882, 0.509804 ); transferFunction->AddRGBPoint( 400.0, 0.807843, 0.243137, 0.305882 ); transferFunction->AddRGBPoint( 401.0, 0.47451, 0.0705882, 0.52549 ); transferFunction->AddRGBPoint( 402.0, 0.780392, 0.227451, 0.980392 ); transferFunction->AddRGBPoint( 403.0, 0.00392157, 0.580392, 0 ); transferFunction->AddRGBPoint( 404.0, 0.866667, 0.972549, 0.643137 ); transferFunction->AddRGBPoint( 405.0, 0.905882, 0.580392, 0.133333 ); transferFunction->AddRGBPoint( 406.0, 0.00392157, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 407.0, 0.470588, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 408.0, 0.482353, 0.729412, 0.866667 ); transferFunction->AddRGBPoint( 409.0, 0.933333, 0.0509804, 0.694118 ); transferFunction->AddRGBPoint( 410.0, 0.482353, 0.729412, 0.862745 ); transferFunction->AddRGBPoint( 411.0, 0.541176, 0.0509804, 0.807843 ); transferFunction->AddRGBPoint( 412.0, 0.933333, 0.509804, 0.690196 ); transferFunction->AddRGBPoint( 413.0, 0.854902, 0.901961, 0.298039 ); transferFunction->AddRGBPoint( 414.0, 0.14902, 0.835294, 0.690196 ); transferFunction->AddRGBPoint( 415.0, 0.00392157, 0.882353, 0.690196 ); transferFunction->AddRGBPoint( 416.0, 0.00392157, 0.882353, 0.690196 ); transferFunction->AddRGBPoint( 417.0, 0.784314, 0.00784314, 0.392157 ); transferFunction->AddRGBPoint( 418.0, 0.784314, 0.00784314, 0.392157 ); transferFunction->AddRGBPoint( 419.0, 0.0196078, 0.784314, 0.352941 ); transferFunction->AddRGBPoint( 420.0, 0.0196078, 0.784314, 0.352941 ); transferFunction->AddRGBPoint( 421.0, 0.392157, 0.0196078, 0.784314 ); transferFunction->AddRGBPoint( 422.0, 0.0980392, 1, 0.392157 ); transferFunction->AddRGBPoint( 423.0, 0.0980392, 1, 0.392157 ); transferFunction->AddRGBPoint( 424.0, 0.901961, 0.027451, 0.392157 ); transferFunction->AddRGBPoint( 425.0, 0.901961, 0.027451, 0.392157 ); transferFunction->AddRGBPoint( 426.0, 0.392157, 0.0196078, 0.784314 ); transferFunction->AddRGBPoint( 427.0, 0.588235, 0.0392157, 0.784314 ); transferFunction->AddRGBPoint( 428.0, 0.588235, 0.0392157, 0.784314 ); transferFunction->AddRGBPoint( 429.0, 0.686275, 0.0392157, 0.690196 ); transferFunction->AddRGBPoint( 430.0, 0.686275, 0.0392157, 0.690196 ); transferFunction->AddRGBPoint( 431.0, 0.0392157, 0.392157, 1 ); transferFunction->AddRGBPoint( 432.0, 0.0392157, 0.392157, 1 ); transferFunction->AddRGBPoint( 433.0, 0.588235, 0.176471, 0.27451 ); transferFunction->AddRGBPoint( 434.0, 0.588235, 0.176471, 0.27451 ); transferFunction->AddRGBPoint( 435.0, 0.176471, 0.784314, 0.0588235 ); transferFunction->AddRGBPoint( 436.0, 0.176471, 0.784314, 0.0588235 ); transferFunction->AddRGBPoint( 437.0, 0.890196, 0.176471, 0.392157 ); transferFunction->AddRGBPoint( 438.0, 0.890196, 0.176471, 0.392157 ); transferFunction->AddRGBPoint( 439.0, 0.890196, 0.176471, 0.392157 ); transferFunction->AddRGBPoint( 498.0, 0.560784, 0.737255, 0.560784 ); transferFunction->AddRGBPoint( 499.0, 1, 0.972549, 0.862745 ); transferFunction->AddRGBPoint( 500.0, 0.0666667, 0.333333, 0.533333 ); transferFunction->AddRGBPoint( 501.0, 0.466667, 0.733333, 0.4 ); transferFunction->AddRGBPoint( 502.0, 0.8, 0.266667, 0.133333 ); transferFunction->AddRGBPoint( 503.0, 0.8, 0, 1 ); transferFunction->AddRGBPoint( 504.0, 0.866667, 0.733333, 0.0666667 ); transferFunction->AddRGBPoint( 505.0, 0.6, 0.866667, 0.933333 ); transferFunction->AddRGBPoint( 506.0, 0.2, 0.0666667, 0.0666667 ); transferFunction->AddRGBPoint( 507.0, 0, 0.466667, 0.333333 ); transferFunction->AddRGBPoint( 508.0, 0.0784314, 0.392157, 0.784314 ); transferFunction->AddRGBPoint( 550.0, 0.0666667, 0.333333, 0.537255 ); transferFunction->AddRGBPoint( 551.0, 0.466667, 0.733333, 0.403922 ); transferFunction->AddRGBPoint( 552.0, 0.8, 0.266667, 0.137255 ); transferFunction->AddRGBPoint( 553.0, 0.8, 0, 0.996078 ); transferFunction->AddRGBPoint( 554.0, 0.866667, 0.733333, 0.0627451 ); transferFunction->AddRGBPoint( 555.0, 0.6, 0.866667, 0.937255 ); transferFunction->AddRGBPoint( 556.0, 0.2, 0.0666667, 0.0705882 ); transferFunction->AddRGBPoint( 557.0, 0, 0.466667, 0.337255 ); transferFunction->AddRGBPoint( 558.0, 0.0784314, 0.392157, 0.788235 ); transferFunction->AddRGBPoint( 600.0, 0.996078, 0.996078, 0.996078 ); transferFunction->AddRGBPoint( 601.0, 0.27451, 0.509804, 0.705882 ); transferFunction->AddRGBPoint( 602.0, 0.960784, 0.960784, 0.960784 ); transferFunction->AddRGBPoint( 603.0, 0.803922, 0.243137, 0.305882 ); transferFunction->AddRGBPoint( 604.0, 0.470588, 0.0705882, 0.52549 ); transferFunction->AddRGBPoint( 605.0, 0.768627, 0.227451, 0.980392 ); transferFunction->AddRGBPoint( 606.0, 0, 0.580392, 0 ); transferFunction->AddRGBPoint( 607.0, 0.862745, 0.972549, 0.643137 ); transferFunction->AddRGBPoint( 608.0, 0.901961, 0.580392, 0.133333 ); transferFunction->AddRGBPoint( 609.0, 0, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 610.0, 0, 0.462745, 0.054902 ); transferFunction->AddRGBPoint( 611.0, 0.478431, 0.729412, 0.862745 ); transferFunction->AddRGBPoint( 612.0, 0.92549, 0.0509804, 0.690196 ); transferFunction->AddRGBPoint( 613.0, 0.0470588, 0.188235, 1 ); transferFunction->AddRGBPoint( 614.0, 0.8, 0.713725, 0.556863 ); transferFunction->AddRGBPoint( 615.0, 0.164706, 0.8, 0.643137 ); transferFunction->AddRGBPoint( 616.0, 0.466667, 0.623529, 0.690196 ); transferFunction->AddRGBPoint( 617.0, 0.862745, 0.847059, 0.0784314 ); transferFunction->AddRGBPoint( 618.0, 0.403922, 1, 1 ); transferFunction->AddRGBPoint( 619.0, 0.313725, 0.768627, 0.384314 ); transferFunction->AddRGBPoint( 620.0, 0.235294, 0.227451, 0.823529 ); transferFunction->AddRGBPoint( 621.0, 0.235294, 0.227451, 0.823529 ); transferFunction->AddRGBPoint( 622.0, 0.235294, 0.227451, 0.823529 ); transferFunction->AddRGBPoint( 623.0, 0.235294, 0.227451, 0.823529 ); transferFunction->AddRGBPoint( 624.0, 0.235294, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 625.0, 1, 0.647059, 0 ); transferFunction->AddRGBPoint( 626.0, 1, 0.647059, 0 ); transferFunction->AddRGBPoint( 627.0, 0, 1, 0.498039 ); transferFunction->AddRGBPoint( 628.0, 0.647059, 0.164706, 0.164706 ); transferFunction->AddRGBPoint( 640.0, 0.8, 0, 0 ); transferFunction->AddRGBPoint( 641.0, 1, 0, 0 ); transferFunction->AddRGBPoint( 642.0, 0, 0, 1 ); transferFunction->AddRGBPoint( 643.0, 0.117647, 0.564706, 1 ); transferFunction->AddRGBPoint( 644.0, 0.392157, 0.831373, 0.929412 ); transferFunction->AddRGBPoint( 645.0, 0.854902, 0.647059, 0.12549 ); transferFunction->AddRGBPoint( 646.0, 1, 0.843137, 0 ); transferFunction->AddRGBPoint( 647.0, 1, 1, 0.65098 ); transferFunction->AddRGBPoint( 648.0, 0.6, 0, 0.8 ); transferFunction->AddRGBPoint( 649.0, 0.6, 0.552941, 0.819608 ); transferFunction->AddRGBPoint( 650.0, 0.8, 0.8, 1 ); transferFunction->AddRGBPoint( 651.0, 0.121569, 0.831373, 0.760784 ); transferFunction->AddRGBPoint( 652.0, 0.0117647, 1, 0.929412 ); transferFunction->AddRGBPoint( 653.0, 0.8, 1, 1 ); transferFunction->AddRGBPoint( 654.0, 0.337255, 0.290196, 0.576471 ); transferFunction->AddRGBPoint( 655.0, 0.447059, 0.447059, 0.745098 ); transferFunction->AddRGBPoint( 656.0, 0.721569, 0.698039, 1 ); transferFunction->AddRGBPoint( 657.0, 0.494118, 0.541176, 0.145098 ); transferFunction->AddRGBPoint( 658.0, 0.741176, 0.772549, 0.458824 ); transferFunction->AddRGBPoint( 659.0, 0.941176, 0.901961, 0.54902 ); transferFunction->AddRGBPoint( 660.0, 0.8, 0, 0 ); transferFunction->AddRGBPoint( 661.0, 1, 0, 0 ); transferFunction->AddRGBPoint( 662.0, 0, 0, 1 ); transferFunction->AddRGBPoint( 663.0, 0.117647, 0.564706, 1 ); transferFunction->AddRGBPoint( 664.0, 0.392157, 0.831373, 0.929412 ); transferFunction->AddRGBPoint( 665.0, 0.854902, 0.647059, 0.12549 ); transferFunction->AddRGBPoint( 666.0, 1, 0.843137, 0 ); transferFunction->AddRGBPoint( 667.0, 1, 1, 0.65098 ); transferFunction->AddRGBPoint( 668.0, 0.6, 0, 0.8 ); transferFunction->AddRGBPoint( 669.0, 0.6, 0.552941, 0.819608 ); transferFunction->AddRGBPoint( 670.0, 0.8, 0.8, 1 ); transferFunction->AddRGBPoint( 671.0, 0.121569, 0.831373, 0.760784 ); transferFunction->AddRGBPoint( 672.0, 0.0117647, 1, 0.929412 ); transferFunction->AddRGBPoint( 673.0, 0.8, 1, 1 ); transferFunction->AddRGBPoint( 674.0, 0.337255, 0.290196, 0.576471 ); transferFunction->AddRGBPoint( 675.0, 0.447059, 0.447059, 0.745098 ); transferFunction->AddRGBPoint( 676.0, 0.721569, 0.698039, 1 ); transferFunction->AddRGBPoint( 677.0, 0.494118, 0.541176, 0.145098 ); transferFunction->AddRGBPoint( 678.0, 0.741176, 0.772549, 0.458824 ); transferFunction->AddRGBPoint( 679.0, 0.941176, 0.901961, 0.54902 ); transferFunction->AddRGBPoint( 701.0, 0.470588, 0.0705882, 0.52549 ); transferFunction->AddRGBPoint( 702.0, 0.803922, 0.243137, 0.305882 ); transferFunction->AddRGBPoint( 703.0, 0, 0.882353, 0 ); transferFunction->AddRGBPoint( 999.0, 1, 0.392157, 0.392157 ); transferFunction->AddRGBPoint( 1000.0, 0.0980392, 0.0196078, 0.0980392 ); transferFunction->AddRGBPoint( 1001.0, 0.0980392, 0.392157, 0.156863 ); transferFunction->AddRGBPoint( 1002.0, 0.490196, 0.392157, 0.627451 ); transferFunction->AddRGBPoint( 1003.0, 0.392157, 0.0980392, 0 ); transferFunction->AddRGBPoint( 1004.0, 0.470588, 0.27451, 0.196078 ); transferFunction->AddRGBPoint( 1005.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 1006.0, 0.862745, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 1007.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 1008.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 1009.0, 0.705882, 0.156863, 0.470588 ); transferFunction->AddRGBPoint( 1010.0, 0.54902, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 1011.0, 0.0784314, 0.117647, 0.54902 ); transferFunction->AddRGBPoint( 1012.0, 0.137255, 0.294118, 0.196078 ); transferFunction->AddRGBPoint( 1013.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 1014.0, 0.784314, 0.137255, 0.294118 ); transferFunction->AddRGBPoint( 1015.0, 0.627451, 0.392157, 0.196078 ); transferFunction->AddRGBPoint( 1016.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 1017.0, 0.235294, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 1018.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 1019.0, 0.0784314, 0.392157, 0.196078 ); transferFunction->AddRGBPoint( 1020.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 1021.0, 0.470588, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 1022.0, 0.862745, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 1023.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 1024.0, 0.235294, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 1025.0, 0.627451, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 1026.0, 0.313725, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 1027.0, 0.294118, 0.196078, 0.490196 ); transferFunction->AddRGBPoint( 1028.0, 0.0784314, 0.862745, 0.627451 ); transferFunction->AddRGBPoint( 1029.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 1030.0, 0.54902, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 1031.0, 0.313725, 0.627451, 0.0784314 ); transferFunction->AddRGBPoint( 1032.0, 0.392157, 0, 0.392157 ); transferFunction->AddRGBPoint( 1033.0, 0.27451, 0.27451, 0.27451 ); transferFunction->AddRGBPoint( 1034.0, 0.588235, 0.588235, 0.784314 ); transferFunction->AddRGBPoint( 1035.0, 1, 0.752941, 0.12549 ); transferFunction->AddRGBPoint( 2000.0, 0.0980392, 0.0196078, 0.0980392 ); transferFunction->AddRGBPoint( 2001.0, 0.0980392, 0.392157, 0.156863 ); transferFunction->AddRGBPoint( 2002.0, 0.490196, 0.392157, 0.627451 ); transferFunction->AddRGBPoint( 2003.0, 0.392157, 0.0980392, 0 ); transferFunction->AddRGBPoint( 2004.0, 0.470588, 0.27451, 0.196078 ); transferFunction->AddRGBPoint( 2005.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 2006.0, 0.862745, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 2007.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 2008.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 2009.0, 0.705882, 0.156863, 0.470588 ); transferFunction->AddRGBPoint( 2010.0, 0.54902, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 2011.0, 0.0784314, 0.117647, 0.54902 ); transferFunction->AddRGBPoint( 2012.0, 0.137255, 0.294118, 0.196078 ); transferFunction->AddRGBPoint( 2013.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 2014.0, 0.784314, 0.137255, 0.294118 ); transferFunction->AddRGBPoint( 2015.0, 0.627451, 0.392157, 0.196078 ); transferFunction->AddRGBPoint( 2016.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 2017.0, 0.235294, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 2018.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 2019.0, 0.0784314, 0.392157, 0.196078 ); transferFunction->AddRGBPoint( 2020.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 2021.0, 0.470588, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 2022.0, 0.862745, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 2023.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 2024.0, 0.235294, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 2025.0, 0.627451, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 2026.0, 0.313725, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 2027.0, 0.294118, 0.196078, 0.490196 ); transferFunction->AddRGBPoint( 2028.0, 0.0784314, 0.862745, 0.627451 ); transferFunction->AddRGBPoint( 2029.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 2030.0, 0.54902, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 2031.0, 0.313725, 0.627451, 0.0784314 ); transferFunction->AddRGBPoint( 2032.0, 0.392157, 0, 0.392157 ); transferFunction->AddRGBPoint( 2033.0, 0.27451, 0.27451, 0.27451 ); transferFunction->AddRGBPoint( 2034.0, 0.588235, 0.588235, 0.784314 ); transferFunction->AddRGBPoint( 2035.0, 1, 0.752941, 0.12549 ); transferFunction->AddRGBPoint( 3000.0, 0.901961, 0.980392, 0.901961 ); transferFunction->AddRGBPoint( 3001.0, 0.901961, 0.607843, 0.843137 ); transferFunction->AddRGBPoint( 3002.0, 0.509804, 0.607843, 0.372549 ); transferFunction->AddRGBPoint( 3003.0, 0.607843, 0.901961, 1 ); transferFunction->AddRGBPoint( 3004.0, 0.529412, 0.72549, 0.803922 ); transferFunction->AddRGBPoint( 3005.0, 0.137255, 0.921569, 0.607843 ); transferFunction->AddRGBPoint( 3006.0, 0.137255, 0.921569, 0.960784 ); transferFunction->AddRGBPoint( 3007.0, 0.294118, 0.137255, 0.45098 ); transferFunction->AddRGBPoint( 3008.0, 0.137255, 0.764706, 0.137255 ); transferFunction->AddRGBPoint( 3009.0, 0.294118, 0.843137, 0.529412 ); transferFunction->AddRGBPoint( 3010.0, 0.45098, 0.921569, 0.45098 ); transferFunction->AddRGBPoint( 3011.0, 0.921569, 0.882353, 0.45098 ); transferFunction->AddRGBPoint( 3012.0, 0.862745, 0.705882, 0.803922 ); transferFunction->AddRGBPoint( 3013.0, 0.117647, 0.45098, 0.45098 ); transferFunction->AddRGBPoint( 3014.0, 0.215686, 0.862745, 0.705882 ); transferFunction->AddRGBPoint( 3015.0, 0.372549, 0.607843, 0.803922 ); transferFunction->AddRGBPoint( 3016.0, 0.921569, 0.137255, 0.764706 ); transferFunction->AddRGBPoint( 3017.0, 0.764706, 0.137255, 0.764706 ); transferFunction->AddRGBPoint( 3018.0, 0.137255, 0.294118, 0.45098 ); transferFunction->AddRGBPoint( 3019.0, 0.921569, 0.607843, 0.803922 ); transferFunction->AddRGBPoint( 3020.0, 0.137255, 0.764706, 0.921569 ); transferFunction->AddRGBPoint( 3021.0, 0.529412, 0.607843, 0.764706 ); transferFunction->AddRGBPoint( 3022.0, 0.137255, 0.921569, 0.921569 ); transferFunction->AddRGBPoint( 3023.0, 0.137255, 0.294118, 0.137255 ); transferFunction->AddRGBPoint( 3024.0, 0.764706, 0.921569, 0.137255 ); transferFunction->AddRGBPoint( 3025.0, 0.372549, 0.45098, 0.294118 ); transferFunction->AddRGBPoint( 3026.0, 0.686275, 0.921569, 0.45098 ); transferFunction->AddRGBPoint( 3027.0, 0.705882, 0.803922, 0.509804 ); transferFunction->AddRGBPoint( 3028.0, 0.921569, 0.137255, 0.372549 ); transferFunction->AddRGBPoint( 3029.0, 0.921569, 0.294118, 0.45098 ); transferFunction->AddRGBPoint( 3030.0, 0.45098, 0.137255, 0.137255 ); transferFunction->AddRGBPoint( 3031.0, 0.686275, 0.372549, 0.921569 ); transferFunction->AddRGBPoint( 3032.0, 0.607843, 1, 0.607843 ); transferFunction->AddRGBPoint( 3033.0, 0.72549, 0.72549, 0.72549 ); transferFunction->AddRGBPoint( 3034.0, 0.411765, 0.411765, 0.215686 ); transferFunction->AddRGBPoint( 3035.0, 0.996078, 0.74902, 0.121569 ); transferFunction->AddRGBPoint( 4000.0, 0.901961, 0.980392, 0.901961 ); transferFunction->AddRGBPoint( 4001.0, 0.901961, 0.607843, 0.843137 ); transferFunction->AddRGBPoint( 4002.0, 0.509804, 0.607843, 0.372549 ); transferFunction->AddRGBPoint( 4003.0, 0.607843, 0.901961, 1 ); transferFunction->AddRGBPoint( 4004.0, 0.529412, 0.72549, 0.803922 ); transferFunction->AddRGBPoint( 4005.0, 0.137255, 0.921569, 0.607843 ); transferFunction->AddRGBPoint( 4006.0, 0.137255, 0.921569, 0.960784 ); transferFunction->AddRGBPoint( 4007.0, 0.294118, 0.137255, 0.45098 ); transferFunction->AddRGBPoint( 4008.0, 0.137255, 0.764706, 0.137255 ); transferFunction->AddRGBPoint( 4009.0, 0.294118, 0.843137, 0.529412 ); transferFunction->AddRGBPoint( 4010.0, 0.45098, 0.921569, 0.45098 ); transferFunction->AddRGBPoint( 4011.0, 0.921569, 0.882353, 0.45098 ); transferFunction->AddRGBPoint( 4012.0, 0.862745, 0.705882, 0.803922 ); transferFunction->AddRGBPoint( 4013.0, 0.117647, 0.45098, 0.45098 ); transferFunction->AddRGBPoint( 4014.0, 0.215686, 0.862745, 0.705882 ); transferFunction->AddRGBPoint( 4015.0, 0.372549, 0.607843, 0.803922 ); transferFunction->AddRGBPoint( 4016.0, 0.921569, 0.137255, 0.764706 ); transferFunction->AddRGBPoint( 4017.0, 0.764706, 0.137255, 0.764706 ); transferFunction->AddRGBPoint( 4018.0, 0.137255, 0.294118, 0.45098 ); transferFunction->AddRGBPoint( 4019.0, 0.921569, 0.607843, 0.803922 ); transferFunction->AddRGBPoint( 4020.0, 0.137255, 0.764706, 0.921569 ); transferFunction->AddRGBPoint( 4021.0, 0.529412, 0.607843, 0.764706 ); transferFunction->AddRGBPoint( 4022.0, 0.137255, 0.921569, 0.921569 ); transferFunction->AddRGBPoint( 4023.0, 0.137255, 0.294118, 0.137255 ); transferFunction->AddRGBPoint( 4024.0, 0.764706, 0.921569, 0.137255 ); transferFunction->AddRGBPoint( 4025.0, 0.372549, 0.45098, 0.294118 ); transferFunction->AddRGBPoint( 4026.0, 0.686275, 0.921569, 0.45098 ); transferFunction->AddRGBPoint( 4027.0, 0.705882, 0.803922, 0.509804 ); transferFunction->AddRGBPoint( 4028.0, 0.921569, 0.137255, 0.372549 ); transferFunction->AddRGBPoint( 4029.0, 0.921569, 0.294118, 0.45098 ); transferFunction->AddRGBPoint( 4030.0, 0.45098, 0.137255, 0.137255 ); transferFunction->AddRGBPoint( 4031.0, 0.686275, 0.372549, 0.921569 ); transferFunction->AddRGBPoint( 4032.0, 0.607843, 1, 0.607843 ); transferFunction->AddRGBPoint( 4033.0, 0.72549, 0.72549, 0.72549 ); transferFunction->AddRGBPoint( 4034.0, 0.411765, 0.411765, 0.215686 ); transferFunction->AddRGBPoint( 4035.0, 0.996078, 0.74902, 0.121569 ); transferFunction->AddRGBPoint( 1101.0, 0.196078, 0.196078, 0.196078 ); transferFunction->AddRGBPoint( 1102.0, 0.705882, 0.0784314, 0.117647 ); transferFunction->AddRGBPoint( 1103.0, 0.235294, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 1104.0, 0.0980392, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 1200.0, 0.0980392, 0.235294, 0.239216 ); transferFunction->AddRGBPoint( 1201.0, 0.0980392, 0.352941, 0.235294 ); transferFunction->AddRGBPoint( 1202.0, 0.0980392, 0.470588, 0.235294 ); transferFunction->AddRGBPoint( 1205.0, 0.0980392, 0.588235, 0.235294 ); transferFunction->AddRGBPoint( 1206.0, 0.0980392, 0.705882, 0.235294 ); transferFunction->AddRGBPoint( 1207.0, 0.0980392, 0.823529, 0.235294 ); transferFunction->AddRGBPoint( 1210.0, 0.0980392, 0.588235, 0.352941 ); transferFunction->AddRGBPoint( 1211.0, 0.0980392, 0.705882, 0.352941 ); transferFunction->AddRGBPoint( 1212.0, 0.0980392, 0.823529, 0.352941 ); transferFunction->AddRGBPoint( 1105.0, 0.705882, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 1106.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 1107.0, 0.54902, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 1108.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 1109.0, 0.54902, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 1110.0, 0.705882, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 1111.0, 0.54902, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 1112.0, 0.0823529, 0.0392157, 0.0392157 ); transferFunction->AddRGBPoint( 1113.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 1114.0, 0.0901961, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 1115.0, 0.705882, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 1116.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 1117.0, 0.235294, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 1118.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 1119.0, 0.254902, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 1120.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 1121.0, 0.235294, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 1122.0, 0.0784314, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 1123.0, 0.392157, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 1124.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 1125.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 1126.0, 0.235294, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 1127.0, 0.0980392, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 1128.0, 0.0784314, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 1129.0, 0.235294, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 1130.0, 0.235294, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 1131.0, 0.862745, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 1132.0, 0.705882, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 1133.0, 0.235294, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 1134.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 1135.0, 0.254902, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 1136.0, 0.0980392, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 1137.0, 0.0509804, 0, 0.980392 ); transferFunction->AddRGBPoint( 1138.0, 0.239216, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 1139.0, 0.239216, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 1140.0, 0.239216, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 1141.0, 0.0980392, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 1142.0, 0.54902, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 1143.0, 0.862745, 0.705882, 0.0784314 ); transferFunction->AddRGBPoint( 1144.0, 0.247059, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 1145.0, 0.866667, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 1146.0, 0.0823529, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 1147.0, 0.717647, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 1148.0, 0.866667, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 1149.0, 0.866667, 0.235294, 0.54902 ); transferFunction->AddRGBPoint( 1150.0, 0.866667, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 1151.0, 0.239216, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 1152.0, 0.392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 1153.0, 0.0392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 1154.0, 0.866667, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 1155.0, 0.552941, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 1156.0, 0.239216, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 1157.0, 0.0823529, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 1158.0, 0.552941, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 1159.0, 0.560784, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 1160.0, 0.239216, 0.0784314, 0.705882 ); transferFunction->AddRGBPoint( 1161.0, 0.396078, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 1162.0, 0.0823529, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 1163.0, 0.866667, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 1164.0, 0.552941, 0.392157, 0.862745 ); transferFunction->AddRGBPoint( 1165.0, 0.396078, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 1166.0, 0.866667, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 1167.0, 0.709804, 0.784314, 0.0784314 ); transferFunction->AddRGBPoint( 1168.0, 0.0823529, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 1169.0, 0.396078, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 1170.0, 0.709804, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 1171.0, 0.0823529, 0.54902, 0.784314 ); transferFunction->AddRGBPoint( 1172.0, 0.0823529, 0.0784314, 0.941176 ); transferFunction->AddRGBPoint( 1173.0, 0.0823529, 0.0784314, 0.784314 ); transferFunction->AddRGBPoint( 1174.0, 0.239216, 0.705882, 0.235294 ); transferFunction->AddRGBPoint( 1175.0, 0.239216, 0.705882, 0.980392 ); transferFunction->AddRGBPoint( 1176.0, 0.0823529, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 1177.0, 0.396078, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 1178.0, 0.0823529, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 1179.0, 0.0823529, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 1180.0, 0.87451, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 1181.0, 0.866667, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 2101.0, 0.196078, 0.196078, 0.196078 ); transferFunction->AddRGBPoint( 2102.0, 0.705882, 0.0784314, 0.117647 ); transferFunction->AddRGBPoint( 2103.0, 0.235294, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 2104.0, 0.0980392, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 2105.0, 0.705882, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 2106.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 2107.0, 0.54902, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 2108.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 2109.0, 0.54902, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 2110.0, 0.705882, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 2111.0, 0.54902, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 2112.0, 0.0823529, 0.0392157, 0.0392157 ); transferFunction->AddRGBPoint( 2113.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 2114.0, 0.0901961, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 2115.0, 0.705882, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 2116.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 2117.0, 0.235294, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 2118.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 2119.0, 0.254902, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 2120.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 2121.0, 0.235294, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 2122.0, 0.0784314, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 2123.0, 0.392157, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 2124.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 2125.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 2126.0, 0.235294, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 2127.0, 0.0980392, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 2128.0, 0.0784314, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 2129.0, 0.235294, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 2130.0, 0.235294, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 2131.0, 0.862745, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 2132.0, 0.705882, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 2133.0, 0.235294, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 2134.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 2135.0, 0.254902, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 2136.0, 0.0980392, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 2137.0, 0.0509804, 0, 0.980392 ); transferFunction->AddRGBPoint( 2138.0, 0.239216, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 2139.0, 0.239216, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 2140.0, 0.239216, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 2141.0, 0.0980392, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 2142.0, 0.54902, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 2143.0, 0.862745, 0.705882, 0.0784314 ); transferFunction->AddRGBPoint( 2144.0, 0.247059, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 2145.0, 0.866667, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 2146.0, 0.0823529, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 2147.0, 0.717647, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 2148.0, 0.866667, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 2149.0, 0.866667, 0.235294, 0.54902 ); transferFunction->AddRGBPoint( 2150.0, 0.866667, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 2151.0, 0.239216, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 2152.0, 0.392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 2153.0, 0.0392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 2154.0, 0.866667, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 2155.0, 0.552941, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 2156.0, 0.239216, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 2157.0, 0.0823529, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 2158.0, 0.552941, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 2159.0, 0.560784, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 2160.0, 0.239216, 0.0784314, 0.705882 ); transferFunction->AddRGBPoint( 2161.0, 0.396078, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 2162.0, 0.0823529, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 2163.0, 0.866667, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 2164.0, 0.552941, 0.392157, 0.862745 ); transferFunction->AddRGBPoint( 2165.0, 0.396078, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 2166.0, 0.866667, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 2167.0, 0.709804, 0.784314, 0.0784314 ); transferFunction->AddRGBPoint( 2168.0, 0.0823529, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 2169.0, 0.396078, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 2170.0, 0.709804, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 2171.0, 0.0823529, 0.54902, 0.784314 ); transferFunction->AddRGBPoint( 2172.0, 0.0823529, 0.0784314, 0.941176 ); transferFunction->AddRGBPoint( 2173.0, 0.0823529, 0.0784314, 0.784314 ); transferFunction->AddRGBPoint( 2174.0, 0.239216, 0.705882, 0.235294 ); transferFunction->AddRGBPoint( 2175.0, 0.239216, 0.705882, 0.980392 ); transferFunction->AddRGBPoint( 2176.0, 0.0823529, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 2177.0, 0.396078, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 2178.0, 0.0823529, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 2179.0, 0.0823529, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 2180.0, 0.87451, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 2181.0, 0.866667, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 2200.0, 0.0980392, 0.235294, 0.239216 ); transferFunction->AddRGBPoint( 2201.0, 0.0980392, 0.352941, 0.235294 ); transferFunction->AddRGBPoint( 2202.0, 0.0980392, 0.470588, 0.235294 ); transferFunction->AddRGBPoint( 2205.0, 0.0980392, 0.588235, 0.235294 ); transferFunction->AddRGBPoint( 2206.0, 0.0980392, 0.705882, 0.235294 ); transferFunction->AddRGBPoint( 2207.0, 0.0980392, 0.823529, 0.235294 ); transferFunction->AddRGBPoint( 2210.0, 0.0980392, 0.588235, 0.352941 ); transferFunction->AddRGBPoint( 2211.0, 0.0980392, 0.705882, 0.352941 ); transferFunction->AddRGBPoint( 2212.0, 0.0980392, 0.823529, 0.352941 ); transferFunction->AddRGBPoint( 3101.0, 0.196078, 0.196078, 0.196078 ); transferFunction->AddRGBPoint( 3102.0, 0.705882, 0.0784314, 0.117647 ); transferFunction->AddRGBPoint( 3103.0, 0.235294, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 3104.0, 0.0980392, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 3105.0, 0.705882, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 3106.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 3107.0, 0.54902, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 3108.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 3109.0, 0.54902, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 3110.0, 0.705882, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 3111.0, 0.54902, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 3112.0, 0.0823529, 0.0392157, 0.0392157 ); transferFunction->AddRGBPoint( 3113.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 3114.0, 0.0901961, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 3115.0, 0.705882, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 3116.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 3117.0, 0.235294, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 3118.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 3119.0, 0.254902, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 3120.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 3121.0, 0.235294, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 3122.0, 0.0784314, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 3123.0, 0.392157, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 3124.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 3125.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 3126.0, 0.235294, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 3127.0, 0.0980392, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 3128.0, 0.0784314, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 3129.0, 0.235294, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 3130.0, 0.235294, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 3131.0, 0.862745, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 3132.0, 0.705882, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 3133.0, 0.235294, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 3134.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 3135.0, 0.254902, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 3136.0, 0.0980392, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 3137.0, 0.0509804, 0, 0.980392 ); transferFunction->AddRGBPoint( 3138.0, 0.239216, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 3139.0, 0.239216, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 3140.0, 0.239216, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 3141.0, 0.0980392, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 3142.0, 0.54902, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 3143.0, 0.862745, 0.705882, 0.0784314 ); transferFunction->AddRGBPoint( 3144.0, 0.247059, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 3145.0, 0.866667, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 3146.0, 0.0823529, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 3147.0, 0.717647, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 3148.0, 0.866667, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 3149.0, 0.866667, 0.235294, 0.54902 ); transferFunction->AddRGBPoint( 3150.0, 0.866667, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 3151.0, 0.239216, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 3152.0, 0.392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 3153.0, 0.0392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 3154.0, 0.866667, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 3155.0, 0.552941, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 3156.0, 0.239216, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 3157.0, 0.0823529, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 3158.0, 0.552941, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 3159.0, 0.560784, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 3160.0, 0.239216, 0.0784314, 0.705882 ); transferFunction->AddRGBPoint( 3161.0, 0.396078, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 3162.0, 0.0823529, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 3163.0, 0.866667, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 3164.0, 0.552941, 0.392157, 0.862745 ); transferFunction->AddRGBPoint( 3165.0, 0.396078, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 3166.0, 0.866667, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 3167.0, 0.709804, 0.784314, 0.0784314 ); transferFunction->AddRGBPoint( 3168.0, 0.0823529, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 3169.0, 0.396078, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 3170.0, 0.709804, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 3171.0, 0.0823529, 0.54902, 0.784314 ); transferFunction->AddRGBPoint( 3172.0, 0.0823529, 0.0784314, 0.941176 ); transferFunction->AddRGBPoint( 3173.0, 0.0823529, 0.0784314, 0.784314 ); transferFunction->AddRGBPoint( 3174.0, 0.239216, 0.705882, 0.235294 ); transferFunction->AddRGBPoint( 3175.0, 0.239216, 0.705882, 0.980392 ); transferFunction->AddRGBPoint( 3176.0, 0.0823529, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 3177.0, 0.396078, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 3178.0, 0.0823529, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 3179.0, 0.0823529, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 3180.0, 0.87451, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 3181.0, 0.866667, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 4101.0, 0.196078, 0.196078, 0.196078 ); transferFunction->AddRGBPoint( 4102.0, 0.705882, 0.0784314, 0.117647 ); transferFunction->AddRGBPoint( 4103.0, 0.235294, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 4104.0, 0.0980392, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 4105.0, 0.705882, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 4106.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 4107.0, 0.54902, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 4108.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 4109.0, 0.54902, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 4110.0, 0.705882, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 4111.0, 0.54902, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 4112.0, 0.0823529, 0.0392157, 0.0392157 ); transferFunction->AddRGBPoint( 4113.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 4114.0, 0.0901961, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 4115.0, 0.705882, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 4116.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 4117.0, 0.235294, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 4118.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 4119.0, 0.254902, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 4120.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 4121.0, 0.235294, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 4122.0, 0.0784314, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 4123.0, 0.392157, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 4124.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 4125.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 4126.0, 0.235294, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 4127.0, 0.0980392, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 4128.0, 0.0784314, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 4129.0, 0.235294, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 4130.0, 0.235294, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 4131.0, 0.862745, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 4132.0, 0.705882, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 4133.0, 0.235294, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 4134.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 4135.0, 0.254902, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 4136.0, 0.0980392, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 4137.0, 0.0509804, 0, 0.980392 ); transferFunction->AddRGBPoint( 4138.0, 0.239216, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 4139.0, 0.239216, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 4140.0, 0.239216, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 4141.0, 0.0980392, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 4142.0, 0.54902, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 4143.0, 0.862745, 0.705882, 0.0784314 ); transferFunction->AddRGBPoint( 4144.0, 0.247059, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 4145.0, 0.866667, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 4146.0, 0.0823529, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 4147.0, 0.717647, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 4148.0, 0.866667, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 4149.0, 0.866667, 0.235294, 0.54902 ); transferFunction->AddRGBPoint( 4150.0, 0.866667, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 4151.0, 0.239216, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 4152.0, 0.392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 4153.0, 0.0392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 4154.0, 0.866667, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 4155.0, 0.552941, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 4156.0, 0.239216, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 4157.0, 0.0823529, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 4158.0, 0.552941, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 4159.0, 0.560784, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 4160.0, 0.239216, 0.0784314, 0.705882 ); transferFunction->AddRGBPoint( 4161.0, 0.396078, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 4162.0, 0.0823529, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 4163.0, 0.866667, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 4164.0, 0.552941, 0.392157, 0.862745 ); transferFunction->AddRGBPoint( 4165.0, 0.396078, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 4166.0, 0.866667, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 4167.0, 0.709804, 0.784314, 0.0784314 ); transferFunction->AddRGBPoint( 4168.0, 0.0823529, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 4169.0, 0.396078, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 4170.0, 0.709804, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 4171.0, 0.0823529, 0.54902, 0.784314 ); transferFunction->AddRGBPoint( 4172.0, 0.0823529, 0.0784314, 0.941176 ); transferFunction->AddRGBPoint( 4173.0, 0.0823529, 0.0784314, 0.784314 ); transferFunction->AddRGBPoint( 4174.0, 0.239216, 0.705882, 0.235294 ); transferFunction->AddRGBPoint( 4175.0, 0.239216, 0.705882, 0.980392 ); transferFunction->AddRGBPoint( 4176.0, 0.0823529, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 4177.0, 0.396078, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 4178.0, 0.0823529, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 4179.0, 0.0823529, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 4180.0, 0.87451, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 4181.0, 0.866667, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 5001.0, 0.0784314, 0.117647, 0.156863 ); transferFunction->AddRGBPoint( 5002.0, 0.0784314, 0.117647, 0.156863 ); transferFunction->AddRGBPoint( 5100.0, 0.8, 0.4, 0.4 ); transferFunction->AddRGBPoint( 5101.0, 0.8, 0.4, 0.4 ); transferFunction->AddRGBPoint( 5102.0, 1, 1, 0.4 ); transferFunction->AddRGBPoint( 5103.0, 0.6, 0.8, 0 ); transferFunction->AddRGBPoint( 5104.0, 0, 0.6, 0.6 ); transferFunction->AddRGBPoint( 5105.0, 0.8, 0.6, 1 ); transferFunction->AddRGBPoint( 5106.0, 1, 0.6, 0.2 ); transferFunction->AddRGBPoint( 5107.0, 0.8, 0.8, 0.8 ); transferFunction->AddRGBPoint( 5108.0, 0.6, 1, 1 ); transferFunction->AddRGBPoint( 5109.0, 0.4, 0.6, 1 ); transferFunction->AddRGBPoint( 5110.0, 1, 1, 0.4 ); transferFunction->AddRGBPoint( 5111.0, 0.6, 0.8, 0 ); transferFunction->AddRGBPoint( 5112.0, 0, 0.6, 0.6 ); transferFunction->AddRGBPoint( 5113.0, 0.8, 0.6, 1 ); transferFunction->AddRGBPoint( 5114.0, 1, 0.6, 0.2 ); transferFunction->AddRGBPoint( 5115.0, 0.8, 0.8, 0.8 ); transferFunction->AddRGBPoint( 5116.0, 0.6, 1, 1 ); transferFunction->AddRGBPoint( 5117.0, 0.4, 0.6, 1 ); transferFunction->AddRGBPoint( 5200.0, 0.8, 0.4, 0.4 ); transferFunction->AddRGBPoint( 5201.0, 0.8, 0.4, 0.4 ); transferFunction->AddRGBPoint( 5202.0, 1, 1, 0.4 ); transferFunction->AddRGBPoint( 5203.0, 0.6, 0.8, 0 ); transferFunction->AddRGBPoint( 5204.0, 0, 0.6, 0.6 ); transferFunction->AddRGBPoint( 5205.0, 0.8, 0.6, 1 ); transferFunction->AddRGBPoint( 5206.0, 1, 0.6, 0.2 ); transferFunction->AddRGBPoint( 5207.0, 0.8, 0.8, 0.8 ); transferFunction->AddRGBPoint( 5208.0, 0.6, 1, 1 ); transferFunction->AddRGBPoint( 5209.0, 0.4, 0.6, 1 ); transferFunction->AddRGBPoint( 5210.0, 1, 1, 0.4 ); transferFunction->AddRGBPoint( 5211.0, 0.6, 0.8, 0 ); transferFunction->AddRGBPoint( 5212.0, 0, 0.6, 0.6 ); transferFunction->AddRGBPoint( 5213.0, 0.8, 0.6, 1 ); transferFunction->AddRGBPoint( 5214.0, 1, 0.6, 0.2 ); transferFunction->AddRGBPoint( 5215.0, 0.8, 0.8, 0.8 ); transferFunction->AddRGBPoint( 5216.0, 0.6, 1, 1 ); transferFunction->AddRGBPoint( 5217.0, 0.4, 0.6, 1 ); transferFunction->AddRGBPoint( 6000.0, 0, 1, 0 ); transferFunction->AddRGBPoint( 6001.0, 1, 1, 0 ); transferFunction->AddRGBPoint( 6002.0, 0, 1, 1 ); transferFunction->AddRGBPoint( 6003.0, 0, 0, 1 ); transferFunction->AddRGBPoint( 6010.0, 0.92549, 0.0627451, 0.905882 ); transferFunction->AddRGBPoint( 6020.0, 0.929412, 0.0705882, 0.909804 ); transferFunction->AddRGBPoint( 6030.0, 0.92549, 0.0509804, 0.890196 ); transferFunction->AddRGBPoint( 6040.0, 0.92549, 0.0666667, 0.894118 ); transferFunction->AddRGBPoint( 6050.0, 0.00392157, 1, 0.00392157 ); transferFunction->AddRGBPoint( 6060.0, 0.00784314, 1, 0.00392157 ); transferFunction->AddRGBPoint( 6070.0, 0.92549, 0.054902, 0.901961 ); transferFunction->AddRGBPoint( 6080.0, 0.929412, 0.054902, 0.901961 ); transferFunction->AddRGBPoint( 7001.0, 0.282353, 0.517647, 0.709804 ); transferFunction->AddRGBPoint( 7002.0, 0.952941, 0.952941, 0.952941 ); transferFunction->AddRGBPoint( 7003.0, 0.811765, 0.247059, 0.309804 ); transferFunction->AddRGBPoint( 7004.0, 0.47451, 0.0784314, 0.529412 ); transferFunction->AddRGBPoint( 7005.0, 0.772549, 0.235294, 0.972549 ); transferFunction->AddRGBPoint( 7006.0, 0.00784314, 0.584314, 0.00784314 ); transferFunction->AddRGBPoint( 7007.0, 0.866667, 0.976471, 0.65098 ); transferFunction->AddRGBPoint( 7008.0, 0.909804, 0.572549, 0.137255 ); transferFunction->AddRGBPoint( 7009.0, 0.0784314, 0.235294, 0.470588 ); transferFunction->AddRGBPoint( 7010.0, 0.980392, 0.980392, 0 ); transferFunction->AddRGBPoint( 7011.0, 0.478431, 0.733333, 0.870588 ); transferFunction->AddRGBPoint( 7012.0, 0.929412, 0.0470588, 0.694118 ); transferFunction->AddRGBPoint( 7013.0, 0.0392157, 0.192157, 1 ); transferFunction->AddRGBPoint( 7014.0, 0.803922, 0.721569, 0.564706 ); transferFunction->AddRGBPoint( 7015.0, 0.176471, 0.803922, 0.647059 ); transferFunction->AddRGBPoint( 7016.0, 0.458824, 0.627451, 0.686275 ); transferFunction->AddRGBPoint( 7017.0, 0.866667, 0.85098, 0.0823529 ); transferFunction->AddRGBPoint( 7018.0, 0.0784314, 0.235294, 0.470588 ); transferFunction->AddRGBPoint( 7019.0, 0.552941, 0.0823529, 0.392157 ); transferFunction->AddRGBPoint( 7020.0, 0.882353, 0.54902, 0.552941 ); transferFunction->AddRGBPoint( 7100.0, 0.164706, 0.788235, 0.658824 ); transferFunction->AddRGBPoint( 7101.0, 0.658824, 0.407843, 0.635294 ); transferFunction->AddRGBPoint( 8001.0, 0.290196, 0.509804, 0.709804 ); transferFunction->AddRGBPoint( 8002.0, 0.94902, 0.945098, 0.941176 ); transferFunction->AddRGBPoint( 8003.0, 0.807843, 0.254902, 0.305882 ); transferFunction->AddRGBPoint( 8004.0, 0.470588, 0.0823529, 0.521569 ); transferFunction->AddRGBPoint( 8005.0, 0.764706, 0.239216, 0.964706 ); transferFunction->AddRGBPoint( 8006.0, 0.0117647, 0.576471, 0.0235294 ); transferFunction->AddRGBPoint( 8007.0, 0.862745, 0.984314, 0.639216 ); transferFunction->AddRGBPoint( 8008.0, 0.909804, 0.572549, 0.129412 ); transferFunction->AddRGBPoint( 8009.0, 0.0156863, 0.447059, 0.054902 ); transferFunction->AddRGBPoint( 8010.0, 0.47451, 0.721569, 0.862745 ); transferFunction->AddRGBPoint( 8011.0, 0.921569, 0.0431373, 0.686275 ); transferFunction->AddRGBPoint( 8012.0, 0.0470588, 0.180392, 0.980392 ); transferFunction->AddRGBPoint( 8013.0, 0.796078, 0.713725, 0.560784 ); transferFunction->AddRGBPoint( 8014.0, 0.164706, 0.8, 0.654902 ); transferFunction->AddRGBPoint( 9000.0, 0.117647, 0.0196078, 0.117647 ); transferFunction->AddRGBPoint( 9001.0, 0.117647, 0.392157, 0.176471 ); transferFunction->AddRGBPoint( 9002.0, 0.509804, 0.392157, 0.647059 ); transferFunction->AddRGBPoint( 9003.0, 0.411765, 0.0980392, 0.0196078 ); transferFunction->AddRGBPoint( 9004.0, 0.490196, 0.27451, 0.215686 ); transferFunction->AddRGBPoint( 9005.0, 0.882353, 0.0784314, 0.411765 ); transferFunction->AddRGBPoint( 9006.0, 0.882353, 0.0784314, 0.0588235 ); transferFunction->AddRGBPoint( 9500.0, 0.117647, 0.215686, 0.117647 ); transferFunction->AddRGBPoint( 9501.0, 0.117647, 0.588235, 0.176471 ); transferFunction->AddRGBPoint( 9502.0, 0.509804, 0.588235, 0.647059 ); transferFunction->AddRGBPoint( 9503.0, 0.411765, 0.294118, 0.0196078 ); transferFunction->AddRGBPoint( 9504.0, 0.490196, 0.470588, 0.215686 ); transferFunction->AddRGBPoint( 9505.0, 0.882353, 0.27451, 0.411765 ); transferFunction->AddRGBPoint( 9506.0, 0.882353, 0.27451, 0.0588235 ); transferFunction->AddRGBPoint( 11101.0, 0.0901961, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 11102.0, 0.0901961, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 11103.0, 0.247059, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 11104.0, 0.247059, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 11105.0, 0.0509804, 0, 0.980392 ); transferFunction->AddRGBPoint( 11106.0, 0.101961, 0.235294, 0 ); transferFunction->AddRGBPoint( 11107.0, 0.101961, 0.235294, 0.294118 ); transferFunction->AddRGBPoint( 11108.0, 0.101961, 0.235294, 0.588235 ); transferFunction->AddRGBPoint( 11109.0, 0.0980392, 0.235294, 0.980392 ); transferFunction->AddRGBPoint( 11110.0, 0.235294, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 11111.0, 0.705882, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 11112.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 11113.0, 0.54902, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 11114.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 11115.0, 0.54902, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 11116.0, 0.705882, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 11117.0, 0.0901961, 0.0392157, 0.0392157 ); transferFunction->AddRGBPoint( 11118.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 11119.0, 0.705882, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 11120.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 11121.0, 0.235294, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 11122.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 11123.0, 0.254902, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 11124.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 11125.0, 0.0784314, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 11126.0, 0.392157, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 11127.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 11128.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 11129.0, 0.235294, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 11130.0, 0.0980392, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 11131.0, 0.0784314, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 11132.0, 0.235294, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 11133.0, 0.235294, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 11134.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 11135.0, 0.254902, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 11136.0, 0.0980392, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 11137.0, 0.862745, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 11138.0, 0.705882, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 11139.0, 0.239216, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 11140.0, 0.239216, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 11141.0, 0.239216, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 11142.0, 0.0980392, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 11143.0, 0.54902, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 11144.0, 0.862745, 0.705882, 0.0784314 ); transferFunction->AddRGBPoint( 11145.0, 0.247059, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 11146.0, 0.866667, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 11147.0, 0.866667, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 11148.0, 0.866667, 0.235294, 0.54902 ); transferFunction->AddRGBPoint( 11149.0, 0.866667, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 11150.0, 0.239216, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 11151.0, 0.392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 11152.0, 0.0392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 11153.0, 0.866667, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 11154.0, 0.552941, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 11155.0, 0.239216, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 11156.0, 0.552941, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 11157.0, 0.560784, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 11158.0, 0.396078, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 11159.0, 0.0823529, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 11160.0, 0.239216, 0.0784314, 0.705882 ); transferFunction->AddRGBPoint( 11161.0, 0.866667, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 11162.0, 0.552941, 0.392157, 0.862745 ); transferFunction->AddRGBPoint( 11163.0, 0.866667, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 11164.0, 0.709804, 0.784314, 0.0784314 ); transferFunction->AddRGBPoint( 11165.0, 0.396078, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 11166.0, 0.396078, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 11167.0, 0.709804, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 11168.0, 0.0823529, 0.54902, 0.784314 ); transferFunction->AddRGBPoint( 11169.0, 0.0823529, 0.0784314, 0.941176 ); transferFunction->AddRGBPoint( 11170.0, 0.0823529, 0.0784314, 0.784314 ); transferFunction->AddRGBPoint( 11171.0, 0.0823529, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 11172.0, 0.396078, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 11173.0, 0.0823529, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 11174.0, 0.87451, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 11175.0, 0.866667, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 12101.0, 0.0901961, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 12102.0, 0.0901961, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 12103.0, 0.247059, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 12104.0, 0.247059, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 12105.0, 0.0509804, 0, 0.980392 ); transferFunction->AddRGBPoint( 12106.0, 0.101961, 0.235294, 0 ); transferFunction->AddRGBPoint( 12107.0, 0.101961, 0.235294, 0.294118 ); transferFunction->AddRGBPoint( 12108.0, 0.101961, 0.235294, 0.588235 ); transferFunction->AddRGBPoint( 12109.0, 0.0980392, 0.235294, 0.980392 ); transferFunction->AddRGBPoint( 12110.0, 0.235294, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 12111.0, 0.705882, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 12112.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 12113.0, 0.54902, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 12114.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 12115.0, 0.54902, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 12116.0, 0.705882, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 12117.0, 0.0901961, 0.0392157, 0.0392157 ); transferFunction->AddRGBPoint( 12118.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 12119.0, 0.705882, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 12120.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 12121.0, 0.235294, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 12122.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 12123.0, 0.254902, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 12124.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 12125.0, 0.0784314, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 12126.0, 0.392157, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 12127.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 12128.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 12129.0, 0.235294, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 12130.0, 0.0980392, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 12131.0, 0.0784314, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 12132.0, 0.235294, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 12133.0, 0.235294, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 12134.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 12135.0, 0.254902, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 12136.0, 0.0980392, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 12137.0, 0.862745, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 12138.0, 0.705882, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 12139.0, 0.239216, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 12140.0, 0.239216, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 12141.0, 0.239216, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 12142.0, 0.0980392, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 12143.0, 0.54902, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 12144.0, 0.862745, 0.705882, 0.0784314 ); transferFunction->AddRGBPoint( 12145.0, 0.247059, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 12146.0, 0.866667, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 12147.0, 0.866667, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 12148.0, 0.866667, 0.235294, 0.54902 ); transferFunction->AddRGBPoint( 12149.0, 0.866667, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 12150.0, 0.239216, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 12151.0, 0.392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 12152.0, 0.0392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 12153.0, 0.866667, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 12154.0, 0.552941, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 12155.0, 0.239216, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 12156.0, 0.552941, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 12157.0, 0.560784, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 12158.0, 0.396078, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 12159.0, 0.0823529, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 12160.0, 0.239216, 0.0784314, 0.705882 ); transferFunction->AddRGBPoint( 12161.0, 0.866667, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 12162.0, 0.552941, 0.392157, 0.862745 ); transferFunction->AddRGBPoint( 12163.0, 0.866667, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 12164.0, 0.709804, 0.784314, 0.0784314 ); transferFunction->AddRGBPoint( 12165.0, 0.396078, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 12166.0, 0.396078, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 12167.0, 0.709804, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 12168.0, 0.0823529, 0.54902, 0.784314 ); transferFunction->AddRGBPoint( 12169.0, 0.0823529, 0.0784314, 0.941176 ); transferFunction->AddRGBPoint( 12170.0, 0.0823529, 0.0784314, 0.784314 ); transferFunction->AddRGBPoint( 12171.0, 0.0823529, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 12172.0, 0.396078, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 12173.0, 0.0823529, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 12174.0, 0.87451, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 12175.0, 0.866667, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 13101.0, 0.0901961, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 13102.0, 0.0901961, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 13103.0, 0.247059, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 13104.0, 0.247059, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 13105.0, 0.0509804, 0, 0.980392 ); transferFunction->AddRGBPoint( 13106.0, 0.101961, 0.235294, 0 ); transferFunction->AddRGBPoint( 13107.0, 0.101961, 0.235294, 0.294118 ); transferFunction->AddRGBPoint( 13108.0, 0.101961, 0.235294, 0.588235 ); transferFunction->AddRGBPoint( 13109.0, 0.0980392, 0.235294, 0.980392 ); transferFunction->AddRGBPoint( 13110.0, 0.235294, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 13111.0, 0.705882, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 13112.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 13113.0, 0.54902, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 13114.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 13115.0, 0.54902, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 13116.0, 0.705882, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 13117.0, 0.0901961, 0.0392157, 0.0392157 ); transferFunction->AddRGBPoint( 13118.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 13119.0, 0.705882, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 13120.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 13121.0, 0.235294, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 13122.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 13123.0, 0.254902, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 13124.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 13125.0, 0.0784314, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 13126.0, 0.392157, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 13127.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 13128.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 13129.0, 0.235294, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 13130.0, 0.0980392, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 13131.0, 0.0784314, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 13132.0, 0.235294, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 13133.0, 0.235294, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 13134.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 13135.0, 0.254902, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 13136.0, 0.0980392, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 13137.0, 0.862745, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 13138.0, 0.705882, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 13139.0, 0.239216, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 13140.0, 0.239216, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 13141.0, 0.239216, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 13142.0, 0.0980392, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 13143.0, 0.54902, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 13144.0, 0.862745, 0.705882, 0.0784314 ); transferFunction->AddRGBPoint( 13145.0, 0.247059, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 13146.0, 0.866667, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 13147.0, 0.866667, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 13148.0, 0.866667, 0.235294, 0.54902 ); transferFunction->AddRGBPoint( 13149.0, 0.866667, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 13150.0, 0.239216, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 13151.0, 0.392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 13152.0, 0.0392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 13153.0, 0.866667, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 13154.0, 0.552941, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 13155.0, 0.239216, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 13156.0, 0.552941, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 13157.0, 0.560784, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 13158.0, 0.396078, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 13159.0, 0.0823529, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 13160.0, 0.239216, 0.0784314, 0.705882 ); transferFunction->AddRGBPoint( 13161.0, 0.866667, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 13162.0, 0.552941, 0.392157, 0.862745 ); transferFunction->AddRGBPoint( 13163.0, 0.866667, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 13164.0, 0.709804, 0.784314, 0.0784314 ); transferFunction->AddRGBPoint( 13165.0, 0.396078, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 13166.0, 0.396078, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 13167.0, 0.709804, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 13168.0, 0.0823529, 0.54902, 0.784314 ); transferFunction->AddRGBPoint( 13169.0, 0.0823529, 0.0784314, 0.941176 ); transferFunction->AddRGBPoint( 13170.0, 0.0823529, 0.0784314, 0.784314 ); transferFunction->AddRGBPoint( 13171.0, 0.0823529, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 13172.0, 0.396078, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 13173.0, 0.0823529, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 13174.0, 0.87451, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 13175.0, 0.866667, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 14101.0, 0.0901961, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 14102.0, 0.0901961, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 14103.0, 0.247059, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 14104.0, 0.247059, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 14105.0, 0.0509804, 0, 0.980392 ); transferFunction->AddRGBPoint( 14106.0, 0.101961, 0.235294, 0 ); transferFunction->AddRGBPoint( 14107.0, 0.101961, 0.235294, 0.294118 ); transferFunction->AddRGBPoint( 14108.0, 0.101961, 0.235294, 0.588235 ); transferFunction->AddRGBPoint( 14109.0, 0.0980392, 0.235294, 0.980392 ); transferFunction->AddRGBPoint( 14110.0, 0.235294, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 14111.0, 0.705882, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 14112.0, 0.862745, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 14113.0, 0.54902, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 14114.0, 0.705882, 0.862745, 0.54902 ); transferFunction->AddRGBPoint( 14115.0, 0.54902, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 14116.0, 0.705882, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 14117.0, 0.0901961, 0.0392157, 0.0392157 ); transferFunction->AddRGBPoint( 14118.0, 0.882353, 0.54902, 0.54902 ); transferFunction->AddRGBPoint( 14119.0, 0.705882, 0.235294, 0.705882 ); transferFunction->AddRGBPoint( 14120.0, 0.0784314, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 14121.0, 0.235294, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 14122.0, 0.862745, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 14123.0, 0.254902, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 14124.0, 0.862745, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 14125.0, 0.0784314, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 14126.0, 0.392157, 0.392157, 0.235294 ); transferFunction->AddRGBPoint( 14127.0, 0.862745, 0.705882, 0.862745 ); transferFunction->AddRGBPoint( 14128.0, 0.0784314, 0.705882, 0.54902 ); transferFunction->AddRGBPoint( 14129.0, 0.235294, 0.54902, 0.705882 ); transferFunction->AddRGBPoint( 14130.0, 0.0980392, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 14131.0, 0.0784314, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 14132.0, 0.235294, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 14133.0, 0.235294, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 14134.0, 0.862745, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 14135.0, 0.254902, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 14136.0, 0.0980392, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 14137.0, 0.862745, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 14138.0, 0.705882, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 14139.0, 0.239216, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 14140.0, 0.239216, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 14141.0, 0.239216, 0.235294, 0.392157 ); transferFunction->AddRGBPoint( 14142.0, 0.0980392, 0.0980392, 0.0980392 ); transferFunction->AddRGBPoint( 14143.0, 0.54902, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 14144.0, 0.862745, 0.705882, 0.0784314 ); transferFunction->AddRGBPoint( 14145.0, 0.247059, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 14146.0, 0.866667, 0.0784314, 0.0392157 ); transferFunction->AddRGBPoint( 14147.0, 0.866667, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 14148.0, 0.866667, 0.235294, 0.54902 ); transferFunction->AddRGBPoint( 14149.0, 0.866667, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 14150.0, 0.239216, 0.862745, 0.862745 ); transferFunction->AddRGBPoint( 14151.0, 0.392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 14152.0, 0.0392157, 0.784314, 0.784314 ); transferFunction->AddRGBPoint( 14153.0, 0.866667, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 14154.0, 0.552941, 0.0784314, 0.392157 ); transferFunction->AddRGBPoint( 14155.0, 0.239216, 0.862745, 0.392157 ); transferFunction->AddRGBPoint( 14156.0, 0.552941, 0.235294, 0.0784314 ); transferFunction->AddRGBPoint( 14157.0, 0.560784, 0.0784314, 0.862745 ); transferFunction->AddRGBPoint( 14158.0, 0.396078, 0.235294, 0.862745 ); transferFunction->AddRGBPoint( 14159.0, 0.0823529, 0.0784314, 0.54902 ); transferFunction->AddRGBPoint( 14160.0, 0.239216, 0.0784314, 0.705882 ); transferFunction->AddRGBPoint( 14161.0, 0.866667, 0.54902, 0.0784314 ); transferFunction->AddRGBPoint( 14162.0, 0.552941, 0.392157, 0.862745 ); transferFunction->AddRGBPoint( 14163.0, 0.866667, 0.392157, 0.0784314 ); transferFunction->AddRGBPoint( 14164.0, 0.709804, 0.784314, 0.0784314 ); transferFunction->AddRGBPoint( 14165.0, 0.396078, 0.0784314, 0.0784314 ); transferFunction->AddRGBPoint( 14166.0, 0.396078, 0.392157, 0.705882 ); transferFunction->AddRGBPoint( 14167.0, 0.709804, 0.862745, 0.0784314 ); transferFunction->AddRGBPoint( 14168.0, 0.0823529, 0.54902, 0.784314 ); transferFunction->AddRGBPoint( 14169.0, 0.0823529, 0.0784314, 0.941176 ); transferFunction->AddRGBPoint( 14170.0, 0.0823529, 0.0784314, 0.784314 ); transferFunction->AddRGBPoint( 14171.0, 0.0823529, 0.0784314, 0.235294 ); transferFunction->AddRGBPoint( 14172.0, 0.396078, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 14173.0, 0.0823529, 0.705882, 0.705882 ); transferFunction->AddRGBPoint( 14174.0, 0.87451, 0.862745, 0.235294 ); transferFunction->AddRGBPoint( 14175.0, 0.866667, 0.235294, 0.235294 ); transferFunction->AddRGBPoint( 0.0, 0.0, 0.0, 0.0 ); transferFunction->AddRGBPoint( 256.0, 0.0, 0.0, 0.0 ); transferFunction->AddRGBPoint( 1100.0, 0.0, 0.0, 0.0 ); transferFunction->AddRGBPoint( 2100.0, 0.0, 0.0, 0.0 ); transferFunction->AddRGBPoint( 3100.0, 0.0, 0.0, 0.0 ); transferFunction->AddRGBPoint( 4100.0, 0.0, 0.0, 0.0 ); transferFunction->AddRGBPoint( 11100.0, 0.0, 0.0, 0.0 ); transferFunction->AddRGBPoint( 12100.0, 0.0, 0.0, 0.0 ); transferFunction->AddRGBPoint( 13100.0, 0.0, 0.0, 0.0 ); transferFunction->AddRGBPoint( 14100.0, 0.0, 0.0, 0.0 ); return transferFunction; } FreeSurferParcellationTranslator::NameTable FreeSurferParcellationTranslator::CreateNameTable() { mitk::FreeSurferParcellationTranslator::NameTable nameTable; nameTable["0"] = "Unknown"; nameTable["1"] = "Left-Cerebral-Exterior"; nameTable["2"] = "Left-Cerebral-White-Matter"; nameTable["3"] = "Left-Cerebral-Cortex"; nameTable["4"] = "Left-Lateral-Ventricle"; nameTable["5"] = "Left-Inf-Lat-Vent"; nameTable["6"] = "Left-Cerebellum-Exterior"; nameTable["7"] = "Left-Cerebellum-White-Matter"; nameTable["8"] = "Left-Cerebellum-Cortex"; nameTable["9"] = "Left-Thalamus"; nameTable["10"] = "Left-Thalamus-Proper"; nameTable["11"] = "Left-Caudate"; nameTable["12"] = "Left-Putamen"; nameTable["13"] = "Left-Pallidum"; nameTable["14"] = "3rd-Ventricle"; nameTable["15"] = "4th-Ventricle"; nameTable["16"] = "Brain-Stem"; nameTable["17"] = "Left-Hippocampus"; nameTable["18"] = "Left-Amygdala"; nameTable["19"] = "Left-Insula"; nameTable["20"] = "Left-Operculum"; nameTable["21"] = "Line-1"; nameTable["22"] = "Line-2"; nameTable["23"] = "Line-3"; nameTable["24"] = "CSF"; nameTable["25"] = "Left-Lesion"; nameTable["26"] = "Left-Accumbens-area"; nameTable["27"] = "Left-Substancia-Nigra"; nameTable["28"] = "Left-VentralDC"; nameTable["29"] = "Left-undetermined"; nameTable["30"] = "Left-vessel"; nameTable["31"] = "Left-choroid-plexus"; nameTable["32"] = "Left-F3orb"; nameTable["33"] = "Left-lOg"; nameTable["34"] = "Left-aOg"; nameTable["35"] = "Left-mOg"; nameTable["36"] = "Left-pOg"; nameTable["37"] = "Left-Stellate"; nameTable["38"] = "Left-Porg"; nameTable["39"] = "Left-Aorg"; nameTable["40"] = "Right-Cerebral-Exterior"; nameTable["41"] = "Right-Cerebral-White-Matter"; nameTable["42"] = "Right-Cerebral-Cortex"; nameTable["43"] = "Right-Lateral-Ventricle"; nameTable["44"] = "Right-Inf-Lat-Vent"; nameTable["45"] = "Right-Cerebellum-Exterior"; nameTable["46"] = "Right-Cerebellum-White-Matter"; nameTable["47"] = "Right-Cerebellum-Cortex"; nameTable["48"] = "Right-Thalamus"; nameTable["49"] = "Right-Thalamus-Proper"; nameTable["50"] = "Right-Caudate"; nameTable["51"] = "Right-Putamen"; nameTable["52"] = "Right-Pallidum"; nameTable["53"] = "Right-Hippocampus"; nameTable["54"] = "Right-Amygdala"; nameTable["55"] = "Right-Insula"; nameTable["56"] = "Right-Operculum"; nameTable["57"] = "Right-Lesion"; nameTable["58"] = "Right-Accumbens-area"; nameTable["59"] = "Right-Substancia-Nigra"; nameTable["60"] = "Right-VentralDC"; nameTable["61"] = "Right-undetermined"; nameTable["62"] = "Right-vessel"; nameTable["63"] = "Right-choroid-plexus"; nameTable["64"] = "Right-F3orb"; nameTable["65"] = "Right-lOg"; nameTable["66"] = "Right-aOg"; nameTable["67"] = "Right-mOg"; nameTable["68"] = "Right-pOg"; nameTable["69"] = "Right-Stellate"; nameTable["70"] = "Right-Porg"; nameTable["71"] = "Right-Aorg"; nameTable["72"] = "5th-Ventricle"; nameTable["73"] = "Left-Interior"; nameTable["74"] = "Right-Interior"; nameTable["77"] = "WM-hypointensities"; nameTable["78"] = "Left-WM-hypointensities"; nameTable["79"] = "Right-WM-hypointensities"; nameTable["80"] = "non-WM-hypointensities"; nameTable["81"] = "Left-non-WM-hypointensities"; nameTable["82"] = "Right-non-WM-hypointensities"; nameTable["83"] = "Left-F1"; nameTable["84"] = "Right-F1"; nameTable["85"] = "Optic-Chiasm"; nameTable["192"] = "Corpus_Callosum"; nameTable["86"] = "Left_future_WMSA"; nameTable["87"] = "Right_future_WMSA"; nameTable["88"] = "future_WMSA"; nameTable["96"] = "Left-Amygdala-Anterior"; nameTable["97"] = "Right-Amygdala-Anterior"; nameTable["98"] = "Dura"; nameTable["100"] = "Left-wm-intensity-abnormality"; nameTable["101"] = "Left-caudate-intensity-abnormality"; nameTable["102"] = "Left-putamen-intensity-abnormality"; nameTable["103"] = "Left-accumbens-intensity-abnormality"; nameTable["104"] = "Left-pallidum-intensity-abnormality"; nameTable["105"] = "Left-amygdala-intensity-abnormality"; nameTable["106"] = "Left-hippocampus-intensity-abnormality"; nameTable["107"] = "Left-thalamus-intensity-abnormality"; nameTable["108"] = "Left-VDC-intensity-abnormality"; nameTable["109"] = "Right-wm-intensity-abnormality"; nameTable["110"] = "Right-caudate-intensity-abnormality"; nameTable["111"] = "Right-putamen-intensity-abnormality"; nameTable["112"] = "Right-accumbens-intensity-abnormality"; nameTable["113"] = "Right-pallidum-intensity-abnormality"; nameTable["114"] = "Right-amygdala-intensity-abnormality"; nameTable["115"] = "Right-hippocampus-intensity-abnormality"; nameTable["116"] = "Right-thalamus-intensity-abnormality"; nameTable["117"] = "Right-VDC-intensity-abnormality"; nameTable["118"] = "Epidermis"; nameTable["119"] = "Conn-Tissue"; nameTable["120"] = "SC-Fat-Muscle"; nameTable["121"] = "Cranium"; nameTable["122"] = "CSF-SA"; nameTable["123"] = "Muscle"; nameTable["124"] = "Ear"; nameTable["125"] = "Adipose"; nameTable["126"] = "Spinal-Cord"; nameTable["127"] = "Soft-Tissue"; nameTable["128"] = "Nerve"; nameTable["129"] = "Bone"; nameTable["130"] = "Air"; nameTable["131"] = "Orbital-Fat"; nameTable["132"] = "Tongue"; nameTable["133"] = "Nasal-Structures"; nameTable["134"] = "Globe"; nameTable["135"] = "Teeth"; nameTable["136"] = "Left-Caudate-Putamen"; nameTable["137"] = "Right-Caudate-Putamen"; nameTable["138"] = "Left-Claustrum"; nameTable["139"] = "Right-Claustrum"; nameTable["140"] = "Cornea"; nameTable["142"] = "Diploe"; nameTable["143"] = "Vitreous-Humor"; nameTable["144"] = "Lens"; nameTable["145"] = "Aqueous-Humor"; nameTable["146"] = "Outer-Table"; nameTable["147"] = "Inner-Table"; nameTable["148"] = "Periosteum"; nameTable["149"] = "Endosteum"; nameTable["150"] = "R-C-S"; nameTable["151"] = "Iris"; nameTable["152"] = "SC-Adipose-Muscle"; nameTable["153"] = "SC-Tissue"; nameTable["154"] = "Orbital-Adipose"; nameTable["155"] = "Left-IntCapsule-Ant"; nameTable["156"] = "Right-IntCapsule-Ant"; nameTable["157"] = "Left-IntCapsule-Pos"; nameTable["158"] = "Right-IntCapsule-Pos"; nameTable["159"] = "Left-Cerebral-WM-unmyelinated"; nameTable["160"] = "Right-Cerebral-WM-unmyelinated"; nameTable["161"] = "Left-Cerebral-WM-myelinated"; nameTable["162"] = "Right-Cerebral-WM-myelinated"; nameTable["163"] = "Left-Subcortical-Gray-Matter"; nameTable["164"] = "Right-Subcortical-Gray-Matter"; nameTable["165"] = "Skull"; nameTable["166"] = "Posterior-fossa"; nameTable["167"] = "Scalp"; nameTable["168"] = "Hematoma"; nameTable["169"] = "Left-Basal-Ganglia"; nameTable["176"] = "Right-Basal-Ganglia"; nameTable["170"] = "brainstem"; nameTable["171"] = "DCG"; nameTable["172"] = "Vermis"; nameTable["173"] = "Midbrain"; nameTable["174"] = "Pons"; nameTable["175"] = "Medulla"; nameTable["180"] = "Left-Cortical-Dysplasia"; nameTable["181"] = "Right-Cortical-Dysplasia"; nameTable["193"] = "Left-hippocampal_fissure"; nameTable["194"] = "Left-CADG-head"; nameTable["195"] = "Left-subiculum"; nameTable["196"] = "Left-fimbria"; nameTable["197"] = "Right-hippocampal_fissure"; nameTable["198"] = "Right-CADG-head"; nameTable["199"] = "Right-subiculum"; nameTable["200"] = "Right-fimbria"; nameTable["201"] = "alveus"; nameTable["202"] = "perforant_pathway"; nameTable["203"] = "parasubiculum"; nameTable["204"] = "presubiculum"; nameTable["205"] = "subiculum"; nameTable["206"] = "CA1"; nameTable["207"] = "CA2"; nameTable["208"] = "CA3"; nameTable["209"] = "CA4"; nameTable["210"] = "GC-ML-DG"; nameTable["211"] = "HATA"; nameTable["212"] = "fimbria"; nameTable["213"] = "lateral_ventricle"; nameTable["214"] = "molecular_layer_HP"; nameTable["215"] = "hippocampal_fissure"; nameTable["216"] = "entorhinal_cortex"; nameTable["217"] = "molecular_layer_subiculum"; nameTable["218"] = "Amygdala"; nameTable["219"] = "Cerebral_White_Matter"; nameTable["220"] = "Cerebral_Cortex"; nameTable["221"] = "Inf_Lat_Vent"; nameTable["222"] = "Perirhinal"; nameTable["223"] = "Cerebral_White_Matter_Edge"; nameTable["224"] = "Background"; nameTable["225"] = "Ectorhinal"; nameTable["226"] = "HP_tail"; nameTable["250"] = "Fornix"; nameTable["251"] = "CC_Posterior"; nameTable["252"] = "CC_Mid_Posterior"; nameTable["253"] = "CC_Central"; nameTable["254"] = "CC_Mid_Anterior"; nameTable["255"] = "CC_Anterior"; nameTable["256"] = "Voxel-Unchanged"; nameTable["331"] = "Aorta"; nameTable["332"] = "Left-Common-IliacA"; nameTable["333"] = "Right-Common-IliacA"; nameTable["334"] = "Left-External-IliacA"; nameTable["335"] = "Right-External-IliacA"; nameTable["336"] = "Left-Internal-IliacA"; nameTable["337"] = "Right-Internal-IliacA"; nameTable["338"] = "Left-Lateral-SacralA"; nameTable["339"] = "Right-Lateral-SacralA"; nameTable["340"] = "Left-ObturatorA"; nameTable["341"] = "Right-ObturatorA"; nameTable["342"] = "Left-Internal-PudendalA"; nameTable["343"] = "Right-Internal-PudendalA"; nameTable["344"] = "Left-UmbilicalA"; nameTable["345"] = "Right-UmbilicalA"; nameTable["346"] = "Left-Inf-RectalA"; nameTable["347"] = "Right-Inf-RectalA"; nameTable["348"] = "Left-Common-IliacV"; nameTable["349"] = "Right-Common-IliacV"; nameTable["350"] = "Left-External-IliacV"; nameTable["351"] = "Right-External-IliacV"; nameTable["352"] = "Left-Internal-IliacV"; nameTable["353"] = "Right-Internal-IliacV"; nameTable["354"] = "Left-ObturatorV"; nameTable["355"] = "Right-ObturatorV"; nameTable["356"] = "Left-Internal-PudendalV"; nameTable["357"] = "Right-Internal-PudendalV"; nameTable["358"] = "Pos-Lymph"; nameTable["359"] = "Neg-Lymph"; nameTable["400"] = "V1"; nameTable["401"] = "V2"; nameTable["402"] = "BA44"; nameTable["403"] = "BA45"; nameTable["404"] = "BA4a"; nameTable["405"] = "BA4p"; nameTable["406"] = "BA6"; nameTable["407"] = "BA2"; nameTable["408"] = "BA1_old"; nameTable["409"] = "BAun2"; nameTable["410"] = "BA1"; nameTable["411"] = "BA2b"; nameTable["412"] = "BA3a"; nameTable["413"] = "BA3b"; nameTable["414"] = "MT"; nameTable["415"] = "AIPS_AIP_l"; nameTable["416"] = "AIPS_AIP_r"; nameTable["417"] = "AIPS_VIP_l"; nameTable["418"] = "AIPS_VIP_r"; nameTable["419"] = "IPL_PFcm_l"; nameTable["420"] = "IPL_PFcm_r"; nameTable["421"] = "IPL_PF_l"; nameTable["422"] = "IPL_PFm_l"; nameTable["423"] = "IPL_PFm_r"; nameTable["424"] = "IPL_PFop_l"; nameTable["425"] = "IPL_PFop_r"; nameTable["426"] = "IPL_PF_r"; nameTable["427"] = "IPL_PFt_l"; nameTable["428"] = "IPL_PFt_r"; nameTable["429"] = "IPL_PGa_l"; nameTable["430"] = "IPL_PGa_r"; nameTable["431"] = "IPL_PGp_l"; nameTable["432"] = "IPL_PGp_r"; nameTable["433"] = "Visual_V3d_l"; nameTable["434"] = "Visual_V3d_r"; nameTable["435"] = "Visual_V4_l"; nameTable["436"] = "Visual_V4_r"; nameTable["437"] = "Visual_V5_b"; nameTable["438"] = "Visual_VP_l"; nameTable["439"] = "Visual_VP_r"; nameTable["498"] = "wmsa"; nameTable["499"] = "other_wmsa"; nameTable["500"] = "right_CA2_3"; nameTable["501"] = "right_alveus"; nameTable["502"] = "right_CA1"; nameTable["503"] = "right_fimbria"; nameTable["504"] = "right_presubiculum"; nameTable["505"] = "right_hippocampal_fissure"; nameTable["506"] = "right_CA4_DG"; nameTable["507"] = "right_subiculum"; nameTable["508"] = "right_fornix"; nameTable["550"] = "left_CA2_3"; nameTable["551"] = "left_alveus"; nameTable["552"] = "left_CA1"; nameTable["553"] = "left_fimbria"; nameTable["554"] = "left_presubiculum"; nameTable["555"] = "left_hippocampal_fissure"; nameTable["556"] = "left_CA4_DG"; nameTable["557"] = "left_subiculum"; nameTable["558"] = "left_fornix"; nameTable["600"] = "Tumor"; nameTable["601"] = "Cbm_Left_I_IV"; nameTable["602"] = "Cbm_Right_I_IV"; nameTable["603"] = "Cbm_Left_V"; nameTable["604"] = "Cbm_Right_V"; nameTable["605"] = "Cbm_Left_VI"; nameTable["606"] = "Cbm_Vermis_VI"; nameTable["607"] = "Cbm_Right_VI"; nameTable["608"] = "Cbm_Left_CrusI"; nameTable["609"] = "Cbm_Vermis_CrusI"; nameTable["610"] = "Cbm_Right_CrusI"; nameTable["611"] = "Cbm_Left_CrusII"; nameTable["612"] = "Cbm_Vermis_CrusII"; nameTable["613"] = "Cbm_Right_CrusII"; nameTable["614"] = "Cbm_Left_VIIb"; nameTable["615"] = "Cbm_Vermis_VIIb"; nameTable["616"] = "Cbm_Right_VIIb"; nameTable["617"] = "Cbm_Left_VIIIa"; nameTable["618"] = "Cbm_Vermis_VIIIa"; nameTable["619"] = "Cbm_Right_VIIIa"; nameTable["620"] = "Cbm_Left_VIIIb"; nameTable["621"] = "Cbm_Vermis_VIIIb"; nameTable["622"] = "Cbm_Right_VIIIb"; nameTable["623"] = "Cbm_Left_IX"; nameTable["624"] = "Cbm_Vermis_IX"; nameTable["625"] = "Cbm_Right_IX"; nameTable["626"] = "Cbm_Left_X"; nameTable["627"] = "Cbm_Vermis_X"; nameTable["628"] = "Cbm_Right_X"; nameTable["640"] = "Cbm_Right_I_V_med"; nameTable["641"] = "Cbm_Right_I_V_mid"; nameTable["642"] = "Cbm_Right_VI_med"; nameTable["643"] = "Cbm_Right_VI_mid"; nameTable["644"] = "Cbm_Right_VI_lat"; nameTable["645"] = "Cbm_Right_CrusI_med"; nameTable["646"] = "Cbm_Right_CrusI_mid"; nameTable["647"] = "Cbm_Right_CrusI_lat"; nameTable["648"] = "Cbm_Right_CrusII_med"; nameTable["649"] = "Cbm_Right_CrusII_mid"; nameTable["650"] = "Cbm_Right_CrusII_lat"; nameTable["651"] = "Cbm_Right_7med"; nameTable["652"] = "Cbm_Right_7mid"; nameTable["653"] = "Cbm_Right_7lat"; nameTable["654"] = "Cbm_Right_8med"; nameTable["655"] = "Cbm_Right_8mid"; nameTable["656"] = "Cbm_Right_8lat"; nameTable["657"] = "Cbm_Right_PUNs"; nameTable["658"] = "Cbm_Right_TONs"; nameTable["659"] = "Cbm_Right_FLOs"; nameTable["660"] = "Cbm_Left_I_V_med"; nameTable["661"] = "Cbm_Left_I_V_mid"; nameTable["662"] = "Cbm_Left_VI_med"; nameTable["663"] = "Cbm_Left_VI_mid"; nameTable["664"] = "Cbm_Left_VI_lat"; nameTable["665"] = "Cbm_Left_CrusI_med"; nameTable["666"] = "Cbm_Left_CrusI_mid"; nameTable["667"] = "Cbm_Left_CrusI_lat"; nameTable["668"] = "Cbm_Left_CrusII_med"; nameTable["669"] = "Cbm_Left_CrusII_mid"; nameTable["670"] = "Cbm_Left_CrusII_lat"; nameTable["671"] = "Cbm_Left_7med"; nameTable["672"] = "Cbm_Left_7mid"; nameTable["673"] = "Cbm_Left_7lat"; nameTable["674"] = "Cbm_Left_8med"; nameTable["675"] = "Cbm_Left_8mid"; nameTable["676"] = "Cbm_Left_8lat"; nameTable["677"] = "Cbm_Left_PUNs"; nameTable["678"] = "Cbm_Left_TONs"; nameTable["679"] = "Cbm_Left_FLOs"; nameTable["701"] = "CSF-FSL-FAST"; nameTable["702"] = "GrayMatter-FSL-FAST"; nameTable["703"] = "WhiteMatter-FSL-FAST"; nameTable["999"] = "SUSPICIOUS"; nameTable["1000"] = "ctx-lh-unknown"; nameTable["1001"] = "ctx-lh-bankssts"; nameTable["1002"] = "ctx-lh-caudalanteriorcingulate"; nameTable["1003"] = "ctx-lh-caudalmiddlefrontal"; nameTable["1004"] = "ctx-lh-corpuscallosum"; nameTable["1005"] = "ctx-lh-cuneus"; nameTable["1006"] = "ctx-lh-entorhinal"; nameTable["1007"] = "ctx-lh-fusiform"; nameTable["1008"] = "ctx-lh-inferiorparietal"; nameTable["1009"] = "ctx-lh-inferiortemporal"; nameTable["1010"] = "ctx-lh-isthmuscingulate"; nameTable["1011"] = "ctx-lh-lateraloccipital"; nameTable["1012"] = "ctx-lh-lateralorbitofrontal"; nameTable["1013"] = "ctx-lh-lingual"; nameTable["1014"] = "ctx-lh-medialorbitofrontal"; nameTable["1015"] = "ctx-lh-middletemporal"; nameTable["1016"] = "ctx-lh-parahippocampal"; nameTable["1017"] = "ctx-lh-paracentral"; nameTable["1018"] = "ctx-lh-parsopercularis"; nameTable["1019"] = "ctx-lh-parsorbitalis"; nameTable["1020"] = "ctx-lh-parstriangularis"; nameTable["1021"] = "ctx-lh-pericalcarine"; nameTable["1022"] = "ctx-lh-postcentral"; nameTable["1023"] = "ctx-lh-posteriorcingulate"; nameTable["1024"] = "ctx-lh-precentral"; nameTable["1025"] = "ctx-lh-precuneus"; nameTable["1026"] = "ctx-lh-rostralanteriorcingulate"; nameTable["1027"] = "ctx-lh-rostralmiddlefrontal"; nameTable["1028"] = "ctx-lh-superiorfrontal"; nameTable["1029"] = "ctx-lh-superiorparietal"; nameTable["1030"] = "ctx-lh-superiortemporal"; nameTable["1031"] = "ctx-lh-supramarginal"; nameTable["1032"] = "ctx-lh-frontalpole"; nameTable["1033"] = "ctx-lh-temporalpole"; nameTable["1034"] = "ctx-lh-transversetemporal"; nameTable["1035"] = "ctx-lh-insula"; nameTable["2000"] = "ctx-rh-unknown"; nameTable["2001"] = "ctx-rh-bankssts"; nameTable["2002"] = "ctx-rh-caudalanteriorcingulate"; nameTable["2003"] = "ctx-rh-caudalmiddlefrontal"; nameTable["2004"] = "ctx-rh-corpuscallosum"; nameTable["2005"] = "ctx-rh-cuneus"; nameTable["2006"] = "ctx-rh-entorhinal"; nameTable["2007"] = "ctx-rh-fusiform"; nameTable["2008"] = "ctx-rh-inferiorparietal"; nameTable["2009"] = "ctx-rh-inferiortemporal"; nameTable["2010"] = "ctx-rh-isthmuscingulate"; nameTable["2011"] = "ctx-rh-lateraloccipital"; nameTable["2012"] = "ctx-rh-lateralorbitofrontal"; nameTable["2013"] = "ctx-rh-lingual"; nameTable["2014"] = "ctx-rh-medialorbitofrontal"; nameTable["2015"] = "ctx-rh-middletemporal"; nameTable["2016"] = "ctx-rh-parahippocampal"; nameTable["2017"] = "ctx-rh-paracentral"; nameTable["2018"] = "ctx-rh-parsopercularis"; nameTable["2019"] = "ctx-rh-parsorbitalis"; nameTable["2020"] = "ctx-rh-parstriangularis"; nameTable["2021"] = "ctx-rh-pericalcarine"; nameTable["2022"] = "ctx-rh-postcentral"; nameTable["2023"] = "ctx-rh-posteriorcingulate"; nameTable["2024"] = "ctx-rh-precentral"; nameTable["2025"] = "ctx-rh-precuneus"; nameTable["2026"] = "ctx-rh-rostralanteriorcingulate"; nameTable["2027"] = "ctx-rh-rostralmiddlefrontal"; nameTable["2028"] = "ctx-rh-superiorfrontal"; nameTable["2029"] = "ctx-rh-superiorparietal"; nameTable["2030"] = "ctx-rh-superiortemporal"; nameTable["2031"] = "ctx-rh-supramarginal"; nameTable["2032"] = "ctx-rh-frontalpole"; nameTable["2033"] = "ctx-rh-temporalpole"; nameTable["2034"] = "ctx-rh-transversetemporal"; nameTable["2035"] = "ctx-rh-insula"; nameTable["3000"] = "wm-lh-unknown"; nameTable["3001"] = "wm-lh-bankssts"; nameTable["3002"] = "wm-lh-caudalanteriorcingulate"; nameTable["3003"] = "wm-lh-caudalmiddlefrontal"; nameTable["3004"] = "wm-lh-corpuscallosum"; nameTable["3005"] = "wm-lh-cuneus"; nameTable["3006"] = "wm-lh-entorhinal"; nameTable["3007"] = "wm-lh-fusiform"; nameTable["3008"] = "wm-lh-inferiorparietal"; nameTable["3009"] = "wm-lh-inferiortemporal"; nameTable["3010"] = "wm-lh-isthmuscingulate"; nameTable["3011"] = "wm-lh-lateraloccipital"; nameTable["3012"] = "wm-lh-lateralorbitofrontal"; nameTable["3013"] = "wm-lh-lingual"; nameTable["3014"] = "wm-lh-medialorbitofrontal"; nameTable["3015"] = "wm-lh-middletemporal"; nameTable["3016"] = "wm-lh-parahippocampal"; nameTable["3017"] = "wm-lh-paracentral"; nameTable["3018"] = "wm-lh-parsopercularis"; nameTable["3019"] = "wm-lh-parsorbitalis"; nameTable["3020"] = "wm-lh-parstriangularis"; nameTable["3021"] = "wm-lh-pericalcarine"; nameTable["3022"] = "wm-lh-postcentral"; nameTable["3023"] = "wm-lh-posteriorcingulate"; nameTable["3024"] = "wm-lh-precentral"; nameTable["3025"] = "wm-lh-precuneus"; nameTable["3026"] = "wm-lh-rostralanteriorcingulate"; nameTable["3027"] = "wm-lh-rostralmiddlefrontal"; nameTable["3028"] = "wm-lh-superiorfrontal"; nameTable["3029"] = "wm-lh-superiorparietal"; nameTable["3030"] = "wm-lh-superiortemporal"; nameTable["3031"] = "wm-lh-supramarginal"; nameTable["3032"] = "wm-lh-frontalpole"; nameTable["3033"] = "wm-lh-temporalpole"; nameTable["3034"] = "wm-lh-transversetemporal"; nameTable["3035"] = "wm-lh-insula"; nameTable["4000"] = "wm-rh-unknown"; nameTable["4001"] = "wm-rh-bankssts"; nameTable["4002"] = "wm-rh-caudalanteriorcingulate"; nameTable["4003"] = "wm-rh-caudalmiddlefrontal"; nameTable["4004"] = "wm-rh-corpuscallosum"; nameTable["4005"] = "wm-rh-cuneus"; nameTable["4006"] = "wm-rh-entorhinal"; nameTable["4007"] = "wm-rh-fusiform"; nameTable["4008"] = "wm-rh-inferiorparietal"; nameTable["4009"] = "wm-rh-inferiortemporal"; nameTable["4010"] = "wm-rh-isthmuscingulate"; nameTable["4011"] = "wm-rh-lateraloccipital"; nameTable["4012"] = "wm-rh-lateralorbitofrontal"; nameTable["4013"] = "wm-rh-lingual"; nameTable["4014"] = "wm-rh-medialorbitofrontal"; nameTable["4015"] = "wm-rh-middletemporal"; nameTable["4016"] = "wm-rh-parahippocampal"; nameTable["4017"] = "wm-rh-paracentral"; nameTable["4018"] = "wm-rh-parsopercularis"; nameTable["4019"] = "wm-rh-parsorbitalis"; nameTable["4020"] = "wm-rh-parstriangularis"; nameTable["4021"] = "wm-rh-pericalcarine"; nameTable["4022"] = "wm-rh-postcentral"; nameTable["4023"] = "wm-rh-posteriorcingulate"; nameTable["4024"] = "wm-rh-precentral"; nameTable["4025"] = "wm-rh-precuneus"; nameTable["4026"] = "wm-rh-rostralanteriorcingulate"; nameTable["4027"] = "wm-rh-rostralmiddlefrontal"; nameTable["4028"] = "wm-rh-superiorfrontal"; nameTable["4029"] = "wm-rh-superiorparietal"; nameTable["4030"] = "wm-rh-superiortemporal"; nameTable["4031"] = "wm-rh-supramarginal"; nameTable["4032"] = "wm-rh-frontalpole"; nameTable["4033"] = "wm-rh-temporalpole"; nameTable["4034"] = "wm-rh-transversetemporal"; nameTable["4035"] = "wm-rh-insula"; nameTable["1100"] = "ctx-lh-Unknown"; nameTable["1101"] = "ctx-lh-Corpus_callosum"; nameTable["1102"] = "ctx-lh-G_and_S_Insula_ONLY_AVERAGE"; nameTable["1103"] = "ctx-lh-G_cingulate-Isthmus"; nameTable["1104"] = "ctx-lh-G_cingulate-Main_part"; nameTable["1200"] = "ctx-lh-G_cingulate-caudal_ACC"; nameTable["1201"] = "ctx-lh-G_cingulate-rostral_ACC"; nameTable["1202"] = "ctx-lh-G_cingulate-posterior"; nameTable["1205"] = "ctx-lh-S_cingulate-caudal_ACC"; nameTable["1206"] = "ctx-lh-S_cingulate-rostral_ACC"; nameTable["1207"] = "ctx-lh-S_cingulate-posterior"; nameTable["1210"] = "ctx-lh-S_pericallosal-caudal"; nameTable["1211"] = "ctx-lh-S_pericallosal-rostral"; nameTable["1212"] = "ctx-lh-S_pericallosal-posterior"; nameTable["1105"] = "ctx-lh-G_cuneus"; nameTable["1106"] = "ctx-lh-G_frontal_inf-Opercular_part"; nameTable["1107"] = "ctx-lh-G_frontal_inf-Orbital_part"; nameTable["1108"] = "ctx-lh-G_frontal_inf-Triangular_part"; nameTable["1109"] = "ctx-lh-G_frontal_middle"; nameTable["1110"] = "ctx-lh-G_frontal_superior"; nameTable["1111"] = "ctx-lh-G_frontomarginal"; nameTable["1112"] = "ctx-lh-G_insular_long"; nameTable["1113"] = "ctx-lh-G_insular_short"; nameTable["1114"] = "ctx-lh-G_and_S_occipital_inferior"; nameTable["1115"] = "ctx-lh-G_occipital_middle"; nameTable["1116"] = "ctx-lh-G_occipital_superior"; nameTable["1117"] = "ctx-lh-G_occipit-temp_lat-Or_fusiform"; nameTable["1118"] = "ctx-lh-G_occipit-temp_med-Lingual_part"; nameTable["1119"] = "ctx-lh-G_occipit-temp_med-Parahippocampal_part"; nameTable["1120"] = "ctx-lh-G_orbital"; nameTable["1121"] = "ctx-lh-G_paracentral"; nameTable["1122"] = "ctx-lh-G_parietal_inferior-Angular_part"; nameTable["1123"] = "ctx-lh-G_parietal_inferior-Supramarginal_part"; nameTable["1124"] = "ctx-lh-G_parietal_superior"; nameTable["1125"] = "ctx-lh-G_postcentral"; nameTable["1126"] = "ctx-lh-G_precentral"; nameTable["1127"] = "ctx-lh-G_precuneus"; nameTable["1128"] = "ctx-lh-G_rectus"; nameTable["1129"] = "ctx-lh-G_subcallosal"; nameTable["1130"] = "ctx-lh-G_subcentral"; nameTable["1131"] = "ctx-lh-G_temporal_inferior"; nameTable["1132"] = "ctx-lh-G_temporal_middle"; nameTable["1133"] = "ctx-lh-G_temp_sup-G_temp_transv_and_interm_S"; nameTable["1134"] = "ctx-lh-G_temp_sup-Lateral_aspect"; nameTable["1135"] = "ctx-lh-G_temp_sup-Planum_polare"; nameTable["1136"] = "ctx-lh-G_temp_sup-Planum_tempolare"; nameTable["1137"] = "ctx-lh-G_and_S_transverse_frontopolar"; nameTable["1138"] = "ctx-lh-Lat_Fissure-ant_sgt-ramus_horizontal"; nameTable["1139"] = "ctx-lh-Lat_Fissure-ant_sgt-ramus_vertical"; nameTable["1140"] = "ctx-lh-Lat_Fissure-post_sgt"; nameTable["1141"] = "ctx-lh-Medial_wall"; nameTable["1142"] = "ctx-lh-Pole_occipital"; nameTable["1143"] = "ctx-lh-Pole_temporal"; nameTable["1144"] = "ctx-lh-S_calcarine"; nameTable["1145"] = "ctx-lh-S_central"; nameTable["1146"] = "ctx-lh-S_central_insula"; nameTable["1147"] = "ctx-lh-S_cingulate-Main_part_and_Intracingulate"; nameTable["1148"] = "ctx-lh-S_cingulate-Marginalis_part"; nameTable["1149"] = "ctx-lh-S_circular_insula_anterior"; nameTable["1150"] = "ctx-lh-S_circular_insula_inferior"; nameTable["1151"] = "ctx-lh-S_circular_insula_superior"; nameTable["1152"] = "ctx-lh-S_collateral_transverse_ant"; nameTable["1153"] = "ctx-lh-S_collateral_transverse_post"; nameTable["1154"] = "ctx-lh-S_frontal_inferior"; nameTable["1155"] = "ctx-lh-S_frontal_middle"; nameTable["1156"] = "ctx-lh-S_frontal_superior"; nameTable["1157"] = "ctx-lh-S_frontomarginal"; nameTable["1158"] = "ctx-lh-S_intermedius_primus-Jensen"; nameTable["1159"] = "ctx-lh-S_intraparietal-and_Parietal_transverse"; nameTable["1160"] = "ctx-lh-S_occipital_anterior"; nameTable["1161"] = "ctx-lh-S_occipital_middle_and_Lunatus"; nameTable["1162"] = "ctx-lh-S_occipital_superior_and_transversalis"; nameTable["1163"] = "ctx-lh-S_occipito-temporal_lateral"; nameTable["1164"] = "ctx-lh-S_occipito-temporal_medial_and_S_Lingual"; nameTable["1165"] = "ctx-lh-S_orbital-H_shapped"; nameTable["1166"] = "ctx-lh-S_orbital_lateral"; nameTable["1167"] = "ctx-lh-S_orbital_medial-Or_olfactory"; nameTable["1168"] = "ctx-lh-S_paracentral"; nameTable["1169"] = "ctx-lh-S_parieto_occipital"; nameTable["1170"] = "ctx-lh-S_pericallosal"; nameTable["1171"] = "ctx-lh-S_postcentral"; nameTable["1172"] = "ctx-lh-S_precentral-Inferior-part"; nameTable["1173"] = "ctx-lh-S_precentral-Superior-part"; nameTable["1174"] = "ctx-lh-S_subcentral_ant"; nameTable["1175"] = "ctx-lh-S_subcentral_post"; nameTable["1176"] = "ctx-lh-S_suborbital"; nameTable["1177"] = "ctx-lh-S_subparietal"; nameTable["1178"] = "ctx-lh-S_supracingulate"; nameTable["1179"] = "ctx-lh-S_temporal_inferior"; nameTable["1180"] = "ctx-lh-S_temporal_superior"; nameTable["1181"] = "ctx-lh-S_temporal_transverse"; nameTable["2100"] = "ctx-rh-Unknown"; nameTable["2101"] = "ctx-rh-Corpus_callosum"; nameTable["2102"] = "ctx-rh-G_and_S_Insula_ONLY_AVERAGE"; nameTable["2103"] = "ctx-rh-G_cingulate-Isthmus"; nameTable["2104"] = "ctx-rh-G_cingulate-Main_part"; nameTable["2105"] = "ctx-rh-G_cuneus"; nameTable["2106"] = "ctx-rh-G_frontal_inf-Opercular_part"; nameTable["2107"] = "ctx-rh-G_frontal_inf-Orbital_part"; nameTable["2108"] = "ctx-rh-G_frontal_inf-Triangular_part"; nameTable["2109"] = "ctx-rh-G_frontal_middle"; nameTable["2110"] = "ctx-rh-G_frontal_superior"; nameTable["2111"] = "ctx-rh-G_frontomarginal"; nameTable["2112"] = "ctx-rh-G_insular_long"; nameTable["2113"] = "ctx-rh-G_insular_short"; nameTable["2114"] = "ctx-rh-G_and_S_occipital_inferior"; nameTable["2115"] = "ctx-rh-G_occipital_middle"; nameTable["2116"] = "ctx-rh-G_occipital_superior"; nameTable["2117"] = "ctx-rh-G_occipit-temp_lat-Or_fusiform"; nameTable["2118"] = "ctx-rh-G_occipit-temp_med-Lingual_part"; nameTable["2119"] = "ctx-rh-G_occipit-temp_med-Parahippocampal_part"; nameTable["2120"] = "ctx-rh-G_orbital"; nameTable["2121"] = "ctx-rh-G_paracentral"; nameTable["2122"] = "ctx-rh-G_parietal_inferior-Angular_part"; nameTable["2123"] = "ctx-rh-G_parietal_inferior-Supramarginal_part"; nameTable["2124"] = "ctx-rh-G_parietal_superior"; nameTable["2125"] = "ctx-rh-G_postcentral"; nameTable["2126"] = "ctx-rh-G_precentral"; nameTable["2127"] = "ctx-rh-G_precuneus"; nameTable["2128"] = "ctx-rh-G_rectus"; nameTable["2129"] = "ctx-rh-G_subcallosal"; nameTable["2130"] = "ctx-rh-G_subcentral"; nameTable["2131"] = "ctx-rh-G_temporal_inferior"; nameTable["2132"] = "ctx-rh-G_temporal_middle"; nameTable["2133"] = "ctx-rh-G_temp_sup-G_temp_transv_and_interm_S"; nameTable["2134"] = "ctx-rh-G_temp_sup-Lateral_aspect"; nameTable["2135"] = "ctx-rh-G_temp_sup-Planum_polare"; nameTable["2136"] = "ctx-rh-G_temp_sup-Planum_tempolare"; nameTable["2137"] = "ctx-rh-G_and_S_transverse_frontopolar"; nameTable["2138"] = "ctx-rh-Lat_Fissure-ant_sgt-ramus_horizontal"; nameTable["2139"] = "ctx-rh-Lat_Fissure-ant_sgt-ramus_vertical"; nameTable["2140"] = "ctx-rh-Lat_Fissure-post_sgt"; nameTable["2141"] = "ctx-rh-Medial_wall"; nameTable["2142"] = "ctx-rh-Pole_occipital"; nameTable["2143"] = "ctx-rh-Pole_temporal"; nameTable["2144"] = "ctx-rh-S_calcarine"; nameTable["2145"] = "ctx-rh-S_central"; nameTable["2146"] = "ctx-rh-S_central_insula"; nameTable["2147"] = "ctx-rh-S_cingulate-Main_part_and_Intracingulate"; nameTable["2148"] = "ctx-rh-S_cingulate-Marginalis_part"; nameTable["2149"] = "ctx-rh-S_circular_insula_anterior"; nameTable["2150"] = "ctx-rh-S_circular_insula_inferior"; nameTable["2151"] = "ctx-rh-S_circular_insula_superior"; nameTable["2152"] = "ctx-rh-S_collateral_transverse_ant"; nameTable["2153"] = "ctx-rh-S_collateral_transverse_post"; nameTable["2154"] = "ctx-rh-S_frontal_inferior"; nameTable["2155"] = "ctx-rh-S_frontal_middle"; nameTable["2156"] = "ctx-rh-S_frontal_superior"; nameTable["2157"] = "ctx-rh-S_frontomarginal"; nameTable["2158"] = "ctx-rh-S_intermedius_primus-Jensen"; nameTable["2159"] = "ctx-rh-S_intraparietal-and_Parietal_transverse"; nameTable["2160"] = "ctx-rh-S_occipital_anterior"; nameTable["2161"] = "ctx-rh-S_occipital_middle_and_Lunatus"; nameTable["2162"] = "ctx-rh-S_occipital_superior_and_transversalis"; nameTable["2163"] = "ctx-rh-S_occipito-temporal_lateral"; nameTable["2164"] = "ctx-rh-S_occipito-temporal_medial_and_S_Lingual"; nameTable["2165"] = "ctx-rh-S_orbital-H_shapped"; nameTable["2166"] = "ctx-rh-S_orbital_lateral"; nameTable["2167"] = "ctx-rh-S_orbital_medial-Or_olfactory"; nameTable["2168"] = "ctx-rh-S_paracentral"; nameTable["2169"] = "ctx-rh-S_parieto_occipital"; nameTable["2170"] = "ctx-rh-S_pericallosal"; nameTable["2171"] = "ctx-rh-S_postcentral"; nameTable["2172"] = "ctx-rh-S_precentral-Inferior-part"; nameTable["2173"] = "ctx-rh-S_precentral-Superior-part"; nameTable["2174"] = "ctx-rh-S_subcentral_ant"; nameTable["2175"] = "ctx-rh-S_subcentral_post"; nameTable["2176"] = "ctx-rh-S_suborbital"; nameTable["2177"] = "ctx-rh-S_subparietal"; nameTable["2178"] = "ctx-rh-S_supracingulate"; nameTable["2179"] = "ctx-rh-S_temporal_inferior"; nameTable["2180"] = "ctx-rh-S_temporal_superior"; nameTable["2181"] = "ctx-rh-S_temporal_transverse"; nameTable["2200"] = "ctx-rh-G_cingulate-caudal_ACC"; nameTable["2201"] = "ctx-rh-G_cingulate-rostral_ACC"; nameTable["2202"] = "ctx-rh-G_cingulate-posterior"; nameTable["2205"] = "ctx-rh-S_cingulate-caudal_ACC"; nameTable["2206"] = "ctx-rh-S_cingulate-rostral_ACC"; nameTable["2207"] = "ctx-rh-S_cingulate-posterior"; nameTable["2210"] = "ctx-rh-S_pericallosal-caudal"; nameTable["2211"] = "ctx-rh-S_pericallosal-rostral"; nameTable["2212"] = "ctx-rh-S_pericallosal-posterior"; nameTable["3100"] = "wm-lh-Unknown"; nameTable["3101"] = "wm-lh-Corpus_callosum"; nameTable["3102"] = "wm-lh-G_and_S_Insula_ONLY_AVERAGE"; nameTable["3103"] = "wm-lh-G_cingulate-Isthmus"; nameTable["3104"] = "wm-lh-G_cingulate-Main_part"; nameTable["3105"] = "wm-lh-G_cuneus"; nameTable["3106"] = "wm-lh-G_frontal_inf-Opercular_part"; nameTable["3107"] = "wm-lh-G_frontal_inf-Orbital_part"; nameTable["3108"] = "wm-lh-G_frontal_inf-Triangular_part"; nameTable["3109"] = "wm-lh-G_frontal_middle"; nameTable["3110"] = "wm-lh-G_frontal_superior"; nameTable["3111"] = "wm-lh-G_frontomarginal"; nameTable["3112"] = "wm-lh-G_insular_long"; nameTable["3113"] = "wm-lh-G_insular_short"; nameTable["3114"] = "wm-lh-G_and_S_occipital_inferior"; nameTable["3115"] = "wm-lh-G_occipital_middle"; nameTable["3116"] = "wm-lh-G_occipital_superior"; nameTable["3117"] = "wm-lh-G_occipit-temp_lat-Or_fusiform"; nameTable["3118"] = "wm-lh-G_occipit-temp_med-Lingual_part"; nameTable["3119"] = "wm-lh-G_occipit-temp_med-Parahippocampal_part"; nameTable["3120"] = "wm-lh-G_orbital"; nameTable["3121"] = "wm-lh-G_paracentral"; nameTable["3122"] = "wm-lh-G_parietal_inferior-Angular_part"; nameTable["3123"] = "wm-lh-G_parietal_inferior-Supramarginal_part"; nameTable["3124"] = "wm-lh-G_parietal_superior"; nameTable["3125"] = "wm-lh-G_postcentral"; nameTable["3126"] = "wm-lh-G_precentral"; nameTable["3127"] = "wm-lh-G_precuneus"; nameTable["3128"] = "wm-lh-G_rectus"; nameTable["3129"] = "wm-lh-G_subcallosal"; nameTable["3130"] = "wm-lh-G_subcentral"; nameTable["3131"] = "wm-lh-G_temporal_inferior"; nameTable["3132"] = "wm-lh-G_temporal_middle"; nameTable["3133"] = "wm-lh-G_temp_sup-G_temp_transv_and_interm_S"; nameTable["3134"] = "wm-lh-G_temp_sup-Lateral_aspect"; nameTable["3135"] = "wm-lh-G_temp_sup-Planum_polare"; nameTable["3136"] = "wm-lh-G_temp_sup-Planum_tempolare"; nameTable["3137"] = "wm-lh-G_and_S_transverse_frontopolar"; nameTable["3138"] = "wm-lh-Lat_Fissure-ant_sgt-ramus_horizontal"; nameTable["3139"] = "wm-lh-Lat_Fissure-ant_sgt-ramus_vertical"; nameTable["3140"] = "wm-lh-Lat_Fissure-post_sgt"; nameTable["3141"] = "wm-lh-Medial_wall"; nameTable["3142"] = "wm-lh-Pole_occipital"; nameTable["3143"] = "wm-lh-Pole_temporal"; nameTable["3144"] = "wm-lh-S_calcarine"; nameTable["3145"] = "wm-lh-S_central"; nameTable["3146"] = "wm-lh-S_central_insula"; nameTable["3147"] = "wm-lh-S_cingulate-Main_part_and_Intracingulate"; nameTable["3148"] = "wm-lh-S_cingulate-Marginalis_part"; nameTable["3149"] = "wm-lh-S_circular_insula_anterior"; nameTable["3150"] = "wm-lh-S_circular_insula_inferior"; nameTable["3151"] = "wm-lh-S_circular_insula_superior"; nameTable["3152"] = "wm-lh-S_collateral_transverse_ant"; nameTable["3153"] = "wm-lh-S_collateral_transverse_post"; nameTable["3154"] = "wm-lh-S_frontal_inferior"; nameTable["3155"] = "wm-lh-S_frontal_middle"; nameTable["3156"] = "wm-lh-S_frontal_superior"; nameTable["3157"] = "wm-lh-S_frontomarginal"; nameTable["3158"] = "wm-lh-S_intermedius_primus-Jensen"; nameTable["3159"] = "wm-lh-S_intraparietal-and_Parietal_transverse"; nameTable["3160"] = "wm-lh-S_occipital_anterior"; nameTable["3161"] = "wm-lh-S_occipital_middle_and_Lunatus"; nameTable["3162"] = "wm-lh-S_occipital_superior_and_transversalis"; nameTable["3163"] = "wm-lh-S_occipito-temporal_lateral"; nameTable["3164"] = "wm-lh-S_occipito-temporal_medial_and_S_Lingual"; nameTable["3165"] = "wm-lh-S_orbital-H_shapped"; nameTable["3166"] = "wm-lh-S_orbital_lateral"; nameTable["3167"] = "wm-lh-S_orbital_medial-Or_olfactory"; nameTable["3168"] = "wm-lh-S_paracentral"; nameTable["3169"] = "wm-lh-S_parieto_occipital"; nameTable["3170"] = "wm-lh-S_pericallosal"; nameTable["3171"] = "wm-lh-S_postcentral"; nameTable["3172"] = "wm-lh-S_precentral-Inferior-part"; nameTable["3173"] = "wm-lh-S_precentral-Superior-part"; nameTable["3174"] = "wm-lh-S_subcentral_ant"; nameTable["3175"] = "wm-lh-S_subcentral_post"; nameTable["3176"] = "wm-lh-S_suborbital"; nameTable["3177"] = "wm-lh-S_subparietal"; nameTable["3178"] = "wm-lh-S_supracingulate"; nameTable["3179"] = "wm-lh-S_temporal_inferior"; nameTable["3180"] = "wm-lh-S_temporal_superior"; nameTable["3181"] = "wm-lh-S_temporal_transverse"; nameTable["4100"] = "wm-rh-Unknown"; nameTable["4101"] = "wm-rh-Corpus_callosum"; nameTable["4102"] = "wm-rh-G_and_S_Insula_ONLY_AVERAGE"; nameTable["4103"] = "wm-rh-G_cingulate-Isthmus"; nameTable["4104"] = "wm-rh-G_cingulate-Main_part"; nameTable["4105"] = "wm-rh-G_cuneus"; nameTable["4106"] = "wm-rh-G_frontal_inf-Opercular_part"; nameTable["4107"] = "wm-rh-G_frontal_inf-Orbital_part"; nameTable["4108"] = "wm-rh-G_frontal_inf-Triangular_part"; nameTable["4109"] = "wm-rh-G_frontal_middle"; nameTable["4110"] = "wm-rh-G_frontal_superior"; nameTable["4111"] = "wm-rh-G_frontomarginal"; nameTable["4112"] = "wm-rh-G_insular_long"; nameTable["4113"] = "wm-rh-G_insular_short"; nameTable["4114"] = "wm-rh-G_and_S_occipital_inferior"; nameTable["4115"] = "wm-rh-G_occipital_middle"; nameTable["4116"] = "wm-rh-G_occipital_superior"; nameTable["4117"] = "wm-rh-G_occipit-temp_lat-Or_fusiform"; nameTable["4118"] = "wm-rh-G_occipit-temp_med-Lingual_part"; nameTable["4119"] = "wm-rh-G_occipit-temp_med-Parahippocampal_part"; nameTable["4120"] = "wm-rh-G_orbital"; nameTable["4121"] = "wm-rh-G_paracentral"; nameTable["4122"] = "wm-rh-G_parietal_inferior-Angular_part"; nameTable["4123"] = "wm-rh-G_parietal_inferior-Supramarginal_part"; nameTable["4124"] = "wm-rh-G_parietal_superior"; nameTable["4125"] = "wm-rh-G_postcentral"; nameTable["4126"] = "wm-rh-G_precentral"; nameTable["4127"] = "wm-rh-G_precuneus"; nameTable["4128"] = "wm-rh-G_rectus"; nameTable["4129"] = "wm-rh-G_subcallosal"; nameTable["4130"] = "wm-rh-G_subcentral"; nameTable["4131"] = "wm-rh-G_temporal_inferior"; nameTable["4132"] = "wm-rh-G_temporal_middle"; nameTable["4133"] = "wm-rh-G_temp_sup-G_temp_transv_and_interm_S"; nameTable["4134"] = "wm-rh-G_temp_sup-Lateral_aspect"; nameTable["4135"] = "wm-rh-G_temp_sup-Planum_polare"; nameTable["4136"] = "wm-rh-G_temp_sup-Planum_tempolare"; nameTable["4137"] = "wm-rh-G_and_S_transverse_frontopolar"; nameTable["4138"] = "wm-rh-Lat_Fissure-ant_sgt-ramus_horizontal"; nameTable["4139"] = "wm-rh-Lat_Fissure-ant_sgt-ramus_vertical"; nameTable["4140"] = "wm-rh-Lat_Fissure-post_sgt"; nameTable["4141"] = "wm-rh-Medial_wall"; nameTable["4142"] = "wm-rh-Pole_occipital"; nameTable["4143"] = "wm-rh-Pole_temporal"; nameTable["4144"] = "wm-rh-S_calcarine"; nameTable["4145"] = "wm-rh-S_central"; nameTable["4146"] = "wm-rh-S_central_insula"; nameTable["4147"] = "wm-rh-S_cingulate-Main_part_and_Intracingulate"; nameTable["4148"] = "wm-rh-S_cingulate-Marginalis_part"; nameTable["4149"] = "wm-rh-S_circular_insula_anterior"; nameTable["4150"] = "wm-rh-S_circular_insula_inferior"; nameTable["4151"] = "wm-rh-S_circular_insula_superior"; nameTable["4152"] = "wm-rh-S_collateral_transverse_ant"; nameTable["4153"] = "wm-rh-S_collateral_transverse_post"; nameTable["4154"] = "wm-rh-S_frontal_inferior"; nameTable["4155"] = "wm-rh-S_frontal_middle"; nameTable["4156"] = "wm-rh-S_frontal_superior"; nameTable["4157"] = "wm-rh-S_frontomarginal"; nameTable["4158"] = "wm-rh-S_intermedius_primus-Jensen"; nameTable["4159"] = "wm-rh-S_intraparietal-and_Parietal_transverse"; nameTable["4160"] = "wm-rh-S_occipital_anterior"; nameTable["4161"] = "wm-rh-S_occipital_middle_and_Lunatus"; nameTable["4162"] = "wm-rh-S_occipital_superior_and_transversalis"; nameTable["4163"] = "wm-rh-S_occipito-temporal_lateral"; nameTable["4164"] = "wm-rh-S_occipito-temporal_medial_and_S_Lingual"; nameTable["4165"] = "wm-rh-S_orbital-H_shapped"; nameTable["4166"] = "wm-rh-S_orbital_lateral"; nameTable["4167"] = "wm-rh-S_orbital_medial-Or_olfactory"; nameTable["4168"] = "wm-rh-S_paracentral"; nameTable["4169"] = "wm-rh-S_parieto_occipital"; nameTable["4170"] = "wm-rh-S_pericallosal"; nameTable["4171"] = "wm-rh-S_postcentral"; nameTable["4172"] = "wm-rh-S_precentral-Inferior-part"; nameTable["4173"] = "wm-rh-S_precentral-Superior-part"; nameTable["4174"] = "wm-rh-S_subcentral_ant"; nameTable["4175"] = "wm-rh-S_subcentral_post"; nameTable["4176"] = "wm-rh-S_suborbital"; nameTable["4177"] = "wm-rh-S_subparietal"; nameTable["4178"] = "wm-rh-S_supracingulate"; nameTable["4179"] = "wm-rh-S_temporal_inferior"; nameTable["4180"] = "wm-rh-S_temporal_superior"; nameTable["4181"] = "wm-rh-S_temporal_transverse"; nameTable["5001"] = "Left-UnsegmentedWhiteMatter"; nameTable["5002"] = "Right-UnsegmentedWhiteMatter"; nameTable["5100"] = "fmajor"; nameTable["5101"] = "fminor"; nameTable["5102"] = "lh.atr"; nameTable["5103"] = "lh.cab"; nameTable["5104"] = "lh.ccg"; nameTable["5105"] = "lh.cst"; nameTable["5106"] = "lh.ilf"; nameTable["5107"] = "lh.slfp"; nameTable["5108"] = "lh.slft"; nameTable["5109"] = "lh.unc"; nameTable["5110"] = "rh.atr"; nameTable["5111"] = "rh.cab"; nameTable["5112"] = "rh.ccg"; nameTable["5113"] = "rh.cst"; nameTable["5114"] = "rh.ilf"; nameTable["5115"] = "rh.slfp"; nameTable["5116"] = "rh.slft"; nameTable["5117"] = "rh.unc"; nameTable["5200"] = "CC-ForcepsMajor"; nameTable["5201"] = "CC-ForcepsMinor"; nameTable["5202"] = "LAntThalRadiation"; nameTable["5203"] = "LCingulumAngBundle"; nameTable["5204"] = "LCingulumCingGyrus"; nameTable["5205"] = "LCorticospinalTract"; nameTable["5206"] = "LInfLongFas"; nameTable["5207"] = "LSupLongFasParietal"; nameTable["5208"] = "LSupLongFasTemporal"; nameTable["5209"] = "LUncinateFas"; nameTable["5210"] = "RAntThalRadiation"; nameTable["5211"] = "RCingulumAngBundle"; nameTable["5212"] = "RCingulumCingGyrus"; nameTable["5213"] = "RCorticospinalTract"; nameTable["5214"] = "RInfLongFas"; nameTable["5215"] = "RSupLongFasParietal"; nameTable["5216"] = "RSupLongFasTemporal"; nameTable["5217"] = "RUncinateFas"; nameTable["6000"] = "CST-orig"; nameTable["6001"] = "CST-hammer"; nameTable["6002"] = "CST-CVS"; nameTable["6003"] = "CST-flirt"; nameTable["6010"] = "Left-SLF1"; nameTable["6020"] = "Right-SLF1"; nameTable["6030"] = "Left-SLF3"; nameTable["6040"] = "Right-SLF3"; nameTable["6050"] = "Left-CST"; nameTable["6060"] = "Right-CST"; nameTable["6070"] = "Left-SLF2"; nameTable["6080"] = "Right-SLF2"; nameTable["7001"] = "Lateral-nucleus"; nameTable["7002"] = "Basolateral-nucleus"; nameTable["7003"] = "Basal-nucleus"; nameTable["7004"] = "Centromedial-nucleus"; nameTable["7005"] = "Central-nucleus"; nameTable["7006"] = "Medial-nucleus"; nameTable["7007"] = "Cortical-nucleus"; nameTable["7008"] = "Accessory-Basal-nucleus"; nameTable["7009"] = "Corticoamygdaloid-transitio"; nameTable["7010"] = "Anterior-amygdaloid-area-AAA"; nameTable["7011"] = "Fusion-amygdala-HP-FAH"; nameTable["7012"] = "Hippocampal-amygdala-transition-HATA"; nameTable["7013"] = "Endopiriform-nucleus"; nameTable["7014"] = "Lateral-nucleus-olfactory-tract"; nameTable["7015"] = "Paralaminar-nucleus"; nameTable["7016"] = "Intercalated-nucleus"; nameTable["7017"] = "Prepiriform-cortex"; nameTable["7018"] = "Periamygdaloid-cortex"; nameTable["7019"] = "Envelope-Amygdala"; nameTable["7020"] = "Extranuclear-Amydala"; nameTable["7100"] = "Brainstem-inferior-colliculus"; nameTable["7101"] = "Brainstem-cochlear-nucleus"; nameTable["8001"] = "Thalamus-Anterior"; nameTable["8002"] = "Thalamus-Ventral-anterior"; nameTable["8003"] = "Thalamus-Lateral-dorsal"; nameTable["8004"] = "Thalamus-Lateral-posterior"; nameTable["8005"] = "Thalamus-Ventral-lateral"; nameTable["8006"] = "Thalamus-Ventral-posterior-medial"; nameTable["8007"] = "Thalamus-Ventral-posterior-lateral"; nameTable["8008"] = "Thalamus-intralaminar"; nameTable["8009"] = "Thalamus-centromedian"; nameTable["8010"] = "Thalamus-mediodorsal"; nameTable["8011"] = "Thalamus-medial"; nameTable["8012"] = "Thalamus-pulvinar"; nameTable["8013"] = "Thalamus-lateral-geniculate"; nameTable["8014"] = "Thalamus-medial-geniculate"; nameTable["9000"] = "ctx-lh-prefrontal"; nameTable["9001"] = "ctx-lh-primary-motor"; nameTable["9002"] = "ctx-lh-premotor"; nameTable["9003"] = "ctx-lh-temporal"; nameTable["9004"] = "ctx-lh-posterior-parietal"; nameTable["9005"] = "ctx-lh-prim-sec-somatosensory"; nameTable["9006"] = "ctx-lh-occipital"; nameTable["9500"] = "ctx-rh-prefrontal"; nameTable["9501"] = "ctx-rh-primary-motor"; nameTable["9502"] = "ctx-rh-premotor"; nameTable["9503"] = "ctx-rh-temporal"; nameTable["9504"] = "ctx-rh-posterior-parietal"; nameTable["9505"] = "ctx-rh-prim-sec-somatosensory"; nameTable["9506"] = "ctx-rh-occipital"; nameTable["11100"] = "ctx_lh_Unknown"; nameTable["11101"] = "ctx_lh_G_and_S_frontomargin"; nameTable["11102"] = "ctx_lh_G_and_S_occipital_inf"; nameTable["11103"] = "ctx_lh_G_and_S_paracentral"; nameTable["11104"] = "ctx_lh_G_and_S_subcentral"; nameTable["11105"] = "ctx_lh_G_and_S_transv_frontopol"; nameTable["11106"] = "ctx_lh_G_and_S_cingul-Ant"; nameTable["11107"] = "ctx_lh_G_and_S_cingul-Mid-Ant"; nameTable["11108"] = "ctx_lh_G_and_S_cingul-Mid-Post"; nameTable["11109"] = "ctx_lh_G_cingul-Post-dorsal"; nameTable["11110"] = "ctx_lh_G_cingul-Post-ventral"; nameTable["11111"] = "ctx_lh_G_cuneus"; nameTable["11112"] = "ctx_lh_G_front_inf-Opercular"; nameTable["11113"] = "ctx_lh_G_front_inf-Orbital"; nameTable["11114"] = "ctx_lh_G_front_inf-Triangul"; nameTable["11115"] = "ctx_lh_G_front_middle"; nameTable["11116"] = "ctx_lh_G_front_sup"; nameTable["11117"] = "ctx_lh_G_Ins_lg_and_S_cent_ins"; nameTable["11118"] = "ctx_lh_G_insular_short"; nameTable["11119"] = "ctx_lh_G_occipital_middle"; nameTable["11120"] = "ctx_lh_G_occipital_sup"; nameTable["11121"] = "ctx_lh_G_oc-temp_lat-fusifor"; nameTable["11122"] = "ctx_lh_G_oc-temp_med-Lingual"; nameTable["11123"] = "ctx_lh_G_oc-temp_med-Parahip"; nameTable["11124"] = "ctx_lh_G_orbital"; nameTable["11125"] = "ctx_lh_G_pariet_inf-Angular"; nameTable["11126"] = "ctx_lh_G_pariet_inf-Supramar"; nameTable["11127"] = "ctx_lh_G_parietal_sup"; nameTable["11128"] = "ctx_lh_G_postcentral"; nameTable["11129"] = "ctx_lh_G_precentral"; nameTable["11130"] = "ctx_lh_G_precuneus"; nameTable["11131"] = "ctx_lh_G_rectus"; nameTable["11132"] = "ctx_lh_G_subcallosal"; nameTable["11133"] = "ctx_lh_G_temp_sup-G_T_transv"; nameTable["11134"] = "ctx_lh_G_temp_sup-Lateral"; nameTable["11135"] = "ctx_lh_G_temp_sup-Plan_polar"; nameTable["11136"] = "ctx_lh_G_temp_sup-Plan_tempo"; nameTable["11137"] = "ctx_lh_G_temporal_inf"; nameTable["11138"] = "ctx_lh_G_temporal_middle"; nameTable["11139"] = "ctx_lh_Lat_Fis-ant-Horizont"; nameTable["11140"] = "ctx_lh_Lat_Fis-ant-Vertical"; nameTable["11141"] = "ctx_lh_Lat_Fis-post"; nameTable["11142"] = "ctx_lh_Medial_wall"; nameTable["11143"] = "ctx_lh_Pole_occipital"; nameTable["11144"] = "ctx_lh_Pole_temporal"; nameTable["11145"] = "ctx_lh_S_calcarine"; nameTable["11146"] = "ctx_lh_S_central"; nameTable["11147"] = "ctx_lh_S_cingul-Marginalis"; nameTable["11148"] = "ctx_lh_S_circular_insula_ant"; nameTable["11149"] = "ctx_lh_S_circular_insula_inf"; nameTable["11150"] = "ctx_lh_S_circular_insula_sup"; nameTable["11151"] = "ctx_lh_S_collat_transv_ant"; nameTable["11152"] = "ctx_lh_S_collat_transv_post"; nameTable["11153"] = "ctx_lh_S_front_inf"; nameTable["11154"] = "ctx_lh_S_front_middle"; nameTable["11155"] = "ctx_lh_S_front_sup"; nameTable["11156"] = "ctx_lh_S_interm_prim-Jensen"; nameTable["11157"] = "ctx_lh_S_intrapariet_and_P_trans"; nameTable["11158"] = "ctx_lh_S_oc_middle_and_Lunatus"; nameTable["11159"] = "ctx_lh_S_oc_sup_and_transversal"; nameTable["11160"] = "ctx_lh_S_occipital_ant"; nameTable["11161"] = "ctx_lh_S_oc-temp_lat"; nameTable["11162"] = "ctx_lh_S_oc-temp_med_and_Lingual"; nameTable["11163"] = "ctx_lh_S_orbital_lateral"; nameTable["11164"] = "ctx_lh_S_orbital_med-olfact"; nameTable["11165"] = "ctx_lh_S_orbital-H_Shaped"; nameTable["11166"] = "ctx_lh_S_parieto_occipital"; nameTable["11167"] = "ctx_lh_S_pericallosal"; nameTable["11168"] = "ctx_lh_S_postcentral"; nameTable["11169"] = "ctx_lh_S_precentral-inf-part"; nameTable["11170"] = "ctx_lh_S_precentral-sup-part"; nameTable["11171"] = "ctx_lh_S_suborbital"; nameTable["11172"] = "ctx_lh_S_subparietal"; nameTable["11173"] = "ctx_lh_S_temporal_inf"; nameTable["11174"] = "ctx_lh_S_temporal_sup"; nameTable["11175"] = "ctx_lh_S_temporal_transverse"; nameTable["12100"] = "ctx_rh_Unknown"; nameTable["12101"] = "ctx_rh_G_and_S_frontomargin"; nameTable["12102"] = "ctx_rh_G_and_S_occipital_inf"; nameTable["12103"] = "ctx_rh_G_and_S_paracentral"; nameTable["12104"] = "ctx_rh_G_and_S_subcentral"; nameTable["12105"] = "ctx_rh_G_and_S_transv_frontopol"; nameTable["12106"] = "ctx_rh_G_and_S_cingul-Ant"; nameTable["12107"] = "ctx_rh_G_and_S_cingul-Mid-Ant"; nameTable["12108"] = "ctx_rh_G_and_S_cingul-Mid-Post"; nameTable["12109"] = "ctx_rh_G_cingul-Post-dorsal"; nameTable["12110"] = "ctx_rh_G_cingul-Post-ventral"; nameTable["12111"] = "ctx_rh_G_cuneus"; nameTable["12112"] = "ctx_rh_G_front_inf-Opercular"; nameTable["12113"] = "ctx_rh_G_front_inf-Orbital"; nameTable["12114"] = "ctx_rh_G_front_inf-Triangul"; nameTable["12115"] = "ctx_rh_G_front_middle"; nameTable["12116"] = "ctx_rh_G_front_sup"; nameTable["12117"] = "ctx_rh_G_Ins_lg_and_S_cent_ins"; nameTable["12118"] = "ctx_rh_G_insular_short"; nameTable["12119"] = "ctx_rh_G_occipital_middle"; nameTable["12120"] = "ctx_rh_G_occipital_sup"; nameTable["12121"] = "ctx_rh_G_oc-temp_lat-fusifor"; nameTable["12122"] = "ctx_rh_G_oc-temp_med-Lingual"; nameTable["12123"] = "ctx_rh_G_oc-temp_med-Parahip"; nameTable["12124"] = "ctx_rh_G_orbital"; nameTable["12125"] = "ctx_rh_G_pariet_inf-Angular"; nameTable["12126"] = "ctx_rh_G_pariet_inf-Supramar"; nameTable["12127"] = "ctx_rh_G_parietal_sup"; nameTable["12128"] = "ctx_rh_G_postcentral"; nameTable["12129"] = "ctx_rh_G_precentral"; nameTable["12130"] = "ctx_rh_G_precuneus"; nameTable["12131"] = "ctx_rh_G_rectus"; nameTable["12132"] = "ctx_rh_G_subcallosal"; nameTable["12133"] = "ctx_rh_G_temp_sup-G_T_transv"; nameTable["12134"] = "ctx_rh_G_temp_sup-Lateral"; nameTable["12135"] = "ctx_rh_G_temp_sup-Plan_polar"; nameTable["12136"] = "ctx_rh_G_temp_sup-Plan_tempo"; nameTable["12137"] = "ctx_rh_G_temporal_inf"; nameTable["12138"] = "ctx_rh_G_temporal_middle"; nameTable["12139"] = "ctx_rh_Lat_Fis-ant-Horizont"; nameTable["12140"] = "ctx_rh_Lat_Fis-ant-Vertical"; nameTable["12141"] = "ctx_rh_Lat_Fis-post"; nameTable["12142"] = "ctx_rh_Medial_wall"; nameTable["12143"] = "ctx_rh_Pole_occipital"; nameTable["12144"] = "ctx_rh_Pole_temporal"; nameTable["12145"] = "ctx_rh_S_calcarine"; nameTable["12146"] = "ctx_rh_S_central"; nameTable["12147"] = "ctx_rh_S_cingul-Marginalis"; nameTable["12148"] = "ctx_rh_S_circular_insula_ant"; nameTable["12149"] = "ctx_rh_S_circular_insula_inf"; nameTable["12150"] = "ctx_rh_S_circular_insula_sup"; nameTable["12151"] = "ctx_rh_S_collat_transv_ant"; nameTable["12152"] = "ctx_rh_S_collat_transv_post"; nameTable["12153"] = "ctx_rh_S_front_inf"; nameTable["12154"] = "ctx_rh_S_front_middle"; nameTable["12155"] = "ctx_rh_S_front_sup"; nameTable["12156"] = "ctx_rh_S_interm_prim-Jensen"; nameTable["12157"] = "ctx_rh_S_intrapariet_and_P_trans"; nameTable["12158"] = "ctx_rh_S_oc_middle_and_Lunatus"; nameTable["12159"] = "ctx_rh_S_oc_sup_and_transversal"; nameTable["12160"] = "ctx_rh_S_occipital_ant"; nameTable["12161"] = "ctx_rh_S_oc-temp_lat"; nameTable["12162"] = "ctx_rh_S_oc-temp_med_and_Lingual"; nameTable["12163"] = "ctx_rh_S_orbital_lateral"; nameTable["12164"] = "ctx_rh_S_orbital_med-olfact"; nameTable["12165"] = "ctx_rh_S_orbital-H_Shaped"; nameTable["12166"] = "ctx_rh_S_parieto_occipital"; nameTable["12167"] = "ctx_rh_S_pericallosal"; nameTable["12168"] = "ctx_rh_S_postcentral"; nameTable["12169"] = "ctx_rh_S_precentral-inf-part"; nameTable["12170"] = "ctx_rh_S_precentral-sup-part"; nameTable["12171"] = "ctx_rh_S_suborbital"; nameTable["12172"] = "ctx_rh_S_subparietal"; nameTable["12173"] = "ctx_rh_S_temporal_inf"; nameTable["12174"] = "ctx_rh_S_temporal_sup"; nameTable["12175"] = "ctx_rh_S_temporal_transverse"; nameTable["13100"] = "wm_lh_Unknown"; nameTable["13101"] = "wm_lh_G_and_S_frontomargin"; nameTable["13102"] = "wm_lh_G_and_S_occipital_inf"; nameTable["13103"] = "wm_lh_G_and_S_paracentral"; nameTable["13104"] = "wm_lh_G_and_S_subcentral"; nameTable["13105"] = "wm_lh_G_and_S_transv_frontopol"; nameTable["13106"] = "wm_lh_G_and_S_cingul-Ant"; nameTable["13107"] = "wm_lh_G_and_S_cingul-Mid-Ant"; nameTable["13108"] = "wm_lh_G_and_S_cingul-Mid-Post"; nameTable["13109"] = "wm_lh_G_cingul-Post-dorsal"; nameTable["13110"] = "wm_lh_G_cingul-Post-ventral"; nameTable["13111"] = "wm_lh_G_cuneus"; nameTable["13112"] = "wm_lh_G_front_inf-Opercular"; nameTable["13113"] = "wm_lh_G_front_inf-Orbital"; nameTable["13114"] = "wm_lh_G_front_inf-Triangul"; nameTable["13115"] = "wm_lh_G_front_middle"; nameTable["13116"] = "wm_lh_G_front_sup"; nameTable["13117"] = "wm_lh_G_Ins_lg_and_S_cent_ins"; nameTable["13118"] = "wm_lh_G_insular_short"; nameTable["13119"] = "wm_lh_G_occipital_middle"; nameTable["13120"] = "wm_lh_G_occipital_sup"; nameTable["13121"] = "wm_lh_G_oc-temp_lat-fusifor"; nameTable["13122"] = "wm_lh_G_oc-temp_med-Lingual"; nameTable["13123"] = "wm_lh_G_oc-temp_med-Parahip"; nameTable["13124"] = "wm_lh_G_orbital"; nameTable["13125"] = "wm_lh_G_pariet_inf-Angular"; nameTable["13126"] = "wm_lh_G_pariet_inf-Supramar"; nameTable["13127"] = "wm_lh_G_parietal_sup"; nameTable["13128"] = "wm_lh_G_postcentral"; nameTable["13129"] = "wm_lh_G_precentral"; nameTable["13130"] = "wm_lh_G_precuneus"; nameTable["13131"] = "wm_lh_G_rectus"; nameTable["13132"] = "wm_lh_G_subcallosal"; nameTable["13133"] = "wm_lh_G_temp_sup-G_T_transv"; nameTable["13134"] = "wm_lh_G_temp_sup-Lateral"; nameTable["13135"] = "wm_lh_G_temp_sup-Plan_polar"; nameTable["13136"] = "wm_lh_G_temp_sup-Plan_tempo"; nameTable["13137"] = "wm_lh_G_temporal_inf"; nameTable["13138"] = "wm_lh_G_temporal_middle"; nameTable["13139"] = "wm_lh_Lat_Fis-ant-Horizont"; nameTable["13140"] = "wm_lh_Lat_Fis-ant-Vertical"; nameTable["13141"] = "wm_lh_Lat_Fis-post"; nameTable["13142"] = "wm_lh_Medial_wall"; nameTable["13143"] = "wm_lh_Pole_occipital"; nameTable["13144"] = "wm_lh_Pole_temporal"; nameTable["13145"] = "wm_lh_S_calcarine"; nameTable["13146"] = "wm_lh_S_central"; nameTable["13147"] = "wm_lh_S_cingul-Marginalis"; nameTable["13148"] = "wm_lh_S_circular_insula_ant"; nameTable["13149"] = "wm_lh_S_circular_insula_inf"; nameTable["13150"] = "wm_lh_S_circular_insula_sup"; nameTable["13151"] = "wm_lh_S_collat_transv_ant"; nameTable["13152"] = "wm_lh_S_collat_transv_post"; nameTable["13153"] = "wm_lh_S_front_inf"; nameTable["13154"] = "wm_lh_S_front_middle"; nameTable["13155"] = "wm_lh_S_front_sup"; nameTable["13156"] = "wm_lh_S_interm_prim-Jensen"; nameTable["13157"] = "wm_lh_S_intrapariet_and_P_trans"; nameTable["13158"] = "wm_lh_S_oc_middle_and_Lunatus"; nameTable["13159"] = "wm_lh_S_oc_sup_and_transversal"; nameTable["13160"] = "wm_lh_S_occipital_ant"; nameTable["13161"] = "wm_lh_S_oc-temp_lat"; nameTable["13162"] = "wm_lh_S_oc-temp_med_and_Lingual"; nameTable["13163"] = "wm_lh_S_orbital_lateral"; nameTable["13164"] = "wm_lh_S_orbital_med-olfact"; nameTable["13165"] = "wm_lh_S_orbital-H_Shaped"; nameTable["13166"] = "wm_lh_S_parieto_occipital"; nameTable["13167"] = "wm_lh_S_pericallosal"; nameTable["13168"] = "wm_lh_S_postcentral"; nameTable["13169"] = "wm_lh_S_precentral-inf-part"; nameTable["13170"] = "wm_lh_S_precentral-sup-part"; nameTable["13171"] = "wm_lh_S_suborbital"; nameTable["13172"] = "wm_lh_S_subparietal"; nameTable["13173"] = "wm_lh_S_temporal_inf"; nameTable["13174"] = "wm_lh_S_temporal_sup"; nameTable["13175"] = "wm_lh_S_temporal_transverse"; nameTable["14100"] = "wm_rh_Unknown"; nameTable["14101"] = "wm_rh_G_and_S_frontomargin"; nameTable["14102"] = "wm_rh_G_and_S_occipital_inf"; nameTable["14103"] = "wm_rh_G_and_S_paracentral"; nameTable["14104"] = "wm_rh_G_and_S_subcentral"; nameTable["14105"] = "wm_rh_G_and_S_transv_frontopol"; nameTable["14106"] = "wm_rh_G_and_S_cingul-Ant"; nameTable["14107"] = "wm_rh_G_and_S_cingul-Mid-Ant"; nameTable["14108"] = "wm_rh_G_and_S_cingul-Mid-Post"; nameTable["14109"] = "wm_rh_G_cingul-Post-dorsal"; nameTable["14110"] = "wm_rh_G_cingul-Post-ventral"; nameTable["14111"] = "wm_rh_G_cuneus"; nameTable["14112"] = "wm_rh_G_front_inf-Opercular"; nameTable["14113"] = "wm_rh_G_front_inf-Orbital"; nameTable["14114"] = "wm_rh_G_front_inf-Triangul"; nameTable["14115"] = "wm_rh_G_front_middle"; nameTable["14116"] = "wm_rh_G_front_sup"; nameTable["14117"] = "wm_rh_G_Ins_lg_and_S_cent_ins"; nameTable["14118"] = "wm_rh_G_insular_short"; nameTable["14119"] = "wm_rh_G_occipital_middle"; nameTable["14120"] = "wm_rh_G_occipital_sup"; nameTable["14121"] = "wm_rh_G_oc-temp_lat-fusifor"; nameTable["14122"] = "wm_rh_G_oc-temp_med-Lingual"; nameTable["14123"] = "wm_rh_G_oc-temp_med-Parahip"; nameTable["14124"] = "wm_rh_G_orbital"; nameTable["14125"] = "wm_rh_G_pariet_inf-Angular"; nameTable["14126"] = "wm_rh_G_pariet_inf-Supramar"; nameTable["14127"] = "wm_rh_G_parietal_sup"; nameTable["14128"] = "wm_rh_G_postcentral"; nameTable["14129"] = "wm_rh_G_precentral"; nameTable["14130"] = "wm_rh_G_precuneus"; nameTable["14131"] = "wm_rh_G_rectus"; nameTable["14132"] = "wm_rh_G_subcallosal"; nameTable["14133"] = "wm_rh_G_temp_sup-G_T_transv"; nameTable["14134"] = "wm_rh_G_temp_sup-Lateral"; nameTable["14135"] = "wm_rh_G_temp_sup-Plan_polar"; nameTable["14136"] = "wm_rh_G_temp_sup-Plan_tempo"; nameTable["14137"] = "wm_rh_G_temporal_inf"; nameTable["14138"] = "wm_rh_G_temporal_middle"; nameTable["14139"] = "wm_rh_Lat_Fis-ant-Horizont"; nameTable["14140"] = "wm_rh_Lat_Fis-ant-Vertical"; nameTable["14141"] = "wm_rh_Lat_Fis-post"; nameTable["14142"] = "wm_rh_Medial_wall"; nameTable["14143"] = "wm_rh_Pole_occipital"; nameTable["14144"] = "wm_rh_Pole_temporal"; nameTable["14145"] = "wm_rh_S_calcarine"; nameTable["14146"] = "wm_rh_S_central"; nameTable["14147"] = "wm_rh_S_cingul-Marginalis"; nameTable["14148"] = "wm_rh_S_circular_insula_ant"; nameTable["14149"] = "wm_rh_S_circular_insula_inf"; nameTable["14150"] = "wm_rh_S_circular_insula_sup"; nameTable["14151"] = "wm_rh_S_collat_transv_ant"; nameTable["14152"] = "wm_rh_S_collat_transv_post"; nameTable["14153"] = "wm_rh_S_front_inf"; nameTable["14154"] = "wm_rh_S_front_middle"; nameTable["14155"] = "wm_rh_S_front_sup"; nameTable["14156"] = "wm_rh_S_interm_prim-Jensen"; nameTable["14157"] = "wm_rh_S_intrapariet_and_P_trans"; nameTable["14158"] = "wm_rh_S_oc_middle_and_Lunatus"; nameTable["14159"] = "wm_rh_S_oc_sup_and_transversal"; nameTable["14160"] = "wm_rh_S_occipital_ant"; nameTable["14161"] = "wm_rh_S_oc-temp_lat"; nameTable["14162"] = "wm_rh_S_oc-temp_med_and_Lingual"; nameTable["14163"] = "wm_rh_S_orbital_lateral"; nameTable["14164"] = "wm_rh_S_orbital_med-olfact"; nameTable["14165"] = "wm_rh_S_orbital-H_Shaped"; nameTable["14166"] = "wm_rh_S_parieto_occipital"; nameTable["14167"] = "wm_rh_S_pericallosal"; nameTable["14168"] = "wm_rh_S_postcentral"; nameTable["14169"] = "wm_rh_S_precentral-inf-part"; nameTable["14170"] = "wm_rh_S_precentral-sup-part"; nameTable["14171"] = "wm_rh_S_suborbital"; nameTable["14172"] = "wm_rh_S_subparietal"; nameTable["14173"] = "wm_rh_S_temporal_inf"; nameTable["14174"] = "wm_rh_S_temporal_sup"; nameTable["14175"] = "wm_rh_S_temporal_transverse"; return nameTable; } diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h index b943c2f054..2cbcc33d31 100644 --- a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h @@ -1,112 +1,111 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkFreeSurferParcellationTranslator_h #define mitkFreeSurferParcellationTranslator_h // MITK #include #include #include #include #include // VTK #include using namespace mitk; -using namespace std; namespace mitk { /** * @brief The mitkFreeSurferParcellationTranslator class * * This class provides a ready to use lookup table for freesurfer processed images and further functions e.g. to get the name assigned to a given label. * Additional you can assign the lookup table or transferfunction by using the AssignLookupTable(DataNode* node) or AssignTransferfunction(DataNode* node) methods. * */ class MITKCONNECTOMICS_EXPORT FreeSurferParcellationTranslator : public itk::Object { /*########### Constructors, Typedefs and Enumerations ###########*/ public: - typedef map NameTable; + typedef std::map NameTable; mitkClassMacroItkParent( FreeSurferParcellationTranslator, itk::Object ) itkNewMacro( FreeSurferParcellationTranslator ) protected: FreeSurferParcellationTranslator(); ~FreeSurferParcellationTranslator(); /*########### Methods ###########*/ public: /** * @brief Assign the lookup table to the given node * @param node the lookup table should be assigned to */ virtual void AssignLookupTable( DataNode::Pointer node ) const; /** * @brief Assign the color transfer function to the given node * @param node the transferfunction should be assigned to */ virtual void AssignTransferFunction( DataNode::Pointer node ) const; /** * @brief Get the label assigned to the given name * @param name the label should be assigned to * @return label */ - virtual const string GetLabel( const string & name ) const; + virtual const std::string GetLabel( const std::string & name ) const; /** * @brief Get the label assigned to the given name * @param name the label should be assigned to * @return label */ - virtual int GetLabelAsNumber( const string & name ) const; + virtual int GetLabelAsNumber( const std::string & name ) const; /** * @brief Return the lookup table * @return lookup table */ virtual LookupTable::Pointer GetLookupTable() const; /** * @brief Get the name assigned to the given label * @param label * @return name */ - virtual const string GetName( const string & label ) const; + virtual const std::string GetName( const std::string & label ) const; /** * @brief Get the name assigned to the given label * @param label * @return name */ - virtual const string GetName( int label ) const; + virtual const std::string GetName( int label ) const; /** * @brief Get the transfer function * @return transfer function */ virtual TransferFunction::Pointer GetTransferFunction() const; private: static LookupTable::Pointer CreateLookupTable(); static TransferFunction::Pointer CreateTransferFunction(); static NameTable CreateNameTable(); /*########### Static Members ###########*/ private: static LookupTable::Pointer m_LookupTable; static TransferFunction::Pointer m_TransferFunction; static const NameTable m_NameTable; }; } #endif // mitkFreeSurferParcellationTranslator_h diff --git a/Modules/DiffusionImaging/Connectomics/cmdapps/NetworkCreation.cpp b/Modules/DiffusionImaging/Connectomics/cmdapps/NetworkCreation.cpp index 14d0f9e7d6..ff18241008 100644 --- a/Modules/DiffusionImaging/Connectomics/cmdapps/NetworkCreation.cpp +++ b/Modules/DiffusionImaging/Connectomics/cmdapps/NetworkCreation.cpp @@ -1,135 +1,133 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // std includes #include // CTK includes #include "mitkCommandLineParser.h" // MITK includes #include "mitkConnectomicsNetworkCreator.h" #include #include -using namespace std; - int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Network Creation"); parser.setCategory("Connectomics"); parser.setDescription(""); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("fiberImage", "f", mitkCommandLineParser::InputFile, "Input image", "input fiber image (.fib)", us::Any(), false); parser.addArgument("parcellation", "p", mitkCommandLineParser::InputFile, "Parcellation image", "parcellation image", us::Any(), false); parser.addArgument("outputNetwork", "o", mitkCommandLineParser::String, "Output network", "where to save the output (.cnf)", us::Any(), false); parser.addArgument("radius", "r", mitkCommandLineParser::Int, "Radius", "Search radius in mm", 15, true); parser.addArgument("noCenterOfMass", "com", mitkCommandLineParser::Bool, "No center of mass", "Do not use center of mass for node positions"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; //default values int searchRadius( 15 ); bool noCenterOfMass( false ); // parse command line arguments std::string fiberFilename = us::any_cast(parsedArgs["fiberImage"]); std::string parcellationFilename = us::any_cast(parsedArgs["parcellation"]); std::string outputFilename = us::any_cast(parsedArgs["outputNetwork"]); if (parsedArgs.count("radius")) searchRadius = us::any_cast(parsedArgs["radius"]); if (parsedArgs.count("noCenterOfMass")) noCenterOfMass = us::any_cast(parsedArgs["noCenterOfMass"]); try { const std::string s1="", s2=""; // load fiber image std::vector fiberInfile = - mitk::IOUtil::Load( fiberFilename); + mitk::IOUtil::Load( fiberFilename); if( fiberInfile.empty() ) { std::string errorMessage = "Fiber Image at " + fiberFilename + " could not be read. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } mitk::BaseData* fiberBaseData = fiberInfile.at(0); mitk::FiberBundle* fiberBundle = dynamic_cast( fiberBaseData ); // load parcellation std::vector parcellationInFile = - mitk::IOUtil::Load( parcellationFilename); + mitk::IOUtil::Load( parcellationFilename); if( parcellationInFile.empty() ) { std::string errorMessage = "Parcellation at " + parcellationFilename + " could not be read. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } mitk::BaseData* parcellationBaseData = parcellationInFile.at(0); mitk::Image* parcellationImage = dynamic_cast( parcellationBaseData ); // do creation mitk::ConnectomicsNetworkCreator::Pointer connectomicsNetworkCreator = mitk::ConnectomicsNetworkCreator::New(); connectomicsNetworkCreator->SetSegmentation( parcellationImage ); connectomicsNetworkCreator->SetFiberBundle( fiberBundle ); if( !noCenterOfMass ) { connectomicsNetworkCreator->CalculateCenterOfMass(); } connectomicsNetworkCreator->SetEndPointSearchRadius( searchRadius ); connectomicsNetworkCreator->CreateNetworkFromFibersAndSegmentation(); mitk::ConnectomicsNetwork::Pointer network = connectomicsNetworkCreator->GetNetwork(); std::cout << "searching writer"; mitk::IOUtil::Save(network.GetPointer(), outputFilename ); return EXIT_SUCCESS; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } std::cout << "DONE"; return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/DiffusionCore/Testing/mitkImageReconstructionTest.cpp b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkImageReconstructionTest.cpp index 9bfd31d000..0925add0f9 100755 --- a/Modules/DiffusionImaging/DiffusionCore/Testing/mitkImageReconstructionTest.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkImageReconstructionTest.cpp @@ -1,157 +1,155 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include -using namespace std; - int mitkImageReconstructionTest(int argc, char* argv[]) { - MITK_TEST_BEGIN("mitkImageReconstructionTest"); + MITK_TEST_BEGIN("mitkImageReconstructionTest"); + + MITK_TEST_CONDITION_REQUIRED(argc>1,"check for input data") + + try + { + mitk::Image::Pointer dwi = dynamic_cast(mitk::IOUtil::Load(argv[1])[0].GetPointer()); - MITK_TEST_CONDITION_REQUIRED(argc>1,"check for input data") + itk::VectorImage::Pointer itkVectorImagePointer = itk::VectorImage::New(); + mitk::CastToItkImage(dwi, itkVectorImagePointer); - try + float b_value = mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi ); + mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradients = mitk::DiffusionPropertyHelper::GetGradientContainer(dwi); { - mitk::Image::Pointer dwi = dynamic_cast(mitk::IOUtil::Load(argv[1])[0].GetPointer()); - - itk::VectorImage::Pointer itkVectorImagePointer = itk::VectorImage::New(); - mitk::CastToItkImage(dwi, itkVectorImagePointer); - - float b_value = mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi ); - mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradients = mitk::DiffusionPropertyHelper::GetGradientContainer(dwi); - { - MITK_INFO << "Tensor reconstruction " << argv[2]; - mitk::TensorImage::Pointer tensorImage = dynamic_cast(mitk::IOUtil::Load(argv[2])[0].GetPointer()); - typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType; - TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); - filter->SetBValue( b_value ); - filter->SetGradientImage( gradients, itkVectorImagePointer ); - filter->Update(); - mitk::TensorImage::Pointer testImage = mitk::TensorImage::New(); - testImage->InitializeByItk( filter->GetOutput() ); - testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *tensorImage, 0.0001, true), "tensor reconstruction test."); - } - - { - MITK_INFO << "Numerical Q-ball reconstruction " << argv[3]; - mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[3])[0].GetPointer()); - typedef itk::DiffusionQballReconstructionImageFilter QballReconstructionImageFilterType; - QballReconstructionImageFilterType::Pointer filter = QballReconstructionImageFilterType::New(); - filter->SetBValue( b_value ); - filter->SetGradientImage( gradients, itkVectorImagePointer ); - filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD); - filter->Update(); - mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); - testImage->InitializeByItk( filter->GetOutput() ); - testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "Numerical Q-ball reconstruction test."); - } - - { - MITK_INFO << "Standard Q-ball reconstruction " << argv[4]; - mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[4])[0].GetPointer()); - typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; - FilterType::Pointer filter = FilterType::New(); - filter->SetBValue( b_value ); - filter->SetGradientImage( gradients, itkVectorImagePointer ); - filter->SetLambda(0.006); - filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); - filter->Update(); - mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); - testImage->InitializeByItk( filter->GetOutput() ); - testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "Standard Q-ball reconstruction test."); - } - - { - MITK_INFO << "CSA Q-ball reconstruction " << argv[5]; - mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[5])[0].GetPointer()); - typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; - FilterType::Pointer filter = FilterType::New(); - filter->SetBValue( b_value ); - filter->SetGradientImage( gradients, itkVectorImagePointer ); - filter->SetLambda(0.006); - filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); - filter->Update(); - mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); - testImage->InitializeByItk( filter->GetOutput() ); - testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "CSA Q-ball reconstruction test."); - } - - { - MITK_INFO << "ADC profile reconstruction " << argv[6]; - mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[6])[0].GetPointer()); - typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; - FilterType::Pointer filter = FilterType::New(); - filter->SetBValue( b_value ); - filter->SetGradientImage( gradients, itkVectorImagePointer ); - filter->SetLambda(0.006); - filter->SetNormalizationMethod(FilterType::QBAR_ADC_ONLY); - filter->Update(); - mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); - testImage->InitializeByItk( filter->GetOutput() ); - testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "ADC profile reconstruction test."); - } - - { - MITK_INFO << "Raw signal modeling " << argv[7]; - mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[7])[0].GetPointer()); - typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; - FilterType::Pointer filter = FilterType::New(); - filter->SetBValue( b_value ); - filter->SetGradientImage( gradients, itkVectorImagePointer ); - filter->SetLambda(0.006); - filter->SetNormalizationMethod(FilterType::QBAR_RAW_SIGNAL); - filter->Update(); - mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); - testImage->InitializeByItk( filter->GetOutput() ); - testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "Raw signal modeling test."); - } + MITK_INFO << "Tensor reconstruction " << argv[2]; + mitk::TensorImage::Pointer tensorImage = dynamic_cast(mitk::IOUtil::Load(argv[2])[0].GetPointer()); + typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType; + TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); + filter->SetBValue( b_value ); + filter->SetGradientImage( gradients, itkVectorImagePointer ); + filter->Update(); + mitk::TensorImage::Pointer testImage = mitk::TensorImage::New(); + testImage->InitializeByItk( filter->GetOutput() ); + testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *tensorImage, 0.0001, true), "tensor reconstruction test."); } - catch (itk::ExceptionObject e) + { - MITK_INFO << e; - return EXIT_FAILURE; + MITK_INFO << "Numerical Q-ball reconstruction " << argv[3]; + mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[3])[0].GetPointer()); + typedef itk::DiffusionQballReconstructionImageFilter QballReconstructionImageFilterType; + QballReconstructionImageFilterType::Pointer filter = QballReconstructionImageFilterType::New(); + filter->SetBValue( b_value ); + filter->SetGradientImage( gradients, itkVectorImagePointer ); + filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD); + filter->Update(); + mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); + testImage->InitializeByItk( filter->GetOutput() ); + testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "Numerical Q-ball reconstruction test."); } - catch (std::exception e) + { - MITK_INFO << e.what(); - return EXIT_FAILURE; + MITK_INFO << "Standard Q-ball reconstruction " << argv[4]; + mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[4])[0].GetPointer()); + typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; + FilterType::Pointer filter = FilterType::New(); + filter->SetBValue( b_value ); + filter->SetGradientImage( gradients, itkVectorImagePointer ); + filter->SetLambda(0.006); + filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); + filter->Update(); + mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); + testImage->InitializeByItk( filter->GetOutput() ); + testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "Standard Q-ball reconstruction test."); } - catch (...) + { - MITK_INFO << "ERROR!?!"; - return EXIT_FAILURE; + MITK_INFO << "CSA Q-ball reconstruction " << argv[5]; + mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[5])[0].GetPointer()); + typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; + FilterType::Pointer filter = FilterType::New(); + filter->SetBValue( b_value ); + filter->SetGradientImage( gradients, itkVectorImagePointer ); + filter->SetLambda(0.006); + filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); + filter->Update(); + mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); + testImage->InitializeByItk( filter->GetOutput() ); + testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "CSA Q-ball reconstruction test."); } - MITK_TEST_END(); + { + MITK_INFO << "ADC profile reconstruction " << argv[6]; + mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[6])[0].GetPointer()); + typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; + FilterType::Pointer filter = FilterType::New(); + filter->SetBValue( b_value ); + filter->SetGradientImage( gradients, itkVectorImagePointer ); + filter->SetLambda(0.006); + filter->SetNormalizationMethod(FilterType::QBAR_ADC_ONLY); + filter->Update(); + mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); + testImage->InitializeByItk( filter->GetOutput() ); + testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "ADC profile reconstruction test."); + } + + { + MITK_INFO << "Raw signal modeling " << argv[7]; + mitk::OdfImage::Pointer odfImage = dynamic_cast(mitk::IOUtil::Load(argv[7])[0].GetPointer()); + typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; + FilterType::Pointer filter = FilterType::New(); + filter->SetBValue( b_value ); + filter->SetGradientImage( gradients, itkVectorImagePointer ); + filter->SetLambda(0.006); + filter->SetNormalizationMethod(FilterType::QBAR_RAW_SIGNAL); + filter->Update(); + mitk::OdfImage::Pointer testImage = mitk::OdfImage::New(); + testImage->InitializeByItk( filter->GetOutput() ); + testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "Raw signal modeling test."); + } + } + catch (itk::ExceptionObject e) + { + MITK_INFO << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + MITK_INFO << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + MITK_INFO << "ERROR!?!"; + return EXIT_FAILURE; + } + + MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/DiffusionCore/cmdapps/CopyGeometry.cpp b/Modules/DiffusionImaging/DiffusionCore/cmdapps/CopyGeometry.cpp index 274be5d649..44de3cca72 100644 --- a/Modules/DiffusionImaging/DiffusionCore/cmdapps/CopyGeometry.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/cmdapps/CopyGeometry.cpp @@ -1,117 +1,114 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "mitkCommandLineParser.h" -using namespace mitk; -using namespace std; - /*! \brief Copies transformation matrix of one image to another */ int main(int argc, char* argv[]) { - mitkCommandLineParser parser; - - parser.setTitle("Copy Geometry"); - parser.setCategory("Preprocessing Tools"); - parser.setDescription("Copies transformation matrix of one image to another"); - parser.setContributor("MIC"); - - parser.setArgumentPrefix("--", "-"); - parser.addArgument("in", "i", mitkCommandLineParser::InputFile, "Input:", "input image", us::Any(), false); - parser.addArgument("ref", "r", mitkCommandLineParser::InputFile, "Reference:", "reference image", us::Any(), false); - parser.addArgument("alignCentroid", "a", mitkCommandLineParser::Bool, "align centroids", "align centroids", us::Any(), true); - parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output:", "output image", us::Any(), false); - - map parsedArgs = parser.parseArguments(argc, argv); - if (parsedArgs.size()==0) - return EXIT_FAILURE; - - // mandatory arguments - string imageName = us::any_cast(parsedArgs["in"]); - string refImage = us::any_cast(parsedArgs["ref"]); - string outImage = us::any_cast(parsedArgs["out"]); - - bool originOnly = false; - - // Show a help message - if ( parsedArgs.count("alignCentroid") || parsedArgs.count("a")) + mitkCommandLineParser parser; + + parser.setTitle("Copy Geometry"); + parser.setCategory("Preprocessing Tools"); + parser.setDescription("Copies transformation matrix of one image to another"); + parser.setContributor("MIC"); + + parser.setArgumentPrefix("--", "-"); + parser.addArgument("in", "i", mitkCommandLineParser::InputFile, "Input:", "input image", us::Any(), false); + parser.addArgument("ref", "r", mitkCommandLineParser::InputFile, "Reference:", "reference image", us::Any(), false); + parser.addArgument("alignCentroid", "a", mitkCommandLineParser::Bool, "align centroids", "align centroids", us::Any(), true); + parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output:", "output image", us::Any(), false); + + std::map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0) + return EXIT_FAILURE; + + // mandatory arguments + std::string imageName = us::any_cast(parsedArgs["in"]); + std::string refImage = us::any_cast(parsedArgs["ref"]); + std::string outImage = us::any_cast(parsedArgs["out"]); + + bool originOnly = false; + + // Show a help message + if ( parsedArgs.count("alignCentroid") || parsedArgs.count("a")) + { + originOnly = true; + } + + try + { + mitk::Image::Pointer source = dynamic_cast(mitk::IOUtil::Load(refImage)[0].GetPointer()); + mitk::Image::Pointer target = dynamic_cast(mitk::IOUtil::Load(imageName)[0].GetPointer()); + if (originOnly) { - originOnly = true; + // Calculate correction to align centroids + double c[3]; + c[0] = source->GetGeometry()->GetOrigin()[0] + + source->GetGeometry()->GetExtent(0)/2.0 + - target->GetGeometry()->GetOrigin()[0] + - target->GetGeometry()->GetExtent(0)/2.0; + + c[1] = source->GetGeometry()->GetOrigin()[1] + + source->GetGeometry()->GetExtent(1)/2.0 + - target->GetGeometry()->GetOrigin()[1] + - target->GetGeometry()->GetExtent(1)/2.0; + + + c[2] = source->GetGeometry()->GetOrigin()[2] + + source->GetGeometry()->GetExtent(2)/2.0 + - target->GetGeometry()->GetOrigin()[2] + - target->GetGeometry()->GetExtent(2)/2.0; + + double newOrigin[3]; + newOrigin[0] = target->GetGeometry()->GetOrigin()[0] +c[0]; + newOrigin[1] = target->GetGeometry()->GetOrigin()[1] +c[1]; + newOrigin[2] = target->GetGeometry()->GetOrigin()[2] +c[2]; + + target->GetGeometry()->SetOrigin(newOrigin); } - - try + else { - Image::Pointer source = dynamic_cast(mitk::IOUtil::Load(refImage)[0].GetPointer()); - Image::Pointer target = dynamic_cast(mitk::IOUtil::Load(imageName)[0].GetPointer()); - if (originOnly) - { - // Calculate correction to align centroids - double c[3]; - c[0] = source->GetGeometry()->GetOrigin()[0] - + source->GetGeometry()->GetExtent(0)/2.0 - - target->GetGeometry()->GetOrigin()[0] - - target->GetGeometry()->GetExtent(0)/2.0; - - c[1] = source->GetGeometry()->GetOrigin()[1] - + source->GetGeometry()->GetExtent(1)/2.0 - - target->GetGeometry()->GetOrigin()[1] - - target->GetGeometry()->GetExtent(1)/2.0; - - - c[2] = source->GetGeometry()->GetOrigin()[2] - + source->GetGeometry()->GetExtent(2)/2.0 - - target->GetGeometry()->GetOrigin()[2] - - target->GetGeometry()->GetExtent(2)/2.0; - - double newOrigin[3]; - newOrigin[0] = target->GetGeometry()->GetOrigin()[0] +c[0]; - newOrigin[1] = target->GetGeometry()->GetOrigin()[1] +c[1]; - newOrigin[2] = target->GetGeometry()->GetOrigin()[2] +c[2]; - - target->GetGeometry()->SetOrigin(newOrigin); - } - else - { - mitk::BaseGeometry* s_geom = source->GetGeometry(); - mitk::BaseGeometry* t_geom = target->GetGeometry(); - - t_geom->SetIndexToWorldTransform(s_geom->GetIndexToWorldTransform()); - target->SetGeometry(t_geom); - } - mitk::IOUtil::Save(target, outImage); - } - 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; + mitk::BaseGeometry* s_geom = source->GetGeometry(); + mitk::BaseGeometry* t_geom = target->GetGeometry(); + + t_geom->SetIndexToWorldTransform(s_geom->GetIndexToWorldTransform()); + target->SetGeometry(t_geom); } - return EXIT_SUCCESS; + mitk::IOUtil::Save(target, outImage); + } + catch (itk::ExceptionObject e) + { + std::cout << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + std::cout << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + std::cout << "ERROR!?!"; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/DiffusionCore/cmdapps/Dicom2Nrrd.cpp b/Modules/DiffusionImaging/DiffusionCore/cmdapps/Dicom2Nrrd.cpp index 53a5ecbf44..663d519a82 100644 --- a/Modules/DiffusionImaging/DiffusionCore/cmdapps/Dicom2Nrrd.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/cmdapps/Dicom2Nrrd.cpp @@ -1,88 +1,86 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDicomSeriesReader.h" #include "mitkProperties.h" #include "mitkCommandLineParser.h" #include "mitkIOUtil.h" -using namespace std; - int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Dicom Loader"); parser.setCategory("Preprocessing Tools"); parser.setDescription(""); parser.setContributor("MIC"); parser.setArgumentPrefix("--","-"); // Add command line argument names parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.addArgument("input", "i", mitkCommandLineParser::InputDirectory, "Input folder:", "Input folder",us::Any(),false); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output file:", "Output file",us::Any(),false); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // Show a help message if ( parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } - std::string inputFolder = us::any_cast(parsedArgs["input"]); - std::string outFileName = us::any_cast(parsedArgs["output"]); + std::string inputFolder = us::any_cast(parsedArgs["input"]); + std::string outFileName = us::any_cast(parsedArgs["output"]); //check if DICOMTags have been set as property for mitk::Image mitk::DicomSeriesReader::FileNamesGrouping seriesInFiles = mitk::DicomSeriesReader::GetSeries( inputFolder, true ); std::list images; std::map fileMap; // TODO sort series UIDs, implementation of map iterator might differ on different platforms (or verify this is a standard topic??) for (mitk::DicomSeriesReader::FileNamesGrouping::const_iterator seriesIter = seriesInFiles.begin(); seriesIter != seriesInFiles.end(); ++seriesIter) { mitk::DicomSeriesReader::StringContainer files = seriesIter->second.GetFilenames(); mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries( files ); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); images.push_back( image ); fileMap.insert( std::pair(image,files)); } } // WARN: EXPECT ONLY ONE ITEM PER FOLDER for ( std::list::const_iterator imageIter = images.begin(); imageIter != images.end(); ++imageIter ) { const mitk::Image::Pointer image = *imageIter; mitk::IOUtil::Save(image,outFileName); } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/DiffusionCore/cmdapps/DiffusionDICOMLoader.cpp b/Modules/DiffusionImaging/DiffusionCore/cmdapps/DiffusionDICOMLoader.cpp index c9fae223b2..093a846f29 100644 --- a/Modules/DiffusionImaging/DiffusionCore/cmdapps/DiffusionDICOMLoader.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/cmdapps/DiffusionDICOMLoader.cpp @@ -1,318 +1,317 @@ /*=================================================================== 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 "mitkImage.h" #include "mitkBaseData.h" #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include "mitkDiffusionDICOMFileReader.h" #include "mitkSortByImagePositionPatient.h" #include "mitkDICOMTagBasedSorter.h" #include "mitkDICOMSortByTag.h" #include "itkMergeDiffusionImagesFilter.h" #include -using namespace std; - static mitk::StringList& GetInputFilenames() { static mitk::StringList inputs; return inputs; } // FIXME slash at the end void SetInputFileNames( std::string input_directory ) { // I. Get all files in directory itksys::Directory input; input.Load( input_directory.c_str() ); // II. Push back files mitk::StringList inputlist;//, mergedlist; for( unsigned long idx=0; idxAddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0010) ); // Number of Rows tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0011) ); // Number of Columns tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0030) ); // Pixel Spacing tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x1164) ); // Imager Pixel Spacing tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0037) ); // Image Orientation (Patient) // TODO add tolerance parameter (l. 1572 of original code) // TODO handle as real vectors! cluster with configurable errors! tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x000e) ); // Series Instance UID tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x0050) ); // Slice Thickness tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0008) ); // Number of Frames //tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0052) ); // Frame of Reference UID // gdcmReader->AddSortingElement( tagSorter ); //mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader ); mitk::DICOMSortCriterion::ConstPointer sorting = mitk::SortByImagePositionPatient::New( // Image Position (Patient) //mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0013), // instance number mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0012), // aqcuisition number mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0032), // aqcuisition time mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0018, 0x1060), // trigger time mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0018) // SOP instance UID (last resort, not really meaningful but decides clearly) ).GetPointer() ).GetPointer() ).GetPointer() ).GetPointer() // ).GetPointer() ).GetPointer(); tagSorter->SetSortCriterion( sorting ); // mosaic //gdcmReader->SetResolveMosaic( this->m_Controls->m_SplitMosaicCheckBox->isChecked() ); gdcmReader->AddSortingElement( tagSorter );*/ gdcmReader->SetInputFiles( input_files ); try { gdcmReader->AnalyzeInputFiles(); } catch( const itk::ExceptionObject &e) { MITK_ERROR << "Failed to analyze data. " << e.what(); } catch( const std::exception &se) { MITK_ERROR << "Std Exception " << se.what(); } gdcmReader->LoadImages(); mitk::Image::Pointer loaded_image = gdcmReader->GetOutput(0).GetMitkImage(); return loaded_image; } typedef short DiffusionPixelType; typedef itk::VectorImage DwiImageType; typedef DwiImageType::PixelType DwiPixelType; typedef DwiImageType::RegionType DwiRegionType; typedef std::vector< DwiImageType::Pointer > DwiImageContainerType; typedef mitk::Image DiffusionImageType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientContainerType; typedef std::vector< GradientContainerType::Pointer > GradientListContainerType; void SearchForInputInSubdirs( std::string root_directory, std::string subdir_prefix , std::vector& output_container) { // I. Get all dirs in directory itksys::Directory rootdir; rootdir.Load( root_directory.c_str() ); MITK_INFO("dicom.loader.setinputdirs.start") << "Prefix = " << subdir_prefix; for( unsigned int idx=0; idx parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) { return EXIT_FAILURE; } std::string inputDirectory = us::any_cast( parsedArgs["inputdir"] ); MITK_INFO << "Loading data from directory: " << inputDirectory; // retrieve the prefix flag (if set) bool search_for_subdirs = false; std::string subdir_prefix; if( parsedArgs.count("dwprefix")) { subdir_prefix = us::any_cast( parsedArgs["dwprefix"] ); if (subdir_prefix != "") { MITK_INFO << "Prefix specified, will search for subdirs in the input directory!"; search_for_subdirs = true; } } // retrieve the output std::string outputFile = us::any_cast< std::string >( parsedArgs["output"] ); // if the executable is called with a single directory, just parse the given folder for files and read them into a diffusion image if( !search_for_subdirs ) { SetInputFileNames( inputDirectory ); MITK_INFO << "Got " << GetInputFilenames().size() << " input files."; mitk::Image::Pointer d_img = ReadInDICOMFiles( GetInputFilenames(), outputFile ); try { mitk::IOUtil::Save(d_img, outputFile.c_str()); } catch( const itk::ExceptionObject& e) { MITK_ERROR << "Failed to write out the output file. \n\t Reason : ITK Exception " << e.what(); } } // if the --dwprefix flag is set, then we have to look for the directories, load each of them separately and afterwards merge the images else { std::vector output_container; SearchForInputInSubdirs( inputDirectory, subdir_prefix, output_container ); // final output image mitk::Image::Pointer image = mitk::Image::New(); if( output_container.size() > 1 ) { DwiImageContainerType imageContainer; GradientListContainerType gradientListContainer; std::vector< double > bValueContainer; for ( std::vector< mitk::Image::Pointer >::iterator dwi = output_container.begin(); dwi != output_container.end(); ++dwi ) { mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(*dwi, itkVectorImagePointer); imageContainer.push_back(itkVectorImagePointer); gradientListContainer.push_back( mitk::DiffusionPropertyHelper::GetGradientContainer(*dwi)); bValueContainer.push_back( mitk::DiffusionPropertyHelper::GetReferenceBValue(*dwi)); } typedef itk::MergeDiffusionImagesFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetImageVolumes(imageContainer); filter->SetGradientLists(gradientListContainer); filter->SetBValues(bValueContainer); filter->Update(); vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity(); image = mitk::GrabItkImageMemory( filter->GetOutput() ); image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetOutputGradients() ) ); image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetB_Value() ) ); image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); } // just output the image if there was only one folder found else { image = output_container.at(0); } MITK_INFO("dicom.import.writeout") << " [OutputFile] " << outputFile.c_str(); try { mitk::IOUtil::Save(image, outputFile.c_str()); } catch( const itk::ExceptionObject& e) { MITK_ERROR << "Failed to write out the output file. \n\t Reason : ITK Exception " << e.what(); } } return 1; } + diff --git a/Modules/DiffusionImaging/DiffusionCore/cmdapps/DwiDenoising.cpp b/Modules/DiffusionImaging/DiffusionCore/cmdapps/DwiDenoising.cpp index c63a897da3..6e6234be05 100644 --- a/Modules/DiffusionImaging/DiffusionCore/cmdapps/DwiDenoising.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/cmdapps/DwiDenoising.cpp @@ -1,139 +1,137 @@ /*=================================================================== 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 "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #include -using namespace std; - typedef mitk::Image DiffusionImageType; typedef itk::Image ImageType; /** * Denoises DWI using the Nonlocal - Means algorithm */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("DWI Denoising"); parser.setCategory("Preprocessing Tools"); parser.setContributor("MIC"); parser.setDescription("Denoising for diffusion weighted images using a non-local means algorithm."); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input image (DWI)", us::Any(), false); parser.addArgument("variance", "v", mitkCommandLineParser::Float, "Variance:", "noise variance", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask:", "brainmask for input image", us::Any(), true); parser.addArgument("search", "s", mitkCommandLineParser::Int, "Search radius:", "search radius", us::Any(), true); parser.addArgument("compare", "c", mitkCommandLineParser::Int, "Comparison radius:", "comparison radius", us::Any(), true); parser.addArgument("joint", "j", mitkCommandLineParser::Bool, "Joint information:", "use joint information"); parser.addArgument("rician", "r", mitkCommandLineParser::Bool, "Rician adaption:", "use rician adaption"); parser.changeParameterGroup("Output", "Output of this miniapp"); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output:", "output image (DWI)", us::Any(), false); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; - string inFileName = us::any_cast(parsedArgs["input"]); + std::string inFileName = us::any_cast(parsedArgs["input"]); double variance = static_cast(us::any_cast(parsedArgs["variance"])); - string maskName; + std::string maskName; if (parsedArgs.count("mask")) - maskName = us::any_cast(parsedArgs["mask"]); - string outFileName = us::any_cast(parsedArgs["output"]); + maskName = us::any_cast(parsedArgs["mask"]); + std::string outFileName = us::any_cast(parsedArgs["output"]); // boost::algorithm::erase_all(outFileName, ".dwi"); int search = 4; if (parsedArgs.count("search")) search = us::any_cast(parsedArgs["search"]); int compare = 1; if (parsedArgs.count("compare")) compare = us::any_cast(parsedArgs["compare"]); bool joint = false; if (parsedArgs.count("joint")) joint = true; bool rician = false; if (parsedArgs.count("rician")) rician = true; try { mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {}); DiffusionImageType::Pointer dwi = dynamic_cast(mitk::IOUtil::LoadImage(inFileName, &functor).GetPointer()); mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); itk::NonLocalMeansDenoisingFilter::Pointer filter = itk::NonLocalMeansDenoisingFilter::New(); filter->SetNumberOfThreads(12); filter->SetInputImage( itkVectorImagePointer ); if (!maskName.empty()) { mitk::Image::Pointer mask = dynamic_cast(mitk::IOUtil::Load(maskName)[0].GetPointer()); ImageType::Pointer itkMask = ImageType::New(); mitk::CastToItkImage(mask, itkMask); filter->SetInputMask(itkMask); } filter->SetUseJointInformation(joint); filter->SetUseRicianAdaption(rician); filter->SetSearchRadius(search); filter->SetComparisonRadius(compare); filter->SetVariance(variance); filter->Update(); DiffusionImageType::Pointer output = mitk::GrabItkImageMemory( filter->GetOutput() ); output->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi) ) ); output->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi) ) ); mitk::DiffusionPropertyHelper propertyHelper( output ); propertyHelper.InitializeImage(); // std::stringstream name; // name << outFileName << "_NLM_" << search << "-" << compare << "-" << variance << ".dwi"; mitk::IOUtil::Save(output, outFileName.c_str()); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/DiffusionCore/cmdapps/ExportShImage.cpp b/Modules/DiffusionImaging/DiffusionCore/cmdapps/ExportShImage.cpp index 79424657ff..87b5c5185c 100644 --- a/Modules/DiffusionImaging/DiffusionCore/cmdapps/ExportShImage.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/cmdapps/ExportShImage.cpp @@ -1,139 +1,137 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -using namespace std; - /*! \brief Convert MITK spherical harmonics image type to MRtrix spherical harmonics image */ template int StartShConversion(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Export SH Image"); parser.setCategory("Preprocessing Tools"); parser.setDescription("Convert MITK spherical harmonics image type to MRtrix spherical harmonics image"); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "MITK SH image", us::Any(), false); parser.addArgument("output", "o", mitkCommandLineParser::InputFile, "Output", "MRtrix SH image", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "SH order:", "spherical harmonics order"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; - string inFile = us::any_cast(parsedArgs["input"]); - string outFile = us::any_cast(parsedArgs["output"]); + std::string inFile = us::any_cast(parsedArgs["input"]); + std::string outFile = us::any_cast(parsedArgs["output"]); try { typedef itk::Image< float, 4 > OutImageType; typedef itk::Image< itk::Vector< float, (shOrder*shOrder + shOrder + 2)/2 + shOrder >, 3 > InputImageType; typename InputImageType::Pointer itkInImage = InputImageType::New(); typedef itk::ImageFileReader< InputImageType > ReaderType; typename ReaderType::Pointer reader = ReaderType::New(); std::cout << "reading " << inFile; reader->SetFileName(inFile.c_str()); reader->Update(); itkInImage = reader->GetOutput(); // extract directions from fiber bundle typename itk::ShCoefficientImageExporter::Pointer filter = itk::ShCoefficientImageExporter::New(); filter->SetInputImage(itkInImage); filter->GenerateData(); OutImageType::Pointer outImage = filter->GetOutputImage(); mitk::Image::Pointer image = mitk::GrabItkImageMemory(outImage.GetPointer()); mitk::IOUtil::Save(image, outFile ); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input image", "MITK SH image", us::Any(), false); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output image", "MRtrix SH image", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "Spherical harmonics order", "spherical harmonics order"); parser.setCategory("Preprocessing Tools"); parser.setTitle("Export SH Image"); parser.setDescription(" "); parser.setContributor("MIC"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; int shOrder = -1; if (parsedArgs.count("shOrder")) shOrder = us::any_cast(parsedArgs["shOrder"]); switch (shOrder) { case 4: return StartShConversion<4>(argc, argv); case 6: return StartShConversion<6>(argc, argv); case 8: return StartShConversion<8>(argc, argv); case 10: return StartShConversion<10>(argc, argv); case 12: return StartShConversion<12>(argc, argv); } return EXIT_FAILURE; } diff --git a/Modules/DiffusionImaging/DiffusionCore/cmdapps/ImageResampler.cpp b/Modules/DiffusionImaging/DiffusionCore/cmdapps/ImageResampler.cpp index bedcbce6ad..5784d3389a 100644 --- a/Modules/DiffusionImaging/DiffusionCore/cmdapps/ImageResampler.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/cmdapps/ImageResampler.cpp @@ -1,423 +1,420 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include // ITK #include #include #include "itkLinearInterpolateImageFunction.h" #include "itkWindowedSincInterpolateImageFunction.h" #include "itkNearestNeighborInterpolateImageFunction.h" #include "itkIdentityTransform.h" #include "itkResampleImageFilter.h" #include "itkResampleDwiImageFilter.h" -using namespace std; - typedef itk::Image InputImageType; typedef itk::Image BinaryImageType; - static mitk::Image::Pointer TransformToReference(mitk::Image *reference, mitk::Image *moving, bool sincInterpol = false, bool nn = false) { // Convert to itk Images // Identify Transform typedef itk::IdentityTransform T_Transform; T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 3> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typedef itk::LinearInterpolateImageFunction< InputImageType> LinearInterpolateImageFunctionType; LinearInterpolateImageFunctionType::Pointer lin_interpolator = LinearInterpolateImageFunctionType::New(); typedef itk::NearestNeighborInterpolateImageFunction< BinaryImageType> NearestNeighborInterpolateImageFunctionType; NearestNeighborInterpolateImageFunctionType::Pointer nn_interpolator = NearestNeighborInterpolateImageFunctionType::New(); if (!nn) { InputImageType::Pointer itkReference = InputImageType::New(); InputImageType::Pointer itkMoving = InputImageType::New(); mitk::CastToItkImage(reference,itkReference); mitk::CastToItkImage(moving,itkMoving); typedef itk::ResampleImageFilter ResampleFilterType; ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(itkMoving); resampler->SetReferenceImage( itkReference ); resampler->UseReferenceImageOn(); resampler->SetTransform(_pTransform); if ( sincInterpol) resampler->SetInterpolator(sinc_interpolator); else resampler->SetInterpolator(lin_interpolator); resampler->Update(); // Convert back to mitk mitk::Image::Pointer result = mitk::Image::New(); result->InitializeByItk(resampler->GetOutput()); GrabItkImageMemory( resampler->GetOutput() , result ); return result; } BinaryImageType::Pointer itkReference = BinaryImageType::New(); BinaryImageType::Pointer itkMoving = BinaryImageType::New(); mitk::CastToItkImage(reference,itkReference); mitk::CastToItkImage(moving,itkMoving); typedef itk::ResampleImageFilter ResampleFilterType; ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(itkMoving); resampler->SetReferenceImage( itkReference ); resampler->UseReferenceImageOn(); resampler->SetTransform(_pTransform); resampler->SetInterpolator(nn_interpolator); resampler->Update(); // Convert back to mitk mitk::Image::Pointer result = mitk::Image::New(); result->InitializeByItk(resampler->GetOutput()); GrabItkImageMemory( resampler->GetOutput() , result ); return result; } static std::vector &split(const std::string &s, char delim, std::vector &elems) { std::stringstream ss(s); std::string item; while (std::getline(ss, item, delim)) { elems.push_back(item); } return elems; } static std::vector split(const std::string &s, char delim) { std::vector < std::string > elems; return split(s, delim, elems); } static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing, bool useLinInt = true, bool useNN = false) { if (!useNN) { InputImageType::Pointer itkImage = InputImageType::New(); CastToItkImage(input,itkImage); /** * 1) Resampling * */ // Identity transform. // We don't want any transform on our image except rescaling which is not // specified by a transform but by the input/output spacing as we will see // later. // So no transform will be specified. typedef itk::IdentityTransform T_Transform; // The resampler type itself. typedef itk::ResampleImageFilter T_ResampleFilter; // Prepare the resampler. // Instantiate the transform and specify it should be the id transform. T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); // Instantiate the resampler. Wire in the transform and the interpolator. T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New(); // Specify the input. _pResizeFilter->SetInput(itkImage); _pResizeFilter->SetTransform(_pTransform); // Set the output origin. _pResizeFilter->SetOutputOrigin(itkImage->GetOrigin()); // Compute the size of the output. // The size (# of pixels) in the output is recomputed using // the ratio of the input and output sizes. InputImageType::SpacingType inputSpacing = itkImage->GetSpacing(); InputImageType::SpacingType outputSpacing; const InputImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion(); InputImageType::SizeType outputSize; typedef InputImageType::SizeType::SizeValueType SizeValueType; // Set the output spacing. outputSpacing[0] = spacing[0]; outputSpacing[1] = spacing[1]; outputSpacing[2] = spacing[2]; outputSize[0] = static_cast(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5); outputSize[1] = static_cast(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5); outputSize[2] = static_cast(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5); _pResizeFilter->SetOutputSpacing(outputSpacing); _pResizeFilter->SetSize(outputSize); typedef itk::LinearInterpolateImageFunction< InputImageType > LinearInterpolatorType; LinearInterpolatorType::Pointer lin_interpolator = LinearInterpolatorType::New(); typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 4> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); if (useLinInt) _pResizeFilter->SetInterpolator(lin_interpolator); else _pResizeFilter->SetInterpolator(sinc_interpolator); _pResizeFilter->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(_pResizeFilter->GetOutput()); mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image); return image; } BinaryImageType::Pointer itkImage = BinaryImageType::New(); CastToItkImage(input,itkImage); /** * 1) Resampling * */ // Identity transform. // We don't want any transform on our image except rescaling which is not // specified by a transform but by the input/output spacing as we will see // later. // So no transform will be specified. typedef itk::IdentityTransform T_Transform; // The resampler type itself. typedef itk::ResampleImageFilter T_ResampleFilter; // Prepare the resampler. // Instantiate the transform and specify it should be the id transform. T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); // Instantiate the resampler. Wire in the transform and the interpolator. T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New(); // Specify the input. _pResizeFilter->SetInput(itkImage); _pResizeFilter->SetTransform(_pTransform); // Set the output origin. _pResizeFilter->SetOutputOrigin(itkImage->GetOrigin()); // Compute the size of the output. // The size (# of pixels) in the output is recomputed using // the ratio of the input and output sizes. BinaryImageType::SpacingType inputSpacing = itkImage->GetSpacing(); BinaryImageType::SpacingType outputSpacing; const BinaryImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion(); BinaryImageType::SizeType outputSize; typedef BinaryImageType::SizeType::SizeValueType SizeValueType; // Set the output spacing. outputSpacing[0] = spacing[0]; outputSpacing[1] = spacing[1]; outputSpacing[2] = spacing[2]; outputSize[0] = static_cast(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5); outputSize[1] = static_cast(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5); outputSize[2] = static_cast(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5); _pResizeFilter->SetOutputSpacing(outputSpacing); _pResizeFilter->SetSize(outputSize); typedef itk::NearestNeighborInterpolateImageFunction< BinaryImageType> NearestNeighborInterpolateImageType; NearestNeighborInterpolateImageType::Pointer nn_interpolator = NearestNeighborInterpolateImageType::New(); _pResizeFilter->SetInterpolator(nn_interpolator); _pResizeFilter->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(_pResizeFilter->GetOutput()); mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image); return image; } static mitk::Image::Pointer ResampleDWIbySpacing(mitk::Image::Pointer input, float* spacing) { itk::Vector spacingVector; spacingVector[0] = spacing[0]; spacingVector[1] = spacing[1]; spacingVector[2] = spacing[2]; typedef itk::ResampleDwiImageFilter ResampleFilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(input, itkVectorImagePointer); ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput( itkVectorImagePointer ); resampler->SetInterpolation(ResampleFilterType::Interpolate_Linear); resampler->SetNewSpacing(spacingVector); resampler->Update(); mitk::Image::Pointer output = mitk::GrabItkImageMemory( resampler->GetOutput() ); output->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer(input) ) ); output->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( mitk::DiffusionPropertyHelper::GetReferenceBValue(input) ) ); mitk::DiffusionPropertyHelper propertyHelper( output ); propertyHelper.InitializeImage(); return output; } int main( int argc, char* argv[] ) { mitkCommandLineParser parser; parser.setArgumentPrefix("--","-"); parser.setTitle("Image Resampler"); parser.setCategory("Preprocessing Tools"); parser.setContributor("MIC"); parser.setDescription("Resample an image to eigther a specific spacing or to a reference image."); // Add command line argument names parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Show this help text"); parser.addArgument("input", "i", mitkCommandLineParser::InputImage, "Input:", "Input file",us::Any(),false); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output:", "Output file",us::Any(),false); parser.addArgument("spacing", "s", mitkCommandLineParser::String, "Spacing:", "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any()); parser.addArgument("reference", "r", mitkCommandLineParser::InputImage, "Reference:", "Resample using supplied reference image. Also cuts image to same dimensions",us::Any()); parser.addArgument("win-sinc", "w", mitkCommandLineParser::Bool, "Windowed-sinc interpolation:", "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any()); parser.addArgument("nearest-neigh", "n", mitkCommandLineParser::Bool, "Nearest Neighbor:", "Use Nearest Neighbor interpolation instead of linear interpolation ",us::Any()); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); // Handle special arguments bool useSpacing = false; bool useLinearInterpol = true; bool useNN= false; { if (parsedArgs.size() == 0) { return EXIT_FAILURE; } if (parsedArgs.count("sinc-int")) useLinearInterpol = false; if (parsedArgs.count("nearest-neigh")) useNN = true; // Show a help message if ( parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } } - std::string outputFile = us::any_cast(parsedArgs["output"]); - std::string inputFile = us::any_cast(parsedArgs["input"]); + std::string outputFile = us::any_cast(parsedArgs["output"]); + std::string inputFile = us::any_cast(parsedArgs["input"]); std::vector spacings; float spacing[] = { 0.0f, 0.0f, 0.0f }; if (parsedArgs.count("spacing")) { - std::string arg = us::any_cast(parsedArgs["spacing"]); + std::string arg = us::any_cast(parsedArgs["spacing"]); if (arg != "") { spacings = split(arg ,','); spacing[0] = atoi(spacings.at(0).c_str()); spacing[1] = atoi(spacings.at(1).c_str()); spacing[2] = atoi(spacings.at(2).c_str()); useSpacing = true; } } std::string refImageFile = ""; if (parsedArgs.count("reference")) { - refImageFile = us::any_cast(parsedArgs["reference"]); + refImageFile = us::any_cast(parsedArgs["reference"]); } if (refImageFile =="" && useSpacing == false) { MITK_ERROR << "No information how to resample is supplied. Use eigther --spacing or --reference !"; return EXIT_FAILURE; } mitk::Image::Pointer refImage; if (!useSpacing) refImage = dynamic_cast(mitk::IOUtil::Load(refImageFile)[0].GetPointer()); mitk::Image::Pointer inputDWI = dynamic_cast(mitk::IOUtil::Load(inputFile)[0].GetPointer()); if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(inputDWI.GetPointer())) { mitk::Image::Pointer outputImage; if (useSpacing) outputImage = ResampleDWIbySpacing(inputDWI, spacing); else { MITK_WARN << "Not supported yet, to resample a DWI please set a new spacing."; return EXIT_FAILURE; } mitk::IOUtil::Save(outputImage, outputFile.c_str()); return EXIT_SUCCESS; } mitk::Image::Pointer inputImage = dynamic_cast(mitk::IOUtil::Load(inputFile)[0].GetPointer()); mitk::Image::Pointer resultImage; if (useSpacing) resultImage = ResampleBySpacing(inputImage,spacing,useLinearInterpol,useNN); else resultImage = TransformToReference(refImage,inputImage,useLinearInterpol,useNN); mitk::IOUtil::Save(resultImage, outputFile); return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/DiffusionCore/cmdapps/Registration.cpp b/Modules/DiffusionImaging/DiffusionCore/cmdapps/Registration.cpp index 1bdf9d1ee2..b4f2c2d26f 100644 --- a/Modules/DiffusionImaging/DiffusionCore/cmdapps/Registration.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/cmdapps/Registration.cpp @@ -1,448 +1,446 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // CTK #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include // ITK #include #include #include "itkLinearInterpolateImageFunction.h" #include "itkWindowedSincInterpolateImageFunction.h" #include "itkIdentityTransform.h" #include "itkResampleImageFilter.h" #include "itkNrrdImageIO.h" -using namespace std; - typedef std::vector FileListType; typedef itk::Image InputImageType; static mitk::Image::Pointer ExtractFirstTS(mitk::Image* image, std::string fileType) { if (fileType == ".dwi") return image; mitk::ImageTimeSelector::Pointer selector = mitk::ImageTimeSelector::New(); selector->SetInput(image); selector->SetTimeNr(0); selector->UpdateLargestPossibleRegion(); mitk::Image::Pointer img =selector->GetOutput()->Clone(); return img; } static std::vector &split(const std::string &s, char delim, std::vector &elems) { std::stringstream ss(s); std::string item; while (std::getline(ss, item, delim)) { elems.push_back(item); } return elems; } static std::vector split(const std::string &s, char delim) { std::vector < std::string > elems; return split(s, delim, elems); } /// Create list of all files in provided folder ending with same postfix static FileListType CreateFileList(std::string folder , std::string postfix) { itk::Directory::Pointer dir = itk::Directory::New(); FileListType fileList; if( dir->Load(folder.c_str() ) ) { int n = dir->GetNumberOfFiles(); for(int r=0;rGetFile( r ); if (filename == "." || filename == "..") continue; filename = folder + filename; if (!itksys::SystemTools::FileExists( filename.c_str())) continue; if (filename.length() <= postfix.length() ) continue; if (filename.substr(filename.length() -postfix.length() ) == postfix) fileList.push_back(filename); } } return fileList; } static std::string GetSavePath(std::string outputFolder, std::string fileName) { std::string fileType = itksys::SystemTools::GetFilenameExtension(fileName); std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(fileName); std::string savePathAndFileName = outputFolder +fileStem + fileType; return savePathAndFileName; } static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing) { InputImageType::Pointer itkImage = InputImageType::New(); CastToItkImage(input,itkImage); /** * 1) Resampling * */ // Identity transform. // We don't want any transform on our image except rescaling which is not // specified by a transform but by the input/output spacing as we will see // later. // So no transform will be specified. typedef itk::IdentityTransform T_Transform; // The resampler type itself. typedef itk::ResampleImageFilter T_ResampleFilter; // Prepare the resampler. // Instantiate the transform and specify it should be the id transform. T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); // Instantiate the resampler. Wire in the transform and the interpolator. T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New(); _pResizeFilter->SetTransform(_pTransform); // Set the output origin. _pResizeFilter->SetOutputOrigin(itkImage->GetOrigin()); // Compute the size of the output. // The size (# of pixels) in the output is recomputed using // the ratio of the input and output sizes. InputImageType::SpacingType inputSpacing = itkImage->GetSpacing(); InputImageType::SpacingType outputSpacing; const InputImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion(); InputImageType::SizeType outputSize; typedef InputImageType::SizeType::SizeValueType SizeValueType; // Set the output spacing. outputSpacing[0] = spacing[0]; outputSpacing[1] = spacing[1]; outputSpacing[2] = spacing[2]; outputSize[0] = static_cast(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5); outputSize[1] = static_cast(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5); outputSize[2] = static_cast(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5); _pResizeFilter->SetOutputSpacing(outputSpacing); _pResizeFilter->SetSize(outputSize); typedef itk::Function::WelchWindowFunction<4> WelchWindowFunction; typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 4,WelchWindowFunction> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); _pResizeFilter->SetInterpolator(sinc_interpolator); // Specify the input. _pResizeFilter->SetInput(itkImage); _pResizeFilter->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(_pResizeFilter->GetOutput()); mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image); return image; } /// Build a derived file name from moving images e.g. xxx_T2.nrrd becomes xxx_GTV.nrrd static FileListType CreateDerivedFileList(std::string baseFN, std::string baseSuffix, std::vector derivedPatterns) { FileListType files; for (unsigned int i=0; i < derivedPatterns.size(); i++) { std::string derResourceSuffix = derivedPatterns.at(i); std::string derivedResourceFilename = baseFN.substr(0,baseFN.length() -baseSuffix.length()) + derResourceSuffix; MITK_INFO <<" Looking for file: " << derivedResourceFilename; if (!itksys::SystemTools::FileExists(derivedResourceFilename.c_str())) { MITK_INFO << "CreateDerivedFileList: File does not exit. Skipping entry."; continue; } files.push_back(derivedResourceFilename); } return files; } /// Copy derived resources from first time step. Append _reg tag, but leave data untouched. static void CopyResources(FileListType fileList, std::string outputPath) { for (unsigned int j=0; j < fileList.size(); j++) { std::string derivedResourceFilename = fileList.at(j); std::string fileType = itksys::SystemTools::GetFilenameExtension(derivedResourceFilename); std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(derivedResourceFilename); std::string savePathAndFileName = outputPath +fileStem + "." + fileType; MITK_INFO << "Copy resource " << savePathAndFileName; mitk::Image::Pointer resImage = ExtractFirstTS(dynamic_cast(mitk::IOUtil::Load(derivedResourceFilename)[0].GetPointer()), fileType); mitk::IOUtil::Save(resImage, savePathAndFileName); } } int main( int argc, char* argv[] ) { mitkCommandLineParser parser; parser.setArgumentPrefix("--","-"); parser.setTitle("Folder Registration"); parser.setCategory("Preprocessing Tools"); parser.setDescription("For detail description see http://docs.mitk.org/nightly/DiffusionMiniApps.html"); parser.setContributor("MIC"); // Add command line argument names parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help", "Show this help text"); //parser.addArgument("usemask", "u", QVariant::Bool, "Use segmentations (derived resources) to exclude areas from registration metrics"); parser.addArgument("input", "i", mitkCommandLineParser::InputDirectory, "Input:", "Input folder",us::Any(),false); parser.addArgument("output", "o", mitkCommandLineParser::OutputDirectory, "Output:", "Output folder (ending with /)",us::Any(),false); parser.addArgument("fixed", "f", mitkCommandLineParser::String, "Fixed images:", "Suffix for fixed image (if none is supplied first file matching moving pattern is chosen)",us::Any(),true); parser.addArgument("moving", "m", mitkCommandLineParser::String, "Moving images:", "Suffix for moving images",us::Any(),false); parser.addArgument("derived", "d", mitkCommandLineParser::String, "Derived resources:", "Derived resources suffixes (replaces suffix for moving images); comma separated",us::Any(),true); parser.addArgument("silent", "s", mitkCommandLineParser::Bool, "Silent:", "No xml progress output."); parser.addArgument("resample", "r", mitkCommandLineParser::String, "Resample (x,y,z)mm:", "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any()); parser.addArgument("binary", "b", mitkCommandLineParser::Bool, "Binary:", "Speficies that derived resource are binary (interpolation using nearest neighbor)",us::Any()); parser.addArgument("correct-origin", "c", mitkCommandLineParser::Bool, "Origin correction:", "Correct for large origin displacement. Use switch when you reveive: Joint PDF summed to zero ",us::Any()); parser.addArgument("sinc-int", "s", mitkCommandLineParser::Bool, "Windowed-sinc interpolation:", "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any()); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); // Handle special arguments bool silent = false; bool isBinary = false; bool alignOrigin = false; { if (parsedArgs.size() == 0) { return EXIT_FAILURE; } if (parsedArgs.count("silent")) silent = true; if (parsedArgs.count("binary")) isBinary = true; if (parsedArgs.count("correct-origin")) alignOrigin = true; // Show a help message if ( parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } } std::string refPattern = ""; bool useFirstMoving = false; - std::string movingImgPattern = us::any_cast(parsedArgs["moving"]); + std::string movingImgPattern = us::any_cast(parsedArgs["moving"]); if (parsedArgs.count("fixed")) { - refPattern = us::any_cast(parsedArgs["fixed"]); + refPattern = us::any_cast(parsedArgs["fixed"]); } else { useFirstMoving = true; refPattern = movingImgPattern; } - std::string outputPath = us::any_cast(parsedArgs["output"]); + std::string outputPath = us::any_cast(parsedArgs["output"]); - std::string inputPath = us::any_cast(parsedArgs["input"]); + std::string inputPath = us::any_cast(parsedArgs["input"]); //QString resampleReference = parsedArgs["resample"].toString(); //bool maskTumor = parsedArgs["usemask"].toBool(); // if derived sources pattern is provided, populate QStringList with possible filename postfixes std::vector derPatterns; if (parsedArgs.count("derived") || parsedArgs.count("d") ) { - std::string arg = us::any_cast(parsedArgs["derived"]); + std::string arg = us::any_cast(parsedArgs["derived"]); derPatterns = split(arg ,','); } std::vector spacings; float spacing[] = { 0.0f, 0.0f, 0.0f }; bool doResampling = false; if (parsedArgs.count("resample") || parsedArgs.count("d") ) { - std::string arg = us::any_cast(parsedArgs["resample"]); + std::string arg = us::any_cast(parsedArgs["resample"]); spacings = split(arg ,','); spacing[0] = atoi(spacings.at(0).c_str()); spacing[1] = atoi(spacings.at(1).c_str()); spacing[2] = atoi(spacings.at(2).c_str()); doResampling = true; } MITK_INFO << "Input Folder : " << inputPath; MITK_INFO << "Looking for reference image ..."; FileListType referenceFileList = CreateFileList(inputPath,refPattern); if ((!useFirstMoving && referenceFileList.size() != 1) || (useFirstMoving && referenceFileList.size() == 0)) { MITK_ERROR << "None or more than one possible reference images (" << refPattern <<") found. Exiting." << referenceFileList.size(); MITK_INFO << "Choose a fixed arguement that is unique in the given folder!"; return EXIT_FAILURE; } std::string referenceFileName = referenceFileList.at(0); MITK_INFO << "Loading Reference (fixed) image: " << referenceFileName; std::string fileType = itksys::SystemTools::GetFilenameExtension(referenceFileName); mitk::Image::Pointer refImage = ExtractFirstTS(dynamic_cast(mitk::IOUtil::Load(referenceFileName)[0].GetPointer()), fileType); mitk::Image::Pointer resampleReference = nullptr; if (doResampling) { refImage = ResampleBySpacing(refImage,spacing); resampleReference = refImage; } if (refImage.IsNull()) MITK_ERROR << "Loaded fixed image is nullptr"; // Copy reference image to destination std::string savePathAndFileName = GetSavePath(outputPath, referenceFileName); mitk::IOUtil::Save(refImage, savePathAndFileName); // Copy all derived resources also to output folder, adding _reg suffix referenceFileList = CreateDerivedFileList(referenceFileName, movingImgPattern,derPatterns); CopyResources(referenceFileList, outputPath); std::string derivedResourceFilename; mitk::Image::Pointer referenceMask = nullptr; // union of all segmentations if (!silent) { // XML Output to report progress std::cout << ""; std::cout << "Batched Registration"; std::cout << "Starting registration ... "; std::cout << ""; } // Now iterate over all files and register them to the reference image, // also register derived resources based on file patterns // ------------------------------------------------------------------------------ // Create File list FileListType movingImagesList = CreateFileList(inputPath, movingImgPattern); for (unsigned int i =0; i < movingImagesList.size(); i++) { std::string fileMorphName = movingImagesList.at(i); if (fileMorphName == referenceFileName) { // do not process reference image again continue; } MITK_INFO << "Processing image " << fileMorphName; // 1 Register morphological file to reference image if (!itksys::SystemTools::FileExists(fileMorphName.c_str())) { MITK_WARN << "File does not exit. Skipping entry."; continue; } // Origin of images is cancelled // TODO make this optional!! double transf[6]; double offset[3]; { std::string fileType = itksys::SystemTools::GetFilenameExtension(fileMorphName); mitk::Image::Pointer movingImage = ExtractFirstTS(dynamic_cast(mitk::IOUtil::Load(fileMorphName)[0].GetPointer()), fileType); if (movingImage.IsNull()) MITK_ERROR << "Loaded moving image is nullptr"; // Store transformation, apply it to morph file MITK_INFO << "----------Registering moving image to reference----------"; mitk::RegistrationWrapper::GetTransformation(refImage, movingImage, transf, offset, alignOrigin, referenceMask); mitk::RegistrationWrapper::ApplyTransformationToImage(movingImage, transf,offset, resampleReference); // , resampleImage savePathAndFileName = GetSavePath(outputPath, fileMorphName); if (fileType == ".dwi") fileType = "dwi"; { mitk::ImageReadAccessor readAccess(movingImage); if (readAccess.GetData() == nullptr) MITK_INFO <<"POST DATA is null"; } mitk::IOUtil::Save(movingImage, savePathAndFileName); } if (!silent) { std::cout << "."; } // Now parse all derived resource and apply the above calculated transformation to them // ------------------------------------------------------------------------------------ FileListType fList = CreateDerivedFileList(fileMorphName, movingImgPattern,derPatterns); if (fList.size() > 0) MITK_INFO << "----------DERIVED RESOURCES ---------"; for (unsigned int j=0; j < fList.size(); j++) { derivedResourceFilename = fList.at(j); MITK_INFO << "----Processing derived resorce " << derivedResourceFilename << " ..."; std::string fileType = itksys::SystemTools::GetFilenameExtension(derivedResourceFilename); mitk::Image::Pointer derivedMovingResource = ExtractFirstTS(dynamic_cast(mitk::IOUtil::Load(derivedResourceFilename)[0].GetPointer()), fileType); // Apply transformation to derived resource, treat derived resource as binary mitk::RegistrationWrapper::ApplyTransformationToImage(derivedMovingResource, transf,offset, resampleReference,isBinary); savePathAndFileName = GetSavePath(outputPath, derivedResourceFilename); mitk::IOUtil::Save(derivedMovingResource, savePathAndFileName); } } if (!silent) std::cout << ""; return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkOdfMaximaExtractionFilter.cpp b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkOdfMaximaExtractionFilter.cpp index cbb87a77f4..c5944c3f54 100644 --- a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkOdfMaximaExtractionFilter.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkOdfMaximaExtractionFilter.cpp @@ -1,637 +1,636 @@ /*=================================================================== 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 __itkOdfMaximaExtractionFilter_cpp #define __itkOdfMaximaExtractionFilter_cpp #include "itkOdfMaximaExtractionFilter.h" #include #include #include #include #include #include #include #include #include #include #include using namespace boost::math; -using namespace std; namespace itk { template< class TOdfPixelType > OdfMaximaExtractionFilter< TOdfPixelType >::OdfMaximaExtractionFilter(): m_NormalizationMethod(MAX_VEC_NORM), m_PeakThreshold(0.2), m_MaxNumPeaks(10), m_ShCoeffImage(nullptr), m_OutputFiberBundle(nullptr), m_NumDirectionsImage(nullptr), m_DirectionImageContainer(nullptr) { } // solve ax? + bx? + cx + d = 0 using cardanos method template< class TOdfPixelType > bool OdfMaximaExtractionFilter::ReconstructQballImage() { if (m_ShCoeffImage.IsNotNull()) { cout << "Using preset coefficient image\n"; return true; } cout << "Starting qball reconstruction\n"; try { QballReconstructionFilterType::Pointer filter = QballReconstructionFilterType::New(); filter->SetBValue(m_Bvalue); filter->SetGradientImage( m_DiffusionGradients, m_DiffusionImage ); filter->SetLambda(0.006); filter->SetNormalizationMethod(QballReconstructionFilterType::QBAR_SOLID_ANGLE); filter->Update(); m_ShCoeffImage = filter->GetCoefficientImage(); if (m_ShCoeffImage.IsNull()) return false; return true; } catch (...) { return false; } } // solve ax³ + bx² + cx + d = 0 using cardanos method template< class TOdfPixelType > std::vector OdfMaximaExtractionFilter< TOdfPixelType > ::SolveCubic(const double& a, const double& b, const double& c, const double& d) { double A, B, p, q, r, D, offset, ee, tmp, root; - vector roots; + std::vector roots; double inv3 = 1.0/3.0; if (a!=0) // solve ax³ + bx² + cx + d = 0 { p = b/a; q = c/a; r = d/a; // x³ + px² + qx + r = 0 A = q-p*p*inv3; B = (2.0*p*p*p-9.0*p*q+27.0*r)/27.0; A = A*inv3; B = B*0.5; D = B*B+A*A*A; offset = p*inv3; if (D>0.0) // one real root { ee = sqrt(D); tmp = -B+ee; root = cbrt(tmp); tmp = -B-ee; root += cbrt(tmp); root -= offset; roots.push_back(root); } else if (D<0.0) // three real roots { ee = sqrt(-D); double tmp2 = -B; double angle = 2.0*inv3*atan(ee/(sqrt(tmp2*tmp2+ee*ee)+tmp2)); double sqrt3 = sqrt(3.0); tmp = cos(angle); tmp2 = sin(angle); ee = sqrt(-A); root = 2*ee*tmp-offset; roots.push_back(root); root = -ee*(tmp+sqrt3*tmp2)-offset; roots.push_back(root); root = -ee*(tmp-sqrt3*tmp2)-offset; roots.push_back(root); } else // one or two real roots { tmp=-B; tmp=cbrt(tmp); root=2*tmp-offset; roots.push_back(root); // TODO: check if this is correct (see history) if (A!=0 || B!=0) { root=-tmp-offset; roots.push_back(root); } } } else if (b!=0) // solve bx² + cx + d = 0 { D = c*c-4*b*d; if (D>0) { tmp = sqrt(D); root = (-c+tmp)/(2.0*b); roots.push_back(root); root = (-c-tmp)/(2.0*b); roots.push_back(root); } // TODO: check if this is correct (see history) else if (D==0) { root = -c/(2.0*b); roots.push_back(root); } } // TODO: check if this is correct (see history) else if (c!=0) // solve cx + d = 0 { root = -d/c; roots.push_back(root); } return roots; } template< class TOdfPixelType > double OdfMaximaExtractionFilter< TOdfPixelType > ::ODF_dtheta(const double& sn, const double& cs, const double& A, const double& B, const double& C, const double& D, const double& E, const double& F, const double& G, const double& H) { double dtheta=(G-7*E)*sn*sn + (7*F-35*D-H)*sn*cs + (H+C-F-3*A-5*D)*sn + (0.5*E+B+0.5*G)*cs -0.5*G+3.5*E; return dtheta; } template< class TOdfPixelType > double OdfMaximaExtractionFilter< TOdfPixelType > ::ODF_dtheta2(const double& sn, const double& cs, const double& A, const double& B, const double& C, const double& D, const double& E, const double& F, const double& G, const double& H) { double dtheta2=4*(G-7*E)*sn*cs + 2*(7*F-35*D-H)*(2*cs*cs-1) + 2*(H+C-F-3*A-5*D)*cs -(E+2*B+G)*sn; return dtheta2; } template< class TOdfPixelType > double OdfMaximaExtractionFilter< TOdfPixelType > ::ODF_dphi2(const double& sn, const double& cs, const double& A, const double& B, const double& C, const double& D, const double& E, const double& F, const double& G, const double& H) { double dphi2=35*D*((1+cs)*(1+cs)/4)+(3*A-30*D)*(1+cs)/2.0+3*D-A + 0.5*(7*E*(1+cs)/2.0-3*E+B)*sn + (7*F*(1+cs)/2+C-F)*(1-cs)/2.0 + G*sn*(1-cs)/4.0 + H*((1-cs)*(1-cs)/4); return dphi2; } template< class TOdfPixelType > void OdfMaximaExtractionFilter< TOdfPixelType > ::FindCandidatePeaks(const CoefficientPixelType& SHcoeff) { const double thr = 0.03; // threshold on the derivative of the ODF with respect to theta const double phi_step = 0.005; // step size for 1D exhaustive search on phi bool highRes; // when close to maxima increase resolution double mag, Y, Yp, sn, cs; double phi, dPhi; double A, B, C, D, E, F, G, H, Bp, Cp, Ep, Fp, Gp, Hp, Bs, Cs, Es, Fs, Gs, Hs; CoefficientPixelType a, ap; a = SHcoeff; ap = SHcoeff; m_CandidatePeaks.clear(); // clear peaks of last voxel for (int adaptiveStepwidth=0; adaptiveStepwidth<=1; adaptiveStepwidth++) { phi=0; while (phi<(2*M_PI)) // phi exhaustive search 0..pi { // calculate 4th order SH representtaion of ODF and according derivative for (int l=0; l<=4; l=l+2) { for (int m=-l; m<=l; m++) { int j=l*(l+1)/2+m; if (m<0) { mag = sqrt(((2*l+1)/(2*M_PI))*factorial(l+m)/factorial(l-m)); Y = mag*cos(m*phi); Yp = -m*mag*sin(m*phi); } else if (m==0) { Y = sqrt((2*l+1)/(4*M_PI)); Yp = 0; } else { mag = pow(-1.0,m)*sqrt(((2*l+1)/(2*M_PI))*factorial(l-m)/factorial(l+m)); Y = mag*sin(m*phi); Yp = m*mag*cos(m*phi); } a[j] = SHcoeff[j]*Y; ap[j] = SHcoeff[j]*Yp; } } // ODF A=0.5*a[3]; B=-3*(a[2]+a[4]); C=3*(a[1]+a[5]); D=0.125*a[10]; E=-2.5*(a[9]+a[11]); F=7.5*(a[8]+a[12]); G=-105*(a[7]+a[13]); H=105*(a[6]+a[14]); // phi derivative Bp=-3*(ap[2]+ap[4]); Cp=3*(ap[1]+ap[5]); Ep=-2.5*(ap[9]+ap[11]); Fp=7.5*(ap[8]+ap[12]); Gp=-105*(ap[7]+ap[13]); Hp=105*(ap[6]+ap[14]); // 2phi derivative Bs=-B; Cs=-4*C; Es=-E; Fs=-4*F; Gs=-9*G; Hs=-16*H; // solve cubic for tan(theta) std::vector tanTheta = SolveCubic(Hp+Cp-Fp, Gp+Bp-3*Ep, 6*Fp+Cp, Bp+4*Ep); highRes = false; dPhi = phi_step; //for each real cubic solution for tan(theta) for (int n=0; n hessian; hessian(0,0) = ODF_dtheta2(sn, cs, A, B, C, D, E, F, G, H); hessian(0,1) = ODF_dtheta(sn, cs, 0, Bp, Cp, 0, Ep, Fp, Gp, Hp); hessian(1,0) = hessian(0,1); hessian(1,1) = ODF_dphi2(sn, cs, 0, Bs, Cs, 0, Es, Fs, Gs, Hs); double det = vnl_det(hessian); // determinant double tr = vnl_trace(hessian); // trace highRes = true; // we are close to a maximum, so turn on high resolution 1D exhaustive search if (det>=0 && tr<=0) // check if we really have a local maximum { vnl_vector_fixed< double, 2 > peak; peak[0] = theta; peak[1] = phi; m_CandidatePeaks.push_back(peak); } } if (adaptiveStepwidth) // calculate adaptive step width { double t2=tanTheta[n]*tanTheta[n]; double t3=t2*tanTheta[n]; double t4=t3*tanTheta[n]; double const_step=phi_step*(1+t2)/sqrt(t2+t4+pow((((Hs+Cs-Fs)*t3+(Gs+Bs-3*Es)*t2+(6*Fs+Cs)*tanTheta[n]+(Bs+4*Es))/(3*(Hp+Cp-Fp)*t2+2*(Gp+Bp-3*Ep)*tanTheta[n]+(6*Fp+Cp))),2.0)); if (const_step std::vector< vnl_vector_fixed< double, 3 > > OdfMaximaExtractionFilter< TOdfPixelType > ::ClusterPeaks(const CoefficientPixelType& shCoeff) { const double distThres = 0.4; int npeaks = 0, nMin = 0; double dMin, dPos, dNeg, d; Vector3D u; - vector< Vector3D > v; + std::vector< Vector3D > v; // initialize container for vector clusters std::vector < std::vector< Vector3D > > clusters; clusters.resize(m_CandidatePeaks.size()); for (int i=0; i::max(); for (int n=0; n shBasis, sphCoords; Cart2Sph(v, sphCoords); // convert candidate peaks to spherical angles shBasis = CalcShBasis(sphCoords, 4); // evaluate spherical harmonics at each peak vnl_vector odfVals(npeaks); odfVals.fill(0.0); double maxVal = itk::NumericTraits::NonpositiveMin(); int maxPos; for (int i=0; imaxVal ) { maxVal = odfVals(i); maxPos = i; } } v.clear(); - vector< double > restVals; + std::vector< double > restVals; for (int i=0; i=m_PeakThreshold*maxVal ) { u[0] = odfVals(i)*cos(sphCoords(i,1))*sin(sphCoords(i,0)); u[1] = odfVals(i)*sin(sphCoords(i,1))*sin(sphCoords(i,0)); u[2] = odfVals(i)*cos(sphCoords(i,0)); restVals.push_back(odfVals(i)); v.push_back(u); } npeaks = v.size(); if (npeaks>m_MaxNumPeaks) // if still too many peaks, keep only the m_MaxNumPeaks with maximum value { - vector< Vector3D > v2; + std::vector< Vector3D > v2; for (int i=0; i::NonpositiveMin(); //Get the maximum ODF peak value and the corresponding peak index for (int i=0; imaxVal ) { maxVal = restVals[i]; maxPos = i; } v2.push_back(v[maxPos]); restVals[maxPos] = 0; //zero that entry in order to find the next maximum } return v2; } } return v; } // convert cartesian to spherical coordinates template< class TOdfPixelType > void OdfMaximaExtractionFilter< TOdfPixelType > ::Cart2Sph(const std::vector< Vector3D >& dir, vnl_matrix& sphCoords) { sphCoords.set_size(dir.size(), 2); for (int i=0; i vnl_matrix OdfMaximaExtractionFilter< TOdfPixelType > ::CalcShBasis(vnl_matrix& sphCoords, const int& shOrder) { int R = (shOrder+1)*(shOrder+2)/2; int M = sphCoords.rows(); int j, m; double mag, plm; vnl_matrix shBasis; shBasis.set_size(M,R); for (int p=0; p(l,abs(m),cos(sphCoords(p,0))); mag = sqrt((double)(2*l+1)/(4.0*M_PI)*factorial(l-abs(m))/factorial(l+abs(m)))*plm; if (m<0) shBasis(p,j) = sqrt(2.0)*mag*cos(fabs((double)m)*sphCoords(p,1)); else if (m==0) shBasis(p,j) = mag; else shBasis(p,j) = pow(-1.0, m)*sqrt(2.0)*mag*sin(m*sphCoords(p,1)); j++; } } return shBasis; } template< class TOdfPixelType > void OdfMaximaExtractionFilter< TOdfPixelType > ::GenerateData() { if (!ReconstructQballImage()) return; std::cout << "Starting maxima extraction\n"; switch (m_NormalizationMethod) { case NO_NORM: std::cout << "NO_NORM\n"; break; case SINGLE_VEC_NORM: std::cout << "SINGLE_VEC_NORM\n"; break; case MAX_VEC_NORM: std::cout << "MAX_VEC_NORM\n"; break; } typedef ImageRegionConstIterator< CoefficientImageType > InputIteratorType; InputIteratorType git(m_ShCoeffImage, m_ShCoeffImage->GetLargestPossibleRegion() ); itk::Vector spacing = m_ShCoeffImage->GetSpacing(); double minSpacing = spacing[0]; if (spacing[1]GetOrigin(); itk::Matrix direction = m_ShCoeffImage->GetDirection(); ImageRegion<3> imageRegion = m_ShCoeffImage->GetLargestPossibleRegion(); // initialize num directions image m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( spacing ); m_NumDirectionsImage->SetOrigin( origin ); m_NumDirectionsImage->SetDirection( direction ); m_NumDirectionsImage->SetRegions( imageRegion ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); m_DirectionImageContainer = ItkDirectionImageContainer::New(); for (int i=0; i nullVec; nullVec.Fill(0.0); ItkDirectionImage::Pointer img = ItkDirectionImage::New(); img->SetSpacing( spacing ); img->SetOrigin( origin ); img->SetDirection( direction ); img->SetRegions( imageRegion ); img->Allocate(); img->FillBuffer(nullVec); m_DirectionImageContainer->InsertElement(m_DirectionImageContainer->Size(), img); } if (m_MaskImage.IsNull()) { m_MaskImage = ItkUcharImgType::New(); m_MaskImage->SetSpacing( spacing ); m_MaskImage->SetOrigin( origin ); m_MaskImage->SetDirection( direction ); m_MaskImage->SetRegions( imageRegion ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } itk::ImageRegionIterator dirIt(m_NumDirectionsImage, m_NumDirectionsImage->GetLargestPossibleRegion()); itk::ImageRegionIterator maskIt(m_MaskImage, m_MaskImage->GetLargestPossibleRegion()); int maxProgress = m_MaskImage->GetLargestPossibleRegion().GetSize()[0]*m_MaskImage->GetLargestPossibleRegion().GetSize()[1]*m_MaskImage->GetLargestPossibleRegion().GetSize()[2]; boost::progress_display disp(maxProgress); git.GoToBegin(); while( !git.IsAtEnd() ) { ++disp; if (maskIt.Value()<=0) { ++git; ++dirIt; ++maskIt; continue; } CoefficientPixelType c = git.Get(); FindCandidatePeaks(c); std::vector< Vector3D > directions = ClusterPeaks(c); typename CoefficientImageType::IndexType index = git.GetIndex(); float max = 0.0; for (int i=0; imax) max = directions.at(i).magnitude(); if (max<0.0001) max = 1.0; for (int i=0; iGetElement(i); itk::Vector< float, 3 > pixel; vnl_vector dir = directions.at(i); vtkSmartPointer container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; itk::Point worldCenter; m_ShCoeffImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); switch (m_NormalizationMethod) { case NO_NORM: break; case SINGLE_VEC_NORM: dir.normalize(); break; case MAX_VEC_NORM: dir /= max; break; } dir = m_MaskImage->GetDirection()*dir; pixel.SetElement(0, dir[0]); pixel.SetElement(1, dir[1]); pixel.SetElement(2, dir[2]); img->SetPixel(index, pixel); itk::Point worldStart; worldStart[0] = worldCenter[0]-dir[0]/2 * minSpacing; worldStart[1] = worldCenter[1]-dir[1]/2 * minSpacing; worldStart[2] = worldCenter[2]-dir[2]/2 * minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dir[0]/2 * minSpacing; worldEnd[1] = worldCenter[1]+dir[1]/2 * minSpacing; worldEnd[2] = worldCenter[2]+dir[2]/2 * minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); } dirIt.Set(directions.size()); ++git; ++dirIt; ++maskIt; } vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); m_OutputFiberBundle = mitk::FiberBundle::New(directionsPolyData); std::cout << "Maxima extraction finished\n"; } } #endif // __itkOdfMaximaExtractionFilter_cpp diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTckReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTckReader.cpp index 1c5d1ddca6..cc326c9b2c 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTckReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTckReader.cpp @@ -1,166 +1,164 @@ /*=================================================================== 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 "mitkFiberBundleTckReader.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDiffusionIOMimeTypes.h" #include #include mitk::FiberBundleTckReader::FiberBundleTckReader() - : mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TCK_MIMETYPE_NAME(), "tck Fiber Bundle Reader (MRtrix format)" ) + : mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TCK_MIMETYPE_NAME(), "tck Fiber Bundle Reader (MRtrix format)" ) { - m_ServiceReg = this->RegisterService(); + m_ServiceReg = this->RegisterService(); } mitk::FiberBundleTckReader::FiberBundleTckReader(const FiberBundleTckReader &other) - :mitk::AbstractFileReader(other) + :mitk::AbstractFileReader(other) { } mitk::FiberBundleTckReader * mitk::FiberBundleTckReader::Clone() const { - return new FiberBundleTckReader(*this); + return new FiberBundleTckReader(*this); } std::vector > mitk::FiberBundleTckReader::Read() { - std::vector > result; - try - { - const std::string& locale = "C"; - const std::string& currLocale = setlocale( LC_ALL, nullptr ); - setlocale(LC_ALL, locale.c_str()); + std::vector > result; + try + { + const std::string& locale = "C"; + const std::string& currLocale = setlocale( LC_ALL, nullptr ); + setlocale(LC_ALL, locale.c_str()); - std::string filename = this->GetInputLocation(); + std::string filename = this->GetInputLocation(); - std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); - ext = itksys::SystemTools::LowerCase(ext); + std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); + ext = itksys::SystemTools::LowerCase(ext); - if (ext==".tck") + if (ext==".tck") + { + MITK_INFO << "Loading tractogram (MRtrix format): " << itksys::SystemTools::GetFilenameName(filename); + std::FILE* filePointer = std::fopen(filename.c_str(),"r+b"); + std::string header = ""; + + bool header_end = false; + int count = 0; + while (!header_end) + { + char c; + count += std::fread(&c, 1, 1, filePointer); + header += c; + if (header.size() >= 3 && header.compare(header.size() - 3, 3, "END") == 0) + header_end = true; + } + MITK_INFO << "TCK Header:"; + MITK_INFO << header; + + int header_size = -1; + try + { + std::string delimiter = "file: . "; + size_t pos = 0; + pos = header.find(delimiter); + header.erase(0, pos + delimiter.length()); + pos = header.find("\n"); + header_size = boost::lexical_cast(header.substr(0, pos)); + } + catch(...) + { + + } + + if (header_size==-1) + mitkThrow() << "Could not parse header size from " << filename; + std::fseek ( filePointer , header_size , SEEK_SET ); + + vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); + vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); + vtkSmartPointer container = vtkSmartPointer::New(); + + float tmp[3]; + count = 1; + int fiber_length = 0; + while (std::fread((char*)tmp, 1, 12, filePointer)==12) + { + if (std::isinf(tmp[0]) || std::isinf(tmp[1]) || std::isinf(tmp[1])) + break; + else if (std::isnan(tmp[0]) || std::isnan(tmp[1]) || std::isnan(tmp[2])) { - std::FILE* filePointer = std::fopen(filename.c_str(),"r+b"); - std::string header = ""; - - bool header_end = false; - int count = 0; - while (!header_end) - { - char c; - count += std::fread(&c, 1, 1, filePointer); - header += c; - if (header.size() >= 3 && header.compare(header.size() - 3, 3, "END") == 0) - header_end = true; - } - MITK_INFO << "TCK Header:"; - MITK_INFO << header; - - int header_size = -1; - try - { - std::string delimiter = "file: . "; - size_t pos = 0; - pos = header.find(delimiter); - header.erase(0, pos + delimiter.length()); - pos = header.find("\n"); - header_size = boost::lexical_cast(header.substr(0, pos)); - } - catch(...) - { - - } - - if (header_size==-1) - mitkThrow() << "Could not parse header size from " << filename; - std::fseek ( filePointer , header_size , SEEK_SET ); - - MITK_INFO << "Reading TCK file"; - - - vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); - vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); - vtkSmartPointer container = vtkSmartPointer::New(); - - float tmp[3]; - count = 1; - int fiber_length = 0; - while (std::fread((char*)tmp, 1, 12, filePointer)==12) - { - if (std::isinf(tmp[0]) || std::isinf(tmp[1]) || std::isinf(tmp[1])) - break; - else if (std::isnan(tmp[0]) || std::isnan(tmp[1]) || std::isnan(tmp[2])) - { - count++; - fiber_length = 0; - vtkNewCells->InsertNextCell(container); - container = vtkSmartPointer::New(); - } - else - { - fiber_length++; - vtkIdType id = vtkNewPoints->InsertNextPoint(tmp); - container->GetPointIds()->InsertNextId(id); - } - } - - vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); - fiberPolyData->SetPoints(vtkNewPoints); - fiberPolyData->SetLines(vtkNewCells); - - // transform polydata from RAS (MRtrix) to LPS (MITK) - mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); - vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New(); - matrix->Identity(); - matrix->SetElement(0,0,-matrix->GetElement(0,0)); - matrix->SetElement(1,1,-matrix->GetElement(1,1)); - geometry->SetIndexToWorldTransformByVtkMatrix(matrix); - - vtkSmartPointer transformFilter = vtkSmartPointer::New(); - transformFilter->SetInputData(fiberPolyData); - transformFilter->SetTransform(geometry->GetVtkTransform()); - transformFilter->Update(); - - FiberBundle::Pointer fib = FiberBundle::New(transformFilter->GetOutput()); - result.push_back(fib.GetPointer()); + count++; + fiber_length = 0; + vtkNewCells->InsertNextCell(container); + container = vtkSmartPointer::New(); } - - setlocale(LC_ALL, currLocale.c_str()); - MITK_INFO << "Fiber bundle read"; - return result; - } - catch(...) - { - throw; + else + { + fiber_length++; + vtkIdType id = vtkNewPoints->InsertNextPoint(tmp); + container->GetPointIds()->InsertNextId(id); + } + } + + vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); + fiberPolyData->SetPoints(vtkNewPoints); + fiberPolyData->SetLines(vtkNewCells); + + // transform polydata from RAS (MRtrix) to LPS (MITK) + mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); + vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New(); + matrix->Identity(); + matrix->SetElement(0,0,-matrix->GetElement(0,0)); + matrix->SetElement(1,1,-matrix->GetElement(1,1)); + geometry->SetIndexToWorldTransformByVtkMatrix(matrix); + + vtkSmartPointer transformFilter = vtkSmartPointer::New(); + transformFilter->SetInputData(fiberPolyData); + transformFilter->SetTransform(geometry->GetVtkTransform()); + transformFilter->Update(); + + FiberBundle::Pointer fib = FiberBundle::New(transformFilter->GetOutput()); + result.push_back(fib.GetPointer()); } + + setlocale(LC_ALL, currLocale.c_str()); + MITK_INFO << "Fiber bundle read"; return result; + } + catch(...) + { + throw; + } + return result; } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.cpp index 0d02e09733..beac4c8317 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.cpp @@ -1,86 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberBundleTrackVisReader.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDiffusionIOMimeTypes.h" mitk::FiberBundleTrackVisReader::FiberBundleTrackVisReader() - : mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE_NAME(), "TrackVis Fiber Bundle Reader" ) + : mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE_NAME(), "TrackVis Fiber Bundle Reader" ) { - m_ServiceReg = this->RegisterService(); + m_ServiceReg = this->RegisterService(); } mitk::FiberBundleTrackVisReader::FiberBundleTrackVisReader(const FiberBundleTrackVisReader &other) - :mitk::AbstractFileReader(other) + :mitk::AbstractFileReader(other) { } mitk::FiberBundleTrackVisReader * mitk::FiberBundleTrackVisReader::Clone() const { - return new FiberBundleTrackVisReader(*this); + return new FiberBundleTrackVisReader(*this); } std::vector > mitk::FiberBundleTrackVisReader::Read() { - std::vector > result; - try - { - const std::string& locale = "C"; - const std::string& currLocale = setlocale( LC_ALL, nullptr ); - setlocale(LC_ALL, locale.c_str()); - - std::string filename = this->GetInputLocation(); - - std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); - ext = itksys::SystemTools::LowerCase(ext); - - if (ext==".trk") - { - FiberBundle::Pointer mitk_fib = FiberBundle::New(); - TrackVisFiberReader reader; - reader.open(this->GetInputLocation().c_str()); - reader.read(mitk_fib.GetPointer()); - result.push_back(mitk_fib.GetPointer()); - return result; - } - - setlocale(LC_ALL, currLocale.c_str()); - MITK_INFO << "Fiber bundle read"; - } - catch(...) + std::vector > result; + try + { + const std::string& locale = "C"; + const std::string& currLocale = setlocale( LC_ALL, nullptr ); + setlocale(LC_ALL, locale.c_str()); + + std::string filename = this->GetInputLocation(); + MITK_INFO << "Loading tractogram (TrackVis format): " << itksys::SystemTools::GetFilenameName(filename); + + std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); + ext = itksys::SystemTools::LowerCase(ext); + + if (ext==".trk") { - throw; + FiberBundle::Pointer mitk_fib = FiberBundle::New(); + TrackVisFiberReader reader; + reader.open(this->GetInputLocation().c_str()); + reader.read(mitk_fib.GetPointer()); + result.push_back(mitk_fib.GetPointer()); + return result; } - return result; + + setlocale(LC_ALL, currLocale.c_str()); + MITK_INFO << "Fiber bundle read"; + } + catch(...) + { + throw; + } + return result; } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.cpp index 81da34bea2..0b98c2ebb2 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.cpp @@ -1,284 +1,284 @@ /*=================================================================== 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 "mitkFiberBundleVtkReader.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDiffusionIOMimeTypes.h" mitk::FiberBundleVtkReader::FiberBundleVtkReader() - : mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE_NAME(), "VTK Fiber Bundle Reader" ) + : mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE_NAME(), "VTK Fiber Bundle Reader" ) { - m_ServiceReg = this->RegisterService(); + m_ServiceReg = this->RegisterService(); } mitk::FiberBundleVtkReader::FiberBundleVtkReader(const FiberBundleVtkReader &other) - :mitk::AbstractFileReader(other) + :mitk::AbstractFileReader(other) { } mitk::FiberBundleVtkReader * mitk::FiberBundleVtkReader::Clone() const { - return new FiberBundleVtkReader(*this); + return new FiberBundleVtkReader(*this); } std::vector > mitk::FiberBundleVtkReader::Read() { - std::vector > result; + std::vector > result; - const std::string& locale = "C"; - const std::string& currLocale = setlocale( LC_ALL, nullptr ); - setlocale(LC_ALL, locale.c_str()); + const std::string& locale = "C"; + const std::string& currLocale = setlocale( LC_ALL, nullptr ); + setlocale(LC_ALL, locale.c_str()); - std::string filename = this->GetInputLocation(); + std::string filename = this->GetInputLocation(); - std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); - ext = itksys::SystemTools::LowerCase(ext); + std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); + ext = itksys::SystemTools::LowerCase(ext); - try + try + { + MITK_INFO << "Loading tractogram (VTK format): " << itksys::SystemTools::GetFilenameName(filename); + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName( this->GetInputLocation().c_str() ); + + if (reader->IsFilePolyData()) { - MITK_INFO << "Trying to load fiber file as VTK format."; - vtkSmartPointer reader = vtkSmartPointer::New(); - reader->SetFileName( this->GetInputLocation().c_str() ); + reader->Update(); - if (reader->IsFilePolyData()) - { - reader->Update(); + if ( reader->GetOutput() != nullptr ) + { + vtkSmartPointer fiberPolyData = reader->GetOutput(); + FiberBundle::Pointer fiberBundle = FiberBundle::New(fiberPolyData); - if ( reader->GetOutput() != nullptr ) + vtkSmartPointer weights = vtkFloatArray::SafeDownCast(fiberPolyData->GetCellData()->GetArray("FIBER_WEIGHTS")); + if (weights!=nullptr) + { + // float weight=0; + for (int i=0; iGetNumberOfValues(); i++) + { + if (weights->GetValue(i)<0.0) { - vtkSmartPointer fiberPolyData = reader->GetOutput(); - FiberBundle::Pointer fiberBundle = FiberBundle::New(fiberPolyData); - - vtkSmartPointer weights = vtkFloatArray::SafeDownCast(fiberPolyData->GetCellData()->GetArray("FIBER_WEIGHTS")); - if (weights!=nullptr) - { -// float weight=0; - for (int i=0; iGetNumberOfValues(); i++) - { - if (weights->GetValue(i)<0.0) - { - MITK_ERROR << "Fiber weight<0 detected! Setting value to 0."; - weights->SetValue(i,0); - } - } -// if (!mitk::Equal(weights->GetValue(i),weight,0.00001)) -// { -// MITK_INFO << "Weight: " << weights->GetValue(i); -// weight = weights->GetValue(i); -// } - fiberBundle->SetFiberWeights(weights); - } - - vtkSmartPointer fiberColors = vtkUnsignedCharArray::SafeDownCast(fiberPolyData->GetPointData()->GetArray("FIBER_COLORS")); - if (fiberColors!=nullptr) - fiberBundle->SetFiberColors(fiberColors); - - result.push_back(fiberBundle.GetPointer()); - return result; + MITK_ERROR << "Fiber weight<0 detected! Setting value to 0."; + weights->SetValue(i,0); } + } + // if (!mitk::Equal(weights->GetValue(i),weight,0.00001)) + // { + // MITK_INFO << "Weight: " << weights->GetValue(i); + // weight = weights->GetValue(i); + // } + fiberBundle->SetFiberWeights(weights); } - else - MITK_INFO << "File is not VTK format."; + + vtkSmartPointer fiberColors = vtkUnsignedCharArray::SafeDownCast(fiberPolyData->GetPointData()->GetArray("FIBER_COLORS")); + if (fiberColors!=nullptr) + fiberBundle->SetFiberColors(fiberColors); + + result.push_back(fiberBundle.GetPointer()); + return result; + } } - catch(...) + else + MITK_INFO << "File is not VTK format."; + } + catch(...) + { + throw; + } + + try + { + MITK_INFO << "Trying to load fiber file as VTP format."; + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName( this->GetInputLocation().c_str() ); + + if ( reader->CanReadFile(this->GetInputLocation().c_str()) ) { - throw; - } + reader->Update(); - try - { - MITK_INFO << "Trying to load fiber file as VTP format."; - vtkSmartPointer reader = vtkSmartPointer::New(); - reader->SetFileName( this->GetInputLocation().c_str() ); + if ( reader->GetOutput() != nullptr ) + { + vtkSmartPointer fiberPolyData = reader->GetOutput(); + FiberBundle::Pointer fiberBundle = FiberBundle::New(fiberPolyData); - if ( reader->CanReadFile(this->GetInputLocation().c_str()) ) - { - reader->Update(); + vtkSmartPointer weights = vtkFloatArray::SafeDownCast(fiberPolyData->GetCellData()->GetArray("FIBER_WEIGHTS")); - if ( reader->GetOutput() != nullptr ) - { - vtkSmartPointer fiberPolyData = reader->GetOutput(); - FiberBundle::Pointer fiberBundle = FiberBundle::New(fiberPolyData); - - vtkSmartPointer weights = vtkFloatArray::SafeDownCast(fiberPolyData->GetCellData()->GetArray("FIBER_WEIGHTS")); - - if (weights!=nullptr) - { -// float weight=0; -// for (int i=0; iGetSize(); i++) -// if (!mitk::Equal(weights->GetValue(i),weight,0.00001)) -// { -// MITK_INFO << "Weight: " << weights->GetValue(i); -// weight = weights->GetValue(i); -// } - fiberBundle->SetFiberWeights(weights); - } - - vtkSmartPointer fiberColors = vtkUnsignedCharArray::SafeDownCast(fiberPolyData->GetPointData()->GetArray("FIBER_COLORS")); - if (fiberColors!=nullptr) - fiberBundle->SetFiberColors(fiberColors); - - result.push_back(fiberBundle.GetPointer()); - return result; - } + if (weights!=nullptr) + { + // float weight=0; + // for (int i=0; iGetSize(); i++) + // if (!mitk::Equal(weights->GetValue(i),weight,0.00001)) + // { + // MITK_INFO << "Weight: " << weights->GetValue(i); + // weight = weights->GetValue(i); + // } + fiberBundle->SetFiberWeights(weights); } - else - MITK_INFO << "File is not VTP format."; - } - catch(...) - { - throw; - } - try + vtkSmartPointer fiberColors = vtkUnsignedCharArray::SafeDownCast(fiberPolyData->GetPointData()->GetArray("FIBER_COLORS")); + if (fiberColors!=nullptr) + fiberBundle->SetFiberColors(fiberColors); + + result.push_back(fiberBundle.GetPointer()); + return result; + } + } + else + MITK_INFO << "File is not VTP format."; + } + catch(...) + { + throw; + } + + try + { + MITK_INFO << "Trying to load fiber file as deprecated XML format."; + vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); + vtkSmartPointer cellArray = vtkSmartPointer::New(); + vtkSmartPointer points = vtkSmartPointer::New(); + TiXmlDocument doc( this->GetInputLocation().c_str() ); + if(doc.LoadFile()) { - MITK_INFO << "Trying to load fiber file as deprecated XML format."; - vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); - vtkSmartPointer cellArray = vtkSmartPointer::New(); - vtkSmartPointer points = vtkSmartPointer::New(); - TiXmlDocument doc( this->GetInputLocation().c_str() ); - if(doc.LoadFile()) + TiXmlHandle hDoc(&doc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + pElem = hDoc.FirstChildElement().Element(); + // save this for later + hRoot = TiXmlHandle(pElem); + pElem = hRoot.FirstChildElement("geometry").Element(); + // read geometry + mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); + // read origin + mitk::Point3D origin; + double temp = 0; + pElem->Attribute("origin_x", &temp); + origin[0] = temp; + pElem->Attribute("origin_y", &temp); + origin[1] = temp; + pElem->Attribute("origin_z", &temp); + origin[2] = temp; + geometry->SetOrigin(origin); + // read spacing + ScalarType spacing[3]; + pElem->Attribute("spacing_x", &temp); + spacing[0] = temp; + pElem->Attribute("spacing_y", &temp); + spacing[1] = temp; + pElem->Attribute("spacing_z", &temp); + spacing[2] = temp; + geometry->SetSpacing(spacing); + // read transform + vtkMatrix4x4* m = vtkMatrix4x4::New(); + pElem->Attribute("xx", &temp); + m->SetElement(0,0,temp); + pElem->Attribute("xy", &temp); + m->SetElement(1,0,temp); + pElem->Attribute("xz", &temp); + m->SetElement(2,0,temp); + pElem->Attribute("yx", &temp); + m->SetElement(0,1,temp); + pElem->Attribute("yy", &temp); + m->SetElement(1,1,temp); + pElem->Attribute("yz", &temp); + m->SetElement(2,1,temp); + pElem->Attribute("zx", &temp); + m->SetElement(0,2,temp); + pElem->Attribute("zy", &temp); + m->SetElement(1,2,temp); + pElem->Attribute("zz", &temp); + m->SetElement(2,2,temp); + m->SetElement(0,3,origin[0]); + m->SetElement(1,3,origin[1]); + m->SetElement(2,3,origin[2]); + m->SetElement(3,3,1); + geometry->SetIndexToWorldTransformByVtkMatrix(m); + // read bounds + float bounds[] = {0, 0, 0, 0, 0, 0}; + pElem->Attribute("size_x", &temp); + bounds[1] = temp; + pElem->Attribute("size_y", &temp); + bounds[3] = temp; + pElem->Attribute("size_z", &temp); + bounds[5] = temp; + geometry->SetFloatBounds(bounds); + geometry->SetImageGeometry(true); + pElem = hRoot.FirstChildElement("fiber_bundle").FirstChild().Element(); + for( ; pElem ; pElem=pElem->NextSiblingElement()) + { + TiXmlElement* pElem2 = pElem->FirstChildElement(); + vtkSmartPointer container = vtkSmartPointer::New(); + for( ; pElem2; pElem2=pElem2->NextSiblingElement()) { - TiXmlHandle hDoc(&doc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - pElem = hDoc.FirstChildElement().Element(); - // save this for later - hRoot = TiXmlHandle(pElem); - pElem = hRoot.FirstChildElement("geometry").Element(); - // read geometry - mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); - // read origin - mitk::Point3D origin; - double temp = 0; - pElem->Attribute("origin_x", &temp); - origin[0] = temp; - pElem->Attribute("origin_y", &temp); - origin[1] = temp; - pElem->Attribute("origin_z", &temp); - origin[2] = temp; - geometry->SetOrigin(origin); - // read spacing - ScalarType spacing[3]; - pElem->Attribute("spacing_x", &temp); - spacing[0] = temp; - pElem->Attribute("spacing_y", &temp); - spacing[1] = temp; - pElem->Attribute("spacing_z", &temp); - spacing[2] = temp; - geometry->SetSpacing(spacing); - // read transform - vtkMatrix4x4* m = vtkMatrix4x4::New(); - pElem->Attribute("xx", &temp); - m->SetElement(0,0,temp); - pElem->Attribute("xy", &temp); - m->SetElement(1,0,temp); - pElem->Attribute("xz", &temp); - m->SetElement(2,0,temp); - pElem->Attribute("yx", &temp); - m->SetElement(0,1,temp); - pElem->Attribute("yy", &temp); - m->SetElement(1,1,temp); - pElem->Attribute("yz", &temp); - m->SetElement(2,1,temp); - pElem->Attribute("zx", &temp); - m->SetElement(0,2,temp); - pElem->Attribute("zy", &temp); - m->SetElement(1,2,temp); - pElem->Attribute("zz", &temp); - m->SetElement(2,2,temp); - m->SetElement(0,3,origin[0]); - m->SetElement(1,3,origin[1]); - m->SetElement(2,3,origin[2]); - m->SetElement(3,3,1); - geometry->SetIndexToWorldTransformByVtkMatrix(m); - // read bounds - float bounds[] = {0, 0, 0, 0, 0, 0}; - pElem->Attribute("size_x", &temp); - bounds[1] = temp; - pElem->Attribute("size_y", &temp); - bounds[3] = temp; - pElem->Attribute("size_z", &temp); - bounds[5] = temp; - geometry->SetFloatBounds(bounds); - geometry->SetImageGeometry(true); - pElem = hRoot.FirstChildElement("fiber_bundle").FirstChild().Element(); - for( ; pElem ; pElem=pElem->NextSiblingElement()) - { - TiXmlElement* pElem2 = pElem->FirstChildElement(); - vtkSmartPointer container = vtkSmartPointer::New(); - for( ; pElem2; pElem2=pElem2->NextSiblingElement()) - { - Point3D point; - pElem2->Attribute("pos_x", &temp); - point[0] = temp; - pElem2->Attribute("pos_y", &temp); - point[1] = temp; - pElem2->Attribute("pos_z", &temp); - point[2] = temp; - geometry->IndexToWorld(point, point); - vtkIdType id = points->InsertNextPoint(point.GetDataPointer()); - container->GetPointIds()->InsertNextId(id); - } - cellArray->InsertNextCell(container); - } - fiberPolyData->SetPoints(points); - fiberPolyData->SetLines(cellArray); - vtkSmartPointer cleaner = vtkSmartPointer::New(); - cleaner->SetInputData(fiberPolyData); - cleaner->Update(); - fiberPolyData = cleaner->GetOutput(); - FiberBundle::Pointer image = FiberBundle::New(fiberPolyData); - result.push_back(image.GetPointer()); - return result; - } - else - { - MITK_INFO << "File is not deprectaed XML format."; + Point3D point; + pElem2->Attribute("pos_x", &temp); + point[0] = temp; + pElem2->Attribute("pos_y", &temp); + point[1] = temp; + pElem2->Attribute("pos_z", &temp); + point[2] = temp; + geometry->IndexToWorld(point, point); + vtkIdType id = points->InsertNextPoint(point.GetDataPointer()); + container->GetPointIds()->InsertNextId(id); } - - setlocale(LC_ALL, currLocale.c_str()); - MITK_INFO << "Fiber bundle read"; + cellArray->InsertNextCell(container); + } + fiberPolyData->SetPoints(points); + fiberPolyData->SetLines(cellArray); + vtkSmartPointer cleaner = vtkSmartPointer::New(); + cleaner->SetInputData(fiberPolyData); + cleaner->Update(); + fiberPolyData = cleaner->GetOutput(); + FiberBundle::Pointer image = FiberBundle::New(fiberPolyData); + result.push_back(image.GetPointer()); + return result; } - catch(...) + else { - throw; + MITK_INFO << "File is not deprectaed XML format."; } - throw "Selected file is no vtk readable fiber format (binary or ascii vtk or vtp file)."; + setlocale(LC_ALL, currLocale.c_str()); + MITK_INFO << "Fiber bundle read"; + } + catch(...) + { + throw; + } + + throw "Selected file is no vtk readable fiber format (binary or ascii vtk or vtp file)."; - return result; + return result; } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.h index 7100f3ce67..807980d77a 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.h @@ -1,70 +1,68 @@ /*=================================================================== 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 _BUILDFIBRES #define _BUILDFIBRES // MITK #include #include // VTK #include #include #include #include #include #include #include -using namespace std; - namespace mitk { /** * \brief Gnerates actual fiber structure (vtkPolyData) from the particle grid content. */ class MITKFIBERTRACKING_EXPORT FiberBuilder { public: typedef itk::Image ItkFloatImageType; FiberBuilder(ParticleGrid* grid, ItkFloatImageType* image); ~FiberBuilder(); vtkSmartPointer iterate(int minFiberLength); protected: void AddPoint(Particle *dp, vtkSmartPointer container); void LabelPredecessors(Particle* p, int ep, vtkPolyLine* container); void LabelSuccessors(Particle* p, int ep, vtkPolyLine* container); itk::Point m_LastPoint; float m_FiberLength; ItkFloatImageType::Pointer m_Image; ParticleGrid* m_Grid; vtkSmartPointer m_VtkCellArray; vtkSmartPointer m_VtkPoints; }; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSimpSamp.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSimpSamp.h index 41a0068456..ba0389fe14 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSimpSamp.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSimpSamp.h @@ -1,124 +1,122 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _SIMPSAMP #define _SIMPSAMP #include #include #include -using namespace std; - namespace mitk { /** * \brief Samples new tract from surrounding fiber segments. */ class MITKFIBERTRACKING_EXPORT SimpSamp { float *P; int cnt; public: EndPoint* objs; SimpSamp() { P = (float*) malloc(sizeof(float)*1000); objs = (EndPoint*) malloc(sizeof(EndPoint)*1000); } ~SimpSamp() { free(P); free(objs); } inline void clear() { cnt = 1; P[0] = 0; } inline void add(float p, EndPoint obj) { P[cnt] = P[cnt-1] + p; objs[cnt-1] = obj; cnt++; } inline int draw(float prob) { float r = prob*P[cnt-1]; int j; int rl = 1; int rh = cnt-1; while(rh != rl) { j = rl + (rh-rl)/2; if (r < P[j]) { rh = j; continue; } if (r > P[j]) { rl = j+1; continue; } break; } return rh-1; } inline EndPoint drawObj(float prob) { return objs[draw(prob)]; } inline bool isempty() { if (cnt == 1) return true; else return false; } float probFor(int idx) { return (P[idx+1]-P[idx])/P[cnt-1]; } float probFor(EndPoint& t) { for (int i = 1; i< cnt;i++) { if (t == objs[i-1]) return probFor(i-1); } return 0; } }; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.cpp index a70444feda..79eee307fc 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.cpp @@ -1,173 +1,173 @@ /*=================================================================== 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 "mitkSphereInterpolator.h" #include #include #include #include #include #include #include #include static const std::string BaryCoordsFileName = "FiberTrackingLUTBaryCoords.bin"; static const std::string IndicesFileName = "FiberTrackingLUTIndices.bin"; -SphereInterpolator::SphereInterpolator(const string& lutPath) +SphereInterpolator::SphereInterpolator(const std::string& lutPath) { m_ValidState = true; if (lutPath.length()==0) { if (!LoadLookuptables()) { m_ValidState = false; return; } } else { if (!LoadLookuptables(lutPath)) { m_ValidState = false; return; } } size = 301; sN = (size-1)/2; nverts = ODF_SAMPLING_SIZE; beta = 0.5; inva = (sqrt(1+beta)-sqrt(beta)); b = 1/(1-sqrt(1/beta + 1)); } SphereInterpolator::~SphereInterpolator() { } -bool SphereInterpolator::LoadLookuptables(const string& lutPath) +bool SphereInterpolator::LoadLookuptables(const std::string& lutPath) { MITK_INFO << "SphereInterpolator: loading lookuptables from custom path: " << lutPath; - string path = lutPath; path.append(BaryCoordsFileName); + std::string path = lutPath; path.append(BaryCoordsFileName); std::ifstream BaryCoordsStream; BaryCoordsStream.open(path.c_str(), ios::in | ios::binary); MITK_INFO << "SphereInterpolator: 1 " << path; if (!BaryCoordsStream.is_open()) { MITK_INFO << "SphereInterpolator: could not load FiberTrackingLUTBaryCoords.bin from " << path; return false; } ifstream IndicesStream; path = lutPath; path.append("FiberTrackingLUTIndices.bin"); IndicesStream.open(path.c_str(), ios::in | ios::binary); MITK_INFO << "SphereInterpolator: 1 " << path; if (!IndicesStream.is_open()) { MITK_INFO << "SphereInterpolator: could not load FiberTrackingLUTIndices.bin from " << path; return false; } if (LoadLookuptables(BaryCoordsStream, IndicesStream)) { MITK_INFO << "SphereInterpolator: first and second lut loaded successfully"; return true; } return false; } bool SphereInterpolator::LoadLookuptables() { MITK_INFO << "SphereInterpolator: loading lookuptables"; us::Module* module = us::GetModuleContext()->GetModule(); us::ModuleResource BaryCoordsRes = module->GetResource(BaryCoordsFileName); if (!BaryCoordsRes.IsValid()) { MITK_INFO << "Could not retrieve resource " << BaryCoordsFileName; return false; } us::ModuleResource IndicesRes = module->GetResource(IndicesFileName); if (!IndicesRes) { MITK_INFO << "Could not retrieve resource " << IndicesFileName; return false; } us::ModuleResourceStream BaryCoordsStream(BaryCoordsRes, std::ios_base::binary); us::ModuleResourceStream IndicesStream(IndicesRes, std::ios_base::binary); return LoadLookuptables(BaryCoordsStream, IndicesStream); } bool SphereInterpolator::LoadLookuptables(std::istream& BaryCoordsStream, std::istream& IndicesStream) { if (BaryCoordsStream) { try { float tmp; BaryCoordsStream.seekg (0, ios::beg); while (!BaryCoordsStream.eof()) { BaryCoordsStream.read((char *)&tmp, sizeof(tmp)); barycoords.push_back(tmp); } } catch (const std::exception& e) { MITK_INFO << e.what(); } } else { MITK_INFO << "SphereInterpolator: could not load FiberTrackingLUTBaryCoords.bin"; return false; } if (IndicesStream) { try { int tmp; IndicesStream.seekg (0, ios::beg); while (!IndicesStream.eof()) { IndicesStream.read((char *)&tmp, sizeof(tmp)); indices.push_back(tmp); } } catch (const std::exception& e) { MITK_INFO << e.what(); } } else { MITK_INFO << "SphereInterpolator: could not load FiberTrackingLUTIndices.bin"; return false; } return true; } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.h index e4aeace36d..b4304c3d1f 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.h @@ -1,169 +1,164 @@ /*=================================================================== 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 _SPHEREINTERPOLATOR #define _SPHEREINTERPOLATOR #include - #include - #include -using namespace std; - - /** * \brief Lookuptable based trilinear interpolation of spherically arranged scalar values. */ class MITKFIBERTRACKING_EXPORT SphereInterpolator { public: int size; // size of LUT int sN; // (sizeofLUT-1)/2 int nverts; // number of data vertices float beta; float inva; float b; bool m_ValidState; - vector< float > barycoords; - vector< int > indices; + std::vector< float > barycoords; + std::vector< int > indices; vnl_vector_fixed< int, 3 > idx; vnl_vector_fixed< float, 3 > interpw; - SphereInterpolator(const string& lutPath); + SphereInterpolator(const std::string& lutPath); inline bool IsInValidState() const { return m_ValidState; } ~SphereInterpolator(); inline void getInterpolation(const vnl_vector_fixed& N) { float nx = N[0]; float ny = N[1]; float nz = N[2]; if (nz > 0.5) { int x = float2int(nx); int y = float2int(ny); int i = 3*6*(x+y*size); // (:,1,x,y) idx[0] = indices[i]; idx[1] = indices[i+1]; idx[2] = indices[i+2]; interpw[0] = barycoords[i]; interpw[1] = barycoords[i+1]; interpw[2] = barycoords[i+2]; return; } if (nz < -0.5) { int x = float2int(nx); int y = float2int(ny); int i = 3*(1+6*(x+y*size)); // (:,2,x,y) idx[0] = indices[i]; idx[1] = indices[i+1]; idx[2] = indices[i+2]; interpw[0] = barycoords[i]; interpw[1] = barycoords[i+1]; interpw[2] = barycoords[i+2]; return; } if (nx > 0.5) { int z = float2int(nz); int y = float2int(ny); int i = 3*(2+6*(z+y*size)); // (:,2,x,y) idx[0] = indices[i]; idx[1] = indices[i+1]; idx[2] = indices[i+2]; interpw[0] = barycoords[i]; interpw[1] = barycoords[i+1]; interpw[2] = barycoords[i+2]; return; } if (nx < -0.5) { int z = float2int(nz); int y = float2int(ny); int i = 3*(3+6*(z+y*size)); // (:,2,x,y) idx[0] = indices[i]; idx[1] = indices[i+1]; idx[2] = indices[i+2]; interpw[0] = barycoords[i]; interpw[1] = barycoords[i+1]; interpw[2] = barycoords[i+2]; return; } if (ny > 0) { int x = float2int(nx); int z = float2int(nz); int i = 3*(4+6*(x+z*size)); // (:,1,x,y) idx[0] = indices[i]; idx[1] = indices[i+1]; idx[2] = indices[i+2]; interpw[0] = barycoords[i]; interpw[1] = barycoords[i+1]; interpw[2] = barycoords[i+2]; return; } else { int x = float2int(nx); int z = float2int(nz); int i = 3*(5+6*(x+z*size)); // (:,1,x,y) idx[0] = indices[i]; idx[1] = indices[i+1]; idx[2] = indices[i+2]; interpw[0] = barycoords[i]; interpw[1] = barycoords[i+1]; interpw[2] = barycoords[i+2]; return; } } protected: - bool LoadLookuptables(const string& lutPath); + bool LoadLookuptables(const std::string& lutPath); bool LoadLookuptables(); bool LoadLookuptables(std::istream& BaryCoordsStream, std::istream& IndicesStream); inline float invrescale(float f) const { float x = (fabs(f)-b)*inva; if (f>0) return (x*x-beta); else return beta - x*x; } inline int float2int(float x) const { return int((invrescale(x)+1)*sN-0.5); } }; #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.h index a6b0c5cfa6..82c84a06a4 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.h @@ -1,83 +1,81 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef itkFiberCurvatureFilter_h #define itkFiberCurvatureFilter_h // MITK #include #include #include // ITK #include // VTK #include #include #include #include #include -using namespace std; - namespace itk{ /** -* \brief Generates artificial fibers distributed in and interpolated between the input planar figures. */ +* \brief */ class FiberCurvatureFilter : public ProcessObject { public: typedef FiberCurvatureFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( FiberCurvatureFilter, ProcessObject ) virtual void Update() override{ this->GenerateData(); } itkSetMacro( Distance, double ) itkSetMacro( AngularDeviation, double ) itkSetMacro( RemoveFibers, bool ) itkSetMacro( InputFiberBundle, FiberBundle::Pointer ) itkGetMacro( OutputFiberBundle, FiberBundle::Pointer ) protected: void GenerateData() override; FiberCurvatureFilter(); virtual ~FiberCurvatureFilter(); FiberBundle::Pointer m_InputFiberBundle; FiberBundle::Pointer m_OutputFiberBundle; double m_AngularDeviation; double m_Distance; bool m_RemoveFibers; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFiberCurvatureFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFitFibersToImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFitFibersToImageFilter.cpp index d9a719ec3d..0e143d3a09 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFitFibersToImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFitFibersToImageFilter.cpp @@ -1,437 +1,459 @@ #include "itkFitFibersToImageFilter.h" #include namespace itk{ FitFibersToImageFilter::FitFibersToImageFilter() : m_PeakImage(nullptr) , m_MaskImage(nullptr) , m_FitIndividualFibers(true) , m_GradientTolerance(1e-5) , m_Lambda(0.1) , m_MaxIterations(20) , m_FiberSampling(10) , m_Coverage(0) , m_Overshoot(0) + , m_RMSE(0.0) , m_FilterOutliers(true) , m_MeanWeight(1.0) , m_MedianWeight(1.0) , m_MinWeight(1.0) , m_MaxWeight(1.0) , m_Verbose(true) , m_DeepCopy(true) + , m_ResampleFibers(true) , m_NumUnknowns(0) , m_NumResiduals(0) , m_NumCoveredDirections(0) { this->SetNumberOfRequiredOutputs(3); } FitFibersToImageFilter::~FitFibersToImageFilter() { } void FitFibersToImageFilter::GenerateData() { int sz_x = m_PeakImage->GetLargestPossibleRegion().GetSize(0); int sz_y = m_PeakImage->GetLargestPossibleRegion().GetSize(1); int sz_z = m_PeakImage->GetLargestPossibleRegion().GetSize(2); int sz_peaks = m_PeakImage->GetLargestPossibleRegion().GetSize(3)/3 + 1; // +1 for zero - peak int num_voxels = sz_x*sz_y*sz_z; float minSpacing = 1; if(m_PeakImage->GetSpacing()[0]GetSpacing()[1] && m_PeakImage->GetSpacing()[0]GetSpacing()[2]) minSpacing = m_PeakImage->GetSpacing()[0]; else if (m_PeakImage->GetSpacing()[1] < m_PeakImage->GetSpacing()[2]) minSpacing = m_PeakImage->GetSpacing()[1]; else minSpacing = m_PeakImage->GetSpacing()[2]; m_NumUnknowns = m_Tractograms.size(); if (m_FitIndividualFibers) { m_NumUnknowns = 0; for (unsigned int bundle=0; bundleGetNumFibers(); } - for (unsigned int bundle=0; bundleGetDeepCopy(); - m_Tractograms.at(bundle)->ResampleLinear(minSpacing/m_FiberSampling); - } + if (m_ResampleFibers) + for (unsigned int bundle=0; bundleGetDeepCopy(); + m_Tractograms.at(bundle)->ResampleLinear(minSpacing/m_FiberSampling); + std::cout.rdbuf (old); + } m_NumResiduals = num_voxels * sz_peaks; MITK_INFO << "Num. unknowns: " << m_NumUnknowns; MITK_INFO << "Num. residuals: " << m_NumResiduals; MITK_INFO << "Creating system ..."; vnl_sparse_matrix A; vnl_vector b; A.set_size(m_NumResiduals, m_NumUnknowns); b.set_size(m_NumResiduals); b.fill(0.0); double TD = 0; double FD = 0; m_NumCoveredDirections = 0; unsigned int fiber_count = 0; for (unsigned int bundle=0; bundle polydata = m_Tractograms.at(bundle)->GetFiberPolyData(); for (int i=0; iGetNumFibers(); ++i) { vtkCell* cell = polydata->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (numPoints<2) MITK_INFO << "FIBER WITH ONLY ONE POINT ENCOUNTERED!"; for (int j=0; jGetPoint(j); PointType4 p; p[0]=p1[0]; p[1]=p1[1]; p[2]=p1[2]; p[3]=0; itk::Index<4> idx4; m_PeakImage->TransformPhysicalPointToIndex(p, idx4); itk::Index<3> idx3; idx3[0] = idx4[0]; idx3[1] = idx4[1]; idx3[2] = idx4[2]; if (!m_PeakImage->GetLargestPossibleRegion().IsInside(idx4) || (m_MaskImage.IsNotNull() && m_MaskImage->GetPixel(idx3)==0)) continue; double* p2 = points->GetPoint(j+1); vnl_vector_fixed fiber_dir; fiber_dir[0] = p[0]-p2[0]; fiber_dir[1] = p[1]-p2[1]; fiber_dir[2] = p[2]-p2[2]; fiber_dir.normalize(); double w = 1; int peak_id = sz_peaks-1; vnl_vector_fixed odf_peak = GetClosestPeak(idx4, m_PeakImage, fiber_dir, peak_id, w); float peak_mag = odf_peak.magnitude(); int x = idx4[0]; int y = idx4[1]; int z = idx4[2]; unsigned int linear_index = x + sz_x*y + sz_x*sz_y*z + sz_x*sz_y*sz_z*peak_id; if (b[linear_index] == 0 && peak_id<3) { m_NumCoveredDirections++; FD += peak_mag; } TD += w; if (m_FitIndividualFibers) { b[linear_index] = peak_mag; A.put(linear_index, fiber_count, A.get(linear_index, fiber_count) + w); } else { b[linear_index] = peak_mag; A.put(linear_index, bundle, A.get(linear_index, bundle) + w); } } ++fiber_count; } } TD /= (m_NumCoveredDirections*fiber_count); FD /= m_NumCoveredDirections; A /= TD; b *= 100.0/FD; // times 100 because we want to avoid too small values for computational reasons double init_lambda = fiber_count; // initialization for lambda estimation itk::TimeProbe clock; clock.Start(); VnlCostFunction cost(m_NumUnknowns); cost.SetProblem(A, b, init_lambda); m_Weights.set_size(m_NumUnknowns); // m_Weights.fill( TD/100.0 * FD/2.0 ); m_Weights.fill( 0.0 ); vnl_lbfgsb minimizer(cost); vnl_vector l; l.set_size(m_NumUnknowns); l.fill(0); vnl_vector bound_selection; bound_selection.set_size(m_NumUnknowns); bound_selection.fill(1); minimizer.set_bound_selection(bound_selection); minimizer.set_lower_bound(l); minimizer.set_projected_gradient_tolerance(m_GradientTolerance); MITK_INFO << "Estimating regularization"; minimizer.set_trace(false); minimizer.set_max_function_evals(2); minimizer.minimize(m_Weights); vnl_vector dx; dx.set_size(m_NumUnknowns); dx.fill(0.0); cost.grad_regu_localMSE(m_Weights, dx); double r = dx.magnitude()/m_Weights.magnitude(); cost.m_Lambda *= m_Lambda*55.0/r; MITK_INFO << r << " - " << m_Lambda*55.0/r; if (cost.m_Lambda>10e7) { MITK_INFO << "Regularization estimation failed. Using default value."; cost.m_Lambda = fiber_count; } MITK_INFO << "Using regularization factor of " << cost.m_Lambda << " (λ: " << m_Lambda << ")"; MITK_INFO << "Fitting fibers"; minimizer.set_trace(m_Verbose); minimizer.set_max_function_evals(m_MaxIterations); minimizer.minimize(m_Weights); std::vector< double > weights; if (m_FilterOutliers) { for (auto w : m_Weights) weights.push_back(w); std::sort(weights.begin(), weights.end()); MITK_INFO << "Setting upper weight bound to " << weights.at(m_NumUnknowns*0.99); vnl_vector u; u.set_size(m_NumUnknowns); u.fill(weights.at(m_NumUnknowns*0.99)); minimizer.set_upper_bound(u); bound_selection.fill(2); minimizer.set_bound_selection(bound_selection); minimizer.minimize(m_Weights); weights.clear(); } for (auto w : m_Weights) weights.push_back(w); std::sort(weights.begin(), weights.end()); m_MeanWeight = m_Weights.mean(); m_MedianWeight = weights.at(m_NumUnknowns*0.5); m_MinWeight = weights.at(0); m_MaxWeight = weights.at(m_NumUnknowns-1); MITK_INFO << "*************************"; MITK_INFO << "Weight statistics"; MITK_INFO << "Mean: " << m_MeanWeight; MITK_INFO << "Median: " << m_MedianWeight; MITK_INFO << "75% quantile: " << weights.at(m_NumUnknowns*0.75); MITK_INFO << "95% quantile: " << weights.at(m_NumUnknowns*0.95); MITK_INFO << "99% quantile: " << weights.at(m_NumUnknowns*0.99); MITK_INFO << "Min: " << m_MinWeight; MITK_INFO << "Max: " << m_MaxWeight; MITK_INFO << "*************************"; MITK_INFO << "NumEvals: " << minimizer.get_num_evaluations(); MITK_INFO << "NumIterations: " << minimizer.get_num_iterations(); MITK_INFO << "Residual cost: " << minimizer.get_end_error(); - MITK_INFO << "Final RMS: " << cost.S->get_rms_error(m_Weights); + m_RMSE = cost.S->get_rms_error(m_Weights); + MITK_INFO << "Final RMS: " << m_RMSE; clock.Stop(); int h = clock.GetTotal()/3600; int m = ((int)clock.GetTotal()%3600)/60; int s = (int)clock.GetTotal()%60; MITK_INFO << "Optimization took " << h << "h, " << m << "m and " << s << "s"; - // transform back for peak image creation - A *= FD/100.0; - b *= FD/100.0; - MITK_INFO << "Weighting fibers"; + m_RmsDiffPerFiber.set_size(m_Weights.size()); + m_RmsDiffPerBundle.set_size(m_Tractograms.size()); + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); if (m_FitIndividualFibers) { unsigned int fiber_count = 0; for (unsigned int bundle=0; bundle temp_weights; + temp_weights.set_size(m_Weights.size()); + temp_weights.copy_in(m_Weights.data_block()); + for (int i=0; iGetNumFibers(); i++) { m_Tractograms.at(bundle)->SetFiberWeight(i, m_Weights[fiber_count]); + temp_weights[fiber_count] = 0; + ++fiber_count; } + double d_rms = cost.S->get_rms_error(temp_weights) - m_RMSE; + m_RmsDiffPerBundle[bundle] = d_rms; m_Tractograms.at(bundle)->Compress(0.1); m_Tractograms.at(bundle)->ColorFibersByFiberWeights(false, true); } } else { for (unsigned int i=0; iSetFiberWeights(m_Weights[i]); m_Tractograms.at(i)->Compress(0.1); m_Tractograms.at(i)->ColorFibersByFiberWeights(false, true); } } + std::cout.rdbuf (old); + + // transform back for peak image creation + A *= FD/100.0; + b *= FD/100.0; MITK_INFO << "Generating output images ..."; itk::ImageDuplicator< PeakImgType >::Pointer duplicator = itk::ImageDuplicator< PeakImgType >::New(); duplicator->SetInputImage(m_PeakImage); duplicator->Update(); m_UnderexplainedImage = duplicator->GetOutput(); m_UnderexplainedImage->FillBuffer(0.0); duplicator->SetInputImage(m_UnderexplainedImage); duplicator->Update(); m_OverexplainedImage = duplicator->GetOutput(); m_OverexplainedImage->FillBuffer(0.0); duplicator->SetInputImage(m_OverexplainedImage); duplicator->Update(); m_ResidualImage = duplicator->GetOutput(); m_ResidualImage->FillBuffer(0.0); duplicator->SetInputImage(m_ResidualImage); duplicator->Update(); m_FittedImage = duplicator->GetOutput(); m_FittedImage->FillBuffer(0.0); vnl_vector fitted_b; fitted_b.set_size(b.size()); cost.S->multiply(m_Weights, fitted_b); for (unsigned int r=0; r idx4; unsigned int linear_index = r; idx4[0] = linear_index % sz_x; linear_index /= sz_x; idx4[1] = linear_index % sz_y; linear_index /= sz_y; idx4[2] = linear_index % sz_z; linear_index /= sz_z; int peak_id = linear_index % sz_peaks; if (peak_id peak_dir; idx4[3] = peak_id*3; peak_dir[0] = m_PeakImage->GetPixel(idx4); idx4[3] += 1; peak_dir[1] = m_PeakImage->GetPixel(idx4); idx4[3] += 1; peak_dir[2] = m_PeakImage->GetPixel(idx4); peak_dir.normalize(); peak_dir *= fitted_b[r]; idx4[3] = peak_id*3; m_FittedImage->SetPixel(idx4, peak_dir[0]); idx4[3] += 1; m_FittedImage->SetPixel(idx4, peak_dir[1]); idx4[3] += 1; m_FittedImage->SetPixel(idx4, peak_dir[2]); } } FD = 0; m_Coverage = 0; m_Overshoot = 0; itk::Index<4> idx4; for (idx4[0]=0; idx4[0] idx3; idx3[0] = idx4[0]; idx3[1] = idx4[1]; idx3[2] = idx4[2]; if (m_MaskImage.IsNotNull() && m_MaskImage->GetPixel(idx3)==0) continue; vnl_vector_fixed peak_dir; vnl_vector_fixed fitted_dir; vnl_vector_fixed overshoot_dir; for (idx4[3]=0; idx4[3]<(itk::IndexValueType)m_PeakImage->GetLargestPossibleRegion().GetSize(3); ++idx4[3]) { peak_dir[idx4[3]%3] = m_PeakImage->GetPixel(idx4); fitted_dir[idx4[3]%3] = m_FittedImage->GetPixel(idx4); m_ResidualImage->SetPixel(idx4, m_PeakImage->GetPixel(idx4) - m_FittedImage->GetPixel(idx4)); if (idx4[3]%3==2) { FD += peak_dir.magnitude(); itk::Index<4> tidx= idx4; if (peak_dir.magnitude()>fitted_dir.magnitude()) { m_Coverage += fitted_dir.magnitude(); m_UnderexplainedImage->SetPixel(tidx, peak_dir[2]-fitted_dir[2]); tidx[3]--; m_UnderexplainedImage->SetPixel(tidx, peak_dir[1]-fitted_dir[1]); tidx[3]--; m_UnderexplainedImage->SetPixel(tidx, peak_dir[0]-fitted_dir[0]); } else { overshoot_dir[0] = fitted_dir[0]-peak_dir[0]; overshoot_dir[1] = fitted_dir[1]-peak_dir[1]; overshoot_dir[2] = fitted_dir[2]-peak_dir[2]; m_Coverage += peak_dir.magnitude(); m_Overshoot += overshoot_dir.magnitude(); m_OverexplainedImage->SetPixel(tidx, overshoot_dir[2]); tidx[3]--; m_OverexplainedImage->SetPixel(tidx, overshoot_dir[1]); tidx[3]--; m_OverexplainedImage->SetPixel(tidx, overshoot_dir[0]); } } } } m_Coverage = m_Coverage/FD; m_Overshoot = m_Overshoot/FD; - MITK_INFO << std::fixed << "Coverage: " << setprecision(1) << 100.0*m_Coverage << "%"; - MITK_INFO << std::fixed << "Overshoot: " << setprecision(1) << 100.0*m_Overshoot << "%"; + MITK_INFO << std::fixed << "Coverage: " << setprecision(2) << 100.0*m_Coverage << "%"; + MITK_INFO << std::fixed << "Overshoot: " << setprecision(2) << 100.0*m_Overshoot << "%"; } vnl_vector_fixed FitFibersToImageFilter::GetClosestPeak(itk::Index<4> idx, PeakImgType::Pointer peak_image , vnl_vector_fixed fiber_dir, int& id, double& w ) { int m_NumDirs = peak_image->GetLargestPossibleRegion().GetSize()[3]/3; vnl_vector_fixed out_dir; out_dir.fill(0); - float angle = 0.8; + float angle = 0.9; for (int i=0; i dir; idx[3] = i*3; dir[0] = peak_image->GetPixel(idx); idx[3] += 1; dir[1] = peak_image->GetPixel(idx); idx[3] += 1; dir[2] = peak_image->GetPixel(idx); float mag = dir.magnitude(); if (magangle) { angle = fabs(a); w = angle; if (a<0) out_dir = -dir; else out_dir = dir; out_dir *= mag; id = i; } } return out_dir; } std::vector FitFibersToImageFilter::GetTractograms() const { return m_Tractograms; } void FitFibersToImageFilter::SetTractograms(const std::vector &tractograms) { m_Tractograms = tractograms; } } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFitFibersToImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFitFibersToImageFilter.h index 119d39e57d..5907d9e874 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFitFibersToImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFitFibersToImageFilter.h @@ -1,262 +1,271 @@ #ifndef __itkFitFibersToImageFilter_h__ #define __itkFitFibersToImageFilter_h__ // MITK #include #include #include #include #include #include #include #include #include namespace itk{ /** * \brief Fits the tractogram to the input peak image by assigning a weight to each fiber (similar to https://doi.org/10.1016/j.neuroimage.2015.06.092). */ class FitFibersToImageFilter : public ImageSource< mitk::PeakImage::ItkPeakImageType > { public: typedef FitFibersToImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef itk::Point PointType4; typedef mitk::PeakImage::ItkPeakImageType PeakImgType; typedef itk::Image UcharImgType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( FitFibersToImageFilter, ImageSource ) itkSetMacro( PeakImage, PeakImgType::Pointer) itkGetMacro( PeakImage, PeakImgType::Pointer) itkSetMacro( MaskImage, UcharImgType::Pointer) itkGetMacro( MaskImage, UcharImgType::Pointer) itkSetMacro( FitIndividualFibers, bool) itkGetMacro( FitIndividualFibers, bool) itkSetMacro( GradientTolerance, double) itkGetMacro( GradientTolerance, double) itkSetMacro( Lambda, double) itkGetMacro( Lambda, double) itkSetMacro( MaxIterations, int) itkGetMacro( MaxIterations, int) itkSetMacro( FiberSampling, float) itkGetMacro( FiberSampling, float) itkSetMacro( FilterOutliers, bool) itkGetMacro( FilterOutliers, bool) itkSetMacro( Verbose, bool) itkGetMacro( Verbose, bool) itkSetMacro( DeepCopy, bool) itkGetMacro( DeepCopy, bool) + itkSetMacro( ResampleFibers, bool) + itkGetMacro( ResampleFibers, bool) itkGetMacro( Weights, vnl_vector) + itkGetMacro( RmsDiffPerBundle, vnl_vector) + itkGetMacro( RmsDiffPerFiber, vnl_vector) itkGetMacro( FittedImage, PeakImgType::Pointer) itkGetMacro( ResidualImage, PeakImgType::Pointer) itkGetMacro( OverexplainedImage, PeakImgType::Pointer) itkGetMacro( UnderexplainedImage, PeakImgType::Pointer) itkGetMacro( Coverage, double) itkGetMacro( Overshoot, double) + itkGetMacro( RMSE, double) itkGetMacro( MeanWeight, double) itkGetMacro( MedianWeight, double) itkGetMacro( MinWeight, double) itkGetMacro( MaxWeight, double) itkGetMacro( NumUnknowns, unsigned int) itkGetMacro( NumResiduals, unsigned int) itkGetMacro( NumCoveredDirections, unsigned int) void SetTractograms(const std::vector &tractograms); void GenerateData() override; std::vector GetTractograms() const; protected: FitFibersToImageFilter(); virtual ~FitFibersToImageFilter(); vnl_vector_fixed GetClosestPeak(itk::Index<4> idx, PeakImgType::Pointer m_PeakImage , vnl_vector_fixed fiber_dir, int& id, double& w ); std::vector< mitk::FiberBundle::Pointer > m_Tractograms; PeakImgType::Pointer m_PeakImage; UcharImgType::Pointer m_MaskImage; bool m_FitIndividualFibers; double m_GradientTolerance; double m_Lambda; int m_MaxIterations; float m_FiberSampling; double m_Coverage; double m_Overshoot; + double m_RMSE; bool m_FilterOutliers; double m_MeanWeight; double m_MedianWeight; double m_MinWeight; double m_MaxWeight; bool m_Verbose; bool m_DeepCopy; + bool m_ResampleFibers; unsigned int m_NumUnknowns; unsigned int m_NumResiduals; unsigned int m_NumCoveredDirections; // output + vnl_vector m_RmsDiffPerBundle; vnl_vector m_Weights; + vnl_vector m_RmsDiffPerFiber; PeakImgType::Pointer m_UnderexplainedImage; PeakImgType::Pointer m_OverexplainedImage; PeakImgType::Pointer m_ResidualImage; PeakImgType::Pointer m_FittedImage; }; } class VnlCostFunction : public vnl_cost_function { public: vnl_sparse_matrix_linear_system< double >* S; vnl_sparse_matrix< double > m_A; vnl_sparse_matrix< double > m_A_Ones; // matrix indicating active weights with 1 vnl_vector< double > m_b; double m_Lambda; // regularization factor vnl_vector row_sums; // number of active weights per row vnl_vector local_weight_means; // mean weight of each row void SetProblem(vnl_sparse_matrix< double >& A, vnl_vector& b, double lambda) { S = new vnl_sparse_matrix_linear_system(A, b); m_A = A; m_b = b; m_Lambda = lambda; m_A_Ones.set_size(m_A.rows(), m_A.cols()); m_A.reset(); while (m_A.next()) m_A_Ones.put(m_A.getrow(), m_A.getcolumn(), 1); unsigned int N = m_b.size(); vnl_vector ones; ones.set_size(dim); ones.fill(1.0); row_sums.set_size(N); m_A_Ones.mult(ones, row_sums); local_weight_means.set_size(N); } VnlCostFunction(const int NumVars) : vnl_cost_function(NumVars) { } void regu_MSE(vnl_vector const &x, double& cost) { double mean = x.mean(); vnl_vector tx = x-mean; cost += m_Lambda*1e8*tx.squared_magnitude()/x.size(); } void regu_MSM(vnl_vector const &x, double& cost) { cost += m_Lambda*1e8*x.squared_magnitude()/x.size(); } void regu_localMSE(vnl_vector const &x, double& cost) { m_A_Ones.mult(x, local_weight_means); local_weight_means = element_quotient(local_weight_means, row_sums); m_A_Ones.reset(); double regu = 0; while (m_A_Ones.next()) { double d = 0; if (x[m_A_Ones.getcolumn()]>local_weight_means[m_A_Ones.getrow()]) d = std::exp(x[m_A_Ones.getcolumn()]) - std::exp(local_weight_means[m_A_Ones.getrow()]); else d = x[m_A_Ones.getcolumn()] - local_weight_means[m_A_Ones.getrow()]; regu += d*d; } cost += m_Lambda*regu/dim; } void grad_regu_MSE(vnl_vector const &x, vnl_vector &dx) { double mean = x.mean(); vnl_vector tx = x-mean; vnl_vector tx2(dim, 0.0); vnl_vector h(dim, 1.0); for (int c=0; c const &x, vnl_vector &dx) { dx += m_Lambda*1e8*2.0*x/dim; } void grad_regu_localMSE(vnl_vector const &x, vnl_vector &dx) { m_A_Ones.mult(x, local_weight_means); local_weight_means = element_quotient(local_weight_means, row_sums); vnl_vector exp_x = x.apply(std::exp); vnl_vector exp_means = local_weight_means.apply(std::exp); vnl_vector tdx(dim, 0); m_A_Ones.reset(); while (m_A_Ones.next()) { int c = m_A_Ones.getcolumn(); int r = m_A_Ones.getrow(); if (x[c]>local_weight_means[r]) tdx[c] += exp_x[c] * ( exp_x[c] - exp_means[r] ); else tdx[c] += x[c] - local_weight_means[r]; } dx += tdx*2.0*m_Lambda/dim; } double f(vnl_vector const &x) { double cost = S->get_rms_error(x); cost *= cost; regu_localMSE(x, cost); return cost; } void gradf(vnl_vector const &x, vnl_vector &dx) { dx.fill(0.0); unsigned int N = m_b.size(); vnl_vector d; d.set_size(N); S->multiply(x,d); d -= m_b; S->transpose_multiply(d, dx); dx *= 2.0/N; grad_regu_localMSE(x,dx); } }; #ifndef ITK_MANUAL_INSTANTIATION #include "itkFitFibersToImageFilter.cpp" #endif #endif // __itkFitFibersToImageFilter_h__ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkGibbsTrackingFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkGibbsTrackingFilter.cpp index 1b2165673d..e712c45e42 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkGibbsTrackingFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkGibbsTrackingFilter.cpp @@ -1,497 +1,497 @@ /*=================================================================== 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 "itkGibbsTrackingFilter.h" // MITK #include #include #include #include #include //#include #include #include // ITK #include #include #include // MISC #include // #include #include #include #include #include #include namespace itk{ template< class ItkOdfImageType > GibbsTrackingFilter< ItkOdfImageType >::GibbsTrackingFilter(): m_StartTemperature(0.1), m_EndTemperature(0.001), m_Iterations(1e9), m_CurrentIteration(0.0), m_CurrentStep(0), m_ParticleWeight(0), m_ParticleWidth(0), m_ParticleLength(0), m_ConnectionPotential(10), m_InexBalance(0), m_ParticlePotential(0.2), m_MinFiberLength(10), m_AbortTracking(false), m_NumAcceptedFibers(0), m_BuildFibers(false), m_ProposalAcceptance(0), m_CurvatureThreshold(0.7), m_DuplicateImage(true), m_NumParticles(0), m_NumConnections(0), m_RandomSeed(-1), m_LoadParameterFile(""), m_LutPath(""), m_IsInValidState(true) { } template< class ItkOdfImageType > GibbsTrackingFilter< ItkOdfImageType >::~GibbsTrackingFilter() { } // fill output fiber bundle datastructure template< class ItkOdfImageType > typename GibbsTrackingFilter< ItkOdfImageType >::FiberPolyDataType GibbsTrackingFilter< ItkOdfImageType >::GetFiberBundle() { if (!m_AbortTracking) { m_BuildFibers = true; while (m_BuildFibers){} } return m_FiberPolyData; } template< class ItkOdfImageType > void GibbsTrackingFilter< ItkOdfImageType > ::EstimateParticleWeight() { MITK_INFO << "GibbsTrackingFilter: estimating particle weight"; float minSpacing; if(m_OdfImage->GetSpacing()[0]GetSpacing()[1] && m_OdfImage->GetSpacing()[0]GetSpacing()[2]) minSpacing = m_OdfImage->GetSpacing()[0]; else if (m_OdfImage->GetSpacing()[1] < m_OdfImage->GetSpacing()[2]) minSpacing = m_OdfImage->GetSpacing()[1]; else minSpacing = m_OdfImage->GetSpacing()[2]; float m_ParticleLength = 1.5*minSpacing; float m_ParticleWidth = 0.5*minSpacing; // seed random generators Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); if (m_RandomSeed>-1) randGen->SetSeed(m_RandomSeed); else randGen->SetSeed(); // instantiate all necessary components SphereInterpolator* interpolator = new SphereInterpolator(m_LutPath); // handle lookup table not found cases if( !interpolator->IsInValidState() ) { m_IsInValidState = false; m_AbortTracking = true; m_BuildFibers = false; mitkThrow() << "Unable to load lookup tables."; } ParticleGrid* particleGrid = new ParticleGrid(m_MaskImage, m_ParticleLength, m_ParticleGridCellCapacity); GibbsEnergyComputer* encomp = new GibbsEnergyComputer(m_OdfImage, m_MaskImage, particleGrid, interpolator, randGen); // EnergyComputer* encomp = new EnergyComputer(m_OdfImage, m_MaskImage, particleGrid, interpolator, randGen); MetropolisHastingsSampler* sampler = new MetropolisHastingsSampler(particleGrid, encomp, randGen, m_CurvatureThreshold); float alpha = log(m_EndTemperature/m_StartTemperature); m_ParticleWeight = 0.01; int ppv = 0; // main loop int neededParts = 3000; while (ppvSetParameters(m_ParticleWeight,m_ParticleWidth,m_ConnectionPotential*m_ParticleLength*m_ParticleLength,m_CurvatureThreshold,m_InexBalance,m_ParticlePotential); for( int step = 0; step < 10; step++ ) { // update temperatur for simulated annealing process float temperature = m_StartTemperature * exp(alpha*(((1.0)*step)/((1.0)*10))); sampler->SetTemperature(temperature); for (unsigned long i=0; i<10000; i++) sampler->MakeProposal(); } ppv = particleGrid->m_NumParticles; particleGrid->ResetGrid(); } delete sampler; delete encomp; delete particleGrid; delete interpolator; MITK_INFO << "GibbsTrackingFilter: finished estimating particle weight"; } // perform global tracking template< class ItkOdfImageType > void GibbsTrackingFilter< ItkOdfImageType >::GenerateData() { TimeProbe preClock; preClock.Start(); // check if input is Odf or tensor image and generate Odf if necessary if (m_OdfImage.IsNull() && m_TensorImage.IsNotNull()) { TensorImageToOdfImageFilter::Pointer filter = TensorImageToOdfImageFilter::New(); filter->SetInput( m_TensorImage ); filter->Update(); m_OdfImage = filter->GetOutput(); } else if (m_DuplicateImage) // generate local working copy of Odf image (if not disabled) { typedef itk::ImageDuplicator< ItkOdfImageType > DuplicateFilterType; typename DuplicateFilterType::Pointer duplicator = DuplicateFilterType::New(); duplicator->SetInputImage( m_OdfImage ); duplicator->Update(); m_OdfImage = duplicator->GetOutput(); } // perform mean subtraction on odfs typedef ImageRegionIterator< ItkOdfImageType > InputIteratorType; InputIteratorType it(m_OdfImage, m_OdfImage->GetLargestPossibleRegion() ); it.GoToBegin(); while (!it.IsAtEnd()) { itk::OrientationDistributionFunction odf(it.Get().GetDataPointer()); float mean = odf.GetMeanValue(); odf -= mean; it.Set(odf.GetDataPointer()); ++it; } // check if mask image is given if it needs resampling PrepareMaskImage(); // load parameter file LoadParameters(); // prepare parameters float minSpacing; if(m_OdfImage->GetSpacing()[0]GetSpacing()[1] && m_OdfImage->GetSpacing()[0]GetSpacing()[2]) minSpacing = m_OdfImage->GetSpacing()[0]; else if (m_OdfImage->GetSpacing()[1] < m_OdfImage->GetSpacing()[2]) minSpacing = m_OdfImage->GetSpacing()[1]; else minSpacing = m_OdfImage->GetSpacing()[2]; if(m_ParticleLength == 0) m_ParticleLength = 1.5*minSpacing; if(m_ParticleWidth == 0) m_ParticleWidth = 0.5*minSpacing; if(m_ParticleWeight == 0) EstimateParticleWeight(); float alpha = log(m_EndTemperature/m_StartTemperature); if (m_CurvatureThreshold < mitk::eps) m_CurvatureThreshold = 0; // seed random generators Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); if (m_RandomSeed>-1) randGen->SetSeed(m_RandomSeed); else randGen->SetSeed(); // load sphere interpolator to evaluate the ODFs SphereInterpolator* interpolator = new SphereInterpolator(m_LutPath); // handle lookup table not found cases if( !interpolator->IsInValidState() ) { m_IsInValidState = false; m_AbortTracking = true; m_BuildFibers = false; mitkThrow() << "Unable to load lookup tables."; } // initialize the actual tracking components (ParticleGrid, Metropolis Hastings Sampler and Energy Computer) ParticleGrid* particleGrid; GibbsEnergyComputer* encomp; MetropolisHastingsSampler* sampler; try{ particleGrid = new ParticleGrid(m_MaskImage, m_ParticleLength, m_ParticleGridCellCapacity); encomp = new GibbsEnergyComputer(m_OdfImage, m_MaskImage, particleGrid, interpolator, randGen); encomp->SetParameters(m_ParticleWeight,m_ParticleWidth,m_ConnectionPotential*m_ParticleLength*m_ParticleLength,m_CurvatureThreshold,m_InexBalance,m_ParticlePotential); sampler = new MetropolisHastingsSampler(particleGrid, encomp, randGen, m_CurvatureThreshold); } catch(...) { MITK_ERROR << "Particle grid allocation failed. Not enough memory? Try to increase the particle length."; m_IsInValidState = false; m_AbortTracking = true; m_BuildFibers = false; return; } MITK_INFO << "----------------------------------------"; MITK_INFO << "Iterations: " << m_Iterations; MITK_INFO << "Particle length: " << m_ParticleLength; MITK_INFO << "Particle width: " << m_ParticleWidth; MITK_INFO << "Particle weight: " << m_ParticleWeight; MITK_INFO << "Start temperature: " << m_StartTemperature; MITK_INFO << "End temperature: " << m_EndTemperature; MITK_INFO << "In/Ex balance: " << m_InexBalance; MITK_INFO << "Min. fiber length: " << m_MinFiberLength; MITK_INFO << "Curvature threshold: " << m_CurvatureThreshold; MITK_INFO << "Random seed: " << m_RandomSeed; MITK_INFO << "----------------------------------------"; // main loop preClock.Stop(); TimeProbe clock; clock.Start(); m_NumAcceptedFibers = 0; m_CurrentIteration = 0; bool just_built_fibers = false; boost::progress_display disp(m_Iterations); if (!m_AbortTracking) while (m_CurrentIterationSetTemperature(temperature); sampler->MakeProposal(); m_ProposalAcceptance = (float)sampler->GetNumAcceptedProposals()/m_CurrentIteration; m_NumParticles = particleGrid->m_NumParticles; m_NumConnections = particleGrid->m_NumConnections; if (m_AbortTracking) break; if (m_BuildFibers) { FiberBuilder fiberBuilder(particleGrid, m_MaskImage); m_FiberPolyData = fiberBuilder.iterate(m_MinFiberLength); m_NumAcceptedFibers = m_FiberPolyData->GetNumberOfLines(); m_BuildFibers = false; just_built_fibers = true; } } if (!just_built_fibers) { FiberBuilder fiberBuilder(particleGrid, m_MaskImage); m_FiberPolyData = fiberBuilder.iterate(m_MinFiberLength); m_NumAcceptedFibers = m_FiberPolyData->GetNumberOfLines(); } clock.Stop(); delete sampler; delete encomp; delete interpolator; delete particleGrid; m_AbortTracking = true; m_BuildFibers = false; int h = clock.GetTotal()/3600; int m = ((int)clock.GetTotal()%3600)/60; int s = (int)clock.GetTotal()%60; MITK_INFO << "GibbsTrackingFilter: finished gibbs tracking in " << h << "h, " << m << "m and " << s << "s"; m = (int)preClock.GetTotal()/60; s = (int)preClock.GetTotal()%60; MITK_INFO << "GibbsTrackingFilter: preparation of the data took " << m << "m and " << s << "s"; MITK_INFO << "GibbsTrackingFilter: " << m_NumAcceptedFibers << " fibers accepted"; // sampler->PrintProposalTimes(); SaveParameters(); } template< class ItkOdfImageType > void GibbsTrackingFilter< ItkOdfImageType >::PrepareMaskImage() { if(m_MaskImage.IsNull()) { MITK_INFO << "GibbsTrackingFilter: generating default mask image"; m_MaskImage = ItkFloatImageType::New(); m_MaskImage->SetSpacing( m_OdfImage->GetSpacing() ); m_MaskImage->SetOrigin( m_OdfImage->GetOrigin() ); m_MaskImage->SetDirection( m_OdfImage->GetDirection() ); m_MaskImage->SetRegions( m_OdfImage->GetLargestPossibleRegion() ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1.0); } else if ( m_MaskImage->GetLargestPossibleRegion().GetSize()[0]!=m_OdfImage->GetLargestPossibleRegion().GetSize()[0] || m_MaskImage->GetLargestPossibleRegion().GetSize()[1]!=m_OdfImage->GetLargestPossibleRegion().GetSize()[1] || m_MaskImage->GetLargestPossibleRegion().GetSize()[2]!=m_OdfImage->GetLargestPossibleRegion().GetSize()[2] || m_MaskImage->GetSpacing()[0]!=m_OdfImage->GetSpacing()[0] || m_MaskImage->GetSpacing()[1]!=m_OdfImage->GetSpacing()[1] || m_MaskImage->GetSpacing()[2]!=m_OdfImage->GetSpacing()[2] ) { MITK_INFO << "GibbsTrackingFilter: resampling mask image"; typedef itk::ResampleImageFilter< ItkFloatImageType, ItkFloatImageType, float > ResamplerType; ResamplerType::Pointer resampler = ResamplerType::New(); resampler->SetOutputSpacing( m_OdfImage->GetSpacing() ); resampler->SetOutputOrigin( m_OdfImage->GetOrigin() ); resampler->SetOutputDirection( m_OdfImage->GetDirection() ); resampler->SetSize( m_OdfImage->GetLargestPossibleRegion().GetSize() ); resampler->SetInput( m_MaskImage ); resampler->SetDefaultPixelValue(0.0); resampler->Update(); m_MaskImage = resampler->GetOutput(); MITK_INFO << "GibbsTrackingFilter: resampling finished"; } } // load tracking paramters from xml file (.gtp) template< class ItkOdfImageType > bool GibbsTrackingFilter< ItkOdfImageType >::LoadParameters() { m_AbortTracking = true; try { if( m_LoadParameterFile.length()==0 ) { m_AbortTracking = false; return true; } MITK_INFO << "GibbsTrackingFilter: loading parameter file " << m_LoadParameterFile; TiXmlDocument doc( m_LoadParameterFile ); doc.LoadFile(); TiXmlHandle hDoc(&doc); TiXmlElement* pElem; TiXmlHandle hRoot(0); pElem = hDoc.FirstChildElement().Element(); hRoot = TiXmlHandle(pElem); pElem = hRoot.FirstChildElement("parameter_set").Element(); - string iterations(pElem->Attribute("iterations")); + std::string iterations(pElem->Attribute("iterations")); m_Iterations = boost::lexical_cast(iterations); - string particleLength(pElem->Attribute("particle_length")); + std::string particleLength(pElem->Attribute("particle_length")); m_ParticleLength = boost::lexical_cast(particleLength); - string particleWidth(pElem->Attribute("particle_width")); + std::string particleWidth(pElem->Attribute("particle_width")); m_ParticleWidth = boost::lexical_cast(particleWidth); - string partWeight(pElem->Attribute("particle_weight")); + std::string partWeight(pElem->Attribute("particle_weight")); m_ParticleWeight = boost::lexical_cast(partWeight); - string startTemp(pElem->Attribute("temp_start")); + std::string startTemp(pElem->Attribute("temp_start")); m_StartTemperature = boost::lexical_cast(startTemp); - string endTemp(pElem->Attribute("temp_end")); + std::string endTemp(pElem->Attribute("temp_end")); m_EndTemperature = boost::lexical_cast(endTemp); - string inExBalance(pElem->Attribute("inexbalance")); + std::string inExBalance(pElem->Attribute("inexbalance")); m_InexBalance = boost::lexical_cast(inExBalance); - string fiberLength(pElem->Attribute("fiber_length")); + std::string fiberLength(pElem->Attribute("fiber_length")); m_MinFiberLength = boost::lexical_cast(fiberLength); - string curvThres(pElem->Attribute("curvature_threshold")); + std::string curvThres(pElem->Attribute("curvature_threshold")); m_CurvatureThreshold = cos(boost::lexical_cast(curvThres)*M_PI/180); m_AbortTracking = false; MITK_INFO << "GibbsTrackingFilter: parameter file loaded successfully"; return true; } catch(...) { MITK_INFO << "GibbsTrackingFilter: could not load parameter file"; return false; } } // save current tracking paramters to xml file (.gtp) template< class ItkOdfImageType > bool GibbsTrackingFilter< ItkOdfImageType >::SaveParameters() { try { if( m_SaveParameterFile.length()==0 ) { MITK_INFO << "GibbsTrackingFilter: no filename specified to save parameters"; return true; } MITK_INFO << "GibbsTrackingFilter: saving parameter file " << m_SaveParameterFile; TiXmlDocument documentXML; TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); documentXML.LinkEndChild( declXML ); TiXmlElement* mainXML = new TiXmlElement("global_tracking_parameter_file"); mainXML->SetAttribute("file_version", "0.1"); documentXML.LinkEndChild(mainXML); TiXmlElement* paramXML = new TiXmlElement("parameter_set"); - paramXML->SetAttribute("iterations", boost::lexical_cast(m_Iterations)); - paramXML->SetAttribute("particle_length", boost::lexical_cast(m_ParticleLength)); - paramXML->SetAttribute("particle_width", boost::lexical_cast(m_ParticleWidth)); - paramXML->SetAttribute("particle_weight", boost::lexical_cast(m_ParticleWeight)); - paramXML->SetAttribute("temp_start", boost::lexical_cast(m_StartTemperature)); - paramXML->SetAttribute("temp_end", boost::lexical_cast(m_EndTemperature)); - paramXML->SetAttribute("inexbalance", boost::lexical_cast(m_InexBalance)); - paramXML->SetAttribute("fiber_length", boost::lexical_cast(m_MinFiberLength)); - paramXML->SetAttribute("curvature_threshold", boost::lexical_cast(m_CurvatureThreshold)); + paramXML->SetAttribute("iterations", boost::lexical_cast(m_Iterations)); + paramXML->SetAttribute("particle_length", boost::lexical_cast(m_ParticleLength)); + paramXML->SetAttribute("particle_width", boost::lexical_cast(m_ParticleWidth)); + paramXML->SetAttribute("particle_weight", boost::lexical_cast(m_ParticleWeight)); + paramXML->SetAttribute("temp_start", boost::lexical_cast(m_StartTemperature)); + paramXML->SetAttribute("temp_end", boost::lexical_cast(m_EndTemperature)); + paramXML->SetAttribute("inexbalance", boost::lexical_cast(m_InexBalance)); + paramXML->SetAttribute("fiber_length", boost::lexical_cast(m_MinFiberLength)); + paramXML->SetAttribute("curvature_threshold", boost::lexical_cast(m_CurvatureThreshold)); mainXML->LinkEndChild(paramXML); if(!boost::algorithm::ends_with(m_SaveParameterFile, ".gtp")) m_SaveParameterFile.append(".gtp"); documentXML.SaveFile( m_SaveParameterFile ); MITK_INFO << "GibbsTrackingFilter: parameter file saved successfully"; return true; } catch(...) { MITK_INFO << "GibbsTrackingFilter: could not save parameter file"; return false; } } } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp index 43076fa0b3..4aa60074cd 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp @@ -1,251 +1,273 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Coindex[1]right (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkTractDensityImageFilter.h" // VTK #include #include #include #include // misc #include #include namespace itk{ template< class OutputImageType > TractDensityImageFilter< OutputImageType >::TractDensityImageFilter() - : m_UpsamplingFactor(1) - , m_InvertImage(false) - , m_BinaryOutput(false) - , m_UseImageGeometry(false) - , m_OutputAbsoluteValues(false) - , m_UseTrilinearInterpolation(false) - , m_DoFiberResampling(true) - , m_WorkOnFiberCopy(true) - , m_MaxDensity(0) + : m_UpsamplingFactor(1) + , m_InvertImage(false) + , m_BinaryOutput(false) + , m_UseImageGeometry(false) + , m_OutputAbsoluteValues(false) + , m_UseTrilinearInterpolation(false) + , m_DoFiberResampling(true) + , m_WorkOnFiberCopy(true) + , m_MaxDensity(0) + , m_NumCoveredVoxels(0) { } template< class OutputImageType > TractDensityImageFilter< OutputImageType >::~TractDensityImageFilter() { } template< class OutputImageType > itk::Point TractDensityImageFilter< OutputImageType >::GetItkPoint(double point[3]) { - itk::Point itkPoint; - itkPoint[0] = point[0]; - itkPoint[1] = point[1]; - itkPoint[2] = point[2]; - return itkPoint; + itk::Point itkPoint; + itkPoint[0] = point[0]; + itkPoint[1] = point[1]; + itkPoint[2] = point[2]; + return itkPoint; } template< class OutputImageType > void TractDensityImageFilter< OutputImageType >::GenerateData() { - // generate upsampled image - mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry(); - typename OutputImageType::Pointer outImage = this->GetOutput(); - - // calculate new image parameters - itk::Vector newSpacing; - mitk::Point3D newOrigin; - itk::Matrix newDirection; - ImageRegion<3> upsampledRegion; - if (m_UseImageGeometry && !m_InputImage.IsNull()) + // generate upsampled image + mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry(); + typename OutputImageType::Pointer outImage = this->GetOutput(); + + // calculate new image parameters + itk::Vector newSpacing; + mitk::Point3D newOrigin; + itk::Matrix newDirection; + ImageRegion<3> upsampledRegion; + if (m_UseImageGeometry && !m_InputImage.IsNull()) + { + MITK_INFO << "TractDensityImageFilter: using image geometry"; + newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor; + upsampledRegion = m_InputImage->GetLargestPossibleRegion(); + newOrigin = m_InputImage->GetOrigin(); + typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize(); + size[0] *= m_UpsamplingFactor; + size[1] *= m_UpsamplingFactor; + size[2] *= m_UpsamplingFactor; + upsampledRegion.SetSize(size); + newDirection = m_InputImage->GetDirection(); + } + else + { + MITK_INFO << "TractDensityImageFilter: using fiber bundle geometry"; + newSpacing = geometry->GetSpacing()/m_UpsamplingFactor; + newOrigin = geometry->GetOrigin(); + mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); + + // we retrieve the origin from a vtk-polydata (corner-based) and hance have to translate it to an image geometry + // i.e. center-based + newOrigin[0] += bounds.GetElement(0) + 0.5 * newSpacing[0]; + newOrigin[1] += bounds.GetElement(2) + 0.5 * newSpacing[1]; + newOrigin[2] += bounds.GetElement(4) + 0.5 * newSpacing[2]; + + for (int i=0; i<3; i++) + for (int j=0; j<3; j++) + newDirection[j][i] = geometry->GetMatrixColumn(i)[j]; + upsampledRegion.SetSize(0, ceil( geometry->GetExtent(0)*m_UpsamplingFactor ) ); + upsampledRegion.SetSize(1, ceil( geometry->GetExtent(1)*m_UpsamplingFactor ) ); + upsampledRegion.SetSize(2, ceil( geometry->GetExtent(2)*m_UpsamplingFactor ) ); + } + typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); + + // apply new image parameters + outImage->SetSpacing( newSpacing ); + outImage->SetOrigin( newOrigin ); + outImage->SetDirection( newDirection ); + outImage->SetLargestPossibleRegion( upsampledRegion ); + outImage->SetBufferedRegion( upsampledRegion ); + outImage->SetRequestedRegion( upsampledRegion ); + outImage->Allocate(); + outImage->FillBuffer(0.0); + + int w = upsampledSize[0]; + int h = upsampledSize[1]; + int d = upsampledSize[2]; + + // set/initialize output + OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer(); + + // resample fiber bundle + float minSpacing = 1; + if(newSpacing[0]GetDeepCopy(); + m_FiberBundle->ResampleLinear(minSpacing/10); + } + + MITK_INFO << "TractDensityImageFilter: starting image generation"; + + vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); + + int numFibers = m_FiberBundle->GetNumFibers(); + boost::progress_display disp(numFibers); + for( int i=0; iGetCell(i); + int numPoints = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); + + float weight = m_FiberBundle->GetFiberWeight(i); + + // fill output image + for( int j=0; jGetSpacing()/m_UpsamplingFactor; - upsampledRegion = m_InputImage->GetLargestPossibleRegion(); - newOrigin = m_InputImage->GetOrigin(); - typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize(); - size[0] *= m_UpsamplingFactor; - size[1] *= m_UpsamplingFactor; - size[2] *= m_UpsamplingFactor; - upsampledRegion.SetSize(size); - newDirection = m_InputImage->GetDirection(); + itk::Point vertex = GetItkPoint(points->GetPoint(j)); + itk::Index<3> index; + itk::ContinuousIndex contIndex; + outImage->TransformPhysicalPointToIndex(vertex, index); + outImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); + + if (!m_UseTrilinearInterpolation && outImage->GetLargestPossibleRegion().IsInside(index)) + { + if (outImage->GetPixel(index)==0) + m_NumCoveredVoxels++; + + if (m_BinaryOutput) + outImage->SetPixel(index, 1); + else + outImage->SetPixel(index, outImage->GetPixel(index)+weight); + continue; + } + + float frac_x = contIndex[0] - index[0]; + float frac_y = contIndex[1] - index[1]; + float frac_z = contIndex[2] - index[2]; + + if (frac_x<0) + { + index[0] -= 1; + frac_x += 1; + } + if (frac_y<0) + { + index[1] -= 1; + frac_y += 1; + } + if (frac_z<0) + { + index[2] -= 1; + frac_z += 1; + } + + frac_x = 1-frac_x; + frac_y = 1-frac_y; + frac_z = 1-frac_z; + + // int coordinates inside image? + if (index[0] < 0 || index[0] >= w-1) + continue; + if (index[1] < 0 || index[1] >= h-1) + continue; + if (index[2] < 0 || index[2] >= d-1) + continue; + + + if (outImageBufferPointer[( index[0] + w*(index[1] + h*index[2] ))]==0) + m_NumCoveredVoxels++; + if (outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2] ))]==0) + m_NumCoveredVoxels++; + if (outImageBufferPointer[( index[0] + w*(index[1] + h*index[2]+h))]==0) + m_NumCoveredVoxels++; + if (outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2]+h))]==0) + m_NumCoveredVoxels++; + if (outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2] ))]==0) + m_NumCoveredVoxels++; + if (outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2]+h))]==0) + m_NumCoveredVoxels++; + if (outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2] ))]==0) + m_NumCoveredVoxels++; + if (outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2]+h))]==0) + m_NumCoveredVoxels++; + + if (m_BinaryOutput) + { + outImageBufferPointer[( index[0] + w*(index[1] + h*index[2] ))] = 1; + outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2] ))] = 1; + outImageBufferPointer[( index[0] + w*(index[1] + h*index[2]+h))] = 1; + outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2]+h))] = 1; + outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2] ))] = 1; + outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2]+h))] = 1; + outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2] ))] = 1; + outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2]+h))] = 1; + } + else + { + outImageBufferPointer[( index[0] + w*(index[1] + h*index[2] ))] += ( frac_x)*( frac_y)*( frac_z); + outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2] ))] += ( frac_x)*(1-frac_y)*( frac_z); + outImageBufferPointer[( index[0] + w*(index[1] + h*index[2]+h))] += ( frac_x)*( frac_y)*(1-frac_z); + outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2]+h))] += ( frac_x)*(1-frac_y)*(1-frac_z); + outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2] ))] += (1-frac_x)*( frac_y)*( frac_z); + outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2]+h))] += (1-frac_x)*( frac_y)*(1-frac_z); + outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2] ))] += (1-frac_x)*(1-frac_y)*( frac_z); + outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2]+h))] += (1-frac_x)*(1-frac_y)*(1-frac_z); + } } - else - { - MITK_INFO << "TractDensityImageFilter: using fiber bundle geometry"; - newSpacing = geometry->GetSpacing()/m_UpsamplingFactor; - newOrigin = geometry->GetOrigin(); - mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); - - // we retrieve the origin from a vtk-polydata (corner-based) and hance have to translate it to an image geometry - // i.e. center-based - newOrigin[0] += bounds.GetElement(0) + 0.5 * newSpacing[0]; - newOrigin[1] += bounds.GetElement(2) + 0.5 * newSpacing[1]; - newOrigin[2] += bounds.GetElement(4) + 0.5 * newSpacing[2]; - - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - newDirection[j][i] = geometry->GetMatrixColumn(i)[j]; - upsampledRegion.SetSize(0, ceil( geometry->GetExtent(0)*m_UpsamplingFactor ) ); - upsampledRegion.SetSize(1, ceil( geometry->GetExtent(1)*m_UpsamplingFactor ) ); - upsampledRegion.SetSize(2, ceil( geometry->GetExtent(2)*m_UpsamplingFactor ) ); - } - typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); - - // apply new image parameters - outImage->SetSpacing( newSpacing ); - outImage->SetOrigin( newOrigin ); - outImage->SetDirection( newDirection ); - outImage->SetLargestPossibleRegion( upsampledRegion ); - outImage->SetBufferedRegion( upsampledRegion ); - outImage->SetRequestedRegion( upsampledRegion ); - outImage->Allocate(); - outImage->FillBuffer(0.0); - - int w = upsampledSize[0]; - int h = upsampledSize[1]; - int d = upsampledSize[2]; - - // set/initialize output - OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer(); - - // resample fiber bundle - float minSpacing = 1; - if(newSpacing[0]GetDeepCopy(); - m_FiberBundle->ResampleLinear(minSpacing/10); - } - - MITK_INFO << "TractDensityImageFilter: starting image generation"; - - vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); - - int numFibers = m_FiberBundle->GetNumFibers(); - boost::progress_display disp(numFibers); - for( int i=0; iGetCell(i); - int numPoints = cell->GetNumberOfPoints(); - vtkPoints* points = cell->GetPoints(); - - float weight = m_FiberBundle->GetFiberWeight(i); - - // fill output image - for( int j=0; j vertex = GetItkPoint(points->GetPoint(j)); - itk::Index<3> index; - itk::ContinuousIndex contIndex; - outImage->TransformPhysicalPointToIndex(vertex, index); - outImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); - - if (!m_UseTrilinearInterpolation && outImage->GetLargestPossibleRegion().IsInside(index)) - { - if (m_BinaryOutput) - outImage->SetPixel(index, 1); - else - outImage->SetPixel(index, outImage->GetPixel(index)+weight); - continue; - } - - float frac_x = contIndex[0] - index[0]; - float frac_y = contIndex[1] - index[1]; - float frac_z = contIndex[2] - index[2]; - - if (frac_x<0) - { - index[0] -= 1; - frac_x += 1; - } - if (frac_y<0) - { - index[1] -= 1; - frac_y += 1; - } - if (frac_z<0) - { - index[2] -= 1; - frac_z += 1; - } - - frac_x = 1-frac_x; - frac_y = 1-frac_y; - frac_z = 1-frac_z; - - // int coordinates inside image? - if (index[0] < 0 || index[0] >= w-1) - continue; - if (index[1] < 0 || index[1] >= h-1) - continue; - if (index[2] < 0 || index[2] >= d-1) - continue; - - if (m_BinaryOutput) - { - outImageBufferPointer[( index[0] + w*(index[1] + h*index[2] ))] = 1; - outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2] ))] = 1; - outImageBufferPointer[( index[0] + w*(index[1] + h*index[2]+h))] = 1; - outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2]+h))] = 1; - outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2] ))] = 1; - outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2]+h))] = 1; - outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2] ))] = 1; - outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2]+h))] = 1; - } - else - { - outImageBufferPointer[( index[0] + w*(index[1] + h*index[2] ))] += ( frac_x)*( frac_y)*( frac_z); - outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2] ))] += ( frac_x)*(1-frac_y)*( frac_z); - outImageBufferPointer[( index[0] + w*(index[1] + h*index[2]+h))] += ( frac_x)*( frac_y)*(1-frac_z); - outImageBufferPointer[( index[0] + w*(index[1]+1+ h*index[2]+h))] += ( frac_x)*(1-frac_y)*(1-frac_z); - outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2] ))] += (1-frac_x)*( frac_y)*( frac_z); - outImageBufferPointer[( index[0]+1 + w*(index[1] + h*index[2]+h))] += (1-frac_x)*( frac_y)*(1-frac_z); - outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2] ))] += (1-frac_x)*(1-frac_y)*( frac_z); - outImageBufferPointer[( index[0]+1 + w*(index[1]+1+ h*index[2]+h))] += (1-frac_x)*(1-frac_y)*(1-frac_z); - } - } - } - - m_MaxDensity = 0; + } + + m_MaxDensity = 0; + for (int i=0; i0) + for (int i=0; i0) - for (int i=0; i #include #include #include #include namespace itk{ /** * \brief Generates tract density images from input fiberbundles (Calamante 2010). */ template< class OutputImageType > class TractDensityImageFilter : public ImageSource< OutputImageType > { public: typedef TractDensityImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename OutputImageType::PixelType OutPixelType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( TractDensityImageFilter, ImageSource ) itkSetMacro( UpsamplingFactor, float) ///< use higher resolution for ouput image itkGetMacro( UpsamplingFactor, float) ///< use higher resolution for ouput image itkSetMacro( InvertImage, bool) ///< voxelvalue = 1-voxelvalue itkGetMacro( InvertImage, bool) ///< voxelvalue = 1-voxelvalue itkSetMacro( BinaryOutput, bool) ///< generate binary fiber envelope itkGetMacro( BinaryOutput, bool) ///< generate binary fiber envelope itkSetMacro( OutputAbsoluteValues, bool) ///< output absolute values of the number of fibers per voxel itkGetMacro( OutputAbsoluteValues, bool) ///< output absolute values of the number of fibers per voxel itkSetMacro( UseImageGeometry, bool) ///< use input image geometry to initialize output image itkGetMacro( UseImageGeometry, bool) ///< use input image geometry to initialize output image itkSetMacro( FiberBundle, mitk::FiberBundle::Pointer) ///< input fiber bundle itkSetMacro( InputImage, typename OutputImageType::Pointer) ///< use input image geometry to initialize output image itkSetMacro( UseTrilinearInterpolation, bool ) itkSetMacro( DoFiberResampling, bool ) itkSetMacro( WorkOnFiberCopy, bool ) itkGetMacro( MaxDensity, OutPixelType) + itkGetMacro( NumCoveredVoxels, unsigned int) void GenerateData(); protected: itk::Point GetItkPoint(double point[3]); TractDensityImageFilter(); virtual ~TractDensityImageFilter(); typename OutputImageType::Pointer m_InputImage; ///< use input image geometry to initialize output image mitk::FiberBundle::Pointer m_FiberBundle; ///< input fiber bundle float m_UpsamplingFactor; ///< use higher resolution for ouput image bool m_InvertImage; ///< voxelvalue = 1-voxelvalue bool m_BinaryOutput; ///< generate binary fiber envelope bool m_UseImageGeometry; ///< use input image geometry to initialize output image bool m_OutputAbsoluteValues; ///< do not normalize image values to 0-1 bool m_UseTrilinearInterpolation; bool m_DoFiberResampling; bool m_WorkOnFiberCopy; OutPixelType m_MaxDensity; + unsigned int m_NumCoveredVoxels; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractDensityImageFilter.cpp" #endif #endif // __itkTractDensityImageFilter_h__ diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/Sequences/mitkCartesianReadout.h b/Modules/DiffusionImaging/FiberTracking/Fiberfox/Sequences/mitkCartesianReadout.h index 4fdae3a29a..9a6cc69f34 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/Sequences/mitkCartesianReadout.h +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/Sequences/mitkCartesianReadout.h @@ -1,89 +1,89 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_CartesianReadout_H #define _MITK_CartesianReadout_H #include namespace mitk { /** * \brief Realizes EPI readout: one echo, maximum intensity in the k-space center, zig-zag trajectory * */ class CartesianReadout : public AcquisitionType { public: CartesianReadout(FiberfoxParameters* parameters) : AcquisitionType(parameters) { kxMax = m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(0); kyMax = m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1); dt = m_Parameters->m_SignalGen.m_tLine/kxMax; // time to read one k-space voxel // maximum echo at center of each line m_NegTEhalf = -dt*(kxMax-(int)kxMax%2)/2; } ~CartesianReadout() {} double GetTimeFromMaxEcho(itk::Index< 2 > index) { double t = 0; t = m_NegTEhalf + (double)index[0]*dt; return t; } double GetRedoutTime(itk::Index< 2 > index) { double t = 0; t = (double)index[0]*dt; return t; } itk::Index< 2 > GetActualKspaceIndex(itk::Index< 2 > index) { // reverse phase if (!m_Parameters->m_SignalGen.m_ReversePhase) index[1] = kyMax-1-index[1]; return index; } void AdjustEchoTime() { if ( m_Parameters->m_SignalGen.m_tEcho/2 < m_Parameters->m_SignalGen.m_tLine/2 ) { m_Parameters->m_SignalGen.m_tEcho = m_Parameters->m_SignalGen.m_tLine; MITK_WARN << "Echo time is too short! Time not sufficient to read slice. Automatically adjusted to " << m_Parameters->m_SignalGen.m_tEcho << " ms"; - m_Parameters->m_Misc.m_AfterSimulationMessage += "Echo time was chosen too short! Time not sufficient to read slice. Internally adjusted to " + boost::lexical_cast(m_Parameters->m_SignalGen.m_tEcho) + " ms\n"; + m_Parameters->m_Misc.m_AfterSimulationMessage += "Echo time was chosen too short! Time not sufficient to read slice. Internally adjusted to " + boost::lexical_cast(m_Parameters->m_SignalGen.m_tEcho) + " ms\n"; } } protected: double dt; int kxMax; int kyMax; }; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/Sequences/mitkSingleShotEpi.h b/Modules/DiffusionImaging/FiberTracking/Fiberfox/Sequences/mitkSingleShotEpi.h index c3d672e6b7..3befa18982 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/Sequences/mitkSingleShotEpi.h +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/Sequences/mitkSingleShotEpi.h @@ -1,100 +1,100 @@ /*=================================================================== 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_SingleShotEpi_H #define _MITK_SingleShotEpi_H #include namespace mitk { /** * \brief Realizes EPI readout: one echo, maximum intensity in the k-space center, zig-zag trajectory * */ class SingleShotEpi : public AcquisitionType { public: SingleShotEpi(FiberfoxParameters* parameters) : AcquisitionType(parameters) { kxMax = m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(0); kyMax = m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1); dt = m_Parameters->m_SignalGen.m_tLine/kxMax; // time to read one k-space voxel // k-space center at maximum echo if ( kyMax%2==0 ) { m_NegTEhalf = -m_Parameters->m_SignalGen.m_tLine*(kyMax-1)/2 + dt*(kxMax-(int)kxMax%2)/2; } else m_NegTEhalf = -m_Parameters->m_SignalGen.m_tLine*(kyMax-1)/2 - dt*(kxMax-(int)kxMax%2)/2; } ~SingleShotEpi() {} double GetTimeFromMaxEcho(itk::Index< 2 > index) { double t = 0; t = m_NegTEhalf + ((double)index[1]*kxMax+(double)index[0])*dt; return t; } double GetRedoutTime(itk::Index< 2 > index) { double t = 0; t = ((double)index[1]*kxMax+(double)index[0])*dt; return t; } itk::Index< 2 > GetActualKspaceIndex(itk::Index< 2 > index) { // reverse phase if (!m_Parameters->m_SignalGen.m_ReversePhase) index[1] = kyMax-1-index[1]; // reverse readout direction if (index[1]%2 == 1) index[0] = kxMax-index[0]-1; return index; } void AdjustEchoTime() { int temp = m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1)*m_Parameters->m_SignalGen.m_PartialFourier - (m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1)+m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1)%2)/2; if ( m_Parameters->m_SignalGen.m_tEcho/2 < temp*m_Parameters->m_SignalGen.m_tLine ) { m_Parameters->m_SignalGen.m_tEcho = 2*temp*m_Parameters->m_SignalGen.m_tLine; MITK_WARN << "Echo time is too short! Time not sufficient to read slice. Automatically adjusted to " << m_Parameters->m_SignalGen.m_tEcho << " ms"; - m_Parameters->m_Misc.m_AfterSimulationMessage += "Echo time was chosen too short! Time not sufficient to read slice. Internally adjusted to " + boost::lexical_cast(m_Parameters->m_SignalGen.m_tEcho) + " ms\n"; + m_Parameters->m_Misc.m_AfterSimulationMessage += "Echo time was chosen too short! Time not sufficient to read slice. Internally adjusted to " + boost::lexical_cast(m_Parameters->m_SignalGen.m_tEcho) + " ms\n"; } } protected: double dt; int kxMax; int kyMax; }; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp index 3d7c80963b..7c272293bc 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp @@ -1,241 +1,241 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkFibersFromPlanarFiguresFilter.h" #define _USE_MATH_DEFINES #include // MITK #include #include #include #include #include #include #include #include #include // ITK #include #include #include #include // MISC #include namespace itk{ FibersFromPlanarFiguresFilter::FibersFromPlanarFiguresFilter() { } FibersFromPlanarFiguresFilter::~FibersFromPlanarFiguresFilter() { } void FibersFromPlanarFiguresFilter::GeneratePoints() { Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); randGen->SetSeed((unsigned int)0); m_2DPoints.clear(); unsigned int count = 0; while (count < m_Parameters.m_Density) { mitk::Vector2D p; switch (m_Parameters.m_Distribution) { case FiberGenerationParameters::DISTRIBUTE_GAUSSIAN: p[0] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); p[1] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); break; default: p[0] = randGen->GetUniformVariate(-1, 1); p[1] = randGen->GetUniformVariate(-1, 1); } if (sqrt(p[0]*p[0]+p[1]*p[1]) <= 1) { m_2DPoints.push_back(p); count++; } } } void FibersFromPlanarFiguresFilter::GenerateData() { // check if enough fiducials are available for (unsigned int i=0; i m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); - vector< mitk::PlanarEllipse::Pointer > bundle = m_Parameters.m_Fiducials.at(i); + std::vector< mitk::PlanarEllipse::Pointer > bundle = m_Parameters.m_Fiducials.at(i); - vector< unsigned int > fliplist; + std::vector< unsigned int > fliplist; if (i container = vtkSmartPointer::New(); mitk::PlanarEllipse::Pointer figure = bundle.at(0); mitk::Point2D p0 = figure->GetControlPoint(0); mitk::Point2D p1 = figure->GetControlPoint(1); mitk::Point2D p2 = figure->GetControlPoint(2); mitk::Point2D p3 = figure->GetControlPoint(3); double r1 = p0.EuclideanDistanceTo(p1); double r2 = p0.EuclideanDistanceTo(p2); mitk::Vector2D eDir = p1-p0; eDir.Normalize(); mitk::Vector2D tDir = p3-p0; tDir.Normalize(); // apply twist vnl_matrix_fixed tRot; tRot[0][0] = tDir[0]; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (tDir[1]<0) tRot.inplace_transpose(); m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); // apply new ellipse shape vnl_vector_fixed< double, 2 > newP; newP[0] = m_2DPoints.at(j)[0]; newP[1] = m_2DPoints.at(j)[1]; double alpha = acos(eDir[0]); if (eDir[1]>0) alpha = 2*M_PI-alpha; vnl_matrix_fixed eRot; eRot[0][0] = cos(alpha); eRot[1][1] = eRot[0][0]; eRot[1][0] = sin(alpha); eRot[0][1] = -eRot[1][0]; newP = eRot*newP; newP[0] *= r1; newP[1] *= r2; newP = eRot.transpose()*newP; p0[0] += newP[0]; p0[1] += newP[1]; const mitk::PlaneGeometry* planeGeo = figure->GetPlaneGeometry(); mitk::Point3D w, wc; planeGeo->Map(p0, w); wc = figure->GetWorldControlPoint(0); vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); container->GetPointIds()->InsertNextId(id); vnl_vector_fixed< double, 3 > n = planeGeo->GetNormalVnl(); for (unsigned int k=1; kGetControlPoint(0); p1 = figure->GetControlPoint(1); p2 = figure->GetControlPoint(2); p3 = figure->GetControlPoint(3); r1 = p0.EuclideanDistanceTo(p1); r2 = p0.EuclideanDistanceTo(p2); eDir = p1-p0; eDir.Normalize(); mitk::Vector2D tDir2 = p3-p0; tDir2.Normalize(); mitk::Vector2D temp; temp.SetVnlVector(tRot.transpose() * tDir2.GetVnlVector()); // apply twist tRot[0][0] = tDir[0]*tDir2[0] + tDir[1]*tDir2[1]; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (temp[1]<0) tRot.inplace_transpose(); m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); tDir = tDir2; // apply new ellipse shape newP[0] = m_2DPoints.at(j)[0]; newP[1] = m_2DPoints.at(j)[1]; // calculate normal mitk::PlaneGeometry* planeGeo = const_cast(figure->GetPlaneGeometry()); mitk::Vector3D perp = wc-planeGeo->ProjectPointOntoPlane(wc); perp.Normalize(); vnl_vector_fixed< double, 3 > n2 = planeGeo->GetNormalVnl(); wc = figure->GetWorldControlPoint(0); // is flip needed? if (dot_product(perp.GetVnlVector(),n2)>0 && dot_product(n,n2)<=0.00001) newP[0] *= -1; if (fliplist.at(k)>0) newP[0] *= -1; n = n2; alpha = acos(eDir[0]); if (eDir[1]>0) alpha = 2*M_PI-alpha; eRot[0][0] = cos(alpha); eRot[1][1] = eRot[0][0]; eRot[1][0] = sin(alpha); eRot[0][1] = -eRot[1][0]; newP = eRot*newP; newP[0] *= r1; newP[1] *= r2; newP = eRot.transpose()*newP; p0[0] += newP[0]; p0[1] += newP[1]; mitk::Point3D w; planeGeo->Map(p0, w); vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); container->GetPointIds()->InsertNextId(id); } m_VtkCellArray->InsertNextCell(container); } vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); fiberPolyData->SetPoints(m_VtkPoints); fiberPolyData->SetLines(m_VtkCellArray); mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(fiberPolyData); mitkFiberBundle->ResampleSpline(m_Parameters.m_Sampling, m_Parameters.m_Tension, m_Parameters.m_Continuity, m_Parameters.m_Bias); m_FiberBundles.push_back(mitkFiberBundle); } } } diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h index 940d41dcda..c4ecb68f52 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h @@ -1,87 +1,85 @@ /*=================================================================== 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 itkFibersFromPlanarFiguresFilter_h #define itkFibersFromPlanarFiguresFilter_h // MITK #include #include #include // ITK #include // VTK #include #include #include #include #include -using namespace std; - namespace itk{ /** * \brief Generates artificial fibers distributed in and interpolated between the input planar figures. */ class FibersFromPlanarFiguresFilter : public ProcessObject { public: typedef FibersFromPlanarFiguresFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; - typedef mitk::FiberBundle::Pointer FiberType; - typedef vector< mitk::FiberBundle::Pointer > FiberContainerType; + typedef mitk::FiberBundle::Pointer FiberType; + typedef std::vector< mitk::FiberBundle::Pointer > FiberContainerType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( FibersFromPlanarFiguresFilter, ProcessObject ) virtual void Update() override{ this->GenerateData(); } // input void SetParameters( FiberGenerationParameters param ) ///< Simulation parameters. { m_Parameters = param; } // output FiberContainerType GetFiberBundles(){ return m_FiberBundles; } protected: void GenerateData() override; FibersFromPlanarFiguresFilter(); virtual ~FibersFromPlanarFiguresFilter(); void GeneratePoints(); FiberContainerType m_FiberBundles; ///< container for the output fiber bundles - vector< mitk::Vector2D > m_2DPoints; ///< container for the 2D fiber waypoints + std::vector< mitk::Vector2D > m_2DPoints; ///< container for the 2D fiber waypoints FiberGenerationParameters m_Parameters; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFibersFromPlanarFiguresFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkKspaceImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkKspaceImageFilter.h index 86933a0ff6..f358baea34 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkKspaceImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkKspaceImageFilter.h @@ -1,145 +1,143 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkKspaceImageFilter_h_ #define __itkKspaceImageFilter_h_ #include #include #include #include #include #include #include #include -using namespace std; - namespace itk{ /** * \brief Simulates k-space acquisition of one slice with a single shot EPI sequence. Enables the simulation of various effects occuring during real MR acquisitions: * - T2 signal relaxation * - Spikes * - N/2 Ghosts * - Aliasing (wrap around) * - Image distortions (off-frequency effects) * - Gibbs ringing * - Eddy current effects * Based on a discrete fourier transformation. * See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. */ template< class TPixelType > class KspaceImageFilter : public ImageSource< Image< vcl_complex< TPixelType >, 2 > > { public: typedef KspaceImageFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageSource< Image< vcl_complex< TPixelType >, 2 > > Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(KspaceImageFilter, ImageToImageFilter) typedef typename itk::Image< double, 2 > InputImageType; typedef typename InputImageType::Pointer InputImagePointerType; typedef typename Superclass::OutputImageType OutputImageType; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef itk::Matrix MatrixType; typedef itk::Point Point2D; typedef itk::Vector< double,3> DoubleVectorType; typedef itk::Image ItkDoubleImgType; itkSetMacro( SpikesPerSlice, unsigned int ) ///< Number of spikes per slice. Corresponding parameter in fiberfox parameter object specifies the number of spikes for the whole image and can thus not be used here. itkSetMacro( Z, double ) ///< Slice position, necessary for eddy current simulation. itkSetMacro( UseConstantRandSeed, bool ) ///< Use constant seed for random generator for reproducible results. ONLY USE FOR TESTING PURPOSES! itkSetMacro( Rotation, DoubleVectorType ) itkSetMacro( Translation, DoubleVectorType ) itkSetMacro( Zidx, int ) itkSetMacro( FiberBundle, FiberBundle::Pointer ) itkSetMacro( CoilPosition, DoubleVectorType ) itkGetMacro( KSpaceImage, typename InputImageType::Pointer ) ///< k-space magnitude image itkGetMacro( SpikeLog, std::string ) void SetParameters( FiberfoxParameters* param ){ m_Parameters = param; } void SetCompartmentImages( std::vector< InputImagePointerType > cImgs ) { m_CompartmentImages=cImgs; } ///< One signal image per compartment. void SetT2( std::vector< double > t2Vector ) { m_T2=t2Vector; } ///< One T2 relaxation constant per compartment image. void SetT1( std::vector< double > t1Vector ) { m_T1=t1Vector; } ///< One T1 relaxation constant per compartment image. void SetDiffusionGradientDirection(itk::Vector g) { m_DiffusionGradientDirection=g; } ///< Gradient direction is needed for eddy current simulation. protected: KspaceImageFilter(); ~KspaceImageFilter() {} double CoilSensitivity(DoubleVectorType& pos); void BeforeThreadedGenerateData(); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadID); void AfterThreadedGenerateData(); double InterpolateFmapValue(itk::Point itkP); DoubleVectorType m_CoilPosition; FiberfoxParameters* m_Parameters; - vector< double > m_T2; - vector< double > m_T1; - vector< InputImagePointerType > m_CompartmentImages; + std::vector< double > m_T2; + std::vector< double > m_T1; + std::vector< InputImagePointerType > m_CompartmentImages; itk::Vector m_DiffusionGradientDirection; double m_Z; int m_Zidx; bool m_UseConstantRandSeed; unsigned int m_SpikesPerSlice; FiberBundle::Pointer m_FiberBundle; double m_Gamma; DoubleVectorType m_Rotation; ///< used to find correct point in frequency map (head motion) DoubleVectorType m_Translation; ///< used to find correct point in frequency map (head motion) bool m_IsBaseline; vcl_complex m_Spike; MatrixType m_Transform; std::string m_SpikeLog; double m_CoilSensitivityFactor; typename InputImageType::Pointer m_KSpaceImage; typename InputImageType::Pointer m_TimeFromEchoImage; typename InputImageType::Pointer m_ReadoutTimeImage; AcquisitionType* m_ReadoutScheme; private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkKspaceImageFilter.cpp" #endif #endif //__itkKspaceImageFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.cpp index 08852798b7..94a7e06a08 100755 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.cpp @@ -1,1735 +1,1735 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkTractsToDWIImageFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace itk { template< class PixelType > TractsToDWIImageFilter< PixelType >::TractsToDWIImageFilter() : m_FiberBundle(nullptr) , m_StatusText("") , m_UseConstantRandSeed(false) , m_RandGen(itk::Statistics::MersenneTwisterRandomVariateGenerator::New()) { m_RandGen->SetSeed(); } template< class PixelType > TractsToDWIImageFilter< PixelType >::~TractsToDWIImageFilter() { } template< class PixelType > TractsToDWIImageFilter< PixelType >::DoubleDwiType::Pointer TractsToDWIImageFilter< PixelType >:: SimulateKspaceAcquisition( std::vector< DoubleDwiType::Pointer >& images ) { unsigned int numFiberCompartments = m_Parameters.m_FiberModelList.size(); // create slice object ImageRegion<2> sliceRegion; sliceRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]); sliceRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]); Vector< double, 2 > sliceSpacing; sliceSpacing[0] = m_WorkingSpacing[0]; sliceSpacing[1] = m_WorkingSpacing[1]; DoubleDwiType::PixelType nullPix; nullPix.SetSize(images.at(0)->GetVectorLength()); nullPix.Fill(0.0); auto magnitudeDwiImage = DoubleDwiType::New(); magnitudeDwiImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); magnitudeDwiImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin ); magnitudeDwiImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); magnitudeDwiImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); magnitudeDwiImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); magnitudeDwiImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); magnitudeDwiImage->SetVectorLength( images.at(0)->GetVectorLength() ); magnitudeDwiImage->Allocate(); magnitudeDwiImage->FillBuffer(nullPix); m_PhaseImage = DoubleDwiType::New(); m_PhaseImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); m_PhaseImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin ); m_PhaseImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); m_PhaseImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_PhaseImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_PhaseImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_PhaseImage->SetVectorLength( images.at(0)->GetVectorLength() ); m_PhaseImage->Allocate(); m_PhaseImage->FillBuffer(nullPix); m_KspaceImage = DoubleDwiType::New(); m_KspaceImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); m_KspaceImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin ); m_KspaceImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); m_KspaceImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_KspaceImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_KspaceImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_KspaceImage->SetVectorLength( m_Parameters.m_SignalGen.m_NumberOfCoils ); m_KspaceImage->Allocate(); m_KspaceImage->FillBuffer(nullPix); std::vector< unsigned int > spikeVolume; for (unsigned int i=0; iGetIntegerVariate()%(images.at(0)->GetVectorLength())); std::sort (spikeVolume.begin(), spikeVolume.end()); std::reverse (spikeVolume.begin(), spikeVolume.end()); // calculate coil positions double a = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0)*m_Parameters.m_SignalGen.m_ImageSpacing[0]; double b = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)*m_Parameters.m_SignalGen.m_ImageSpacing[1]; double c = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(2)*m_Parameters.m_SignalGen.m_ImageSpacing[2]; double diagonal = sqrt(a*a+b*b)/1000; // image diagonal in m m_CoilPointset = mitk::PointSet::New(); std::vector< itk::Vector > coilPositions; itk::Vector pos; pos.Fill(0.0); pos[1] = -diagonal/2; itk::Vector center; center[0] = a/2-m_Parameters.m_SignalGen.m_ImageSpacing[0]/2; center[1] = b/2-m_Parameters.m_SignalGen.m_ImageSpacing[2]/2; center[2] = c/2-m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; for (int c=0; cInsertPoint(c, pos*1000 + m_Parameters.m_SignalGen.m_ImageOrigin.GetVectorFromOrigin() + center ); double rz = 360.0/m_Parameters.m_SignalGen.m_NumberOfCoils * M_PI/180; 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]; pos.SetVnlVector(rotZ*pos.GetVnlVector()); } PrintToLog("0% 10 20 30 40 50 60 70 80 90 100%", false, true, false); PrintToLog("|----|----|----|----|----|----|----|----|----|----|\n*", false, false, false); unsigned long lastTick = 0; boost::progress_display disp(images.at(0)->GetVectorLength()*images.at(0)->GetLargestPossibleRegion().GetSize(2)); for (unsigned int g=0; gGetVectorLength(); g++) { std::vector< unsigned int > spikeSlice; while (!spikeVolume.empty() && spikeVolume.back()==g) { spikeSlice.push_back(m_RandGen->GetIntegerVariate()%images.at(0)->GetLargestPossibleRegion().GetSize(2)); spikeVolume.pop_back(); } std::sort (spikeSlice.begin(), spikeSlice.end()); std::reverse (spikeSlice.begin(), spikeSlice.end()); for (unsigned int z=0; zGetLargestPossibleRegion().GetSize(2); z++) { std::vector< SliceType::Pointer > compartmentSlices; std::vector< double > t2Vector; std::vector< double > t1Vector; for (unsigned int i=0; i* signalModel; if (iSetLargestPossibleRegion( sliceRegion ); slice->SetBufferedRegion( sliceRegion ); slice->SetRequestedRegion( sliceRegion ); slice->SetSpacing(sliceSpacing); slice->Allocate(); slice->FillBuffer(0.0); // extract slice from channel g for (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; slice->SetPixel(index2D, images.at(i)->GetPixel(index3D)[g]); } compartmentSlices.push_back(slice); t2Vector.push_back(signalModel->GetT2()); t1Vector.push_back(signalModel->GetT1()); } int numSpikes = 0; while (!spikeSlice.empty() && spikeSlice.back()==z) { numSpikes++; spikeSlice.pop_back(); } int spikeCoil = m_RandGen->GetIntegerVariate()%m_Parameters.m_SignalGen.m_NumberOfCoils; if (this->GetAbortGenerateData()) return nullptr; #pragma omp parallel for for (int c=0; c::New(); idft->SetCompartmentImages(compartmentSlices); idft->SetT2(t2Vector); idft->SetT1(t1Vector); idft->SetUseConstantRandSeed(m_UseConstantRandSeed); idft->SetParameters(&m_Parameters); idft->SetZ((double)z-(double)( images.at(0)->GetLargestPossibleRegion().GetSize(2) -images.at(0)->GetLargestPossibleRegion().GetSize(2)%2 ) / 2.0); idft->SetZidx(z); idft->SetCoilPosition(coilPositions.at(c)); idft->SetFiberBundle(m_FiberBundleWorkingCopy); idft->SetTranslation(m_Translations.at(g)); idft->SetRotation(m_Rotations.at(g)); idft->SetDiffusionGradientDirection(m_Parameters.m_SignalGen.GetGradientDirection(g)); if (c==spikeCoil) idft->SetSpikesPerSlice(numSpikes); idft->Update(); #pragma omp critical if (c==spikeCoil && numSpikes>0) { m_SpikeLog += "Volume " + boost::lexical_cast(g) + " Coil " + boost::lexical_cast(c) + "\n"; m_SpikeLog += idft->GetSpikeLog(); } ComplexSliceType::Pointer fSlice; fSlice = idft->GetOutput(); // fourier transform slice ComplexSliceType::Pointer newSlice; auto dft = itk::DftImageFilter< SliceType::PixelType >::New(); dft->SetInput(fSlice); dft->SetParameters(m_Parameters); dft->Update(); newSlice = dft->GetOutput(); // put slice back into channel g for (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; ComplexSliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; ComplexSliceType::PixelType cPix = newSlice->GetPixel(index2D); double magn = sqrt(cPix.real()*cPix.real()+cPix.imag()*cPix.imag()); double phase = 0; if (cPix.real()!=0) phase = atan( cPix.imag()/cPix.real() ); DoubleDwiType::PixelType dwiPix = magnitudeDwiImage->GetPixel(index3D); DoubleDwiType::PixelType phasePix = m_PhaseImage->GetPixel(index3D); if (m_Parameters.m_SignalGen.m_NumberOfCoils>1) { dwiPix[g] += magn*magn; phasePix[g] += phase*phase; } else { dwiPix[g] = magn; phasePix[g] = phase; } #pragma omp critical { magnitudeDwiImage->SetPixel(index3D, dwiPix); m_PhaseImage->SetPixel(index3D, phasePix); // k-space image if (g==0) { DoubleDwiType::PixelType kspacePix = m_KspaceImage->GetPixel(index3D); kspacePix[c] = idft->GetKSpaceImage()->GetPixel(index2D); m_KspaceImage->SetPixel(index3D, kspacePix); } } } } if (m_Parameters.m_SignalGen.m_NumberOfCoils>1) { #ifdef WIN32 #pragma omp parallel for #else #pragma omp parallel for collapse(2) #endif for (int y=0; y(magnitudeDwiImage->GetLargestPossibleRegion().GetSize(1)); y++) for (int x=0; x(magnitudeDwiImage->GetLargestPossibleRegion().GetSize(0)); x++) { DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; DoubleDwiType::PixelType magPix = magnitudeDwiImage->GetPixel(index3D); magPix[g] = sqrt(magPix[g]/m_Parameters.m_SignalGen.m_NumberOfCoils); DoubleDwiType::PixelType phasePix = m_PhaseImage->GetPixel(index3D); phasePix[g] = sqrt(phasePix[g]/m_Parameters.m_SignalGen.m_NumberOfCoils); #pragma omp critical { magnitudeDwiImage->SetPixel(index3D, magPix); m_PhaseImage->SetPixel(index3D, phasePix); } } } ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) PrintToLog("*", false, false, false); lastTick = newTick; } } PrintToLog("\n", false); return magnitudeDwiImage; } template< class PixelType > TractsToDWIImageFilter< PixelType >::ItkDoubleImgType::Pointer TractsToDWIImageFilter< PixelType >:: NormalizeInsideMask(ItkDoubleImgType::Pointer image) { double max = itk::NumericTraits< double >::min(); double min = itk::NumericTraits< double >::max(); itk::ImageRegionIterator< ItkDoubleImgType > it(image, image->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull() && m_Parameters.m_SignalGen.m_MaskImage->GetPixel(it.GetIndex())<=0) { it.Set(0.0); ++it; continue; } // if (it.Get()>900) // it.Set(900); if (it.Get()>max) max = it.Get(); if (it.Get()::New(); scaler->SetInput(image); scaler->SetShift(-min); scaler->SetScale(1.0/(max-min)); scaler->Update(); return scaler->GetOutput(); } template< class PixelType > void TractsToDWIImageFilter< PixelType >::CheckVolumeFractionImages() { m_UseRelativeNonFiberVolumeFractions = false; // check for fiber volume fraction maps unsigned int fibVolImages = 0; for (std::size_t i=0; iGetVolumeFractionImage().IsNotNull()) { PrintToLog("Using volume fraction map for fiber compartment " + boost::lexical_cast(i+1)); fibVolImages++; } } // check for non-fiber volume fraction maps unsigned int nonfibVolImages = 0; for (std::size_t i=0; iGetVolumeFractionImage().IsNotNull()) { PrintToLog("Using volume fraction map for non-fiber compartment " + boost::lexical_cast(i+1)); nonfibVolImages++; } } // not all fiber compartments are using volume fraction maps // --> non-fiber volume fractions are assumed to be relative to the // non-fiber volume and not absolute voxel-volume fractions. // this means if two non-fiber compartments are used but only one of them // has an associated volume fraction map, the repesctive other volume fraction map // can be determined as inverse (1-val) of the present volume fraction map- if ( fibVolImages::New(); inverter->SetMaximum(1.0); if ( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage().IsNull() && m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage().IsNotNull() ) { // m_Parameters.m_NonFiberModelList[1]->SetVolumeFractionImage( // NormalizeInsideMask( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage() ) ); inverter->SetInput( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage() ); inverter->Update(); m_Parameters.m_NonFiberModelList[0]->SetVolumeFractionImage(inverter->GetOutput()); } else if ( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage().IsNull() && m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage().IsNotNull() ) { // m_Parameters.m_NonFiberModelList[0]->SetVolumeFractionImage( // NormalizeInsideMask( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage() ) ); inverter->SetInput( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage() ); inverter->Update(); m_Parameters.m_NonFiberModelList[1]->SetVolumeFractionImage(inverter->GetOutput()); } else { itkExceptionMacro("Something went wrong in automatically calculating the missing non-fiber volume fraction image!" " Did you use two non fiber compartments but only one volume fraction image?" " Then it should work and this error is really strange."); } m_UseRelativeNonFiberVolumeFractions = true; nonfibVolImages++; } // Up to two fiber compartments are allowed without volume fraction maps since the volume fractions can then be determined automatically if (m_Parameters.m_FiberModelList.size()>2 && fibVolImages!=m_Parameters.m_FiberModelList.size()) itkExceptionMacro("More than two fiber compartment selected but no corresponding volume fraction maps set!"); // One non-fiber compartment is allowed without volume fraction map since the volume fraction can then be determined automatically if (m_Parameters.m_NonFiberModelList.size()>1 && nonfibVolImages!=m_Parameters.m_NonFiberModelList.size()) itkExceptionMacro("More than one non-fiber compartment selected but no volume fraction maps set!"); if (fibVolImages0) { PrintToLog("Not all fiber compartments are using an associated volume fraction image.\n" "Assuming non-fiber volume fraction images to contain values relative to the" " remaining non-fiber volume, not absolute values."); m_UseRelativeNonFiberVolumeFractions = true; // itk::ImageFileWriter::Pointer wr = itk::ImageFileWriter::New(); // wr->SetInput(m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage()); // wr->SetFileName("/local/volumefraction.nrrd"); // wr->Update(); } // initialize the images that store the output volume fraction of each compartment m_VolumeFractions.clear(); for (std::size_t i=0; iSetSpacing( m_WorkingSpacing ); doubleImg->SetOrigin( m_WorkingOrigin ); doubleImg->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); doubleImg->SetLargestPossibleRegion( m_WorkingImageRegion ); doubleImg->SetBufferedRegion( m_WorkingImageRegion ); doubleImg->SetRequestedRegion( m_WorkingImageRegion ); doubleImg->Allocate(); doubleImg->FillBuffer(0); m_VolumeFractions.push_back(doubleImg); } } template< class PixelType > void TractsToDWIImageFilter< PixelType >::InitializeData() { m_Rotations.clear(); m_Translations.clear(); m_MotionLog = ""; m_SpikeLog = ""; // initialize output dwi image m_Parameters.m_SignalGen.m_CroppedRegion = m_Parameters.m_SignalGen.m_ImageRegion; m_Parameters.m_SignalGen.m_CroppedRegion.SetSize( 1, m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1) *m_Parameters.m_SignalGen.m_CroppingFactor); itk::Point shiftedOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; shiftedOrigin[1] += (m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1) -m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1))*m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; m_OutputImage = OutputImageType::New(); m_OutputImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); m_OutputImage->SetOrigin( shiftedOrigin ); m_OutputImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); m_OutputImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_OutputImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_OutputImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_OutputImage->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); m_OutputImage->Allocate(); typename OutputImageType::PixelType temp; temp.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); temp.Fill(0.0); m_OutputImage->FillBuffer(temp); // Apply in-plane upsampling for Gibbs ringing artifact double upsampling = 1; if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) upsampling = 2; m_WorkingSpacing = m_Parameters.m_SignalGen.m_ImageSpacing; m_WorkingSpacing[0] /= upsampling; m_WorkingSpacing[1] /= upsampling; m_WorkingImageRegion = m_Parameters.m_SignalGen.m_ImageRegion; m_WorkingImageRegion.SetSize(0, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[0]*upsampling); m_WorkingImageRegion.SetSize(1, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[1]*upsampling); m_WorkingOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; m_WorkingOrigin[0] -= m_Parameters.m_SignalGen.m_ImageSpacing[0]/2; m_WorkingOrigin[0] += m_WorkingSpacing[0]/2; m_WorkingOrigin[1] -= m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; m_WorkingOrigin[1] += m_WorkingSpacing[1]/2; m_WorkingOrigin[2] -= m_Parameters.m_SignalGen.m_ImageSpacing[2]/2; m_WorkingOrigin[2] += m_WorkingSpacing[2]/2; m_VoxelVolume = m_WorkingSpacing[0]*m_WorkingSpacing[1]*m_WorkingSpacing[2]; // generate double images to store the individual compartment signals m_CompartmentImages.clear(); int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); for (int i=0; iSetSpacing( m_WorkingSpacing ); doubleDwi->SetOrigin( m_WorkingOrigin ); doubleDwi->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); doubleDwi->SetLargestPossibleRegion( m_WorkingImageRegion ); doubleDwi->SetBufferedRegion( m_WorkingImageRegion ); doubleDwi->SetRequestedRegion( m_WorkingImageRegion ); doubleDwi->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); doubleDwi->Allocate(); DoubleDwiType::PixelType pix; pix.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); pix.Fill(0.0); doubleDwi->FillBuffer(pix); m_CompartmentImages.push_back(doubleDwi); } if (m_FiberBundle.IsNull() && m_InputImage.IsNotNull()) { m_CompartmentImages.clear(); m_Parameters.m_SignalGen.m_DoAddMotion = false; m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false; PrintToLog("Simulating acquisition for input diffusion-weighted image.", false); auto caster = itk::CastImageFilter< OutputImageType, DoubleDwiType >::New(); caster->SetInput(m_InputImage); caster->Update(); if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) { PrintToLog("Upsampling input diffusion-weighted image for Gibbs ringing simulation.", false); auto resampler = itk::ResampleDwiImageFilter< double >::New(); resampler->SetInput(caster->GetOutput()); itk::Vector< double, 3 > samplingFactor; samplingFactor[0] = upsampling; samplingFactor[1] = upsampling; samplingFactor[2] = 1; resampler->SetSamplingFactor(samplingFactor); resampler->SetInterpolation(itk::ResampleDwiImageFilter< double >::Interpolate_WindowedSinc); resampler->Update(); m_CompartmentImages.push_back(resampler->GetOutput()); } else m_CompartmentImages.push_back(caster->GetOutput()); for (unsigned int g=0; g::New(); rescaler->SetInput(0,m_Parameters.m_SignalGen.m_MaskImage); rescaler->SetOutputMaximum(100); rescaler->SetOutputMinimum(0); rescaler->Update(); // resample mask image auto resampler = itk::ResampleImageFilter::New(); resampler->SetInput(rescaler->GetOutput()); resampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage); resampler->SetSize(m_WorkingImageRegion.GetSize()); resampler->SetOutputSpacing(m_WorkingSpacing); resampler->SetOutputOrigin(m_WorkingOrigin); auto nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(nn_interpolator); resampler->Update(); m_Parameters.m_SignalGen.m_MaskImage = resampler->GetOutput(); } // resample frequency map if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull()) { auto resampler = itk::ResampleImageFilter::New(); resampler->SetInput(m_Parameters.m_SignalGen.m_FrequencyMap); resampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_FrequencyMap); resampler->SetSize(m_WorkingImageRegion.GetSize()); resampler->SetOutputSpacing(m_WorkingSpacing); resampler->SetOutputOrigin(m_WorkingOrigin); auto nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(nn_interpolator); resampler->Update(); m_Parameters.m_SignalGen.m_FrequencyMap = resampler->GetOutput(); } } m_MaskImageSet = true; if (m_Parameters.m_SignalGen.m_MaskImage.IsNull()) { // no input tissue mask is set -> create default PrintToLog("No tissue mask set", false); m_Parameters.m_SignalGen.m_MaskImage = ItkUcharImgType::New(); m_Parameters.m_SignalGen.m_MaskImage->SetSpacing( m_WorkingSpacing ); m_Parameters.m_SignalGen.m_MaskImage->SetOrigin( m_WorkingOrigin ); m_Parameters.m_SignalGen.m_MaskImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); m_Parameters.m_SignalGen.m_MaskImage->SetLargestPossibleRegion( m_WorkingImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->SetBufferedRegion( m_WorkingImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->SetRequestedRegion( m_WorkingImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->Allocate(); m_Parameters.m_SignalGen.m_MaskImage->FillBuffer(100); m_MaskImageSet = false; } else { if (m_Parameters.m_SignalGen.m_MaskImage->GetLargestPossibleRegion()!=m_WorkingImageRegion) { itkExceptionMacro("Mask image and specified DWI geometry are not matching!"); } PrintToLog("Using tissue mask", false); } if (m_Parameters.m_SignalGen.m_DoAddMotion) { if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { PrintToLog("Random motion artifacts:", false); PrintToLog("Maximum rotation: +/-" + boost::lexical_cast(m_Parameters.m_SignalGen.m_Rotation) + "°", false); PrintToLog("Maximum translation: +/-" + boost::lexical_cast(m_Parameters.m_SignalGen.m_Translation) + "mm", false); } else { PrintToLog("Linear motion artifacts:", false); PrintToLog("Maximum rotation: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Rotation) + "°", false); PrintToLog("Maximum translation: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Translation) + "mm", false); } } if ( m_Parameters.m_SignalGen.m_MotionVolumes.empty() ) { // no motion in first volume m_Parameters.m_SignalGen.m_MotionVolumes.push_back(false); // motion in all other volumes while ( m_Parameters.m_SignalGen.m_MotionVolumes.size() < m_Parameters.m_SignalGen.GetNumVolumes() ) { m_Parameters.m_SignalGen.m_MotionVolumes.push_back(true); } } // we need to know for every volume if there is motion. if this information is missing, then set corresponding fal to false while ( m_Parameters.m_SignalGen.m_MotionVolumes.size()::New(); duplicator->SetInputImage(m_Parameters.m_SignalGen.m_MaskImage); duplicator->Update(); m_TransformedMaskImage = duplicator->GetOutput(); // second upsampling needed for motion artifacts ImageRegion<3> upsampledImageRegion = m_WorkingImageRegion; DoubleVectorType upsampledSpacing = m_WorkingSpacing; upsampledSpacing[0] /= 4; upsampledSpacing[1] /= 4; upsampledSpacing[2] /= 4; upsampledImageRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]*4); upsampledImageRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]*4); upsampledImageRegion.SetSize(2, m_WorkingImageRegion.GetSize()[2]*4); itk::Point upsampledOrigin = m_WorkingOrigin; upsampledOrigin[0] -= m_WorkingSpacing[0]/2; upsampledOrigin[0] += upsampledSpacing[0]/2; upsampledOrigin[1] -= m_WorkingSpacing[1]/2; upsampledOrigin[1] += upsampledSpacing[1]/2; upsampledOrigin[2] -= m_WorkingSpacing[2]/2; upsampledOrigin[2] += upsampledSpacing[2]/2; m_UpsampledMaskImage = ItkUcharImgType::New(); auto upsampler = itk::ResampleImageFilter::New(); upsampler->SetInput(m_Parameters.m_SignalGen.m_MaskImage); upsampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage); upsampler->SetSize(upsampledImageRegion.GetSize()); upsampler->SetOutputSpacing(upsampledSpacing); upsampler->SetOutputOrigin(upsampledOrigin); auto nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); upsampler->SetInterpolator(nn_interpolator); upsampler->Update(); m_UpsampledMaskImage = upsampler->GetOutput(); } template< class PixelType > void TractsToDWIImageFilter< PixelType >::InitializeFiberData() { // resample fiber bundle for sufficient voxel coverage PrintToLog("Resampling fibers ..."); m_SegmentVolume = 0.0001; float minSpacing = 1; if( m_WorkingSpacing[0]GetDeepCopy(); double volumeAccuracy = 10; m_FiberBundleWorkingCopy->ResampleLinear(minSpacing/volumeAccuracy); m_mmRadius = m_Parameters.m_SignalGen.m_AxonRadius/1000; auto caster = itk::CastImageFilter< itk::Image, itk::Image >::New(); caster->SetInput(m_TransformedMaskImage); caster->Update(); auto density_calculator = itk::TractDensityImageFilter< itk::Image >::New(); density_calculator->SetFiberBundle(m_FiberBundleWorkingCopy); density_calculator->SetInputImage(caster->GetOutput()); density_calculator->SetBinaryOutput(false); density_calculator->SetUseImageGeometry(true); density_calculator->SetDoFiberResampling(false); density_calculator->SetOutputAbsoluteValues(true); density_calculator->SetWorkOnFiberCopy(false); density_calculator->Update(); float max_density = density_calculator->GetMaxDensity(); if (m_mmRadius>0) { m_SegmentVolume = M_PI*m_mmRadius*m_mmRadius*minSpacing/volumeAccuracy; - stringstream stream; - stream << fixed << setprecision(2) << max_density * m_SegmentVolume; - string s = stream.str(); + std::stringstream stream; + stream << std::fixed << setprecision(2) << max_density * m_SegmentVolume; + std::string s = stream.str(); PrintToLog("\nMax. fiber volume: " + s + "mm².", false, true, true); } else { - stringstream stream; - stream << fixed << setprecision(2) << max_density * m_SegmentVolume; - string s = stream.str(); + std::stringstream stream; + stream << std::fixed << setprecision(2) << max_density * m_SegmentVolume; + std::string s = stream.str(); PrintToLog("\nMax. fiber volume: " + s + "mm² (before rescaling to voxel volume).", false, true, true); } float voxel_volume = m_WorkingSpacing[0]*m_WorkingSpacing[1]*m_WorkingSpacing[2]; float new_seg_vol = voxel_volume/max_density; float new_fib_radius = 1000*std::sqrt(new_seg_vol*volumeAccuracy/(minSpacing*M_PI)); - stringstream stream; - stream << fixed << setprecision(2) << new_fib_radius; - string s = stream.str(); + std::stringstream stream; + stream << std::fixed << setprecision(2) << new_fib_radius; + std::string s = stream.str(); PrintToLog("\nA full fiber voxel corresponds to a fiber radius of ~" + s + "µm, given the current fiber configuration.", false, true, true); // a second fiber bundle is needed to store the transformed version of the m_FiberBundleWorkingCopy m_FiberBundleTransformed = m_FiberBundleWorkingCopy; } template< class PixelType > bool TractsToDWIImageFilter< PixelType >::PrepareLogFile() { assert( ! m_Logfile.is_open() ); std::string filePath; std::string fileName; // Get directory name: if (m_Parameters.m_Misc.m_OutputPath.size() > 0) { filePath = m_Parameters.m_Misc.m_OutputPath; if( *(--(filePath.cend())) != '/') { filePath.push_back('/'); } } else { filePath = mitk::IOUtil::GetTempPath() + '/'; } // check if directory exists, else use /tmp/: if( itksys::SystemTools::FileIsDirectory( filePath ) ) { while( *(--(filePath.cend())) == '/') { filePath.pop_back(); } filePath = filePath + '/'; } else { filePath = mitk::IOUtil::GetTempPath() + '/'; } // Get file name: if( ! m_Parameters.m_Misc.m_ResultNode->GetName().empty() ) { fileName = m_Parameters.m_Misc.m_ResultNode->GetName(); } else { fileName = ""; } if( ! m_Parameters.m_Misc.m_OutputPrefix.empty() ) { fileName = m_Parameters.m_Misc.m_OutputPrefix + fileName; } else { fileName = "fiberfox"; } // check if file already exists and DO NOT overwrite existing files: std::string NameTest = fileName; int c = 0; while( itksys::SystemTools::FileExists( filePath + '/' + fileName + ".log" ) && c <= std::numeric_limits::max() ) { fileName = NameTest + "_" + boost::lexical_cast(c); ++c; } try { m_Logfile.open( ( filePath + '/' + fileName + ".log" ).c_str() ); } catch (const std::ios_base::failure &fail) { MITK_ERROR << "itkTractsToDWIImageFilter.cpp: Exception " << fail.what() << " while trying to open file" << filePath << '/' << fileName << ".log"; return false; } if ( m_Logfile.is_open() ) { PrintToLog( "Logfile: " + filePath + '/' + fileName + ".log", false ); return true; } else { m_StatusText += "Logfile could not be opened!\n"; MITK_ERROR << "itkTractsToDWIImageFilter.cpp: Logfile could not be opened!"; return false; } } template< class PixelType > void TractsToDWIImageFilter< PixelType >::GenerateData() { // prepare logfile if ( ! PrepareLogFile() ) { this->SetAbortGenerateData( true ); return; } m_TimeProbe.Start(); // check input data if (m_FiberBundle.IsNull() && m_InputImage.IsNull()) itkExceptionMacro("Input fiber bundle and input diffusion-weighted image is nullptr!"); if (m_Parameters.m_FiberModelList.empty() && m_InputImage.IsNull()) itkExceptionMacro("No diffusion model for fiber compartments defined and input diffusion-weighted" " image is nullptr! At least one fiber compartment is necessary to simulate diffusion."); if (m_Parameters.m_NonFiberModelList.empty() && m_InputImage.IsNull()) itkExceptionMacro("No diffusion model for non-fiber compartments defined and input diffusion-weighted" " image is nullptr! At least one non-fiber compartment is necessary to simulate diffusion."); int baselineIndex = m_Parameters.m_SignalGen.GetFirstBaselineIndex(); if (baselineIndex<0) { itkExceptionMacro("No baseline index found!"); } if (!m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition) // No upsampling of input image needed if no k-space simulation is performed { m_Parameters.m_SignalGen.m_DoAddGibbsRinging = false; } if (m_UseConstantRandSeed) // always generate the same random numbers? { m_RandGen->SetSeed(0); } else { m_RandGen->SetSeed(); } InitializeData(); if ( m_FiberBundle.IsNotNull() ) // if no fiber bundle is found, we directly proceed to the k-space acquisition simulation { CheckVolumeFractionImages(); InitializeFiberData(); int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); double maxVolume = 0; unsigned long lastTick = 0; int signalModelSeed = m_RandGen->GetIntegerVariate(); PrintToLog("\n", false, false); PrintToLog("Generating " + boost::lexical_cast(numFiberCompartments+numNonFiberCompartments) + "-compartment diffusion-weighted signal."); std::vector< int > bVals = m_Parameters.m_SignalGen.GetBvalues(); PrintToLog("b-values: ", false, false, true); for (auto v : bVals) PrintToLog(boost::lexical_cast(v) + " ", false, false, true); PrintToLog("\n", false, false, true); PrintToLog("\n", false, false, true); int numFibers = m_FiberBundleWorkingCopy->GetNumFibers(); boost::progress_display disp(numFibers*m_Parameters.m_SignalGen.GetNumVolumes()); PrintToLog("0% 10 20 30 40 50 60 70 80 90 100%", false, true, false); PrintToLog("|----|----|----|----|----|----|----|----|----|----|\n*", false, false, false); for (unsigned int g=0; gSetSeed(signalModelSeed); for (std::size_t i=0; iSetSeed(signalModelSeed); // storing voxel-wise intra-axonal volume in mm³ auto intraAxonalVolumeImage = ItkDoubleImgType::New(); intraAxonalVolumeImage->SetSpacing( m_WorkingSpacing ); intraAxonalVolumeImage->SetOrigin( m_WorkingOrigin ); intraAxonalVolumeImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); intraAxonalVolumeImage->SetLargestPossibleRegion( m_WorkingImageRegion ); intraAxonalVolumeImage->SetBufferedRegion( m_WorkingImageRegion ); intraAxonalVolumeImage->SetRequestedRegion( m_WorkingImageRegion ); intraAxonalVolumeImage->Allocate(); intraAxonalVolumeImage->FillBuffer(0); maxVolume = 0; vtkPolyData* fiberPolyData = m_FiberBundleTransformed->GetFiberPolyData(); // generate fiber signal (if there are any fiber models present) if (!m_Parameters.m_FiberModelList.empty()) for( int i=0; iGetFiberWeight(i); vtkCell* cell = fiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (numPoints<2) continue; for( int j=0; jGetAbortGenerateData()) { PrintToLog("\n", false, false); PrintToLog("Simulation aborted"); return; } double* temp = points->GetPoint(j); itk::Point vertex = GetItkPoint(temp); itk::Vector v = GetItkVector(temp); itk::Vector dir(3); if (jGetPoint(j+1))-v; } else { dir = v-GetItkVector(points->GetPoint(j-1)); } if ( dir.GetSquaredNorm()<0.0001 || dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2] ) { continue; } itk::Index<3> idx; itk::ContinuousIndex contIndex; m_TransformedMaskImage->TransformPhysicalPointToIndex(vertex, idx); m_TransformedMaskImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); if (!m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(idx) || m_TransformedMaskImage->GetPixel(idx)<=0) { continue; } // generate signal for each fiber compartment for (int k=0; kSetFiberDirection(dir); DoubleDwiType::PixelType pix = m_CompartmentImages.at(k)->GetPixel(idx); pix[g] += fiberWeight*m_SegmentVolume*m_Parameters.m_FiberModelList[k]->SimulateMeasurement(g); m_CompartmentImages.at(k)->SetPixel(idx, pix); } // update fiber volume image double vol = intraAxonalVolumeImage->GetPixel(idx) + m_SegmentVolume*fiberWeight; intraAxonalVolumeImage->SetPixel(idx, vol); // we assume that the first volume is always unweighted! if (vol>maxVolume) { maxVolume = vol; } } // progress report ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) { PrintToLog("*", false, false, false); } lastTick = newTick; } // generate non-fiber signal ImageRegionIterator it3(m_TransformedMaskImage, m_TransformedMaskImage->GetLargestPossibleRegion()); double fact = 1; // density correction factor in mm³ if (m_Parameters.m_SignalGen.m_AxonRadius<0.0001 || maxVolume>m_VoxelVolume) // the fullest voxel is always completely full fact = m_VoxelVolume/maxVolume; while(!it3.IsAtEnd()) { if (it3.Get()>0) { DoubleDwiType::IndexType index = it3.GetIndex(); itk::Point point; m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, point); if ( m_Parameters.m_SignalGen.m_DoAddMotion && g>=0 && m_Parameters.m_SignalGen.m_MotionVolumes[g] ) { if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { point = m_FiberBundleWorkingCopy->TransformPoint( point.GetVnlVector(), -m_Rotation[0], -m_Rotation[1], -m_Rotation[2], -m_Translation[0], -m_Translation[1], -m_Translation[2] ); } else { point = m_FiberBundleWorkingCopy->TransformPoint( point.GetVnlVector(), -m_Rotation[0]*m_MotionCounter, -m_Rotation[1]*m_MotionCounter, -m_Rotation[2]*m_MotionCounter, -m_Translation[0]*m_MotionCounter, -m_Translation[1]*m_MotionCounter, -m_Translation[2]*m_MotionCounter ); } } double iAxVolume = intraAxonalVolumeImage->GetPixel(index); // if volume fraction image is set use it, otherwise use scaling factor to obtain one full fiber voxel double fact2 = fact; if ( m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()!=nullptr && iAxVolume>0.0001 ) { double val = InterpolateValue(point, m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()); if (val<0) mitkThrow() << "Volume fraction image (index 1) contains negative values (intra-axonal compartment)!"; fact2 = m_VoxelVolume*val/iAxVolume; } // adjust intra-axonal image value for (int i=0; iGetPixel(index); pix[g] *= fact2; m_CompartmentImages.at(i)->SetPixel(index, pix); } // simulate other compartments SimulateExtraAxonalSignal(index, iAxVolume*fact2, g); } ++it3; } } PrintToLog("\n", false); if (this->GetAbortGenerateData()) { PrintToLog("\n", false, false); PrintToLog("Simulation aborted"); return; } } DoubleDwiType::Pointer doubleOutImage; double signalScale = m_Parameters.m_SignalGen.m_SignalScale; if ( m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition ) // do k-space stuff { PrintToLog("\n", false, false); PrintToLog("Simulating k-space acquisition using " +boost::lexical_cast(m_Parameters.m_SignalGen.m_NumberOfCoils) +" coil(s)"); switch (m_Parameters.m_SignalGen.m_AcquisitionType) { case SignalGenerationParameters::SingleShotEpi: { PrintToLog("Acquisition type: single shot EPI", false); break; } case SignalGenerationParameters::SpinEcho: { PrintToLog("Acquisition type: classic spin echo with cartesian k-space trajectory", false); break; } default: { PrintToLog("Acquisition type: single shot EPI", false); break; } } if (m_Parameters.m_SignalGen.m_NoiseVariance>0) PrintToLog("Simulating complex Gaussian noise", false); if (m_Parameters.m_SignalGen.m_DoSimulateRelaxation) PrintToLog("Simulating signal relaxation", false); if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull()) PrintToLog("Simulating distortions", false); if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) PrintToLog("Simulating ringing artifacts", false); if (m_Parameters.m_SignalGen.m_EddyStrength>0) PrintToLog("Simulating eddy currents", false); if (m_Parameters.m_SignalGen.m_Spikes>0) PrintToLog("Simulating spikes", false); if (m_Parameters.m_SignalGen.m_CroppingFactor<1.0) PrintToLog("Simulating aliasing artifacts", false); if (m_Parameters.m_SignalGen.m_KspaceLineOffset>0) PrintToLog("Simulating ghosts", false); doubleOutImage = SimulateKspaceAcquisition(m_CompartmentImages); signalScale = 1; // already scaled in SimulateKspaceAcquisition() } else // don't do k-space stuff, just sum compartments { PrintToLog("Summing compartments"); doubleOutImage = m_CompartmentImages.at(0); for (unsigned int i=1; i::New(); adder->SetInput1(doubleOutImage); adder->SetInput2(m_CompartmentImages.at(i)); adder->Update(); doubleOutImage = adder->GetOutput(); } } if (this->GetAbortGenerateData()) { PrintToLog("\n", false, false); PrintToLog("Simulation aborted"); return; } PrintToLog("Finalizing image"); if (signalScale>1) PrintToLog(" Scaling signal", false); if (m_Parameters.m_NoiseModel) PrintToLog(" Adding noise", false); unsigned int window = 0; unsigned int min = itk::NumericTraits::max(); ImageRegionIterator it4 (m_OutputImage, m_OutputImage->GetLargestPossibleRegion()); DoubleDwiType::PixelType signal; signal.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); boost::progress_display disp2(m_OutputImage->GetLargestPossibleRegion().GetNumberOfPixels()); PrintToLog("0% 10 20 30 40 50 60 70 80 90 100%", false, true, false); PrintToLog("|----|----|----|----|----|----|----|----|----|----|\n*", false, false, false); int lastTick = 0; while(!it4.IsAtEnd()) { if (this->GetAbortGenerateData()) { PrintToLog("\n", false, false); PrintToLog("Simulation aborted"); return; } ++disp2; unsigned long newTick = 50*disp2.count()/disp2.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) PrintToLog("*", false, false, false); lastTick = newTick; typename OutputImageType::IndexType index = it4.GetIndex(); signal = doubleOutImage->GetPixel(index)*signalScale; if (m_Parameters.m_NoiseModel) m_Parameters.m_NoiseModel->AddNoise(signal); for (unsigned int i=0; i0) signal[i] = floor(signal[i]+0.5); else signal[i] = ceil(signal[i]-0.5); if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]>window) window = signal[i]; if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]SetNthOutput(0, m_OutputImage); PrintToLog("\n", false); PrintToLog("Finished simulation"); m_TimeProbe.Stop(); if (m_Parameters.m_SignalGen.m_DoAddMotion) { PrintToLog("\nHead motion log:", false); PrintToLog(m_MotionLog, false, false); } if (m_Parameters.m_SignalGen.m_Spikes>0) { PrintToLog("\nSpike log:", false); PrintToLog(m_SpikeLog, false, false); } if (m_Logfile.is_open()) m_Logfile.close(); } template< class PixelType > - void TractsToDWIImageFilter< PixelType >::PrintToLog(string m, bool addTime, bool linebreak, bool stdOut) + void TractsToDWIImageFilter< PixelType >::PrintToLog(std::string m, bool addTime, bool linebreak, bool stdOut) { // timestamp if (addTime) { m_Logfile << this->GetTime() << " > "; m_StatusText += this->GetTime() + " > "; if (stdOut) std::cout << this->GetTime() << " > "; } // message if (m_Logfile.is_open()) m_Logfile << m; m_StatusText += m; if (stdOut) std::cout << m; // new line if (linebreak) { if (m_Logfile.is_open()) m_Logfile << "\n"; m_StatusText += "\n"; if (stdOut) std::cout << "\n"; } } template< class PixelType > void TractsToDWIImageFilter< PixelType >::SimulateMotion(int g) { // is motion artifact enabled? // is the current volume g affected by motion? if ( m_Parameters.m_SignalGen.m_DoAddMotion && m_Parameters.m_SignalGen.m_MotionVolumes[g] && g(m_Parameters.m_SignalGen.GetNumVolumes()) ) { if ( m_Parameters.m_SignalGen.m_DoRandomizeMotion ) { // either undo last transform or work on fresh copy of untransformed fibers m_FiberBundleTransformed = m_FiberBundleWorkingCopy->GetDeepCopy(); m_Rotation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[0]*2) -m_Parameters.m_SignalGen.m_Rotation[0]; m_Rotation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[1]*2) -m_Parameters.m_SignalGen.m_Rotation[1]; m_Rotation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[2]*2) -m_Parameters.m_SignalGen.m_Rotation[2]; m_Translation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[0]*2) -m_Parameters.m_SignalGen.m_Translation[0]; m_Translation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[1]*2) -m_Parameters.m_SignalGen.m_Translation[1]; m_Translation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[2]*2) -m_Parameters.m_SignalGen.m_Translation[2]; } else { m_Rotation = m_Parameters.m_SignalGen.m_Rotation / m_NumMotionVolumes; m_Translation = m_Parameters.m_SignalGen.m_Translation / m_NumMotionVolumes; m_MotionCounter++; } // move mask image if (m_MaskImageSet) { ImageRegionIterator maskIt(m_UpsampledMaskImage, m_UpsampledMaskImage->GetLargestPossibleRegion()); m_TransformedMaskImage->FillBuffer(0); while(!maskIt.IsAtEnd()) { if (maskIt.Get()<=0) { ++maskIt; continue; } DoubleDwiType::IndexType index = maskIt.GetIndex(); itk::Point point; m_UpsampledMaskImage->TransformIndexToPhysicalPoint(index, point); if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), m_Rotation[0],m_Rotation[1],m_Rotation[2], m_Translation[0],m_Translation[1],m_Translation[2]); } else { point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), m_Rotation[0]*m_MotionCounter,m_Rotation[1]*m_MotionCounter,m_Rotation[2]*m_MotionCounter, m_Translation[0]*m_MotionCounter,m_Translation[1]*m_MotionCounter,m_Translation[2]*m_MotionCounter); } m_TransformedMaskImage->TransformPhysicalPointToIndex(point, index); if (m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(index)) { m_TransformedMaskImage->SetPixel(index,100); } ++maskIt; } } if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { m_Rotations.push_back(m_Rotation); m_Translations.push_back(m_Translation); m_MotionLog += boost::lexical_cast(g) + " rotation: " + boost::lexical_cast(m_Rotation[0]) + "," + boost::lexical_cast(m_Rotation[1]) + "," + boost::lexical_cast(m_Rotation[2]) + ";"; m_MotionLog += " translation: " + boost::lexical_cast(m_Translation[0]) + "," + boost::lexical_cast(m_Translation[1]) + "," + boost::lexical_cast(m_Translation[2]) + "\n"; } else { m_Rotations.push_back(m_Rotation*m_MotionCounter); m_Translations.push_back(m_Translation*m_MotionCounter); m_MotionLog += boost::lexical_cast(g) + " rotation: " + boost::lexical_cast(m_Rotation[0]*m_MotionCounter) + "," + boost::lexical_cast(m_Rotation[1]*m_MotionCounter) + "," + boost::lexical_cast(m_Rotation[2]*m_MotionCounter) + ";"; m_MotionLog += " translation: " + boost::lexical_cast(m_Translation[0]*m_MotionCounter) + "," + boost::lexical_cast(m_Translation[1]*m_MotionCounter) + "," + boost::lexical_cast(m_Translation[2]*m_MotionCounter) + "\n"; } m_FiberBundleTransformed->TransformFibers(m_Rotation[0],m_Rotation[1],m_Rotation[2],m_Translation[0],m_Translation[1],m_Translation[2]); } else { m_Rotation.Fill(0.0); m_Translation.Fill(0.0); m_Rotations.push_back(m_Rotation); m_Translations.push_back(m_Translation); m_MotionLog += boost::lexical_cast(g) + " rotation: " + boost::lexical_cast(m_Rotation[0]) + "," + boost::lexical_cast(m_Rotation[1]) + "," + boost::lexical_cast(m_Rotation[2]) + ";"; m_MotionLog += " translation: " + boost::lexical_cast(m_Translation[0]) + "," + boost::lexical_cast(m_Translation[1]) + "," + boost::lexical_cast(m_Translation[2]) + "\n"; } } template< class PixelType > void TractsToDWIImageFilter< PixelType >:: SimulateExtraAxonalSignal(ItkUcharImgType::IndexType index, double intraAxonalVolume, int g) { int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); if (intraAxonalVolume>0.0001 && m_Parameters.m_SignalGen.m_DoDisablePartialVolume) // only fiber in voxel { DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(index); if (g>=0) pix[g] *= m_VoxelVolume/intraAxonalVolume; else pix *= m_VoxelVolume/intraAxonalVolume; m_CompartmentImages.at(0)->SetPixel(index, pix); if (g==0) m_VolumeFractions.at(0)->SetPixel(index, 1); for (int i=1; iGetPixel(index); if (g>=0) pix[g] = 0.0; else pix.Fill(0.0); m_CompartmentImages.at(i)->SetPixel(index, pix); } } else { if (g==0) { m_VolumeFractions.at(0)->SetPixel(index, intraAxonalVolume/m_VoxelVolume); } // get non-transformed point (remove headmotion tranformation) // this point can then be transformed to each of the original images, regardless of their geometry itk::Point point; m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, point); if ( m_Parameters.m_SignalGen.m_DoAddMotion && g>=0 && m_Parameters.m_SignalGen.m_MotionVolumes[g] ) { if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), -m_Rotation[0],-m_Rotation[1],-m_Rotation[2], -m_Translation[0],-m_Translation[1],-m_Translation[2]); } else { point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), -m_Rotation[0]*m_MotionCounter,-m_Rotation[1]*m_MotionCounter,-m_Rotation[2]*m_MotionCounter, -m_Translation[0]*m_MotionCounter,-m_Translation[1]*m_MotionCounter,-m_Translation[2]*m_MotionCounter); } } if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume) { int maxVolumeIndex = 0; double maxWeight = 0; for (int i=0; i1) { double val = InterpolateValue(point, m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()); if (val<0) mitkThrow() << "Volume fraction image (index " << i << ") contains values less than zero!"; else weight = val; } if (weight>maxWeight) { maxWeight = weight; maxVolumeIndex = i; } } DoubleDwiType::Pointer doubleDwi = m_CompartmentImages.at(maxVolumeIndex+numFiberCompartments); DoubleDwiType::PixelType pix = doubleDwi->GetPixel(index); if (g>=0) pix[g] += m_Parameters.m_NonFiberModelList[maxVolumeIndex]->SimulateMeasurement(g)*m_VoxelVolume; else pix += m_Parameters.m_NonFiberModelList[maxVolumeIndex]->SimulateMeasurement()*m_VoxelVolume; doubleDwi->SetPixel(index, pix); if (g==0) m_VolumeFractions.at(maxVolumeIndex+numFiberCompartments)->SetPixel(index, 1); } else { double extraAxonalVolume = m_VoxelVolume-intraAxonalVolume; // non-fiber volume if (extraAxonalVolume<0) { if (extraAxonalVolume<-0.001) MITK_ERROR << "Corrupted intra-axonal signal voxel detected. Fiber volume larger voxel volume! " << m_VoxelVolume << "<" << intraAxonalVolume; extraAxonalVolume = 0; } double interAxonalVolume = 0; if (numFiberCompartments>1) interAxonalVolume = extraAxonalVolume * intraAxonalVolume/m_VoxelVolume; // inter-axonal fraction of non fiber compartment double other = extraAxonalVolume - interAxonalVolume; // rest of compartment if (other<0) { if (other<-0.001) MITK_ERROR << "Corrupted signal voxel detected. Fiber volume larger voxel volume!"; other = 0; interAxonalVolume = extraAxonalVolume; } double compartmentSum = intraAxonalVolume; // adjust non-fiber and intra-axonal signal for (int i=1; iGetPixel(index); if (intraAxonalVolume>0) // remove scaling by intra-axonal volume from inter-axonal compartment { if (g>=0) pix[g] /= intraAxonalVolume; else pix /= intraAxonalVolume; } else { if (g>=0) pix[g] = 0; else pix *= 0; } if (m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()!=nullptr) { double val = InterpolateValue(point, m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()); if (val<0) mitkThrow() << "Volume fraction image (index " << i+1 << ") contains negative values!"; else weight = val*m_VoxelVolume; } compartmentSum += weight; if (g>=0) pix[g] *= weight; else pix *= weight; m_CompartmentImages.at(i)->SetPixel(index, pix); if (g==0) m_VolumeFractions.at(i)->SetPixel(index, weight/m_VoxelVolume); } for (int i=0; iGetPixel(index); if (m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()!=nullptr) { double val = InterpolateValue(point, m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()); if (val<0) mitkThrow() << "Volume fraction image (index " << numFiberCompartments+i+1 << ") contains negative values (non-fiber compartment)!"; else weight = val*m_VoxelVolume; if (m_UseRelativeNonFiberVolumeFractions) weight *= other/m_VoxelVolume; } compartmentSum += weight; if (g>=0) pix[g] += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement(g)*weight; else pix += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement()*weight; m_CompartmentImages.at(i+numFiberCompartments)->SetPixel(index, pix); if (g==0) m_VolumeFractions.at(i+numFiberCompartments)->SetPixel(index, weight/m_VoxelVolume); } if (compartmentSum/m_VoxelVolume>1.05) MITK_ERROR << "Compartments do not sum to 1 in voxel " << index << " (" << compartmentSum/m_VoxelVolume << ")"; } } } template< class PixelType > double TractsToDWIImageFilter< PixelType >:: InterpolateValue(itk::Point itkP, ItkDoubleImgType::Pointer img) { itk::Index<3> idx; itk::ContinuousIndex< double, 3> cIdx; img->TransformPhysicalPointToIndex(itkP, idx); img->TransformPhysicalPointToContinuousIndex(itkP, cIdx); double pix = 0; if ( img->GetLargestPossibleRegion().IsInside(idx) ) pix = img->GetPixel(idx); else return pix; double frac_x = cIdx[0] - idx[0]; double frac_y = cIdx[1] - idx[1]; double frac_z = cIdx[2] - idx[2]; if (frac_x<0) { idx[0] -= 1; frac_x += 1; } if (frac_y<0) { idx[1] -= 1; frac_y += 1; } if (frac_z<0) { idx[2] -= 1; frac_z += 1; } frac_x = 1-frac_x; frac_y = 1-frac_y; frac_z = 1-frac_z; // int coordinates inside image? if (idx[0] >= 0 && idx[0] < static_cast(img->GetLargestPossibleRegion().GetSize(0) - 1) && idx[1] >= 0 && idx[1] < static_cast(img->GetLargestPossibleRegion().GetSize(1) - 1) && idx[2] >= 0 && idx[2] < static_cast(img->GetLargestPossibleRegion().GetSize(2) - 1)) { vnl_vector_fixed interpWeights; interpWeights[0] = ( frac_x)*( frac_y)*( frac_z); interpWeights[1] = (1-frac_x)*( frac_y)*( frac_z); interpWeights[2] = ( frac_x)*(1-frac_y)*( frac_z); interpWeights[3] = ( frac_x)*( frac_y)*(1-frac_z); interpWeights[4] = (1-frac_x)*(1-frac_y)*( frac_z); interpWeights[5] = ( frac_x)*(1-frac_y)*(1-frac_z); interpWeights[6] = (1-frac_x)*( frac_y)*(1-frac_z); interpWeights[7] = (1-frac_x)*(1-frac_y)*(1-frac_z); pix = img->GetPixel(idx) * interpWeights[0]; ItkDoubleImgType::IndexType tmpIdx = idx; tmpIdx[0]++; pix += img->GetPixel(tmpIdx) * interpWeights[1]; tmpIdx = idx; tmpIdx[1]++; pix += img->GetPixel(tmpIdx) * interpWeights[2]; tmpIdx = idx; tmpIdx[2]++; pix += img->GetPixel(tmpIdx) * interpWeights[3]; tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; pix += img->GetPixel(tmpIdx) * interpWeights[4]; tmpIdx = idx; tmpIdx[1]++; tmpIdx[2]++; pix += img->GetPixel(tmpIdx) * interpWeights[5]; tmpIdx = idx; tmpIdx[2]++; tmpIdx[0]++; pix += img->GetPixel(tmpIdx) * interpWeights[6]; tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; tmpIdx[2]++; pix += img->GetPixel(tmpIdx) * interpWeights[7]; } return pix; } template< class PixelType > itk::Point TractsToDWIImageFilter< PixelType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class PixelType > itk::Vector TractsToDWIImageFilter< PixelType >::GetItkVector(double point[3]) { itk::Vector itkVector; itkVector[0] = point[0]; itkVector[1] = point[1]; itkVector[2] = point[2]; return itkVector; } template< class PixelType > vnl_vector_fixed TractsToDWIImageFilter< PixelType >::GetVnlVector(double point[3]) { vnl_vector_fixed vnlVector; vnlVector[0] = point[0]; vnlVector[1] = point[1]; vnlVector[2] = point[2]; return vnlVector; } template< class PixelType > vnl_vector_fixed TractsToDWIImageFilter< PixelType >::GetVnlVector(Vector& vector) { vnl_vector_fixed vnlVector; vnlVector[0] = vector[0]; vnlVector[1] = vector[1]; vnlVector[2] = vector[2]; return vnlVector; } template< class PixelType > double TractsToDWIImageFilter< PixelType >::RoundToNearest(double num) { return (num > 0.0) ? floor(num + 0.5) : ceil(num - 0.5); } template< class PixelType > std::string TractsToDWIImageFilter< PixelType >::GetTime() { m_TimeProbe.Stop(); unsigned long total = RoundToNearest(m_TimeProbe.GetTotal()); unsigned long hours = total/3600; unsigned long minutes = (total%3600)/60; unsigned long seconds = total%60; std::string out = ""; out.append(boost::lexical_cast(hours)); out.append(":"); out.append(boost::lexical_cast(minutes)); out.append(":"); out.append(boost::lexical_cast(seconds)); m_TimeProbe.Start(); return out; } } diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.h index b1cf984985..cb2372167d 100755 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.h @@ -1,163 +1,163 @@ /*=================================================================== 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 __itkTractsToDWIImageFilter_h__ #define __itkTractsToDWIImageFilter_h__ #include #include #include #include #include #include #include #include #include namespace itk { /** * \brief Generates artificial diffusion weighted image volume from the input fiberbundle using a generic multicompartment model. * See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. */ template< class PixelType > class TractsToDWIImageFilter : public ImageSource< itk::VectorImage< PixelType, 3 > > { public: typedef TractsToDWIImageFilter Self; typedef ImageSource< itk::VectorImage< PixelType, 3 > > Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename Superclass::OutputImageType OutputImageType; typedef itk::Image ItkDoubleImgType4D; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; typedef mitk::FiberBundle::Pointer FiberBundleType; typedef itk::VectorImage< double, 3 > DoubleDwiType; typedef itk::Matrix MatrixType; typedef itk::Image< double, 2 > SliceType; typedef itk::VnlForwardFFTImageFilter::OutputImageType ComplexSliceType; typedef itk::VectorImage< vcl_complex< double >, 3 > ComplexDwiType; typedef itk::Vector< double,3> DoubleVectorType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( TractsToDWIImageFilter, ImageSource ) /** Input */ itkSetMacro( FiberBundle, FiberBundleType ) ///< Input fiber bundle itkSetMacro( InputImage, typename OutputImageType::Pointer ) ///< Input diffusion-weighted image. If no fiber bundle is set, then the acquisition is simulated for this image without a new diffusion simulation. itkSetMacro( UseConstantRandSeed, bool ) ///< Seed for random generator. void SetParameters( FiberfoxParameters param ) ///< Simulation parameters. { m_Parameters = param; } /** Output */ FiberfoxParameters GetParameters(){ return m_Parameters; } std::vector< ItkDoubleImgType::Pointer > GetVolumeFractions() ///< one double image for each compartment containing the corresponding volume fraction per voxel { return m_VolumeFractions; } mitk::LevelWindow GetLevelWindow() ///< Level window is determined from the output image { return m_LevelWindow; } itkGetMacro( StatusText, std::string ) itkGetMacro( PhaseImage, DoubleDwiType::Pointer ) itkGetMacro( KspaceImage, DoubleDwiType::Pointer ) itkGetMacro( CoilPointset, mitk::PointSet::Pointer ) void GenerateData(); protected: TractsToDWIImageFilter(); virtual ~TractsToDWIImageFilter(); itk::Point GetItkPoint(double point[3]); itk::Vector GetItkVector(double point[3]); vnl_vector_fixed GetVnlVector(double point[3]); vnl_vector_fixed GetVnlVector(Vector< float, 3 >& vector); double RoundToNearest(double num); std::string GetTime(); bool PrepareLogFile(); /** Prepares the log file and returns true if successful or false if failed. */ - void PrintToLog(string m, bool addTime=true, bool linebreak=true, bool stdOut=true); + void PrintToLog(std::string m, bool addTime=true, bool linebreak=true, bool stdOut=true); /** Transform generated image compartment by compartment, channel by channel and slice by slice using DFT and add k-space artifacts/effects. */ DoubleDwiType::Pointer SimulateKspaceAcquisition(std::vector< DoubleDwiType::Pointer >& images); /** Generate signal of non-fiber compartments. */ void SimulateExtraAxonalSignal(ItkUcharImgType::IndexType index, double intraAxonalVolume, int g=-1); /** Move fibers to simulate headmotion */ void SimulateMotion(int g=-1); void CheckVolumeFractionImages(); ItkDoubleImgType::Pointer NormalizeInsideMask(ItkDoubleImgType::Pointer image); void InitializeData(); void InitializeFiberData(); double InterpolateValue(itk::Point itkP, ItkDoubleImgType::Pointer img); // input mitk::FiberfoxParameters m_Parameters; FiberBundleType m_FiberBundle; typename OutputImageType::Pointer m_InputImage; // output typename OutputImageType::Pointer m_OutputImage; typename DoubleDwiType::Pointer m_PhaseImage; typename DoubleDwiType::Pointer m_KspaceImage; mitk::LevelWindow m_LevelWindow; std::vector< ItkDoubleImgType::Pointer > m_VolumeFractions; std::string m_StatusText; // MISC itk::TimeProbe m_TimeProbe; bool m_UseConstantRandSeed; bool m_MaskImageSet; ofstream m_Logfile; std::string m_MotionLog; std::string m_SpikeLog; // signal generation FiberBundleType m_FiberBundleWorkingCopy; ///< we work on an upsampled version of the input bundle FiberBundleType m_FiberBundleTransformed; ///< transformed bundle simulating headmotion itk::Vector m_WorkingSpacing; itk::Point m_WorkingOrigin; ImageRegion<3> m_WorkingImageRegion; double m_VoxelVolume; std::vector< DoubleDwiType::Pointer > m_CompartmentImages; ItkUcharImgType::Pointer m_TransformedMaskImage; ///< copy of mask image (changes for each motion step) ItkUcharImgType::Pointer m_UpsampledMaskImage; ///< helper image for motion simulation DoubleVectorType m_Rotation; DoubleVectorType m_Translation; std::vector< DoubleVectorType > m_Rotations; /// m_Translations; /// #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"; -using namespace std; - 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 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::AddBundle(mitk::FiberBundle* fib) +mitk::FiberBundle::Pointer mitk::FiberBundle::AddBundles(std::vector< mitk::FiberBundle::Pointer > fibs) { - if (fib==nullptr) + 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++) { - MITK_WARN << "trying to call AddBundle with nullptr argument"; - return nullptr; + 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) { - MITK_INFO << "Subtracting fibers"; + 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; +// 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(); - } +//#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 nullptr; + 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); - vector< double > values; + 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::ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert, bool bothEnds, float fraction, bool do_resampling) { + if (m_NumFibers==0 || mask==nullptr) + return mitk::FiberBundle::New(nullptr); + vtkSmartPointer PolyData = m_FiberPolyData; mitk::FiberBundle::Pointer fibCopy = this; if (anyPoint && 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(); } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); std::vector< float > new_weights; MITK_INFO << "Extracting fibers with mask image"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cellOriginal = m_FiberPolyData->GetCell(i); int numPointsOriginal = cellOriginal->GetNumberOfPoints(); vtkPoints* pointsOriginal = cellOriginal->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1 && numPointsOriginal) { if (anyPoint) { int inside = 0; int outside = 0; if (!invert) { for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetLargestPossibleRegion().IsInside(idx) && mask->GetPixel(idx) != 0 ) { inside++; if (fraction==0) break; } else outside++; } float current_fraction = 0.0; if (inside+outside>0) current_fraction = (float)inside/(inside+outside); if (current_fraction>fraction) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } else { bool includeFiber = true; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx) != 0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { inside++; includeFiber = false; break; } else outside++; } if (includeFiber) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } else { double* start = pointsOriginal->GetPoint(0); itk::Point itkStart; itkStart[0] = start[0]; itkStart[1] = start[1]; itkStart[2] = start[2]; itk::Index<3> idxStart; mask->TransformPhysicalPointToIndex(itkStart, idxStart); double* end = pointsOriginal->GetPoint(numPointsOriginal-1); itk::Point itkEnd; itkEnd[0] = end[0]; itkEnd[1] = end[1]; itkEnd[2] = end[2]; itk::Index<3> idxEnd; mask->TransformPhysicalPointToIndex(itkEnd, idxEnd); if (invert) { if (bothEnds) { if ( mask->GetPixel(idxStart) == 0 && mask->GetPixel(idxEnd) == 0 ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } else if ( mask->GetPixel(idxStart) == 0 || mask->GetPixel(idxEnd) == 0 ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } else { if (bothEnds) { if ( mask->GetPixel(idxStart) != 0 && mask->GetPixel(idxEnd) != 0 && mask->GetLargestPossibleRegion().IsInside(idxStart) && mask->GetLargestPossibleRegion().IsInside(idxEnd) ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } else if ( (mask->GetPixel(idxStart) != 0 && mask->GetLargestPossibleRegion().IsInside(idxStart)) || (mask->GetPixel(idxEnd) != 0 && mask->GetLargestPossibleRegion().IsInside(idxEnd)) ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } } if (container->GetNumberOfPoints()>0) { new_weights.push_back(fibCopy->GetFiberWeight(i)); vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) - return nullptr; + return mitk::FiberBundle::New(nullptr); vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); + mitk::FiberBundle::Pointer newfib = mitk::FiberBundle::New(newPolyData); for (unsigned int i=0; iSetFiberWeight(i, new_weights.at(i)); return newfib; } 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 pTmp = GeneratePolyDataByIds(tmp); - return mitk::FiberBundle::New(pTmp); + 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(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 vtkIdType pointHelperCnt = 0; MITK_INFO << "Smoothing fibers"; vtkSmartPointer newFiberWeights = vtkSmartPointer::New(); newFiberWeights->SetName("FIBER_WEIGHTS"); newFiberWeights->SetNumberOfValues(m_NumFibers); boost::progress_display disp(m_NumFibers); #pragma omp parallel for for (int i=0; i newPoints = vtkSmartPointer::New(); float length = 0; float weight = 1; #pragma omp critical { length = m_FiberLengths.at(i); weight = m_FiberWeights->GetValue(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(); smoothLine->GetPointIds()->SetNumberOfIds(tmpSmoothPnts->GetNumberOfPoints()); #pragma omp critical { for (int j=0; jGetNumberOfPoints(); j++) { smoothLine->GetPointIds()->SetId(j, j+pointHelperCnt); vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j)); } newFiberWeights->SetValue(vtkSmoothCells->GetNumberOfCells(), weight); vtkSmoothCells->InsertNextCell(smoothLine); pointHelperCnt += tmpSmoothPnts->GetNumberOfPoints(); } } SetFiberWeights(newFiberWeights); 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::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); #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); } } 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 { newFiberWeights->SetValue(vtkNewCells->GetNumberOfCells(), weight); vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()>0) { SetFiberWeights(newFiberWeights); 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 a49a44e2dd..863c50b64d 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.h @@ -1,179 +1,179 @@ /*=================================================================== 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 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); + 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 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 ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert=false, bool bothEnds=true, float fraction=0.0, bool do_resampling=true); FiberBundle::Pointer RemoveFibersOutside(ItkUcharImgType* mask, bool invert=false); - - vtkSmartPointer GeneratePolyDataByIds( std::vector ); // TODO: make protected - void GenerateFiberIds(); // TODO: make protected + float GetOverlap(ItkUcharImgType* mask, bool do_resampling); + mitk::FiberBundle::Pointer SubsampleFibers(float factor); // get/set data 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 ) protected: FiberBundle( vtkPolyData* fiberPolyData = nullptr ); virtual ~FiberBundle(); - itk::Point GetItkPoint(double point[3]); - - // calculate geometry from fiber extent - void UpdateFiberGeometry(); - - virtual void PrintSelf(std::ostream &os, itk::Indent indent) const override; + vtkSmartPointer GeneratePolyDataByIds(std::vector fiberIds, vtkSmartPointer weights); + 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/IODataStructures/FiberBundle/mitkTrackvis.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.cpp index e501575e58..b83375800c 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.cpp @@ -1,240 +1,241 @@ #include #include TrackVisFiberReader::TrackVisFiberReader() { m_Filename = ""; m_FilePointer = nullptr; } TrackVisFiberReader::~TrackVisFiberReader() { if (m_FilePointer) fclose( m_FilePointer ); } // Create a TrackVis file and store standard metadata. The file is ready to append fibers. // --------------------------------------------------------------------------------------- -short TrackVisFiberReader::create(string filename , const mitk::FiberBundle *fib, bool lps) +short TrackVisFiberReader::create(std::string filename , const mitk::FiberBundle *fib, bool lps) { - // prepare the header - for(int i=0; i<3 ;i++) + // prepare the header + for(int i=0; i<3 ;i++) + { + if (fib->GetReferenceGeometry().IsNotNull()) { - if (fib->GetReferenceGeometry().IsNotNull()) - { - m_Header.dim[i] = fib->GetReferenceGeometry()->GetExtent(i); - m_Header.voxel_size[i] = fib->GetReferenceGeometry()->GetSpacing()[i]; - m_Header.origin[i] = fib->GetReferenceGeometry()->GetOrigin()[i]; - } - else - { - m_Header.dim[i] = fib->GetGeometry()->GetExtent(i); - m_Header.voxel_size[i] = fib->GetGeometry()->GetSpacing()[i]; - m_Header.origin[i] = fib->GetGeometry()->GetOrigin()[i]; - } + m_Header.dim[i] = fib->GetReferenceGeometry()->GetExtent(i); + m_Header.voxel_size[i] = fib->GetReferenceGeometry()->GetSpacing()[i]; + m_Header.origin[i] = fib->GetReferenceGeometry()->GetOrigin()[i]; } - m_Header.n_scalars = 0; - m_Header.n_properties = 0; - if (lps) - sprintf(m_Header.voxel_order,"LPS"); else - sprintf(m_Header.voxel_order,"RAS"); - m_Header.image_orientation_patient[0] = 1.0; - m_Header.image_orientation_patient[1] = 0.0; - m_Header.image_orientation_patient[2] = 0.0; - m_Header.image_orientation_patient[3] = 0.0; - m_Header.image_orientation_patient[4] = 1.0; - m_Header.image_orientation_patient[5] = 0.0; - m_Header.pad1[0] = 0; - m_Header.pad1[1] = 0; - m_Header.pad2[0] = 0; - m_Header.pad2[1] = 0; - m_Header.invert_x = 0; - m_Header.invert_y = 0; - m_Header.invert_z = 0; - m_Header.swap_xy = 0; - m_Header.swap_yz = 0; - m_Header.swap_zx = 0; - m_Header.n_count = 0; - m_Header.version = 1; - m_Header.hdr_size = 1000; - - // write the header to the file - m_FilePointer = fopen(filename.c_str(),"w+b"); - if (m_FilePointer == nullptr) { - printf("[ERROR] Unable to create file '%s'\n",filename.c_str()); - return 0; + m_Header.dim[i] = fib->GetGeometry()->GetExtent(i); + m_Header.voxel_size[i] = fib->GetGeometry()->GetSpacing()[i]; + m_Header.origin[i] = fib->GetGeometry()->GetOrigin()[i]; } - sprintf(m_Header.id_string,"TRACK"); - if (fwrite((char*)&m_Header, 1, 1000, m_FilePointer) != 1000) - MITK_ERROR << "TrackVis::create : Error occurding during writing fiber."; + } + m_Header.n_scalars = 0; + m_Header.n_properties = 0; + if (lps) + sprintf(m_Header.voxel_order,"LPS"); + else + sprintf(m_Header.voxel_order,"RAS"); + m_Header.image_orientation_patient[0] = 1.0; + m_Header.image_orientation_patient[1] = 0.0; + m_Header.image_orientation_patient[2] = 0.0; + m_Header.image_orientation_patient[3] = 0.0; + m_Header.image_orientation_patient[4] = 1.0; + m_Header.image_orientation_patient[5] = 0.0; + m_Header.pad1[0] = 0; + m_Header.pad1[1] = 0; + m_Header.pad2[0] = 0; + m_Header.pad2[1] = 0; + m_Header.invert_x = 0; + m_Header.invert_y = 0; + m_Header.invert_z = 0; + m_Header.swap_xy = 0; + m_Header.swap_yz = 0; + m_Header.swap_zx = 0; + m_Header.n_count = 0; + m_Header.version = 1; + m_Header.hdr_size = 1000; + + // write the header to the file + m_FilePointer = fopen(filename.c_str(),"w+b"); + if (m_FilePointer == nullptr) + { + printf("[ERROR] Unable to create file '%s'\n",filename.c_str()); + return 0; + } + sprintf(m_Header.id_string,"TRACK"); + if (fwrite((char*)&m_Header, 1, 1000, m_FilePointer) != 1000) + MITK_ERROR << "TrackVis::create : Error occurding during writing fiber."; - this->m_Filename = filename; + this->m_Filename = filename; - return 1; + return 1; } // Open an existing TrackVis file and read metadata information. // The file pointer is positiond at the beginning of fibers data // ------------------------------------------------------------- -short TrackVisFiberReader::open( string filename ) +short TrackVisFiberReader::open( std::string filename ) { - m_FilePointer = fopen(filename.c_str(), "rb"); - if (m_FilePointer == nullptr) - { - printf("[ERROR] Unable to open file '%s'\n",filename.c_str()); - return 0; - } - this->m_Filename = filename; + m_FilePointer = std::fopen(filename.c_str(), "rb"); + if (m_FilePointer == nullptr) + { + printf("[ERROR] Unable to open file '%s'\n",filename.c_str()); + return 0; + } + this->m_Filename = filename; - return fread((char*)(&m_Header), 1, 1000, m_FilePointer); + return fread((char*)(&m_Header), 1, 1000, m_FilePointer); } // Append a fiber to the file // -------------------------- short TrackVisFiberReader::append(const mitk::FiberBundle *fib) { - vtkPolyData* poly = fib->GetFiberPolyData(); - for (int i=0; iGetNumFibers(); i++) + vtkPolyData* poly = fib->GetFiberPolyData(); + for (int i=0; iGetNumFibers(); i++) + { + vtkCell* cell = poly->GetCell(i); + int numPoints = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); + + unsigned int numSaved, pos = 0; + //float* tmp = new float[3*maxSteps]; + std::vector< float > tmp; + tmp.reserve(3*numPoints); + + numSaved = numPoints; + for(unsigned int i=0; iGetCell(i); - int numPoints = cell->GetNumberOfPoints(); - vtkPoints* points = cell->GetPoints(); - - unsigned int numSaved, pos = 0; - //float* tmp = new float[3*maxSteps]; - std::vector< float > tmp; - tmp.reserve(3*numPoints); - - numSaved = numPoints; - for(unsigned int i=0; iGetPoint(i); - - tmp[pos++] = p[0]; - tmp[pos++] = p[1]; - tmp[pos++] = p[2]; - } - - // write the coordinates to the file - if ( fwrite((char*)&numSaved, 1, 4, m_FilePointer) != 4 ) - { - printf( "[ERROR] Problems saving the fiber!\n" ); - return 1; - } - if ( fwrite((char*)&(tmp.front()), 1, 4*pos, m_FilePointer) != 4*pos ) - { - printf( "[ERROR] Problems saving the fiber!\n" ); - return 1; - } + double* p = points->GetPoint(i); + + tmp[pos++] = p[0]; + tmp[pos++] = p[1]; + tmp[pos++] = p[2]; } - return 0; + // write the coordinates to the file + if ( fwrite((char*)&numSaved, 1, 4, m_FilePointer) != 4 ) + { + printf( "[ERROR] Problems saving the fiber!\n" ); + return 1; + } + if ( fwrite((char*)&(tmp.front()), 1, 4*pos, m_FilePointer) != 4*pos ) + { + printf( "[ERROR] Problems saving the fiber!\n" ); + return 1; + } + } + + return 0; } //// Read one fiber from the file //// ---------------------------- short TrackVisFiberReader::read( mitk::FiberBundle* fib ) { - int numPoints; - vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); - vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); + int numPoints; + vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); + vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); - while (fread((char*)&numPoints, 1, 4, m_FilePointer)==4) + while (fread((char*)&numPoints, 1, 4, m_FilePointer)==4) + { + if ( numPoints <= 0 ) { - if ( numPoints <= 0 ) - { - printf( "[ERROR] Trying to read a fiber with %d points!\n", numPoints ); - return -1; - } - vtkSmartPointer container = vtkSmartPointer::New(); - - float tmp[3]; - for(int i=0; iInsertNextPoint(tmp); - container->GetPointIds()->InsertNextId(id); - } - vtkNewCells->InsertNextCell(container); + printf( "[ERROR] Trying to read a fiber with %d points!\n", numPoints ); + return -1; } + vtkSmartPointer container = vtkSmartPointer::New(); - vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); - fiberPolyData->SetPoints(vtkNewPoints); - fiberPolyData->SetLines(vtkNewCells); - - MITK_INFO << "Coordinate convention: " << m_Header.voxel_order; - - mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); - vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New(); - matrix->Identity(); - - if (m_Header.voxel_order[0]=='R') - matrix->SetElement(0,0,-matrix->GetElement(0,0)); - if (m_Header.voxel_order[1]=='A') - matrix->SetElement(1,1,-matrix->GetElement(1,1)); - if (m_Header.voxel_order[2]=='I') - matrix->SetElement(2,2,-matrix->GetElement(2,2)); - - geometry->SetIndexToWorldTransformByVtkMatrix(matrix); - - vtkSmartPointer transformFilter = vtkSmartPointer::New(); - transformFilter->SetInputData(fiberPolyData); - transformFilter->SetTransform(geometry->GetVtkTransform()); - transformFilter->Update(); - fib->SetFiberPolyData(transformFilter->GetOutput()); - - mitk::Point3D origin; - origin[0]=m_Header.origin[0]; - origin[1]=m_Header.origin[1]; - origin[2]=m_Header.origin[2]; - geometry->SetOrigin(origin); - - mitk::Vector3D spacing; - spacing[0]=m_Header.voxel_size[0]; - spacing[1]=m_Header.voxel_size[1]; - spacing[2]=m_Header.voxel_size[2]; - geometry->SetSpacing(spacing); + float tmp[3]; + for(int i=0; iInsertNextPoint(tmp); + container->GetPointIds()->InsertNextId(id); + } + vtkNewCells->InsertNextCell(container); + } + + vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); + fiberPolyData->SetPoints(vtkNewPoints); + fiberPolyData->SetLines(vtkNewCells); + + // MITK_INFO << "Coordinate convention: " << m_Header.voxel_order; + + mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); + vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New(); + matrix->Identity(); + + if (m_Header.voxel_order[0]=='R') + matrix->SetElement(0,0,-matrix->GetElement(0,0)); + if (m_Header.voxel_order[1]=='A') + matrix->SetElement(1,1,-matrix->GetElement(1,1)); + if (m_Header.voxel_order[2]=='I') + matrix->SetElement(2,2,-matrix->GetElement(2,2)); + + geometry->SetIndexToWorldTransformByVtkMatrix(matrix); + + vtkSmartPointer transformFilter = vtkSmartPointer::New(); + transformFilter->SetInputData(fiberPolyData); + transformFilter->SetTransform(geometry->GetVtkTransform()); + transformFilter->Update(); + fib->SetFiberPolyData(transformFilter->GetOutput()); + + mitk::Point3D origin; + origin[0]=m_Header.origin[0]; + origin[1]=m_Header.origin[1]; + origin[2]=m_Header.origin[2]; + geometry->SetOrigin(origin); + + mitk::Vector3D spacing; + spacing[0]=m_Header.voxel_size[0]; + spacing[1]=m_Header.voxel_size[1]; + spacing[2]=m_Header.voxel_size[2]; + + if (spacing[0]>0 && spacing[1]>0 && spacing[2]>0 && m_Header.dim[0]>0 && m_Header.dim[1]>0 && m_Header.dim[2]>0) + { + geometry->SetSpacing(spacing); geometry->SetExtentInMM(0, m_Header.voxel_size[0]*m_Header.dim[0]); geometry->SetExtentInMM(1, m_Header.voxel_size[1]*m_Header.dim[1]); geometry->SetExtentInMM(2, m_Header.voxel_size[2]*m_Header.dim[2]); - fib->SetReferenceGeometry(dynamic_cast(geometry.GetPointer())); - - return numPoints; + } + return numPoints; } // Update the field in the header to the new FIBER TOTAL. // ------------------------------------------------------ void TrackVisFiberReader::updateTotal( int totFibers ) { - fseek(m_FilePointer, 1000-12, SEEK_SET); - if (fwrite((char*)&totFibers, 1, 4, m_FilePointer) != 4) - MITK_ERROR << "[ERROR] Problems saving the fiber!"; + fseek(m_FilePointer, 1000-12, SEEK_SET); + if (fwrite((char*)&totFibers, 1, 4, m_FilePointer) != 4) + MITK_ERROR << "[ERROR] Problems saving the fiber!"; } void TrackVisFiberReader::writeHdr() { - fseek(m_FilePointer, 0, SEEK_SET); - if (fwrite((char*)&m_Header, 1, 1000, m_FilePointer) != 1000) - MITK_ERROR << "[ERROR] Problems saving the fiber!"; + fseek(m_FilePointer, 0, SEEK_SET); + if (fwrite((char*)&m_Header, 1, 1000, m_FilePointer) != 1000) + MITK_ERROR << "[ERROR] Problems saving the fiber!"; } // Close the TrackVis file, but keep the metadata in the header. // ------------------------------------------------------------- void TrackVisFiberReader::close() { - fclose(m_FilePointer); - m_FilePointer = nullptr; + fclose(m_FilePointer); + m_FilePointer = nullptr; } bool TrackVisFiberReader::IsTransformValid() { - if (fabs(m_Header.image_orientation_patient[0])<=0.001 || fabs(m_Header.image_orientation_patient[3])<=0.001 || fabs(m_Header.image_orientation_patient[5])<=0.001) - return false; - return true; + if (fabs(m_Header.image_orientation_patient[0])<=0.001 || fabs(m_Header.image_orientation_patient[3])<=0.001 || fabs(m_Header.image_orientation_patient[5])<=0.001) + return false; + return true; } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.h index ee931b73df..513b0a5ca5 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.h @@ -1,82 +1,80 @@ /*=================================================================== 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 _TRACKVIS #define _TRACKVIS #include #include #include #include #include #include #include #include -using namespace std; - // Structure to hold metadata of a TrackVis file // --------------------------------------------- struct TrackVis_header { char id_string[6]; short int dim[3]; float voxel_size[3]; float origin[3]; short int n_scalars; char scalar_name[10][20]; short int n_properties; char property_name[10][20]; char reserved[508]; char voxel_order[4]; char pad2[4]; float image_orientation_patient[6]; char pad1[2]; unsigned char invert_x; unsigned char invert_y; unsigned char invert_z; unsigned char swap_xy; unsigned char swap_yz; unsigned char swap_zx; int n_count; int version; int hdr_size; }; // Class to handle TrackVis files. // ------------------------------- class MITKFIBERTRACKING_EXPORT TrackVisFiberReader { private: - string m_Filename; + std::string m_Filename; FILE* m_FilePointer; public: TrackVis_header m_Header; - short create(string m_Filename, const mitk::FiberBundle* fib, bool lps); - short open( string m_Filename ); + short create(std::string m_Filename, const mitk::FiberBundle* fib, bool lps); + short open(std::string m_Filename ); short read( mitk::FiberBundle* fib ); short append(const mitk::FiberBundle* fib ); void writeHdr(); void updateTotal( int totFibers ); void close(); bool IsTransformValid(); TrackVisFiberReader(); ~TrackVisFiberReader(); }; #endif diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp index 94b7d103a7..b1e9857193 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp @@ -1,871 +1,872 @@ /*=================================================================== 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 RAPIDXML_NO_EXCEPTIONS #include #include #include #include #include #include +#include template< class ScalarType > mitk::FiberfoxParameters< ScalarType >::FiberfoxParameters() : m_NoiseModel(nullptr) { } template< class ScalarType > mitk::FiberfoxParameters< ScalarType >::~FiberfoxParameters() { // if (m_NoiseModel!=nullptr) // delete m_NoiseModel; } void mitk::SignalGenerationParameters::GenerateGradientHalfShell() { int NPoints = 2*m_NumGradients; m_GradientDirections.clear(); m_NumBaseline = NPoints/20; if (m_NumBaseline==0) m_NumBaseline=1; GradientType g; g.Fill(0.0); for (unsigned int i=0; i theta; theta.set_size(NPoints); vnl_vector phi; phi.set_size(NPoints); double C = sqrt(4*M_PI); phi(0) = 0.0; phi(NPoints-1) = 0.0; for(int i=0; i0 && i mitk::SignalGenerationParameters::GetBaselineIndices() { std::vector< int > result; for( unsigned int i=0; im_GradientDirections.size(); i++) if (m_GradientDirections.at(i).GetNorm()<0.0001) result.push_back(i); return result; } unsigned int mitk::SignalGenerationParameters::GetFirstBaselineIndex() { for( unsigned int i=0; im_GradientDirections.size(); i++) if (m_GradientDirections.at(i).GetNorm()<0.0001) return i; return -1; } bool mitk::SignalGenerationParameters::IsBaselineIndex(unsigned int idx) { if (m_GradientDirections.size()>idx && m_GradientDirections.at(idx).GetNorm()<0.0001) return true; return false; } unsigned int mitk::SignalGenerationParameters::GetNumWeightedVolumes() { return m_NumGradients; } unsigned int mitk::SignalGenerationParameters::GetNumBaselineVolumes() { return m_NumBaseline; } unsigned int mitk::SignalGenerationParameters::GetNumVolumes() { return m_GradientDirections.size(); } mitk::SignalGenerationParameters::GradientListType mitk::SignalGenerationParameters::GetGradientDirections() { return m_GradientDirections; } mitk::SignalGenerationParameters::GradientType mitk::SignalGenerationParameters::GetGradientDirection(unsigned int i) { return m_GradientDirections.at(i); } void mitk::SignalGenerationParameters::SetNumWeightedVolumes(int numGradients) { m_NumGradients = numGradients; GenerateGradientHalfShell(); } std::vector< int > mitk::SignalGenerationParameters::GetBvalues() { std::vector< int > bVals; for( GradientType g : m_GradientDirections) { float norm = g.GetNorm(); int bVal = std::round(norm*norm*m_Bvalue); if ( std::find(bVals.begin(), bVals.end(), bVal) == bVals.end() ) bVals.push_back(bVal); } return bVals; } void mitk::SignalGenerationParameters::SetGradienDirections(GradientListType gradientList) { m_GradientDirections = gradientList; m_NumGradients = 0; m_NumBaseline = 0; for( unsigned int i=0; im_GradientDirections.size(); i++) { float norm = m_GradientDirections.at(i).GetNorm(); if (norm>0.0001) m_NumGradients++; else m_NumBaseline++; } } void mitk::SignalGenerationParameters::SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList) { m_NumGradients = 0; m_NumBaseline = 0; m_GradientDirections.clear(); for( unsigned int i=0; iSize(); i++) { GradientType g; g[0] = gradientList->at(i)[0]; g[1] = gradientList->at(i)[1]; g[2] = gradientList->at(i)[2]; m_GradientDirections.push_back(g); float norm = m_GradientDirections.at(i).GetNorm(); if (norm>0.0001) m_NumGradients++; else m_NumBaseline++; } } template< class ScalarType > -void mitk::FiberfoxParameters< ScalarType >::SaveParameters(string filename) +void mitk::FiberfoxParameters< ScalarType >::SaveParameters(std::string filename) { if(filename.empty()) return; if(".ffp"!=filename.substr(filename.size()-4, 4)) filename += ".ffp"; const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, nullptr ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } boost::property_tree::ptree parameters; // fiber generation parameters parameters.put("fiberfox.fibers.distribution", m_FiberGen.m_Distribution); parameters.put("fiberfox.fibers.variance", m_FiberGen.m_Variance); parameters.put("fiberfox.fibers.density", m_FiberGen.m_Density); parameters.put("fiberfox.fibers.spline.sampling", m_FiberGen.m_Sampling); parameters.put("fiberfox.fibers.spline.tension", m_FiberGen.m_Tension); parameters.put("fiberfox.fibers.spline.continuity", m_FiberGen.m_Continuity); parameters.put("fiberfox.fibers.spline.bias", m_FiberGen.m_Bias); parameters.put("fiberfox.fibers.rotation.x", m_FiberGen.m_Rotation[0]); parameters.put("fiberfox.fibers.rotation.y", m_FiberGen.m_Rotation[1]); parameters.put("fiberfox.fibers.rotation.z", m_FiberGen.m_Rotation[2]); parameters.put("fiberfox.fibers.translation.x", m_FiberGen.m_Translation[0]); parameters.put("fiberfox.fibers.translation.y", m_FiberGen.m_Translation[1]); parameters.put("fiberfox.fibers.translation.z", m_FiberGen.m_Translation[2]); parameters.put("fiberfox.fibers.scale.x", m_FiberGen.m_Scale[0]); parameters.put("fiberfox.fibers.scale.y", m_FiberGen.m_Scale[1]); parameters.put("fiberfox.fibers.scale.z", m_FiberGen.m_Scale[2]); // image generation parameters parameters.put("fiberfox.image.basic.size.x", m_SignalGen.m_ImageRegion.GetSize(0)); parameters.put("fiberfox.image.basic.size.y", m_SignalGen.m_ImageRegion.GetSize(1)); parameters.put("fiberfox.image.basic.size.z", m_SignalGen.m_ImageRegion.GetSize(2)); parameters.put("fiberfox.image.basic.spacing.x", m_SignalGen.m_ImageSpacing[0]); parameters.put("fiberfox.image.basic.spacing.y", m_SignalGen.m_ImageSpacing[1]); parameters.put("fiberfox.image.basic.spacing.z", m_SignalGen.m_ImageSpacing[2]); parameters.put("fiberfox.image.basic.origin.x", m_SignalGen.m_ImageOrigin[0]); parameters.put("fiberfox.image.basic.origin.y", m_SignalGen.m_ImageOrigin[1]); parameters.put("fiberfox.image.basic.origin.z", m_SignalGen.m_ImageOrigin[2]); parameters.put("fiberfox.image.basic.direction.1", m_SignalGen.m_ImageDirection[0][0]); parameters.put("fiberfox.image.basic.direction.2", m_SignalGen.m_ImageDirection[0][1]); parameters.put("fiberfox.image.basic.direction.3", m_SignalGen.m_ImageDirection[0][2]); parameters.put("fiberfox.image.basic.direction.4", m_SignalGen.m_ImageDirection[1][0]); parameters.put("fiberfox.image.basic.direction.5", m_SignalGen.m_ImageDirection[1][1]); parameters.put("fiberfox.image.basic.direction.6", m_SignalGen.m_ImageDirection[1][2]); parameters.put("fiberfox.image.basic.direction.7", m_SignalGen.m_ImageDirection[2][0]); parameters.put("fiberfox.image.basic.direction.8", m_SignalGen.m_ImageDirection[2][1]); parameters.put("fiberfox.image.basic.direction.9", m_SignalGen.m_ImageDirection[2][2]); parameters.put("fiberfox.image.basic.numgradients", m_SignalGen.GetNumWeightedVolumes()); for( unsigned int i=0; im_SignalGen.GetNumVolumes(); i++) { - parameters.put("fiberfox.image.gradients."+boost::lexical_cast(i)+".x", m_SignalGen.GetGradientDirection(i)[0]); - parameters.put("fiberfox.image.gradients."+boost::lexical_cast(i)+".y", m_SignalGen.GetGradientDirection(i)[1]); - parameters.put("fiberfox.image.gradients."+boost::lexical_cast(i)+".z", m_SignalGen.GetGradientDirection(i)[2]); + parameters.put("fiberfox.image.gradients."+boost::lexical_cast(i)+".x", m_SignalGen.GetGradientDirection(i)[0]); + parameters.put("fiberfox.image.gradients."+boost::lexical_cast(i)+".y", m_SignalGen.GetGradientDirection(i)[1]); + parameters.put("fiberfox.image.gradients."+boost::lexical_cast(i)+".z", m_SignalGen.GetGradientDirection(i)[2]); } parameters.put("fiberfox.image.acquisitiontype", m_SignalGen.m_AcquisitionType); parameters.put("fiberfox.image.coilsensitivityprofile", m_SignalGen.m_CoilSensitivityProfile); parameters.put("fiberfox.image.numberofcoils", m_SignalGen.m_NumberOfCoils); parameters.put("fiberfox.image.reversephase", m_SignalGen.m_ReversePhase); parameters.put("fiberfox.image.partialfourier", m_SignalGen.m_PartialFourier); parameters.put("fiberfox.image.noisevariance", m_SignalGen.m_NoiseVariance); parameters.put("fiberfox.image.trep", m_SignalGen.m_tRep); parameters.put("fiberfox.image.signalScale", m_SignalGen.m_SignalScale); parameters.put("fiberfox.image.tEcho", m_SignalGen.m_tEcho); parameters.put("fiberfox.image.tLine", m_SignalGen.m_tLine); parameters.put("fiberfox.image.tInhom", m_SignalGen.m_tInhom); parameters.put("fiberfox.image.bvalue", m_SignalGen.m_Bvalue); parameters.put("fiberfox.image.simulatekspace", m_SignalGen.m_SimulateKspaceAcquisition); parameters.put("fiberfox.image.axonRadius", m_SignalGen.m_AxonRadius); parameters.put("fiberfox.image.doSimulateRelaxation", m_SignalGen.m_DoSimulateRelaxation); parameters.put("fiberfox.image.doDisablePartialVolume", m_SignalGen.m_DoDisablePartialVolume); parameters.put("fiberfox.image.artifacts.spikesnum", m_SignalGen.m_Spikes); parameters.put("fiberfox.image.artifacts.spikesscale", m_SignalGen.m_SpikeAmplitude); parameters.put("fiberfox.image.artifacts.kspaceLineOffset", m_SignalGen.m_KspaceLineOffset); parameters.put("fiberfox.image.artifacts.eddyStrength", m_SignalGen.m_EddyStrength); parameters.put("fiberfox.image.artifacts.eddyTau", m_SignalGen.m_Tau); parameters.put("fiberfox.image.artifacts.aliasingfactor", m_SignalGen.m_CroppingFactor); parameters.put("fiberfox.image.artifacts.addringing", m_SignalGen.m_DoAddGibbsRinging); parameters.put("fiberfox.image.artifacts.doAddMotion", m_SignalGen.m_DoAddMotion); parameters.put("fiberfox.image.artifacts.randomMotion", m_SignalGen.m_DoRandomizeMotion); parameters.put("fiberfox.image.artifacts.translation0", m_SignalGen.m_Translation[0]); parameters.put("fiberfox.image.artifacts.translation1", m_SignalGen.m_Translation[1]); parameters.put("fiberfox.image.artifacts.translation2", m_SignalGen.m_Translation[2]); parameters.put("fiberfox.image.artifacts.rotation0", m_SignalGen.m_Rotation[0]); parameters.put("fiberfox.image.artifacts.rotation1", m_SignalGen.m_Rotation[1]); parameters.put("fiberfox.image.artifacts.rotation2", m_SignalGen.m_Rotation[2]); parameters.put("fiberfox.image.artifacts.motionvolumes", m_Misc.m_MotionVolumesBox); parameters.put("fiberfox.image.artifacts.addnoise", m_Misc.m_CheckAddNoiseBox); parameters.put("fiberfox.image.artifacts.addghosts", m_Misc.m_CheckAddGhostsBox); parameters.put("fiberfox.image.artifacts.addaliasing", m_Misc.m_CheckAddAliasingBox); parameters.put("fiberfox.image.artifacts.addspikes", m_Misc.m_CheckAddSpikesBox); parameters.put("fiberfox.image.artifacts.addeddycurrents", m_Misc.m_CheckAddEddyCurrentsBox); parameters.put("fiberfox.image.artifacts.doAddDistortions", m_Misc.m_CheckAddDistortionsBox); parameters.put("fiberfox.image.outputvolumefractions", m_Misc.m_CheckOutputVolumeFractionsBox); parameters.put("fiberfox.image.showadvanced", m_Misc.m_CheckAdvancedSignalOptionsBox); parameters.put("fiberfox.image.signalmodelstring", m_Misc.m_SignalModelString); parameters.put("fiberfox.image.artifactmodelstring", m_Misc.m_ArtifactModelString); parameters.put("fiberfox.image.outpath", m_Misc.m_OutputPath); parameters.put("fiberfox.fibers.realtime", m_Misc.m_CheckRealTimeFibersBox); parameters.put("fiberfox.fibers.showadvanced", m_Misc.m_CheckAdvancedFiberOptionsBox); parameters.put("fiberfox.fibers.constantradius", m_Misc.m_CheckConstantRadiusBox); parameters.put("fiberfox.fibers.includeFiducials", m_Misc.m_CheckIncludeFiducialsBox); if (m_NoiseModel!=nullptr) { parameters.put("fiberfox.image.artifacts.noisevariance", m_NoiseModel->GetNoiseVariance()); if (dynamic_cast*>(m_NoiseModel.get())) parameters.put("fiberfox.image.artifacts.noisetype", "rice"); else if (dynamic_cast*>(m_NoiseModel.get())) parameters.put("fiberfox.image.artifacts.noisetype", "chisquare"); } for (std::size_t i=0; i* signalModel = nullptr; if (i(i)+".type", "fiber"); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".type", "fiber"); } else { signalModel = m_NonFiberModelList.at(i-m_FiberModelList.size()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".type", "non-fiber"); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".type", "non-fiber"); } if (dynamic_cast*>(signalModel)) { mitk::StickModel* model = dynamic_cast*>(signalModel); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "stick"); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d", model->GetDiffusivity()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "stick"); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d", model->GetDiffusivity()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel* model = dynamic_cast*>(signalModel); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "tensor"); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d1", model->GetDiffusivity1()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d2", model->GetDiffusivity2()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d3", model->GetDiffusivity3()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "tensor"); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d1", model->GetDiffusivity1()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d2", model->GetDiffusivity2()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d3", model->GetDiffusivity3()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel* model = dynamic_cast*>(signalModel); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "prototype"); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".minFA", model->GetFaRange().first); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".maxFA", model->GetFaRange().second); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".minADC", model->GetAdcRange().first); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".maxADC", model->GetAdcRange().second); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".maxNumSamples", model->GetMaxNumKernels()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".numSamples", model->GetNumberOfKernels()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "prototype"); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".minFA", model->GetFaRange().first); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".maxFA", model->GetFaRange().second); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".minADC", model->GetAdcRange().first); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".maxADC", model->GetAdcRange().second); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".maxNumSamples", model->GetMaxNumKernels()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".numSamples", model->GetNumberOfKernels()); int shOrder = model->GetShOrder(); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".numCoeffs", (shOrder*shOrder + shOrder + 2)/2 + shOrder); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".numCoeffs", (shOrder*shOrder + shOrder + 2)/2 + shOrder); for (unsigned int j=0; jGetNumberOfKernels(); j++) { vnl_vector< double > coeffs = model->GetCoefficients(j); for (unsigned int k=0; k(i)+".kernels."+boost::lexical_cast(j)+".coeffs."+boost::lexical_cast(k), coeffs[k]); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".kernels."+boost::lexical_cast(j)+".B0", model->GetBaselineSignal(j)); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".kernels."+boost::lexical_cast(j)+".coeffs."+boost::lexical_cast(k), coeffs[k]); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".kernels."+boost::lexical_cast(j)+".B0", model->GetBaselineSignal(j)); } } else if (dynamic_cast*>(signalModel)) { mitk::BallModel* model = dynamic_cast*>(signalModel); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "ball"); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d", model->GetDiffusivity()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "ball"); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d", model->GetDiffusivity()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel* model = dynamic_cast*>(signalModel); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "astrosticks"); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d", model->GetDiffusivity()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".randomize", model->GetRandomizeSticks()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "astrosticks"); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".d", model->GetDiffusivity()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".randomize", model->GetRandomizeSticks()); } else if (dynamic_cast*>(signalModel)) { mitk::DotModel* model = dynamic_cast*>(signalModel); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "dot"); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".model", "dot"); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t2", model->GetT2()); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".t1", model->GetT1()); } if (signalModel!=nullptr) { - parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".ID", signalModel->m_CompartmentId); + parameters.put("fiberfox.image.compartments."+boost::lexical_cast(i)+".ID", signalModel->m_CompartmentId); if (signalModel->GetVolumeFractionImage().IsNotNull()) { try{ itk::ImageFileWriter::Pointer writer = itk::ImageFileWriter::New(); - writer->SetFileName(filename+"_VOLUME"+boost::lexical_cast(signalModel->m_CompartmentId)+".nrrd"); + writer->SetFileName(filename+"_VOLUME"+boost::lexical_cast(signalModel->m_CompartmentId)+".nrrd"); writer->SetInput(signalModel->GetVolumeFractionImage()); writer->Update(); - MITK_INFO << "Volume fraction image for compartment "+boost::lexical_cast(signalModel->m_CompartmentId)+" saved."; + MITK_INFO << "Volume fraction image for compartment "+boost::lexical_cast(signalModel->m_CompartmentId)+" saved."; } catch(...) { } } } } boost::property_tree::xml_writer_settings writerSettings(' ', 2); boost::property_tree::xml_parser::write_xml(filename, parameters, std::locale(), writerSettings); try{ itk::ImageFileWriter::Pointer writer = itk::ImageFileWriter::New(); writer->SetFileName(filename+"_FMAP.nrrd"); writer->SetInput(m_SignalGen.m_FrequencyMap); writer->Update(); } catch(...) { MITK_INFO << "No frequency map saved."; } try{ itk::ImageFileWriter::Pointer writer = itk::ImageFileWriter::New(); writer->SetFileName(filename+"_MASK.nrrd"); writer->SetInput(m_SignalGen.m_MaskImage); writer->Update(); } catch(...) { MITK_INFO << "No mask image saved."; } setlocale(LC_ALL, currLocale.c_str()); } template< class ScalarType > template< class ParameterType > ParameterType mitk::FiberfoxParameters< ScalarType >::ReadVal(boost::property_tree::ptree::value_type const& v, std::string tag, ParameterType defaultValue, bool essential) { try { return v.second.get(tag); } catch (...) { if (essential) { mitkThrow() << "Parameter file corrupted. Essential tag is missing: '" << tag << "'"; } if (tag!="artifacts.noisetype") { MITK_INFO << "Tag '" << tag << "' not found. Using default value '" << defaultValue << "'."; m_MissingTags += "\n- "; m_MissingTags += tag; } return defaultValue; } } template< class ScalarType > -void mitk::FiberfoxParameters< ScalarType >::LoadParameters(string filename) +void mitk::FiberfoxParameters< ScalarType >::LoadParameters(std::string filename) { m_MissingTags = ""; if(filename.empty()) { return; } const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, nullptr ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } boost::property_tree::ptree parameterTree; boost::property_tree::xml_parser::read_xml( filename, parameterTree ); m_FiberModelList.clear(); m_NonFiberModelList.clear(); if (m_NoiseModel) { m_NoiseModel = nullptr; } BOOST_FOREACH( boost::property_tree::ptree::value_type const& v1, parameterTree.get_child("fiberfox") ) { if( v1.first == "fibers" ) { m_Misc.m_CheckRealTimeFibersBox = ReadVal(v1,"realtime", m_Misc.m_CheckRealTimeFibersBox); m_Misc.m_CheckAdvancedFiberOptionsBox = ReadVal(v1,"showadvanced", m_Misc.m_CheckAdvancedFiberOptionsBox); m_Misc.m_CheckConstantRadiusBox = ReadVal(v1,"constantradius", m_Misc.m_CheckConstantRadiusBox); m_Misc.m_CheckIncludeFiducialsBox = ReadVal(v1,"includeFiducials", m_Misc.m_CheckIncludeFiducialsBox); switch (ReadVal(v1,"distribution", 0)) { case 0: m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; break; case 1: m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; break; default: m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; } m_FiberGen.m_Variance = ReadVal(v1,"variance", m_FiberGen.m_Variance); m_FiberGen.m_Density = ReadVal(v1,"density", m_FiberGen.m_Density); m_FiberGen.m_Sampling = ReadVal(v1,"spline.sampling", m_FiberGen.m_Sampling); m_FiberGen.m_Tension = ReadVal(v1,"spline.tension", m_FiberGen.m_Tension); m_FiberGen.m_Continuity = ReadVal(v1,"spline.continuity", m_FiberGen.m_Continuity); m_FiberGen.m_Bias = ReadVal(v1,"spline.bias", m_FiberGen.m_Bias); m_FiberGen.m_Rotation[0] = ReadVal(v1,"rotation.x", m_FiberGen.m_Rotation[0]); m_FiberGen.m_Rotation[1] = ReadVal(v1,"rotation.y", m_FiberGen.m_Rotation[1]); m_FiberGen.m_Rotation[2] = ReadVal(v1,"rotation.z", m_FiberGen.m_Rotation[2]); m_FiberGen.m_Translation[0] = ReadVal(v1,"translation.x", m_FiberGen.m_Translation[0]); m_FiberGen.m_Translation[1] = ReadVal(v1,"translation.y", m_FiberGen.m_Translation[1]); m_FiberGen.m_Translation[2] = ReadVal(v1,"translation.z", m_FiberGen.m_Translation[2]); m_FiberGen.m_Scale[0] = ReadVal(v1,"scale.x", m_FiberGen.m_Scale[0]); m_FiberGen.m_Scale[1] = ReadVal(v1,"scale.y", m_FiberGen.m_Scale[1]); m_FiberGen.m_Scale[2] = ReadVal(v1,"scale.z", m_FiberGen.m_Scale[2]); } else if ( v1.first == "image" ) { - m_Misc.m_SignalModelString = ReadVal(v1,"signalmodelstring", m_Misc.m_SignalModelString); - m_Misc.m_ArtifactModelString = ReadVal(v1,"artifactmodelstring", m_Misc.m_ArtifactModelString); - m_Misc.m_OutputPath = ReadVal(v1,"outpath", m_Misc.m_OutputPath); + m_Misc.m_SignalModelString = ReadVal(v1,"signalmodelstring", m_Misc.m_SignalModelString); + m_Misc.m_ArtifactModelString = ReadVal(v1,"artifactmodelstring", m_Misc.m_ArtifactModelString); + m_Misc.m_OutputPath = ReadVal(v1,"outpath", m_Misc.m_OutputPath); m_Misc.m_CheckOutputVolumeFractionsBox = ReadVal(v1,"outputvolumefractions", m_Misc.m_CheckOutputVolumeFractionsBox); m_Misc.m_CheckAdvancedSignalOptionsBox = ReadVal(v1,"showadvanced", m_Misc.m_CheckAdvancedSignalOptionsBox); m_Misc.m_CheckAddDistortionsBox = ReadVal(v1,"artifacts.doAddDistortions", m_Misc.m_CheckAddDistortionsBox); m_Misc.m_CheckAddNoiseBox = ReadVal(v1,"artifacts.addnoise", m_Misc.m_CheckAddNoiseBox); m_Misc.m_CheckAddGhostsBox = ReadVal(v1,"artifacts.addghosts", m_Misc.m_CheckAddGhostsBox); m_Misc.m_CheckAddAliasingBox = ReadVal(v1,"artifacts.addaliasing", m_Misc.m_CheckAddAliasingBox); m_Misc.m_CheckAddSpikesBox = ReadVal(v1,"artifacts.addspikes", m_Misc.m_CheckAddSpikesBox); m_Misc.m_CheckAddEddyCurrentsBox = ReadVal(v1,"artifacts.addeddycurrents", m_Misc.m_CheckAddEddyCurrentsBox); m_SignalGen.m_ImageRegion.SetSize(0, ReadVal(v1,"basic.size.x",m_SignalGen.m_ImageRegion.GetSize(0))); m_SignalGen.m_ImageRegion.SetSize(1, ReadVal(v1,"basic.size.y",m_SignalGen.m_ImageRegion.GetSize(1))); m_SignalGen.m_ImageRegion.SetSize(2, ReadVal(v1,"basic.size.z",m_SignalGen.m_ImageRegion.GetSize(2))); m_SignalGen.m_ImageSpacing[0] = ReadVal(v1,"basic.spacing.x",m_SignalGen.m_ImageSpacing[0]); m_SignalGen.m_ImageSpacing[1] = ReadVal(v1,"basic.spacing.y",m_SignalGen.m_ImageSpacing[1]); m_SignalGen.m_ImageSpacing[2] = ReadVal(v1,"basic.spacing.z",m_SignalGen.m_ImageSpacing[2]); m_SignalGen.m_ImageOrigin[0] = ReadVal(v1,"basic.origin.x",m_SignalGen.m_ImageOrigin[0]); m_SignalGen.m_ImageOrigin[1] = ReadVal(v1,"basic.origin.y",m_SignalGen.m_ImageOrigin[1]); m_SignalGen.m_ImageOrigin[2] = ReadVal(v1,"basic.origin.z",m_SignalGen.m_ImageOrigin[2]); m_SignalGen.m_ImageDirection[0][0] = ReadVal(v1,"basic.direction.1",m_SignalGen.m_ImageDirection[0][0]); m_SignalGen.m_ImageDirection[0][1] = ReadVal(v1,"basic.direction.2",m_SignalGen.m_ImageDirection[0][1]); m_SignalGen.m_ImageDirection[0][2] = ReadVal(v1,"basic.direction.3",m_SignalGen.m_ImageDirection[0][2]); m_SignalGen.m_ImageDirection[1][0] = ReadVal(v1,"basic.direction.4",m_SignalGen.m_ImageDirection[1][0]); m_SignalGen.m_ImageDirection[1][1] = ReadVal(v1,"basic.direction.5",m_SignalGen.m_ImageDirection[1][1]); m_SignalGen.m_ImageDirection[1][2] = ReadVal(v1,"basic.direction.6",m_SignalGen.m_ImageDirection[1][2]); m_SignalGen.m_ImageDirection[2][0] = ReadVal(v1,"basic.direction.7",m_SignalGen.m_ImageDirection[2][0]); m_SignalGen.m_ImageDirection[2][1] = ReadVal(v1,"basic.direction.8",m_SignalGen.m_ImageDirection[2][1]); m_SignalGen.m_ImageDirection[2][2] = ReadVal(v1,"basic.direction.9",m_SignalGen.m_ImageDirection[2][2]); m_SignalGen.m_AcquisitionType = (SignalGenerationParameters::AcquisitionType) ReadVal(v1,"acquisitiontype", m_SignalGen.m_AcquisitionType); m_SignalGen.m_CoilSensitivityProfile = (SignalGenerationParameters::CoilSensitivityProfile) ReadVal(v1,"coilsensitivityprofile", m_SignalGen.m_CoilSensitivityProfile); m_SignalGen.m_NumberOfCoils = ReadVal(v1,"numberofcoils", m_SignalGen.m_NumberOfCoils); m_SignalGen.m_ReversePhase = ReadVal(v1,"reversephase", m_SignalGen.m_ReversePhase); m_SignalGen.m_PartialFourier = ReadVal(v1,"partialfourier", m_SignalGen.m_PartialFourier); m_SignalGen.m_NoiseVariance = ReadVal(v1,"noisevariance", m_SignalGen.m_NoiseVariance); m_SignalGen.m_tRep = ReadVal(v1,"trep", m_SignalGen.m_tRep); m_SignalGen.m_SignalScale = ReadVal(v1,"signalScale", m_SignalGen.m_SignalScale); m_SignalGen.m_tEcho = ReadVal(v1,"tEcho", m_SignalGen.m_tEcho); m_SignalGen.m_tLine = ReadVal(v1,"tLine", m_SignalGen.m_tLine); m_SignalGen.m_tInhom = ReadVal(v1,"tInhom", m_SignalGen.m_tInhom); m_SignalGen.m_Bvalue = ReadVal(v1,"bvalue", m_SignalGen.m_Bvalue); m_SignalGen.m_SimulateKspaceAcquisition = ReadVal(v1,"simulatekspace", m_SignalGen.m_SimulateKspaceAcquisition); m_SignalGen.m_AxonRadius = ReadVal(v1,"axonRadius", m_SignalGen.m_AxonRadius); m_SignalGen.m_Spikes = ReadVal(v1,"artifacts.spikesnum", m_SignalGen.m_Spikes); m_SignalGen.m_SpikeAmplitude = ReadVal(v1,"artifacts.spikesscale", m_SignalGen.m_SpikeAmplitude); m_SignalGen.m_KspaceLineOffset = ReadVal(v1,"artifacts.kspaceLineOffset", m_SignalGen.m_KspaceLineOffset); m_SignalGen.m_EddyStrength = ReadVal(v1,"artifacts.eddyStrength", m_SignalGen.m_EddyStrength); m_SignalGen.m_Tau = ReadVal(v1,"artifacts.eddyTau", m_SignalGen.m_Tau); m_SignalGen.m_CroppingFactor = ReadVal(v1,"artifacts.aliasingfactor", m_SignalGen.m_CroppingFactor); m_SignalGen.m_DoAddGibbsRinging = ReadVal(v1,"artifacts.addringing", m_SignalGen.m_DoAddGibbsRinging); m_SignalGen.m_DoSimulateRelaxation = ReadVal(v1,"doSimulateRelaxation", m_SignalGen.m_DoSimulateRelaxation); m_SignalGen.m_DoDisablePartialVolume = ReadVal(v1,"doDisablePartialVolume", m_SignalGen.m_DoDisablePartialVolume); m_SignalGen.m_DoAddMotion = ReadVal(v1,"artifacts.doAddMotion", m_SignalGen.m_DoAddMotion); m_SignalGen.m_DoRandomizeMotion = ReadVal(v1,"artifacts.randomMotion", m_SignalGen.m_DoRandomizeMotion); m_SignalGen.m_Translation[0] = ReadVal(v1,"artifacts.translation0", m_SignalGen.m_Translation[0]); m_SignalGen.m_Translation[1] = ReadVal(v1,"artifacts.translation1", m_SignalGen.m_Translation[1]); m_SignalGen.m_Translation[2] = ReadVal(v1,"artifacts.translation2", m_SignalGen.m_Translation[2]); m_SignalGen.m_Rotation[0] = ReadVal(v1,"artifacts.rotation0", m_SignalGen.m_Rotation[0]); m_SignalGen.m_Rotation[1] = ReadVal(v1,"artifacts.rotation1", m_SignalGen.m_Rotation[1]); m_SignalGen.m_Rotation[2] = ReadVal(v1,"artifacts.rotation2", m_SignalGen.m_Rotation[2]); // m_SignalGen.SetNumWeightedVolumes(ReadVal(v1,"numgradients", m_SignalGen.GetNumWeightedVolumes())); SignalGenerationParameters::GradientListType gradients; BOOST_FOREACH( boost::property_tree::ptree::value_type const& v2, v1.second.get_child("gradients") ) { SignalGenerationParameters::GradientType g; g[0] = ReadVal(v2,"x",0); g[1] = ReadVal(v2,"y",0); g[2] = ReadVal(v2,"z",0); gradients.push_back(g); } m_SignalGen.SetGradienDirections(gradients); - m_Misc.m_MotionVolumesBox = ReadVal(v1,"artifacts.motionvolumes", m_Misc.m_MotionVolumesBox); + m_Misc.m_MotionVolumesBox = ReadVal(v1,"artifacts.motionvolumes", m_Misc.m_MotionVolumesBox); m_SignalGen.m_MotionVolumes.clear(); if ( m_Misc.m_MotionVolumesBox == "random" ) { for ( size_t i=0; i < m_SignalGen.GetNumVolumes(); ++i ) { m_SignalGen.m_MotionVolumes.push_back( bool( rand()%2 ) ); } MITK_DEBUG << "mitkFiberfoxParameters.cpp: Case m_Misc.m_MotionVolumesBox == \"random\"."; } else if ( ! m_Misc.m_MotionVolumesBox.empty() ) { - stringstream stream( m_Misc.m_MotionVolumesBox ); + std::stringstream stream( m_Misc.m_MotionVolumesBox ); std::vector numbers; int nummer = std::numeric_limits::max(); while( stream >> nummer ) { if( nummer < std::numeric_limits::max() ) { numbers.push_back( nummer ); } } // If a list of negative numbers is given: if( *(std::min_element( numbers.begin(), numbers.end() )) < 0 && *(std::max_element( numbers.begin(), numbers.end() )) <= 0 ) // cave: -0 == +0 { for ( size_t i=0; i(m_SignalGen.GetNumVolumes()) && -number >= 0 ) m_SignalGen.m_MotionVolumes.at(-number) = false; } MITK_DEBUG << "mitkFiberfoxParameters.cpp: Case list of negative numbers."; } // If a list of positive numbers is given: else if( *(std::min_element( numbers.begin(), numbers.end() )) >= 0 && *(std::max_element( numbers.begin(), numbers.end() )) >= 0 ) { for ( size_t i=0; i(m_SignalGen.GetNumVolumes()) && number >= 0) m_SignalGen.m_MotionVolumes.at(number) = true; } MITK_DEBUG << "mitkFiberfoxParameters.cpp: Case list of positive numbers."; } else { MITK_WARN << "mitkFiberfoxParameters.cpp: Inconsistent list of numbers in m_MotionVolumesBox."; break; } } else { MITK_WARN << "mitkFiberfoxParameters.cpp: Cannot make sense of string in m_MotionVolumesBox."; break; } try { - if (ReadVal(v1,"artifacts.noisetype","")=="rice") + if (ReadVal(v1,"artifacts.noisetype","")=="rice") { m_NoiseModel = std::make_shared< mitk::RicianNoiseModel >(); m_NoiseModel->SetNoiseVariance(ReadVal(v1,"artifacts.noisevariance",m_NoiseModel->GetNoiseVariance())); } } catch(...) { MITK_DEBUG << "mitkFiberfoxParameters.cpp: caught some error while trying m_NoiseModel->SetNoiseVariance()"; // throw; } try { - if (ReadVal(v1,"artifacts.noisetype","")=="chisquare") + if (ReadVal(v1,"artifacts.noisetype","")=="chisquare") { m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel >(); m_NoiseModel->SetNoiseVariance(ReadVal(v1,"artifacts.noisevariance",m_NoiseModel->GetNoiseVariance())); } } catch(...) { MITK_DEBUG << "mitkFiberfoxParameters.cpp: caught some error while trying m_NoiseModel->SetNoiseVariance()"; // throw; } BOOST_FOREACH( boost::property_tree::ptree::value_type const& v2, v1.second.get_child("compartments") ) { mitk::DiffusionSignalModel* signalModel = nullptr; std::string model = ReadVal(v2,"model","",true); if (model=="stick") { mitk::StickModel* model = new mitk::StickModel(); model->SetDiffusivity(ReadVal(v2,"d",model->GetDiffusivity())); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->SetBvalue(m_SignalGen.m_Bvalue); model->m_CompartmentId = ReadVal(v2,"ID",0,true); - if (ReadVal(v2,"type","",true)=="fiber") + if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); - else if (ReadVal(v2,"type","",true)=="non-fiber") + else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="tensor") { mitk::TensorModel* model = new mitk::TensorModel(); model->SetDiffusivity1(ReadVal(v2,"d1",model->GetDiffusivity1())); model->SetDiffusivity2(ReadVal(v2,"d2",model->GetDiffusivity2())); model->SetDiffusivity3(ReadVal(v2,"d3",model->GetDiffusivity3())); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->SetBvalue(m_SignalGen.m_Bvalue); model->m_CompartmentId = ReadVal(v2,"ID",0,true); - if (ReadVal(v2,"type","",true)=="fiber") + if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); - else if (ReadVal(v2,"type","",true)=="non-fiber") + else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="ball") { mitk::BallModel* model = new mitk::BallModel(); model->SetDiffusivity(ReadVal(v2,"d",model->GetDiffusivity())); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->SetBvalue(m_SignalGen.m_Bvalue); model->m_CompartmentId = ReadVal(v2,"ID",0,true); - if (ReadVal(v2,"type","",true)=="fiber") + if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); - else if (ReadVal(v2,"type","",true)=="non-fiber") + else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="astrosticks") { mitk::AstroStickModel* model = new AstroStickModel(); model->SetDiffusivity(ReadVal(v2,"d",model->GetDiffusivity())); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->SetBvalue(m_SignalGen.m_Bvalue); model->SetRandomizeSticks(ReadVal(v2,"randomize",model->GetRandomizeSticks())); model->m_CompartmentId = ReadVal(v2,"ID",0,true); - if (ReadVal(v2,"type","",true)=="fiber") + if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); - else if (ReadVal(v2,"type","",true)=="non-fiber") + else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="dot") { mitk::DotModel* model = new mitk::DotModel(); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->m_CompartmentId = ReadVal(v2,"ID",0,true); - if (ReadVal(v2,"type","",true)=="fiber") + if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); - else if (ReadVal(v2,"type","",true)=="non-fiber") + else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="prototype") { mitk::RawShModel* model = new mitk::RawShModel(); model->SetMaxNumKernels(ReadVal(v2,"maxNumSamples",model->GetMaxNumKernels())); model->SetFaRange(ReadVal(v2,"minFA",model->GetFaRange().first), ReadVal(v2,"maxFA",model->GetFaRange().second)); model->SetAdcRange(ReadVal(v2,"minADC",model->GetAdcRange().first), ReadVal(v2,"maxADC",model->GetAdcRange().second)); model->m_CompartmentId = ReadVal(v2,"ID",0,true); unsigned int numCoeffs = ReadVal(v2,"numCoeffs",0,true); unsigned int numSamples = ReadVal(v2,"numSamples",0,true); for (unsigned int j=0; j coeffs(numCoeffs); for (unsigned int k=0; k(v2,"kernels."+boost::lexical_cast(j)+".coeffs."+boost::lexical_cast(k),0,true); + coeffs[k] = ReadVal(v2,"kernels."+boost::lexical_cast(j)+".coeffs."+boost::lexical_cast(k),0,true); } - model->SetShCoefficients( coeffs, ReadVal(v2,"kernels."+boost::lexical_cast(j)+".B0",0,true) ); + model->SetShCoefficients( coeffs, ReadVal(v2,"kernels."+boost::lexical_cast(j)+".B0",0,true) ); } - if (ReadVal(v2,"type","",true)=="fiber") + if (ReadVal(v2,"type","",true)=="fiber") { m_FiberModelList.push_back(model); } - else if (ReadVal(v2,"type","",true)=="non-fiber") + else if (ReadVal(v2,"type","",true)=="non-fiber") { m_NonFiberModelList.push_back(model); } // else ? signalModel = model; } if (signalModel!=nullptr) { signalModel->SetGradientList(gradients); try { itk::ImageFileReader::Pointer reader = itk::ImageFileReader::New(); - reader->SetFileName(filename+"_VOLUME"+ReadVal(v2,"ID","")+".nrrd"); + reader->SetFileName(filename+"_VOLUME"+ReadVal(v2,"ID","")+".nrrd"); reader->Update(); signalModel->SetVolumeFractionImage(reader->GetOutput()); MITK_INFO << "Volume fraction image loaded for compartment " << signalModel->m_CompartmentId; } catch(...) { MITK_INFO << "No volume fraction image found for compartment " << signalModel->m_CompartmentId; } } } } else { } } try { itk::ImageFileReader::Pointer reader = itk::ImageFileReader::New(); reader->SetFileName(filename+"_FMAP.nrrd"); reader->Update(); m_SignalGen.m_FrequencyMap = reader->GetOutput(); MITK_INFO << "Frequency map loaded."; } catch(...) { MITK_INFO << "No frequency map found."; } try { itk::ImageFileReader::Pointer reader = itk::ImageFileReader::New(); reader->SetFileName(filename+"_MASK.nrrd"); reader->Update(); m_SignalGen.m_MaskImage = reader->GetOutput(); MITK_INFO << "Mask image loaded."; } catch(...) { MITK_INFO << "No mask image found."; } setlocale(LC_ALL, currLocale.c_str()); } template< class ScalarType > void mitk::FiberfoxParameters< ScalarType >::PrintSelf() { MITK_INFO << "Not implemented :("; } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h index 94003af019..2c3365f23c 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h @@ -1,354 +1,352 @@ /*=================================================================== 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_FiberfoxParameters_H #define _MITK_FiberfoxParameters_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -using namespace std; - namespace mitk { /** Signal generation */ class SignalGenerationParameters { public: typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkUcharImgType; typedef itk::Vector GradientType; typedef std::vector GradientListType; enum CoilSensitivityProfile : int { COIL_CONSTANT, COIL_LINEAR, COIL_EXPONENTIAL }; enum AcquisitionType : int { SingleShotEpi, SpinEcho }; SignalGenerationParameters() : m_AcquisitionType(SignalGenerationParameters::SingleShotEpi) , m_SignalScale(100) , m_tEcho(100) , m_tRep(4000) , m_tLine(1) , m_tInhom(50) , m_ReversePhase(false) , m_PartialFourier(1.0) , m_NoiseVariance(0.001) , m_NumberOfCoils(1) , m_CoilSensitivityProfile(SignalGenerationParameters::COIL_CONSTANT) , m_Bvalue(1000) , m_SimulateKspaceAcquisition(false) , m_AxonRadius(0) , m_DoDisablePartialVolume(false) , m_Spikes(0) , m_SpikeAmplitude(1) , m_KspaceLineOffset(0) , m_EddyStrength(300) , m_Tau(70) , m_CroppingFactor(1) , m_DoAddGibbsRinging(false) , m_DoSimulateRelaxation(true) , m_DoAddMotion(false) , m_DoRandomizeMotion(true) , m_FrequencyMap(nullptr) , m_MaskImage(nullptr) { m_ImageRegion.SetSize(0, 12); m_ImageRegion.SetSize(1, 12); m_ImageRegion.SetSize(2, 3); m_ImageSpacing.Fill(2.0); m_ImageOrigin.Fill(0.0); m_ImageDirection.SetIdentity(); m_Translation.Fill(0.0); m_Rotation.Fill(0.0); SetNumWeightedVolumes(6); } /** input/output image specifications */ itk::ImageRegion<3> m_CroppedRegion; ///< Image size with reduced FOV. itk::ImageRegion<3> m_ImageRegion; ///< Image size. itk::Vector m_ImageSpacing; ///< Image voxel size. itk::Point m_ImageOrigin; ///< Image origin. itk::Matrix m_ImageDirection; ///< Image rotation matrix. /** Other acquisitions parameters */ AcquisitionType m_AcquisitionType; ///< determines k-space trajectory and maximum echo position(s) double m_SignalScale; ///< Scaling factor for output signal (before noise is added). double m_tEcho; ///< Echo time TE. double m_tRep; ///< Echo time TR. double m_tLine; ///< k-space line readout time (dwell time). double m_tInhom; ///< T2' bool m_ReversePhase; ///< If true, the phase readout direction will be inverted (-y instead of y) double m_PartialFourier; ///< Partial fourier factor (0.5-1) double m_NoiseVariance; ///< Variance of complex gaussian noise int m_NumberOfCoils; ///< Number of coils in multi-coil acquisition CoilSensitivityProfile m_CoilSensitivityProfile; ///< Choose between constant, linear or exponential sensitivity profile of the used coils double m_Bvalue; ///< Acquisition b-value bool m_SimulateKspaceAcquisition;///< Flag to enable/disable k-space acquisition simulation double m_AxonRadius; ///< Determines compartment volume fractions (0 == automatic axon radius estimation) bool m_DoDisablePartialVolume; ///< Disable partial volume effects. Each voxel is either all fiber or all non-fiber. /** Artifacts and other effects */ unsigned int m_Spikes; ///< Number of spikes randomly appearing in the image double m_SpikeAmplitude; ///< amplitude of spikes relative to the largest signal intensity (magnitude of complex) double m_KspaceLineOffset; ///< Causes N/2 ghosts. Larger offset means stronger ghost. double m_EddyStrength; ///< Strength of eddy current induced gradients in mT/m. double m_Tau; ///< Eddy current decay constant (in ms) double m_CroppingFactor; ///< FOV size in y-direction is multiplied by this factor. Causes aliasing artifacts. bool m_DoAddGibbsRinging; ///< Add Gibbs ringing artifact bool m_DoSimulateRelaxation; ///< Add T2 relaxation effects bool m_DoAddMotion; ///< Enable motion artifacts. bool m_DoRandomizeMotion; ///< Toggles between random and linear motion. std::vector< bool > m_MotionVolumes; ///< Indicates the image volumes that are affected by motion ///< with positive numbers, inverted logic with negative numbers. itk::Vector m_Translation; ///< Maximum translational motion. itk::Vector m_Rotation; ///< Maximum rotational motion. ItkDoubleImgType::Pointer m_FrequencyMap; ///< If != nullptr, distortions are added to the image using this frequency map. ItkUcharImgType::Pointer m_MaskImage; ///< Signal is only genrated inside of the mask image. inline void GenerateGradientHalfShell(); ///< Generates half shell of gradient directions (with m_NumGradients non-zero directions) inline std::vector< int > GetBaselineIndices(); ///< Returns list of nun-diffusion-weighted image volume indices inline unsigned int GetFirstBaselineIndex(); ///< Returns index of first non-diffusion-weighted image volume inline bool IsBaselineIndex(unsigned int idx); ///< Checks if image volume with given index is non-diffusion-weighted volume or not. inline unsigned int GetNumWeightedVolumes(); ///< Get number of diffusion-weighted image volumes inline unsigned int GetNumBaselineVolumes(); ///< Get number of non-diffusion-weighted image volumes inline unsigned int GetNumVolumes(); ///< Get number of baseline and diffusion-weighted image volumes inline GradientListType GetGradientDirections(); ///< Return gradient direction container inline GradientType GetGradientDirection(unsigned int i); inline std::vector< int > GetBvalues(); ///< Returns a vector with all unique b-values (determined by the gradient magnitudes) inline void SetNumWeightedVolumes(int numGradients); ///< Automaticall calls GenerateGradientHalfShell() afterwards. inline void SetGradienDirections(GradientListType gradientList); inline void SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList); protected: unsigned int m_NumGradients; ///< Number of diffusion-weighted image volumes. unsigned int m_NumBaseline; ///< Number of non-diffusion-weighted image volumes. GradientListType m_GradientDirections; ///< Total number of image volumes. }; /** Fiber generation */ class FiberGenerationParameters { public: enum FiberDistribution { DISTRIBUTE_UNIFORM, // distribute fibers uniformly in the ROIs DISTRIBUTE_GAUSSIAN // distribute fibers using a 2D gaussian }; - typedef vector< vector< mitk::PlanarEllipse::Pointer > > FiducialListType; - typedef vector< vector< unsigned int > > FlipListType; + typedef std::vector< std::vector< mitk::PlanarEllipse::Pointer > > FiducialListType; + typedef std::vector< std::vector< unsigned int > > FlipListType; FiberGenerationParameters() : m_Distribution(DISTRIBUTE_UNIFORM) , m_Density(100) , m_Variance(100) , m_Sampling(1) , m_Tension(0) , m_Continuity(0) , m_Bias(0) { m_Rotation.Fill(0.0); m_Translation.Fill(0.0); m_Scale.Fill(1.0); } FiberDistribution m_Distribution; unsigned int m_Density; double m_Variance; double m_Sampling; double m_Tension; double m_Continuity; double m_Bias; mitk::Vector3D m_Rotation; mitk::Vector3D m_Translation; mitk::Vector3D m_Scale; FlipListType m_FlipList; ///< contains flags indicating a flip of the 2D fiber x-coordinates (needed to resolve some unwanted fiber twisting) FiducialListType m_Fiducials; ///< container of the planar ellipses used as fiducials for the fiber generation process }; /** GUI persistence, input, output, ... */ class MiscFiberfoxParameters { public: MiscFiberfoxParameters() : m_ResultNode(DataNode::New()) , m_ParentNode(nullptr) , m_SignalModelString("") , m_ArtifactModelString("") , m_OutputPath("/tmp/") , m_OutputPrefix("fiberfox") , m_CheckOutputVolumeFractionsBox(false) , m_CheckAdvancedSignalOptionsBox(false) , m_CheckAddNoiseBox(false) , m_CheckAddGhostsBox(false) , m_CheckAddAliasingBox(false) , m_CheckAddSpikesBox(false) , m_CheckAddEddyCurrentsBox(false) , m_CheckAddDistortionsBox(false) , m_MotionVolumesBox("random") , m_CheckRealTimeFibersBox(true) , m_CheckAdvancedFiberOptionsBox(false) , m_CheckConstantRadiusBox(false) , m_CheckIncludeFiducialsBox(true) {} DataNode::Pointer m_ResultNode; ///< Stores resulting image. DataNode::Pointer m_ParentNode; ///< Parent node of result node. - string m_SignalModelString; ///< Appendet to the name of the result node - string m_ArtifactModelString; ///< Appendet to the name of the result node - string m_OutputPath; ///< Image is automatically saved to the specified folder after simulation is finished. - string m_OutputPrefix; /** Prefix for filename of output files and logfile. */ - string m_AfterSimulationMessage; ///< Store messages that are displayed after the simulation has finished (e.g. warnings, automatic parameter adjustments etc.) + std::string m_SignalModelString; ///< Appendet to the name of the result node + std::string m_ArtifactModelString; ///< Appendet to the name of the result node + std::string m_OutputPath; ///< Image is automatically saved to the specified folder after simulation is finished. + std::string m_OutputPrefix; /** Prefix for filename of output files and logfile. */ + std::string m_AfterSimulationMessage; ///< Store messages that are displayed after the simulation has finished (e.g. warnings, automatic parameter adjustments etc.) /** member variables that store the check-state of GUI checkboxes */ // image generation bool m_CheckOutputVolumeFractionsBox; bool m_CheckAdvancedSignalOptionsBox; bool m_CheckAddNoiseBox; bool m_CheckAddGhostsBox; bool m_CheckAddAliasingBox; bool m_CheckAddSpikesBox; bool m_CheckAddEddyCurrentsBox; bool m_CheckAddDistortionsBox; - string m_MotionVolumesBox; + std::string m_MotionVolumesBox; // fiber generation bool m_CheckRealTimeFibersBox; bool m_CheckAdvancedFiberOptionsBox; bool m_CheckConstantRadiusBox; bool m_CheckIncludeFiducialsBox; }; /** * \brief Datastructure to manage the Fiberfox signal generation parameters. * */ template< class ScalarType = double > class FiberfoxParameters { public: typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkUcharImgType; typedef DiffusionSignalModel DiffusionModelType; typedef std::vector< DiffusionModelType* > DiffusionModelListType; typedef DiffusionNoiseModel NoiseModelType; FiberfoxParameters(); ~FiberfoxParameters(); /** Get same parameter object with different template parameter */ template< class OutType > FiberfoxParameters< OutType > CopyParameters() { FiberfoxParameters< OutType > out; out.m_FiberGen = m_FiberGen; out.m_SignalGen = m_SignalGen; out.m_Misc = m_Misc; if (m_NoiseModel!=nullptr) { if (dynamic_cast*>(m_NoiseModel.get())) out.m_NoiseModel = std::make_shared< mitk::RicianNoiseModel >(); else if (dynamic_cast*>(m_NoiseModel.get())) out.m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel >(); out.m_NoiseModel->SetNoiseVariance(m_NoiseModel->GetNoiseVariance()); } for (unsigned int i=0; i* outModel = nullptr; mitk::DiffusionSignalModel* signalModel = nullptr; if (i*>(signalModel)) outModel = new mitk::StickModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::TensorModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::RawShModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::BallModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::AstroStickModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::DotModel(dynamic_cast*>(signalModel)); if (i m_NoiseModel; ///< If != nullptr, noise is added to the image. void PrintSelf(); ///< Print parameters to stdout. - void SaveParameters(string filename); ///< Save image generation parameters to .ffp file. - void LoadParameters(string filename); ///< Load image generation parameters from .ffp file. + void SaveParameters(std::string filename); ///< Save image generation parameters to .ffp file. + void LoadParameters(std::string filename); ///< Load image generation parameters from .ffp file. template< class ParameterType > ParameterType ReadVal(boost::property_tree::ptree::value_type const& v, std::string tag, ParameterType defaultValue, bool essential=false); std::string m_MissingTags; }; } #include "mitkFiberfoxParameters.cpp" #endif diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkTractographyForest.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkTractographyForest.cpp index 7187027c20..9de8432872 100755 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkTractographyForest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkTractographyForest.cpp @@ -1,119 +1,117 @@ /*=================================================================== 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 "mitkTractographyForest.h" #include #include -using namespace std; - namespace mitk { TractographyForest::TractographyForest( std::shared_ptr< vigra::RandomForest > forest ) { m_Forest = forest; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); SetGeometry(geometry); } TractographyForest::~TractographyForest() { } void TractographyForest::PredictProbabilities(vigra::MultiArray<2, float>& features, vigra::MultiArray<2, float>& probabilities) const { m_Forest->predictProbabilities(features, probabilities); } int TractographyForest::GetNumFeatures() const { if (!HasForest()) mitkThrow() << "Forest is NULL"; return m_Forest->feature_count(); } int TractographyForest::GetNumTrees() const { if (!HasForest()) mitkThrow() << "Forest is NULL"; return m_Forest->tree_count(); } int TractographyForest::GetNumClasses() const { if (!HasForest()) mitkThrow() << "Forest is NULL"; return m_Forest->class_count(); } int TractographyForest::GetMaxTreeDepth() const { if (!HasForest()) mitkThrow() << "Forest is NULL"; return m_Forest->ext_param_.max_tree_depth; } int TractographyForest::IndexToClassLabel(int idx) const { if (!HasForest()) mitkThrow() << "Forest is NULL"; unsigned int classLabel = 0; m_Forest->ext_param_.to_classlabel(idx, classLabel); return classLabel; } bool TractographyForest::HasForest() const { return m_Forest!=nullptr; } void TractographyForest::PrintSelf(std::ostream &os, itk::Indent indent) const { // Superclass::PrintSelf(os, indent); os << indent << this->GetNameOfClass() << ":\n"; os << indent << "Number of features: " << GetNumFeatures() << std::endl; os << indent << "Number of classes: " << GetNumClasses() << std::endl; os << indent << "Number of trees: " << GetNumTrees() << std::endl; os << indent << "Maximum tree depth: " << GetMaxTreeDepth() << std::endl; } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void TractographyForest::UpdateOutputInformation() { } void TractographyForest::SetRequestedRegionToLargestPossibleRegion() { } bool TractographyForest::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool TractographyForest::VerifyRequestedRegion() { return true; } void TractographyForest::SetRequestedRegion(const itk::DataObject* ) { } } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberGenerationTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberGenerationTest.cpp index ec79d22b94..287cfb6ea8 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberGenerationTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberGenerationTest.cpp @@ -1,80 +1,80 @@ /*=================================================================== 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 /**Documentation * Test if fiber transfortaiom methods work correctly */ int mitkFiberGenerationTest(int argc, char* argv[]) { omp_set_num_threads(1); MITK_TEST_BEGIN("mitkFiberGenerationTest"); MITK_TEST_CONDITION_REQUIRED(argc==6,"check for input data") try{ - + mitk::PlanarEllipse::Pointer pf1 = dynamic_cast(mitk::IOUtil::Load(argv[1])[0].GetPointer()); mitk::PlanarEllipse::Pointer pf2 = dynamic_cast(mitk::IOUtil::Load(argv[2])[0].GetPointer()); mitk::PlanarEllipse::Pointer pf3 = dynamic_cast(mitk::IOUtil::Load(argv[3])[0].GetPointer()); mitk::FiberBundle::Pointer uniform = dynamic_cast(mitk::IOUtil::Load(argv[4])[0].GetPointer()); mitk::FiberBundle::Pointer gaussian = dynamic_cast(mitk::IOUtil::Load(argv[5])[0].GetPointer()); FiberGenerationParameters parameters; - vector< mitk::PlanarEllipse::Pointer > fid; fid.push_back(pf1); fid.push_back(pf2); fid.push_back(pf3); - vector< unsigned int > flip; flip.push_back(0); flip.push_back(0); flip.push_back(0); + std::vector< mitk::PlanarEllipse::Pointer > fid; fid.push_back(pf1); fid.push_back(pf2); fid.push_back(pf3); + std::vector< unsigned int > flip; flip.push_back(0); flip.push_back(0); flip.push_back(0); parameters.m_Fiducials.push_back(fid); parameters.m_FlipList.push_back(flip); parameters.m_Density = 50; parameters.m_Tension = 0; parameters.m_Continuity = 0; parameters.m_Bias = 0; parameters.m_Sampling = 1; parameters.m_Variance = 0.1; // check uniform fiber distribution { itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); parameters.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; filter->SetParameters(parameters); filter->Update(); - vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); + std::vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); MITK_TEST_CONDITION_REQUIRED(uniform->Equals(fiberBundles.at(0)),"check uniform bundle") } // check gaussian fiber distribution { itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); parameters.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; filter->SetParameters(parameters); filter->SetParameters(parameters); filter->Update(); - vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); + std::vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); MITK_TEST_CONDITION_REQUIRED(gaussian->Equals(fiberBundles.at(0)),"check gaussian bundle") } } catch(...) { return EXIT_FAILURE; } // always end with this! MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp index a8f78de973..2a6365c5ab 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp @@ -1,259 +1,259 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkTestFixture.h" class mitkFiberfoxSignalGenerationTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkFiberfoxSignalGenerationTestSuite); //MITK_TEST(Test0); //MITK_TEST(Test1); MITK_TEST(Test2); MITK_TEST(Test3); MITK_TEST(Test4); MITK_TEST(Test5); //MITK_TEST(Test6); MITK_TEST(Test7); MITK_TEST(Test8); CPPUNIT_TEST_SUITE_END(); typedef itk::VectorImage< short, 3> ItkDwiType; private: public: /** Members used inside the different (sub-)tests. All members are initialized via setUp().*/ FiberBundle::Pointer m_FiberBundle; std::vector< FiberfoxParameters > m_Parameters; std::vector< mitk::Image::Pointer > m_RefImages; void setUp() override { m_FiberBundle = dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/Signalgen.fib"))[0].GetPointer()); { FiberfoxParameters parameters; parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param1.ffp")); m_Parameters.push_back(parameters); m_RefImages.push_back(dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param1.dwi"))[0].GetPointer())); } { FiberfoxParameters parameters; parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param2.ffp")); m_Parameters.push_back(parameters); m_RefImages.push_back(dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param2.dwi"))[0].GetPointer())); } { FiberfoxParameters parameters; parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param3.ffp")); m_Parameters.push_back(parameters); m_RefImages.push_back(dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param3.dwi"))[0].GetPointer())); } { FiberfoxParameters parameters; parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param4.ffp")); m_Parameters.push_back(parameters); m_RefImages.push_back(dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param4.dwi"))[0].GetPointer())); } { FiberfoxParameters parameters; parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param5.ffp")); m_Parameters.push_back(parameters); m_RefImages.push_back(dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param5.dwi"))[0].GetPointer())); } { FiberfoxParameters parameters; parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param6.ffp")); m_Parameters.push_back(parameters); m_RefImages.push_back(dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param6.dwi"))[0].GetPointer())); } { FiberfoxParameters parameters; parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param7.ffp")); m_Parameters.push_back(parameters); m_RefImages.push_back(dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param7.dwi"))[0].GetPointer())); } { FiberfoxParameters parameters; parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param8.ffp")); m_Parameters.push_back(parameters); m_RefImages.push_back(dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param8.dwi"))[0].GetPointer())); } { FiberfoxParameters parameters; parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param9.ffp")); m_Parameters.push_back(parameters); m_RefImages.push_back(dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param9.dwi"))[0].GetPointer())); } } void tearDown() override { } bool CompareDwi(itk::VectorImage< short, 3 >* dwi1, itk::VectorImage< short, 3 >* dwi2) { bool out = true; typedef itk::VectorImage< short, 3 > DwiImageType; try{ itk::ImageRegionIterator< DwiImageType > it1(dwi1, dwi1->GetLargestPossibleRegion()); itk::ImageRegionIterator< DwiImageType > it2(dwi2, dwi2->GetLargestPossibleRegion()); int count = 0; while(!it1.IsAtEnd()) { if (it1.Get()!=it2.Get()) { if (count<10) { MITK_INFO << "**************************************"; MITK_INFO << "Test value: " << it1.GetIndex() << ":" << it1.Get(); MITK_INFO << "Ref. value: " << it2.GetIndex() << ":" << it2.Get(); } out = false; count++; } ++it1; ++it2; } if (count>=10) MITK_INFO << "Skipping errors."; MITK_INFO << "Errors detected: " << count; } catch(...) { return false; } return out; } - void StartSimulation(FiberfoxParameters parameters, mitk::Image::Pointer refImage, string out) + void StartSimulation(FiberfoxParameters parameters, mitk::Image::Pointer refImage, std::string out) { itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); tractsToDwiFilter->SetUseConstantRandSeed(true); tractsToDwiFilter->SetParameters(parameters); tractsToDwiFilter->SetFiberBundle(m_FiberBundle); tractsToDwiFilter->Update(); mitk::Image::Pointer testImage = mitk::GrabItkImageMemory( tractsToDwiFilter->GetOutput() ); testImage->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( parameters.m_SignalGen.GetGradientDirections() ) ); testImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( parameters.m_SignalGen.m_Bvalue ) ); mitk::DiffusionPropertyHelper propertyHelper( testImage ); propertyHelper.InitializeImage(); if (refImage.IsNotNull()) { if( static_cast( refImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer().IsNotNull() ) { ItkDwiType::Pointer itkTestImagePointer = ItkDwiType::New(); mitk::CastToItkImage(testImage, itkTestImagePointer); ItkDwiType::Pointer itkRefImagePointer = ItkDwiType::New(); mitk::CastToItkImage(refImage, itkRefImagePointer); bool cond = CompareDwi(itkTestImagePointer, itkRefImagePointer); if (!cond) { MITK_INFO << "Saving test image to " << mitk::IOUtil::GetTempPath(); mitk::IOUtil::Save(testImage, mitk::IOUtil::GetTempPath()+out); } CPPUNIT_ASSERT_MESSAGE("Simulated images should be equal", cond); } } } void Test0() { StartSimulation(m_Parameters.at(0), m_RefImages.at(0), "param1.dwi"); } void Test1() { StartSimulation(m_Parameters.at(1), m_RefImages.at(1), "param2.dwi"); } void Test2() { StartSimulation(m_Parameters.at(2), m_RefImages.at(2), "param3.dwi"); } void Test3() { StartSimulation(m_Parameters.at(3), m_RefImages.at(3), "param4.dwi"); } void Test4() { StartSimulation(m_Parameters.at(4), m_RefImages.at(4), "param5.dwi"); } void Test5() { StartSimulation(m_Parameters.at(5), m_RefImages.at(5), "param6.dwi"); } void Test6() { StartSimulation(m_Parameters.at(6), m_RefImages.at(6), "param7.dwi"); } void Test7() { StartSimulation(m_Parameters.at(7), m_RefImages.at(7), "param8.dwi"); } void Test8() { StartSimulation(m_Parameters.at(8), m_RefImages.at(8), "param9.dwi"); } }; MITK_TEST_SUITE_REGISTRATION(mitkFiberfoxSignalGeneration) diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp index 0dd0aa5f74..7f26a19759 100755 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp @@ -1,161 +1,159 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -using namespace std; - int mitkLocalFiberPlausibilityTest(int argc, char* argv[]) { omp_set_num_threads(1); MITK_TEST_BEGIN("mitkLocalFiberPlausibilityTest"); MITK_TEST_CONDITION_REQUIRED(argc==8,"check for input data") - string fibFile = argv[1]; - vector< string > referenceImages; + std::string fibFile = argv[1]; + std::vector< std::string > referenceImages; referenceImages.push_back(argv[2]); referenceImages.push_back(argv[3]); - string LDFP_ERROR_IMAGE = argv[4]; - string LDFP_NUM_DIRECTIONS = argv[5]; - string LDFP_VECTOR_FIELD = argv[6]; - string LDFP_ERROR_IMAGE_IGNORE = argv[7]; + std::string LDFP_ERROR_IMAGE = argv[4]; + std::string LDFP_NUM_DIRECTIONS = argv[5]; + std::string LDFP_VECTOR_FIELD = argv[6]; + std::string LDFP_ERROR_IMAGE_IGNORE = argv[7]; float angularThreshold = 30; try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; // load fiber bundle mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::Load(fibFile)[0].GetPointer()); // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::Load(referenceImages.at(i))[0].GetPointer()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ MITK_INFO << "could not load: " << referenceImages.at(i); } } ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); itkMaskImage->SetSpacing( dirImg->GetSpacing() ); itkMaskImage->SetOrigin( dirImg->GetOrigin() ); itkMaskImage->SetDirection( dirImg->GetDirection() ); itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->Allocate(); itkMaskImage->FillBuffer(1); // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter::NormalizationMethods::SINGLE_VEC_NORM); fOdfFilter->SetMaxNumDirections(3); fOdfFilter->SetSizeThreshold(0.3); fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->SetNumberOfThreads(1); fOdfFilter->Update(); itk::TractsToVectorImageFilter::ItkDirectionImageType::Pointer direction_image = fOdfFilter->GetDirectionImage(); // Get directions and num directions image ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); mitk::Image::Pointer mitkNumDirImage = mitk::Image::New(); mitkNumDirImage->InitializeByItk( numDirImage.GetPointer() ); mitkNumDirImage->SetVolume( numDirImage->GetBufferPointer() ); // mitk::FiberBundle::Pointer testDirections = fOdfFilter->GetOutputFiberBundle(); // evaluate directions with missing directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); // evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(false); evaluationFilter->Update(); EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); mitk::Image::Pointer mitkAngularErrorImage = mitk::Image::New(); mitkAngularErrorImage->InitializeByItk( angularErrorImage.GetPointer() ); mitkAngularErrorImage->SetVolume( angularErrorImage->GetBufferPointer() ); // evaluate directions without missing directions evaluationFilter->SetIgnoreMissingDirections(true); evaluationFilter->Update(); EvaluationFilterType::OutputImageType::Pointer angularErrorImageIgnore = evaluationFilter->GetOutput(0); mitk::Image::Pointer mitkAngularErrorImageIgnore = mitk::Image::New(); mitkAngularErrorImageIgnore->InitializeByItk( angularErrorImageIgnore.GetPointer() ); mitkAngularErrorImageIgnore->SetVolume( angularErrorImageIgnore->GetBufferPointer() ); mitk::Image::Pointer gtAngularErrorImageIgnore = dynamic_cast(mitk::IOUtil::Load(LDFP_ERROR_IMAGE_IGNORE)[0].GetPointer()); mitk::Image::Pointer gtAngularErrorImage = dynamic_cast(mitk::IOUtil::Load(LDFP_ERROR_IMAGE)[0].GetPointer()); mitk::Image::Pointer gtNumTestDirImage = dynamic_cast(mitk::IOUtil::Load(LDFP_NUM_DIRECTIONS)[0].GetPointer()); MITK_ASSERT_EQUAL(gtAngularErrorImageIgnore, mitkAngularErrorImageIgnore, "Check if error images are equal (ignored missing directions)."); MITK_ASSERT_EQUAL(gtAngularErrorImage, mitkAngularErrorImage, "Check if error images are equal."); MITK_ASSERT_EQUAL(gtNumTestDirImage, mitkNumDirImage, "Check if num direction images are equal."); } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberDirectionExtraction.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberDirectionExtraction.cpp index 9867591755..c1a013d1cc 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberDirectionExtraction.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberDirectionExtraction.cpp @@ -1,180 +1,178 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -using namespace std; - /*! \brief Extract principal fiber directions from a tractogram */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fiber Direction Extraction"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription("Extract principal fiber directions from a tractogram"); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib/.trk)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask:", "mask image"); parser.addArgument("athresh", "a", mitkCommandLineParser::Float, "Angular threshold:", "angular threshold in degrees. closer fiber directions are regarded as one direction and clustered together.", 25, true); parser.addArgument("peakthresh", "t", mitkCommandLineParser::Float, "Peak size threshold:", "peak size threshold relative to largest peak in voxel", 0.2, true); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose:", "output optional and intermediate calculation results"); parser.addArgument("numdirs", "d", mitkCommandLineParser::Int, "Max. num. directions:", "maximum number of fibers per voxel", 3, true); parser.addArgument("normalization", "n", mitkCommandLineParser::Int, "Normalization method:", "1=global maximum, 2=single vector, 3=voxel-wise maximum", 1); parser.addArgument("file_ending", "f", mitkCommandLineParser::String, "Image type:", ".nrrd, .nii, .nii.gz"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; - string fibFile = us::any_cast(parsedArgs["input"]); + std::string fibFile = us::any_cast(parsedArgs["input"]); - string maskImage(""); + std::string maskImage(""); if (parsedArgs.count("mask")) - maskImage = us::any_cast(parsedArgs["mask"]); + maskImage = us::any_cast(parsedArgs["mask"]); float peakThreshold = 0.2; if (parsedArgs.count("peakthresh")) peakThreshold = us::any_cast(parsedArgs["peakthresh"]); float angularThreshold = 25; if (parsedArgs.count("athresh")) angularThreshold = us::any_cast(parsedArgs["athresh"]); - string outRoot = us::any_cast(parsedArgs["out"]); + std::string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); int maxNumDirs = 3; if (parsedArgs.count("numdirs")) maxNumDirs = us::any_cast(parsedArgs["numdirs"]); int normalization = 1; if (parsedArgs.count("normalization")) normalization = us::any_cast(parsedArgs["normalization"]); std::string file_ending = ".nrrd"; if (parsedArgs.count("file_ending")) file_ending = us::any_cast(parsedArgs["file_ending"]); try { typedef itk::Image ItkUcharImgType; // load fiber bundle mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::Load(fibFile)[0].GetPointer()); // load/create mask image ItkUcharImgType::Pointer itkMaskImage = nullptr; if (maskImage.compare("")!=0) { std::cout << "Using mask image"; itkMaskImage = ItkUcharImgType::New(); mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::Load(maskImage)[0].GetPointer()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); } // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); switch (normalization) { case 1: fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter::NormalizationMethods::GLOBAL_MAX); break; case 2: fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter::NormalizationMethods::SINGLE_VEC_NORM); break; case 3: fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter::NormalizationMethods::MAX_VEC_NORM); break; } fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->SetSizeThreshold(peakThreshold); fOdfFilter->SetMaxNumDirections(maxNumDirs); fOdfFilter->Update(); { itk::TractsToVectorImageFilter::ItkDirectionImageType::Pointer itkImg = fOdfFilter->GetDirectionImage(); typedef itk::ImageFileWriter< itk::TractsToVectorImageFilter::ItkDirectionImageType > WriterType; WriterType::Pointer writer = WriterType::New(); - string outfilename = outRoot; + std::string outfilename = outRoot; outfilename.append("_DIRECTIONS"); outfilename.append(file_ending); writer->SetFileName(outfilename.c_str()); writer->SetInput(itkImg); writer->Update(); } if (verbose) { // write num direction image ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); - string outfilename = outRoot; + std::string outfilename = outRoot; outfilename.append("_NUM_DIRECTIONS"); outfilename.append(file_ending); writer->SetFileName(outfilename.c_str()); writer->SetInput(numDirImage); writer->Update(); } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberExtraction.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberExtraction.cpp index ad71c0002a..96da7b68df 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberExtraction.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberExtraction.cpp @@ -1,166 +1,164 @@ /*=================================================================== 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 "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -using namespace std; - /*! \brief Extract fibers from a tractogram using planar figure ROIs */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fiber Extraction"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setContributor("MIC"); parser.setDescription("Extract fibers from a tractogram using planar figure ROIs"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::String, "Input:", "input tractogram (.fib/.trk)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::String, "Output:", "output tractogram", us::Any(), false); parser.addArgument("planfirgure1", "pf1", mitkCommandLineParser::String, "Figure 1:", "first ROI", us::Any(), false); parser.addArgument("planfirgure2", "pf2", mitkCommandLineParser::String, "Figure 2:", "second ROI", us::Any()); parser.addArgument("operation", "op", mitkCommandLineParser::String, "Operation:", "logical operation (AND, OR, NOT)", us::Any()); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; - string inFib = us::any_cast(parsedArgs["input"]); - string outFib = us::any_cast(parsedArgs["out"]); - string pf1_path = us::any_cast(parsedArgs["planfirgure1"]); + std::string inFib = us::any_cast(parsedArgs["input"]); + std::string outFib = us::any_cast(parsedArgs["out"]); + std::string pf1_path = us::any_cast(parsedArgs["planfirgure1"]); - string operation(""); - string pf2_path(""); + std::string operation(""); + std::string pf2_path(""); if (parsedArgs.count("operation")) { - operation = us::any_cast(parsedArgs["operation"]); + operation = us::any_cast(parsedArgs["operation"]); if (parsedArgs.count("planfirgure2") && (operation=="AND" || operation=="OR")) - pf2_path = us::any_cast(parsedArgs["planfirgure2"]); + pf2_path = us::any_cast(parsedArgs["planfirgure2"]); } try { typedef itk::Image ItkUcharImgType; // load fiber bundle mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::Load(inFib)[0].GetPointer()); mitk::FiberBundle::Pointer result; mitk::StandaloneDataStorage::Pointer storage = mitk::StandaloneDataStorage::New(); auto data = mitk::IOUtil::Load(pf1_path)[0]; auto input1 = mitk::DataNode::New(); input1->SetData(data); if (input1.IsNotNull()) { mitk::PlanarFigureComposite::Pointer pfc = mitk::PlanarFigureComposite::New(); mitk::DataNode::Pointer pfcNode = mitk::DataNode::New(); pfcNode->SetData(pfc); mitk::DataStorage::SetOfObjects::Pointer set1 = mitk::DataStorage::SetOfObjects::New(); set1->push_back(pfcNode); storage->Add(pfcNode); auto input2 = mitk::DataNode::New(); if (!pf2_path.empty()) { data = mitk::IOUtil::Load(pf2_path)[0]; input2->SetData(data); } if (operation.empty()) { result = inputTractogram->ExtractFiberSubset(input1, nullptr); } else if (operation=="NOT") { pfc->setOperationType(mitk::PlanarFigureComposite::NOT); storage->Add(input1, set1); result = inputTractogram->ExtractFiberSubset(pfcNode, storage); } else if (operation=="AND" && input2.IsNotNull()) { pfc->setOperationType(mitk::PlanarFigureComposite::AND); storage->Add(input1, set1); storage->Add(input2, set1); result = inputTractogram->ExtractFiberSubset(pfcNode, storage); } else if (operation=="OR" && input2.IsNotNull()) { pfc->setOperationType(mitk::PlanarFigureComposite::OR); storage->Add(input1, set1); storage->Add(input2, set1); result = inputTractogram->ExtractFiberSubset(pfcNode, storage); } else { std::cout << "Could not process input:"; std::cout << pf1_path; std::cout << pf2_path; std::cout << operation; } } else { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::Load(pf1_path)[0].GetPointer()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); if (operation=="NOT") result = inputTractogram->ExtractFiberSubset(itkMaskImage, true, true); else result = inputTractogram->ExtractFiberSubset(itkMaskImage, true, false); } if (result.IsNotNull()) mitk::IOUtil::Save(result, outFib); else std::cout << "No valid fiber bundle extracted."; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberProcessing.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberProcessing.cpp index 452baf25c5..a532ffcb16 100644 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberProcessing.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FiberProcessing.cpp @@ -1,220 +1,219 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include -#include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include 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()); } /*! \brief Modify input tractogram: fiber resampling, compression, pruning and transformation. */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fiber Processing"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription("Modify input tractogram: fiber resampling, compression, pruning and transformation."); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input fiber bundle (.fib, .trk, .tck)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output:", "output fiber bundle (.fib, .trk)", us::Any(), false); parser.addArgument("smooth", "s", mitkCommandLineParser::Float, "Spline resampling:", "Resample fiber using splines with the given point distance (in mm)"); parser.addArgument("compress", "c", mitkCommandLineParser::Float, "Compress:", "Compress fiber using the given error threshold (in mm)"); parser.addArgument("minLength", "l", mitkCommandLineParser::Float, "Minimum length:", "Minimum fiber length (in mm)"); parser.addArgument("maxLength", "m", mitkCommandLineParser::Float, "Maximum length:", "Maximum fiber length (in mm)"); parser.addArgument("maxAngle", "a", mitkCommandLineParser::Float, "Maximum angle:", "Maximum angular STDEV over 1cm (in degree)"); parser.addArgument("remove", "rm", mitkCommandLineParser::Bool, "Remove fibers exceeding curvature threshold:", "if false, only the high curvature parts are removed"); parser.addArgument("mirror", "p", mitkCommandLineParser::Int, "Invert coordinates:", "Invert fiber coordinates XYZ (e.g. 010 to invert y-coordinate of each fiber point)"); parser.addArgument("rotate-x", "rx", mitkCommandLineParser::Float, "Rotate x-axis:", "Rotate around x-axis (in deg)"); parser.addArgument("rotate-y", "ry", mitkCommandLineParser::Float, "Rotate y-axis:", "Rotate around y-axis (in deg)"); parser.addArgument("rotate-z", "rz", mitkCommandLineParser::Float, "Rotate z-axis:", "Rotate around z-axis (in deg)"); parser.addArgument("scale-x", "sx", mitkCommandLineParser::Float, "Scale x-axis:", "Scale in direction of x-axis"); parser.addArgument("scale-y", "sy", mitkCommandLineParser::Float, "Scale y-axis:", "Scale in direction of y-axis"); parser.addArgument("scale-z", "sz", mitkCommandLineParser::Float, "Scale z-axis", "Scale in direction of z-axis"); parser.addArgument("translate-x", "tx", mitkCommandLineParser::Float, "Translate x-axis:", "Translate in direction of x-axis (in mm)"); parser.addArgument("translate-y", "ty", mitkCommandLineParser::Float, "Translate y-axis:", "Translate in direction of y-axis (in mm)"); parser.addArgument("translate-z", "tz", mitkCommandLineParser::Float, "Translate z-axis:", "Translate in direction of z-axis (in mm)"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; bool remove = false; if (parsedArgs.count("remove")) remove = us::any_cast(parsedArgs["remove"]); float smoothDist = -1; if (parsedArgs.count("smooth")) smoothDist = us::any_cast(parsedArgs["smooth"]); float compress = -1; if (parsedArgs.count("compress")) compress = us::any_cast(parsedArgs["compress"]); float minFiberLength = -1; if (parsedArgs.count("minLength")) minFiberLength = us::any_cast(parsedArgs["minLength"]); float maxFiberLength = -1; if (parsedArgs.count("maxLength")) maxFiberLength = us::any_cast(parsedArgs["maxLength"]); float maxAngularDev = -1; if (parsedArgs.count("maxAngle")) maxAngularDev = us::any_cast(parsedArgs["maxAngle"]); int axis = 0; if (parsedArgs.count("mirror")) axis = us::any_cast(parsedArgs["mirror"]); float rotateX = 0; if (parsedArgs.count("rotate-x")) rotateX = us::any_cast(parsedArgs["rotate-x"]); float rotateY = 0; if (parsedArgs.count("rotate-y")) rotateY = us::any_cast(parsedArgs["rotate-y"]); float rotateZ = 0; if (parsedArgs.count("rotate-z")) rotateZ = us::any_cast(parsedArgs["rotate-z"]); float scaleX = 0; if (parsedArgs.count("scale-x")) scaleX = us::any_cast(parsedArgs["scale-x"]); float scaleY = 0; if (parsedArgs.count("scale-y")) scaleY = us::any_cast(parsedArgs["scale-y"]); float scaleZ = 0; if (parsedArgs.count("scale-z")) scaleZ = us::any_cast(parsedArgs["scale-z"]); float translateX = 0; if (parsedArgs.count("translate-x")) translateX = us::any_cast(parsedArgs["translate-x"]); float translateY = 0; if (parsedArgs.count("translate-y")) translateY = us::any_cast(parsedArgs["translate-y"]); float translateZ = 0; if (parsedArgs.count("translate-z")) translateZ = us::any_cast(parsedArgs["translate-z"]); - string inFileName = us::any_cast(parsedArgs["input"]); - string outFileName = us::any_cast(parsedArgs["outFile"]); + std::string inFileName = us::any_cast(parsedArgs["input"]); + std::string outFileName = us::any_cast(parsedArgs["outFile"]); try { mitk::FiberBundle::Pointer fib = LoadFib(inFileName); if (maxAngularDev>0) { auto filter = itk::FiberCurvatureFilter::New(); filter->SetInputFiberBundle(fib); filter->SetAngularDeviation(maxAngularDev); filter->SetDistance(10); filter->SetRemoveFibers(remove); filter->Update(); fib = filter->GetOutputFiberBundle(); } if (minFiberLength>0) fib->RemoveShortFibers(minFiberLength); if (maxFiberLength>0) fib->RemoveLongFibers(maxFiberLength); if (smoothDist>0) fib->ResampleSpline(smoothDist); if (compress>0) fib->Compress(compress); if (axis/100==1) fib->MirrorFibers(0); if ((axis%100)/10==1) fib->MirrorFibers(1); if (axis%10==1) fib->MirrorFibers(2); if (rotateX > 0 || rotateY > 0 || rotateZ > 0){ std::cout << "Rotate " << rotateX << " " << rotateY << " " << rotateZ; fib->RotateAroundAxis(rotateX, rotateY, rotateZ); } if (translateX > 0 || translateY > 0 || translateZ > 0){ fib->TranslateFibers(translateX, translateY, translateZ); } if (scaleX > 0 || scaleY > 0 || scaleZ > 0) fib->ScaleFibers(scaleX, scaleY, scaleZ); mitk::IOUtil::Save(fib.GetPointer(), outFileName ); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FitFibersToImage.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FitFibersToImage.cpp index e58629356e..fc207cccba 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FitFibersToImage.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/FiberProcessing/FitFibersToImage.cpp @@ -1,203 +1,216 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include -using namespace std; typedef itksys::SystemTools ist; typedef itk::Point PointType4; typedef itk::Image< float, 4 > PeakImgType; -std::vector< string > get_file_list(const std::string& path) +std::vector< std::string > get_file_list(const std::string& path) { - std::vector< string > file_list; + std::vector< std::string > file_list; itk::Directory::Pointer dir = itk::Directory::New(); if (dir->Load(path.c_str())) { int n = dir->GetNumberOfFiles(); for (int r = 0; r < n; r++) { const char *filename = dir->GetFile(r); std::string ext = ist::GetFilenameExtension(filename); if (ext==".fib" || ext==".trk") file_list.push_back(path + '/' + filename); } } return file_list; } /*! \brief Fits the tractogram to the input peak image by assigning a weight to each fiber (similar to https://doi.org/10.1016/j.neuroimage.2015.06.092). */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fit Fibers To Image"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription("Assigns a weight to each fiber in order to optimally explain the input peak image"); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("", "i1", mitkCommandLineParser::StringList, "Input tractograms:", "input tractograms (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("", "i2", mitkCommandLineParser::InputFile, "Input peaks:", "input peak image", us::Any(), false); parser.addArgument("", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("max_iter", "", mitkCommandLineParser::Int, "Max. iterations:", "maximum number of optimizer iterations", 20); parser.addArgument("bundle_based", "", mitkCommandLineParser::Bool, "Bundle based fit:", "fit one weight per input tractogram/bundle, not for each fiber", false); parser.addArgument("min_g", "", mitkCommandLineParser::Float, "Min. g:", "lower termination threshold for gradient magnitude", 1e-5); parser.addArgument("lambda", "", mitkCommandLineParser::Float, "Lambda:", "modifier for regularization", 0.1); - parser.addArgument("save_res", "", mitkCommandLineParser::Bool, "Residuals:", "save residual images", false); + parser.addArgument("save_res", "", mitkCommandLineParser::Bool, "Save Residuals:", "save residual images", false); + parser.addArgument("save_weights", "", mitkCommandLineParser::Bool, "Save Weights:", "save fiber weights in a separate text file", false); parser.addArgument("dont_filter_outliers", "", mitkCommandLineParser::Bool, "Don't filter outliers:", "don't perform second optimization run with an upper weight bound based on the first weight estimation (95% quantile)", false); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType fib_files = us::any_cast(parsedArgs["i1"]); - string peak_file_name = us::any_cast(parsedArgs["i2"]); - string outRoot = us::any_cast(parsedArgs["o"]); + std::string peak_file_name = us::any_cast(parsedArgs["i2"]); + std::string outRoot = us::any_cast(parsedArgs["o"]); bool single_fib = true; if (parsedArgs.count("bundle_based")) single_fib = !us::any_cast(parsedArgs["bundle_based"]); bool save_residuals = false; if (parsedArgs.count("save_res")) save_residuals = us::any_cast(parsedArgs["save_res"]); + bool save_weights = false; + if (parsedArgs.count("save_weights")) + save_weights = us::any_cast(parsedArgs["save_weights"]); + int max_iter = 20; if (parsedArgs.count("max_iter")) max_iter = us::any_cast(parsedArgs["max_iter"]); float g_tol = 1e-5; if (parsedArgs.count("min_g")) g_tol = us::any_cast(parsedArgs["min_g"]); float lambda = 0.1; if (parsedArgs.count("lambda")) lambda = us::any_cast(parsedArgs["lambda"]); bool filter_outliers = true; if (parsedArgs.count("dont_filter_outliers")) filter_outliers = !us::any_cast(parsedArgs["dont_filter_outliers"]); try { std::vector< mitk::FiberBundle::Pointer > input_tracts; mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Peak Image", "Fiberbundles"}, {}); mitk::Image::Pointer inputImage = dynamic_cast(mitk::IOUtil::Load(peak_file_name, &functor)[0].GetPointer()); typedef mitk::ImageToItk< PeakImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(inputImage); caster->Update(); PeakImgType::Pointer peak_image = caster->GetOutput(); std::vector< std::string > fib_names; for (auto item : fib_files) { if ( ist::FileIsDirectory(item) ) { for ( auto fibFile : get_file_list(item) ) { mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::Load(fibFile)[0].GetPointer()); if (inputTractogram.IsNull()) continue; input_tracts.push_back(inputTractogram); fib_names.push_back(fibFile); } } else { mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::Load(item)[0].GetPointer()); if (inputTractogram.IsNull()) continue; input_tracts.push_back(inputTractogram); fib_names.push_back(item); } } itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New(); fitter->SetPeakImage(peak_image); fitter->SetTractograms(input_tracts); fitter->SetFitIndividualFibers(single_fib); fitter->SetMaxIterations(max_iter); fitter->SetGradientTolerance(g_tol); fitter->SetLambda(lambda); fitter->SetFilterOutliers(filter_outliers); fitter->Update(); if (save_residuals) { itk::ImageFileWriter< PeakImgType >::Pointer writer = itk::ImageFileWriter< PeakImgType >::New(); writer->SetInput(fitter->GetFittedImage()); writer->SetFileName(outRoot + "fitted_image.nrrd"); writer->Update(); writer->SetInput(fitter->GetResidualImage()); writer->SetFileName(outRoot + "residual_image.nrrd"); writer->Update(); writer->SetInput(fitter->GetOverexplainedImage()); writer->SetFileName(outRoot + "overexplained_image.nrrd"); writer->Update(); writer->SetInput(fitter->GetUnderexplainedImage()); writer->SetFileName(outRoot + "underexplained_image.nrrd"); writer->Update(); } std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms(); for (unsigned int bundle=0; bundleGetNumFibers(); ++f) + logfile << output_tracts.at(bundle)->GetFiberWeight(f) << "\n"; + logfile.close(); + } } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/Fiberfox/Fiberfox.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/Fiberfox/Fiberfox.cpp index 30fd887c00..ddf7ec9b03 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/Fiberfox/Fiberfox.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/Fiberfox/Fiberfox.cpp @@ -1,209 +1,209 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include using namespace mitk; /*! * \brief Command line interface to Fiberfox. * Simulate a diffusion-weighted image from a tractogram using the specified parameter file. */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fiberfox"); parser.setCategory("Diffusion Simulation Tools"); parser.setContributor("MIC"); parser.setDescription("Command line interface to Fiberfox." " Simulate a diffusion-weighted image from a tractogram using the specified parameter file."); parser.setArgumentPrefix("--", "-"); parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output root:", "output root", us::Any(), false); parser.addArgument("parameters", "p", mitkCommandLineParser::InputFile, "Parameter file:", "fiberfox parameter file (.ffp)", us::Any(), false); parser.addArgument("input", "i", mitkCommandLineParser::String, "Input:", "Input tractogram or diffusion-weighted image.", us::Any(), false); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Output additional images:", "output volume fraction images etc.", us::Any()); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) { return EXIT_FAILURE; } - string outName = us::any_cast(parsedArgs["out"]); - string paramName = us::any_cast(parsedArgs["parameters"]); + std::string outName = us::any_cast(parsedArgs["out"]); + std::string paramName = us::any_cast(parsedArgs["parameters"]); - string input=""; + std::string input=""; if (parsedArgs.count("input")) { - input = us::any_cast(parsedArgs["input"]); + input = us::any_cast(parsedArgs["input"]); } bool verbose = false; if (parsedArgs.count("verbose")) { verbose = us::any_cast(parsedArgs["verbose"]); } FiberfoxParameters parameters; parameters.LoadParameters(paramName); // Test if /path/dir is an existing directory: - string file_extension = ""; + std::string file_extension = ""; if( itksys::SystemTools::FileIsDirectory( outName ) ) { while( *(--(outName.cend())) == '/') { outName.pop_back(); } outName = outName + '/'; parameters.m_Misc.m_OutputPath = outName; outName = outName + parameters.m_Misc.m_OutputPrefix; // using default m_OutputPrefix as initialized. } else { // outName is NOT an existing directory, so we need to remove all trailing slashes: while( *(--(outName.cend())) == '/') { outName.pop_back(); } // now split up the given outName into directory and (prefix of) filename: if( ! itksys::SystemTools::GetFilenamePath( outName ).empty() && itksys::SystemTools::FileIsDirectory(itksys::SystemTools::GetFilenamePath( outName ) ) ) { parameters.m_Misc.m_OutputPath = itksys::SystemTools::GetFilenamePath( outName ) + '/'; } else { parameters.m_Misc.m_OutputPath = itksys::SystemTools::GetCurrentWorkingDirectory() + '/'; } file_extension = itksys::SystemTools::GetFilenameExtension(outName); if( ! itksys::SystemTools::GetFilenameWithoutExtension( outName ).empty() ) { parameters.m_Misc.m_OutputPrefix = itksys::SystemTools::GetFilenameWithoutExtension( outName ); } else { parameters.m_Misc.m_OutputPrefix = "fiberfox"; } outName = parameters.m_Misc.m_OutputPath + parameters.m_Misc.m_OutputPrefix; } // check if log file already exists and avoid overwriting existing files: std::string NameTest = outName; int c = 0; while( itksys::SystemTools::FileExists( outName + ".log" ) && c <= std::numeric_limits::max() ) { outName = NameTest + "_" + boost::lexical_cast(c); ++c; } if (verbose) { MITK_DEBUG << outName << ".ffp"; parameters.SaveParameters(outName+".ffp"); } mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images", "Fiberbundles"}, {}); mitk::BaseData::Pointer inputData = mitk::IOUtil::Load(input, &functor)[0]; itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); if ( dynamic_cast(inputData.GetPointer()) ) // simulate dataset from fibers { tractsToDwiFilter->SetFiberBundle(dynamic_cast(inputData.GetPointer())); } else if ( dynamic_cast(inputData.GetPointer()) ) // add artifacts to existing image { typedef itk::VectorImage< short, 3 > ItkDwiType; mitk::Image::Pointer diffImg = dynamic_cast(inputData.GetPointer()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); parameters.m_SignalGen.m_SignalScale = 1; parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection(); parameters.m_SignalGen.m_Bvalue = static_cast (diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue(); parameters.m_SignalGen.SetGradienDirections( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); tractsToDwiFilter->SetInputImage(itkVectorImagePointer); } tractsToDwiFilter->SetParameters(parameters); tractsToDwiFilter->Update(); mitk::Image::Pointer image = mitk::GrabItkImageMemory( tractsToDwiFilter->GetOutput() ); image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( parameters.m_SignalGen.GetGradientDirections() ) ); image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( parameters.m_SignalGen.m_Bvalue ) ); mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); if (file_extension=="") mitk::IOUtil::Save(image, "application/vnd.mitk.nii.gz", outName+".nii.gz"); else if (file_extension==".nii" || file_extension==".nii.gz") mitk::IOUtil::Save(image, "application/vnd.mitk.nii.gz", outName+file_extension); else mitk::IOUtil::Save(image, outName+file_extension); if (verbose) { std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = tractsToDwiFilter->GetVolumeFractions(); for (unsigned int k=0; kInitializeByItk(volumeFractions.at(k).GetPointer()); image->SetVolume(volumeFractions.at(k)->GetBufferPointer()); - mitk::IOUtil::Save(image, outName+"_Compartment"+boost::lexical_cast(k+1)+".nrrd"); + mitk::IOUtil::Save(image, outName+"_Compartment"+boost::lexical_cast(k+1)+".nrrd"); } if (tractsToDwiFilter->GetPhaseImage().IsNotNull()) { mitk::Image::Pointer image = mitk::Image::New(); itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkPhase = tractsToDwiFilter->GetPhaseImage(); image = mitk::GrabItkImageMemory( itkPhase.GetPointer() ); mitk::IOUtil::Save(image, outName+"_Phase.nrrd"); } if (tractsToDwiFilter->GetKspaceImage().IsNotNull()) { mitk::Image::Pointer image = mitk::Image::New(); itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkImage = tractsToDwiFilter->GetKspaceImage(); image = mitk::GrabItkImageMemory( itkImage.GetPointer() ); mitk::IOUtil::Save(image, outName+"_kSpace.nrrd"); } } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/Misc/FileFormatConverter.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/Misc/FileFormatConverter.cpp index d5a405a5d2..1e706eae8e 100644 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/Misc/FileFormatConverter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/Misc/FileFormatConverter.cpp @@ -1,83 +1,80 @@ /*=================================================================== 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 "mitkCommandLineParser.h" #include #include -using namespace mitk; -using namespace std; - /*! \brief Load image and save as specified file type. */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Format Converter"); parser.setCategory("Preprocessing Tools"); parser.setDescription("Load image and save as specified file type."); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("in", "i", mitkCommandLineParser::InputFile, "Input:", "input file", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output:", "output file", us::Any(), false); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments - string inName = us::any_cast(parsedArgs["in"]); - string outName = us::any_cast(parsedArgs["out"]); + std::string inName = us::any_cast(parsedArgs["in"]); + std::string outName = us::any_cast(parsedArgs["out"]); try { mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {}); std::vector baseData = mitk::IOUtil::Load(inName, &functor); - if ( baseData.size()>0 && dynamic_cast(baseData[0].GetPointer()) ) + if ( baseData.size()>0 && dynamic_cast(baseData[0].GetPointer()) ) { - mitk::IOUtil::Save(dynamic_cast(baseData[0].GetPointer()), outName.c_str()); + mitk::IOUtil::Save(dynamic_cast(baseData[0].GetPointer()), outName.c_str()); } - else if ( baseData.size()>0 && dynamic_cast(baseData[0].GetPointer()) ) + else if ( baseData.size()>0 && dynamic_cast(baseData[0].GetPointer()) ) { - mitk::IOUtil::Save(dynamic_cast(baseData[0].GetPointer()) ,outName.c_str()); + mitk::IOUtil::Save(dynamic_cast(baseData[0].GetPointer()) ,outName.c_str()); } else std::cout << "File type currently not supported!"; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/Misc/PeakExtraction.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/Misc/PeakExtraction.cpp index f0009f4a7b..f81f293629 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/Misc/PeakExtraction.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/Misc/PeakExtraction.cpp @@ -1,362 +1,360 @@ /*=================================================================== 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 "mitkCommandLineParser.h" #include #include #include #include #include -using namespace std; - template int StartPeakExtraction(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("image", "i", mitkCommandLineParser::InputFile, "Input image", "sh coefficient image", us::Any(), false); parser.addArgument("outroot", "o", mitkCommandLineParser::OutputDirectory, "Output directory", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask", "mask image"); parser.addArgument("normalization", "n", mitkCommandLineParser::Int, "Normalization", "0=no norm, 1=max norm, 2=single vec norm", 1, true); parser.addArgument("numpeaks", "p", mitkCommandLineParser::Int, "Max. number of peaks", "maximum number of extracted peaks", 2, true); parser.addArgument("peakthres", "r", mitkCommandLineParser::Float, "Peak threshold", "peak threshold relative to largest peak", 0.4, true); parser.addArgument("abspeakthres", "a", mitkCommandLineParser::Float, "Absolute peak threshold", "absolute peak threshold weighted with local GFA value", 0.06, true); - parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "Use specified SH-basis", "use specified SH-basis (MITK, FSL, MRtrix)", string("MITK"), true); + parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "Use specified SH-basis", "use specified SH-basis (MITK, FSL, MRtrix)", std::string("MITK"), true); parser.addArgument("noFlip", "f", mitkCommandLineParser::Bool, "No flip", "do not flip input image to match MITK coordinate convention"); parser.addArgument("clusterThres", "c", mitkCommandLineParser::Float, "Clustering threshold", "directions closer together than the specified angular threshold will be clustered (in rad)", 0.9); parser.addArgument("flipX", "fx", mitkCommandLineParser::Bool, "Flip X", "Flip peaks in x direction"); parser.addArgument("flipY", "fy", mitkCommandLineParser::Bool, "Flip Y", "Flip peaks in y direction"); parser.addArgument("flipZ", "fz", mitkCommandLineParser::Bool, "Flip Z", "Flip peaks in z direction"); parser.setCategory("Preprocessing Tools"); parser.setTitle("Peak Extraction"); parser.setDescription(""); parser.setContributor("MIC"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments - string imageName = us::any_cast(parsedArgs["image"]); - string outRoot = us::any_cast(parsedArgs["outroot"]); + std::string imageName = us::any_cast(parsedArgs["image"]); + std::string outRoot = us::any_cast(parsedArgs["outroot"]); // optional arguments - string maskImageName(""); + std::string maskImageName(""); if (parsedArgs.count("mask")) - maskImageName = us::any_cast(parsedArgs["mask"]); + maskImageName = us::any_cast(parsedArgs["mask"]); int normalization = 1; if (parsedArgs.count("normalization")) normalization = us::any_cast(parsedArgs["normalization"]); int numPeaks = 2; if (parsedArgs.count("numpeaks")) numPeaks = us::any_cast(parsedArgs["numpeaks"]); float peakThres = 0.4; if (parsedArgs.count("peakthres")) peakThres = us::any_cast(parsedArgs["peakthres"]); float absPeakThres = 0.06; if (parsedArgs.count("abspeakthres")) absPeakThres = us::any_cast(parsedArgs["abspeakthres"]); float clusterThres = 0.9; if (parsedArgs.count("clusterThres")) clusterThres = us::any_cast(parsedArgs["clusterThres"]); bool noFlip = false; if (parsedArgs.count("noFlip")) noFlip = us::any_cast(parsedArgs["noFlip"]); bool flipX = false; if (parsedArgs.count("flipX")) flipX = us::any_cast(parsedArgs["flipX"]); bool flipY = false; if (parsedArgs.count("flipY")) flipY = us::any_cast(parsedArgs["flipY"]); bool flipZ = false; if (parsedArgs.count("flipZ")) flipZ = us::any_cast(parsedArgs["flipZ"]); std::cout << "image: " << imageName; std::cout << "outroot: " << outRoot; if (!maskImageName.empty()) std::cout << "mask: " << maskImageName; else std::cout << "no mask image selected"; std::cout << "numpeaks: " << numPeaks; std::cout << "peakthres: " << peakThres; std::cout << "abspeakthres: " << absPeakThres; std::cout << "shOrder: " << shOrder; try { mitk::Image::Pointer image = dynamic_cast(mitk::IOUtil::Load(imageName)[0].GetPointer()); mitk::Image::Pointer mask = dynamic_cast(mitk::IOUtil::Load(maskImageName)[0].GetPointer()); typedef itk::Image ItkUcharImgType; typedef itk::FiniteDiffOdfMaximaExtractionFilter< float, shOrder, 20242 > MaximaExtractionFilterType; typename MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New(); int toolkitConvention = 0; if (parsedArgs.count("shConvention")) { - string convention = us::any_cast(parsedArgs["shConvention"]).c_str(); + std::string convention = us::any_cast(parsedArgs["shConvention"]).c_str(); if ( boost::algorithm::equals(convention, "FSL") ) { toolkitConvention = 1; std::cout << "Using FSL SH-basis"; } else if ( boost::algorithm::equals(convention, "MRtrix") ) { toolkitConvention = 2; std::cout << "Using MRtrix SH-basis"; } else std::cout << "Using MITK SH-basis"; } else std::cout << "Using MITK SH-basis"; ItkUcharImgType::Pointer itkMaskImage = nullptr; if (mask.IsNotNull()) { try{ itkMaskImage = ItkUcharImgType::New(); mitk::CastToItkImage(mask, itkMaskImage); filter->SetMaskImage(itkMaskImage); } catch(...) { } } if (toolkitConvention>0) { std::cout << "Converting coefficient image to MITK format"; typedef itk::ShCoefficientImageImporter< float, shOrder > ConverterType; typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(image); caster->Update(); itk::Image< float, 4 >::Pointer itkImage = caster->GetOutput(); typename ConverterType::Pointer converter = ConverterType::New(); if (noFlip) { converter->SetInputImage(itkImage); } else { std::cout << "Flipping image"; itk::FixedArray flipAxes; flipAxes[0] = true; flipAxes[1] = true; flipAxes[2] = false; flipAxes[3] = false; itk::FlipImageFilter< itk::Image< float, 4 > >::Pointer flipper = itk::FlipImageFilter< itk::Image< float, 4 > >::New(); flipper->SetInput(itkImage); flipper->SetFlipAxes(flipAxes); flipper->Update(); itk::Image< float, 4 >::Pointer flipped = flipper->GetOutput(); itk::Matrix< double,4,4 > m = itkImage->GetDirection(); m[0][0] *= -1; m[1][1] *= -1; flipped->SetDirection(m); itk::Point< float, 4 > o = itkImage->GetOrigin(); o[0] -= (flipped->GetLargestPossibleRegion().GetSize(0)-1); o[1] -= (flipped->GetLargestPossibleRegion().GetSize(1)-1); flipped->SetOrigin(o); converter->SetInputImage(flipped); } std::cout << "Starting conversion"; switch (toolkitConvention) { case 1: converter->SetToolkit(ConverterType::FSL); filter->SetToolkit(MaximaExtractionFilterType::FSL); break; case 2: converter->SetToolkit(ConverterType::MRTRIX); filter->SetToolkit(MaximaExtractionFilterType::MRTRIX); break; default: converter->SetToolkit(ConverterType::FSL); filter->SetToolkit(MaximaExtractionFilterType::FSL); break; } converter->GenerateData(); filter->SetInput(converter->GetCoefficientImage()); } else { try{ typedef mitk::ImageToItk< typename MaximaExtractionFilterType::CoefficientImageType > CasterType; typename CasterType::Pointer caster = CasterType::New(); caster->SetInput(image); caster->Update(); filter->SetInput(caster->GetOutput()); } catch(...) { std::cout << "wrong image type"; return EXIT_FAILURE; } } filter->SetMaxNumPeaks(numPeaks); filter->SetPeakThreshold(peakThres); filter->SetAbsolutePeakThreshold(absPeakThres); filter->SetAngularThreshold(1); filter->SetClusteringThreshold(clusterThres); filter->SetFlipX(flipX); filter->SetFlipY(flipY); filter->SetFlipZ(flipZ); switch (normalization) { case 0: filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM); break; case 1: filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM); break; case 2: filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM); break; } std::cout << "Starting extraction"; filter->Update(); // write direction image { typename MaximaExtractionFilterType::PeakImageType::Pointer itkImg = filter->GetPeakImage(); - string outfilename = outRoot; + std::string outfilename = outRoot; outfilename.append("_PEAKS.nrrd"); typedef itk::ImageFileWriter< typename MaximaExtractionFilterType::PeakImageType > WriterType; typename WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outfilename); writer->SetInput(itkImg); writer->Update(); } // write num directions image { ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); if (itkMaskImage.IsNotNull()) { numDirImage->SetDirection(itkMaskImage->GetDirection()); numDirImage->SetOrigin(itkMaskImage->GetOrigin()); } - string outfilename = outRoot.c_str(); + std::string outfilename = outRoot.c_str(); outfilename.append("_NUM_PEAKS.nrrd"); typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outfilename); writer->SetInput(numDirImage); writer->Update(); } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } /*! \brief Extract maxima in the input spherical harmonics image. */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("image", "i", mitkCommandLineParser::InputFile, "Input image", "sh coefficient image", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "Spherical harmonics order", "spherical harmonics order"); parser.addArgument("outroot", "o", mitkCommandLineParser::OutputDirectory, "Output directory", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask", "mask image"); parser.addArgument("normalization", "n", mitkCommandLineParser::Int, "Normalization", "0=no norm, 1=max norm, 2=single vec norm", 1, true); parser.addArgument("numpeaks", "p", mitkCommandLineParser::Int, "Max. number of peaks", "maximum number of extracted peaks", 2, true); parser.addArgument("peakthres", "r", mitkCommandLineParser::Float, "Peak threshold", "peak threshold relative to largest peak", 0.4, true); parser.addArgument("abspeakthres", "a", mitkCommandLineParser::Float, "Absolute peak threshold", "absolute peak threshold weighted with local GFA value", 0.06, true); - parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "Use specified SH-basis", "use specified SH-basis (MITK, FSL, MRtrix)", string("MITK"), true); + parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "Use specified SH-basis", "use specified SH-basis (MITK, FSL, MRtrix)", std::string("MITK"), true); parser.addArgument("noFlip", "f", mitkCommandLineParser::Bool, "No flip", "do not flip input image to match MITK coordinate convention"); parser.setCategory("Preprocessing Tools"); parser.setTitle("Peak Extraction"); parser.setDescription("Extract maxima in the input spherical harmonics image."); parser.setContributor("MIC"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; int shOrder = -1; if (parsedArgs.count("shOrder")) shOrder = us::any_cast(parsedArgs["shOrder"]); switch (shOrder) { case 4: return StartPeakExtraction<4>(argc, argv); case 6: return StartPeakExtraction<6>(argc, argv); case 8: return StartPeakExtraction<8>(argc, argv); case 10: return StartPeakExtraction<10>(argc, argv); case 12: return StartPeakExtraction<12>(argc, argv); } return EXIT_FAILURE; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/GlobalTractography.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/GlobalTractography.cpp index 42be6a2dbc..f6c7a11c7e 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/GlobalTractography.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/GlobalTractography.cpp @@ -1,240 +1,240 @@ /*=================================================================== 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 "mitkCommandLineParser.h" #include #include #include template typename itk::ShCoefficientImageImporter< float, shOrder >::OdfImageType::Pointer TemplatedConvertShCoeffs(mitk::Image* mitkImg, int toolkit, bool noFlip = false) { typedef itk::ShCoefficientImageImporter< float, shOrder > FilterType; typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImg); caster->Update(); itk::Image< float, 4 >::Pointer itkImage = caster->GetOutput(); typename FilterType::Pointer filter = FilterType::New(); if (noFlip) { filter->SetInputImage(itkImage); } else { std::cout << "Flipping image"; itk::FixedArray flipAxes; flipAxes[0] = true; flipAxes[1] = true; flipAxes[2] = false; flipAxes[3] = false; itk::FlipImageFilter< itk::Image< float, 4 > >::Pointer flipper = itk::FlipImageFilter< itk::Image< float, 4 > >::New(); flipper->SetInput(itkImage); flipper->SetFlipAxes(flipAxes); flipper->Update(); itk::Image< float, 4 >::Pointer flipped = flipper->GetOutput(); itk::Matrix< double,4,4 > m = itkImage->GetDirection(); m[0][0] *= -1; m[1][1] *= -1; flipped->SetDirection(m); itk::Point< float, 4 > o = itkImage->GetOrigin(); o[0] -= (flipped->GetLargestPossibleRegion().GetSize(0)-1); o[1] -= (flipped->GetLargestPossibleRegion().GetSize(1)-1); flipped->SetOrigin(o); filter->SetInputImage(flipped); } switch (toolkit) { case 0: filter->SetToolkit(FilterType::FSL); break; case 1: filter->SetToolkit(FilterType::MRTRIX); break; default: filter->SetToolkit(FilterType::FSL); } filter->GenerateData(); return filter->GetOdfImage(); } /*! \brief Perform global fiber tractography (Gibbs tractography) */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Gibbs Tracking"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription("Perform global fiber tractography (Gibbs tractography)"); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input image (tensor, ODF or FSL/MRTrix SH-coefficient image)", us::Any(), false); parser.addArgument("parameters", "p", mitkCommandLineParser::InputFile, "Parameters:", "parameter file (.gtp)", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask:", "binary mask image"); - parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "SH coefficient:", "sh coefficient convention (FSL, MRtrix)", string("FSL"), true); + parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "SH coefficient:", "sh coefficient convention (FSL, MRtrix)", std::string("FSL"), true); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output:", "output fiber bundle (.fib)", us::Any(), false); parser.addArgument("noFlip", "f", mitkCommandLineParser::Bool, "No flip:", "do not flip input image to match MITK coordinate convention"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; - string inFileName = us::any_cast(parsedArgs["input"]); - string paramFileName = us::any_cast(parsedArgs["parameters"]); - string outFileName = us::any_cast(parsedArgs["outFile"]); + std::string inFileName = us::any_cast(parsedArgs["input"]); + std::string paramFileName = us::any_cast(parsedArgs["parameters"]); + std::string outFileName = us::any_cast(parsedArgs["outFile"]); bool noFlip = false; if (parsedArgs.count("noFlip")) noFlip = us::any_cast(parsedArgs["noFlip"]); try { // instantiate gibbs tracker typedef itk::Vector OdfVectorType; typedef itk::Image ItkOdfImageType; typedef itk::GibbsTrackingFilter GibbsTrackingFilterType; GibbsTrackingFilterType::Pointer gibbsTracker = GibbsTrackingFilterType::New(); // load input image mitk::Image::Pointer mitkImage = dynamic_cast(mitk::IOUtil::Load(inFileName)[0].GetPointer()); // try to cast to Odf image if( boost::algorithm::ends_with(inFileName, ".odf") || boost::algorithm::ends_with(inFileName, ".qbi") ) { std::cout << "Loading Odf image ..."; mitk::OdfImage::Pointer mitkOdfImage = dynamic_cast(mitkImage.GetPointer()); ItkOdfImageType::Pointer itk_odf = ItkOdfImageType::New(); mitk::CastToItkImage(mitkOdfImage, itk_odf); gibbsTracker->SetOdfImage(itk_odf.GetPointer()); } else if( boost::algorithm::ends_with(inFileName, ".dti") ) { std::cout << "Loading tensor image ..."; typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(mitkImage.GetPointer()); ItkTensorImage::Pointer itk_dti = ItkTensorImage::New(); mitk::CastToItkImage(mitkTensorImage, itk_dti); gibbsTracker->SetTensorImage(itk_dti); } else if ( boost::algorithm::ends_with(inFileName, ".nii") ) { std::cout << "Loading sh-coefficient image ..."; int nrCoeffs = mitkImage->GetLargestPossibleRegion().GetSize()[3]; int c=3, d=2-2*nrCoeffs; double D = c*c-4*d; int shOrder = 0; if (D>0) { shOrder = (-c+sqrt(D))/2.0; if (shOrder<0) shOrder = (-c-sqrt(D))/2.0; } else if (D==0) shOrder = -c/2.0; std::cout << "using SH-order " << shOrder; int toolkitConvention = 0; if (parsedArgs.count("shConvention")) { - string convention = us::any_cast(parsedArgs["shConvention"]).c_str(); + std::string convention = us::any_cast(parsedArgs["shConvention"]).c_str(); if ( boost::algorithm::equals(convention, "MRtrix") ) { toolkitConvention = 1; std::cout << "Using MRtrix style sh-coefficient convention"; } else std::cout << "Using FSL style sh-coefficient convention"; } else std::cout << "Using FSL style sh-coefficient convention"; switch (shOrder) { case 4: gibbsTracker->SetOdfImage(TemplatedConvertShCoeffs<4>(mitkImage, toolkitConvention, noFlip)); break; case 6: gibbsTracker->SetOdfImage(TemplatedConvertShCoeffs<6>(mitkImage, toolkitConvention, noFlip)); break; case 8: gibbsTracker->SetOdfImage(TemplatedConvertShCoeffs<8>(mitkImage, toolkitConvention, noFlip)); break; case 10: gibbsTracker->SetOdfImage(TemplatedConvertShCoeffs<10>(mitkImage, toolkitConvention, noFlip)); break; case 12: gibbsTracker->SetOdfImage(TemplatedConvertShCoeffs<12>(mitkImage, toolkitConvention, noFlip)); break; default: std::cout << "SH-order " << shOrder << " not supported"; } } else return EXIT_FAILURE; // global tracking if (parsedArgs.count("mask")) { typedef itk::Image MaskImgType; - mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::Load(us::any_cast(parsedArgs["mask"]))[0].GetPointer()); + mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::Load(us::any_cast(parsedArgs["mask"]))[0].GetPointer()); MaskImgType::Pointer itk_mask = MaskImgType::New(); mitk::CastToItkImage(mitkMaskImage, itk_mask); gibbsTracker->SetMaskImage(itk_mask); } gibbsTracker->SetDuplicateImage(false); gibbsTracker->SetLoadParameterFile( paramFileName ); // gibbsTracker->SetLutPath( "" ); gibbsTracker->Update(); mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(gibbsTracker->GetFiberBundle()); mitkFiberBundle->SetReferenceGeometry(mitkImage->GetGeometry()); mitk::IOUtil::Save(mitkFiberBundle, outFileName ); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/RfTraining.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/RfTraining.cpp index fcb397fc2c..24e8cd4a6d 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/RfTraining.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/RfTraining.cpp @@ -1,232 +1,230 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -using namespace std; - /*! \brief Train random forest classifier for machine learning based streamline tractography */ int main(int argc, char* argv[]) { MITK_INFO << "RfTraining"; mitkCommandLineParser parser; parser.setTitle("Trains Random Forests for Machine Learning Based Tractography"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription("Train random forest classifier for machine learning based streamline tractography"); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("images", "i", mitkCommandLineParser::StringList, "DWIs:", "input diffusion-weighted images", us::Any(), false); parser.addArgument("tractograms", "t", mitkCommandLineParser::StringList, "Tractograms:", "input training tractograms (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("forest", "f", mitkCommandLineParser::OutputFile, "Forest:", "output random forest (HDF5)", us::Any(), false); parser.addArgument("masks", "", mitkCommandLineParser::StringList, "Masks:", "restrict training using a binary mask image", us::Any()); parser.addArgument("wm_masks", "", mitkCommandLineParser::StringList, "WM-Masks:", "if no binary white matter mask is specified, the envelope of the input tractogram is used", us::Any()); parser.addArgument("volume_modification_images", "", mitkCommandLineParser::StringList, "Volume modification images:", "specify a list of float images that modify the fiber density", us::Any()); parser.addArgument("additional_feature_images", "", mitkCommandLineParser::StringList, "Additional feature images:", "specify a list of float images that hold additional features (float)", us::Any()); parser.addArgument("sampling_distance", "", mitkCommandLineParser::Float, "Sampling distance:", "resampling parameter for the input tractogram in mm (determines number of white-matter samples)", us::Any()); parser.addArgument("num_gm_samples", "", mitkCommandLineParser::Int, "Number of gray matter samples per voxel:", "Number of gray matter samples per voxel", us::Any()); parser.addArgument("num_trees", "", mitkCommandLineParser::Int, "Number of trees:", "number of trees", 30); parser.addArgument("max_tree_depth", "", mitkCommandLineParser::Int, "Max. tree depth:", "maximum tree depth", 25); parser.addArgument("sample_fraction", "", mitkCommandLineParser::Float, "Sample fraction:", "fraction of samples used per tree", 0.7); parser.addArgument("use_sh_features", "", mitkCommandLineParser::Bool, "Use SH features:", "use SH features", false); parser.addArgument("max_wm_samples", "", mitkCommandLineParser::Int, "Max. num. WM samples:", "upper limit for the number of WM samples"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; bool shfeatures = false; if (parsedArgs.count("use_sh_features")) shfeatures = us::any_cast(parsedArgs["use_sh_features"]); mitkCommandLineParser::StringContainerType imageFiles = us::any_cast(parsedArgs["images"]); mitkCommandLineParser::StringContainerType wmMaskFiles; if (parsedArgs.count("wm_masks")) wmMaskFiles = us::any_cast(parsedArgs["wm_masks"]); mitkCommandLineParser::StringContainerType volModFiles; if (parsedArgs.count("volume_modification_images")) volModFiles = us::any_cast(parsedArgs["volume_modification_images"]); mitkCommandLineParser::StringContainerType addFeatFiles; if (parsedArgs.count("additional_feature_images")) addFeatFiles = us::any_cast(parsedArgs["additional_feature_images"]); mitkCommandLineParser::StringContainerType maskFiles; if (parsedArgs.count("masks")) maskFiles = us::any_cast(parsedArgs["masks"]); - string forestFile = us::any_cast(parsedArgs["forest"]); + std::string forestFile = us::any_cast(parsedArgs["forest"]); mitkCommandLineParser::StringContainerType tractogramFiles; if (parsedArgs.count("tractograms")) tractogramFiles = us::any_cast(parsedArgs["tractograms"]); int num_trees = 30; if (parsedArgs.count("num_trees")) num_trees = us::any_cast(parsedArgs["num_trees"]); int gm_samples = -1; if (parsedArgs.count("num_gm_samples")) gm_samples = us::any_cast(parsedArgs["num_gm_samples"]); float sampling_distance = -1; if (parsedArgs.count("sampling_distance")) sampling_distance = us::any_cast(parsedArgs["sampling_distance"]); int max_tree_depth = 25; if (parsedArgs.count("max_tree_depth")) max_tree_depth = us::any_cast(parsedArgs["max_tree_depth"]); double sample_fraction = 0.7; if (parsedArgs.count("sample_fraction")) sample_fraction = us::any_cast(parsedArgs["sample_fraction"]); int maxWmSamples = -1; if (parsedArgs.count("max_wm_samples")) maxWmSamples = us::any_cast(parsedArgs["max_wm_samples"]); MITK_INFO << "loading diffusion-weighted images"; std::vector< mitk::Image::Pointer > rawData; mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {}); for (auto imgFile : imageFiles) { mitk::Image::Pointer dwi = dynamic_cast(mitk::IOUtil::LoadImage(imgFile, &functor).GetPointer()); rawData.push_back(dwi); } typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; MITK_INFO << "loading mask images"; std::vector< ItkUcharImgType::Pointer > maskImageVector; for (auto maskFile : maskFiles) { mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(maskFile)[0].GetPointer()); ItkUcharImgType::Pointer mask = ItkUcharImgType::New(); mitk::CastToItkImage(img, mask); maskImageVector.push_back(mask); } MITK_INFO << "loading white matter mask images"; std::vector< ItkUcharImgType::Pointer > wmMaskImageVector; for (auto wmFile : wmMaskFiles) { mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(wmFile)[0].GetPointer()); ItkUcharImgType::Pointer wmmask = ItkUcharImgType::New(); mitk::CastToItkImage(img, wmmask); wmMaskImageVector.push_back(wmmask); } MITK_INFO << "loading tractograms"; std::vector< mitk::FiberBundle::Pointer > tractograms; for (auto tractFile : tractogramFiles) { mitk::FiberBundle::Pointer fib = dynamic_cast(mitk::IOUtil::Load(tractFile).at(0).GetPointer()); tractograms.push_back(fib); } MITK_INFO << "loading white volume modification images"; std::vector< ItkFloatImgType::Pointer > volumeModImages; for (auto file : volModFiles) { mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(file)[0].GetPointer()); ItkFloatImgType::Pointer itkimg = ItkFloatImgType::New(); mitk::CastToItkImage(img, itkimg); volumeModImages.push_back(itkimg); } MITK_INFO << "loading additional feature images"; std::vector< std::vector< ItkFloatImgType::Pointer > > addFeatImages; for (std::size_t i=0; i()); int c = 0; for (auto file : addFeatFiles) { mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(file)[0].GetPointer()); ItkFloatImgType::Pointer itkimg = ItkFloatImgType::New(); mitk::CastToItkImage(img, itkimg); addFeatImages.at(c%addFeatImages.size()).push_back(itkimg); c++; } mitk::TractographyForest::Pointer forest = nullptr; if (shfeatures) { mitk::TrackingHandlerRandomForest<6,28> forestHandler; forestHandler.SetDwis(rawData); forestHandler.SetMaskImages(maskImageVector); forestHandler.SetWhiteMatterImages(wmMaskImageVector); forestHandler.SetFiberVolumeModImages(volumeModImages); forestHandler.SetAdditionalFeatureImages(addFeatImages); forestHandler.SetTractograms(tractograms); forestHandler.SetNumTrees(num_trees); forestHandler.SetMaxTreeDepth(max_tree_depth); forestHandler.SetGrayMatterSamplesPerVoxel(gm_samples); forestHandler.SetSampleFraction(sample_fraction); forestHandler.SetFiberSamplingStep(sampling_distance); forestHandler.SetMaxNumWmSamples(maxWmSamples); forestHandler.StartTraining(); forest = forestHandler.GetForest(); } else { mitk::TrackingHandlerRandomForest<6,100> forestHandler; forestHandler.SetDwis(rawData); forestHandler.SetMaskImages(maskImageVector); forestHandler.SetWhiteMatterImages(wmMaskImageVector); forestHandler.SetFiberVolumeModImages(volumeModImages); forestHandler.SetAdditionalFeatureImages(addFeatImages); forestHandler.SetTractograms(tractograms); forestHandler.SetNumTrees(num_trees); forestHandler.SetMaxTreeDepth(max_tree_depth); forestHandler.SetGrayMatterSamplesPerVoxel(gm_samples); forestHandler.SetSampleFraction(sample_fraction); forestHandler.SetFiberSamplingStep(sampling_distance); forestHandler.SetMaxNumWmSamples(maxWmSamples); forestHandler.StartTraining(); forest = forestHandler.GetForest(); } mitk::IOUtil::Save(forest, forestFile); return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/StreamlineTractography.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/StreamlineTractography.cpp index 9829d3502d..34c2acea79 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/StreamlineTractography.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/Tractography/StreamlineTractography.cpp @@ -1,471 +1,469 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -using namespace std; - const int numOdfSamples = 200; typedef itk::Image< itk::Vector< float, numOdfSamples > , 3 > SampledShImageType; /*! \brief */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Streamline Tractography"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription("Perform streamline tractography"); parser.setContributor("MIC"); // parameters fo all methods parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::StringList, "Input:", "input image (multiple possible for 'DetTensor' algorithm)", us::Any(), false); parser.addArgument("algorithm", "a", mitkCommandLineParser::String, "Algorithm:", "which algorithm to use (Peaks, DetTensor, ProbTensor, DetODF, ProbODF, DetRF, ProbRF)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output fiberbundle/probability map", us::Any(), false); parser.addArgument("stop_mask", "", mitkCommandLineParser::String, "Stop image:", "streamlines entering the binary mask will stop immediately", us::Any()); parser.addArgument("tracking_mask", "", mitkCommandLineParser::String, "Mask image:", "restrict tractography with a binary mask image", us::Any()); parser.addArgument("seed_mask", "", mitkCommandLineParser::String, "Seed image:", "binary mask image defining seed voxels", us::Any()); parser.addArgument("tissue_image", "", mitkCommandLineParser::String, "Tissue type image:", "image with tissue type labels (WM=3, GM=1)", us::Any()); parser.addArgument("sharpen_odfs", "", mitkCommandLineParser::Bool, "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 for CSD fODFs, since they are narurally much sharper."); parser.addArgument("cutoff", "", mitkCommandLineParser::Float, "Cutoff:", "set the FA, GFA or Peak amplitude cutoff for terminating tracks", 0.1); parser.addArgument("odf_cutoff", "", mitkCommandLineParser::Float, "ODF Cutoff:", "additional threshold on the ODF magnitude. this is useful in case of CSD fODF tractography.", 0.1); parser.addArgument("step_size", "", mitkCommandLineParser::Float, "Step size:", "step size (in voxels)", 0.5); parser.addArgument("angular_threshold", "", mitkCommandLineParser::Float, "Angular threshold:", "angular threshold between two successive steps, (default: 90° * step_size)"); parser.addArgument("min_tract_length", "", mitkCommandLineParser::Float, "Min. tract length:", "minimum fiber length (in mm)", 20); parser.addArgument("seeds", "", mitkCommandLineParser::Int, "Seeds per voxel:", "number of seed points per voxel", 1); parser.addArgument("seed_gm", "", mitkCommandLineParser::Bool, "Seed only GM:", "Seed only in gray matter (requires tissue type image --tissue_image)"); parser.addArgument("control_gm_endings", "", mitkCommandLineParser::Bool, "Control GM endings:", "Seed perpendicular to gray matter and enforce endings inside of the gray matter (requires tissue type image --tissue_image)"); parser.addArgument("max_tracts", "", mitkCommandLineParser::Int, "Max. number of tracts:", "tractography is stopped if the reconstructed number of tracts is exceeded.", -1); parser.addArgument("num_samples", "", mitkCommandLineParser::Int, "Num. neighborhood samples:", "number of neighborhood samples that are use to determine the next progression direction", 0); parser.addArgument("sampling_distance", "", mitkCommandLineParser::Float, "Sampling distance:", "distance of neighborhood sampling points (in voxels)", 0.25); parser.addArgument("use_stop_votes", "", mitkCommandLineParser::Bool, "Use stop votes:", "use stop votes"); parser.addArgument("use_only_forward_samples", "", mitkCommandLineParser::Bool, "Use only forward samples:", "use only forward samples"); parser.addArgument("output_prob_map", "", mitkCommandLineParser::Bool, "Output probability map:", "output probability map instead of tractogram"); parser.addArgument("no_interpolation", "", mitkCommandLineParser::Bool, "Don't interpolate:", "don't interpolate image values"); parser.addArgument("flip_x", "", mitkCommandLineParser::Bool, "Flip X:", "multiply x-coordinate of direction proposal by -1"); parser.addArgument("flip_y", "", mitkCommandLineParser::Bool, "Flip Y:", "multiply y-coordinate of direction proposal by -1"); parser.addArgument("flip_z", "", mitkCommandLineParser::Bool, "Flip Z:", "multiply z-coordinate of direction proposal by -1"); //parser.addArgument("apply_image_rotation", "", mitkCommandLineParser::Bool, "Apply image rotation:", "applies image rotation to image peaks (only for 'Peaks' algorithm). This is necessary in some cases, e.g. if the peaks were obtained with MRtrix."); parser.addArgument("compress", "", mitkCommandLineParser::Float, "Compress:", "Compress output fibers using the given error threshold (in mm)"); parser.addArgument("additional_images", "", mitkCommandLineParser::StringList, "Additional images:", "specify a list of float images that hold additional information (FA, GFA, additional Features)", us::Any()); // parameters for random forest based tractography parser.addArgument("forest", "", mitkCommandLineParser::String, "Forest:", "input random forest (HDF5 file)", us::Any()); parser.addArgument("use_sh_features", "", mitkCommandLineParser::Bool, "Use SH features:", "use SH features"); // parameters for tensor tractography parser.addArgument("tend_f", "", mitkCommandLineParser::Float, "Weight f", "Weighting factor between first eigenvector (f=1 equals FACT tracking) and input vector dependent direction (f=0).", 1.0); parser.addArgument("tend_g", "", mitkCommandLineParser::Float, "Weight g", "Weighting factor between input vector (g=0) and tensor deflection (g=1 equals TEND tracking)", 0.0); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType input_files = us::any_cast(parsedArgs["input"]); - string outFile = us::any_cast(parsedArgs["out"]); - string algorithm = us::any_cast(parsedArgs["algorithm"]); + std::string outFile = us::any_cast(parsedArgs["out"]); + std::string algorithm = us::any_cast(parsedArgs["algorithm"]); bool sharpen_odfs = false; if (parsedArgs.count("sharpen_odfs")) sharpen_odfs = us::any_cast(parsedArgs["sharpen_odfs"]); bool interpolate = true; if (parsedArgs.count("no_interpolation")) interpolate = !us::any_cast(parsedArgs["no_interpolation"]); bool use_sh_features = false; if (parsedArgs.count("use_sh_features")) use_sh_features = us::any_cast(parsedArgs["use_sh_features"]); bool seed_gm = false; if (parsedArgs.count("seed_gm")) seed_gm = us::any_cast(parsedArgs["seed_gm"]); bool control_gm_endings = false; if (parsedArgs.count("control_gm_endings")) control_gm_endings = us::any_cast(parsedArgs["control_gm_endings"]); bool use_stop_votes = false; if (parsedArgs.count("use_stop_votes")) use_stop_votes = us::any_cast(parsedArgs["use_stop_votes"]); bool use_only_forward_samples = false; if (parsedArgs.count("use_only_forward_samples")) use_only_forward_samples = us::any_cast(parsedArgs["use_only_forward_samples"]); bool output_prob_map = false; if (parsedArgs.count("output_prob_map")) output_prob_map = us::any_cast(parsedArgs["output_prob_map"]); bool flip_x = false; if (parsedArgs.count("flip_x")) flip_x = us::any_cast(parsedArgs["flip_x"]); bool flip_y = false; if (parsedArgs.count("flip_y")) flip_y = us::any_cast(parsedArgs["flip_y"]); bool flip_z = false; if (parsedArgs.count("flip_z")) flip_z = us::any_cast(parsedArgs["flip_z"]); bool apply_image_rotation = false; if (parsedArgs.count("apply_image_rotation")) apply_image_rotation = us::any_cast(parsedArgs["apply_image_rotation"]); float compress = -1; if (parsedArgs.count("compress")) compress = us::any_cast(parsedArgs["compress"]); float min_tract_length = 20; if (parsedArgs.count("min_tract_length")) min_tract_length = us::any_cast(parsedArgs["min_tract_length"]); - string forestFile; + std::string forestFile; if (parsedArgs.count("forest")) - forestFile = us::any_cast(parsedArgs["forest"]); + forestFile = us::any_cast(parsedArgs["forest"]); - string maskFile = ""; + std::string maskFile = ""; if (parsedArgs.count("tracking_mask")) - maskFile = us::any_cast(parsedArgs["tracking_mask"]); + maskFile = us::any_cast(parsedArgs["tracking_mask"]); - string seedFile = ""; + std::string seedFile = ""; if (parsedArgs.count("seed_mask")) - seedFile = us::any_cast(parsedArgs["seed_mask"]); + seedFile = us::any_cast(parsedArgs["seed_mask"]); - string stopFile = ""; + std::string stopFile = ""; if (parsedArgs.count("stop_mask")) - stopFile = us::any_cast(parsedArgs["stop_mask"]); + stopFile = us::any_cast(parsedArgs["stop_mask"]); - string tissueFile = ""; + std::string tissueFile = ""; if (parsedArgs.count("tissue_image")) - tissueFile = us::any_cast(parsedArgs["tissue_image"]); + tissueFile = us::any_cast(parsedArgs["tissue_image"]); float cutoff = 0.1; if (parsedArgs.count("cutoff")) cutoff = us::any_cast(parsedArgs["cutoff"]); float odf_cutoff = 0.1; if (parsedArgs.count("odf_cutoff")) odf_cutoff = us::any_cast(parsedArgs["odf_cutoff"]); float stepsize = -1; if (parsedArgs.count("step_size")) stepsize = us::any_cast(parsedArgs["step_size"]); float sampling_distance = -1; if (parsedArgs.count("sampling_distance")) sampling_distance = us::any_cast(parsedArgs["sampling_distance"]); int num_samples = 0; if (parsedArgs.count("num_samples")) num_samples = us::any_cast(parsedArgs["num_samples"]); int seeds = 1; if (parsedArgs.count("seeds")) seeds = us::any_cast(parsedArgs["seeds"]); float tend_f = 1; if (parsedArgs.count("tend_f")) tend_f = us::any_cast(parsedArgs["tend_f"]); float tend_g = 0; if (parsedArgs.count("tend_g")) tend_g = us::any_cast(parsedArgs["tend_g"]); float angular_threshold = -1; if (parsedArgs.count("angular_threshold")) angular_threshold = us::any_cast(parsedArgs["angular_threshold"]); unsigned int max_tracts = -1; if (parsedArgs.count("max_tracts")) max_tracts = us::any_cast(parsedArgs["max_tracts"]); // LOAD DATASETS mitkCommandLineParser::StringContainerType addFiles; if (parsedArgs.count("additional_images")) addFiles = us::any_cast(parsedArgs["additional_images"]); typedef itk::Image ItkUcharImgType; MITK_INFO << "loading input"; std::vector< mitk::Image::Pointer > input_images; for (unsigned int i=0; i(mitk::IOUtil::Load(input_files.at(i))[0].GetPointer()); input_images.push_back(mitkImage); } ItkUcharImgType::Pointer mask; if (!maskFile.empty()) { MITK_INFO << "loading mask image"; mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(maskFile)[0].GetPointer()); mask = ItkUcharImgType::New(); mitk::CastToItkImage(img, mask); } ItkUcharImgType::Pointer seed; if (!seedFile.empty()) { MITK_INFO << "loading seed image"; mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(seedFile)[0].GetPointer()); seed = ItkUcharImgType::New(); mitk::CastToItkImage(img, seed); } ItkUcharImgType::Pointer stop; if (!stopFile.empty()) { MITK_INFO << "loading stop image"; mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(stopFile)[0].GetPointer()); stop = ItkUcharImgType::New(); mitk::CastToItkImage(img, stop); } ItkUcharImgType::Pointer tissue; if (!tissueFile.empty()) { MITK_INFO << "loading tissue image"; mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(tissueFile)[0].GetPointer()); tissue = ItkUcharImgType::New(); mitk::CastToItkImage(img, tissue); } MITK_INFO << "loading additional images"; typedef itk::Image ItkFloatImgType; std::vector< std::vector< ItkFloatImgType::Pointer > > addImages; addImages.push_back(std::vector< ItkFloatImgType::Pointer >()); for (auto file : addFiles) { mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(file)[0].GetPointer()); ItkFloatImgType::Pointer itkimg = ItkFloatImgType::New(); mitk::CastToItkImage(img, itkimg); addImages.at(0).push_back(itkimg); } // ////////////////////////////////////////////////////////////////// // omp_set_num_threads(1); if (algorithm == "ProbTensor") { typedef mitk::ImageToItk< mitk::TrackingHandlerTensor::ItkTensorImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(input_images.at(0)); caster->Update(); mitk::TrackingHandlerTensor::ItkTensorImageType::Pointer itkTensorImg = caster->GetOutput(); typedef itk::TensorImageToOdfImageFilter< float, float > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkTensorImg ); filter->Update(); mitk::Image::Pointer image = mitk::Image::New(); FilterType::OutputImageType::Pointer outimg = filter->GetOutput(); image->InitializeByItk( outimg.GetPointer() ); image->SetVolume( outimg->GetBufferPointer() ); input_images.clear(); input_images.push_back(image); algorithm = "ProbODF"; sharpen_odfs = true; odf_cutoff = 0; } typedef itk::StreamlineTrackingFilter TrackerType; TrackerType::Pointer tracker = TrackerType::New(); mitk::TrackingDataHandler* handler; if (algorithm == "DetRF" || algorithm == "ProbRF") { mitk::TractographyForest::Pointer forest = dynamic_cast(mitk::IOUtil::Load(forestFile)[0].GetPointer()); if (forest.IsNull()) mitkThrow() << "Forest file " << forestFile << " could not be read."; if (use_sh_features) { handler = new mitk::TrackingHandlerRandomForest<6,28>(); dynamic_cast*>(handler)->SetForest(forest); dynamic_cast*>(handler)->AddDwi(input_images.at(0)); dynamic_cast*>(handler)->SetAdditionalFeatureImages(addImages); } else { handler = new mitk::TrackingHandlerRandomForest<6,100>(); dynamic_cast*>(handler)->SetForest(forest); dynamic_cast*>(handler)->AddDwi(input_images.at(0)); dynamic_cast*>(handler)->SetAdditionalFeatureImages(addImages); } if (algorithm == "ProbRF") handler->SetMode(mitk::TrackingDataHandler::MODE::PROBABILISTIC); } else if (algorithm == "Peaks") { handler = new mitk::TrackingHandlerPeaks(); typedef mitk::ImageToItk< mitk::TrackingHandlerPeaks::PeakImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(input_images.at(0)); caster->Update(); mitk::TrackingHandlerPeaks::PeakImgType::Pointer itkImg = caster->GetOutput(); dynamic_cast(handler)->SetPeakImage(itkImg); dynamic_cast(handler)->SetApplyDirectionMatrix(apply_image_rotation); dynamic_cast(handler)->SetPeakThreshold(cutoff); } else if (algorithm == "DetTensor") { handler = new mitk::TrackingHandlerTensor(); for (auto input_image : input_images) { typedef mitk::ImageToItk< mitk::TrackingHandlerTensor::ItkTensorImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(input_image); caster->Update(); mitk::TrackingHandlerTensor::ItkTensorImageType::ConstPointer itkImg = caster->GetOutput(); dynamic_cast(handler)->AddTensorImage(itkImg); } dynamic_cast(handler)->SetFaThreshold(cutoff); dynamic_cast(handler)->SetF(tend_f); dynamic_cast(handler)->SetG(tend_g); if (addImages.at(0).size()>0) dynamic_cast(handler)->SetFaImage(addImages.at(0).at(0)); } else if (algorithm == "DetODF" || algorithm == "ProbODF") { handler = new mitk::TrackingHandlerOdf(); typedef mitk::ImageToItk< mitk::TrackingHandlerOdf::ItkOdfImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(input_images.at(0)); caster->Update(); mitk::TrackingHandlerOdf::ItkOdfImageType::Pointer itkImg = caster->GetOutput(); dynamic_cast(handler)->SetOdfImage(itkImg); dynamic_cast(handler)->SetGfaThreshold(cutoff); dynamic_cast(handler)->SetOdfThreshold(odf_cutoff); dynamic_cast(handler)->SetSharpenOdfs(sharpen_odfs); if (algorithm == "ProbODF") dynamic_cast(handler)->SetMode(mitk::TrackingHandlerOdf::MODE::PROBABILISTIC); if (addImages.at(0).size()>0) dynamic_cast(handler)->SetGfaImage(addImages.at(0).at(0)); } else { MITK_INFO << "Unknown tractography algorithm (" + algorithm+"). Known types are Peaks, DetTensor, ProbTensor, DetODF, ProbODF, DetRF, ProbRF."; return EXIT_FAILURE; } handler->SetInterpolate(interpolate); handler->SetFlipX(flip_x); handler->SetFlipY(flip_y); handler->SetFlipZ(flip_z); MITK_INFO << "Tractography algorithm: " << algorithm; tracker->SetNumberOfSamples(num_samples); tracker->SetAngularThreshold(angular_threshold); tracker->SetMaskImage(mask); tracker->SetSeedImage(seed); tracker->SetStoppingRegions(stop); tracker->SetSeedsPerVoxel(seeds); tracker->SetStepSize(stepsize); tracker->SetSamplingDistance(sampling_distance); tracker->SetUseStopVotes(use_stop_votes); tracker->SetOnlyForwardSamples(use_only_forward_samples); tracker->SetAposterioriCurvCheck(false); tracker->SetTissueImage(tissue); tracker->SetSeedOnlyGm(seed_gm); tracker->SetControlGmEndings(control_gm_endings); tracker->SetMaxNumTracts(max_tracts); tracker->SetTrackingHandler(handler); tracker->SetUseOutputProbabilityMap(output_prob_map); tracker->SetMinTractLength(min_tract_length); tracker->Update(); std::string ext = itksys::SystemTools::GetFilenameExtension(outFile); if (!output_prob_map) { vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData(); mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly); if (compress > 0) outFib->Compress(compress); if (ext != ".fib" && ext != ".trk" && ext != ".tck") outFile += ".fib"; mitk::IOUtil::Save(outFib, outFile); } else { TrackerType::ItkDoubleImgType::Pointer outImg = tracker->GetOutputProbabilityMap(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); if (ext != ".nii" && ext != ".nii.gz" && ext != ".nrrd") outFile += ".nii.gz"; mitk::IOUtil::Save(img, outFile); } delete handler; return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/AnchorBasedScoring.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/AnchorBasedScoring.cpp new file mode 100755 index 0000000000..fb08c52ef5 --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/AnchorBasedScoring.cpp @@ -0,0 +1,443 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef itksys::SystemTools ist; +typedef itk::Point PointType4; +typedef itk::Image< float, 4 > PeakImgType; +typedef itk::Image< unsigned char, 3 > ItkUcharImageType; + +std::vector< std::string > get_file_list(const std::string& path, std::vector< std::string > extensions={".fib", ".trk"}) +{ + std::vector< std::string > file_list; + itk::Directory::Pointer dir = itk::Directory::New(); + + if (dir->Load(path.c_str())) + { + int n = dir->GetNumberOfFiles(); + for (int r = 0; r < n; r++) + { + const char *filename = dir->GetFile(r); + std::string ext = ist::GetFilenameExtension(filename); + for (auto e : extensions) + { + if (ext==e) + { + file_list.push_back(path + '/' + filename); + break; + } + } + } + } + return file_list; +} + +std::vector< mitk::FiberBundle::Pointer > CombineTractograms(std::vector< mitk::FiberBundle::Pointer > reference, std::vector< mitk::FiberBundle::Pointer > candidates, int skip=-1) +{ + std::vector< mitk::FiberBundle::Pointer > fib; + for (auto f : reference) + fib.push_back(f); + + int c = 0; + for (auto f : candidates) + { + if (c!=skip) + fib.push_back(f); + ++c; + } + + return fib; +} + +/*! +\brief Fits the tractogram to the input peak image by assigning a weight to each fiber (similar to https://doi.org/10.1016/j.neuroimage.2015.06.092). +*/ +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + + parser.setTitle("Anchor Based Scoring"); + parser.setCategory("Fiber Tracking Evaluation"); + parser.setDescription(""); + parser.setContributor("MIC"); + + parser.setArgumentPrefix("--", "-"); + parser.addArgument("", "i1", mitkCommandLineParser::InputFile, "Anchor tractogram:", "anchor tracts in one tractogram file", us::Any(), false); + parser.addArgument("", "i2", mitkCommandLineParser::InputFile, "Input peaks:", "input peak image", us::Any(), false); + parser.addArgument("", "i3", mitkCommandLineParser::InputFile, "Candidate folder:", "folder containing all candidate tracts (separate files)", us::Any(), false); + parser.addArgument("", "o", mitkCommandLineParser::OutputDirectory, "Output folder:", "output folder", us::Any(), false); + + parser.addArgument("reference_mask_folder", "", mitkCommandLineParser::String, "Reference Mask Folder:", "reference tract masks for accuracy evaluation"); + parser.addArgument("mask", "", mitkCommandLineParser::InputFile, "Mask image:", "scoring is only performed inside the mask image"); + parser.addArgument("greedy_add", "", mitkCommandLineParser::Bool, "Greedy:", "if enabled, the candidate tracts are not jointly fitted to the residual image but one after the other employing a greedy scheme", false); + parser.addArgument("lambda", "", mitkCommandLineParser::Float, "Lambda:", "modifier for regularization", 0.1); + parser.addArgument("dont_filter_outliers", "", mitkCommandLineParser::Bool, "Don't filter outliers:", "don't perform second optimization run with an upper weight bound based on the first weight estimation (95% quantile)", false); + + std::map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0) + return EXIT_FAILURE; + + std::string anchors_file = us::any_cast(parsedArgs["i1"]); + std::string peak_file_name = us::any_cast(parsedArgs["i2"]); + std::string candidate_folder = us::any_cast(parsedArgs["i3"]); + std::string out_folder = us::any_cast(parsedArgs["o"]); + + bool greedy_add = false; + if (parsedArgs.count("greedy_add")) + greedy_add = us::any_cast(parsedArgs["greedy_add"]); + + float lambda = 0.1; + if (parsedArgs.count("lambda")) + lambda = us::any_cast(parsedArgs["lambda"]); + + bool filter_outliers = true; + if (parsedArgs.count("dont_filter_outliers")) + filter_outliers = !us::any_cast(parsedArgs["dont_filter_outliers"]); + + std::string mask_file = ""; + if (parsedArgs.count("mask")) + mask_file = us::any_cast(parsedArgs["mask"]); + + std::string reference_mask_folder = ""; + if (parsedArgs.count("reference_mask_folder")) + reference_mask_folder = us::any_cast(parsedArgs["reference_mask_folder"]); + + try + { + itk::TimeProbe clock; + clock.Start(); + + MITK_INFO << "Creating directory structure"; + if (ist::PathExists(out_folder)) + ist::RemoveADirectory(out_folder); + ist::MakeDirectory(out_folder); + + MITK_INFO << "Loading data"; + + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + + ofstream logfile; + logfile.open (out_folder + "log.txt"); + + itk::ImageFileWriter< PeakImgType >::Pointer peak_image_writer = itk::ImageFileWriter< PeakImgType >::New(); + mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Peak Image", "Fiberbundles"}, {}); + mitk::Image::Pointer inputImage = dynamic_cast(mitk::IOUtil::Load(peak_file_name, &functor)[0].GetPointer()); + + float minSpacing = 1; + if(inputImage->GetGeometry()->GetSpacing()[0]GetGeometry()->GetSpacing()[1] && inputImage->GetGeometry()->GetSpacing()[0]GetGeometry()->GetSpacing()[2]) + minSpacing = inputImage->GetGeometry()->GetSpacing()[0]; + else if (inputImage->GetGeometry()->GetSpacing()[1] < inputImage->GetGeometry()->GetSpacing()[2]) + minSpacing = inputImage->GetGeometry()->GetSpacing()[1]; + else + minSpacing = inputImage->GetGeometry()->GetSpacing()[2]; + + // Load mask file. Fit is only performed inside the mask + itk::FitFibersToImageFilter::UcharImgType::Pointer mask = nullptr; + if (mask_file.compare("")!=0) + { + mitk::Image::Pointer mitk_mask = dynamic_cast(mitk::IOUtil::Load(mask_file)[0].GetPointer()); + mitk::CastToItkImage(mitk_mask, mask); + } + + // Load masks covering the true positives for evaluation purposes + std::vector< std::string > reference_mask_filenames; + std::vector< itk::FitFibersToImageFilter::UcharImgType::Pointer > reference_masks; + if (reference_mask_folder.compare("")!=0) + { + reference_mask_filenames = get_file_list(reference_mask_folder, {".nii", ".nii.gz", ".nrrd"}); + for (auto filename : reference_mask_filenames) + { + itk::FitFibersToImageFilter::UcharImgType::Pointer ref_mask = nullptr; + mitk::Image::Pointer ref_mitk_mask = dynamic_cast(mitk::IOUtil::Load(filename)[0].GetPointer()); + mitk::CastToItkImage(ref_mitk_mask, ref_mask); + reference_masks.push_back(ref_mask); + } + } + + // Load peak image + typedef mitk::ImageToItk< PeakImgType > CasterType; + CasterType::Pointer caster = CasterType::New(); + caster->SetInput(inputImage); + caster->Update(); + PeakImgType::Pointer peak_image = caster->GetOutput(); + + // Load all candidate tracts + std::vector< mitk::FiberBundle::Pointer > input_candidates; + std::vector< std::string > candidate_tract_files = get_file_list(candidate_folder); + for (std::string f : candidate_tract_files) + { + mitk::FiberBundle::Pointer fib = dynamic_cast(mitk::IOUtil::Load(f)[0].GetPointer()); + if (fib.IsNull()) + continue; + if (fib->GetNumFibers()<=0) + return 0; + fib->ResampleLinear(minSpacing/10.0); + input_candidates.push_back(fib); + } + std::cout.rdbuf (old); // <-- restore + + double rmse = 0.0; + int iteration = 0; + std::string name = "NOANCHOR"; + // Load reference tractogram consisting of all known tracts + std::vector< mitk::FiberBundle::Pointer > input_reference; + mitk::FiberBundle::Pointer anchor_tractogram = dynamic_cast(mitk::IOUtil::Load(anchors_file)[0].GetPointer()); + if ( !(anchor_tractogram.IsNull() || anchor_tractogram->GetNumFibers()==0) ) + { + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + anchor_tractogram->ResampleLinear(minSpacing/10.0); + std::cout.rdbuf (old); // <-- restore + input_reference.push_back(anchor_tractogram); + + // Fit known tracts to peak image to obtain underexplained image + MITK_INFO << "Fit anchor tracts"; + itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New(); + fitter->SetTractograms(input_reference); + fitter->SetLambda(lambda); + fitter->SetFilterOutliers(filter_outliers); + fitter->SetPeakImage(peak_image); + fitter->SetVerbose(true); + fitter->SetResampleFibers(false); + fitter->SetMaskImage(mask); + fitter->Update(); + rmse = fitter->GetRMSE(); + + name = ist::GetFilenameWithoutExtension(anchors_file); + mitk::FiberBundle::Pointer anchor_tracts = fitter->GetTractograms().at(0); + anchor_tracts->SetFiberColors(255,255,255); + mitk::IOUtil::Save(anchor_tracts, out_folder + "0_" + name + ".fib"); + + peak_image = fitter->GetUnderexplainedImage(); + peak_image_writer->SetInput(peak_image); + peak_image_writer->SetFileName(out_folder + boost::lexical_cast(iteration) + "_" + name + ".nrrd"); + peak_image_writer->Update(); + } + + if (!greedy_add) + { + MITK_INFO << "Fit candidate tracts"; + itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New(); + fitter->SetLambda(lambda); + fitter->SetFilterOutliers(filter_outliers); + fitter->SetVerbose(true); + fitter->SetPeakImage(peak_image); + fitter->SetResampleFibers(false); + fitter->SetMaskImage(mask); + fitter->SetTractograms(input_candidates); + fitter->Update(); + vnl_vector rms_diff = fitter->GetRmsDiffPerBundle(); + + vnl_vector log_rms_diff = rms_diff-rms_diff.min_value() + 1; + log_rms_diff = log_rms_diff.apply(std::log); + log_rms_diff /= log_rms_diff.max_value(); + int c = 0; + for (auto fib : input_candidates) + { + fib->SetFiberWeights( log_rms_diff[c] ); + fib->ColorFibersByFiberWeights(false, true); + + std::string bundle_name = ist::GetFilenameWithoutExtension(candidate_tract_files.at(c)); + + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + mitk::IOUtil::Save(fib, out_folder + boost::lexical_cast((int)(10000*rms_diff[c])) + "_" + bundle_name + ".fib"); + + float best_overlap = 0; + int best_overlap_index = -1; + int m_idx = 0; + for (auto ref_mask : reference_masks) + { + float overlap = fib->GetOverlap(ref_mask, false); + if (overlap>best_overlap) + { + best_overlap = overlap; + best_overlap_index = m_idx; + } + ++m_idx; + } + + unsigned int num_voxels = 0; + { + itk::TractDensityImageFilter< ItkUcharImageType >::Pointer masks_filter = itk::TractDensityImageFilter< ItkUcharImageType >::New(); + masks_filter->SetInputImage(mask); + masks_filter->SetBinaryOutput(true); + masks_filter->SetFiberBundle(fib); + masks_filter->SetUseImageGeometry(true); + masks_filter->Update(); + num_voxels = masks_filter->GetNumCoveredVoxels(); + } + + std::cout.rdbuf (old); // <-- restore + + logfile << "RMS_DIFF: " << setprecision(5) << rms_diff[c] << " " << bundle_name << " " << num_voxels << "\n"; + if (best_overlap_index>=0) + logfile << "Best_overlap: " << setprecision(5) << best_overlap << " " << ist::GetFilenameWithoutExtension(reference_mask_filenames.at(best_overlap_index)) << "\n"; + else + logfile << "No_overlap\n"; + + ++c; + } + + mitk::FiberBundle::Pointer out_fib = mitk::FiberBundle::New(); + out_fib = out_fib->AddBundles(input_candidates); + out_fib->ColorFibersByFiberWeights(false, true); + mitk::IOUtil::Save(out_fib, out_folder + "AllCandidates.fib"); + } + else + { + MITK_INFO << "RMSE: " << setprecision(5) << rmse; + // fitter->SetPeakImage(peak_image); + + // Iteratively add candidate bundles in a greedy manner + while (!input_candidates.empty()) + { + double next_rmse = rmse; + double num_peaks = 0; + mitk::FiberBundle::Pointer best_candidate = nullptr; + PeakImgType::Pointer best_candidate_peak_image = nullptr; + + for (int i=0; i<(int)input_candidates.size(); ++i) + { + // WHY NECESSARY AGAIN?? + itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New(); + fitter->SetLambda(lambda); + fitter->SetFilterOutliers(filter_outliers); + fitter->SetVerbose(false); + fitter->SetPeakImage(peak_image); + fitter->SetResampleFibers(false); + fitter->SetMaskImage(mask); + // ****************************** + fitter->SetTractograms({input_candidates.at(i)}); + + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + fitter->Update(); + std::cout.rdbuf (old); // <-- restore + + double candidate_rmse = fitter->GetRMSE(); + + if (candidate_rmseGetNumCoveredDirections(); + best_candidate = fitter->GetTractograms().at(0); + best_candidate_peak_image = fitter->GetUnderexplainedImage(); + } + } + + if (best_candidate.IsNull()) + break; + + // fitter->SetPeakImage(peak_image); + peak_image = best_candidate_peak_image; + + int i=0; + std::vector< mitk::FiberBundle::Pointer > remaining_candidates; + std::vector< std::string > remaining_candidate_files; + for (auto fib : input_candidates) + { + if (fib!=best_candidate) + { + remaining_candidates.push_back(fib); + remaining_candidate_files.push_back(candidate_tract_files.at(i)); + } + else + name = ist::GetFilenameWithoutExtension(candidate_tract_files.at(i)); + ++i; + } + input_candidates = remaining_candidates; + candidate_tract_files = remaining_candidate_files; + + iteration++; + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + // Save winning candidate + mitk::IOUtil::Save(best_candidate, out_folder + boost::lexical_cast(iteration) + "_" + name + ".fib"); + peak_image_writer->SetInput(peak_image); + peak_image_writer->SetFileName(out_folder + boost::lexical_cast(iteration) + "_" + name + ".nrrd"); + peak_image_writer->Update(); + + // Calculate best overlap with reference masks for evaluation purposes + float best_overlap = 0; + int best_overlap_index = -1; + i = 0; + for (auto ref_mask : reference_masks) + { + float overlap = best_candidate->GetOverlap(ref_mask, false); + if (overlap>best_overlap) + { + best_overlap = overlap; + best_overlap_index = i; + } + ++i; + } + std::cout.rdbuf (old); // <-- restore + + logfile << "RMSE: " << setprecision(5) << rmse << " " << name << " " << num_peaks << "\n"; + if (best_overlap_index>=0) + logfile << "Best_overlap: " << setprecision(5) << best_overlap << " " << ist::GetFilenameWithoutExtension(reference_mask_filenames.at(best_overlap_index)) << "\n"; + else + logfile << "No_overlap\n"; + } + } + + clock.Stop(); + int h = clock.GetTotal()/3600; + int m = ((int)clock.GetTotal()%3600)/60; + int s = (int)clock.GetTotal()%60; + MITK_INFO << "Plausibility estimation took " << h << "h, " << m << "m and " << s << "s"; + logfile.close(); + } + catch (itk::ExceptionObject e) + { + std::cout << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + std::cout << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + std::cout << "ERROR!?!"; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/CMakeLists.txt b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/CMakeLists.txt index 9e7cf2c5a7..a72860b7ab 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/CMakeLists.txt +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/CMakeLists.txt @@ -1,42 +1,44 @@ option(BUILD_DiffusionTractographyEvaluationCmdApps "Build commandline tools for diffusion fiber tractography evaluation" OFF) if(BUILD_DiffusionTractographyEvaluationCmdApps OR MITK_BUILD_ALL_APPS) # needed include directories include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) # list of diffusion cmdapps # if an app requires additional dependencies # they are added after a "^^" and separated by "_" set( diffusionTractographyEvaluationcmdapps PeaksAngularError^^MitkFiberTracking TractometerMetrics^^MitkFiberTracking - TractPlausibility^^MitkFiberTracking - TractPlausibilityFit^^MitkFiberTracking + MergeOverlappingTracts^^MitkFiberTracking + ExtractAnchorTracts^^MitkFiberTracking + AnchorBasedScoring^^MitkFiberTracking + EvaluateLiFE^^MitkFiberTracking # LocalDirectionalFiberPlausibility^^MitkFiberTracking # HAS TO USE NEW PEAK IMAGE FORMAT ) foreach(diffusionTractographyEvaluationcmdapp ${diffusionTractographyEvaluationcmdapps}) # extract cmd app name and dependencies string(REPLACE "^^" "\\;" cmdapp_info ${diffusionTractographyEvaluationcmdapp}) set(cmdapp_info_list ${cmdapp_info}) list(GET cmdapp_info_list 0 appname) list(GET cmdapp_info_list 1 raw_dependencies) string(REPLACE "_" "\\;" dependencies "${raw_dependencies}") set(dependencies_list ${dependencies}) mitkFunctionCreateCommandLineApp( NAME ${appname} DEPENDS MitkCore MitkDiffusionCore ${dependencies_list} PACKAGE_DEPENDS ITK ) endforeach() if(EXECUTABLE_IS_ENABLED) MITK_INSTALL_TARGETS(EXECUTABLES ${EXECUTABLE_TARGET}) endif() endif() diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/EvaluateLiFE.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/EvaluateLiFE.cpp new file mode 100755 index 0000000000..66e8baf820 --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/EvaluateLiFE.cpp @@ -0,0 +1,226 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef itksys::SystemTools ist; +typedef itk::Image ItkUcharImgType; +typedef std::tuple< ItkUcharImgType::Pointer, std::string > MaskType; + +ItkUcharImgType::Pointer LoadItkMaskImage(const std::string& filename) +{ + mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(filename)[0].GetPointer()); + ItkUcharImgType::Pointer itkMask = ItkUcharImgType::New(); + mitk::CastToItkImage(img, itkMask); + return itkMask; +} + +std::vector< MaskType > get_file_list(const std::string& path) +{ + std::chrono::milliseconds ms = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()); + std::srand(ms.count()); + + std::vector< MaskType > mask_list; + + itk::Directory::Pointer dir = itk::Directory::New(); + + if (dir->Load(path.c_str())) + { + int n = dir->GetNumberOfFiles(); + int num_images = 0; + + std::vector< int > im_indices; + for (int r = 0; r < n; r++) + { + const char *filename = dir->GetFile(r); + std::string ext = ist::GetFilenameExtension(filename); + if (ext==".nii" || ext==".nii.gz" || ext==".nrrd") + { + ++num_images; + im_indices.push_back(r); + } + } + + int c = -1; + for (int r : im_indices) + { + c++; + const char *filename = dir->GetFile(r); + + MITK_INFO << "Loading " << ist::GetFilenameWithoutExtension(filename); + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + MaskType m(LoadItkMaskImage(path + '/' + filename), ist::GetFilenameName(filename)); + mask_list.push_back(m); + std::cout.rdbuf (old); // <-- restore + } + } + + return mask_list; +} + +/*! +\brief +*/ +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + + parser.setTitle("Evaluate LiFE results"); + parser.setCategory("Fiber Tracking Evaluation"); + parser.setDescription(""); + parser.setContributor("MIC"); + + parser.setArgumentPrefix("--", "-"); + parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); + parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output folder", us::Any(), false); + parser.addArgument("reference_mask_folder", "m", mitkCommandLineParser::String, "Reference Mask Folder:", "reference masks of known bundles", false); + parser.addArgument("overlap", "", mitkCommandLineParser::Float, "Overlap threshold:", "Overlap threshold used to identify true positives", 0.8); + parser.addArgument("steps", "", mitkCommandLineParser::Int, "Threshold steps:", "number of weight thresholds used to calculate the ROC curve", 100); + parser.addArgument("pre_filter_zeros", "", mitkCommandLineParser::Bool, "Remove zero weights:", "remove fibers with zero weights before starting the evaluation"); + + std::map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0) + return EXIT_FAILURE; + + std::string fibFile = us::any_cast(parsedArgs["input"]); + std::string reference_mask_folder = us::any_cast(parsedArgs["reference_mask_folder"]); + std::string out_folder = us::any_cast(parsedArgs["out"]); + + float overlap = 0.8; + if (parsedArgs.count("overlap")) + overlap = us::any_cast(parsedArgs["overlap"]); + + int steps = 10; + if (parsedArgs.count("steps")) + steps = us::any_cast(parsedArgs["steps"]); + + bool pre_filter_zeros = false; + if (parsedArgs.count("pre_filter_zeros")) + pre_filter_zeros = us::any_cast(parsedArgs["pre_filter_zeros"]); + + try + { + std::vector< MaskType > known_tract_masks = get_file_list(reference_mask_folder); + if (known_tract_masks.empty()) + return EXIT_FAILURE; + + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::Load(fibFile)[0].GetPointer()); + + // resample fibers + float minSpacing = 1; + if(std::get<0>(known_tract_masks.at(0))->GetSpacing()[0](known_tract_masks.at(0))->GetSpacing()[1] && std::get<0>(known_tract_masks.at(0))->GetSpacing()[0](known_tract_masks.at(0))->GetSpacing()[2]) + minSpacing = std::get<0>(known_tract_masks.at(0))->GetSpacing()[0]; + else if (std::get<0>(known_tract_masks.at(0))->GetSpacing()[1] < std::get<0>(known_tract_masks.at(0))->GetSpacing()[2]) + minSpacing = std::get<0>(known_tract_masks.at(0))->GetSpacing()[1]; + else + minSpacing = std::get<0>(known_tract_masks.at(0))->GetSpacing()[2]; + inputTractogram->ResampleLinear(minSpacing/5); + + std::vector< float > weights; + for (int i=0; iGetNumFibers(); ++i) + weights.push_back(inputTractogram->GetFiberWeight(i)); + std::sort(weights.begin(), weights.end()); + + if (pre_filter_zeros) + inputTractogram = inputTractogram->FilterByWeights(0.0); + mitk::FiberBundle::Pointer pred_positives = inputTractogram->GetDeepCopy(); + mitk::FiberBundle::Pointer pred_negatives = mitk::FiberBundle::New(nullptr); + + ofstream logfile; + logfile.open (out_folder + "LiFE_ROC.txt"); + + float fpr = 1.0; + float tpr = 1.0; + float step = weights.back()/steps; + float w = 0; + if (!pre_filter_zeros) + w -= step; + while (pred_positives->GetNumFibers()>0 && fpr>0.001 && tpr>0.001) + { + w += step; + + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + + mitk::FiberBundle::Pointer tp_tracts = mitk::FiberBundle::New(nullptr); + mitk::FiberBundle::Pointer fn_tracts = mitk::FiberBundle::New(nullptr); + for ( MaskType mask : known_tract_masks ) + { + ItkUcharImgType::Pointer mask_image = std::get<0>(mask); + + mitk::FiberBundle::Pointer a = pred_positives->ExtractFiberSubset(mask_image, true, false, false, overlap, false); + tp_tracts = tp_tracts->AddBundle(a); + + mitk::FiberBundle::Pointer b = pred_negatives->ExtractFiberSubset(mask_image, true, false, false, overlap, false); + fn_tracts = fn_tracts->AddBundle(b); + } + mitk::FiberBundle::Pointer fp_tracts = pred_positives->SubtractBundle(tp_tracts); + mitk::FiberBundle::Pointer tn_tracts = pred_negatives->SubtractBundle(fn_tracts); + + std::cout.rdbuf (old); // <-- restore + + float positives = tp_tracts->GetNumFibers() + fn_tracts->GetNumFibers(); + float negatives = tn_tracts->GetNumFibers() + fp_tracts->GetNumFibers(); + fpr = (float)fp_tracts->GetNumFibers() / negatives; + tpr = (float)tp_tracts->GetNumFibers() / positives; + + float accuracy = 1.0; + if (pred_positives->GetNumFibers()>0) + accuracy = (float)tp_tracts->GetNumFibers()/pred_positives->GetNumFibers(); + logfile << w << " " << fpr << " " << tpr << " " << accuracy << " \n"; + MITK_INFO << "#Fibers: " << pred_positives->GetNumFibers(); + MITK_INFO << "FPR/TPR: " << fpr << "/" << tpr; + MITK_INFO << "Acc: " << accuracy; + + pred_positives = inputTractogram->FilterByWeights(w); + pred_negatives = inputTractogram->FilterByWeights(w, true); + } + logfile.close(); + } + catch (itk::ExceptionObject e) + { + std::cout << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + std::cout << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + std::cout << "ERROR!?!"; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractAnchorTracts.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractAnchorTracts.cpp new file mode 100755 index 0000000000..a38418adeb --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractAnchorTracts.cpp @@ -0,0 +1,268 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef itksys::SystemTools ist; +typedef itk::Image ItkUcharImgType; +typedef std::tuple< ItkUcharImgType::Pointer, std::string > MaskType; + +void CreateFolderStructure(const std::string& path) +{ + if (ist::PathExists(path)) + ist::RemoveADirectory(path); + + ist::MakeDirectory(path); + ist::MakeDirectory(path + "/anchor_tracts/"); + ist::MakeDirectory(path + "/candidate_tracts/"); + ist::MakeDirectory(path + "/implausible_tracts/"); + ist::MakeDirectory(path + "/skipped_masks/"); +} + +ItkUcharImgType::Pointer LoadItkMaskImage(const std::string& filename) +{ + mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(filename)[0].GetPointer()); + ItkUcharImgType::Pointer itkMask = ItkUcharImgType::New(); + mitk::CastToItkImage(img, itkMask); + return itkMask; +} + +std::vector< MaskType > get_file_list(const std::string& path, float anchor_fraction, const std::string& skipped_path) +{ + if (anchor_fraction<0) + anchor_fraction = 0; + else if (anchor_fraction>1.0) + anchor_fraction = 1.0; + + std::chrono::milliseconds ms = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()); + std::srand(ms.count()); + + std::vector< MaskType > mask_list; + + itk::Directory::Pointer dir = itk::Directory::New(); + + int skipped = 0; + if (dir->Load(path.c_str())) + { + int n = dir->GetNumberOfFiles(); + int num_images = 0; + + std::vector< int > im_indices; + for (int r = 0; r < n; r++) + { + const char *filename = dir->GetFile(r); + std::string ext = ist::GetFilenameExtension(filename); + if (ext==".nii" || ext==".nii.gz" || ext==".nrrd") + { + ++num_images; + im_indices.push_back(r); + } + } + + int skipping_num = num_images * (1.0 - anchor_fraction); + std::random_shuffle(im_indices.begin(), im_indices.end()); + MITK_INFO << "Skipping " << skipping_num << " images"; + MITK_INFO << "Number of anchors: " << num_images-skipping_num; + + int c = -1; + for (int r : im_indices) + { + c++; + const char *filename = dir->GetFile(r); + + if (c matrix = vtkSmartPointer< vtkMatrix4x4 >::New(); + matrix->Identity(); + matrix->SetElement(0,0,-matrix->GetElement(0,0)); + matrix->SetElement(1,1,-matrix->GetElement(1,1)); + geometry->SetIndexToWorldTransformByVtkMatrix(matrix); + + vtkSmartPointer transformFilter = vtkSmartPointer::New(); + transformFilter->SetInputData(fib->GetFiberPolyData()); + transformFilter->SetTransform(geometry->GetVtkTransform()); + transformFilter->Update(); + mitk::FiberBundle::Pointer transformed_fib = mitk::FiberBundle::New(transformFilter->GetOutput()); + return transformed_fib; +} + +/*! +\brief +*/ +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + + parser.setTitle("Extract Anchor Tracts"); + parser.setCategory("Fiber Tracking Evaluation"); + parser.setDescription(""); + parser.setContributor("MIC"); + + parser.setArgumentPrefix("--", "-"); + parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); + parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output folder", us::Any(), false); + parser.addArgument("reference_mask_folder", "m", mitkCommandLineParser::String, "Reference Mask Folder:", "reference masks of known bundles", us::Any(), false); + parser.addArgument("gray_matter_mask", "gm", mitkCommandLineParser::String, "GM mask:", "remove fibers not ending in the gray matter"); + parser.addArgument("anchor_fraction", "", mitkCommandLineParser::Float, "Anchor fraction:", "Fraction of tracts used as anchors", 0.5); + parser.addArgument("overlap", "", mitkCommandLineParser::Float, "Overlap threshold:", "Overlap threshold used to identify the anchor tracts", 0.8); + parser.addArgument("subsample", "", mitkCommandLineParser::Float, "Subsampling factor:", "Only use specified fraction of input fibers for the analysis", 1.0); + + std::map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0) + return EXIT_FAILURE; + + std::string fibFile = us::any_cast(parsedArgs["input"]); + std::string reference_mask_folder = us::any_cast(parsedArgs["reference_mask_folder"]); + std::string out_folder = us::any_cast(parsedArgs["out"]); + + std::string gray_matter_mask = ""; + if (parsedArgs.count("gray_matter_mask")) + gray_matter_mask = us::any_cast(parsedArgs["gray_matter_mask"]); + + float anchor_fraction = 0.5; + if (parsedArgs.count("anchor_fraction")) + anchor_fraction = us::any_cast(parsedArgs["anchor_fraction"]); + + float overlap = 0.8; + if (parsedArgs.count("overlap")) + overlap = us::any_cast(parsedArgs["overlap"]); + + float subsample = 1.0; + if (parsedArgs.count("subsample")) + subsample = us::any_cast(parsedArgs["subsample"]); + + try + { + CreateFolderStructure(out_folder); + std::vector< MaskType > known_tract_masks = get_file_list(reference_mask_folder, anchor_fraction, out_folder + "/skipped_masks/"); + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::Load(fibFile)[0].GetPointer()); + + MITK_INFO << "Removing fibers not ending inside of GM"; + if (gray_matter_mask.compare("")!=0) + { + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + ItkUcharImgType::Pointer gm_image = LoadItkMaskImage(gray_matter_mask); + std::cout.rdbuf (old); // <-- restore + + mitk::FiberBundle::Pointer not_gm_fibers = inputTractogram->ExtractFiberSubset(gm_image, false, true, true); + + old = cout.rdbuf(); // <-- save + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + mitk::IOUtil::Save(not_gm_fibers, out_folder + "/implausible_tracts/no_gm_endings.trk"); + inputTractogram = inputTractogram->ExtractFiberSubset(gm_image, false, false, true); + std::cout.rdbuf (old); // <-- restore + } + + if (subsample<1.0) + inputTractogram = inputTractogram->SubsampleFibers(subsample); + + + // resample fibers + float minSpacing = 1; + if (!known_tract_masks.empty()) + { + if(std::get<0>(known_tract_masks.at(0))->GetSpacing()[0](known_tract_masks.at(0))->GetSpacing()[1] && std::get<0>(known_tract_masks.at(0))->GetSpacing()[0](known_tract_masks.at(0))->GetSpacing()[2]) + minSpacing = std::get<0>(known_tract_masks.at(0))->GetSpacing()[0]; + else if (std::get<0>(known_tract_masks.at(0))->GetSpacing()[1] < std::get<0>(known_tract_masks.at(0))->GetSpacing()[2]) + minSpacing = std::get<0>(known_tract_masks.at(0))->GetSpacing()[1]; + else + minSpacing = std::get<0>(known_tract_masks.at(0))->GetSpacing()[2]; + } + inputTractogram->ResampleLinear(minSpacing/5); + + mitk::FiberBundle::Pointer all_anchor_tracts = mitk::FiberBundle::New(nullptr); + if (!known_tract_masks.empty()) + { + MITK_INFO << "Find known tracts via overlap match"; + boost::progress_display disp(known_tract_masks.size()); + for ( MaskType mask : known_tract_masks ) + { + ++disp; + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + + ItkUcharImgType::Pointer mask_image = std::get<0>(mask); + std::string mask_name = std::get<1>(mask); + mitk::FiberBundle::Pointer known_tract = inputTractogram->ExtractFiberSubset(mask_image, true, false, false, overlap, false); + mitk::IOUtil::Save(known_tract, out_folder + "/anchor_tracts/" + mask_name + ".trk"); + + all_anchor_tracts = all_anchor_tracts->AddBundle(known_tract); + + std::cout.rdbuf (old); // <-- restore + } + } + + mitk::IOUtil::Save(all_anchor_tracts, out_folder + "/anchor_tracts/anchor_tractogram.trk"); + mitk::FiberBundle::Pointer remaining_tracts = inputTractogram->SubtractBundle(all_anchor_tracts); + mitk::IOUtil::Save(remaining_tracts, out_folder + "/candidate_tracts/candidate_tractogram.trk"); + mitk::IOUtil::Save(inputTractogram, out_folder + "/filtered_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/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/LocalDirectionalFiberPlausibility.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/LocalDirectionalFiberPlausibility.cpp index 3d1daf42db..cc76a4e9f2 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/LocalDirectionalFiberPlausibility.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/LocalDirectionalFiberPlausibility.cpp @@ -1,320 +1,318 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -using namespace std; - /*! \brief Calculate angular error of a tractogram with respect to the input reference directions. */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Local Directional Fiber Plausibility"); parser.setCategory("Fiber Tracking Evaluation"); parser.setDescription("Calculate angular error of a tractogram with respect to the input reference directions."); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("reference", "r", mitkCommandLineParser::StringList, "Reference images:", "reference direction images", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::StringList, "Masks:", "mask images"); parser.addArgument("athresh", "a", mitkCommandLineParser::Float, "Angular threshold:", "angular threshold in degrees. closer fiber directions are regarded as one direction and clustered together.", 25, true); parser.addArgument("sthresh", "s", mitkCommandLineParser::Float, "Size threshold:", "Relative peak size threshold per voxel.", 0.0, true); parser.addArgument("maxdirs", "md", mitkCommandLineParser::Int, "Max. Clusters:", "Maximum number of fiber clusters.", 0, true); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose:", "output optional and intermediate calculation results"); parser.addArgument("ignore", "n", mitkCommandLineParser::Bool, "Ignore:", "don't increase error for missing or too many directions"); parser.addArgument("empty", "e", mitkCommandLineParser::Bool, "Empty Voxels:", "don't increase error for empty voxels"); parser.addArgument("fileID", "id", mitkCommandLineParser::String, "ID:", "optional ID field"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType referenceImages = us::any_cast(parsedArgs["reference"]); mitkCommandLineParser::StringContainerType maskImages; if (parsedArgs.count("mask")) maskImages = us::any_cast(parsedArgs["mask"]); string fibFile = us::any_cast(parsedArgs["input"]); float angularThreshold = 25; if (parsedArgs.count("athresh")) angularThreshold = us::any_cast(parsedArgs["athresh"]); float sizeThreshold = 0; if (parsedArgs.count("sthresh")) sizeThreshold = us::any_cast(parsedArgs["sthresh"]); int maxDirs = 0; if (parsedArgs.count("maxdirs")) maxDirs = us::any_cast(parsedArgs["maxdirs"]); string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); bool ignoreMissing = false; if (parsedArgs.count("ignore")) ignoreMissing = us::any_cast(parsedArgs["ignore"]); bool ignoreEmpty = false; if (parsedArgs.count("empty")) ignoreEmpty = us::any_cast(parsedArgs["empty"]); string fileID = ""; if (parsedArgs.count("fileID")) fileID = us::any_cast(parsedArgs["fileID"]); try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; // load fiber bundle mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadData(fibFile)[0].GetPointer()); // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::Load(referenceImages.at(i))[0].GetPointer()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ std::cout << "could not load: " << referenceImages.at(i); } } ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); itkMaskImage->SetSpacing( dirImg->GetSpacing() ); itkMaskImage->SetOrigin( dirImg->GetOrigin() ); itkMaskImage->SetDirection( dirImg->GetDirection() ); itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->Allocate(); itkMaskImage->FillBuffer(1); // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); fOdfFilter->SetNormalizeVectors(true); fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->SetSizeThreshold(sizeThreshold); fOdfFilter->SetMaxNumDirections(maxDirs); fOdfFilter->Update(); if (verbose) { // write vector field mitk::FiberBundle::Pointer directions = fOdfFilter->GetOutputFiberBundle(); string outfilename = outRoot; outfilename.append("_VECTOR_FIELD.fib"); mitk::IOUtil::Save(directions.GetPointer(), outfilename ); // write direction images { itk::TractsToVectorImageFilter::ItkDirectionImageType::Pointer itkImg = fOdfFilter->GetDirectionImage(); typedef itk::ImageFileWriter< itk::TractsToVectorImageFilter::ItkDirectionImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_DIRECTIONS.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(itkImg); writer->Update(); } // write num direction image { ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_NUM_DIRECTIONS.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(numDirImage); writer->Update(); } } string logFile = outRoot; logFile.append("_ANGULAR_ERROR.csv"); ofstream file; file.open (logFile.c_str()); if (maskImages.size()>0) { for (unsigned int i=0; i(mitk::IOUtil::Load(maskImages.at(i))[0].GetPointer()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); // evaluate directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); //evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(ignoreMissing); evaluationFilter->SetIgnoreEmptyVoxels(ignoreEmpty); evaluationFilter->Update(); if (verbose) { EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_ERROR_IMAGE.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(angularErrorImage); writer->Update(); } string maskFileName = itksys::SystemTools::GetFilenameWithoutExtension(maskImages.at(i)); unsigned found = maskFileName.find_last_of("_"); string sens = itksys::SystemTools::GetFilenameWithoutLastExtension(fibFile); if (!fileID.empty()) sens = fileID; sens.append(","); sens.append(maskFileName.substr(found+1)); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); sens.append(","); sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); sens.append(";\n"); file << sens; } } else { // evaluate directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); //evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(ignoreMissing); evaluationFilter->SetIgnoreEmptyVoxels(ignoreEmpty); evaluationFilter->Update(); if (verbose) { EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_ERROR_IMAGE.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(angularErrorImage); writer->Update(); } string sens = itksys::SystemTools::GetFilenameWithoutLastExtension(fibFile); if (!fileID.empty()) sens = fileID; sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); sens.append(","); sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); sens.append(";\n"); file << sens; } file.close(); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/MergeOverlappingTracts.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/MergeOverlappingTracts.cpp new file mode 100755 index 0000000000..a9488c0b72 --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/MergeOverlappingTracts.cpp @@ -0,0 +1,251 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef itksys::SystemTools ist; +typedef itk::Image ItkUcharImgType; +typedef itk::Image ItkUIntImgType; + +std::vector< std::string > get_file_list(const std::string& path, std::vector< std::string > extensions={".fib", ".trk"}) +{ + std::vector< std::string > file_list; + itk::Directory::Pointer dir = itk::Directory::New(); + + if (dir->Load(path.c_str())) + { + int n = dir->GetNumberOfFiles(); + for (int r = 0; r < n; r++) + { + const char *filename = dir->GetFile(r); + std::string ext = ist::GetFilenameExtension(filename); + for (auto e : extensions) + { + if (ext==e) + { + file_list.push_back(path + '/' + filename); + break; + } + } + } + } + return file_list; +} + +/*! +\brief +*/ +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + + parser.setTitle("Merge Overlapping Tracts"); + parser.setCategory("Fiber Tracking Evaluation"); + parser.setDescription(""); + parser.setContributor("MIC"); + + parser.setArgumentPrefix("--", "-"); + parser.addArgument("in", "i", mitkCommandLineParser::InputFile, "Input Folder:", "input folder", us::Any(), false); + parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output Folder:", "output folder", us::Any(), false); + parser.addArgument("overlap", "", mitkCommandLineParser::Float, "Overlap threshold:", "Tracts with overlap larger than this threshold are merged", false, 0.8); + + std::map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0) + return EXIT_FAILURE; + + std::string input_folder = us::any_cast(parsedArgs["in"]); + std::string out_folder = us::any_cast(parsedArgs["out"]); + + float overlap = 0.8; + if (parsedArgs.count("overlap")) + overlap = us::any_cast(parsedArgs["overlap"]); + + try + { + if (ist::PathExists(out_folder)) + ist::RemoveADirectory(out_folder); + ist::MakeDirectory(out_folder); + + std::vector< std::string > fib_files = get_file_list(input_folder, {".fib", ".trk", ".tck"}); + if (fib_files.empty()) + return EXIT_FAILURE; + + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + + std::vector< mitk::FiberBundle::Pointer > fibs; + for (std::string f : fib_files) + { + mitk::FiberBundle::Pointer fib = dynamic_cast(mitk::IOUtil::Load(f)[0].GetPointer()); + fibs.push_back(fib); + } + + mitk::FiberBundle::Pointer combined = mitk::FiberBundle::New(); + combined = combined->AddBundles(fibs); + + itk::TractsToFiberEndingsImageFilter< ItkUcharImgType >::Pointer endings = itk::TractsToFiberEndingsImageFilter< ItkUcharImgType >::New(); + endings->SetFiberBundle(combined); + endings->SetUpsamplingFactor(0.25); + endings->Update(); + ItkUcharImgType::Pointer ref_image = endings->GetOutput(); + + std::cout.rdbuf (old); // <-- restore + + for (int its = 0; its<3; its++) + { + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + + std::vector< ItkUcharImgType::Pointer > mask_images; + for (auto fib : fibs) + { + itk::TractDensityImageFilter< ItkUcharImgType >::Pointer masks = itk::TractDensityImageFilter< ItkUcharImgType >::New(); + masks->SetInputImage(ref_image); + masks->SetBinaryOutput(true); + masks->SetFiberBundle(fib); + masks->SetUseImageGeometry(true); + masks->Update(); + mask_images.push_back(masks->GetOutput()); + } + + int r=0; + vnl_matrix< int > mat; mat.set_size(mask_images.size(), mask_images.size()); mat.fill(0); + for (auto m1 : mask_images) + { + float max_overlap = overlap; + int c = 0; + for (auto m2 : mask_images) + { + if (c<=r) + { + ++c; + continue; + } + + itk::ImageRegionConstIterator it1(m1, m1->GetLargestPossibleRegion()); + itk::ImageRegionConstIterator it2(m2, m2->GetLargestPossibleRegion()); + + unsigned int c1 = 0; + unsigned int c2 = 0; + unsigned int intersect = 0; + while( !it1.IsAtEnd() ) + { + if( it1.Get()>0 && it2.Get()>0) + ++intersect; + if(it1.Get()>0) + ++c1; + if(it2.Get()>0) + ++c2; + ++it1; + ++it2; + } + + if ( (float)intersect/c1>max_overlap ) + { + max_overlap = (float)intersect/c1; + mat.put(r,c, 1); + } + if ( (float)intersect/c2>max_overlap ) + { + max_overlap = (float)intersect/c2; + mat.put(r,c, 1); + } + ++c; + } + + ++r; + } + + std::vector< mitk::FiberBundle::Pointer > out_fibs; + std::vector< bool > used; + for (unsigned int i=0; i0) + { + fib = fib->AddBundle(fibs.at(c)); + MITK_INFO << c; + used[c] = true; + } + } + + out_fibs.push_back(fib); + } + std::cout.rdbuf (old); // <-- restore + + MITK_INFO << fibs.size() << " --> " << out_fibs.size(); + + if (fibs.size()==out_fibs.size()) + break; + fibs = out_fibs; + } + + int c = 0; + for (auto fib : fibs) + { + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + mitk::IOUtil::Save(fib, out_folder + "/bundle_" + boost::lexical_cast(c) + ".trk"); + std::cout.rdbuf (old); // <-- restore + + ++c; + } + } + catch (itk::ExceptionObject e) + { + std::cout << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + std::cout << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + std::cout << "ERROR!?!"; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/PeaksAngularError.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/PeaksAngularError.cpp index a691475f78..6ddf817ab4 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/PeaksAngularError.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/PeaksAngularError.cpp @@ -1,209 +1,207 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -using namespace std; - /*! \brief Calculate angular error between two sets of directions stored in multiple 3D vector images where each pixel corresponds to a vector (itk::Image< itk::Vector< float, 3>, 3 >) */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("test", "t", mitkCommandLineParser::StringList, "Test images", "test direction images", us::Any(), false); parser.addArgument("reference", "r", mitkCommandLineParser::StringList, "Reference images", "reference direction images", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output directory", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask", "mask image"); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose", "output optional and intermediate calculation results"); parser.addArgument("ignore", "i", mitkCommandLineParser::Bool, "Ignore", "don't increase error for missing or too many directions"); parser.setCategory("Fiber Tracking Evaluation"); parser.setTitle("Peaks Angular Error"); parser.setDescription("Calculate angular error between two sets of directions stored in multiple 3D vector images where each pixel corresponds to a vector (itk::Image< itk::Vector< float, 3>, 3 >)"); parser.setContributor("MIC"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType testImages = us::any_cast(parsedArgs["test"]); mitkCommandLineParser::StringContainerType referenceImages = us::any_cast(parsedArgs["reference"]); - string maskImage(""); + std::string maskImage(""); if (parsedArgs.count("mask")) - maskImage = us::any_cast(parsedArgs["mask"]); + maskImage = us::any_cast(parsedArgs["mask"]); - string outRoot = us::any_cast(parsedArgs["out"]); + std::string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); bool ignore = false; if (parsedArgs.count("ignore")) ignore = us::any_cast(parsedArgs["ignore"]); try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; ItkDirectionImageContainerType::Pointer directionImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::Load(testImages.at(i))[0].GetPointer()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); directionImageContainer->InsertElement(directionImageContainer->Size(),itkImg); } catch(...){ std::cout << "could not load: " << referenceImages.at(i); } } // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::Load(referenceImages.at(i))[0].GetPointer()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ std::cout << "could not load: " << referenceImages.at(i); } } // load/create mask image ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); if (maskImage.compare("")==0) { ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); itkMaskImage->SetSpacing( dirImg->GetSpacing() ); itkMaskImage->SetOrigin( dirImg->GetOrigin() ); itkMaskImage->SetDirection( dirImg->GetDirection() ); itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->Allocate(); itkMaskImage->FillBuffer(1); } else { mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::Load(maskImage)[0].GetPointer()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); } // evaluate directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(ignore); evaluationFilter->Update(); if (verbose) { EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); - string outfilename = outRoot; + std::string outfilename = outRoot; outfilename.append("_ERROR_IMAGE.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(angularErrorImage); writer->Update(); } - string logFile = outRoot; + std::string logFile = outRoot; logFile.append("_ANGULAR_ERROR.csv"); ofstream file; file.open (logFile.c_str()); - string sens = "Mean:"; + std::string sens = "Mean:"; sens.append(","); - sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); + sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); sens.append(";\n"); sens.append("Median:"); sens.append(","); - sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); + sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); sens.append(";\n"); sens.append("Maximum:"); sens.append(","); - sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); + sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); sens.append(";\n"); sens.append("Minimum:"); sens.append(","); - sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); + sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); sens.append(";\n"); sens.append("STDEV:"); sens.append(","); - sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); + sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); sens.append(";\n"); file << sens; file.close(); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractPlausibility.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractPlausibility.cpp deleted file mode 100755 index ecf520ae8f..0000000000 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractPlausibility.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -typedef itksys::SystemTools ist; -typedef itk::Image ItkUcharImgType; -typedef std::tuple< ItkUcharImgType::Pointer, std::string > MaskType; - -void CreateFolderStructure(const std::string& path) -{ - if (ist::PathExists(path)) - ist::RemoveADirectory(path); - - ist::MakeDirectory(path); - ist::MakeDirectory(path + "/known_tracts/"); - ist::MakeDirectory(path + "/plausible_tracts/"); - ist::MakeDirectory(path + "/implausible_tracts/"); -} - -ItkUcharImgType::Pointer LoadItkMaskImage(const std::string& filename) -{ - mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(filename)[0].GetPointer()); - ItkUcharImgType::Pointer itkMask = ItkUcharImgType::New(); - mitk::CastToItkImage(img, itkMask); - return itkMask; -} - -std::vector< MaskType > get_file_list(const std::string& path, const std::string& skipped) -{ - std::srand(std::time(0)); - - std::vector< MaskType > mask_list; - - itk::Directory::Pointer dir = itk::Directory::New(); - - ofstream myfile; - myfile.open (skipped); - if (dir->Load(path.c_str())) - { - int n = dir->GetNumberOfFiles(); - for (int r = 0; r < n; r++) - { - const char *filename = dir->GetFile(r); - - if (std::rand()%3==0 && ist::GetFilenameWithoutExtension(filename)!="CC") - { - MITK_INFO << "Dismissing " << ist::GetFilenameWithoutExtension(filename); - myfile << ist::GetFilenameName(filename) << "\n"; - continue; - } - - std::string ext = ist::GetFilenameExtension(filename); - if (ext==".nii" || ext==".nii.gz" || ext==".nrrd") - { - MITK_INFO << "Loading " << ist::GetFilenameWithoutExtension(filename); - streambuf *old = cout.rdbuf(); // <-- save - stringstream ss; - std::cout.rdbuf (ss.rdbuf()); // <-- redirect - - MaskType m(LoadItkMaskImage(path + '/' + filename), ist::GetFilenameWithoutExtension(filename)); - mask_list.push_back(m); - - std::cout.rdbuf (old); // <-- restore - } - } - } - myfile.close(); - - return mask_list; -} - -mitk::FiberBundle::Pointer TransformToMRtrixSpace(mitk::FiberBundle::Pointer fib) -{ - mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); - vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New(); - matrix->Identity(); - matrix->SetElement(0,0,-matrix->GetElement(0,0)); - matrix->SetElement(1,1,-matrix->GetElement(1,1)); - geometry->SetIndexToWorldTransformByVtkMatrix(matrix); - - vtkSmartPointer transformFilter = vtkSmartPointer::New(); - transformFilter->SetInputData(fib->GetFiberPolyData()); - transformFilter->SetTransform(geometry->GetVtkTransform()); - transformFilter->Update(); - mitk::FiberBundle::Pointer transformed_fib = mitk::FiberBundle::New(transformFilter->GetOutput()); - return transformed_fib; -} - -/*! -\brief -*/ -int main(int argc, char* argv[]) -{ - mitkCommandLineParser parser; - - parser.setTitle("Tract Plausibility"); - parser.setCategory("Fiber Tracking Evaluation"); - parser.setDescription(""); - parser.setContributor("MIC"); - - parser.setArgumentPrefix("--", "-"); - parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); - parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output folder", us::Any(), false); - parser.addArgument("reference_mask_folder", "m", mitkCommandLineParser::String, "Reference Mask Folder:", "reference masks of known bundles", false); - parser.addArgument("gray_matter_mask", "gm", mitkCommandLineParser::String, "", "", false); - - map parsedArgs = parser.parseArguments(argc, argv); - if (parsedArgs.size()==0) - return EXIT_FAILURE; - - string fibFile = us::any_cast(parsedArgs["input"]); - string gray_matter_mask = us::any_cast(parsedArgs["gray_matter_mask"]); - string reference_mask_folder = us::any_cast(parsedArgs["reference_mask_folder"]); - string out_folder = us::any_cast(parsedArgs["out"]); - - try - { - CreateFolderStructure(out_folder); - - std::vector< MaskType > known_tract_masks = get_file_list(reference_mask_folder, out_folder + "skipped_masks.txt"); - if (known_tract_masks.empty()) - return EXIT_FAILURE; - - ItkUcharImgType::Pointer gm_image = LoadItkMaskImage(gray_matter_mask); - - mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::Load(fibFile)[0].GetPointer()); - - // filter gray matter fibers - mitk::FiberBundle::Pointer not_gm_fibers = inputTractogram->ExtractFiberSubset(gm_image, false, true, true); - mitk::IOUtil::Save(not_gm_fibers, out_folder + "/implausible_tracts/no_gm_endings.trk"); - inputTractogram = inputTractogram->ExtractFiberSubset(gm_image, false, false, true); - - // resample fibers - float minSpacing = 1; - if(std::get<0>(known_tract_masks.at(0))->GetSpacing()[0](known_tract_masks.at(0))->GetSpacing()[1] && std::get<0>(known_tract_masks.at(0))->GetSpacing()[0](known_tract_masks.at(0))->GetSpacing()[2]) - minSpacing = std::get<0>(known_tract_masks.at(0))->GetSpacing()[0]; - else if (std::get<0>(known_tract_masks.at(0))->GetSpacing()[1] < std::get<0>(known_tract_masks.at(0))->GetSpacing()[2]) - minSpacing = std::get<0>(known_tract_masks.at(0))->GetSpacing()[1]; - else - minSpacing = std::get<0>(known_tract_masks.at(0))->GetSpacing()[2]; - inputTractogram->ResampleLinear(minSpacing/5); - - // find known tracts via overlap match - mitk::FiberBundle::Pointer all_known_tracts = nullptr; - for ( MaskType mask : known_tract_masks ) - { - ItkUcharImgType::Pointer mask_image = std::get<0>(mask); - std::string mask_name = std::get<1>(mask); - mitk::FiberBundle::Pointer known_tract = inputTractogram->ExtractFiberSubset(mask_image, true, false, false, 0.7, false); - mitk::IOUtil::Save(known_tract, out_folder + "/known_tracts/" + mask_name + ".trk"); - - if (all_known_tracts.IsNull()) - all_known_tracts = mitk::FiberBundle::New(known_tract->GetFiberPolyData()); - else - all_known_tracts = all_known_tracts->AddBundle(known_tract); - } - mitk::IOUtil::Save(all_known_tracts, out_folder + "/known_tracts/all_known_tracts.trk"); - mitk::IOUtil::Save(TransformToMRtrixSpace(all_known_tracts), out_folder + "/known_tracts/all_known_tracts_mrtrixspace.fib"); - - mitk::FiberBundle::Pointer remaining_tracts = inputTractogram->SubtractBundle(all_known_tracts); - mitk::IOUtil::Save(remaining_tracts, out_folder + "/plausible_tracts/remaining_tracts.trk"); - mitk::IOUtil::Save(TransformToMRtrixSpace(remaining_tracts), out_folder + "/plausible_tracts/remaining_tracts_mrtrixspace.fib"); - MITK_INFO << "step_size: " << minSpacing/5; - } - catch (itk::ExceptionObject e) - { - std::cout << e; - return EXIT_FAILURE; - } - catch (std::exception e) - { - std::cout << e.what(); - return EXIT_FAILURE; - } - catch (...) - { - std::cout << "ERROR!?!"; - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractPlausibilityFit.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractPlausibilityFit.cpp deleted file mode 100755 index 6b1f1240c0..0000000000 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractPlausibilityFit.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -typedef itksys::SystemTools ist; -typedef itk::Point PointType4; -typedef itk::Image< float, 4 > PeakImgType; - -std::vector< string > get_file_list(const std::string& path) -{ - std::vector< string > file_list; - itk::Directory::Pointer dir = itk::Directory::New(); - - if (dir->Load(path.c_str())) - { - int n = dir->GetNumberOfFiles(); - for (int r = 0; r < n; r++) - { - const char *filename = dir->GetFile(r); - std::string ext = ist::GetFilenameExtension(filename); - if (ext==".fib" || ext==".trk") - file_list.push_back(path + '/' + filename); - } - } - return file_list; -} - -/*! -\brief Fits the tractogram to the input peak image by assigning a weight to each fiber (similar to https://doi.org/10.1016/j.neuroimage.2015.06.092). -*/ -int main(int argc, char* argv[]) -{ - mitkCommandLineParser parser; - - parser.setTitle(""); - parser.setCategory("Fiber Tracking Evaluation"); - parser.setDescription(""); - parser.setContributor("MIC"); - - parser.setArgumentPrefix("--", "-"); - parser.addArgument("", "i1", mitkCommandLineParser::InputFile, "Input tractogram:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); - parser.addArgument("", "i2", mitkCommandLineParser::InputFile, "Input peaks:", "input peak image", us::Any(), false); - parser.addArgument("", "i3", mitkCommandLineParser::InputFile, "", "", us::Any(), false); - parser.addArgument("", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any()); - - parser.addArgument("mask", "", mitkCommandLineParser::InputFile, "", "", us::Any(), false); - parser.addArgument("min_gain", "", mitkCommandLineParser::Float, "Min. gain:", "process stops if remaining bundles don't contribute enough", 0.05); - - - parser.addArgument("max_iter", "", mitkCommandLineParser::Int, "Max. iterations:", "maximum number of optimizer iterations", 20); - parser.addArgument("bundle_based", "", mitkCommandLineParser::Bool, "Bundle based fit:", "fit one weight per input tractogram/bundle, not for each fiber", false); - parser.addArgument("min_g", "", mitkCommandLineParser::Float, "Min. gradient:", "lower termination threshold for gradient magnitude", 1e-5); - parser.addArgument("lambda", "", mitkCommandLineParser::Float, "Lambda:", "modifier for regularization", 0.1); - parser.addArgument("dont_filter_outliers", "", mitkCommandLineParser::Bool, "Don't filter outliers:", "don't perform second optimization run with an upper weight bound based on the first weight estimation (95% quantile)", false); - - map parsedArgs = parser.parseArguments(argc, argv); - if (parsedArgs.size()==0) - return EXIT_FAILURE; - - string fib_file = us::any_cast(parsedArgs["i1"]); - string peak_file_name = us::any_cast(parsedArgs["i2"]); - string candidate_folder = us::any_cast(parsedArgs["i3"]); - string outRoot = us::any_cast(parsedArgs["o"]); - - bool single_fib = true; - if (parsedArgs.count("bundle_based")) - single_fib = !us::any_cast(parsedArgs["bundle_based"]); - - int max_iter = 20; - if (parsedArgs.count("max_iter")) - max_iter = us::any_cast(parsedArgs["max_iter"]); - - float g_tol = 1e-5; - if (parsedArgs.count("min_g")) - g_tol = us::any_cast(parsedArgs["min_g"]); - - float min_gain = 0.05; - if (parsedArgs.count("min_gain")) - min_gain = us::any_cast(parsedArgs["min_gain"]); - - float lambda = 0.1; - if (parsedArgs.count("lambda")) - lambda = us::any_cast(parsedArgs["lambda"]); - - bool filter_outliers = true; - if (parsedArgs.count("dont_filter_outliers")) - filter_outliers = !us::any_cast(parsedArgs["dont_filter_outliers"]); - - string mask_file = ""; - if (parsedArgs.count("mask")) - mask_file = us::any_cast(parsedArgs["mask"]); - - try - { - itk::TimeProbe clock; - clock.Start(); - - mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Peak Image", "Fiberbundles"}, {}); - mitk::Image::Pointer inputImage = dynamic_cast(mitk::IOUtil::Load(peak_file_name, &functor)[0].GetPointer()); - - itk::FitFibersToImageFilter::UcharImgType::Pointer mask = nullptr; - if (mask_file.compare("")!=0) - { - mitk::Image::Pointer mitk_mask = dynamic_cast(mitk::IOUtil::Load(mask_file)[0].GetPointer()); - mitk::CastToItkImage(mitk_mask, mask); - } - - typedef mitk::ImageToItk< PeakImgType > CasterType; - CasterType::Pointer caster = CasterType::New(); - caster->SetInput(inputImage); - caster->Update(); - PeakImgType::Pointer peak_image = caster->GetOutput(); - - std::vector< mitk::FiberBundle::Pointer > input_reference; - mitk::FiberBundle::Pointer fib = dynamic_cast(mitk::IOUtil::Load(fib_file)[0].GetPointer()); - if (fib.IsNull()) - return EXIT_FAILURE; - input_reference.push_back(fib); - - std::vector< mitk::FiberBundle::Pointer > input_candidates; - std::vector< string > candidate_tract_files = get_file_list(candidate_folder); - for (string f : candidate_tract_files) - { - mitk::FiberBundle::Pointer fib = dynamic_cast(mitk::IOUtil::Load(f)[0].GetPointer()); - if (fib.IsNull()) - continue; - input_candidates.push_back(fib); - } - - int iteration = 0; - std::string name = ist::GetFilenameWithoutExtension(fib_file); - - itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New(); - fitter->SetTractograms(input_reference); - fitter->SetFitIndividualFibers(single_fib); - fitter->SetMaxIterations(max_iter); - fitter->SetGradientTolerance(g_tol); - fitter->SetLambda(lambda); - fitter->SetFilterOutliers(filter_outliers); - fitter->SetPeakImage(peak_image); - fitter->SetVerbose(true); - fitter->SetDeepCopy(false); - fitter->SetMaskImage(mask); - fitter->Update(); - -// fitter->GetTractograms().at(0)->SetFiberWeights(fitter->GetCoverage()); -// fitter->GetTractograms().at(0)->ColorFibersByFiberWeights(false, false); - - mitk::IOUtil::Save(fitter->GetTractograms().at(0), outRoot + "0_" + name + ".fib"); - peak_image = fitter->GetUnderexplainedImage(); - - itk::ImageFileWriter< PeakImgType >::Pointer writer = itk::ImageFileWriter< PeakImgType >::New(); - writer->SetInput(peak_image); - writer->SetFileName(outRoot + boost::lexical_cast(iteration) + "_" + name + ".nrrd"); - writer->Update(); - - double coverage = fitter->GetCoverage(); - MITK_INFO << "Iteration: " << iteration; - MITK_INFO << std::fixed << "Coverage: " << setprecision(2) << 100.0*coverage << "%"; -// fitter->SetPeakImage(peak_image); - - while (!input_candidates.empty()) - { - streambuf *old = cout.rdbuf(); // <-- save - stringstream ss; - std::cout.rdbuf (ss.rdbuf()); // <-- redirect - - double next_coverage = 0; - mitk::FiberBundle::Pointer best_candidate = nullptr; - for (auto fib : input_candidates) - { - - // WHY NECESSARY AGAIN?? - itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New(); - fitter->SetFitIndividualFibers(single_fib); - fitter->SetMaxIterations(max_iter); - fitter->SetGradientTolerance(g_tol); - fitter->SetLambda(lambda); - fitter->SetFilterOutliers(filter_outliers); - fitter->SetVerbose(false); - fitter->SetPeakImage(peak_image); - fitter->SetDeepCopy(false); - fitter->SetMaskImage(mask); - // ****************************** - fitter->SetTractograms({fib}); - fitter->Update(); - - double candidate_coverage = fitter->GetCoverage(); - - if (candidate_coverage>next_coverage) - { - next_coverage = candidate_coverage; - if ((1.0-coverage) * next_coverage >= min_gain) - { - best_candidate = fitter->GetTractograms().at(0); - peak_image = fitter->GetUnderexplainedImage(); - } - } - } - - if (best_candidate.IsNull()) - { - std::cout.rdbuf (old); // <-- restore - break; - } - -// fitter->SetPeakImage(peak_image); -// best_candidate->SetFiberWeights((1.0-coverage) * next_coverage); -// best_candidate->ColorFibersByFiberWeights(false, false); - - coverage += (1.0-coverage) * next_coverage; - - int i=0; - std::vector< mitk::FiberBundle::Pointer > remaining_candidates; - std::vector< string > remaining_candidate_files; - for (auto fib : input_candidates) - { - if (fib!=best_candidate) - { - remaining_candidates.push_back(fib); - remaining_candidate_files.push_back(candidate_tract_files.at(i)); - } - else - name = ist::GetFilenameWithoutExtension(candidate_tract_files.at(i)); - ++i; - } - input_candidates = remaining_candidates; - candidate_tract_files = remaining_candidate_files; - - iteration++; - mitk::IOUtil::Save(best_candidate, outRoot + boost::lexical_cast(iteration) + "_" + name + ".fib"); - writer->SetInput(peak_image); - writer->SetFileName(outRoot + boost::lexical_cast(iteration) + "_" + name + ".nrrd"); - writer->Update(); - std::cout.rdbuf (old); // <-- restore - - MITK_INFO << "Iteration: " << iteration; - MITK_INFO << std::fixed << "Coverage: " << setprecision(2) << 100.0*coverage << "% (+" << 100*(1.0-coverage) * next_coverage << "%)"; - } - - clock.Stop(); - int h = clock.GetTotal()/3600; - int m = ((int)clock.GetTotal()%3600)/60; - int s = (int)clock.GetTotal()%60; - MITK_INFO << "Plausibility estimation took " << h << "h, " << m << "m and " << s << "s"; - } - catch (itk::ExceptionObject e) - { - std::cout << e; - return EXIT_FAILURE; - } - catch (std::exception e) - { - std::cout << e.what(); - return EXIT_FAILURE; - } - catch (...) - { - std::cout << "ERROR!?!"; - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractometerMetrics.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractometerMetrics.cpp index 0cba898e93..864e58a084 100755 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractometerMetrics.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/TractometerMetrics.cpp @@ -1,417 +1,415 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -using namespace std; - /*! \brief Calculates the Tractometer evaluation metrics for tractograms (http://www.tractometer.org/) */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Tractometer Metrics"); parser.setCategory("Fiber Tracking Evaluation"); parser.setDescription("Calculates the Tractometer evaluation metrics for tractograms (http://www.tractometer.org/)"); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("labels", "l", mitkCommandLineParser::StringList, "Label pairs:", "label pairs", false); parser.addArgument("labelimage", "li", mitkCommandLineParser::String, "Label image:", "label image", false); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose:", "output valid, invalid and no connections as fiber bundles"); parser.addArgument("fileID", "id", mitkCommandLineParser::String, "ID:", "optional ID field"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType labelpairs = us::any_cast(parsedArgs["labels"]); - string fibFile = us::any_cast(parsedArgs["input"]); - string labelImageFile = us::any_cast(parsedArgs["labelimage"]); + std::string fibFile = us::any_cast(parsedArgs["input"]); + std::string labelImageFile = us::any_cast(parsedArgs["labelimage"]); - string outRoot = us::any_cast(parsedArgs["out"]); + std::string outRoot = us::any_cast(parsedArgs["out"]); - string fileID = ""; + std::string fileID = ""; if (parsedArgs.count("fileID")) - fileID = us::any_cast(parsedArgs["fileID"]); + fileID = us::any_cast(parsedArgs["fileID"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); try { typedef itk::Image ItkShortImgType; typedef itk::Image ItkUcharImgType; // load fiber bundle mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::Load(fibFile)[0].GetPointer()); mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(labelImageFile)[0].GetPointer()); typedef mitk::ImageToItk< ItkShortImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkShortImgType::Pointer labelImage = caster->GetOutput(); - string path = itksys::SystemTools::GetFilenamePath(labelImageFile); + std::string path = itksys::SystemTools::GetFilenamePath(labelImageFile); std::vector< bool > detected; std::vector< std::pair< int, int > > labelsvector; std::vector< ItkUcharImgType::Pointer > bundleMasks; std::vector< ItkUcharImgType::Pointer > bundleMasksCoverage; short max = 0; for (unsigned int i=0; i l; l.first = boost::lexical_cast(labelpairs.at(i)); l.second = boost::lexical_cast(labelpairs.at(i+1)); std::cout << labelpairs.at(i); std::cout << labelpairs.at(i+1); if (l.first>max) max=l.first; if (l.second>max) max=l.second; labelsvector.push_back(l); detected.push_back(false); { - mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(path+"/Bundle"+boost::lexical_cast(labelsvector.size())+"_MASK.nrrd")[0].GetPointer()); + mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(path+"/Bundle"+boost::lexical_cast(labelsvector.size())+"_MASK.nrrd")[0].GetPointer()); typedef mitk::ImageToItk< ItkUcharImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkUcharImgType::Pointer bundle = caster->GetOutput(); bundleMasks.push_back(bundle); } { - mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(path+"/Bundle"+boost::lexical_cast(labelsvector.size())+"_MASK_COVERAGE.nrrd")[0].GetPointer()); + mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(path+"/Bundle"+boost::lexical_cast(labelsvector.size())+"_MASK_COVERAGE.nrrd")[0].GetPointer()); typedef mitk::ImageToItk< ItkUcharImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkUcharImgType::Pointer bundle = caster->GetOutput(); bundleMasksCoverage.push_back(bundle); } } vnl_matrix< unsigned char > matrix; matrix.set_size(max, max); matrix.fill(0); vtkSmartPointer polyData = inputTractogram->GetFiberPolyData(); int validConnections = 0; int noConnection = 0; int validBundles = 0; int invalidBundles = 0; int invalidConnections = 0; ItkUcharImgType::Pointer coverage = ItkUcharImgType::New(); coverage->SetSpacing(labelImage->GetSpacing()); coverage->SetOrigin(labelImage->GetOrigin()); coverage->SetDirection(labelImage->GetDirection()); coverage->SetLargestPossibleRegion(labelImage->GetLargestPossibleRegion()); coverage->SetBufferedRegion( labelImage->GetLargestPossibleRegion() ); coverage->SetRequestedRegion( labelImage->GetLargestPossibleRegion() ); coverage->Allocate(); coverage->FillBuffer(0); vtkSmartPointer noConnPoints = vtkSmartPointer::New(); vtkSmartPointer noConnCells = vtkSmartPointer::New(); vtkSmartPointer invalidPoints = vtkSmartPointer::New(); vtkSmartPointer invalidCells = vtkSmartPointer::New(); vtkSmartPointer validPoints = vtkSmartPointer::New(); vtkSmartPointer validCells = vtkSmartPointer::New(); boost::progress_display disp(inputTractogram->GetNumFibers()); for (int i=0; iGetNumFibers(); i++) { ++disp; vtkCell* cell = polyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (numPoints>1) { double* start = points->GetPoint(0); itk::Point itkStart; itkStart[0] = start[0]; itkStart[1] = start[1]; itkStart[2] = start[2]; itk::Index<3> idxStart; labelImage->TransformPhysicalPointToIndex(itkStart, idxStart); double* end = points->GetPoint(numPoints-1); itk::Point itkEnd; itkEnd[0] = end[0]; itkEnd[1] = end[1]; itkEnd[2] = end[2]; itk::Index<3> idxEnd; labelImage->TransformPhysicalPointToIndex(itkEnd, idxEnd); if ( labelImage->GetPixel(idxStart)==0 || labelImage->GetPixel(idxEnd)==0 ) { noConnection++; if (verbose) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = noConnPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } noConnCells->InsertNextCell(container); } } else { bool invalid = true; for (unsigned int i=0; i l = labelsvector.at(i); if ( (labelImage->GetPixel(idxStart)==l.first && labelImage->GetPixel(idxEnd)==l.second) || (labelImage->GetPixel(idxStart)==l.second && labelImage->GetPixel(idxEnd)==l.first) ) { 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; bundle->TransformPhysicalPointToIndex(itkP, idx); if ( bundle->GetPixel(idx) == 0 && bundle->GetLargestPossibleRegion().IsInside(idx) ) { outside=true; } } if (!outside) { validConnections++; if (detected.at(i)==false) validBundles++; detected.at(i) = true; invalid = false; vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = validPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; coverage->TransformPhysicalPointToIndex(itkP, idx); if ( coverage->GetLargestPossibleRegion().IsInside(idx) ) coverage->SetPixel(idx, 1); } validCells->InsertNextCell(container); } break; } } if (invalid==true) { invalidConnections++; int x = labelImage->GetPixel(idxStart)-1; int y = labelImage->GetPixel(idxEnd)-1; if (x>=0 && y>0 && x(matrix.cols()) && y(matrix.rows()) && (matrix[x][y]==0 || matrix[y][x]==0) ) { invalidBundles++; matrix[x][y]=1; matrix[y][x]=1; } if (verbose) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = invalidPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } invalidCells->InsertNextCell(container); } } } } } if (verbose) { vtkSmartPointer noConnPolyData = vtkSmartPointer::New(); noConnPolyData->SetPoints(noConnPoints); noConnPolyData->SetLines(noConnCells); mitk::FiberBundle::Pointer noConnFib = mitk::FiberBundle::New(noConnPolyData); - string ncfilename = outRoot; + std::string ncfilename = outRoot; ncfilename.append("_NC.fib"); mitk::IOUtil::Save(noConnFib.GetPointer(), ncfilename ); vtkSmartPointer invalidPolyData = vtkSmartPointer::New(); invalidPolyData->SetPoints(invalidPoints); invalidPolyData->SetLines(invalidCells); mitk::FiberBundle::Pointer invalidFib = mitk::FiberBundle::New(invalidPolyData); - string icfilename = outRoot; + std::string icfilename = outRoot; icfilename.append("_IC.fib"); mitk::IOUtil::Save(invalidFib.GetPointer(), icfilename ); vtkSmartPointer validPolyData = vtkSmartPointer::New(); validPolyData->SetPoints(validPoints); validPolyData->SetLines(validCells); mitk::FiberBundle::Pointer validFib = mitk::FiberBundle::New(validPolyData); - string vcfilename = outRoot; + std::string vcfilename = outRoot; vcfilename.append("_VC.fib"); mitk::IOUtil::Save(validFib.GetPointer(), vcfilename ); { typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outRoot+"_ABC.nrrd"); writer->SetInput(coverage); writer->Update(); } } // calculate coverage int wmVoxels = 0; int coveredVoxels = 0; itk::ImageRegionIterator it (coverage, coverage->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { bool wm = false; for (unsigned int i=0; iGetPixel(it.GetIndex())>0) { wm = true; wmVoxels++; break; } } if (wm && it.Get()>0) coveredVoxels++; ++it; } int numFibers = inputTractogram->GetNumFibers(); double nc = (double)noConnection/numFibers; double vc = (double)validConnections/numFibers; double ic = (double)invalidConnections/numFibers; if (numFibers==0) { nc = 0.0; vc = 0.0; ic = 0.0; } int vb = validBundles; int ib = invalidBundles; double abc = (double)coveredVoxels/wmVoxels; std::cout << "NC: " << nc; std::cout << "VC: " << vc; std::cout << "IC: " << ic; std::cout << "VB: " << vb; std::cout << "IB: " << ib; std::cout << "ABC: " << abc; - string logFile = outRoot; + std::string logFile = outRoot; logFile.append("_TRACTOMETER.csv"); ofstream file; file.open (logFile.c_str()); { - string sens = itksys::SystemTools::GetFilenameWithoutLastExtension(fibFile); + std::string sens = itksys::SystemTools::GetFilenameWithoutLastExtension(fibFile); if (!fileID.empty()) sens = fileID; sens.append(","); - sens.append(boost::lexical_cast(nc)); + sens.append(boost::lexical_cast(nc)); sens.append(","); - sens.append(boost::lexical_cast(vc)); + sens.append(boost::lexical_cast(vc)); sens.append(","); - sens.append(boost::lexical_cast(ic)); + sens.append(boost::lexical_cast(ic)); sens.append(","); - sens.append(boost::lexical_cast(validBundles)); + sens.append(boost::lexical_cast(validBundles)); sens.append(","); - sens.append(boost::lexical_cast(invalidBundles)); + sens.append(boost::lexical_cast(invalidBundles)); sens.append(","); - sens.append(boost::lexical_cast(abc)); + sens.append(boost::lexical_cast(abc)); sens.append(";\n"); file << sens; } file.close(); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/Quantification/Algorithms/mitkTractAnalyzer.cpp b/Modules/DiffusionImaging/Quantification/Algorithms/mitkTractAnalyzer.cpp index 9a708f8d52..7d0b7b9f16 100644 --- a/Modules/DiffusionImaging/Quantification/Algorithms/mitkTractAnalyzer.cpp +++ b/Modules/DiffusionImaging/Quantification/Algorithms/mitkTractAnalyzer.cpp @@ -1,218 +1,216 @@ /*=================================================================== 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 __mitkTractAnalyzer_cpp #define __mitkTractAnalyzer_cpp #include #include #include #include #include #include #include #include -using namespace std; - namespace mitk { TractAnalyzer::TractAnalyzer() { } void TractAnalyzer::MakeRoi() { m_CostSum = 0.0; int n = 0; if(m_PointSetNode.IsNotNull()) { n = m_PointSetNode->GetSize(); if(n==0) { mitkThrow() << "No points have been set yet."; } } else{ mitkThrow() << "No points have been set yet."; } std::string pathDescription = ""; std::vector< itk::Index<3> > totalPath; if(n>0) { for(int i=0; iProgress(); mitk::Point3D p = m_PointSetNode->GetPoint(i); mitk::Point3D p2 = m_PointSetNode->GetPoint(i+1); itk::Index<3> startPoint; itk::Index<3> endPoint; m_InputImage->GetGeometry()->WorldToIndex(p,startPoint); m_InputImage->GetGeometry()->WorldToIndex(p2,endPoint); MITK_INFO << "create roi"; std::vector< itk::Index<3> > path = CreateSegment(startPoint, endPoint); for(auto it = path.begin(); it != path.end(); it++) { itk::Index<3> ix = *it; if (!(ix==endPoint)) { mitk::ProgressBar::GetInstance()->Progress(); totalPath.push_back(ix); std::stringstream ss; ss << ix[0] << " " << ix[1] << " " << ix[2] << "\n"; pathDescription += ss.str(); } else { // Only when dealing with the last segment the last point should be added. This one will not occur // as the first point of the next roi segment. if(i == (n-2)) { totalPath.push_back(endPoint); std::stringstream ss; ss << endPoint[0] << " " << endPoint[1] << " " << endPoint[2] << "\n"; pathDescription += ss.str(); } } } } // save pathDescription to m_PathDescription m_PathDescription = pathDescription; FloatImageType::Pointer itkImg = FloatImageType::New(); mitk::CastToItkImage(m_InputImage, itkImg); CharImageType::Pointer roiImg = CharImageType::New(); roiImg->SetRegions(itkImg->GetLargestPossibleRegion().GetSize()); roiImg->SetOrigin(itkImg->GetOrigin()); roiImg->SetSpacing(itkImg->GetSpacing()); roiImg->SetDirection(itkImg->GetDirection()); roiImg->Allocate(); roiImg->FillBuffer(0); std::vector< itk::Index<3> > roi; std::vector< itk::Index<3> >::iterator it; for(it = totalPath.begin(); it != totalPath.end(); it++) { itk::Index<3> ix = *it; roiImg->SetPixel(ix, 1); roi.push_back(ix); } m_TbssRoi = mitk::TbssRoiImage::New(); m_TbssRoi->SetRoi(roi); m_TbssRoi->SetImage(roiImg); m_TbssRoi->InitializeFromImage(); } } std::vector< itk::Index<3> > TractAnalyzer::CreateSegment(itk::Index<3> startPoint, itk::Index<3> endPoint) { typedef itk::ShortestPathImageFilter ShortestPathFilterType; typedef itk::ShortestPathCostFunctionTbss CostFunctionType; FloatImageType::Pointer meanSkeleton; mitk::CastToItkImage(m_InputImage, meanSkeleton); // Only use the mitk image if(meanSkeleton) { CostFunctionType::Pointer costFunction = CostFunctionType::New(); costFunction->SetImage(meanSkeleton); costFunction->SetStartIndex(startPoint); costFunction->SetEndIndex(endPoint); costFunction->SetThreshold(m_Threshold); ShortestPathFilterType::Pointer pathFinder = ShortestPathFilterType::New(); pathFinder->SetCostFunction(costFunction); pathFinder->SetFullNeighborsMode(true); pathFinder->SetGraph_fullNeighbors(true); //pathFinder->SetCalcMode(ShortestPathFilterType::A_STAR); pathFinder->SetInput(meanSkeleton); pathFinder->SetStartIndex(startPoint); pathFinder->SetEndIndex(endPoint); pathFinder->Update(); double segmentCost = 0.0; std::vector< itk::Index<3> > path = pathFinder->GetVectorPath(); for(unsigned int i=0; i ix1 = path[i]; itk::Index<3> ix2 = path[i+1]; segmentCost += costFunction->GetCost(ix1, ix2); } m_CostSum += segmentCost; return pathFinder->GetVectorPath(); } return std::vector< itk::Index<3> >(); } } #endif diff --git a/Modules/DiffusionImaging/Quantification/cmdapps/DiffusionIndices.cpp b/Modules/DiffusionImaging/Quantification/cmdapps/DiffusionIndices.cpp index e53c28b780..a22074d5bf 100644 --- a/Modules/DiffusionImaging/Quantification/cmdapps/DiffusionIndices.cpp +++ b/Modules/DiffusionImaging/Quantification/cmdapps/DiffusionIndices.cpp @@ -1,145 +1,143 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include -using namespace std; - /** * Calculate indices derived from Odf or tensor images */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Diffusion Indices"); parser.setCategory("Diffusion Related Measures"); parser.setDescription("Computes requested diffusion related measures"); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input image (tensor, ODF or FSL/MRTrix SH-coefficient image)", us::Any(), false); parser.addArgument("index", "idx", mitkCommandLineParser::String, "Index:", "index (fa, gfa, ra, ad, rd, ca, l2, l3, md)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output:", "output file", us::Any(), false); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; - string inFileName = us::any_cast(parsedArgs["input"]); - string index = us::any_cast(parsedArgs["index"]); - string outFileName = us::any_cast(parsedArgs["outFile"]); + std::string inFileName = us::any_cast(parsedArgs["input"]); + std::string index = us::any_cast(parsedArgs["index"]); + std::string outFileName = us::any_cast(parsedArgs["outFile"]); - string ext = itksys::SystemTools::GetFilenameLastExtension(outFileName); + std::string ext = itksys::SystemTools::GetFilenameLastExtension(outFileName); if (ext.empty()) outFileName += ".nrrd"; try { // load input image std::vector infile = mitk::IOUtil::Load( inFileName ); if( (boost::algorithm::ends_with(inFileName, ".odf") || boost::algorithm::ends_with(inFileName, ".qbi")) && index=="gfa" ) { typedef itk::Vector OdfVectorType; typedef itk::Image ItkOdfImageType; mitk::OdfImage::Pointer mitkOdfImage = dynamic_cast(infile[0].GetPointer()); ItkOdfImageType::Pointer itk_odf = ItkOdfImageType::New(); mitk::CastToItkImage(mitkOdfImage, itk_odf); typedef itk::DiffusionOdfGeneralizedFaImageFilter GfaFilterType; GfaFilterType::Pointer gfaFilter = GfaFilterType::New(); gfaFilter->SetInput(itk_odf); gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); gfaFilter->Update(); itk::ImageFileWriter< itk::Image >::Pointer fileWriter = itk::ImageFileWriter< itk::Image >::New(); fileWriter->SetInput(gfaFilter->GetOutput()); fileWriter->SetFileName(outFileName); fileWriter->Update(); } else if( boost::algorithm::ends_with(inFileName, ".dti") ) { typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(infile[0].GetPointer()); ItkTensorImage::Pointer itk_dti = ItkTensorImage::New(); mitk::CastToItkImage(mitkTensorImage, itk_dti); typedef itk::TensorDerivedMeasurementsFilter MeasurementsType; MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itk_dti.GetPointer() ); if(index=="fa") measurementsCalculator->SetMeasure(MeasurementsType::FA); else if(index=="ra") measurementsCalculator->SetMeasure(MeasurementsType::RA); else if(index=="ad") measurementsCalculator->SetMeasure(MeasurementsType::AD); else if(index=="rd") measurementsCalculator->SetMeasure(MeasurementsType::RD); else if(index=="ca") measurementsCalculator->SetMeasure(MeasurementsType::CA); else if(index=="l2") measurementsCalculator->SetMeasure(MeasurementsType::L2); else if(index=="l3") measurementsCalculator->SetMeasure(MeasurementsType::L3); else if(index=="md") measurementsCalculator->SetMeasure(MeasurementsType::MD); else { MITK_WARN << "No valid diffusion index for input image (tensor image) defined"; return EXIT_FAILURE; } measurementsCalculator->Update(); itk::ImageFileWriter< itk::Image >::Pointer fileWriter = itk::ImageFileWriter< itk::Image >::New(); fileWriter->SetInput(measurementsCalculator->GetOutput()); fileWriter->SetFileName(outFileName); fileWriter->Update(); } else std::cout << "Diffusion index " << index << " not supported for supplied file type."; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/Quantification/cmdapps/MultishellMethods.cpp b/Modules/DiffusionImaging/Quantification/cmdapps/MultishellMethods.cpp index c8a9955245..231410751c 100644 --- a/Modules/DiffusionImaging/Quantification/cmdapps/MultishellMethods.cpp +++ b/Modules/DiffusionImaging/Quantification/cmdapps/MultishellMethods.cpp @@ -1,219 +1,216 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #include #include #include -using namespace std; - int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Multishell Methods"); parser.setCategory("Preprocessing Tools"); parser.setDescription(""); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("in", "i", mitkCommandLineParser::InputFile, "Input:", "input file", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output:", "output file", us::Any(), false); parser.addArgument("adc", "D", mitkCommandLineParser::Bool, "ADC:", "ADC Average", us::Any(), false); parser.addArgument("akc", "K", mitkCommandLineParser::Bool, "Kurtosis fit:", "Kurtosis Fit", us::Any(), false); parser.addArgument("biexp", "B", mitkCommandLineParser::Bool, "BiExp fit:", "BiExp fit", us::Any(), false); parser.addArgument("targetbvalue", "b", mitkCommandLineParser::String, "b Value:", "target bValue (mean, min, max)", us::Any(), false); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments - string inName = us::any_cast(parsedArgs["in"]); - string outName = us::any_cast(parsedArgs["out"]); + std::string inName = us::any_cast(parsedArgs["in"]); + std::string outName = us::any_cast(parsedArgs["out"]); bool applyADC = us::any_cast(parsedArgs["adc"]); bool applyAKC = us::any_cast(parsedArgs["akc"]); bool applyBiExp = us::any_cast(parsedArgs["biexp"]); - string targetType = us::any_cast(parsedArgs["targetbvalue"]); + std::string targetType = us::any_cast(parsedArgs["targetbvalue"]); try { std::cout << "Loading " << inName; mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {}); mitk::Image::Pointer dwi = mitk::IOUtil::LoadImage(inName, &functor); if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dwi ) ) { typedef itk::RadialMultishellToSingleshellImageFilter FilterType; typedef itk::DwiGradientLengthCorrectionFilter CorrectionFilterType; CorrectionFilterType::Pointer roundfilter = CorrectionFilterType::New(); roundfilter->SetRoundingValue( 1000 ); roundfilter->SetReferenceBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi )); roundfilter->SetReferenceGradientDirectionContainer(mitk::DiffusionPropertyHelper::GetGradientContainer(dwi)); roundfilter->Update(); dwi->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( roundfilter->GetNewBValue() ) ); dwi->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( roundfilter->GetOutputGradientDirectionContainer() ) ); // filter input parameter const mitk::DiffusionPropertyHelper::BValueMapType &originalShellMap = mitk::DiffusionPropertyHelper::GetBValueMap(dwi); mitk::DiffusionPropertyHelper::ImageType::Pointer vectorImage = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, vectorImage); const mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientContainer = mitk::DiffusionPropertyHelper::GetGradientContainer(dwi); const unsigned int &bValue = mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi ); // filter call vnl_vector bValueList(originalShellMap.size()-1); double targetBValue = bValueList.mean(); mitk::DiffusionPropertyHelper::BValueMapType::const_iterator it = originalShellMap.begin(); ++it; int i = 0 ; for(; it != originalShellMap.end(); ++it) bValueList.put(i++,it->first); if( targetType == "mean" ) targetBValue = bValueList.mean(); else if( targetType == "min" ) targetBValue = bValueList.min_value(); else if( targetType == "max" ) targetBValue = bValueList.max_value(); if(applyADC) { FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetOriginalBValueMap(originalShellMap); filter->SetOriginalBValue(bValue); itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); filter->SetFunctor(functor); filter->Update(); // create new DWI image mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() ); outImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( targetBValue ) ); outImage->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetTargetGradientDirections() ) ); mitk::DiffusionPropertyHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); mitk::IOUtil::Save(outImage, (outName + "_ADC.dwi").c_str()); } if(applyAKC) { FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetOriginalBValueMap(originalShellMap); filter->SetOriginalBValue(bValue); itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); filter->SetFunctor(functor); filter->Update(); // create new DWI image mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() ); outImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( targetBValue ) ); outImage->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetTargetGradientDirections() ) ); mitk::DiffusionPropertyHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); - mitk::IOUtil::Save(outImage, (string(outName) + "_AKC.dwi").c_str()); + mitk::IOUtil::Save(outImage, (std::string(outName) + "_AKC.dwi").c_str()); } if(applyBiExp) { FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetOriginalBValueMap(originalShellMap); filter->SetOriginalBValue(bValue); itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); filter->SetFunctor(functor); filter->Update(); // create new DWI image mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() ); outImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( targetBValue ) ); outImage->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetTargetGradientDirections() ) ); mitk::DiffusionPropertyHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); - mitk::IOUtil::Save(outImage, (string(outName) + "_BiExp.dwi").c_str()); + mitk::IOUtil::Save(outImage, (std::string(outName) + "_BiExp.dwi").c_str()); } } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/Quantification/cmdapps/QballReconstruction.cpp b/Modules/DiffusionImaging/Quantification/cmdapps/QballReconstruction.cpp index 22ffb67b83..dc12f4571a 100644 --- a/Modules/DiffusionImaging/Quantification/cmdapps/QballReconstruction.cpp +++ b/Modules/DiffusionImaging/Quantification/cmdapps/QballReconstruction.cpp @@ -1,266 +1,263 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkImage.h" #include "itkAnalyticalDiffusionQballReconstructionImageFilter.h" #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include -using namespace mitk; -using namespace std; - /** * Perform Q-ball reconstruction using a spherical harmonics basis */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input file", "input raw dwi (.dwi or .nii/.nii.gz)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output file", "output file", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "Spherical harmonics order", "spherical harmonics order", 4, true); parser.addArgument("b0Threshold", "t", mitkCommandLineParser::Int, "b0 threshold", "baseline image intensity threshold", 0, true); parser.addArgument("lambda", "r", mitkCommandLineParser::Float, "Lambda", "ragularization factor lambda", 0.006, true); parser.addArgument("csa", "csa", mitkCommandLineParser::Bool, "Constant solid angle consideration", "use constant solid angle consideration"); parser.addArgument("outputCoeffs", "shc", mitkCommandLineParser::Bool, "Output coefficients", "output file containing the SH coefficients"); parser.addArgument("mrtrix", "mb", mitkCommandLineParser::Bool, "MRtrix", "use MRtrix compatible spherical harmonics definition"); parser.setCategory("Signal Modelling"); parser.setTitle("Qball Reconstruction"); parser.setDescription(""); parser.setContributor("MIC"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; - std::string inFileName = us::any_cast(parsedArgs["input"]); - std::string outfilename = us::any_cast(parsedArgs["outFile"]); + std::string inFileName = us::any_cast(parsedArgs["input"]); + std::string outfilename = us::any_cast(parsedArgs["outFile"]); outfilename = itksys::SystemTools::GetFilenamePath(outfilename)+"/"+itksys::SystemTools::GetFilenameWithoutExtension(outfilename); int threshold = 0; if (parsedArgs.count("b0Threshold")) threshold = us::any_cast(parsedArgs["b0Threshold"]); int shOrder = 4; if (parsedArgs.count("shOrder")) shOrder = us::any_cast(parsedArgs["shOrder"]); float lambda = 0.006; if (parsedArgs.count("lambda")) lambda = us::any_cast(parsedArgs["lambda"]); int normalization = 0; if (parsedArgs.count("csa") && us::any_cast(parsedArgs["csa"])) normalization = 6; bool outCoeffs = false; if (parsedArgs.count("outputCoeffs")) outCoeffs = us::any_cast(parsedArgs["outputCoeffs"]); bool mrTrix = false; if (parsedArgs.count("mrtrix")) mrTrix = us::any_cast(parsedArgs["mrtrix"]); try { mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {}); std::vector< mitk::BaseData::Pointer > infile = mitk::IOUtil::Load(inFileName, &functor); - Image::Pointer dwi = dynamic_cast(infile.at(0).GetPointer()); + mitk::Image::Pointer dwi = dynamic_cast(infile.at(0).GetPointer()); mitk::DiffusionPropertyHelper propertyHelper(dwi); propertyHelper.AverageRedundantGradients(0.001); propertyHelper.InitializeImage(); mitk::OdfImage::Pointer image = mitk::OdfImage::New(); mitk::Image::Pointer coeffsImage = mitk::Image::New(); std::cout << "SH order: " << shOrder; std::cout << "lambda: " << lambda; std::cout << "B0 threshold: " << threshold; switch ( shOrder ) { case 4: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 6: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 8: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 10: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 12: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetThreshold( threshold ); filter->SetLambda(lambda); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } default: { std::cout << "Supplied SH order not supported. Using default order of 4."; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); } } std::string coeffout = outfilename; coeffout += "_shcoeffs.nrrd"; outfilename += ".odf"; mitk::IOUtil::Save(image, outfilename); if (outCoeffs) mitk::IOUtil::Save(coeffsImage, coeffout); } catch ( itk::ExceptionObject &err) { std::cout << "Exception: " << err; } catch ( std::exception err) { std::cout << "Exception: " << err.what(); } catch ( ... ) { std::cout << "Exception!"; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/Quantification/cmdapps/TensorDerivedMapsExtraction.cpp b/Modules/DiffusionImaging/Quantification/cmdapps/TensorDerivedMapsExtraction.cpp index 3568ab653e..26c3538bc4 100644 --- a/Modules/DiffusionImaging/Quantification/cmdapps/TensorDerivedMapsExtraction.cpp +++ b/Modules/DiffusionImaging/Quantification/cmdapps/TensorDerivedMapsExtraction.cpp @@ -1,181 +1,179 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkImage.h" #include #include "mitkITKImageImport.h" #include #include #include #include #include #include "itkTensorDerivedMeasurementsFilter.h" #include "itkDiffusionTensor3DReconstructionImageFilter.h" #include "mitkCommandLineParser.h" #include #include #include -using namespace std; - typedef short DiffusionPixelType; typedef double TTensorPixelType; static void ExtractMapsAndSave(mitk::TensorImage::Pointer tensorImage, std::string filename, std::string postfix = "") { mitk::Image* image = dynamic_cast (tensorImage.GetPointer()); typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(image, itkvol); typedef itk::TensorDerivedMeasurementsFilter MeasurementsType; MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); mitk::Image::Pointer map = mitk::Image::New(); // FA measurementsCalculator->SetMeasure(MeasurementsType::FA); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::Save(map, filename + "_FA" + postfix + ".nrrd"); // MD measurementsCalculator->SetMeasure(MeasurementsType::MD); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::Save(map, filename + "_MD" + postfix + ".nrrd"); // AD measurementsCalculator->SetMeasure(MeasurementsType::AD); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::Save(map, filename + "_AD" + postfix + ".nrrd"); // CA measurementsCalculator->SetMeasure(MeasurementsType::CA); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::Save(map, filename + "_CA" + postfix + ".nrrd"); // RA measurementsCalculator->SetMeasure(MeasurementsType::RA); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::Save(map, filename + "_RA" + postfix + ".nrrd"); // RD measurementsCalculator->SetMeasure(MeasurementsType::RD); measurementsCalculator->Update(); map->InitializeByItk( measurementsCalculator->GetOutput() ); map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); mitk::IOUtil::Save(map, filename + "_RD" + postfix + ".nrrd"); } int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("help", "h", mitkCommandLineParser::String, "Help", "Show this help text"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input file", "input dwi file", us::Any(),false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output folder", "output folder and base name, e.g. /tmp/outPatient1 ", us::Any(),false); parser.setTitle("Tensor Derived Maps Extraction"); parser.setCategory("Diffusion Related Measures"); parser.setDescription(""); parser.setContributor("MIC"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) { std::cout << parser.helpText(); return EXIT_SUCCESS; } - std::string inputFile = us::any_cast(parsedArgs["input"]); - std::string baseFileName = us::any_cast(parsedArgs["out"]); + std::string inputFile = us::any_cast(parsedArgs["input"]); + std::string baseFileName = us::any_cast(parsedArgs["out"]); std::string dtiFileName = "_dti.dti"; mitk::Image::Pointer diffusionImage = dynamic_cast(mitk::IOUtil::Load(inputFile)[0].GetPointer()); if (diffusionImage.IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(diffusionImage)) // does nullptr pointer check make sense after static cast ? { MITK_ERROR << "Invalid Input Image. Must be DWI. Aborting."; return -1; } typedef itk::DiffusionTensor3DReconstructionImageFilter< DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter = TensorReconstructionImageFilterType::New(); mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientContainerCopy = mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::New(); for( mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::ConstIterator it = mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImage)->Begin(); it != mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImage)->End(); it++) { gradientContainerCopy->push_back(it.Value()); } mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(diffusionImage, itkVectorImagePointer); tensorReconstructionFilter->SetGradientImage( gradientContainerCopy, itkVectorImagePointer ); tensorReconstructionFilter->SetBValue( mitk::DiffusionPropertyHelper::GetReferenceBValue( diffusionImage ) ); tensorReconstructionFilter->SetThreshold(50); tensorReconstructionFilter->Update(); typedef itk::Image, 3> TensorImageType; TensorImageType::Pointer tensorImage = tensorReconstructionFilter->GetOutput(); tensorImage->SetDirection( itkVectorImagePointer->GetDirection() ); mitk::TensorImage::Pointer tensorImageMitk = mitk::TensorImage::New(); tensorImageMitk->InitializeByItk(tensorImage.GetPointer()); tensorImageMitk->SetVolume( tensorImage->GetBufferPointer() ); itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< double >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< double >, 3 > >::New(); writer->SetInput(tensorReconstructionFilter->GetOutput()); writer->SetFileName(baseFileName + dtiFileName); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); ExtractMapsAndSave(tensorImageMitk,baseFileName); return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/Quantification/cmdapps/TensorReconstruction.cpp b/Modules/DiffusionImaging/Quantification/cmdapps/TensorReconstruction.cpp index 412fcb32aa..06f82a4903 100644 --- a/Modules/DiffusionImaging/Quantification/cmdapps/TensorReconstruction.cpp +++ b/Modules/DiffusionImaging/Quantification/cmdapps/TensorReconstruction.cpp @@ -1,101 +1,99 @@ /*=================================================================== 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 "mitkImage.h" #include #include "mitkBaseData.h" #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include -using namespace mitk; -using namespace std; /** * Convert files from one ending to the other */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input file", "input raw dwi (.dwi or .fsl/.fslgz)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output file", "output file", us::Any(), false); parser.addArgument("b0Threshold", "t", mitkCommandLineParser::Int, "b0 threshold", "baseline image intensity threshold", 0, true); parser.setCategory("Signal Modelling"); parser.setTitle("Tensor Reconstruction"); parser.setDescription(""); parser.setContributor("MIC"); - map parsedArgs = parser.parseArguments(argc, argv); + std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; - std::string inFileName = us::any_cast(parsedArgs["input"]); - std::string outfilename = us::any_cast(parsedArgs["outFile"]); + std::string inFileName = us::any_cast(parsedArgs["input"]); + std::string outfilename = us::any_cast(parsedArgs["outFile"]); outfilename = itksys::SystemTools::GetFilenamePath(outfilename)+"/"+itksys::SystemTools::GetFilenameWithoutExtension(outfilename); outfilename += ".dti"; int threshold = 0; if (parsedArgs.count("b0Threshold")) threshold = us::any_cast(parsedArgs["b0Threshold"]); try { - Image::Pointer dwi = dynamic_cast(IOUtil::Load(inFileName)[0].GetPointer()); + mitk::Image::Pointer dwi = dynamic_cast(mitk::IOUtil::Load(inFileName)[0].GetPointer()); mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue( mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi )); filter->SetThreshold(threshold); filter->Update(); // Save tensor image itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::New(); writer->SetInput(filter->GetOutput()); writer->SetFileName(outfilename); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); } catch ( itk::ExceptionObject &err) { std::cout << "Exception: " << err; } catch ( std::exception err) { std::cout << "Exception: " << err.what(); } catch ( ... ) { std::cout << "Exception!"; } return EXIT_SUCCESS; } diff --git a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidDefaultRegistrationAlgorithm.h b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidDefaultRegistrationAlgorithm.h index 48d312c47c..750fecde0a 100644 --- a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidDefaultRegistrationAlgorithm.h +++ b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidDefaultRegistrationAlgorithm.h @@ -1,134 +1,134 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkMultiModalRigidDefaultRegistrationAlgorithm_h #define mitkMultiModalRigidDefaultRegistrationAlgorithm_h #include "mapDiscreteElements.h" #include "mapITKEuler3DMattesMIMultiResRegistrationAlgorithmTemplate.h" #include "mapConfigure.h" #include "mitkMultiModalRigidDefaultRegistrationAlgorithm_ProfileResource.h" namespace mitk { /** \class MultiModalRigidDefaultRegistrationAlgorithm * Algorithm is used as default solution for multimodal rigid problem statements in DIPP. * Uses 3 Resolution levels. By default initializes via image centers */ template class MultiModalRigidDefaultRegistrationAlgorithm : - public map::algorithm::boxed::ITKEuler3DMattesMIMultiResRegistrationAlgorithm >, map::algorithm::itk::NoComponentInitializationPolicy> + public ::map::algorithm::boxed::ITKEuler3DMattesMIMultiResRegistrationAlgorithm >, ::map::algorithm::itk::NoComponentInitializationPolicy> { public: typedef MultiModalRigidDefaultRegistrationAlgorithm Self; - typedef map::algorithm::boxed::ITKEuler3DMattesMIMultiResRegistrationAlgorithm >, map::algorithm::itk::NoComponentInitializationPolicy> + typedef ::map::algorithm::boxed::ITKEuler3DMattesMIMultiResRegistrationAlgorithm >, ::map::algorithm::itk::NoComponentInitializationPolicy> Superclass; typedef ::itk::SmartPointer Pointer; typedef ::itk::SmartPointer ConstPointer; itkTypeMacro(MultiModalRigidDefaultRegistrationAlgorithm, ITKEuler3DMattesMIMultiResRegistrationAlgorithm); mapNewAlgorithmMacro(Self); protected: MultiModalRigidDefaultRegistrationAlgorithm() { }; virtual ~MultiModalRigidDefaultRegistrationAlgorithm() { }; void configureAlgorithm() { Superclass::configureAlgorithm(); this->setResolutionLevels(3); this->_preInitialize = true; this->_useCenterOfGravity = false; //optimizer typename Superclass::ConcreteOptimizerType::ScalesType scales(6); scales[0] = 1.0; scales[1] = 1.0; scales[2] = 1.0; scales[3] = 1.0 / 1000; scales[4] = 1.0 / 1000; scales[5] = 1.0 / 1000; this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetScales(scales); this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetMaximumStepLength(3.00); this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetMinimumStepLength(0.5); this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetNumberOfIterations(200); this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetRelaxationFactor(0.8); this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetGradientMagnitudeTolerance(1e-4); //metric this->getConcreteMetricControl()->getConcreteMetric()->SetNumberOfHistogramBins(30); this->getConcreteMetricControl()->getConcreteMetric()->SetUseAllPixels(true); this->getConcreteMetricControl()->getConcreteMetric()->ReinitializeSeed(); this->getConcreteMetricControl()->getConcreteMetric()->UseExplicitPDFDerivativesOn(); } void doInterLevelSetup() { Superclass::doInterLevelSetup(); if (this->getCurrentLevel() == 0) { typename Superclass::OptimizerBaseType::SVNLOptimizerBaseType::ScalesType scales(6); scales[0] = 10.0; scales[1] = 10.0; scales[2] = 10.0; scales[3] = 1.0 / 10000; scales[4] = 1.0 / 10000; scales[5] = 1.0 / 10000; this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetScales(scales); } else { this->getConcreteMetricControl()->getConcreteMetric()->SetUseAllPixels(false); typename Superclass::OptimizerBaseType::SVNLOptimizerBaseType::ScalesType scales(6); scales[0] = 1.0; scales[1] = 1.0; scales[2] = 1.0; scales[3] = 1.0 / 1000; scales[4] = 1.0 / 1000; scales[5] = 1.0 / 1000; this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetScales(scales); unsigned int nrOfSmpl = ::itk::Math::Round (this->getMovingImage()->GetLargestPossibleRegion().GetNumberOfPixels() * 0.15); this->getConcreteMetricControl()->getConcreteMetric()->SetNumberOfSpatialSamples(nrOfSmpl); } }; private: MultiModalRigidDefaultRegistrationAlgorithm(const Self& source); //purposely not implemented void operator=(const Self&); //purposely not implemented }; } #endif diff --git a/Modules/MatchPointRegistration/mitkMAPRegistrationWrapper.h b/Modules/MatchPointRegistration/mitkMAPRegistrationWrapper.h index 3bc49d990e..62a93c5108 100644 --- a/Modules/MatchPointRegistration/mitkMAPRegistrationWrapper.h +++ b/Modules/MatchPointRegistration/mitkMAPRegistrationWrapper.h @@ -1,272 +1,272 @@ /*=================================================================== 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 mitkMAPRegistrationWrapper_h #define mitkMAPRegistrationWrapper_h //MITK #include #include //MatchPoint #include #include #include #include //MITK #include "MitkMatchPointRegistrationExports.h" namespace mitk { /*! \brief MAPRegistrationWrapper Wrapper class to allow the handling of MatchPoint registration objects as mitk data (e.g. in the data explorer). */ class MITKMATCHPOINTREGISTRATION_EXPORT MAPRegistrationWrapper: public mitk::BaseData { public: mitkClassMacro( MAPRegistrationWrapper, BaseData ); itkNewMacro( Self ); /** * Empty implementation, since the MAPRegistrationWrapper doesn't * support the requested region concept */ virtual void SetRequestedRegionToLargestPossibleRegion(); /** * Empty implementation, since the MAPRegistrationWrapper doesn't * support the requested region concept */ virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); /** * Empty implementation, since the MAPRegistrationWrapper doesn't * support the requested region concept */ virtual bool VerifyRequestedRegion(); /** * Empty implementation, since the MAPRegistrationWrapper doesn't * support the requested region concept */ virtual void SetRequestedRegion(const itk::DataObject*); /*! @brief Gets the number of moving dimensions @pre valid registration instance must be set. */ virtual unsigned int GetMovingDimensions() const; /*! @brief Gets the number of target dimensions @pre valid registration instance must be set. */ virtual unsigned int GetTargetDimensions() const; /*! typedefs used for the TagMap */ typedef ::map::core::RegistrationBase::TagType TagType; typedef ::map::core::RegistrationBase::ValueType ValueType; typedef ::map::core::RegistrationBase::TagMapType TagMapType; /*! @brief returns the tags associated with this registration @pre valid registration instance must be set. @return a TagMapType containing tags */ const TagMapType& GetTags() const; /*! @brief returns the tag value for a specific tag @pre valid registration instance must be set. @return the success of the operation */ bool GetTagValue(const TagType & tag, ValueType & value) const; /*! Indicates @pre valid registration instance must be set. @return is the target representation limited @retval true if target representation is limited. Thus it is not guaranteed that all inverse mapping operations will succeed. Transformation(inverse kernel) covers only a part of the target space). @retval false if target representation is not limited. Thus it is guaranteed that all inverse mapping operations will succeed. */ bool HasLimitedTargetRepresentation() const; /*! @pre valid registration instance must be set. @return is the moving representation limited @retval true if moving representation is limited. Thus it is not guaranteed that all direct mapping operations will succeed. Transformation(direct kernel) covers only a part of the moving space). @retval false if moving representation is not limited. Thus it is guaranteed that all direct mapping operations will succeed. */ bool HasLimitedMovingRepresentation() const; /*! Helper function that maps a mitk point (of arbitrary dimension) from moving space to target space. @remarks The operation might fail, if the moving and target dimension of the registration is not equal to the dimensionality of the passed points. @pre valid registration instance must be set. @param inPoint Reference pointer to a MovingPointType @param outPoint pointer to a TargetPointType @return success of operation. @pre direct mapping kernel must be defined */ template bool MapPoint(const ::itk::Point& inPoint, ::itk::Point& outPoint) const { typedef typename ::map::core::continuous::Elements::PointType MAPMovingPointType; typedef typename ::map::core::continuous::Elements::PointType MAPTargetPointType; if (m_spRegistration.IsNull()) { mapDefaultExceptionMacro(<< "Error. Cannot map point. Wrapper points to invalid registration (nullptr). Point: " << inPoint); } bool result = false; if ((this->GetMovingDimensions() == VMovingDim)&&(this->GetTargetDimensions() == VTargetDim)) { MAPMovingPointType tempInP; MAPTargetPointType tempOutP; tempInP.CastFrom(inPoint); - typedef map::core::Registration CastedRegType; + typedef ::map::core::Registration CastedRegType; const CastedRegType* pCastedReg = dynamic_cast(m_spRegistration.GetPointer()); if (!pCastedReg) { mapDefaultExceptionMacro(<< "Error. Cannot map point. Registration has invalid dimension. Point: " << inPoint); } result = pCastedReg->mapPoint(tempInP,tempOutP); if (result) { outPoint.CastFrom(tempOutP); } } return result; }; /*! Helper function that maps a mitk point (of arbitrary dimension) from target space to moving space @remarks The operation might faile, if the moving and target dimension of the registration is not equal to the dimensionalities of the passed points. @pre valid registration instance must be set. @param inPoint pointer to a TargetPointType @param outPoint pointer to a MovingPointType @return success of operation */ template bool MapPointInverse(const ::itk::Point & inPoint, ::itk::Point & outPoint) const { typedef typename ::map::core::continuous::Elements::PointType MAPMovingPointType; typedef typename ::map::core::continuous::Elements::PointType MAPTargetPointType; if (m_spRegistration.IsNull()) { mapDefaultExceptionMacro(<< "Error. Cannot map point. Wrapper points to invalid registration (nullptr). Point: " << inPoint); } bool result = false; if ((this->GetMovingDimensions() == VMovingDim)&&(this->GetTargetDimensions() == VTargetDim)) { MAPTargetPointType tempInP; MAPMovingPointType tempOutP; tempInP.CastFrom(inPoint); - typedef map::core::Registration CastedRegType; + typedef ::map::core::Registration CastedRegType; const CastedRegType* pCastedReg = dynamic_cast(m_spRegistration.GetPointer()); if (!pCastedReg) { mapDefaultExceptionMacro(<< "Error. Cannot map point. Registration has invalid dimension. Point: " << inPoint); } result = pCastedReg->mapPointInverse(tempInP,tempOutP); if (result) { outPoint.CastFrom(tempOutP); } } return result; }; /*! returns the direct FieldRepresentationDescriptor which defines the part of the moving space that is guaranteed to be mapped by the direct mapping kernel. This member converts the internal MatchPoint type into a mitk::Geometry3D. @pre valid registration instance must be set. @return smart pointer to a FieldRepresentationDescriptor for the supported registration space in the moving domain. May be null if the direct registration kernel is global and thus not limited. If there is a limitation, the retun value is not nullptr. @retval nullptr no field representation set/requested by the creating registration algorithm. */ mitk::Geometry3D GetDirectFieldRepresentation() const; /*! returns the inverse FieldRepresentationDescriptor which defines the part of the target space that is guaranteed to be mapped by the inverse mapping kernel. This member converts the internal MatchPoint type into a mitk::Geometry3D. @pre valid registration instance must be set. @return a const FieldRepresentationDescriptor for the supported registration space in the target domain. May be null if the inverse registration kernel is global and thus not limited. If there is a limitation, the retun value is not nullptr. @retval nullptr no field representation set/requested by the creating registration algorithm. */ mitk::Geometry3D GetInverseFieldRepresentation() const; /*! forces kernel to precompute, even if it is a LazyFieldKernel @pre valid registration instance must be set. @todo der LazyFieldBasedRegistrationKernel muss dann die stong guarantee erfllen beim erzeugen des feldes ansonsten ist die garantie dieser methode nicht erfllbar. noch berprfen */ void PrecomputeDirectMapping(); /*! forces kernel to precompute, even if it is a LazyFieldKernel @pre valid registration instance must be set. @todo der LazyFieldBasedRegistrationKernel muss dann die stong guarantee erfllen beim erzeugen des feldes ansonsten ist die garantie dieser methode nicht erfllbar. noch berprfen */ void PrecomputeInverseMapping(); - map::core::RegistrationBase* GetRegistration(); - const map::core::RegistrationBase* GetRegistration() const; + ::map::core::RegistrationBase* GetRegistration(); + const ::map::core::RegistrationBase* GetRegistration() const; - void SetRegistration(map::core::RegistrationBase* pReg); + void SetRegistration(::map::core::RegistrationBase* pReg); protected: virtual void PrintSelf (std::ostream &os, itk::Indent indent) const; MAPRegistrationWrapper(); virtual ~MAPRegistrationWrapper(); - map::core::RegistrationBase::Pointer m_spRegistration; + ::map::core::RegistrationBase::Pointer m_spRegistration; private: MAPRegistrationWrapper& operator = (const MAPRegistrationWrapper&); MAPRegistrationWrapper(const MAPRegistrationWrapper&); }; } #endif diff --git a/Modules/MatchPointRegistrationUI/Qmitk/QmitkRegistrationJob.h b/Modules/MatchPointRegistrationUI/Qmitk/QmitkRegistrationJob.h index a1ffdd634b..cfbf51d556 100644 --- a/Modules/MatchPointRegistrationUI/Qmitk/QmitkRegistrationJob.h +++ b/Modules/MatchPointRegistrationUI/Qmitk/QmitkRegistrationJob.h @@ -1,105 +1,105 @@ /*=================================================================== 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 __QMITK_REGISTRATION_JOB_H #define __QMITK_REGISTRATION_JOB_H // QT #include #include // ITK #include // MITK #include "mitkUIDHelper.h" #include #include #include // MatchPoint #include #include #include #include #include #include class MITKMATCHPOINTREGISTRATIONUI_EXPORT QmitkRegistrationJob : public QObject, public QRunnable { // 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: - QmitkRegistrationJob(map::algorithm::RegistrationAlgorithmBase *pAlgorithm); + QmitkRegistrationJob(::map::algorithm::RegistrationAlgorithmBase *pAlgorithm); ~QmitkRegistrationJob(); void run(); signals: void Finished(); void Error(QString err); void RegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob *pJob); void AlgorithmIterated(QString info, bool hasIterationCount, unsigned long currentIteration); void LevelChanged(QString info, bool hasLevelCount, unsigned long currentLevel); void AlgorithmStatusChanged(QString info); void AlgorithmInfo(QString info); public: // Inputs mitk::BaseData::ConstPointer m_spTargetData; mitk::BaseData::ConstPointer m_spMovingData; mitk::Image::ConstPointer m_spTargetMask; mitk::Image::ConstPointer m_spMovingMask; // job settings bool m_MapEntity; bool m_StoreReg; bool m_ErrorOccured; std::string m_JobName; mitk::NodeUIDType m_TargetDataUID; mitk::NodeUIDType m_MovingDataUID; mitk::NodeUIDType m_TargetMaskDataUID; mitk::NodeUIDType m_MovingMaskDataUID; - const map::algorithm::RegistrationAlgorithmBase *GetLoadedAlgorithm() const; + const ::map::algorithm::RegistrationAlgorithmBase *GetLoadedAlgorithm() const; protected: - typedef map::algorithm::facet::IterativeAlgorithmInterface IIterativeAlgorithm; - typedef map::algorithm::facet::MultiResRegistrationAlgorithmInterface IMultiResAlgorithm; + typedef ::map::algorithm::facet::IterativeAlgorithmInterface IIterativeAlgorithm; + typedef ::map::algorithm::facet::MultiResRegistrationAlgorithmInterface IMultiResAlgorithm; // Result registration. - map::core::RegistrationBase::Pointer m_spResultRegistration; + ::map::core::RegistrationBase::Pointer m_spResultRegistration; mitk::DataNode::Pointer m_spRegNode; // mapped image. May be null if m_MapEntity is false. mitk::DataNode::Pointer m_spMappedImageNode; ::itk::MemberCommand::Pointer m_spCommand; unsigned long m_ObserverID; - map::algorithm::RegistrationAlgorithmBase::Pointer m_spLoadedAlgorithm; + ::map::algorithm::RegistrationAlgorithmBase::Pointer m_spLoadedAlgorithm; // Helper functions const mitk::Image *GetTargetDataAsImage() const; const mitk::Image *GetMovingDataAsImage() const; void OnMapAlgorithmEvent(::itk::Object *, const itk::EventObject &event); }; #endif diff --git a/Plugins/org.blueberry.ui.qt/src/actions/berryMenuManager.cpp b/Plugins/org.blueberry.ui.qt/src/actions/berryMenuManager.cpp index 55918a7107..e181208629 100644 --- a/Plugins/org.blueberry.ui.qt/src/actions/berryMenuManager.cpp +++ b/Plugins/org.blueberry.ui.qt/src/actions/berryMenuManager.cpp @@ -1,679 +1,679 @@ /*=================================================================== BlueBerry Platform Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "berryMenuManager.h" #include "berryIContributionManagerOverrides.h" #include "berryQActionProperties.h" #include "berrySubContributionItem.h" #include #include class QMenuProxy { public: QMenu* menu; QMenuBar* menuBar; enum Type { MenuBar, Menu }; QMenuProxy(Type type, QWidget* parent = nullptr) : menu(nullptr), menuBar(nullptr) { switch (type) { - case MenuBar: menuBar = new QMenuBar(parent); - case Menu: menu = new QMenu(parent); + case MenuBar: menuBar = new QMenuBar(parent); break; + case Menu: menu = new QMenu(parent); break; } } bool isMenuBar() const { return menuBar != nullptr; } void setTitle(const QString& title) { if (menu) menu->setTitle(title); } void setIcon(const QIcon& icon) { if (menu) menu->setIcon(icon); } QList actions() const { return menu ? menu->actions() : menuBar->actions(); } void removeAction(QAction* action) { menu ? menu->removeAction(action) : menuBar->removeAction(action); } bool isEnabled() const { return menu ? menu->isEnabled() : menuBar->isEnabled(); } void setEnabled(bool enabled) { menu ? menu->setEnabled(enabled) : menuBar->setEnabled(enabled); } QAction* getParentItem() const { return menu ? menu->menuAction() : nullptr; } }; namespace berry { struct NullOverrides: public IContributionManagerOverrides { public: int GetEnabled(const IContributionItem* /*item*/) const override { return -1; } int GetVisible(const IContributionItem* /*item*/) const override { return -1; } }; void MenuManager::HandleAboutToShow() { if (this->removeAllWhenShown) { this->RemoveAll(); } emit AboutToShow(this); this->Update(false, false); } void MenuManager::HandleAboutToHide() { emit AboutToHide(this); } MenuManager::MenuManager(const QString& text, const QString& id) : id(id), menu(nullptr), menuItem(nullptr) , menuText(text), parent(nullptr) , removeAllWhenShown(false), visible(true) { } MenuManager::MenuManager(const QString& text, const QIcon& image, const QString& id) : id(id), menu(nullptr), menuItem(nullptr) , menuText(text), image(image) , parent(nullptr), removeAllWhenShown(false), visible(true) { } bool MenuManager::IsDirty() const { return ContributionManager::IsDirty(); } MenuManager::~MenuManager() { delete menu; } QMenu* MenuManager::CreateContextMenu(QWidget* parent) { if (!menu) { menu = new QMenuProxy(QMenuProxy::Menu, parent); this->InitializeMenu(); } return menu->menu; } QMenuBar* MenuManager::CreateMenuBar(QWidget* parent) { if (!menu) { menu = new QMenuProxy(QMenuProxy::MenuBar, parent); this->Update(false); } return menu->menuBar; } void MenuManager::AddMenuListener(QObject* listener) { this->connect(this, SIGNAL(AboutToShow(IMenuManager*)), listener, SLOT(MenuAboutToShow(IMenuManager*))); this->connect(this, SIGNAL(AboutToHide(IMenuManager*)), listener, SLOT(MenuAboutToHide(IMenuManager*))); } void MenuManager::RemoveMenuListener(QObject* listener) { this->disconnect(listener); } void MenuManager::Fill(QStatusBar* /*parent*/) { } void MenuManager::Fill(QToolBar* /*parent*/, QAction* /*before*/) { } void MenuManager::Fill(QMenu* parent, QAction* before) { this->FillMenu(parent, before); } void MenuManager::Fill(QMenuBar* parent, QAction* before) { this->FillMenu(parent, before); } void MenuManager::FillMenu(QWidget* parent, QAction* before) { if (!menuItem) { menuItem = new QAction(parent); if (parent) { parent->insertAction(before, menuItem); } menuItem->setText(GetMenuText()); menuItem->setIcon(image); if(!menu) { menu = new QMenuProxy(QMenuProxy::Menu, parent); } if (!menu->isMenuBar()) menuItem->setMenu(menu->menu); this->InitializeMenu(); this->SetDirty(true); } } IMenuManager::Pointer MenuManager::FindMenuUsingPath(const QString& path) const { IContributionItem::Pointer item(this->FindUsingPath(path)); if (IMenuManager::Pointer manager = item.Cast()) { return manager; } return IMenuManager::Pointer(nullptr); } IContributionItem::Pointer MenuManager::FindUsingPath(const QString& path) const { QString id(path); QString rest; int separator = path.indexOf('/'); if (separator != -1) { id = path.left(separator); rest = path.mid(separator + 1); } else { return ContributionManager::Find(path); } IContributionItem::Pointer item(ContributionManager::Find(id)); if (IMenuManager::Pointer manager = item.Cast()) { return manager->FindUsingPath(rest); } return IContributionItem::Pointer(nullptr); } QString MenuManager::GetId() const { return id; } QMenu* MenuManager::GetMenu() const { return menu->menu; } QString MenuManager::GetMenuText() const { if (definitionId == "") { return menuText; } // ExternalActionManager::ICallback callback = ExternalActionManager // .getInstance().getCallback(); // if (callback != null) // { // String shortCut = callback.getAcceleratorText(definitionId); // if (shortCut == null) // { // return menuText; // } // return menuText + "\t" + shortCut; //$NON-NLS-1$ // } return menuText; } QIcon MenuManager::GetImage() const { return image; } SmartPointer MenuManager::GetOverrides() { if (!overrides) { if (!parent) { overrides = new NullOverrides(); } else { overrides = parent->GetOverrides(); } ContributionManager::SetOverrides(overrides); } return overrides; } IContributionManager* MenuManager::GetParent() const { return parent; } bool MenuManager::GetRemoveAllWhenShown() const { return removeAllWhenShown; } bool MenuManager::IsDynamic() const { return false; } bool MenuManager::IsEnabled() const { return true; } bool MenuManager::IsGroupMarker() const { return false; } bool MenuManager::IsSeparator() const { return false; } bool MenuManager::IsVisible() const { if (!visible) { return false; // short circuit calculations in this case } if (removeAllWhenShown) { // we have no way of knowing if the menu has children return true; } // menus aren't visible if all of its children are invisible (or only contains visible separators). bool visibleChildren = false; foreach(IContributionItem::Pointer item, this->GetItems()) { if (item->IsVisible() && !item->IsSeparator()) { visibleChildren = true; break; } } return visibleChildren; } void MenuManager::MarkDirty() { ContributionManager::MarkDirty(); // Can't optimize by short-circuiting when the first dirty manager is encountered, // since non-visible children are not even processed. // That is, it's possible to have a dirty sub-menu under a non-dirty parent menu // even after the parent menu has been updated. // If items are added/removed in the sub-menu, we still need to propagate the dirty flag up, // even if the sub-menu is already dirty, since the result of isVisible() may change // due to the added/removed items. IContributionManager* p = this->GetParent(); if (p) { p->MarkDirty(); } } void MenuManager::SaveWidgetState() { } void MenuManager::SetOverrides(SmartPointer newOverrides) { overrides = newOverrides; ContributionManager::SetOverrides(overrides); } void MenuManager::SetParent(IContributionManager* manager) { parent = manager; } void MenuManager::SetRemoveAllWhenShown(bool removeAll) { this->removeAllWhenShown = removeAll; } void MenuManager::SetVisible(bool visible) { this->visible = visible; } void MenuManager::SetCommandId(const QString& definitionId) { this->definitionId = definitionId; } void MenuManager::Update() { this->UpdateMenuItem(); } void MenuManager::Update(const QString& property) { QList items = GetItems(); for (int i = 0; i < items.size(); i++) { items[i]->Update(property); } if (menu != nullptr && menu->getParentItem() != nullptr) { if (QActionProperties::TEXT == property) { QString text = GetMenuText(); if (!text.isNull()) { menu->getParentItem()->setText(text); } } else if (QActionProperties::IMAGE == property && !image.isNull()) { menu->getParentItem()->setIcon(image); } } } void MenuManager::Update(bool force) { this->Update(force, false); } void MenuManager::UpdateAll(bool force) { this->Update(force, true); } void MenuManager::InitializeMenu() { menu->setTitle(GetMenuText()); menu->setIcon(GetImage()); if (!menu->isMenuBar()) { this->connect(menu->menu, SIGNAL(aboutToShow()), SLOT(HandleAboutToShow())); this->connect(menu->menu, SIGNAL(aboutToHide()), SLOT(HandleAboutToHide())); } // Don't do an update(true) here, in case menu is never opened. // Always do it lazily in handleAboutToShow(). } void MenuManager::UpdateMenuItem() { if (menuItem && menu) { bool enabled = removeAllWhenShown || menu->actions().size() > 0; if (menu->isEnabled() != enabled) { menuItem->setEnabled(enabled); } } } void MenuManager::DoItemFill(IContributionItem::Pointer ci, QAction* before) { if (menu->isMenuBar()) { ci->Fill(menu->menuBar, before); } else { ci->Fill(menu->menu, before); } } void MenuManager::Update(bool force, bool recursive) { if (ContributionManager::IsDirty() || force) { if (menu) { // clean contains all active items without double separators QList items = this->GetItems(); QList clean; IContributionItem::Pointer separator; foreach (IContributionItem::Pointer ci, items) { if (!ci->IsVisible()) { continue; } if (ci->IsSeparator()) { // delay creation until necessary // (handles both adjacent separators, and separator at end) separator = ci; } else { if (separator) { if (clean.size() > 0) { clean.push_back(separator); } separator = nullptr; } clean.push_back(ci); } } // remove obsolete (removed or non active) QList mi = menu->actions(); for (int i = 0; i < mi.size(); i++) { Object::Pointer data = mi[i]->data().value(); if (!data || !clean.contains(data.Cast())) { menu->removeAction(mi[i]); } else if (IContributionItem::Pointer ci = data.Cast()) { if(ci->IsDynamic() && ci->IsDirty()) { menu->removeAction(mi[i]); delete mi[i]; } } } // add new mi = menu->actions(); int srcIx = 0; int destIx = 0; for (QList::Iterator e = clean.begin(); e != clean.end(); ++e) { IContributionItem::Pointer src(*e); IContributionItem::Pointer dest; // get corresponding item in widget if (srcIx < mi.size()) { dest = mi[srcIx]->data().value().Cast(); } else { dest = nullptr; } if (dest && src == dest) { srcIx++; destIx++; } else if (dest && dest->IsSeparator() && src->IsSeparator()) { mi[srcIx]->setData(QVariant::fromValue(src)); srcIx++; destIx++; } else { int start = menu->actions().size(); //qDebug() << "***** Filling item destIx = " << destIx << " (size: " << start << ")"; this->DoItemFill(src, destIx >= start ? nullptr : menu->actions().at(destIx)); int newItems = menu->actions().size() - start; //qDebug() << "***** New items: " << newItems; for (int i = 0; i < newItems; ++i) { menu->actions().at(destIx++)->setData(QVariant::fromValue(src)); } } // May be we can optimize this call. If the menu has just // been created via the call src.fill(fMenuBar, destIx) then // the menu has already been updated with update(true) // (see MenuManager). So if force is true we do it again. But // we can't set force to false since then information for the // sub sub menus is lost. if (recursive) { IContributionItem::Pointer item(src); if (SubContributionItem::Pointer subItem = item.Cast()) { item = subItem->GetInnerItem(); } if (IMenuManager::Pointer mm = item.Cast()) { mm->UpdateAll(force); } } } // remove any old menu items not accounted for for (; srcIx < mi.size(); srcIx++) { menu->removeAction(mi[srcIx]); delete mi[srcIx]; } this->SetDirty(false); } } else { // I am not dirty. Check if I must recursivly walk down the hierarchy. if (recursive) { foreach (IContributionItem::Pointer ci, this->GetItems()) { if (IMenuManager::Pointer mm = ci.Cast()) { if (mm->IsVisible()) { mm->UpdateAll(force); } } } } } this->UpdateMenuItem(); } void MenuManager::DumpActionInfo(QMenuProxy* menu) { if (menu->isMenuBar()) { //qDebug() << "QMenuBar [" << menu->menuBar << "]"; DumpActionInfo(menu->menuBar, 1); } else { //qDebug() << "QMenu [" << menu->menu << "]" << menu->menu; DumpActionInfo(menu->menu, 1); } } void MenuManager::DumpActionInfo(QWidget* widget, int level) { QString indent = " |"; for (int i = 0; i < level; ++i) indent += "--"; foreach(QAction* action, widget->actions()) { qDebug() << qPrintable(indent) << action->text() << "[" << action << "]"; if (action->menu()) { DumpActionInfo(action->menu(), level+1); } } } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.cpp index d84069a36e..2eff6caac7 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.cpp @@ -1,125 +1,123 @@ /*=================================================================== 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 "QmitkFreeSurferParcellationHandler.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include -using namespace mitk; -using namespace std; US_USE_NAMESPACE QmitkFreeSurferParcellationHandler::QmitkFreeSurferParcellationHandler() : m_LastPixelvalue( 0 ), m_Translator( mitk::FreeSurferParcellationTranslator::New() ) { us::ServiceProperties props; props["name"] = std::string("ParcellationHandler"); us::ModuleContext* context = us::ModuleRegistry::GetModule(1)->GetModuleContext(); m_ServiceRegistration = context->RegisterService( this, props); } QmitkFreeSurferParcellationHandler::~QmitkFreeSurferParcellationHandler() { m_ServiceRegistration.Unregister(); } void QmitkFreeSurferParcellationHandler::Notify(InteractionEvent *interactionEvent, bool isHandled) { Q_UNUSED( isHandled ) BaseRenderer* sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = static_cast(interactionEvent); TNodePredicateDataType::Pointer isImageData = TNodePredicateDataType::New(); DataStorage::SetOfObjects::ConstPointer nodes = sender->GetDataStorage()->GetSubset(isImageData).GetPointer(); if(nodes.IsNull() || nodes->size() <= 0) return; Point3D worldposition = positionEvent->GetPositionInWorld(); for (unsigned int x = 0; x < nodes->size(); x++) { DataNode::Pointer node = static_cast( nodes->at(x) ); if(node.IsNotNull()) { Image::Pointer image = dynamic_cast( node->GetData() ); if( image.IsNotNull() && image->GetGeometry()->IsInside(worldposition) ) { - string typeStr = image->GetPixelType().GetComponentTypeAsString(); + std::string typeStr = image->GetPixelType().GetComponentTypeAsString(); int value = 0; try { if( typeStr == "int" ) { ImagePixelReadAccessor readAccess( image ); value = static_cast( readAccess.GetPixelByWorldCoordinates( worldposition ) ); } else if( typeStr == "unsigned_char" ) { ImagePixelReadAccessor readAccess( image ); value = static_cast( readAccess.GetPixelByWorldCoordinates( worldposition ) ); } else if( typeStr == "short" ) { ImagePixelReadAccessor readAccess( image ); value = static_cast( readAccess.GetPixelByWorldCoordinates( worldposition ) ); } else if( typeStr == "float" ) { ImagePixelReadAccessor readAccess( image ); value = static_cast( readAccess.GetPixelByWorldCoordinates( worldposition ) ); } else { MITK_WARN("QmitkFreeSurferParcellationHandler") << "Pixeltype '" << typeStr << "' is not implemented yet."; return; } emit this->changed( value ); QString name( QString::fromStdString( this->m_Translator->GetName( value ) ) ); emit this->changed( name ); MousePressEvent::Pointer mouseEvent = dynamic_cast( interactionEvent ); MouseWheelEvent::Pointer wheelEvent = dynamic_cast( interactionEvent ); if(mouseEvent.IsNotNull()) { emit this->clicked( value ); emit this->clicked( name ); } if( wheelEvent.IsNotNull() ) { emit this->scrolled( value ); emit this->scrolled( name ); } return; // exit loop } catch( const Exception& ex ) { MITK_WARN("QmitkFreeSurferParcellationHandler") << "Could not access image for reading pixelvalue due to: " << ex.GetDescription(); } catch(...) { MITK_WARN("QmitkFreeSurferParcellationHandler") << "Could not access image for reading pixelvalue."; } } } } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.h index dd143b8e12..d4a112ec6f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.h @@ -1,99 +1,97 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkFreeSurferParcellationHandler_h #define QmitkFreeSurferParcellationHandler_h // MITK #include #include #include // Qt #include -using namespace mitk; -using namespace std; /** * @brief This handler returns either the pixelvalue or anatomical label of the current position of the crosshair inside a visible parcellation. * If no parcellation is visible no data is thrown. */ class QmitkFreeSurferParcellationHandler : public QObject, public EventStateMachine, public InteractionEventObserver { Q_OBJECT public: mitkClassMacro(QmitkFreeSurferParcellationHandler, DataInteractor) itkNewMacro(QmitkFreeSurferParcellationHandler) QmitkFreeSurferParcellationHandler(); ~QmitkFreeSurferParcellationHandler(); // Signals Q_SIGNALS: /** * @brief Emitted when pixelValue has changed * @param value of the current selected pixel */ void changed(int); /** * @brief Emitted when pixelValue has changed * @param anatomical label */ void changed(const QString &); /** * @brief Thrown if and only if the left mousebutton is pressed and pixelValue has changed * @param value of the selected pixel */ void clicked(int); /** * @brief Thrown if and only if the left mousebutton is pressed and pixelValue has changed * @param anatomical label */ void clicked(const QString &); /** * @brief Thrown if mouse scrolled and pixelvalue changed * @param value of the selected pixel */ void scrolled(int); /** * @brief Thrown if mouse scrolled and anatomcial labl changed * @param anatomical label */ void scrolled(const QString &); // Methods protected: virtual void Notify(InteractionEvent* interactionEvent,bool isHandled); // Members protected: /** * @brief The current pixelvalue */ int m_LastPixelvalue; /** * @brief Translator for coverting pixelvalue into anatomical label */ mitk::FreeSurferParcellationTranslator::Pointer m_Translator; /** * Reference to the service registration of the observer, * it is needed to unregister the observer on unload. */ us::ServiceRegistration m_ServiceRegistration; }; #endif //QmitkPixelvalueHandler_h diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp index 4b7c2b94ed..a6bd567f01 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp @@ -1,2903 +1,2903 @@ /*=================================================================== 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 "QmitkFiberfoxView.h" // MITK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RAPIDXML_NO_EXCEPTIONS #include #include #include #include #include "usModuleRegistry.h" #include #include #include #include #include #include #include #include #include #include "mitkNodePredicateDataType.h" #include #include #include #include #define _USE_MATH_DEFINES #include QmitkFiberfoxWorker::QmitkFiberfoxWorker(QmitkFiberfoxView* view) : m_View(view) { } void QmitkFiberfoxWorker::run() { try{ m_View->m_TractsToDwiFilter->Update(); } catch( ... ) { } m_View->m_Thread.quit(); } const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview"; QmitkFiberfoxView::QmitkFiberfoxView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImageNode( nullptr ) , m_Worker(this) , m_ThreadIsRunning(false) { m_Worker.moveToThread(&m_Thread); connect(&m_Thread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_Thread, SIGNAL(started()), &m_Worker, SLOT(run())); connect(&m_Thread, SIGNAL(finished()), this, SLOT(AfterThread())); // connect(&m_Thread, SIGNAL(terminated()), this, SLOT(AfterThread())); m_SimulationTimer = new QTimer(this); } void QmitkFiberfoxView::KillThread() { MITK_INFO << "Aborting DWI simulation."; m_TractsToDwiFilter->SetAbortGenerateData(true); m_Controls->m_AbortSimulationButton->setEnabled(false); m_Controls->m_AbortSimulationButton->setText("Aborting simulation ..."); } void QmitkFiberfoxView::BeforeThread() { m_SimulationTime = QTime::currentTime(); m_SimulationTimer->start(100); m_Controls->m_AbortSimulationButton->setVisible(true); m_Controls->m_GenerateImageButton->setVisible(false); m_Controls->m_SimulationStatusText->setVisible(true); m_ThreadIsRunning = true; } void QmitkFiberfoxView::AfterThread() { UpdateSimulationStatus(); m_SimulationTimer->stop(); m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_AbortSimulationButton->setEnabled(true); m_Controls->m_AbortSimulationButton->setText("Abort simulation"); m_Controls->m_GenerateImageButton->setVisible(true); m_ThreadIsRunning = false; QString statusText; FiberfoxParameters parameters; mitk::Image::Pointer mitkImage = mitk::Image::New(); statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); if (m_TractsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } parameters = m_TractsToDwiFilter->GetParameters(); mitkImage = mitk::GrabItkImageMemory( m_TractsToDwiFilter->GetOutput() ); mitkImage->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( parameters.m_SignalGen.GetGradientDirections() )); mitkImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( parameters.m_SignalGen.m_Bvalue )); mitk::DiffusionPropertyHelper propertyHelper( mitkImage ); propertyHelper.InitializeImage(); parameters.m_Misc.m_ResultNode->SetData( mitkImage ); GetDataStorage()->Add(parameters.m_Misc.m_ResultNode, parameters.m_Misc.m_ParentNode); parameters.m_Misc.m_ResultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(m_TractsToDwiFilter->GetLevelWindow()) ); if (m_Controls->m_VolumeFractionsBox->isChecked()) { std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = m_TractsToDwiFilter->GetVolumeFractions(); for (unsigned int k=0; kInitializeByItk(volumeFractions.at(k).GetPointer()); image->SetVolume(volumeFractions.at(k)->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("CompartmentVolume-"+QString::number(k).toStdString()); GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode); } if (m_TractsToDwiFilter->GetPhaseImage().IsNotNull()) { mitk::Image::Pointer phaseImage = mitk::Image::New(); itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkPhase = m_TractsToDwiFilter->GetPhaseImage(); phaseImage = mitk::GrabItkImageMemory( itkPhase.GetPointer() ); mitk::DataNode::Pointer phaseNode = mitk::DataNode::New(); phaseNode->SetData( phaseImage ); phaseNode->SetName("Phase Image"); GetDataStorage()->Add(phaseNode, parameters.m_Misc.m_ResultNode); } if (m_TractsToDwiFilter->GetKspaceImage().IsNotNull()) { mitk::Image::Pointer image = mitk::Image::New(); itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkImage = m_TractsToDwiFilter->GetKspaceImage(); image = mitk::GrabItkImageMemory( itkImage.GetPointer() ); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("k-Space"); GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode); } { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(m_TractsToDwiFilter->GetCoilPointset()); node->SetName("Coil Positions"); node->SetProperty("pointsize", mitk::FloatProperty::New(parameters.m_SignalGen.m_ImageSpacing[0]/4)); node->SetProperty("color", mitk::ColorProperty::New(0, 1, 0)); GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode); } } m_TractsToDwiFilter = nullptr; if (parameters.m_Misc.m_AfterSimulationMessage.size()>0) QMessageBox::information( nullptr, "Warning", parameters.m_Misc.m_AfterSimulationMessage.c_str()); mitk::BaseData::Pointer basedata = parameters.m_Misc.m_ResultNode->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } if (!parameters.m_Misc.m_OutputPath.empty()) { try{ QString outputFileName(parameters.m_Misc.m_OutputPath.c_str()); outputFileName += parameters.m_Misc.m_ResultNode->GetName().c_str(); outputFileName.replace(QString("."), QString("_")); SaveParameters(outputFileName+".ffp"); outputFileName += ".dwi"; QString status("Saving output image to "); status += outputFileName; m_Controls->m_SimulationStatusText->append(status); mitk::IOUtil::Save(mitkImage, outputFileName.toStdString()); m_Controls->m_SimulationStatusText->append("File saved successfully."); } catch (itk::ExceptionObject &e) { QString status("Exception during DWI writing: "); status += e.GetDescription(); m_Controls->m_SimulationStatusText->append(status); } catch (...) { m_Controls->m_SimulationStatusText->append("Unknown exception during DWI writing!"); } } parameters.m_SignalGen.m_FrequencyMap = nullptr; } void QmitkFiberfoxView::UpdateSimulationStatus() { QString statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); if (QString::compare(m_SimulationStatusText,statusText)!=0) { m_Controls->m_SimulationStatusText->clear(); m_Controls->m_SimulationStatusText->setText(statusText); QScrollBar *vScrollBar = m_Controls->m_SimulationStatusText->verticalScrollBar(); vScrollBar->triggerAction(QScrollBar::SliderToMaximum); } } // Destructor QmitkFiberfoxView::~QmitkFiberfoxView() { delete m_SimulationTimer; } void QmitkFiberfoxView::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::QmitkFiberfoxViewControls; m_Controls->setupUi( parent ); m_Controls->m_StickWidget1->setVisible(true); m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); m_Controls->m_BallWidget1->setVisible(true); m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_BallWidget2->SetT1(4500); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_AstrosticksWidget2->SetT1(4500); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_DotWidget2->SetT1(4500); m_Controls->m_PrototypeWidget1->setVisible(false); m_Controls->m_PrototypeWidget2->setVisible(false); m_Controls->m_PrototypeWidget3->setVisible(false); m_Controls->m_PrototypeWidget4->setVisible(false); m_Controls->m_PrototypeWidget3->SetMinFa(0.0); m_Controls->m_PrototypeWidget3->SetMaxFa(0.15); m_Controls->m_PrototypeWidget4->SetMinFa(0.0); m_Controls->m_PrototypeWidget4->SetMaxFa(0.15); m_Controls->m_PrototypeWidget3->SetMinAdc(0.0); m_Controls->m_PrototypeWidget3->SetMaxAdc(0.001); m_Controls->m_PrototypeWidget4->SetMinAdc(0.003); m_Controls->m_PrototypeWidget4->SetMaxAdc(0.004); m_Controls->m_Comp2FractionFrame->setVisible(false); m_Controls->m_Comp4FractionFrame->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_VarianceBox->setVisible(false); m_Controls->m_NoiseFrame->setVisible(false); m_Controls->m_GhostFrame->setVisible(false); m_Controls->m_DistortionsFrame->setVisible(false); m_Controls->m_EddyFrame->setVisible(false); m_Controls->m_SpikeFrame->setVisible(false); m_Controls->m_AliasingFrame->setVisible(false); m_Controls->m_MotionArtifactFrame->setVisible(false); m_ParameterFile = QDir::currentPath()+"/param.ffp"; m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_SimulationStatusText->setVisible(false); m_Controls->m_FrequencyMapBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp1VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp2VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp3VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp4VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_MaskComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TemplateComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_FiberBundleComboBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isFiberBundle = mitk::TNodePredicateDataType::New(); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New( ); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("Odfmage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isOdf); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer isNonDiffMitkImage = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer isBinaryMitkImage = mitk::NodePredicateAnd::New( isNonDiffMitkImage, isBinaryPredicate ); m_Controls->m_FrequencyMapBox->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp1VolumeFraction->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp1VolumeFraction->SetZeroEntryText("--"); m_Controls->m_Comp2VolumeFraction->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp2VolumeFraction->SetZeroEntryText("--"); m_Controls->m_Comp3VolumeFraction->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp3VolumeFraction->SetZeroEntryText("--"); m_Controls->m_Comp4VolumeFraction->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp4VolumeFraction->SetZeroEntryText("--"); m_Controls->m_MaskComboBox->SetPredicate(isBinaryMitkImage); m_Controls->m_MaskComboBox->SetZeroEntryText("--"); m_Controls->m_TemplateComboBox->SetPredicate(isMitkImage); m_Controls->m_TemplateComboBox->SetZeroEntryText("--"); m_Controls->m_FiberBundleComboBox->SetPredicate(isFiberBundle); m_Controls->m_FiberBundleComboBox->SetZeroEntryText("--"); QFont font; font.setFamily("Courier"); font.setStyleHint(QFont::Monospace); font.setFixedPitch(true); font.setPointSize(7); m_Controls->m_SimulationStatusText->setFont(font); connect( m_SimulationTimer, SIGNAL(timeout()), this, SLOT(UpdateSimulationStatus()) ); connect((QObject*) m_Controls->m_AbortSimulationButton, SIGNAL(clicked()), (QObject*) this, SLOT(KillThread())); connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage())); connect((QObject*) m_Controls->m_GenerateFibersButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFibers())); connect((QObject*) m_Controls->m_CircleButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnDrawROI())); connect((QObject*) m_Controls->m_FlipButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnFlipButton())); connect((QObject*) m_Controls->m_JoinBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(JoinBundles())); connect((QObject*) m_Controls->m_VarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double))); connect((QObject*) m_Controls->m_DistributionBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnDistributionChanged(int))); connect((QObject*) m_Controls->m_FiberDensityBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberDensityChanged(int))); connect((QObject*) m_Controls->m_FiberSamplingBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnFiberSamplingChanged(double))); connect((QObject*) m_Controls->m_TensionBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnTensionChanged(double))); connect((QObject*) m_Controls->m_ContinuityBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnContinuityChanged(double))); connect((QObject*) m_Controls->m_BiasBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnBiasChanged(double))); connect((QObject*) m_Controls->m_AddNoise, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddNoise(int))); connect((QObject*) m_Controls->m_AddGhosts, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGhosts(int))); connect((QObject*) m_Controls->m_AddDistortions, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddDistortions(int))); connect((QObject*) m_Controls->m_AddEddy, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddEddy(int))); connect((QObject*) m_Controls->m_AddSpikes, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddSpikes(int))); connect((QObject*) m_Controls->m_AddAliasing, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddAliasing(int))); connect((QObject*) m_Controls->m_AddMotion, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddMotion(int))); connect((QObject*) m_Controls->m_ConstantRadiusBox, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnConstantRadius(int))); connect((QObject*) m_Controls->m_CopyBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(CopyBundles())); connect((QObject*) m_Controls->m_TransformBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(ApplyTransform())); connect((QObject*) m_Controls->m_AlignOnGrid, SIGNAL(clicked()), (QObject*) this, SLOT(AlignOnGrid())); connect((QObject*) m_Controls->m_Compartment1Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp1ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment2Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp2ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment3Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp3ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment4Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp4ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox_2, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); connect((QObject*) m_Controls->m_SaveParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(SaveParameters())); connect((QObject*) m_Controls->m_LoadParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(LoadParameters())); connect((QObject*) m_Controls->m_OutputPathButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetOutputPath())); connect((QObject*) m_Controls->m_MaskComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnMaskSelected(int))); connect((QObject*) m_Controls->m_TemplateComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnTemplateSelected(int))); connect((QObject*) m_Controls->m_FiberBundleComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnFibSelected(int))); } } void QmitkFiberfoxView::OnMaskSelected(int ) { UpdateGui(); } void QmitkFiberfoxView::OnTemplateSelected(int ) { UpdateGui(); } void QmitkFiberfoxView::OnFibSelected(int ) { UpdateGui(); } template< class ScalarType > FiberfoxParameters< ScalarType > QmitkFiberfoxView::UpdateImageParameters(bool all, bool save) { FiberfoxParameters< ScalarType > parameters; parameters.m_Misc.m_OutputPath = ""; parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); parameters.m_Misc.m_CheckAdvancedSignalOptionsBox = m_Controls->m_AdvancedOptionsBox_2->isChecked(); parameters.m_Misc.m_CheckOutputVolumeFractionsBox = m_Controls->m_VolumeFractionsBox->isChecked(); parameters.m_Misc.m_AfterSimulationMessage = ""; - string outputPath = m_Controls->m_SavePathEdit->text().toStdString(); + std::string outputPath = m_Controls->m_SavePathEdit->text().toStdString(); if (outputPath.compare("-")!=0) { parameters.m_Misc.m_OutputPath = outputPath; parameters.m_Misc.m_OutputPath += "/"; } switch(m_Controls->m_DistributionBox->currentIndex()) { case 0: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; break; case 1: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; break; default: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; } parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value(); parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value(); parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value(); parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value(); parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value(); parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value(); parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value(); parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value(); parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value(); parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value(); parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value(); parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value(); parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value(); parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value(); parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value(); if (!all) return parameters; if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer mitkMaskImage = dynamic_cast(m_Controls->m_MaskComboBox->GetSelectedNode()->GetData()); mitk::CastToItkImage(mitkMaskImage, parameters.m_SignalGen.m_MaskImage); itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(parameters.m_SignalGen.m_MaskImage); duplicator->Update(); parameters.m_SignalGen.m_MaskImage = duplicator->GetOutput(); } if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode())) // use parameters of selected DWI { mitk::Image::Pointer dwi = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection(); parameters.m_SignalGen.m_Bvalue = static_cast(dwi->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); parameters.m_SignalGen.SetGradienDirections(static_cast( dwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()); } else if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) // use geometry of selected image { mitk::Image::Pointer img = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); itk::Image< float, 3 >::Pointer itkImg = itk::Image< float, 3 >::New(); CastToItkImage< itk::Image< float, 3 > >(img, itkImg); parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); } else if (parameters.m_SignalGen.m_MaskImage.IsNotNull()) // use geometry of mask image { ItkUcharImgType::Pointer itkImg = parameters.m_SignalGen.m_MaskImage; parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); } else // use GUI parameters { parameters.m_SignalGen.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value()); parameters.m_SignalGen.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value()); parameters.m_SignalGen.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value()); parameters.m_SignalGen.m_ImageSpacing[0] = m_Controls->m_SpacingX->value(); parameters.m_SignalGen.m_ImageSpacing[1] = m_Controls->m_SpacingY->value(); parameters.m_SignalGen.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value(); parameters.m_SignalGen.m_ImageOrigin[0] = parameters.m_SignalGen.m_ImageSpacing[0]/2; parameters.m_SignalGen.m_ImageOrigin[1] = parameters.m_SignalGen.m_ImageSpacing[1]/2; parameters.m_SignalGen.m_ImageOrigin[2] = parameters.m_SignalGen.m_ImageSpacing[2]/2; parameters.m_SignalGen.m_ImageDirection.SetIdentity(); parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); parameters.m_SignalGen.GenerateGradientHalfShell(); } // signal relaxation parameters.m_SignalGen.m_DoSimulateRelaxation = false; if (m_Controls->m_RelaxationBox->isChecked() && (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull() || save) ) { parameters.m_SignalGen.m_DoSimulateRelaxation = true; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(true)); parameters.m_Misc.m_ArtifactModelString += "_RELAX"; } parameters.m_SignalGen.m_SimulateKspaceAcquisition = parameters.m_SignalGen.m_DoSimulateRelaxation; // N/2 ghosts parameters.m_Misc.m_CheckAddGhostsBox = m_Controls->m_AddGhosts->isChecked(); if (m_Controls->m_AddGhosts->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_GHOST"; parameters.m_SignalGen.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(parameters.m_SignalGen.m_KspaceLineOffset)); } else parameters.m_SignalGen.m_KspaceLineOffset = 0; // Aliasing parameters.m_Misc.m_CheckAddAliasingBox = m_Controls->m_AddAliasing->isChecked(); if (m_Controls->m_AddAliasing->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_ALIASING"; parameters.m_SignalGen.m_CroppingFactor = (100-m_Controls->m_WrapBox->value())/100; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value())); } // Spikes parameters.m_Misc.m_CheckAddSpikesBox = m_Controls->m_AddSpikes->isChecked(); if (m_Controls->m_AddSpikes->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_SignalGen.m_Spikes = m_Controls->m_SpikeNumBox->value(); parameters.m_SignalGen.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value(); parameters.m_Misc.m_ArtifactModelString += "_SPIKES"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(parameters.m_SignalGen.m_Spikes)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(parameters.m_SignalGen.m_SpikeAmplitude)); } // gibbs ringing parameters.m_SignalGen.m_DoAddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked(); if (m_Controls->m_AddGibbsRinging->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true)); parameters.m_Misc.m_ArtifactModelString += "_RINGING"; } // add distortions parameters.m_Misc.m_CheckAddDistortionsBox = m_Controls->m_AddDistortions->isChecked(); if (m_Controls->m_AddDistortions->isChecked() && m_Controls->m_FrequencyMapBox->GetSelectedNode().IsNotNull()) { mitk::DataNode::Pointer fMapNode = m_Controls->m_FrequencyMapBox->GetSelectedNode(); mitk::Image* img = dynamic_cast(fMapNode->GetData()); ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New(); CastToItkImage< ItkDoubleImgType >(img, itkImg); if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull()) // use geometry of frequency map { parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); } if (parameters.m_SignalGen.m_ImageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) && parameters.m_SignalGen.m_ImageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) && parameters.m_SignalGen.m_ImageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2)) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(itkImg); duplicator->Update(); parameters.m_SignalGen.m_FrequencyMap = duplicator->GetOutput(); parameters.m_Misc.m_ArtifactModelString += "_DISTORTED"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true)); } } parameters.m_SignalGen.m_EddyStrength = 0; parameters.m_Misc.m_CheckAddEddyCurrentsBox = m_Controls->m_AddEddy->isChecked(); if (m_Controls->m_AddEddy->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_SignalGen.m_EddyStrength = m_Controls->m_EddyGradientStrength->value(); parameters.m_Misc.m_ArtifactModelString += "_EDDY"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(parameters.m_SignalGen.m_EddyStrength)); } // Motion parameters.m_SignalGen.m_DoAddMotion = false; parameters.m_SignalGen.m_DoRandomizeMotion = m_Controls->m_RandomMotion->isChecked(); parameters.m_SignalGen.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value(); parameters.m_SignalGen.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value(); parameters.m_SignalGen.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value(); parameters.m_SignalGen.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value(); parameters.m_SignalGen.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value(); parameters.m_SignalGen.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value(); parameters.m_SignalGen.m_MotionVolumes.clear(); parameters.m_Misc.m_MotionVolumesBox = m_Controls->m_MotionVolumesBox->text().toStdString(); if ( m_Controls->m_AddMotion->isChecked() && (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull() || save) ) { parameters.m_SignalGen.m_DoAddMotion = true; parameters.m_Misc.m_ArtifactModelString += "_MOTION"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(parameters.m_SignalGen.m_DoRandomizeMotion)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(parameters.m_SignalGen.m_Translation[0])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(parameters.m_SignalGen.m_Translation[1])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(parameters.m_SignalGen.m_Translation[2])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[0])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[1])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[2])); if ( parameters.m_Misc.m_MotionVolumesBox == "random" ) { for ( size_t i=0; i < parameters.m_SignalGen.GetNumVolumes(); ++i ) { parameters.m_SignalGen.m_MotionVolumes.push_back( bool( rand()%2 ) ); } MITK_DEBUG << "QmitkFiberfoxView.cpp: Case m_Misc.m_MotionVolumesBox == \"random\"."; } else if ( ! parameters.m_Misc.m_MotionVolumesBox.empty() ) { - stringstream stream( parameters.m_Misc.m_MotionVolumesBox ); + std::stringstream stream( parameters.m_Misc.m_MotionVolumesBox ); std::vector numbers; int number = std::numeric_limits::max(); while( stream >> number ) { if( number < std::numeric_limits::max() ) { numbers.push_back( number ); } } // If a list of negative numbers is given: if( *(std::min_element( numbers.begin(), numbers.end() )) < 0 && *(std::max_element( numbers.begin(), numbers.end() )) <= 0 ) // cave: -0 == +0 { for ( size_t i=0; i < parameters.m_SignalGen.GetNumVolumes(); ++i ) { parameters.m_SignalGen.m_MotionVolumes.push_back( true ); } // set all true except those given. for( auto iter = std::begin( numbers ); iter != std::end( numbers ); ++iter ) { if ( -(*iter) < (int)parameters.m_SignalGen.GetNumVolumes() && -(*iter) >= 0 ) { parameters.m_SignalGen.m_MotionVolumes.at( -(*iter) ) = false; } } MITK_DEBUG << "QmitkFiberfoxView.cpp: Case list of negative numbers."; } // If a list of positive numbers is given: else if( *(std::min_element( numbers.begin(), numbers.end() )) >= 0 && *(std::max_element( numbers.begin(), numbers.end() )) >= 0 ) { for ( size_t i=0; i < parameters.m_SignalGen.GetNumVolumes(); ++i ) { parameters.m_SignalGen.m_MotionVolumes.push_back( false ); } // set all false except those given. for( auto iter = std::begin( numbers ); iter != std::end( numbers ); ++iter ) { if ( *iter < (int)parameters.m_SignalGen.GetNumVolumes() && *iter >= 0 ) { parameters.m_SignalGen.m_MotionVolumes.at( *iter ) = true; } } MITK_DEBUG << "QmitkFiberfoxView.cpp: Case list of positive numbers."; } else { MITK_ERROR << "QmitkFiberfoxView.cpp: Inconsistent list of numbers in m_MotionVolumesBox."; } } else { MITK_WARN << "QmitkFiberfoxView.cpp: Unrecognised parameters.m_Misc.m_MotionVolumesBox: " << parameters.m_Misc.m_MotionVolumesBox; parameters.m_Misc.m_MotionVolumesBox = "random"; // set default. for (unsigned int i=0; im_AcquisitionTypeBox->currentIndex(); parameters.m_SignalGen.m_CoilSensitivityProfile = (SignalGenerationParameters::CoilSensitivityProfile)m_Controls->m_CoilSensBox->currentIndex(); parameters.m_SignalGen.m_NumberOfCoils = m_Controls->m_NumCoilsBox->value(); parameters.m_SignalGen.m_PartialFourier = m_Controls->m_PartialFourier->value(); parameters.m_SignalGen.m_ReversePhase = m_Controls->m_ReversePhaseBox->isChecked(); parameters.m_SignalGen.m_tLine = m_Controls->m_LineReadoutTimeBox->value(); parameters.m_SignalGen.m_tInhom = m_Controls->m_T2starBox->value(); parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value(); parameters.m_SignalGen.m_tRep = m_Controls->m_TRbox->value(); parameters.m_SignalGen.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked(); parameters.m_SignalGen.m_AxonRadius = m_Controls->m_FiberRadius->value(); parameters.m_SignalGen.m_SignalScale = m_Controls->m_SignalScaleBox->value(); double voxelVolume = parameters.m_SignalGen.m_ImageSpacing[0] * parameters.m_SignalGen.m_ImageSpacing[1] * parameters.m_SignalGen.m_ImageSpacing[2]; if ( parameters.m_SignalGen.m_SignalScale*voxelVolume > itk::NumericTraits::max()*0.75 ) { parameters.m_SignalGen.m_SignalScale = itk::NumericTraits::max()*0.75/voxelVolume; m_Controls->m_SignalScaleBox->setValue(parameters.m_SignalGen.m_SignalScale); QMessageBox::information( nullptr, "Warning", "Maximum signal exceeding data type limits. Automatically adjusted to " + QString::number(parameters.m_SignalGen.m_SignalScale) + " to obtain a maximum signal of 75% of the data type maximum." " Relaxation and other effects that affect the signal intensities are not accounted for."); } // Noise parameters.m_Misc.m_CheckAddNoiseBox = m_Controls->m_AddNoise->isChecked(); parameters.m_SignalGen.m_NoiseVariance = 0; if (m_Controls->m_AddNoise->isChecked()) { double noiseVariance = m_Controls->m_NoiseLevel->value(); switch (m_Controls->m_NoiseDistributionBox->currentIndex()) { case 0: { if (noiseVariance>0) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_COMPLEX-GAUSSIAN-"; parameters.m_SignalGen.m_NoiseVariance = m_Controls->m_NoiseLevel->value(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Complex Gaussian")); } break; } case 1: { if (noiseVariance>0) { parameters.m_NoiseModel = std::make_shared< mitk::RicianNoiseModel >(); parameters.m_Misc.m_ArtifactModelString += "_RICIAN-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); parameters.m_NoiseModel->SetNoiseVariance(noiseVariance); } break; } case 2: { if (noiseVariance>0) { parameters.m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel >(); parameters.m_Misc.m_ArtifactModelString += "_CHISQUARED-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared")); parameters.m_NoiseModel->SetNoiseVariance(noiseVariance); } break; } default: { if (noiseVariance>0) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_COMPLEX-GAUSSIAN-"; parameters.m_SignalGen.m_NoiseVariance = m_Controls->m_NoiseLevel->value(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Complex Gaussian")); } break; } } if (noiseVariance>0) { parameters.m_Misc.m_ArtifactModelString += QString::number(noiseVariance).toStdString(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); } } // signal models { // compartment 1 switch (m_Controls->m_Compartment1Box->currentIndex()) { case 0: { mitk::StickModel* model = new mitk::StickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_StickWidget1->GetD()); model->SetT2(m_Controls->m_StickWidget1->GetT2()); model->SetT1(m_Controls->m_StickWidget1->GetT1()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Stick"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget1->GetT2()); model->SetT1(m_Controls->m_ZeppelinWidget1->GetT1()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Zeppelin"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_TensorWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget1->GetD3()); model->SetT2(m_Controls->m_TensorWidget1->GetT2()); model->SetT1(m_Controls->m_TensorWidget1->GetT1()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Tensor"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget1->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget1->GetMinFa(), m_Controls->m_PrototypeWidget1->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget1->GetMinAdc(), m_Controls->m_PrototypeWidget1->GetMaxAdc()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Prototype") ); break; } } if (m_Controls->m_Comp1VolumeFraction->GetSelectedNode().IsNotNull()) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp1VolumeFraction->GetSelectedNode(); ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage); parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); } // compartment 2 switch (m_Controls->m_Compartment2Box->currentIndex()) { case 0: break; case 1: { mitk::StickModel* model = new mitk::StickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_StickWidget2->GetD()); model->SetT2(m_Controls->m_StickWidget2->GetT2()); model->SetT1(m_Controls->m_StickWidget2->GetT1()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Stick"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget2->GetT2()); model->SetT1(m_Controls->m_ZeppelinWidget2->GetT1()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Zeppelin"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_TensorWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget2->GetD3()); model->SetT2(m_Controls->m_TensorWidget2->GetT2()); model->SetT1(m_Controls->m_TensorWidget2->GetT1()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Tensor"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } } if (m_Controls->m_Comp2VolumeFraction->GetSelectedNode().IsNotNull() && parameters.m_FiberModelList.size()==2) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp2VolumeFraction->GetSelectedNode(); ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage); parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); } // compartment 3 switch (m_Controls->m_Compartment3Box->currentIndex()) { case 0: { mitk::BallModel* model = new mitk::BallModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_BallWidget1->GetD()); model->SetT2(m_Controls->m_BallWidget1->GetT2()); model->SetT1(m_Controls->m_BallWidget1->GetT1()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Ball"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::AstroStickModel* model = new mitk::AstroStickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_AstrosticksWidget1->GetD()); model->SetT2(m_Controls->m_AstrosticksWidget1->GetT2()); model->SetT1(m_Controls->m_AstrosticksWidget1->GetT1()); model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Astrosticks"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); break; } case 2: { mitk::DotModel* model = new mitk::DotModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetT2(m_Controls->m_DotWidget1->GetT2()); model->SetT1(m_Controls->m_DotWidget1->GetT1()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Dot"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget3->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget3->GetMinFa(), m_Controls->m_PrototypeWidget3->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget3->GetMinAdc(), m_Controls->m_PrototypeWidget3->GetMaxAdc()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Prototype") ); break; } } if (m_Controls->m_Comp3VolumeFraction->GetSelectedNode().IsNotNull()) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp3VolumeFraction->GetSelectedNode(); ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage); parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); } switch (m_Controls->m_Compartment4Box->currentIndex()) { case 0: break; case 1: { mitk::BallModel* model = new mitk::BallModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_BallWidget2->GetD()); model->SetT2(m_Controls->m_BallWidget2->GetT2()); model->SetT1(m_Controls->m_BallWidget2->GetT1()); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Ball"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::AstroStickModel* model = new mitk::AstroStickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD()); model->SetT2(m_Controls->m_AstrosticksWidget2->GetT2()); model->SetT1(m_Controls->m_AstrosticksWidget2->GetT1()); model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Astrosticks"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); break; } case 3: { mitk::DotModel* model = new mitk::DotModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetT2(m_Controls->m_DotWidget2->GetT2()); model->SetT1(m_Controls->m_DotWidget2->GetT1()); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Dot"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); break; } case 4: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget4->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget4->GetMinFa(), m_Controls->m_PrototypeWidget4->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget4->GetMinAdc(), m_Controls->m_PrototypeWidget4->GetMaxAdc()); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Prototype") ); break; } } if (m_Controls->m_Comp4VolumeFraction->GetSelectedNode().IsNotNull() && parameters.m_NonFiberModelList.size()==2) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode(); ItkDoubleImgType::Pointer compVolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, compVolumeImage); parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(compVolumeImage); } } parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(parameters.m_SignalGen.m_SignalScale)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(parameters.m_SignalGen.m_AxonRadius)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(parameters.m_SignalGen.m_tInhom)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(parameters.m_SignalGen.m_tLine)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(parameters.m_SignalGen.m_tEcho)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(parameters.m_SignalGen.m_Bvalue)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(parameters.m_SignalGen.m_DoDisablePartialVolume)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(parameters.m_SignalGen.m_DoSimulateRelaxation)); parameters.m_Misc.m_ResultNode->AddProperty("binary", BoolProperty::New(false)); parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked(); parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked(); parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked(); return parameters; } void QmitkFiberfoxView::SaveParameters(QString filename) { FiberfoxParameters<> ffParamaters = UpdateImageParameters(true, true); std::vector< int > bVals = ffParamaters.m_SignalGen.GetBvalues(); std::cout << "b-values: "; for (auto v : bVals) std::cout << v << " "; std::cout << std::endl; bool ok = true; bool first = true; bool dosampling = false; mitk::Image::Pointer diffImg = nullptr; itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = nullptr; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = nullptr; ItkDoubleImgType::Pointer adcImage = nullptr; for (unsigned int i=0; i* model = nullptr; if (i* >(ffParamaters.m_FiberModelList.at(i)); } else { model = dynamic_cast< mitk::RawShModel<>* >(ffParamaters.m_NonFiberModelList.at(i-ffParamaters.m_FiberModelList.size())); } if ( model!=nullptr && model->GetNumberOfKernels() <= 0 ) { if (first==true) { if ( QMessageBox::question(nullptr, "Prototype signal sampling", "Do you want to sample prototype signals from the selected diffusion-weighted imag and save them?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes ) dosampling = true; first = false; if ( dosampling && (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()) ) ) ) { QMessageBox::information(nullptr, "Parameter file not saved", "No diffusion-weighted image selected to sample signal from."); return; } else if (dosampling) { diffImg = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); filter->SetBValue( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str() ).GetPointer() ) ->GetValue() ); filter->SetGradientImage( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(), itkVectorImagePointer ); filter->Update(); tensorImage = filter->GetOutput(); QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetBValue( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); qballfilter->SetGradientImage( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(), itkVectorImagePointer ); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); adcFilter->SetB_value( static_cast (diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); adcFilter->Update(); adcImage = adcFilter->GetOutput(); } } typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); filter->SetBValue( static_cast (diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); filter->SetGradientImage( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(), itkVectorImagePointer ); filter->Update(); tensorImage = filter->GetOutput(); QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetBValue( static_cast (diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); qballfilter->SetGradientImage( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(), itkVectorImagePointer ); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); adcFilter->SetB_value( static_cast (diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); adcFilter->Update(); adcImage = adcFilter->GetOutput(); if (dosampling && diffImg.IsNotNull()) { ok = model->SampleKernels(diffImg, ffParamaters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) { QMessageBox::information( nullptr, "Parameter file not saved", "No valid prototype signals could be sampled."); return; } } } } ffParamaters.SaveParameters(filename.toStdString()); m_ParameterFile = filename; } void QmitkFiberfoxView::SaveParameters() { QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), m_ParameterFile, tr("Fiberfox Parameters (*.ffp)") ); SaveParameters(filename); } void QmitkFiberfoxView::LoadParameters() { QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") ); if(filename.isEmpty() || filename.isNull()) return; m_ParameterFile = filename; FiberfoxParameters<> parameters = UpdateImageParameters(); parameters.LoadParameters(filename.toStdString()); if (parameters.m_MissingTags.size()>0) { QString missing("Parameter file might be corrupted. The following parameters could not be read: "); missing += QString(parameters.m_MissingTags.c_str()); missing += "\nDefault values have been assigned to the missing parameters."; QMessageBox::information( nullptr, "Warning!", missing); } m_Controls->m_RealTimeFibers->setChecked(parameters.m_Misc.m_CheckRealTimeFibersBox); m_Controls->m_AdvancedOptionsBox->setChecked(parameters.m_Misc.m_CheckAdvancedFiberOptionsBox); m_Controls->m_IncludeFiducials->setChecked(parameters.m_Misc.m_CheckIncludeFiducialsBox); m_Controls->m_ConstantRadiusBox->setChecked(parameters.m_Misc.m_CheckConstantRadiusBox); m_Controls->m_DistributionBox->setCurrentIndex(parameters.m_FiberGen.m_Distribution); m_Controls->m_VarianceBox->setValue(parameters.m_FiberGen.m_Variance); m_Controls->m_FiberDensityBox->setValue(parameters.m_FiberGen.m_Density); m_Controls->m_FiberSamplingBox->setValue(parameters.m_FiberGen.m_Sampling); m_Controls->m_TensionBox->setValue(parameters.m_FiberGen.m_Tension); m_Controls->m_ContinuityBox->setValue(parameters.m_FiberGen.m_Continuity); m_Controls->m_BiasBox->setValue(parameters.m_FiberGen.m_Bias); m_Controls->m_XrotBox->setValue(parameters.m_FiberGen.m_Rotation[0]); m_Controls->m_YrotBox->setValue(parameters.m_FiberGen.m_Rotation[1]); m_Controls->m_ZrotBox->setValue(parameters.m_FiberGen.m_Rotation[2]); m_Controls->m_XtransBox->setValue(parameters.m_FiberGen.m_Translation[0]); m_Controls->m_YtransBox->setValue(parameters.m_FiberGen.m_Translation[1]); m_Controls->m_ZtransBox->setValue(parameters.m_FiberGen.m_Translation[2]); m_Controls->m_XscaleBox->setValue(parameters.m_FiberGen.m_Scale[0]); m_Controls->m_YscaleBox->setValue(parameters.m_FiberGen.m_Scale[1]); m_Controls->m_ZscaleBox->setValue(parameters.m_FiberGen.m_Scale[2]); // image generation parameters m_Controls->m_SizeX->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(0)); m_Controls->m_SizeY->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(1)); m_Controls->m_SizeZ->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(2)); m_Controls->m_SpacingX->setValue(parameters.m_SignalGen.m_ImageSpacing[0]); m_Controls->m_SpacingY->setValue(parameters.m_SignalGen.m_ImageSpacing[1]); m_Controls->m_SpacingZ->setValue(parameters.m_SignalGen.m_ImageSpacing[2]); m_Controls->m_NumGradientsBox->setValue(parameters.m_SignalGen.GetNumWeightedVolumes()); m_Controls->m_BvalueBox->setValue(parameters.m_SignalGen.m_Bvalue); m_Controls->m_SignalScaleBox->setValue(parameters.m_SignalGen.m_SignalScale); m_Controls->m_TEbox->setValue(parameters.m_SignalGen.m_tEcho); m_Controls->m_LineReadoutTimeBox->setValue(parameters.m_SignalGen.m_tLine); m_Controls->m_T2starBox->setValue(parameters.m_SignalGen.m_tInhom); m_Controls->m_FiberRadius->setValue(parameters.m_SignalGen.m_AxonRadius); m_Controls->m_RelaxationBox->setChecked(parameters.m_SignalGen.m_DoSimulateRelaxation); m_Controls->m_EnforcePureFiberVoxelsBox->setChecked(parameters.m_SignalGen.m_DoDisablePartialVolume); m_Controls->m_ReversePhaseBox->setChecked(parameters.m_SignalGen.m_ReversePhase); m_Controls->m_PartialFourier->setValue(parameters.m_SignalGen.m_PartialFourier); m_Controls->m_TRbox->setValue(parameters.m_SignalGen.m_tRep); m_Controls->m_NumCoilsBox->setValue(parameters.m_SignalGen.m_NumberOfCoils); m_Controls->m_CoilSensBox->setCurrentIndex(parameters.m_SignalGen.m_CoilSensitivityProfile); m_Controls->m_AcquisitionTypeBox->setCurrentIndex(parameters.m_SignalGen.m_AcquisitionType); if (parameters.m_NoiseModel!=nullptr) { m_Controls->m_AddNoise->setChecked(parameters.m_Misc.m_CheckAddNoiseBox); if (dynamic_cast*>(parameters.m_NoiseModel.get())) { m_Controls->m_NoiseDistributionBox->setCurrentIndex(0); } else if (dynamic_cast*>(parameters.m_NoiseModel.get())) { m_Controls->m_NoiseDistributionBox->setCurrentIndex(1); } m_Controls->m_NoiseLevel->setValue(parameters.m_NoiseModel->GetNoiseVariance()); } else { m_Controls->m_AddNoise->setChecked(parameters.m_Misc.m_CheckAddNoiseBox); m_Controls->m_NoiseLevel->setValue(parameters.m_SignalGen.m_NoiseVariance); } m_Controls->m_VolumeFractionsBox->setChecked(parameters.m_Misc.m_CheckOutputVolumeFractionsBox); m_Controls->m_AdvancedOptionsBox_2->setChecked(parameters.m_Misc.m_CheckAdvancedSignalOptionsBox); m_Controls->m_AddGhosts->setChecked(parameters.m_Misc.m_CheckAddGhostsBox); m_Controls->m_AddAliasing->setChecked(parameters.m_Misc.m_CheckAddAliasingBox); m_Controls->m_AddDistortions->setChecked(parameters.m_Misc.m_CheckAddDistortionsBox); m_Controls->m_AddSpikes->setChecked(parameters.m_Misc.m_CheckAddSpikesBox); m_Controls->m_AddEddy->setChecked(parameters.m_Misc.m_CheckAddEddyCurrentsBox); m_Controls->m_kOffsetBox->setValue(parameters.m_SignalGen.m_KspaceLineOffset); m_Controls->m_WrapBox->setValue(100*(1-parameters.m_SignalGen.m_CroppingFactor)); m_Controls->m_SpikeNumBox->setValue(parameters.m_SignalGen.m_Spikes); m_Controls->m_SpikeScaleBox->setValue(parameters.m_SignalGen.m_SpikeAmplitude); m_Controls->m_EddyGradientStrength->setValue(parameters.m_SignalGen.m_EddyStrength); m_Controls->m_AddGibbsRinging->setChecked(parameters.m_SignalGen.m_DoAddGibbsRinging); m_Controls->m_AddMotion->setChecked(parameters.m_SignalGen.m_DoAddMotion); m_Controls->m_RandomMotion->setChecked(parameters.m_SignalGen.m_DoRandomizeMotion); m_Controls->m_MotionVolumesBox->setText(QString(parameters.m_Misc.m_MotionVolumesBox.c_str())); m_Controls->m_MaxTranslationBoxX->setValue(parameters.m_SignalGen.m_Translation[0]); m_Controls->m_MaxTranslationBoxY->setValue(parameters.m_SignalGen.m_Translation[1]); m_Controls->m_MaxTranslationBoxZ->setValue(parameters.m_SignalGen.m_Translation[2]); m_Controls->m_MaxRotationBoxX->setValue(parameters.m_SignalGen.m_Rotation[0]); m_Controls->m_MaxRotationBoxY->setValue(parameters.m_SignalGen.m_Rotation[1]); m_Controls->m_MaxRotationBoxZ->setValue(parameters.m_SignalGen.m_Rotation[2]); m_Controls->m_Compartment1Box->setCurrentIndex(0); m_Controls->m_Compartment2Box->setCurrentIndex(0); m_Controls->m_Compartment3Box->setCurrentIndex(0); m_Controls->m_Compartment4Box->setCurrentIndex(0); for (unsigned int i=0; i* signalModel = nullptr; if (iGetVolumeFractionImage().IsNotNull() ) { compVolNode = mitk::DataNode::New(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(signalModel->GetVolumeFractionImage().GetPointer()); image->SetVolume(signalModel->GetVolumeFractionImage()->GetBufferPointer()); compVolNode->SetData( image ); compVolNode->SetName("Compartment volume "+QString::number(signalModel->m_CompartmentId).toStdString()); GetDataStorage()->Add(compVolNode); } switch (signalModel->m_CompartmentId) { case 1: { if (compVolNode.IsNotNull()) m_Controls->m_Comp1VolumeFraction->SetSelectedNode(compVolNode); if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget1->SetT2(model->GetT2()); m_Controls->m_StickWidget1->SetT1(model->GetT1()); m_Controls->m_StickWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment1Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget1->SetT2(model->GetT2()); m_Controls->m_TensorWidget1->SetT1(model->GetT1()); m_Controls->m_TensorWidget1->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget1->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget1->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment1Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget1->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget1->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget1->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget1->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget1->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment1Box->setCurrentIndex(3); break; } break; } case 2: { if (compVolNode.IsNotNull()) m_Controls->m_Comp2VolumeFraction->SetSelectedNode(compVolNode); if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget2->SetT2(model->GetT2()); m_Controls->m_StickWidget2->SetT1(model->GetT1()); m_Controls->m_StickWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment2Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget2->SetT2(model->GetT2()); m_Controls->m_TensorWidget2->SetT1(model->GetT1()); m_Controls->m_TensorWidget2->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget2->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget2->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment2Box->setCurrentIndex(3); break; } break; } case 3: { if (compVolNode.IsNotNull()) m_Controls->m_Comp3VolumeFraction->SetSelectedNode(compVolNode); if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget1->SetT2(model->GetT2()); m_Controls->m_BallWidget1->SetT1(model->GetT1()); m_Controls->m_BallWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment3Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget1->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget1->SetT1(model->GetT1()); m_Controls->m_AstrosticksWidget1->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget1->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment3Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget1->SetT2(model->GetT2()); m_Controls->m_DotWidget1->SetT1(model->GetT1()); m_Controls->m_Compartment3Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget3->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget3->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget3->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget3->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget3->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment3Box->setCurrentIndex(3); break; } break; } case 4: { if (compVolNode.IsNotNull()) m_Controls->m_Comp4VolumeFraction->SetSelectedNode(compVolNode); if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget2->SetT2(model->GetT2()); m_Controls->m_BallWidget2->SetT1(model->GetT1()); m_Controls->m_BallWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment4Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget2->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget2->SetT1(model->GetT1()); m_Controls->m_AstrosticksWidget2->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget2->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment4Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget2->SetT2(model->GetT2()); m_Controls->m_DotWidget2->SetT1(model->GetT1()); m_Controls->m_Compartment4Box->setCurrentIndex(3); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget4->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget4->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget4->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget4->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget4->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment4Box->setCurrentIndex(4); break; } break; } } } if ( parameters.m_SignalGen.m_MaskImage ) { mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(parameters.m_SignalGen.m_MaskImage.GetPointer()); image->SetVolume(parameters.m_SignalGen.m_MaskImage->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Tissue mask"); GetDataStorage()->Add(node); m_Controls->m_MaskComboBox->SetSelectedNode(node); } if ( parameters.m_SignalGen.m_FrequencyMap ) { mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(parameters.m_SignalGen.m_FrequencyMap.GetPointer()); image->SetVolume(parameters.m_SignalGen.m_FrequencyMap->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Frequency map"); GetDataStorage()->Add(node); m_Controls->m_FrequencyMapBox->SetSelectedNode(node); } } void QmitkFiberfoxView::ShowAdvancedOptions(int state) { if (state) { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(true); m_Controls->m_AdvancedOptionsBox->setChecked(true); m_Controls->m_AdvancedOptionsBox_2->setChecked(true); } else { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedOptionsBox->setChecked(false); m_Controls->m_AdvancedOptionsBox_2->setChecked(false); } } void QmitkFiberfoxView::Comp1ModelFrameVisibility(int index) { m_Controls->m_StickWidget1->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); m_Controls->m_PrototypeWidget1->setVisible(false); switch (index) { case 0: m_Controls->m_StickWidget1->setVisible(true); break; case 1: m_Controls->m_ZeppelinWidget1->setVisible(true); break; case 2: m_Controls->m_TensorWidget1->setVisible(true); break; case 3: m_Controls->m_PrototypeWidget1->setVisible(true); break; } } void QmitkFiberfoxView::Comp2ModelFrameVisibility(int index) { m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); m_Controls->m_Comp2FractionFrame->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_StickWidget2->setVisible(true); m_Controls->m_Comp2FractionFrame->setVisible(true); break; case 2: m_Controls->m_ZeppelinWidget2->setVisible(true); m_Controls->m_Comp2FractionFrame->setVisible(true); break; case 3: m_Controls->m_TensorWidget2->setVisible(true); m_Controls->m_Comp2FractionFrame->setVisible(true); break; } } void QmitkFiberfoxView::Comp3ModelFrameVisibility(int index) { m_Controls->m_BallWidget1->setVisible(false); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_PrototypeWidget3->setVisible(false); switch (index) { case 0: m_Controls->m_BallWidget1->setVisible(true); break; case 1: m_Controls->m_AstrosticksWidget1->setVisible(true); break; case 2: m_Controls->m_DotWidget1->setVisible(true); break; case 3: m_Controls->m_PrototypeWidget3->setVisible(true); break; } } void QmitkFiberfoxView::Comp4ModelFrameVisibility(int index) { m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_PrototypeWidget4->setVisible(false); m_Controls->m_Comp4FractionFrame->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_BallWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 2: m_Controls->m_AstrosticksWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 3: m_Controls->m_DotWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 4: m_Controls->m_PrototypeWidget4->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; } } void QmitkFiberfoxView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnAddMotion(int value) { if (value>0) m_Controls->m_MotionArtifactFrame->setVisible(true); else m_Controls->m_MotionArtifactFrame->setVisible(false); } void QmitkFiberfoxView::OnAddAliasing(int value) { if (value>0) m_Controls->m_AliasingFrame->setVisible(true); else m_Controls->m_AliasingFrame->setVisible(false); } void QmitkFiberfoxView::OnAddSpikes(int value) { if (value>0) m_Controls->m_SpikeFrame->setVisible(true); else m_Controls->m_SpikeFrame->setVisible(false); } void QmitkFiberfoxView::OnAddEddy(int value) { if (value>0) m_Controls->m_EddyFrame->setVisible(true); else m_Controls->m_EddyFrame->setVisible(false); } void QmitkFiberfoxView::OnAddDistortions(int value) { if (value>0) m_Controls->m_DistortionsFrame->setVisible(true); else m_Controls->m_DistortionsFrame->setVisible(false); } void QmitkFiberfoxView::OnAddGhosts(int value) { if (value>0) m_Controls->m_GhostFrame->setVisible(true); else m_Controls->m_GhostFrame->setVisible(false); } void QmitkFiberfoxView::OnAddNoise(int value) { if (value>0) m_Controls->m_NoiseFrame->setVisible(true); else m_Controls->m_NoiseFrame->setVisible(false); } void QmitkFiberfoxView::OnDistributionChanged(int value) { if (value==1) m_Controls->m_VarianceBox->setVisible(true); else m_Controls->m_VarianceBox->setVisible(false); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnVarianceChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberDensityChanged(int) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberSamplingChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnTensionChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnContinuityChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnBiasChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::AlignOnGrid() { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it ) { mitk::DataNode::Pointer pFibNode = *it; if ( pFibNode.IsNotNull() && dynamic_cast(pFibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(pImgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); break; } } break; } } } for(unsigned int i=0; iGetSources(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it ) { mitk::DataNode::Pointer imgNode = *it; if ( imgNode.IsNotNull() && dynamic_cast(imgNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Image::Pointer img = dynamic_cast(imgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } break; } } } for(unsigned int i=0; i(m_SelectedImages.at(i)->GetData()); mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFlipButton() { if (m_SelectedFiducial.IsNull()) return; std::map::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; data.m_Flipped += 1; data.m_Flipped %= 2; } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } QmitkFiberfoxView::GradientListType QmitkFiberfoxView::GenerateHalfShell(int NPoints) { NPoints *= 2; GradientListType pointshell; int numB0 = NPoints/20; if (numB0==0) numB0=1; GradientType g; g.Fill(0.0); for (int i=0; i theta; theta.set_size(NPoints); vnl_vector phi; phi.set_size(NPoints); double C = sqrt(4*M_PI); phi(0) = 0.0; phi(NPoints-1) = 0.0; for(int i=0; i0 && i std::vector > QmitkFiberfoxView::MakeGradientList() { std::vector > retval; vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); // Add 0 vector for B0 int numB0 = ndirs/10; if (numB0==0) numB0=1; itk::Vector v; v.Fill(0.0); for (int i=0; i v; v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i); retval.push_back(v); } return retval; } void QmitkFiberfoxView::OnAddBundle() { if (m_SelectedImageNode.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImageNode); mitk::FiberBundle::Pointer bundle = mitk::FiberBundle::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( bundle ); QString name = QString("Bundle_%1").arg(children->size()); node->SetName(name.toStdString()); m_SelectedBundles.push_back(node); UpdateGui(); GetDataStorage()->Add(node, m_SelectedImageNode); } void QmitkFiberfoxView::OnDrawROI() { if (m_SelectedBundles.empty()) OnAddBundle(); if (m_SelectedBundles.empty()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(0)); mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( figure ); node->SetBoolProperty("planarfigure.3drendering", true); node->SetBoolProperty("planarfigure.3drendering.fill", true); QList nodes = this->GetDataManagerSelection(); for( int i=0; iSetSelected(false); m_SelectedFiducial = node; QString name = QString("Fiducial_%1").arg(children->size()); node->SetName(name.toStdString()); node->SetSelected(true); this->DisableCrosshairNavigation(); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( node ); } UpdateGui(); GetDataStorage()->Add(node, m_SelectedBundles.at(0)); } bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j) { int li = -1; i->GetPropertyValue("layer", li); int lj = -1; j->GetPropertyValue("layer", lj); return liGetSources(m_SelectedFiducial); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) if(dynamic_cast((*it)->GetData())) m_SelectedBundles.push_back(*it); if (m_SelectedBundles.empty()) return; } FiberfoxParameters parameters = UpdateImageParameters(false); for (unsigned int i=0; iGetDerivations(m_SelectedBundles.at(i)); std::vector< mitk::DataNode::Pointer > childVector; for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it ) childVector.push_back(*it); - sort(childVector.begin(), childVector.end(), CompareLayer); + std::sort(childVector.begin(), childVector.end(), CompareLayer); - vector< mitk::PlanarEllipse::Pointer > fib; - vector< unsigned int > flip; + std::vector< mitk::PlanarEllipse::Pointer > fib; + std::vector< unsigned int > flip; float radius = 1; int count = 0; for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::PlanarEllipse* ellipse = dynamic_cast(node->GetData()); if (m_Controls->m_ConstantRadiusBox->isChecked()) { ellipse->SetTreatAsCircle(true); mitk::Point2D c = ellipse->GetControlPoint(0); mitk::Point2D p = ellipse->GetControlPoint(1); mitk::Vector2D v = p-c; if (count==0) { radius = v.GetVnlVector().magnitude(); ellipse->SetControlPoint(1, p); ellipse->Modified(); } else { v.Normalize(); v *= radius; ellipse->SetControlPoint(1, c+v); ellipse->Modified(); } } fib.push_back(ellipse); std::map::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; flip.push_back(data.m_Flipped); } else flip.push_back(0); } count++; } if (fib.size()>1) { parameters.m_FiberGen.m_Fiducials.push_back(fib); parameters.m_FiberGen.m_FlipList.push_back(flip); } else if (fib.size()>0) m_SelectedBundles.at(i)->SetData( mitk::FiberBundle::New() ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); filter->SetParameters(parameters.m_FiberGen); filter->Update(); - vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); + std::vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); for (unsigned int i=0; iSetData( fiberBundles.at(i) ); if (fiberBundles.at(i)->GetNumFibers()>50000) m_SelectedBundles.at(i)->SetVisibility(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::GenerateImage() { if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNull() && !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode())) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage( m_Controls->m_SizeX->value(), m_Controls->m_SizeY->value(), m_Controls->m_SizeZ->value(), m_Controls->m_SpacingX->value(), m_Controls->m_SpacingY->value(), m_Controls->m_SpacingZ->value()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Dummy"); unsigned int window = m_Controls->m_SizeX->value()*m_Controls->m_SizeY->value()*m_Controls->m_SizeZ->value(); unsigned int level = window/2; mitk::LevelWindow lw; lw.SetLevelWindow(level, window); node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); GetDataStorage()->Add(node); m_SelectedImageNode = node; mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } UpdateGui(); QMessageBox::information(nullptr, "Template image generated", "You have selected no fiber bundle or diffusion-weighted image, which can be used to simulate a new diffusion-weighted image. A template image with the specified geometry has been generated that can be used to draw artificial fibers (see tab 'Fiber Definition')."); } else if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull()) SimulateImageFromFibers(m_Controls->m_FiberBundleComboBox->GetSelectedNode()); else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode()) ) SimulateForExistingDwi(m_Controls->m_TemplateComboBox->GetSelectedNode()); else QMessageBox::information(nullptr, "No image generated", "You have selected no fiber bundle or diffusion-weighted image, which can be used to simulate a new diffusion-weighted image."); } void QmitkFiberfoxView::SimulateForExistingDwi(mitk::DataNode* imageNode) { bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(imageNode->GetData())) ); if ( !isDiffusionImage ) { return; } FiberfoxParameters parameters = UpdateImageParameters(); mitk::Image::Pointer diffImg = dynamic_cast(imageNode->GetData()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); parameters.m_Misc.m_ParentNode = imageNode; parameters.m_SignalGen.m_SignalScale = 1; parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName() +"_D"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(0)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(1)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(2)).toStdString() +"_S"+QString::number(parameters.m_SignalGen.m_ImageSpacing[0]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[1]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[2]).toStdString() +"_b"+QString::number(parameters.m_SignalGen.m_Bvalue).toStdString() +"_"+parameters.m_Misc.m_SignalModelString +parameters.m_Misc.m_ArtifactModelString); m_TractsToDwiFilter->SetParameters(parameters); m_TractsToDwiFilter->SetInputImage(itkVectorImagePointer); m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::SimulateImageFromFibers(mitk::DataNode* fiberNode) { mitk::FiberBundle::Pointer fiberBundle = dynamic_cast(fiberNode->GetData()); if (fiberBundle->GetNumFibers()<=0) { return; } FiberfoxParameters parameters = UpdateImageParameters(); m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); parameters.m_Misc.m_ParentNode = fiberNode; parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName() +"_D"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(0)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(1)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(2)).toStdString() +"_S"+QString::number(parameters.m_SignalGen.m_ImageSpacing[0]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[1]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[2]).toStdString() +"_b"+QString::number(parameters.m_SignalGen.m_Bvalue).toStdString() +"_"+parameters.m_Misc.m_SignalModelString +parameters.m_Misc.m_ArtifactModelString); if ( m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast (m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()) ) ) { bool first = true; bool ok = true; mitk::Image::Pointer diffImg = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = nullptr; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = nullptr; ItkDoubleImgType::Pointer adcImage = nullptr; for (unsigned int i=0; i* model = nullptr; if (i* >(parameters.m_FiberModelList.at(i)); else model = dynamic_cast< mitk::RawShModel<>* >(parameters.m_NonFiberModelList.at(i-parameters.m_FiberModelList.size())); if (model!=0 && model->GetNumberOfKernels()<=0) { if (first==true) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetBValue( static_cast (diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); filter->SetGradientImage( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(), itkVectorImagePointer ); filter->Update(); tensorImage = filter->GetOutput(); QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetGradientImage( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(), itkVectorImagePointer ); qballfilter->SetBValue( static_cast (diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections( static_cast ( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); adcFilter->SetB_value( static_cast (diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); adcFilter->Update(); adcImage = adcFilter->GetOutput(); } ok = model->SampleKernels(diffImg, parameters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) break; } } if (!ok) { QMessageBox::information( nullptr, "Simulation cancelled", "No valid prototype signals could be sampled."); return; } } else if ( m_Controls->m_Compartment1Box->currentIndex()==3 || m_Controls->m_Compartment3Box->currentIndex()==3 || m_Controls->m_Compartment4Box->currentIndex()==4 ) { QMessageBox::information( nullptr, "Simulation cancelled", "Prototype signal but no diffusion-weighted image selected to sample signal from."); return; } m_TractsToDwiFilter->SetParameters(parameters); m_TractsToDwiFilter->SetFiberBundle(fiberBundle); m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::ApplyTransform() { - vector< mitk::DataNode::Pointer > selectedBundles; + std::vector< mitk::DataNode::Pointer > selectedBundles; for(unsigned int i=0; iGetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) selectedBundles.push_back(fibNode); } } if (selectedBundles.empty()) selectedBundles = m_SelectedBundles2; if (!selectedBundles.empty()) { for (std::vector::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it) { mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value()); fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value()); fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value()); // handle child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse* pe = dynamic_cast(fiducialNode->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); // implicit translation mitk::Vector3D trans; trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0]; trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1]; trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2]; mitk::Vector3D newWc = rot*trans; newWc = newWc-trans; geom->Translate(newWc); pe->Modified(); } } } } } else { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); pe->Modified(); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::CopyBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( nullptr, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberFoxView") << "Select at least one fiber bundle!"; return; } for (std::vector::const_iterator it = m_SelectedBundles.begin(); it!=m_SelectedBundles.end(); ++it) { // find parent image mitk::DataNode::Pointer parentNode; mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { parentNode = pImgNode; break; } } mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); mitk::FiberBundle::Pointer newBundle = fib->GetDeepCopy(); QString name((*it)->GetName().c_str()); name += "_copy"; mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); if (parentNode.IsNotNull()) GetDataStorage()->Add(fbNode, parentNode); else GetDataStorage()->Add(fbNode); // copy child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData())->Clone(); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pe); newNode->SetName(fiducialNode->GetName()); newNode->SetBoolProperty("planarfigure.3drendering", true); GetDataStorage()->Add(newNode, fbNode); } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::JoinBundles() { if ( m_SelectedBundles.size()<2 ){ QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberFoxView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); mitk::FiberBundle::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (; it!=m_SelectedBundles.end(); ++it) { newBundle = newBundle->AddBundle(dynamic_cast((*it)->GetData())); name += "+"+QString((*it)->GetName().c_str()); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::UpdateGui() { m_Controls->m_GeometryFrame->setEnabled(true); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_FiberGenMessage->setVisible(true); m_Controls->m_TransformBundlesButton->setEnabled(false); m_Controls->m_CopyBundlesButton->setEnabled(false); m_Controls->m_GenerateFibersButton->setEnabled(false); m_Controls->m_FlipButton->setEnabled(false); m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_BvalueBox->setEnabled(true); m_Controls->m_NumGradientsBox->setEnabled(true); m_Controls->m_JoinBundlesButton->setEnabled(false); m_Controls->m_AlignOnGrid->setEnabled(false); // Fiber generation gui if (m_SelectedFiducial.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_FlipButton->setEnabled(true); m_Controls->m_AlignOnGrid->setEnabled(true); } if (m_SelectedImageNode.IsNotNull() || !m_SelectedBundles.empty()) { m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); } if (m_SelectedImageNode.IsNotNull() && !m_SelectedBundles.empty()) m_Controls->m_AlignOnGrid->setEnabled(true); if (!m_SelectedBundles.empty()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_CopyBundlesButton->setEnabled(true); m_Controls->m_GenerateFibersButton->setEnabled(true); if (m_SelectedBundles.size()>1) m_Controls->m_JoinBundlesButton->setEnabled(true); } // Signal generation gui if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull() || m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) { m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if ( m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()) ) ) { m_Controls->m_DiffusionPropsMessage->setVisible(true); m_Controls->m_BvalueBox->setEnabled(false); m_Controls->m_NumGradientsBox->setEnabled(false); m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } } void QmitkFiberfoxView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& nodes) { m_SelectedBundles2.clear(); m_SelectedImages.clear(); m_SelectedFiducials.clear(); m_SelectedFiducial = nullptr; m_SelectedBundles.clear(); m_SelectedImageNode = nullptr; // iterate all selected objects, adjust warning visibility for( int i=0; i(node->GetData()) ) { m_SelectedImages.push_back(node); m_SelectedImageNode = node; } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedBundles2.push_back(node); if (m_Controls->m_RealTimeFibers->isChecked()) { m_SelectedBundles.push_back(node); mitk::FiberBundle::Pointer newFib = dynamic_cast(node->GetData()); if (newFib->GetNumFibers()!=m_Controls->m_FiberDensityBox->value()) GenerateFibers(); } else m_SelectedBundles.push_back(node); } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedFiducials.push_back(node); m_SelectedFiducial = node; m_SelectedBundles.clear(); mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) { mitk::DataNode::Pointer pNode = *it; if ( pNode.IsNotNull() && dynamic_cast(pNode->GetData()) ) m_SelectedBundles.push_back(pNode); } } } UpdateGui(); } void QmitkFiberfoxView::EnableCrosshairNavigation() { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::DisableCrosshairNavigation() { } void QmitkFiberfoxView::NodeRemoved(const mitk::DataNode* node) { mitk::DataNode* nonConstNode = const_cast(node); std::map::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode); if (dynamic_cast(node->GetData())) { m_SelectedBundles.clear(); m_SelectedBundles2.clear(); } else if (dynamic_cast(node->GetData())) m_SelectedImages.clear(); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; // remove observers data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag ); data.m_Figure->RemoveObserver( data.m_SelectObserverTag ); data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag ); data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag ); m_DataNodeToPlanarFigureData.erase( it ); } } void QmitkFiberfoxView::NodeAdded( const mitk::DataNode* node ) { // add observer for selection in renderwindow mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); bool isPositionMarker (false); node->GetBoolProperty("isContourMarker", isPositionMarker); if( figure && !isPositionMarker ) { MITK_DEBUG << "figure added. will add interactor if needed."; mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); mitk::DataNode* nonConstNode = const_cast( node ); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( nonConstNode ); } MITK_DEBUG << "will now add observers for planarfigure"; QmitkPlanarFigureData data; data.m_Figure = figure; // // add observer for event when figure has been placed typedef itk::SimpleMemberCommand< QmitkFiberfoxView > SimpleCommandType; // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); // initializationCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureInitialized ); // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); // add observer for event when figure is picked (selected) typedef itk::MemberCommand< QmitkFiberfoxView > MemberCommandType; MemberCommandType::Pointer selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureSelected ); data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New(); startInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::DisableCrosshairNavigation); data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkFiberfoxView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& ) { mitk::TNodePredicateDataType::Pointer isPf = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf ); for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it) { mitk::DataNode* node = *it; if( node->GetData() == object ) { node->SetSelected(true); m_SelectedFiducial = node; } else node->SetSelected(false); } UpdateGui(); this->RequestRenderWindowUpdate(); } void QmitkFiberfoxView::SetFocus() { m_Controls->m_CircleButton->setFocus(); } void QmitkFiberfoxView::SetOutputPath() { // SELECT FOLDER DIALOG - string outputPath; + std::string outputPath; outputPath = QFileDialog::getExistingDirectory(nullptr, "Save images to...", QString(outputPath.c_str())).toStdString(); if (outputPath.empty()) m_Controls->m_SavePathEdit->setText("-"); else { outputPath += "/"; m_Controls->m_SavePathEdit->setText(QString(outputPath.c_str())); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h index fa1768f6b4..8f7ac44dce 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h @@ -1,215 +1,213 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "ui_QmitkFiberfoxViewControls.h" #include #include #include #ifndef Q_MOC_RUN #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include #include #include #include /*! \brief View for fiber based diffusion software phantoms (Fiberfox). See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. */ // Forward Qt class declarations -using namespace std; - class QmitkFiberfoxView; class QmitkFiberfoxWorker : public QObject { Q_OBJECT public: QmitkFiberfoxWorker(QmitkFiberfoxView* view); public slots: void run(); private: QmitkFiberfoxView* m_View; }; class QmitkFiberfoxView : 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 string VIEW_ID; + static const std::string VIEW_ID; QmitkFiberfoxView(); virtual ~QmitkFiberfoxView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; typedef itk::Vector GradientType; - typedef vector GradientListType; + typedef std::vector GradientListType; typedef itk::VectorImage< short, 3 > ItkDwiType; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; - template vector > MakeGradientList(); + template std::vector > MakeGradientList(); protected slots: void SetOutputPath(); ///< path where image is automatically saved to after the simulation is finished void LoadParameters(); ///< load fiberfox parameters void SaveParameters(); ///< save fiberfox parameters void BeforeThread(); void AfterThread(); void KillThread(); ///< abort simulation void UpdateSimulationStatus(); ///< print simulation progress and satus messages void OnDrawROI(); ///< adds new ROI, handles interactors etc. void OnAddBundle(); ///< adds new fiber bundle to datastorage void OnFlipButton(); ///< negate one coordinate of the fiber waypoints in the selcted planar figure. needed in case of unresolvable twists void GenerateFibers(); ///< generate fibers from the selected ROIs void GenerateImage(); ///< start image simulation void JoinBundles(); ///< merges selcted fiber bundles into one void CopyBundles(); ///< add copy of the selected bundle to the datamanager void ApplyTransform(); ///< rotate and shift selected bundles void AlignOnGrid(); ///< shift selected fiducials to nearest voxel center void Comp1ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 1 void Comp2ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 2 void Comp3ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 3 void Comp4ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 4 void ShowAdvancedOptions(int state); /** update fibers if any parameter changes */ void OnFiberDensityChanged(int value); void OnFiberSamplingChanged(double value); void OnTensionChanged(double value); void OnContinuityChanged(double value); void OnBiasChanged(double value); void OnVarianceChanged(double value); void OnDistributionChanged(int value); void OnConstantRadius(int value); /** update GUI elements */ void OnAddNoise(int value); void OnAddGhosts(int value); void OnAddDistortions(int value); void OnAddEddy(int value); void OnAddSpikes(int value); void OnAddAliasing(int value); void OnAddMotion(int value); void OnMaskSelected(int value); void OnFibSelected(int value); void OnTemplateSelected(int value); protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; GradientListType GenerateHalfShell(int NPoints); ///< generate vectors distributed over the halfsphere Ui::QmitkFiberfoxViewControls* m_Controls; void SimulateForExistingDwi(mitk::DataNode* imageNode); ///< add artifacts to existing diffusion weighted image void SimulateImageFromFibers(mitk::DataNode* fiberNode); ///< simulate new diffusion weighted image template< class ScalarType > FiberfoxParameters< ScalarType > UpdateImageParameters(bool all=true, bool save=false); ///< update fiberfox paramater object (template parameter defines noise model type) void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection void PlanarFigureSelected( itk::Object* object, const itk::EventObject& ); void EnableCrosshairNavigation(); ///< enable crosshair navigation if planar figure interaction ends void DisableCrosshairNavigation(); ///< disable crosshair navigation if planar figure interaction starts void NodeAdded( const mitk::DataNode* node ) override; ///< add observers void NodeRemoved(const mitk::DataNode* node) override; ///< remove observers void SaveParameters(QString filename); /** structure to keep track of planar figures and observers */ struct QmitkPlanarFigureData { QmitkPlanarFigureData() : m_Figure(0) , m_EndPlacementObserverTag(0) , m_SelectObserverTag(0) , m_StartInteractionObserverTag(0) , m_EndInteractionObserverTag(0) , m_Flipped(0) { } mitk::PlanarFigure* m_Figure; unsigned int m_EndPlacementObserverTag; unsigned int m_SelectObserverTag; unsigned int m_StartInteractionObserverTag; unsigned int m_EndInteractionObserverTag; unsigned int m_Flipped; }; std::map m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData mitk::DataNode::Pointer m_SelectedFiducial; ///< selected planar ellipse mitk::DataNode::Pointer m_SelectedImageNode; - vector< mitk::DataNode::Pointer > m_SelectedBundles; - vector< mitk::DataNode::Pointer > m_SelectedBundles2; - vector< mitk::DataNode::Pointer > m_SelectedFiducials; - vector< mitk::DataNode::Pointer > m_SelectedImages; + std::vector< mitk::DataNode::Pointer > m_SelectedBundles; + std::vector< mitk::DataNode::Pointer > m_SelectedBundles2; + std::vector< mitk::DataNode::Pointer > m_SelectedFiducials; + std::vector< mitk::DataNode::Pointer > m_SelectedImages; QString m_ParameterFile; ///< parameter file name // GUI thread QmitkFiberfoxWorker m_Worker; ///< runs filter QThread m_Thread; ///< worker thread bool m_ThreadIsRunning; QTimer* m_SimulationTimer; QTime m_SimulationTime; QString m_SimulationStatusText; /** Image filters that do all the simulations. */ itk::TractsToDWIImageFilter< short >::Pointer m_TractsToDwiFilter; friend class QmitkFiberfoxWorker; }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/documentation/UserManual/QmitkFiberProcessingViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/documentation/UserManual/QmitkFiberProcessingViewUserManual.dox index 586d5dd171..46f70c978c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/documentation/UserManual/QmitkFiberProcessingViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/documentation/UserManual/QmitkFiberProcessingViewUserManual.dox @@ -1,9 +1,9 @@ /** \page org_mitk_views_fiberprocessing Fiber Processing -This view provides tools to extract subbundles from a given fiber bundle, to remove unwanted fibers (e.g. via length, curvature and directional constraints) and to modify the properties of a fiber bundles such as coloring or fiber sampling. +This view provides tools to extract subbundles from a given fiber bundle, to remove unwanted fibers (e.g. via length, curvature, directional and fiber weight constraints) and to modify the properties of a fiber bundles such as coloring or fiber sampling. Fiber Extraction: Place ROIs in the 2D render widgets (cricles or polygons) and extract fibers from the bundle that pass through these ROIs by selecting the according ROI and fiber bundle in the datamanger and starting the extraction. The ROIs can be combined via logical operations. All fibers that pass through the thus generated composite ROI are extracted. The extraction can also be performed using 3D ROIs represented as binary mask images. In this extraction method, the logical operations are not implemented at the moment. */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.cpp index 3e3cee250e..e313b9abb3 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.cpp @@ -1,1546 +1,1577 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include #include // Qmitk #include "QmitkFiberProcessingView.h" // Qt #include // MITK #include #include #include #include #include #include #include #include #include #include #include "usModuleRegistry.h" #include #include "mitkNodePredicateDataType.h" #include #include #include #include // ITK #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include const std::string QmitkFiberProcessingView::VIEW_ID = "org.mitk.views.fiberprocessing"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace mitk; QmitkFiberProcessingView::QmitkFiberProcessingView() : QmitkAbstractView() , m_Controls( 0 ) , m_CircleCounter(0) , m_PolygonCounter(0) , m_UpsamplingFactor(1) { } // Destructor QmitkFiberProcessingView::~QmitkFiberProcessingView() { RemoveObservers(); } void QmitkFiberProcessingView::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::QmitkFiberProcessingViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( OnDrawCircle() ) ); connect( m_Controls->m_PolygonButton, SIGNAL( clicked() ), this, SLOT( OnDrawPolygon() ) ); connect(m_Controls->PFCompoANDButton, SIGNAL(clicked()), this, SLOT(GenerateAndComposite()) ); connect(m_Controls->PFCompoORButton, SIGNAL(clicked()), this, SLOT(GenerateOrComposite()) ); connect(m_Controls->PFCompoNOTButton, SIGNAL(clicked()), this, SLOT(GenerateNotComposite()) ); connect(m_Controls->m_GenerateRoiImage, SIGNAL(clicked()), this, SLOT(GenerateRoiImage()) ); connect(m_Controls->m_JoinBundles, SIGNAL(clicked()), this, SLOT(JoinBundles()) ); connect(m_Controls->m_SubstractBundles, SIGNAL(clicked()), this, SLOT(SubstractBundles()) ); connect(m_Controls->m_CopyBundle, SIGNAL(clicked()), this, SLOT(CopyBundles()) ); connect(m_Controls->m_ExtractFibersButton, SIGNAL(clicked()), this, SLOT(Extract())); connect(m_Controls->m_RemoveButton, SIGNAL(clicked()), this, SLOT(Remove())); connect(m_Controls->m_ModifyButton, SIGNAL(clicked()), this, SLOT(Modify())); connect(m_Controls->m_ExtractionMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); connect(m_Controls->m_RemovalMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); connect(m_Controls->m_ModificationMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); connect(m_Controls->m_ExtractionBoxMask, SIGNAL(currentIndexChanged(int)), this, SLOT(OnMaskExtractionChanged())); m_Controls->m_ColorMapBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("OdfImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isOdf); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer finalPredicate = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); m_Controls->m_ColorMapBox->SetPredicate(finalPredicate); m_Controls->label_17->setVisible(false); m_Controls->m_FiberExtractionFractionBox->setVisible(false); } UpdateGui(); } void QmitkFiberProcessingView::OnMaskExtractionChanged() { if (m_Controls->m_ExtractionBoxMask->currentIndex() == 2) { m_Controls->label_17->setVisible(true); m_Controls->m_FiberExtractionFractionBox->setVisible(true); m_Controls->m_BothEnds->setVisible(false); } else { m_Controls->label_17->setVisible(false); m_Controls->m_FiberExtractionFractionBox->setVisible(false); if (m_Controls->m_ExtractionBoxMask->currentIndex() != 3) m_Controls->m_BothEnds->setVisible(true); } } void QmitkFiberProcessingView::SetFocus() { m_Controls->toolBoxx->setFocus(); } void QmitkFiberProcessingView::Modify() { switch (m_Controls->m_ModificationMethodBox->currentIndex()) { case 0: { ResampleSelectedBundlesSpline(); break; } case 1: { ResampleSelectedBundlesLinear(); break; } case 2: { CompressSelectedBundles(); break; } case 3: { DoImageColorCoding(); break; } case 4: { MirrorFibers(); break; } case 5: { WeightFibers(); break; } case 6: { DoCurvatureColorCoding(); break; } case 7: { DoWeightColorCoding(); break; } } } void QmitkFiberProcessingView::WeightFibers() { float weight = this->m_Controls->m_BundleWeightBox->value(); for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); fib->SetFiberWeights(weight); } } void QmitkFiberProcessingView::Remove() { switch (m_Controls->m_RemovalMethodBox->currentIndex()) { case 0: { RemoveDir(); break; } case 1: { PruneBundle(); break; } case 2: { ApplyCurvatureThreshold(); break; } case 3: { RemoveWithMask(false); break; } case 4: { RemoveWithMask(true); break; } + case 5: + { + ApplyWeightThreshold(); + break; + } } } void QmitkFiberProcessingView::Extract() { switch (m_Controls->m_ExtractionMethodBox->currentIndex()) { case 0: { ExtractWithPlanarFigure(); break; } case 1: { switch (m_Controls->m_ExtractionBoxMask->currentIndex()) { { case 0: ExtractWithMask(true, false); break; } { case 1: ExtractWithMask(true, true); break; } { case 2: ExtractWithMask(false, false); break; } { case 3: ExtractWithMask(false, true); break; } } break; } } } void QmitkFiberProcessingView::PruneBundle() { int minLength = this->m_Controls->m_PruneFibersMinBox->value(); int maxLength = this->m_Controls->m_PruneFibersMaxBox->value(); for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); if (!fib->RemoveShortFibers(minLength)) QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers."); else if (!fib->RemoveLongFibers(maxLength)) QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers."); } RenderingManager::GetInstance()->RequestUpdateAll(); } +void QmitkFiberProcessingView::ApplyWeightThreshold() +{ + float thr = this->m_Controls->m_WeightThresholdBox->value(); + std::vector< DataNode::Pointer > nodes = m_SelectedFB; + for (auto node : nodes) + { + mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); + + mitk::FiberBundle::Pointer newFib = fib->FilterByWeights(thr); + if (newFib->GetNumFibers()>0) + { + newFib->ColorFibersByFiberWeights(false, true); + node->SetData(newFib); + } + else + QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers."); + } + RenderingManager::GetInstance()->RequestUpdateAll(); +} + void QmitkFiberProcessingView::ApplyCurvatureThreshold() { int angle = this->m_Controls->m_CurvSpinBox->value(); int dist = this->m_Controls->m_CurvDistanceSpinBox->value(); std::vector< DataNode::Pointer > nodes = m_SelectedFB; for (auto node : nodes) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); itk::FiberCurvatureFilter::Pointer filter = itk::FiberCurvatureFilter::New(); filter->SetInputFiberBundle(fib); filter->SetAngularDeviation(angle); filter->SetDistance(dist); filter->SetRemoveFibers(m_Controls->m_RemoveCurvedFibersBox->isChecked()); filter->Update(); mitk::FiberBundle::Pointer newFib = filter->GetOutputFiberBundle(); if (newFib->GetNumFibers()>0) { newFib->ColorFibersByOrientation(); node->SetData(newFib); } else QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers."); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::RemoveDir() { for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); vnl_vector_fixed dir; dir[0] = m_Controls->m_ExtractDirX->value(); dir[1] = m_Controls->m_ExtractDirY->value(); dir[2] = m_Controls->m_ExtractDirZ->value(); fib->RemoveDir(dir,cos((float)m_Controls->m_ExtractAngle->value()*M_PI/180)); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::RemoveWithMask(bool removeInside) { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); mitk::FiberBundle::Pointer newFib = fib->RemoveFibersOutside(mask, removeInside); if (newFib->GetNumFibers()<=0) { QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } node->SetData(newFib); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::ExtractWithMask(bool onlyEnds, bool invert) { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); QString name(node->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); mitk::FiberBundle::Pointer newFib = fib->ExtractFiberSubset(mask, !onlyEnds, invert, m_Controls->m_BothEnds->isChecked(), m_Controls->m_FiberExtractionFractionBox->value()); if (newFib->GetNumFibers()<=0) { QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); if (invert) { name += "_not"; if (onlyEnds) name += "-ending-in-mask"; else name += "-passing-mask"; } else { if (onlyEnds) name += "_ending-in-mask"; else name += "_passing-mask"; } newNode->SetName(name.toStdString()); GetDataStorage()->Add(newNode); node->SetVisibility(false); } } void QmitkFiberProcessingView::GenerateRoiImage() { if (m_SelectedPF.empty()) return; mitk::BaseGeometry::Pointer geometry; if (!m_SelectedFB.empty()) { mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.front()->GetData()); geometry = fib->GetGeometry(); } else if (m_SelectedImage) geometry = m_SelectedImage->GetGeometry(); else return; itk::Vector spacing = geometry->GetSpacing(); spacing /= m_UpsamplingFactor; mitk::Point3D newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); itk::Matrix direction; itk::ImageRegion<3> imageRegion; for (int i=0; i<3; i++) for (int j=0; j<3; j++) direction[j][i] = geometry->GetMatrixColumn(i)[j]/spacing[j]; imageRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); imageRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); imageRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); m_PlanarFigureImage = itkUCharImageType::New(); m_PlanarFigureImage->SetSpacing( spacing ); // Set the image spacing m_PlanarFigureImage->SetOrigin( newOrigin ); // Set the image origin m_PlanarFigureImage->SetDirection( direction ); // Set the image direction m_PlanarFigureImage->SetRegions( imageRegion ); m_PlanarFigureImage->Allocate(); m_PlanarFigureImage->FillBuffer( 0 ); Image::Pointer tmpImage = Image::New(); tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer()); tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); std::string name = m_SelectedPF.at(0)->GetName(); WritePfToImage(m_SelectedPF.at(0), tmpImage); for (unsigned int i=1; iGetName(); WritePfToImage(m_SelectedPF.at(i), tmpImage); } DataNode::Pointer node = DataNode::New(); tmpImage = Image::New(); tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer()); tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); node->SetData(tmpImage); node->SetName(name); this->GetDataStorage()->Add(node); } void QmitkFiberProcessingView::WritePfToImage(mitk::DataNode::Pointer node, mitk::Image* image) { if (dynamic_cast(node->GetData())) { m_PlanarFigure = dynamic_cast(node->GetData()); AccessFixedDimensionByItk_2( image, InternalReorientImagePlane, 3, m_PlanarFigure->GetGeometry(), -1); AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 3, 2, node->GetName() ); } else if (dynamic_cast(node->GetData())) { DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(node); for (unsigned int i=0; iSize(); i++) { WritePfToImage(children->at(i), image); } } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberProcessingView::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< float, VImageDimension > FloatImageType; typedef itk::ResampleImageFilter ResamplerType; typename ResamplerType::Pointer resampler = ResamplerType::New(); mitk::PlaneGeometry* planegeo = dynamic_cast(planegeo3D); float upsamp = m_UpsamplingFactor; float gausssigma = 0.5; // Spacing typename ResamplerType::SpacingType spacing = planegeo->GetSpacing(); spacing[0] = image->GetSpacing()[0] / upsamp; spacing[1] = image->GetSpacing()[1] / upsamp; spacing[2] = image->GetSpacing()[2]; resampler->SetOutputSpacing( spacing ); // Size typename ResamplerType::SizeType size; size[0] = planegeo->GetExtentInMM(0) / spacing[0]; size[1] = planegeo->GetExtentInMM(1) / spacing[1]; size[2] = 1; resampler->SetSize( size ); // Origin typename mitk::Point3D orig = planegeo->GetOrigin(); typename mitk::Point3D corrorig; planegeo3D->WorldToIndex(orig,corrorig); corrorig[0] += 0.5/upsamp; corrorig[1] += 0.5/upsamp; corrorig[2] += 0; planegeo3D->IndexToWorld(corrorig,corrorig); resampler->SetOutputOrigin(corrorig ); // Direction typename ResamplerType::DirectionType direction; typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix(); for(unsigned int c=0; cSetOutputDirection( direction ); // Gaussian interpolation if(gausssigma != 0) { double sigma[3]; for( unsigned int d = 0; d < 3; d++ ) sigma[d] = gausssigma * image->GetSpacing()[d]; double alpha = 2.0; typedef itk::GaussianInterpolateImageFunction GaussianInterpolatorType; typename GaussianInterpolatorType::Pointer interpolator = GaussianInterpolatorType::New(); interpolator->SetInputImage( image ); interpolator->SetParameters( sigma, alpha ); resampler->SetInterpolator( interpolator ); } else { typedef typename itk::LinearInterpolateImageFunction InterpolatorType; typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); resampler->SetInterpolator( interpolator ); } resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); resampler->Update(); if(additionalIndex < 0) { this->m_InternalImage = mitk::Image::New(); this->m_InternalImage->InitializeByItk( resampler->GetOutput() ); this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberProcessingView::InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::CastImageFilter< ImageType, itkUCharImageType > CastFilterType; // Generate mask image as new image with same header as input image and // initialize with "1". itkUCharImageType::Pointer newMaskImage = itkUCharImageType::New(); newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction newMaskImage->SetRegions( image->GetLargestPossibleRegion() ); newMaskImage->Allocate(); newMaskImage->FillBuffer( 1 ); // Generate VTK polygon from (closed) PlanarFigure polyline // (The polyline points are shifted by -0.5 in z-direction to make sure // that the extrusion filter, which afterwards elevates all points by +0.5 // in z-direction, creates a 3D object which is cut by the the plane z=0) const PlaneGeometry *planarFigurePlaneGeometry = m_PlanarFigure->GetPlaneGeometry(); const PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const BaseGeometry *imageGeometry3D = m_InternalImage->GetGeometry( 0 ); vtkPolyData *polyline = vtkPolyData::New(); polyline->Allocate( 1, 1 ); // Determine x- and y-dimensions depending on principal axis int i0, i1; switch ( axis ) { case 0: i0 = 1; i1 = 2; break; case 1: i0 = 0; i1 = 2; break; case 2: default: i0 = 0; i1 = 1; break; } // Create VTK polydata object of polyline contour vtkPoints *points = vtkPoints::New(); PlanarFigure::PolyLineType::const_iterator it; unsigned int numberOfPoints = 0; for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it ) { Point3D point3D; // Convert 2D point back to the local index coordinates of the selected image Point2D point2D = *it; planarFigurePlaneGeometry->WorldToIndex(point2D, point2D); point2D[0] -= 0.5/m_UpsamplingFactor; point2D[1] -= 0.5/m_UpsamplingFactor; planarFigurePlaneGeometry->IndexToWorld(point2D, point2D); planarFigurePlaneGeometry->Map( point2D, point3D ); // Polygons (partially) outside of the image bounds can not be processed further due to a bug in vtkPolyDataToImageStencil if ( !imageGeometry3D->IsInside( point3D ) ) { float bounds[2] = {0,0}; bounds[0] = this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i0); bounds[1] = this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i1); imageGeometry3D->WorldToIndex( point3D, point3D ); if (point3D[i0]<0) point3D[i0] = 0.0; else if (point3D[i0]>bounds[0]) point3D[i0] = bounds[0]-0.001; if (point3D[i1]<0) point3D[i1] = 0.0; else if (point3D[i1]>bounds[1]) point3D[i1] = bounds[1]-0.001; points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); numberOfPoints++; } else { imageGeometry3D->WorldToIndex( point3D, point3D ); // Add point to polyline array points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); numberOfPoints++; } } polyline->SetPoints( points ); points->Delete(); vtkIdType *ptIds = new vtkIdType[numberOfPoints]; for ( vtkIdType i = 0; i < numberOfPoints; ++i ) ptIds[i] = i; polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds ); // Extrude the generated contour polygon vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New(); extrudeFilter->SetInputData( polyline ); extrudeFilter->SetScaleFactor( 1 ); extrudeFilter->SetExtrusionTypeToNormalExtrusion(); extrudeFilter->SetVector( 0.0, 0.0, 1.0 ); // Make a stencil from the extruded polygon vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New(); polyDataToImageStencil->SetInputConnection( extrudeFilter->GetOutputPort() ); // Export from ITK to VTK (to use a VTK filter) typedef itk::VTKImageImport< itkUCharImageType > ImageImportType; typedef itk::VTKImageExport< itkUCharImageType > ImageExportType; typename ImageExportType::Pointer itkExporter = ImageExportType::New(); itkExporter->SetInput( newMaskImage ); vtkImageImport *vtkImporter = vtkImageImport::New(); this->ConnectPipelines( itkExporter, vtkImporter ); vtkImporter->Update(); // Apply the generated image stencil to the input image vtkImageStencil *imageStencilFilter = vtkImageStencil::New(); imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() ); imageStencilFilter->SetStencilConnection(polyDataToImageStencil->GetOutputPort() ); imageStencilFilter->ReverseStencilOff(); imageStencilFilter->SetBackgroundValue( 0 ); imageStencilFilter->Update(); // Export from VTK back to ITK vtkImageExport *vtkExporter = vtkImageExport::New(); vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() ); vtkExporter->Update(); typename ImageImportType::Pointer itkImporter = ImageImportType::New(); this->ConnectPipelines( vtkExporter, itkImporter ); itkImporter->Update(); // calculate cropping bounding box m_InternalImageMask3D = itkImporter->GetOutput(); m_InternalImageMask3D->SetDirection(image->GetDirection()); itk::ImageRegionConstIterator itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itk::ImageRegionIterator itimage(image, image->GetLargestPossibleRegion()); itmask.GoToBegin(); itimage.GoToBegin(); typename ImageType::SizeType lowersize = {{itk::NumericTraits::max(),itk::NumericTraits::max(),itk::NumericTraits::max()}}; typename ImageType::SizeType uppersize = {{0,0,0}}; while( !itmask.IsAtEnd() ) { if(itmask.Get() == 0) itimage.Set(0); else { typename ImageType::IndexType index = itimage.GetIndex(); typename ImageType::SizeType signedindex; signedindex[0] = index[0]; signedindex[1] = index[1]; signedindex[2] = index[2]; lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0]; lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1]; lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2]; uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0]; uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1]; uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2]; } ++itmask; ++itimage; } typename ImageType::IndexType index; index[0] = lowersize[0]; index[1] = lowersize[1]; index[2] = lowersize[2]; typename ImageType::SizeType size; size[0] = uppersize[0] - lowersize[0] + 1; size[1] = uppersize[1] - lowersize[1] + 1; size[2] = uppersize[2] - lowersize[2] + 1; itk::ImageRegion<3> cropRegion = itk::ImageRegion<3>(index, size); // crop internal mask typedef itk::RegionOfInterestImageFilter< itkUCharImageType, itkUCharImageType > ROIMaskFilterType; typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New(); roi2->SetRegionOfInterest(cropRegion); roi2->SetInput(m_InternalImageMask3D); roi2->Update(); m_InternalImageMask3D = roi2->GetOutput(); Image::Pointer tmpImage = Image::New(); tmpImage->InitializeByItk(m_InternalImageMask3D.GetPointer()); tmpImage->SetVolume(m_InternalImageMask3D->GetBufferPointer()); Image::Pointer tmpImage2 = Image::New(); tmpImage2->InitializeByItk(m_PlanarFigureImage.GetPointer()); const BaseGeometry *pfImageGeometry3D = tmpImage2->GetGeometry( 0 ); const BaseGeometry *intImageGeometry3D = tmpImage->GetGeometry( 0 ); typedef itk::ImageRegionIteratorWithIndex IteratorType; IteratorType imageIterator (m_InternalImageMask3D, m_InternalImageMask3D->GetRequestedRegion()); imageIterator.GoToBegin(); while ( !imageIterator.IsAtEnd() ) { unsigned char val = imageIterator.Value(); if (val>0) { itk::Index<3> index = imageIterator.GetIndex(); Point3D point; point[0] = index[0]; point[1] = index[1]; point[2] = index[2]; intImageGeometry3D->IndexToWorld(point, point); pfImageGeometry3D->WorldToIndex(point, point); point[i0] += 0.5; point[i1] += 0.5; index[0] = point[0]; index[1] = point[1]; index[2] = point[2]; if (pfImageGeometry3D->IsIndexInside(index)) m_PlanarFigureImage->SetPixel(index, 1); } ++imageIterator; } // Clean up VTK objects polyline->Delete(); extrudeFilter->Delete(); polyDataToImageStencil->Delete(); vtkImporter->Delete(); imageStencilFilter->Delete(); //vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak?? delete[] ptIds; } void QmitkFiberProcessingView::UpdateGui() { m_Controls->m_FibLabel->setText("mandatory"); m_Controls->m_PfLabel->setText("needed for extraction"); m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->m_RemoveButton->setEnabled(false); m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false); m_Controls->PFCompoANDButton->setEnabled(false); m_Controls->PFCompoORButton->setEnabled(false); m_Controls->PFCompoNOTButton->setEnabled(false); m_Controls->m_GenerateRoiImage->setEnabled(false); m_Controls->m_ExtractFibersButton->setEnabled(false); m_Controls->m_ModifyButton->setEnabled(false); m_Controls->m_CopyBundle->setEnabled(false); m_Controls->m_JoinBundles->setEnabled(false); m_Controls->m_SubstractBundles->setEnabled(false); // disable alle frames m_Controls->m_BundleWeightFrame->setVisible(false); m_Controls->m_ExtactionFramePF->setVisible(false); m_Controls->m_RemoveDirectionFrame->setVisible(false); m_Controls->m_RemoveLengthFrame->setVisible(false); m_Controls->m_RemoveCurvatureFrame->setVisible(false); + m_Controls->m_RemoveByWeightFrame->setVisible(false); m_Controls->m_SmoothFibersFrame->setVisible(false); m_Controls->m_CompressFibersFrame->setVisible(false); m_Controls->m_ColorFibersFrame->setVisible(false); m_Controls->m_MirrorFibersFrame->setVisible(false); m_Controls->m_MaskExtractionFrame->setVisible(false); m_Controls->m_ColorMapBox->setVisible(false); bool pfSelected = !m_SelectedPF.empty(); bool fibSelected = !m_SelectedFB.empty(); bool multipleFibsSelected = (m_SelectedFB.size()>1); bool maskSelected = m_MaskImageNode.IsNotNull(); bool imageSelected = m_SelectedImage.IsNotNull(); // toggle visibility of elements according to selected method switch ( m_Controls->m_ExtractionMethodBox->currentIndex() ) { case 0: m_Controls->m_ExtactionFramePF->setVisible(true); break; case 1: m_Controls->m_MaskExtractionFrame->setVisible(true); break; } switch ( m_Controls->m_RemovalMethodBox->currentIndex() ) { case 0: m_Controls->m_RemoveDirectionFrame->setVisible(true); if ( fibSelected ) m_Controls->m_RemoveButton->setEnabled(true); break; case 1: m_Controls->m_RemoveLengthFrame->setVisible(true); if ( fibSelected ) m_Controls->m_RemoveButton->setEnabled(true); break; case 2: m_Controls->m_RemoveCurvatureFrame->setVisible(true); if ( fibSelected ) m_Controls->m_RemoveButton->setEnabled(true); break; case 3: break; case 4: break; + case 5: + m_Controls->m_RemoveByWeightFrame->setVisible(true); + if ( fibSelected ) + m_Controls->m_RemoveButton->setEnabled(true); + break; } switch ( m_Controls->m_ModificationMethodBox->currentIndex() ) { case 0: m_Controls->m_SmoothFibersFrame->setVisible(true); break; case 1: m_Controls->m_SmoothFibersFrame->setVisible(true); break; case 2: m_Controls->m_CompressFibersFrame->setVisible(true); break; case 3: m_Controls->m_ColorFibersFrame->setVisible(true); m_Controls->m_ColorMapBox->setVisible(true); break; case 4: m_Controls->m_MirrorFibersFrame->setVisible(true); if (m_SelectedSurfaces.size()>0) m_Controls->m_ModifyButton->setEnabled(true); break; case 5: m_Controls->m_BundleWeightFrame->setVisible(true); break; case 6: m_Controls->m_ColorFibersFrame->setVisible(true); break; case 7: m_Controls->m_ColorFibersFrame->setVisible(true); break; } // are fiber bundles selected? if ( fibSelected ) { m_Controls->m_CopyBundle->setEnabled(true); m_Controls->m_ModifyButton->setEnabled(true); m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true); m_Controls->m_FibLabel->setText(QString(m_SelectedFB.at(0)->GetName().c_str())); // one bundle and one planar figure needed to extract fibers if (pfSelected && m_Controls->m_ExtractionMethodBox->currentIndex()==0) { m_Controls->m_InputData->setTitle("Input Data"); m_Controls->m_PfLabel->setText(QString(m_SelectedPF.at(0)->GetName().c_str())); m_Controls->m_ExtractFibersButton->setEnabled(true); } // more than two bundles needed to join/subtract if (multipleFibsSelected) { m_Controls->m_FibLabel->setText("multiple bundles selected"); m_Controls->m_JoinBundles->setEnabled(true); m_Controls->m_SubstractBundles->setEnabled(true); } if (maskSelected && m_Controls->m_ExtractionMethodBox->currentIndex()==1) { m_Controls->m_InputData->setTitle("Input Data"); m_Controls->m_PfLabel->setText(QString(m_MaskImageNode->GetName().c_str())); m_Controls->m_ExtractFibersButton->setEnabled(true); } if (maskSelected && (m_Controls->m_RemovalMethodBox->currentIndex()==3 || m_Controls->m_RemovalMethodBox->currentIndex()==4) ) { m_Controls->m_InputData->setTitle("Input Data"); m_Controls->m_PfLabel->setText(QString(m_MaskImageNode->GetName().c_str())); m_Controls->m_RemoveButton->setEnabled(true); } } // are planar figures selected? if (pfSelected) { if ( fibSelected || m_SelectedImage.IsNotNull()) m_Controls->m_GenerateRoiImage->setEnabled(true); if (m_SelectedPF.size() > 1) { m_Controls->PFCompoANDButton->setEnabled(true); m_Controls->PFCompoORButton->setEnabled(true); } else m_Controls->PFCompoNOTButton->setEnabled(true); } // is image selected if (imageSelected || maskSelected) { m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true); } } void QmitkFiberProcessingView::NodeRemoved(const mitk::DataNode* node ) { for (auto fnode: m_SelectedFB) if (node == fnode) { m_SelectedFB.clear(); break; } berry::IWorkbenchPart::Pointer nullPart; QList nodes; OnSelectionChanged(nullPart, nodes); } void QmitkFiberProcessingView::NodeAdded(const mitk::DataNode* ) { if (!m_Controls->m_InteractiveBox->isChecked()) { berry::IWorkbenchPart::Pointer nullPart; QList nodes; OnSelectionChanged(nullPart, nodes); } } void QmitkFiberProcessingView::OnEndInteraction() { if (m_Controls->m_InteractiveBox->isChecked()) ExtractWithPlanarFigure(true); } void QmitkFiberProcessingView::AddObservers() { typedef itk::SimpleMemberCommand< QmitkFiberProcessingView > SimpleCommandType; for (auto node : m_SelectedPF) { mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); if (figure!=nullptr) { figure->RemoveAllObservers(); // add observer for event when interaction with figure starts SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction( this, &QmitkFiberProcessingView::OnEndInteraction); m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); } } } void QmitkFiberProcessingView::RemoveObservers() { for (auto node : m_SelectedPF) { mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); if (figure!=nullptr) figure->RemoveAllObservers(); } } void QmitkFiberProcessingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { RemoveObservers(); //reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection std::vector lastSelectedFB = m_SelectedFB; m_SelectedFB.clear(); m_SelectedPF.clear(); m_SelectedSurfaces.clear(); m_SelectedImage = nullptr; m_MaskImageNode = nullptr; for (auto node: nodes) { if ( dynamic_cast(node->GetData()) ) m_SelectedFB.push_back(node); else if (dynamic_cast(node->GetData()) || dynamic_cast(node->GetData()) || dynamic_cast(node->GetData())) m_SelectedPF.push_back(node); else if (dynamic_cast(node->GetData())) { m_SelectedImage = dynamic_cast(node->GetData()); bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) m_MaskImageNode = node; } else if (dynamic_cast(node->GetData())) m_SelectedSurfaces.push_back(dynamic_cast(node->GetData())); } // if we perform interactive fiber extraction, we want to avoid auto-selection of the extracted bundle if (m_SelectedFB.empty() && m_Controls->m_InteractiveBox->isChecked()) m_SelectedFB = lastSelectedFB; // if no fibers or surfaces are selected, select topmost if (m_SelectedFB.empty() && m_SelectedSurfaces.empty()) { int maxLayer = 0; itk::VectorContainer::ConstPointer nodes = this->GetDataStorage()->GetAll(); for (unsigned int i=0; iSize(); i++) if (dynamic_cast(nodes->at(i)->GetData())) { mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i)); if (sources->Size()>0) continue; int layer = 0; nodes->at(i)->GetPropertyValue("layer", layer); if (layer>=maxLayer) { maxLayer = layer; m_SelectedFB.clear(); m_SelectedFB.push_back(nodes->at(i)); } } } // if no plar figure is selected, select topmost if (m_SelectedPF.empty()) { int maxLayer = 0; itk::VectorContainer::ConstPointer nodes = this->GetDataStorage()->GetAll(); for (unsigned int i=0; iSize(); i++) if (dynamic_cast(nodes->at(i)->GetData()) || dynamic_cast(nodes->at(i)->GetData()) || dynamic_cast(nodes->at(i)->GetData())) { mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i)); if (sources->Size()>0) continue; int layer = 0; nodes->at(i)->GetPropertyValue("layer", layer); if (layer>=maxLayer) { maxLayer = layer; m_SelectedPF.clear(); m_SelectedPF.push_back(nodes->at(i)); } } } AddObservers(); UpdateGui(); } void QmitkFiberProcessingView::OnDrawPolygon() { mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New(); figure->ClosedOn(); this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter)); } void QmitkFiberProcessingView::OnDrawCircle() { mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New(); this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_CircleCounter)); } void QmitkFiberProcessingView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *, mitk::BaseProperty* ) { // initialize figure's geometry with empty geometry mitk::PlaneGeometry::Pointer emptygeometry = mitk::PlaneGeometry::New(); figure->SetPlaneGeometry( emptygeometry ); //set desired data to DataNode where Planarfigure is stored mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetName(name.toStdString()); newNode->SetData(figure); newNode->SetBoolProperty("planarfigure.3drendering", true); newNode->SetBoolProperty("planarfigure.3drendering.fill", true); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(newNode->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode(newNode); } // figure drawn on the topmost layer / image GetDataStorage()->Add(newNode ); RemoveObservers(); for(unsigned int i = 0; i < m_SelectedPF.size(); i++) m_SelectedPF[i]->SetSelected(false); newNode->SetSelected(true); m_SelectedPF.clear(); m_SelectedPF.push_back(newNode); AddObservers(); UpdateGui(); } void QmitkFiberProcessingView::ExtractWithPlanarFigure(bool interactive) { if ( m_SelectedFB.empty() || m_SelectedPF.empty() ){ QMessageBox::information( nullptr, "Warning", "No fibe bundle selected!"); return; } try { std::vector fiberBundles = m_SelectedFB; mitk::DataNode::Pointer planarFigure = m_SelectedPF.at(0); for (unsigned int i=0; i(fiberBundles.at(i)->GetData()); mitk::FiberBundle::Pointer extFB = fib->ExtractFiberSubset(planarFigure, GetDataStorage()); if (interactive && m_Controls->m_InteractiveBox->isChecked()) { if (m_InteractiveNode.IsNull()) { m_InteractiveNode = mitk::DataNode::New(); QString name("Interactive"); m_InteractiveNode->SetName(name.toStdString()); GetDataStorage()->Add(m_InteractiveNode); } float op = 5.0/sqrt(fib->GetNumFibers()); float currentOp = 0; fiberBundles.at(i)->GetFloatProperty("opacity", currentOp); if (currentOp!=op) { fib->SetFiberColors(255, 255, 255); fiberBundles.at(i)->SetFloatProperty("opacity", op); fiberBundles.at(i)->SetBoolProperty("Fiber2DfadeEFX", false); } m_InteractiveNode->SetData(extFB); } else { if (extFB->GetNumFibers()<=0) { QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } mitk::DataNode::Pointer node; node = mitk::DataNode::New(); node->SetData(extFB); QString name(fiberBundles.at(i)->GetName().c_str()); name += "*"; node->SetName(name.toStdString()); fiberBundles.at(i)->SetVisibility(false); GetDataStorage()->Add(node); } } } catch(const std::out_of_range& ) { QMessageBox::warning( nullptr, "Fiber extraction failed", "Did you only create the planar figure, using the circle or polygon button, but forgot to actually place it in the image afterwards? \nAfter creating a planar figure, simply left-click at the desired position in the image or on the tractogram to place it."); } } void QmitkFiberProcessingView::GenerateAndComposite() { mitk::PlanarFigureComposite::Pointer PFCAnd = mitk::PlanarFigureComposite::New(); PFCAnd->setOperationType(mitk::PlanarFigureComposite::AND); mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); newPFCNode->SetName("AND"); newPFCNode->SetData(PFCAnd); AddCompositeToDatastorage(newPFCNode, m_SelectedPF); RemoveObservers(); m_SelectedPF.clear(); m_SelectedPF.push_back(newPFCNode); AddObservers(); UpdateGui(); } void QmitkFiberProcessingView::GenerateOrComposite() { mitk::PlanarFigureComposite::Pointer PFCOr = mitk::PlanarFigureComposite::New(); PFCOr->setOperationType(mitk::PlanarFigureComposite::OR); mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); newPFCNode->SetName("OR"); newPFCNode->SetData(PFCOr); RemoveObservers(); AddCompositeToDatastorage(newPFCNode, m_SelectedPF); m_SelectedPF.clear(); m_SelectedPF.push_back(newPFCNode); UpdateGui(); } void QmitkFiberProcessingView::GenerateNotComposite() { mitk::PlanarFigureComposite::Pointer PFCNot = mitk::PlanarFigureComposite::New(); PFCNot->setOperationType(mitk::PlanarFigureComposite::NOT); mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); newPFCNode->SetName("NOT"); newPFCNode->SetData(PFCNot); RemoveObservers(); AddCompositeToDatastorage(newPFCNode, m_SelectedPF); m_SelectedPF.clear(); m_SelectedPF.push_back(newPFCNode); AddObservers(); UpdateGui(); } void QmitkFiberProcessingView::AddCompositeToDatastorage(mitk::DataNode::Pointer pfc, std::vector children, mitk::DataNode::Pointer parentNode ) { pfc->SetSelected(true); if (parentNode.IsNotNull()) GetDataStorage()->Add(pfc, parentNode); else GetDataStorage()->Add(pfc); for (auto child : children) { if (dynamic_cast(child->GetData())) { mitk::DataNode::Pointer newChild; newChild = mitk::DataNode::New(); newChild->SetData(dynamic_cast(child->GetData())); newChild->SetName( child->GetName() ); newChild->SetBoolProperty("planarfigure.3drendering", true); newChild->SetBoolProperty("planarfigure.3drendering.fill", true); GetDataStorage()->Add(newChild, pfc); GetDataStorage()->Remove(child); } else if (dynamic_cast(child->GetData())) { mitk::DataNode::Pointer newChild; newChild = mitk::DataNode::New(); newChild->SetData(dynamic_cast(child->GetData())); newChild->SetName( child->GetName() ); std::vector< mitk::DataNode::Pointer > grandChildVector; mitk::DataStorage::SetOfObjects::ConstPointer grandchildren = GetDataStorage()->GetDerivations(child); for( mitk::DataStorage::SetOfObjects::const_iterator it = grandchildren->begin(); it != grandchildren->end(); ++it ) grandChildVector.push_back(*it); AddCompositeToDatastorage(newChild, grandChildVector, pfc); GetDataStorage()->Remove(child); } } UpdateGui(); } void QmitkFiberProcessingView::CopyBundles() { if ( m_SelectedFB.empty() ){ QMessageBox::information( nullptr, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least one fiber bundle!"; return; } for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); mitk::FiberBundle::Pointer newFib = fib->GetDeepCopy(); node->SetVisibility(false); QString name(""); name += QString(m_SelectedFB.at(0)->GetName().c_str()); name += "_copy"; mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newFib); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } UpdateGui(); } void QmitkFiberProcessingView::JoinBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } mitk::FiberBundle::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); m_SelectedFB.at(0)->SetVisibility(false); QString name(""); name += QString(m_SelectedFB.at(0)->GetName().c_str()); for (unsigned int i=1; iAddBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); name += "+"+QString(m_SelectedFB.at(i)->GetName().c_str()); m_SelectedFB.at(i)->SetVisibility(false); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); UpdateGui(); } void QmitkFiberProcessingView::SubstractBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } mitk::FiberBundle::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); m_SelectedFB.at(0)->SetVisibility(false); QString name(""); name += QString(m_SelectedFB.at(0)->GetName().c_str()); for (unsigned int i=1; iSubtractBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); if (newBundle.IsNull()) break; name += "-"+QString(m_SelectedFB.at(i)->GetName().c_str()); m_SelectedFB.at(i)->SetVisibility(false); } if (newBundle.IsNull()) { QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers. Did you select the fiber bundles in the correct order? X-Y is not equal to Y-X!"); return; } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); UpdateGui(); } void QmitkFiberProcessingView::ResampleSelectedBundlesSpline() { double factor = this->m_Controls->m_SmoothFibersBox->value(); for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); fib->ResampleSpline(factor); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::ResampleSelectedBundlesLinear() { double factor = this->m_Controls->m_SmoothFibersBox->value(); for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); fib->ResampleLinear(factor); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::CompressSelectedBundles() { double factor = this->m_Controls->m_ErrorThresholdBox->value(); for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); fib->Compress(factor); fib->ColorFibersByOrientation(); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::DoImageColorCoding() { if (m_Controls->m_ColorMapBox->GetSelectedNode().IsNull()) { QMessageBox::information(nullptr, "Bundle coloring aborted:", "No image providing the scalar values for coloring the selected bundle available."); return; } for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); fib->ColorFibersByScalarMap(dynamic_cast(m_Controls->m_ColorMapBox->GetSelectedNode()->GetData()), m_Controls->m_FiberOpacityBox->isChecked(), m_Controls->m_NormalizeColorValues->isChecked()); } if (auto renderWindowPart = this->GetRenderWindowPart()) { renderWindowPart->RequestUpdate(); } } void QmitkFiberProcessingView::DoCurvatureColorCoding() { for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); fib->ColorFibersByCurvature(m_Controls->m_FiberOpacityBox->isChecked(), m_Controls->m_NormalizeColorValues->isChecked()); } if (auto renderWindowPart = this->GetRenderWindowPart()) { renderWindowPart->RequestUpdate(); } } void QmitkFiberProcessingView::DoWeightColorCoding() { for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); fib->ColorFibersByFiberWeights(m_Controls->m_FiberOpacityBox->isChecked(), m_Controls->m_NormalizeColorValues->isChecked()); } if (auto renderWindowPart = this->GetRenderWindowPart()) { renderWindowPart->RequestUpdate(); } } void QmitkFiberProcessingView::MirrorFibers() { unsigned int axis = this->m_Controls->m_MirrorFibersBox->currentIndex(); for (auto node : m_SelectedFB) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); if (m_SelectedImage.IsNotNull()) fib->SetReferenceGeometry(m_SelectedImage->GetGeometry()); fib->MirrorFibers(axis); } for (auto surf : m_SelectedSurfaces) { vtkSmartPointer poly = surf->GetVtkPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); for (int i=0; iGetNumberOfPoints(); i++) { double* point = poly->GetPoint(i); point[axis] *= -1; vtkNewPoints->InsertNextPoint(point); } poly->SetPoints(vtkNewPoints); surf->CalculateBoundingBox(); } if (auto renderWindowPart = this->GetRenderWindowPart()) { renderWindowPart->RequestUpdate(); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.h index 522d304afe..4651a3f7ed 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.h @@ -1,199 +1,200 @@ /*=================================================================== 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 QmitkFiberProcessingView_h #define QmitkFiberProcessingView_h #include #include "ui_QmitkFiberProcessingViewControls.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! \brief View to process fiber bundles. Supplies methods to extract fibers from the bundle, fiber resampling, mirroring, join and subtract bundles and much more. */ class QmitkFiberProcessingView : 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< unsigned char, 3 > itkUCharImageType; static const std::string VIEW_ID; QmitkFiberProcessingView(); virtual ~QmitkFiberProcessingView(); virtual void CreateQtPartControl(QWidget *parent) override; /// /// Sets the focus to an internal widget. /// virtual void SetFocus() override; protected slots: void OnDrawCircle(); ///< add circle interactors etc. void OnDrawPolygon(); ///< add circle interactors etc. void GenerateAndComposite(); void GenerateOrComposite(); void GenerateNotComposite(); void CopyBundles(); ///< add copies of selected bundles to data storage void JoinBundles(); ///< merge selected fiber bundles void SubstractBundles(); ///< subtract bundle A from bundle B. Not commutative! Defined by order of selection. void GenerateRoiImage(); ///< generate binary image of selected planar figures. void Remove(); void Extract(); void Modify(); void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection void OnMaskExtractionChanged(); virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey = nullptr, mitk::BaseProperty *property = nullptr ); protected: void MirrorFibers(); ///< mirror bundle on the specified plane void ResampleSelectedBundlesSpline(); ///< void ResampleSelectedBundlesLinear(); ///< void DoImageColorCoding(); ///< color fibers by selected scalar image void DoWeightColorCoding(); ///< color fibers by their respective weights void DoCurvatureColorCoding(); ///< color fibers by curvature void CompressSelectedBundles(); ///< remove points below certain error threshold void WeightFibers(); + void ApplyWeightThreshold(); void RemoveWithMask(bool removeInside); void RemoveDir(); void ApplyCurvatureThreshold(); ///< remove/split fibers with a too high curvature threshold void PruneBundle(); ///< remove too short/too long fibers void ExtractWithMask(bool onlyEnds, bool invert); void ExtractWithPlanarFigure(bool interactive=false); void OnEndInteraction(); /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; Ui::QmitkFiberProcessingViewControls* m_Controls; /** Connection from VTK to ITK */ template void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template < typename TPixel, unsigned int VImageDimension > void InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName ); template < typename TPixel, unsigned int VImageDimension > void InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex ); int m_CircleCounter; ///< used for data node naming int m_PolygonCounter; ///< used for data node naming std::vector m_SelectedFB; ///< selected fiber bundle nodes std::vector m_SelectedPF; ///< selected planar figure nodes std::vector m_SelectedSurfaces; mitk::Image::Pointer m_SelectedImage; mitk::Image::Pointer m_InternalImage; mitk::PlanarFigure::Pointer m_PlanarFigure; itkUCharImageType::Pointer m_InternalImageMask3D; itkUCharImageType::Pointer m_PlanarFigureImage; float m_UpsamplingFactor; ///< upsampling factor for all image generations mitk::DataNode::Pointer m_MaskImageNode; unsigned int m_StartInteractionObserverTag; unsigned int m_EndInteractionObserverTag; mitk::DataNode::Pointer m_InteractiveNode; void AddCompositeToDatastorage(mitk::DataNode::Pointer pfc, std::vector children, mitk::DataNode::Pointer parentNode=nullptr); void debugPFComposition(mitk::PlanarFigureComposite::Pointer , int ); void WritePfToImage(mitk::DataNode::Pointer node, mitk::Image* image); mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundle::Pointer fib, bool binary, bool absolute); mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundle::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundle::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundle::Pointer fib); void NodeAdded( const mitk::DataNode* node ) override; void NodeRemoved(const mitk::DataNode* node) override; void RemoveObservers(); void AddObservers(); }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingViewControls.ui index d49bc8afea..3df18fd8fc 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingViewControls.ui @@ -1,1450 +1,1502 @@ QmitkFiberProcessingViewControls 0 0 385 - 564 + 684 Form 0 5 0 0 - 353 + 367 382 Fiber Extraction Extract a fiber subset from the selected fiber bundle using manually placed planar figures as waypoints or binary regions of interest. false 0 0 200 16777215 11 Extract fibers passing through selected ROI or composite ROI. Select ROI and fiber bundle to execute. Extract Qt::Vertical 20 40 QFrame::NoFrame QFrame::Raised 9 9 9 9 0 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 0 0 0 false 60 16777215 Create OR composition with selected ROIs. OR Qt::Horizontal 40 20 false 60 16777215 Create NOT composition from selected ROI. NOT false 60 16777215 Create AND composition with selected ROIs. AND 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 0 0 0 30 30 Draw circular ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png 32 32 false true Qt::Horizontal 40 20 30 30 Draw polygonal ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/polygon.png:/QmitkDiffusionImaging/polygon.png 32 32 true true false 0 0 16777215 16777215 11 Generate a binary image containing all selected ROIs. Select at least one ROI (planar figure) and a reference fiber bundle or image. Generate ROI Image Interactive Extraction 0 0 Extract using planar figures Extract using binary ROI image QFrame::NoFrame QFrame::Raised 0 0 0 0 Both ends true 1.000000000000000 0.100000000000000 Extract fibers: 0 0 Ending in mask Not ending in mask Passing mask Not passing mask Min. overlap: 0 0 - 353 - 371 + 367 + 408 Fiber Removal Remove fibers that satisfy certain criteria from the selected bundle. - - - - - 0 - 0 - - - - - Remove fibers in direction - - - - - Remove fibers by length - - - - - Remove fibers by curvature - - - - - Remove fiber parts outside mask - - - - - Remove fiber parts inside mask - - - - - - + + QFrame::NoFrame QFrame::Raised - + 0 0 0 0 - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - + + - Minimum fiber length in mm - - - 0 - - - 999999999 - - - 20 + If unchecked, the fiber exceeding the threshold will be split in two instead of removed. - - - - - Max. Length: + Remove Fiber - - - - - - Min. Length: + + false - - - - Maximum fiber length in mm - - - 0 - - - 999999999 + + + + QFrame::NoFrame - - 300 + + QFrame::Raised + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Max. Angular Deviation: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Maximum angular deviation in degree + + + 180.000000000000000 + + + 0.100000000000000 + + + 30.000000000000000 + + + + + + + Distance: + + + + + + + Distance in mm + + + 1 + + + 999.000000000000000 + + + 1.000000000000000 + + + 10.000000000000000 + + + + QFrame::NoFrame QFrame::Raised 0 0 0 0 0 X: Y: Z: Angle: Angular deviation threshold in degree 1 90.000000000000000 1.000000000000000 25.000000000000000 - - + + QFrame::NoFrame QFrame::Raised - + 0 0 0 0 - - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + - If unchecked, the fiber exceeding the threshold will be split in two instead of removed. + Minimum fiber length in mm + + + 0 + + + 999999999 + + 20 + + + + + - Remove Fiber + Max. Length: - - false + + + + + + Min. Length: - - - - QFrame::NoFrame + + + + Maximum fiber length in mm - - QFrame::Raised + + 0 + + + 999999999 + + + 300 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Max. Angular Deviation: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Maximum angular deviation in degree - - - 180.000000000000000 - - - 0.100000000000000 - - - 30.000000000000000 - - - - - - - Distance: - - - - - - - Distance in mm - - - 1 - - - 999.000000000000000 - - - 1.000000000000000 - - - 10.000000000000000 - - - - - + false 0 0 200 16777215 11 Remove - + Qt::Vertical 20 40 + + + + + 0 + 0 + + + + + Remove fibers in direction + + + + + Remove fibers by length + + + + + Remove fibers by curvature + + + + + Remove fiber parts outside mask + + + + + Remove fiber parts inside mask + + + + + Remove fibers by weight + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Weight threshold: + + + + + + + Only fibers with weight larger than this threshold are kept. + + + 5 + + + 0.100000000000000 + + + + + + 0 0 - 353 - 364 + 367 + 408 Bundle Modification Modify the selected bundle with operations such as fiber resampling, FA coloring, etc. QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Error threshold in mm: 999999999.000000000000000 0.100000000000000 0.100000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Sagittal Coronal Axial Select direction: QFrame::NoFrame QFrame::Raised 0 0 0 0 0 If checked, the image values are not only used to color the fibers but are also used as opaxity values. Values as opacity false Scalar map: The values used to color the fibers are min-max normalized. If not checked, the values should be between 0 and 1. Normalize values true 0 0 Resample fibers (spline) Resample fibers (linear) Compress fibers Color fibers by scalar map (e.g. FA) Mirror fibers Weight bundle Color fibers by curvature Color fibers by fiber weights QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0.010000000000000 999999999.000000000000000 0.100000000000000 1.000000000000000 Point distance in mm: Qt::Vertical 20 40 false 0 0 200 16777215 11 Execute QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Weight: 7 999999999.000000000000000 0.100000000000000 1.000000000000000 0 0 367 - 152 + 165 Bundle Operations Join, subtract or copy bundles. false 0 0 200 16777215 11 Returns all fibers contained in bundle X that are not contained in bundle Y (not commutative!). Select at least two fiber bundles to execute. Substract Qt::Vertical 20 40 false 0 0 200 16777215 11 Merge selected fiber bundles. Select at least two fiber bundles to execute. Join false 0 0 200 16777215 11 Merge selected fiber bundles. Select at least two fiber bundles to execute. Copy Please Select Input Data <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true <html><head/><body><p><span style=" color:#969696;">needed for extraction</span></p></body></html> true Input DTI Fiber Bundle: Binary seed ROI. If not specified, the whole image area is seeded. ROI: Qt::Vertical 20 40 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
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 074d5c67ef..c410e854d2 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 Fiber Processing") +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) 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 074d5c67ef..d9d2df538c 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 Fiber Processing") +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) 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 074d5c67ef..dbf79c0d1e 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 Fiber Processing") +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) 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 074d5c67ef..b9885bba96 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 Fiber Processing") +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) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp index 6675188dbf..26310fa9ab 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp @@ -1,1963 +1,1962 @@ /*=================================================================== 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 MBILOG_ENABLE_DEBUG #include "QmitkPreprocessingView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include // itk includes #include "itkTimeProbe.h" #include "itkB0ImageExtractionImageFilter.h" #include "itkB0ImageExtractionToSeparateImageFilter.h" #include "itkBrainMaskExtractionImageFilter.h" #include "itkCastImageFilter.h" #include "itkVectorContainer.h" #include #include #include #include #include #include // Multishell includes #include // Multishell Functors #include #include #include #include // mitk includes #include "QmitkDataStorageComboBox.h" #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "mitkProperties.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include const std::string QmitkPreprocessingView::VIEW_ID = "org.mitk.views.preprocessing"; #define DI_INFO MITK_INFO("DiffusionImaging") typedef float TTensorPixelType; QmitkPreprocessingView::QmitkPreprocessingView() : QmitkAbstractView(), m_Controls(nullptr) { } QmitkPreprocessingView::~QmitkPreprocessingView() { } void QmitkPreprocessingView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkPreprocessingViewControls; m_Controls->setupUi(parent); this->CreateConnections(); m_Controls->m_MeasurementFrameTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_Controls->m_MeasurementFrameTable->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_Controls->m_DirectionMatrixTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_Controls->m_DirectionMatrixTable->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); } } void QmitkPreprocessingView::SetFocus() { m_Controls->m_MirrorGradientToHalfSphereButton->setFocus(); } void QmitkPreprocessingView::CreateConnections() { if ( m_Controls ) { m_Controls->m_NormalizationMaskBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_SelctedImageComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_MergeDwiBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_AlignImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("OdfImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isOdf, isDti); mitk::NodePredicateAnd::Pointer noDiffusionImage = mitk::NodePredicateAnd::New(isMitkImage, mitk::NodePredicateNot::New(isDiffusionImage)); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer binaryNoDiffusionImage = mitk::NodePredicateAnd::New(noDiffusionImage, isBinaryPredicate); m_Controls->m_NormalizationMaskBox->SetPredicate(binaryNoDiffusionImage); m_Controls->m_SelctedImageComboBox->SetPredicate(isMitkImage); m_Controls->m_MergeDwiBox->SetPredicate(isMitkImage); m_Controls->m_AlignImageBox->SetPredicate(isMitkImage); m_Controls->m_ExtractBrainMask->setVisible(false); m_Controls->m_BrainMaskIterationsBox->setVisible(false); m_Controls->m_ResampleIntFrame->setVisible(false); connect( (QObject*)(m_Controls->m_ButtonAverageGradients), SIGNAL(clicked()), this, SLOT(AverageGradients()) ); connect( (QObject*)(m_Controls->m_ButtonExtractB0), SIGNAL(clicked()), this, SLOT(ExtractB0()) ); connect( (QObject*)(m_Controls->m_ReduceGradientsButton), SIGNAL(clicked()), this, SLOT(DoReduceGradientDirections()) ); connect( (QObject*)(m_Controls->m_ShowGradientsButton), SIGNAL(clicked()), this, SLOT(DoShowGradientDirections()) ); connect( (QObject*)(m_Controls->m_MirrorGradientToHalfSphereButton), SIGNAL(clicked()), this, SLOT(DoHalfSphereGradientDirections()) ); connect( (QObject*)(m_Controls->m_MergeDwisButton), SIGNAL(clicked()), this, SLOT(MergeDwis()) ); connect( (QObject*)(m_Controls->m_ProjectSignalButton), SIGNAL(clicked()), this, SLOT(DoProjectSignal()) ); connect( (QObject*)(m_Controls->m_B_ValueMap_Rounder_SpinBox), SIGNAL(valueChanged(int)), this, SLOT(UpdateDwiBValueMapRounder(int))); connect( (QObject*)(m_Controls->m_CreateLengthCorrectedDwi), SIGNAL(clicked()), this, SLOT(DoLengthCorrection()) ); connect( (QObject*)(m_Controls->m_NormalizeImageValuesButton), SIGNAL(clicked()), this, SLOT(DoDwiNormalization()) ); connect( (QObject*)(m_Controls->m_ResampleImageButton), SIGNAL(clicked()), this, SLOT(DoResampleImage()) ); connect( (QObject*)(m_Controls->m_ResampleTypeBox), SIGNAL(currentIndexChanged(int)), this, SLOT(DoUpdateInterpolationGui(int)) ); connect( (QObject*)(m_Controls->m_CropImageButton), SIGNAL(clicked()), this, SLOT(DoCropImage()) ); connect( (QObject*)(m_Controls->m_RemoveGradientButton), SIGNAL(clicked()), this, SLOT(DoRemoveGradient()) ); connect( (QObject*)(m_Controls->m_ExtractGradientButton), SIGNAL(clicked()), this, SLOT(DoExtractGradient()) ); connect( (QObject*)(m_Controls->m_FlipAxis), SIGNAL(clicked()), this, SLOT(DoFlipAxis()) ); connect( (QObject*)(m_Controls->m_FlipGradientsButton), SIGNAL(clicked()), this, SLOT(DoFlipGradientDirections()) ); connect( (QObject*)(m_Controls->m_ClearRotationButton), SIGNAL(clicked()), this, SLOT(DoClearRotationOfGradients()) ); connect( (QObject*)(m_Controls->m_ModifyHeader), SIGNAL(clicked()), this, SLOT(DoApplyHeader()) ); connect( (QObject*)(m_Controls->m_AlignImageButton), SIGNAL(clicked()), this, SLOT(DoAlignImages()) ); connect( (QObject*)(m_Controls->m_SelctedImageComboBox), SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnImageSelectionChanged()) ); m_Controls->m_NormalizationMaskBox->SetZeroEntryText("--"); } } void QmitkPreprocessingView::DoAlignImages() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } mitk::DataNode::Pointer target_node = m_Controls->m_AlignImageBox->GetSelectedNode(); if (target_node.IsNull()) { return; } mitk::Image::Pointer target_image = dynamic_cast(target_node->GetData()); if ( target_image == nullptr ) { return; } target_image->SetOrigin(image->GetGeometry()->GetOrigin()); mitk::RenderingManager::GetInstance()->InitializeViews( target_image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoFlipAxis() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(node) ); if (isDiffusionImage) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); itk::FixedArray flipAxes; flipAxes[0] = m_Controls->m_FlipX->isChecked(); flipAxes[1] = m_Controls->m_FlipY->isChecked(); flipAxes[2] = m_Controls->m_FlipZ->isChecked(); itk::FlipImageFilter< ItkDwiType >::Pointer flipper = itk::FlipImageFilter< ItkDwiType >::New(); flipper->SetInput(itkVectorImagePointer); flipper->SetFlipAxes(flipAxes); flipper->Update(); GradProp::GradientDirectionsContainerType::Pointer oldGradients = static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); GradProp::GradientDirectionsContainerType::Pointer newGradients = GradProp::GradientDirectionsContainerType::New(); for (unsigned int i=0; iSize(); i++) { GradProp::GradientDirectionType g = oldGradients->GetElement(i); GradProp::GradientDirectionType newG = g; if (flipAxes[0]) { newG[0] *= -1; } if (flipAxes[1]) { newG[1] *= -1; } if (flipAxes[2]) { newG[2] *= -1; } newGradients->InsertElement(i, newG); } mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( flipper->GetOutput() ); PropHelper::CopyProperties(image, newImage, true); newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( newGradients ) ); PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); newImage->GetGeometry()->SetOrigin(image->GetGeometry()->GetOrigin()); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_flipped").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if( image->GetPixelType().GetNumberOfComponents() == 1 ) { AccessFixedDimensionByItk(image, TemplatedFlipAxis,3); } else { QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedFlipAxis(itk::Image* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } itk::FixedArray flipAxes; flipAxes[0] = m_Controls->m_FlipX->isChecked(); flipAxes[1] = m_Controls->m_FlipY->isChecked(); flipAxes[2] = m_Controls->m_FlipZ->isChecked(); typename itk::FlipImageFilter< itk::Image >::Pointer flipper = itk::FlipImageFilter< itk::Image >::New(); flipper->SetInput(itkImage); flipper->SetFlipAxes(flipAxes); flipper->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( flipper->GetOutput() ); newImage->GetGeometry()->SetOrigin(image->GetGeometry()->GetOrigin()); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_flipped").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoRemoveGradient() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } std::vector< unsigned int > channelsToRemove; channelsToRemove.push_back(m_Controls->m_RemoveGradientBox->value()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); itk::RemoveDwiChannelFilter< short >::Pointer filter = itk::RemoveDwiChannelFilter< short >::New(); filter->SetInput(itkVectorImagePointer); filter->SetChannelIndices(channelsToRemove); filter->SetDirections( static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() ); PropHelper::CopyProperties(image, newImage, true); newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( filter->GetNewDirections() ) ); PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_removedgradients").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoExtractGradient() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); unsigned int channel = m_Controls->m_ExtractGradientBox->value(); itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New(); filter->SetInput( itkVectorImagePointer); filter->SetChannelIndex(channel); filter->Update(); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( filter->GetOutput() ); newImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName( (name+"_direction-"+QString::number(channel)).toStdString().c_str() ); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } void QmitkPreprocessingView::DoCropImage() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( isDiffusionImage ) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); ItkDwiType::SizeType lower; ItkDwiType::SizeType upper; lower[0] = m_Controls->m_XstartBox->value(); lower[1] = m_Controls->m_YstartBox->value(); lower[2] = m_Controls->m_ZstartBox->value(); upper[0] = m_Controls->m_XendBox->value(); upper[1] = m_Controls->m_YendBox->value(); upper[2] = m_Controls->m_ZendBox->value(); itk::CropImageFilter< ItkDwiType, ItkDwiType >::Pointer cropper = itk::CropImageFilter< ItkDwiType, ItkDwiType >::New(); cropper->SetLowerBoundaryCropSize(lower); cropper->SetUpperBoundaryCropSize(upper); cropper->SetInput( itkVectorImagePointer ); cropper->Update(); ItkDwiType::Pointer itkOutImage = cropper->GetOutput(); ItkDwiType::DirectionType dir = itkOutImage->GetDirection(); itk::Point origin = itkOutImage->GetOrigin(); itk::Point t; t[0] = lower[0]*itkOutImage->GetSpacing()[0]; t[1] = lower[1]*itkOutImage->GetSpacing()[1]; t[2] = lower[2]*itkOutImage->GetSpacing()[2]; t= dir*t; origin[0] += t[0]; origin[1] += t[1]; origin[2] += t[2]; itkOutImage->SetOrigin(origin); mitk::Image::Pointer newimage = mitk::GrabItkImageMemory( itkOutImage ); PropHelper::CopyProperties(image, newimage, false); PropHelper propertyHelper( newimage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newimage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_cropped").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if( image->GetPixelType().GetNumberOfComponents() ) { AccessFixedDimensionByItk(image, TemplatedCropImage,3); } else { QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedCropImage( itk::Image* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } ItkDwiType::SizeType lower; ItkDwiType::SizeType upper; lower[0] = m_Controls->m_XstartBox->value(); lower[1] = m_Controls->m_YstartBox->value(); lower[2] = m_Controls->m_ZstartBox->value(); upper[0] = m_Controls->m_XendBox->value(); upper[1] = m_Controls->m_YendBox->value(); upper[2] = m_Controls->m_ZendBox->value(); typedef itk::Image ImageType; typename itk::CropImageFilter< ImageType, ImageType >::Pointer cropper = itk::CropImageFilter< ImageType, ImageType >::New(); cropper->SetLowerBoundaryCropSize(lower); cropper->SetUpperBoundaryCropSize(upper); cropper->SetInput(itkImage); cropper->Update(); typename ImageType::Pointer itkOutImage = cropper->GetOutput(); typename ImageType::DirectionType dir = itkOutImage->GetDirection(); itk::Point origin = itkOutImage->GetOrigin(); itk::Point t; t[0] = lower[0]*itkOutImage->GetSpacing()[0]; t[1] = lower[1]*itkOutImage->GetSpacing()[1]; t[2] = lower[2]*itkOutImage->GetSpacing()[2]; t= dir*t; origin[0] += t[0]; origin[1] += t[1]; origin[2] += t[2]; itkOutImage->SetOrigin(origin); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( itkOutImage.GetPointer() ); image->SetVolume( itkOutImage->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_cropped").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoUpdateInterpolationGui(int i) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } switch (i) { case 0: { m_Controls->m_ResampleIntFrame->setVisible(false); m_Controls->m_ResampleDoubleFrame->setVisible(true); break; } case 1: { m_Controls->m_ResampleIntFrame->setVisible(false); m_Controls->m_ResampleDoubleFrame->setVisible(true); mitk::BaseGeometry* geom = image->GetGeometry(); m_Controls->m_ResampleDoubleX->setValue(geom->GetSpacing()[0]); m_Controls->m_ResampleDoubleY->setValue(geom->GetSpacing()[1]); m_Controls->m_ResampleDoubleZ->setValue(geom->GetSpacing()[2]); break; } case 2: { m_Controls->m_ResampleIntFrame->setVisible(true); m_Controls->m_ResampleDoubleFrame->setVisible(false); mitk::BaseGeometry* geom = image->GetGeometry(); m_Controls->m_ResampleIntX->setValue(geom->GetExtent(0)); m_Controls->m_ResampleIntY->setValue(geom->GetExtent(1)); m_Controls->m_ResampleIntZ->setValue(geom->GetExtent(2)); break; } default: { m_Controls->m_ResampleIntFrame->setVisible(false); m_Controls->m_ResampleDoubleFrame->setVisible(true); } } } void QmitkPreprocessingView::DoExtractBrainMask() { } void QmitkPreprocessingView::DoResampleImage() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( isDiffusionImage ) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); typedef itk::ResampleDwiImageFilter< short > ResampleFilter; ResampleFilter::Pointer resampler = ResampleFilter::New(); resampler->SetInput( itkVectorImagePointer ); switch (m_Controls->m_ResampleTypeBox->currentIndex()) { case 0: { itk::Vector< double, 3 > samplingFactor; samplingFactor[0] = m_Controls->m_ResampleDoubleX->value(); samplingFactor[1] = m_Controls->m_ResampleDoubleY->value(); samplingFactor[2] = m_Controls->m_ResampleDoubleZ->value(); resampler->SetSamplingFactor(samplingFactor); break; } case 1: { itk::Vector< double, 3 > newSpacing; newSpacing[0] = m_Controls->m_ResampleDoubleX->value(); newSpacing[1] = m_Controls->m_ResampleDoubleY->value(); newSpacing[2] = m_Controls->m_ResampleDoubleZ->value(); resampler->SetNewSpacing(newSpacing); break; } case 2: { itk::ImageRegion<3> newRegion; newRegion.SetSize(0, m_Controls->m_ResampleIntX->value()); newRegion.SetSize(1, m_Controls->m_ResampleIntY->value()); newRegion.SetSize(2, m_Controls->m_ResampleIntZ->value()); resampler->SetNewImageSize(newRegion); break; } default: { MITK_WARN << "Unknown resampling parameters!"; return; } } QString outAdd; switch (m_Controls->m_InterpolatorBox->currentIndex()) { case 0: { resampler->SetInterpolation(ResampleFilter::Interpolate_NearestNeighbour); outAdd = "NearestNeighbour"; break; } case 1: { resampler->SetInterpolation(ResampleFilter::Interpolate_Linear); outAdd = "Linear"; break; } case 2: { resampler->SetInterpolation(ResampleFilter::Interpolate_BSpline); outAdd = "BSpline"; break; } case 3: { resampler->SetInterpolation(ResampleFilter::Interpolate_WindowedSinc); outAdd = "WindowedSinc"; break; } default: { resampler->SetInterpolation(ResampleFilter::Interpolate_NearestNeighbour); outAdd = "NearestNeighbour"; } } resampler->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( resampler->GetOutput() ); PropHelper::CopyProperties(image, newImage, false); PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_resampled_"+outAdd).toStdString().c_str()); imageNode->SetVisibility(false); GetDataStorage()->Add(imageNode, node); } else if( image->GetPixelType().GetNumberOfComponents() ) { AccessFixedDimensionByItk(image, TemplatedResampleImage,3); } else { QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedResampleImage( itk::Image* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } itk::Vector< double, 3 > newSpacing; itk::ImageRegion<3> newRegion; switch (m_Controls->m_ResampleTypeBox->currentIndex()) { case 0: { itk::Vector< double, 3 > sampling; sampling[0] = m_Controls->m_ResampleDoubleX->value(); sampling[1] = m_Controls->m_ResampleDoubleY->value(); sampling[2] = m_Controls->m_ResampleDoubleZ->value(); newSpacing = itkImage->GetSpacing(); newSpacing[0] /= sampling[0]; newSpacing[1] /= sampling[1]; newSpacing[2] /= sampling[2]; newRegion = itkImage->GetLargestPossibleRegion(); newRegion.SetSize(0, newRegion.GetSize(0)*sampling[0]); newRegion.SetSize(1, newRegion.GetSize(1)*sampling[1]); newRegion.SetSize(2, newRegion.GetSize(2)*sampling[2]); break; } case 1: { newSpacing[0] = m_Controls->m_ResampleDoubleX->value(); newSpacing[1] = m_Controls->m_ResampleDoubleY->value(); newSpacing[2] = m_Controls->m_ResampleDoubleZ->value(); itk::Vector< double, 3 > oldSpacing = itkImage->GetSpacing(); itk::Vector< double, 3 > sampling; sampling[0] = oldSpacing[0]/newSpacing[0]; sampling[1] = oldSpacing[1]/newSpacing[1]; sampling[2] = oldSpacing[2]/newSpacing[2]; newRegion = itkImage->GetLargestPossibleRegion(); newRegion.SetSize(0, newRegion.GetSize(0)*sampling[0]); newRegion.SetSize(1, newRegion.GetSize(1)*sampling[1]); newRegion.SetSize(2, newRegion.GetSize(2)*sampling[2]); break; } case 2: { newRegion.SetSize(0, m_Controls->m_ResampleIntX->value()); newRegion.SetSize(1, m_Controls->m_ResampleIntY->value()); newRegion.SetSize(2, m_Controls->m_ResampleIntZ->value()); itk::ImageRegion<3> oldRegion = itkImage->GetLargestPossibleRegion(); itk::Vector< double, 3 > sampling; sampling[0] = (double)newRegion.GetSize(0)/oldRegion.GetSize(0); sampling[1] = (double)newRegion.GetSize(1)/oldRegion.GetSize(1); sampling[2] = (double)newRegion.GetSize(2)/oldRegion.GetSize(2); newSpacing = itkImage->GetSpacing(); newSpacing[0] /= sampling[0]; newSpacing[1] /= sampling[1]; newSpacing[2] /= sampling[2]; break; } default: { MITK_WARN << "Unknown resampling parameters!"; return; } } itk::Point origin = itkImage->GetOrigin(); origin[0] -= itkImage->GetSpacing()[0]/2; origin[1] -= itkImage->GetSpacing()[1]/2; origin[2] -= itkImage->GetSpacing()[2]/2; origin[0] += newSpacing[0]/2; origin[1] += newSpacing[1]/2; origin[2] += newSpacing[2]/2; typedef itk::Image ImageType; typename ImageType::Pointer outImage = ImageType::New(); outImage->SetSpacing( newSpacing ); outImage->SetOrigin( origin ); outImage->SetDirection( itkImage->GetDirection() ); outImage->SetLargestPossibleRegion( newRegion ); outImage->SetBufferedRegion( newRegion ); outImage->SetRequestedRegion( newRegion ); outImage->Allocate(); typedef itk::ResampleImageFilter ResampleFilter; typename ResampleFilter::Pointer resampler = ResampleFilter::New(); resampler->SetInput(itkImage); resampler->SetOutputParametersFromImage(outImage); QString outAdd; switch (m_Controls->m_InterpolatorBox->currentIndex()) { case 0: { typename itk::NearestNeighborInterpolateImageFunction::Pointer interp = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "NearestNeighbour"; break; } case 1: { typename itk::LinearInterpolateImageFunction::Pointer interp = itk::LinearInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "Linear"; break; } case 2: { typename itk::BSplineInterpolateImageFunction::Pointer interp = itk::BSplineInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "BSpline"; break; } case 3: { typename itk::WindowedSincInterpolateImageFunction::Pointer interp = itk::WindowedSincInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "WindowedSinc"; break; } default: { typename itk::NearestNeighborInterpolateImageFunction::Pointer interp = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "NearestNeighbour"; } } resampler->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( resampler->GetOutput() ); image->SetVolume( resampler->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_resampled_"+outAdd).toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::DoApplyHeader() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); bool isDti = false; bool isOdf = false; bool isPeak = false; if (!isDiffusionImage) { if ( dynamic_cast(node->GetData()) ) isDti = true; else if ( dynamic_cast(node->GetData()) ) isOdf = true; else if ( dynamic_cast(node->GetData()) ) isPeak = true; } mitk::Image::Pointer newImage = image->Clone(); mitk::Vector3D spacing; spacing[0] = m_Controls->m_HeaderSpacingX->value(); spacing[1] = m_Controls->m_HeaderSpacingY->value(); spacing[2] = m_Controls->m_HeaderSpacingZ->value(); newImage->GetGeometry()->SetSpacing( spacing ); mitk::Point3D origin; origin[0] = m_Controls->m_HeaderOriginX->value(); origin[1] = m_Controls->m_HeaderOriginY->value(); origin[2] = m_Controls->m_HeaderOriginZ->value(); newImage->GetGeometry()->SetOrigin(origin); vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New(); matrix->SetElement(0,3,newImage->GetGeometry()->GetOrigin()[0]); matrix->SetElement(1,3,newImage->GetGeometry()->GetOrigin()[1]); matrix->SetElement(2,3,newImage->GetGeometry()->GetOrigin()[2]); for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item(r,c); if (!item) continue; matrix->SetElement(r,c,item->text().toDouble()); } } newImage->GetGeometry()->SetIndexToWorldTransformByVtkMatrixWithoutChangingSpacing(matrix); if ( isDiffusionImage ) { vnl_matrix_fixed< double, 3, 3 > mf; for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); if (!item) continue; mf[r][c] = item->text().toDouble(); } } newImage->GetPropertyList()->ReplaceProperty( PropHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); } mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); if (isOdf) { mitk::OdfImage::ItkOdfImageType::Pointer itk_img = mitk::OdfImage::ItkOdfImageType::New(); mitk::CastToItkImage(newImage, itk_img); mitk::Image::Pointer odfImage = dynamic_cast(mitk::OdfImage::New().GetPointer()); mitk::CastToMitkImage(itk_img, odfImage); odfImage->SetVolume(itk_img->GetBufferPointer()); imageNode->SetData( odfImage ); } else if (isDti) { mitk::TensorImage::ItkTensorImageType::Pointer itk_img = mitk::ImageToItkImage(newImage); mitk::Image::Pointer tensorImage = dynamic_cast(mitk::TensorImage::New().GetPointer()); mitk::CastToMitkImage(itk_img, tensorImage); tensorImage->SetVolume(itk_img->GetBufferPointer()); imageNode->SetData( tensorImage ); } else if (isPeak) { mitk::PeakImage::ItkPeakImageType::Pointer itk_img = mitk::ImageToItkImage(newImage); mitk::Image::Pointer peakImage = dynamic_cast(mitk::PeakImage::New().GetPointer()); mitk::CastToMitkImage(itk_img, peakImage); peakImage->SetVolume(itk_img->GetBufferPointer()); imageNode->SetData( peakImage ); } else imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_newheader").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoProjectSignal() { switch(m_Controls->m_ProjectionMethodBox->currentIndex()) { case 0: DoADCAverage(); break; case 1: DoAKCFit(); break; case 2: DoBiExpFit(); break; default: DoADCAverage(); } } void QmitkPreprocessingView::DoDwiNormalization() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) { return; } GradientDirectionContainerType::Pointer gradientContainer = static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); int b0Index = -1; for (unsigned int i=0; isize(); i++) { GradientDirectionType g = gradientContainer->GetElement(i); if (g.magnitude()<0.001) { b0Index = i; break; } } if (b0Index==-1) { return; } typedef itk::DwiNormilzationFilter FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); filter->SetGradientDirections( static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->SetNewMean(m_Controls->m_NewMean->value()); filter->SetNewStdev(m_Controls->m_NewStdev->value()); UcharImageType::Pointer itkImage = nullptr; if (m_Controls->m_NormalizationMaskBox->GetSelectedNode().IsNotNull()) { itkImage = UcharImageType::New(); if ( dynamic_cast(m_Controls->m_NormalizationMaskBox->GetSelectedNode()->GetData()) != nullptr ) { mitk::CastToItkImage( dynamic_cast(m_Controls->m_NormalizationMaskBox->GetSelectedNode()->GetData()), itkImage ); } filter->SetMaskImage(itkImage); } filter->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() ); PropHelper::CopyProperties(image, newImage, false); PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_normalized").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::DoLengthCorrection() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) { return; } typedef itk::DwiGradientLengthCorrectionFilter FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetRoundingValue( m_Controls->m_B_ValueMap_Rounder_SpinBox->value()); filter->SetReferenceBValue( static_cast (image->GetProperty(PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); filter->SetReferenceGradientDirectionContainer( static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->Update(); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( itkVectorImagePointer.GetPointer() ); newImage->SetImportVolume( itkVectorImagePointer->GetBufferPointer(), 0, 0, mitk::Image::CopyMemory); itkVectorImagePointer->GetPixelContainer()->ContainerManageMemoryOff(); PropHelper::CopyProperties(image, newImage, true); newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( filter->GetOutputGradientDirectionContainer() ) ); newImage->GetPropertyList()->ReplaceProperty( PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetNewBValue() ) ); PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_rounded").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::UpdateDwiBValueMapRounder(int i) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(node) ); if ( ! isDiffusionImage ) { return; } UpdateBValueTableWidget(i); } void QmitkPreprocessingView:: CallMultishellToSingleShellFilter( itk::DWIVoxelFunctor * functor, mitk::Image::Pointer image, QString imageName, mitk::DataNode* parent ) { typedef itk::RadialMultishellToSingleshellImageFilter FilterType; // filter input parameter const mitk::BValueMapProperty::BValueMap& originalShellMap = static_cast (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); ItkDwiType* vectorImage = itkVectorImagePointer.GetPointer(); const GradProp::GradientDirectionsContainerType::Pointer gradientContainer = static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); const unsigned int& bValue = static_cast (image->GetProperty(PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue(); mitk::DataNode::Pointer imageNode = 0; // filter call FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetOriginalBValueMap(originalShellMap); filter->SetOriginalBValue(bValue); filter->SetFunctor(functor); filter->Update(); // create new DWI image mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() ); PropHelper::CopyProperties(image, outImage, true); outImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( filter->GetTargetGradientDirections() ) ); outImage->GetPropertyList()->ReplaceProperty( PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( m_Controls->m_targetBValueSpinBox->value() ) ); PropHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); imageNode = mitk::DataNode::New(); imageNode->SetData( outImage ); imageNode->SetName(imageName.toStdString().c_str()); GetDataStorage()->Add(imageNode, parent); // if(m_Controls->m_OutputRMSErrorImage->isChecked()){ // // create new Error image // FilterType::ErrorImageType::Pointer errImage = filter->GetErrorImage(); // mitk::Image::Pointer mitkErrImage = mitk::Image::New(); // mitkErrImage->InitializeByItk(errImage); // mitkErrImage->SetVolume(errImage->GetBufferPointer()); // imageNode = mitk::DataNode::New(); // imageNode->SetData( mitkErrImage ); // imageNode->SetName((imageName+"_Error").toStdString().c_str()); // GetDataStorage()->Add(imageNode); // } } void QmitkPreprocessingView::DoBiExpFit() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) { return; } itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New(); QString name(node->GetName().c_str()); const mitk::BValueMapProperty::BValueMap& originalShellMap = static_cast (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); mitk::BValueMapProperty::BValueMap::const_iterator it = originalShellMap.begin(); ++it;/* skip b=0*/ unsigned int s = 0; /*shell index */ vnl_vector bValueList(originalShellMap.size()-1); while( it != originalShellMap.end() ) { bValueList.put(s++,(it++)->first); } const double targetBValue = m_Controls->m_targetBValueSpinBox->value(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); CallMultishellToSingleShellFilter(functor,image,name + "_BiExp", node); } void QmitkPreprocessingView::DoAKCFit() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) { return; } itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New(); QString name(node->GetName().c_str()); const mitk::BValueMapProperty::BValueMap& originalShellMap = static_cast (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); mitk::BValueMapProperty::BValueMap::const_iterator it = originalShellMap.begin(); ++it;/* skip b=0*/ unsigned int s = 0; /*shell index */ vnl_vector bValueList(originalShellMap.size()-1); while(it != originalShellMap.end()) bValueList.put(s++,(it++)->first); const double targetBValue = m_Controls->m_targetBValueSpinBox->value(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); CallMultishellToSingleShellFilter(functor,image,name + "_AKC", node); } void QmitkPreprocessingView::DoADCFit() { // later } void QmitkPreprocessingView::DoADCAverage() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) return; itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New(); QString name(node->GetName().c_str()); const mitk::BValueMapProperty::BValueMap &originalShellMap = static_cast(image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); mitk::BValueMapProperty::BValueMap::const_iterator it = originalShellMap.begin(); ++it;/* skip b=0*/ unsigned int s = 0; /*shell index */ vnl_vector bValueList(originalShellMap.size()-1); while(it != originalShellMap.end()) bValueList.put(s++,(it++)->first); const double targetBValue = m_Controls->m_targetBValueSpinBox->value(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); CallMultishellToSingleShellFilter(functor,image,name + "_ADC", node); } void QmitkPreprocessingView::CleanBValueTableWidget() { m_Controls->m_B_ValueMap_TableWidget->clear(); m_Controls->m_B_ValueMap_TableWidget->setRowCount(1); QStringList headerList; headerList << "b-Value" << "Number of gradients"; m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList); m_Controls->m_B_ValueMap_TableWidget->setItem(0,0,new QTableWidgetItem("-")); m_Controls->m_B_ValueMap_TableWidget->setItem(0,1,new QTableWidgetItem("-")); } void QmitkPreprocessingView::UpdateBValueTableWidget(int) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { CleanBValueTableWidget(); return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage(false); isDiffusionImage = PropHelper::IsDiffusionWeightedImage(image); if ( ! isDiffusionImage ) { CleanBValueTableWidget(); } else { typedef mitk::BValueMapProperty::BValueMap BValueMap; typedef mitk::BValueMapProperty::BValueMap::iterator BValueMapIterator; BValueMapIterator it; BValueMap roundedBValueMap = static_cast (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); m_Controls->m_B_ValueMap_TableWidget->clear(); m_Controls->m_B_ValueMap_TableWidget->setRowCount(roundedBValueMap.size() ); QStringList headerList; headerList << "b-Value" << "Number of gradients"; m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList); int i = 0 ; for(it = roundedBValueMap.begin() ;it != roundedBValueMap.end(); it++) { m_Controls->m_B_ValueMap_TableWidget->setItem(i,0,new QTableWidgetItem(QString::number(it->first))); QTableWidgetItem* item = m_Controls->m_B_ValueMap_TableWidget->item(i,0); item->setFlags(item->flags() & ~Qt::ItemIsEditable); m_Controls->m_B_ValueMap_TableWidget->setItem(i,1,new QTableWidgetItem(QString::number(it->second.size()))); i++; } } } void QmitkPreprocessingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer , const QList& nodes) { (void) nodes; this->OnImageSelectionChanged(); } void QmitkPreprocessingView::OnImageSelectionChanged() { for (int r=0; r<3; r++) for (int c=0; c<3; c++) { { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item( r, c ); delete item; item = new QTableWidgetItem(); m_Controls->m_MeasurementFrameTable->setItem( r, c, item ); } { QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item( r, c ); delete item; item = new QTableWidgetItem(); m_Controls->m_DirectionMatrixTable->setItem( r, c, item ); } } bool foundImageVolume = true; mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } bool foundDwiVolume( PropHelper::IsDiffusionWeightedImage( node ) ); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool multiComponentVolume = (image->GetPixelType().GetNumberOfComponents() > 1); bool threeDplusTVolume = (image->GetTimeSteps() > 1); m_Controls->m_ButtonAverageGradients->setEnabled(foundDwiVolume); m_Controls->m_ButtonExtractB0->setEnabled(foundDwiVolume); m_Controls->m_CheckExtractAll->setEnabled(foundDwiVolume); m_Controls->m_MeasurementFrameTable->setEnabled(foundDwiVolume); m_Controls->m_ReduceGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_ShowGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_MirrorGradientToHalfSphereButton->setEnabled(foundDwiVolume); m_Controls->m_MergeDwisButton->setEnabled(foundDwiVolume); m_Controls->m_B_ValueMap_Rounder_SpinBox->setEnabled(foundDwiVolume); m_Controls->m_ProjectSignalButton->setEnabled(foundDwiVolume); m_Controls->m_CreateLengthCorrectedDwi->setEnabled(foundDwiVolume); m_Controls->m_targetBValueSpinBox->setEnabled(foundDwiVolume); m_Controls->m_NormalizeImageValuesButton->setEnabled(foundDwiVolume); m_Controls->m_RemoveGradientButton->setEnabled(foundDwiVolume); m_Controls->m_ExtractGradientButton->setEnabled(foundDwiVolume); m_Controls->m_FlipGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_ClearRotationButton->setEnabled(foundDwiVolume); m_Controls->m_DirectionMatrixTable->setEnabled(foundImageVolume); m_Controls->m_ModifyHeader->setEnabled(foundImageVolume); m_Controls->m_AlignImageBox->setEnabled(foundImageVolume); // we do not support multi-component and 3D+t images for certain operations bool foundSingleImageVolume = foundDwiVolume || (foundImageVolume && !(multiComponentVolume || threeDplusTVolume)); m_Controls->m_FlipAxis->setEnabled(foundSingleImageVolume); m_Controls->m_CropImageButton->setEnabled(foundSingleImageVolume); m_Controls->m_ExtractBrainMask->setEnabled(foundSingleImageVolume); m_Controls->m_ResampleImageButton->setEnabled(foundSingleImageVolume); // reset sampling frame to 1 and update all ealted components m_Controls->m_B_ValueMap_Rounder_SpinBox->setValue(1); UpdateBValueTableWidget(m_Controls->m_B_ValueMap_Rounder_SpinBox->value()); DoUpdateInterpolationGui(m_Controls->m_ResampleTypeBox->currentIndex()); m_Controls->m_HeaderSpacingX->setValue(image->GetGeometry()->GetSpacing()[0]); m_Controls->m_HeaderSpacingY->setValue(image->GetGeometry()->GetSpacing()[1]); m_Controls->m_HeaderSpacingZ->setValue(image->GetGeometry()->GetSpacing()[2]); m_Controls->m_HeaderOriginX->setValue(image->GetGeometry()->GetOrigin()[0]); m_Controls->m_HeaderOriginY->setValue(image->GetGeometry()->GetOrigin()[1]); m_Controls->m_HeaderOriginZ->setValue(image->GetGeometry()->GetOrigin()[2]); m_Controls->m_XstartBox->setMaximum(image->GetGeometry()->GetExtent(0)-1); m_Controls->m_YstartBox->setMaximum(image->GetGeometry()->GetExtent(1)-1); m_Controls->m_ZstartBox->setMaximum(image->GetGeometry()->GetExtent(2)-1); m_Controls->m_XendBox->setMaximum(image->GetGeometry()->GetExtent(0)-1); m_Controls->m_YendBox->setMaximum(image->GetGeometry()->GetExtent(1)-1); m_Controls->m_ZendBox->setMaximum(image->GetGeometry()->GetExtent(2)-1); for (int r=0; r<3; r++) for (int c=0; c<3; c++) { // Direction matrix QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item( r, c ); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); double val = image->GetGeometry()->GetVtkMatrix()->GetElement(r,c)/image->GetGeometry()->GetSpacing()[c]; item->setText(QString::number(val)); m_Controls->m_DirectionMatrixTable->setItem( r, c, item ); } if (foundDwiVolume) { m_Controls->m_InputData->setTitle("Input Data"); vnl_matrix_fixed< double, 3, 3 > mf = static_cast (image->GetProperty(PropHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) ->GetMeasurementFrame(); for (int r=0; r<3; r++) for (int c=0; c<3; c++) { // Measurement frame QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item( r, c ); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); item->setText(QString::number(mf.get(r,c))); m_Controls->m_MeasurementFrameTable->setItem( r, c, item ); } //calculate target bValue for MultishellToSingleShellfilter const mitk::BValueMapProperty::BValueMap & bValMap = static_cast (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); mitk::BValueMapProperty::BValueMap::const_iterator it = bValMap.begin(); unsigned int targetBVal = 0; while(it != bValMap.end()) { targetBVal += (it++)->first; } targetBVal /= (float)bValMap.size()-1; m_Controls->m_targetBValueSpinBox->setValue(targetBVal); m_Controls->m_RemoveGradientBox->setMaximum(static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer()->Size()-1); m_Controls->m_ExtractGradientBox->setMaximum(static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer()->Size()-1); } } void QmitkPreprocessingView::Activated() { } void QmitkPreprocessingView::Deactivated() { OnImageSelectionChanged(); } void QmitkPreprocessingView::Visible() { OnImageSelectionChanged(); } void QmitkPreprocessingView::Hidden() { } void QmitkPreprocessingView::DoClearRotationOfGradients() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) return; mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image == nullptr) return; if(!PropHelper::IsDiffusionWeightedImage(image)) return; mitk::Image::Pointer newDwi = image->Clone(); PropHelper propertyHelper( newDwi ); propertyHelper.InitializeImage(); PropHelper::ClearMeasurementFrameAndRotationMatrixFromGradients(newDwi); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); QString name = node->GetName().c_str(); imageNode->SetName( (name+"_OriginalGradients").toStdString().c_str() ); GetDataStorage()->Add( imageNode, node ); } void QmitkPreprocessingView::DoFlipGradientDirections() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } mitk::Image::Pointer newDwi = image->Clone(); GradientDirectionContainerType::Pointer gradientContainer = static_cast ( newDwi->GetProperty(PropHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); for (unsigned int j=0; jSize(); j++) { if (m_Controls->m_FlipGradBoxX->isChecked()) { gradientContainer->at(j)[0] *= -1; } if (m_Controls->m_FlipGradBoxY->isChecked()) { gradientContainer->at(j)[1] *= -1; } if (m_Controls->m_FlipGradBoxZ->isChecked()) { gradientContainer->at(j)[2] *= -1; } } PropHelper::CopyProperties(image, newDwi, true); newDwi->GetPropertyList()->ReplaceProperty( PropHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( gradientContainer ) ); PropHelper propertyHelper( newDwi ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); QString name = node->GetName().c_str(); imageNode->SetName( (name+"_GradientFlip").toStdString().c_str() ); GetDataStorage()->Add( imageNode, node ); } void QmitkPreprocessingView::DoHalfSphereGradientDirections() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } mitk::Image::Pointer newDwi = image->Clone(); GradientDirectionContainerType::Pointer gradientContainer = static_cast ( newDwi->GetProperty(PropHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); for (unsigned int j=0; jSize(); j++) { if (gradientContainer->at(j)[0]<0) { gradientContainer->at(j) = -gradientContainer->at(j); } } PropHelper::CopyProperties(image, newDwi, true); newDwi->GetPropertyList()->ReplaceProperty( PropHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( gradientContainer ) ); PropHelper propertyHelper( newDwi ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); QString name = node->GetName().c_str(); imageNode->SetName( (name+"_halfsphere").toStdString().c_str() ); GetDataStorage()->Add( imageNode, node ); } void QmitkPreprocessingView::DoShowGradientDirections() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } int maxIndex = 0; unsigned int maxSize = image->GetDimension(0); if (maxSizeGetDimension(1)) { maxSize = image->GetDimension(1); maxIndex = 1; } if (maxSizeGetDimension(2)) { maxSize = image->GetDimension(2); maxIndex = 2; } mitk::Point3D origin = image->GetGeometry()->GetOrigin(); mitk::PointSet::Pointer originSet = mitk::PointSet::New(); typedef mitk::BValueMapProperty::BValueMap BValueMap; typedef mitk::BValueMapProperty::BValueMap::iterator BValueMapIterator; BValueMap bValMap = static_cast (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); GradientDirectionContainerType::Pointer gradientContainer = static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); mitk::BaseGeometry::Pointer geometry = image->GetGeometry(); int shellCount = 1; for(BValueMapIterator it = bValMap.begin(); it!=bValMap.end(); ++it) { mitk::PointSet::Pointer pointset = mitk::PointSet::New(); for (unsigned int j=0; jsecond.size(); j++) { mitk::Point3D ip; vnl_vector_fixed< double, 3 > v = gradientContainer->at(it->second[j]); if (v.magnitude()>mitk::eps) { ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*image->GetDimension(0)/2; ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*image->GetDimension(1)/2; ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*image->GetDimension(2)/2; pointset->InsertPoint(j, ip); } else if (originSet->IsEmpty()) { ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*image->GetDimension(0)/2; ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*image->GetDimension(1)/2; ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*image->GetDimension(2)/2; originSet->InsertPoint(j, ip); } } if ( it->first < mitk::eps ) { continue; } // add shell to datastorage mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pointset); QString name = node->GetName().c_str(); name += "_Shell_"; name += QString::number( it->first ); newNode->SetName( name.toStdString().c_str() ); newNode->SetProperty( "pointsize", mitk::FloatProperty::New((float)maxSize / 50) ); int b0 = shellCount % 2; int b1 = 0; int b2 = 0; if (shellCount>4) { b2 = 1; } if (shellCount%4 >= 2) { b1 = 1; } newNode->SetProperty("color", mitk::ColorProperty::New( b2, b1, b0 )); GetDataStorage()->Add( newNode, node ); shellCount++; } // add origin to datastorage mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(originSet); QString name = node->GetName().c_str(); name += "_Origin"; newNode->SetName(name.toStdString().c_str()); newNode->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50)); newNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); GetDataStorage()->Add(newNode, node); } void QmitkPreprocessingView::DoReduceGradientDirections() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter FilterType; typedef mitk::BValueMapProperty::BValueMap BValueMap; // GetShellSelection from GUI BValueMap shellSlectionMap; BValueMap originalShellMap = static_cast (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); std::vector newNumGradientDirections; int shellCounter = 0; QString name = node->GetName().c_str(); for (int i=0; im_B_ValueMap_TableWidget->rowCount(); i++) { double BValue = m_Controls->m_B_ValueMap_TableWidget->item(i,0)->text().toDouble(); shellSlectionMap[BValue] = originalShellMap[BValue]; unsigned int num = m_Controls->m_B_ValueMap_TableWidget->item(i,1)->text().toUInt(); newNumGradientDirections.push_back(num); name += "_"; name += QString::number(num); shellCounter++; } if (newNumGradientDirections.empty()) { return; } GradientDirectionContainerType::Pointer gradientContainer = static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); filter->SetOriginalGradientDirections(gradientContainer); filter->SetNumGradientDirections(newNumGradientDirections); filter->SetOriginalBValueMap(originalShellMap); filter->SetShellSelectionBValueMap(shellSlectionMap); filter->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() ); PropHelper::CopyProperties(image, newImage, true); newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( filter->GetGradientDirections() ) ); PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); imageNode->SetName(name.toStdString().c_str()); GetDataStorage()->Add(imageNode, node); // update the b-value widget to remove the modified number of gradients used for extraction this->CleanBValueTableWidget(); this->UpdateBValueTableWidget(0); } void QmitkPreprocessingView::MergeDwis() { typedef GradProp::GradientDirectionsContainerType GradientContainerType; mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } mitk::DataNode::Pointer node2 = m_Controls->m_MergeDwiBox->GetSelectedNode(); if (node2.IsNull()) { return; } mitk::Image::Pointer image2 = dynamic_cast(node2->GetData()); if ( image2 == nullptr ) { return; } typedef itk::VectorImage DwiImageType; typedef std::vector< DwiImageType::Pointer > DwiImageContainerType; typedef std::vector< GradientContainerType::Pointer > GradientListContainerType; DwiImageContainerType imageContainer; GradientListContainerType gradientListContainer; std::vector< double > bValueContainer; QString name = ""; { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); imageContainer.push_back( itkVectorImagePointer ); gradientListContainer.push_back( static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); bValueContainer.push_back( static_cast (image->GetProperty(PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); name += node->GetName().c_str(); } { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image2, itkVectorImagePointer); imageContainer.push_back( itkVectorImagePointer ); gradientListContainer.push_back( static_cast ( image2->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); bValueContainer.push_back( static_cast (image2->GetProperty(PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); name += "+"; name += node2->GetName().c_str(); } typedef itk::MergeDiffusionImagesFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetImageVolumes(imageContainer); filter->SetGradientLists(gradientListContainer); filter->SetBValues(bValueContainer); filter->Update(); vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() ); newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( filter->GetOutputGradients() ) ); newImage->GetPropertyList()->ReplaceProperty( PropHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); newImage->GetPropertyList()->ReplaceProperty( PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetB_Value() ) ); PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); imageNode->SetName(name.toStdString().c_str()); GetDataStorage()->Add(imageNode); } void QmitkPreprocessingView::ExtractB0() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } // call the extraction withou averaging if the check-box is checked if( this->m_Controls->m_CheckExtractAll->isChecked() ) { DoExtractBOWithoutAveraging(); return; } ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); // Extract image using found index typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); filter->SetDirections( static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer newNode=mitk::DataNode::New(); newNode->SetData( mitkImage ); newNode->SetProperty( "name", mitk::StringProperty::New(node->GetName() + "_B0")); GetDataStorage()->Add(newNode, node); } void QmitkPreprocessingView::DoExtractBOWithoutAveraging() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } // typedefs typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); // Extract image using found index FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); filter->SetDirections( static_cast ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer newNode=mitk::DataNode::New(); newNode->SetData( mitkImage ); newNode->SetProperty( "name", mitk::StringProperty::New(node->GetName() + "_B0_ALL")); GetDataStorage()->Add(newNode, node); /*A reinitialization is needed to access the time channels via the ImageNavigationController The Global-Geometry can not recognize the time channel without a re-init. (for a new selection in datamanger a automatically updated of the Global-Geometry should be done - if it contains the time channel)*/ mitk::RenderingManager::GetInstance()->InitializeViews( newNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } void QmitkPreprocessingView::AverageGradients() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) return; mitk::Image::Pointer newDwi = image->Clone(); PropHelper propertyHelper(newDwi); propertyHelper.AverageRedundantGradients(m_Controls->m_Blur->value()); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_averaged").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/CMakeLists.txt b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/CMakeLists.txt index aea4114c8e..ef0bf7b66f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/CMakeLists.txt @@ -1,9 +1,9 @@ # The project name must correspond to the directory name of your plug-in # and must not contain periods. project(org_mitk_gui_qt_diffusionimaging_registration) mitk_create_plugin( EXPORT_DIRECTIVE DIFFUSIONIMAGING_REGISTRATION_EXPORT EXPORTED_INCLUDE_SUFFIXES src - MODULE_DEPENDS MitkDiffusionCore + MODULE_DEPENDS MitkDiffusionCore MitkMatchPointRegistration MitkMatchPointRegistrationUI ) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox index 771863b4ba..9ee9c72c29 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox @@ -1,16 +1,14 @@ /** -\page org_mitk_views_diffusionregistrationview DWI Registration +\page org_mitk_views_diffusionregistrationview Head-Motion Correction -\section QmitkDiffusionImagingUserManualDWIRegistration DWI Registration - -The DWI registration view allows head-motion and eddy-current correction. First the b=0 images (if more than 1) are registered and averaged. The averaged image then serves as fixed image for the alignment of the remaining (weighted, b>0) images. +This view provides head-motion and eddy-current correction methods. First the b=0 images (if more than 1) are registered and averaged. The averaged image then serves as fixed image for the alignment of the remaining (weighted, b>0) images. \imageMacro{registration_basic.png,"Basic DWI Registration Interface",8.00} In the basic settings, a selected DW image in the Data Manager is marked as Input Data and the Start Head Motion Correction button is enabled. If more than one DW images are selected, they will be processed in a consecutive manner. For larger sets of dw images to be processed, the Advanced settings can be used. \imageMacro{registration_batch.png,"Batch Processing DWI Registration Interface",8.00} Here all valid .dwi data located in the given input folder will be processed through the head motion correction and the output will be stored in the current working directory or in a custom folder if specified in the user interface. The output image will have the _MC postfix attached to the input's name. */ 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 new file mode 100644 index 0000000000..d98878e5a2 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRigidRegistration.dox @@ -0,0 +1,5 @@ +/** +\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 fe5c97e6a5..b20be9d47b 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake @@ -1,41 +1,46 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp - + QmitkDiffusionRegistrationView.cpp + QmitkSimpleRigidRegistrationView.cpp + QmitkDwiRegistrationPerspective.cpp ) set(UI_FILES src/internal/QmitkDiffusionRegistrationViewControls.ui + src/internal/QmitkSimpleRigidRegistrationViewControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h src/internal/QmitkDiffusionRegistrationView.h + src/internal/QmitkSimpleRigidRegistrationView.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 074d5c67ef..d54299c5e7 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 Fiber Processing") +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) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml index cc8c81d085..3a030cdea7 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml @@ -1,24 +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/QmitkDiffusionRegistrationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.h index 9eaac301a2..5272cb951e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.h @@ -1,132 +1,130 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "ui_QmitkDiffusionRegistrationViewControls.h" #include #include #include #include typedef short DiffusionPixelType; /*! \brief View for diffusion image registration / head motion correction */ // Forward Qt class declarations -using namespace std; - class QmitkDiffusionRegistrationView; class QmitkRegistrationWorker : public QObject { Q_OBJECT public: QmitkRegistrationWorker(QmitkDiffusionRegistrationView* view); public slots: void run(); private: QmitkDiffusionRegistrationView* m_View; }; class QmitkDiffusionRegistrationView : 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 string VIEW_ID; + static const std::string VIEW_ID; QmitkDiffusionRegistrationView(); virtual ~QmitkDiffusionRegistrationView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; typedef mitk::DWIHeadMotionCorrectionFilter DWIHeadMotionCorrectionFilterType; protected slots: void StartRegistration(); void StopRegistration(); void AfterThread(); ///< update gui etc. after registrations has finished void BeforeThread(); ///< start timer etc. void TimerUpdate(); void AddInputFolderName(); void AddOutputFolderName(); void StartBatch(); void AdvancedSettings(); 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; mitk::Image::Pointer m_DiffusionImage; std::vector< mitk::DataNode::Pointer > m_SelectedDiffusionNodes; private: void UpdateRegistrationStatus(); ///< update textual status display of the Registration process void UpdateGUI(); ///< update button activity etc. dpending on current datamanager selection /** flags etc. */ bool m_IsBatch, m_IsAborted; QStringList m_BatchList; bool m_ThreadIsRunning; QTimer* m_RegistrationTimer; QTime m_RegistrationTime; unsigned long m_ElapsedTime; unsigned long m_Steps; int m_LastStep; unsigned int m_CurrentFile; unsigned int m_TotalFiles; // the Qt parent of our GUI (NOT of this object) QWidget* m_Parent; /** global Registerer and friends */ itk::SmartPointer m_GlobalRegisterer; QmitkRegistrationWorker m_RegistrationWorker; QThread m_RegistrationThread; friend class QmitkRegistrationWorker; }; 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 new file mode 100644 index 0000000000..7f1109ce4d --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.cpp @@ -0,0 +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.1f, "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"); +} diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.h similarity index 50% copy from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp copy to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.h index 488e20c269..c89a61672e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.h @@ -1,39 +1,36 @@ /*=================================================================== 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" +#ifndef QmitkDwiRegistrationPerspective_H_ +#define QmitkDwiRegistrationPerspective_H_ +#include -ctkPluginContext* mitk::PluginActivator::m_Context = nullptr; - -ctkPluginContext* mitk::PluginActivator::GetContext() +class QmitkDwiRegistrationPerspective : public QObject, public berry::IPerspectiveFactory { - return m_Context; -} + Q_OBJECT + Q_INTERFACES(berry::IPerspectiveFactory) -void mitk::PluginActivator::start(ctkPluginContext* context) -{ - BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionRegistrationView, context) - m_Context = context; -} +public: -void mitk::PluginActivator::stop(ctkPluginContext* context) -{ - Q_UNUSED(context) - m_Context = nullptr; -} + QmitkDwiRegistrationPerspective() {} + ~QmitkDwiRegistrationPerspective() {} + + void CreateInitialLayout(berry::IPageLayout::Pointer layout) override; +}; + +#endif /* QmitkFiberProcessingPerspective_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/QmitkSimpleRigidRegistrationView.cpp new file mode 100644 index 0000000000..2954bc3839 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.cpp @@ -0,0 +1,275 @@ +/*=================================================================== + +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" + +// MITK +#include +#include +#include +#include +#include +#include + +// Qt +#include + +#define _USE_MATH_DEFINES +#include + +const std::string QmitkSimpleRigidRegistrationView::VIEW_ID = "org.mitk.views.simplerigidregistrationview"; + +QmitkSimpleRigidRegistrationView::QmitkSimpleRigidRegistrationView() + : QmitkAbstractView() + , m_Controls( 0 ) +{ + +} + +// Destructor +QmitkSimpleRigidRegistrationView::~QmitkSimpleRigidRegistrationView() +{ + +} + +void QmitkSimpleRigidRegistrationView::StartRegistration() +{ + typedef itk::Image< float, 3 > ItkFloatImageType; + mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::New(); + + 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* ) +{ + mitk::Image::Pointer movingImage = dynamic_cast(m_MovingImageNode->GetData()); + mitk::Image::Pointer image = mitk::ImageMappingHelper::refineGeometry(movingImage, spResultRegistration, 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()); + } + else + resultNode->SetName("Registered"); + resultNode->SetOpacity(0.6); + resultNode->SetColor(0.0, 0.0, 1.0); + + GetDataStorage()->Add(resultNode); + + this->GetRenderWindowPart()->RequestUpdate(); + + m_Controls->m_RegistrationStartButton->setEnabled(true); + m_Controls->m_RegistrationStartButton->setText("Start Registration"); + + m_MovingImageNode = nullptr; +} + +void QmitkSimpleRigidRegistrationView::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->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); + + 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_RegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartRegistration()) ); + + FixedImageChanged(); + MovingImageChanged(); + } +} + +void QmitkSimpleRigidRegistrationView::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() +{ + 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& ) +{ + FixedImageChanged(); + MovingImageChanged(); +} + + +void QmitkSimpleRigidRegistrationView::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/QmitkSimpleRigidRegistrationView.h new file mode 100644 index 0000000000..23f278e3f4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.h @@ -0,0 +1,71 @@ +/*=================================================================== + +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 +#include +#include + +typedef short DiffusionPixelType; + +/*! +\brief View for diffusion image registration / head motion correction +*/ + +// Forward Qt class declarations + +class QmitkSimpleRigidRegistrationView : 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::VectorImage< short, 3 > ItkDwiType; + static const std::string VIEW_ID; + + QmitkSimpleRigidRegistrationView(); + virtual ~QmitkSimpleRigidRegistrationView(); + + virtual void CreateQtPartControl(QWidget *parent) override; + void SetFocus() override; + +protected slots: + + void MovingImageChanged(); + void FixedImageChanged(); + void StartRegistration(); + 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; + mitk::DataNode::Pointer m_MovingImageNode; + +private: + +}; 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 new file mode 100644 index 0000000000..e20c3f8dca --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationViewControls.ui @@ -0,0 +1,118 @@ + + + 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 DWI registration/Head Motion Correction + + + 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 488e20c269..581c7cf5d6 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,39 +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/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(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.remeshing/documentation/UserManual/QmitkRemeshing.dox b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing.dox index 6715cf2f7d..810053213a 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing.dox +++ b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing.dox @@ -1,71 +1,19 @@ /** \page org_mitk_gui_qt_remeshing The Remeshing Plugin \imageMacro{QmitkRemeshing_Icon.png,"Icon of the Remeshing Plugin.",2.00} \tableofcontents \section org_mitk_gui_qt_remeshingOverview Overview The Remeshing View allows you to remesh surfaces. If done right, remeshing can dramatically increase the quality of your surface mesh. -However, you might lose precision if you reduce your surface mesh too strong. -Even when you keep the detail of your mesh there might be a tiny distance between your original surface and the remeshed surface. +However, you might lose precision if you reduce the vertex density of your surface mesh too strong. +Even when you preserve the detail of your mesh, there might be a tiny distance between your original surface and the remeshed surface. Hence, be careful when using remeshed surfaces for evaluation purposes and always keep the original versions. \section org_mitk_gui_qt_remeshingUsage Usage -\imageMacro{QmitkRemeshing_RemeshingView.png,"Basic and advanced mode of the Remeshing View.",13.29} - -There are two basic and about a handful of advanced settings that influence remeshing. -Most of the time you should be able to gain satisfying results by adjusting only the two basic settings or even without changing any of the default parameters. -In the following the effects of all settings are described in more detail. Image examples are based on the following surface: - -\imageMacro{QmitkRemeshing_OriginalMesh.png,"The surface from which all examples below originate from.",10.08} - -\subsection org_mitk_gui_qt_remeshingBasicSettings Basic Settings - -The Vertices setting is the number of vertices the remeshed surface will consist of. -This is exact as long as Boundary fixing is turned off (default). -The maximum number of vertices is limited to the number of vertices of the input surface, however, you can increase this limit by adjusting the Max. # of vertices setting. - -The Gradation setting controls the distribution of vertices in the remeshed surface. -If set to zero the vertices are distributed equally all over the remeshed surface. -You can push more vertices towards surface regions with high curvature, i.e., more detailed regions, by increasing this setting. - -\imageMacro{QmitkRemeshing_Gradation10Percent.png,"Vertex count reduced to 10 percent\, gradation 0 vs. 1.",16.00} - -\subsection org_mitk_gui_qt_remeshingAdvancedSettings Advanced Settings - -You can arbirarily increase the maximum adjustable number of vertices by changing the Max. # of vertices setting. - -Edge splitting is disabled by default and might take a long time during remeshing when enabled. -This setting represents a number by which the average edge length of the input surface is multiplied to serve as a threshold which regulates edge splitting. -Long edges are split recursively until all edges satisfy the threshold. -Edge splitting is useful for surfaces that contain thin and long polygons. - -\imageMacro{QmitkRemeshing_cylinder.png,"A surface that contains extremely long polygons.",16.00} - -
- -\imageMacro{QmitkRemeshing_CylinderBad.png,"A remeshing attempt without edge splitting.",16.00} - -
- -\imageMacro{QmitkRemeshing_CylinderGood.png,"Increased max. # of vertices\, enabled edge splitting\, followed by a second remeshing run without edge splitting.",16.00} - -The Subsampling setting has direct impact on the quality of the remeshed surface. -The input surface is recursively subdivided until the total number of vertices exceeds its initial vertex count times this setting. - -\imageMacro{QmitkRemeshing_Subsampling20percent.png,"Vertex count reduced to 20 percent\, subsampling 10 vs. 500.",16.00} - -You usually leave the Optimization level set to its default value 1. -When disabled, the remeshed surface has usually a slightly smaller volume than the original surface. -The optimization process minimizes the distance between the two surfaces but values higher than 1 introduce degenerated triangles to the remeshed surface. - -If your surface is open, i.e., it has holes in it, boundaries tend to shrink irregularly during remeshing. -If the position and smoothness of your surface boundaries are important, you should activate the Boundary fixing setting. -This results in additional vertices that make up extra polygons at the remeshed boundaries to keep the original boundaries. - -\imageMacro{QmitkRemeshing_NoBoundaryFixing10Percent.png,"Vertex count reduced to 10 percent\, no boundary fixing.",10.08} +The Remeshing View provides details on its parameters in its user interface. When in doubt, start with the default parameters and iterate to your desired result by reducing the density parameter. */ diff --git a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_CylinderBad.png b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_CylinderBad.png deleted file mode 100644 index b50eab3701..0000000000 Binary files a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_CylinderBad.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_CylinderGood.png b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_CylinderGood.png deleted file mode 100644 index f9e6e9e1d0..0000000000 Binary files a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_CylinderGood.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_Gradation10Percent.png b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_Gradation10Percent.png deleted file mode 100644 index 878a421d85..0000000000 Binary files a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_Gradation10Percent.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_NoBoundaryFixing10Percent.png b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_NoBoundaryFixing10Percent.png deleted file mode 100644 index 937b7d2957..0000000000 Binary files a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_NoBoundaryFixing10Percent.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_OriginalMesh.png b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_OriginalMesh.png deleted file mode 100644 index 473a7bd4a5..0000000000 Binary files a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_OriginalMesh.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_RemeshingView.png b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_RemeshingView.png deleted file mode 100644 index 94fb6094ee..0000000000 Binary files a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_RemeshingView.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_Subsampling20percent.png b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_Subsampling20percent.png deleted file mode 100644 index 06f3878191..0000000000 Binary files a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_Subsampling20percent.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_cylinder.png b/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_cylinder.png deleted file mode 100644 index e24f55aa46..0000000000 Binary files a/Plugins/org.mitk.gui.qt.remeshing/documentation/UserManual/QmitkRemeshing_cylinder.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.cpp b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.cpp index aa43ed2f17..697ddbc62a 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.cpp +++ b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.cpp @@ -1,254 +1,156 @@ /*=================================================================== 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 "QmitkRemeshingView.h" -// MITK #include #include #include #include #include #include #include -// Qt -#include - -// VTK #include #include -// C++ Standard Library -#include -#include - QmitkRemeshingView::QmitkRemeshingView() { } QmitkRemeshingView::~QmitkRemeshingView() { } void QmitkRemeshingView::CreateQtPartControl(QWidget* parent) { m_Controls.setupUi(parent); m_Controls.surfaceComboBox->SetDataStorage(this->GetDataStorage()); m_Controls.surfaceComboBox->SetPredicate(mitk::NodePredicateAnd::New( mitk::TNodePredicateDataType::New(), mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")))); - QIntValidator* posIntValidator = new QIntValidator(0, std::numeric_limits::max(), parent); - m_Controls.maxNumVerticesLineEdit->setValidator(posIntValidator); - - this->EnableWidgets(m_Controls.surfaceComboBox->GetSelectedNode().IsNotNull()); - this->OnAdvancedSettingsButtonToggled(false); - connect(m_Controls.surfaceComboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode *)), this, SLOT(OnSelectedSurfaceChanged(const mitk::DataNode *))); - connect(m_Controls.numVerticesSlider, SIGNAL(valueChanged(int)), this, SLOT(OnNumberOfVerticesChanged(int))); - connect(m_Controls.numVerticesSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnNumberOfVerticesChanged(int))); - connect(m_Controls.gradationSlider, SIGNAL(valueChanged(double)), this, SLOT(OnGradationChanged(double))); - connect(m_Controls.gradationSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnGradationChanged(double))); - connect(m_Controls.advancedSettingsButton, SIGNAL(toggled(bool)), this, SLOT(OnAdvancedSettingsButtonToggled(bool))); - connect(m_Controls.maxNumVerticesLineEdit, SIGNAL(editingFinished()), this, SLOT(OnMaxNumVerticesLineEditEditingFinished())); - connect(m_Controls.edgeSplittingSlider, SIGNAL(valueChanged(double)), this, SLOT(OnEdgeSplittingChanged(double))); - connect(m_Controls.edgeSplittingSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnEdgeSplittingChanged(double))); - connect(m_Controls.subsamplingSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSubsamplingChanged(int))); - connect(m_Controls.subsamplingSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSubsamplingChanged(int))); - connect(m_Controls.optimizationLevelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnOptimizationLevelChanged(int))); - connect(m_Controls.optimizationLevelSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnOptimizationLevelChanged(int))); + connect(m_Controls.densitySlider, SIGNAL(valueChanged(int)), this, SLOT(OnDensityChanged(int))); + connect(m_Controls.densitySpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnDensityChanged(int))); connect(m_Controls.remeshPushButton, SIGNAL(clicked()), this, SLOT(OnRemeshButtonClicked())); this->OnSelectedSurfaceChanged(m_Controls.surfaceComboBox->GetSelectedNode()); } -void QmitkRemeshingView::EnableWidgets(bool enable) -{ - m_Controls.surfaceComboBox->setEnabled(enable); - m_Controls.numVerticesSlider->setEnabled(enable); - m_Controls.numVerticesSpinBox->setEnabled(enable); - m_Controls.gradationSlider->setEnabled(enable); - m_Controls.gradationSpinBox->setEnabled(enable); - m_Controls.maxNumVerticesLineEdit->setEnabled(enable); - m_Controls.edgeSplittingSlider->setEnabled(enable); - m_Controls.edgeSplittingSpinBox->setEnabled(enable); - m_Controls.subsamplingSlider->setEnabled(enable); - m_Controls.subsamplingSpinBox->setEnabled(enable); - m_Controls.optimizationLevelSlider->setEnabled(enable); - m_Controls.optimizationLevelSpinBox->setEnabled(enable); - m_Controls.forceManifoldCheckBox->setEnabled(enable); - m_Controls.boundaryFixingCheckBox->setEnabled(enable); - m_Controls.remeshPushButton->setEnabled(enable); -} - -void QmitkRemeshingView::OnAdvancedSettingsButtonToggled(bool toggled) -{ - m_Controls.maxNumVerticesLabel->setVisible(toggled); - m_Controls.maxNumVerticesLineEdit->setVisible(toggled); - m_Controls.edgeSplittingLabel->setVisible(toggled); - m_Controls.edgeSplittingSlider->setVisible(toggled); - m_Controls.edgeSplittingSpinBox->setVisible(toggled); - m_Controls.subsamplingLabel->setVisible(toggled); - m_Controls.subsamplingSlider->setVisible(toggled); - m_Controls.subsamplingSpinBox->setVisible(toggled); - m_Controls.optimizationLevelLabel->setVisible(toggled); - m_Controls.optimizationLevelSlider->setVisible(toggled); - m_Controls.optimizationLevelSpinBox->setVisible(toggled); - m_Controls.forceManifoldCheckBox->setVisible(toggled); - m_Controls.boundaryFixingCheckBox->setVisible(toggled); -} - -void QmitkRemeshingView::OnEdgeSplittingChanged(double edgeSplitting) -{ - if (edgeSplitting != m_Controls.edgeSplittingSlider->value()) - m_Controls.edgeSplittingSlider->setValue(edgeSplitting); - - if (edgeSplitting != m_Controls.edgeSplittingSpinBox->value()) - m_Controls.edgeSplittingSpinBox->setValue(edgeSplitting); -} - -void QmitkRemeshingView::OnGradationChanged(double gradation) -{ - if (gradation != m_Controls.gradationSlider->value()) - m_Controls.gradationSlider->setValue(gradation); - - if (gradation != m_Controls.gradationSpinBox->value()) - m_Controls.gradationSpinBox->setValue(gradation); -} - -void QmitkRemeshingView::OnMaxNumVerticesLineEditEditingFinished() +void QmitkRemeshingView::OnSelectedSurfaceChanged(const mitk::DataNode *node) { - int maximum = m_Controls.maxNumVerticesLineEdit->text().toInt(); - - if (m_Controls.numVerticesSpinBox->maximum() != maximum) + if (node != nullptr) { - m_Controls.numVerticesSlider->setMaximum(maximum); - m_Controls.numVerticesSpinBox->setMaximum(maximum); + m_MaxNumberOfVertices = static_cast(static_cast(node->GetData())->GetVtkPolyData()->GetNumberOfPoints()); + this->EnableWidgets(true); + } + else + { + m_MaxNumberOfVertices = 0; + this->EnableWidgets(false); } } -void QmitkRemeshingView::OnNumberOfVerticesChanged(int numVertices) -{ - if (numVertices != m_Controls.numVerticesSlider->value()) - m_Controls.numVerticesSlider->setValue(numVertices); - - if (numVertices != m_Controls.numVerticesSpinBox->value()) - m_Controls.numVerticesSpinBox->setValue(numVertices); -} - -void QmitkRemeshingView::OnOptimizationLevelChanged(int optimizationLevel) +void QmitkRemeshingView::OnDensityChanged(int density) { - if (optimizationLevel != m_Controls.optimizationLevelSlider->value()) - m_Controls.optimizationLevelSlider->setValue(optimizationLevel); + if (density != m_Controls.densitySlider->value()) + m_Controls.densitySlider->setValue(density); - if (optimizationLevel != m_Controls.optimizationLevelSpinBox->value()) - m_Controls.optimizationLevelSpinBox->setValue(optimizationLevel); + if (density != m_Controls.densitySpinBox->value()) + m_Controls.densitySpinBox->setValue(density); } void QmitkRemeshingView::OnRemeshButtonClicked() { mitk::DataNode::Pointer selectedNode = m_Controls.surfaceComboBox->GetSelectedNode(); mitk::Surface::ConstPointer surface = static_cast(selectedNode->GetData()); - int numVertices = m_Controls.numVerticesSpinBox->value(); - double gradation = m_Controls.gradationSpinBox->value(); - int subsampling = m_Controls.subsamplingSpinBox->value(); - double edgeSplitting = m_Controls.edgeSplittingSpinBox->value(); - int optimizationLevel = m_Controls.optimizationLevelSpinBox->value(); - bool forceManifold = m_Controls.forceManifoldCheckBox->isChecked(); - bool boundaryFixing = m_Controls.boundaryFixingCheckBox->isChecked(); - // mitk::Surface::Pointer remeshedSurface = mitk::ACVD::Remesh(surface, 0, numVertices, gradation, subsampling, edgeSplitting, optimizationLevel, forceManifold, boundaryFixing); + int density = m_Controls.densitySpinBox->value(); + int numVertices = std::max(100, static_cast(m_MaxNumberOfVertices * (density * 0.01))); + + double gradation = m_Controls.remeshingComboBox->currentText() == QStringLiteral("Adaptive") + ? 1.0 + : 0.0; + + const QString quality = m_Controls.qualityComboBox->currentText(); + int subsampling; + + if (QStringLiteral("High (slow)") == quality) + { + subsampling = 50; + } + else if (QStringLiteral("Maximum (very slow)") == quality) + { + subsampling = 500; + } + else // The default is "Medium (fast)". + { + subsampling = 10; + } + + bool boundaryFixing = m_Controls.preserveEdgesCheckBox->isChecked(); mitk::ACVD::RemeshFilter::Pointer remesher = mitk::ACVD::RemeshFilter::New(); remesher->SetInput(surface); remesher->SetTimeStep(0); remesher->SetNumVertices(numVertices); remesher->SetGradation(gradation); remesher->SetSubsampling(subsampling); - remesher->SetEdgeSplitting(edgeSplitting); - remesher->SetOptimizationLevel(optimizationLevel); - remesher->SetForceManifold(forceManifold); + remesher->SetEdgeSplitting(0.0); + remesher->SetOptimizationLevel(1.0); + remesher->SetForceManifold(false); remesher->SetBoundaryFixing(boundaryFixing); try { remesher->Update(); } catch(const mitk::Exception& exception) { MITK_ERROR << exception.GetDescription(); return; } mitk::Surface::Pointer remeshedSurface = remesher->GetOutput(); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - newNode->SetName(QString("%1 (%2, %3)").arg(selectedNode->GetName().c_str()).arg(remeshedSurface->GetVtkPolyData()->GetNumberOfPoints()).arg(gradation).toStdString()); + newNode->SetName(QString("%1 (%2%)").arg(selectedNode->GetName().c_str()).arg(density).toStdString()); newNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME)); newNode->SetData(remeshedSurface); this->GetDataStorage()->Add(newNode, selectedNode); } -void QmitkRemeshingView::OnSelectedSurfaceChanged(const mitk::DataNode *node) -{ - if (node != nullptr) - { - int numVertices = static_cast(static_cast(node->GetData())->GetVtkPolyData()->GetNumberOfPoints()); - int minimum = numVertices < 100 ? numVertices : 100; - int maximum = numVertices == minimum ? numVertices * 10 : numVertices; - int step = std::max(1, maximum / 10); - - this->SetNumberOfVertices(minimum, maximum, step, numVertices); - this->EnableWidgets(true); - } - else - { - this->EnableWidgets(false); - this->SetNumberOfVertices(0, 0, 0, 0); - } -} - -void QmitkRemeshingView::OnSubsamplingChanged(int subsampling) +void QmitkRemeshingView::EnableWidgets(bool enable) { - if (subsampling != m_Controls.subsamplingSlider->value()) - m_Controls.subsamplingSlider->setValue(subsampling); + m_Controls.surfaceComboBox->setEnabled(enable); + m_Controls.densitySlider->setEnabled(enable); + m_Controls.densitySpinBox->setEnabled(enable); + m_Controls.remeshingComboBox->setEnabled(enable); + m_Controls.qualityComboBox->setEnabled(enable); + m_Controls.preserveEdgesCheckBox->setEnabled(enable); + m_Controls.remeshPushButton->setEnabled(enable); - if (subsampling != m_Controls.subsamplingSpinBox->value()) - m_Controls.subsamplingSpinBox->setValue(subsampling); + m_Controls.explanationLabel->setVisible(enable); } void QmitkRemeshingView::SetFocus() { m_Controls.surfaceComboBox->setFocus(); } -void QmitkRemeshingView::SetNumberOfVertices(int minimum, int maximum, int step, int value) -{ - m_Controls.numVerticesSlider->setMinimum(minimum); - m_Controls.numVerticesSlider->setMaximum(maximum); - m_Controls.numVerticesSlider->setSingleStep(1); - m_Controls.numVerticesSlider->setPageStep(step); - - m_Controls.numVerticesSpinBox->setMinimum(minimum); - m_Controls.numVerticesSpinBox->setMaximum(maximum); - m_Controls.numVerticesSpinBox->setSingleStep(step); - m_Controls.numVerticesSpinBox->setValue(value); - - m_Controls.maxNumVerticesLineEdit->setText(QString("%1").arg(maximum)); -} diff --git a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.h b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.h index ab5fc54a47..59979f8458 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.h +++ b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.h @@ -1,54 +1,46 @@ /*=================================================================== 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 QmitkRemeshingView_h #define QmitkRemeshingView_h #include -#include #include class QmitkRemeshingView : public QmitkAbstractView { Q_OBJECT public: QmitkRemeshingView(); ~QmitkRemeshingView(); void CreateQtPartControl(QWidget* parent) override; void SetFocus() override; private slots: - void OnAdvancedSettingsButtonToggled(bool toggled); - void OnEdgeSplittingChanged(double edgeSplitting); - void OnGradationChanged(double gradation); - void OnMaxNumVerticesLineEditEditingFinished(); - void OnNumberOfVerticesChanged(int numVertices); - void OnOptimizationLevelChanged(int optimizationLevel); - void OnRemeshButtonClicked(); void OnSelectedSurfaceChanged(const mitk::DataNode *node); - void OnSubsamplingChanged(int subsampling); + void OnDensityChanged(int numVertices); + void OnRemeshButtonClicked(); private: void EnableWidgets(bool enable); - void SetNumberOfVertices(int minimum, int maximum, int step, int value); Ui::QmitkRemeshingViewControls m_Controls; - QThread m_Thread; + int m_MaxNumberOfVertices; }; #endif diff --git a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingViewControls.ui b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingViewControls.ui index ce63997fb1..0fbd4a62dc 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingViewControls.ui @@ -1,440 +1,247 @@ QmitkRemeshingViewControls true 0 0 - 260 - 423 + 253 + 573 Remeshing - - - - - - 0 - 0 - - - - Surface - - - - - - - true - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Vertices - - - - - - - - 0 - 0 - - - - 10000 - - - 100 - - + + + + 0 - - Qt::Horizontal - + + + Medium (fast) + + + + + High (slow) + + + + + Maximum (very slow) + + - + + + % + - 0 + 1 - 10000 + 100 - 100 + 1 - 0 + 100 - - + + - + 0 0 - Gradation - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - 1.000000000000000 - - - 10.000000000000000 - - - Qt::Horizontal - - - - - - - 1 - - - 10.000000000000000 + Preserve Edges - - 0.100000000000000 - - - 1.000000000000000 + + true - - - - - - - 0 - 0 - - - - - 0 - 32 - - - - Advanced settings - - - Qt::ToolButtonTextBesideIcon - - - Qt::Vertical - - - true - - - - - - + 0 0 - Max. # of vertices + Surface - - - 0 - - - 10 - - - - - - - - 0 - 0 - - - - Subsampling + + + true - - - - 0 0 - - 500 - - - 10 - - - 50 - - - 50 - - - Qt::Horizontal - - - - - - - 0 - - - 500 - - - 10 - - - 50 - - - + + - + 0 0 - Force manifold - - - false + Density - - + + 0 0 - - Boundary fixing - - - false - - - - - - - 10 - - + 1 - - - - - - Optimization Level - - - - - - 10 + 100 - 1 + 10 - 1 + 100 Qt::Horizontal - - + + 0 0 - Edge splitting + Remeshing - - - - 0.000000000000000 - - - 0.010000000000000 - - - 1.000000000000000 - - - 10.000000000000000 - - - Qt::Horizontal - + + + + + Adaptive + + + + + Regular + + - - - - 2 - - - 10.000000000000000 - - - 0.100000000000000 + + + + + 0 + 0 + - - 0.000000000000000 + + Quality true Remesh :/Remeshing/RemeshingIcon.png:/Remeshing/RemeshingIcon.png 24 24 + + + + <html><head/><body><p><span style=" font-weight:600;">Density:</span> The density of the resulting surface compared to the input surface. For example, a density of 50% will effectively halve the number of vertices. It's not uncommen to choose values as low as 10% for overly dense input surfaces. The minimum number of output vertices is at least 100, though.</p><p><span style=" font-weight:600;">Remeshing:</span> Adaptive remeshing results in higher density in curvy areas and less density in flat areas. This remeshing strategy can preserve fine shape details even when the overall density is heavily reduced. Regular remeshing evenly distributes the density regardless of the local shape of the surface.</p><p><span style=" font-weight:600;">Quality</span>: While medium quality is sufficient for the vast majority of use cases, you can increase this setting to further optimize the mesh quality in terms of uniformly shaped triangles. However, computation time and memory consumption increase dramatically compared to very small improvements.</p><p><span style=" font-weight:600;">Preserve Edges:</span> If the input surface contains holes or edges, they will be preserved very accurately by default at the cost of less uniform triangles at their direct neighborhood.</p></body></html> + + + true + + + Qt::Vertical 20 40 - - ctkDoubleSlider - QWidget -
ctkDoubleSlider.h
-
- - ctkExpandButton - QToolButton -
ctkExpandButton.h
-
QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
surfaceComboBox - numVerticesSpinBox - gradationSpinBox - advancedSettingsButton - maxNumVerticesLineEdit - edgeSplittingSpinBox - subsamplingSpinBox - optimizationLevelSpinBox - forceManifoldCheckBox - boundaryFixingCheckBox + densitySpinBox + preserveEdgesCheckBox remeshPushButton