MNE-CPP  0.1.9
A Framework for Electrophysiology
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>
42 #include "helpers/scalecontrol.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 
61 using namespace DISPLIB;
62 using namespace FIFFLIB;
63 
64 //=============================================================================================================
65 // DEFINE GLOBAL DISPLIB METHODS
66 //=============================================================================================================
67 
71 const static float m_fScaleMAG = 1e-12f;
72 const static float m_fScaleGRAD = 1e-15f;
73 const static float m_fScaleEEG = 1e-5f;
74 const static float m_fScaleEOG = 1e-6f;
75 const static float m_fScaleECG = 1e-2f;
76 const static float m_fScaleSTIM = 1e-3f;
77 const static float m_fScaleMISC = 1e-3f;
78 const static float m_fScaleEMG = 1e-3f;
79 const static int MAG_TO_GRAD_LINK = 31337;
80 
81 float 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 
136 float 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 
156 ScalingView::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 
196 void 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 
207 void 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 
218 QMap<qint32,float> ScalingView::getScaleMap() const
219 {
220  return m_qMapChScaling;
221 }
222 
223 //=============================================================================================================
224 
225 void 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 
305 void 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 
317 void 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 
329 void ScalingView::processScalingChange()
330 {
331  emit scalingChanged(m_qMapChScaling);
332  saveSettings();
333 }
334 
335 //=============================================================================================================
336 
337 void ScalingView::updateMAGScale(double dScale)
338 {
339  m_qMapChScaling.insert(FIFF_UNIT_T, dScale * m_fScaleMAG);
340  linkMagToGrad();
341  processScalingChange();
342 }
343 
344 //=============================================================================================================
345 
346 void 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 
358 void 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 
370 void 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 
379 void ScalingView::updateEEGScale(double dScale)
380 {
381  m_qMapChScaling.insert(FIFFV_EEG_CH, dScale * m_fScaleEEG);
382  processScalingChange();
383 }
384 
385 //=============================================================================================================
386 
387 void ScalingView::updateEOGScale(double dScale)
388 {
389  m_qMapChScaling.insert(FIFFV_EOG_CH, dScale * m_fScaleEOG);
390  processScalingChange();
391 }
392 
393 //=============================================================================================================
394 
395 void ScalingView::updateEMGScale(double dScale)
396 {
397  m_qMapChScaling.insert(FIFFV_EMG_CH, dScale * m_fScaleEMG);
398  processScalingChange();
399 }
400 
401 //=============================================================================================================
402 
403 void ScalingView::updateECGScale(double dScale)
404 {
405  m_qMapChScaling.insert(FIFFV_ECG_CH, dScale * m_fScaleECG);
406  processScalingChange();
407 }
408 
409 //=============================================================================================================
410 
411 void ScalingView::updateMISCScale(double dScale)
412 {
413  m_qMapChScaling.insert(FIFFV_MISC_CH, dScale * m_fScaleMISC);
414  processScalingChange();
415 }
416 
417 //=============================================================================================================
418 
419 void ScalingView::updateSTIMScale(double scale)
420 {
421  m_qMapChScaling.insert(FIFFV_STIM_CH, scale * m_fScaleSTIM);
422  processScalingChange();
423 }
424 
425 //=============================================================================================================
426 
427 void ScalingView::updateMAGtoGRADlink(double dScale)
428 {
429  Q_UNUSED(dScale)
430 
431  linkMagToGrad();
432 }
433 
434 //=============================================================================================================
435 
436 void 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 
476 void 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 
486 void 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 
602 void 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 }
DISPSHARED_EXPORT float getDefaultScalingValue(int iChannelKind, int iChannelUnit)
Definition: scalingview.cpp:81
DISPSHARED_EXPORT float getScalingValue(const QMap< qint32, float > &qMapChScaling, int iChannelKind, int iChannelUnit)
Declaration of the ScaleControl Class.
Declaration of the ScalingView Class.
The ScaleControl class packs together a QLabel, a DoubleSpinbox and a Slider with the necessary facil...
Definition: scalecontrol.h:75
void saveSettings() override
void clearView() override
Fiff constants.
Definition: applytoview.h:58
void setScaleMap(const QMap< qint32, float > &qMapChScaling)
ScalingView(const QString &sSettingsPath="", QWidget *parent=0, Qt::WindowFlags f=Qt::Widget, const QStringList &lChannelsToShow=QStringList()<< "all")
QMap< qint32, float > getScaleMap() const
void scalingChanged(const QMap< qint32, float > &scalingMap)
#define FIFFV_REF_MEG_CH
void valueChanged(double dScale)
The AbstractView class provides the base calss for all Disp viewers.
Definition: abstractview.h:75
void loadSettings() override
void setMagGradLink(int l)