MNE-CPP 0.1.9
A Framework for Electrophysiology
Loading...
Searching...
No Matches
rtfiffrawview.cpp
Go to the documentation of this file.
1//=============================================================================================================
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)
87, m_iDistanceTimeSpacer(1)
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) {
514 case GuiMode::Clinical:
515 break;
516 default: // default is research mode
517 break;
518 }
519}
520
521//=============================================================================================================
522
523void RtFiffRawView::updateProcessingMode(ProcessingMode mode)
524{
525 switch(mode) {
526 case ProcessingMode::Offline:
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...
RTPROCESINGSHARED_EXPORT 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)
Declaration of the RtFiffRawView Class.
Declaration of the RtFiffRawViewModel Class.
Declaration of the RtFiffRawViewDelegate Class.
FiffInfo class declaration.
The AbstractView class provides the base calss for all Disp viewers.
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 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.