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