35 # define M_PI 3.14159265358979323846
42 #include "ui_coregsettingsview.h"
56 #include <QFileDialog>
57 #include <QMessageBox>
65 #include <Eigen/Geometry>
71 using namespace DISPLIB;
72 using namespace Eigen;
86 , m_pUi(new Ui::CoregSettingsViewWidget)
88 m_sSettingsPath = sSettingsPath;
94 connect(m_pUi->m_qPushButton_LoadFid, &QPushButton::released,
95 this, &CoregSettingsView::onLoadFidFile);
96 connect(m_pUi->m_qPushButton_StoreFid, &QPushButton::released,
97 this, &CoregSettingsView::onStoreFidFile);
98 connect(m_pUi->m_qPushButton_LoadDig, &QPushButton::released,
99 this, &CoregSettingsView::onLoadDigFile);
100 connect(m_pUi->m_qPushButton_LoadTrans, &QPushButton::released,
101 this, &CoregSettingsView::onLoadTrans);
102 connect(m_pUi->m_qPushButton_StoreTrans, &QPushButton::released,
103 this, &CoregSettingsView::onStoreTrans);
104 connect(m_pUi->m_qComboBox_BemItems, &QComboBox::currentTextChanged,
107 connect(m_pUi->m_qComboBox_BemItems, &QComboBox::currentTextChanged,
109 connect(m_pUi->m_qComboBox_BemItems, &QComboBox::currentTextChanged,
113 connect(m_pUi->m_qCheckBox_PickFiducials, &QCheckBox::stateChanged,
114 this, &CoregSettingsView::onPickingStatus);
115 connect(m_pUi->m_qRadioButton_LPA, &QCheckBox::toggled,
116 this, &CoregSettingsView::onFiducialChanged);
117 connect(m_pUi->m_qRadioButton_NAS, &QCheckBox::toggled,
118 this, &CoregSettingsView::onFiducialChanged);
119 connect(m_pUi->m_qRadioButton_RPA, &QCheckBox::toggled,
120 this, &CoregSettingsView::onFiducialChanged);
124 connect(m_pUi->m_qPushButton_FitFiducials, &QPushButton::released,
125 this, &CoregSettingsView::onFitFiducials);
126 connect(m_pUi->m_qPushButton_FitICP, &QPushButton::released,
127 this, &CoregSettingsView::onFitICP);
130 connect(m_pUi->m_qDoubleSpinBox_ScalingX,
static_cast<void (QDoubleSpinBox::*)(
double)
>(&QDoubleSpinBox::valueChanged),
132 connect(m_pUi->m_qDoubleSpinBox_ScalingY,
static_cast<void (QDoubleSpinBox::*)(
double)
>(&QDoubleSpinBox::valueChanged),
134 connect(m_pUi->m_qDoubleSpinBox_ScalingZ,
static_cast<void (QDoubleSpinBox::*)(
double)
>(&QDoubleSpinBox::valueChanged),
136 connect(m_pUi->m_qDoubleSpinBox_RotX,
static_cast<void (QDoubleSpinBox::*)(
double)
>(&QDoubleSpinBox::valueChanged),
138 connect(m_pUi->m_qDoubleSpinBox_RotY,
static_cast<void (QDoubleSpinBox::*)(
double)
>(&QDoubleSpinBox::valueChanged),
140 connect(m_pUi->m_qDoubleSpinBox_RotZ,
static_cast<void (QDoubleSpinBox::*)(
double)
>(&QDoubleSpinBox::valueChanged),
142 connect(m_pUi->m_qDoubleSpinBox_TransX,
static_cast<void (QDoubleSpinBox::*)(
double)
>(&QDoubleSpinBox::valueChanged),
144 connect(m_pUi->m_qDoubleSpinBox_TransY,
static_cast<void (QDoubleSpinBox::*)(
double)
>(&QDoubleSpinBox::valueChanged),
146 connect(m_pUi->m_qDoubleSpinBox_TransZ,
static_cast<void (QDoubleSpinBox::*)(
double)
>(&QDoubleSpinBox::valueChanged),
148 connect(m_pUi->m_qComboBox_ScalingMode, &QComboBox::currentTextChanged,
149 this, &CoregSettingsView::onScalingModeChanges, Qt::UniqueConnection);
150 onScalingModeChanges();
158 CoregSettingsView::~CoregSettingsView()
168 if(m_sSettingsPath.isEmpty()) {
173 QSettings settings(
"MNECPP");
181 if(m_sSettingsPath.isEmpty()) {
186 QSettings settings(
"MNECPP");
195 case GuiMode::Clinical:
207 case ProcessingMode::Offline:
216 void CoregSettingsView::setToolTipInfo()
218 m_pUi->m_qComboBox_BemItems->setToolTip(
"Select the Bem to use for coregistration. Load the Bem via: File->Open");
219 m_pUi->m_qPushButton_LoadFid->setToolTip(
"Optional. Load the fiducials from file.");
220 m_pUi->m_qPushButton_StoreFid->setToolTip(
"Store the fiducials to file.");
221 m_pUi->m_qPushButton_LoadDig->setToolTip(
"Load the digitizers from file.");
222 m_pUi->m_qPushButton_LoadTrans->setToolTip(
"Optional. Load the coordinate transformation from file.");
223 m_pUi->m_qPushButton_StoreTrans->setToolTip(
"Store the coordinate transformation to file.");
225 m_pUi->m_qDoubleSpinBox_WeightRpa->setToolTip(
"The weight for the RPA.");
226 m_pUi->m_qDoubleSpinBox_WeightLpa->setToolTip(
"The weight for the LPA.");
227 m_pUi->m_qDoubleSpinBox_WeightNas->setToolTip(
"The weight for the Nasion.");
228 m_pUi->m_qDoubleSpinBox_WeightEEG->setToolTip(
"The weight for the EEG points.");
229 m_pUi->m_qDoubleSpinBox_WeightHPI->setToolTip(
"The weight for the HPI points.");
230 m_pUi->m_qDoubleSpinBox_WeightHSP->setToolTip(
"The weight for the HSP points. HSP = Head Shape Points");
231 m_pUi->m_qCheckBox_HSP->setToolTip(
"Wheater to use the HSP points for the Coregistration. HSP = Head Shape Points");
232 m_pUi->m_qCheckBox_EEG->setToolTip(
"Wheater to use the EEG points for the Coregistration.");
233 m_pUi->m_qCheckBox_HPI->setToolTip(
"Wheater to use the HPI points for the Coregistration.");
234 m_pUi->m_qSpinBox_MaxDist->setToolTip(
"The maximum allowed distace between head surface and digitizer cloud. This is used to discard outliers.");
236 m_pUi->m_qCheckBox_AutoScale->setToolTip(
"Wheater to use automatic scaling for the fiducial alignment.");
237 m_pUi->m_qDoubleSpinBox_Converge->setToolTip(
"The convergence limit for the ICP algorithm.");
238 m_pUi->m_qSpinBox_MaxIter->setToolTip(
"The maximum number of iterations for the ICP algorithm.");
239 m_pUi->m_qPushButton_FitFiducials->setToolTip(
"Fiducial alignment. Apply this step before using the ICP algorithm to get a better first guess.");
240 m_pUi->m_qPushButton_FitICP->setToolTip(
"Co-Registration with the ICP algorithm.");
241 m_pUi->m_qLabel_RMSE->setToolTip(
"The Root-Mean-Square-Error of the distance between closest point and digigizer in mm");
242 m_pUi->m_qComboBox_ScalingMode->setToolTip(
"The scaling Mode. None - No scaling is applied; Uniform - same scaling for x,y,z-axis; 3-Axis - scaling on each axis.");
243 m_pUi->m_qDoubleSpinBox_ScalingX->setToolTip(
"Scaling to apply in x-direction.");
244 m_pUi->m_qDoubleSpinBox_ScalingY->setToolTip(
"Scaling to apply in y-direction.");
245 m_pUi->m_qDoubleSpinBox_ScalingZ->setToolTip(
"Scaling to apply in z-direction.");
247 m_pUi->m_qDoubleSpinBox_RotX->setToolTip(
"Rotation arround x-axis.");
248 m_pUi->m_qDoubleSpinBox_RotY->setToolTip(
"Rotation arround y-axis.");
249 m_pUi->m_qDoubleSpinBox_RotZ->setToolTip(
"Rotation arround z-axis.");
251 m_pUi->m_qDoubleSpinBox_TransX->setToolTip(
"Translation to apply in x-direction.");
252 m_pUi->m_qDoubleSpinBox_TransY->setToolTip(
"Translation to apply in y-direction.");
253 m_pUi->m_qDoubleSpinBox_TransZ->setToolTip(
"Translation to apply in z-direction.");
259 void CoregSettingsView::onLoadFidFile()
261 QString sFileName = QFileDialog::getOpenFileName(
this,
262 tr(
"Select fiducials"),
264 tr(
"Fif Files (*.fif)"));
266 if (sFileName.isEmpty()) {
275 void CoregSettingsView::onPickingStatus()
277 bool bState = m_pUi->m_qCheckBox_PickFiducials->isChecked();
279 m_pUi->m_qWidget_ResultFiducials->setEnabled(
true);
282 m_pUi->m_qWidget_ResultFiducials->setEnabled(
false);
294 if(m_pUi->m_qRadioButton_LPA->isChecked()) {
295 m_vecLPA = vecPosition;
298 m_pUi->m_qRadioButton_NAS->setChecked(
true);
301 }
else if (m_pUi->m_qRadioButton_NAS->isChecked()) {
302 m_vecNAS = vecPosition;
305 m_pUi->m_qRadioButton_RPA->setChecked(
true);
309 m_vecRPA = vecPosition;
312 m_pUi->m_qRadioButton_LPA->setChecked(
true);
318 m_pUi->m_qLineEdit_FidX->setText(QString::number(floor(vecTemp[0]*100)/100 * 1000) +
" mm" );
319 m_pUi->m_qLineEdit_FidY->setText(QString::number(floor(vecTemp[1]*100)/100 * 1000) +
" mm" );
320 m_pUi->m_qLineEdit_FidZ->setText(QString::number(floor(vecTemp[2]*100)/100 * 1000) +
" mm" );
326 void CoregSettingsView::onFiducialChanged()
329 if(m_pUi->m_qRadioButton_LPA->isChecked()) {
332 }
else if (m_pUi->m_qRadioButton_NAS->isChecked()) {
341 m_pUi->m_qLineEdit_FidX->setText(QString::number(floor(vecTemp[0]*100)/100 * 1000) +
" mm" );
342 m_pUi->m_qLineEdit_FidY->setText(QString::number(floor(vecTemp[1]*100)/100 * 1000) +
" mm" );
343 m_pUi->m_qLineEdit_FidZ->setText(QString::number(floor(vecTemp[2]*100)/100 * 1000) +
" mm" );
349 void CoregSettingsView::onStoreFidFile()
351 QString sFileName = QFileDialog::getSaveFileName(Q_NULLPTR,
352 tr(
"Save Fiducials"),
"",
353 tr(
"Fif file (*fiducials.fif)"));
355 if (sFileName.isEmpty()) {
364 void CoregSettingsView::onLoadDigFile()
366 QString sFileName = QFileDialog::getOpenFileName(
this,
367 tr(
"Select digitizer file"),
369 tr(
"Fif Files (*.fif)"));
371 if (sFileName.isEmpty()) {
380 void CoregSettingsView::onLoadTrans()
382 QString sFileName = QFileDialog::getOpenFileName(
this,
383 tr(
"Select Transformation"),
385 tr(
"Fif Files (*-trans.fif)"));
387 if (sFileName.isEmpty()) {
396 void CoregSettingsView::onStoreTrans()
398 QString sFileName = QFileDialog::getSaveFileName(Q_NULLPTR,
399 tr(
"Save Transformation"),
"",
400 tr(
"Fif file (*-trans.fif)"));
402 if (sFileName.isEmpty()) {
414 if(m_pUi->m_qRadioButton_LPA->isChecked()) {
415 return FIFFV_POINT_LPA;
416 }
else if(m_pUi->m_qRadioButton_NAS->isChecked()) {
417 return FIFFV_POINT_NASION;
418 }
else if(m_pUi->m_qRadioButton_RPA->isChecked()) {
419 return FIFFV_POINT_RPA;
428 return m_pUi->m_qSpinBox_MaxIter->value();
435 return m_pUi->m_qDoubleSpinBox_Converge->value()/1000;
442 return m_pUi->m_qCheckBox_AutoScale->isChecked();
449 return m_pUi->m_qDoubleSpinBox_WeightLpa->text().toFloat();
454 float CoregSettingsView::getWeightRPA()
456 return m_pUi->m_qDoubleSpinBox_WeightRpa->text().toFloat();
461 float CoregSettingsView::getWeightNAS()
463 return m_pUi->m_qDoubleSpinBox_WeightNas->text().toFloat();
468 float CoregSettingsView::getWeightEEG()
470 return m_pUi->m_qDoubleSpinBox_WeightEEG->text().toFloat();
475 float CoregSettingsView::getWeightHPI()
477 return m_pUi->m_qDoubleSpinBox_WeightHPI->text().toFloat();
482 float CoregSettingsView::getWeightHSP()
484 return m_pUi->m_qDoubleSpinBox_WeightHSP->text().toFloat();
491 return static_cast<float>(m_pUi->m_qSpinBox_MaxDist->value())/1000.0;
499 QList<int> lPicks({FIFFV_POINT_CARDINAL});
502 if(m_pUi->m_qCheckBox_EEG) {
503 lPicks << FIFFV_POINT_EEG;
505 if(m_pUi->m_qCheckBox_HPI) {
506 lPicks << FIFFV_POINT_HPI;
508 if(m_pUi->m_qCheckBox_HSP) {
509 lPicks << FIFFV_POINT_EXTRA;
519 QSignalBlocker blockerComboBox(m_pUi->m_qComboBox_BemItems);
520 m_pUi->m_qComboBox_BemItems->clear();
527 m_pUi->m_qComboBox_BemItems->addItem(sBemName);
534 return m_pUi->m_qComboBox_BemItems->currentText();
541 m_pUi->m_qLabel_NOmitted->setText(QString::number(iN));
548 m_pUi->m_qLabel_RMSE->setText(QString::number(fRMSE*1000) +
" mm");
554 const Vector3f& vecRot,
555 const Vector3f& vecScale)
558 QSignalBlocker blockerTransX(m_pUi->m_qDoubleSpinBox_TransX);
559 QSignalBlocker blockerTransY(m_pUi->m_qDoubleSpinBox_TransY);
560 QSignalBlocker blockerTransZ(m_pUi->m_qDoubleSpinBox_TransZ);
561 QSignalBlocker blockerRotX(m_pUi->m_qDoubleSpinBox_RotX);
562 QSignalBlocker blockerRotY(m_pUi->m_qDoubleSpinBox_RotY);
563 QSignalBlocker blockerRotZ(m_pUi->m_qDoubleSpinBox_RotZ);
564 QSignalBlocker blockerScaleX(m_pUi->m_qDoubleSpinBox_ScalingX);
565 QSignalBlocker blockerScaleY(m_pUi->m_qDoubleSpinBox_ScalingY);
566 QSignalBlocker blockerScaleZ(m_pUi->m_qDoubleSpinBox_ScalingZ);
568 m_pUi->m_qDoubleSpinBox_TransX->setValue(vecTrans(0)*1000);
569 m_pUi->m_qDoubleSpinBox_TransY->setValue(vecTrans(1)*1000);
570 m_pUi->m_qDoubleSpinBox_TransZ->setValue(vecTrans(2)*1000);
573 m_pUi->m_qDoubleSpinBox_RotX->setValue(vecRot(2)*180/M_PI);
574 m_pUi->m_qDoubleSpinBox_RotY->setValue(vecRot(1)*180/M_PI);
575 m_pUi->m_qDoubleSpinBox_RotZ->setValue(vecRot(0)*180/M_PI);
577 m_pUi->m_qDoubleSpinBox_ScalingX->setValue(vecScale(2));
578 m_pUi->m_qDoubleSpinBox_ScalingY->setValue(vecScale(1));
579 m_pUi->m_qDoubleSpinBox_ScalingZ->setValue(vecScale(0));
588 vecTrans(0) = m_pUi->m_qDoubleSpinBox_TransX->value()/1000.0;
589 vecTrans(1) = m_pUi->m_qDoubleSpinBox_TransY->value()/1000.0;
590 vecTrans(2) = m_pUi->m_qDoubleSpinBox_TransZ->value()/1000.0;
593 vecRot(2) = m_pUi->m_qDoubleSpinBox_RotX->value() * M_PI/180.0;
594 vecRot(1) = m_pUi->m_qDoubleSpinBox_RotY->value() * M_PI/180.0;
595 vecRot(0) = m_pUi->m_qDoubleSpinBox_RotZ->value() * M_PI/180.0;
598 if (m_pUi->m_qComboBox_ScalingMode->currentText() ==
"Uniform") {
599 vecScale.fill(m_pUi->m_qDoubleSpinBox_ScalingX->value());
600 }
else if (m_pUi->m_qComboBox_ScalingMode->currentText() ==
"3-Axis") {
601 vecScale(0) = m_pUi->m_qDoubleSpinBox_ScalingX->value();
602 vecScale(1) = m_pUi->m_qDoubleSpinBox_ScalingY->value();
603 vecScale(2) = m_pUi->m_qDoubleSpinBox_ScalingZ->value();
613 void CoregSettingsView::onScalingModeChanges()
616 if (m_pUi->m_qComboBox_ScalingMode->currentText() ==
"Uniform") {
617 m_pUi->m_qDoubleSpinBox_ScalingX->setEnabled(
true);
618 m_pUi->m_qDoubleSpinBox_ScalingY->setEnabled(
false);
619 m_pUi->m_qDoubleSpinBox_ScalingZ->setEnabled(
false);
620 }
else if (m_pUi->m_qComboBox_ScalingMode->currentText() ==
"3-Axis") {
621 m_pUi->m_qDoubleSpinBox_ScalingX->setEnabled(
true);
622 m_pUi->m_qDoubleSpinBox_ScalingY->setEnabled(
true);
623 m_pUi->m_qDoubleSpinBox_ScalingZ->setEnabled(
true);
625 m_pUi->m_qDoubleSpinBox_ScalingX->setEnabled(
false);
626 m_pUi->m_qDoubleSpinBox_ScalingY->setEnabled(
false);
627 m_pUi->m_qDoubleSpinBox_ScalingZ->setEnabled(
false);
634 void CoregSettingsView::onFitFiducials()
636 m_pUi->m_qCheckBox_PickFiducials->setChecked(
false);
642 void CoregSettingsView::onFitICP()
644 m_pUi->m_qCheckBox_PickFiducials->setChecked(
false);