Fraxinus  17.12
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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 #include "cxImageLandmarksWidget.h"
34 
35 #include <sstream>
36 #include <QVBoxLayout>
37 #include <QPushButton>
38 #include <QTableWidget>
39 #include <QTableWidgetItem>
40 #include <QHeaderView>
41 #include <QLabel>
42 #include <QSlider>
43 #include <vtkDoubleArray.h>
44 #include <vtkImageData.h>
45 #include "cxLogger.h"
46 #include "cxPickerRep.h"
48 #include "cxSettings.h"
49 #include "cxLandmarkRep.h"
50 #include "cxView.h"
51 #include "cxTypeConversions.h"
53 #include "cxRegistrationService.h"
54 #include "cxPatientModelService.h"
55 #include "cxViewService.h"
56 #include "cxRepContainer.h"
57 #include "cxTrackingService.h"
58 #include "cxLandmarkListener.h"
59 #include "cxActiveData.h"
60 #include "cxPointMetric.h"
61 #include "cxSpaceProvider.h"
62 
63 namespace cx
64 {
65 ImageLandmarksWidget::ImageLandmarksWidget(RegServicesPtr services, QWidget* parent,
66  QString objectName, QString windowTitle, bool useRegistrationFixedPropertyInsteadOfActiveImage) :
67  LandmarkRegistrationWidget(services, parent, objectName, windowTitle),
68  mUseRegistrationFixedPropertyInsteadOfActiveImage(useRegistrationFixedPropertyInsteadOfActiveImage),
69  mLandmarksShowAdvancedSettingsString("Landmarks/ShowAdvanced")
70 {
71  if(mUseRegistrationFixedPropertyInsteadOfActiveImage)
72  mCurrentProperty.reset(new StringPropertyRegistrationFixedImage(services->registration(), services->patient()));
73  else
76 
77  mLandmarkListener->useOnlyOneSourceUpdatedFromOutside();
78 
79  mActiveToolProxy = ActiveToolProxy::New(services->tracking());
80  connect(mActiveToolProxy.get(), SIGNAL(toolVisible(bool)), this, SLOT(enableButtons()));
81  connect(mActiveToolProxy.get(), SIGNAL(activeToolChanged(const QString&)), this, SLOT(enableButtons()));
82 
83  //pushbuttons
84  mAddLandmarkButton = new QPushButton("New Landmark", this);
85  mAddLandmarkButton->setToolTip("Add landmark");
86  mAddLandmarkButton->setDisabled(true);
87  connect(mAddLandmarkButton, SIGNAL(clicked()), this, SLOT(addLandmarkButtonClickedSlot()));
88 
89  mEditLandmarkButton = new QPushButton("Resample", this);
90  mEditLandmarkButton->setToolTip("Resample the selected landmark");
91  mEditLandmarkButton->setDisabled(true);
92  connect(mEditLandmarkButton, SIGNAL(clicked()), this, SLOT(editLandmarkButtonClickedSlot()));
93 
94  mRemoveLandmarkButton = new QPushButton("Clear", this);
95  mRemoveLandmarkButton->setToolTip("Clear the selected landmark");
96  mRemoveLandmarkButton->setDisabled(true);
97  connect(mRemoveLandmarkButton, SIGNAL(clicked()), this, SLOT(removeLandmarkButtonClickedSlot()));
98 
99  mDeleteLandmarksButton = new QPushButton("Delete All", this);
100  mDeleteLandmarksButton->setToolTip("Delete all landmarks");
101  connect(mDeleteLandmarksButton, SIGNAL(clicked()), this, SLOT(deleteLandmarksButtonClickedSlot()));
102 
103  mImportLandmarksFromPointMetricsButton = new QPushButton("Import Point Metrics", this);
104  mImportLandmarksFromPointMetricsButton->setToolTip("Import point metrics as landmarks. See the help pages for the details.");
106 
107  //layout
111 
112  QHBoxLayout* landmarkButtonsLayout = new QHBoxLayout;
113  landmarkButtonsLayout->addWidget(mAddLandmarkButton);
114  landmarkButtonsLayout->addWidget(mEditLandmarkButton);
115  landmarkButtonsLayout->addWidget(mRemoveLandmarkButton);
116  landmarkButtonsLayout->addWidget(mDeleteLandmarksButton);
117  mDetailsAction = this->createAction(this,
118  QIcon(":/icons/open_icon_library/system-run-5.png"),
119  "Advanced", "Toggle advanced options",
120  SLOT(toggleDetailsSlot()),
121  landmarkButtonsLayout);
122  mVerticalLayout->addLayout(landmarkButtonsLayout);
123 
124  QHBoxLayout* landmarkAdvancedButtonsLayout = new QHBoxLayout;
125  landmarkAdvancedButtonsLayout = new QHBoxLayout;
126  landmarkAdvancedButtonsLayout->addWidget(mImportLandmarksFromPointMetricsButton);
127  mVerticalLayout->addLayout(landmarkAdvancedButtonsLayout);
128 
129  this->showOrHideDetails();
130 }
131 
133 {
134 }
135 
137 {
138  DataPtr data = mCurrentProperty->getData();
139 
140  mLandmarkListener->setLandmarkSource(data);
141  this->enableButtons();
142 
143  if (data && !mServices->registration()->getFixedData())
144  mServices->registration()->setFixedData(data);
145 
146  this->setModified();
147 }
148 
150 {
151  bool newShowAdvancedValue = !settings()->value(mLandmarksShowAdvancedSettingsString, "true").toBool();
152  settings()->setValue(mLandmarksShowAdvancedSettingsString, newShowAdvancedValue);
153  this->showOrHideDetails();
154 }
155 
156 void ImageLandmarksWidget::showOrHideDetails()
157 {
158  bool showAdvanced = settings()->value(mLandmarksShowAdvancedSettingsString).toBool();
159  mImportLandmarksFromPointMetricsButton->setVisible(showAdvanced);
160 }
161 
163 {
164  return mServices->view()->get3DReps(0, 0)->findFirst<PickerRep>();
165 }
166 
167 DataPtr ImageLandmarksWidget::getCurrentData() const
168 {
169  return mLandmarkListener->getLandmarkSource();
170 }
171 
173 {
175  if (!PickerRep)
176  {
177  reportError("Need a 3D view to set landmarks.");
178  return;
179  }
180 
181  DataPtr image = this->getCurrentData();
182  if (!image)
183  return;
184 
185  QString uid = mServices->patient()->addLandmark();
186  Vector3D pos_r = PickerRep->getPosition();
187  Vector3D pos_d = image->get_rMd().inv().coord(pos_r);
188  image->getLandmarks()->setLandmark(Landmark(uid, pos_d));
189 
190  this->activateLandmark(uid);
191 }
192 
193 
195 {
197  if (!PickerRep)
198  {
199  reportError("Need a 3D view to edit landmarks.");
200  return;
201  }
202 
203  DataPtr image = this->getCurrentData();
204  if (!image)
205  return;
206 
207  QString uid = mActiveLandmark;
208  Vector3D pos_r = PickerRep->getPosition();
209  Vector3D pos_d = image->get_rMd().inv().coord(pos_r);
210  image->getLandmarks()->setLandmark(Landmark(uid, pos_d));
211 
212  this->activateLandmark(this->getNextLandmark());
213 }
214 
216 {
217  DataPtr image = this->getCurrentData();
218  if (!image)
219  return;
220 
221  QString next = this->getNextLandmark();
222  image->getLandmarks()->removeLandmark(mActiveLandmark);
223  this->activateLandmark(next);
224 }
225 
227 {
228  DataPtr image = this->getCurrentData();
229  if (!image)
230  return;
231 
232  image->getLandmarks()->clear();
233  this->setModified();
234  mServices->patient()->deleteLandmarks();
235 }
236 
238 {
239  DataPtr image = this->getCurrentData();
240  if(!image)
241  return;
242 
243  std::map<QString, DataPtr> point_metrics = mServices->patient()->getChildren(image->getUid(), "pointMetric");
244  std::map<QString, DataPtr>::iterator it = point_metrics.begin();
245 
246  //Make sure we have enough landmarks
247  int number_of_landmarks = mServices->patient()->getLandmarkProperties().size();
248  int number_of_metrics = point_metrics.size();
249  for(int i=number_of_landmarks; i<number_of_metrics; ++i)
250  {
251  QString uid = mServices->patient()->addLandmark();
252  }
253 
254  for(; it != point_metrics.end(); ++it)
255  {
256  PointMetricPtr point_metric = boost::static_pointer_cast<PointMetric>(it->second);
257  if(!point_metric)
258  continue;
259 
260  Vector3D pos_x = point_metric->getCoordinate();
261  //Transform3D d_M_x = mServices->spaceProvider()->get_toMfrom(CoordinateSystem::fromString(image->getSpace()), point_metric->getSpace());
262  //Vector3D pos_d = d_M_x.coord(pos_x);
263  QString point_metric_name = point_metric->getName();
264  image->getLandmarks()->setLandmark(Landmark(point_metric_name, pos_x));
265  this->activateLandmark(point_metric_name);
266  }
267 }
268 
269 void ImageLandmarksWidget::cellClickedSlot(int row, int column)
270 {
272  this->enableButtons();
273 }
274 
276 {
277  bool selected = !mLandmarkTableWidget->selectedItems().isEmpty();
278  bool loaded = this->getCurrentData() != 0;
279 
280  mEditLandmarkButton->setEnabled(selected);
281  mRemoveLandmarkButton->setEnabled(selected);
282  mDeleteLandmarksButton->setEnabled(loaded);
283  mAddLandmarkButton->setEnabled(loaded);
284  mImportLandmarksFromPointMetricsButton->setEnabled(loaded);
285 
286  DataPtr image = this->getCurrentData();
287  if (image)
288  {
289  mAddLandmarkButton->setToolTip(QString("Add landmark to image %1").arg(image->getName()));
290  mEditLandmarkButton->setToolTip(QString("Resample landmark in image %1").arg(image->getName()));
291  }
292 }
293 
294 void ImageLandmarksWidget::showEvent(QShowEvent* event)
295 {
296  mServices->view()->setRegistrationMode(rsIMAGE_REGISTRATED);
298 
299  if(!mUseRegistrationFixedPropertyInsteadOfActiveImage)
300  {
301  ActiveDataPtr activeData = mServices->patient()->getActiveData();
302  ImagePtr image = activeData->getActive<Image>();
303  if (image)
304  mCurrentProperty->setValue(image->getUid());
305  }
306 }
307 
308 void ImageLandmarksWidget::hideEvent(QHideEvent* event)
309 {
310  mServices->view()->setRegistrationMode(rsNOT_REGISTRATED);
312 
313 }
314 
316 {
318 
319  std::vector<Landmark> landmarks = this->getAllLandmarks();
320 
321  //update buttons
322  mRemoveLandmarkButton->setEnabled(!landmarks.empty() && !mActiveLandmark.isEmpty());
323  mEditLandmarkButton->setEnabled(!landmarks.empty() && !mActiveLandmark.isEmpty());
324  this->showOrHideDetails();
325 }
326 
328 {
329  DataPtr image = this->getCurrentData();
330  if (!image)
331  return LandmarkMap();
332 
333  return image->getLandmarks()->getLandmarks();
334 }
335 
340 {
341  DataPtr image = this->getCurrentData();
342  if (!image)
343  return Transform3D::Identity();
344  return image->get_rMd();
345 }
346 
348 {
349  DataPtr image = this->getCurrentData();
350  if (!image)
351  return;
352  image->getLandmarks()->setLandmark(Landmark(uid, p_target));
353 }
354 
356 {
357  DataPtr image = this->getCurrentData();
358  if (!image)
359  return "None";
360  return image->getName();
361 }
362 
363 
364 }//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:92
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:61
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:48
virtual void hideEvent(QHideEvent *event)
boost::shared_ptr< class ActiveData > ActiveDataPtr
Definition: cxColorWidget.h:42
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:87
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:150
virtual void hideEvent(QHideEvent *event)
static ActiveToolProxyPtr New(TrackingServicePtr trackingService)
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:79
boost::shared_ptr< class Data > DataPtr
boost::shared_ptr< class PickerRep > PickerRepPtr
ActiveToolProxyPtr mActiveToolProxy
Picking of points in an image.
Definition: cxPickerRep.h:70
void addLandmarkButtonClickedSlot()
reacts when the Add Landmark button is clicked
QPushButton * mImportLandmarksFromPointMetricsButton
the Import Landmarks button
A volumetric data set.
Definition: cxImage.h:66
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:41
virtual void prePaintEvent()
populates the table widget
rsNOT_REGISTRATED
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:42
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:63
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
std::map< QString, class Landmark > LandmarkMap
QString mActiveLandmark
uid of surrently selected landmark.
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 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