MNE-CPP  beta 1.0
realtimemultisamplearraywidget.cpp
1 //=============================================================================================================
36 //ToDo Paint to render area
37 
38 //*************************************************************************************************************
39 //=============================================================================================================
40 // INCLUDES
41 //=============================================================================================================
42 
44 //#include "annotationwindow.h"
45 #include <helpers/chinfomodel.h>
47 
48 #include <Eigen/Core>
49 
50 
51 //*************************************************************************************************************
52 //=============================================================================================================
53 // STL INCLUDES
54 //=============================================================================================================
55 
56 #include <math.h>
57 
58 
59 //*************************************************************************************************************
60 //=============================================================================================================
61 // QT INCLUDES
62 //=============================================================================================================
63 
64 #include <QPaintEvent>
65 #include <QPainter>
66 #include <QTimer>
67 #include <QTime>
68 #include <QVBoxLayout>
69 #include <QHeaderView>
70 #include <QMenu>
71 #include <QMessageBox>
72 #include <QSettings>
73 
74 #include <QScroller>
75 
76 #include <QDebug>
77 
78 //*************************************************************************************************************
79 //=============================================================================================================
80 // USED NAMESPACES
81 //=============================================================================================================
82 
83 using namespace XDISPLIB;
84 using namespace XMEASLIB;
85 
86 
87 //=============================================================================================================
91 enum Tool
92 {
93  Freeze = 0,
94  Annotation = 1
95 };
96 
97 
98 //*************************************************************************************************************
99 //=============================================================================================================
100 // DEFINE MEMBER METHODS
101 //=============================================================================================================
102 
103 RealTimeMultiSampleArrayWidget::RealTimeMultiSampleArrayWidget(QSharedPointer<NewRealTimeMultiSampleArray> pRTMSA, QSharedPointer<QTime> &pTime, QWidget* parent)
104 : NewMeasurementWidget(parent)
105 , m_pRTMSAModel(NULL)
106 , m_pRTMSADelegate(NULL)
107 , m_pTableView(NULL)
108 , m_fDefaultSectionSize(80.0f)
109 , m_fZoomFactor(1.0f)
110 , m_pRTMSA(pRTMSA)
111 , m_bInitialized(false)
112 , m_iT(10)
113 , m_fSamplingRate(1024)
114 , m_fDesiredSamplingRate(128)
115 , m_bHideBadChannels(false)
116 {
117  Q_UNUSED(pTime)
118 
119  m_pDoubleSpinBoxZoom = new QDoubleSpinBox(this);
120  m_pDoubleSpinBoxZoom->setMinimum(0.3);
121  m_pDoubleSpinBoxZoom->setMaximum(4.0);
122  m_pDoubleSpinBoxZoom->setSingleStep(0.1);
123  m_pDoubleSpinBoxZoom->setValue(1.0);
124  m_pDoubleSpinBoxZoom->setSuffix(" x");
125  connect(m_pDoubleSpinBoxZoom, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this, &RealTimeMultiSampleArrayWidget::zoomChanged);
126  addDisplayWidget(m_pDoubleSpinBoxZoom);
127 
128  m_pSpinBoxTimeScale = new QSpinBox(this);
129  m_pSpinBoxTimeScale->setMinimum(1);
130  m_pSpinBoxTimeScale->setMaximum(20);
131  m_pSpinBoxTimeScale->setValue(m_iT);
132  m_pSpinBoxTimeScale->setSuffix(" s");
133  connect(m_pSpinBoxTimeScale, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &RealTimeMultiSampleArrayWidget::timeWindowChanged);
134  addDisplayWidget(m_pSpinBoxTimeScale);
135 
136  m_pActionSelectSensors = new QAction(QIcon(":/images/selectSensors.png"), tr("Shows the region selection widget (F10)"),this);
137  m_pActionSelectSensors->setShortcut(tr("F10"));
138  m_pActionSelectSensors->setStatusTip(tr("Shows the region selection widget (F10)"));
139  m_pActionSelectSensors->setVisible(true);
140  connect(m_pActionSelectSensors, &QAction::triggered, this, &RealTimeMultiSampleArrayWidget::showSensorSelectionWidget);
141  addDisplayAction(m_pActionSelectSensors);
142 
143  m_pActionChScaling = new QAction(QIcon(":/images/channelScaling.png"), tr("Shows the channel scaling widget (F11)"),this);
144  m_pActionChScaling->setShortcut(tr("F11"));
145  m_pActionChScaling->setStatusTip(tr("Shows the channel scaling widget (F11)"));
146  connect(m_pActionChScaling, &QAction::triggered, this, &RealTimeMultiSampleArrayWidget::showChScalingWidget);
147  addDisplayAction(m_pActionChScaling);
148  m_pActionChScaling->setVisible(false);
149 
150 
151  m_pActionProjection = new QAction(QIcon(":/images/iconSSP.png"), tr("Shows the SSP widget (F12)"),this);
152  m_pActionProjection->setShortcut(tr("F12"));
153  m_pActionProjection->setStatusTip(tr("Shows the SSP widget (F12)"));
154  connect(m_pActionProjection, &QAction::triggered, this, &RealTimeMultiSampleArrayWidget::showProjectionWidget);
155  addDisplayAction(m_pActionProjection);
156  m_pActionProjection->setVisible(true);
157 
158  if(m_pTableView)
159  delete m_pTableView;
160  m_pTableView = new QTableView;
161 
162  //set vertical layout
163  QVBoxLayout *rtmsaLayout = new QVBoxLayout(this);
164 
165  rtmsaLayout->addWidget(m_pTableView);
166 
167  //set layouts
168  this->setLayout(rtmsaLayout);
169 
170  //Create pointers for selection manager
171  m_pChInfoModel = QSharedPointer<ChInfoModel>(new ChInfoModel(this));
172  m_pSelectionManagerWindow = QSharedPointer<SelectionManagerWindow>(new SelectionManagerWindow(this, m_pChInfoModel.data()));
173 
174  init();
175 }
176 
177 
178 //*************************************************************************************************************
179 
181 {
182  //
183  // Store Settings
184  //
185  if(!m_pRTMSA->getName().isEmpty())
186  {
187  QString t_sRTMSAWName = m_pRTMSA->getName();
188 
189  QSettings settings;
190 
191  if(m_qMapChScaling.contains(FIFF_UNIT_T))
192  settings.setValue(QString("RTMSAW/%1/scaleMAG").arg(t_sRTMSAWName), m_qMapChScaling[FIFF_UNIT_T]);
193 
194  if(m_qMapChScaling.contains(FIFF_UNIT_T_M))
195  settings.setValue(QString("RTMSAW/%1/scaleGRAD").arg(t_sRTMSAWName), m_qMapChScaling[FIFF_UNIT_T_M]);
196 
197  if(m_qMapChScaling.contains(FIFFV_EEG_CH))
198  settings.setValue(QString("RTMSAW/%1/scaleEEG").arg(t_sRTMSAWName), m_qMapChScaling[FIFFV_EEG_CH]);
199 
200  if(m_qMapChScaling.contains(FIFFV_EOG_CH))
201  settings.setValue(QString("RTMSAW/%1/scaleEOG").arg(t_sRTMSAWName), m_qMapChScaling[FIFFV_EOG_CH]);
202 
203  if(m_qMapChScaling.contains(FIFFV_STIM_CH))
204  settings.setValue(QString("RTMSAW/%1/scaleSTIM").arg(t_sRTMSAWName), m_qMapChScaling[FIFFV_STIM_CH]);
205 
206  if(m_qMapChScaling.contains(FIFFV_MISC_CH))
207  settings.setValue(QString("RTMSAW/%1/scaleMISC").arg(t_sRTMSAWName), m_qMapChScaling[FIFFV_MISC_CH]);
208  }
209 }
210 
211 
212 //*************************************************************************************************************
213 
214 void RealTimeMultiSampleArrayWidget::broadcastScaling()
215 {
216  m_pRTMSAModel->setScaling(m_qMapChScaling);
217 }
218 
219 
220 //*************************************************************************************************************
221 
223 {
224  if(!m_bInitialized)
225  {
226  if(m_pRTMSA->isChInit())
227  {
228  m_qListChInfo = m_pRTMSA->chInfo(); //ToDo Obsolete -> use fiffInfo instead
229  m_pFiffInfo = m_pRTMSA->info();
230 
231  emit fiffFileUpdated(*m_pFiffInfo.data());
232 
233  m_fSamplingRate = m_pRTMSA->getSamplingRate();
234 
235  init();
236  }
237  }
238  else
239  m_pRTMSAModel->addData(m_pRTMSA->getMultiSampleArray());
240 }
241 
242 
243 //*************************************************************************************************************
244 
246 {
247  if(m_qListChInfo.size() > 0)
248  {
249  if(m_pRTMSAModel)
250  delete m_pRTMSAModel;
251  m_pRTMSAModel = new RealTimeMultiSampleArrayModel(this);
252 
253  m_pRTMSAModel->setFiffInfo(m_pFiffInfo);
254  m_pRTMSAModel->setChannelInfo(m_qListChInfo);//ToDo Obsolete
255  m_pRTMSAModel->setSamplingInfo(m_fSamplingRate, m_iT, m_fDesiredSamplingRate);
256 
257  if(m_pRTMSADelegate)
258  delete m_pRTMSADelegate;
259  m_pRTMSADelegate = new RealTimeMultiSampleArrayDelegate(this);
260 
261  connect(m_pTableView, &QTableView::doubleClicked, m_pRTMSAModel, &RealTimeMultiSampleArrayModel::toggleFreeze);
262 
263  m_pTableView->setModel(m_pRTMSAModel);
264  m_pTableView->setItemDelegate(m_pRTMSADelegate);
265 
266  //set some size settings for m_pTableView
267  m_pTableView->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
268 
269  m_pTableView->setShowGrid(false);
270 
271  m_pTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); //Stretch 2 column to maximal width
272  m_pTableView->horizontalHeader()->hide();
273  m_pTableView->verticalHeader()->setDefaultSectionSize(m_fZoomFactor*m_fDefaultSectionSize);//Row Height
274 
275  m_pTableView->setAutoScroll(false);
276  m_pTableView->setColumnHidden(0,true); //because content is plotted jointly with column=1
277 
278  m_pTableView->resizeColumnsToContents();
279 
280  m_pTableView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
281 
282  //set context menu
283  m_pTableView->setContextMenuPolicy(Qt::CustomContextMenu);
284  connect(m_pTableView,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(channelContextMenu(QPoint)));
285 
286  //Scaling
287  QString t_sRTMSAWName = m_pRTMSA->getName();
288 
289  if(!t_sRTMSAWName.isEmpty())
290  {
291  m_qMapChScaling.clear();
292 
293  QSettings settings;
294  float val = 0.0f;
295  val = settings.value(QString("RTMSAW/%1/scaleMAG").arg(t_sRTMSAWName), 1e-11f).toFloat();
296  m_qMapChScaling.insert(FIFF_UNIT_T, val);
297 
298  val = settings.value(QString("RTMSAW/%1/scaleGRAD").arg(t_sRTMSAWName), 1e-10f).toFloat();
299  m_qMapChScaling.insert(FIFF_UNIT_T_M, val);
300 
301  val = settings.value(QString("RTMSAW/%1/scaleEEG").arg(t_sRTMSAWName), 1e-4f).toFloat();
302  m_qMapChScaling.insert(FIFFV_EEG_CH, val);
303 
304  val = settings.value(QString("RTMSAW/%1/scaleEOG").arg(t_sRTMSAWName), 1e-3f).toFloat();
305  m_qMapChScaling.insert(FIFFV_EOG_CH, val);
306 
307  val = settings.value(QString("RTMSAW/%1/scaleSTIM").arg(t_sRTMSAWName), 1e-3f).toFloat();
308  m_qMapChScaling.insert(FIFFV_STIM_CH, val);
309 
310  val = settings.value(QString("RTMSAW/%1/scaleMISC").arg(t_sRTMSAWName), 1e-3f).toFloat();
311  m_qMapChScaling.insert(FIFFV_MISC_CH, val);
312 
313  m_pRTMSAModel->setScaling(m_qMapChScaling);
314 
315  m_pActionChScaling->setVisible(true);
316  }
317 
318  //Set up selection manager
319  connect(m_pSelectionManagerWindow.data(), &SelectionManagerWindow::showSelectedChannelsOnly,
320  this, &RealTimeMultiSampleArrayWidget::showSelectedChannelsOnly);
321 
322  //Connect channel info model
323  connect(m_pSelectionManagerWindow.data(), &SelectionManagerWindow::loadedLayoutMap,
324  m_pChInfoModel.data(), &ChInfoModel::layoutChanged);
325 
326  connect(m_pChInfoModel.data(), &ChInfoModel::channelsMappedToLayout,
327  m_pSelectionManagerWindow.data(), &SelectionManagerWindow::setCurrentlyMappedFiffChannels);
328 
329  m_pChInfoModel->fiffInfoChanged(*m_pFiffInfo.data());
330 
331  m_bInitialized = true;
332  }
333 }
334 
335 
336 //*************************************************************************************************************
337 
339 {
340  //obtain index where index was clicked
341  QModelIndex index = m_pTableView->indexAt(pos);
342 
343  //get selected items
344  QModelIndexList selected = m_pTableView->selectionModel()->selectedIndexes();
345 
346 // // Lambda C++11 version
347 // QVector<qint32> vecSelection;
348 // for(qint32 i = 0; i < selected.size(); ++i)
349 // if(selected[i].column() == 1)
350 // vecSelection.append(m_pRTMSAModel->getIdxSelMap()[selected[i].row()]);
351 
352 // //create custom context menu and actions
353 // QMenu *menu = new QMenu(this);
354 
355 // //select channels
356 // QAction* doSelection = menu->addAction(tr("Apply selection"));
357 // connect(doSelection,&QAction::triggered, [=](){
358 // m_pRTMSAModel->selectRows(vecSelection);
359 // });
360 
361  // non C++11 alternative
362  m_qListCurrentSelection.clear();
363  for(qint32 i = 0; i < selected.size(); ++i)
364  if(selected[i].column() == 1)
365  m_qListCurrentSelection.append(m_pRTMSAModel->getIdxSelMap()[selected[i].row()]);
366 
367  //create custom context menu and actions
368  QMenu *menu = new QMenu(this);
369 
370  //select channels
371  QAction* doSelection = menu->addAction(tr("Apply selection"));
372  connect(doSelection, &QAction::triggered, this, &RealTimeMultiSampleArrayWidget::applySelection);
373 
374  //undo selection
375  QAction* resetAppliedSelection = menu->addAction(tr("Reset selection"));
376  connect(resetAppliedSelection,&QAction::triggered, m_pRTMSAModel, &RealTimeMultiSampleArrayModel::resetSelection);
377  connect(resetAppliedSelection,&QAction::triggered, this, &RealTimeMultiSampleArrayWidget::resetSelection);
378 
379  //show context menu
380  menu->popup(m_pTableView->viewport()->mapToGlobal(pos));
381 }
382 
383 
384 //*************************************************************************************************************
385 
386 void RealTimeMultiSampleArrayWidget::resizeEvent(QResizeEvent* resizeEvent)
387 {
388  Q_UNUSED(resizeEvent)
389 }
390 
391 
392 //*************************************************************************************************************
393 
395 {
396  Q_UNUSED(keyEvent)
397 }
398 
399 
400 //*************************************************************************************************************
401 
403 {
404  Q_UNUSED(mouseEvent)
405 }
406 
407 
408 //*************************************************************************************************************
409 
411 {
412  Q_UNUSED(mouseEvent)
413 }
414 
415 
416 //*************************************************************************************************************
417 
419 {
420  Q_UNUSED(mouseEvent)
421 }
422 
423 
424 //*************************************************************************************************************
425 
427 {
428  Q_UNUSED(mouseEvent)
429 }
430 
431 
432 //*************************************************************************************************************
433 
435 {
436  if(!m_pRTMSAScalingWidget)
437  {
438  m_pRTMSAScalingWidget = QSharedPointer<RealTimeMultiSampleArrayScalingWidget>(new RealTimeMultiSampleArrayScalingWidget(this));
439 
440  m_pRTMSAScalingWidget->setWindowTitle("Channel Scaling");
441 
442  connect(m_pRTMSAScalingWidget.data(), &RealTimeMultiSampleArrayScalingWidget::scalingChanged, this, &RealTimeMultiSampleArrayWidget::broadcastScaling);
443  }
444  m_pRTMSAScalingWidget->show();
445 }
446 
447 
448 //*************************************************************************************************************
449 
450 void RealTimeMultiSampleArrayWidget::wheelEvent(QWheelEvent* wheelEvent)
451 {
452  Q_UNUSED(wheelEvent)
453 }
454 
455 //*************************************************************************************************************
456 
457 void RealTimeMultiSampleArrayWidget::zoomChanged(double zoomFac)
458 {
459  m_fZoomFactor = zoomFac;
460 
461  m_pTableView->verticalHeader()->setDefaultSectionSize(m_fZoomFactor*m_fDefaultSectionSize);//Row Height
462 }
463 
464 
465 //*************************************************************************************************************
466 
467 void RealTimeMultiSampleArrayWidget::timeWindowChanged(int T)
468 {
469  m_iT = T;
470  m_pRTMSAModel->setSamplingInfo(m_fSamplingRate, T, m_fDesiredSamplingRate);
471 }
472 
473 
474 //*************************************************************************************************************
475 
476 void RealTimeMultiSampleArrayWidget::showProjectionWidget()
477 {
478  //SSP selection
479  if(m_pFiffInfo && m_pFiffInfo->projs.size() > 0)
480  {
481  if(!m_pProjectorSelectionWidget)
482  {
483  m_pProjectorSelectionWidget = QSharedPointer<ProjectorWidget>(new ProjectorWidget);
484 
485  m_pProjectorSelectionWidget->setFiffInfo(m_pFiffInfo);
486 
487  connect(m_pProjectorSelectionWidget.data(), &ProjectorWidget::projSelectionChanged, this->m_pRTMSAModel, &RealTimeMultiSampleArrayModel::updateProjection);
488  }
489 
490  m_pProjectorSelectionWidget->show();
491  }
492 }
493 
494 
495 //*************************************************************************************************************
496 
497 void RealTimeMultiSampleArrayWidget::showSensorSelectionWidget()
498 {
499  if(!m_pSelectionManagerWindow) {
500  m_pSelectionManagerWindow = QSharedPointer<SelectionManagerWindow>(new SelectionManagerWindow);
501  }
502 
503  m_pSelectionManagerWindow->show();
504 }
505 
506 
507 //*************************************************************************************************************
508 
509 void RealTimeMultiSampleArrayWidget::applySelection()
510 {
511  m_pRTMSAModel->selectRows(m_qListCurrentSelection);
512 }
513 
514 
515 //*************************************************************************************************************
516 
517 void RealTimeMultiSampleArrayWidget::resetSelection()
518 {
519  // non C++11 alternative
520  m_qListCurrentSelection.clear();
521  for(qint32 i = 0; i < m_qListChInfo.size(); ++i)
522  m_qListCurrentSelection.append(i);
523 
524  applySelection();
525 }
526 
527 
528 //*************************************************************************************************************
529 
530 void RealTimeMultiSampleArrayWidget::showSelectedChannelsOnly(QStringList selectedChannels)
531 {
532  m_slSelectedChannels = selectedChannels;
533 
534  //Hide non selected channels/rows in the data views
535  for(int i = 0; i<m_pRTMSAModel->rowCount(); i++) {
536  QString channel = m_pRTMSAModel->data(m_pRTMSAModel->index(i, 0), Qt::DisplayRole).toString();
537  QVariant v = m_pRTMSAModel->data(m_pRTMSAModel->index(i,1), Qt::BackgroundRole);
538 
539  if(!selectedChannels.contains(channel))
540  m_pTableView->hideRow(i);
541  else
542  m_pTableView->showRow(i);
543 
544  //if channel is a bad channel and bad channels are to be hidden -> do not show
545  if(v.canConvert<QBrush>() && m_bHideBadChannels)
546  m_pTableView->hideRow(i);
547  }
548 }
549 
Free surfer annotation.
Definition: annotation.h:97
The RealTimeMultiSampleArrayDelegate class represents a RTMSA delegate which creates the plot paths...
void setCurrentlyMappedFiffChannels(const QStringList &mappedLayoutChNames)
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
The EvokedModalityWidget class provides the sensor selection widget.
const QMap< qint32, qint32 > & getIdxSelMap() const
void setSamplingInfo(float sps, int T, float dest_sps=128.0f)
virtual void mousePressEvent(QMouseEvent *mouseEvent)
void setFiffInfo(FIFFLIB::FiffInfo::SPtr &p_pFiffInfo)
virtual void wheelEvent(QWheelEvent *wheelEvent)
void showSelectedChannelsOnly(QStringList selectedChannels)
The SelectionManagerWindow class provides a channel selection window.
The RealTimeMultiSampleArrayModel class implements the data access model for a real-time multi sample...
virtual void update(XMEASLIB::NewMeasurement::SPtr pMeasurement)
void loadedLayoutMap(const QMap< QString, QPointF > &layoutMap)
void fiffFileUpdated(const FiffInfo &)
RealTimeMultiSampleArrayWidget(QSharedPointer< NewRealTimeMultiSampleArray > pRTMSA_New, QSharedPointer< QTime > &pTime, QWidget *parent=0)
Declaration of the RealTimeMultiSampleArrayWidget Class.
#define FIFF_UNIT_T_M
void layoutChanged(const QMap< QString, QPointF > &layoutMap)
void setScaling(const QMap< qint32, float > &p_qMapChScaling)
QSharedPointer< NewMeasurement > SPtr
Contains the declaration of the NewRealTimeMultiSampleArray class.
void setChannelInfo(QList< RealTimeSampleArrayChInfo > &chInfo)
The ProjectorWidget class provides the sensor selection widget.
void selectRows(const QList< qint32 > &selection)
The MeasurementWidget class is the base class of all measurement widgets.
void addDisplayWidget(QWidget *pWidget)
void addDisplayAction(QAction *pAction)
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
virtual void mouseMoveEvent(QMouseEvent *mouseEvent)
void channelsMappedToLayout(const QStringList &mappedLayoutChNames)