Fraxinus  17.12-rc4
An IGT application
cxReconstructionWidget.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 #include "cxReconstructionWidget.h"
33 
35 #include "cxLogger.h"
36 #include "cxHelperWidgets.h"
37 #include "cxTypeConversions.h"
39 #include "cxSettings.h"
40 #include "cxTimedAlgorithm.h"
41 #include "cxStringProperty.h"
42 #include "cxDoubleProperty.h"
43 #include "cxBoolProperty.h"
45 
46 namespace cx
47 {
48 
50  BaseWidget(parent, "us_reconstruction", "US Reconstruction"),
51  mReconstructer(reconstructer),
52  mFileSelectWidget( new FileSelectWidget(this))
53 {
54  this->setToolTip("Reconstruct 3D US data from an acquired 2D sequence");
55  connect(mReconstructer.get(), &UsReconstructionService::reconstructAboutToStart, this, &ReconstructionWidget::reconstructAboutToStartSlot);
56  connect(mReconstructer.get(), &UsReconstructionService::reconstructStarted, this, &ReconstructionWidget::reconstructStartedSlot);
57  connect(mReconstructer.get(), &UsReconstructionService::reconstructFinished, this, &ReconstructionWidget::reconstructFinishedSlot);
58 
60  connect(mReconstructer.get(), &UsReconstructionService::inputDataSelected, this, &ReconstructionWidget::inputDataSelected);
61  connect(mReconstructer.get(), &UsReconstructionService::algorithmChanged, this, &ReconstructionWidget::repopulateAlgorithmGroup);
62 
63 
64  QVBoxLayout* topLayout = new QVBoxLayout(this);
65 
66  connect(mFileSelectWidget, &FileSelectWidget::fileSelected, this, &ReconstructionWidget::selectData);
67  mFileSelectWidget->setNameFilter(QStringList() << "*.fts");
68  connect(mReconstructer.get(), &UsReconstructionService::newInputDataAvailable, mFileSelectWidget, &FileSelectWidget::refresh);
69  connect(mReconstructer.get(), &UsReconstructionService::newInputDataPath, this, &ReconstructionWidget::updateFileSelectorPath);
70 
71  QHBoxLayout* extentLayout = new QHBoxLayout;
72  mExtentLineEdit = new QLineEdit(this);
73  mExtentLineEdit->setReadOnly(true);
74  extentLayout->addWidget(new QLabel("Extent", this));
75  extentLayout->addWidget(mExtentLineEdit);
76 
77  mInputSpacingLineEdit = new QLineEdit(this);
78  mInputSpacingLineEdit->setReadOnly(true);
79  QLabel* inputSpacingLabel = new QLabel("Spacing In", this);
80 
81  mReconstructButton = new QPushButton("Reconstruct", this);
82  connect(mReconstructButton, &QPushButton::clicked, this, &ReconstructionWidget::reconstruct);
83 
84  mTimedAlgorithmProgressBar = new cx::TimedAlgorithmProgressBar;
85 
86  QGridLayout* sizesLayout = new QGridLayout;
87  QWidget* maxVolSizeWidget = sscCreateDataWidget(this, mReconstructer->getParam("Volume Size"));
88  sizesLayout->addWidget(inputSpacingLabel, 0, 0);
89  sizesLayout->addWidget(mInputSpacingLineEdit, 0, 1);
90  sizesLayout->addLayout(extentLayout, 0, 2);
91  mSpacingWidget = new SpinBoxGroupWidget(this, DoublePropertyBasePtr(new DoublePropertySpacing(mReconstructer)), sizesLayout, 1);
92  sizesLayout->addWidget(maxVolSizeWidget, 1, 2);
93 
94  QHBoxLayout* runLayout = new QHBoxLayout;
95  topLayout->addLayout(runLayout);
96  runLayout->addWidget(mReconstructButton);
97  this->createAction(this,
98  QIcon(":/icons/open_icon_library/system-run-5.png"),
99  "Details", "Show Advanced Settings",
100  SLOT(toggleDetailsSlot()),
101  runLayout);
102 
103  topLayout->addWidget(mFileSelectWidget);
104  topLayout->addLayout(sizesLayout);
105 
106  QWidget* presetTFWidget = sscCreateDataWidget(this, mReconstructer->getParam("Preset"));
107  topLayout->addWidget(presetTFWidget);
108 
109  mOptionsWidget = this->createOptionsWidget();
110  mOptionsWidget->setVisible(settings()->value("reconstruction/guiShowDetails").toBool());
111  topLayout->addWidget(mOptionsWidget);
112 
113  topLayout->addStretch();
114  topLayout->addWidget(mTimedAlgorithmProgressBar);
115 }
116 
117 void ReconstructionWidget::updateFileSelectorPath(QString path)
118 {
119  mFileSelectWidget->setPath(path);
120  mFileSelectWidget->refresh();
121 }
122 
123 void ReconstructionWidget::toggleDetailsSlot()
124 {
125  mOptionsWidget->setVisible(!mOptionsWidget->isVisible());
126  settings()->setValue("reconstruction/guiShowDetails", mOptionsWidget->isVisible());
127 }
128 
129 QWidget* ReconstructionWidget::createOptionsWidget()
130 {
131  QWidget* retval = new QWidget(this);
132  QGridLayout* layout = new QGridLayout(retval);
133  layout->setMargin(0);
134 
135  int line = 0;
136 
137  layout->addWidget(this->createHorizontalLine(), line, 0, 1, 2);
138  ++line;
139 
140  mAlgorithmGroup = new QFrame(this);
141  mAlgorithmGroup->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
142  mAlgorithmGroup->setFocusPolicy(Qt::StrongFocus); // needed for help system: focus is used to display help text
143  mAlgorithmGroup->setSizePolicy(mAlgorithmGroup->sizePolicy().horizontalPolicy(),QSizePolicy::Fixed);
144 
145  QVBoxLayout* algoOuterLayout = new QVBoxLayout(mAlgorithmGroup);
146  //algoOuterLayout->setMargin(0);
147  QWidget* algorithmWidget = sscCreateDataWidget(this, mReconstructer->getParam("Algorithm"));
148  algoOuterLayout->addWidget(algorithmWidget);
149  mAlgoLayout = new QStackedLayout;
150  this->repopulateAlgorithmGroup();
151  mAlgoLayout->setMargin(0);
152  algoOuterLayout->addLayout(mAlgoLayout);
153  //algoOuterLayout->addStretch();
154  layout->addWidget(mAlgorithmGroup, line, 0, 1, 2);
155  ++line;
156 
157  sscCreateDataWidget(this, mReconstructer->getParam("Angio data"), layout, line++);
158  sscCreateDataWidget(this, mReconstructer->getParam("Dual Angio"), layout, line++);
159  sscCreateDataWidget(this, mReconstructer->getParam("Orientation"), layout, line++);
160  layout->addWidget(this->createHorizontalLine(), line++, 0, 1, 2);
161 
162  mDimXWidget = new SpinBoxGroupWidget(this, DoublePropertyBasePtr(new DoublePropertyXDim(mReconstructer)));
163  mDimYWidget = new SpinBoxGroupWidget(this, DoublePropertyBasePtr(new DoublePropertyYDim(mReconstructer)));
164  mDimZWidget = new SpinBoxGroupWidget(this, DoublePropertyBasePtr(new DoublePropertyZDim(mReconstructer)));
165  QHBoxLayout* outputVolDimLayout = new QHBoxLayout;
166  outputVolDimLayout->addWidget(mDimXWidget);
167  outputVolDimLayout->addWidget(mDimYWidget);
168  outputVolDimLayout->addWidget(mDimZWidget);
169  layout->addLayout(outputVolDimLayout, line++, 0, 1, 2);
170 
171  sscCreateDataWidget(this, mReconstructer->getParam("Align timestamps"), layout, line++);
172  sscCreateDataWidget(this, mReconstructer->getParam("Extra Temporal Calib"), layout, line++);
173  sscCreateDataWidget(this, mReconstructer->getParam("Reduce mask (% in 1D)"), layout, line++);
174 
175  return retval;
176 }
177 
178 void ReconstructionWidget::repopulateAlgorithmGroup()
179 {
180  QString algoName = mReconstructer->getParam("Algorithm")->getValueAsVariant().toString();
181 
182  if (mAlgoLayout->currentWidget() && (algoName == mAlgoLayout->currentWidget()->objectName()))
183  return;
184 
185  for (int i=0; i<mAlgoLayout->count(); ++i)
186  {
187  if (algoName==mAlgoLayout->widget(i)->objectName())
188  {
189  mAlgoLayout->setCurrentIndex(i);
190  return;
191  }
192  }
193 
194  // Remove previous widget: this ensures that the widget wraps tightly around the current
195  // widget instead of wrapping all algorithms.
196  QLayoutItem *child;
197  while ((child = mAlgoLayout->takeAt(0)) != 0)
198  {
199  // delete both the layoutitem AND the widget. Not auto done because layoutitem is no QObject.
200  QWidget* widget = child->widget();
201  delete child;
202  delete widget;
203  }
204 
205  this->createNewStackedWidget(algoName);
206 }
207 
208 void ReconstructionWidget::createNewStackedWidget(QString algoName)
209 {
210  QWidget* oneAlgoWidget = new QWidget(this);
211  oneAlgoWidget->setObjectName(algoName);
212  mAlgorithmGroup->setObjectName(algoName);
213  mAlgoLayout->addWidget(oneAlgoWidget);
214  QGridLayout* oneAlgoLayout = new QGridLayout(oneAlgoWidget);
215  oneAlgoLayout->setMargin(0);
216 
217  std::vector<PropertyPtr> algoOption = mReconstructer->getAlgoOptions();
218  unsigned row = 0;
219  for (;row < algoOption.size(); ++row)
220  {
221  sscCreateDataWidget(oneAlgoWidget, algoOption[row], oneAlgoLayout, row);
222  }
223  oneAlgoLayout->setRowStretch(row, 1); // Set stretch on last row
224 
225  mAlgoLayout->setCurrentWidget(oneAlgoWidget);
226 }
227 
228 QString ReconstructionWidget::getCurrentPath()
229 {
230  return QFileInfo(mReconstructer->getSelectedFilename()).dir().absolutePath();
231 }
232 
234 {
235  mReconstructer->startReconstruction();
236 }
237 
238 
240 {
241  this->selectData(mReconstructer->getSelectedFilename());
242 }
243 
247 void ReconstructionWidget::inputDataSelected(QString mhdFileName)
248 {
249  if (mReconstructer->getSelectedFilename().isEmpty())
250  {
251  return;
252  }
253 
254  mFileSelectWidget->setFilename(mhdFileName);
255 }
256 
257 void ReconstructionWidget::selectData(QString filename)
258 {
259  if (filename.isEmpty())
260  {
261  reportWarning("no file selected");
262  return;
263  }
264 
265  mReconstructer->selectData(filename);
266 }
267 
272 {
273  Vector3D range = mReconstructer->getOutputVolumeParams().getExtent().range();
274 
275  QString extText =
276  QString("%1, %2, %3").arg(range[0], 0, 'f', 1).arg(range[1], 0, 'f', 1).arg(range[2], 0, 'f', 1);
277  mExtentLineEdit->setText(extText);
278 
279  mInputSpacingLineEdit->setText(QString("%1").arg(mReconstructer->getOutputVolumeParams().getInputSpacing(), 0, 'f', 4));
280 }
281 
282 void ReconstructionWidget::reconstructAboutToStartSlot()
283 {
284  std::set<cx::TimedAlgorithmPtr> threads = mReconstructer->getThreadedReconstruction();
285  mTimedAlgorithmProgressBar->attach(threads);
286 }
287 
288 void ReconstructionWidget::reconstructStartedSlot()
289 {
290  mReconstructButton->setEnabled(false);
291 }
292 
293 void ReconstructionWidget::reconstructFinishedSlot()
294 {
295  std::set<cx::TimedAlgorithmPtr> threads = mReconstructer->getThreadedReconstruction();
296  mTimedAlgorithmProgressBar->detach(threads);
297  mReconstructButton->setEnabled(true);
298 }
299 
300 
301 }//namespace
void newInputDataAvailable(QString mhdFileName)
void fileSelected(QString name)
boost::shared_ptr< class UsReconstructionService > UsReconstructionServicePtr
void inputDataSelected(QString mhdFileName)
void setNameFilter(QStringList filter)
ReconstructionWidget(QWidget *parent, UsReconstructionServicePtr reconstructer)
Show progress for a TimedBaseAlgorithm.
QAction * createAction(QObject *parent, QIcon iconName, QString text, QString tip, T slot, QLayout *layout=NULL, QToolButton *button=new QToolButton())
Definition: cxBaseWidget.h:150
void detach(TimedAlgorithmPtr algorithm)
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:79
static QFrame * createHorizontalLine()
Creates a horizontal line which can be inserted into widgets.
void reportWarning(QString msg)
Definition: cxLogger.cpp:91
void setFilename(QString name)
void setPath(QString path)
boost::shared_ptr< class DoublePropertyBase > DoublePropertyBasePtr
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:42
void attach(TimedAlgorithmPtr algorithm)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:109
Composite widget for scalar data manipulation.
void newInputDataPath(QString path)
QWidget * sscCreateDataWidget(QWidget *parent, PropertyPtr data, QGridLayout *gridLayout, int row)
Create a widget capable of displaying the input data.
void selectData(QString inputfile)
Widget for displaying and selecting a single file.
Namespace for all CustusX production code.