MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
QmitkUSNavigationMarkerPlacement.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12
14#include "ui_QmitkUSNavigationMarkerPlacement.h"
15
22
24
26#include "mitkIRenderingManager.h"
29#include <mitkIOUtil.h>
30
32
33#include <QDateTime>
34#include <QDir>
35#include <QInputDialog>
36#include <QMessageBox>
37#include <QSignalMapper>
38#include <QTimer>
39
40#include "QmitkRenderWindow.h"
41#include "QmitkStdMultiWidget.h"
42#include "QmitkStdMultiWidgetEditor.h"
43#include "mitkCameraController.h"
44#include "mitkLayoutAnnotationRenderer.h"
45#include <vtkSmartPointer.h>
46
47// scene serialization
48#include <mitkConvert2Dto3DImageFilter.h>
49#include <mitkNodePredicateNot.h>
50#include <mitkNodePredicateProperty.h>
51#include <mitkSceneIO.h>
52#include <mitkSurface.h>
53
54const std::string QmitkUSNavigationMarkerPlacement::VIEW_ID = "org.mitk.views.usmarkerplacement";
55
62
64 : m_Parent(nullptr),
65 m_UpdateTimer(new QTimer(this)),
66 m_ImageAndNavigationDataLoggingTimer(new QTimer(this)),
67 m_StdMultiWidget(nullptr),
68 m_CombinedModality(nullptr),
69 m_ReinitAlreadyDone(false),
70 m_IsExperimentRunning(false),
71 m_CurrentApplicationName(),
72 m_NavigationStepTimer(mitk::USNavigationStepTimer::New()),
73 m_IconRunning(QPixmap(":/USNavigation/record.png")),
74 m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")),
75 m_ResultsDirectory(),
76 m_ExperimentName(),
77 m_ExperimentResultsSubDirectory(),
78 m_NavigationStepNames(),
79 m_LoggingBackend(),
80 m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()),
81 m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()),
82 m_TargetNodeDisplacementFilter(nullptr),
83 m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()),
84 m_ToolVisualizationFilter(nullptr),
85 m_AblationZonesVector(),
86 m_NeedleIndex(0),
87 m_MarkerIndex(1),
88 m_SceneNumber(1),
89 m_WarnOverlay(mitk::TextAnnotation2D::New()),
90 m_NavigationDataSource(nullptr),
91 m_CurrentStorage(nullptr),
92 m_ImageStreamNode(nullptr),
94{
95 connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
96 connect(
98
99 // scale running (and not running) icon the specific height
100 m_IconRunning = m_IconRunning.scaledToHeight(20, Qt::SmoothTransformation);
101 m_IconNotRunning = m_IconNotRunning.scaledToHeight(20, Qt::SmoothTransformation);
102
103
104}
105
107{
108 this->GetDataStorage()->Remove(m_InstrumentNode);
109 delete ui;
110}
111
113{
114 if ((static_cast<int>(m_AblationZonesVector.size()) < id) || (id < 0))
115 {
116 return;
117 }
118
119 MITK_INFO << "Ablation Zone " << id << " changed, new size: " << newSize;
120
121 // create a vtk sphere with given radius
123 vtkSphere->SetRadius(newSize / 2);
124 vtkSphere->SetCenter(0, 0, 0);
125 vtkSphere->SetPhiResolution(20);
126 vtkSphere->SetThetaResolution(20);
127 vtkSphere->Update();
128
129 mitk::Surface::Pointer zoneSurface = dynamic_cast<mitk::Surface *>(m_AblationZonesVector.at(id)->GetData());
130 zoneSurface->SetVtkPolyData(vtkSphere->GetOutput());
131}
132
134{
135 m_AblationZonesDisplacementFilter->SetInitialReferencePose(
136 m_CombinedModality->GetNavigationDataSource()->GetOutput(m_MarkerIndex));
137 mitk::DataNode::Pointer NewAblationZone = mitk::DataNode::New();
138
139 mitk::Point3D origin = m_CombinedModality->GetNavigationDataSource()->GetOutput(m_NeedleIndex)->GetPosition();
140
141 MITK_INFO("USNavigationLogging") << "Ablation Zone Added, initial size: " << size << ", origin: " << origin;
142
143 mitk::Surface::Pointer zone = mitk::Surface::New();
144
145 // create a vtk sphere with given radius
147 vtkSphere->SetRadius(size / 2);
148 vtkSphere->SetCenter(0, 0, 0);
149 vtkSphere->SetPhiResolution(20);
150 vtkSphere->SetThetaResolution(20);
151 vtkSphere->Update();
152 zone->SetVtkPolyData(vtkSphere->GetOutput());
153
154 // set vtk sphere and origin to data node (origin must be set
155 // again, because of the new sphere set as data)
156 NewAblationZone->SetData(zone);
157 NewAblationZone->GetData()->GetGeometry()->SetOrigin(origin);
158 mitk::Color SphereColor = mitk::Color();
159 // default color
160 SphereColor[0] = 102;
161 SphereColor[1] = 0;
162 SphereColor[2] = 204;
163 NewAblationZone->SetColor(SphereColor);
164 NewAblationZone->SetOpacity(0.3);
165
166 // set name of zone
167 std::stringstream name;
168 name << "Ablation Zone" << m_AblationZonesVector.size();
169 NewAblationZone->SetName(name.str());
170
171 // add zone to filter
172 m_AblationZonesDisplacementFilter->AddNode(NewAblationZone);
173 m_AblationZonesVector.push_back(NewAblationZone);
174 this->GetDataStorage()->Add(NewAblationZone);
175}
176
178{
179 m_Parent = parent;
180 ui->setupUi(parent);
181
182 connect(ui->startExperimentButton, SIGNAL(clicked()), this, SLOT(OnStartExperiment()));
183 connect(ui->finishExperimentButton, SIGNAL(clicked()), this, SLOT(OnFinishExperiment()));
184 connect(ui->m_enableNavigationLayout, SIGNAL(clicked()), this, SLOT(OnChangeLayoutClicked()));
185 connect(ui->m_RenderWindowSelection, SIGNAL(valueChanged(int)), this, SLOT(OnRenderWindowSelection()));
186 connect(ui->m_RefreshView, SIGNAL(clicked()), this, SLOT(OnRefreshView()));
187
188 m_BaseNode = this->GetDataStorage()->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_BASENODE);
189 if (m_BaseNode.IsNull())
190 {
191 m_BaseNode = mitk::DataNode::New();
193 this->GetDataStorage()->Add(m_BaseNode);
194 }
195
196 connect(ui->m_CtToUsRegistrationWidget, SIGNAL(GetCursorPosition()), this, SLOT(OnGetCursorPosition()));
197 connect(ui->m_CtToUsRegistrationWidget, SIGNAL(ActualizeCtToUsRegistrationWidget()), this, SLOT(OnActualizeCtToUsRegistrationWidget()));
198 connect(ui->m_initializeCtToUsRegistration, SIGNAL(clicked()), this, SLOT(OnInitializeCtToUsRegistration()));
199 connect(ui->m_initializeTargetMarking, SIGNAL(clicked()), this, SLOT(OnInitializeTargetMarking()));
200 connect(ui->m_initializeCritStructureMarking, SIGNAL(clicked()), this, SLOT(OnInitializeCriticalStructureMarking()));
201 connect(ui->m_initializeNavigation, SIGNAL(clicked()), this, SLOT(OnInitializeNavigation()));
202
203 // indicate that no experiment is running at start
204 ui->runningLabel->setPixmap(m_IconNotRunning);
205
206 connect(ui->m_settingsWidget, SIGNAL(SettingsChanged(itk::SmartPointer<mitk::DataNode>)),
208}
209
211{
212 //If update timer is not stopped (signals stopped), setting the m_CombinedModality
213 // will cause a crash of the workbench in some times.
214 m_UpdateTimer->blockSignals(true);
215 m_UpdateTimer->stop();
216 m_SettingsNode = mitk::DataNode::New();
217 ui->m_settingsWidget->OnSetSettingsNode(m_SettingsNode, true);
219 m_CombinedModality = ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality();
220 // Having set the m_CombinedModality reactivate the update timer again
221 m_UpdateTimer->start(50); // every 50 Milliseconds = 20 Frames/Second
222 m_UpdateTimer->blockSignals(false);
223}
224
226{
227 auto centroid = this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetSelectedPosition();
228 ui->m_CtToUsRegistrationWidget->OnCalculateTRE(centroid);
229}
230
232{
233 m_SettingsNode = mitk::DataNode::New();
234 ui->m_settingsWidget->OnSetSettingsNode(m_SettingsNode, true);
235 this->InitImageStream();
236
237 if (ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality().IsNull())
238 {
239 return;
240 }
241 ui->m_CtToUsRegistrationWidget->SetCombinedModality(
242 ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality());
243
244 m_CombinedModality = ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality();
245
246 if (!m_StdMultiWidget)
247 {
248 // try to get the standard multi widget if it couldn't be got before
249 mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart();
250
251 QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast<QmitkStdMultiWidgetEditor *>(renderWindowPart);
252
253 // if there is a standard multi widget now, disable the level window and
254 // change the layout to 2D up and 3d down
255 if (multiWidgetEditor)
256 {
257 m_StdMultiWidget = dynamic_cast<QmitkStdMultiWidget *>(multiWidgetEditor->GetMultiWidget());
258 multiWidgetEditor->ShowLevelWindowWidget(false);
260 }
261 }
262 else
263 {
264 this->OnRefreshView();
265 }
266 m_UpdateTimer->start(50); // every 50 Milliseconds = 20 Frames/Second
267}
268
270{
271 ui->m_CtToUsRegistrationWidget->SetDataStorage(this->GetDataStorage());
272 ui->m_CtToUsRegistrationWidget->OnSettingsChanged(m_SettingsNode);
273 ui->m_CtToUsRegistrationWidget->OnActivateStep();
274 ui->m_CtToUsRegistrationWidget->OnStartStep();
275 ui->m_CtToUsRegistrationWidget->Update();
276}
277
279{
281 ui->m_TargetMarkingWidget->SetCombinedModality(m_CombinedModality);
282 ui->m_TargetMarkingWidget->SetDataStorage(this->GetDataStorage());
283 ui->m_TargetMarkingWidget->OnSettingsChanged(m_SettingsNode);
284 ui->m_TargetMarkingWidget->OnActivateStep();
285 ui->m_TargetMarkingWidget->OnStartStep();
286 ui->m_TargetMarkingWidget->Update();
287}
288
290{
292 ui->m_CriticalStructuresWidget->SetCombinedModality(m_CombinedModality);
293 ui->m_CriticalStructuresWidget->SetDataStorage(this->GetDataStorage());
294 ui->m_CriticalStructuresWidget->OnSettingsChanged(m_SettingsNode);
295 ui->m_CriticalStructuresWidget->OnActivateStep();
296 ui->m_CriticalStructuresWidget->OnStartStep();
297 ui->m_CriticalStructuresWidget->Update();
298}
299
301{
303 ui->m_NavigationWidget->SetCombinedModality(m_CombinedModality);
304 ui->m_NavigationWidget->SetDataStorage(this->GetDataStorage());
305 ui->m_NavigationWidget->OnSettingsChanged(m_SettingsNode);
306 ui->m_NavigationWidget->OnActivateStep();
307 ui->m_NavigationWidget->OnStartStep();
308 ui->m_NavigationWidget->Update();
309
310 // test if it is tracked US, if yes add visualization filter
311 if (m_CombinedModality->GetIsTrackedUltrasoundActive())
312 {
313 m_InstrumentNode = mitk::DataNode::New();
314 m_InstrumentNode->SetName("Tracked US Instrument");
315 m_InstrumentNode->SetData(
316 m_CombinedModality->GetNavigationDataSource()->GetToolMetaData(0)->GetToolSurface()->Clone());
317 this->GetDataStorage()->Add(m_InstrumentNode);
318 m_ToolVisualizationFilter = mitk::NavigationDataObjectVisualizationFilter::New();
319 m_ToolVisualizationFilter->ConnectTo(m_CombinedModality->GetNavigationDataSource());
320 m_ToolVisualizationFilter->SetRepresentationObject(0, m_InstrumentNode->GetData()); //caution: currently hard coded that instrument has id 0
321 //set dummy objects to avoid spamming of console
322 mitk::Surface::Pointer dummyObject = mitk::Surface::New();
323 m_ToolVisualizationFilter->SetRepresentationObject(1, dummyObject.GetPointer());
324 m_ToolVisualizationFilter->SetRepresentationObject(2, dummyObject.GetPointer());
325 }
326}
327
329{
330 if (m_ImageStreamNode.IsNull())
331 {
332 m_ImageStreamNode = mitk::DataNode::New();
333 m_ImageStreamNode->SetName("US Navigation Viewing Stream");
334 this->GetDataStorage()->Add(m_ImageStreamNode);
335 }
336}
337
338void QmitkUSNavigationMarkerPlacement::OnCombinedModalityPropertyChanged(const std::string &key, const std::string &)
339{
340 if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH)
341 {
342 m_ReinitAlreadyDone = false;
343 this->ReinitOnImage();
344
345 if (m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsCalibratedForCurrentStatus())
346 {
347 mitk::LayoutAnnotationRenderer::AddAnnotation(
348 m_WarnOverlay.GetPointer(), "stdmulti.widget0", mitk::LayoutAnnotationRenderer::TopLeft);
349 MITK_WARN << "No calibration available for the selected ultrasound image depth.";
350 }
351 }
352}
353
358
360{
361 if (m_CombinedModality.IsNull())
362 return;
363 m_CombinedModality->Modified(); // shouldn't be necessary ... fix in abstract ultrasound tracker device!
364 m_CombinedModality->Update();
365 if (m_ToolVisualizationFilter.IsNotNull())
366 {
368 }
369
370 ui->m_CtToUsRegistrationWidget->Update();
371 ui->m_TargetMarkingWidget->Update();
372 ui->m_CriticalStructuresWidget->Update();
373 ui->m_NavigationWidget->Update();
374
375 mitk::Image::Pointer image = m_CombinedModality->GetOutput();
376 // make sure that always the current image is set to the data node
377 if (image.IsNotNull() && m_ImageStreamNode->GetData() != image.GetPointer() && image->IsInitialized())
378 {
379 m_ImageStreamNode->SetData(image);
380 }
381
382 if (!m_StdMultiWidget)
383 {
384 // try to get the standard multi widget if it couldn't be got before
385 mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart();
386
387 QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast<QmitkStdMultiWidgetEditor*>(renderWindowPart);
388
389 // if there is a standard multi widget now, disable the level window and
390 // change the layout to 2D up and 3d down
391 if (multiWidgetEditor)
392 {
393 m_StdMultiWidget = dynamic_cast<QmitkStdMultiWidget*>(multiWidgetEditor->GetMultiWidget());
394 multiWidgetEditor->ShowLevelWindowWidget(false);
396 }
397
398 this->CreateOverlays();
399 }
400
401 if (m_CombinedModality.IsNotNull() && !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing
402 {
404
405 // update the 3D window only every fourth time to speed up the rendering (at least in 2D)
406 this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS);
407
408 // make sure that a reinit was performed on the image
409 this->ReinitOnImage();
410 }
411}
412
414{
415 MITK_INFO << "Navigation Layout";
416 // try to get the standard multi widget if it couldn't be got before
417 mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart();
418
419 QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast<QmitkStdMultiWidgetEditor*>(renderWindowPart);
420
421 // if there is a standard multi widget now, disable the level window and
422 // change the layout to 2D up and 3d down
423 if (multiWidgetEditor)
424 {
425 m_StdMultiWidget = dynamic_cast<QmitkStdMultiWidget*>(multiWidgetEditor->GetMultiWidget());
426 multiWidgetEditor->ShowLevelWindowWidget(false);
428 }
429}
430
435
437{
438 if (!ui->m_enableNavigationLayout->isChecked())
440 else
441 {
442 // Reinit the US Image Stream (this might be broken if there was a global reinit somewhere...)
443 try
444 {
445 mitk::RenderingManager::GetInstance()->InitializeViews( // Reinit
446 this
447 ->GetDataStorage() // GetDataStorage
448 ->GetNamedNode("US Viewing Stream - Image 0")
449 ->GetData()
450 ->GetTimeGeometry()); // GetNode
451 }
452 catch (...)
453 {
454 MITK_DEBUG << "No reinit possible";
455 }
457 }
458}
459
461{
463 {
464 int i, j, k;
465 switch (this->ui->m_RenderWindowSelection->value())
466 {
467 case 1:
468 mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetCameraController()->SetViewToCaudal();
469 i = 1;
470 j = 2; // other windows
471 k = 0;
472 break;
473 case 2:
474 mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetCameraController()->SetViewToSinister();
475 i = 0;
476 j = 2;
477 k = 1;
478 break;
479 case 3:
480 mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetCameraController()->SetViewToAnterior();
481 i = 1;
482 j = 0;
483 k = 2;
484 break;
485 default:
486 return;
487 }
488
489 // get the render window which is defined by index "k" and set it as "current render window widget"
490 // chose the layout that will set the current 2D window as top render window and the 3D windows as bottom render window
491 auto renderWindowWidget = m_StdMultiWidget->GetRenderWindowWidget(m_StdMultiWidget->GetNameFromIndex(k));
492 m_StdMultiWidget->GetMultiWidgetLayoutManager()->SetCurrentRenderWindowWidget(renderWindowWidget.get());
493 m_StdMultiWidget->GetMultiWidgetLayoutManager()->SetOneTop3DBottomLayout();
494
496 this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane")
497 ->SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")));
498 this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane")
499 ->SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")));
500 this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(k) + ".plane")
501 ->SetBoolProperty("visible", true, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")));
502 this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane")
503 ->SetIntProperty("Crosshair.Gap Size", 0);
504 this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane")
505 ->SetIntProperty("Crosshair.Gap Size", 0);
506 }
507}
508
510{
512 {
513 //reset render windows
514 m_StdMultiWidget->SetCrosshairVisibility(true);
515 m_StdMultiWidget->GetMultiWidgetLayoutManager()->SetDefaultLayout();
516 }
517}
518
520{
521 if (ui->m_enableNavigationLayout->isChecked())
523 else
525}
526
528{
529 // update filter for logging navigation data and ultrasound images
530 if (m_CombinedModality.IsNotNull())
531 {
532 m_NavigationDataRecorder->Update();
533 // get last messages for logging filer and store them
534 std::vector<std::string> messages = m_LoggingBackend.GetNavigationMessages();
535 std::string composedMessage = "";
536 for (std::size_t i = 0; i < messages.size(); i++)
537 {
538 composedMessage += messages.at(i);
539 }
540 m_USImageLoggingFilter->AddMessageToCurrentImage(composedMessage);
542 // update logging filter
543 m_USImageLoggingFilter->Update();
544 }
545}
546
548{
549 // get name for the experiment by a QInputDialog
550 bool ok;
551 if (m_ExperimentName.isEmpty())
552 { // default: current date
553 m_ExperimentName = QString::number(QDateTime::currentDateTime().date().year()) + "_" +
554 QString::number(QDateTime::currentDateTime().date().month()) + "_" +
555 QString::number(QDateTime::currentDateTime().date().day()) + "_experiment_" +
556 QString::number(QDateTime::currentDateTime().time().hour()) + "." +
557 QString::number(QDateTime::currentDateTime().time().minute());
558 }
559 m_ExperimentName = QInputDialog::getText(
560 m_Parent, QString("Experiment Name"), QString("Name of the Experiment"), QLineEdit::Normal, m_ExperimentName, &ok);
561 MITK_INFO("USNavigationLogging") << "Experiment started: " << m_ExperimentName.toStdString();
562 if (ok && !m_ExperimentName.isEmpty())
563 {
564 // display error message and call the function recursively if a directory
565 // with the given name already exists
566 QDir experimentResultsDir(m_ResultsDirectory + QDir::separator() + m_ExperimentName);
567 if (experimentResultsDir.exists())
568 {
569 QMessageBox::critical(
570 m_Parent, "Results Directory Exists", "The result directory already exists.\nPlease choose an other name.");
571 this->OnStartExperiment();
572 }
573 else
574 {
577
578 // experiment is running now
579 ui->runningLabel->setPixmap(m_IconRunning);
580
581 // (re)start timer for navigation step durations
582 m_NavigationStepTimer->Reset();
583 m_NavigationStepTimer->SetOutputFileName(
584 QString(m_ExperimentResultsSubDirectory + QDir::separator() + QString("durations.cvs")).toStdString());
585 m_NavigationStepTimer->SetActiveIndex(0, "Initialization");
586
587 ui->finishExperimentButton->setEnabled(true);
588 ui->startExperimentButton->setDisabled(true);
589
590 // initialize and register logging backend
591 QString loggingFilename = m_ExperimentResultsSubDirectory + QDir::separator() + "logging.txt";
592 m_LoggingBackend.SetOutputFileName(loggingFilename.toStdString());
593 mitk::RegisterBackend(&m_LoggingBackend);
594
595 // initialize and start navigation data recorder form xml recording
596 m_NavigationDataRecorder->StartRecording();
597
599
601 }
602 }
603}
604
606{
607 this->WaitCursorOn();
608
609 MITK_INFO("USNavigationLogging") << "Experiment finished!";
610 MITK_INFO("USNavigationLogging") << "Position/Orientation of needle tip: "
611 << (dynamic_cast<mitk::NavigationData *>(
612 m_CombinedModality->GetTrackingDeviceDataSource()->GetOutput(0)))
613 ->GetPosition();
614 MITK_INFO("USNavigationLogging")
615 << "Position of target: " << m_TargetNodeDisplacementFilter->GetRawDisplacementNavigationData(0)->GetPosition();
616 MITK_INFO("USNavigationLogging") << "Total duration: " << m_NavigationStepTimer->GetTotalDuration();
617
619
620 ui->runningLabel->setPixmap(m_IconNotRunning);
621
622 m_NavigationStepTimer->Stop();
623
624 ui->finishExperimentButton->setDisabled(true);
625 ui->startExperimentButton->setEnabled(true);
626
627 MITK_INFO("USNavigationLogging") << "Writing logging data to " << m_ExperimentResultsSubDirectory.toStdString();
628 // save ultrasound images to the file system
629 QDir(m_ExperimentResultsSubDirectory).mkdir("ImageStream");
630 m_USImageLoggingFilter->Update();
631 m_USImageLoggingFilter->SetImageFilesExtension(".jpg");
632 m_USImageLoggingFilter->SaveImages(
633 QString(m_ExperimentResultsSubDirectory + QDir::separator() + "ImageStream" + QDir::separator()).toStdString());
634 m_USImageLoggingFilter = mitk::USImageLoggingFilter::New();
635
636 m_NavigationDataRecorder->StopRecording();
637
638 // Write data to csv and xml file
639 mitk::IOUtil::Save(
640 m_NavigationDataRecorder->GetNavigationDataSet(),
641 (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.xml").toStdString().c_str()));
642 mitk::IOUtil::Save(
643 m_NavigationDataRecorder->GetNavigationDataSet(),
644 (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.csv").toStdString().c_str()));
645
646 // write logged navigation data messages to separate file
647 std::stringstream csvNavigationMessagesFilename;
648 csvNavigationMessagesFilename << m_ExperimentResultsSubDirectory.toStdString() << QDir::separator().toLatin1()
649 << "CSVNavigationMessagesLogFile.csv";
650 MITK_INFO("USNavigationLogging") << "Writing logged navigation messages to separate csv file: "
651 << csvNavigationMessagesFilename.str();
652 m_LoggingBackend.WriteCSVFileWithNavigationMessages(csvNavigationMessagesFilename.str());
653
654 mitk::UnregisterBackend(&m_LoggingBackend);
655
656 m_IsExperimentRunning = false;
657
659 m_CombinedModality = nullptr;
660
661 // reset scene number for next experiment
662 m_SceneNumber = 1;
663
664 this->WaitCursorOff();
665 MITK_INFO("USNavigationLogging") << "Finished!";
666}
667
669{
670 // initialize gui according to the experiment mode setting
671 bool experimentMode = false;
672 settings->GetBoolProperty("settings.experiment-mode", experimentMode);
673 ui->startExperimentButton->setVisible(experimentMode);
674 ui->finishExperimentButton->setVisible(experimentMode);
675 ui->runningLabel->setVisible(experimentMode);
676 if (experimentMode && !m_IsExperimentRunning)
677 {
678 ui->runningLabel->setPixmap(m_IconNotRunning);
679 }
680 else if (!experimentMode)
681 {
683 {
684 this->OnFinishExperiment();
685 }
686 }
687
688 // get the results directory from the settings and use home directory if
689 // there is no results directory configured
690 std::string resultsDirectory;
691 if (settings->GetStringProperty("settings.experiment-results-directory", resultsDirectory))
692 {
693 m_ResultsDirectory = QString::fromStdString(resultsDirectory);
694 }
695 else
696 {
697 m_ResultsDirectory = QDir::homePath();
698 }
699
700 // make sure that the results directory exists
701 QDir resultsDirectoryQDir = QDir(m_ResultsDirectory);
702 if (!resultsDirectoryQDir.exists())
703 {
704 resultsDirectoryQDir.mkpath(m_ResultsDirectory);
705 }
706
707 MITK_INFO("USNavigation") << "Results Directory: " << m_ResultsDirectory.toStdString();
708}
709
711{
712 if (!m_ReinitAlreadyDone && m_CombinedModality.IsNotNull())
713 {
714 // make sure that the output is already calibrated correctly
715 // (if the zoom level was changed recently)
716 m_CombinedModality->Modified();
717 m_CombinedModality->Update();
718
719 mitk::Image::Pointer image = m_CombinedModality->GetOutput();
720 if (image.IsNotNull() && image->IsInitialized())
721 {
722 // make a reinit on the ultrasound image
723 mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart();
724 if (renderWindowPart != nullptr && image->GetTimeGeometry()->IsValid())
725 {
726 renderWindowPart->GetRenderingManager()->InitializeViews(image->GetTimeGeometry());
727 }
728
729 this->RequestRenderWindowUpdate();
730
731 m_ReinitAlreadyDone = true;
732 }
733 }
734}
735
736void QmitkUSNavigationMarkerPlacement::Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes)
737{
738 for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); ++it)
739 {
740 if (it->Value()->GetData() && strcmp(it->Value()->GetData()->GetNameOfClass(), "Image") == 0)
741 {
742 // convert image to 3d image if it is 2d at the moment
743 mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(it->Value()->GetData());
744 if (image.IsNotNull() && image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable())
745 {
746 mitk::Convert2Dto3DImageFilter::Pointer convert2DTo3DImageFilter = mitk::Convert2Dto3DImageFilter::New();
747 convert2DTo3DImageFilter->SetInput(image);
748 convert2DTo3DImageFilter->Update();
749 it->Value()->SetData(convert2DTo3DImageFilter->GetOutput());
750 }
751 }
752 }
753}
754
756{
757 // initialize warning overlay (and do not display it, yet)
758 m_WarnOverlay->SetText("Warning: No calibration available for current depth.");
759
760 // set position and font size for the text overlay
761 // (nonsense position as a layouter is used, but it ignored
762 // the overlay without setting a position here)
763 mitk::Point2D overlayPosition;
764 overlayPosition.SetElement(0, -50.0f);
765 overlayPosition.SetElement(1, -50.0f);
766 m_WarnOverlay->SetPosition2D(overlayPosition);
767 m_WarnOverlay->SetFontSize(22);
768 m_WarnOverlay->SetColor(1, 0, 0); // overlay should be red
769}
770
772{
773 if (m_NavigationDataSource.IsNull())
774 {
775 m_NavigationDataSource = m_CombinedModality->GetNavigationDataSource();
776 }
777 if (m_NavigationDataSource.IsNull())
778 {
779 MITK_WARN << "Found an invalid navigation data source object!";
780 }
781 us::ModuleContext *context = us::GetModuleContext();
782 std::string id = m_NavigationDataSource->US_PROPKEY_ID;
783 std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + id + ")";
784 // Get Storage
785 std::vector<us::ServiceReference<mitk::NavigationToolStorage>> refs =
786 context->GetServiceReferences<mitk::NavigationToolStorage>();
787 m_CurrentStorage = context->GetService(refs.front());
788
789 if (m_CurrentStorage.IsNull())
790 {
791 MITK_WARN << "Found an invalid storage object!";
792 }
793 else if (m_CurrentStorage->GetToolCount() !=
794 m_NavigationDataSource->GetNumberOfOutputs()) // there is something wrong with the storage
795 {
796 MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This "
797 "storage won't be used because it isn't the right one.";
798 m_CurrentStorage = nullptr;
799 }
800}
View for navigated marker placement using the combined modality. This view utilizes the QmitkUSNaviga...
mitk::NavigationDataRecorder::Pointer m_NavigationDataRecorder
void ReinitOnImage()
Helper function which performs a reinit on the ultrasound image.
mitk::NodeDisplacementFilter::Pointer m_TargetNodeDisplacementFilter
void OnSettingsChanged(itk::SmartPointer< mitk::DataNode >)
Switches the navigation step widgets if the navigation application was changed.
mitk::NodeDisplacementFilter::Pointer m_AblationZonesDisplacementFilter
void OnCombinedModalityPropertyChanged(const std::string &, const std::string &)
itk::SmartPointer< mitk::DataNode > m_SettingsNode
mitk::USImageLoggingFilter::Pointer m_USImageLoggingFilter
itk::SmartPointer< mitk::AbstractUltrasoundTrackerDevice > m_CombinedModality
itk::SmartPointer< mitk::DataNode > m_ImageStreamNode
itk::SmartPointer< mitk::DataNode > m_BaseNode
mitk::NavigationToolStorage::Pointer m_CurrentStorage
void Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes)
Helper function for being able to serialize the 2d ultrasound image.
itk::SmartPointer< mitk::TextAnnotation2D > m_WarnOverlay
void OnTimeout()
Called periodically to update the rendering. The standard multi widget is changed to fit the navigati...
void OnStartExperiment()
Initializes anything necessary for an experiment. The user is asked for a directory for storing the r...
mitk::NavigationDataObjectVisualizationFilter::Pointer m_ToolVisualizationFilter
void OnFinishExperiment()
Stops logging and saves everything to the file system.
mitk::NavigationDataSource::Pointer m_NavigationDataSource
virtual void SetTwoWindowView()
Sets the multiwidget to two windows, axial on top and 3D render window on the bottom.
void OnImageAndNavigationDataLoggingTimeout()
Called periodically during an experiment for logging the ultrasound images.
std::vector< mitk::DataNode::Pointer > m_AblationZonesVector
itk::SmartPointer< mitk::USNavigationStepTimer > m_NavigationStepTimer
mitk::USNavigationLoggingBackend m_LoggingBackend
void SetFocus() override
A reinit on the ultrasound image is performed every time the view gets the focus.
An object of this class represents a collection of navigation tools. You may add/delete navigation to...
static const std::string US_PROPKEY_SOURCE_ID
static mitk::USDevice::PropertyKeys GetPropertyKeys()
void WriteCSVFileWithNavigationMessages(std::string filename)
void SetOutputFileName(std::string filename)
Set file path und name for the output file. The file will be opened and all log messages will be dire...
IGT Exceptions.
int strcmp(const String &s1, const String &s2)
Definition relates.cpp:14