CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxImageLandmarksWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxImageLandmarksWidget.h"
13 
14 #include <sstream>
15 #include <QVBoxLayout>
16 #include <QPushButton>
17 #include <QTableWidget>
18 #include <QTableWidgetItem>
19 #include <QHeaderView>
20 #include <QLabel>
21 #include <QSlider>
22 #include <QCheckBox>
23 #include <vtkDoubleArray.h>
24 #include <vtkImageData.h>
25 #include "cxLogger.h"
26 #include "cxPickerRep.h"
28 #include "cxSettings.h"
29 #include "cxLandmarkRep.h"
30 #include "cxView.h"
31 #include "cxTypeConversions.h"
33 #include "cxRegistrationService.h"
34 #include "cxPatientModelService.h"
35 #include "cxViewService.h"
36 #include "cxRepContainer.h"
37 #include "cxTrackingService.h"
38 #include "cxLandmarkListener.h"
39 #include "cxActiveData.h"
40 #include "cxPointMetric.h"
41 #include "cxSpaceProvider.h"
42 
43 namespace cx
44 {
45 ImageLandmarksWidget::ImageLandmarksWidget(RegServicesPtr services, QWidget* parent,
46  QString objectName, QString windowTitle,
47  bool useRegistrationFixedPropertyInsteadOfActiveImage) :
48  LandmarkRegistrationWidget(services, parent, objectName, windowTitle),
49  mUseRegistrationFixedPropertyInsteadOfActiveImage(useRegistrationFixedPropertyInsteadOfActiveImage),
50  mLandmarksShowAdvancedSettingsString("Landmarks/ShowAdvanced")
51 {
52  if(mUseRegistrationFixedPropertyInsteadOfActiveImage)
53  mCurrentProperty.reset(new StringPropertyRegistrationFixedImage(services->registration(), services->patient()));
54  else
57 
58  mLandmarkListener->useOnlyOneSourceUpdatedFromOutside();
59 
60  mActiveToolProxy = ActiveToolProxy::New(services->tracking());
61  connect(mActiveToolProxy.get(), SIGNAL(toolVisible(bool)), this, SLOT(enableButtons()));
62  connect(mActiveToolProxy.get(), SIGNAL(activeToolChanged(const QString&)), this, SLOT(enableButtons()));
63 
64  //pushbuttons
65  mAddLandmarkButton = new QPushButton("New Landmark", this);
66  mAddLandmarkButton->setToolTip("Add landmark");
67  mAddLandmarkButton->setDisabled(true);
68  connect(mAddLandmarkButton, SIGNAL(clicked()), this, SLOT(addLandmarkButtonClickedSlot()));
69 
70  mEditLandmarkButton = new QPushButton("Resample", this);
71  mEditLandmarkButton->setToolTip("Resample the selected landmark");
72  mEditLandmarkButton->setDisabled(true);
73  connect(mEditLandmarkButton, SIGNAL(clicked()), this, SLOT(editLandmarkButtonClickedSlot()));
74 
75  mRemoveLandmarkButton = new QPushButton("Clear", this);
76  mRemoveLandmarkButton->setToolTip("Clear the selected landmark");
77  mRemoveLandmarkButton->setDisabled(true);
78  connect(mRemoveLandmarkButton, SIGNAL(clicked()), this, SLOT(removeLandmarkButtonClickedSlot()));
79 
80  mDeleteLandmarksButton = new QPushButton("Delete All", this);
81  mDeleteLandmarksButton->setToolTip("Delete all landmarks");
82  connect(mDeleteLandmarksButton, SIGNAL(clicked()), this, SLOT(deleteLandmarksButtonClickedSlot()));
83 
84  mImportLandmarksFromPointMetricsButton = new QPushButton("Import Point Metrics", this);
85  mImportLandmarksFromPointMetricsButton->setToolTip("Import point metrics as landmarks. See the help pages for the details.");
87 
88  //layout
92 
93  QHBoxLayout* landmarkButtonsLayout = new QHBoxLayout;
94  landmarkButtonsLayout->addWidget(mAddLandmarkButton);
95  landmarkButtonsLayout->addWidget(mEditLandmarkButton);
96  landmarkButtonsLayout->addWidget(mRemoveLandmarkButton);
97  landmarkButtonsLayout->addWidget(mDeleteLandmarksButton);
98  mDetailsAction = this->createAction(this,
99  QIcon(":/icons/open_icon_library/system-run-5.png"),
100  "Advanced", "Toggle advanced options",
101  SLOT(toggleDetailsSlot()),
102  landmarkButtonsLayout);
103  mVerticalLayout->addLayout(landmarkButtonsLayout);
104 
105  QHBoxLayout* landmarkAdvancedButtonsLayout = new QHBoxLayout;
106  landmarkAdvancedButtonsLayout = new QHBoxLayout;
107  landmarkAdvancedButtonsLayout->addWidget(mImportLandmarksFromPointMetricsButton);
108  mVerticalLayout->addLayout(landmarkAdvancedButtonsLayout);
109 
110  mMouseClickSample->show();
111  connect(mMouseClickSample, &QCheckBox::stateChanged, this, &ImageLandmarksWidget::mouseClickSampleStateChanged);
113 
114  this->showOrHideDetails();
115 }
116 
118 {
119 }
120 
122 {
123  DataPtr data = mCurrentProperty->getData();
124 
125  mLandmarkListener->setLandmarkSource(data);
126  this->enableButtons();
127 
128  if (data && !mServices->registration()->getFixedData())
129  mServices->registration()->setFixedData(data);
130 
131  this->setModified();
132 }
133 
135 {
136  bool newShowAdvancedValue = !settings()->value(mLandmarksShowAdvancedSettingsString, "true").toBool();
137  settings()->setValue(mLandmarksShowAdvancedSettingsString, newShowAdvancedValue);
138  this->showOrHideDetails();
139 }
140 
141 void ImageLandmarksWidget::showOrHideDetails()
142 {
143  bool showAdvanced = settings()->value(mLandmarksShowAdvancedSettingsString).toBool();
144  mImportLandmarksFromPointMetricsButton->setVisible(showAdvanced);
145 }
146 
148 {
149  return mServices->view()->get3DReps(0, 0)->findFirst<PickerRep>();
150 }
151 
152 DataPtr ImageLandmarksWidget::getCurrentData() const
153 {
154  return mLandmarkListener->getLandmarkSource();
155 }
156 
157 
159 {
160  this->resampleLandmark(p_r);
161  //Only use the anyplane sampler for resample for now
162  //this->addLandmark(p_r);
163 }
164 
166 {
168  if (!PickerRep)
169  {
170  reportError("Need a 3D view to set landmarks.");
171  return;
172  }
173  Vector3D pos_r = PickerRep->getPosition();
174  this->addLandmark(pos_r);
175 }
176 
178 {
179  DataPtr image = this->getCurrentData();
180  if (!image)
181  return;
182  QString uid = mServices->patient()->addLandmark();
183  Vector3D pos_d = image->get_rMd().inv().coord(p_r);
184  image->getLandmarks()->setLandmark(Landmark(uid, pos_d));
185  this->activateLandmark(uid);
186 }
187 
188 
190 {
192  if (!PickerRep)
193  {
194  reportError("Need a 3D view to edit landmarks.");
195  return;
196  }
197 
198  Vector3D pos_r = PickerRep->getPosition();
199  this->resampleLandmark(pos_r);
200 }
201 
203 {
204  DataPtr image = this->getCurrentData();
205  if (!image)
206  return;
207  QString uid = mActiveLandmark;
208  Vector3D pos_d = image->get_rMd().inv().coord(p_r);
209  image->getLandmarks()->setLandmark(Landmark(uid, pos_d));
210 
211  this->activateLandmark(this->getNextLandmark());
212 }
213 
215 {
216  DataPtr image = this->getCurrentData();
217  if (!image)
218  return;
219 
220  QString next = this->getNextLandmark();
221  image->getLandmarks()->removeLandmark(mActiveLandmark);
222  this->activateLandmark(next);
223 }
224 
226 {
227  DataPtr image = this->getCurrentData();
228  if (!image)
229  return;
230 
231  image->getLandmarks()->clear();
232  this->setModified();
233  mServices->patient()->deleteLandmarks();
234 }
235 
237 {
238  DataPtr image = this->getCurrentData();
239  if(!image)
240  return;
241 
242  std::map<QString, DataPtr> point_metrics = mServices->patient()->getChildren(image->getUid(), PointMetric::getTypeName());
243  std::map<QString, DataPtr>::iterator it = point_metrics.begin();
244 
245  //Make sure we have enough landmarks
246  int number_of_landmarks = mServices->patient()->getLandmarkProperties().size();
247  int number_of_metrics = point_metrics.size();
248  for(int i=number_of_landmarks; i<number_of_metrics; ++i)
249  {
250  QString uid = mServices->patient()->addLandmark();
251  }
252 
253  for(; it != point_metrics.end(); ++it)
254  {
255  PointMetricPtr point_metric = boost::static_pointer_cast<PointMetric>(it->second);
256  if(!point_metric)
257  continue;
258 
259  Vector3D pos_x = point_metric->getCoordinate();
260  //Transform3D d_M_x = mServices->spaceProvider()->get_toMfrom(CoordinateSystem::fromString(image->getSpace()), point_metric->getSpace());
261  //Vector3D pos_d = d_M_x.coord(pos_x);
262  QString point_metric_name = point_metric->getName();
263  image->getLandmarks()->setLandmark(Landmark(point_metric_name, pos_x));
264  this->activateLandmark(point_metric_name);
265  }
266 }
267 
268 void ImageLandmarksWidget::cellClickedSlot(int row, int column)
269 {
271  this->enableButtons();
272 }
273 
275 {
276  bool selected = !mLandmarkTableWidget->selectedItems().isEmpty();
277  bool loaded = this->getCurrentData() != 0;
278 
279  mEditLandmarkButton->setEnabled(selected);
280  mRemoveLandmarkButton->setEnabled(selected);
281  mDeleteLandmarksButton->setEnabled(loaded);
282  mAddLandmarkButton->setEnabled(loaded);
283  mImportLandmarksFromPointMetricsButton->setEnabled(loaded);
284 
285  DataPtr image = this->getCurrentData();
286  if (image)
287  {
288  mAddLandmarkButton->setToolTip(QString("Add landmark to image %1").arg(image->getName()));
289  mEditLandmarkButton->setToolTip(QString("Resample landmark in image %1").arg(image->getName()));
290  }
291 }
292 
293 void ImageLandmarksWidget::showEvent(QShowEvent* event)
294 {
295  mServices->view()->setRegistrationMode(rsIMAGE_REGISTRATED);
297 
298  if(!mUseRegistrationFixedPropertyInsteadOfActiveImage)
299  {
300  ActiveDataPtr activeData = mServices->patient()->getActiveData();
301  ImagePtr image = activeData->getActive<Image>();
302  if (image)
303  mCurrentProperty->setValue(image->getUid());
304  }
305 }
306 
307 void ImageLandmarksWidget::hideEvent(QHideEvent* event)
308 {
309  mServices->view()->setRegistrationMode(rsNOT_REGISTRATED);
311 
312 }
313 
315 {
317 
318  std::vector<Landmark> landmarks = this->getAllLandmarks();
319 
320  //update buttons
321  mRemoveLandmarkButton->setEnabled(!landmarks.empty() && !mActiveLandmark.isEmpty());
322  mEditLandmarkButton->setEnabled(!landmarks.empty() && !mActiveLandmark.isEmpty());
323  this->showOrHideDetails();
324 }
325 
327 {
328  DataPtr image = this->getCurrentData();
329  if (!image)
330  return LandmarkMap();
331 
332  return image->getLandmarks()->getLandmarks();
333 }
334 
339 {
340  DataPtr image = this->getCurrentData();
341  if (!image)
342  return Transform3D::Identity();
343  return image->get_rMd();
344 }
345 
347 {
348  DataPtr image = this->getCurrentData();
349  if (!image)
350  return;
351  image->getLandmarks()->setLandmark(Landmark(uid, p_target));
352 }
353 
355 {
356  DataPtr image = this->getCurrentData();
357  if (!image)
358  return "None";
359  return image->getName();
360 }
361 
362 
363 }//namespace cx
void deleteLandmarksButtonClickedSlot()
reacts when the Delete Landmarks button is clicked
virtual void showEvent(QShowEvent *event)
updates internal info before showing the widget
virtual void editLandmarkButtonClickedSlot()
reacts when the Edit Landmark button is clicked
QPushButton * mRemoveLandmarkButton
the Remove Landmark button
void reportError(QString msg)
Definition: cxLogger.cpp:71
void removeLandmarkButtonClickedSlot()
reacts when the Remove Landmark button is clicked
QPushButton * mEditLandmarkButton
the Edit Landmark button
QLabel * mAvarageAccuracyLabel
label showing the average accuracy
QPushButton * mAddLandmarkButton
the Add Landmark button
One landmark, or fiducial, coordinate.
Definition: cxLandmark.h:40
virtual Transform3D getTargetTransform() const
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
virtual void showEvent(QShowEvent *event)
updates internal info before showing the widget
static StringPropertySelectDataPtr New(PatientModelServicePtr patientModelService, QString typeRegexp=".*")
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
virtual void hideEvent(QHideEvent *event)
boost::shared_ptr< class ActiveData > ActiveDataPtr
Definition: cxColorWidget.h:21
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:66
Composite widget for string selection.
QVBoxLayout * mVerticalLayout
vertical layout is used
virtual void setTargetLandmark(QString uid, Vector3D p_target)
QAction * createAction(QObject *parent, QIcon iconName, QString text, QString tip, T slot, QLayout *layout=NULL, QToolButton *button=new QToolButton())
Definition: cxBaseWidget.h:129
virtual void hideEvent(QHideEvent *event)
static ActiveToolProxyPtr New(TrackingServicePtr trackingService)
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:58
boost::shared_ptr< class Data > DataPtr
boost::shared_ptr< class PickerRep > PickerRepPtr
ActiveToolProxyPtr mActiveToolProxy
Picking of points in an image.
Definition: cxPickerRep.h:49
void addLandmarkButtonClickedSlot()
reacts when the Add Landmark button is clicked
QPushButton * mImportLandmarksFromPointMetricsButton
the Import Landmarks button
A volumetric data set.
Definition: cxImage.h:45
virtual void cellClickedSlot(int row, int column)
when a landmark is selected from the table
Vector3D getCoordinate() const
boost::shared_ptr< class RegServices > RegServicesPtr
Definition: cxRegServices.h:20
virtual void prePaintEvent()
populates the table widget
rsNOT_REGISTRATED
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:21
virtual void prePaintEvent()
populates the table widget
void changed()
emit when the underlying data value is changed: The user interface will be updated.
virtual QString getTargetName() const
Data class that represents a single point.
Definition: cxPointMetric.h:42
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
std::map< QString, class Landmark > LandmarkMap
QString mActiveLandmark
uid of currently selected landmark.
static QString getTypeName()
Definition: cxPointMetric.h:58
std::vector< Landmark > getAllLandmarks() const
get all the landmarks from the image and the datamanager
SelectDataStringPropertyBasePtr mCurrentProperty
QPushButton * mDeleteLandmarksButton
the Delete Landmarks button
virtual LandmarkMap getTargetLandmarks() const
virtual void pointSampled(Vector3D p_r)
virtual void cellClickedSlot(int row, int column)
when a landmark is selected from the table
rsIMAGE_REGISTRATED
QTableWidget * mLandmarkTableWidget
the table widget presenting the landmarks
Namespace for all CustusX production code.
boost::shared_ptr< class PointMetric > PointMetricPtr