v2.0.0
Loading...
Searching...
No Matches
rtfiffrawview.cpp
Go to the documentation of this file.
1//=============================================================================================================
36
37//=============================================================================================================
38// INCLUDES
39//=============================================================================================================
40
41#include "rtfiffrawview.h"
42
45
46#include <dsp/filterkernel.h>
47#include <fiff/fiff_info.h>
48
49//=============================================================================================================
50// QT INCLUDES
51//=============================================================================================================
52
53#include <QGridLayout>
54#include <QHeaderView>
55#include <QTableView>
56#include <QMenu>
57#include <QSvgGenerator>
58#include <QSettings>
59#include <QScrollBar>
60#include <QMouseEvent>
61
62#if !defined(NO_QOPENGLWIDGET)
63 #include <QOpenGLWidget>
64#endif
65
66//=============================================================================================================
67// USED NAMESPACES
68//=============================================================================================================
69
70using namespace DISPLIB;
71using namespace FIFFLIB;
72using namespace Eigen;
73using namespace RTPROCESSINGLIB;
74using namespace UTILSLIB;
75
76//=============================================================================================================
77// DEFINE MEMBER METHODS
78//=============================================================================================================
79
80RtFiffRawView::RtFiffRawView(const QString& sSettingsPath,
81 QWidget *parent,
82 Qt::WindowFlags f)
83: AbstractView(parent, f)
84, m_iT(10)
85, m_fSamplingRate(1024)
86, m_fZoomFactor(1.0f)
87, m_bHideBadChannels(false)
89, m_iClickPosX(0)
90{
91 m_sSettingsPath = sSettingsPath;
92 m_pTableView = new QTableView;
93
94#if !defined(NO_QOPENGLWIDGET)
95 m_pTableView->setViewport(new QOpenGLWidget);
96#endif
97
98 // Install event filter for tracking mouse movements
99 m_pTableView->viewport()->installEventFilter(this);
100 m_pTableView->setMouseTracking(true);
101
102 // Set layout
103 QVBoxLayout *neLayout = new QVBoxLayout(this);
104 neLayout->addWidget(m_pTableView);
105 neLayout->setContentsMargins(0,0,0,0);
106 this->setLayout(neLayout);
107
108 loadSettings();
109}
110
111//=============================================================================================================
112
117
118//=============================================================================================================
119
121{
122#if !defined(NO_QOPENGLWIDGET)
123 if(m_pTableView) {
124 m_pTableView->setViewport(new QOpenGLWidget);
125 }
126#endif
127}
128
129//=============================================================================================================
130
131void RtFiffRawView::setSettingsPath(const QString& sSettingsPath)
132{
133 m_sSettingsPath = sSettingsPath;
134 loadSettings();
135}
136
137//=============================================================================================================
138
139void RtFiffRawView::init(QSharedPointer<FIFFLIB::FiffInfo> &info)
140{
141 m_pFiffInfo = info;
143
144 //Init the model
145 m_pModel = new RtFiffRawViewModel(this);
146 m_pModel->setFiffInfo(m_pFiffInfo);
147 m_pModel->setSamplingInfo(m_fSamplingRate, m_iT, true);
150 connect(this, &RtFiffRawView::addSampleAsEvent,
151 m_pModel, &RtFiffRawViewModel::addEvent, Qt::UniqueConnection);
152
153 //Init bad channel list
154 m_qListBadChannels.clear();
155 for(int i = 0; i<m_pModel->rowCount(); i++) {
156 if(m_pModel->data(m_pModel->index(i,2)).toBool()) {
158 }
159 }
160
161 //Init the delegate
163 m_pDelegate->initPainterPaths(m_pModel);
164
165 connect(this, &RtFiffRawView::markerMoved,
167
168 //Init the view
169 m_pTableView->setModel(m_pModel);
170 m_pTableView->setItemDelegate(m_pDelegate);
171 m_pTableView->setContextMenuPolicy(Qt::CustomContextMenu);
172
173 connect(m_pTableView.data(), &QTableView::doubleClicked,
175
176 connect(m_pTableView.data(), &QTableView::customContextMenuRequested,
178
179 //set some size settings for m_pTableView
180 m_pTableView->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
181 m_pTableView->setShowGrid(false);
182 m_pTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); //Stretch 2 column to maximal width
183 m_pTableView->horizontalHeader()->hide();
184 m_pTableView->verticalHeader()->setDefaultSectionSize(m_pTableView->height() / m_fZoomFactor);//Row Height
185 m_pTableView->setAutoScroll(false);
186 m_pTableView->setColumnHidden(0,true); //because content is plotted jointly with column=1
187 m_pTableView->setColumnHidden(2,true);
188 m_pTableView->resizeColumnsToContents();
189 m_pTableView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
190
191 connect(m_pTableView->verticalScrollBar(), &QScrollBar::valueChanged,
193}
194
195//=============================================================================================================
196
197void RtFiffRawView::addData(const QList<Eigen::MatrixXd> &data)
198{
199 if(!data.isEmpty()) {
200 m_pModel->addData(data);
201
202 if(m_qListBadChannels.size() != m_pFiffInfo->bads.size()) {
203 m_qListBadChannels.clear();
204 for(int i = 0; i<m_pModel->rowCount(); i++) {
205 if(m_pModel->data(m_pModel->index(i,2)).toBool()) {
207 }
208 }
209
210 //Hide non selected channels/rows in the data views
211 for(int i = 0; i<m_qListBadChannels.size(); i++) {
213 m_pTableView->hideRow(m_qListBadChannels.at(i));
214 } else {
215 m_pTableView->showRow(m_qListBadChannels.at(i));
216 }
217 }
218 }
219 } else {
220 qWarning() << "[RtFiffRawView::addData] Received data list is empty.";
221 }
222}
223
224//=============================================================================================================
225
227{
228 return m_pModel->getLastBlock();
229}
230
231//=============================================================================================================
232
233bool RtFiffRawView::eventFilter(QObject *object, QEvent *event)
234{
235// if (object == m_pTableView->viewport() && event->type() == QEvent::MouseMove) {
236// QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
237// emit markerMoved(mouseEvent->pos(), m_pTableView->rowAt(mouseEvent->pos().y()));
238// return true;
239// }
240
241 return QWidget::eventFilter(object, event);
242}
243
244//=============================================================================================================
245
246void RtFiffRawView::setBackgroundColor(const QColor& backgroundColor)
247{
248 m_backgroundColor = backgroundColor;
249
250 if(m_pModel) {
251 m_pModel->setBackgroundColor(m_backgroundColor);
252 }
253
254// QPalette pal;
255// pal.setColor(QPalette::Window, m_backgroundColor);
256// m_pTableView->viewport()->setPalette(pal);
257// m_pTableView->viewport()->setBackgroundRole(QPalette::Window);
258}
259
260//=============================================================================================================
261
266
267//=============================================================================================================
268
269QMap<qint32, float> RtFiffRawView::getScalingMap()
270{
271 return m_qMapChScaling;
272}
273
274//=============================================================================================================
275
276void RtFiffRawView::setScalingMap(const QMap<qint32, float>& scaleMap)
277{
278 m_qMapChScaling = scaleMap;
279 m_pModel->setScaling(scaleMap);
280}
281
282//=============================================================================================================
283
284void RtFiffRawView::setSignalColor(const QColor& signalColor)
285{
286 m_pDelegate->setSignalColor(signalColor);
287}
288
289//=============================================================================================================
290
292{
293 return m_pDelegate->getSignalColor();
294}
295
296//=============================================================================================================
297
299{
301 m_bHideBadChannels = false;
302 } else {
303 m_bHideBadChannels = true;
304 }
305
306 //Hide non selected channels/rows in the data views
307 for(int i = 0; i<m_qListBadChannels.size(); i++) {
309 m_pTableView->hideRow(m_qListBadChannels.at(i));
310 } else {
311 m_pTableView->showRow(m_qListBadChannels.at(i));
312 }
313 }
314
315 //Update the visible channel list which are to be filtered
317}
318
319//=============================================================================================================
320
325
326//=============================================================================================================
327
328void RtFiffRawView::showSelectedChannelsOnly(const QStringList &selectedChannels)
329{
330 m_slSelectedChannels = selectedChannels;
331
332 //Hide non selected channels/rows in the data views
333 for(int i = 0; i<m_pModel->rowCount(); i++) {
334 QString channel = m_pModel->data(m_pModel->index(i, 0), Qt::DisplayRole).toString();
335
336 //if channel is a bad channel and bad channels are to be hidden -> do not show
337 if(!selectedChannels.contains(channel) || (m_qListBadChannels.contains(i) && m_bHideBadChannels)) {
338 m_pTableView->hideRow(i);
339 } else {
340 m_pTableView->showRow(i);
341 }
342 }
343
344 //Update the visible channel list which are to be filtered
346}
347
348//=============================================================================================================
349
350void RtFiffRawView::setZoom(double zoomFac)
351{
352 m_fZoomFactor = zoomFac;
353
354 m_pTableView->verticalHeader()->setDefaultSectionSize(m_pTableView->height() / m_fZoomFactor);//Row Height
355}
356
357//=============================================================================================================
358
360{
361 return m_fZoomFactor;
362}
363
364//=============================================================================================================
365
367{
368 m_iT = T;
369
370 m_pModel->setSamplingInfo(m_fSamplingRate, T);
371}
372
373//=============================================================================================================
374
376{
377 return m_iT;
378}
379
380//=============================================================================================================
381
383{
384 return m_fSamplingRate;
385}
386
387//=============================================================================================================
388
389void RtFiffRawView::takeScreenshot(const QString& fileName)
390{
391 if(fileName.contains(".svg", Qt::CaseInsensitive)) {
392 // Generate screenshot
393 QSvgGenerator svgGen;
394 svgGen.setFileName(fileName);
395 svgGen.setSize(m_pTableView->size());
396 svgGen.setViewBox(m_pTableView->rect());
397
398 m_pTableView->render(&svgGen);
399 }
400
401 if(fileName.contains(".png", Qt::CaseInsensitive)) {
402 QPixmap pixMap(m_pTableView->grab());
403 pixMap.save(fileName);
404 }
405}
406
407//=============================================================================================================
408
409void RtFiffRawView::updateProjection(const QList<FIFFLIB::FiffProj>& projs)
410{
411 m_pModel->updateProjection(projs);
412}
413
414//=============================================================================================================
415
417{
418 m_pModel->updateCompensator(to);
419}
420
421//=============================================================================================================
422
424{
425 m_pModel->updateSpharaActivation(state);
426}
427
428//=============================================================================================================
429
430void RtFiffRawView::updateSpharaOptions(const QString& sSytemType, int nBaseFctsFirst, int nBaseFctsSecond)
431{
432 m_pModel->updateSpharaOptions(sSytemType, nBaseFctsFirst, nBaseFctsSecond);
433}
434
435//=============================================================================================================
436
438{
439 m_pModel->setFilter(QList<FilterKernel>() << filterData);
440}
441
442//=============================================================================================================
443
445{
446 m_pModel->setFilterActive(state);
447}
448
449//=============================================================================================================
450
451void RtFiffRawView::setFilterChannelType(const QString &channelType)
452{
453 m_pModel->setFilterChannelType(channelType);
454}
455
456//=============================================================================================================
457
458void RtFiffRawView::triggerInfoChanged(const QMap<double, QColor>& colorMap,
459 bool active,
460 const QString &triggerCh,
461 double threshold)
462{
463 m_pModel->triggerInfoChanged(colorMap, active, triggerCh, threshold);
464}
465
466//=============================================================================================================
467
469{
470 m_iDistanceTimeSpacer = value;
471 m_pModel->distanceTimeSpacerChanged(value);
472}
473
474//=============================================================================================================
475
480
481//=============================================================================================================
482
484{
485 m_pModel->resetTriggerCounter();
486}
487
488//=============================================================================================================
489
491{
492 if(m_sSettingsPath.isEmpty()) {
493 return;
494 }
495
496 QSettings settings("MNECPP");
497}
498
499//=============================================================================================================
500
502{
503 if(m_sSettingsPath.isEmpty()) {
504 return;
505 }
506
507 QSettings settings("MNECPP");
508}
509
510//=============================================================================================================
511
513{
514 switch(mode) {
516 break;
517 default: // default is research mode
518 break;
519 }
520}
521
522//=============================================================================================================
523
525{
526 switch(mode) {
528 break;
529 default: // default is realtime mode
530 break;
531 }
532}
533
534//=============================================================================================================
535
537{
538 m_iClickPosX = pos.x();
539
540 //obtain index where index was clicked
541 QModelIndex index = m_pTableView->indexAt(pos);
542
543 //get selected items
544 QModelIndexList selected = m_pTableView->selectionModel()->selectedIndexes();
545
546 //create custom context menu and actions
547 QMenu *menu = new QMenu(this);
548
549 menu->addSection("Events");
550
551 QAction* addEventMarker = menu->addAction(tr("Add event"));
552 connect(addEventMarker, &QAction::triggered,
554
555 //Marking
556
557 menu->addSection("Channel Marking");
558
559 if(!m_qListBadChannels.contains(index.row())) {
560 QAction* doMarkChBad = menu->addAction(tr("Mark as bad"));
561 connect(doMarkChBad, &QAction::triggered,
563 } else {
564 QAction* doMarkChGood = menu->addAction(tr("Mark as good"));
565 connect(doMarkChGood, &QAction::triggered,
567 }
568
569 // non C++11 alternative
571 for(qint32 i = 0; i < selected.size(); ++i)
572 if(selected[i].column() == 1)
573 m_qListCurrentSelection.append(m_pModel->getIdxSelMap()[selected[i].row()]);
574
575 menu->addSection("Selection");
576
577 QAction* doSelection = menu->addAction(tr("Only show selection"));
578 connect(doSelection, &QAction::triggered,
580
581 //select channels
582 QAction* hideSelection = menu->addAction(tr("Hide selection"));
583 connect(hideSelection, &QAction::triggered, this,
585
586 //undo selection
587 QAction* resetAppliedSelection = menu->addAction(tr("Reset selection"));
588 connect(resetAppliedSelection, &QAction::triggered,
590 connect(resetAppliedSelection, &QAction::triggered,
592
593 //show context menu
594 menu->popup(m_pTableView->viewport()->mapToGlobal(pos));
595}
596
597//=============================================================================================================
598
600{
601 //Hide non selected channels/rows in the data views
602 for(int i = 0; i<m_pModel->rowCount(); i++) {
603 //if channel is a bad channel and bad channels are to be hidden -> do not show
604 if(m_qListCurrentSelection.contains(i)) {
605 m_pTableView->showRow(i);
606 } else {
607 m_pTableView->hideRow(i);
608 }
609 }
610
611 //Update the visible channel list which are to be filtered
612 //visibleRowsChanged();
613
614 //m_pModel->selectRows(m_qListCurrentSelection);
615}
616
617//=============================================================================================================
618
620{
621 for(int i=0; i<m_qListCurrentSelection.size(); i++) {
623 }
624
625 //Update the visible channel list which are to be filtered
626 //visibleRowsChanged();
627}
628
629//=============================================================================================================
630
632{
633 // non C++11 alternative
634 for(qint32 i = 0; i < m_pFiffInfo->chs.size(); ++i) {
635 if(m_qListBadChannels.contains(i)) {
636 if(!m_bHideBadChannels) {
637 m_pTableView->showRow(i);
638 }
639 } else {
640 m_pTableView->showRow(i);
641 }
642 }
643
644 //Update the visible channel list which are to be filtered
645 //visibleRowsChanged();
646}
647
648//=============================================================================================================
649
651{
652 if(!m_pTableView || !m_pModel || !m_pDelegate) {
653 return;
654 }
655
656 int from = m_pTableView->rowAt(0);
657// if(from != 0){
658// from--;
659
660 int to = m_pTableView->rowAt(m_pTableView->height()-1);
661 if(to != m_pModel->rowCount()-1)
662 to++;
663
664 if(from > to)
665 to = m_pModel->rowCount()-1;
666
667// //Update visible rows in order to only filter the visible rows
668// QStringList channelNames;
669
670// for(int i = from; i<=to; i++) {
671// channelNames << m_pModel->data(m_pModel->index(i, 0), Qt::DisplayRole).toString();
672// }
673
674// m_pModel->createFilterChannelList(channelNames);
675
676 m_pDelegate->setUpperItemIndex(from/*+1*/);
677
678 //qDebug() <<"RtFiffRawView::visibleRowsChanged - from "<< from << " to" << to;
679}
680
681//=============================================================================================================
682
684{
685 QModelIndexList selected = m_pTableView->selectionModel()->selectedIndexes();
686
687 for(int i=0; i<selected.size(); i++) {
688 if(m_qListBadChannels.contains(selected[i].row())) { //mark as good
689 m_pModel->markChBad(selected[i], false);
690 m_qListBadChannels.removeAll(selected[i].row());
691 }
692 else {
693 m_pModel->markChBad(selected[i], true);
694 m_qListBadChannels.append(selected[i].row());
695 }
696 }
697
698 m_pModel->updateProjection(m_pFiffInfo->projs);
699
700 //Hide non selected channels/rows in the data views
701 for(int i = 0; i<m_qListBadChannels.size(); i++) {
703 m_pTableView->hideRow(m_qListBadChannels.at(i));
704 } else {
705 m_pTableView->showRow(m_qListBadChannels.at(i));
706 }
707 }
708
710}
711
712//=============================================================================================================
713
715{
716
717}
718
719//=============================================================================================================
720
721void RtFiffRawView::onAddEvent(bool bChecked)
722{
723 Q_UNUSED(bChecked)
724 double dDx = static_cast<double>(m_pTableView->columnWidth(1)) / static_cast<double>(m_pModel->getMaxSamples());
725 double dSample = static_cast<double>(m_iClickPosX) / dDx;
726
727 int iFirstSampleOffset = m_pModel->getFirstSampleOffset();
728
729 // Dont allow adding events to blank space in the beginning
730 if (dSample > m_pModel->getCurrentSampleIndex() && iFirstSampleOffset == 0){
731 return;
732 }
733
734 //Add offset
735 int iAbsoluteSample = static_cast<int>(dSample) + iFirstSampleOffset;
736
737 //Account for whether adding before or after draw point
738 if (dSample > m_pModel->getCurrentSampleIndex()){
739 iAbsoluteSample -= m_pModel->getMaxSamples();
740 }
741
742 qDebug() << "EVENT SAMPLE:" << iAbsoluteSample;
743
744 emit addSampleAsEvent(iAbsoluteSample);
745}
Declaration of the RtFiffRawView Class.
Declaration of the RtFiffRawViewModel Class.
Declaration of the RtFiffRawViewDelegate Class.
FiffInfo class declaration.
The FilterKernel class represents a filter object that generates the FIR filter coefficients using Pa...
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
2-D display widgets and visualisation helpers (charts, topography, colour maps).
DSPSHARED_EXPORT Eigen::MatrixXd filterData(const Eigen::MatrixXd &matData, int type, double dCenterfreq, double dBandwidth, double dTransition, double dSFreq, int iOrder=1024, int designMethod=UTILSLIB::FilterKernel::m_designMethods.indexOf(UTILSLIB::FilterParameter("Cosine")), const Eigen::RowVectorXi &vecPicks=Eigen::RowVectorXi(), bool bUseThreads=true, bool bKeepOverhead=false)
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
AbstractView(QWidget *parent=0, Qt::WindowFlags f=Qt::Widget)
The RtFiffRawViewDelegate class represents a RTMSA delegate which creates the plot paths.
void markerMoved(QPoint position, int activeRow)
The RtFiffRawViewModel class implements the data access model for a real-time multi sample array data...
void toggleFreeze(const QModelIndex &index)
void triggerDetected(int numberDetectedTriggers, const QMap< int, QList< QPair< int, double > > > &mapDetectedTriggers)
void setFilterChannelType(const QString &channelType)
QPointer< DISPLIB::RtFiffRawViewModel > m_pModel
QMap< qint32, float > m_qMapChScaling
void init(QSharedPointer< FIFFLIB::FiffInfo > &info)
QMap< qint32, float > getScalingMap()
RtFiffRawView(const QString &sSettingsPath="", QWidget *parent=0, Qt::WindowFlags f=Qt::Widget)
void takeScreenshot(const QString &fileName)
void updateGuiMode(GuiMode mode)
bool eventFilter(QObject *object, QEvent *event)
void triggerDetected(int numberDetectedTriggers, const QMap< int, QList< QPair< int, double > > > &mapDetectedTriggers)
void setBackgroundColor(const QColor &backgroundColor)
void addSampleAsEvent(int iSample)
void updateSpharaOptions(const QString &sSytemType, int nBaseFctsFirst, int nBaseFctsSecond)
void setDistanceTimeSpacer(int value)
QList< qint32 > m_qListBadChannels
float getSamplingFreq() const
QStringList m_slSelectedChannels
void channelContextMenu(QPoint pos)
Eigen::MatrixXd getLastBlock()
QPointer< QTableView > m_pTableView
void markerMoved(QPoint position, int activeRow)
void addData(const QList< Eigen::MatrixXd > &data)
void updateProcessingMode(ProcessingMode mode)
void showSelectedChannelsOnly(const QStringList &selectedChannels)
void updateSpharaActivation(bool state)
QSharedPointer< FIFFLIB::FiffInfo > m_pFiffInfo
void triggerInfoChanged(const QMap< double, QColor > &colorMap, bool active, const QString &triggerCh, double threshold)
void setSignalColor(const QColor &signalColor)
void setSettingsPath(const QString &sSettingsPath)
QPointer< DISPLIB::RtFiffRawViewDelegate > m_pDelegate
void onAddEvent(bool bChecked)
void setFilterActive(bool state)
void setFilter(const UTILSLIB::FilterKernel &filterData)
QList< qint32 > m_qListCurrentSelection
void updateProjection(const QList< FIFFLIB::FiffProj > &projs)
void setZoom(double zoomFac)
void setScalingMap(const QMap< qint32, float > &scaleMap)
The FilterKernel class provides methods to create/design a FIR filter kernel.