MNE-CPP  beta 1.0
bcisetupwidget.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //*************************************************************************************************************
38 //=============================================================================================================
39 // INCLUDES
40 //=============================================================================================================
41 
42 #include "bcisetupwidget.h"
43 #include "bciaboutwidget.h"
44 #include "../bci.h"
45 
46 
47 //*************************************************************************************************************
48 //=============================================================================================================
49 // QT INCLUDES
50 //=============================================================================================================
51 
52 #include <QDir>
53 #include <QDebug>
54 
55 
56 //*************************************************************************************************************
57 //=============================================================================================================
58 // USED NAMESPACES
59 //=============================================================================================================
60 
61 using namespace BCIPlugin;
62 using namespace Eigen;
63 
64 
65 //*************************************************************************************************************
66 //=============================================================================================================
67 // DEFINE MEMBER METHODS
68 //=============================================================================================================
69 
70 BCISetupWidget::BCISetupWidget(BCI* pBCI, QWidget* parent)
71 : QWidget(parent)
72 , m_pBCI(pBCI)
73 {
74  ui.setupUi(this);
75 
76  // Connect general options
77  connect(ui.m_checkBox_UseSourceData, static_cast<void (QCheckBox::*)(bool)>(&QCheckBox::clicked),
78  this, &BCISetupWidget::setGeneralOptions);
79  connect(ui.m_checkBox_UseSensorData, static_cast<void (QCheckBox::*)(bool)>(&QCheckBox::clicked),
80  this, &BCISetupWidget::setGeneralOptions);
81  connect(ui.m_checkBox_DisplayFeatures, static_cast<void (QCheckBox::*)(bool)>(&QCheckBox::clicked),
82  this, &BCISetupWidget::setGeneralOptions);
83  connect(ui.m_SpinBox_NumberFeaturesToDisplay, static_cast<void (QSpinBox::*)()>(&QSpinBox::editingFinished),
84  this, &BCISetupWidget::setGeneralOptions);
85  connect(ui.m_doubleSpinBox_Boundary, static_cast<void (QDoubleSpinBox::*)()>(&QDoubleSpinBox::editingFinished),
86  this, &BCISetupWidget::setGeneralOptions);
87  connect(ui.m_doubleSpinBox_Variances, static_cast<void (QDoubleSpinBox::*)()>(&QDoubleSpinBox::editingFinished),
88  this, &BCISetupWidget::setGeneralOptions);
89  connect(ui.m_doubleSpinBox_Electrodes, static_cast<void (QDoubleSpinBox::*)()>(&QDoubleSpinBox::editingFinished),
90  this, &BCISetupWidget::setGeneralOptions);
91  connect(ui.m_spinBox_exponentBoundary, static_cast<void (QSpinBox::*)()>(&QSpinBox::editingFinished),
92  this, &BCISetupWidget::setGeneralOptions);
93  connect(ui.m_spinBox_exponentVariances, static_cast<void (QSpinBox::*)()>(&QSpinBox::editingFinished),
94  this, &BCISetupWidget::setGeneralOptions);
95  connect(ui.m_spinBox_exponentElectrodes, static_cast<void (QSpinBox::*)()>(&QSpinBox::editingFinished),
96  this, &BCISetupWidget::setGeneralOptions);
97 
98  // Connect processing options
99  connect(ui.m_checkBox_SubtractMean, static_cast<void (QCheckBox::*)(bool)>(&QCheckBox::clicked),
100  this, &BCISetupWidget::setProcessingOptions);
101  connect(ui.m_doubleSpinBox_SlidingWindowSize, static_cast<void (QDoubleSpinBox::*)()>(&QDoubleSpinBox::editingFinished),
102  this, &BCISetupWidget::setProcessingOptions);
103  connect(ui.m_spinBox_NumberFeatures, static_cast<void (QSpinBox::*)()>(&QSpinBox::editingFinished),
104  this, &BCISetupWidget::setProcessingOptions);
105  connect(ui.m_doubleSpinBox_TimeBetweenWindows, static_cast<void (QDoubleSpinBox::*)()>(&QDoubleSpinBox::editingFinished),
106  this, &BCISetupWidget::setProcessingOptions);
107  connect(ui.m_checkBox_UseThresholdArtefactReduction, static_cast<void (QCheckBox::*)(bool)>(&QCheckBox::clicked),
108  this, &BCISetupWidget::setProcessingOptions);
109  connect(ui.m_SpinBox_ThresholdValue, static_cast<void (QDoubleSpinBox::*)()>(&QDoubleSpinBox::editingFinished),
110  this, &BCISetupWidget::setProcessingOptions);
111 
112  // Connect classification options
113  connect(ui.m_comboBox_featureCalculationType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
114  this, &BCISetupWidget::setClassificationOptions);
115 
116  connect(ui.m_pushButton_LoadSensorBoundary, &QPushButton::released,
117  this, &BCISetupWidget::changeLoadSensorBoundary);
118  connect(ui.m_pushButton_LoadSourceBoundary, &QPushButton::released,
119  this, &BCISetupWidget::changeLoadSourceBoundary);
120 
121  // Connect feature selection
122  ui.m_listWidget_ChosenFeaturesOnSensorLevel->installEventFilter(this);
123  ui.m_listWidget_ChosenFeaturesOnSourceLevel->installEventFilter(this);
124  ui.m_listWidget_AvailableFeaturesOnSensorLevel->installEventFilter(this);
125  ui.m_listWidget_AvailableFeaturesOnSourceLevel->installEventFilter(this);
126 
127  // Connect filter options
128  connect(ui.m_checkBox_UseFilter, static_cast<void (QCheckBox::*)(bool)>(&QCheckBox::clicked),
129  this, &BCISetupWidget::setFilterOptions);
130  connect(ui.m_doubleSpinBox_FilterLowerBound, static_cast<void (QDoubleSpinBox::*)()>(&QDoubleSpinBox::editingFinished),
131  this, &BCISetupWidget::setFilterOptions);
132  connect(ui.m_doubleSpinBox_FilterUpperBound, static_cast<void (QDoubleSpinBox::*)()>(&QDoubleSpinBox::editingFinished),
133  this, &BCISetupWidget::setFilterOptions);
134  connect(ui.m_SpinBox_FilterOrder, static_cast<void (QSpinBox::*)()>(&QSpinBox::editingFinished),
135  this, &BCISetupWidget::setFilterOptions);
136  connect(ui.m_doubleSpinBox_ParcksWidth, static_cast<void (QDoubleSpinBox::*)()>(&QDoubleSpinBox::editingFinished),
137  this, &BCISetupWidget::setFilterOptions);
138 
139  //Connect about button
140  connect(ui.m_qPushButton_About, &QPushButton::released, this, &BCISetupWidget::showAboutDialog);
141 
142  //Fill info box
143  QFile file(m_pBCI->m_qStringResourcePath+"readme.txt");
144  if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
145  return;
146 
147  QTextStream in(&file);
148  while (!in.atEnd())
149  {
150  QString line = in.readLine();
151  ui.m_qTextBrowser_Information->insertHtml(line);
152  ui.m_qTextBrowser_Information->insertHtml("<br>");
153  }
154 }
155 
156 
157 //*************************************************************************************************************
158 
160 {
161 }
162 
163 
164 //*************************************************************************************************************
165 
167 {
168  // General options
169  ui.m_checkBox_UseSensorData->setChecked(m_pBCI->m_bUseSensorData);
170  ui.m_checkBox_UseSourceData->setChecked(m_pBCI->m_bUseSourceData);
171  ui.m_checkBox_DisplayFeatures->setChecked(m_pBCI->m_bDisplayFeatures);
172  ui.m_SpinBox_NumberFeaturesToDisplay->setValue(m_pBCI->m_iNumberFeaturesToDisplay);
173  ui.m_doubleSpinBox_Boundary->setValue(m_pBCI->m_dDisplayRangeBoundary);
174  ui.m_doubleSpinBox_Variances->setValue(m_pBCI->m_dDisplayRangeVariances);
175  ui.m_doubleSpinBox_Electrodes->setValue(m_pBCI->m_dDisplayRangeElectrodes);
176 
177  setGeneralOptions(); // Set up ranges for the first time
178 
179  // Processing options
180  ui.m_checkBox_SubtractMean->setChecked(m_pBCI->m_bSubtractMean);
181  ui.m_doubleSpinBox_SlidingWindowSize->setValue(m_pBCI->m_dSlidingWindowSize);
182  ui.m_doubleSpinBox_TimeBetweenWindows->setValue(m_pBCI->m_dTimeBetweenWindows);
183  ui.m_spinBox_NumberFeatures->setValue(m_pBCI->m_iNumberFeatures);
184  ui.m_checkBox_UseThresholdArtefactReduction->setChecked(m_pBCI->m_bUseArtefactThresholdReduction);
185  ui.m_SpinBox_ThresholdValue->setValue(m_pBCI->m_dThresholdValue);
186 
187  // Init time displays
188  double totalProcessingTime = ui.m_doubleSpinBox_SlidingWindowSize->value() + (ui.m_doubleSpinBox_TimeBetweenWindows->value() * (ui.m_spinBox_NumberFeatures->value()-1));
189  ui.m_label_TotalProcessedTimeDisplay->setNum(totalProcessingTime);
190  ui.m_label_TotalProcessedTimeDisplay->setText(ui.m_label_TotalProcessedTimeDisplay->text().append(" s"));
191 
192  double timeForNextResult = ui.m_doubleSpinBox_TimeBetweenWindows->value() * ui.m_spinBox_NumberFeatures->value();
193  ui.m_label_TimeNeededForResultsDisplay->setNum(timeForNextResult);
194  ui.m_label_TimeNeededForResultsDisplay->setText(ui.m_label_TimeNeededForResultsDisplay->text().append(" s"));
195 
196  // Classification boundaries
197  ui.m_comboBox_featureCalculationType->setCurrentIndex(m_pBCI->m_iFeatureCalculationType);
198  QString temp = m_pBCI->m_qStringResourcePath;
199  temp.append(QString("LDA_linear_boundary_Sensor.txt"));
200  ui.m_lineEdit_SensorBoundary->setText(temp);
201  ui.m_lineEdit_SourceBoundary->setText(temp);
202  m_pBCI->m_vLoadedSensorBoundary = readBoundaryInformation(temp);
203  m_pBCI->m_vLoadedSourceBoundary = readBoundaryInformation(temp);
204 
205  // Filter options
206  ui.m_checkBox_UseFilter->setChecked(m_pBCI->m_bUseFilter);
207  ui.m_doubleSpinBox_FilterLowerBound->setValue(m_pBCI->m_dFilterLowerBound);
208  ui.m_doubleSpinBox_FilterUpperBound->setValue(m_pBCI->m_dFilterUpperBound);
209  ui.m_SpinBox_FilterOrder->setValue(m_pBCI->m_iFilterOrder);
210  ui.m_doubleSpinBox_ParcksWidth->setValue(m_pBCI->m_dParcksWidth);
211 
212  // Selected features on sensor level
213  initSelectedFeaturesSensor();
214 }
215 
216 
217 //*************************************************************************************************************
218 
219 void BCISetupWidget::setGeneralOptions()
220 {
221  m_pBCI->m_bUseSensorData = ui.m_checkBox_UseSensorData->isChecked();
222  m_pBCI->m_bUseSourceData = ui.m_checkBox_UseSourceData->isChecked();
223  m_pBCI->m_bDisplayFeatures = ui.m_checkBox_DisplayFeatures->isChecked();
224  m_pBCI->m_iNumberFeaturesToDisplay = ui.m_SpinBox_NumberFeaturesToDisplay->value();
225 
226  m_pBCI->m_dDisplayRangeBoundary = ui.m_doubleSpinBox_Boundary->value() * std::pow(10, ui.m_spinBox_exponentBoundary->value());
227  m_pBCI->m_dDisplayRangeVariances = ui.m_doubleSpinBox_Variances->value() * std::pow(10, ui.m_spinBox_exponentVariances->value());
228  m_pBCI->m_dDisplayRangeElectrodes = ui.m_doubleSpinBox_Electrodes->value() * std::pow(10, ui.m_spinBox_exponentElectrodes->value());
229 }
230 
231 
232 //*************************************************************************************************************
233 
234 void BCISetupWidget::setProcessingOptions()
235 {
236  m_pBCI->m_bSubtractMean = ui.m_checkBox_SubtractMean->isChecked();
237  m_pBCI->m_dSlidingWindowSize = ui.m_doubleSpinBox_SlidingWindowSize->value();
238  m_pBCI->m_dTimeBetweenWindows = ui.m_doubleSpinBox_TimeBetweenWindows->value();
239  m_pBCI->m_iNumberFeatures = ui.m_spinBox_NumberFeatures->value();
240  m_pBCI->m_bUseArtefactThresholdReduction = ui.m_checkBox_UseThresholdArtefactReduction->isChecked();
241  m_pBCI->m_dThresholdValue = ui.m_SpinBox_ThresholdValue->value();
242 
243  double totalProcessingTime = ui.m_doubleSpinBox_SlidingWindowSize->value() + (ui.m_doubleSpinBox_TimeBetweenWindows->value() * (ui.m_spinBox_NumberFeatures->value()-1));
244  ui.m_label_TotalProcessedTimeDisplay->setNum(totalProcessingTime);
245  ui.m_label_TotalProcessedTimeDisplay->setText(ui.m_label_TotalProcessedTimeDisplay->text().append(" s"));
246 
247  double timeForNextResult = ui.m_doubleSpinBox_TimeBetweenWindows->value() * ui.m_spinBox_NumberFeatures->value();
248  ui.m_label_TimeNeededForResultsDisplay->setNum(timeForNextResult);
249  ui.m_label_TimeNeededForResultsDisplay->setText(ui.m_label_TimeNeededForResultsDisplay->text().append(" s"));
250 }
251 
252 
253 //*************************************************************************************************************
254 
255 void BCISetupWidget::changeLoadSensorBoundary()
256 {
257  QString path = QFileDialog::getOpenFileName(
258  this,
259  "Load decision boundary for sensor level",
260  "mne_x_plugins/resources/bci/LDA_linear_boundary.txt",
261  tr("Text files (*.txt)"));
262 
263  if(path==NULL)
264  path = ui.m_lineEdit_SensorBoundary->text();
265 
266  m_pBCI->m_vLoadedSensorBoundary = readBoundaryInformation(path);
267 
268  ui.m_lineEdit_SensorBoundary->setText(path);
269 }
270 
271 
272 //*************************************************************************************************************
273 
274 void BCISetupWidget::changeLoadSourceBoundary()
275 {
276  QString path = QFileDialog::getOpenFileName(
277  this,
278  "Load decision boundary for source level",
279  "mne_x_plugins/resources/bci/LDA_linear_boundary.txt",
280  tr("Text files (*.txt)"));
281 
282  if(path==NULL)
283  path = ui.m_lineEdit_SourceBoundary->text();
284 
285 
286  m_pBCI->m_vLoadedSourceBoundary = readBoundaryInformation(path);
287 
288  ui.m_lineEdit_SourceBoundary->setText(path);
289 }
290 
291 
292 //*************************************************************************************************************
293 
294 QVector<VectorXd> BCISetupWidget::readBoundaryInformation(QString path)
295 {
296  QVector<VectorXd> boundary_final;
297 
298  // Read boundary information generated with matlab
299  QFile file(path);
300  if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
301  {
302  // Initialise boundaries with linear coefficients y = mx+c -> vector = [m c] -> default [1 0]
303  VectorXd const_temp(1);
304  const_temp << 0.0;
305  VectorXd linear_temp(2);
306  linear_temp << 1.0, 1.0;
307 
308  boundary_final.push_back(const_temp);
309  boundary_final.push_back(linear_temp);
310 
311  return boundary_final;
312  }
313 
314  //Start reading from file
315  VectorXd const_temp;
316  VectorXd linear_temp;
317 
318  QTextStream in(&file);
319 
320  while(!in.atEnd())
321  {
322  QString line = in.readLine();
323 
324  if(line.contains(QString("const")))
325  {
326  QStringList list_temp = line.split(QRegExp("\\s+"));
327 
328  const_temp.resize(list_temp.at(1).toInt());
329 
330  for(int i = 0; i<list_temp.at(1).toInt(); i++)
331  {
332  QString line_temp = in.readLine();
333  const_temp(i) = line_temp.toDouble();
334  }
335  }
336 
337  if(line.contains(QString("linear")))
338  {
339  QStringList list_temp = line.split(QRegExp("\\s+"));
340 
341  linear_temp.resize(list_temp.at(1).toInt());
342 
343  for(int i = 0; i<list_temp.at(1).toInt(); i++)
344  {
345  QString line_temp = in.readLine();
346  linear_temp(i) = line_temp.toDouble();
347  }
348  }
349  }
350 
351  file.close();
352 
353  boundary_final.push_back(const_temp);
354  boundary_final.push_back(linear_temp);
355 
356  return boundary_final;
357 }
358 
359 
360 //*************************************************************************************************************
361 
362 void BCISetupWidget::initSelectedFeaturesSensor()
363 {
364  // Read electrode pinnig scheme from file and initialise List and store in QMap in BCI object
365  QString path;
366  path.prepend(m_pBCI->m_qStringResourcePath);
367  path.append("Pinning_Scheme_Duke_128.txt");
368  QFile file(path);
369  if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
370  return;
371 
372  //Start reading from file
373  m_vAvailableFeaturesSensor.clear();
374  QMap<QString, int> mapElectrodePinningScheme;
375 
376  QTextStream in(&file);
377 
378  while(!in.atEnd())
379  {
380  QString line = in.readLine();
381 
382  QStringList list_temp = line.split(QRegExp("\\s+"));
383 
384  if(list_temp.size() >= 2)
385  mapElectrodePinningScheme.insert(list_temp.at(1), list_temp.at(0).toInt()-1); // Decrement by 1 because channels in matrix start with 0
386 
387  m_vAvailableFeaturesSensor.append(list_temp.at(1));
388  }
389 
390  file.close();
391 
392  m_pBCI->m_mapElectrodePinningScheme = mapElectrodePinningScheme;
393 
394  // Remove default items from list
395  for(int i=0; i<m_pBCI->m_slChosenFeatureSensor.size(); i++)
396  m_vAvailableFeaturesSensor.removeAt(m_vAvailableFeaturesSensor.indexOf(m_pBCI->m_slChosenFeatureSensor.at(i)));
397 
398  ui.m_listWidget_AvailableFeaturesOnSensorLevel->addItems(m_vAvailableFeaturesSensor);
399  ui.m_listWidget_ChosenFeaturesOnSensorLevel->addItems(m_pBCI->m_slChosenFeatureSensor);
400 }
401 
402 
403 //*************************************************************************************************************
404 
405 void BCISetupWidget::setFeatureSelection()
406 {
407  QStringList ChosenFeaturesOnSensorLevel;
408  for(int i=0; i< ui.m_listWidget_ChosenFeaturesOnSensorLevel->count(); i++)
409  ChosenFeaturesOnSensorLevel << ui.m_listWidget_ChosenFeaturesOnSensorLevel->item(i)->text();
410 
411  QStringList ChosenFeaturesOnSourceLevel;
412  for(int i=0; i< ui.m_listWidget_ChosenFeaturesOnSourceLevel->count(); i++)
413  ChosenFeaturesOnSourceLevel << ui.m_listWidget_ChosenFeaturesOnSourceLevel->item(i)->text();
414 
415  m_pBCI->m_slChosenFeatureSensor = ChosenFeaturesOnSensorLevel;
416  m_pBCI->m_slChosenFeatureSource = ChosenFeaturesOnSourceLevel;
417 }
418 
419 
420 //*************************************************************************************************************
421 
422 void BCISetupWidget::setFilterOptions()
423 {
424  m_pBCI->m_bUseFilter = ui.m_checkBox_UseFilter->isChecked();
425  m_pBCI->m_dFilterLowerBound = ui.m_doubleSpinBox_FilterLowerBound->value();
426  m_pBCI->m_dFilterUpperBound = ui.m_doubleSpinBox_FilterUpperBound->value();
427  m_pBCI->m_iFilterOrder = ui.m_SpinBox_FilterOrder->value();
428  m_pBCI->m_dParcksWidth = ui.m_doubleSpinBox_ParcksWidth->value();
429 }
430 
431 
432 //*************************************************************************************************************
433 
434 void BCISetupWidget::setClassificationOptions()
435 {
436  m_pBCI->m_iFeatureCalculationType = ui.m_comboBox_featureCalculationType->currentIndex();
437 }
438 
439 
440 //*************************************************************************************************************
441 
442 void BCISetupWidget::showAboutDialog()
443 {
444  BCIAboutWidget aboutDialog(this);
445  aboutDialog.exec();
446 }
447 
448 
449 //*************************************************************************************************************
450 
451 bool BCISetupWidget::eventFilter(QObject *object, QEvent *event)
452 {
453  if ((object == ui.m_listWidget_ChosenFeaturesOnSensorLevel ||
454  object == ui.m_listWidget_ChosenFeaturesOnSourceLevel ||
455  object == ui.m_listWidget_AvailableFeaturesOnSensorLevel ||
456  object == ui.m_listWidget_AvailableFeaturesOnSourceLevel) && event->type() == QEvent::Leave)
457  setFeatureSelection();
458 
459  return QObject::eventFilter(object, event);;
460 }
Definition: bci.h:75
Contains the declaration of the BCIAboutWidget class.
bool eventFilter(QObject *object, QEvent *event)
The BCIAboutWidget class provides the about dialog for the BCI.
BCISetupWidget(BCI *pBCI, QWidget *parent=0)
The BCI class provides an EEG BCI.
Definition: bci.h:103
Contains the declaration of the BCISetupWidget class.