diff --git a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp b/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp index c5edc79596..ba4897ef7f 100644 --- a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp +++ b/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp @@ -1,193 +1,184 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // MITK #include "mitkNeedleProjectionFilter.h" #include #include "mitkUSCombinedModality.h" // VTK #include - - mitk::NeedleProjectionFilter::NeedleProjectionFilter() : m_Projection(mitk::PointSet::New()), m_OriginalPoints(mitk::PointSet::New()), m_SelectedInput(-1) { // Tool Coordinates:x axis is chosen as default axis when no axis is specified - - MITK_INFO << "Constructor called"; - - mitk::Point3D point; - point.SetElement(0, 1 * 400); - point.SetElement(1, 0 * 400); - point.SetElement(2, 0 * 400); - m_OriginalPoints->InsertPoint(point); - - mitk::Point3D point1; - point1.SetElement(0, 0 * 400); - point1.SetElement(1, 0 * 400); - point1.SetElement(2, 0 * 400); - m_OriginalPoints->InsertPoint(point1); - - mitk::Point3D point2; - point2.SetElement(0, -1 * 400); - point2.SetElement(1, 0 * 400); - point2.SetElement(2, 0 * 400); - m_OriginalPoints->InsertPoint(point2); - - MITK_INFO << "orginal point 0 set constructor" << m_OriginalPoints->GetPoint(0); - MITK_INFO << "orginal point 1 set constructor" << m_OriginalPoints->GetPoint(1); + + MITK_DEBUG << "Constructor called"; + + mitk::Point3D point; + point.SetElement(0, 1 * 400); + point.SetElement(1, 0 * 400); + point.SetElement(2, 0 * 400); + m_OriginalPoints->InsertPoint(point); + + mitk::Point3D point1; + point1.SetElement(0, 0 * 400); + point1.SetElement(1, 0 * 400); + point1.SetElement(2, 0 * 400); + m_OriginalPoints->InsertPoint(point1); + + mitk::Point3D point2; + point2.SetElement(0, -1 * 400); + point2.SetElement(1, 0 * 400); + point2.SetElement(2, 0 * 400); + m_OriginalPoints->InsertPoint(point2); + + MITK_DEBUG << "orginal point 0 set constructor" << m_OriginalPoints->GetPoint(0); + MITK_DEBUG << "orginal point 1 set constructor" << m_OriginalPoints->GetPoint(1); } void mitk::NeedleProjectionFilter::SetToolAxisForFilter(mitk::Point3D point) { - m_startPoint.SetElement(0, point.GetElement(0) * 400); m_startPoint.SetElement(1, point.GetElement(1) * 400); m_startPoint.SetElement(2, point.GetElement(2) * 400); m_OriginalPoints->SetPoint(0, m_startPoint); - MITK_INFO << "orginal point 0 set mutator" << m_OriginalPoints->GetPoint(0); - - // Tool Coordinates: First point - Tip of Needle, Second Point - 40 cm distance from needle - //mitk::Point3D originPoint; - // originPoint.SetElement(0, 0); - //originPoint.SetElement(1, 0); - //originPoint.SetElement(2, 0); - //m_OriginalPoints->SetPoint(1, originPoint); m_endPoint.SetElement(0, point.GetElement(0) * -400); m_endPoint.SetElement(1, point.GetElement(1) * -400); m_endPoint.SetElement(2, point.GetElement(2) * -400); m_OriginalPoints->SetPoint(1, m_endPoint); - MITK_INFO << "orginal point 1 set mutator" << m_OriginalPoints->GetPoint(1); + + MITK_DEBUG << "orginal point 1 set mutator" << m_OriginalPoints->GetPoint(1); + MITK_DEBUG << "orginal point 0 set mutator" << m_OriginalPoints->GetPoint(0); } mitk::NeedleProjectionFilter::~NeedleProjectionFilter() { } void mitk::NeedleProjectionFilter::SelectInput(int i) { if (i < 0) mitkThrow() << "Negative Input selected in NeedleProjectionFilter"; if (! (static_cast(i) < this->GetInputs().size())) mitkThrow() << "Selected input index is larger than actual number of inputs in NeedleProjectionFilter"; m_SelectedInput = i; } void mitk::NeedleProjectionFilter::GenerateData() { // copy the navigation data from the inputs to the outputs mitk::NavigationDataPassThroughFilter::GenerateData(); // If no reference has been set yet, warn and abort if (m_SelectedInput == -1) { MITK_INFO << "No input has been selected in NeedleProjection Filter. Only forwarding NavigationData..."; return; } // Cancel, if selected tool is currently not being tracked if (! GetInput(m_SelectedInput)->IsDataValid()) return; // Outputs have been updated, now to calculate the Projection // 1) Generate Pseudo-Geometry for Input mitk::AffineTransform3D::Pointer refTrans = this->NavigationDataToTransform(this->GetInput(m_SelectedInput)); mitk::Geometry3D::Pointer refGeom = this->TransformToGeometry(refTrans); // 2) Transform Original Pointset m_OriginalPoints->SetGeometry(refGeom); // Update Projection (We do not clone, since we want to keep properties alive) m_Projection->SetPoint(0, m_OriginalPoints->GetPoint(0)); m_Projection->SetPoint(1, m_OriginalPoints->GetPoint(1)); m_Projection->SetPoint(2, m_OriginalPoints->GetPoint(2)); //m_Projection->SetPoint(2, m_OriginalPoints->GetPoint(2)); // 3a) If no target Plane has been set, then leave it at that if (this->m_TargetPlane.IsNull()) return; // 3b) else, calculate intersection with plane mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); plane->SetIndexToWorldTransform(m_TargetPlane); //plane->TransferItkToVtkTransform(); //included in SetIndexToWorldTransform double t; double x[3]; // Points that define the needle vector double p1[3] = {m_OriginalPoints->GetPoint(1)[0], m_OriginalPoints->GetPoint(1)[1], m_OriginalPoints->GetPoint(1)[2]}; double p2[3] = {m_OriginalPoints->GetPoint(2)[0], m_OriginalPoints->GetPoint(2)[1], m_OriginalPoints->GetPoint(2)[2]}; // Center of image plane and it's normal double center[3] = {plane->GetCenter()[0], plane->GetCenter()[1], plane->GetCenter()[2]}; double normal[3] = {plane->GetNormal()[0], plane->GetNormal()[1], plane->GetNormal()[2]}; vtkPlane::IntersectWithLine(p1, p2, normal, center, t, x); // change (cut) needle path only if the needle points to the image plane; // otherwise the needle path direction would be changed pointing to the image plane if ( t >= 0 ) { // Convert vtk to itk mitk::Point3D intersection; intersection[0] = x[0]; intersection[1] = x[1]; intersection[2] = x[2]; // Replace distant point with image intersection m_Projection->SetPoint(2, intersection); } } mitk::AffineTransform3D::Pointer mitk::NeedleProjectionFilter::NavigationDataToTransform(const mitk::NavigationData * nd) { mitk::AffineTransform3D::Pointer affineTransform = mitk::AffineTransform3D::New(); affineTransform->SetIdentity(); //calculate the transform from the quaternions static itk::QuaternionRigidTransform::Pointer quatTransform = itk::QuaternionRigidTransform::New(); mitk::NavigationData::OrientationType orientation = nd->GetOrientation(); // convert mitk::ScalarType quaternion to double quaternion because of itk bug vnl_quaternion doubleQuaternion(orientation.x(), orientation.y(), orientation.z(), orientation.r()); quatTransform->SetIdentity(); quatTransform->SetRotation(doubleQuaternion); quatTransform->Modified(); /* because of an itk bug, the transform can not be calculated with float data type. To use it in the mitk geometry classes, it has to be transfered to mitk::ScalarType which is float */ static AffineTransform3D::MatrixType m; mitk::TransferMatrix(quatTransform->GetMatrix(), m); affineTransform->SetMatrix(m); /*set the offset by convert from itkPoint to itkVector and setting offset of transform*/ mitk::Vector3D pos; pos.SetVnlVector(nd->GetPosition().GetVnlVector()); affineTransform->SetOffset(pos); affineTransform->Modified(); return affineTransform; } mitk::Geometry3D::Pointer mitk::NeedleProjectionFilter::TransformToGeometry(mitk::AffineTransform3D::Pointer transform){ mitk::Geometry3D::Pointer g3d = mitk::Geometry3D::New(); mitk::ScalarType scale[] = {1.0, 1.0, 1.0}; g3d->SetSpacing(scale); g3d->SetIndexToWorldTransform(transform); //g3d->TransferItkToVtkTransform(); // update VTK Transform for rendering too //included in SetIndexToWorldTransform g3d->Modified(); return g3d; } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp index e8aa2fd09f..f8edc7a2fa 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp @@ -1,808 +1,807 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "USNavigationMarkerPlacement.h" #include "ui_USNavigationMarkerPlacement.h" #include "NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h" #include "NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h" #include "NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h" #include "NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h" #include "NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h" #include "NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h" #include "SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h" #include "mitkIRenderingManager.h" #include "mitkNodeDisplacementFilter.h" #include "mitkUSCombinedModality.h" #include #include "IO/mitkUSNavigationExperimentLogging.h" #include "IO/mitkUSNavigationStepTimer.h" #include #include #include #include #include #include #include "QmitkRenderWindow.h" #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" #include "mitkLayoutAnnotationRenderer.h" // scene serialization #include #include #include #include #include const std::string USNavigationMarkerPlacement::VIEW_ID = "org.mitk.views.usmarkerplacement"; const char *USNavigationMarkerPlacement::DATANAME_TUMOUR = "Tumour"; const char *USNavigationMarkerPlacement::DATANAME_TARGETSURFACE = "Target Surface"; const char *USNavigationMarkerPlacement::DATANAME_ZONES = "Zones"; const char *USNavigationMarkerPlacement::DATANAME_TARGETS = "Targets"; const char *USNavigationMarkerPlacement::DATANAME_TARGETS_PATHS = "Target Paths"; const char *USNavigationMarkerPlacement::DATANAME_REACHED_TARGETS = "Reached Targets"; USNavigationMarkerPlacement::USNavigationMarkerPlacement() - : m_UpdateTimer(new QTimer(this)), - m_ImageAndNavigationDataLoggingTimer(new QTimer(this)), - m_StdMultiWidget(0), - m_ReinitAlreadyDone(false), - m_IsExperimentRunning(false), - m_NavigationStepTimer(mitk::USNavigationStepTimer::New()), - m_ExperimentLogging(mitk::USNavigationExperimentLogging::New()), - m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()), - m_IconRunning(QPixmap(":/USNavigation/record.png")), - m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")), - m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()), - m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()), - m_SceneNumber(1), - m_WarnOverlay(mitk::TextAnnotation2D::New()), - m_ListenerDeviceChanged(this, &USNavigationMarkerPlacement::OnCombinedModalityPropertyChanged), - m_NeedleIndex(0), - m_MarkerIndex(1), - ui(new Ui::USNavigationMarkerPlacement) + : m_UpdateTimer(new QTimer(this)), + m_ImageAndNavigationDataLoggingTimer(new QTimer(this)), + m_StdMultiWidget(0), + m_ReinitAlreadyDone(false), + m_IsExperimentRunning(false), + m_NavigationStepTimer(mitk::USNavigationStepTimer::New()), + m_ExperimentLogging(mitk::USNavigationExperimentLogging::New()), + m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()), + m_IconRunning(QPixmap(":/USNavigation/record.png")), + m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")), + m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()), + m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()), + m_SceneNumber(1), + m_WarnOverlay(mitk::TextAnnotation2D::New()), + m_ListenerDeviceChanged(this, &USNavigationMarkerPlacement::OnCombinedModalityPropertyChanged), + m_NeedleIndex(0), + m_MarkerIndex(1), + ui(new Ui::USNavigationMarkerPlacement) { - connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnTimeout())); - connect( - m_ImageAndNavigationDataLoggingTimer, SIGNAL(timeout()), this, SLOT(OnImageAndNavigationDataLoggingTimeout())); + connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnTimeout())); + connect( + m_ImageAndNavigationDataLoggingTimer, SIGNAL(timeout()), this, SLOT(OnImageAndNavigationDataLoggingTimeout())); - // scale running (and not running) icon the specific height - m_IconRunning = m_IconRunning.scaledToHeight(20, Qt::SmoothTransformation); - m_IconNotRunning = m_IconNotRunning.scaledToHeight(20, Qt::SmoothTransformation); + // scale running (and not running) icon the specific height + m_IconRunning = m_IconRunning.scaledToHeight(20, Qt::SmoothTransformation); + m_IconNotRunning = m_IconNotRunning.scaledToHeight(20, Qt::SmoothTransformation); - // set prefix for experiment logging (only keys with this prefix are taken - // into consideration - m_ExperimentLogging->SetKeyPrefix("USNavigation::"); + // set prefix for experiment logging (only keys with this prefix are taken + // into consideration + m_ExperimentLogging->SetKeyPrefix("USNavigation::"); - m_UpdateTimer->start(33); // every 33 Milliseconds = 30 Frames/Second + m_UpdateTimer->start(33); // every 33 Milliseconds = 30 Frames/Second } USNavigationMarkerPlacement::~USNavigationMarkerPlacement() { - // remove listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); - } + // remove listener for ultrasound device changes + if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) + { + m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); + } // remove listener for ultrasound device changes if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } delete ui; } void USNavigationMarkerPlacement::OnChangeAblationZone(int id, int newSize) { - if ((m_AblationZonesVector.size() < id) || (id < 0)) - { - return; - } - - MITK_INFO << "Ablation Zone " << id << " changed, new size: " << newSize; - - // create a vtk sphere with given radius - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(newSize / 2); - vtkData->SetCenter(0, 0, 0); - vtkData->SetPhiResolution(20); - vtkData->SetThetaResolution(20); - vtkData->Update(); - - mitk::Surface::Pointer zoneSurface = dynamic_cast(m_AblationZonesVector.at(id)->GetData()); - zoneSurface->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); + if ((m_AblationZonesVector.size() < id) || (id < 0)) + { + return; + } + + MITK_INFO << "Ablation Zone " << id << " changed, new size: " << newSize; + + // create a vtk sphere with given radius + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(newSize / 2); + vtkData->SetCenter(0, 0, 0); + vtkData->SetPhiResolution(20); + vtkData->SetThetaResolution(20); + vtkData->Update(); + + mitk::Surface::Pointer zoneSurface = dynamic_cast(m_AblationZonesVector.at(id)->GetData()); + zoneSurface->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); } void USNavigationMarkerPlacement::OnAddAblationZone(int size) { - m_AblationZonesDisplacementFilter->SetInitialReferencePose( - m_CombinedModality->GetNavigationDataSource()->GetOutput(m_MarkerIndex)); - mitk::DataNode::Pointer NewAblationZone = mitk::DataNode::New(); - - mitk::Point3D origin = m_CombinedModality->GetNavigationDataSource()->GetOutput(m_NeedleIndex)->GetPosition(); - - MITK_INFO("USNavigationLogging") << "Ablation Zone Added, initial size: " << size << ", origin: " << origin; - - mitk::Surface::Pointer zone = mitk::Surface::New(); - - // create a vtk sphere with given radius - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(size / 2); - vtkData->SetCenter(0, 0, 0); - vtkData->SetPhiResolution(20); - vtkData->SetThetaResolution(20); - vtkData->Update(); - zone->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - - // set vtk sphere and origin to data node (origin must be set - // again, because of the new sphere set as data) - NewAblationZone->SetData(zone); - NewAblationZone->GetData()->GetGeometry()->SetOrigin(origin); - mitk::Color SphereColor = mitk::Color(); - // default color - SphereColor[0] = 102; - SphereColor[1] = 0; - SphereColor[2] = 204; - NewAblationZone->SetColor(SphereColor); - NewAblationZone->SetOpacity(0.3); - - // set name of zone - std::stringstream name; - name << "Ablation Zone" << m_AblationZonesVector.size(); - NewAblationZone->SetName(name.str()); - - // add zone to filter - m_AblationZonesDisplacementFilter->AddNode(NewAblationZone); - m_AblationZonesVector.push_back(NewAblationZone); - this->GetDataStorage()->Add(NewAblationZone); + m_AblationZonesDisplacementFilter->SetInitialReferencePose( + m_CombinedModality->GetNavigationDataSource()->GetOutput(m_MarkerIndex)); + mitk::DataNode::Pointer NewAblationZone = mitk::DataNode::New(); + + mitk::Point3D origin = m_CombinedModality->GetNavigationDataSource()->GetOutput(m_NeedleIndex)->GetPosition(); + + MITK_INFO("USNavigationLogging") << "Ablation Zone Added, initial size: " << size << ", origin: " << origin; + + mitk::Surface::Pointer zone = mitk::Surface::New(); + + // create a vtk sphere with given radius + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(size / 2); + vtkData->SetCenter(0, 0, 0); + vtkData->SetPhiResolution(20); + vtkData->SetThetaResolution(20); + vtkData->Update(); + zone->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + + // set vtk sphere and origin to data node (origin must be set + // again, because of the new sphere set as data) + NewAblationZone->SetData(zone); + NewAblationZone->GetData()->GetGeometry()->SetOrigin(origin); + mitk::Color SphereColor = mitk::Color(); + // default color + SphereColor[0] = 102; + SphereColor[1] = 0; + SphereColor[2] = 204; + NewAblationZone->SetColor(SphereColor); + NewAblationZone->SetOpacity(0.3); + + // set name of zone + std::stringstream name; + name << "Ablation Zone" << m_AblationZonesVector.size(); + NewAblationZone->SetName(name.str()); + + // add zone to filter + m_AblationZonesDisplacementFilter->AddNode(NewAblationZone); + m_AblationZonesVector.push_back(NewAblationZone); + this->GetDataStorage()->Add(NewAblationZone); } void USNavigationMarkerPlacement::CreateQtPartControl(QWidget *parent) { - m_Parent = parent; - ui->setupUi(parent); + m_Parent = parent; + ui->setupUi(parent); - connect(ui->navigationProcessWidget, - SIGNAL(SignalCombinedModalityChanged(itk::SmartPointer)), - this, - SLOT(OnCombinedModalityChanged(itk::SmartPointer))); + connect(ui->navigationProcessWidget, + SIGNAL(SignalCombinedModalityChanged(itk::SmartPointer)), + this, + SLOT(OnCombinedModalityChanged(itk::SmartPointer))); - connect(ui->navigationProcessWidget, - SIGNAL(SignalSettingsChanged(itk::SmartPointer)), - this, - SLOT(OnSettingsChanged(itk::SmartPointer))); + connect(ui->navigationProcessWidget, + SIGNAL(SignalSettingsChanged(itk::SmartPointer)), + this, + SLOT(OnSettingsChanged(itk::SmartPointer))); - connect(ui->navigationProcessWidget, - SIGNAL(SignalActiveNavigationStepChanged(int)), - this, - SLOT(OnActiveNavigationStepChanged(int))); + connect(ui->navigationProcessWidget, + SIGNAL(SignalActiveNavigationStepChanged(int)), + this, + SLOT(OnActiveNavigationStepChanged(int))); connect(ui->navigationProcessWidget, SIGNAL(SignalActiveNavigationStepChangeRequested(int)), this, SLOT(OnNextNavigationStepInitialization(int))); - connect(ui->startExperimentButton, SIGNAL(clicked()), this, SLOT(OnStartExperiment())); - connect(ui->finishExperimentButton, SIGNAL(clicked()), this, SLOT(OnFinishExperiment())); + connect(ui->startExperimentButton, SIGNAL(clicked()), this, SLOT(OnStartExperiment())); + connect(ui->finishExperimentButton, SIGNAL(clicked()), this, SLOT(OnFinishExperiment())); connect(ui->m_enableNavigationLayout, SIGNAL(clicked()), this, SLOT(OnChangeLayoutClicked())); - connect(ui->navigationProcessWidget, - SIGNAL(SignalIntermediateResult(const itk::SmartPointer)), - this, - SLOT(OnIntermediateResultProduced(const itk::SmartPointer))); + connect(ui->navigationProcessWidget, + SIGNAL(SignalIntermediateResult(const itk::SmartPointer)), + this, + SLOT(OnIntermediateResultProduced(const itk::SmartPointer))); - ui->navigationProcessWidget->SetDataStorage(this->GetDataStorage()); + ui->navigationProcessWidget->SetDataStorage(this->GetDataStorage()); - // indicate that no experiment is running at start - ui->runningLabel->setPixmap(m_IconNotRunning); + // indicate that no experiment is running at start + ui->runningLabel->setPixmap(m_IconNotRunning); - ui->navigationProcessWidget->SetSettingsWidget(new QmitkUSNavigationCombinedSettingsWidget(m_Parent)); + ui->navigationProcessWidget->SetSettingsWidget(new QmitkUSNavigationCombinedSettingsWidget(m_Parent)); } void USNavigationMarkerPlacement::OnCombinedModalityPropertyChanged(const std::string &key, const std::string &) { - if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) - { - m_ReinitAlreadyDone = false; - this->ReinitOnImage(); - - if (m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsCalibratedForCurrentStatus()) - { - mitk::LayoutAnnotationRenderer::AddAnnotation( - m_WarnOverlay.GetPointer(), "stdmulti.widget1", mitk::LayoutAnnotationRenderer::TopLeft); - MITK_WARN << "No calibration available for the selected ultrasound image depth."; - } - } + if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) + { + m_ReinitAlreadyDone = false; + this->ReinitOnImage(); + + if (m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsCalibratedForCurrentStatus()) + { + mitk::LayoutAnnotationRenderer::AddAnnotation( + m_WarnOverlay.GetPointer(), "stdmulti.widget1", mitk::LayoutAnnotationRenderer::TopLeft); + MITK_WARN << "No calibration available for the selected ultrasound image depth."; + } + } } void USNavigationMarkerPlacement::SetFocus() { - this->ReinitOnImage(); + this->ReinitOnImage(); } void USNavigationMarkerPlacement::OnTimeout() { - if (!m_StdMultiWidget) - { - // try to get the standard multi widget if it couldn't be got before - mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); - - QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); - - // if there is a standard multi widget now, disable the level window and - // change the layout to 2D up and 3d down - if (multiWidgetEditor) - { - m_StdMultiWidget = multiWidgetEditor->GetStdMultiWidget(); - if (m_StdMultiWidget) - { - m_StdMultiWidget->DisableStandardLevelWindow(); - m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(); - } - } - - this->CreateOverlays(); - } - - if (m_CombinedModality.IsNotNull() && - !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing - { - ui->navigationProcessWidget->UpdateNavigationProgress(); - m_AblationZonesDisplacementFilter->Update(); - - // update the 3D window only every fourth time to speed up the rendering (at least in 2D) - this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); - - // make sure that a reinit was performed on the image - this->ReinitOnImage(); - } + if (!m_StdMultiWidget) + { + // try to get the standard multi widget if it couldn't be got before + mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); + + QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); + + // if there is a standard multi widget now, disable the level window and + // change the layout to 2D up and 3d down + if (multiWidgetEditor) + { + m_StdMultiWidget = multiWidgetEditor->GetStdMultiWidget(); + if (m_StdMultiWidget) + { + m_StdMultiWidget->DisableStandardLevelWindow(); + m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(); + } + } + + this->CreateOverlays(); + } + + if (m_CombinedModality.IsNotNull() && + !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing + { + ui->navigationProcessWidget->UpdateNavigationProgress(); + m_AblationZonesDisplacementFilter->Update(); + + // update the 3D window only every fourth time to speed up the rendering (at least in 2D) + this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); + + // make sure that a reinit was performed on the image + this->ReinitOnImage(); + } } void USNavigationMarkerPlacement::OnEnableNavigationLayout() { MITK_INFO << "Navigation Layout"; // try to get the standard multi widget if it couldn't be got before mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); // if there is a standard multi widget now, disable the level window and // change the layout to 2D up and 3d down if (multiWidgetEditor) { m_StdMultiWidget = multiWidgetEditor->GetStdMultiWidget(); if (m_StdMultiWidget) { m_StdMultiWidget->DisableStandardLevelWindow(); m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(); this->GetDataStorage()->GetNamedNode("stdmulti.widget1.plane")->SetVisibility(false); this->GetDataStorage()->GetNamedNode("stdmulti.widget3.plane")->SetVisibility(false); } } } void USNavigationMarkerPlacement::OnResetStandardLayout() { //reset render windows mitk::DataNode::Pointer widget1 = this->GetDataStorage()->GetNamedNode("stdmulti.widget1.plane"); if (widget1.IsNotNull()) { widget1->SetVisibility(true); } mitk::DataNode::Pointer widget3 = this->GetDataStorage()->GetNamedNode("stdmulti.widget3.plane"); if (widget3.IsNotNull()) { widget3->SetVisibility(true); } m_StdMultiWidget->changeLayoutToDefault(); } void USNavigationMarkerPlacement::OnChangeLayoutClicked() { if (ui->m_enableNavigationLayout->isChecked()) OnEnableNavigationLayout(); else OnResetStandardLayout(); } void USNavigationMarkerPlacement::OnImageAndNavigationDataLoggingTimeout() { - // update filter for logging navigation data and ultrasound images - if (m_CombinedModality.IsNotNull()) - { - m_NavigationDataRecorder->Update(); - // get last messages for logging filer and store them - std::vector messages = m_LoggingBackend.GetNavigationMessages(); - std::string composedMessage = ""; - for (int i = 0; i < messages.size(); i++) - { - composedMessage += messages.at(i); - } - m_USImageLoggingFilter->AddMessageToCurrentImage(composedMessage); - m_LoggingBackend.ClearNavigationMessages(); - // update logging filter - m_USImageLoggingFilter->Update(); - } + // update filter for logging navigation data and ultrasound images + if (m_CombinedModality.IsNotNull()) + { + m_NavigationDataRecorder->Update(); + // get last messages for logging filer and store them + std::vector messages = m_LoggingBackend.GetNavigationMessages(); + std::string composedMessage = ""; + for (int i = 0; i < messages.size(); i++) + { + composedMessage += messages.at(i); + } + m_USImageLoggingFilter->AddMessageToCurrentImage(composedMessage); + m_LoggingBackend.ClearNavigationMessages(); + // update logging filter + m_USImageLoggingFilter->Update(); + } } void USNavigationMarkerPlacement::OnStartExperiment() { - // get name for the experiment by a QInputDialog - bool ok; - if (m_ExperimentName.isEmpty()) - { // default: current date - m_ExperimentName = QString::number(QDateTime::currentDateTime().date().year()) + "_" + - QString::number(QDateTime::currentDateTime().date().month()) + "_" + - QString::number(QDateTime::currentDateTime().date().day()) + "_experiment_" + - QString::number(QDateTime::currentDateTime().time().hour()) + "." + - QString::number(QDateTime::currentDateTime().time().minute()); - } - m_ExperimentName = QInputDialog::getText( - m_Parent, QString("Experiment Name"), QString("Name of the Experiment"), QLineEdit::Normal, m_ExperimentName, &ok); - MITK_INFO("USNavigationLogging") << "Experiment started: " << m_ExperimentName.toStdString(); - if (ok && !m_ExperimentName.isEmpty()) - { - // display error message and call the function recursivly if a directory - // with the given name already exists - QDir experimentResultsDir(m_ResultsDirectory + QDir::separator() + m_ExperimentName); - if (experimentResultsDir.exists()) - { - QMessageBox::critical( - m_Parent, "Results Directory Exists", "The result directory already exists.\nPlease choose an other name."); - this->OnStartExperiment(); - } - else - { - QDir(m_ResultsDirectory).mkdir(m_ExperimentName); - m_ExperimentResultsSubDirectory = m_ResultsDirectory + QDir::separator() + m_ExperimentName; - - // experiment is running now - ui->runningLabel->setPixmap(m_IconRunning); - ui->navigationProcessWidget->EnableInteraction(true); - - // (re)start timer for navigation step durations - m_NavigationStepTimer->Reset(); - m_NavigationStepTimer->SetOutputFileName( - QString(m_ExperimentResultsSubDirectory + QDir::separator() + QString("durations.cvs")).toStdString()); - m_NavigationStepTimer->SetActiveIndex(0, m_NavigationSteps.at(0)->GetTitle().toStdString()); - - ui->finishExperimentButton->setEnabled(true); - ui->startExperimentButton->setDisabled(true); - - // initialize and register logging backend - QString loggingFilename = m_ExperimentResultsSubDirectory + QDir::separator() + "logging.txt"; - m_LoggingBackend.SetOutputFileName(loggingFilename.toStdString()); - mbilog::RegisterBackend(&m_LoggingBackend); - - // initialize and start navigation data recorder form xml recording - m_NavigationDataRecorder->StartRecording(); - - m_IsExperimentRunning = true; - - m_ImageAndNavigationDataLoggingTimer->start(1000); - - // (re)start experiment logging and set output file name - m_ExperimentLogging->Reset(); - m_ExperimentLogging->SetFileName( - QString(m_ExperimentResultsSubDirectory + QDir::separator() + "experiment-logging.xml").toStdString()); - } - } + // get name for the experiment by a QInputDialog + bool ok; + if (m_ExperimentName.isEmpty()) + { // default: current date + m_ExperimentName = QString::number(QDateTime::currentDateTime().date().year()) + "_" + + QString::number(QDateTime::currentDateTime().date().month()) + "_" + + QString::number(QDateTime::currentDateTime().date().day()) + "_experiment_" + + QString::number(QDateTime::currentDateTime().time().hour()) + "." + + QString::number(QDateTime::currentDateTime().time().minute()); + } + m_ExperimentName = QInputDialog::getText( + m_Parent, QString("Experiment Name"), QString("Name of the Experiment"), QLineEdit::Normal, m_ExperimentName, &ok); + MITK_INFO("USNavigationLogging") << "Experiment started: " << m_ExperimentName.toStdString(); + if (ok && !m_ExperimentName.isEmpty()) + { + // display error message and call the function recursivly if a directory + // with the given name already exists + QDir experimentResultsDir(m_ResultsDirectory + QDir::separator() + m_ExperimentName); + if (experimentResultsDir.exists()) + { + QMessageBox::critical( + m_Parent, "Results Directory Exists", "The result directory already exists.\nPlease choose an other name."); + this->OnStartExperiment(); + } + else + { + QDir(m_ResultsDirectory).mkdir(m_ExperimentName); + m_ExperimentResultsSubDirectory = m_ResultsDirectory + QDir::separator() + m_ExperimentName; + + // experiment is running now + ui->runningLabel->setPixmap(m_IconRunning); + ui->navigationProcessWidget->EnableInteraction(true); + + // (re)start timer for navigation step durations + m_NavigationStepTimer->Reset(); + m_NavigationStepTimer->SetOutputFileName( + QString(m_ExperimentResultsSubDirectory + QDir::separator() + QString("durations.cvs")).toStdString()); + m_NavigationStepTimer->SetActiveIndex(0, m_NavigationSteps.at(0)->GetTitle().toStdString()); + + ui->finishExperimentButton->setEnabled(true); + ui->startExperimentButton->setDisabled(true); + + // initialize and register logging backend + QString loggingFilename = m_ExperimentResultsSubDirectory + QDir::separator() + "logging.txt"; + m_LoggingBackend.SetOutputFileName(loggingFilename.toStdString()); + mbilog::RegisterBackend(&m_LoggingBackend); + + // initialize and start navigation data recorder form xml recording + m_NavigationDataRecorder->StartRecording(); + + m_IsExperimentRunning = true; + + m_ImageAndNavigationDataLoggingTimer->start(1000); + + // (re)start experiment logging and set output file name + m_ExperimentLogging->Reset(); + m_ExperimentLogging->SetFileName( + QString(m_ExperimentResultsSubDirectory + QDir::separator() + "experiment-logging.xml").toStdString()); + } + } } void USNavigationMarkerPlacement::OnFinishExperiment() { - this->WaitCursorOn(); - - MITK_INFO("USNavigationLogging") << "Experiment finished!"; - MITK_INFO("USNavigationLogging") - << "Position/Orientation of needle tip: " - << (dynamic_cast(m_CombinedModality->GetTrackingDevice()->GetOutput(0)))->GetPosition(); - MITK_INFO("USNavigationLogging") - << "Position of target: " << m_TargetNodeDisplacementFilter->GetRawDisplacementNavigationData(0)->GetPosition(); - MITK_INFO("USNavigationLogging") << "Total duration: " << m_NavigationStepTimer->GetTotalDuration(); - - ui->navigationProcessWidget->FinishCurrentNavigationStep(); - m_ImageAndNavigationDataLoggingTimer->stop(); - - ui->runningLabel->setPixmap(m_IconNotRunning); - ui->navigationProcessWidget->EnableInteraction(false); - - m_NavigationStepTimer->Stop(); - - // make sure that the navigation process will be start from beginning at the - // next experiment - ui->navigationProcessWidget->ResetNavigationProcess(); - - ui->finishExperimentButton->setDisabled(true); - ui->startExperimentButton->setEnabled(true); - - MITK_INFO("USNavigationLogging") << "Writing logging data to " << m_ExperimentResultsSubDirectory.toStdString(); - // save ultrasound images to the file system - QDir(m_ExperimentResultsSubDirectory).mkdir("ImageStream"); - m_USImageLoggingFilter->Update(); - m_USImageLoggingFilter->SetImageFilesExtension(".jpg"); - m_USImageLoggingFilter->SaveImages( - QString(m_ExperimentResultsSubDirectory + QDir::separator() + "ImageStream" + QDir::separator()).toStdString()); - m_USImageLoggingFilter = mitk::USImageLoggingFilter::New(); - - m_NavigationDataRecorder->StopRecording(); - - // Write data to csv and xml file - mitk::IOUtil::SaveBaseData( - m_NavigationDataRecorder->GetNavigationDataSet(), - (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.xml").toStdString().c_str())); - mitk::IOUtil::SaveBaseData( - m_NavigationDataRecorder->GetNavigationDataSet(), - (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.csv").toStdString().c_str())); - - // write logged navigation data messages to separate file - std::stringstream csvNavigationMessagesFilename; - csvNavigationMessagesFilename << m_ExperimentResultsSubDirectory.toStdString() << QDir::separator().toLatin1() - << "CSVNavigationMessagesLogFile.csv"; - MITK_INFO("USNavigationLogging") << "Writing logged navigation messages to separate csv file: " - << csvNavigationMessagesFilename.str(); - m_LoggingBackend.WriteCSVFileWithNavigationMessages(csvNavigationMessagesFilename.str()); - - mbilog::UnregisterBackend(&m_LoggingBackend); - - m_IsExperimentRunning = false; - - m_ImageAndNavigationDataLoggingTimer->stop(); - m_CombinedModality = 0; - - // reset scene number for next experiment - m_SceneNumber = 1; - - this->WaitCursorOff(); - MITK_INFO("USNavigationLogging") << "Finished!"; + this->WaitCursorOn(); + + MITK_INFO("USNavigationLogging") << "Experiment finished!"; + MITK_INFO("USNavigationLogging") + << "Position/Orientation of needle tip: " + << (dynamic_cast(m_CombinedModality->GetTrackingDevice()->GetOutput(0)))->GetPosition(); + MITK_INFO("USNavigationLogging") + << "Position of target: " << m_TargetNodeDisplacementFilter->GetRawDisplacementNavigationData(0)->GetPosition(); + MITK_INFO("USNavigationLogging") << "Total duration: " << m_NavigationStepTimer->GetTotalDuration(); + + ui->navigationProcessWidget->FinishCurrentNavigationStep(); + m_ImageAndNavigationDataLoggingTimer->stop(); + + ui->runningLabel->setPixmap(m_IconNotRunning); + ui->navigationProcessWidget->EnableInteraction(false); + + m_NavigationStepTimer->Stop(); + + // make sure that the navigation process will be start from beginning at the + // next experiment + ui->navigationProcessWidget->ResetNavigationProcess(); + + ui->finishExperimentButton->setDisabled(true); + ui->startExperimentButton->setEnabled(true); + + MITK_INFO("USNavigationLogging") << "Writing logging data to " << m_ExperimentResultsSubDirectory.toStdString(); + // save ultrasound images to the file system + QDir(m_ExperimentResultsSubDirectory).mkdir("ImageStream"); + m_USImageLoggingFilter->Update(); + m_USImageLoggingFilter->SetImageFilesExtension(".jpg"); + m_USImageLoggingFilter->SaveImages( + QString(m_ExperimentResultsSubDirectory + QDir::separator() + "ImageStream" + QDir::separator()).toStdString()); + m_USImageLoggingFilter = mitk::USImageLoggingFilter::New(); + + m_NavigationDataRecorder->StopRecording(); + + // Write data to csv and xml file + mitk::IOUtil::SaveBaseData( + m_NavigationDataRecorder->GetNavigationDataSet(), + (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.xml").toStdString().c_str())); + mitk::IOUtil::SaveBaseData( + m_NavigationDataRecorder->GetNavigationDataSet(), + (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.csv").toStdString().c_str())); + + // write logged navigation data messages to separate file + std::stringstream csvNavigationMessagesFilename; + csvNavigationMessagesFilename << m_ExperimentResultsSubDirectory.toStdString() << QDir::separator().toLatin1() + << "CSVNavigationMessagesLogFile.csv"; + MITK_INFO("USNavigationLogging") << "Writing logged navigation messages to separate csv file: " + << csvNavigationMessagesFilename.str(); + m_LoggingBackend.WriteCSVFileWithNavigationMessages(csvNavigationMessagesFilename.str()); + + mbilog::UnregisterBackend(&m_LoggingBackend); + + m_IsExperimentRunning = false; + + m_ImageAndNavigationDataLoggingTimer->stop(); + m_CombinedModality = 0; + + // reset scene number for next experiment + m_SceneNumber = 1; + + this->WaitCursorOff(); + MITK_INFO("USNavigationLogging") << "Finished!"; } void USNavigationMarkerPlacement::OnCombinedModalityChanged( - itk::SmartPointer combinedModality) + itk::SmartPointer combinedModality) { - // remove old listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); - } - - m_CombinedModality = combinedModality; - m_ReinitAlreadyDone = false; - - // add a listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->AddPropertyChangedListener(m_ListenerDeviceChanged); - } - - // update navigation data recorder for using the new combined modality - mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource(); - m_NavigationDataRecorder->ConnectTo(navigationDataSource); - m_NavigationDataRecorder->ResetRecording(); + // remove old listener for ultrasound device changes + if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) + { + m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); + } + + m_CombinedModality = combinedModality; + m_ReinitAlreadyDone = false; + + // add a listener for ultrasound device changes + if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) + { + m_CombinedModality->GetUltrasoundDevice()->AddPropertyChangedListener(m_ListenerDeviceChanged); + } + + // update navigation data recorder for using the new combined modality + mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource(); + m_NavigationDataRecorder->ConnectTo(navigationDataSource); + m_NavigationDataRecorder->ResetRecording(); // update ultrasound image logging filter for using the new combined modality mitk::USDevice::Pointer ultrasoundImageSource = combinedModality->GetUltrasoundDevice(); for (unsigned int n = 0; n < ultrasoundImageSource->GetNumberOfIndexedOutputs(); ++n) { m_USImageLoggingFilter->SetInput(n, ultrasoundImageSource->GetOutput(n)); } // update ablation zone filter for using the new combined modality for (unsigned int n = 0; n < navigationDataSource->GetNumberOfIndexedOutputs(); ++n) { m_AblationZonesDisplacementFilter->SetInput(n, navigationDataSource->GetOutput(n)); } m_AblationZonesDisplacementFilter->SelectInput(m_MarkerIndex); // make sure that a reinit is done for the new images this->ReinitOnImage(); } void USNavigationMarkerPlacement::OnSettingsChanged(itk::SmartPointer settings) { - std::string applicationName; - if (!settings->GetStringProperty("settings.application", applicationName)) - { - // set default application if the string property is not available - applicationName = "Marker Placement"; - } - - // create navigation step widgets according to the selected application - if (applicationName != m_CurrentApplicationName) - { - m_CurrentApplicationName = applicationName; + std::string applicationName; + if (!settings->GetStringProperty("settings.application", applicationName)) + { + // set default application if the string property is not available + applicationName = "Marker Placement"; + } + + // create navigation step widgets according to the selected application + if (applicationName != m_CurrentApplicationName) + { + m_CurrentApplicationName = applicationName; QmitkUSNavigationProcessWidget::NavigationStepVector navigationSteps; if (applicationName == "Puncture") { QmitkUSNavigationStepCombinedModality* stepCombinedModality = new QmitkUSNavigationStepCombinedModality(m_Parent); QmitkUSNavigationStepTumourSelection* stepTumourSelection = new QmitkUSNavigationStepTumourSelection(m_Parent); stepTumourSelection->SetTargetSelectionOptional(true); m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); QmitkUSNavigationStepZoneMarking* stepZoneMarking = new QmitkUSNavigationStepZoneMarking(m_Parent); QmitkUSNavigationStepPunctuationIntervention* stepIntervention = new QmitkUSNavigationStepPunctuationIntervention(m_Parent); - connect(stepIntervention, SIGNAL(AddAblationZoneClicked(int)), this, SLOT(OnAddAblationZone(int))); - connect(stepIntervention, SIGNAL(AblationZoneChanged(int, int)), this, SLOT(OnChangeAblationZone(int, int))); - - m_NavigationStepNames = std::vector(); - navigationSteps.push_back(stepCombinedModality); - m_NavigationStepNames.push_back("Combined Modality Initialization"); - navigationSteps.push_back(stepTumourSelection); - m_NavigationStepNames.push_back("Target Selection"); - navigationSteps.push_back(stepZoneMarking); - m_NavigationStepNames.push_back("Critical Structure Marking"); - navigationSteps.push_back(stepIntervention); - m_NavigationStepNames.push_back("Intervention"); - } - else if (applicationName == "Marker Placement") - { - QmitkUSNavigationStepCombinedModality *stepCombinedModality = new QmitkUSNavigationStepCombinedModality(m_Parent); - QmitkUSNavigationStepTumourSelection *stepTumourSelection = new QmitkUSNavigationStepTumourSelection(m_Parent); - m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); - QmitkUSNavigationStepZoneMarking *stepZoneMarking = new QmitkUSNavigationStepZoneMarking(m_Parent); - QmitkUSNavigationStepPlacementPlanning *stepPlacementPlanning = - new QmitkUSNavigationStepPlacementPlanning(m_Parent); - QmitkUSNavigationStepMarkerIntervention *stepMarkerIntervention = - new QmitkUSNavigationStepMarkerIntervention(m_Parent); - - m_NavigationStepNames = std::vector(); - navigationSteps.push_back(stepCombinedModality); - m_NavigationStepNames.push_back("Combined Modality Initialization"); - navigationSteps.push_back(stepTumourSelection); - m_NavigationStepNames.push_back("Target Selection"); - navigationSteps.push_back(stepZoneMarking); - m_NavigationStepNames.push_back("Critical Structure Marking"); - navigationSteps.push_back(stepPlacementPlanning); - m_NavigationStepNames.push_back("Placement Planning"); - navigationSteps.push_back(stepMarkerIntervention); - m_NavigationStepNames.push_back("Marker Intervention"); - } - - // set navigation step widgets to the process widget - ui->navigationProcessWidget->SetNavigationSteps(navigationSteps); - - for (QmitkUSNavigationProcessWidget::NavigationStepIterator it = m_NavigationSteps.begin(); - it != m_NavigationSteps.end(); - ++it) - { - delete *it; - } - m_NavigationSteps.clear(); - m_NavigationSteps = navigationSteps; - } - - // initialize gui according to the experiment mode setting - bool experimentMode = false; - settings->GetBoolProperty("settings.experiment-mode", experimentMode); - ui->startExperimentButton->setVisible(experimentMode); - ui->finishExperimentButton->setVisible(experimentMode); - ui->runningLabel->setVisible(experimentMode); - if (experimentMode && !m_IsExperimentRunning) - { - ui->navigationProcessWidget->ResetNavigationProcess(); - ui->navigationProcessWidget->EnableInteraction(false); - ui->runningLabel->setPixmap(m_IconNotRunning); - } - else if (!experimentMode) - { - if (m_IsExperimentRunning) - { - this->OnFinishExperiment(); - } - ui->navigationProcessWidget->EnableInteraction(true); - } - - // get the results directory from the settings and use home directory if - // there is no results directory configured - std::string resultsDirectory; - if (settings->GetStringProperty("settings.experiment-results-directory", resultsDirectory)) - { - m_ResultsDirectory = QString::fromStdString(resultsDirectory); - } - else - { - m_ResultsDirectory = QDir::homePath(); - } - - // make sure that the results directory exists - QDir resultsDirectoryQDir = QDir(m_ResultsDirectory); - if (!resultsDirectoryQDir.exists()) - { - resultsDirectoryQDir.mkpath(m_ResultsDirectory); - } - - MITK_INFO << "Results Directory: " << m_ResultsDirectory.toStdString(); + connect(stepIntervention, SIGNAL(AddAblationZoneClicked(int)), this, SLOT(OnAddAblationZone(int))); + connect(stepIntervention, SIGNAL(AblationZoneChanged(int, int)), this, SLOT(OnChangeAblationZone(int, int))); + + m_NavigationStepNames = std::vector(); + navigationSteps.push_back(stepCombinedModality); + m_NavigationStepNames.push_back("Combined Modality Initialization"); + navigationSteps.push_back(stepTumourSelection); + m_NavigationStepNames.push_back("Target Selection"); + navigationSteps.push_back(stepZoneMarking); + m_NavigationStepNames.push_back("Critical Structure Marking"); + navigationSteps.push_back(stepIntervention); + m_NavigationStepNames.push_back("Intervention"); + } + else if (applicationName == "Marker Placement") + { + QmitkUSNavigationStepCombinedModality *stepCombinedModality = new QmitkUSNavigationStepCombinedModality(m_Parent); + QmitkUSNavigationStepTumourSelection *stepTumourSelection = new QmitkUSNavigationStepTumourSelection(m_Parent); + m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); + QmitkUSNavigationStepZoneMarking *stepZoneMarking = new QmitkUSNavigationStepZoneMarking(m_Parent); + QmitkUSNavigationStepPlacementPlanning *stepPlacementPlanning = + new QmitkUSNavigationStepPlacementPlanning(m_Parent); + QmitkUSNavigationStepMarkerIntervention *stepMarkerIntervention = + new QmitkUSNavigationStepMarkerIntervention(m_Parent); + + m_NavigationStepNames = std::vector(); + navigationSteps.push_back(stepCombinedModality); + m_NavigationStepNames.push_back("Combined Modality Initialization"); + navigationSteps.push_back(stepTumourSelection); + m_NavigationStepNames.push_back("Target Selection"); + navigationSteps.push_back(stepZoneMarking); + m_NavigationStepNames.push_back("Critical Structure Marking"); + navigationSteps.push_back(stepPlacementPlanning); + m_NavigationStepNames.push_back("Placement Planning"); + navigationSteps.push_back(stepMarkerIntervention); + m_NavigationStepNames.push_back("Marker Intervention"); + } + + // set navigation step widgets to the process widget + ui->navigationProcessWidget->SetNavigationSteps(navigationSteps); + + for (QmitkUSNavigationProcessWidget::NavigationStepIterator it = m_NavigationSteps.begin(); + it != m_NavigationSteps.end(); + ++it) + { + delete *it; + } + m_NavigationSteps.clear(); + m_NavigationSteps = navigationSteps; + } + + // initialize gui according to the experiment mode setting + bool experimentMode = false; + settings->GetBoolProperty("settings.experiment-mode", experimentMode); + ui->startExperimentButton->setVisible(experimentMode); + ui->finishExperimentButton->setVisible(experimentMode); + ui->runningLabel->setVisible(experimentMode); + if (experimentMode && !m_IsExperimentRunning) + { + ui->navigationProcessWidget->ResetNavigationProcess(); + ui->navigationProcessWidget->EnableInteraction(false); + ui->runningLabel->setPixmap(m_IconNotRunning); + } + else if (!experimentMode) + { + if (m_IsExperimentRunning) + { + this->OnFinishExperiment(); + } + ui->navigationProcessWidget->EnableInteraction(true); + } + + // get the results directory from the settings and use home directory if + // there is no results directory configured + std::string resultsDirectory; + if (settings->GetStringProperty("settings.experiment-results-directory", resultsDirectory)) + { + m_ResultsDirectory = QString::fromStdString(resultsDirectory); + } + else + { + m_ResultsDirectory = QDir::homePath(); + } + + // make sure that the results directory exists + QDir resultsDirectoryQDir = QDir(m_ResultsDirectory); + if (!resultsDirectoryQDir.exists()) + { + resultsDirectoryQDir.mkpath(m_ResultsDirectory); + } + + MITK_INFO("USNavigation") << "Results Directory: " << m_ResultsDirectory.toStdString(); } void USNavigationMarkerPlacement::OnActiveNavigationStepChanged(int index) { - // update navigation step timer each time the active navigation step changes - m_NavigationStepTimer->SetActiveIndex(index, m_NavigationSteps.at(index)->GetTitle().toStdString()); - if (m_NavigationStepNames.size() <= index) - { - MITK_INFO("USNavigationLogging") << "Someting went wrong: unknown navigation step!"; - } - else - { - MITK_INFO("USNavigationLogging") << "Navigation step finished/changed, next step: " - << this->m_NavigationStepNames.at(index).toStdString() - << "; duration until now: " << m_NavigationStepTimer->GetTotalDuration(); - } + // update navigation step timer each time the active navigation step changes + m_NavigationStepTimer->SetActiveIndex(index, m_NavigationSteps.at(index)->GetTitle().toStdString()); + if (m_NavigationStepNames.size() <= index) + { + MITK_INFO("USNavigationLogging") << "Someting went wrong: unknown navigation step!"; + } + else + { + MITK_INFO("USNavigationLogging") << "Navigation step finished/changed, next step: " + << this->m_NavigationStepNames.at(index).toStdString() + << "; duration until now: " << m_NavigationStepTimer->GetTotalDuration(); + } } void USNavigationMarkerPlacement::OnNextNavigationStepInitialization(int index) { - MITK_INFO << "Next Step: " << m_NavigationSteps.at(index)->GetTitle().toStdString(); + MITK_DEBUG << "Next Step: " << m_NavigationSteps.at(index)->GetTitle().toStdString(); if (m_NavigationSteps.at(index)->GetTitle().toStdString() == "Computer-assisted Intervention") { - MITK_INFO << "Initializing Navigation Step Puncture"; QmitkUSNavigationStepPunctuationIntervention* navigationStepPunctuationIntervention = static_cast(m_NavigationSteps.at(index)); if (navigationStepPunctuationIntervention != nullptr) { if (m_CurrentStorage.IsNull()) { this->UpdateToolStorage(); } if (m_CurrentStorage.IsNull() || (m_CurrentStorage->GetTool(m_NeedleIndex).IsNull())) { MITK_WARN << "Found null pointer when setting the tool axis, aborting"; } else { navigationStepPunctuationIntervention->SetNeedleMetaData(m_CurrentStorage->GetTool(m_NeedleIndex)); - MITK_INFO << "Needle axis vector: " << m_CurrentStorage->GetTool(m_NeedleIndex)->GetToolAxis(); + MITK_DEBUG << "Needle axis vector: " << m_CurrentStorage->GetTool(m_NeedleIndex)->GetToolAxis(); } } } } void USNavigationMarkerPlacement::OnIntermediateResultProduced(const itk::SmartPointer resultsNode) { - // intermediate results only matter during an experiment - if (!m_IsExperimentRunning) - { - return; - } - - this->WaitCursorOn(); - - // set results node to the experiment logging (for saving contents to the - // file system) - m_ExperimentLogging->SetResult(resultsNode); - - std::string resultsName; - if (!resultsNode->GetName(resultsName)) - { - MITK_WARN << "Could not get name of current results node."; - return; - } - - // save the mitk scene - std::string scenefile = QString(m_ExperimentResultsSubDirectory + QDir::separator() + - QString("Scene %1 - ").arg(m_SceneNumber++, 2, 10, QChar('0')) + - QString::fromStdString(resultsName).replace(":", "_") + ".mitk") - .toStdString(); - MITK_INFO << "Saving Scene File: " << scenefile; - - mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); - mitk::NodePredicateNot::Pointer isNotHelperObject = - mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); - mitk::DataStorage::SetOfObjects::ConstPointer nodesToBeSaved = this->GetDataStorage()->GetSubset(isNotHelperObject); - - this->Convert2DImagesTo3D(nodesToBeSaved); - - sceneIO->SaveScene(nodesToBeSaved, this->GetDataStorage(), scenefile); - - this->WaitCursorOff(); + // intermediate results only matter during an experiment + if (!m_IsExperimentRunning) + { + return; + } + + this->WaitCursorOn(); + + // set results node to the experiment logging (for saving contents to the + // file system) + m_ExperimentLogging->SetResult(resultsNode); + + std::string resultsName; + if (!resultsNode->GetName(resultsName)) + { + MITK_WARN << "Could not get name of current results node."; + return; + } + + // save the mitk scene + std::string scenefile = QString(m_ExperimentResultsSubDirectory + QDir::separator() + + QString("Scene %1 - ").arg(m_SceneNumber++, 2, 10, QChar('0')) + + QString::fromStdString(resultsName).replace(":", "_") + ".mitk") + .toStdString(); + MITK_INFO << "Saving Scene File: " << scenefile; + + mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); + mitk::NodePredicateNot::Pointer isNotHelperObject = + mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); + mitk::DataStorage::SetOfObjects::ConstPointer nodesToBeSaved = this->GetDataStorage()->GetSubset(isNotHelperObject); + + this->Convert2DImagesTo3D(nodesToBeSaved); + + sceneIO->SaveScene(nodesToBeSaved, this->GetDataStorage(), scenefile); + + this->WaitCursorOff(); } void USNavigationMarkerPlacement::ReinitOnImage() { - if (!m_ReinitAlreadyDone && m_CombinedModality.IsNotNull()) - { - // make sure that the output is already calibrated correctly - // (if the zoom level was changed recently) - m_CombinedModality->Modified(); - m_CombinedModality->Update(); - - mitk::Image::Pointer image = m_CombinedModality->GetOutput(); - if (image.IsNotNull() && image->IsInitialized()) - { - // make a reinit on the ultrasound image - mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); - if (renderWindow != NULL && image->GetTimeGeometry()->IsValid()) - { - renderWindow->GetRenderingManager()->InitializeViews( - image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); - renderWindow->GetRenderingManager()->RequestUpdateAll(); - } - - this->RequestRenderWindowUpdate(); - - m_ReinitAlreadyDone = true; - } - } + if (!m_ReinitAlreadyDone && m_CombinedModality.IsNotNull()) + { + // make sure that the output is already calibrated correctly + // (if the zoom level was changed recently) + m_CombinedModality->Modified(); + m_CombinedModality->Update(); + + mitk::Image::Pointer image = m_CombinedModality->GetOutput(); + if (image.IsNotNull() && image->IsInitialized()) + { + // make a reinit on the ultrasound image + mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); + if (renderWindow != NULL && image->GetTimeGeometry()->IsValid()) + { + renderWindow->GetRenderingManager()->InitializeViews( + image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); + renderWindow->GetRenderingManager()->RequestUpdateAll(); + } + + this->RequestRenderWindowUpdate(); + + m_ReinitAlreadyDone = true; + } + } } void USNavigationMarkerPlacement::Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes) { - for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); ++it) - { - if (it->Value()->GetData() && strcmp(it->Value()->GetData()->GetNameOfClass(), "Image") == 0) - { - // convert image to 3d image if it is 2d at the moment - mitk::Image::Pointer image = dynamic_cast(it->Value()->GetData()); - if (image.IsNotNull() && image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable()) - { - mitk::Convert2Dto3DImageFilter::Pointer convert2DTo3DImageFilter = mitk::Convert2Dto3DImageFilter::New(); - convert2DTo3DImageFilter->SetInput(image); - convert2DTo3DImageFilter->Update(); - it->Value()->SetData(convert2DTo3DImageFilter->GetOutput()); - } - } - } + for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); ++it) + { + if (it->Value()->GetData() && strcmp(it->Value()->GetData()->GetNameOfClass(), "Image") == 0) + { + // convert image to 3d image if it is 2d at the moment + mitk::Image::Pointer image = dynamic_cast(it->Value()->GetData()); + if (image.IsNotNull() && image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable()) + { + mitk::Convert2Dto3DImageFilter::Pointer convert2DTo3DImageFilter = mitk::Convert2Dto3DImageFilter::New(); + convert2DTo3DImageFilter->SetInput(image); + convert2DTo3DImageFilter->Update(); + it->Value()->SetData(convert2DTo3DImageFilter->GetOutput()); + } + } + } } void USNavigationMarkerPlacement::CreateOverlays() { - // initialize warning overlay (and do not display it, yet) - m_WarnOverlay->SetText("Warning: No calibration available for current depth."); - - // set position and font size for the text overlay - // (nonesense postition as a layouter is used, but it ignored - // the overlay without setting a position here) - mitk::Point2D overlayPosition; - overlayPosition.SetElement(0, -50.0f); - overlayPosition.SetElement(1, -50.0f); - m_WarnOverlay->SetPosition2D(overlayPosition); - m_WarnOverlay->SetFontSize(22); - m_WarnOverlay->SetColor(1, 0, 0); // overlay should be red + // initialize warning overlay (and do not display it, yet) + m_WarnOverlay->SetText("Warning: No calibration available for current depth."); + + // set position and font size for the text overlay + // (nonesense postition as a layouter is used, but it ignored + // the overlay without setting a position here) + mitk::Point2D overlayPosition; + overlayPosition.SetElement(0, -50.0f); + overlayPosition.SetElement(1, -50.0f); + m_WarnOverlay->SetPosition2D(overlayPosition); + m_WarnOverlay->SetFontSize(22); + m_WarnOverlay->SetColor(1, 0, 0); // overlay should be red } void USNavigationMarkerPlacement::UpdateToolStorage() { if (m_NavigationDataSource.IsNull()) { m_NavigationDataSource = m_CombinedModality->GetNavigationDataSource(); } if (m_NavigationDataSource.IsNull()) { MITK_WARN << "Found an invalid navigation data source object!"; } us::ModuleContext* context = us::GetModuleContext(); std::string id = m_NavigationDataSource->US_PROPKEY_ID; std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + id + ")"; // Get Storage std::vector > refs = context->GetServiceReferences(); m_CurrentStorage = context->GetService(refs.front()); if (m_CurrentStorage.IsNull()) { MITK_WARN << "Found an invalid storage object!"; } else if (m_CurrentStorage->GetToolCount() != m_NavigationDataSource->GetNumberOfOutputs()) //there is something wrong with the storage { MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This storage won't be used because it isn't the right one."; m_CurrentStorage = NULL; } } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp index 14f88fb8c6..2f131ffd21 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp @@ -1,557 +1,557 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkUSNavigationProcessWidget.h" #include "ui_QmitkUSNavigationProcessWidget.h" #include "../NavigationStepWidgets/QmitkUSAbstractNavigationStep.h" #include "../SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.h" #include "mitkDataNode.h" #include "mitkNavigationDataToNavigationDataFilter.h" #include #include #include QmitkUSNavigationProcessWidget::QmitkUSNavigationProcessWidget(QWidget* parent) : QWidget(parent), m_SettingsWidget(0), m_BaseNode(mitk::DataNode::New()), m_CurrentTabIndex(0), m_CurrentMaxStep(0), m_ImageAlreadySetToNode(false), m_ReadySignalMapper(new QSignalMapper(this)), m_NoLongerReadySignalMapper(new QSignalMapper(this)), m_StdMultiWidget(0), m_UsePlanningStepWidget(false), ui(new Ui::QmitkUSNavigationProcessWidget) { m_Parent = parent; ui->setupUi(this); // remove the default page ui->stepsToolBox->setCurrentIndex(1);// ->removeItem(0); //set shortcuts QShortcut *nextShortcut = new QShortcut(QKeySequence("F10"), parent); QShortcut *prevShortcut = new QShortcut(QKeySequence("F11"), parent); connect(nextShortcut, SIGNAL(activated()), this, SLOT(OnNextButtonClicked())); connect(prevShortcut, SIGNAL(activated()), this, SLOT(OnPreviousButtonClicked())); //connect other slots connect( ui->restartStepButton, SIGNAL(clicked()), this, SLOT(OnRestartStepButtonClicked()) ); connect( ui->previousButton, SIGNAL(clicked()), this, SLOT(OnPreviousButtonClicked()) ); connect( ui->nextButton, SIGNAL(clicked()), this, SLOT(OnNextButtonClicked()) ); connect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); connect (ui->settingsButton, SIGNAL(clicked()), this, SLOT(OnSettingsButtonClicked()) ); connect( m_ReadySignalMapper, SIGNAL(mapped(int)), this, SLOT(OnStepReady(int)) ); connect( m_NoLongerReadySignalMapper, SIGNAL(mapped(int)), this, SLOT(OnStepNoLongerReady(int)) ); ui->settingsFrameWidget->setHidden(true); } QmitkUSNavigationProcessWidget::~QmitkUSNavigationProcessWidget() { ui->stepsToolBox->blockSignals(true); for ( NavigationStepVector::iterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it ) { if ( (*it)->GetNavigationStepState() > QmitkUSAbstractNavigationStep::State_Stopped ) { (*it)->StopStep(); } delete *it; } m_NavigationSteps.clear(); if ( m_SettingsNode.IsNotNull() && m_DataStorage.IsNotNull() ) { m_DataStorage->Remove(m_SettingsNode); } delete ui; } void QmitkUSNavigationProcessWidget::EnableInteraction(bool enable) { if (enable) { ui->restartStepButton->setEnabled(true); ui->previousButton->setEnabled(true); ui->nextButton->setEnabled(true); ui->stepsToolBox->setEnabled(true); } else { ui->restartStepButton->setEnabled(false); ui->previousButton->setEnabled(false); ui->nextButton->setEnabled(false); ui->stepsToolBox->setEnabled(false); } } void QmitkUSNavigationProcessWidget::SetDataStorage(itk::SmartPointer dataStorage) { m_DataStorage = dataStorage; if ( dataStorage.IsNull() ) { mitkThrow() << "Data Storage must not be null for QmitkUSNavigationProcessWidget."; } // test if base node is already in the data storage and add it if not m_BaseNode = dataStorage->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if ( m_BaseNode.IsNull() ) { m_BaseNode = mitk::DataNode::New(); m_BaseNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); dataStorage->Add(m_BaseNode); } // base node and image stream node may be the same node if ( strcmp(QmitkUSAbstractNavigationStep::DATANAME_BASENODE, QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM) != 0) { m_ImageStreamNode = dataStorage->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM); if (m_ImageStreamNode.IsNull()) { // Create Node for US Stream m_ImageStreamNode = mitk::DataNode::New(); m_ImageStreamNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM); dataStorage->Add(m_ImageStreamNode); } } else { m_ImageStreamNode = m_BaseNode; } m_SettingsNode = dataStorage->GetNamedDerivedNode(QmitkUSAbstractNavigationStep::DATANAME_SETTINGS, m_BaseNode); if ( m_SettingsNode.IsNull() ) { m_SettingsNode = mitk::DataNode::New(); m_SettingsNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_SETTINGS); dataStorage->Add(m_SettingsNode, m_BaseNode); } if (m_SettingsWidget) { m_SettingsWidget->SetSettingsNode(m_SettingsNode); } } void QmitkUSNavigationProcessWidget::SetSettingsWidget(QmitkUSNavigationAbstractSettingsWidget* settingsWidget) { // disconnect slots to settings widget if there was a widget before if ( m_SettingsWidget ) { disconnect( ui->settingsSaveButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnSave()) ); disconnect( ui->settingsCancelButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnCancel()) ); disconnect (m_SettingsWidget, SIGNAL(Saved()), this, SLOT(OnSettingsWidgetReturned()) ); disconnect (m_SettingsWidget, SIGNAL(Canceled()), this, SLOT(OnSettingsWidgetReturned()) ); disconnect (m_SettingsWidget, SIGNAL(SettingsChanged(itk::SmartPointer)), this, SLOT(OnSettingsChanged(itk::SmartPointer)) ); ui->settingsWidget->removeWidget(m_SettingsWidget); } m_SettingsWidget = settingsWidget; if ( m_SettingsWidget ) { m_SettingsWidget->LoadSettings(); connect( ui->settingsSaveButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnSave()) ); connect( ui->settingsCancelButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnCancel()) ); connect (m_SettingsWidget, SIGNAL(Saved()), this, SLOT(OnSettingsWidgetReturned()) ); connect (m_SettingsWidget, SIGNAL(Canceled()), this, SLOT(OnSettingsWidgetReturned()) ); connect (m_SettingsWidget, SIGNAL(SettingsChanged(itk::SmartPointer)), this, SLOT(OnSettingsChanged(itk::SmartPointer)) ); if ( m_SettingsNode.IsNotNull() ) { m_SettingsWidget->SetSettingsNode(m_SettingsNode, true); } ui->settingsWidget->addWidget(m_SettingsWidget); } ui->settingsButton->setEnabled(m_SettingsWidget != 0); } void QmitkUSNavigationProcessWidget::SetNavigationSteps(NavigationStepVector navigationSteps) { disconnect( this, SLOT(OnTabChanged(int)) ); for ( int n = ui->stepsToolBox->count()-1; n >= 0; --n ) { //ui->stepsToolBox->removeItem(n); } connect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); m_NavigationSteps.clear(); m_NavigationSteps = navigationSteps; this->InitializeNavigationStepWidgets(); // notify all navigation step widgets about the current settings for (NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { (*it)->OnSettingsChanged(m_SettingsNode); } } void QmitkUSNavigationProcessWidget::ResetNavigationProcess() { MITK_INFO("QmitkUSNavigationProcessWidget") << "Resetting navigation process."; ui->stepsToolBox->blockSignals(true); for ( int n = 0; n <= m_CurrentMaxStep; ++n ) { m_NavigationSteps.at(n)->StopStep(); //if ( n > 0 ) { ui->stepsToolBox->setItemEnabled(n, false); } } ui->stepsToolBox->blockSignals(false); m_CurrentMaxStep = 0; ui->stepsToolBox->setCurrentIndex(0); if ( m_NavigationSteps.size() > 0 ) { m_NavigationSteps.at(0)->ActivateStep(); } this->UpdatePrevNextButtons(); } void QmitkUSNavigationProcessWidget::UpdateNavigationProgress() { if ( m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsFreezed() ) { m_CombinedModality->Modified(); m_CombinedModality->Update(); if ( m_LastNavigationDataFilter.IsNotNull() ) { m_LastNavigationDataFilter->Update(); } mitk::Image::Pointer image = m_CombinedModality->GetOutput(); // make sure that always the current image is set to the data node if ( image.IsNotNull() && m_ImageStreamNode->GetData() != image.GetPointer() && image->IsInitialized() ) { m_ImageStreamNode->SetData(image); m_ImageAlreadySetToNode = true; } } if ( m_CurrentTabIndex > 0 && static_cast(m_CurrentTabIndex) < m_NavigationSteps.size() ) { m_NavigationSteps.at(m_CurrentTabIndex)->Update(); } } void QmitkUSNavigationProcessWidget::OnNextButtonClicked() { if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetIsFreezed()) {return;} //no moving through steps when the modality is NULL or frozen int currentIndex = ui->stepsToolBox->currentIndex(); if (currentIndex >= m_CurrentMaxStep) { MITK_WARN << "Next button clicked though no next tab widget is available."; return; } ui->stepsToolBox->setCurrentIndex(++currentIndex); this->UpdatePrevNextButtons(); } void QmitkUSNavigationProcessWidget::OnPreviousButtonClicked() { if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetIsFreezed()) {return;} //no moving through steps when the modality is NULL or frozen int currentIndex = ui->stepsToolBox->currentIndex(); if (currentIndex <= 0) { MITK_WARN << "Previous button clicked though no previous tab widget is available."; return; } ui->stepsToolBox->setCurrentIndex(--currentIndex); this->UpdatePrevNextButtons(); } void QmitkUSNavigationProcessWidget::OnRestartStepButtonClicked() { - MITK_INFO("QmitkUSNavigationProcessWidget") << "Restarting step " + MITK_DEBUG("QmitkUSNavigationProcessWidget") << "Restarting step " << m_CurrentTabIndex << " (" << m_NavigationSteps.at(m_CurrentTabIndex)->GetTitle().toStdString() << ")."; m_NavigationSteps.at(ui->stepsToolBox->currentIndex())->RestartStep(); m_NavigationSteps.at(ui->stepsToolBox->currentIndex())->ActivateStep(); } void QmitkUSNavigationProcessWidget::OnTabChanged(int index) { emit SignalActiveNavigationStepChangeRequested(index); if ( index < 0 || index >= static_cast(m_NavigationSteps.size()) ) { return; } else if ( m_CurrentTabIndex == index ) { // just activate the step if it is the same step againg m_NavigationSteps.at(index)->ActivateStep(); return; } - MITK_INFO("QmitkUSNavigationProcessWidget") << "Activating navigation step " + MITK_DEBUG("QmitkUSNavigationProcessWidget") << "Activating navigation step " << index << " (" << m_NavigationSteps.at(index)->GetTitle().toStdString() <<")."; if (index > m_CurrentTabIndex) { this->UpdateFilterPipeline(); // finish all previous steps to make sure that all data is valid for (int n = m_CurrentTabIndex; n < index; ++n) { m_NavigationSteps.at(n)->FinishStep(); } } // deactivate the previously active step if ( m_CurrentTabIndex > 0 && m_NavigationSteps.size() > static_cast(m_CurrentTabIndex) ) { m_NavigationSteps.at(m_CurrentTabIndex)->DeactivateStep(); } // start step of the current tab if it wasn't started before if ( m_NavigationSteps.at(index)->GetNavigationStepState() == QmitkUSAbstractNavigationStep::State_Stopped ) { m_NavigationSteps.at(index)->StartStep(); } m_NavigationSteps.at(index)->ActivateStep(); if (static_cast(index) < m_NavigationSteps.size()) ui->restartStepButton->setEnabled(m_NavigationSteps.at(index)->GetIsRestartable()); this->UpdatePrevNextButtons(); m_CurrentTabIndex = index; emit SignalActiveNavigationStepChanged(index); } void QmitkUSNavigationProcessWidget::OnSettingsButtonClicked() { this->SetSettingsWidgetVisible(true); } void QmitkUSNavigationProcessWidget::OnSettingsWidgetReturned() { this->SetSettingsWidgetVisible(false); } void QmitkUSNavigationProcessWidget::OnSettingsNodeChanged(itk::SmartPointer dataNode) { if ( m_SettingsWidget ) m_SettingsWidget->SetSettingsNode(dataNode); } void QmitkUSNavigationProcessWidget::OnStepReady(int index) { if (m_CurrentMaxStep <= index) { m_CurrentMaxStep = index + 1; this->UpdatePrevNextButtons(); for (int n = 0; n <= m_CurrentMaxStep; ++n) { //ui->stepsToolBox->setItemEnabled(n, true); } } emit SignalNavigationStepFinished(index, true); } void QmitkUSNavigationProcessWidget::OnStepNoLongerReady(int index) { if (m_CurrentMaxStep > index) { m_CurrentMaxStep = index; this->UpdatePrevNextButtons(); this->UpdateFilterPipeline(); for (int n = m_CurrentMaxStep+1; n < ui->stepsToolBox->count(); ++n) { //ui->stepsToolBox->setItemEnabled(n, false); m_NavigationSteps.at(n)->StopStep(); } } emit SignalNavigationStepFinished(index, false); } void QmitkUSNavigationProcessWidget::OnCombinedModalityChanged(itk::SmartPointer combinedModality) { m_CombinedModality = combinedModality; m_ImageAlreadySetToNode = false; if ( combinedModality.IsNotNull() ) { if ( combinedModality->GetNavigationDataSource().IsNull() ) { MITK_WARN << "There is no navigation data source set for the given combined modality."; return; } this->UpdateFilterPipeline(); } for (NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { (*it)->SetCombinedModality(combinedModality); } emit SignalCombinedModalityChanged(combinedModality); } void QmitkUSNavigationProcessWidget::OnSettingsChanged(const mitk::DataNode::Pointer dataNode) { static bool methodEntered = false; if ( methodEntered ) { MITK_WARN("QmitkUSNavigationProcessWidget") << "Ignoring recursive call to 'OnSettingsChanged()'. " << "Make sure to no emit 'SignalSettingsNodeChanged' in an 'OnSettingsChanged()' method."; return; } methodEntered = true; std::string application; if ( dataNode->GetStringProperty("settings.application", application) ) { QString applicationQString = QString::fromStdString(application); if ( applicationQString != ui->titleLabel->text() ) { ui->titleLabel->setText(applicationQString); } } // notify all navigation step widgets about the changed settings for (NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { (*it)->OnSettingsChanged(dataNode); } emit SignalSettingsChanged(dataNode); methodEntered = false; } void QmitkUSNavigationProcessWidget::InitializeNavigationStepWidgets() { // do not listen for steps tool box signal during insertion of items into tool box disconnect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); m_CurrentMaxStep = 0; mitk::DataStorage::Pointer dataStorage = m_DataStorage; for (unsigned int n = 0; n < m_NavigationSteps.size(); ++n) { QmitkUSAbstractNavigationStep* curNavigationStep = m_NavigationSteps.at(n); curNavigationStep->SetDataStorage(dataStorage); connect( curNavigationStep, SIGNAL(SignalReadyForNextStep()), m_ReadySignalMapper, SLOT(map())); connect( curNavigationStep, SIGNAL(SignalNoLongerReadyForNextStep()), m_NoLongerReadySignalMapper, SLOT(map()) ); connect( curNavigationStep, SIGNAL(SignalCombinedModalityChanged(itk::SmartPointer)), this, SLOT(OnCombinedModalityChanged(itk::SmartPointer)) ); connect( curNavigationStep, SIGNAL(SignalIntermediateResult(const itk::SmartPointer)), this, SIGNAL(SignalIntermediateResult(const itk::SmartPointer)) ); connect( curNavigationStep, SIGNAL(SignalSettingsNodeChanged(itk::SmartPointer)), this, SLOT(OnSettingsNodeChanged(itk::SmartPointer)) ); m_ReadySignalMapper->setMapping(curNavigationStep, n); m_NoLongerReadySignalMapper->setMapping(curNavigationStep, n); ui->stepsToolBox->insertWidget(n, curNavigationStep); //if ( n > 0 ) { ui->stepsToolBox->get(n, false); } } ui->restartStepButton->setEnabled(m_NavigationSteps.at(0)->GetIsRestartable()); ui->stepsToolBox->setCurrentIndex(0); // activate the first navigation step widgets if ( ! m_NavigationSteps.empty() ) { m_NavigationSteps.at(0)->ActivateStep(); } // after filling the steps tool box the signal is interesting again connect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); this->UpdateFilterPipeline(); } void QmitkUSNavigationProcessWidget::UpdatePrevNextButtons() { int currentIndex = ui->stepsToolBox->currentIndex(); ui->previousButton->setEnabled(currentIndex > 0); ui->nextButton->setEnabled(currentIndex < m_CurrentMaxStep); } void QmitkUSNavigationProcessWidget::UpdateFilterPipeline() { if ( m_CombinedModality.IsNull() ) { return; } std::vector filterList; mitk::NavigationDataSource::Pointer navigationDataSource = m_CombinedModality->GetNavigationDataSource(); for (unsigned int n = 0; n <= m_CurrentMaxStep && n < m_NavigationSteps.size(); ++n) { QmitkUSAbstractNavigationStep::FilterVector filter = m_NavigationSteps.at(n)->GetFilter(); if ( ! filter.empty() ) { filterList.insert(filterList.end(), filter.begin(), filter.end()); } } if ( ! filterList.empty() ) { for (unsigned int n = 0; n < navigationDataSource->GetNumberOfOutputs(); ++n) { filterList.at(0)->SetInput(n, navigationDataSource->GetOutput(n)); } for (std::vector::iterator it = filterList.begin()+1; it != filterList.end(); ++it) { std::vector::iterator prevIt = it-1; for (unsigned int n = 0; n < (*prevIt)->GetNumberOfOutputs(); ++n) { (*it)->SetInput(n, (*prevIt)->GetOutput(n)); } } m_LastNavigationDataFilter = filterList.at(filterList.size()-1); } else { m_LastNavigationDataFilter = navigationDataSource.GetPointer(); } } void QmitkUSNavigationProcessWidget::SetSettingsWidgetVisible(bool visible) { ui->settingsFrameWidget->setVisible(visible); ui->stepsToolBox->setHidden(visible); ui->settingsButton->setHidden(visible); ui->restartStepButton->setHidden(visible); ui->previousButton->setHidden(visible); ui->nextButton->setHidden(visible); } void QmitkUSNavigationProcessWidget::FinishCurrentNavigationStep() { int currentIndex = ui->stepsToolBox->currentIndex(); QmitkUSAbstractNavigationStep* curNavigationStep = m_NavigationSteps.at(currentIndex); curNavigationStep->FinishStep(); }