MNE-CPP 0.1.9
A Framework for Electrophysiology
Loading...
Searching...
No Matches
hpisettingsview.cpp
Go to the documentation of this file.
1//=============================================================================================================
36//=============================================================================================================
37// INCLUDES
38//=============================================================================================================
39
40#include "hpisettingsview.h"
41
42#include "ui_hpisettingsview.h"
43
45#include <iostream>
46
47//=============================================================================================================
48// QT INCLUDES
49//=============================================================================================================
50
51#include <QFileInfo>
52#include <QFileDialog>
53#include <QMessageBox>
54#include <QSettings>
55#include <QJsonObject>
56#include <QJsonArray>
57
58//=============================================================================================================
59// EIGEN INCLUDES
60//=============================================================================================================
61
62//=============================================================================================================
63// USED NAMESPACES
64//=============================================================================================================
65
66using namespace DISPLIB;
67using namespace FIFFLIB;
68
69//=============================================================================================================
70// DEFINE MEMBER METHODS
71//=============================================================================================================
72
73HpiSettingsView::HpiSettingsView(const QString& sSettingsPath,
74 QWidget *parent,
75 Qt::WindowFlags f)
76: AbstractView(parent, f)
77, m_pUi(new Ui::HpiSettingsViewWidget)
78{
79 m_sSettingsPath = sSettingsPath;
80 m_pUi->setupUi(this);
81
82 connect(m_pUi->m_pushButton_loadDigitizers, &QPushButton::released,
84 connect(m_pUi->m_pushButton_doFreqOrder, &QPushButton::clicked,
86 connect(m_pUi->m_pushButton_doSingleFit, &QPushButton::clicked,
88 connect(m_pUi->m_tableWidget_Frequencies, &QTableWidget::cellChanged,
90 connect(m_pUi->m_pushButton_addCoil, &QPushButton::clicked,
92 connect(m_pUi->m_pushButton_removeCoil, &QPushButton::clicked,
94 connect(m_pUi->m_checkBox_useSSP, &QCheckBox::clicked,
96 connect(m_pUi->m_checkBox_useComp, &QCheckBox::clicked,
98 connect(m_pUi->m_checkBox_continousHPI, &QCheckBox::clicked,
100 connect(m_pUi->m_spinBox_samplesToFit, QOverload<int>::of(&QSpinBox::valueChanged),
102 connect(m_pUi->m_doubleSpinBox_maxHPIContinousDist, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
104 connect(m_pUi->m_doubleSpinBox_moveThreshold, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
106 connect(m_pUi->m_doubleSpinBox_rotThreshold, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
108 connect(m_pUi->comboBox_coilPreset, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
110
111 //Init coil freqs
112 m_vCoilFreqs << 293 << 307 << 314 << 321;
113
114 loadSettings();
115}
116
117//=============================================================================================================
118
119HpiSettingsView::~HpiSettingsView()
120{
121 saveSettings();
122
123 delete m_pUi;
124}
125
126//=============================================================================================================
127
128void HpiSettingsView::setErrorLabels(const QVector<double>& vError,
129 const double dMeanErrorDist)
130{
131 //Update eror labels and change from m to mm
132 QString sGof("0mm");
133
134 for(int i = 0; i < vError.size(); ++i) {
135 if(i < m_pUi->m_tableWidget_results->rowCount()) {
136 sGof = QString::number(vError[i]*1000,'f',2)+QString(" mm");
137 m_pUi->m_tableWidget_results->item(i, 1)->setText(sGof);
138 }
139 }
140
141 m_pUi->m_label_averagedFitError->setText(QString::number(dMeanErrorDist*1000,'f',2)+QString(" mm"));
142
143 //Update good/bad fit label
144 if(dMeanErrorDist*1000 > m_pUi->m_doubleSpinBox_maxHPIContinousDist->value()) {
145 m_pUi->m_label_fitFeedback->setText("Last fit: Bad");
146 m_pUi->m_label_fitFeedback->setStyleSheet("QLabel { background-color : red;}");
147 } else {
148 m_pUi->m_label_fitFeedback->setText("Last fit: Good");
149 m_pUi->m_label_fitFeedback->setStyleSheet("QLabel { background-color : green;}");
150 }
151}
152
153//=============================================================================================================
154
155void HpiSettingsView::setGoFLabels(const Eigen::VectorXd & vGoF,
156 const double dMeanGof)
157{
158 //Update gof labels and change to %
159 QString sGof("00.00");
160
161 for(int i = 0; i < vGoF.size(); ++i) {
162 if(i < m_pUi->m_tableWidget_results->rowCount()) {
163 sGof = QString::number(vGoF[i]*100,'f',2)+QString(" %");
164 m_pUi->m_tableWidget_results->item(i, 2)->setText(sGof);
165 }
166 }
167
168 m_pUi->m_average_gof_set->setText(QString::number(dMeanGof*100,'f',2)+QString(" %"));
169
170}
171
172//=========================================================================================================
173
175 double dRotation)
176{
177 m_pUi->m_qLineEdit_moveResult->setText(QString::number(dMovement*1000,'f',2) + QString(" mm"));
178 m_pUi->m_qLineEdit_rotResult->setText(QString::number(dRotation,'f',2) + QString(" °"));
179
180 if(dMovement*1000 > m_pUi->m_doubleSpinBox_moveThreshold->value() || dRotation > m_pUi->m_doubleSpinBox_rotThreshold->value()) {
181 m_pUi->m_label_movementFeedback->setText("Big");
182 m_pUi->m_label_movementFeedback->setStyleSheet("QLabel { background-color : red;}");
183 } else {
184 m_pUi->m_label_movementFeedback->setText("Small");
185 m_pUi->m_label_movementFeedback->setStyleSheet("QLabel { background-color : green;}");
186 }
187}
188
189//=============================================================================================================
190
192{
193 return m_pUi->m_checkBox_useSSP->isChecked();
194}
195
196//=============================================================================================================
197
199{
200 return m_pUi->m_checkBox_useComp->isChecked();
201}
202
203//=============================================================================================================
204
206{
207 return m_pUi->m_doubleSpinBox_maxHPIContinousDist->value();
208}
209
210//=============================================================================================================
211
213{
214 return m_pUi->m_doubleSpinBox_moveThreshold->value();
215}
216
217//=============================================================================================================
218
220{
221 return m_pUi->m_doubleSpinBox_rotThreshold->value();
222}
223
224//=============================================================================================================
225
227{
228 return m_pUi->m_checkBox_continousHPI->isChecked();
229}
230
231//=============================================================================================================
232
234{
235 return m_pUi->m_spinBox_samplesToFit->value();
236}
237
238//=============================================================================================================
239
241{
242 if(m_sSettingsPath.isEmpty()) {
243 return;
244 }
245
246 QSettings settings("MNECPP");
247
248 settings.setValue(m_sSettingsPath + QString("/HpiSettingsView/coilFreqs"),
249 QVariant::fromValue(m_vCoilFreqs));
250
251 settings.setValue(m_sSettingsPath + QString("/HpiSettingsView/useSSP"),
252 QVariant::fromValue(m_pUi->m_checkBox_useSSP->isChecked()));
253
254 settings.setValue(m_sSettingsPath + QString("/HpiSettingsView/useCOMP"),
255 QVariant::fromValue(m_pUi->m_checkBox_useComp->isChecked()));
256
257 settings.setValue(m_sSettingsPath + QString("/HpiSettingsView/continousHPI"),\
258 QVariant::fromValue(m_pUi->m_checkBox_continousHPI->isChecked()));
259
260 settings.setValue(m_sSettingsPath + QString("/HpiSettingsView/maxError"),
261 QVariant::fromValue(m_pUi->m_doubleSpinBox_maxHPIContinousDist->value()));
262
263 settings.setValue(m_sSettingsPath + QString("/HpiSettingsView/fittingWindowSize"),
264 QVariant::fromValue(m_pUi->m_spinBox_samplesToFit->value()));
265}
266
267//=============================================================================================================
268
270{
271 if(m_sSettingsPath.isEmpty()) {
272 return;
273 }
274
275 QSettings settings("MNECPP");
276 QVariant defaultData;
277
278 defaultData.setValue(m_vCoilFreqs);
279 m_vCoilFreqs = settings.value(m_sSettingsPath + QString("/HpiSettingsView/coilFreqs"), defaultData).value<QVector<int> >();
281
282 m_pUi->m_checkBox_useSSP->setChecked(settings.value(m_sSettingsPath + QString("/HpiSettingsView/useSSP"), false).toBool());
283 m_pUi->m_checkBox_useComp->setChecked(settings.value(m_sSettingsPath + QString("/HpiSettingsView/useCOMP"), false).toBool());
284 m_pUi->m_checkBox_continousHPI->setChecked(settings.value(m_sSettingsPath + QString("/HpiSettingsView/continousHPI"), false).toBool());
285 m_pUi->m_doubleSpinBox_maxHPIContinousDist->setValue(settings.value(m_sSettingsPath + QString("/HpiSettingsView/maxError"), 10.0).toDouble());
286 m_pUi->m_spinBox_samplesToFit->setValue(settings.value(m_sSettingsPath + QString("/HpiSettingsView/fittingWindowSize"), 300).toInt());
287}
288
289//=============================================================================================================
290
292{
293 switch(mode) {
294 case GuiMode::Clinical:
295 break;
296 default: // default is research mode
297 break;
298 }
299}
300
301//=============================================================================================================
302
304{
305 switch(mode) {
306 case ProcessingMode::Offline:
307 break;
308 default: // default is realtime mode
309 break;
310 }
311}
312
313//=============================================================================================================
314
316{
317 //Get file location
318 QString fileName_HPI = QFileDialog::getOpenFileName(this,
319 tr("Open digitizer file"),
320 "",
321 tr("Fiff file (*.fif)"));
322
323 if(!fileName_HPI.isEmpty()) {
324 m_pUi->m_lineEdit_filePath->setText(fileName_HPI);
325 }
326
327 //Load Polhemus file
328 if (!fileName_HPI.isEmpty()) {
329 fileName_HPI = fileName_HPI.trimmed();
330 QFileInfo checkFile(fileName_HPI);
331
332 if (checkFile.exists() && checkFile.isFile()) {
333 // Stop cont HPI first
334 m_pUi->m_checkBox_continousHPI->setChecked(false);
335 emit digitizersChanged(readDigitizersFromFile(fileName_HPI), fileName_HPI);
336 } else {
337 QMessageBox msgBox;
338 msgBox.setText("File could not be loaded!");
339 msgBox.exec();
340 return;
341 }
342 }
343}
344
345//=============================================================================================================
346
348 int col)
349{
350 if(col != 1 || row >= m_vCoilFreqs.size()) {
351 return;
352 }
353
354 if(QTableWidgetItem *pItem = m_pUi->m_tableWidget_Frequencies->item(row, col)) {
355 if(pItem->text() == "none") {
356 m_vCoilFreqs[row] = -1;
357 } else {
358 m_vCoilFreqs[row] = pItem->text().toInt();
359 }
360
362 }
363}
364
365//=============================================================================================================
366
368{
369 if(m_pUi->m_tableWidget_Frequencies->rowCount() + 1 > m_pUi->m_label_numberLoadedCoils->text().toInt()) {
370 QMessageBox msgBox;
371 msgBox.setText("Cannot add more HPI coils. Not enough digitzed HPI coils loaded.");
372 msgBox.exec();
373 return;
374 }
375
376 // Add column 0 in freq table widget
377 m_pUi->m_tableWidget_Frequencies->insertRow(m_pUi->m_tableWidget_Frequencies->rowCount());
378 QTableWidgetItem* pTableItemA = new QTableWidgetItem(QString::number(m_pUi->m_tableWidget_Frequencies->rowCount()));
379 pTableItemA->setFlags(Qt::ItemIsEnabled);
380 m_pUi->m_tableWidget_Frequencies->setItem(m_pUi->m_tableWidget_Frequencies->rowCount()-1,
381 0,
382 pTableItemA);
383
384 // Add column 1 in freq table widget
385 if(m_vCoilFreqs.size() >= m_pUi->m_tableWidget_Frequencies->rowCount()) {
386 m_pUi->m_tableWidget_Frequencies->setItem(m_pUi->m_tableWidget_Frequencies->rowCount()-1,
387 1,
388 new QTableWidgetItem(QString::number(m_vCoilFreqs.at(m_pUi->m_tableWidget_Frequencies->rowCount()-1))));
389 } else {
390 m_pUi->m_tableWidget_Frequencies->setItem(m_pUi->m_tableWidget_Frequencies->rowCount()-1,
391 1,
392 new QTableWidgetItem("none"));
393 m_vCoilFreqs.append(-1);
394 }
395
396 // Add column 0 in error table widget (coil number)
397 m_pUi->m_tableWidget_results->insertRow(m_pUi->m_tableWidget_results->rowCount());
398 QTableWidgetItem* pTableItemB = new QTableWidgetItem(QString::number(m_pUi->m_tableWidget_Frequencies->rowCount()));
399 pTableItemB->setFlags(Qt::ItemIsEnabled);
400 m_pUi->m_tableWidget_results->setItem(m_pUi->m_tableWidget_results->rowCount()-1,
401 0,
402 pTableItemB);
403
404 // Add column 1 in error table widget (error)
405 QTableWidgetItem* pTableItemC = new QTableWidgetItem("0mm");
406 pTableItemC->setFlags(Qt::ItemIsEnabled);
407 m_pUi->m_tableWidget_results->setItem(m_pUi->m_tableWidget_results->rowCount()-1,
408 1,
409 pTableItemC);
410
411 // Add column 2 in error table widget (gof)
412 QTableWidgetItem* pTableItemD = new QTableWidgetItem("00.00");
413 pTableItemD->setFlags(Qt::ItemIsEnabled);
414 m_pUi->m_tableWidget_results->setItem(m_pUi->m_tableWidget_results->rowCount()-1,
415 2,
416 pTableItemD);
417
419}
420
421//=============================================================================================================
422
424{
425 int row = m_pUi->m_tableWidget_Frequencies->currentRow();
426
427 if(row >= 0 && row < m_vCoilFreqs.size()) {
428 m_vCoilFreqs.remove(row);
429 m_pUi->m_tableWidget_Frequencies->removeRow(row);
430
431 for (int i = 0; i < m_pUi->m_tableWidget_Frequencies->rowCount(); ++i) {
432 m_pUi->m_tableWidget_Frequencies->item(i, 0)->setText(QString::number(i+1));
433 }
434
435 m_pUi->m_tableWidget_results->removeRow(row);
436
437 for (int i = 0; i < m_pUi->m_tableWidget_results->rowCount(); ++i) {
438 m_pUi->m_tableWidget_results->item(i, 0)->setText(QString::number(i+1));
439 }
440
442 }
443}
444
445//=============================================================================================================
446
447QList<FiffDigPoint> HpiSettingsView::readDigitizersFromFile(const QString& fileName)
448{
449 clearCoilGUI();
450
451 QFile t_fileDig(fileName);
452 FiffDigPointSet t_digSet(t_fileDig);
453 updateDigitizerInfoGUI(t_digSet);
454
455 return t_digSet.getList();
456}
457
458//=============================================================================================================
459
460void HpiSettingsView::newDigitizerList(QList<FIFFLIB::FiffDigPoint> pointList)
461{
462 clearCoilGUI();
463
464 FiffDigPointSet t_digSet(pointList);
465 updateDigitizerInfoGUI(t_digSet);
466}
467
468//=============================================================================================================
469
471{
472 qint16 numHPI = 0;
473 qint16 numFiducials = 0;
474 qint16 numEEG = 0;
475 qint16 numAdditional = 0;
476
477 for(int i = 0; i < digSet.size(); ++i) {
478 switch(digSet[i].kind) {
479 case FIFFV_POINT_HPI:
480 if(m_vCoilFreqs.size() <= numHPI) {
481 m_vCoilFreqs.append(-1);
482 }
483 numHPI++;
484 break;
485 case FIFFV_POINT_CARDINAL:
486 numFiducials++;
487 break;
488 case FIFFV_POINT_EEG:
489 numEEG++;
490 break;
491 case FIFFV_POINT_EXTRA:
492 numAdditional++;
493 break;
494 }
495 }
496
497 //Set loaded number of digitizers
498 m_pUi->m_label_numberLoadedCoils->setNum(numHPI);
499 m_pUi->m_label_numberLoadedFiducials->setNum(numFiducials);
500 m_pUi->m_label_numberLoadedEEG->setNum(numEEG);
501 m_pUi->m_label_numberLoadedAdditional->setNum(numAdditional);
502
503 m_vCoilFreqs.resize(numHPI);
505 setupCoilPresets(numHPI);
506
507 // Make sure that the stored coil freqs always match the number of loaded ones
508 m_vCoilFreqs.resize(numHPI);
510}
511
512//=============================================================================================================
513
515{
516 for(int iCoilFreq : m_vCoilFreqs){
517 addCoilFreqToGUI(iCoilFreq);
519 }
520}
521
522//=============================================================================================================
523
525{
526 // Add column 0 in freq table widget
527 m_pUi->m_tableWidget_Frequencies->insertRow(m_pUi->m_tableWidget_Frequencies->rowCount());
528 QTableWidgetItem* pTableItemA = new QTableWidgetItem(QString::number(m_pUi->m_tableWidget_Frequencies->rowCount()));
529 pTableItemA->setFlags(Qt::ItemIsEnabled);
530 m_pUi->m_tableWidget_Frequencies->setItem(m_pUi->m_tableWidget_Frequencies->rowCount()-1,
531 0,
532 pTableItemA);
533
534 // Add column 1 in freq table widget
535 m_pUi->m_tableWidget_Frequencies->setItem(m_pUi->m_tableWidget_Frequencies->rowCount()-1,
536 1,
537 new QTableWidgetItem(QString::number(iCoilFreq)));
538}
539
540//=============================================================================================================
541
543{
544 // Add column 0 in error table widget
545 m_pUi->m_tableWidget_results->insertRow(m_pUi->m_tableWidget_results->rowCount());
546 QTableWidgetItem* pTableItemB = new QTableWidgetItem(QString::number(m_pUi->m_tableWidget_Frequencies->rowCount()));
547 pTableItemB->setFlags(Qt::ItemIsEnabled);
548 m_pUi->m_tableWidget_results->setItem(m_pUi->m_tableWidget_results->rowCount()-1,
549 0,
550 pTableItemB);
551
552 // Add column 1 in error table widget
553 QTableWidgetItem* pTableItemC = new QTableWidgetItem("0mm");
554 pTableItemC->setFlags(Qt::ItemIsEnabled);
555 m_pUi->m_tableWidget_results->setItem(m_pUi->m_tableWidget_results->rowCount()-1,
556 1,
557 pTableItemC);
558
559 // Add column 2 in error table widget
560 QTableWidgetItem* pTableItemD = new QTableWidgetItem("00.00%");
561 pTableItemD->setFlags(Qt::ItemIsEnabled);
562 m_pUi->m_tableWidget_results->setItem(m_pUi->m_tableWidget_results->rowCount()-1,
563 2,
564 pTableItemD);
565}
566
567//=============================================================================================================
568
570{
571 m_pUi->m_tableWidget_Frequencies->clear();
572 m_pUi->m_tableWidget_Frequencies->setRowCount(0);
573 m_pUi->m_tableWidget_Frequencies->setHorizontalHeaderItem(0, new QTableWidgetItem("#Coil"));
574 m_pUi->m_tableWidget_Frequencies->setHorizontalHeaderItem(1, new QTableWidgetItem("Frequency (Hz)"));
575
576 m_pUi->m_tableWidget_results->clear();
577 m_pUi->m_tableWidget_results->setRowCount(0);
578 m_pUi->m_tableWidget_results->setHorizontalHeaderItem(0, new QTableWidgetItem("#Coil"));
579 m_pUi->m_tableWidget_results->setHorizontalHeaderItem(1, new QTableWidgetItem("Error"));
580 m_pUi->m_tableWidget_results->setHorizontalHeaderItem(2, new QTableWidgetItem("GoF"));
581
582}
583
584//=============================================================================================================
585
587{
588
589}
590
591//==============================================void populateCoilGUI(int iNumCoils);===============================================================
592
593void HpiSettingsView::loadCoilPresets(const QString &sFilePath)
594{
595 QFile inFile(sFilePath);
596 if (inFile.open(QIODevice::ReadOnly)){
597 QByteArray inArray = inFile.readAll();
598 m_CoilPresets = QJsonDocument::fromJson(inArray);
599 }
600}
601
602//=============================================================================================================
603
605{
606 if(!m_CoilPresets.isNull()){
607 QJsonArray presetData = m_CoilPresets.object()[QString::number(iNumCoils)].toArray();
608 populatePresetGUI(presetData);
609 }
610}
611
612//=============================================================================================================
613
614void HpiSettingsView::populatePresetGUI(const QJsonArray& presetData)
615{
616 m_pUi->comboBox_coilPreset->clear();
617 m_pUi->comboBox_coilPreset->addItem("Load preset");
618
619 for(const auto& entry : presetData){
620 QString name = entry.toObject()["name"].toString();
621 QVector<int> data;
622
623 for (const auto& coil : entry.toObject()["coils"].toArray()){
624 data.append(coil.toInt());
625 }
626
627 m_pUi->comboBox_coilPreset->addItem(name, QVariant::fromValue(data));
628 }
629}
630
631//=============================================================================================================
632
633void HpiSettingsView::selectCoilPreset(int iCoilPresetIndex)
634{
635 if (iCoilPresetIndex < (m_pUi->comboBox_coilPreset->count())){
636 auto coilFreqData = m_pUi->comboBox_coilPreset->itemData(iCoilPresetIndex);
637 if (!coilFreqData.isNull() && coilFreqData.canConvert<QVector<int>>()){
638 m_vCoilFreqs = coilFreqData.value<QVector<int>>();
639 clearCoilGUI();
641
643 }
644 }
645}
HpiSettingsView class declaration.
FiffDigPointSet class declaration.
The AbstractView class provides the base calss for all Disp viewers.
void allowedRotationChanged(double dAllowedRotation)
void updateProcessingMode(ProcessingMode mode)
void sspStatusChanged(bool bChecked)
void updateDigitizerInfoGUI(const FIFFLIB::FiffDigPointSet &digSet)
void fittingWindowSizeChanged(int iFitsPerSecond)
void setMovementResults(double dMovement, double dRotation)
void loadCoilPresets(const QString &sFilePath)
void coilFrequenciesChanged(const QVector< int > &vCoilFreqs)
void newDigitizerList(QList< FIFFLIB::FiffDigPoint > pointList)
void addCoilFreqToGUI(int iCoilFreq)
void updateGuiMode(GuiMode mode)
void populatePresetGUI(const QJsonArray &presetData)
void setGoFLabels(const Eigen::VectorXd &vGoF, const double dMeanGof)
void compStatusChanged(bool bChecked)
void setupCoilPresets(int iNumCoils)
void onFrequencyCellChanged(int row, int col)
void setErrorLabels(const QVector< double > &vError, const double dMeanErrorDist)
void addCoilErrorToGUI()
addCoilErrorToGUI
HpiSettingsView(const QString &sSettingsPath="", QWidget *parent=0, Qt::WindowFlags f=Qt::Widget)
void allowedMovementChanged(double dAllowedMovement)
void allowedMeanErrorDistChanged(double dAllowedMeanErrorDist)
void selectCoilPreset(int iCoilPresetIndex)
Ui::HpiSettingsViewWidget * m_pUi
QList< FIFFLIB::FiffDigPoint > readDigitizersFromFile(const QString &fileName)
void digitizersChanged(const QList< FIFFLIB::FiffDigPoint > &lDigitzers, const QString &sFilePath)
void contHpiStatusChanged(bool bChecked)
Holds a set of digitizer points.
QList< FiffDigPoint > getList()