MNE-CPP 0.1.9
A Framework for Electrophysiology
Loading...
Searching...
No Matches
frequencyspectrumdelegate.cpp
Go to the documentation of this file.
1//=============================================================================================================
36//=============================================================================================================
37// INCLUDES
38//=============================================================================================================
39
41
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
58using namespace DISPLIB;
59using namespace Eigen;
60
61//=============================================================================================================
62// DEFINE MEMBER METHODS
63//=============================================================================================================
64
65FrequencySpectrumDelegate::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
88void 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
172QSize 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
194void 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
212void 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
308void 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
354void 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
407void 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
Declaration of the FrequencySpectrumModel Class.
Declaration of the FrequencySpectrumDelegate Class.
FiffInfo class declaration.
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
void rcvMouseLoc(int row, int x, int y, QRect visRect)
FrequencySpectrumDelegate(QTableView *m_pTableView, QObject *parent=0)
virtual void paint(QPainter *painter, 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
Eigen::RowVectorXd getFreqScaleBound() const
Eigen::RowVectorXd getFreqScale() const