MNE-CPP 0.1.9
A Framework for Electrophysiology
Loading...
Searching...
No Matches
scalingview.cpp
Go to the documentation of this file.
1//=============================================================================================================
35//=============================================================================================================
36// INCLUDES
37//=============================================================================================================
38
39#include "scalingview.h"
40#include "ui_scalingview.h"
41#include <fiff/fiff_constants.h>
43
44//=============================================================================================================
45// QT INCLUDES
46//=============================================================================================================
47
48#include <QSettings>
49#include <QKeyEvent>
50#include <QCheckBox>
51#include <QDebug>
52
53//=============================================================================================================
54// EIGEN INCLUDES
55//=============================================================================================================
56
57//=============================================================================================================
58// USED NAMESPACES
59//=============================================================================================================
60
61using namespace DISPLIB;
62using namespace FIFFLIB;
63
64//=============================================================================================================
65// DEFINE GLOBAL DISPLIB METHODS
66//=============================================================================================================
67
71const static float m_fScaleMAG = 1e-12f;
72const static float m_fScaleGRAD = 1e-15f;
73const static float m_fScaleEEG = 1e-5f;
74const static float m_fScaleEOG = 1e-6f;
75const static float m_fScaleECG = 1e-2f;
76const static float m_fScaleSTIM = 1e-3f;
77const static float m_fScaleMISC = 1e-3f;
78const static float m_fScaleEMG = 1e-3f;
79const static int MAG_TO_GRAD_LINK = 31337;
80
81float DISPLIB::getDefaultScalingValue(int iChannelKind,
82 int iChannelUnit)
83{
84 float fMaxScale(1e-9f);
85
86 switch(iChannelKind) {
87 case FIFFV_MEG_CH: {
88 if( iChannelUnit == FIFF_UNIT_T_M ) { //Gradiometers
89 fMaxScale = m_fScaleGRAD;
90 }
91 else if( iChannelUnit == FIFF_UNIT_T ) { //Magnetometers
92 fMaxScale = m_fScaleMAG;
93 }
94 break;
95 }
96
97 case FIFFV_REF_MEG_CH: {
98 fMaxScale = m_fScaleMAG;
99 break;
100 }
101
102 case FIFFV_EEG_CH: { //EEG Channels
103 fMaxScale = m_fScaleEEG;
104 break;
105 }
106
107 case FIFFV_ECG_CH: { //ECG Channels
108 fMaxScale = m_fScaleECG;
109 break;
110 }
111 case FIFFV_EMG_CH: { //EMG Channels
112 fMaxScale = m_fScaleEMG;
113 break;
114 }
115 case FIFFV_EOG_CH: { //EOG Channels
116 fMaxScale = m_fScaleEOG;
117 break;
118 }
119
120 case FIFFV_STIM_CH: { //STIM Channels
121 fMaxScale = m_fScaleSTIM;
122 break;
123 }
124
125 case FIFFV_MISC_CH: { //MISC Channels
126 fMaxScale = m_fScaleMISC;
127 break;
128 }
129 }
130
131 return fMaxScale;
132}
133
134//=============================================================================================================
135
136float DISPLIB::getScalingValue(const QMap<qint32, float>& qMapChScaling,
137 int iChannelKind,
138 int iChannelUnit)
139{
140 float fMaxScale = qMapChScaling.value(iChannelKind);
141
142 if(iChannelKind == FIFFV_MEG_CH) {
143 fMaxScale = qMapChScaling.value(iChannelUnit);
144 }
145
146 if(qIsNaN(fMaxScale) || fMaxScale == 0) {
147 fMaxScale = DISPLIB::getDefaultScalingValue(iChannelKind, iChannelUnit);
148 }
149 return fMaxScale;
150}
151
152//=============================================================================================================
153// DEFINE MEMBER METHODS
154//=============================================================================================================
155
156ScalingView::ScalingView(const QString& sSettingsPath,
157 QWidget *parent,
158 Qt::WindowFlags f,
159 const QStringList& lChannelsToShow)
160: AbstractView(parent, f)
161, m_lChannelTypesToShow(lChannelsToShow)
162, m_pUi(new Ui::ScalingViewWidget)
163, m_bLinkMAGtoGRAD(false)
164, m_bIsShiftKeyPressed(false)
165, m_bManagingSpinBoxChange(false)
166, m_bManagingSliderChange(false)
167, m_bManagingLinkMagToGrad(false)
168{
169 m_sSettingsPath = sSettingsPath;
170 m_pUi->setupUi(this);
171
172 this->setWindowTitle("Scaling");
173 this->setMinimumWidth(230);
174
175 loadSettings();
176 createScaleControls();
177 drawScalingGUI();
178}
179
180//=============================================================================================================
181
183{
184 saveSettings();
185
186 delete m_pUi;
187
188 for(auto& control : m_qMapScaleControls)
189 {
190 delete control;
191 }
192}
193
194//=============================================================================================================
195
196void ScalingView::keyReleaseEvent(QKeyEvent *event)
197{
198 if(event->key() == Qt::Key_Shift)
199 {
200 m_bIsShiftKeyPressed = false;
201 }
202 QWidget::keyReleaseEvent(event);
203}
204
205//=============================================================================================================
206
207void ScalingView::keyPressEvent(QKeyEvent *event)
208{
209 if(event->key() == Qt::Key_Shift)
210 {
211 m_bIsShiftKeyPressed = true;
212 }
213 QWidget::keyPressEvent(event);
214}
215
216//=============================================================================================================
217
218QMap<qint32,float> ScalingView::getScaleMap() const
219{
220 return m_qMapChScaling;
221}
222
223//=============================================================================================================
224
225void ScalingView::setScaleMap(const QMap<qint32,float>& qMapChScaling)
226{
227 m_qMapChScaling = qMapChScaling;
228
229 createScaleControls();
230}
231
232//=============================================================================================================
233
235{
236 if(m_sSettingsPath.isEmpty()) {
237 return;
238 }
239
240 QSettings settings("MNECPP");
241
242 if(m_qMapChScaling.contains(FIFF_UNIT_T)) {
243 settings.setValue(m_sSettingsPath + QString("/ScalingView/scaleMAG"), m_qMapChScaling[FIFF_UNIT_T]);
244 }
245
246 if(m_qMapChScaling.contains(FIFF_UNIT_T_M)) {
247 settings.setValue(m_sSettingsPath + QString("/ScalingView/scaleGRAD"), m_qMapChScaling[FIFF_UNIT_T_M]);
248 }
249
250 if(m_qMapChScaling.contains(FIFFV_EEG_CH)) {
251 settings.setValue(m_sSettingsPath + QString("/ScalingView/scaleEEG"), m_qMapChScaling[FIFFV_EEG_CH]);
252 }
253
254 if(m_qMapChScaling.contains(FIFFV_EOG_CH)) {
255 settings.setValue(m_sSettingsPath + QString("/ScalingView/scaleEOG"), m_qMapChScaling[FIFFV_EOG_CH]);
256 }
257
258 if(m_qMapChScaling.contains(FIFFV_ECG_CH)) {
259 settings.setValue(m_sSettingsPath + QString("/ScalingView/scaleECG"), m_qMapChScaling[FIFFV_ECG_CH]);
260 }
261
262 if(m_qMapChScaling.contains(FIFFV_STIM_CH)) {
263 settings.setValue(m_sSettingsPath + QString("/ScalingView/scaleSTIM"), m_qMapChScaling[FIFFV_STIM_CH]);
264 }
265
266 if(m_qMapChScaling.contains(FIFFV_MISC_CH)) {
267 settings.setValue(m_sSettingsPath + QString("/ScalingView/scaleMISC"), m_qMapChScaling[FIFFV_MISC_CH]);
268 }
269}
270
271//=============================================================================================================
272
274{
275 if(m_sSettingsPath.isEmpty()) {
276 return;
277 }
278
279 QSettings settings("MNECPP");
280
281 float val = settings.value(m_sSettingsPath + QString("/ScalingView/scaleMAG"), m_fScaleMAG * 3).toFloat();
282 m_qMapChScaling.insert(FIFF_UNIT_T, val);
283
284 val = settings.value(m_sSettingsPath + QString("/ScalingView/scaleGRAD"), m_fScaleGRAD * 300 * 100/*convert cm to m*/).toFloat();
285 m_qMapChScaling.insert(FIFF_UNIT_T_M, val);
286
287 val = settings.value(m_sSettingsPath + QString("/ScalingView/scaleEEG"), m_fScaleEEG * 10).toFloat();
288 m_qMapChScaling.insert(FIFFV_EEG_CH, val);
289
290 val = settings.value(m_sSettingsPath + QString("/ScalingView/scaleEOG"), m_fScaleEOG).toFloat();
291 m_qMapChScaling.insert(FIFFV_EOG_CH, val);
292
293 val = settings.value(m_sSettingsPath + QString("/ScalingView/scaleECG"), m_fScaleECG).toFloat();
294 m_qMapChScaling.insert(FIFFV_ECG_CH, val);
295
296 val = settings.value(m_sSettingsPath + QString("/ScalingView/scaleSTIM"), m_fScaleSTIM).toFloat();
297 m_qMapChScaling.insert(FIFFV_STIM_CH, val);
298
299 val = settings.value(m_sSettingsPath + QString("/ScalingView/scaleMISC"), m_fScaleMISC).toFloat();
300 m_qMapChScaling.insert(FIFFV_MISC_CH, val);
301}
302
303//=============================================================================================================
304
305void ScalingView::updateGuiMode(GuiMode mode)
306{
307 switch(mode) {
308 case GuiMode::Clinical:
309 break;
310 default: // default is research mode
311 break;
312 }
313}
314
315//=============================================================================================================
316
317void ScalingView::updateProcessingMode(ProcessingMode mode)
318{
319 switch(mode) {
320 case ProcessingMode::Offline:
321 break;
322 default: // default is realtime mode
323 break;
324 }
325}
326
327//=============================================================================================================
328
329void ScalingView::processScalingChange()
330{
331 emit scalingChanged(m_qMapChScaling);
332 saveSettings();
333}
334
335//=============================================================================================================
336
337void ScalingView::updateMAGScale(double dScale)
338{
339 m_qMapChScaling.insert(FIFF_UNIT_T, dScale * m_fScaleMAG);
340 linkMagToGrad();
341 processScalingChange();
342}
343
344//=============================================================================================================
345
346void ScalingView::linkMagToGrad()
347{
348 if(m_bLinkMAGtoGRAD && !m_bManagingLinkMagToGrad)
349 {
350 m_bManagingLinkMagToGrad = true;
351 m_qMapScaleControls[FIFF_UNIT_T_M]->setValue(m_qMapScaleControls[FIFF_UNIT_T]->value() / (m_qMapScaleControls[MAG_TO_GRAD_LINK]->value() / 100.f));
352 m_bManagingLinkMagToGrad = false;
353 }
354}
355
356//=============================================================================================================
357
358void ScalingView::linkGradToMag()
359{
360 if(m_bLinkMAGtoGRAD && !m_bManagingLinkMagToGrad)
361 {
362 m_bManagingLinkMagToGrad = true;
363 m_qMapScaleControls[FIFF_UNIT_T]->setValue(m_qMapScaleControls[FIFF_UNIT_T_M]->value() * (m_qMapScaleControls[MAG_TO_GRAD_LINK]->value() / 100.0f));
364 m_bManagingLinkMagToGrad = false;
365 }
366}
367
368//=============================================================================================================
369
370void ScalingView::updateGRADScale(double dScale)
371{
372 m_qMapChScaling.insert(FIFF_UNIT_T_M, dScale * m_fScaleGRAD * 100.0);//*100 because we have data in fT/cm and we want it in ft/m.
373 linkGradToMag();
374 processScalingChange();
375}
376
377//=============================================================================================================
378
379void ScalingView::updateEEGScale(double dScale)
380{
381 m_qMapChScaling.insert(FIFFV_EEG_CH, dScale * m_fScaleEEG);
382 processScalingChange();
383}
384
385//=============================================================================================================
386
387void ScalingView::updateEOGScale(double dScale)
388{
389 m_qMapChScaling.insert(FIFFV_EOG_CH, dScale * m_fScaleEOG);
390 processScalingChange();
391}
392
393//=============================================================================================================
394
395void ScalingView::updateEMGScale(double dScale)
396{
397 m_qMapChScaling.insert(FIFFV_EMG_CH, dScale * m_fScaleEMG);
398 processScalingChange();
399}
400
401//=============================================================================================================
402
403void ScalingView::updateECGScale(double dScale)
404{
405 m_qMapChScaling.insert(FIFFV_ECG_CH, dScale * m_fScaleECG);
406 processScalingChange();
407}
408
409//=============================================================================================================
410
411void ScalingView::updateMISCScale(double dScale)
412{
413 m_qMapChScaling.insert(FIFFV_MISC_CH, dScale * m_fScaleMISC);
414 processScalingChange();
415}
416
417//=============================================================================================================
418
419void ScalingView::updateSTIMScale(double scale)
420{
421 m_qMapChScaling.insert(FIFFV_STIM_CH, scale * m_fScaleSTIM);
422 processScalingChange();
423}
424
425//=============================================================================================================
426
427void ScalingView::updateMAGtoGRADlink(double dScale)
428{
429 Q_UNUSED(dScale)
430
431 linkMagToGrad();
432}
433
434//=============================================================================================================
435
436void ScalingView::drawScalingGUI()
437{
438 int i(0);
439 int controls[] = {FIFF_UNIT_T,
440 MAG_TO_GRAD_LINK,
441 FIFF_UNIT_T_M,
442 FIFFV_EEG_CH,
443 FIFFV_EOG_CH,
444 FIFFV_ECG_CH,
445 FIFFV_STIM_CH,
446 FIFFV_MISC_CH };
447 for(int c: controls)
448 {
449 if(m_qMapScaleControls.contains(c))
450 {
451 m_pUi->verticalLayout->insertWidget(i++, m_qMapScaleControls[c].data());
452 }
453 }
454 createLinkMagGradCheckBox();
455}
456
457//=============================================================================================================
458
460{
461 if(m_qMapScaleControls.contains(MAG_TO_GRAD_LINK))
462 {
463 m_bLinkMAGtoGRAD = (l == 2)? true: false;
464 } else {
465 m_bLinkMAGtoGRAD = false;
466 }
467 if(m_bLinkMAGtoGRAD)
468 {
469 m_qMapScaleControls[MAG_TO_GRAD_LINK]->setValue(100 * m_qMapScaleControls[FIFF_UNIT_T]->value() / m_qMapScaleControls[FIFF_UNIT_T_M]->value());
470 }
471 showLinkControl();
472}
473
474//=============================================================================================================
475
476void ScalingView::showLinkControl()
477{
478 if(m_qMapScaleControls.contains(MAG_TO_GRAD_LINK))
479 {
480 m_qMapScaleControls[MAG_TO_GRAD_LINK]->setVisible(m_bLinkMAGtoGRAD);
481 }
482}
483
484//=============================================================================================================
485
486void ScalingView::createScaleControls()
487{
488 //MAG
489 if(m_qMapChScaling.contains(FIFF_UNIT_T) && (m_lChannelTypesToShow.contains("mag") || m_lChannelTypesToShow.contains("all")))
490 {
491 QPointer<ScaleControl> pControlMAG = QPointer<ScaleControl>(new ScaleControl("MAG [pT])"));
492 pControlMAG->setRange(0.2f, 20.0f);
493 pControlMAG->setMaxSensitivityPoint(1.5);
494 pControlMAG->setValue(1.5f);
495 pControlMAG->setSensitivity(0.7f);
496 pControlMAG->invertSlider(true);
497 connect(pControlMAG, &ScaleControl::valueChanged, this, &ScalingView::updateMAGScale);
498 m_qMapScaleControls.insert(FIFF_UNIT_T, pControlMAG);
499 }
500
501 //GRAD
502 if(m_qMapChScaling.contains(FIFF_UNIT_T_M) && (m_lChannelTypesToShow.contains("grad") || m_lChannelTypesToShow.contains("all")))
503 {
504 QPointer<ScaleControl> pControlGRAD = QPointer<ScaleControl>(new ScaleControl("GRAD [fT/cm]"));
505 pControlGRAD->setRange(30.0f, 5000.0f);
506 pControlGRAD->setMaxSensitivityPoint(100.0f);
507 pControlGRAD->setValue(240.0f);
508 pControlGRAD->setSensitivity(0.7f);
509 pControlGRAD->invertSlider(true);
510 connect(pControlGRAD, &ScaleControl::valueChanged, this, &ScalingView::updateGRADScale);
511 m_qMapScaleControls.insert(FIFF_UNIT_T_M, pControlGRAD);
512 }
513
514 //MAGtoGRADlink only if we have Mags and Grads to link
515 if(m_qMapScaleControls.contains(FIFF_UNIT_T) && m_qMapScaleControls.contains(FIFF_UNIT_T_M))
516 {
517 QPointer<ScaleControl> pControlMAGtoGRADlink = QPointer<ScaleControl>(new ScaleControl("MAG-GRAD link [cm]"));
518 pControlMAGtoGRADlink->setRange(0.10f, 8.0f);
519 pControlMAGtoGRADlink->setMaxSensitivityPoint(2.0f);
520 pControlMAGtoGRADlink->setValue(2.0f);
521 pControlMAGtoGRADlink->setSensitivity(0.7f);
522 connect(pControlMAGtoGRADlink, &ScaleControl::valueChanged, this, &ScalingView::updateMAGtoGRADlink);
523 pControlMAGtoGRADlink->setVisible(m_bLinkMAGtoGRAD);
524 m_qMapScaleControls.insert(MAG_TO_GRAD_LINK,pControlMAGtoGRADlink);
525 }
526
527 //EEG
528 if(m_qMapChScaling.contains(FIFFV_EEG_CH) && (m_lChannelTypesToShow.contains("eeg") || m_lChannelTypesToShow.contains("all")))
529 {
530 QPointer<ScaleControl> pControlEEG = QPointer<ScaleControl>(new ScaleControl("EEG [uV]"));
531 pControlEEG->setRange(3.0f, 100.0f);
532 pControlEEG->setMaxSensitivityPoint(14.0f);
533 pControlEEG->setValue(14.0f);
534 pControlEEG->setSensitivity(0.4f);
535 pControlEEG->invertSlider(true);
536 connect(pControlEEG, &ScaleControl::valueChanged, this, &ScalingView::updateEEGScale);
537 m_qMapScaleControls.insert(FIFFV_EEG_CH, pControlEEG);
538 }
539
540 //EOG
541 if(m_qMapChScaling.contains(FIFFV_EOG_CH) && (m_lChannelTypesToShow.contains("eog") || m_lChannelTypesToShow.contains("all")))
542 {
543 QPointer<ScaleControl> pControlEOG = QPointer<ScaleControl>(new ScaleControl("EOG [uV]"));
544 pControlEOG->setRange(3.0f, 100.0f);
545 pControlEOG->setMaxSensitivityPoint(14.0f);
546 pControlEOG->setValue(14.0f);
547 pControlEOG->setSensitivity(0.4f);
548 pControlEOG->invertSlider(true);
549 connect(pControlEOG, &ScaleControl::valueChanged, this, &ScalingView::updateEOGScale);
550 m_qMapScaleControls.insert(FIFFV_EOG_CH, pControlEOG);
551 }
552
553 //ECG
554 if(m_qMapChScaling.contains(FIFFV_ECG_CH) && (m_lChannelTypesToShow.contains("ecg") || m_lChannelTypesToShow.contains("all")))
555 {
556 QPointer<ScaleControl> pControlECG = QPointer<ScaleControl>(new ScaleControl("ECG [uV]"));
557 pControlECG->setRange(3.0f, 100.0f);
558 pControlECG->setMaxSensitivityPoint(14.0f);
559 pControlECG->setValue(14.0f);
560 pControlECG->setSensitivity(0.4f);
561 pControlECG->invertSlider(true);
562 connect(pControlECG, &ScaleControl::valueChanged, this, &ScalingView::updateECGScale);
563 m_qMapScaleControls.insert(FIFFV_ECG_CH, pControlECG);
564 }
565
566 //STIM
567 if(m_qMapChScaling.contains(FIFFV_STIM_CH) && (m_lChannelTypesToShow.contains("stim") || m_lChannelTypesToShow.contains("all")))
568 {
569 QPointer<ScaleControl> pControlSTIM = QPointer<ScaleControl>(new ScaleControl("STIM"));
570 pControlSTIM->setRange(1.0f, 99999.0f);
571 pControlSTIM->setMaxSensitivityPoint(5000.0f);
572 pControlSTIM->setValue(5000.0f);
573 pControlSTIM->setSensitivity(0.8f);
574 pControlSTIM->invertSlider(true);
575 connect(pControlSTIM, &ScaleControl::valueChanged, this, &ScalingView::updateSTIMScale);
576 m_qMapScaleControls.insert(FIFFV_STIM_CH, pControlSTIM);
577 }
578
579 //MISC
580 if(m_qMapChScaling.contains(FIFFV_MISC_CH) && (m_lChannelTypesToShow.contains("misc") || m_lChannelTypesToShow.contains("all")))
581 {
582 QPointer<ScaleControl> pControlMISC = QPointer<ScaleControl>(new ScaleControl("MISC"));
583 pControlMISC->setRange(3.0f, 100.0f);
584 pControlMISC->setMaxSensitivityPoint(14.0f);
585 pControlMISC->setValue(14.0f);
586 pControlMISC->setSensitivity(0.4f);
587 pControlMISC->invertSlider(true);
588 connect(pControlMISC, &ScaleControl::valueChanged, this, &ScalingView::updateMISCScale);
589 m_qMapScaleControls.insert(FIFFV_MISC_CH, pControlMISC);
590 }
591}
592
593//=============================================================================================================
594
596{
597
598}
599
600//=============================================================================================================
601
602void ScalingView::createLinkMagGradCheckBox()
603{
604 m_pCheckBox = QPointer<QCheckBox>(new QCheckBox("Link MAGs -> GRADs"));
605 m_pCheckBox->setChecked(m_bLinkMAGtoGRAD);
606 connect(m_pCheckBox, &QCheckBox::stateChanged, this, &ScalingView::setMagGradLink);
607 m_pUi->verticalLayout->addWidget(m_pCheckBox);
608}
Declaration of the ScalingView Class.
DISPSHARED_EXPORT float getScalingValue(const QMap< qint32, float > &qMapChScaling, int iChannelKind, int iChannelUnit)
DISPSHARED_EXPORT float getDefaultScalingValue(int iChannelKind, int iChannelUnit)
Declaration of the ScaleControl Class.
Fiff constants.
#define FIFFV_REF_MEG_CH
The AbstractView class provides the base calss for all Disp viewers.
The ScaleControl class packs together a QLabel, a DoubleSpinbox and a Slider with the necessary facil...
void valueChanged(double dScale)
void setMagGradLink(int l)
void scalingChanged(const QMap< qint32, float > &scalingMap)
void saveSettings() override
void loadSettings() override
void clearView() override
ScalingView(const QString &sSettingsPath="", QWidget *parent=0, Qt::WindowFlags f=Qt::Widget, const QStringList &lChannelsToShow=QStringList()<< "all")
void setScaleMap(const QMap< qint32, float > &qMapChScaling)
QMap< qint32, float > getScaleMap() const