diff --git a/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox b/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox
index 0ec050c887..7d38e016f0 100644
--- a/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox
+++ b/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox
@@ -1,32 +1,32 @@
/**
\page PluginListGeneralPage List of General Purpose Plugins
\li \subpage org_mitk_views_basicimageprocessing
\li \subpage org_mitk_views_datamanager
\li \subpage org_mitk_views_properties
\li \subpage org_mitk_editors_dicombrowser
- \li \subpage org_mitk_gui_qt_dicominspector
+ \li \subpage org_mitk_views_dicominspector
\li \subpage org_mitk_views_imagecropper
\li \subpage org_mitk_views_imagenavigator
\li \subpage org_blueberry_views_logview
\li \subpage org_mitk_gui_qt_matchpoint_algorithm_batch
\li \subpage org_mitk_views_matchpoint_algorithm_browser
\li \subpage org_mitk_views_matchpoint_algorithm_control
\li \subpage org_mitk_views_matchpoint_evaluator
\li \subpage org_mitk_views_matchpoint_framereg
\li \subpage org_mitk_views_matchpoint_manipulator
\li \subpage org_mitk_views_matchpoint_mapper
\li \subpage org_mitk_views_matchpoint_visualizer
\li \subpage org_mitk_gui_qt_measurementtoolbox
\li \subpage org_mitk_views_moviemaker
\li \subpage org_mitk_views_multilabelsegmentation
\li \subpage org_mitk_views_pointsetinteraction
- \li \subpage org_mitk_gui_qt_python
- \li \subpage org_mitk_gui_qt_remeshing
+ \li \subpage org_mitk_views_python
+ \li \subpage org_mitk_views_qt_remeshing
\li \subpage org_mitk_views_screenshotmaker
\li \subpage org_mitk_views_segmentation
\li \subpage org_mitk_gui_qt_flow_segmentation
- \li \subpage org_mitk_gui_qt_viewnavigator
+ \li \subpage org_mitk_views_viewnavigatorview
\li \subpage org_mitk_views_volumevisualization
*/
diff --git a/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox b/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox
index 133bb9f5ab..2bcc3ca505 100644
--- a/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox
+++ b/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox
@@ -1,84 +1,82 @@
/**
\page PluginListPage MITK Plugin Manuals
The plugins and bundles provide much of the extended functionality of MITK. Each encapsulates a solution to a problem and associated features. This way one can easily assemble the necessary capabilites for a workflow without adding a lot of bloat, by combining plugins as needed.
-
\subpage PluginListGeneralPage
- - \ref org_mitk_views_basicimageprocessing
- - \ref org_mitk_views_datamanager
- - \ref org_mitk_editors_dicombrowser
- - \ref org_mitk_gui_qt_dicominspector
- - \ref org_mitk_gui_qt_flowapplication
- - \ref org_mitk_views_imagecropper
- - \ref org_mitk_views_imagenavigator
- - \ref org_blueberry_views_logview
- - \ref org_mitk_views_matchpoint_algorithm_browser
- - \ref org_mitk_views_matchpoint_algorithm_control
- - \ref org_mitk_views_matchpoint_evaluator
- - \ref org_mitk_views_matchpoint_framereg
- - \ref org_mitk_views_matchpoint_manipulator
- - \ref org_mitk_views_matchpoint_mapper
- - \ref org_mitk_views_matchpoint_visualizer
- - \ref org_mitk_gui_qt_measurementtoolbox
- - \ref org_mitk_views_moviemaker
- - \ref org_mitk_views_multilabelsegmentation
- - \ref org_mitk_views_pointsetinteraction
- - \ref org_mitk_gui_qt_python
- - \ref org_mitk_gui_qt_remeshing
- - \ref org_mitk_views_screenshotmaker
- - \ref org_mitk_views_segmentation
- - \ref org_mitk_gui_qt_flow_segmentation
- - \ref org_mitk_gui_qt_viewnavigator
- - \ref org_mitk_views_volumevisualization
- - \ref org_mitk_views_properties
+ - \ref org_mitk_views_basicimageprocessing
+ - \ref org_mitk_views_datamanager
+ - \ref org_mitk_editors_dicombrowser
+ - \ref org_mitk_views_dicominspector
+ - \ref org_mitk_views_imagecropper
+ - \ref org_mitk_views_imagenavigator
+ - \ref org_blueberry_views_logview
+ - \ref org_mitk_views_matchpoint_algorithm_browser
+ - \ref org_mitk_views_matchpoint_algorithm_control
+ - \ref org_mitk_views_matchpoint_evaluator
+ - \ref org_mitk_views_matchpoint_framereg
+ - \ref org_mitk_views_matchpoint_manipulator
+ - \ref org_mitk_views_matchpoint_mapper
+ - \ref org_mitk_views_matchpoint_visualizer
+ - \ref org_mitk_views_measurement
+ - \ref org_mitk_views_imagestatistics
+ - \ref org_mitk_views_moviemaker
+ - \ref org_mitk_views_multilabelsegmentation
+ - \ref org_mitk_views_pointsetinteraction
+ - \ref org_mitk_views_python
+ - \ref org_mitk_views_remeshing
+ - \ref org_mitk_views_screenshotmaker
+ - \ref org_mitk_views_segmentation
+ - \ref org_mitk_views_viewnavigatorview
+ - \ref org_mitk_views_volumevisualization
+ - \ref org_mitk_views_properties
\subpage PluginListSpecificPage
- - \ref org_mitk_gui_qt_aicpregistration
- - \ref org_mitk_gui_qt_cest
- - \ref org_mitk_gui_qt_classificationsegmentation
- - \ref org_mitk_views_cmdlinemodules
- - \ref org_mitk_views_pharmacokinetics_concentration_mri
- - \ref org_mitk_views_pharmacokinetics_mri
- - \ref org_mitk_views_pharmacokinetics_pet
- - \ref org_mitk_gui_qt_eventrecorder
- - \ref org_mitk_gui_qt_examples
- - \ref org_mitk_gui_qt_geometrytools
- - \ref org_mitk_gui_qt_igtexample
- - \ref org_mitk_gui_qt_igtlplugin
- - \ref org_mitk_gui_qt_igttracking
- - \ref org_mitk_views_igttrackingsemiautomaticmeasurement
- - \ref org_mitk_views_imagestatistics
- - \ref org_mitk_gui_qt_lasercontrol
- - \ref org_mitk_views_fit_demo
- - \ref org_mitk_gui_qt_fit_genericfitting
- - \ref org_mitk_views_fit_inspector
- - \ref org_mitkexamplesopencv
- - \ref org_mitk_gui_qt_overlaymanager
- - \ref org_mitk_gui_qt_mitkphenotyping
- - \ref org_mitk_gui_qt_photoacoustics_pausmotioncompensation
- - \ref org_mitk_example_gui_pcaexample
- - \ref org_mitk_gui_qt_preprocessing_resampling
- - \ref org_mitk_views_pharmacokinetics_curvedescriptor
- - \ref org_mitk_views_photoacoustics_imageprocessing
- - \ref org_mitk_gui_qt_pharmacokinetics_simulation
- - \ref org_mitk_gui_qt_pointsetinteractionmultispectrum
- - \ref org_mitk_gui_qt_renderwindowmanager
- - \ref org_mitk_gui_qt_photoacoustics_spectralunmixing
- - \ref org_mitk_gui_qt_spectrocamrecorder
- - \ref org_surfacematerialeditor
- - \ref org_toftutorial
- - \ref org_blueberry_ui_qt_objectinspector
- - \ref org_mitk_gui_qt_ultrasound
- - \ref org_mitk_gui_qt_igt_app_echotrack
- - \ref org_mitk_gui_qt_xnat
+ - \ref org_mitk_gui_qt_flowapplication
+ - \ref org_mitk_views_flow_control
+ - \ref org_mitk_gui_qt_aicpregistration
+ - \ref org_mitk_gui_qt_cest
+ - \ref org_mitk_gui_qt_classificationsegmentation
+ - \ref org_mitk_views_cmdlinemodules
+ - \ref org_mitk_views_pharmacokinetics_concentration_mri
+ - \ref org_mitk_views_pharmacokinetics_mri
+ - \ref org_mitk_views_pharmacokinetics_pet
+ - \ref org_mitk_gui_qt_eventrecorder
+ - \ref org_mitk_gui_qt_examples
+ - \ref org_mitk_gui_qt_geometrytools
+ - \ref org_mitk_gui_qt_igtexample
+ - \ref org_mitk_gui_qt_igtlplugin
+ - \ref org_mitk_gui_qt_igttracking
+ - \ref org_mitk_views_igttrackingsemiautomaticmeasurement
+ - \ref org_mitk_gui_qt_lasercontrol
+ - \ref org_mitk_views_fit_demo
+ - \ref org_mitk_views_fit_genericfitting
+ - \ref org_mitk_views_fit_inspector
+ - \ref org_mitkexamplesopencv
+ - \ref org_mitk_gui_qt_overlaymanager
+ - \ref org_mitk_gui_qt_mitkphenotyping
+ - \ref org_mitk_gui_qt_photoacoustics_pausmotioncompensation
+ - \ref org_mitk_example_gui_pcaexample
+ - \ref org_mitk_gui_qt_preprocessing_resampling
+ - \ref org_mitk_views_pharmacokinetics_curvedescriptor
+ - \ref org_mitk_views_photoacoustics_imageprocessing
+ - \ref org_mitk_gui_qt_pharmacokinetics_simulation
+ - \ref org_mitk_gui_qt_pointsetinteractionmultispectrum
+ - \ref org_mitk_gui_qt_renderwindowmanager
+ - \ref org_mitk_gui_qt_photoacoustics_spectralunmixing
+ - \ref org_mitk_gui_qt_spectrocamrecorder
+ - \ref org_surfacematerialeditor
+ - \ref org_toftutorial
+ - \ref org_blueberry_ui_qt_objectinspector
+ - \ref org_mitk_gui_qt_ultrasound
+ - \ref org_mitk_gui_qt_igt_app_echotrack
+ - \ref org_mitk_gui_qt_xnat
-
*/
diff --git a/Documentation/Doxygen/2-UserManual/MITKPluginSpecificManualsList.dox b/Documentation/Doxygen/2-UserManual/MITKPluginSpecificManualsList.dox
index ebc2b9753a..c30e4932d9 100644
--- a/Documentation/Doxygen/2-UserManual/MITKPluginSpecificManualsList.dox
+++ b/Documentation/Doxygen/2-UserManual/MITKPluginSpecificManualsList.dox
@@ -1,45 +1,46 @@
/**
\page PluginListSpecificPage List of Application-specific Plugins
\li \subpage org_mitk_gui_qt_aicpregistration
\li \subpage org_mitk_gui_qt_cest
\li \subpage org_mitk_gui_qt_classificationsegmentation
\li \subpage org_mitk_gui_qt_flowapplication
\li \subpage org_mitk_views_cmdlinemodules
\li \subpage org_mitk_views_pharmacokinetics_concentration_mri
\li \subpage org_mitk_views_pharmacokinetics_mri
\li \subpage org_mitk_views_pharmacokinetics_pet
+ \li \subpage org_mitk_views_pharmacokinetics_simulation
\li \subpage org_mitk_gui_qt_eventrecorder
\li \subpage org_mitk_gui_qt_examples
\li \subpage org_mitk_gui_qt_geometrytools
\li \subpage org_mitk_gui_qt_igtexample
\li \subpage org_mitk_gui_qt_igtlplugin
\li \subpage org_mitk_gui_qt_igttracking
\li \subpage org_mitk_views_igttrackingsemiautomaticmeasurement
\li \subpage org_mitk_views_imagestatistics
\li \subpage org_mitk_gui_qt_lasercontrol
\li \subpage org_mitk_views_fit_demo
- \li \subpage org_mitk_gui_qt_fit_genericfitting
+ \li \subpage org_mitk_views_fit_genericfitting
\li \subpage org_mitk_views_fit_inspector
\li \subpage org_mitkexamplesopencv
\li \subpage org_mitk_gui_qt_overlaymanager
\li \subpage org_mitk_gui_qt_mitkphenotyping
\li \subpage org_mitk_gui_qt_photoacoustics_pausmotioncompensation
\li \subpage org_mitk_example_gui_pcaexample
\li \subpage org_mitk_gui_qt_preprocessing_resampling
\li \subpage org_mitk_views_pharmacokinetics_curvedescriptor
\li \subpage org_mitk_views_photoacoustics_imageprocessing
\li \subpage org_mitk_gui_qt_pharmacokinetics_simulation
\li \subpage org_mitk_gui_qt_pointsetinteractionmultispectrum
\li \subpage org_mitk_gui_qt_renderwindowmanager
\li \subpage org_mitk_gui_qt_photoacoustics_spectralunmixing
\li \subpage org_mitk_gui_qt_spectrocamrecorder
\li \subpage org_surfacematerialeditor
\li \subpage org_blueberry_ui_qt_objectinspector
\li \subpage org_toftutorial
\li \subpage org_mitk_gui_qt_ultrasound
\li \subpage org_mitk_gui_qt_igt_app_echotrack
\li \subpage org_mitk_gui_qt_xnat
-*/
\ No newline at end of file
+*/
diff --git a/Plugins/org.mitk.gui.qt.cest/src/internal/QmitkCESTNormalizeView.cpp b/Plugins/org.mitk.gui.qt.cest/src/internal/QmitkCESTNormalizeView.cpp
index 6ff6b43f96..7a9de6b733 100644
--- a/Plugins/org.mitk.gui.qt.cest/src/internal/QmitkCESTNormalizeView.cpp
+++ b/Plugins/org.mitk.gui.qt.cest/src/internal/QmitkCESTNormalizeView.cpp
@@ -1,110 +1,110 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "QmitkCESTNormalizeView.h"
#include
#include "mitkWorkbenchUtil.h"
#include "mitkNodePredicateAnd.h"
#include "mitkNodePredicateDataProperty.h"
#include "mitkNodePredicateDataType.h"
#include "QmitkDataStorageComboBoxWithSelectNone.h"
#include
#include "mitkCESTImageNormalizationFilter.h"
#include "mitkCESTPropertyHelper.h"
#include "mitkCESTImageDetectionHelper.h"
-const std::string QmitkCESTNormalizeView::VIEW_ID = "org.mitk.gui.qt.cest.normalize";
+const std::string QmitkCESTNormalizeView::VIEW_ID = "org.mitk.views.cest.normalization";
void QmitkCESTNormalizeView::SetFocus()
{
m_Controls.btnNormalize->setFocus();
}
void QmitkCESTNormalizeView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_Controls.btnNormalize->setEnabled(false);
m_Controls.comboCESTImage->SetPredicate(this->m_IsCESTImagePredicate);
m_Controls.comboCESTImage->SetDataStorage(this->GetDataStorage());
connect(m_Controls.btnNormalize, SIGNAL(clicked()), this, SLOT(OnNormalizeButtonClicked()));
connect(m_Controls.comboCESTImage, SIGNAL(OnSelectionChanged(const mitk::DataNode *)), this, SLOT(UpdateGUIControls()));
UpdateGUIControls();
}
void QmitkCESTNormalizeView::UpdateGUIControls()
{
m_Controls.btnNormalize->setEnabled(m_Controls.comboCESTImage->GetSelectedNode().IsNotNull());
}
void QmitkCESTNormalizeView::OnNormalizeButtonClicked()
{
auto selectedImageNode = m_Controls.comboCESTImage->GetSelectedNode();
if (!selectedImageNode)
{
MITK_ERROR << "Invalid system state. CEST selection is invalid. Selected node is null_ptr.";
return;
}
auto selectedImage = dynamic_cast(selectedImageNode->GetData());
if (!selectedImageNode)
{
MITK_ERROR << "Invalid system state. CEST selection is invalid. Selected node is not an image.";
return;
}
std::string offsetsStr = "";
bool hasOffsets = selectedImage->GetPropertyList()->GetStringProperty(mitk::CEST_PROPERTY_NAME_OFFSETS().c_str(), offsetsStr);
if (!hasOffsets)
{
QMessageBox::information(nullptr, "CEST normalization", "Selected image was missing CEST offset information.");
return;
}
if (!mitk::IsNotNormalizedCESTImage(selectedImage))
{
QMessageBox::information(nullptr, "CEST normalization", "Selected image already seems to be normalized.");
return;
}
if (selectedImage->GetDimension() == 4)
{
auto normalizationFilter = mitk::CESTImageNormalizationFilter::New();
normalizationFilter->SetInput(selectedImage);
normalizationFilter->Update();
auto resultImage = normalizationFilter->GetOutput();
mitk::DataNode::Pointer dataNode = mitk::DataNode::New();
dataNode->SetData(resultImage);
std::string normalizedName = selectedImageNode->GetName() + "_normalized";
dataNode->SetName(normalizedName);
this->GetDataStorage()->Add(dataNode);
}
}
QmitkCESTNormalizeView::QmitkCESTNormalizeView()
{
auto isImage = mitk::NodePredicateDataType::New("Image");
this->m_IsCESTImagePredicate = mitk::NodePredicateAnd::New(isImage, mitk::CreateAnyCESTImageNodePredicate()).GetPointer();
}
diff --git a/Plugins/org.mitk.gui.qt.cest/src/internal/QmitkCESTStatisticsView.cpp b/Plugins/org.mitk.gui.qt.cest/src/internal/QmitkCESTStatisticsView.cpp
index 2b8c2c96bf..5f913cf2a3 100644
--- a/Plugins/org.mitk.gui.qt.cest/src/internal/QmitkCESTStatisticsView.cpp
+++ b/Plugins/org.mitk.gui.qt.cest/src/internal/QmitkCESTStatisticsView.cpp
@@ -1,815 +1,815 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
// itk
#include "itksys/SystemTools.hxx"
#include
#include
// Blueberry
#include
#include
// Qmitk
#include "QmitkCESTStatisticsView.h"
// Qt
#include
#include
// qwt
#include
// mitk
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// boost
#include
#include
// stl
#include
#include
#include
#include
#include
#include
namespace
{
template
void GetSortPermutation(std::vector &out,
const std::vector &determiningVector,
Compare compare = std::less())
{
out.resize(determiningVector.size());
std::iota(out.begin(), out.end(), 0);
std::sort(out.begin(), out.end(), [&](unsigned i, unsigned j) {
return compare(determiningVector[i], determiningVector[j]);
});
}
template
void ApplyPermutation(const std::vector &order, std::vector &vectorToSort)
{
assert(order.size() == vectorToSort.size());
std::vector tempVector(vectorToSort.size());
for (unsigned i = 0; i < vectorToSort.size(); i++)
{
tempVector[i] = vectorToSort[order[i]];
}
vectorToSort = tempVector;
}
template
void ApplyPermutation(const std::vector &order,
std::vector ¤tVector,
std::vector &... remainingVectors)
{
ApplyPermutation(order, currentVector);
ApplyPermutation(order, remainingVectors...);
}
template
void SortVectors(const std::vector &orderDeterminingVector,
Compare comparison,
std::vector &... vectorsToBeSorted)
{
std::vector order;
GetSortPermutation(order, orderDeterminingVector, comparison);
ApplyPermutation(order, vectorsToBeSorted...);
}
} // namespace
-const std::string QmitkCESTStatisticsView::VIEW_ID = "org.mitk.views.ceststatistics";
+const std::string QmitkCESTStatisticsView::VIEW_ID = "org.mitk.views.cest.statistics";
QmitkCESTStatisticsView::QmitkCESTStatisticsView(QObject * /*parent*/, const char * /*name*/)
{
this->m_CalculatorJob = new QmitkImageStatisticsCalculationJob();
m_currentSelectedPosition.Fill(0.0);
m_currentSelectedTimePoint = 0.;
m_CrosshairPointSet = mitk::PointSet::New();
}
QmitkCESTStatisticsView::~QmitkCESTStatisticsView()
{
while (this->m_CalculatorJob->isRunning()) // wait until thread has finished
{
itksys::SystemTools::Delay(100);
}
delete this->m_CalculatorJob;
}
void QmitkCESTStatisticsView::SetFocus()
{
m_Controls.threeDimToFourDimPushButton->setFocus();
}
void QmitkCESTStatisticsView::CreateQtPartControl(QWidget *parent)
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls.setupUi(parent);
connect(
m_Controls.threeDimToFourDimPushButton, SIGNAL(clicked()), this, SLOT(OnThreeDimToFourDimPushButtonClicked()));
connect((QObject *)this->m_CalculatorJob,
SIGNAL(finished()),
this,
SLOT(OnThreadedStatisticsCalculationEnds()),
Qt::QueuedConnection);
connect((QObject *)(this->m_Controls.fixedRangeCheckBox),
SIGNAL(toggled(bool)),
(QObject *)this,
SLOT(OnFixedRangeCheckBoxToggled(bool)));
connect((QObject *)(this->m_Controls.fixedRangeLowerDoubleSpinBox),
SIGNAL(editingFinished()),
(QObject *)this,
SLOT(OnFixedRangeDoubleSpinBoxChanged()));
connect((QObject *)(this->m_Controls.fixedRangeUpperDoubleSpinBox),
SIGNAL(editingFinished()),
(QObject *)this,
SLOT(OnFixedRangeDoubleSpinBoxChanged()));
m_Controls.threeDimToFourDimPushButton->setEnabled(false);
m_Controls.widget_statistics->SetDataStorage(this->GetDataStorage());
this->m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
}
void QmitkCESTStatisticsView::RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart)
{
this->m_SliceChangeListener.RenderWindowPartActivated(renderWindowPart);
}
void QmitkCESTStatisticsView::RenderWindowPartDeactivated(mitk::IRenderWindowPart *renderWindowPart)
{
this->m_SliceChangeListener.RenderWindowPartDeactivated(renderWindowPart);
}
void QmitkCESTStatisticsView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/,
const QList &nodes)
{
if (nodes.empty())
{
std::stringstream message;
message << "Please select an image.";
m_Controls.labelWarning->setText(message.str().c_str());
m_Controls.labelWarning->show();
this->Clear();
return;
}
// iterate all selected objects
bool atLeastOneWasCESTImage = false;
foreach (mitk::DataNode::Pointer node, nodes)
{
if (node.IsNull())
{
continue;
}
if (dynamic_cast(node->GetData()) != nullptr)
{
m_Controls.labelWarning->setVisible(false);
bool zSpectrumSet = SetZSpectrum(dynamic_cast(
node->GetData()->GetProperty(mitk::CEST_PROPERTY_NAME_OFFSETS().c_str()).GetPointer()));
atLeastOneWasCESTImage = atLeastOneWasCESTImage || zSpectrumSet;
if (zSpectrumSet)
{
m_ZImage = dynamic_cast(node->GetData());
m_Controls.widget_statistics->SetImageNodes({node.GetPointer()});
}
else
{
m_MaskImage = dynamic_cast(node->GetData());
m_Controls.widget_statistics->SetMaskNodes({node.GetPointer()});
}
}
if (dynamic_cast(node->GetData()) != nullptr)
{
m_MaskPlanarFigure = dynamic_cast(node->GetData());
m_Controls.widget_statistics->SetMaskNodes({node.GetPointer()});
}
if (dynamic_cast(node->GetData()) != nullptr)
{
m_PointSet = dynamic_cast(node->GetData());
}
}
// We only want to offer normalization or timestep copying if one object is selected
if (nodes.size() == 1)
{
if (dynamic_cast(nodes.front()->GetData()))
{
m_Controls.threeDimToFourDimPushButton->setDisabled(atLeastOneWasCESTImage);
}
else
{
m_Controls.threeDimToFourDimPushButton->setEnabled(false);
std::stringstream message;
message << "The selected node is not an image.";
m_Controls.labelWarning->setText(message.str().c_str());
m_Controls.labelWarning->show();
}
this->Clear();
return;
}
// we always need a mask, either image or planar figure as well as an image for further processing
if (nodes.size() != 2)
{
this->Clear();
return;
}
m_Controls.threeDimToFourDimPushButton->setEnabled(false);
if (!atLeastOneWasCESTImage)
{
std::stringstream message;
message << "None of the selected data nodes contains required CEST meta information";
m_Controls.labelWarning->setText(message.str().c_str());
m_Controls.labelWarning->show();
this->Clear();
return;
}
bool bothAreImages = (m_ZImage.GetPointer() != nullptr) && (m_MaskImage.GetPointer() != nullptr);
if (bothAreImages)
{
bool geometriesMatch =
mitk::Equal(*(m_ZImage->GetTimeGeometry()), *(m_MaskImage->GetTimeGeometry()), mitk::eps, false);
if (!geometriesMatch)
{
std::stringstream message;
message << "The selected images have different geometries.";
m_Controls.labelWarning->setText(message.str().c_str());
m_Controls.labelWarning->show();
this->Clear();
return;
}
}
if (!this->DataSanityCheck())
{
this->Clear();
return;
}
if (m_PointSet.IsNull())
{
// initialize thread and trigger it
this->m_CalculatorJob->SetIgnoreZeroValueVoxel(false);
this->m_CalculatorJob->Initialize(m_ZImage.GetPointer(), m_MaskImage.GetPointer(), m_MaskPlanarFigure.GetPointer());
std::stringstream message;
message << "Calculating statistics...";
m_Controls.labelWarning->setText(message.str().c_str());
m_Controls.labelWarning->show();
try
{
// Compute statistics
this->m_CalculatorJob->start();
}
catch (const mitk::Exception &e)
{
std::stringstream message;
message << "" << e.GetDescription() << "";
m_Controls.labelWarning->setText(message.str().c_str());
m_Controls.labelWarning->show();
}
catch (const std::runtime_error &e)
{
// In case of exception, print error message on GUI
std::stringstream message;
message << "" << e.what() << "";
m_Controls.labelWarning->setText(message.str().c_str());
m_Controls.labelWarning->show();
}
catch (const std::exception &e)
{
MITK_ERROR << "Caught exception: " << e.what();
// In case of exception, print error message on GUI
std::stringstream message;
message << "Error! Unequal Dimensions of Image and Segmentation. No recompute possible ";
m_Controls.labelWarning->setText(message.str().c_str());
m_Controls.labelWarning->show();
}
while (this->m_CalculatorJob->isRunning()) // wait until thread has finished
{
itksys::SystemTools::Delay(100);
}
}
if (m_PointSet.IsNotNull())
{
if (m_ZImage->GetDimension() == 4)
{
AccessFixedDimensionByItk(m_ZImage, PlotPointSet, 4);
}
else
{
MITK_WARN << "Expecting a 4D image.";
}
}
}
void QmitkCESTStatisticsView::OnThreadedStatisticsCalculationEnds()
{
this->m_Controls.m_DataViewWidget->SetAxisTitle(QwtPlot::Axis::xBottom, "delta w");
this->m_Controls.m_DataViewWidget->SetAxisTitle(QwtPlot::Axis::yLeft, "z");
if (this->m_CalculatorJob->GetStatisticsUpdateSuccessFlag())
{
auto statistics = this->m_CalculatorJob->GetStatisticsData();
std::string statisticsNodeName = "CEST_statistics";
auto statisticsNode = mitk::CreateImageStatisticsNode(statistics, statisticsNodeName);
auto imageRule = mitk::StatisticsToImageRelationRule::New();
imageRule->Connect(statistics, m_CalculatorJob->GetStatisticsImage());
if (m_CalculatorJob->GetMaskImage())
{
auto maskRule = mitk::StatisticsToMaskRelationRule::New();
maskRule->Connect(statistics, m_CalculatorJob->GetMaskImage());
}
else if (m_CalculatorJob->GetPlanarFigure())
{
auto planarFigureRule = mitk::StatisticsToMaskRelationRule::New();
planarFigureRule->Connect(statistics, m_CalculatorJob->GetPlanarFigure());
}
this->GetDataStorage()->Add(statisticsNode);
QmitkPlotWidget::DataVector::size_type numberOfSpectra = this->m_zSpectrum.size();
QmitkPlotWidget::DataVector means(numberOfSpectra);
QmitkPlotWidget::DataVector stdevs(numberOfSpectra);
for (unsigned int index = 0; index < numberOfSpectra; ++index)
{
means[index] =
statistics->GetStatisticsForTimeStep(index).GetValueConverted(
mitk::ImageStatisticsConstants::MEAN());
stdevs[index] =
statistics->GetStatisticsForTimeStep(index).GetValueConverted(
mitk::ImageStatisticsConstants::STANDARDDEVIATION());
}
QmitkPlotWidget::DataVector xValues = this->m_zSpectrum;
RemoveMZeros(xValues, means, stdevs);
::SortVectors(xValues, std::less(), xValues, means, stdevs);
unsigned int curveId = this->m_Controls.m_DataViewWidget->InsertCurve("Spectrum");
this->m_Controls.m_DataViewWidget->SetCurveData(curveId, xValues, means, stdevs, stdevs);
this->m_Controls.m_DataViewWidget->SetErrorPen(curveId, QPen(Qt::blue));
QwtSymbol *blueSymbol = new QwtSymbol(QwtSymbol::Rect, QColor(Qt::blue), QColor(Qt::blue), QSize(8, 8));
this->m_Controls.m_DataViewWidget->SetCurveSymbol(curveId, blueSymbol);
this->m_Controls.m_DataViewWidget->SetLegendAttribute(curveId, QwtPlotCurve::LegendShowSymbol);
QwtLegend *legend = new QwtLegend();
legend->setFrameShape(QFrame::Box);
legend->setFrameShadow(QFrame::Sunken);
legend->setLineWidth(1);
this->m_Controls.m_DataViewWidget->SetLegend(legend, QwtPlot::BottomLegend);
m_Controls.m_DataViewWidget->GetPlot()
->axisScaleEngine(QwtPlot::Axis::xBottom)
->setAttributes(QwtScaleEngine::Inverted);
this->m_Controls.m_DataViewWidget->Replot();
m_Controls.labelWarning->setVisible(false);
m_Controls.m_StatisticsGroupBox->setEnabled(true);
m_Controls.m_StatisticsGroupBox->setEnabled(true);
if (this->m_Controls.fixedRangeCheckBox->isChecked())
{
this->m_Controls.m_DataViewWidget->GetPlot()->setAxisAutoScale(2, false);
this->m_Controls.m_DataViewWidget->GetPlot()->setAxisScale(
2,
this->m_Controls.fixedRangeLowerDoubleSpinBox->value(),
this->m_Controls.fixedRangeUpperDoubleSpinBox->value());
}
else
{
this->m_Controls.m_DataViewWidget->GetPlot()->setAxisAutoScale(2, true);
}
}
else
{
m_Controls.labelWarning->setText(m_CalculatorJob->GetLastErrorMessage().c_str());
m_Controls.labelWarning->setVisible(true);
this->Clear();
}
}
void QmitkCESTStatisticsView::OnFixedRangeDoubleSpinBoxChanged()
{
if (this->m_Controls.fixedRangeCheckBox->isChecked())
{
this->m_Controls.m_DataViewWidget->GetPlot()->setAxisAutoScale(2, false);
this->m_Controls.m_DataViewWidget->GetPlot()->setAxisScale(2,
this->m_Controls.fixedRangeLowerDoubleSpinBox->value(),
this->m_Controls.fixedRangeUpperDoubleSpinBox->value());
}
this->m_Controls.m_DataViewWidget->Replot();
}
template
void QmitkCESTStatisticsView::PlotPointSet(itk::Image *image)
{
this->m_Controls.m_DataViewWidget->SetAxisTitle(QwtPlot::Axis::xBottom, "delta w");
this->m_Controls.m_DataViewWidget->SetAxisTitle(QwtPlot::Axis::yLeft, "z");
QmitkPlotWidget::DataVector::size_type numberOfSpectra = this->m_zSpectrum.size();
mitk::PointSet::Pointer internalPointset;
if (m_PointSet.IsNotNull())
{
internalPointset = m_PointSet;
}
else
{
internalPointset = m_CrosshairPointSet;
}
if (internalPointset.IsNull())
{
return;
}
if (!this->DataSanityCheck())
{
m_Controls.labelWarning->setText("Data can not be plotted, internally inconsistent.");
m_Controls.labelWarning->show();
return;
}
auto maxIndex = internalPointset->GetMaxId().Index();
for (std::size_t number = 0; number < maxIndex + 1; ++number)
{
mitk::PointSet::PointType point;
if (!internalPointset->GetPointIfExists(number, &point))
{
continue;
}
if (!this->m_ZImage->GetGeometry()->IsInside(point))
{
continue;
}
itk::Index<3> itkIndex;
this->m_ZImage->GetGeometry()->WorldToIndex(point, itkIndex);
itk::Index itkIndexTime;
itkIndexTime[0] = itkIndex[0];
itkIndexTime[1] = itkIndex[1];
itkIndexTime[2] = itkIndex[2];
QmitkPlotWidget::DataVector values(numberOfSpectra);
for (std::size_t step = 0; step < numberOfSpectra; ++step)
{
if (VImageDimension == 4)
{
itkIndexTime[3] = step;
}
values[step] = image->GetPixel(itkIndexTime);
}
std::stringstream name;
name << "Point " << number;
// Qcolor enums go from 0 to 19, but 19 is transparent and 0,1 are for bitmaps
// 3 is white and thus not visible
QColor color(static_cast(number % 17 + 4));
QmitkPlotWidget::DataVector xValues = this->m_zSpectrum;
RemoveMZeros(xValues, values);
::SortVectors(xValues, std::less(), xValues, values);
unsigned int curveId = this->m_Controls.m_DataViewWidget->InsertCurve(name.str().c_str());
this->m_Controls.m_DataViewWidget->SetCurveData(curveId, xValues, values);
this->m_Controls.m_DataViewWidget->SetCurvePen(curveId, QPen(color));
QwtSymbol *symbol = new QwtSymbol(QwtSymbol::Rect, color, color, QSize(8, 8));
this->m_Controls.m_DataViewWidget->SetCurveSymbol(curveId, symbol);
this->m_Controls.m_DataViewWidget->SetLegendAttribute(curveId, QwtPlotCurve::LegendShowSymbol);
}
if (this->m_Controls.fixedRangeCheckBox->isChecked())
{
this->m_Controls.m_DataViewWidget->GetPlot()->setAxisAutoScale(2, false);
this->m_Controls.m_DataViewWidget->GetPlot()->setAxisScale(2,
this->m_Controls.fixedRangeLowerDoubleSpinBox->value(),
this->m_Controls.fixedRangeUpperDoubleSpinBox->value());
}
else
{
this->m_Controls.m_DataViewWidget->GetPlot()->setAxisAutoScale(2, true);
}
QwtLegend *legend = new QwtLegend();
legend->setFrameShape(QFrame::Box);
legend->setFrameShadow(QFrame::Sunken);
legend->setLineWidth(1);
this->m_Controls.m_DataViewWidget->SetLegend(legend, QwtPlot::BottomLegend);
m_Controls.m_DataViewWidget->GetPlot()
->axisScaleEngine(QwtPlot::Axis::xBottom)
->setAttributes(QwtScaleEngine::Inverted);
this->m_Controls.m_DataViewWidget->Replot();
m_Controls.labelWarning->setVisible(false);
}
void QmitkCESTStatisticsView::OnFixedRangeCheckBoxToggled(bool state)
{
this->m_Controls.fixedRangeLowerDoubleSpinBox->setEnabled(state);
this->m_Controls.fixedRangeUpperDoubleSpinBox->setEnabled(state);
}
void QmitkCESTStatisticsView::RemoveMZeros(QmitkPlotWidget::DataVector &xValues, QmitkPlotWidget::DataVector &yValues)
{
QmitkPlotWidget::DataVector tempX;
QmitkPlotWidget::DataVector tempY;
for (std::size_t index = 0; index < xValues.size(); ++index)
{
if ((xValues.at(index) < -299) || (xValues.at(index)) > 299)
{
// do not include
}
else
{
tempX.push_back(xValues.at(index));
tempY.push_back(yValues.at(index));
}
}
xValues = tempX;
yValues = tempY;
}
void QmitkCESTStatisticsView::RemoveMZeros(QmitkPlotWidget::DataVector &xValues,
QmitkPlotWidget::DataVector &yValues,
QmitkPlotWidget::DataVector &stdDevs)
{
QmitkPlotWidget::DataVector tempX;
QmitkPlotWidget::DataVector tempY;
QmitkPlotWidget::DataVector tempDevs;
for (std::size_t index = 0; index < xValues.size(); ++index)
{
if ((xValues.at(index) < -299) || (xValues.at(index)) > 299)
{
// do not include
}
else
{
tempX.push_back(xValues.at(index));
tempY.push_back(yValues.at(index));
tempDevs.push_back(stdDevs.at(index));
}
}
xValues = tempX;
yValues = tempY;
stdDevs = tempDevs;
}
void QmitkCESTStatisticsView::OnThreeDimToFourDimPushButtonClicked()
{
QList nodes = this->GetDataManagerSelection();
if (nodes.empty())
return;
mitk::DataNode *node = nodes.front();
if (!node)
{
// Nothing selected. Inform the user and return
QMessageBox::information(nullptr, "CEST View", "Please load and select an image before starting image processing.");
return;
}
// here we have a valid mitk::DataNode
// a node itself is not very useful, we need its data item (the image)
mitk::BaseData *data = node->GetData();
if (data)
{
// test if this data item is an image or not (could also be a surface or something totally different)
mitk::Image *image = dynamic_cast(data);
if (image)
{
if (image->GetDimension() == 4)
{
AccessFixedDimensionByItk(image, CopyTimesteps, 4);
}
this->Clear();
}
}
}
template
void QmitkCESTStatisticsView::CopyTimesteps(itk::Image *image)
{
typedef itk::Image ImageType;
// typedef itk::PasteImageFilter PasteImageFilterType;
unsigned int numberOfTimesteps = image->GetLargestPossibleRegion().GetSize(3);
typename ImageType::RegionType sourceRegion = image->GetLargestPossibleRegion();
sourceRegion.SetSize(3, 1);
typename ImageType::RegionType targetRegion = image->GetLargestPossibleRegion();
targetRegion.SetSize(3, 1);
for (unsigned int timestep = 1; timestep < numberOfTimesteps; ++timestep)
{
targetRegion.SetIndex(3, timestep);
itk::ImageRegionConstIterator sourceIterator(image, sourceRegion);
itk::ImageRegionIterator targetIterator(image, targetRegion);
while (!sourceIterator.IsAtEnd())
{
targetIterator.Set(sourceIterator.Get());
++sourceIterator;
++targetIterator;
}
}
}
bool QmitkCESTStatisticsView::SetZSpectrum(mitk::StringProperty *zSpectrumProperty)
{
if (zSpectrumProperty == nullptr)
{
return false;
}
mitk::LocaleSwitch localeSwitch("C");
std::string zSpectrumString = zSpectrumProperty->GetValueAsString();
std::istringstream iss(zSpectrumString);
std::vector zSpectra;
std::copy(
std::istream_iterator(iss), std::istream_iterator(), std::back_inserter(zSpectra));
m_zSpectrum.clear();
m_zSpectrum.resize(0);
for (auto const &spectrumString : zSpectra)
{
m_zSpectrum.push_back(std::stod(spectrumString));
}
return (m_zSpectrum.size() > 0);
}
bool QmitkCESTStatisticsView::DataSanityCheck()
{
QmitkPlotWidget::DataVector::size_type numberOfSpectra = m_zSpectrum.size();
// if we do not have a spectrum, the data can not be processed
if (numberOfSpectra == 0)
{
return false;
}
// if we do not have CEST image data, the data can not be processed
if (m_ZImage.IsNull())
{
return false;
}
// if the CEST image data and the meta information do not match, the data can not be processed
if (numberOfSpectra != m_ZImage->GetTimeSteps())
{
MITK_INFO << "CEST meta information and number of volumes does not match.";
return false;
}
// if we have neither a mask image, a point set nor a mask planar figure, we can not do statistics
// statistics on the whole image would not make sense
if (m_MaskImage.IsNull() && m_MaskPlanarFigure.IsNull() && m_PointSet.IsNull() && m_CrosshairPointSet->IsEmpty())
{
return false;
}
// if we have a mask image and a mask planar figure, we can not do statistics
// we do not know which one to use
if (m_MaskImage.IsNotNull() && m_MaskPlanarFigure.IsNotNull())
{
return false;
}
return true;
}
void QmitkCESTStatisticsView::Clear()
{
this->m_zSpectrum.clear();
this->m_zSpectrum.resize(0);
this->m_ZImage = nullptr;
this->m_MaskImage = nullptr;
this->m_MaskPlanarFigure = nullptr;
this->m_PointSet = nullptr;
this->m_Controls.m_DataViewWidget->Clear();
this->m_Controls.m_StatisticsGroupBox->setEnabled(false);
this->m_Controls.widget_statistics->SetImageNodes({});
this->m_Controls.widget_statistics->SetMaskNodes({});
}
void QmitkCESTStatisticsView::OnSliceChanged()
{
mitk::Point3D currentSelectedPosition = this->GetRenderWindowPart()->GetSelectedPosition(nullptr);
mitk::TimePointType currentSelectedTimePoint = this->GetRenderWindowPart()->GetSelectedTimePoint();
if (m_currentSelectedPosition != currentSelectedPosition || currentSelectedTimePoint != currentSelectedTimePoint)
//|| m_selectedNodeTime > m_currentPositionTime)
{
// the current position has been changed or the selected node has been changed since the last position validation ->
// check position
m_currentSelectedPosition = currentSelectedPosition;
m_currentSelectedTimePoint = currentSelectedTimePoint;
m_currentPositionTime.Modified();
m_CrosshairPointSet->Clear();
m_CrosshairPointSet->SetPoint(0, m_currentSelectedPosition);
QList nodes = this->GetDataManagerSelection();
if (nodes.empty() || nodes.size() > 1)
return;
mitk::DataNode *node = nodes.front();
if (!node)
{
return;
}
if (dynamic_cast(node->GetData()) != nullptr)
{
m_Controls.labelWarning->setVisible(false);
bool zSpectrumSet = SetZSpectrum(dynamic_cast(
node->GetData()->GetProperty(mitk::CEST_PROPERTY_NAME_OFFSETS().c_str()).GetPointer()));
if (zSpectrumSet)
{
m_ZImage = dynamic_cast(node->GetData());
}
else
{
return;
}
}
else
{
return;
}
this->m_Controls.m_DataViewWidget->Clear();
AccessFixedDimensionByItk(m_ZImage, PlotPointSet, 4);
}
}
diff --git a/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesViewConstants.cpp b/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesViewConstants.cpp
index 8b2532e75e..6b63d6c35e 100644
--- a/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesViewConstants.cpp
+++ b/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesViewConstants.cpp
@@ -1,31 +1,31 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "CommandLineModulesViewConstants.h"
-const QString CommandLineModulesViewConstants::VIEW_ID = "org.mitk.gui.qt.cmdlinemodules";
+const QString CommandLineModulesViewConstants::VIEW_ID = "org.mitk.views.cmdlinemodules";
const QString CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME = "temporary directory";
const QString CommandLineModulesViewConstants::OUTPUT_DIRECTORY_NODE_NAME = "output directory";
const QString CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME = "module directories";
const QString CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME = "module files";
const QString CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME = "debug output";
const QString CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR = "load from application dir";
const QString CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR = "load from home dir";
const QString CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR = "load from current dir";
const QString CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR = "load from auto-load dir";
const QString CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR_CLI_MODULES = "load from application dir/cli-modules";
const QString CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR_CLI_MODULES = "load from home dir/cli-modules";
const QString CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR_CLI_MODULES = "load from current dir/cli-modules";
const QString CommandLineModulesViewConstants::XML_VALIDATION_MODE = "xml validation mode";
const QString CommandLineModulesViewConstants::XML_TIMEOUT_SECS = "xml time-out";
const QString CommandLineModulesViewConstants::MAX_CONCURRENT = "max concurrent processes";
const QString CommandLineModulesViewConstants::SHOW_ADVANCED_WIDGETS_NAME = "show advanced widgets";
diff --git a/Plugins/org.mitk.gui.qt.dicominspector/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.dicominspector/documentation/UserManual/Manual.dox
index f45e70d5e1..e1305a43b8 100644
--- a/Plugins/org.mitk.gui.qt.dicominspector/documentation/UserManual/Manual.dox
+++ b/Plugins/org.mitk.gui.qt.dicominspector/documentation/UserManual/Manual.dox
@@ -1,12 +1,12 @@
/**
-\page org_mitk_gui_qt_dicominspector The DICOM Inspector
+\page org_mitk_views_dicominspector The DICOM Inspector
\imageMacro{ "inspector.png", "Icon of DICOM Inspector", 2}
This is a simple view that displays all DICOM properties of the data of the currently selected node.
DICOM properties are all properties that have a property name starting with "DICOM".
The plugin will show the dicom values corresponding to the currently selected time point and z slice.
E.G. the value of "acquesition time" will change with changing the time step of 3d+t image or the value
of "slice position" will change with changing the current z slice of the image.
*/
diff --git a/Plugins/org.mitk.gui.qt.dicominspector/plugin.xml b/Plugins/org.mitk.gui.qt.dicominspector/plugin.xml
index dde8b4b9d1..8da249251b 100644
--- a/Plugins/org.mitk.gui.qt.dicominspector/plugin.xml
+++ b/Plugins/org.mitk.gui.qt.dicominspector/plugin.xml
@@ -1,10 +1,10 @@
-
diff --git a/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.cpp b/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.cpp
index 8400fd4978..531f020f2b 100644
--- a/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.cpp
+++ b/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.cpp
@@ -1,376 +1,376 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
// Blueberry
#include
#include
#include
// mitk
#include
#include
#include
// Qt
#include
#include
#include
#include
#include "QmitkDicomInspectorView.h"
-const std::string QmitkDicomInspectorView::VIEW_ID = "org.mitk.gui.qt.dicominspector";
+const std::string QmitkDicomInspectorView::VIEW_ID = "org.mitk.views.dicominspector";
QmitkDicomInspectorView::ObserverInfo::ObserverInfo(mitk::SliceNavigationController* controller,
int observerTag, const std::string& renderWindowName, mitk::IRenderWindowPart* part) : controller(controller), observerTag(observerTag),
renderWindowName(renderWindowName), renderWindowPart(part)
{
}
QmitkDicomInspectorView::QmitkDicomInspectorView()
: m_RenderWindowPart(nullptr)
, m_PendingSliceChangedEvent(false)
, m_SelectedNode(nullptr)
, m_SelectedTimePoint(0.)
, m_CurrentSelectedZSlice(0)
{
m_SelectedPosition.Fill(0.0);
}
QmitkDicomInspectorView::~QmitkDicomInspectorView()
{
this->RemoveAllObservers();
}
void QmitkDicomInspectorView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
if (m_RenderWindowPart != renderWindowPart)
{
m_RenderWindowPart = renderWindowPart;
if (!InitObservers())
{
QMessageBox::information(nullptr, "Error", "Unable to set up the event observers. The " \
"plot will not be triggered on changing the crosshair, " \
"position or time step.");
}
}
}
void QmitkDicomInspectorView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart)
{
m_RenderWindowPart = nullptr;
this->RemoveAllObservers(renderWindowPart);
}
void QmitkDicomInspectorView::CreateQtPartControl(QWidget* parent)
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls.setupUi(parent);
m_Controls.singleSlot->SetDataStorage(GetDataStorage());
m_Controls.singleSlot->SetSelectionIsOptional(true);
m_Controls.singleSlot->SetEmptyInfo(QString("Please select a data node"));
m_Controls.singleSlot->SetPopUpTitel(QString("Select data node"));
m_SelectionServiceConnector = std::make_unique();
SetAsSelectionListener(true);
m_Controls.timePointValueLabel->setText(QString(""));
m_Controls.sliceNumberValueLabel->setText(QString(""));
connect(m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged,
this, &QmitkDicomInspectorView::OnCurrentSelectionChanged);
mitk::IRenderWindowPart* renderWindowPart = GetRenderWindowPart();
RenderWindowPartActivated(renderWindowPart);
}
bool QmitkDicomInspectorView::InitObservers()
{
bool result = true;
typedef QHash WindowMapType;
WindowMapType windowMap = m_RenderWindowPart->GetQmitkRenderWindows();
auto i = windowMap.begin();
while (i != windowMap.end())
{
mitk::SliceNavigationController* sliceNavController =
i.value()->GetSliceNavigationController();
if (sliceNavController)
{
auto cmdSliceEvent = itk::SimpleMemberCommand::New();
cmdSliceEvent->SetCallbackFunction(this, &QmitkDicomInspectorView::OnSliceChanged);
int tag = sliceNavController->AddObserver(
mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), cmdSliceEvent);
m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
i.key().toStdString(), m_RenderWindowPart)));
auto cmdTimeEvent = itk::SimpleMemberCommand::New();
cmdTimeEvent->SetCallbackFunction(this, &QmitkDicomInspectorView::OnSliceChanged);
tag = sliceNavController->AddObserver(
mitk::SliceNavigationController::GeometryTimeEvent(nullptr, 0), cmdTimeEvent);
m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
i.key().toStdString(), m_RenderWindowPart)));
auto cmdDelEvent = itk::MemberCommand::New();
cmdDelEvent->SetCallbackFunction(this, &QmitkDicomInspectorView::OnSliceNavigationControllerDeleted);
tag = sliceNavController->AddObserver(itk::DeleteEvent(), cmdDelEvent);
m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
i.key().toStdString(), m_RenderWindowPart)));
}
++i;
result = result && sliceNavController;
}
return result;
}
void QmitkDicomInspectorView::RemoveObservers(const mitk::SliceNavigationController* deletedSlicer)
{
std::pair obsRange =
m_ObserverMap.equal_range(deletedSlicer);
for (ObserverMapType::const_iterator pos = obsRange.first; pos != obsRange.second; ++pos)
{
pos->second.controller->RemoveObserver(pos->second.observerTag);
}
m_ObserverMap.erase(deletedSlicer);
}
void QmitkDicomInspectorView::RemoveAllObservers(mitk::IRenderWindowPart* deletedPart)
{
for (ObserverMapType::const_iterator pos = m_ObserverMap.begin(); pos != m_ObserverMap.end();)
{
ObserverMapType::const_iterator delPos = pos++;
if (nullptr == deletedPart || deletedPart == delPos->second.renderWindowPart)
{
delPos->second.controller->RemoveObserver(delPos->second.observerTag);
m_ObserverMap.erase(delPos);
}
}
}
void QmitkDicomInspectorView::OnCurrentSelectionChanged(QList nodes)
{
if (nodes.empty() || nodes.front().IsNull())
{
m_SelectedNode = nullptr;
m_SelectedData = nullptr;
UpdateData();
return;
}
if (nodes.front() != this->m_SelectedNode)
{
// node is selected, create DICOM tag table
m_SelectedNode = nodes.front();
m_SelectedData = this->m_SelectedNode->GetData();
m_SelectedNodeTime.Modified();
UpdateData();
OnSliceChangedDelayed();
}
}
void QmitkDicomInspectorView::OnSliceChanged()
{
// Taken from QmitkStdMultiWidget::HandleCrosshairPositionEvent().
// Since there are always 3 events arriving (one for each render window) every time the slice
// or time changes, the slot OnSliceChangedDelayed is triggered - and only if it hasn't been
// triggered yet - so it is only executed once for every slice/time change.
if (!m_PendingSliceChangedEvent)
{
m_PendingSliceChangedEvent = true;
QTimer::singleShot(0, this, SLOT(OnSliceChangedDelayed()));
}
}
void QmitkDicomInspectorView::OnSliceNavigationControllerDeleted(const itk::Object* sender, const itk::EventObject& /*e*/)
{
auto sendingSlicer = dynamic_cast(sender);
this->RemoveObservers(sendingSlicer);
}
void QmitkDicomInspectorView::ValidateAndSetCurrentPosition()
{
mitk::Point3D currentSelectedPosition = GetRenderWindowPart()->GetSelectedPosition(nullptr);
const auto currentSelectedTimePoint = GetRenderWindowPart()->GetSelectedTimePoint();
if (m_SelectedPosition != currentSelectedPosition
|| m_SelectedTimePoint != currentSelectedTimePoint
|| m_SelectedNodeTime > m_CurrentPositionTime)
{
// the current position has been changed, the selected node has been changed since
// the last position validation or the current time position has been changed -> check position
m_SelectedPosition = currentSelectedPosition;
m_SelectedTimePoint = currentSelectedTimePoint;
m_CurrentPositionTime.Modified();
m_ValidSelectedPosition = false;
if (m_SelectedData.IsNull())
{
return;
}
mitk::BaseGeometry::Pointer geometry = m_SelectedData->GetTimeGeometry()->GetGeometryForTimePoint(m_SelectedTimePoint);
// check for invalid time step
if (geometry.IsNull())
{
geometry = m_SelectedData->GetTimeGeometry()->GetGeometryForTimeStep(0);
}
if (geometry.IsNull())
{
return;
}
m_ValidSelectedPosition = geometry->IsInside(m_SelectedPosition);
itk::Index<3> index;
geometry->WorldToIndex(m_SelectedPosition, index);
m_CurrentSelectedZSlice = index[2];
}
}
void QmitkDicomInspectorView::OnSliceChangedDelayed()
{
m_PendingSliceChangedEvent = false;
ValidateAndSetCurrentPosition();
m_Controls.tableTags->setEnabled(m_ValidSelectedPosition);
if (m_SelectedNode.IsNotNull())
{
RenderTable();
}
}
void QmitkDicomInspectorView::RenderTable()
{
assert(nullptr != m_RenderWindowPart);
const auto timeStep = (m_SelectedData.IsNull()) ? 0 : m_SelectedData->GetTimeGeometry()->TimePointToTimeStep(m_SelectedTimePoint);
unsigned int rowIndex = 0;
for (const auto& element : m_Tags)
{
QTableWidgetItem* newItem = new QTableWidgetItem(QString::fromStdString(
element.second.prop->GetValue(timeStep, m_CurrentSelectedZSlice, true, true)));
m_Controls.tableTags->setItem(rowIndex, 3, newItem);
++rowIndex;
}
UpdateLabels();
}
void QmitkDicomInspectorView::UpdateData()
{
QStringList headers;
m_Controls.tableTags->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
m_Tags.clear();
if (m_SelectedData.IsNotNull())
{
for (const auto& element : *(m_SelectedData->GetPropertyList()->GetMap()))
{
if (element.first.find("DICOM") == 0)
{
std::istringstream stream(element.first);
std::string token;
std::getline(stream, token, '.'); //drop the DICOM suffix
std::getline(stream, token, '.'); //group id
unsigned long dcmgroup = std::stoul(token, nullptr, 16);
std::getline(stream, token, '.'); //element id
unsigned long dcmelement = std::stoul(token, nullptr, 16);
TagInfo info(mitk::DICOMTag(dcmgroup, dcmelement), dynamic_cast(element.second.GetPointer()));
m_Tags.insert(std::make_pair(element.first, info));
}
}
}
m_Controls.tableTags->setRowCount(m_Tags.size());
unsigned int rowIndex = 0;
for (const auto& element : m_Tags)
{
QTableWidgetItem* newItem = new QTableWidgetItem(QString::number(element.second.tag.GetGroup(), 16));
m_Controls.tableTags->setItem(rowIndex, 0, newItem);
newItem = new QTableWidgetItem(QString::number(element.second.tag.GetElement(), 16));
m_Controls.tableTags->setItem(rowIndex, 1, newItem);
newItem = new QTableWidgetItem(QString::fromStdString(element.second.tag.GetName()));
m_Controls.tableTags->setItem(rowIndex, 2, newItem);
newItem = new QTableWidgetItem(QString::fromStdString(element.second.prop->GetValue()));
m_Controls.tableTags->setItem(rowIndex, 3, newItem);
++rowIndex;
}
UpdateLabels();
}
void QmitkDicomInspectorView::UpdateLabels()
{
if (m_SelectedData.IsNull())
{
m_Controls.timePointValueLabel->setText(QString(""));
m_Controls.sliceNumberValueLabel->setText(QString(""));
}
else
{
const auto timeStep = m_SelectedData->GetTimeGeometry()->TimePointToTimeStep(m_SelectedTimePoint);
if (m_ValidSelectedPosition)
{
m_Controls.timePointValueLabel->setText(QString::number(timeStep) + QStringLiteral("(")+ QString::number(m_SelectedTimePoint/1000.) + QStringLiteral(" [s])"));
m_Controls.sliceNumberValueLabel->setText(QString::number(m_CurrentSelectedZSlice));
}
else
{
m_Controls.timePointValueLabel->setText(QString("outside data geometry"));
m_Controls.sliceNumberValueLabel->setText(QString("outside data geometry"));
}
}
}
void QmitkDicomInspectorView::SetAsSelectionListener(bool checked)
{
if (checked)
{
m_SelectionServiceConnector->AddPostSelectionListener(GetSite()->GetWorkbenchWindow()->GetSelectionService());
connect(m_SelectionServiceConnector.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged,
m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetCurrentSelection);
}
else
{
m_SelectionServiceConnector->RemovePostSelectionListener();
disconnect(m_SelectionServiceConnector.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged,
m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetCurrentSelection);
}
}
diff --git a/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.cpp b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.cpp
index 899fbaee1a..321d361ff4 100644
--- a/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.cpp
+++ b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.cpp
@@ -1,254 +1,254 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "FitGeneratorDemoView.h"
#include
#include
#include
#include
#include "mitkWorkbenchUtil.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
-const std::string FitGeneratorDemoView::VIEW_ID = "org.mitk.gui.qt.fit.demo";
+const std::string FitGeneratorDemoView::VIEW_ID = "org.mitk.views.fit.demo";
typedef itk::Image FrameITKImageType;
typedef itk::Image DynamicITKImageType;
void FitGeneratorDemoView::SetFocus()
{
m_Controls.btnModelling->setFocus();
}
void FitGeneratorDemoView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_Controls.btnModelling->setEnabled(false);
connect(m_Controls.btnModelling, SIGNAL(clicked()), this, SLOT(OnModellingButtonClicked()));
connect(m_Controls.btnGenerateTestData, SIGNAL(clicked()), this,
SLOT(OnGenerateTestDataButtonClicked()));
m_Controls.leFitName->setText(tr("demo"));
}
void FitGeneratorDemoView::OnModellingButtonClicked()
{
Generate();
}
void FitGeneratorDemoView::OnGenerateTestDataButtonClicked()
{
mitk::Image::Pointer testImage = mitk::GenerateDynamicTestImageMITK();
mitk::DataNode::Pointer testNode = mitk::DataNode::New();
testNode->SetData(testImage);
testNode->SetName("LinearModel_4DTestImage");
this->GetDataStorage()->Add(testNode);
}
void FitGeneratorDemoView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/,
const QList& /*nodes*/)
{
QList dataNodes = this->GetDataManagerSelection();
m_selectedNode = nullptr;
m_selectedImage = nullptr;
m_selectedMaskNode = nullptr;
m_selectedMask = nullptr;
if (!dataNodes.empty())
{
m_selectedNode = dataNodes[0];
mitk::Image* selectedImage = dynamic_cast(m_selectedNode->GetData());
if (selectedImage && selectedImage->GetDimension(3) > 1)
{
m_selectedImage = selectedImage;
}
if (dataNodes.size() > 1)
{
m_selectedMaskNode = dataNodes[1];
mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage");
mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image");
mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary);
mitk::NodePredicateOr::Pointer maskPredicate = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet);
mitk::Image* selectedMask = dynamic_cast(this->m_selectedMaskNode->GetData());
if (selectedMask && maskPredicate->CheckNode(m_selectedMaskNode))
{
m_selectedMask = selectedMask;
if (this->m_selectedMask->GetTimeSteps() > 1)
{
MITK_INFO <<
"Selected mask has multiple timesteps. Only use first timestep to mask model fit. Mask name: " <<
m_selectedMaskNode->GetName() ;
mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New();
maskedImageTimeSelector->SetInput(this->m_selectedMask);
maskedImageTimeSelector->SetTimeNr(0);
maskedImageTimeSelector->UpdateLargestPossibleRegion();
this->m_selectedMask = maskedImageTimeSelector->GetOutput();
}
}
}
}
if (m_selectedImage)
{
m_Controls.lTimeseries->setText((m_selectedNode->GetName()).c_str());
}
else
{
if (m_selectedNode.IsNull())
{
m_Controls.lTimeseries->setText("None");
}
else
{
m_Controls.lTimeseries->setText("Error. Selected node #1 is no 4D image!");
}
}
if (m_selectedMask)
{
m_Controls.lMask->setText((m_selectedMaskNode->GetName()).c_str());
}
else
{
if (m_selectedMaskNode.IsNull())
{
m_Controls.lMask->setText("None");
}
else
{
m_Controls.lMask->setText("Error. Selected node #2 is no mask!");
}
}
m_Controls.btnModelling->setEnabled(m_selectedImage.IsNotNull());
}
void FitGeneratorDemoView::Generate()
{
mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator =
mitk::PixelBasedParameterFitImageGenerator::New();
//Model configuration (static parameters) can be done now
//Specify fitting strategy and evaluation parameters
mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor =
mitk::LevenbergMarquardtModelFitFunctor::New();
mitk::SumOfSquaredDifferencesFitCostFunction::Pointer evaluation =
mitk::SumOfSquaredDifferencesFitCostFunction::New();
fitFunctor->RegisterEvaluationParameter("sum_diff^2", evaluation);
//Parametrize fit generator
mitk::LinearModelParameterizer::Pointer parameterizer = mitk::LinearModelParameterizer::New();
fitGenerator->SetModelParameterizer(parameterizer);
fitGenerator->SetDynamicImage(m_selectedImage);
fitGenerator->SetFitFunctor(fitFunctor);
if (m_selectedMask.IsNotNull())
{
fitGenerator->SetMask(m_selectedMask);
}
mitk::modelFit::ModelFitInfo::Pointer fitSession =
mitk::modelFit::CreateFitInfoFromModelParameterizer(parameterizer, m_selectedNode->GetData(),
mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), m_Controls.leFitName->text().toStdString());
/////////////////////////
//create job and put it into the thread pool
ParameterFitBackgroundJob* pJob = new ParameterFitBackgroundJob(fitGenerator, fitSession, m_selectedNode);
pJob->setAutoDelete(true);
connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnJobError(QString)));
connect(pJob, SIGNAL(Finished()), this, SLOT(OnJobFinished()));
connect(pJob, SIGNAL(ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType,
const ParameterFitBackgroundJob*)), this,
SLOT(OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType,
const ParameterFitBackgroundJob*)), Qt::BlockingQueuedConnection);
connect(pJob, SIGNAL(JobProgress(double)), this, SLOT(OnJobProgress(double)));
connect(pJob, SIGNAL(JobStatusChanged(QString)), this, SLOT(OnJobStatusChanged(QString)));
QThreadPool* threadPool = QThreadPool::globalInstance();
threadPool->start(pJob);
}
FitGeneratorDemoView::FitGeneratorDemoView()
{
m_selectedImage = nullptr;
m_selectedNode = nullptr;
}
void FitGeneratorDemoView::OnJobFinished()
{
this->m_Controls.textEdit->append(QString("Fitting finished"));
};
void FitGeneratorDemoView::OnJobError(QString err)
{
MITK_ERROR << err.toStdString().c_str();
m_Controls.textEdit->append(QString("") + err + QString(""));
};
void FitGeneratorDemoView::OnJobResultsAreAvailable(
mitk::modelFit::ModelFitResultNodeVectorType results, const ParameterFitBackgroundJob* pJob)
{
//Store the resulting parameter fit image via convenience helper function in data storage
//(handles the correct generation of the nodes and their properties)
mitk::modelFit::StoreResultsInDataStorage(this->GetDataStorage(), results, pJob->GetParentNode());
};
void FitGeneratorDemoView::OnJobProgress(double progress)
{
QString report = QString("Progress. ") + QString::number(progress);
this->m_Controls.textEdit->append(report);
};
void FitGeneratorDemoView::OnJobStatusChanged(QString info)
{
this->m_Controls.textEdit->append(info);
}
diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/UserManual/Manual.dox
index 063fdf0dd9..c90a30a4de 100644
--- a/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/UserManual/Manual.dox
+++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/UserManual/Manual.dox
@@ -1,16 +1,16 @@
/**
-\page org_mitk_gui_qt_fit_genericfitting The Model Fit Generic Fitting View
+\page org_mitk_views_fit_genericfitting The Model Fit Generic Fitting View
\imageMacro{fit_generic_doc.svg,"Icon of the Generic Fitting View",3.0}
\tableofcontents
\section FIT_GENERIC_Introduction Introduction
This plug-in offers a generic fitting component for time resolved image data.
\section FIT_GENERIC_Contact Contact information
This plug-in is being developed by the SIDT group (Software development for Integrated Diagnostics
and Therapy) at the German Cancer Research Center (DKFZ). If you have any questions, need support,
find a bug or have a feature request, feel free to contact us at www.mitk.org.
*/
diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/plugin.xml b/Plugins/org.mitk.gui.qt.fit.genericfitting/plugin.xml
index c77936d932..258904cf04 100644
--- a/Plugins/org.mitk.gui.qt.fit.genericfitting/plugin.xml
+++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/plugin.xml
@@ -1,12 +1,12 @@
-
diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp
index 3a8dfb2d14..44a8d83a62 100644
--- a/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp
+++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp
@@ -1,639 +1,639 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "GenericDataFittingView.h"
#include "mitkWorkbenchUtil.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// Includes for image casting between ITK and MITK
#include
#include "mitkImageCast.h"
#include "mitkITKImageImport.h"
#include
#include
#include
-const std::string GenericDataFittingView::VIEW_ID = "org.mitk.gui.qt.fit.genericfitting";
+const std::string GenericDataFittingView::VIEW_ID = "org.mitk.views.fit.genericfitting";
void GenericDataFittingView::SetFocus()
{
m_Controls.btnModelling->setFocus();
}
void GenericDataFittingView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_Controls.btnModelling->setEnabled(false);
this->InitModelComboBox();
connect(m_Controls.btnModelling, SIGNAL(clicked()), this, SLOT(OnModellingButtonClicked()));
connect(m_Controls.comboModel, SIGNAL(currentIndexChanged(int)), this, SLOT(OnModellSet(int)));
connect(m_Controls.radioPixelBased, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls()));
//Gerneric setting
m_Controls.groupGeneric->hide();
m_Controls.labelFormulaInfo->hide();
connect(m_Controls.editFormula, SIGNAL(textChanged(const QString&)), this,
SLOT(UpdateGUIControls()));
connect(m_Controls.checkFormulaInfo, SIGNAL(toggled(bool)), m_Controls.labelFormulaInfo,
SLOT(setVisible(bool)));
connect(m_Controls.nrOfParams, SIGNAL(valueChanged(int)), this, SLOT(OnNrOfParamsChanged()));
//Model fit configuration
m_Controls.groupBox_FitConfiguration->hide();
m_Controls.checkBox_Constraints->setEnabled(false);
m_Controls.constraintManager->setEnabled(false);
m_Controls.initialValuesManager->setEnabled(false);
connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)), this,
SLOT(UpdateGUIControls()));
connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), this,
SLOT(UpdateGUIControls()));
connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)),
m_Controls.initialValuesManager,
SLOT(setEnabled(bool)));
connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager,
SLOT(setEnabled(bool)));
connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager,
SLOT(setVisible(bool)));
UpdateGUIControls();
}
void GenericDataFittingView::UpdateGUIControls()
{
m_Controls.lineFitName->setPlaceholderText(QString::fromStdString(this->GetDefaultFitName()));
m_Controls.lineFitName->setEnabled(!m_FittingInProgress);
m_Controls.checkBox_Constraints->setEnabled(m_modelConstraints.IsNotNull());
bool isGenericFactory = dynamic_cast
(m_selectedModelFactory.GetPointer()) != nullptr;
m_Controls.groupGeneric->setVisible(isGenericFactory);
m_Controls.groupBox_FitConfiguration->setVisible(m_selectedModelFactory);
m_Controls.groupBox->setEnabled(!m_FittingInProgress);
m_Controls.comboModel->setEnabled(!m_FittingInProgress);
m_Controls.groupGeneric->setEnabled(!m_FittingInProgress);
m_Controls.groupBox_FitConfiguration->setEnabled(!m_FittingInProgress);
m_Controls.radioROIbased->setEnabled(m_selectedMask.IsNotNull());
m_Controls.btnModelling->setEnabled(m_selectedImage.IsNotNull()
&& m_selectedModelFactory.IsNotNull() && !m_FittingInProgress && CheckModelSettings());
}
std::string GenericDataFittingView::GetFitName() const
{
std::string fitName = m_Controls.lineFitName->text().toStdString();
if (fitName.empty())
{
fitName = m_Controls.lineFitName->placeholderText().toStdString();
}
return fitName;
}
std::string GenericDataFittingView::GetDefaultFitName() const
{
std::string defaultName = "undefined model";
if (this->m_selectedModelFactory.IsNotNull())
{
defaultName = this->m_selectedModelFactory->GetClassID();
}
if (this->m_Controls.radioPixelBased->isChecked())
{
defaultName += "_pixel";
}
else
{
defaultName += "_roi";
}
return defaultName;
}
void GenericDataFittingView::OnNrOfParamsChanged()
{
PrepareFitConfiguration();
UpdateGUIControls();
}
void GenericDataFittingView::OnModellSet(int index)
{
m_selectedModelFactory = nullptr;
if (index > 0)
{
if (static_cast(index) <= m_FactoryStack.size() )
{
m_selectedModelFactory = m_FactoryStack[index - 1];
}
else
{
MITK_WARN << "Invalid model index. Index outside of the factory stack. Factory stack size: "<< m_FactoryStack.size() << "; invalid index: "<< index;
}
}
UpdateGUIControls();
}
bool GenericDataFittingView::IsGenericParamFactorySelected() const
{
return dynamic_cast
(m_selectedModelFactory.GetPointer()) != nullptr;
}
void GenericDataFittingView::PrepareFitConfiguration()
{
if (m_selectedModelFactory)
{
mitk::ModelBase::ParameterNamesType paramNames = m_selectedModelFactory->GetParameterNames();
unsigned int nrOfPools = this->m_Controls.nrOfParams->value();
//init values
if (this->IsGenericParamFactorySelected())
{
mitk::modelFit::ModelFitInfo::Pointer fitInfo = mitk::modelFit::ModelFitInfo::New();
fitInfo->staticParamMap.Add(mitk::GenericParamModel::NAME_STATIC_PARAMETER_number, { static_cast(nrOfPools) });
auto parameterizer = m_selectedModelFactory->CreateParameterizer(fitInfo);
paramNames = parameterizer->GetParameterNames();
m_Controls.initialValuesManager->setInitialValues(paramNames, parameterizer->GetDefaultInitialParameterization());
}
else
{
m_Controls.initialValuesManager->setInitialValues(paramNames, this->m_selectedModelFactory->GetDefaultInitialParameterization());
}
//constraints
this->m_modelConstraints = dynamic_cast
(m_selectedModelFactory->CreateDefaultConstraints().GetPointer());
if (this->m_modelConstraints.IsNull())
{
this->m_modelConstraints = mitk::SimpleBarrierConstraintChecker::New();
}
m_Controls.constraintManager->setChecker(this->m_modelConstraints, paramNames);
}
};
void GenericDataFittingView::OnModellingButtonClicked()
{
//check if all static parameters set
if (m_selectedModelFactory.IsNotNull() && CheckModelSettings())
{
mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr;
mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr;
bool isLinearFactory = dynamic_cast
(m_selectedModelFactory.GetPointer()) != nullptr;
bool isGenericFactory = dynamic_cast
(m_selectedModelFactory.GetPointer()) != nullptr;
bool isT2DecayFactory = dynamic_cast
(m_selectedModelFactory.GetPointer()) != nullptr;
if (isLinearFactory)
{
if (this->m_Controls.radioPixelBased->isChecked())
{
GenerateModelFit_PixelBased(fitSession, generator);
}
else
{
GenerateModelFit_ROIBased(fitSession, generator);
}
}
else if (isGenericFactory)
{
if (this->m_Controls.radioPixelBased->isChecked())
{
GenerateModelFit_PixelBased(fitSession, generator);
}
else
{
GenerateModelFit_ROIBased(fitSession, generator);
}
}
else if (isT2DecayFactory)
{
if (this->m_Controls.radioPixelBased->isChecked())
{
GenerateModelFit_PixelBased(fitSession, generator);
}
else
{
GenerateModelFit_ROIBased(fitSession, generator);
}
}
//add other models with else if
if (generator.IsNotNull() && fitSession.IsNotNull())
{
m_FittingInProgress = true;
UpdateGUIControls();
DoFit(fitSession, generator);
}
else
{
QMessageBox box;
box.setText("Fitting error!");
box.setInformativeText("Could not establish fitting job. Error when setting ab generator, model parameterizer or session info.");
box.setStandardButtons(QMessageBox::Ok);
box.setDefaultButton(QMessageBox::Ok);
box.setIcon(QMessageBox::Warning);
box.exec();
}
}
else
{
QMessageBox box;
box.setText("Static parameters for model are not set!");
box.setInformativeText("Some static parameters, that are needed for calculation are not set and equal to zero. Modeling not possible");
box.setStandardButtons(QMessageBox::Ok);
box.setDefaultButton(QMessageBox::Ok);
box.setIcon(QMessageBox::Warning);
box.exec();
}
}
void GenericDataFittingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/,
const QList& selectedNodes)
{
m_selectedNode = nullptr;
m_selectedImage = nullptr;
m_selectedMaskNode = nullptr;
m_selectedMask = nullptr;
m_Controls.masklabel->setText("No (valid) mask selected.");
m_Controls.timeserieslabel->setText("No (valid) series selected.");
QList nodes = selectedNodes;
mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage");
mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image");
mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary);
mitk::NodePredicateOr::Pointer maskPredicate = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet);
if (nodes.size() > 0 && isImage->CheckNode(nodes.front()))
{
this->m_selectedNode = nodes.front();
this->m_selectedImage = dynamic_cast(this->m_selectedNode->GetData());
m_Controls.timeserieslabel->setText((this->m_selectedNode->GetName()).c_str());
nodes.pop_front();
}
if (nodes.size() > 0 && maskPredicate->CheckNode(nodes.front()))
{
this->m_selectedMaskNode = nodes.front();
this->m_selectedMask = dynamic_cast(this->m_selectedMaskNode->GetData());
if (this->m_selectedMask->GetTimeSteps() > 1)
{
MITK_INFO <<
"Selected mask has multiple timesteps. Only use first timestep to mask model fit. Mask name: " <<
m_selectedMaskNode->GetName();
mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New();
maskedImageTimeSelector->SetInput(this->m_selectedMask);
maskedImageTimeSelector->SetTimeNr(0);
maskedImageTimeSelector->UpdateLargestPossibleRegion();
this->m_selectedMask = maskedImageTimeSelector->GetOutput();
}
m_Controls.masklabel->setText((this->m_selectedMaskNode->GetName()).c_str());
}
if (m_selectedMask.IsNull())
{
this->m_Controls.radioPixelBased->setChecked(true);
}
UpdateGUIControls();
}
bool GenericDataFittingView::CheckModelSettings() const
{
bool ok = true;
//check wether any model is set at all. Otherwise exit with false
if (m_selectedModelFactory.IsNotNull())
{
bool isGenericFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != nullptr;
if (isGenericFactory)
{
ok = !m_Controls.editFormula->text().isEmpty();
}
}
else
{
ok = false;
}
return ok;
}
void GenericDataFittingView::ConfigureInitialParametersOfParameterizer(mitk::ModelParameterizerBase*
parameterizer) const
{
if (m_Controls.radioButton_StartParameters->isChecked())
{
//use user defined initial parameters
mitk::ValueBasedParameterizationDelegate::Pointer paramDelegate =
mitk::ValueBasedParameterizationDelegate::New();
paramDelegate->SetInitialParameterization(m_Controls.initialValuesManager->getInitialValues());
parameterizer->SetInitialParameterizationDelegate(paramDelegate);
}
mitk::GenericParamModelParameterizer* genericParameterizer =
dynamic_cast(parameterizer);
if (genericParameterizer)
{
genericParameterizer->SetFunctionString(m_Controls.editFormula->text().toStdString());
}
}
template
void GenericDataFittingView::GenerateModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer&
modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
{
mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator =
mitk::PixelBasedParameterFitImageGenerator::New();
typename TParameterizer::Pointer modelParameterizer =
TParameterizer::New();
auto genericParameterizer = dynamic_cast(modelParameterizer.GetPointer());
if (genericParameterizer)
{
genericParameterizer->SetNumberOfParameters(this->m_Controls.nrOfParams->value());
}
this->ConfigureInitialParametersOfParameterizer(modelParameterizer);
//Specify fitting strategy and criterion parameters
mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer);
//Parametrize fit generator
fitGenerator->SetModelParameterizer(modelParameterizer);
std::string roiUID = "";
if (m_selectedMask.IsNotNull())
{
fitGenerator->SetMask(m_selectedMask);
roiUID = m_selectedMask->GetUID();
}
fitGenerator->SetDynamicImage(this->m_selectedImage);
fitGenerator->SetFitFunctor(fitFunctor);
generator = fitGenerator.GetPointer();
//Create model info
modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer,
m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), this->GetFitName(),
roiUID);
}
template
void GenericDataFittingView::GenerateModelFit_ROIBased(
mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo,
mitk::ParameterFitImageGeneratorBase::Pointer& generator)
{
mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator =
mitk::ROIBasedParameterFitImageGenerator::New();
typename TParameterizer::Pointer modelParameterizer =
TParameterizer::New();
auto genericParameterizer = dynamic_cast(modelParameterizer.GetPointer());
if (genericParameterizer)
{
genericParameterizer->SetNumberOfParameters(this->m_Controls.nrOfParams->value());
}
this->ConfigureInitialParametersOfParameterizer(modelParameterizer);
//Compute ROI signal
mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator =
mitk::MaskedDynamicImageStatisticsGenerator::New();
signalGenerator->SetMask(m_selectedMask);
signalGenerator->SetDynamicImage(m_selectedImage);
signalGenerator->Generate();
mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean();
//Specify fitting strategy and criterion parameters
mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer);
//Parametrize fit generator
fitGenerator->SetModelParameterizer(modelParameterizer);
fitGenerator->SetMask(m_selectedMask);
fitGenerator->SetFitFunctor(fitFunctor);
fitGenerator->SetSignal(roiSignal);
fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(m_selectedImage));
generator = fitGenerator.GetPointer();
std::string roiUID = this->m_selectedMask->GetUID();
//Create model info
modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer,
m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), this->GetFitName(),
roiUID);
mitk::ScalarListLookupTable::ValueType infoSignal;
for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos =
roiSignal.begin(); pos != roiSignal.end(); ++pos)
{
infoSignal.push_back(*pos);
}
modelFitInfo->inputData.SetTableValue("ROI", infoSignal);
}
void GenericDataFittingView::DoFit(const mitk::modelFit::ModelFitInfo* fitSession,
mitk::ParameterFitImageGeneratorBase* generator)
{
QString message = "Fitting Data Set . . .";
m_Controls.infoBox->append(message);
/////////////////////////
//create job and put it into the thread pool
ParameterFitBackgroundJob* pJob = new ParameterFitBackgroundJob(generator, fitSession, this->m_selectedNode);
pJob->setAutoDelete(true);
connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnJobError(QString)));
connect(pJob, SIGNAL(Finished()), this, SLOT(OnJobFinished()));
connect(pJob, SIGNAL(ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType,
const ParameterFitBackgroundJob*)), this,
SLOT(OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType,
const ParameterFitBackgroundJob*)), Qt::BlockingQueuedConnection);
connect(pJob, SIGNAL(JobProgress(double)), this, SLOT(OnJobProgress(double)));
connect(pJob, SIGNAL(JobStatusChanged(QString)), this, SLOT(OnJobStatusChanged(QString)));
QThreadPool* threadPool = QThreadPool::globalInstance();
threadPool->start(pJob);
}
GenericDataFittingView::GenericDataFittingView() : m_FittingInProgress(false)
{
m_selectedImage = nullptr;
m_selectedMask = nullptr;
mitk::ModelFactoryBase::Pointer factory =
mitk::LinearModelFactory::New().GetPointer();
m_FactoryStack.push_back(factory);
factory = mitk::GenericParamModelFactory::New().GetPointer();
m_FactoryStack.push_back(factory);
factory = mitk::T2DecayModelFactory::New().GetPointer();
m_FactoryStack.push_back(factory);
this->m_IsNotABinaryImagePredicate = mitk::NodePredicateAnd::New(
mitk::TNodePredicateDataType::New(),
mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("binary",
mitk::BoolProperty::New(true))),
mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer();
this->m_IsBinaryImagePredicate = mitk::NodePredicateAnd::New(
mitk::TNodePredicateDataType::New(),
mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)),
mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer();
}
void GenericDataFittingView::OnJobFinished()
{
this->m_Controls.infoBox->append(QString("Fitting finished"));
this->m_FittingInProgress = false;
this->UpdateGUIControls();
};
void GenericDataFittingView::OnJobError(QString err)
{
MITK_ERROR << err.toStdString().c_str();
m_Controls.infoBox->append(QString("") + err + QString(""));
};
void GenericDataFittingView::OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType
results,
const ParameterFitBackgroundJob* pJob)
{
//Store the resulting parameter fit image via convenience helper function in data storage
//(handles the correct generation of the nodes and their properties)
mitk::modelFit::StoreResultsInDataStorage(this->GetDataStorage(), results, pJob->GetParentNode());
};
void GenericDataFittingView::OnJobProgress(double progress)
{
QString report = QString("Progress. ") + QString::number(progress);
this->m_Controls.infoBox->append(report);
};
void GenericDataFittingView::OnJobStatusChanged(QString info)
{
this->m_Controls.infoBox->append(info);
}
void GenericDataFittingView::InitModelComboBox() const
{
this->m_Controls.comboModel->clear();
this->m_Controls.comboModel->addItem(tr("No model selected"));
for (ModelFactoryStackType::const_iterator pos = m_FactoryStack.begin();
pos != m_FactoryStack.end(); ++pos)
{
this->m_Controls.comboModel->addItem(QString::fromStdString((*pos)->GetClassID()));
}
this->m_Controls.comboModel->setCurrentIndex(0);
};
mitk::ModelFitFunctorBase::Pointer GenericDataFittingView::CreateDefaultFitFunctor(
const mitk::ModelParameterizerBase* parameterizer) const
{
mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor =
mitk::LevenbergMarquardtModelFitFunctor::New();
mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::Pointer chi2 =
mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::New();
fitFunctor->RegisterEvaluationParameter("Chi^2", chi2);
if (m_Controls.checkBox_Constraints->isChecked())
{
fitFunctor->SetConstraintChecker(m_modelConstraints);
}
mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel();
::itk::LevenbergMarquardtOptimizer::ScalesType scales;
scales.SetSize(refModel->GetNumberOfParameters());
scales.Fill(1.0);
fitFunctor->SetScales(scales);
fitFunctor->SetDebugParameterMaps(m_Controls.checkDebug->isChecked());
return fitFunctor.GetPointer();
}
diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp
index dcf1116823..89d950ed79 100644
--- a/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp
+++ b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp
@@ -1,920 +1,920 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
// Blueberry
#include
#include
#include
// mitk
#include
// Qt
#include
#include
#include
#include
#include "QmitkPlotWidget.h"
#include "mitkNodePredicateFunction.h"
#include "mitkScalarListLookupTableProperty.h"
#include "mitkModelFitConstants.h"
#include "mitkExtractTimeGrid.h"
#include "mitkModelGenerator.h"
#include "mitkModelFitException.h"
#include "mitkModelFitParameterValueExtraction.h"
#include "mitkTimeGridHelper.h"
#include "mitkModelFitResultRelationRule.h"
#include "mitkModelFitPlotDataHelper.h"
#include "ModelFitInspectorView.h"
-const std::string ModelFitInspectorView::VIEW_ID = "org.mitk.gui.gt.fit.inspector";
+const std::string ModelFitInspectorView::VIEW_ID = "org.mitk.views.fit.inspector";
const unsigned int ModelFitInspectorView::INTERPOLATION_STEPS = 10;
const std::string DEFAULT_X_AXIS = "Time [s]";
ModelFitInspectorView::ModelFitInspectorView() :
m_renderWindowPart(nullptr),
m_internalUpdateFlag(false),
m_currentFit(nullptr),
m_currentModelParameterizer(nullptr),
m_currentModelProviderService(nullptr),
m_currentSelectedTimeStep(0),
m_currentSelectedNode(nullptr)
{
m_currentSelectedPosition.Fill(0.0);
m_modelfitList.clear();
}
ModelFitInspectorView::~ModelFitInspectorView()
{
}
void ModelFitInspectorView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
if (m_renderWindowPart != renderWindowPart)
{
m_renderWindowPart = renderWindowPart;
}
this->m_SliceChangeListener.RenderWindowPartActivated(renderWindowPart);
}
void ModelFitInspectorView::RenderWindowPartDeactivated(
mitk::IRenderWindowPart* renderWindowPart)
{
m_renderWindowPart = nullptr;
this->m_SliceChangeListener.RenderWindowPartDeactivated(renderWindowPart);
}
void ModelFitInspectorView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_SelectionServiceConnector = std::make_unique();
m_SelectionServiceConnector->AddPostSelectionListener(this->GetSite()->GetWorkbenchWindow()->GetSelectionService());
m_Controls.inputNodeSelector->SetDataStorage(GetDataStorage());
m_Controls.inputNodeSelector->SetEmptyInfo(QString("Please select input data to be viewed."));
m_Controls.inputNodeSelector->SetInvalidInfo(QString("No input data is selected"));
m_Controls.inputNodeSelector->SetPopUpTitel(QString("Choose 3D+t input data that should be viewed!"));
m_Controls.inputNodeSelector->SetSelectionIsOptional(false);
m_Controls.inputNodeSelector->SetSelectOnlyVisibleNodes(true);
auto predicate = mitk::NodePredicateFunction::New([](const mitk::DataNode *node) {
bool isModelFitNode = node->GetData() && node->GetData()->GetProperty(mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str()).IsNotNull();
return isModelFitNode || (node && node->GetData() && node->GetData()->GetTimeSteps() > 1);
});
m_Controls.inputNodeSelector->SetNodePredicate(predicate);
connect(m_SelectionServiceConnector.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, m_Controls.inputNodeSelector, &QmitkSingleNodeSelectionWidget::SetCurrentSelection);
connect(m_Controls.inputNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &ModelFitInspectorView::OnInputChanged);
this->m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
connect(m_Controls.cmbFit, SIGNAL(currentIndexChanged(int)), this,
SLOT(OnFitSelectionChanged(int)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.sbFixMin,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.sbFixMax,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.labelFixMin,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.labelFixMax,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.btnScaleToData,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), this, SLOT(OnScaleFixedYChecked(bool)));
connect(m_Controls.btnScaleToData, SIGNAL(clicked()), this, SLOT(OnScaleToDataYClicked()));
connect(m_Controls.sbFixMax, SIGNAL(valueChanged(double)), this,
SLOT(OnFixedScalingYChanged(double)));
connect(m_Controls.sbFixMin, SIGNAL(valueChanged(double)), this,
SLOT(OnFixedScalingYChanged(double)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.sbFixMin_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.sbFixMax_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.labelFixMin_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.labelFixMax_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.btnScaleToData_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), this, SLOT(OnScaleFixedXChecked(bool)));
connect(m_Controls.btnScaleToData_x, SIGNAL(clicked()), this, SLOT(OnScaleToDataXClicked()));
connect(m_Controls.sbFixMax_x, SIGNAL(valueChanged(double)), this,
SLOT(OnFixedScalingXChanged(double)));
connect(m_Controls.sbFixMin_x, SIGNAL(valueChanged(double)), this,
SLOT(OnFixedScalingXChanged(double)));
connect(m_Controls.btnFullPlot, SIGNAL(clicked(bool)), this, SLOT(OnFullPlotClicked(bool)));
this->EnsureBookmarkPointSet();
m_Controls.inspectionPositionWidget->SetPositionBookmarkNode(m_PositionBookmarksNode.Lock());
connect(m_Controls.inspectionPositionWidget, SIGNAL(PositionBookmarksChanged()), this, SLOT(OnPositionBookmarksChanged()));
// For some reason this needs to be called to set the plot widget's minimum width to an
// acceptable level (since Qwt 6).
// Otherwise it tries to keep both axes equal in length, resulting in a minimum width of
// 400-500px which is way too much.
m_Controls.widgetPlot->GetPlot()->updateAxes();
m_Controls.cmbFit->clear();
mitk::IRenderWindowPart* renderWindowPart = GetRenderWindowPart();
RenderWindowPartActivated(renderWindowPart);
}
void ModelFitInspectorView::SetFocus()
{
}
void ModelFitInspectorView::NodeRemoved(const mitk::DataNode* node)
{
if (node == this->m_currentSelectedNode)
{
QmitkSingleNodeSelectionWidget::NodeList emptylist;
this->m_Controls.inputNodeSelector->SetCurrentSelection(emptylist);
}
}
void ModelFitInspectorView::OnScaleFixedYChecked(bool checked)
{
m_Controls.widgetPlot->GetPlot()->setAxisAutoScale(QwtPlot::yLeft, !checked);
if (checked)
{
OnScaleToDataYClicked();
}
m_Controls.widgetPlot->GetPlot()->replot();
};
void ModelFitInspectorView::OnScaleFixedXChecked(bool checked)
{
m_Controls.widgetPlot->GetPlot()->setAxisAutoScale(QwtPlot::xBottom, !checked);
if (checked)
{
OnScaleToDataXClicked();
}
m_Controls.widgetPlot->GetPlot()->replot();
};
void ModelFitInspectorView::OnScaleToDataYClicked()
{
auto minmax = this->m_PlotCurves.GetYMinMax();
auto min = minmax.first - std::abs(minmax.first) * 0.01;
auto max = minmax.second + std::abs(minmax.second) * 0.01;
m_Controls.sbFixMin->setValue(min);
m_Controls.sbFixMax->setValue(max);
};
void ModelFitInspectorView::OnScaleToDataXClicked()
{
auto minmax = this->m_PlotCurves.GetXMinMax();
auto min = minmax.first - std::abs(minmax.first) * 0.01;
auto max = minmax.second + std::abs(minmax.second) * 0.01;
m_Controls.sbFixMin_x->setValue(min);
m_Controls.sbFixMax_x->setValue(max);
};
void ModelFitInspectorView::OnFixedScalingYChanged(double /*value*/)
{
m_Controls.widgetPlot->GetPlot()->setAxisScale(QwtPlot::yLeft, m_Controls.sbFixMin->value(),
m_Controls.sbFixMax->value());
m_Controls.widgetPlot->GetPlot()->replot();
};
void ModelFitInspectorView::OnFixedScalingXChanged(double /*value*/)
{
m_Controls.widgetPlot->GetPlot()->setAxisScale(QwtPlot::xBottom, m_Controls.sbFixMin_x->value(),
m_Controls.sbFixMax_x->value());
m_Controls.widgetPlot->GetPlot()->replot();
};
void ModelFitInspectorView::OnFullPlotClicked(bool checked)
{
m_Controls.tabWidget->setVisible(!checked);
};
int ModelFitInspectorView::ActualizeFitSelectionWidget()
{
mitk::modelFit::ModelFitInfo::UIDType selectedFitUD = "";
bool isModelFitNode = false;
if (this->m_Controls.inputNodeSelector->GetSelectedNode().IsNotNull())
{
isModelFitNode = this->m_Controls.inputNodeSelector->GetSelectedNode()->GetData()->GetPropertyList()->GetStringProperty(
mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(), selectedFitUD);
}
mitk::DataStorage::Pointer storage = this->GetDataStorage();
mitk::modelFit::NodeUIDSetType fitUIDs = mitk::modelFit::GetFitUIDsOfNode(
this->m_currentSelectedNode, storage);
this->m_modelfitList.clear();
this->m_Controls.cmbFit->clear();
for (const auto & fitUID : fitUIDs)
{
mitk::modelFit::ModelFitInfo::ConstPointer info = mitk::modelFit::CreateFitInfoFromNode(fitUID,
storage).GetPointer();
if (info.IsNotNull())
{
this->m_modelfitList.insert(std::make_pair(info->uid, info));
std::ostringstream nameStrm;
if (info->fitName.empty())
{
nameStrm << info->uid;
}
else
{
nameStrm << info->fitName;
}
nameStrm << " (" << info->modelName << ")";
QVariant data(info->uid.c_str());
m_Controls.cmbFit->addItem(QString::fromStdString(nameStrm.str()), data);
}
else
{
MITK_ERROR <<
"Was not able to extract model fit information from storage. Node properties in storage may be invalid. Failed fit UID:"
<< fitUID;
}
}
int cmbIndex = 0;
if (m_modelfitList.empty())
{
cmbIndex = -1;
};
if (isModelFitNode)
{
//model was selected, thus select this one in combobox
QVariant data(selectedFitUD.c_str());
cmbIndex = m_Controls.cmbFit->findData(data);
if (cmbIndex == -1)
{
MITK_WARN <<
"Model fit Inspector in invalid state. Selected fit seems to be not avaible in plugin selection. Failed fit UID:"
<< selectedFitUD;
}
};
m_Controls.cmbFit->setCurrentIndex(cmbIndex);
return cmbIndex;
}
void ModelFitInspectorView::OnInputChanged(const QList& nodes)
{
if (nodes.size() > 0)
{
if (nodes.front() != this->m_currentSelectedNode)
{
m_internalUpdateFlag = true;
this->m_currentSelectedNode = nodes.front();
mitk::modelFit::ModelFitInfo::UIDType selectedFitUD = "";
bool isModelFitNode = this->m_currentSelectedNode->GetData()->GetPropertyList()->GetStringProperty(
mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(), selectedFitUD);
if (isModelFitNode)
{
this->m_currentSelectedNode = this->GetInputNode(this->m_currentSelectedNode);
if (this->m_currentSelectedNode.IsNull())
{
MITK_WARN <<
"Model fit Inspector in invalid state. Input image for selected fit cannot be found in data storage. Failed fit UID:"
<< selectedFitUD;
}
}
auto cmbIndex = ActualizeFitSelectionWidget();
m_internalUpdateFlag = false;
m_selectedNodeTime.Modified();
if (cmbIndex == -1)
{
//only raw 4D data selected. Just update plots for current position
m_currentFit = nullptr;
m_currentFitTime.Modified();
OnSliceChanged();
m_Controls.plotDataWidget->SetXName(DEFAULT_X_AXIS);
}
else
{
//refresh fit selection (and implicitly update plots)
OnFitSelectionChanged(cmbIndex);
}
}
}
else
{
if (this->m_currentSelectedNode.IsNotNull())
{
m_internalUpdateFlag = true;
this->m_currentSelectedNode = nullptr;
this->m_currentFit = nullptr;
this->m_modelfitList.clear();
this->m_Controls.cmbFit->clear();
m_internalUpdateFlag = false;
m_selectedNodeTime.Modified();
OnFitSelectionChanged(0);
RefreshPlotData();
m_Controls.plotDataWidget->SetPlotData(&(this->m_PlotCurves));
m_Controls.fitParametersWidget->setFits(QmitkFitParameterModel::FitVectorType());
RenderPlot();
}
}
}
mitk::DataNode::ConstPointer
ModelFitInspectorView::GetInputNode(mitk::DataNode::ConstPointer node)
{
if (node.IsNotNull())
{
std::string selectedFitUD = "";
auto rule = mitk::ModelFitResultRelationRule::New();
auto predicate = rule->GetDestinationsDetector(node);
mitk::DataStorage::SetOfObjects::ConstPointer parentNodeList =
GetDataStorage()->GetSubset(predicate);
if (parentNodeList->size() > 0)
{
return parentNodeList->front().GetPointer();
}
}
return mitk::DataNode::ConstPointer();
}
void ModelFitInspectorView::ValidateAndSetCurrentPosition()
{
mitk::Point3D currentSelectedPosition = GetRenderWindowPart()->GetSelectedPosition(nullptr);
unsigned int currentSelectedTimestep = m_renderWindowPart->GetTimeNavigationController()->GetTime()->
GetPos();
if (m_currentSelectedPosition != currentSelectedPosition
|| m_currentSelectedTimeStep != currentSelectedTimestep
|| m_selectedNodeTime > m_currentPositionTime)
{
//the current position has been changed or the selected node has been changed since the last position validation -> check position
m_currentSelectedPosition = currentSelectedPosition;
m_currentSelectedTimeStep = currentSelectedTimestep;
m_currentPositionTime.Modified();
m_validSelectedPosition = false;
auto inputImage = this->GetCurrentInputImage();
if (inputImage.IsNull())
{
return;
}
mitk::BaseGeometry::ConstPointer geometry = inputImage->GetTimeGeometry()->GetGeometryForTimeStep(
m_currentSelectedTimeStep).GetPointer();
// check for invalid time step
if (geometry.IsNull())
{
geometry = inputImage->GetTimeGeometry()->GetGeometryForTimeStep(0);
}
if (geometry.IsNull())
{
return;
}
m_validSelectedPosition = geometry->IsInside(m_currentSelectedPosition);
}
}
mitk::Image::ConstPointer ModelFitInspectorView::GetCurrentInputImage() const
{
mitk::Image::ConstPointer result = nullptr;
if (this->m_currentFit.IsNotNull())
{
result = m_currentFit->inputImage;
}
else if (this->m_currentSelectedNode.IsNotNull())
{
result = dynamic_cast(this->m_currentSelectedNode->GetData());
if (result.IsNotNull() && result->GetTimeSteps() <= 1)
{
//if the image is not dynamic, we can't use it.
result = nullptr;
}
}
return result;
};
const mitk::ModelBase::TimeGridType ModelFitInspectorView::GetCurrentTimeGrid() const
{
if (m_currentModelProviderService && m_currentFit.IsNotNull())
{
return m_currentModelProviderService->GetVariableGrid(m_currentFit);
}
else
{ //fall back if there is no model provider we assume to use the normal time grid.
return ExtractTimeGrid(GetCurrentInputImage());
}
};
void ModelFitInspectorView::OnSliceChanged()
{
ValidateAndSetCurrentPosition();
m_Controls.widgetPlot->setEnabled(m_validSelectedPosition);
if (m_currentSelectedNode.IsNotNull())
{
m_Controls.inspectionPositionWidget->SetCurrentPosition(m_currentSelectedPosition);
if (RefreshPlotData())
{
RenderPlot();
m_Controls.plotDataWidget->SetPlotData(&m_PlotCurves);
RenderFitInfo();
}
}
}
void ModelFitInspectorView::OnPositionBookmarksChanged()
{
if (RefreshPlotData())
{
RenderPlot();
m_Controls.plotDataWidget->SetPlotData(&m_PlotCurves);
RenderFitInfo();
}
}
void ModelFitInspectorView::OnFitSelectionChanged(int index)
{
if (!m_internalUpdateFlag)
{
MITK_DEBUG << "selected fit index: " << index;
std::string uid = "";
if (m_Controls.cmbFit->count() > index)
{
uid = m_Controls.cmbFit->itemData(index).toString().toStdString();
}
mitk::modelFit::ModelFitInfo::ConstPointer newFit = nullptr;
ModelFitInfoListType::iterator finding = m_modelfitList.find(uid);
if (finding != m_modelfitList.end())
{
newFit = finding->second;
}
if (m_currentFit != newFit)
{
m_currentModelParameterizer = nullptr;
m_currentModelProviderService = nullptr;
if (newFit.IsNotNull())
{
m_currentModelParameterizer = mitk::ModelGenerator::GenerateModelParameterizer(*newFit);
m_currentModelProviderService = mitk::ModelGenerator::GetProviderService(newFit->functionClassID);
}
m_currentFit = newFit;
m_currentFitTime.Modified();
auto name = m_currentFit->xAxisName;
if (!m_currentFit->xAxisUnit.empty())
{
name += " [" + m_currentFit->xAxisUnit + "]";
}
m_Controls.plotDataWidget->SetXName(name);
OnSliceChanged();
}
}
}
mitk::PlotDataCurveCollection::Pointer ModelFitInspectorView::RefreshPlotDataCurveCollection(const mitk::Point3D& position,
const mitk::Image* input, const mitk::modelFit::ModelFitInfo* fitInfo,
const mitk::ModelBase::TimeGridType& timeGrid, mitk::ModelParameterizerBase* parameterizer)
{
mitk::PlotDataCurveCollection::Pointer result = mitk::PlotDataCurveCollection::New();
//sample curve
if (input)
{
result->InsertElement(mitk::MODEL_FIT_PLOT_SAMPLE_NAME(), GenerateImageSamplePlotData(position, input, timeGrid));
}
//model signal curve
if (fitInfo)
{
// Interpolate time grid (x values) so the curve looks smooth
const mitk::ModelBase::TimeGridType interpolatedTimeGrid = mitk::GenerateSupersampledTimeGrid(timeGrid, INTERPOLATION_STEPS);
auto hires_curve = mitk::GenerateModelSignalPlotData(position, fitInfo, interpolatedTimeGrid, parameterizer);
result->InsertElement(mitk::MODEL_FIT_PLOT_INTERPOLATED_SIGNAL_NAME(), hires_curve);
auto curve = mitk::GenerateModelSignalPlotData(position, fitInfo, timeGrid, parameterizer);
result->InsertElement(mitk::MODEL_FIT_PLOT_SIGNAL_NAME(), curve);
}
return result;
};
bool ModelFitInspectorView::RefreshPlotData()
{
bool changed = false;
if (m_currentSelectedNode.IsNull())
{
this->m_PlotCurves = mitk::ModelFitPlotData();
changed = m_selectedNodeTime > m_lastRefreshTime;
m_lastRefreshTime.Modified();
}
else
{
assert(GetRenderWindowPart() != NULL);
const mitk::Image* input = GetCurrentInputImage();
const mitk::ModelBase::TimeGridType timeGrid = GetCurrentTimeGrid();
if (m_currentFitTime > m_lastRefreshTime || m_currentPositionTime > m_lastRefreshTime)
{
if (m_validSelectedPosition)
{
m_PlotCurves.currentPositionPlots = RefreshPlotDataCurveCollection(m_currentSelectedPosition,input,m_currentFit, timeGrid, m_currentModelParameterizer);
}
else
{
m_PlotCurves.currentPositionPlots = mitk::PlotDataCurveCollection::New();
}
changed = true;
}
auto bookmarks = m_PositionBookmarks.Lock();
if (bookmarks.IsNotNull())
{
if (m_currentFitTime > m_lastRefreshTime || bookmarks->GetMTime() > m_lastRefreshTime)
{
m_PlotCurves.positionalPlots.clear();
auto endIter = bookmarks->End();
for (auto iter = bookmarks->Begin(); iter != endIter; iter++)
{
auto collection = RefreshPlotDataCurveCollection(iter.Value(), input, m_currentFit, timeGrid, m_currentModelParameterizer);
m_PlotCurves.positionalPlots.emplace(iter.Index(), std::make_pair(iter.Value(), collection));
}
changed = true;
}
}
else
{
m_PlotCurves.positionalPlots.clear();
}
// input data curve
if (m_currentFitTime > m_lastRefreshTime)
{
m_PlotCurves.staticPlots->clear();
if (m_currentFit.IsNotNull())
{
m_PlotCurves.staticPlots = GenerateAdditionalModelFitPlotData(m_currentSelectedPosition, m_currentFit, timeGrid);
}
changed = true;
}
m_lastRefreshTime.Modified();
}
return changed;
}
void ModelFitInspectorView::RenderFitInfo()
{
assert(m_renderWindowPart != nullptr);
// configure fit information
if (m_currentFit.IsNull())
{
m_Controls.lFitType->setText("");
m_Controls.lFitUID->setText("");
m_Controls.lModelName->setText("");
m_Controls.lModelType->setText("");
}
else
{
m_Controls.lFitType->setText(QString::fromStdString(m_currentFit->fitType));
m_Controls.lFitUID->setText(QString::fromStdString(m_currentFit->uid));
m_Controls.lModelName->setText(QString::fromStdString(m_currentFit->modelName));
m_Controls.lModelType->setText(QString::fromStdString(m_currentFit->modelType));
}
// print results
std::stringstream infoOutput;
m_Controls.fitParametersWidget->setVisible(false);
m_Controls.groupSettings->setVisible(false);
if (m_currentFit.IsNull())
{
infoOutput << "No fit selected. Only raw image data is plotted.";
}
else if (!m_validSelectedPosition)
{
infoOutput <<
"Current position is outside of the input image of the selected fit.\nInspector is deactivated.";
}
else
{
m_Controls.fitParametersWidget->setVisible(true);
m_Controls.fitParametersWidget->setFits({ m_currentFit });
m_Controls.fitParametersWidget->setPositionBookmarks(m_PositionBookmarks.Lock());
m_Controls.fitParametersWidget->setCurrentPosition(m_currentSelectedPosition);
}
// configure data table
m_Controls.tableInputData->clearContents();
if (m_currentFit.IsNull())
{
infoOutput << "No fit selected. Only raw image data is plotted.";
}
else
{
m_Controls.groupSettings->setVisible(true);
m_Controls.tableInputData->setRowCount(m_PlotCurves.staticPlots->size());
unsigned int rowIndex = 0;
for (mitk::PlotDataCurveCollection::const_iterator pos = m_PlotCurves.staticPlots->begin();
pos != m_PlotCurves.staticPlots->end(); ++pos, ++rowIndex)
{
QColor dataColor;
if (pos->first == "ROI")
{
dataColor = QColor(0, 190, 0);
}
else
{
//Use HSV schema of QColor to calculate a different color depending on the
//number of already existing free iso lines.
dataColor.setHsv(((rowIndex + 1) * 85) % 360, 255, 255);
}
QTableWidgetItem* newItem = new QTableWidgetItem(QString::fromStdString(pos->first));
m_Controls.tableInputData->setItem(rowIndex, 0, newItem);
newItem = new QTableWidgetItem();
newItem->setBackgroundColor(dataColor);
m_Controls.tableInputData->setItem(rowIndex, 1, newItem);
}
}
m_Controls.lInfo->setText(QString::fromStdString(infoOutput.str()));
}
void ModelFitInspectorView::RenderPlotCurve(const mitk::PlotDataCurveCollection* curveCollection, const QColor& sampleColor, const QColor& signalColor, const std::string& posString)
{
auto sampleCurve = mitk::ModelFitPlotData::GetSamplePlot(curveCollection);
if (sampleCurve)
{
std::string name = mitk::MODEL_FIT_PLOT_SAMPLE_NAME() + posString;
unsigned int curveId = m_Controls.widgetPlot->InsertCurve(name.c_str());
m_Controls.widgetPlot->SetCurveData(curveId, sampleCurve->GetValues());
m_Controls.widgetPlot->SetCurvePen(curveId, QPen(Qt::NoPen));
// QwtSymbol needs to passed as a real pointer from MITK v2013.09.0 on
// (QwtPlotCurve deletes it on destruction and assignment).
QwtSymbol* dataSymbol = new QwtSymbol(QwtSymbol::Diamond, sampleColor, sampleColor, QSize(8, 8));
m_Controls.widgetPlot->SetCurveSymbol(curveId, dataSymbol);
// Again, there is no way to set a curve's legend attributes via QmitkPlotWidget so this
// gets unnecessarily complicated.
QwtPlotCurve* measurementCurve = dynamic_cast(m_Controls.widgetPlot->
GetPlot()->itemList(QwtPlotItem::Rtti_PlotCurve).back());
measurementCurve->setLegendAttribute(QwtPlotCurve::LegendShowSymbol);
measurementCurve->setLegendIconSize(QSize(8, 8));
}
//draw model curve
auto signalCurve = mitk::ModelFitPlotData::GetInterpolatedSignalPlot(curveCollection);
if (signalCurve)
{
std::string name = mitk::MODEL_FIT_PLOT_SIGNAL_NAME() + posString;
QPen pen;
pen.setColor(signalColor);
pen.setWidth(2);
unsigned int curveId = m_Controls.widgetPlot->InsertCurve(name.c_str());
m_Controls.widgetPlot->SetCurveData(curveId, signalCurve->GetValues());
m_Controls.widgetPlot->SetCurvePen(curveId, pen);
// Manually set the legend attribute to use the symbol as the legend icon and alter its
// size. Otherwise it would revert to default which is drawing a square which is the color
// of the curve's pen, so in this case none which defaults to black.
// Unfortunately, QmitkPlotWidget offers no way to set the legend attribute and icon size so
// this looks a bit hacky.
QwtPlotCurve* fitCurve = dynamic_cast(m_Controls.widgetPlot->GetPlot()->
itemList(QwtPlotItem::Rtti_PlotCurve).back());
fitCurve->setLegendAttribute(QwtPlotCurve::LegendShowLine);
}
}
void ModelFitInspectorView::RenderPlot()
{
m_Controls.widgetPlot->Clear();
std::string xAxis = DEFAULT_X_AXIS;
std::string yAxis = "Intensity";
std::string plotTitle = "Raw data plot: no data";
if (m_currentSelectedNode.IsNotNull())
{
plotTitle = "Raw data plot: " + m_currentSelectedNode->GetName();
}
if (m_currentFit.IsNotNull())
{
plotTitle = m_currentFit->modelName.c_str();
xAxis = m_currentFit->xAxisName;
if (!m_currentFit->xAxisUnit.empty())
{
xAxis += " [" + m_currentFit->xAxisUnit + "]";
}
yAxis = m_currentFit->yAxisName;
if (!m_currentFit->yAxisUnit.empty())
{
yAxis += " [" + m_currentFit->yAxisUnit + "]";
}
}
m_Controls.widgetPlot->SetAxisTitle(QwtPlot::xBottom, xAxis.c_str());
m_Controls.widgetPlot->SetAxisTitle(QwtPlot::yLeft, yAxis.c_str());
m_Controls.widgetPlot->SetPlotTitle(plotTitle.c_str());
// Draw static curves
unsigned int colorIndex = 0;
for (mitk::PlotDataCurveCollection::const_iterator pos = m_PlotCurves.staticPlots->begin();
pos != m_PlotCurves.staticPlots->end(); ++pos)
{
QColor dataColor;
unsigned int curveId = m_Controls.widgetPlot->InsertCurve(pos->first.c_str());
m_Controls.widgetPlot->SetCurveData(curveId, pos->second->GetValues());
if (pos->first == "ROI")
{
dataColor = QColor(0, 190, 0);
QPen pen;
pen.setColor(dataColor);
pen.setStyle(Qt::SolidLine);
m_Controls.widgetPlot->SetCurvePen(curveId, pen);
}
else
{
//Use HSV schema of QColor to calculate a different color depending on the
//number of already existing curves.
dataColor.setHsv((++colorIndex * 85) % 360, 255, 150);
m_Controls.widgetPlot->SetCurvePen(curveId, QPen(Qt::NoPen));
}
// QwtSymbol needs to passed as a real pointer from MITK v2013.09.0 on
// (QwtPlotCurve deletes it on destruction and assignment).
QwtSymbol* dataSymbol = new QwtSymbol(QwtSymbol::Triangle, dataColor, dataColor,
QSize(8, 8));
m_Controls.widgetPlot->SetCurveSymbol(curveId, dataSymbol);
// Again, there is no way to set a curve's legend attributes via QmitkPlotWidget so this
// gets unnecessarily complicated.
QwtPlotCurve* measurementCurve = dynamic_cast(m_Controls.widgetPlot->
GetPlot()->itemList(QwtPlotItem::Rtti_PlotCurve).back());
measurementCurve->setLegendAttribute(QwtPlotCurve::LegendShowSymbol);
measurementCurve->setLegendIconSize(QSize(8, 8));
}
// Draw positional curves
for (const auto& posIter : this->m_PlotCurves.positionalPlots)
{
QColor dataColor;
dataColor.setHsv((++colorIndex * 85) % 360, 255, 150);
this->RenderPlotCurve(posIter.second.second, dataColor, dataColor, " @ "+mitk::ModelFitPlotData::GetPositionalCollectionName(posIter));
}
// Draw current pos curve
this->RenderPlotCurve(m_PlotCurves.currentPositionPlots, QColor(Qt::red), QColor(Qt::black), "");
QwtLegend* legend = new QwtLegend();
legend->setFrameShape(QFrame::Box);
legend->setFrameShadow(QFrame::Sunken);
legend->setLineWidth(1);
m_Controls.widgetPlot->SetLegend(legend, QwtPlot::BottomLegend);
m_Controls.widgetPlot->Replot();
}
void ModelFitInspectorView::EnsureBookmarkPointSet()
{
if (m_PositionBookmarks.IsExpired() || m_PositionBookmarksNode.IsExpired())
{
const char* nodeName = "org.mitk.gui.qt.fit.inspector.positions";
mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode(nodeName);
if (!node)
{
node = mitk::DataNode::New();
node->SetName(nodeName);
node->SetBoolProperty("helper object", true);
this->GetDataStorage()->Add(node);
}
m_PositionBookmarksNode = node;
mitk::PointSet::Pointer pointSet = dynamic_cast(node->GetData());
if (pointSet.IsNull())
{
pointSet = mitk::PointSet::New();
node->SetData(pointSet);
}
m_PositionBookmarks = pointSet;
}
}
diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.cpp
index 72750ec552..1ec7c9c470 100644
--- a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.cpp
+++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.cpp
@@ -1,551 +1,551 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include
#include "mitkWorkbenchUtil.h"
#include "ConcentrationCurveConverterView.h"
#include "mitkConcentrationCurveGenerator.h"
#include "mitkNodePredicateDataType.h"
#include "mitkConvertToConcentrationTurboFlashFunctor.h"
#include "mitkConvertToConcentrationAbsoluteFunctor.h"
#include "mitkConvertToConcentrationRelativeFunctor.h"
#include "itkBinaryFunctorImageFilter.h"
#include "boost/math/constants/constants.hpp"
#include
#include
#include
#include
#include
#include
#include "mitkNodePredicateFunction.h"
#include
#include
// Includes for image casting between ITK and MITK
#include "mitkImageTimeSelector.h"
#include "mitkImageCast.h"
#include "mitkITKImageImport.h"
#include
#include
-const std::string ConcentrationCurveConverterView::VIEW_ID = "org.mitk.ConcentrationCurveConverterView";
+const std::string ConcentrationCurveConverterView::VIEW_ID = "org.mitk.views.pharmacokinetics.concentration.mri";
void ConcentrationCurveConverterView::SetFocus()
{
m_Controls.btnConvertToConcentration->setFocus();
}
void ConcentrationCurveConverterView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_Controls.btnConvertToConcentration->setEnabled(false);
connect(m_Controls.btnConvertToConcentration, SIGNAL(clicked()), this, SLOT(OnConvertToConcentrationButtonClicked()));
m_Controls.timeSeriesNodeSelector->SetNodePredicate(this->m_isValidTimeSeriesImagePredicate);
m_Controls.timeSeriesNodeSelector->SetDataStorage(this->GetDataStorage());
m_Controls.timeSeriesNodeSelector->SetSelectionIsOptional(false);
m_Controls.timeSeriesNodeSelector->SetInvalidInfo("Please select time series.");
m_Controls.image3DNodeSelector->SetNodePredicate(this->m_isValidPDWImagePredicate);
m_Controls.image3DNodeSelector->SetDataStorage(this->GetDataStorage());
m_Controls.image3DNodeSelector->SetSelectionIsOptional(false);
m_Controls.image3DNodeSelector->SetInvalidInfo("Please select 3D image.");
m_Controls.baselineImageNodeSelector->SetNodePredicate(this->m_isValidPDWImagePredicate);
m_Controls.baselineImageNodeSelector->SetDataStorage(this->GetDataStorage());
m_Controls.baselineImageNodeSelector->SetSelectionIsOptional(false);
m_Controls.baselineImageNodeSelector->SetInvalidInfo("Please select baseline image.");
m_Controls.t2TimeSeriesNodeSelector->SetNodePredicate(this->m_isValidTimeSeriesImagePredicate);
m_Controls.t2TimeSeriesNodeSelector->SetDataStorage(this->GetDataStorage());
m_Controls.t2TimeSeriesNodeSelector->SetSelectionIsOptional(false);
m_Controls.t2TimeSeriesNodeSelector->SetInvalidInfo("Please select time series.");
m_Controls.PDWImageNodeSelector->SetNodePredicate(m_isValidPDWImagePredicate);
m_Controls.PDWImageNodeSelector->SetDataStorage(this->GetDataStorage());
m_Controls.PDWImageNodeSelector->SetInvalidInfo("Please select PDW Image.");
m_Controls.PDWImageNodeSelector->setEnabled(false);
m_Controls.groupBox_T1->hide();
m_Controls.groupBox_T2->hide();
m_Controls.groupBox3D->hide();
m_Controls.groupBox4D->hide();
m_Controls.groupBoxTurboFlash->hide();
m_Controls.groupConcentration->hide();
connect(m_Controls.radioButton_T1, SIGNAL(toggled(bool)),this, SLOT(OnSettingChanged()));
connect(m_Controls.radioButton_T2, SIGNAL(toggled(bool)),this, SLOT(OnSettingChanged()));
connect(m_Controls.radioButton3D, SIGNAL(toggled(bool)),this, SLOT(OnSettingChanged()));
connect(m_Controls.radioButton4D, SIGNAL(toggled(bool)),this, SLOT(OnSettingChanged()));
//Concentration
m_Controls.groupConcentration->hide();
m_Controls.groupBoxEnhancement->hide();
m_Controls.groupBoxTurboFlash->hide();
m_Controls.groupBox_T1MapviaVFA->hide();
m_Controls.spinBox_baselineStartTimeStep->setValue(0);
m_Controls.spinBox_baselineEndTimeStep->setValue(0);
m_Controls.spinBox_baselineEndTimeStep->setMinimum(0);
m_Controls.spinBox_baselineStartTimeStep->setMinimum(0);
m_Controls.spinBox_baselineStartTimeStepT2->setValue(0);
m_Controls.spinBox_baselineEndTimeStepT2->setValue(0);
m_Controls.spinBox_baselineEndTimeStepT2->setMinimum(0);
m_Controls.spinBox_baselineStartTimeStepT2->setMinimum(0);
connect(m_Controls.radioButtonTurboFlash, SIGNAL(toggled(bool)), m_Controls.groupBoxTurboFlash, SLOT(setVisible(bool)));
connect(m_Controls.radioButtonTurboFlash, SIGNAL(toggled(bool)), this, SLOT(OnSettingChanged()));
connect(m_Controls.relaxationtime, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged()));
connect(m_Controls.recoverytime, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged()));
connect(m_Controls.relaxivity, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged()));
connect(m_Controls.timeSeriesNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &ConcentrationCurveConverterView::OnNodeSelectionChanged);
connect(m_Controls.image3DNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &ConcentrationCurveConverterView::OnNodeSelectionChanged);
connect(m_Controls.baselineImageNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &ConcentrationCurveConverterView::OnNodeSelectionChanged);
connect(m_Controls.t2TimeSeriesNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &ConcentrationCurveConverterView::OnNodeSelectionChanged);
connect(m_Controls.PDWImageNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &ConcentrationCurveConverterView::OnSettingChanged);
connect(m_Controls.radioButton_absoluteEnhancement, SIGNAL(toggled(bool)), this, SLOT(OnSettingChanged()));
connect(m_Controls.radioButton_relativeEnchancement, SIGNAL(toggled(bool)), this, SLOT(OnSettingChanged()));
connect(m_Controls.radioButton_absoluteEnhancement, SIGNAL(toggled(bool)), m_Controls.groupBoxEnhancement, SLOT(setVisible(bool)));
connect(m_Controls.radioButton_relativeEnchancement, SIGNAL(toggled(bool)), m_Controls.groupBoxEnhancement, SLOT(setVisible(bool)));
connect(m_Controls.factorSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged()));
connect(m_Controls.spinBox_baselineStartTimeStep, SIGNAL(valueChanged(int)), this, SLOT(OnSettingChanged()));
connect(m_Controls.spinBox_baselineEndTimeStep, SIGNAL(valueChanged(int)), this, SLOT(OnSettingChanged()));
connect(m_Controls.spinBox_baselineStartTimeStepT2, SIGNAL(valueChanged(int)), this, SLOT(OnSettingChanged()));
connect(m_Controls.spinBox_baselineEndTimeStepT2, SIGNAL(valueChanged(int)), this, SLOT(OnSettingChanged()));
connect(m_Controls.radioButtonUsingT1viaVFA, SIGNAL(toggled(bool)), m_Controls.groupBox_T1MapviaVFA, SLOT(setVisible(bool)));
connect(m_Controls.radioButtonUsingT1viaVFA, SIGNAL(toggled(bool)), this, SLOT(OnSettingChanged()));
connect(m_Controls.FlipangleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged()));
connect(m_Controls.RelaxivitySpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged()));
connect(m_Controls.TRSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged()));
connect(m_Controls.T2EchoTimeSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged()));
connect(m_Controls.T2FactorSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged()));
connect(m_Controls.radioButtonUsingT1viaVFA, SIGNAL(toggled(bool)), m_Controls.PDWImageNodeSelector, SLOT(setEnabled(bool)));
}
void ConcentrationCurveConverterView::OnSettingChanged()
{
bool ok = false;
m_Controls.groupBox_T1->setVisible(m_Controls.radioButton_T1->isChecked());
m_Controls.groupBox_T2->setVisible(m_Controls.radioButton_T2->isChecked());
if(m_Controls.radioButton_T1->isChecked())
{
m_Controls.groupBox3D->setVisible(m_Controls.radioButton3D->isChecked());
m_Controls.groupBox4D->setVisible(m_Controls.radioButton4D->isChecked());
if(m_Controls.radioButton4D->isChecked())
{
m_Controls.groupConcentration->setVisible(true);
ok = m_selectedImage.IsNotNull() && CheckSettings();
}
else if(m_Controls.radioButton3D->isChecked())
{
m_Controls.groupConcentration->setVisible(true);
ok = m_selectedImage.IsNotNull() && m_selectedBaselineImage.IsNotNull() && CheckSettings();
}
}
else if (m_Controls.radioButton_T2->isChecked())
{
m_Controls.groupConcentration->setVisible(false);
ok = m_selectedImage.IsNotNull() && CheckSettings();
}
m_Controls.btnConvertToConcentration->setEnabled(ok);
}
bool ConcentrationCurveConverterView::CheckSettings() const
{
bool ok = true;
if (m_Controls.radioButton_T1->isChecked())
{
if (this->m_Controls.radioButtonTurboFlash->isChecked())
{
ok = ok && (m_Controls.recoverytime->value() > 0);
ok = ok && (m_Controls.relaxationtime->value() > 0);
ok = ok && (m_Controls.relaxivity->value() > 0);
ok = ok && (m_Controls.AifRecoverytime->value() > 0);
ok = ok && CheckBaselineSelectionSettings();
}
else if (this->m_Controls.radioButton_absoluteEnhancement->isChecked()
|| this->m_Controls.radioButton_relativeEnchancement->isChecked())
{
ok = ok && (m_Controls.factorSpinBox->value() > 0);
ok = ok && CheckBaselineSelectionSettings();
}
else if (this->m_Controls.radioButtonUsingT1viaVFA->isChecked())
{
ok = ok && (m_Controls.FlipangleSpinBox->value() > 0);
ok = ok && (m_Controls.TRSpinBox->value() > 0);
ok = ok && (m_Controls.RelaxivitySpinBox->value() > 0);
ok = ok && (m_Controls.PDWImageNodeSelector->GetSelectedNode().IsNotNull());
ok = ok && CheckBaselineSelectionSettings();
}
else
{
ok = false;
}
}
else if (this->m_Controls.radioButton_T2->isChecked())
{
ok = ok && m_Controls.T2EchoTimeSpinBox->value() > 0;
ok = ok && m_Controls.T2FactorSpinBox->value() > 0;
ok = ok && CheckBaselineSelectionSettings();
}
else
{
ok = false;
}
return ok;
}
bool ConcentrationCurveConverterView::CheckBaselineSelectionSettings() const
{
if (this->m_Controls.radioButton_T1->isChecked())
{
return m_Controls.spinBox_baselineStartTimeStep->value() <= m_Controls.spinBox_baselineEndTimeStep->value();
}
else if (this->m_Controls.radioButton_T2->isChecked())
{
return m_Controls.spinBox_baselineStartTimeStepT2->value() <= m_Controls.spinBox_baselineEndTimeStepT2->value();
}
else
{
return 0;
}
}
void ConcentrationCurveConverterView::OnConvertToConcentrationButtonClicked()
{
mitk::Image::Pointer concentrationImage;
mitk::DataNode::Pointer concentrationNode;
if(m_Controls.radioButton_T1->isChecked())
{
if(m_Controls.radioButton4D->isChecked())
{
concentrationImage = this->Convert4DConcentrationImage(this->m_selectedImage);
}
else if(m_Controls.radioButton3D->isChecked())
{
concentrationImage = Convert3DConcentrationImage(this->m_selectedImage, this->m_selectedBaselineImage);
}
}
else if(m_Controls.radioButton_T2->isChecked())
{
concentrationImage = this->ConvertT2ConcentrationImgage(this->m_selectedImage);
}
std::string nameOfResultImage = m_selectedNode->GetName();
nameOfResultImage.append("_Concentration");
concentrationNode = AddConcentrationImage(concentrationImage,nameOfResultImage);
}
mitk::Image::Pointer ConcentrationCurveConverterView::Convert3DConcentrationImage(mitk::Image::Pointer inputImage,mitk::Image::Pointer baselineImage)
{
typedef itk::Image InputImageType;
InputImageType::Pointer itkInputImage = InputImageType::New();
InputImageType::Pointer itkBaselineImage = InputImageType::New();
mitk::CastToItkImage(inputImage, itkInputImage );
mitk::CastToItkImage(baselineImage, itkBaselineImage );
mitk::Image::Pointer outputImage;
if(this->m_Controls.radioButtonTurboFlash->isChecked())
{
typedef mitk::ConvertToConcentrationTurboFlashFunctor ConversionFunctorTurboFlashType;
typedef itk::BinaryFunctorImageFilter FilterTurboFlashType;
ConversionFunctorTurboFlashType ConversionTurboFlashFunctor;
ConversionTurboFlashFunctor.initialize(m_Controls.relaxationtime->value(), m_Controls.relaxivity->value(), m_Controls.recoverytime->value());
FilterTurboFlashType::Pointer ConversionTurboFlashFilter = FilterTurboFlashType::New();
ConversionTurboFlashFilter->SetFunctor(ConversionTurboFlashFunctor);
ConversionTurboFlashFilter->SetInput1(itkInputImage);
ConversionTurboFlashFilter->SetInput2(itkBaselineImage);
ConversionTurboFlashFilter->Update();
outputImage = mitk::ImportItkImage(ConversionTurboFlashFilter->GetOutput())->Clone();
}
else if(this->m_Controls.radioButton_absoluteEnhancement->isChecked())
{
typedef mitk::ConvertToConcentrationAbsoluteFunctor ConversionFunctorAbsoluteType;
typedef itk::BinaryFunctorImageFilter FilterAbsoluteType;
ConversionFunctorAbsoluteType ConversionAbsoluteFunctor;
ConversionAbsoluteFunctor.initialize(m_Controls.factorSpinBox->value());
FilterAbsoluteType::Pointer ConversionAbsoluteFilter = FilterAbsoluteType::New();
ConversionAbsoluteFilter->SetFunctor(ConversionAbsoluteFunctor);
ConversionAbsoluteFilter->SetInput1(itkInputImage);
ConversionAbsoluteFilter->SetInput2(itkBaselineImage);
ConversionAbsoluteFilter->Update();
outputImage = mitk::ImportItkImage(ConversionAbsoluteFilter->GetOutput())->Clone();
}
else if(m_Controls.radioButton_relativeEnchancement->isChecked())
{
typedef mitk::ConvertToConcentrationRelativeFunctor ConversionFunctorRelativeType;
typedef itk::BinaryFunctorImageFilter FilterRelativeType;
ConversionFunctorRelativeType ConversionRelativeFunctor;
ConversionRelativeFunctor.initialize(m_Controls.factorSpinBox->value());
FilterRelativeType::Pointer ConversionRelativeFilter = FilterRelativeType::New();
ConversionRelativeFilter->SetFunctor(ConversionRelativeFunctor);
ConversionRelativeFilter->SetInput1(itkInputImage);
ConversionRelativeFilter->SetInput2(itkBaselineImage);
ConversionRelativeFilter->Update();
outputImage = mitk::ImportItkImage(ConversionRelativeFilter->GetOutput())->Clone();
}
return outputImage;
}
mitk::DataNode::Pointer ConcentrationCurveConverterView::AddConcentrationImage(mitk::Image* image, std::string nodeName) const
{
if (!image)
{
mitkThrow() << "Cannot generate concentration node. Passed image is null. parameter name: ";
}
mitk::DataNode::Pointer result = mitk::DataNode::New();
result->SetData(image);
result->SetName(nodeName);
result->SetVisibility(true);
this->GetDataStorage()->Add(result, m_selectedNode);
return result;
};
mitk::Image::Pointer ConcentrationCurveConverterView::Convert4DConcentrationImage(mitk::Image::Pointer inputImage)
{
//Compute Concentration image
mitk::ConcentrationCurveGenerator::Pointer concentrationGen =
mitk::ConcentrationCurveGenerator::New();
concentrationGen->SetDynamicImage(inputImage);
concentrationGen->SetisTurboFlashSequence(m_Controls.radioButtonTurboFlash->isChecked());
concentrationGen->SetAbsoluteSignalEnhancement(m_Controls.radioButton_absoluteEnhancement->isChecked());
concentrationGen->SetRelativeSignalEnhancement(m_Controls.radioButton_relativeEnchancement->isChecked());
concentrationGen->SetUsingT1Map(m_Controls.radioButtonUsingT1viaVFA->isChecked());
concentrationGen->SetBaselineStartTimeStep(m_Controls.spinBox_baselineStartTimeStepT2->value());
concentrationGen->SetBaselineEndTimeStep(m_Controls.spinBox_baselineEndTimeStepT2->value());
concentrationGen->SetisT2weightedImage(false);
if (m_Controls.radioButtonTurboFlash->isChecked())
{
concentrationGen->SetRecoveryTime(m_Controls.recoverytime->value());
concentrationGen->SetRelaxationTime(m_Controls.relaxationtime->value());
concentrationGen->SetRelaxivity(m_Controls.relaxivity->value());
concentrationGen->SetBaselineStartTimeStep(m_Controls.spinBox_baselineStartTimeStep->value());
concentrationGen->SetBaselineEndTimeStep(m_Controls.spinBox_baselineEndTimeStep->value());
}
else if (this->m_Controls.radioButtonUsingT1viaVFA->isChecked())
{
concentrationGen->SetRecoveryTime(m_Controls.TRSpinBox->value());
concentrationGen->SetRelaxivity(m_Controls.RelaxivitySpinBox->value());
concentrationGen->SetT10Image(dynamic_cast(m_Controls.PDWImageNodeSelector->GetSelectedNode()->GetData()));
concentrationGen->SetBaselineStartTimeStep(m_Controls.spinBox_baselineStartTimeStep->value());
concentrationGen->SetBaselineEndTimeStep(m_Controls.spinBox_baselineEndTimeStep->value());
//Convert Flipangle from degree to radiant
double alpha = m_Controls.FlipangleSpinBox->value()/360*2* boost::math::constants::pi();
concentrationGen->SetFlipAngle(alpha);
}
else
{
concentrationGen->SetFactor(m_Controls.factorSpinBox->value());
concentrationGen->SetBaselineStartTimeStep(m_Controls.spinBox_baselineStartTimeStep->value());
concentrationGen->SetBaselineEndTimeStep(m_Controls.spinBox_baselineEndTimeStep->value());
}
mitk::Image::Pointer concentrationImage = concentrationGen->GetConvertedImage();
return concentrationImage;
}
mitk::Image::Pointer ConcentrationCurveConverterView::ConvertT2ConcentrationImgage(mitk::Image::Pointer inputImage)
{
//Compute Concentration image
mitk::ConcentrationCurveGenerator::Pointer concentrationGen =
mitk::ConcentrationCurveGenerator::New();
concentrationGen->SetDynamicImage(inputImage);
concentrationGen->SetisTurboFlashSequence(false);
concentrationGen->SetAbsoluteSignalEnhancement(false);
concentrationGen->SetRelativeSignalEnhancement(false);
concentrationGen->SetisT2weightedImage(true);
concentrationGen->SetT2Factor(m_Controls.T2FactorSpinBox->value());
concentrationGen->SetT2EchoTime(m_Controls.T2EchoTimeSpinBox->value());
concentrationGen->SetBaselineStartTimeStep(m_Controls.spinBox_baselineStartTimeStep->value());
concentrationGen->SetBaselineEndTimeStep(m_Controls.spinBox_baselineEndTimeStep->value());
mitk::Image::Pointer concentrationImage = concentrationGen->GetConvertedImage();
return concentrationImage;
}
void ConcentrationCurveConverterView::OnNodeSelectionChanged(QList/*nodes*/)
{
m_selectedNode = nullptr;
m_selectedImage = nullptr;
m_selectedBaselineNode = nullptr;
m_selectedBaselineImage = nullptr;
if (m_Controls.radioButton_T1->isChecked())
{
if (m_Controls.radioButton4D->isChecked())
{
if (m_Controls.timeSeriesNodeSelector->GetSelectedNode().IsNotNull())
{
this->m_selectedNode = m_Controls.timeSeriesNodeSelector->GetSelectedNode();
m_selectedImage = dynamic_cast(m_selectedNode->GetData());
}
else
{
this->m_selectedNode = nullptr;
this->m_selectedImage = nullptr;
}
}
else if (m_Controls.radioButton3D->isChecked())
{
if (m_Controls.image3DNodeSelector->GetSelectedNode().IsNotNull() && m_Controls.baselineImageNodeSelector->GetSelectedNode().IsNotNull())
{
this->m_selectedNode = m_Controls.image3DNodeSelector->GetSelectedNode();
m_selectedImage = dynamic_cast(m_selectedNode->GetData());
this->m_selectedBaselineNode = m_Controls.baselineImageNodeSelector->GetSelectedNode();
m_selectedBaselineImage = dynamic_cast(m_selectedBaselineNode->GetData());
}
else
{
this->m_selectedNode = nullptr;
this->m_selectedImage = nullptr;
m_selectedBaselineNode = nullptr;
m_selectedBaselineImage = nullptr;
}
}
if (this->m_selectedImage.IsNotNull())
{
m_Controls.spinBox_baselineStartTimeStep->setMaximum((this->m_selectedImage->GetDimension(3)) - 1);
m_Controls.spinBox_baselineEndTimeStep->setMaximum((this->m_selectedImage->GetDimension(3)) - 1);
}
}
if (m_Controls.radioButton_T2->isChecked())
{
if (m_Controls.t2TimeSeriesNodeSelector->GetSelectedNode().IsNotNull())
{
this->m_selectedNode = m_Controls.t2TimeSeriesNodeSelector->GetSelectedNode();
m_selectedImage = dynamic_cast(m_selectedNode->GetData());
}
else
{
this->m_selectedNode = nullptr;
this->m_selectedImage = nullptr;
}
if (this->m_selectedImage.IsNotNull())
{
m_Controls.spinBox_baselineStartTimeStepT2->setMaximum((this->m_selectedImage->GetDimension(3)) - 1);
m_Controls.spinBox_baselineEndTimeStepT2->setMaximum((this->m_selectedImage->GetDimension(3)) - 1);
}
}
m_Controls.btnConvertToConcentration->setEnabled(m_selectedImage.IsNotNull() && CheckSettings());
}
ConcentrationCurveConverterView::ConcentrationCurveConverterView()
{
mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage");
mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image");
mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary);
mitk::NodePredicateDimension::Pointer is3D = mitk::NodePredicateDimension::New(3);
mitk::NodePredicateOr::Pointer isMask = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet);
mitk::NodePredicateAnd::Pointer isNoMask = mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isMask));
mitk::NodePredicateAnd::Pointer is3DImage = mitk::NodePredicateAnd::New(isImage, is3D, isNoMask);
this->m_IsMaskPredicate = mitk::NodePredicateAnd::New(isMask, mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer();
this->m_IsNoMaskImagePredicate = mitk::NodePredicateAnd::New(isNoMask, mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer();
auto isDynamicData = mitk::NodePredicateFunction::New([](const mitk::DataNode* node)
{
return (node && node->GetData() && node->GetData()->GetTimeSteps() > 1);
});
auto modelFitResultRelationRule = mitk::ModelFitResultRelationRule::New();
auto isNoModelFitNodePredicate = mitk::NodePredicateNot::New(modelFitResultRelationRule->GetConnectedSourcesDetector());
this->m_isValidPDWImagePredicate = mitk::NodePredicateAnd::New(is3DImage, isNoModelFitNodePredicate);
this->m_isValidTimeSeriesImagePredicate = mitk::NodePredicateAnd::New(isDynamicData, isImage, isNoMask);
}
diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.cpp
index 58a2b09b74..8a3f465aff 100644
--- a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.cpp
+++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.cpp
@@ -1,216 +1,216 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include
#include
#include "mitkWorkbenchUtil.h"
#include "PerfusionCurveDescriptionParameterView.h"
#include "QmitkDescriptionParameterBackgroundJob.h"
#include "mitkAreaUnderTheCurveDescriptionParameter.h"
#include "mitkAreaUnderFirstMomentDescriptionParameter.h"
#include "mitkMeanResidenceTimeDescriptionParameter.h"
#include "mitkTimeToPeakCurveDescriptionParameter.h"
#include "mitkMaximumCurveDescriptionParameter.h"
#include "mitkPixelBasedDescriptionParameterImageGenerator.h"
#include "mitkCurveParameterFunctor.h"
#include "mitkExtractTimeGrid.h"
#include
const std::string PerfusionCurveDescriptionParameterView::VIEW_ID =
- "org.mitk.gui.qt.pharmacokinetics.curvedescriptor";
+ "org.mitk.views.pharmacokinetics.curvedescriptor";
void PerfusionCurveDescriptionParameterView::SetFocus()
{
m_Controls.btnCalculateParameters->setFocus();
}
void PerfusionCurveDescriptionParameterView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_Controls.btnCalculateParameters->setEnabled(false);
connect(m_Controls.btnCalculateParameters, SIGNAL(clicked()), this,
SLOT(OnCalculateParametersButtonClicked()));
InitParameterList();
}
void PerfusionCurveDescriptionParameterView::OnSelectionChanged(
berry::IWorkbenchPart::Pointer /*source*/, const QList& /*nodes*/)
{
m_Controls.btnCalculateParameters->setEnabled(false);
QList dataNodes = this->GetDataManagerSelection();
if (dataNodes.empty())
{
m_selectedNode = nullptr;
m_selectedImage = nullptr;
}
else
{
m_selectedNode = dataNodes[0];
m_selectedImage = dynamic_cast(m_selectedNode->GetData());
}
m_Controls.lableSelectedImage->setText("No series selected.");
if (m_selectedImage.IsNotNull())
{
if (m_selectedImage->GetTimeGeometry()->CountTimeSteps() > 1)
{
m_Controls.btnCalculateParameters->setEnabled(true);
m_Controls.lableSelectedImage->setText((this->m_selectedNode->GetName()).c_str());
}
else
{
this->OnJobStatusChanged("Cannot compute parameters. Selected image must have multiple time steps.");
}
}
else if (m_selectedNode.IsNotNull())
{
this->OnJobStatusChanged("Cannot compute parameters. Selected node is not an image.");
}
else
{
this->OnJobStatusChanged("Cannot compute parameters. No node selected.");
}
}
PerfusionCurveDescriptionParameterView::PerfusionCurveDescriptionParameterView()
{
m_selectedNode = nullptr;
m_selectedImage = nullptr;
m_selectedMask = nullptr;
}
void PerfusionCurveDescriptionParameterView::InitParameterList()
{
m_ParameterMap.clear();
mitk::CurveDescriptionParameterBase::Pointer parameterFunction =
mitk::AreaUnderTheCurveDescriptionParameter::New().GetPointer();
m_ParameterMap.insert(std::make_pair(ParameterNameType("AUC"), parameterFunction));
parameterFunction = mitk::AreaUnderFirstMomentDescriptionParameter::New().GetPointer();
m_ParameterMap.insert(std::make_pair(ParameterNameType("AUMC"), parameterFunction));
parameterFunction = mitk::MeanResidenceTimeDescriptionParameter::New().GetPointer();
m_ParameterMap.insert(std::make_pair(ParameterNameType("MRT"), parameterFunction));
parameterFunction = mitk::MaximumCurveDescriptionParameter::New().GetPointer();
m_ParameterMap.insert(std::make_pair(ParameterNameType("Maximum"), parameterFunction));
parameterFunction = mitk::TimeToPeakCurveDescriptionParameter::New().GetPointer();
m_ParameterMap.insert(std::make_pair(ParameterNameType("TimeToPeak"), parameterFunction));
for (ParameterMapType::const_iterator pos = m_ParameterMap.begin(); pos != m_ParameterMap.end();
++pos)
{
QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(pos->first),
this->m_Controls.parameterlist);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
}
};
void PerfusionCurveDescriptionParameterView::ConfigureFunctor(mitk::CurveParameterFunctor* functor)
const
{
functor->SetGrid(mitk::ExtractTimeGrid(m_selectedImage));
for (int pos = 0; pos < this->m_Controls.parameterlist->count(); ++pos)
{
QListWidgetItem* item = this->m_Controls.parameterlist->item(pos);
mitk::CurveDescriptionParameterBase::Pointer parameterFunction = m_ParameterMap.at(
item->text().toStdString());
if (item->checkState() == Qt::Checked)
{
functor->RegisterDescriptionParameter(item->text().toStdString(), parameterFunction);
}
}
}
void PerfusionCurveDescriptionParameterView::OnCalculateParametersButtonClicked()
{
mitk::PixelBasedDescriptionParameterImageGenerator::Pointer generator =
mitk::PixelBasedDescriptionParameterImageGenerator::New();
mitk::CurveParameterFunctor::Pointer functor = mitk::CurveParameterFunctor::New();
this->ConfigureFunctor(functor);
generator->SetFunctor(functor);
generator->SetDynamicImage(m_selectedImage);
generator->SetMask(m_selectedMask);
/////////////////////////
//create job and put it into the thread pool
DescriptionParameterBackgroundJob* pJob = new DescriptionParameterBackgroundJob(generator,
this->m_selectedNode);
pJob->setAutoDelete(true);
connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnJobError(QString)));
connect(pJob, SIGNAL(Finished()), this, SLOT(OnJobFinished()));
connect(pJob, SIGNAL(ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType,
const DescriptionParameterBackgroundJob*)), this,
SLOT(OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType,
const DescriptionParameterBackgroundJob*)), Qt::BlockingQueuedConnection);
connect(pJob, SIGNAL(JobProgress(double)), this, SLOT(OnJobProgress(double)));
connect(pJob, SIGNAL(JobStatusChanged(QString)), this, SLOT(OnJobStatusChanged(QString)));
QThreadPool* threadPool = QThreadPool::globalInstance();
threadPool->start(pJob);
}
void PerfusionCurveDescriptionParameterView::OnJobFinished()
{
this->m_Controls.infoBox->append(QString("Fitting finished"));
};
void PerfusionCurveDescriptionParameterView::OnJobError(QString err)
{
MITK_ERROR << err.toStdString().c_str();
m_Controls.infoBox->append(QString("") + err + QString(""));
};
void PerfusionCurveDescriptionParameterView::OnJobResultsAreAvailable(
mitk::modelFit::ModelFitResultNodeVectorType results, const DescriptionParameterBackgroundJob* pJob)
{
for (auto image : results)
{
this->GetDataStorage()->Add(image, pJob->GetParentNode());
}
};
void PerfusionCurveDescriptionParameterView::OnJobProgress(double progress)
{
this->m_Controls.progressBar->setValue(100 * progress);
QString report = QString("Progress. ") + QString::number(progress);
this->m_Controls.infoBox->append(report);
};
void PerfusionCurveDescriptionParameterView::OnJobStatusChanged(QString info)
{
this->m_Controls.infoBox->append(info);
MITK_INFO << info.toStdString().c_str();
}
diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp
index 9ee2b5e3f5..5158170817 100644
--- a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp
+++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp
@@ -1,1485 +1,1485 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "MRPerfusionView.h"
#include "boost/tokenizer.hpp"
#include "boost/math/constants/constants.hpp"
#include
#include "mitkWorkbenchUtil.h"
#include "mitkAterialInputFunctionGenerator.h"
#include "mitkConcentrationCurveGenerator.h"
#include
#include
#include
#include "mitkThreeStepLinearModelFactory.h"
#include "mitkThreeStepLinearModelParameterizer.h"
#include "mitkTwoStepLinearModelFactory.h"
#include "mitkTwoStepLinearModelParameterizer.h"
#include
#include
#include
#include
#include "mitkTwoCompartmentExchangeModelFactory.h"
#include "mitkTwoCompartmentExchangeModelParameterizer.h"
#include "mitkNumericTwoCompartmentExchangeModelFactory.h"
#include "mitkNumericTwoCompartmentExchangeModelParameterizer.h"
#include
#include
#include
#include
#include
#include
#include
#include "mitkNodePredicateFunction.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// Includes for image casting between ITK and MITK
#include