MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
QmitkUSNavigationStepTumourSelection.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============================================================================*/
13#include "ui_QmitkUSNavigationStepTumourSelection.h"
14
15#include "usModuleRegistry.h"
16
17#include "mitkDataNode.h"
18#include "mitkSurface.h"
23
25
26#include "mitkIOUtil.h"
27
28#include "vtkSmartPointer.h"
29#include "vtkDoubleArray.h"
30#include "vtkPolyData.h"
31#include "vtkPointData.h"
32#include "vtkWarpScalar.h"
33
36 m_targetSelectionOptional(false),
37 m_SecurityDistance(0),
38 m_Interactor(mitk::USZonesInteractor::New()),
39 m_NodeDisplacementFilter(mitk::NodeDisplacementFilter::New()),
40 m_StateMachineFilename("USZoneInteractions.xml"),
41 m_ReferenceSensorIndex(1),
42 m_ListenerChangeNode(this, &QmitkUSNavigationStepTumourSelection::TumourNodeChanged),
44{
45 ui->setupUi(this);
46
47 connect(ui->freezeImageButton, SIGNAL(SignalFreezed(bool)), this, SLOT(OnFreeze(bool)));
48 connect(ui->tumourSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnTumourSizeChanged(int)));
49 connect(ui->deleteTumourButton, SIGNAL(clicked()), this, SLOT(OnDeleteButtonClicked()));
50
51 m_SphereColor = mitk::Color();
52 //default color: green
53 m_SphereColor[0] = 0;
54 m_SphereColor[1] = 255;
55 m_SphereColor[2] = 0;
56}
61
66
71
73{
78
79 // load state machine and event config for data interactor
80 m_Interactor->LoadStateMachine(m_StateMachineFilename, us::ModuleRegistry::GetModule("MitkUS"));
81 m_Interactor->SetEventConfig("globalConfig.xml");
82
83 this->GetDataStorage()->ChangedNodeEvent.AddListener(m_ListenerChangeNode);
84
88
89 // do not show the surface until this is requested
90 m_TargetSurfaceNode->SetBoolProperty("visible", false);
91
92 // make sure that scalars will be renderer on the surface
93 m_TargetSurfaceNode->SetBoolProperty("scalar visibility", true);
94 m_TargetSurfaceNode->SetBoolProperty("color mode", true);
95 m_TargetSurfaceNode->SetBoolProperty("Backface Culling", true);
96
97 return true;
98}
99
101{
102 // make sure that imaging isn't freezed anymore
103 ui->freezeImageButton->Unfreeze();
104
105 m_NodeDisplacementFilter->ResetNodes();
106
107 mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(false);
108 if (dataStorage.IsNotNull())
109 {
110 // remove target surface node from data storage, if available there
111 if (m_TargetSurfaceNode.IsNotNull()) { dataStorage->Remove(m_TargetSurfaceNode); }
112
113 dataStorage->ChangedNodeEvent.RemoveListener(m_ListenerChangeNode);
114 dataStorage->Remove(m_TumourNode);
115 m_TumourNode = nullptr;
116 }
117
118 MITK_INFO("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection")
119 << "Removing tumour.";
120
121 return true;
122}
123
125{
126 ui->tumourSizeExplanationLabel->setEnabled(false);
127 ui->tumourSizeLabel->setEnabled(false);
128 ui->tumourSizeSlider->setEnabled(false);
129 ui->deleteTumourButton->setEnabled(false);
130
131 ui->tumourSizeSlider->blockSignals(true);
132 ui->tumourSizeSlider->setValue(0);
133 ui->tumourSizeSlider->blockSignals(false);
134
135
137}
138
140{
141 // make sure that the surface has the right extent (in case the
142 // tumor size was changed since the initial surface creation)
144
145 return true;
146}
147
149{
150 m_Interactor = mitk::USZonesInteractor::New();
151 m_Interactor->LoadStateMachine(m_StateMachineFilename, us::ModuleRegistry::GetModule("MitkUS"));
152 m_Interactor->SetEventConfig("globalConfig.xml");
153
154 m_NodeDisplacementFilter->ConnectTo(this->GetCombinedModality()->GetNavigationDataSource());
155 m_NodeDisplacementFilter->SelectInput(1);//m_ReferenceSensorIndex
156
157 //target selection is optional
159
160 return true;
161}
162
164{
165 m_Interactor->SetDataNode(nullptr);
166
167 bool value;
168 if (m_TumourNode.IsNotNull() && !(m_TumourNode->GetBoolProperty("zone.created", value) && value))
169 {
170 m_TumourNode->SetData(nullptr);
171 }
172
173 // make sure that imaging isn't freezed anymore
174 ui->freezeImageButton->Unfreeze();
175
176 return true;
177}
178
180{
181 if (m_NavigationDataSource.IsNull()) { return; }
182
183 m_NavigationDataSource->Update();
184 m_NodeDisplacementFilter->Update();
185
186 bool valid = m_NavigationDataSource->GetOutput(m_ReferenceSensorIndex)->IsDataValid();
187
188 if (valid)
189 {
190 ui->bodyMarkerTrackingStatusLabel->setStyleSheet(
191 "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey");
192 ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume.");
193 }
194 else
195 {
196 ui->bodyMarkerTrackingStatusLabel->setStyleSheet(
197 "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey");
198 ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume.");
199 }
200
201 ui->freezeImageButton->setEnabled(valid);
202
203 bool created;
204 if (m_TumourNode.IsNull() || !m_TumourNode->GetBoolProperty("zone.created", created) || !created)
205 {
206 ui->tumourSearchExplanationLabel->setEnabled(valid);
207 }
208}
209
211{
212 if (settingsNode.IsNull()) { return; }
213
214 float securityDistance;
215 if (settingsNode->GetFloatProperty("settings.security-distance", securityDistance))
216 {
217 m_SecurityDistance = securityDistance;
218 }
219
220 std::string stateMachineFilename;
221 if (settingsNode->GetStringProperty("settings.interaction-concept", stateMachineFilename) && stateMachineFilename != m_StateMachineFilename)
222 {
223 m_StateMachineFilename = stateMachineFilename;
224 m_Interactor->LoadStateMachine(stateMachineFilename, us::ModuleRegistry::GetModule("MitkUS"));
225 }
226
227 std::string referenceSensorName;
228 if (settingsNode->GetStringProperty("settings.reference-name-selected", referenceSensorName))
229 {
230 m_ReferenceSensorName = referenceSensorName;
231 }
232
234}
235
237{
238 return "Localisation of Tumour Position";
239}
240
245
247{
248 if (freezed) this->GetCombinedModality()->SetIsFreezed(true);
249
250 ui->tumourSelectionExplanation1Label->setEnabled(freezed);
251 ui->tumourSelectionExplanation2Label->setEnabled(freezed);
252
253 if (freezed)
254 {
255 if (!m_TumourNode->GetData())
256 {
257 // load state machine and event config for data interactor
258 m_Interactor->LoadStateMachine(m_StateMachineFilename, us::ModuleRegistry::GetModule("MitkUS"));
259 m_Interactor->SetEventConfig("globalConfig.xml");
260
261 m_Interactor->SetDataNode(m_TumourNode);
262 // feed reference pose to node displacement filter
263 m_NodeDisplacementFilter->SetInitialReferencePose(this->GetCombinedModality()->GetNavigationDataSource()->GetOutput(m_ReferenceSensorIndex)->Clone());
264 }
265 }
266 else
267 {
268 bool value;
269 if (m_TumourNode->GetBoolProperty("zone.created", value) && value)
270 {
271 ui->freezeImageButton->setEnabled(false);
272 ui->tumourSearchExplanationLabel->setEnabled(false);
273 }
274 }
275
276 if (!freezed) this->GetCombinedModality()->SetIsFreezed(false);
277}
278
280{
281 mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false);
282 if (combinedModality.IsNotNull())
283 {
284 m_NavigationDataSource = combinedModality->GetNavigationDataSource();
285 }
286 else
287 {
288 m_NavigationDataSource = nullptr;
289 }
290
291 ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex);
292
294}
295
297{
298 m_TumourNode->SetFloatProperty("zone.size", static_cast<float>(size));
300
301 MITK_INFO("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection")
302 << "Changing tumour radius to " << size << ".";
303}
304
309
311{
312 // only changes of tumour node are of interest
313 if (dataNode != m_TumourNode) { return; }
314
315 float size;
316 dataNode->GetFloatProperty("zone.size", size);
317
318 ui->tumourSizeSlider->setValue(static_cast<int>(size));
319
320 bool created;
321 if (dataNode->GetBoolProperty("zone.created", created) && created)
322 {
323 if (ui->freezeImageButton->isChecked())
324 {
325 m_NodeDisplacementFilter->AddNode(const_cast<mitk::DataNode*>(dataNode));
326
329
330 MITK_INFO("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection")
331 << "Tumour created with center " << dataNode->GetData()->GetGeometry()->GetOrigin()
332 << " and radius " << size << ".";
333
334 mitk::DataNode::Pointer tumourResultNode = mitk::DataNode::New();
335 tumourResultNode->SetName("TumourResult");
336 tumourResultNode->SetProperty("USNavigation::TumourCenter",
337 mitk::Point3dProperty::New(dataNode->GetData()->GetGeometry()->GetOrigin()));
338 tumourResultNode->SetProperty("USNavigation::TumourRadius", mitk::DoubleProperty::New(size));
339
340 emit SignalIntermediateResult(tumourResultNode);
341
342 ui->freezeImageButton->Unfreeze();
343 }
344
345 ui->tumourSearchExplanationLabel->setEnabled(false);
346 ui->tumourSizeExplanationLabel->setEnabled(true);
347 ui->tumourSizeLabel->setEnabled(true);
348 ui->tumourSizeSlider->setEnabled(true);
349 ui->deleteTumourButton->setEnabled(true);
350
352 }
353}
354
356{
357 mitk::Surface::Pointer tumourSurface = dynamic_cast<mitk::Surface*>(m_TumourNode->GetData());
358
359 if (tumourSurface.IsNull())
360 {
361 MITK_WARN << "No target selected, cannot create surface!";
362 return mitk::Surface::New(); //return a empty surface in this case...
363 }
364
365 // make a deep copy of the tumour surface polydata
367 tumourSurfaceVtk->DeepCopy(tumourSurface->GetVtkPolyData());
368
369 // create scalars for moving every point the same size onto its normal vector
371 int numberOfPoints = tumourSurfaceVtk->GetNumberOfPoints();
372 scalars->SetNumberOfTuples(numberOfPoints);
373
374 // set scalars for warp filter
375 for (vtkIdType i = 0; i < numberOfPoints; ++i) { scalars->SetTuple1(i, m_SecurityDistance * 10); }
376 tumourSurfaceVtk->GetPointData()->SetScalars(scalars);
377
379 warpScalar->SetInputData(tumourSurfaceVtk);
380 warpScalar->SetScaleFactor(1); // use the scalars themselves
381 warpScalar->Update();
382 vtkSmartPointer<vtkPolyData> targetSurfaceVtk = warpScalar->GetPolyDataOutput();
383
384 // set the moved points to the deep copied tumour surface; this is
385 // necessary as setting the targetSurfaceVtk as polydata for the
386 // targetSurface would result in flat shading for the surface (seems
387 // to be a bug in MITK or VTK)
388 tumourSurfaceVtk->SetPoints(targetSurfaceVtk->GetPoints());
389
390 mitk::Surface::Pointer targetSurface = mitk::Surface::New();
391 targetSurface->SetVtkPolyData(tumourSurfaceVtk);
392 targetSurface->GetGeometry()->SetOrigin(tumourSurface->GetGeometry()->GetOrigin());
393
394 return targetSurface;
395}
396
401
403{
404 if (m_NavigationDataSource.IsNull()) { return; }
405
406 if (!m_ReferenceSensorName.empty())
407 {
408 try
409 {
411 }
412 catch (const std::exception &e)
413 {
414 MITK_WARN("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection")
415 << "Cannot get index for reference sensor name: " << e.what();
416 }
417 }
418
420 {
421 MITK_INFO << "############### " << m_NodeDisplacementFilter->GetNumberOfIndexedInputs();
423 }
424
425 ui->freezeImageButton->SetCombinedModality(this->GetCombinedModality(false), m_ReferenceSensorIndex);
426}
Abstract base class for navigation step widgets.
itk::SmartPointer< mitk::DataStorage > GetDataStorage(bool throwNull=true)
Returns the data storage set for the navigation step.
NavigationStepState GetNavigationStepState()
Get the current state of the navigation step.
void SignalReadyForNextStep()
Signals that all necessary actions where done. The user can proceed with the next stept after this wa...
itk::SmartPointer< mitk::DataNode > GetNamedDerivedNodeAndCreate(const char *name, const char *sourceName)
Returns node with the given name and the given source node (parent) from the data storage....
itk::SmartPointer< mitk::AbstractUltrasoundTrackerDevice > GetCombinedModality(bool throwNull=true)
Returns the combined modality set for the navigation step.
std::vector< itk::SmartPointer< mitk::NavigationDataToNavigationDataFilter > > FilterVector
virtual bool OnRestartStep()
Called when restarting a navigation step. This method may be implemented by a concrete subclass to ha...
void SignalIntermediateResult(const itk::SmartPointer< mitk::DataNode >)
Signals that an intermediate result was produced. The properties of the given data node must contain ...
Navigation step for marking the tumor position and extent. The user can mark the position by interact...
void OnDeleteButtonClicked()
Just restarts the navigation step for deleting the tumour.
bool OnStartStep() override
Initializes tumour and target surface.
void OnTumourSizeChanged(int)
Updates the surface of the tumor node according to the new size.
void OnFreeze(bool freezed)
Activates or deactivates the ineractor for tumour creation.
itk::SmartPointer< mitk::NavigationDataSource > m_NavigationDataSource
itk::SmartPointer< mitk::USZonesInteractor > m_Interactor
void OnSetCombinedModality() override
Called every time SetCombinedModality() was called. This method may be implemented by a concrete subc...
QString GetTitle() override
Getter for the title of the navigation step. This title should be human readable and can be used to d...
bool OnFinishStep() override
(Re)creates the target surface.
itk::SmartPointer< mitk::NodeDisplacementFilter > m_NodeDisplacementFilter
bool OnRestartStep() override
Reinitializes buttons and sliders in addition of calling the default implementation.
itk::SmartPointer< mitk::DataNode > m_TargetSurfaceNode
bool OnActivateStep() override
Initializes (but not activates) the interactor for tumour selection.
bool OnStopStep() override
Removes target surface and tumour node from the data storage. Additionally an unfreeze is done and th...
void OnSettingsChanged(const itk::SmartPointer< mitk::DataNode > settingsNode) override
void OnUpdate() override
Updates tracking validity status and checks tumour node for the end of tumour creation.
itk::SmartPointer< mitk::NodeDisplacementFilter > GetTumourNodeDisplacementFilter()
bool OnDeactivateStep() override
Deactivates the interactor for tumour selection and removes data of the tumour node if selection wasn...
static void UpdateSurface(itk::SmartPointer< mitk::DataNode >)
Creates Vtk Sphere according to current radius. The radius is gotten from the float property "zone....
IGT Exceptions.