diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui
index 48f6321379..0975608f73 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui
@@ -1,486 +1,492 @@
QmitkFiberClusteringViewControls
0
0
- 484
- 574
+ 474
+ 669
Form
- -
+
+ 25
+
+
-
Qt::Vertical
20
40
- -
-
-
- QFrame::NoFrame
-
-
- QFrame::Raised
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 6
-
-
-
-
-
- If set, the input tractogram is clustered around the input centroids and no new clusters are created.
-
-
-
- -
-
-
- Output Centroids:
-
-
-
- -
-
-
- false
-
-
-
- 0
- 0
-
-
-
-
- 200
- 16777215
-
-
-
-
- 11
-
-
-
-
-
-
- Start
-
-
-
- -
-
-
- Cluster Size:
-
-
-
- -
-
-
- Fiber Points:
-
-
-
- -
-
-
- Only output the N largest clusters. Zero means no limit.
-
-
- 99999999
-
-
- 10
-
-
-
- -
-
-
- Fibers are resampled to the desired number of points for clustering. Smaller is faster but less accurate.
-
-
- 2
-
-
- 9999999
-
-
- 12
-
-
-
- -
-
-
- Input Centroids:
-
-
-
- -
-
-
-
-
-
-
- -
-
-
- Min. Fibers per Cluster:
-
-
-
- -
-
-
- Merge duplicate clusters withthe specified distance threshold. If threshold is < 0, the threshold is set to half of the specified cluster size.
-
-
- -1.000000000000000
-
-
- 99999.000000000000000
-
-
- -1.000000000000000
-
-
-
- -
-
-
- Max. Clusters:
-
-
-
- -
-
-
- Merge Duplicate Clusters:
-
-
-
- -
-
-
- Tractogram:
-
-
-
- -
-
-
- Only output clusters with ate least the specified number of fibers.
-
-
- 1
-
-
- 9999999
-
-
- 50
-
-
-
- -
-
-
- Cluster size in mm.
-
-
- 1
-
-
- 9999999
-
-
- 20
-
-
-
- -
-
-
-
-
-
- -
+
-
Metrics
0
0
0
0
-
Weighting factor for metric values.
1
999.000000000000000
1.000000000000000
-
Euclidean
true
-
Euclidean with STDEV
-
Euclidean Maximum
-
Inner Angles
-
QFrame::NoFrame
QFrame::Raised
0
0
0
0
6
-
Distance is based on the selected parcellation.
Anatomical
-
Distance is based on the selected parcellation.
-
Weighting factor for metric values.
1
999.000000000000000
1.000000000000000
-
Weighting factor for metric values.
1
999.000000000000000
1.000000000000000
-
Weighting factor for metric values.
1
999.000000000000000
1.000000000000000
-
Weighting factor for metric values.
1
999.000000000000000
1.000000000000000
-
Weighting factor for metric values.
1
999.000000000000000
30.000000000000000
-
QFrame::NoFrame
QFrame::Raised
0
0
0
0
-
Distance is based on the scalar map values along the tract.
Scalar Map
-
Distance is based on the scalar map values along the tract.
+ -
+
+
+ Input Data
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Input Centroids:
+
+
+
+ -
+
+
+ If set, the input tractogram is clustered around the input centroids and no new clusters are created.
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 200
+ 16777215
+
+
+
+
+ 11
+
+
+
+
+
+
+ Start
+
+
+
+ -
+
+
+ Tractogram:
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+ Parameters
+
+
+
-
+
+
+ Only output clusters with ate least the specified number of fibers.
+
+
+ 1
+
+
+ 9999999
+
+
+ 50
+
+
+
+ -
+
+
+ Only output the N largest clusters. Zero means no limit.
+
+
+ 99999999
+
+
+ 10
+
+
+
+ -
+
+
+ Min. Fibers per Cluster:
+
+
+
+ -
+
+
+ Max. Clusters:
+
+
+
+ -
+
+
+ Fiber Points:
+
+
+
+ -
+
+
+ Merge duplicate clusters withthe specified distance threshold. If threshold is < 0, the threshold is set to half of the specified cluster size.
+
+
+ -1.000000000000000
+
+
+ 99999.000000000000000
+
+
+ 0.000000000000000
+
+
+
+ -
+
+
+ Cluster Size:
+
+
+
+ -
+
+
+ Cluster size in mm.
+
+
+ 1
+
+
+ 9999999
+
+
+ 20
+
+
+
+ -
+
+
+ Fibers are resampled to the desired number of points for clustering. Smaller is faster but less accurate.
+
+
+ 2
+
+
+ 9999999
+
+
+ 12
+
+
+
+ -
+
+
+ Merge Duplicate Clusters:
+
+
+
+ -
+
+
+ Output Centroids:
+
+
+
+ -
+
+
+
+
+
+
+
+
+
QmitkDataStorageComboBox
QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone
QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.cpp
index 555e0fe29f..3d67315158 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.cpp
@@ -1,229 +1,229 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#include
#include
#include "QmitkFiberFitView.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const std::string QmitkFiberFitView::VIEW_ID = "org.mitk.views.fiberfit";
using namespace mitk;
QmitkFiberFitView::QmitkFiberFitView()
: QmitkAbstractView()
, m_Controls( nullptr )
{
}
// Destructor
QmitkFiberFitView::~QmitkFiberFitView()
{
}
void QmitkFiberFitView::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::QmitkFiberFitViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(StartFit()) );
connect( m_Controls->m_ImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DataSelectionChanged()) );
connect( m_Controls->m_TractBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DataSelectionChanged()) );
mitk::TNodePredicateDataType::Pointer isFib = mitk::TNodePredicateDataType::New();
- mitk::TNodePredicateDataType::Pointer isPeak = mitk::TNodePredicateDataType::New();
+ mitk::TNodePredicateDataType::Pointer isPeak = mitk::TNodePredicateDataType::New();
m_Controls->m_TractBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_TractBox->SetPredicate(isFib);
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_ImageBox->SetPredicate(isPeak);
DataSelectionChanged();
}
}
void QmitkFiberFitView::DataSelectionChanged()
{
if (m_Controls->m_TractBox->GetSelectedNode().IsNull() || m_Controls->m_ImageBox->GetSelectedNode().IsNull())
m_Controls->m_StartButton->setEnabled(false);
else
m_Controls->m_StartButton->setEnabled(true);
}
void QmitkFiberFitView::SetFocus()
{
DataSelectionChanged();
}
void QmitkFiberFitView::StartFit()
{
if (m_Controls->m_TractBox->GetSelectedNode().IsNull() || m_Controls->m_ImageBox->GetSelectedNode().IsNull())
return;
mitk::FiberBundle::Pointer input_tracts = dynamic_cast(m_Controls->m_TractBox->GetSelectedNode()->GetData());
mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode();
itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New();
mitk::Image::Pointer mitk_diff_image = dynamic_cast(node->GetData());
mitk::PeakImage::Pointer mitk_peak_image = dynamic_cast(node->GetData());
if (mitk_peak_image.IsNotNull())
{
typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitk_peak_image);
caster->Update();
mitk::PeakImage::ItkPeakImageType::Pointer peak_image = caster->GetOutput();
fitter->SetPeakImage(peak_image);
}
else
{
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(mitk_diff_image))
{
fitter->SetDiffImage(mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk_diff_image));
mitk::TensorModel<>* model = new mitk::TensorModel<>();
model->SetBvalue(1000);
model->SetDiffusivity1(0.0010);
model->SetDiffusivity2(0.00015);
model->SetDiffusivity3(0.00015);
model->SetGradientList(mitk::DiffusionPropertyHelper::GetGradientContainer(mitk_diff_image));
fitter->SetSignalModel(model);
}
else
return;
}
fitter->SetTractograms({input_tracts});
fitter->SetFitIndividualFibers(true);
fitter->SetMaxIterations(20);
fitter->SetVerbose(true);
fitter->SetGradientTolerance(1e-5);
fitter->SetLambda(m_Controls->m_ReguBox->value());
fitter->SetFilterOutliers(m_Controls->m_OutliersBox->isChecked());
fitter->Update();
mitk::FiberBundle::Pointer output_tracts = fitter->GetTractograms().at(0);
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(output_tracts);
new_node->SetName("Fitted");
this->GetDataStorage()->Add(new_node, node);
m_Controls->m_TractBox->GetSelectedNode()->SetVisibility(false);
if (m_Controls->m_ResidualsBox->isChecked() && mitk_peak_image.IsNotNull())
{
{
mitk::PeakImage::ItkPeakImageType::Pointer itk_image = fitter->GetFittedImage();
mitk::Image::Pointer mitk_image = dynamic_cast(PeakImage::New().GetPointer());
mitk::CastToMitkImage(itk_image, mitk_image);
mitk_image->SetVolume(itk_image->GetBufferPointer());
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(mitk_image);
new_node->SetName("Fitted");
this->GetDataStorage()->Add(new_node, node);
}
{
mitk::PeakImage::ItkPeakImageType::Pointer itk_image = fitter->GetResidualImage();
mitk::Image::Pointer mitk_image = dynamic_cast(PeakImage::New().GetPointer());
mitk::CastToMitkImage(itk_image, mitk_image);
mitk_image->SetVolume(itk_image->GetBufferPointer());
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(mitk_image);
new_node->SetName("Residual");
this->GetDataStorage()->Add(new_node, node);
}
{
mitk::PeakImage::ItkPeakImageType::Pointer itk_image = fitter->GetUnderexplainedImage();
mitk::Image::Pointer mitk_image = dynamic_cast(PeakImage::New().GetPointer());
mitk::CastToMitkImage(itk_image, mitk_image);
mitk_image->SetVolume(itk_image->GetBufferPointer());
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(mitk_image);
new_node->SetName("Underexplained");
this->GetDataStorage()->Add(new_node, node);
}
{
mitk::PeakImage::ItkPeakImageType::Pointer itk_image = fitter->GetOverexplainedImage();
mitk::Image::Pointer mitk_image = dynamic_cast(PeakImage::New().GetPointer());
mitk::CastToMitkImage(itk_image, mitk_image);
mitk_image->SetVolume(itk_image->GetBufferPointer());
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(mitk_image);
new_node->SetName("Overexplained");
this->GetDataStorage()->Add(new_node, node);
}
}
else if (m_Controls->m_ResidualsBox->isChecked() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(mitk_diff_image))
{
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetFittedImageDiff().GetPointer() );
mitk::DiffusionPropertyHelper::CopyProperties(mitk_diff_image, outImage, true);
mitk::DiffusionPropertyHelper propertyHelper( outImage );
propertyHelper.InitializeImage();
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(outImage);
new_node->SetName("Fitted");
this->GetDataStorage()->Add(new_node, node);
}
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetResidualImageDiff().GetPointer() );
mitk::DiffusionPropertyHelper::CopyProperties(mitk_diff_image, outImage, true);
mitk::DiffusionPropertyHelper propertyHelper( outImage );
propertyHelper.InitializeImage();
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(outImage);
new_node->SetName("Residual");
this->GetDataStorage()->Add(new_node, node);
}
}
}
void QmitkFiberFitView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& )
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitViewControls.ui
index 28ab5be067..7c1c06263c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitViewControls.ui
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitViewControls.ui
@@ -1,179 +1,179 @@
QmitkFiberFitViewControls
0
0
484
574
Form
-
QFrame::NoFrame
QFrame::Raised
0
0
0
0
6
-
Select a peak or raw diffusion-weighted image.
-
true
-
- Input Image:
+ Peak Image:
-
Suppress Outliers:
-
Modifier for regularization.
999999.000000000000000
0.100000000000000
1.000000000000000
-
false
0
0
200
16777215
11
Start
-
Tractogram:
-
-
λ:
-
Output Residuals:
-
false
-
Qt::Vertical
20
40
QmitkDataStorageComboBox
QComboBox
QmitkDataStorageComboBox.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.cpp
index a9b8973b6f..cd1cd24e86 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.cpp
@@ -1,474 +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.
===================================================================*/
// Blueberry
#include
#include
// Qmitk
#include "QmitkFiberQuantificationView.h"
// Qt
#include
// MITK
#include
#include
#include
#include
#include
#include
#include
#include
// ITK
#include
#include
#include
#include
#include
#include
const std::string QmitkFiberQuantificationView::VIEW_ID = "org.mitk.views.fiberquantification";
using namespace mitk;
QmitkFiberQuantificationView::QmitkFiberQuantificationView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_UpsamplingFactor(5)
+ , m_Visible(false)
{
}
// Destructor
QmitkFiberQuantificationView::~QmitkFiberQuantificationView()
{
}
void QmitkFiberQuantificationView::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::QmitkFiberQuantificationViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_ProcessFiberBundleButton, SIGNAL(clicked()), this, SLOT(ProcessSelectedBundles()) );
connect( m_Controls->m_ExtractFiberPeaks, SIGNAL(clicked()), this, SLOT(CalculateFiberDirections()) );
m_Controls->m_TractBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType::Pointer isFib = mitk::TNodePredicateDataType::New();
m_Controls->m_TractBox->SetPredicate( isFib );
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_ImageBox->SetZeroEntryText("--");
mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New();
mitk::NodePredicateDimension::Pointer is3D = mitk::NodePredicateDimension::New(3);
m_Controls->m_ImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, is3D) );
connect( (QObject*)(m_Controls->m_TractBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
connect( (QObject*)(m_Controls->m_ImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
}
}
+void QmitkFiberQuantificationView::Activated()
+{
+
+}
+
+void QmitkFiberQuantificationView::Deactivated()
+{
+
+}
+
+void QmitkFiberQuantificationView::Visible()
+{
+ m_Visible = true;
+ QList selection = GetDataManagerSelection();
+ berry::IWorkbenchPart::Pointer nullPart;
+ OnSelectionChanged(nullPart, selection);
+}
+
+void QmitkFiberQuantificationView::Hidden()
+{
+ m_Visible = false;
+}
+
void QmitkFiberQuantificationView::SetFocus()
{
m_Controls->m_ProcessFiberBundleButton->setFocus();
}
void QmitkFiberQuantificationView::CalculateFiberDirections()
{
typedef itk::Image ItkUcharImgType;
// load fiber bundle
mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(m_SelectedFB.back()->GetData());
itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New();
if (m_SelectedImage.IsNotNull())
{
ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New();
mitk::CastToItkImage(m_SelectedImage, itkMaskImage);
fOdfFilter->SetMaskImage(itkMaskImage);
}
// extract directions from fiber bundle
fOdfFilter->SetFiberBundle(inputTractogram);
fOdfFilter->SetAngularThreshold(cos(m_Controls->m_AngularThreshold->value()*M_PI/180));
switch (m_Controls->m_FiberDirNormBox->currentIndex())
{
case 0:
fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter::NormalizationMethods::GLOBAL_MAX);
break;
case 1:
fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter::NormalizationMethods::SINGLE_VEC_NORM);
break;
case 2:
fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter::NormalizationMethods::MAX_VEC_NORM);
break;
}
fOdfFilter->SetUseWorkingCopy(true);
fOdfFilter->SetSizeThreshold(m_Controls->m_PeakThreshold->value());
fOdfFilter->SetMaxNumDirections(m_Controls->m_MaxNumDirections->value());
fOdfFilter->Update();
QString name = m_SelectedFB.back()->GetName().c_str();
if (m_Controls->m_NumDirectionsBox->isChecked())
{
mitk::Image::Pointer mitkImage = mitk::Image::New();
mitkImage->InitializeByItk( fOdfFilter->GetNumDirectionsImage().GetPointer() );
mitkImage->SetVolume( fOdfFilter->GetNumDirectionsImage()->GetBufferPointer() );
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(mitkImage);
node->SetName((name+"_NUM_DIRECTIONS").toStdString().c_str());
GetDataStorage()->Add(node, m_SelectedFB.back());
}
Image::Pointer mitkImage = dynamic_cast(PeakImage::New().GetPointer());
mitk::CastToMitkImage(fOdfFilter->GetDirectionImage(), mitkImage);
mitkImage->SetVolume(fOdfFilter->GetDirectionImage()->GetBufferPointer());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(mitkImage);
node->SetName( (name+"_DIRECTIONS").toStdString().c_str());
GetDataStorage()->Add(node, m_SelectedFB.back());
}
void QmitkFiberQuantificationView::UpdateGui()
{
m_SelectedFB.clear();
if (m_Controls->m_TractBox->GetSelectedNode().IsNotNull())
m_SelectedFB.push_back(m_Controls->m_TractBox->GetSelectedNode());
m_SelectedImage = nullptr;
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
m_SelectedImage = dynamic_cast(m_Controls->m_ImageBox->GetSelectedNode()->GetData());
m_Controls->m_ProcessFiberBundleButton->setEnabled(!m_SelectedFB.empty());
m_Controls->m_ExtractFiberPeaks->setEnabled(!m_SelectedFB.empty());
+
+ GenerateStats();
}
void QmitkFiberQuantificationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& )
{
UpdateGui();
- GenerateStats();
}
void QmitkFiberQuantificationView::GenerateStats()
{
- if ( m_SelectedFB.empty() )
+ if ( m_SelectedFB.empty() || !m_Visible )
return;
QString stats("");
for( unsigned int i=0; i(node->GetData()))
{
if (i>0)
stats += "\n-----------------------------\n";
stats += QString(node->GetName().c_str()) + "\n";
mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData());
stats += "Number of fibers: "+ QString::number(fib->GetNumFibers()) + "\n";
stats += "Number of points: "+ QString::number(fib->GetNumberOfPoints()) + "\n";
stats += "Min. length: "+ QString::number(fib->GetMinFiberLength(),'f',1) + " mm\n";
stats += "Max. length: "+ QString::number(fib->GetMaxFiberLength(),'f',1) + " mm\n";
stats += "Mean length: "+ QString::number(fib->GetMeanFiberLength(),'f',1) + " mm\n";
stats += "Median length: "+ QString::number(fib->GetMedianFiberLength(),'f',1) + " mm\n";
stats += "Standard deviation: "+ QString::number(fib->GetLengthStDev(),'f',1) + " mm\n";
vtkSmartPointer weights = fib->GetFiberWeights();
if (weights!=nullptr)
{
std::vector< float > weights2;
for (int i=0; iGetSize(); i++)
weights2.push_back(weights->GetValue(i));
std::sort(weights2.begin(), weights2.end());
stats += "\nFiber weight statistics\n";
stats += "Min: " + QString::number(weights2.front()) + "\n";
stats += "1% quantile: " + QString::number(weights2.at(weights2.size()*0.01)) + "\n";
stats += "5% quantile: " + QString::number(weights2.at(weights2.size()*0.05)) + "\n";
stats += "25% quantile: " + QString::number(weights2.at(weights2.size()*0.25)) + "\n";
stats += "Median: " + QString::number(weights2.at(weights2.size()*0.5)) + "\n";
stats += "75% quantile: " + QString::number(weights2.at(weights2.size()*0.75)) + "\n";
stats += "95% quantile: " + QString::number(weights2.at(weights2.size()*0.95)) + "\n";
stats += "99% quantile: " + QString::number(weights2.at(weights2.size()*0.99)) + "\n";
stats += "Max: " + QString::number(weights2.back()) + "\n";
}
else
stats += "No fiber weight array found.\n";
}
}
this->m_Controls->m_StatsTextEdit->setText(stats);
}
void QmitkFiberQuantificationView::ProcessSelectedBundles()
{
if ( m_SelectedFB.empty() ){
QMessageBox::information( nullptr, "Warning", "No fibe bundle selected!");
MITK_WARN("QmitkFiberQuantificationView") << "no fibe bundle selected";
return;
}
int generationMethod = m_Controls->m_GenerationBox->currentIndex();
for( unsigned int i=0; i(node->GetData()))
{
mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData());
QString name(node->GetName().c_str());
DataNode::Pointer newNode = nullptr;
switch(generationMethod){
case 0:
newNode = GenerateTractDensityImage(fib, false, true);
name += "_TDI";
break;
case 1:
newNode = GenerateTractDensityImage(fib, false, false);
name += "_TDI";
break;
case 2:
newNode = GenerateTractDensityImage(fib, true, false);
name += "_envelope";
break;
case 3:
newNode = GenerateColorHeatmap(fib);
break;
case 4:
newNode = GenerateFiberEndingsImage(fib);
name += "_fiber_endings";
break;
case 5:
newNode = GenerateFiberEndingsPointSet(fib);
name += "_fiber_endings";
break;
}
if (newNode.IsNotNull())
{
newNode->SetName(name.toStdString());
GetDataStorage()->Add(newNode);
}
}
}
}
// generate pointset displaying the fiber endings
mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateFiberEndingsPointSet(mitk::FiberBundle::Pointer fib)
{
mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
vtkSmartPointer fiberPolyData = fib->GetFiberPolyData();
int count = 0;
int numFibers = fib->GetNumFibers();
for( int i=0; iGetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (numPoints>0)
{
double* point = points->GetPoint(0);
itk::Point itkPoint;
itkPoint[0] = point[0];
itkPoint[1] = point[1];
itkPoint[2] = point[2];
pointSet->InsertPoint(count, itkPoint);
count++;
}
if (numPoints>2)
{
double* point = points->GetPoint(numPoints-1);
itk::Point itkPoint;
itkPoint[0] = point[0];
itkPoint[1] = point[1];
itkPoint[2] = point[2];
pointSet->InsertPoint(count, itkPoint);
count++;
}
}
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( pointSet );
return node;
}
// generate image displaying the fiber endings
mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateFiberEndingsImage(mitk::FiberBundle::Pointer fib)
{
typedef unsigned int OutPixType;
typedef itk::Image OutImageType;
typedef itk::TractsToFiberEndingsImageFilter< OutImageType > ImageGeneratorType;
ImageGeneratorType::Pointer generator = ImageGeneratorType::New();
generator->SetFiberBundle(fib);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
if (m_SelectedImage.IsNotNull())
{
OutImageType::Pointer itkImage = OutImageType::New();
CastToItkImage(m_SelectedImage, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
generator->Update();
// get output image
OutImageType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// init data node
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
return node;
}
// generate rgba heatmap from fiber bundle
mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateColorHeatmap(mitk::FiberBundle::Pointer fib)
{
typedef itk::RGBAPixel OutPixType;
typedef itk::Image OutImageType;
typedef itk::TractsToRgbaImageFilter< OutImageType > ImageGeneratorType;
ImageGeneratorType::Pointer generator = ImageGeneratorType::New();
generator->SetFiberBundle(fib);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
if (m_SelectedImage.IsNotNull())
{
itk::Image::Pointer itkImage = itk::Image::New();
CastToItkImage(m_SelectedImage, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
generator->Update();
// get output image
typedef itk::Image OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// init data node
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
return node;
}
// generate tract density image from fiber bundle
mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateTractDensityImage(mitk::FiberBundle::Pointer fib, bool binary, bool absolute)
{
mitk::DataNode::Pointer node = mitk::DataNode::New();
if (binary)
{
typedef unsigned char OutPixType;
typedef itk::Image OutImageType;
itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New();
generator->SetFiberBundle(fib);
generator->SetBinaryOutput(binary);
generator->SetOutputAbsoluteValues(absolute);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
if (m_SelectedImage.IsNotNull())
{
OutImageType::Pointer itkImage = OutImageType::New();
CastToItkImage(m_SelectedImage, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
generator->Update();
// get output image
typedef itk::Image OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
if (m_SelectedImage.IsNotNull())
{
mitk::LabelSetImage::Pointer multilabelImage = mitk::LabelSetImage::New();
multilabelImage->InitializeByLabeledImage(img);
mitk::Label::Pointer label = multilabelImage->GetActiveLabel();
label->SetName("Tractogram");
// label->SetColor(color);
label->SetValue(1);
// multilabelImage->GetActiveLabelSet()->AddLabel(label);
multilabelImage->GetActiveLabelSet()->SetActiveLabel(1);
PropertyList::Pointer dicomSegPropertyList = mitk::DICOMSegmentationPropertyHandler::GetDICOMSegmentationProperties(m_SelectedImage->GetPropertyList());
multilabelImage->GetPropertyList()->ConcatenatePropertyList(dicomSegPropertyList);
mitk::DICOMSegmentationPropertyHandler::GetDICOMSegmentProperties(multilabelImage->GetActiveLabel(multilabelImage->GetActiveLayer()));
// init data node
node->SetData(multilabelImage);
}
else
{
// init data node
node->SetData(img);
}
}
else
{
typedef float OutPixType;
typedef itk::Image OutImageType;
itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New();
generator->SetFiberBundle(fib);
generator->SetBinaryOutput(binary);
generator->SetOutputAbsoluteValues(absolute);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
if (m_SelectedImage.IsNotNull())
{
OutImageType::Pointer itkImage = OutImageType::New();
CastToItkImage(m_SelectedImage, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
//generator->SetDoFiberResampling(false);
generator->Update();
// get output image
typedef itk::Image OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// init data node
node->SetData(img);
}
return node;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.h
index 35f06374ce..a970115b29 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.h
@@ -1,81 +1,88 @@
/*===================================================================
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 QmitkFiberQuantificationView_h
#define QmitkFiberQuantificationView_h
#include
#include "ui_QmitkFiberQuantificationViewControls.h"
#include
#include
#include
+#include
/*!
\brief Generation of images from fiber bundles (TDI, envelopes, endpoint distribution) and extraction of principal fiber directions from tractograms.
*/
-class QmitkFiberQuantificationView : public QmitkAbstractView
+class QmitkFiberQuantificationView : public QmitkAbstractView, public mitk::ILifecycleAwarePart
{
// 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;
QmitkFiberQuantificationView();
virtual ~QmitkFiberQuantificationView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
+ virtual void Activated() override;
+ virtual void Deactivated() override;
+ virtual void Visible() override;
+ virtual void Hidden() override;
+
protected slots:
void ProcessSelectedBundles(); ///< start selected operation on fiber bundle (e.g. tract density image generation)
void CalculateFiberDirections(); ///< Calculate main fiber directions from tractogram
void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override;
Ui::QmitkFiberQuantificationViewControls* m_Controls;
void GenerateStats(); ///< generate statistics of selected fiber bundles
std::vector m_SelectedFB; ///< selected fiber bundle nodes
mitk::Image::Pointer m_SelectedImage;
float m_UpsamplingFactor; ///< upsampling factor for all image generations
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);
+ bool m_Visible;
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
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
index 62ebf80acf..50d11a0469 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp
@@ -1,310 +1,339 @@
/*===================================================================
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
#include
#include
+#include
const std::string QmitkTractometryView::VIEW_ID = "org.mitk.views.tractometry";
using namespace mitk;
QmitkTractometryView::QmitkTractometryView()
: QmitkAbstractView()
, m_Controls( nullptr )
+ , m_Visible(false)
{
}
// 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 );
connect( m_Controls->m_SamplingPointsBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateGui()) );
connect( m_Controls->m_StDevBox, SIGNAL(stateChanged(int)), this, SLOT(UpdateGui()) );
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");
+ m_Controls->m_ChartWidget->SetXAxisLabel("Tract position");
+ 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()
{
}
void QmitkTractometryView::UpdateGui()
{
berry::IWorkbenchPart::Pointer nullPart;
OnSelectionChanged(nullPart, QList(m_CurrentSelection));
}
bool QmitkTractometryView::Flip(vtkSmartPointer< vtkPolyData > polydata1, int i, vtkSmartPointer< vtkPolyData > ref_poly)
{
float d_direct = 0;
float d_flipped = 0;
vtkCell* cell1 = polydata1->GetCell(0);
if (ref_poly!=nullptr)
cell1 = ref_poly->GetCell(0);
int numPoints1 = cell1->GetNumberOfPoints();
vtkPoints* points1 = cell1->GetPoints();
vtkCell* cell2 = polydata1->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, std::string& clipboard_string)
{
int num_points = m_Controls->m_SamplingPointsBox->value();
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);
else if (m_ReferencePolyData!=nullptr)
flip = Flip(polydata, 0, m_ReferencePolyData);
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);
}
if (m_ReferencePolyData==nullptr)
m_ReferencePolyData = polydata;
std::vector< double > std_values1;
std::vector< double > std_values2;
for (int i=0; iGetNumFibers();
double stdev = 0;
for (unsigned int j=0; j(mean_values.at(i));
clipboard_string += " ";
clipboard_string += boost::lexical_cast(stdev);
clipboard_string += "\n";
}
clipboard_string += "\n";
data.push_back(mean_values);
data.push_back(std_values1);
data.push_back(std_values2);
MITK_INFO << "Min: " << min;
MITK_INFO << "Max: " << max;
MITK_INFO << "Mean: " << mean/working_fib->GetNumberOfPoints();
}
+void QmitkTractometryView::Activated()
+{
+
+}
+
+void QmitkTractometryView::Deactivated()
+{
+
+}
+
+void QmitkTractometryView::Visible()
+{
+ m_Visible = true;
+ QList selection = GetDataManagerSelection();
+ berry::IWorkbenchPart::Pointer nullPart;
+ OnSelectionChanged(nullPart, selection);
+}
+
+void QmitkTractometryView::Hidden()
+{
+ m_Visible = false;
+}
+
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_Visible)
+ return;
+
m_CurrentSelection.clear();
if(m_Controls->m_ImageBox->GetSelectedNode().IsNull())
return;
std::string clipboardString = "";
m_ReferencePolyData = nullptr;
mitk::Image::Pointer image = dynamic_cast(m_Controls->m_ImageBox->GetSelectedNode()->GetData());
vtkSmartPointer lookupTable = vtkSmartPointer::New();
lookupTable->SetTableRange(0.0, 1.0);
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()) )
{
clipboardString += node->GetName() + "\n";
clipboardString += "mean stdev\n";
mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData());
m_CurrentSelection.push_back(node);
std::vector< std::vector< double > > data;
mitkPixelTypeMultiplex4( ImageValuesAlongTract, image->GetPixelType(), image, fib, data, clipboardString );
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;
+ color[0] *= 0.5;
+ color[1] *= 0.5;
+ color[2] *= 0.5;
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;
}
}
QApplication::clipboard()->setText(clipboardString.c_str(), QClipboard::Clipboard);
}
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
index 2cf16b6518..47fc86c951 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.h
@@ -1,75 +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 QmitkTractometryView_h
#define QmitkTractometryView_h
#include
#include "ui_QmitkTractometryViewControls.h"
#include
#include
#include
#include
+#include
/*!
\brief Weight fibers by linearly fitting them to the image data.
*/
-class QmitkTractometryView : public QmitkAbstractView
+class QmitkTractometryView : public QmitkAbstractView, public mitk::ILifecycleAwarePart
{
// 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, std::string& clipboard_string);
virtual void SetFocus() override;
void OnPageSuccessfullyLoaded();
+ virtual void Activated() override;
+ virtual void Deactivated() override;
+ virtual void Visible() override;
+ virtual void Hidden() override;
protected slots:
void UpdateGui();
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 > polydata1, int i, vtkSmartPointer ref_poly=nullptr);
std::string RGBToHexString(double *rgb);
vtkSmartPointer< vtkPolyData > m_ReferencePolyData;
QList m_CurrentSelection;
+ bool m_Visible;
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp
index e2bbfaa9cf..9424224dfa 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp
@@ -1,928 +1,932 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
// Blueberry
#include
#include
// Qmitk
#include "QmitkIVIMView.h"
// qt
#include "qmessagebox.h"
#include "qclipboard.h"
// mitk
#include "mitkImage.h"
#include "mitkImageCast.h"
#include "mitkLookupTable.h"
#include "mitkLookupTableProperty.h"
#include
#include
// itk
#include "itkScalarImageToHistogramGenerator.h"
#include "itkRegionOfInterestImageFilter.h"
#include "itkImageRegionConstIteratorWithIndex.h"
// itk/mitk
#include "itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h"
#include "itkRegularizedIVIMReconstructionFilter.h"
#include "mitkImageCast.h"
#include
#include
#include
#include
#include
#include
const std::string QmitkIVIMView::VIEW_ID = "org.mitk.views.ivim";
QmitkIVIMView::QmitkIVIMView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_Active(false)
, m_Visible(false)
, m_HoldUpdate(false)
{
}
QmitkIVIMView::~QmitkIVIMView()
{
}
void QmitkIVIMView::CreateQtPartControl( QWidget *parent )
{
// hold update untill all elements are set
this->m_HoldUpdate = true;
// build up qt view, unless already done
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkIVIMViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_ButtonStart, SIGNAL(clicked()), this, SLOT(FittIVIMStart()) );
connect( m_Controls->m_ButtonAutoThres, SIGNAL(clicked()), this, SLOT(AutoThreshold()) );
connect( m_Controls->m_MethodCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(MethodCombo(int)) );
connect( m_Controls->m_DStarSlider, SIGNAL(valueChanged(int)), this, SLOT(DStarSlider(int)) );
connect( m_Controls->m_BThreshSlider, SIGNAL(valueChanged(int)), this, SLOT(BThreshSlider(int)) );
connect( m_Controls->m_S0ThreshSlider, SIGNAL(valueChanged(int)), this, SLOT(S0ThreshSlider(int)) );
connect( m_Controls->m_NumItSlider, SIGNAL(valueChanged(int)), this, SLOT(NumItsSlider(int)) );
connect( m_Controls->m_LambdaSlider, SIGNAL(valueChanged(int)), this, SLOT(LambdaSlider(int)) );
connect( m_Controls->m_CheckDStar, SIGNAL(clicked()), this, SLOT(Checkbox()) );
connect( m_Controls->m_CheckD, SIGNAL(clicked()), this, SLOT(Checkbox()) );
connect( m_Controls->m_Checkf, SIGNAL(clicked()), this, SLOT(Checkbox()) );
connect( m_Controls->m_ChooseMethod, SIGNAL(clicked()), this, SLOT(ChooseMethod()) );
connect( m_Controls->m_CurveClipboard, SIGNAL(clicked()), this, SLOT(ClipboardCurveButtonClicked()) );
connect( m_Controls->m_ValuesClipboard, SIGNAL(clicked()), this, SLOT(ClipboardStatisticsButtonClicked()) );
// connect all kurtosis actions to a recompute
connect( m_Controls->m_KurtosisRangeWidget, SIGNAL( rangeChanged(double, double)), this, SLOT(OnKurtosisParamsChanged() ) );
//connect( m_Controls->m_MaximalBValueWidget, SIGNAL( valueChanged(double)), this, SLOT( OnKurtosisParamsChanged() ) );
connect( m_Controls->m_OmitBZeroCB, SIGNAL( stateChanged(int) ), this, SLOT( OnKurtosisParamsChanged() ) );
connect( m_Controls->m_KurtosisFitScale, SIGNAL( currentIndexChanged(int)), this, SLOT( OnKurtosisParamsChanged() ) );
connect( m_Controls->m_UseKurtosisBoundsCB, SIGNAL(clicked() ), this, SLOT( OnKurtosisParamsChanged() ) );
m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
m_Controls->m_DwiBox->SetDataStorage(this->GetDataStorage());
mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New();
m_Controls->m_DwiBox->SetPredicate( isDwi );
connect( (QObject*)(m_Controls->m_DwiBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
m_Controls->m_MaskBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_MaskBox->SetZeroEntryText("--");
mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New();
mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateDimension::Pointer is3D = mitk::NodePredicateDimension::New(3);
m_Controls->m_MaskBox->SetPredicate( mitk::NodePredicateAnd::New(isBinaryPredicate, mitk::NodePredicateAnd::New(isImagePredicate, is3D)) );
connect( (QObject*)(m_Controls->m_MaskBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
connect( (QObject*)(m_Controls->m_ModelTabSelectionWidget), SIGNAL(currentChanged(int)), this, SLOT(UpdateGui()));
}
QString dstar = QString::number(m_Controls->m_DStarSlider->value()/1000.0);
m_Controls->m_DStarLabel->setText(dstar);
QString bthresh = QString::number(m_Controls->m_BThreshSlider->value()*5.0);
m_Controls->m_BThreshLabel->setText(bthresh);
QString s0thresh = QString::number(m_Controls->m_S0ThreshSlider->value()*0.5);
m_Controls->m_S0ThreshLabel->setText(s0thresh);
QString numits = QString::number(m_Controls->m_NumItSlider->value());
m_Controls->m_NumItsLabel->setText(numits);
QString lambda = QString::number(m_Controls->m_LambdaSlider->value()*.00001);
m_Controls->m_LambdaLabel->setText(lambda);
m_Controls->m_MethodCombo->setVisible(m_Controls->m_ChooseMethod->isChecked());
m_Controls->m_Warning->setVisible(false);
MethodCombo(m_Controls->m_MethodCombo->currentIndex());
m_Controls->m_KurtosisRangeWidget->setSingleStep(0.1);
m_Controls->m_KurtosisRangeWidget->setRange( 0.0, 10.0 );
m_Controls->m_KurtosisRangeWidget->setMaximumValue( 5.0 );
// LogScale not working yet, have to fix that first
// m_Controls->m_KurtosisFitScale->setEnabled(false);
//m_Controls->m_MaximalBValueWidget->setVisible( false );
// release update block after the UI-elements were all set
this->m_HoldUpdate = false;
}
void QmitkIVIMView::SetFocus()
{
m_Controls->m_ButtonAutoThres->setFocus();
}
void QmitkIVIMView::Checkbox()
{
OnSliceChanged();
}
void QmitkIVIMView::MethodCombo(int val)
{
switch(val)
{
case 0:
m_Controls->m_DstarFrame->setVisible(false);
m_Controls->m_NeglSiFrame->setVisible(true);
m_Controls->m_NeglBframe->setVisible(false);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
case 1:
m_Controls->m_DstarFrame->setVisible(true);
m_Controls->m_NeglSiFrame->setVisible(true);
m_Controls->m_NeglBframe->setVisible(false);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
case 2:
m_Controls->m_DstarFrame->setVisible(false);
m_Controls->m_NeglSiFrame->setVisible(true);
m_Controls->m_NeglBframe->setVisible(true);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
case 3:
m_Controls->m_DstarFrame->setVisible(false);
m_Controls->m_NeglSiFrame->setVisible(true);
m_Controls->m_NeglBframe->setVisible(true);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
case 4:
m_Controls->m_DstarFrame->setVisible(false);
m_Controls->m_NeglSiFrame->setVisible(false);
m_Controls->m_NeglBframe->setVisible(false);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
}
OnSliceChanged();
}
void QmitkIVIMView::DStarSlider (int val)
{
QString sval = QString::number(val/1000.0);
m_Controls->m_DStarLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::BThreshSlider (int val)
{
QString sval = QString::number(val*5.0);
m_Controls->m_BThreshLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::S0ThreshSlider (int val)
{
QString sval = QString::number(val*0.5);
m_Controls->m_S0ThreshLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::NumItsSlider (int val)
{
QString sval = QString::number(val);
m_Controls->m_NumItsLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::LambdaSlider (int val)
{
QString sval = QString::number(val*.00001);
m_Controls->m_LambdaLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::UpdateGui()
{
if (m_Controls->m_DwiBox->GetSelectedNode().IsNotNull())
{
m_Controls->m_VisualizeResultsWidget->setVisible(true);
m_Controls->m_KurtosisVisualizationWidget->setVisible(true);
m_HoldUpdate = false;
}
else
{
m_Controls->m_VisualizeResultsWidget->setVisible(false);
m_Controls->m_KurtosisVisualizationWidget->setVisible(false);
}
m_Controls->m_ButtonStart->setEnabled( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() );
m_Controls->m_ButtonAutoThres->setEnabled( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() );
m_Controls->m_ControlsFrame->setEnabled( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() );
m_Controls->m_BottomControlsFrame->setEnabled( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() );
OnSliceChanged();
}
void QmitkIVIMView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& )
{
UpdateGui();
}
void QmitkIVIMView::AutoThreshold()
{
if (m_Controls->m_DwiBox->GetSelectedNode().IsNull())
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, "Template", "Please load and select a diffusion image before starting image processing.");
return;
}
mitk::Image* dimg = dynamic_cast(m_Controls->m_DwiBox->GetSelectedNode()->GetData());
if (!dimg)
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, "Template", "No valid diffusion image was found.");
return;
}
// find bzero index
int index = -1;
DirContainerType::Pointer directions = static_cast( dimg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer();
for(DirContainerType::ConstIterator it = directions->Begin();
it != directions->End(); ++it)
{
index++;
GradientDirectionType g = it.Value();
if(g[0] == 0 && g[1] == 0 && g[2] == 0 )
break;
}
VecImgType::Pointer vecimg = VecImgType::New();
mitk::CastToItkImage(dimg, vecimg);
int vecLength = vecimg->GetVectorLength();
index = index > vecLength-1 ? vecLength-1 : index;
MITK_INFO << "Performing Histogram Analysis on Channel" << index;
typedef itk::Image ImgType;
ImgType::Pointer img = ImgType::New();
mitk::CastToItkImage(dimg, img);
itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() );
itw.GoToBegin();
itk::ImageRegionConstIterator itr (vecimg, vecimg->GetLargestPossibleRegion() );
itr.GoToBegin();
while(!itr.IsAtEnd())
{
itw.Set(itr.Get().GetElement(index));
++itr;
++itw;
}
typedef itk::Statistics::ScalarImageToHistogramGenerator< ImgType >
HistogramGeneratorType;
typedef HistogramGeneratorType::HistogramType HistogramType;
HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New();
histogramGenerator->SetInput( img );
histogramGenerator->SetMarginalScale( 10 ); // Defines y-margin width of histogram
histogramGenerator->SetNumberOfBins( 100 ); // CT range [-1024, +2048] --> bin size 4 values
histogramGenerator->SetHistogramMin( dimg->GetStatistics()->GetScalarValueMin() );
histogramGenerator->SetHistogramMax( dimg->GetStatistics()->GetScalarValueMax() * .5 );
histogramGenerator->Compute();
HistogramType::ConstIterator iter = histogramGenerator->GetOutput()->Begin();
float maxFreq = 0;
float maxValue = 0;
while ( iter != histogramGenerator->GetOutput()->End() )
{
if(iter.GetFrequency() > maxFreq)
{
maxFreq = iter.GetFrequency();
maxValue = iter.GetMeasurementVector()[0];
}
++iter;
}
maxValue *= 2;
int sliderPos = maxValue * 2;
m_Controls->m_S0ThreshSlider->setValue(sliderPos);
S0ThreshSlider(sliderPos);
}
void QmitkIVIMView::FittIVIMStart()
{
if (m_Controls->m_DwiBox->GetSelectedNode().IsNull())
{
QMessageBox::information( nullptr, "Template", "No valid diffusion-weighted image selected.");
return;
}
mitk::Image* img = dynamic_cast(m_Controls->m_DwiBox->GetSelectedNode()->GetData());
VecImgType::Pointer vecimg = VecImgType::New();
mitk::CastToItkImage(img, vecimg);
OutImgType::IndexType dummy;
if( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
// KURTOSIS
KurtosisFilterType::Pointer filter = KurtosisFilterType::New();
filter->SetInput(vecimg);
filter->SetReferenceBValue( static_cast(img->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() );
filter->SetGradientDirections( static_cast( img->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() );
filter->SetSmoothingSigma( this->m_Controls->m_SigmaSpinBox->value() );
if( this->m_Controls->m_UseKurtosisBoundsCB->isChecked() )
filter->SetBoundariesForKurtosis( this->m_Controls->m_KurtosisRangeWidget->minimumValue(), this->m_Controls->m_KurtosisRangeWidget->maximumValue() );
filter->SetFittingScale( static_cast(this->m_Controls->m_KurtosisFitScale->currentIndex() ) );
if( m_Controls->m_MaskBox->GetSelectedNode().IsNotNull() )
{
mitk::Image::Pointer maskImg = dynamic_cast(m_Controls->m_MaskBox->GetSelectedNode()->GetData());
typedef itk::Image MaskImgType;
MaskImgType::Pointer maskItk;
CastToItkImage( maskImg, maskItk );
filter->SetImageMask( maskItk );
}
filter->Update();
mitk::LookupTable::Pointer kurt_map_lut = mitk::LookupTable::New();
kurt_map_lut->SetType( mitk::LookupTable::JET_TRANSPARENT );
mitk::LookupTableProperty::Pointer kurt_lut_prop =
mitk::LookupTableProperty::New();
kurt_lut_prop->SetLookupTable( kurt_map_lut );
mitk::Image::Pointer dimage = mitk::Image::New();
dimage->InitializeByItk( filter->GetOutput(0) );
dimage->SetVolume( filter->GetOutput(0)->GetBufferPointer());
mitk::Image::Pointer kimage = mitk::Image::New();
kimage->InitializeByItk( filter->GetOutput(1) );
kimage->SetVolume( filter->GetOutput(1)->GetBufferPointer());
QString new_dname = "Kurtosis_DMap";
new_dname.append("_Method-"+m_Controls->m_KurtosisFitScale->currentText());
QString new_kname = "Kurtosis_KMap";
new_kname.append("_Method-"+m_Controls->m_KurtosisFitScale->currentText());
if( this->m_Controls->m_CheckKurtD->isChecked() )
{
mitk::DataNode::Pointer dnode = mitk::DataNode::New();
dnode->SetData( dimage );
dnode->SetName(new_dname.toLatin1());
dnode->SetProperty("LookupTable", kurt_lut_prop );
GetDataStorage()->Add(dnode, m_Controls->m_DwiBox->GetSelectedNode());
}
if( this->m_Controls->m_CheckKurtK->isChecked() )
{
mitk::DataNode::Pointer knode = mitk::DataNode::New();
knode->SetData( kimage );
knode->SetName(new_kname.toLatin1());
knode->SetProperty("LookupTable", kurt_lut_prop );
GetDataStorage()->Add(knode, m_Controls->m_DwiBox->GetSelectedNode());
}
}
else
{
FittIVIM(vecimg,
static_cast( img->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(),
static_cast(img->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(),
true,
dummy);
OutputToDatastorage(m_Controls->m_DwiBox->GetSelectedNode());
}
}
void QmitkIVIMView::OnKurtosisParamsChanged()
{
OnSliceChanged();
}
void QmitkIVIMView::OnSliceChanged()
{
- if(m_HoldUpdate)
+ if(m_HoldUpdate || !m_Visible)
return;
m_Controls->m_Warning->setVisible(false);
if(!m_Controls || m_Controls->m_DwiBox->GetSelectedNode().IsNull())
return;
m_Controls->m_VisualizeResultsWidget->setVisible(false);
m_Controls->m_KurtosisVisualizationWidget->setVisible(false);
mitk::Image::Pointer diffusionImg = dynamic_cast(m_Controls->m_DwiBox->GetSelectedNode()->GetData());
mitk::Image::Pointer maskImg = nullptr;
if (m_Controls->m_MaskBox->GetSelectedNode().IsNotNull())
maskImg = dynamic_cast(m_Controls->m_MaskBox->GetSelectedNode()->GetData());
if (!this->GetRenderWindowPart()) return;
VecImgType::Pointer vecimg = VecImgType::New();
mitk::CastToItkImage(diffusionImg, vecimg);
VecImgType::Pointer roiImage = VecImgType::New();
bool success = false;
if(maskImg.IsNull())
{
int roisize = 0;
if(m_Controls->m_MethodCombo->currentIndex() == 4)
roisize = 5;
mitk::Point3D pos = this->GetRenderWindowPart()->GetSelectedPosition();
VecImgType::IndexType crosspos;
diffusionImg->GetGeometry()->WorldToIndex(pos, crosspos);
if (!vecimg->GetLargestPossibleRegion().IsInside(crosspos))
{
m_Controls->m_Warning->setText(QString("Crosshair position not inside of selected diffusion weighted image. Reinit needed!"));
m_Controls->m_Warning->setVisible(true);
return;
}
else
m_Controls->m_Warning->setVisible(false);
VecImgType::IndexType index;
index[0] = crosspos[0] - roisize; index[0] = index[0] < 0 ? 0 : index[0];
index[1] = crosspos[1] - roisize; index[1] = index[1] < 0 ? 0 : index[1];
index[2] = crosspos[2] - roisize; index[2] = index[2] < 0 ? 0 : index[2];
VecImgType::SizeType size;
size[0] = roisize*2+1;
size[1] = roisize*2+1;
size[2] = roisize*2+1;
VecImgType::SizeType maxSize = vecimg->GetLargestPossibleRegion().GetSize();
size[0] = index[0]+size[0] > maxSize[0] ? maxSize[0]-index[0] : size[0];
size[1] = index[1]+size[1] > maxSize[1] ? maxSize[1]-index[1] : size[1];
size[2] = index[2]+size[2] > maxSize[2] ? maxSize[2]-index[2] : size[2];
VecImgType::RegionType region;
region.SetSize( size );
region.SetIndex( index );
vecimg->SetRequestedRegion( region );
VecImgType::IndexType newstart;
newstart.Fill(0);
VecImgType::RegionType newregion;
newregion.SetSize( size );
newregion.SetIndex( newstart );
roiImage->CopyInformation( vecimg );
roiImage->SetRegions( newregion );
roiImage->SetOrigin( pos );
roiImage->Allocate();
roiImage->SetPixel(newstart, vecimg->GetPixel(index));
if( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
success = FitKurtosis(roiImage,
static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(),
static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(),
newstart);
}
else
{
success = FittIVIM(roiImage,
static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(),
static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(),
false,
crosspos);
}
}
else
{
typedef itk::Image MaskImgType;
MaskImgType::Pointer maskItk;
CastToItkImage( maskImg, maskItk );
mitk::Point3D pos;
pos[0] = 0;
pos[1] = 0;
pos[2] = 0;
VecImgType::IndexType index;
index[0] = 0;
index[1] = 0;
index[2] = 0;
VecImgType::SizeType size;
size[0] = 1;
size[1] = 1;
size[2] = 1;
VecImgType::RegionType region;
region.SetSize( size );
region.SetIndex( index );
vecimg->SetRequestedRegion( region );
// iterators over output and input
itk::ImageRegionConstIteratorWithIndex
vecit(vecimg, vecimg->GetLargestPossibleRegion());
itk::VariableLengthVector avg(vecimg->GetVectorLength());
avg.Fill(0);
float numPixels = 0;
while ( ! vecit.IsAtEnd() )
{
VecImgType::PointType point;
vecimg->TransformIndexToPhysicalPoint(vecit.GetIndex(), point);
MaskImgType::IndexType index;
maskItk->TransformPhysicalPointToIndex(point, index);
if(maskItk->GetPixel(index) != 0)
{
avg += vecit.Get();
numPixels += 1.0;
}
// update iterators
++vecit;
}
avg /= numPixels;
m_Controls->m_Warning->setText(QString("Averaging ")+QString::number((int)numPixels)+QString(" voxels!"));
m_Controls->m_Warning->setVisible(true);
roiImage->CopyInformation( vecimg );
roiImage->SetRegions( region );
roiImage->SetOrigin( pos );
roiImage->Allocate();
roiImage->SetPixel(index, avg);
if( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
success = FitKurtosis(roiImage,
static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(),
static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(),
index);
}
else
{
success = FittIVIM(roiImage,
static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(),
static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(),
false,
index);
}
// do not update until selection changed, the values will remain the same as long as the mask is selected!
m_HoldUpdate = true;
}
vecimg->SetRegions( vecimg->GetLargestPossibleRegion() );
if (success)
{
// 0 - IVIM, 1 - Kurtosis
if( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
m_Controls->m_KurtosisVisualizationWidget->setVisible(true);
m_Controls->m_KurtosisVisualizationWidget->SetData(m_KurtosisSnap);
}
else
{
m_Controls->m_VisualizeResultsWidget->setVisible(true);
m_Controls->m_VisualizeResultsWidget->SetParameters(m_Snap);
}
}
}
bool QmitkIVIMView::FitKurtosis( itk::VectorImage *vecimg, DirContainerType *dirs, float bval, OutImgType::IndexType &crosspos )
{
KurtosisFilterType::Pointer filter = KurtosisFilterType::New();
itk::KurtosisFitConfiguration fit_config;
fit_config.omit_bzero = this->m_Controls->m_OmitBZeroCB->isChecked();
if( this->m_Controls->m_UseKurtosisBoundsCB->isChecked() )
{
fit_config.use_K_limits = true;
vnl_vector_fixed k_limits;
k_limits[0] = this->m_Controls->m_KurtosisRangeWidget->minimumValue();
k_limits[1] = this->m_Controls->m_KurtosisRangeWidget->maximumValue();
fit_config.K_limits = k_limits;
}
fit_config.fit_scale = static_cast(this->m_Controls->m_KurtosisFitScale->currentIndex() );
m_KurtosisSnap = filter->GetSnapshot( vecimg->GetPixel( crosspos ), dirs, bval, fit_config );
return true;
}
bool QmitkIVIMView::FittIVIM(itk::VectorImage* vecimg, DirContainerType* dirs, float bval, bool multivoxel, OutImgType::IndexType &crosspos)
{
IVIMFilterType::Pointer filter = IVIMFilterType::New();
filter->SetInput(vecimg);
filter->SetGradientDirections(dirs);
filter->SetBValue(bval);
switch(m_Controls->m_MethodCombo->currentIndex())
{
case 0:
filter->SetMethod(IVIMFilterType::IVIM_FIT_ALL);
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
break;
case 1:
filter->SetMethod(IVIMFilterType::IVIM_DSTAR_FIX);
filter->SetDStar(m_Controls->m_DStarLabel->text().toDouble());
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
break;
case 2:
filter->SetMethod(IVIMFilterType::IVIM_D_THEN_DSTAR);
filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble());
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked());
break;
case 3:
filter->SetMethod(IVIMFilterType::IVIM_LINEAR_D_THEN_F);
filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble());
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked());
break;
case 4:
filter->SetMethod(IVIMFilterType::IVIM_REGULARIZED);
filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble());
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
filter->SetNumberIterations(m_Controls->m_NumItsLabel->text().toInt());
filter->SetLambda(m_Controls->m_LambdaLabel->text().toDouble());
filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked());
break;
}
if(!multivoxel)
{
filter->SetFitDStar(true);
}
filter->SetNumberOfThreads(1);
filter->SetVerbose(false);
filter->SetCrossPosition(crosspos);
try{
filter->Update();
m_Snap = filter->GetSnapshot();
m_DStarMap = filter->GetOutput(2);
m_DMap = filter->GetOutput(1);
m_fMap = filter->GetOutput();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
m_Controls->m_Warning->setText(QString("IVIM fit not possible: ")+ex.GetDescription());
m_Controls->m_Warning->setVisible(true);
return false;
}
return true;
}
void QmitkIVIMView::OutputToDatastorage(mitk::DataNode::Pointer node)
{
if(m_Controls->m_CheckDStar->isChecked())
{
mitk::Image::Pointer dstarimage = mitk::Image::New();
dstarimage->InitializeByItk(m_DStarMap.GetPointer());
dstarimage->SetVolume(m_DStarMap->GetBufferPointer());
QString newname2 = ""; newname2 = newname2.append("IVIM_DStarMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText());
mitk::DataNode::Pointer node2=mitk::DataNode::New();
node2->SetData( dstarimage );
node2->SetName(newname2.toLatin1());
GetDataStorage()->Add(node2, node);
}
if(m_Controls->m_CheckD->isChecked())
{
mitk::Image::Pointer dimage = mitk::Image::New();
dimage->InitializeByItk(m_DMap.GetPointer());
dimage->SetVolume(m_DMap->GetBufferPointer());
QString newname1 = ""; newname1 = newname1.append("IVIM_DMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText());
mitk::DataNode::Pointer node1=mitk::DataNode::New();
node1->SetData( dimage );
node1->SetName(newname1.toLatin1());
GetDataStorage()->Add(node1, node);
}
if(m_Controls->m_Checkf->isChecked())
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(m_fMap.GetPointer());
image->SetVolume(m_fMap->GetBufferPointer());
QString newname0 = ""; newname0 = newname0.append("IVIM_fMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText());
mitk::DataNode::Pointer node3=mitk::DataNode::New();
node3->SetData( image );
node3->SetName(newname0.toLatin1());
GetDataStorage()->Add(node3, node);
}
this->GetRenderWindowPart()->RequestUpdate();
}
void QmitkIVIMView::ChooseMethod()
{
m_Controls->m_MethodCombo->setVisible(m_Controls->m_ChooseMethod->isChecked());
}
void QmitkIVIMView::ClipboardCurveButtonClicked()
{
// Kurtosis
if ( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
std::stringstream ss;
QString clipboard("Measurement Points\n");
ss << m_KurtosisSnap.bvalues << "\n" << m_KurtosisSnap.measurements << "\n\n";
ss << "Fitted Values ( D K [b_0] ) \n" << m_KurtosisSnap.m_D << " " << m_KurtosisSnap.m_K;
if( m_KurtosisSnap.m_fittedBZero )
ss << " " << m_KurtosisSnap.m_BzeroFit;
ss << "\n\n";
clipboard.append( QString( ss.str().c_str() ));
ss.str( std::string() );
ss.clear();
QApplication::clipboard()->setText(
clipboard, QClipboard::Clipboard );
}
else
{
QString clipboard("Measurement Points\n");
for ( unsigned int i=0; isetText(
clipboard, QClipboard::Clipboard );
}
}
void QmitkIVIMView::ClipboardStatisticsButtonClicked()
{
// Kurtosis
if ( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
QString clipboard( "D \t K \n" );
clipboard = clipboard.append( "%L1 \t %L2" )
.arg( m_KurtosisSnap.m_D, 0, 'f', 10 )
.arg( m_KurtosisSnap.m_K, 0, 'f', 10 ) ;
QApplication::clipboard()->setText(
clipboard, QClipboard::Clipboard );
}
else
{
QString clipboard( "f \t D \t D* \n" );
clipboard = clipboard.append( "%L1 \t %L2 \t %L3" )
.arg( m_Snap.currentF, 0, 'f', 10 )
.arg( m_Snap.currentD, 0, 'f', 10 )
.arg( m_Snap.currentDStar, 0, 'f', 10 ) ;
QApplication::clipboard()->setText(
clipboard, QClipboard::Clipboard );
}
}
void QmitkIVIMView::Activated()
{
m_Active = true;
}
void QmitkIVIMView::Deactivated()
{
m_Active = false;
}
void QmitkIVIMView::Visible()
{
m_Visible = true;
+
+ QList selection = GetDataManagerSelection();
+ berry::IWorkbenchPart::Pointer nullPart;
+ OnSelectionChanged(nullPart, selection);
}
void QmitkIVIMView::Hidden()
{
m_Visible = false;
}
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 64376688e7..5aed2247ee 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,921 +1,950 @@
/*===================================================================
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_Visible(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_ForestBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_ExclusionImageBox->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(isImagePredicate, dimensionPredicate) );
m_Controls->m_SeedImageBox->SetZeroEntryText("--");
m_Controls->m_MaskImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) );
m_Controls->m_MaskImageBox->SetZeroEntryText("--");
m_Controls->m_StopImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) );
m_Controls->m_StopImageBox->SetZeroEntryText("--");
m_Controls->m_TargetImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) );
m_Controls->m_TargetImageBox->SetZeroEntryText("--");
m_Controls->m_ExclusionImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) );
m_Controls->m_ExclusionImageBox->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_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_SeedImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) );
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_ExclusionImageBox, 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_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()) );
connect( m_Controls->m_LoopCheckBox, SIGNAL(valueChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_TrialsPerSeedBox, SIGNAL(valueChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_EpConstraintsBox, SIGNAL(currentIndexChanged(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);
m_InteractiveNode->SetFloatProperty("Fiber2DSliceThickness", m_Tracker->GetMinVoxelSize()/2);
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());
node->SetFloatProperty("Fiber2DSliceThickness", m_Tracker->GetMinVoxelSize()/2);
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));
m_InteractiveNode->SetFloatProperty("Fiber2DSliceThickness", m_Tracker->GetMinVoxelSize()/2);
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)
+ if (m_ThreadIsRunning || !m_Visible)
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()
{
UpdateGui();
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_SeedImageBox->setEnabled(!m_Controls->m_InteractiveBox->isChecked());
m_Controls->label_6->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;
-// }
+ 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::Activated()
+{
+
+}
+
+void QmitkStreamlineTrackingView::Deactivated()
+{
+
+}
+
+void QmitkStreamlineTrackingView::Visible()
+{
+ m_Visible = true;
+ QList selection = GetDataManagerSelection();
+ berry::IWorkbenchPart::Pointer nullPart;
+ OnSelectionChanged(nullPart, selection);
+}
+
+void QmitkStreamlineTrackingView::Hidden()
+{
+ m_Visible = false;
+ m_Controls->m_InteractiveBox->setChecked(false);
+ ToggleInteractive();
+}
+
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 )
{
+ if (!m_Visible)
+ return;
+
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("select in data-manager");
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(true);
m_Controls->mFaImageLabel->setEnabled(true);
m_Controls->m_OdfCutoffBox->setEnabled(false);
m_Controls->m_OdfCutoffLabel->setEnabled(false);
m_Controls->m_SharpenOdfsBox->setEnabled(false);
m_Controls->m_ForestBox->setVisible(false);
m_Controls->m_ForestLabel->setVisible(false);
m_Controls->commandLinkButton->setEnabled(false);
m_Controls->m_TrialsPerSeedBox->setEnabled(false);
m_Controls->m_TrialsPerSeedLabel->setEnabled(false);
m_Controls->m_TargetImageBox->setVisible(false);
m_Controls->m_TargetImageLabel->setVisible(false);
if (m_Controls->m_InteractiveBox->isChecked())
{
m_Controls->m_InteractiveSeedingFrame->setVisible(true);
m_Controls->m_StaticSeedingFrame->setVisible(false);
m_Controls->commandLinkButton_2->setVisible(false);
m_Controls->commandLinkButton->setVisible(false);
}
else
{
m_Controls->m_InteractiveSeedingFrame->setVisible(false);
m_Controls->m_StaticSeedingFrame->setVisible(true);
m_Controls->commandLinkButton_2->setVisible(m_ThreadIsRunning);
m_Controls->commandLinkButton->setVisible(!m_ThreadIsRunning);
}
if (m_Controls->m_EpConstraintsBox->currentIndex()>0)
{
m_Controls->m_TargetImageBox->setVisible(true);
m_Controls->m_TargetImageLabel->setVisible(true);
}
// trials per seed are only important for probabilistic tractography
if (m_Controls->m_ModeBox->currentIndex()==1)
{
m_Controls->m_TrialsPerSeedBox->setEnabled(true);
m_Controls->m_TrialsPerSeedLabel->setEnabled(true);
}
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->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);
}
else if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) )
{
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->setVisible(true);
m_Controls->m_ForestLabel->setVisible(true);
m_Controls->m_ScalarThresholdBox->setEnabled(false);
m_Controls->m_FaThresholdLabel->setEnabled(false);
}
}
}
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