MNE-CPP  0.1.9
A Framework for Electrophysiology
frequencyspectrumdelegate.cpp
Go to the documentation of this file.
1 //=============================================================================================================
36 //=============================================================================================================
37 // INCLUDES
38 //=============================================================================================================
39 
41 
42 #include "frequencyspectrummodel.h"
43 
44 #include <fiff/fiff_info.h>
45 
46 //=============================================================================================================
47 // QT INCLUDES
48 //=============================================================================================================
49 
50 #include <QPainter>
51 #include <QTableView>
52 #include <QPainterPath>
53 
54 //=============================================================================================================
55 // USED NAMESPACES
56 //=============================================================================================================
57 
58 using namespace DISPLIB;
59 using namespace Eigen;
60 
61 //=============================================================================================================
62 // DEFINE MEMBER METHODS
63 //=============================================================================================================
64 
65 FrequencySpectrumDelegate::FrequencySpectrumDelegate(QTableView* m_pTableView,QObject *parent)
66 : QAbstractItemDelegate(parent)
67 , m_iScaleType(0)
68 , m_fMaxValue(0.0)
69 , m_fScaleY(0.0)
70 , m_tableview_row(0)
71 , m_mousex(0)
72 , m_mousey(0)
73 , m_x_rate(0.0)
74 {
75  m_tableview = m_pTableView;
76  m_tableview->setMouseTracking(true);
77 }
78 
79 //=============================================================================================================
80 
82 {
83  m_iScaleType = ScaleType;
84 }
85 
86 //=============================================================================================================
87 
88 void FrequencySpectrumDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
89 {
90  float t_fPlotHeight = option.rect.height();
91  switch(index.column()) {
92  case 0: { //chnames
93  painter->save();
94 
95  painter->rotate(-90);
96  painter->drawText(QRectF(-option.rect.y()-t_fPlotHeight,0,t_fPlotHeight,20),Qt::AlignCenter,index.model()->data(index,Qt::DisplayRole).toString());
97 
98  painter->restore();
99  break;
100  }
101  case 1: { //data plot
102  painter->save();
103 
104  //draw special background when channel is marked as bad
105 // QVariant v = index.model()->data(index,Qt::BackgroundRole);
106 // if(v.canConvert<QBrush>() && !(option.state & QStyle::State_Selected)) {
107 // QPointF oldBO = painter->brushOrigin();
108 // painter->setBrushOrigin(option.rect.topLeft());
109 // painter->fillRect(option.rect, qvariant_cast<QBrush>(v));
110 // painter->setBrushOrigin(oldBO);
111 // }
112 
113 // //Highlight selected channels
114 // if(option.state & QStyle::State_Selected) {
115 // QPointF oldBO = painter->brushOrigin();
116 // painter->setBrushOrigin(option.rect.topLeft());
117 // painter->fillRect(option.rect, option.palette.highlight());
118 // painter->setBrushOrigin(oldBO);
119 // }
120 
121  //Get data
122  QVariant variant = index.model()->data(index,Qt::DisplayRole);
123  RowVectorXd data = variant.value< RowVectorXd >();
124 
125  const FrequencySpectrumModel* t_pModel = static_cast<const FrequencySpectrumModel*>(index.model());
126 
127  if(data.size() > 0)
128  {
129  QPainterPath path(QPointF(option.rect.x(),option.rect.y()));//QPointF(option.rect.x()+t_rtmsaModel->relFiffCursor()-1,option.rect.y()));
130 
131  //Plot grid
132  painter->setRenderHint(QPainter::Antialiasing, false);
133  createGridPath(index, option, path, data);
134  createGridTick(index, option, painter);
135 
136  //capture the mouse
137  capturePoint(index, option, path, data, painter);
138 
139  painter->save();
140  QPen pen;
141  pen.setStyle(Qt::DotLine);
142  pen.setWidthF(0.5);
143  painter->setPen(pen);
144  painter->drawPath(path);
145  painter->restore();
146 
147  //Plot data path
148  path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));//QPointF(option.rect.x()+t_rtmsaModel->relFiffCursor(),option.rect.y()));
149 
150  createPlotPath(index, option, path, data);
151 
152  painter->save();
153  painter->translate(0,t_fPlotHeight/2);
154  painter->setRenderHint(QPainter::Antialiasing, true);
155 
156  if(option.state & QStyle::State_Selected)
157  painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkRed : Qt::red, 1, Qt::SolidLine));
158  else
159  painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkGray : Qt::darkBlue, 1, Qt::SolidLine));
160 
161  painter->drawPath(path);
162  painter->restore();
163  }
164  painter->restore();
165  break;
166  }
167  }
168 }
169 
170 //=============================================================================================================
171 
172 QSize FrequencySpectrumDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
173 {
174  QSize size;
175 
176  switch(index.column()) {
177  case 0:
178  size = QSize(20,option.rect.height());
179  break;
180  case 1:
181  RowVectorXd data = index.model()->data(index).value< RowVectorXd >();
182 // qint32 nsamples = (static_cast<const FrequencySpectrumModel*>(index.model()))->lastSample()-(static_cast<const FrequencySpectrumModel*>(index.model()))->firstSample();
183 
184 // size = QSize(nsamples*m_dDx,m_dPlotHeight);
185  Q_UNUSED(option);
186  break;
187  }
188 
189  return size;
190 }
191 
192 //=============================================================================================================
193 
194 void FrequencySpectrumDelegate::rcvMouseLoc(int tableview_row, int mousex, int mousey, QRect visRect)
195 {
196 
197  if(mousex != m_mousex){
198 
199  m_tableview_row = tableview_row;
200  m_mousex = mousex;
201  m_mousey = mousey;
202  m_visRect = visRect;
203 
204  m_x_rate = (float)m_mousex/(float)m_visRect.width();
205 
206  m_tableview->viewport()->repaint();
207  }
208 }
209 
210 //=============================================================================================================
211 
212 void FrequencySpectrumDelegate::capturePoint(const QModelIndex &index, const QStyleOptionViewItem &option, QPainterPath& path, RowVectorXd& data, QPainter *painter) const
213 {
214  Q_UNUSED(option);
215  Q_UNUSED(path);
216 
217  if (m_tableview_row == index.row()){
218  const FrequencySpectrumModel* t_pModel = static_cast<const FrequencySpectrumModel*>(index.model());
219 
220  qint32 i;
221 
222  RowVectorXd org_vecFreqScale = t_pModel->getFreqScale();
223  RowVectorXd vecFreqScale = t_pModel->getFreqScaleBound();
224 
225  qint32 lowerIdx = t_pModel->getLowerFrqBound();
226  qint32 upperIdx = t_pModel->getUpperFrqBound();
227 
228  //qint32 numbins = vecFreqScale.size();// data.size();
229 
230  //qDebug() << "numbins" << numbins;
231  //qDebug() << "lowerIdx" << lowerIdx << "upperIdx" << upperIdx;
232 
233  // find the index for the current mouse cursor location
234  for(i = lowerIdx+1; i <= upperIdx; ++i) {
235 
236  //float tmp_rate = t_pModel->getFreqScale()[i]/t_pModel->getFreqScale()[numbins-1];
237 
238  float tmp_rate = (vecFreqScale[i] - vecFreqScale[lowerIdx])/(vecFreqScale[upperIdx]-vecFreqScale[lowerIdx]);
239 
240  if (tmp_rate > m_x_rate) { break;}
241  //qDebug()<<"tmp_rate"<<tmp_rate<<"m_x_rate"<<m_x_rate<<"i"<<i;
242  }
243 
244  /***************************************************
245  * Mouse moving showing the frequency and value
246  *
247  * *************************************************/
248 
249  unsigned short usPosY = m_visRect.bottom();
250  unsigned short usPosX = m_visRect.left();
251  unsigned short usHeight = m_visRect.height();
252  unsigned short usWidth = m_visRect.width();
253 
254  int iPosX = m_mousex;
255  int iPosY = m_mousey;
256 
257  if(iPosX>usPosX && iPosX < usPosX+usWidth && iPosY > (usPosY - usHeight) && iPosY < usPosY )
258  {
259  //qDebug()<<" index row" << index.row()<< "i"<< i << "iPosX,iposY" << iPosX << iPosY << "usPosY"<<usPosY<<"usHeight"<<usHeight;
260  //Horizontal line
261  painter->setPen(QPen(Qt::gray, 1, Qt::DashLine));
262 
263  QPoint start(iPosX - 25, iPosY);//iStartY-5);//paint measure line vertical direction
264  QPoint end(iPosX + 25, iPosY);//iStartY+5);
265 
266 // painter->drawLine(start, end);
267 
268  //vertical line
269  start.setX(iPosX); start.setY(usPosY -usHeight); // iPosY - 25);//iStartY - 5);
270  end.setX(iPosX); end.setY(usPosY); //iPosY + 25);//iStartY + 5);
271  painter->drawLine(start, end);
272  // Draw text
273  painter->setPen(QPen(Qt::black, 1, Qt::SolidLine));
274 
275  // cal the frequency according to the iPosX
276  double fs = t_pModel->getInfo()->sfreq/2;
277 
278  //RowVectorXd vecFreqScale = t_pModel->getFreqScale();
279  //RowVectorXd vecFreqScale = t_pModel->getFreqScaleBound();
280  double freq;
281  if (m_iScaleType) // log
282  {
283  double max = log10(fs+1);
284  org_vecFreqScale *= max;
285 
286  freq = pow(10,org_vecFreqScale[i]) - 1;
287  }
288  else //normal
289  {
290  org_vecFreqScale *= fs;
291 
292  freq = org_vecFreqScale[i];
293 
294  }
295 
296  QString tx = QString("%1 [DB], %2 [Hz]").arg(data[i]).arg(freq);
297 
298  if (iPosX > usPosX + usWidth - tx.size()*8 )
299  painter->drawText(iPosX-tx.size()*8, iPosY-8, tx);// ToDo Precision should be part of preferences
300  else
301  painter->drawText(iPosX+8, iPosY-8, tx);// ToDo Precision should be part of preferences
302  }
303  }//correct row to plot
304 }
305 
306 //=============================================================================================================
307 
308 void FrequencySpectrumDelegate::createPlotPath(const QModelIndex &index, const QStyleOptionViewItem &option, QPainterPath& path, RowVectorXd& data) const
309 {
310  const FrequencySpectrumModel* t_pModel = static_cast<const FrequencySpectrumModel*>(index.model());
311 
312  float fMaxValue = data.maxCoeff();
313 
314  float fValue;
315  float fScaleY = option.rect.height()/(fMaxValue*0.5);
316 
317  float y_base = path.currentPosition().y();
318  QPointF qSamplePosition;
319 
320  qint32 lowerIdx = t_pModel->getLowerFrqBound();
321  qint32 upperIdx = t_pModel->getUpperFrqBound();
322 
323  //Move to initial starting point
324  if(data.size() > 0)
325  {
326  float val = 0;
327  fValue = val*fScaleY;
328 
329  float newY = y_base+fValue;
330 
331  qSamplePosition.setY(newY);
332  qSamplePosition.setX((double)option.rect.width()*t_pModel->getFreqScaleBound()[lowerIdx]);
333 
334  path.moveTo(qSamplePosition);
335  }
336 
337  //create lines from one to the next sample
338  qint32 i;
339  for(i = lowerIdx+1; i <= upperIdx; ++i) {
340  float val = data[i]-data[0]; //remove first sample data[0] as offset
341  fValue = val*fScaleY;
342 
343  float newY = y_base+fValue;
344 
345  qSamplePosition.setY(newY);
346  qSamplePosition.setX((double)option.rect.width()*t_pModel->getFreqScaleBound()[i]);
347 
348  path.lineTo(qSamplePosition);
349  }
350 }
351 
352 //=============================================================================================================
353 
354 void FrequencySpectrumDelegate::createGridPath(const QModelIndex &index, const QStyleOptionViewItem &option, QPainterPath& path, RowVectorXd& data) const
355 {
356  Q_UNUSED(data)
357 
358  const FrequencySpectrumModel* t_pModel = static_cast<const FrequencySpectrumModel*>(index.model());
359 
360  if(t_pModel->getInfo())
361  {
362  double nf = t_pModel->getInfo()->sfreq/2;
363 
364  qint32 numLines = (m_iScaleType)? (qint32)ceil(log10(nf)) : 5 ;
365 
366  QList<qint32> qListLineSamples;
367 
368  qListLineSamples << 0;
369 
370  if (m_iScaleType)
371  { // log
372  for(qint32 lineIdx = 0; lineIdx < numLines; ++lineIdx)
373  {
374  double val = pow(10,lineIdx);
375  qint32 idx = (qint32)floor(val / ((float)nf/(float)t_pModel->getNumStems()));
376  qListLineSamples.append(idx);
377  }
378  }
379  else{ // normal
380  for(qint32 lineIdx = 1; lineIdx < numLines; ++lineIdx)
381  {
382  double val = lineIdx*(nf/numLines);
383  qint32 idx = (qint32)floor(val / ((float)nf/(float)t_pModel->getNumStems()));
384  qListLineSamples.append(idx);
385  }
386 
387  }
388  //vertical lines
389  float yStart = option.rect.topLeft().y();
390 
391  float yEnd = option.rect.bottomRight().y();
392 
393  for(qint32 i = 0; i < qListLineSamples.size(); ++i) {
394  if(qListLineSamples[i] > t_pModel->getLowerFrqBound() && qListLineSamples[i] < t_pModel->getUpperFrqBound())
395  {
396  float x = (t_pModel->getFreqScaleBound()[qListLineSamples[i]])*option.rect.width();
397  path.moveTo(x,yStart);
398  path.lineTo(x,yEnd);
399  }
400  }
401 
402  }
403 }
404 
405 //=============================================================================================================
406 
407 void FrequencySpectrumDelegate::createGridTick(const QModelIndex &index, const QStyleOptionViewItem &option, QPainter *painter) const
408 {
409  const FrequencySpectrumModel* t_pModel = static_cast<const FrequencySpectrumModel*>(index.model());
410 
411  if(t_pModel->getInfo())
412  {
413  double nf = t_pModel->getInfo()->sfreq/2;
414 
415  qint32 numLines = (m_iScaleType)? (qint32)ceil(log10(nf)) : 5 ;
416 
417  QList<qint32> qListLineSamples;
418 
419  qListLineSamples << 0;
420  if (m_iScaleType)
421  { // log
422  for(qint32 lineIdx = 0; lineIdx < numLines; ++lineIdx)
423  {
424  double val = pow(10,lineIdx);
425  qint32 idx = (qint32)floor(val / ((float)nf/(float)t_pModel->getNumStems()));
426  qListLineSamples.append(idx);
427  }
428  }
429  else
430  { // normal
431  for(qint32 lineIdx = 1; lineIdx < numLines; ++lineIdx)
432  {
433  double val = lineIdx*(nf/numLines);
434  qint32 idx = (qint32)floor(val / ((float)nf/(float)t_pModel->getNumStems()));
435  qListLineSamples.append(idx);
436  }
437 
438  }
439 
440  // XTick
441  float yStart = 1.0*option.rect.topLeft().y();
442 
443  if(qListLineSamples[0] > t_pModel->getLowerFrqBound() && qListLineSamples[0] < t_pModel->getUpperFrqBound())
444  {
445  double val = 0.0;
446  float x = (t_pModel->getFreqScaleBound()[qListLineSamples[0]])*option.rect.width();
447  painter->drawText(x,yStart,QString("%1Hz").arg(val));
448  }
449 
450  for(qint32 i = 1; i < qListLineSamples.size(); ++i) {
451  if(qListLineSamples[i] > t_pModel->getLowerFrqBound() && qListLineSamples[i] < t_pModel->getUpperFrqBound())
452  {
453  double val = (m_iScaleType)? pow(10,i-1) : t_pModel->getFreqScaleBound()[qListLineSamples[i]]*nf;
454  float x = (t_pModel->getFreqScaleBound()[qListLineSamples[i]])*option.rect.width();
455  painter->drawText(x,yStart,QString("%1Hz").arg(val));
456  }
457  }
458 
459  // YTick
460  }
461 }
462 
Eigen::RowVectorXd getFreqScaleBound() const
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
The FrequencySpectrumModel class implements the data access model for a real-time multi sample array ...
QSharedPointer< FIFFLIB::FiffInfo > getInfo() const
void rcvMouseLoc(int row, int x, int y, QRect visRect)
Eigen::RowVectorXd getFreqScale() const
Declaration of the FrequencySpectrumDelegate Class.
FiffInfo class declaration.
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
FrequencySpectrumDelegate(QTableView *m_pTableView, QObject *parent=0)
Declaration of the FrequencySpectrumModel Class.