MNE-CPP  beta 1.0
realtimesamplearraywidget.cpp
Go to the documentation of this file.
1 //=============================================================================================================
36 //ToDo Paint to render area
37 
38 //*************************************************************************************************************
39 //=============================================================================================================
40 // INCLUDES
41 //=============================================================================================================
42 
44 //#include "annotationwindow.h"
45 
47 #include "iostream"
48 
49 
50 //*************************************************************************************************************
51 //=============================================================================================================
52 // STL INCLUDES
53 //=============================================================================================================
54 
55 #include <math.h>
56 
57 
58 //*************************************************************************************************************
59 //=============================================================================================================
60 // QT INCLUDES
61 //=============================================================================================================
62 
63 #include <QPaintEvent>
64 #include <QPainter>
65 #include <QTimer>
66 #include <QTime>
67 
68 #include <QDebug>
69 
70 
71 //*************************************************************************************************************
72 //=============================================================================================================
73 // USED NAMESPACES
74 //=============================================================================================================
75 
76 using namespace XDISPLIB;
77 using namespace XMEASLIB;
78 
79 
80 //*************************************************************************************************************
81 //=============================================================================================================
82 // DEFINE MEMBER METHODS
83 //=============================================================================================================
84 
85 RealTimeSampleArrayWidget::RealTimeSampleArrayWidget(QSharedPointer<NewRealTimeSampleArray> &pRTSA, QSharedPointer<QTime> &pTime, QWidget* parent)
86 : NewMeasurementWidget(parent)
87 , m_pRTSA(pRTSA)
88 , m_bMeasurement(false)
89 , m_bPosition(true)
90 , m_bFrozen(false)
91 , m_bScaling(false)
92 , m_bToolInUse(false)
93 , m_dSampleWidth(1.0)
94 , m_dPosX(0.0)
95 , m_dPosY(0)
96 , m_bStartFlag(true)
97 , m_ucToolIndex(0)
98 , m_pTimerToolDisplay(0)
99 , m_pTimerUpdate(new QTimer(this))
100 , m_pTime(pTime)
101 , m_pTimeCurrentDisplay(0)
102 {
103  ui.setupUi(this);
104  ui.m_qLabel_Tool->hide();
105 
106  // Add tool names to vector
107  m_vecTool.push_back("Freeze");
108  m_vecTool.push_back("Annotation");
109 
110  // Start timer
111  connect(m_pTimerUpdate.data(), SIGNAL(timeout()), this, SLOT(update())); //ToDo Qt5 syntax
112 
113  m_pTimerUpdate->start(25);
114 
115  //connect(ui.m_qSpinBox_Max, SIGNAL(valueChanged(int)), this, SLOT(maxValueChanged(int)));
116  //connect(ui.m_qSpinBox_Min, SIGNAL(valueChanged(int)), this, SLOT(minValueChanged(int)));
117 
118  setMouseTracking(true);
119 }
120 
121 
122 //*************************************************************************************************************
123 
125 {
126 // qDebug() << "NewRealTimeSampleArrayWidget deleted";
127  // Clear sampling rate vector
128  RealTimeSampleArrayWidget::s_listSamplingRates.clear();
129 }
130 
131 
132 //*************************************************************************************************************
133 
134 void RealTimeSampleArrayWidget::actualize()
135 {
136  m_dPosY = ui.m_qFrame->pos().y()+0.5*ui.m_qFrame->height();
137 
138 
139  // Compute scaling factor
140  m_fScaleFactor = ui.m_qFrame->height()/static_cast<float>(m_pRTSA->getMaxValue()-m_pRTSA->getMinValue());
141 
142  // Compute the middle of RTSA values
143  m_dMiddle = 0.5*(m_pRTSA->getMinValue()+m_pRTSA->getMaxValue())*m_fScaleFactor;
144 
145  //*********************************************************************************************************
146  //=========================================================================================================
147  // Compute new sample width in order to synchronize all RTSA
148  //=========================================================================================================
149 
150 // if((m_pRTSA->getSamplingRate() == 0) || (DisplayManager::getRTSAWidgets().size() == 0))
151 // return;
152 
153  if((m_pRTSA->getSamplingRate() == 0))
154  return;
155 
156  // Add current sampling rate to s_listSamplingRates
157  RealTimeSampleArrayWidget::s_listSamplingRates << m_pRTSA->getSamplingRate();
158 
159  // Find maximal sampling rate in s_listSamplingRates
160  double dMax = 0;
161  foreach (double value, s_listSamplingRates)
162  dMax = value > dMax ? value : dMax;
163 
164 // // Set new sample widths
165 // foreach(NewRealTimeSampleArrayWidget* pRTSAW, DisplayManager::getRTSAWidgets().values())
166 // pRTSAW->m_dSampleWidth = dMax/pRTSAW->m_pRTSA->getSamplingRate();
167 }
168 
169 
170 //*************************************************************************************************************
171 
172 void RealTimeSampleArrayWidget::stopAnnotation()
173 {
174  m_bToolInUse = !m_bToolInUse;
175 }
176 
177 
178 //*************************************************************************************************************
179 
180 void RealTimeSampleArrayWidget::maxValueChanged(double maxValue)
181 {
182  m_pRTSA->setMaxValue(maxValue);
183 // ui.m_qLabel_MaxValue->setText(QString::number(maxValue));
184  actualize();
185 }
186 
187 
188 //*************************************************************************************************************
189 
190 void RealTimeSampleArrayWidget::minValueChanged(double minValue)
191 {
192  m_pRTSA->setMinValue(minValue);
193 // ui.m_qLabel_MinValue->setText(QString::number(minValue));
194  actualize();
195 }
196 
197 
198 //*************************************************************************************************************
199 
201 {
202  if(m_pRTSA->getSampleArray().size() > 0)
203  {
204  double dValue = 0;
205  double dPositionDifference = 0.0;
206  QVector<double> vecSamples = m_pRTSA->getSampleArray();
207  for(unsigned char i = 0; i < vecSamples.size(); ++i)
208  {
209  dValue = vecSamples[i]*m_fScaleFactor - m_dMiddle;
210  dPositionDifference = m_dPosition - (m_dPosX+ui.m_qFrame->width());
211 
212  if((dPositionDifference >= 0) || m_bStartFlag)
213  {
214  if(m_bStartFlag)
215  dPositionDifference = 0;
216 
217  m_qMutex.lock();
218  m_qPainterPath = QPainterPath();
219  m_dPosition = m_dPosX + dPositionDifference;
220  m_qPainterPath.moveTo(m_dPosition, m_dPosY-dValue);
221  m_qMutex.unlock();
222  m_bStartFlag = false;
223 
224  if(!m_bFrozen)
225  m_pTimeCurrentDisplay->setHMS(m_pTime->hour(),m_pTime->minute(),m_pTime->second(),m_pTime->msec());
226  }
227  else
228  {
229  m_qMutex.lock();
230  m_qPainterPath.lineTo(m_dPosition, m_dPosY-dValue);
231  m_qMutex.unlock();
232  }
233 
234  m_dPosition = m_dPosition + m_dSampleWidth;
235  }
236  }
237  else
238  qWarning() << "NewRealTimeSampleArrayWidget::update; getArraySize():" << m_pRTSA->getArraySize() << "getSampleArray():" << m_pRTSA->getSampleArray().size();
239 }
240 
241 
242 //*************************************************************************************************************
243 
245 {
246  ui.m_qLabel_Caption->setText(m_pRTSA->getName());
247 // ui.m_qLabel_MinValue->setText(QString::number(m_pRTSA->getMinValue()));
248 // ui.m_qLabel_MaxValue->setText(QString::number(m_pRTSA->getMaxValue()));
249 
250  m_dMinValue_init = m_pRTSA->getMinValue();
251  m_dMaxValue_init = m_pRTSA->getMaxValue();
252 
253 
254  // Set drawing start position in X and Y direction
255  m_dPosX = ui.m_qFrame->pos().x()+1;
256  m_dPosition = m_dPosX;
257 // m_dPosY = ui.m_qFrame->pos().y()+0.5*ui.m_qFrame->height();// set to actualize
258 
259  m_qPainterPath = QPainterPath();
260  m_bStartFlag = true;
261 
262  m_pTimeCurrentDisplay = QSharedPointer<QTime>(new QTime(0, 0));
263 
264  actualize();
265 }
266 
267 
268 //*************************************************************************************************************
269 
271 {
272  QPainter painter(this);
273 
274 
275 // //*************************************************************************************************************
276 // //=============================================================================================================
277 // // Draw white background
278 // //=============================================================================================================
279 //
280 // painter.setBrush(Qt::white);
281 // painter.drawRect(0, 0, width(), height());
282 
283 
284  painter.setPen(QPen(Qt::gray, 1, Qt::DashLine));
285 
286  //*************************************************************************************************************
287  //=============================================================================================================
288  // Draw grid in X direction (each 100ms)
289  //=============================================================================================================
290 
291  double dNumPixelsX = m_pRTSA->getSamplingRate()/10.0f;
292  double dMinMaxDifference = static_cast<double>(m_pRTSA->getMaxValue()-m_pRTSA->getMinValue());
293  double dActualPosX = 0.0;
294  unsigned short usNumOfGridsX = (unsigned short)(ui.m_qFrame->width()/dNumPixelsX);
295  unsigned short usPosY = ui.m_qFrame->pos().y()+1;
296  unsigned short usPosX = ui.m_qFrame->pos().x()+1;
297  unsigned short usHeight = ui.m_qFrame->height()-2;
298  unsigned short usWidth = ui.m_qFrame->width()-2;
299 
300  for(unsigned short i = 1; i <= usNumOfGridsX; ++i)
301  {
302  dActualPosX = m_dPosX+i*dNumPixelsX;
303  painter.drawLine((int)dActualPosX, usPosY, (int)dActualPosX, usPosY+usHeight);
304  }
305 
306 
307  //*************************************************************************************************************
308  //=============================================================================================================
309  // Draw grid in Y direction
310  //=============================================================================================================
311 
312  double exponent = (int)floor(log10(dMinMaxDifference))-1;//math.h
313  double dim = pow(10.0, exponent);//respectively at 0.001; 0.01, 0.1, 1, 10, 100
314 
315  int NumOfLines = (int)floor(dMinMaxDifference/(dim*5));
316 
317  double dDifferenceToFirstLine = (m_pRTSA->getMaxValue()-floor(m_pRTSA->getMaxValue()/dim)*dim);
318 
319  double dNumPixelsY = usHeight/NumOfLines;//10.0f;
320  double dActualPosY = usPosY + dDifferenceToFirstLine * (usHeight/dMinMaxDifference);
321 
322  for(unsigned char i = 1; i <= NumOfLines; ++i)
323  {
324  painter.drawLine((int)m_dPosX, (int)dActualPosY, usWidth, (int)dActualPosY);
325  dActualPosY += dNumPixelsY;
326  }
327 
328  //Paint middle value
329 // painter.setPen(QPen(Qt::gray, 1, Qt::SolidLine));
330 // painter.drawText(usWidth-75, usHeight/2, tr("%1%2").arg(m_dMiddle, 0, 'f', 2).arg(m_pRTSA->getUnit()));
331 // painter.setPen(QPen(Qt::gray, 1, Qt::DotLine));
332 // painter.drawLine(m_dPosX, usHeight/2, usWidth, usHeight/2);
333 
334  painter.setPen(QPen(Qt::blue, 1, Qt::SolidLine));
335  painter.setRenderHint(QPainter::Antialiasing);
336 
337 
338  //*************************************************************************************************************
339  //=============================================================================================================
340  // Draw real time curve respectively frozen curve
341  //=============================================================================================================
342 
343  if(m_bFrozen)
344  {
345  painter.setPen(QPen(Qt::darkGray, 1, Qt::SolidLine));
346  painter.drawPath(m_qPainterPath_Freeze);
347  }
348  else
349  {
350  m_qMutex.lock();
351  painter.drawPath(m_qPainterPath);
352  m_qMutex.unlock();
353  }
354 
355 
356  //*************************************************************************************************************
357  //=============================================================================================================
358  // Calculates zoom with the help of new minimum/maximum factors.
359  //=============================================================================================================
360 
361  if(m_bScaling)
362  {
363  int iStartX = m_qPointMouseStartPosition.x();
364 
365  int iEndY = m_qPointMouseEndPosition.y();
366  int iStartY = m_qPointMouseStartPosition.y();
367 
368  // Compute pixel difference
369  int iPixelDifferenceY = abs(iStartY - iEndY);
370 
371  double scale = (m_dMaxValue_init-m_dMinValue_init)/usHeight;
372 
373  if(iStartY>iEndY)
374  {
375  double changeValue = scale * iPixelDifferenceY;
376 
377  if(changeValue*2 < m_dMaxValue_init - m_dMinValue_init)
378  {
379  minValueChanged(m_dMinValue_init + changeValue);
380  maxValueChanged(m_dMaxValue_init - changeValue);
381  }
382  else
383  {
384  double maxChange = (m_dMaxValue_init - m_dMinValue_init)*0.499999;
385  minValueChanged(m_dMinValue_init + maxChange);
386  maxValueChanged(m_dMaxValue_init - maxChange);
387  }
388  }
389  else
390  {
391  double changeValue = scale * iPixelDifferenceY*10;
392 
393  minValueChanged(m_dMinValue_init - changeValue);
394  maxValueChanged(m_dMaxValue_init + changeValue);
395  }
396 
397  double factor = (m_dMaxValue_init-m_dMinValue_init)/(m_pRTSA->getMaxValue()-m_pRTSA->getMinValue());
398  // Draw text
399  painter.setPen(QPen(Qt::darkCyan, 1, Qt::SolidLine));
400  painter.drawText(iStartX+8, iEndY, tr("Zoom %1x").arg(factor, 0, 'f', 2));
401 
402  }
403 
404  //*************************************************************************************************************
405  //=============================================================================================================
406  // Draw coordinates at mouse position
407  //=============================================================================================================
408 
409  if(m_bPosition && m_pRTSA->getSamplingRate())
410  {
411  int iPosX = mapFromGlobal(QCursor::pos()).x();
412 
413  int iPosY = mapFromGlobal(QCursor::pos()).y();
414 
415  if(iPosX > usPosX && iPosX < (usPosX + usWidth) && iPosY > usPosY && iPosY < usPosY + usHeight )
416  {
417  //Vertical Measuring
418  painter.setPen(QPen(Qt::gray, 1, Qt::DashLine));
419 
420  QPoint start(usPosX, iPosY);//iStartY-5);//paint measure line vertical direction
421  QPoint end(usPosX + usWidth, iPosY);//iStartY+5);
422 
423  painter.drawLine(start, end);
424 
425  start.setX(iPosX); start.setY(usPosY);//iStartY - 5);
426  end.setX(iPosX); end.setY(usPosY + usHeight);//iStartY + 5);
427  painter.drawLine(start, end);
428 
429  // Compute time between MouseStartPosition and MouseEndPosition
430  QTime t = m_pTimeCurrentDisplay->addMSecs((int)(1000*(iPosX-usPosX)/(float)m_pRTSA->getSamplingRate()));
431  float fAbsMag = m_pRTSA->getMinValue()+(usHeight-(iPosY-usPosY))*(dMinMaxDifference/usHeight);
432 
433  // Draw text
434  painter.setPen(QPen(Qt::darkGray, 1, Qt::SolidLine));
435 
436  painter.drawText(iPosX+8, iPosY-22, tr("%1").arg(t.toString("hh:mm:ss.zzz")));// ToDo Precision should be part of preferences
437  painter.drawText(iPosX+8, iPosY-8, tr("%1%2").arg(fAbsMag, 0, 'e', 3).arg(m_pRTSA->getUnit()));
438  }
439  }
440 
441  //*************************************************************************************************************
442  //=============================================================================================================
443  // Draw the measurement tools of the curve
444  //=============================================================================================================
445 
446  if(m_bMeasurement && m_pRTSA->getSamplingRate())
447  {
448  int iEndX = m_qPointMouseEndPosition.x();
449  int iStartX = m_qPointMouseStartPosition.x();
450 
451  int iEndY = m_qPointMouseEndPosition.y();
452  int iStartY = m_qPointMouseStartPosition.y();
453 
454 
455  // Compute pixel difference
456  double iPixelDifferenceX = abs(iStartX - iEndX);
457  double iPixelDifferenceY = abs(iStartY - iEndY);
458 
459  if(iPixelDifferenceX < 5 && iPixelDifferenceY < 5)
460  return;
461 
462  //Vertical Measuring
463  painter.setPen(QPen(Qt::darkCyan, 1, Qt::DashLine));
464  if(iPixelDifferenceX > iPixelDifferenceY)
465  {
466  // Draw measuring line
467 // QPoint endPosY(iEndX, iStartY);
468 // painter.drawLine(m_qPointMouseStartPosition, endPosY);
469 
470  QPoint start(iStartX, usPosY);//iStartY-5);//paint measure line vertical direction
471  QPoint end(iStartX, usPosY+usHeight);//iStartY+5);
472  painter.drawLine(start, end);
473 
474  start.setX(iEndX); start.setY(usPosY);//iStartY - 5);
475  end.setX(iEndX); end.setY(usPosY+usHeight);//iStartY + 5);
476  painter.drawLine(start, end);
477 
478  // Compute text position
479  if(iEndX > iStartX)
480  iEndX = iEndX + 9;
481  else
482  iEndX = iEndX - 67;
483 
484  // Compute time between MouseStartPosition and MouseEndPosition
485  float iTime = 1000.0f*(float)iPixelDifferenceX/(float)m_pRTSA->getSamplingRate();
486  float iHz = 1000.0f/(float)iTime;
487 
488  // Draw text
489  painter.setPen(QPen(Qt::darkCyan, 1, Qt::SolidLine));
490 
491  painter.drawText(iEndX, iEndY-18, tr("%1ms").arg(iTime, 0, 'f', 2));// ToDo Precision should be part of preferences
492  painter.drawText(iEndX, iEndY-4, tr("%1Hz").arg(iHz, 0, 'f', 2));
493  }
494  else
495  {
496  // Draw measuring line
497 // QPoint endPosX(iStartX, iEndY);
498 // painter.drawLine(endPosX, m_qPointMouseStartPosition);
499 
500  QPoint start(usPosX, iStartY);//iStartY-5);//paint measure line vertical direction
501  QPoint end(usPosX+usWidth, iStartY);//iStartY+5);
502  painter.drawLine(start, end);
503 
504  start.setX(usPosX); start.setY(iEndY);//iStartY - 5);
505  end.setX(usPosX+usWidth); end.setY(iEndY);//iStartY + 5);
506  painter.drawLine(start, end);
507 
508 
509  // Compute text position
510  if(iEndY > iStartY)
511  iEndY = iEndY + 1;
512  else
513  iEndY = iEndY + 23 ;
514 
515  // Compute time between MouseStartPosition and MouseEndPosition
516  float fMagnitude = (float)iPixelDifferenceY * (dMinMaxDifference/usHeight) ;
517 
518  // Draw text
519  painter.setPen(QPen(Qt::darkCyan, 1, Qt::SolidLine));
520  painter.drawText(iEndX+14, iEndY-8, tr("%1%2").arg(fMagnitude, 0, 'e', 3).arg(m_pRTSA->getUnit()));// ToDo Precision should be part of preferences
521  }
522  }
523 }
524 
525 
526 //*************************************************************************************************************
527 
529 {
530  m_bStartFlag = true; //start new painting
531  actualize();
532 }
533 
534 //*************************************************************************************************************
535 
536 void RealTimeSampleArrayWidget::mousePressEvent(QMouseEvent* mouseEvent)
537 {
538  m_qPointMouseStartPosition = m_qPointMouseEndPosition = mouseEvent->pos();
539  if(mouseEvent->button() == Qt::LeftButton)
540  {
541  m_bMeasurement = true;
542  m_bPosition = false;
543  }
544  else if(mouseEvent->button() == Qt::RightButton)
545  {
546  m_bScaling = true;
547  m_bPosition = false;
548  }
549 }
550 
551 
552 //*************************************************************************************************************
553 
554 void RealTimeSampleArrayWidget::mouseMoveEvent(QMouseEvent* mouseEvent)
555 {
556  if(m_bMeasurement || m_bScaling)
557  m_qPointMouseEndPosition = mouseEvent->pos();
558 }
559 
560 
561 //*************************************************************************************************************
562 
564 {
565  m_bMeasurement = false;
566  m_bPosition = true;
567  m_bScaling = false;
568 }
569 
570 
571 //*************************************************************************************************************
572 
574 {
575  switch((Tool)m_ucToolIndex)
576  {
577  case Freeze:
578  m_bFrozen = !m_bFrozen;
579  if(m_bFrozen)
580  m_qPainterPath_Freeze = m_qPainterPath;
581  else
582  m_pTimeCurrentDisplay->setHMS(m_pTime->hour(),m_pTime->minute(),m_pTime->second(),m_pTime->msec());
583  break;
584 
585  case Annotation:
586  break;
587  }
588 
589  m_bToolInUse = !m_bToolInUse;
590 }
591 
592 
593 //*************************************************************************************************************
594 
595 void RealTimeSampleArrayWidget::wheelEvent(QWheelEvent* wheelEvent)
596 {
597  if(m_bToolInUse)
598  return;
599 
600  if(wheelEvent->delta() < 0)
601  {
602  if(m_ucToolIndex == 0)
603  m_ucToolIndex = m_vecTool.size()-1;
604  else
605  --m_ucToolIndex;
606  }
607  else
608  {
609  if(m_ucToolIndex == m_vecTool.size()-1)
610  m_ucToolIndex = 0;
611  else
612  ++m_ucToolIndex;
613  }
614 
615  QString text = QString("%1/%2 Tool: %3").arg(m_ucToolIndex+1).arg(m_vecTool.size()).arg(m_vecTool[m_ucToolIndex]);
616  ui.m_qLabel_Tool->setText(text);
617  ui.m_qLabel_Tool->show();
618 
619  m_pTimerToolDisplay = QSharedPointer<QTimer>(new QTimer(this));
620 
621  connect( m_pTimerToolDisplay.data(), SIGNAL(timeout()), ui.m_qLabel_Tool, SLOT(hide()));
622  m_pTimerToolDisplay->start(2000);
623 }
624 
625 
626 //*************************************************************************************************************
627 //=============================================================================================================
628 // STATIC DEFINITIONS
629 //=============================================================================================================
630 
631 QList<double> RealTimeSampleArrayWidget::s_listSamplingRates;
Free surfer annotation.
Definition: annotation.h:97
virtual void mouseMoveEvent(QMouseEvent *mouseEvent)
virtual void resizeEvent(QResizeEvent *event)
virtual void mousePressEvent(QMouseEvent *mouseEvent)
virtual void update(XMEASLIB::NewMeasurement::SPtr pMeasurement)
virtual void paintEvent(QPaintEvent *event)
Declaration of the RealTimeSampleArrayWidget Class.
Contains the declaration of the NewRealTimeSampleArray class.
QSharedPointer< NewMeasurement > SPtr
virtual void mouseDoubleClickEvent(QMouseEvent *event)
RealTimeSampleArrayWidget(QSharedPointer< NewRealTimeSampleArray > &pRTSA, QSharedPointer< QTime > &pTime, QWidget *parent=0)
The MeasurementWidget class is the base class of all measurement widgets.
virtual void wheelEvent(QWheelEvent *wheelEvent)
virtual void mouseReleaseEvent(QMouseEvent *event)