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