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