diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/CMakeLists.txt b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/CMakeLists.txt
index fe11d8c713..20294539db 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/CMakeLists.txt
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/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_fiberprocessing)
mitk_create_plugin(
EXPORT_DIRECTIVE DIFFUSIONIMAGING_FIBERPROCESSING_EXPORT
- EXPORTED_INCLUDE_SUFFIXES src
- MODULE_DEPENDS MitkFiberTracking
+ EXPORTED_INCLUDE_SUFFIXES src
+ MODULE_DEPENDS MitkFiberTracking MitkChart
)
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/files.cmake
index f62f281e40..0993574f5c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/files.cmake
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/files.cmake
@@ -1,59 +1,63 @@
set(SRC_CPP_FILES
)
set(INTERNAL_CPP_FILES
mitkPluginActivator.cpp
QmitkFiberQuantificationView.cpp
QmitkFiberProcessingView.cpp
QmitkFiberClusteringView.cpp
QmitkFiberFitView.cpp
+ QmitkTractometryView.cpp
Perspectives/QmitkFiberProcessingPerspective.cpp
)
set(UI_FILES
src/internal/QmitkFiberQuantificationViewControls.ui
src/internal/QmitkFiberProcessingViewControls.ui
src/internal/QmitkFiberClusteringViewControls.ui
src/internal/QmitkFiberFitViewControls.ui
+ src/internal/QmitkTractometryViewControls.ui
)
set(MOC_H_FILES
src/internal/mitkPluginActivator.h
src/internal/QmitkFiberQuantificationView.h
src/internal/QmitkFiberProcessingView.h
src/internal/QmitkFiberClusteringView.h
src/internal/QmitkFiberFitView.h
+ src/internal/QmitkTractometryView.h
src/internal/Perspectives/QmitkFiberProcessingPerspective.h
)
set(CACHED_RESOURCE_FILES
plugin.xml
resources/FiberBundleOperations.png
resources/FiberQuantification.png
resources/FiberClustering.png
resources/FiberFit.png
+ resources/Tractometry.png
resources/circle.png
resources/polygon.png
)
set(QRC_FILES
resources/QmitkDiffusionImaging.qrc
)
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.fiberprocessing/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/plugin.xml
index 6332195af5..41500049dd 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/plugin.xml
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/plugin.xml
@@ -1,155 +1,163 @@
+
+
+
+
This perspective contains all views necessary to post process fibers.
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/resources/Tractometry.png b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/resources/Tractometry.png
new file mode 100644
index 0000000000..85c6c25cfc
Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/resources/Tractometry.png differ
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp
new file mode 100644
index 0000000000..05c6ec0191
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp
@@ -0,0 +1,277 @@
+/*===================================================================
+
+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 "QmitkTractometryView.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+const std::string QmitkTractometryView::VIEW_ID = "org.mitk.views.tractometry";
+using namespace mitk;
+
+QmitkTractometryView::QmitkTractometryView()
+ : QmitkAbstractView()
+ , m_Controls( nullptr )
+{
+
+}
+
+// Destructor
+QmitkTractometryView::~QmitkTractometryView()
+{
+
+}
+
+void QmitkTractometryView::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::QmitkTractometryViewControls;
+ m_Controls->setupUi( parent );
+
+ mitk::TNodePredicateDataType::Pointer imageP = mitk::TNodePredicateDataType::New();
+ mitk::NodePredicateDimension::Pointer dimP = mitk::NodePredicateDimension::New(3);
+
+ m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
+ m_Controls->m_ImageBox->SetPredicate(mitk::NodePredicateAnd::New(imageP, dimP));
+
+ this->m_Controls->m_ChartWidget->SetXAxisLabel("Tract position");
+ this->m_Controls->m_ChartWidget->SetYAxisLabel("Image Value");
+ }
+}
+
+void QmitkTractometryView::OnPageSuccessfullyLoaded()
+{
+// berry::IPreferencesService* prefService = berry::WorkbenchPlugin::GetDefault()->GetPreferencesService();
+// berry::IPreferences::Pointer m_StylePref = prefService->GetSystemPreferences()->Node(berry::QtPreferences::QT_STYLES_NODE);
+
+// QString styleName = m_StylePref->Get(berry::QtPreferences::QT_STYLE_NAME, "");
+
+// if (styleName == ":/org.blueberry.ui.qt/darkstyle.qss")
+// {
+// this->m_Controls->m_ChartWidget->SetTheme(QmitkChartWidget::ChartStyle::darkstyle);
+// }
+// else
+// {
+// this->m_Controls->m_ChartWidget->SetTheme(QmitkChartWidget::ChartStyle::lightstyle);
+// }
+}
+
+void QmitkTractometryView::SetFocus()
+{
+}
+
+bool QmitkTractometryView::Flip(vtkSmartPointer< vtkPolyData > polydata, int i)
+{
+ float d_direct = 0;
+ float d_flipped = 0;
+
+ vtkCell* cell1 = polydata->GetCell(0);
+ int numPoints1 = cell1->GetNumberOfPoints();
+ vtkPoints* points1 = cell1->GetPoints();
+
+ vtkCell* cell2 = polydata->GetCell(i);
+ vtkPoints* points2 = cell2->GetPoints();
+
+ for (int j=0; jGetPoint(j);
+ double* p2 = points2->GetPoint(j);
+ d_direct = (p1[0]-p2[0])*(p1[0]-p2[0]) + (p1[1]-p2[1])*(p1[1]-p2[1]) + (p1[2]-p2[2])*(p1[2]-p2[2]);
+
+ double* p3 = points2->GetPoint(numPoints1-j-1);
+ d_flipped = (p1[0]-p3[0])*(p1[0]-p3[0]) + (p1[1]-p3[1])*(p1[1]-p3[1]) + (p1[2]-p3[2])*(p1[2]-p3[2]);
+ }
+
+ if (d_direct>d_flipped)
+ return true;
+ return false;
+}
+
+template
+void QmitkTractometryView::ImageValuesAlongTract(const mitk::PixelType, mitk::Image::Pointer image, mitk::FiberBundle::Pointer fib, std::vector > &data)
+{
+ int num_points = 100;
+ mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0));
+ mitk::FiberBundle::Pointer working_fib = fib->GetDeepCopy();
+ working_fib->ResampleToNumPoints(num_points);
+ vtkSmartPointer< vtkPolyData > polydata = working_fib->GetFiberPolyData();
+
+ std::vector > all_values;
+ std::vector< double > mean_values;
+ for (int i=0; iGetNumFibers(); ++i)
+ {
+ vtkCell* cell = polydata->GetCell(i);
+ int numPoints = cell->GetNumberOfPoints();
+ vtkPoints* points = cell->GetPoints();
+
+ std::vector< double > fib_vals;
+
+ bool flip = false;
+ if (i>0)
+ flip = Flip(polydata, i);
+
+ for (int j=0; jGetPoint(numPoints - j - 1);
+ else
+ p = points->GetPoint(j);
+
+ Point3D px;
+ px[0] = p[0];
+ px[1] = p[1];
+ px[2] = p[2];
+ double pixelValue = readimage.GetPixelByWorldCoordinates(px);
+ fib_vals.push_back(pixelValue);
+ mean += pixelValue;
+ if (pixelValuemax)
+ max = pixelValue;
+
+ mean_values.at(j) += pixelValue;
+ }
+
+ all_values.push_back(fib_vals);
+ }
+
+ std::vector< double > std_values1;
+ std::vector< double > std_values2;
+ for (int i=0; iGetNumFibers();
+ double stdev = 0;
+
+ for (unsigned int j=0; jGetNumberOfPoints();
+}
+
+std::string QmitkTractometryView::RGBToHexString(double *rgb)
+{
+ std::ostringstream os;
+ for (int i = 0; i < 3; ++i)
+ {
+ os << std::setw(2) << std::setfill('0') << std::hex
+ << static_cast(rgb[i] * 255);
+ }
+ return os.str();
+}
+
+void QmitkTractometryView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes)
+{
+ if(m_Controls->m_ImageBox->GetSelectedNode().IsNull())
+ return;
+
+ mitk::Image::Pointer image = dynamic_cast(m_Controls->m_ImageBox->GetSelectedNode()->GetData());
+
+ vtkSmartPointer lookupTable = vtkSmartPointer::New();
+ lookupTable->SetTableRange(0.0, 0.8);
+ lookupTable->Build();
+
+ int num_tracts = 0;
+ for (auto node: nodes)
+ if ( dynamic_cast(node->GetData()) )
+ num_tracts++;
+
+ int c = 1;
+ this->m_Controls->m_ChartWidget->Clear();
+ for (auto node: nodes)
+ {
+ if ( dynamic_cast(node->GetData()) )
+ {
+ mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData());
+
+ std::vector< std::vector< double > > data;
+ mitkPixelTypeMultiplex3( ImageValuesAlongTract, image->GetPixelType(), image, fib, data );
+
+ m_Controls->m_ChartWidget->AddData1D(data.at(0), node->GetName() + " Mean", QmitkChartWidget::ChartType::line);
+ if (m_Controls->m_StDevBox->isChecked())
+ {
+ this->m_Controls->m_ChartWidget->AddData1D(data.at(1), node->GetName() + " +STDEV", QmitkChartWidget::ChartType::line);
+ this->m_Controls->m_ChartWidget->AddData1D(data.at(2), node->GetName() + " -STDEV", QmitkChartWidget::ChartType::line);
+ }
+
+ double color[3];
+ if (num_tracts>1)
+ {
+ float scalar_color = ( (float)c/num_tracts - 1.0/num_tracts )/(1.0-1.0/num_tracts);
+ lookupTable->GetColor(1.0 - scalar_color, color);
+ }
+ else
+ lookupTable->GetColor(0, color);
+
+ this->m_Controls->m_ChartWidget->SetColor(node->GetName() + " Mean", RGBToHexString(color));
+
+ if (m_Controls->m_StDevBox->isChecked())
+ {
+ color[0] *= 0.8;
+ color[1] *= 0.8;
+ color[2] *= 0.8;
+ this->m_Controls->m_ChartWidget->SetColor(node->GetName() + " +STDEV", RGBToHexString(color));
+ this->m_Controls->m_ChartWidget->SetColor(node->GetName() + " -STDEV", RGBToHexString(color));
+ }
+
+ this->m_Controls->m_ChartWidget->Show(true);
+ this->m_Controls->m_ChartWidget->SetShowDataPoints(false);
+ ++c;
+ }
+ }
+}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.h
new file mode 100644
index 0000000000..00f1c1a986
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.h
@@ -0,0 +1,69 @@
+/*===================================================================
+
+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 QmitkTractometryView_h
+#define QmitkTractometryView_h
+
+#include
+#include "ui_QmitkTractometryViewControls.h"
+#include
+#include
+#include
+#include
+
+/*!
+\brief Weight fibers by linearly fitting them to the image data.
+
+*/
+class QmitkTractometryView : public QmitkAbstractView
+{
+ // this is needed for all Qt objects that should have a Qt meta-object
+ // (everything that derives from QObject and wants to have signal/slots)
+ Q_OBJECT
+
+public:
+
+ static const std::string VIEW_ID;
+
+ QmitkTractometryView();
+ virtual ~QmitkTractometryView();
+
+ virtual void CreateQtPartControl(QWidget *parent) override;
+
+ template
+ void ImageValuesAlongTract(const mitk::PixelType, mitk::Image::Pointer image, mitk::FiberBundle::Pointer fib, std::vector< std::vector< double > >& data);
+
+ virtual void SetFocus() override;
+
+ void OnPageSuccessfullyLoaded();
+
+protected slots:
+
+protected:
+
+ /// \brief called by QmitkAbstractView when DataManager's selection has changed
+ virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override;
+
+ Ui::QmitkTractometryViewControls* m_Controls;
+
+ bool Flip(vtkSmartPointer< vtkPolyData > polydata, int i);
+ std::string RGBToHexString(double *rgb);
+};
+
+
+
+#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
+
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryViewControls.ui
new file mode 100644
index 0000000000..f97c61b283
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryViewControls.ui
@@ -0,0 +1,107 @@
+
+
+ QmitkTractometryViewControls
+
+
+
+ 0
+ 0
+ 484
+ 574
+
+
+
+ Form
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
-
+
+
+ Select a peak or raw diffusion-weighted image.
+
+
+
+ -
+
+
+ Input image:
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 100
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Show STDEV
+
+
+ true
+
+
+
+
+
+
+
+ QmitkChartWidget
+ QWidget
+
+
+
+ QmitkDataStorageComboBox
+ QComboBox
+ QmitkDataStorageComboBox.h
+
+
+
+
+
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.cpp
index 6132a2a747..7ae0cfc39d 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.cpp
@@ -1,48 +1,51 @@
/*===================================================================
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/Perspectives/QmitkFiberProcessingPerspective.h"
#include "src/internal/QmitkFiberProcessingView.h"
#include "src/internal/QmitkFiberQuantificationView.h"
#include "src/internal/QmitkFiberClusteringView.h"
#include "src/internal/QmitkFiberFitView.h"
+#include "src/internal/QmitkTractometryView.h"
+
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberProcessingPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberQuantificationView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberProcessingView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberClusteringView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberFitView, context)
+ BERRY_REGISTER_EXTENSION_CLASS(QmitkTractometryView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp
index a59a47b943..2257778a7e 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp
@@ -1,856 +1,859 @@
/*===================================================================
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 "QmitkStreamlineTrackingView.h"
#include "QmitkStdMultiWidget.h"
// Qt
#include
// MITK
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// VTK
#include
#include
#include
#include
#include
#include
#include
#include
#include
const std::string QmitkStreamlineTrackingView::VIEW_ID = "org.mitk.views.streamlinetracking";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;
QmitkStreamlineTrackingWorker::QmitkStreamlineTrackingWorker(QmitkStreamlineTrackingView* view)
: m_View(view)
{
}
void QmitkStreamlineTrackingWorker::run()
{
m_View->m_Tracker->Update();
m_View->m_TrackingThread.quit();
}
QmitkStreamlineTrackingView::QmitkStreamlineTrackingView()
: m_TrackingWorker(this)
, m_Controls(nullptr)
, m_FirstTensorProbRun(true)
, m_FirstInteractiveRun(true)
, m_TrackingHandler(nullptr)
, m_ThreadIsRunning(false)
, m_DeleteTrackingHandler(false)
{
m_TrackingWorker.moveToThread(&m_TrackingThread);
connect(&m_TrackingThread, SIGNAL(started()), this, SLOT(BeforeThread()));
connect(&m_TrackingThread, SIGNAL(started()), &m_TrackingWorker, SLOT(run()));
connect(&m_TrackingThread, SIGNAL(finished()), this, SLOT(AfterThread()));
m_TrackingTimer = new QTimer(this);
}
// Destructor
QmitkStreamlineTrackingView::~QmitkStreamlineTrackingView()
{
if (m_Tracker.IsNull())
return;
m_Tracker->SetStopTracking(true);
m_TrackingThread.wait();
}
void QmitkStreamlineTrackingView::CreateQtPartControl( QWidget *parent )
{
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkStreamlineTrackingViewControls;
m_Controls->setupUi( parent );
m_Controls->m_FaImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_SeedImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_MaskImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_TargetImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_StopImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_TissueImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_ForestBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New();
mitk::TNodePredicateDataType::Pointer isTractographyForest = mitk::TNodePredicateDataType::New();
mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New( isBinaryPredicate );
mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New( isImagePredicate, isNotBinaryPredicate );
mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3);
m_Controls->m_ForestBox->SetPredicate(isTractographyForest);
m_Controls->m_FaImageBox->SetPredicate( mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, dimensionPredicate) );
m_Controls->m_FaImageBox->SetZeroEntryText("--");
m_Controls->m_SeedImageBox->SetPredicate( mitk::NodePredicateAnd::New(isBinaryPredicate, dimensionPredicate) );
m_Controls->m_SeedImageBox->SetZeroEntryText("--");
m_Controls->m_MaskImageBox->SetPredicate( mitk::NodePredicateAnd::New(isBinaryPredicate, dimensionPredicate) );
m_Controls->m_MaskImageBox->SetZeroEntryText("--");
m_Controls->m_StopImageBox->SetPredicate( mitk::NodePredicateAnd::New(isBinaryPredicate, dimensionPredicate) );
m_Controls->m_StopImageBox->SetZeroEntryText("--");
m_Controls->m_TargetImageBox->SetPredicate( dimensionPredicate );
m_Controls->m_TargetImageBox->SetZeroEntryText("--");
m_Controls->m_TissueImageBox->SetPredicate( mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, dimensionPredicate) );
m_Controls->m_TissueImageBox->SetZeroEntryText("--");
connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(TimerUpdate()) );
connect( m_Controls->commandLinkButton_2, SIGNAL(clicked()), this, SLOT(StopTractography()) );
connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) );
connect( m_Controls->m_InteractiveBox, SIGNAL(stateChanged(int)), this, SLOT(ToggleInteractive()) );
connect( m_Controls->m_TissueImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()) );
connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()) );
connect( m_Controls->m_FaImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DeleteTrackingHandler()) );
connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DeleteTrackingHandler()) );
connect( m_Controls->m_OutputProbMap, SIGNAL(stateChanged(int)), this, SLOT(OutputStyleSwitched()) );
connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_StopImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_TargetImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_MaskImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_FaImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_ForestBox, SIGNAL(currentIndexChanged(int)), this, SLOT(ForestSwitched()) );
connect( m_Controls->m_ForestBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_SeedsPerVoxelBox, SIGNAL(valueChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_NumFibersBox, SIGNAL(valueChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_ScalarThresholdBox, SIGNAL(valueChanged(double)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_OdfCutoffBox, SIGNAL(valueChanged(double)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_StepSizeBox, SIGNAL(valueChanged(double)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_SamplingDistanceBox, SIGNAL(valueChanged(double)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_AngularThresholdBox, SIGNAL(valueChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_MinTractLengthBox, SIGNAL(valueChanged(double)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_fBox, SIGNAL(valueChanged(double)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_gBox, SIGNAL(valueChanged(double)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_NumSamplesBox, SIGNAL(valueChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_SeedRadiusBox, SIGNAL(valueChanged(double)), this, SLOT(InteractiveSeedChanged()) );
connect( m_Controls->m_NumSeedsBox, SIGNAL(valueChanged(int)), this, SLOT(InteractiveSeedChanged()) );
connect( m_Controls->m_OutputProbMap, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_SharpenOdfsBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_InterpolationBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
+ connect( m_Controls->m_MaskInterpolationBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_SeedGmBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_FlipXBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_FlipYBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_FlipZBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_FrontalSamplesBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_StopVotesBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
StartStopTrackingGui(false);
}
UpdateGui();
}
void QmitkStreamlineTrackingView::StopTractography()
{
if (m_Tracker.IsNull())
return;
m_Tracker->SetStopTracking(true);
}
void QmitkStreamlineTrackingView::TimerUpdate()
{
if (m_Tracker.IsNull())
return;
QString status_text(m_Tracker->GetStatusText().c_str());
m_Controls->m_StatusTextBox->setText(status_text);
}
void QmitkStreamlineTrackingView::BeforeThread()
{
m_TrackingTimer->start(1000);
}
void QmitkStreamlineTrackingView::AfterThread()
{
m_TrackingTimer->stop();
if (!m_Tracker->GetUseOutputProbabilityMap())
{
vtkSmartPointer fiberBundle = m_Tracker->GetFiberPolyData();
if (!m_Controls->m_InteractiveBox->isChecked() && fiberBundle->GetNumberOfLines() == 0)
{
QMessageBox warnBox;
warnBox.setWindowTitle("Warning");
warnBox.setText("No fiberbundle was generated!");
warnBox.setDetailedText("No fibers were generated using the chosen parameters. Typical reasons are:\n\n- Cutoff too high. Some images feature very low FA/GFA/peak size. Try to lower this parameter.\n- Angular threshold too strict. Try to increase this parameter.\n- A small step sizes also means many steps to go wrong. Especially in the case of probabilistic tractography. Try to adjust the angular threshold.");
warnBox.setIcon(QMessageBox::Warning);
warnBox.exec();
if (m_InteractivePointSetNode.IsNotNull())
m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1));
StartStopTrackingGui(false);
if (m_DeleteTrackingHandler)
DeleteTrackingHandler();
UpdateGui();
return;
}
mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(fiberBundle);
fib->SetReferenceGeometry(dynamic_cast(m_ParentNode->GetData())->GetGeometry());
if (m_Controls->m_ResampleFibersBox->isChecked() && fiberBundle->GetNumberOfLines()>0)
fib->Compress(m_Controls->m_FiberErrorBox->value());
fib->ColorFibersByOrientation();
m_Tracker->SetDicomProperties(fib);
if (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);
}
m_InteractiveNode->SetData(fib);
if (auto renderWindowPart = this->GetRenderWindowPart())
renderWindowPart->RequestUpdate();
}
else
{
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(fib);
QString name("FiberBundle_");
name += m_ParentNode->GetName().c_str();
name += "_Streamline";
node->SetName(name.toStdString());
GetDataStorage()->Add(node, m_ParentNode);
}
}
else
{
TrackerType::ItkDoubleImgType::Pointer outImg = m_Tracker->GetOutputProbabilityMap();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
if (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);
}
m_InteractiveNode->SetData(img);
mitk::LookupTable::Pointer lut = mitk::LookupTable::New();
lut->SetType(mitk::LookupTable::JET_TRANSPARENT);
mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New();
lut_prop->SetLookupTable(lut);
m_InteractiveNode->SetProperty("LookupTable", lut_prop);
m_InteractiveNode->SetProperty("opacity", mitk::FloatProperty::New(0.5));
if (auto renderWindowPart = this->GetRenderWindowPart())
renderWindowPart->RequestUpdate();
}
else
{
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
QString name("ProbabilityMap_");
name += m_ParentNode->GetName().c_str();
node->SetName(name.toStdString());
mitk::LookupTable::Pointer lut = mitk::LookupTable::New();
lut->SetType(mitk::LookupTable::JET_TRANSPARENT);
mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New();
lut_prop->SetLookupTable(lut);
node->SetProperty("LookupTable", lut_prop);
node->SetProperty("opacity", mitk::FloatProperty::New(0.5));
GetDataStorage()->Add(node, m_ParentNode);
}
}
if (m_InteractivePointSetNode.IsNotNull())
m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1));
StartStopTrackingGui(false);
if (m_DeleteTrackingHandler)
DeleteTrackingHandler();
UpdateGui();
}
void QmitkStreamlineTrackingView::InteractiveSeedChanged(bool posChanged)
{
if (m_ThreadIsRunning)
return;
if (!posChanged && (!m_Controls->m_InteractiveBox->isChecked() || !m_Controls->m_ParamUpdateBox->isChecked()))
return;
std::srand(std::time(0));
m_SeedPoints.clear();
itk::Point world_pos = this->GetRenderWindowPart()->GetSelectedPosition();
m_SeedPoints.push_back(world_pos);
float radius = m_Controls->m_SeedRadiusBox->value();
int num = m_Controls->m_NumSeedsBox->value();
mitk::PointSet::Pointer pointset = mitk::PointSet::New();
pointset->InsertPoint(0, world_pos);
m_InteractivePointSetNode->SetProperty("pointsize", mitk::FloatProperty::New(radius*2));
m_InteractivePointSetNode->SetProperty("point 2D size", mitk::FloatProperty::New(radius*2));
m_InteractivePointSetNode->SetData(pointset);
for (int i=1; i p;
p[0] = rand()%1000-500;
p[1] = rand()%1000-500;
p[2] = rand()%1000-500;
p.Normalize();
p *= radius;
m_SeedPoints.push_back(world_pos+p);
}
m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,0,0));
DoFiberTracking();
}
void QmitkStreamlineTrackingView::OnParameterChanged()
{
if (m_Controls->m_InteractiveBox->isChecked() && m_Controls->m_ParamUpdateBox->isChecked())
DoFiberTracking();
}
void QmitkStreamlineTrackingView::ToggleInteractive()
{
UpdateGui();
m_Controls->m_SeedsPerVoxelBox->setEnabled(!m_Controls->m_InteractiveBox->isChecked());
m_Controls->m_SeedsPerVoxelLabel->setEnabled(!m_Controls->m_InteractiveBox->isChecked());
m_Controls->m_SeedGmBox->setEnabled(!m_Controls->m_InteractiveBox->isChecked());
m_Controls->m_SeedImageBox->setEnabled(!m_Controls->m_InteractiveBox->isChecked());
m_Controls->label_6->setEnabled(!m_Controls->m_InteractiveBox->isChecked());
m_Controls->m_TissueImageBox->setEnabled(!m_Controls->m_InteractiveBox->isChecked());
m_Controls->label_10->setEnabled(!m_Controls->m_InteractiveBox->isChecked());
if ( m_Controls->m_InteractiveBox->isChecked() )
{
if (m_FirstInteractiveRun)
{
QMessageBox::information(nullptr, "Information", "Place and move a spherical seed region anywhere in the image by left-clicking and dragging. If the seed region is colored red, tracking is in progress. If the seed region is colored white, tracking is finished.\nPlacing the seed region for the first time in a newly selected dataset might cause a short delay, since the tracker needs to be initialized.");
m_FirstInteractiveRun = false;
}
QApplication::setOverrideCursor(Qt::PointingHandCursor);
QApplication::processEvents();
m_InteractivePointSetNode = mitk::DataNode::New();
m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1));
m_InteractivePointSetNode->SetName("InteractiveSeedRegion");
mitk::PointSetShapeProperty::Pointer shape_prop = mitk::PointSetShapeProperty::New();
shape_prop->SetValue(mitk::PointSetShapeProperty::PointSetShape::CIRCLE);
m_InteractivePointSetNode->SetProperty("Pointset.2D.shape", shape_prop);
GetDataStorage()->Add(m_InteractivePointSetNode);
m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
}
else
{
QApplication::restoreOverrideCursor();
QApplication::processEvents();
m_InteractiveNode = nullptr;
m_InteractivePointSetNode = nullptr;
m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
disconnect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
}
}
void QmitkStreamlineTrackingView::OnSliceChanged()
{
InteractiveSeedChanged(true);
}
void QmitkStreamlineTrackingView::SetFocus()
{
}
void QmitkStreamlineTrackingView::DeleteTrackingHandler()
{
if (!m_ThreadIsRunning && m_TrackingHandler != nullptr)
{
delete m_TrackingHandler;
m_TrackingHandler = nullptr;
m_DeleteTrackingHandler = false;
}
else if (m_ThreadIsRunning)
{
m_DeleteTrackingHandler = true;
}
}
void QmitkStreamlineTrackingView::ForestSwitched()
{
DeleteTrackingHandler();
}
void QmitkStreamlineTrackingView::OutputStyleSwitched()
{
if (m_InteractiveNode.IsNotNull())
GetDataStorage()->Remove(m_InteractiveNode);
m_InteractiveNode = nullptr;
}
void QmitkStreamlineTrackingView::OnSelectionChanged( berry::IWorkbenchPart::Pointer , const QList& nodes )
{
std::vector< mitk::DataNode::Pointer > last_nodes = m_InputImageNodes;
m_InputImageNodes.clear();
m_InputImages.clear();
m_AdditionalInputImages.clear();
bool retrack = false;
for( auto node : nodes )
{
if( node.IsNotNull() && dynamic_cast(node->GetData()) )
{
if( dynamic_cast(node->GetData()) )
{
m_InputImageNodes.push_back(node);
m_InputImages.push_back(dynamic_cast(node->GetData()));
retrack = true;
}
else if ( dynamic_cast(node->GetData()) )
{
m_InputImageNodes.push_back(node);
m_InputImages.push_back(dynamic_cast(node->GetData()));
retrack = true;
}
else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())) )
{
m_InputImageNodes.push_back(node);
m_InputImages.push_back(dynamic_cast(node->GetData()));
retrack = true;
}
else
{
mitk::Image* img = dynamic_cast(node->GetData());
if (img!=nullptr)
{
int dim = img->GetDimension();
unsigned int* dimensions = img->GetDimensions();
if (dim==4 && dimensions[3]%3==0)
{
m_InputImageNodes.push_back(node);
m_InputImages.push_back(dynamic_cast(node->GetData()));
retrack = true;
}
else if (dim==3)
{
m_AdditionalInputImages.push_back(dynamic_cast(node->GetData()));
}
}
}
}
}
// sometimes the OnSelectionChanged event is sent twice and actually no selection has changed for the first event. We need to catch that.
if (last_nodes.size() == m_InputImageNodes.size())
{
bool same_nodes = true;
for (unsigned int i=0; im_TensorImageLabel->setText("mandatory");
m_Controls->m_fBox->setEnabled(false);
m_Controls->m_fLabel->setEnabled(false);
m_Controls->m_gBox->setEnabled(false);
m_Controls->m_gLabel->setEnabled(false);
m_Controls->m_FaImageBox->setEnabled(false);
m_Controls->mFaImageLabel->setEnabled(false);
m_Controls->m_OdfCutoffBox->setEnabled(false);
m_Controls->m_OdfCutoffLabel->setEnabled(false);
m_Controls->m_SharpenOdfsBox->setEnabled(false);
m_Controls->m_ForestBox->setEnabled(false);
m_Controls->m_ForestLabel->setEnabled(false);
m_Controls->commandLinkButton->setEnabled(false);
if (m_Controls->m_TissueImageBox->GetSelectedNode().IsNotNull())
m_Controls->m_SeedGmBox->setEnabled(true);
else
m_Controls->m_SeedGmBox->setEnabled(false);
if(!m_InputImageNodes.empty())
{
if (m_InputImageNodes.size()>1)
m_Controls->m_TensorImageLabel->setText( ( std::to_string(m_InputImageNodes.size()) + " images selected").c_str() );
else
m_Controls->m_TensorImageLabel->setText(m_InputImageNodes.at(0)->GetName().c_str());
m_Controls->m_InputData->setTitle("Input Data");
m_Controls->commandLinkButton->setEnabled(!m_Controls->m_InteractiveBox->isChecked() && !m_ThreadIsRunning);
m_Controls->m_ScalarThresholdBox->setEnabled(true);
m_Controls->m_FaThresholdLabel->setEnabled(true);
if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) )
{
m_Controls->m_fBox->setEnabled(true);
m_Controls->m_fLabel->setEnabled(true);
m_Controls->m_gBox->setEnabled(true);
m_Controls->m_gLabel->setEnabled(true);
m_Controls->mFaImageLabel->setEnabled(true);
m_Controls->m_FaImageBox->setEnabled(true);
}
else if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) )
{
m_Controls->mFaImageLabel->setEnabled(true);
m_Controls->m_FaImageBox->setEnabled(true);
m_Controls->m_OdfCutoffBox->setEnabled(true);
m_Controls->m_OdfCutoffLabel->setEnabled(true);
m_Controls->m_SharpenOdfsBox->setEnabled(true);
}
else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_InputImageNodes.at(0)->GetData())) )
{
m_Controls->m_ForestBox->setEnabled(true);
m_Controls->m_ForestLabel->setEnabled(true);
m_Controls->m_ScalarThresholdBox->setEnabled(false);
m_Controls->m_FaThresholdLabel->setEnabled(false);
}
}
else
m_Controls->m_InputData->setTitle("Please Select Input Data");
}
void QmitkStreamlineTrackingView::StartStopTrackingGui(bool start)
{
m_ThreadIsRunning = start;
if (!m_Controls->m_InteractiveBox->isChecked())
{
m_Controls->commandLinkButton_2->setVisible(start);
m_Controls->commandLinkButton->setVisible(!start);
m_Controls->m_InteractiveBox->setEnabled(!start);
m_Controls->m_StatusTextBox->setVisible(start);
}
}
void QmitkStreamlineTrackingView::DoFiberTracking()
{
if (m_ThreadIsRunning)
return;
if (m_InputImages.empty())
return;
if (m_Controls->m_InteractiveBox->isChecked() && m_SeedPoints.empty())
return;
StartStopTrackingGui(true);
m_Tracker = TrackerType::New();
if( dynamic_cast(m_InputImageNodes.at(0)->GetData()) )
{
typedef mitk::ImageToItk CasterType;
if (m_Controls->m_ModeBox->currentIndex()==1)
{
if (m_InputImages.size()>1)
{
QMessageBox::information(nullptr, "Information", "Probabilistic tensor tractography is only implemented for single-tensor mode!");
StartStopTrackingGui(false);
return;
}
if (m_FirstTensorProbRun)
{
QMessageBox::information(nullptr, "Information", "Internally calculating ODF from tensor image and performing probabilistic ODF tractography. ODFs are sharpened (min-max normalized and raised to the power of 4). TEND parameters are ignored.");
m_FirstTensorProbRun = false;
}
if (m_TrackingHandler==nullptr)
{
typedef mitk::ImageToItk< mitk::TrackingHandlerOdf::ItkOdfImageType > CasterType;
m_TrackingHandler = new mitk::TrackingHandlerOdf();
mitk::TensorImage::ItkTensorImageType::Pointer itkImg = mitk::TensorImage::ItkTensorImageType::New();
mitk::CastToItkImage(m_InputImages.at(0), itkImg);
typedef itk::TensorImageToOdfImageFilter< float, float > FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkImg );
filter->Update();
dynamic_cast(m_TrackingHandler)->SetOdfImage(filter->GetOutput());
if (m_Controls->m_FaImageBox->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData()), itkImg);
dynamic_cast(m_TrackingHandler)->SetGfaImage(itkImg);
}
}
dynamic_cast(m_TrackingHandler)->SetGfaThreshold(m_Controls->m_ScalarThresholdBox->value());
dynamic_cast(m_TrackingHandler)->SetOdfThreshold(0);
dynamic_cast(m_TrackingHandler)->SetSharpenOdfs(true);
dynamic_cast(m_TrackingHandler)->SetIsOdfFromTensor(true);
}
else
{
if (m_TrackingHandler==nullptr)
{
m_TrackingHandler = new mitk::TrackingHandlerTensor();
for (int i=0; i<(int)m_InputImages.size(); i++)
{
typedef mitk::ImageToItk< mitk::TrackingHandlerTensor::ItkTensorImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(m_InputImages.at(i));
caster->Update();
mitk::TrackingHandlerTensor::ItkTensorImageType::ConstPointer itkImg = caster->GetOutput();
dynamic_cast(m_TrackingHandler)->AddTensorImage(itkImg);
}
if (m_Controls->m_FaImageBox->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData()), itkImg);
dynamic_cast(m_TrackingHandler)->SetFaImage(itkImg);
}
}
dynamic_cast(m_TrackingHandler)->SetFaThreshold(m_Controls->m_ScalarThresholdBox->value());
dynamic_cast(m_TrackingHandler)->SetF((float)m_Controls->m_fBox->value());
dynamic_cast(m_TrackingHandler)->SetG((float)m_Controls->m_gBox->value());
}
}
else if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) )
{
if (m_TrackingHandler==nullptr)
{
typedef mitk::ImageToItk< mitk::TrackingHandlerOdf::ItkOdfImageType > CasterType;
m_TrackingHandler = new mitk::TrackingHandlerOdf();
mitk::TrackingHandlerOdf::ItkOdfImageType::Pointer itkImg = mitk::TrackingHandlerOdf::ItkOdfImageType::New();
mitk::CastToItkImage(m_InputImages.at(0), itkImg);
dynamic_cast(m_TrackingHandler)->SetOdfImage(itkImg);
if (m_Controls->m_FaImageBox->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData()), itkImg);
dynamic_cast(m_TrackingHandler)->SetGfaImage(itkImg);
}
}
dynamic_cast(m_TrackingHandler)->SetGfaThreshold(m_Controls->m_ScalarThresholdBox->value());
dynamic_cast(m_TrackingHandler)->SetOdfThreshold(m_Controls->m_OdfCutoffBox->value());
dynamic_cast(m_TrackingHandler)->SetSharpenOdfs(m_Controls->m_SharpenOdfsBox->isChecked());
}
else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_InputImageNodes.at(0)->GetData())) )
{
if ( m_Controls->m_ForestBox->GetSelectedNode().IsNull() )
{
QMessageBox::information(nullptr, "Information", "Not random forest for machine learning based tractography selected.");
StartStopTrackingGui(false);
return;
}
if (m_TrackingHandler==nullptr)
{
mitk::TractographyForest::Pointer forest = dynamic_cast(m_Controls->m_ForestBox->GetSelectedNode()->GetData());
mitk::Image::Pointer dwi = dynamic_cast(m_InputImageNodes.at(0)->GetData());
std::vector< std::vector< ItkFloatImageType::Pointer > > additionalFeatureImages;
additionalFeatureImages.push_back(std::vector< ItkFloatImageType::Pointer >());
for (auto img : m_AdditionalInputImages)
{
ItkFloatImageType::Pointer itkimg = ItkFloatImageType::New();
mitk::CastToItkImage(img, itkimg);
additionalFeatureImages.at(0).push_back(itkimg);
}
bool forest_valid = false;
if (forest->GetNumFeatures()>=100)
{
int num_previous_directions = (forest->GetNumFeatures() - (100 + additionalFeatureImages.at(0).size()))/3;
m_TrackingHandler = new mitk::TrackingHandlerRandomForest<6, 100>();
dynamic_cast*>(m_TrackingHandler)->AddDwi(dwi);
dynamic_cast*>(m_TrackingHandler)->SetAdditionalFeatureImages(additionalFeatureImages);
dynamic_cast*>(m_TrackingHandler)->SetForest(forest);
dynamic_cast*>(m_TrackingHandler)->SetNumPreviousDirections(num_previous_directions);
forest_valid = dynamic_cast*>(m_TrackingHandler)->IsForestValid();
}
else
{
int num_previous_directions = (forest->GetNumFeatures() - (28 + additionalFeatureImages.at(0).size()))/3;
m_TrackingHandler = new mitk::TrackingHandlerRandomForest<6, 28>();
dynamic_cast*>(m_TrackingHandler)->AddDwi(dwi);
dynamic_cast*>(m_TrackingHandler)->SetAdditionalFeatureImages(additionalFeatureImages);
dynamic_cast*>(m_TrackingHandler)->SetForest(forest);
dynamic_cast*>(m_TrackingHandler)->SetNumPreviousDirections(num_previous_directions);
forest_valid = dynamic_cast*>(m_TrackingHandler)->IsForestValid();
}
if (!forest_valid)
{
QMessageBox::information(nullptr, "Information", "Random forest is invalid. The forest signatue does not match the parameters of TrackingHandlerRandomForest.");
StartStopTrackingGui(false);
return;
}
}
}
else
{
if (m_Controls->m_ModeBox->currentIndex()==1)
{
QMessageBox::information(nullptr, "Information", "Probabilstic tractography is not implemented for peak images.");
StartStopTrackingGui(false);
return;
}
try {
if (m_TrackingHandler==nullptr)
{
typedef mitk::ImageToItk< mitk::TrackingHandlerPeaks::PeakImgType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(m_InputImages.at(0));
caster->Update();
mitk::TrackingHandlerPeaks::PeakImgType::Pointer itkImg = caster->GetOutput();
m_TrackingHandler = new mitk::TrackingHandlerPeaks();
dynamic_cast(m_TrackingHandler)->SetPeakImage(itkImg);
}
dynamic_cast(m_TrackingHandler)->SetPeakThreshold(m_Controls->m_ScalarThresholdBox->value());
}
catch(...)
{
QMessageBox::information(nullptr, "Error", "Peak tracker could not be initialized. Is your input image in the correct format (4D float image, peaks in the 4th dimension)?");
StartStopTrackingGui(false);
return;
}
}
m_TrackingHandler->SetFlipX(m_Controls->m_FlipXBox->isChecked());
m_TrackingHandler->SetFlipY(m_Controls->m_FlipYBox->isChecked());
m_TrackingHandler->SetFlipZ(m_Controls->m_FlipZBox->isChecked());
m_TrackingHandler->SetInterpolate(m_Controls->m_InterpolationBox->isChecked());
switch (m_Controls->m_ModeBox->currentIndex())
{
case 0:
m_TrackingHandler->SetMode(mitk::TrackingDataHandler::MODE::DETERMINISTIC);
break;
case 1:
m_TrackingHandler->SetMode(mitk::TrackingDataHandler::MODE::PROBABILISTIC);
break;
default:
m_TrackingHandler->SetMode(mitk::TrackingDataHandler::MODE::DETERMINISTIC);
}
if (m_Controls->m_InteractiveBox->isChecked())
{
m_Tracker->SetSeedPoints(m_SeedPoints);
}
else if (m_Controls->m_SeedImageBox->GetSelectedNode().IsNotNull())
{
ItkUCharImageType::Pointer mask = ItkUCharImageType::New();
mitk::CastToItkImage(dynamic_cast(m_Controls->m_SeedImageBox->GetSelectedNode()->GetData()), mask);
m_Tracker->SetSeedImage(mask);
}
+ m_Tracker->SetInterpolateMask(false);
if (m_Controls->m_MaskImageBox->GetSelectedNode().IsNotNull())
{
ItkUCharImageType::Pointer mask = ItkUCharImageType::New();
mitk::CastToItkImage(dynamic_cast(m_Controls->m_MaskImageBox->GetSelectedNode()->GetData()), mask);
m_Tracker->SetMaskImage(mask);
+ m_Tracker->SetInterpolateMask(m_Controls->m_MaskInterpolationBox->isChecked());
}
if (m_Controls->m_StopImageBox->GetSelectedNode().IsNotNull())
{
ItkUCharImageType::Pointer mask = ItkUCharImageType::New();
mitk::CastToItkImage(dynamic_cast(m_Controls->m_StopImageBox->GetSelectedNode()->GetData()), mask);
m_Tracker->SetStoppingRegions(mask);
}
if (m_Controls->m_TargetImageBox->GetSelectedNode().IsNotNull())
{
ItkUintImgType::Pointer mask = ItkUintImgType::New();
mitk::CastToItkImage(dynamic_cast(m_Controls->m_TargetImageBox->GetSelectedNode()->GetData()), mask);
m_Tracker->SetTargetRegions(mask);
}
if (m_Controls->m_TissueImageBox->GetSelectedNode().IsNotNull())
{
ItkUCharImageType::Pointer mask = ItkUCharImageType::New();
mitk::CastToItkImage(dynamic_cast(m_Controls->m_TissueImageBox->GetSelectedNode()->GetData()), mask);
m_Tracker->SetTissueImage(mask);
m_Tracker->SetSeedOnlyGm(m_Controls->m_SeedGmBox->isChecked());
}
m_Tracker->SetVerbose(!m_Controls->m_InteractiveBox->isChecked());
m_Tracker->SetSeedsPerVoxel(m_Controls->m_SeedsPerVoxelBox->value());
m_Tracker->SetStepSize(m_Controls->m_StepSizeBox->value());
m_Tracker->SetSamplingDistance(m_Controls->m_SamplingDistanceBox->value());
m_Tracker->SetUseStopVotes(m_Controls->m_StopVotesBox->isChecked());
m_Tracker->SetOnlyForwardSamples(m_Controls->m_FrontalSamplesBox->isChecked());
m_Tracker->SetAposterioriCurvCheck(false);
m_Tracker->SetMaxNumTracts(m_Controls->m_NumFibersBox->value());
m_Tracker->SetNumberOfSamples(m_Controls->m_NumSamplesBox->value());
m_Tracker->SetTrackingHandler(m_TrackingHandler);
m_Tracker->SetAngularThreshold(m_Controls->m_AngularThresholdBox->value());
m_Tracker->SetMinTractLength(m_Controls->m_MinTractLengthBox->value());
m_Tracker->SetUseOutputProbabilityMap(m_Controls->m_OutputProbMap->isChecked());
m_ParentNode = m_InputImageNodes.at(0);
m_TrackingThread.start(QThread::LowestPriority);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui
index 5bd1175989..92621907c5 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui
@@ -1,1084 +1,1097 @@
QmitkStreamlineTrackingViewControls
0
0
413
- 1325
+ 1356
0
0
QmitkTemplate
0
0
3
3
-
Please Select Input Data
-
Tissue label image needed for gray matter seeding (WM=3, GM=1). Use e.g. MRtrix 5ttgen to generate such a label image.
QComboBox::AdjustToMinimumContentsLength
-
-
-
Tissue Image:
-
Tractography Forest:
-
Seed Image:
-
Input Image. ODF, tensor and peak images are currently supported.
Input Image:
-
Tractography is only performed inside the mask image. Fibers that leave the mask image are stopped.
QComboBox::AdjustToMinimumContentsLength
-
-
-
Fibers that enter a region defined in this image will stop immediately.
QComboBox::AdjustToMinimumContentsLength
-
-
-
FA/GFA Image:
-
Random forest for machine learning based tractography.
QComboBox::AdjustToMinimumContentsLength
-
-
-
If an image is selected, the stopping criterion is not calculated from the input image but instead the selected image is used.
QComboBox::AdjustToMinimumContentsLength
-
-
-
Stop Image:
-
Mask Image:
-
Seed points are only placed inside the mask image. If no seed mask is selected, the whole image is seeded.
QComboBox::AdjustToMinimumContentsLength
-
-
-
Input Image. ODF, tensor, peak, and, in case of ML tractography, raw diffusion-weighted images are currently supported.
<html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html>
true
-
Target Image:
-
Fibers that do not start and end in a region defined in this image will be discarded.
QComboBox::AdjustToMinimumContentsLength
-
-
-
false
Start Tractography
-
0
0
Interactive Tractography
-
Number of seed points normally distributed around selected position.
1
9999999
50
-
Num. Seeds:
-
true
Dynamically pick seed location by click into image.
Enable Interactive Tractography
-
Seedpoints are normally distributed within a sphere centered at the selected position with the specified radius (in mm).
2
50.000000000000000
0.100000000000000
2.500000000000000
-
Radius:
-
true
When checked, parameter changes cause instant retracking while in interactive mode.
Update on Parameter Change
true
-
0
0
Parameters
-
Mode:
-
Toggle between deterministic and probabilistic tractography. Some modes might not be available for all types of tractography.
-
Deterministic
-
Probabilistic
-
Seeds per Voxel:
-
Number of seed points placed in each voxel.
1
9999999
-
Max. num. fibers:
-
Tractography is stopped after the desired number of fibers is reached, even before all seed points are processed.
-1
999999999
-1
-
Cutoff:
-
Threshold on peak magnitude, FA, GFA, ...
5
1.000000000000000
0.100000000000000
0.100000000000000
-
ODF Cutoff:
-
Additional threshold on the ODF magnitude. This is useful in case of CSD fODF tractography.
5
1.000000000000000
0.100000000000000
0.100000000000000
-
If you are using dODF images as input, it is advisable to sharpen the ODFs (min-max normalize and raise to the power of 4). This is not necessary for CSD fODFs, since they are naturally much sharper.
Sharpen ODFs
-
Qt::Horizontal
QSizePolicy::Fixed
200
0
-
Advanced Parameters
-
QFrame::NoFrame
QFrame::Raised
0
0
0
0
-
Min. Tract Length:
-
Step size (in voxels)
2
0.010000000000000
10.000000000000000
0.100000000000000
0.500000000000000
-
Angular Threshold:
-
Flip directions:
-
f=1 + g=0 means FACT (depending on the chosen interpolation). f=0 and g=1 means TEND (disable interpolation for this mode!).
2
1.000000000000000
0.100000000000000
1.000000000000000
-
f parameter of tensor tractography. f=1 + g=0 means FACT (depending on the chosen interpolation). f=0 and g=1 means TEND (disable interpolation for this mode!).
f:
-
g:
-
Shorter fibers are discarded.
Minimum fiber length (in mm)
1
999.000000000000000
1.000000000000000
20.000000000000000
-
QFrame::NoFrame
QFrame::Raised
0
0
0
0
-
Internally flips progression directions. This might be necessary depending on the input data.
x
-
Internally flips progression directions. This might be necessary depending on the input data.
y
-
Internally flips progression directions. This might be necessary depending on the input data.
z
-
Step Size:
-
Default: 90° * step_size
-1
90
1
-1
-
f=1 + g=0 means FACT (depending on the chosen interpolation). f=0 and g=1 means TEND (disable interpolation for this mode!).
2
1.000000000000000
0.100000000000000
0.000000000000000
-
QFrame::NoFrame
QFrame::Raised
0
0
0
0
-
-
+
-
Requires tissue image.
Enable Gray Matter Seeding
false
-
If false, nearest neighbor interpolation is used.
- Enable Trilinear Interpolation
+ Interpolate Tractography Data
true
+ -
+
+
+ The tractography mask is not interpolated by default.
+
+
+ Interpolate Mask Image
+
+
+ false
+
+
+
-
0
0
Neighborhood Sampling
-
QFrame::NoFrame
QFrame::Raised
0
0
0
0
-
Num. Samples:
-
Number of neighborhood samples that are used to determine the next fiber progression direction.
50
-
Sampling Distance:
-
Sampling distance (in voxels)
2
10.000000000000000
0.100000000000000
0.250000000000000
-
Only neighborhood samples in front of the current streamline position are considered.
Use Only Frontal Samples
false
-
If checked, the majority of sampling points has to place a stop-vote for the streamline to terminate. If not checked, all sampling positions have to vote for a streamline termination.
Use Stop-Votes
false
-
Qt::Vertical
QSizePolicy::Expanding
20
220
-
0
0
Output and Postprocessing
-
QFrame::NoFrame
QFrame::Raised
0
0
0
0
-
Resample fibers using the specified error constraint.
Compress Fibers
true
-
Qt::StrongFocus
Lossy fiber compression. Recommended for large tractograms. Maximum error in mm.
3
10.000000000000000
0.010000000000000
0.100000000000000
-
Output probability map instead of tractogram.
Output Probability Map
false
-
true
Stop Tractography
-
true
0
0
true
QmitkDataStorageComboBox
QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone
QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimagingapp/plugin.xml
index ac5ff80818..f3ed00e11e 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/plugin.xml
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/plugin.xml
@@ -1,31 +1,49 @@
-
+
+
+
+
+
+
+
+
+
+
+