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