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