MNE-CPP  beta 1.0
realtimemultisamplearraymodel.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 
38 #include <iostream>
39 
40 #include <QDebug>
41 #include <QBrush>
42 #include <QThread>
43 
44 
45 //*************************************************************************************************************
46 //=============================================================================================================
47 // USED NAMESPACES
48 //=============================================================================================================
49 
50 using namespace XDISPLIB;
51 
52 
53 //*************************************************************************************************************
54 //=============================================================================================================
55 // DEFINE MEMBER METHODS
56 //=============================================================================================================
57 
59 : QAbstractTableModel(parent)
60 , m_bProjActivated(false)
61 , m_fSps(1024.0f)
62 , m_iT(10)
63 , m_iDownsampling(10)
64 , m_iMaxSamples(1024)
65 , m_iCurrentSample(0)
66 , m_bIsFreezed(false)
67 {
68 }
69 
70 
71 //*************************************************************************************************************
72 //virtual functions
73 int RealTimeMultiSampleArrayModel::rowCount(const QModelIndex & /*parent*/) const
74 {
75  if(!m_qMapIdxRowSelection.empty())
76  return m_qMapIdxRowSelection.size();
77  else
78  return 0;
79 }
80 
81 
82 //*************************************************************************************************************
83 
84 int RealTimeMultiSampleArrayModel::columnCount(const QModelIndex & /*parent*/) const
85 {
86  return 2;
87 }
88 
89 
90 //*************************************************************************************************************
91 
92 QVariant RealTimeMultiSampleArrayModel::data(const QModelIndex &index, int role) const
93 {
94  if(role != Qt::DisplayRole && role != Qt::BackgroundRole)
95  return QVariant();
96 
97  if (index.isValid()) {
98  qint32 row = m_qMapIdxRowSelection[index.row()];
99 
100  //******** first column (chname) ********
101  if(index.column() == 0 && role == Qt::DisplayRole)
102  return QVariant(m_qListChInfo[row].getChannelName());
103 
104  //******** second column (data plot) ********
105  if(index.column()==1) {
106  QVariant v;
107 
108  switch(role) {
109  case Qt::DisplayRole: {
110  //pack all adjacent (after reload) RowVectorPairs into a QList
111  QList< QVector<float> > qListVector;
112 
113  if(m_bIsFreezed)
114  {
115  // data freeze
116  QVector<float> data;
117  for(qint32 i = 0; i < m_dataCurrentFreeze.size(); ++i)
118  data.append(m_dataCurrentFreeze[i](row));
119  qListVector.append(data);
120 
121  // last data freeze
122  QVector<float> lastData;
123  for(qint32 i=0; i < m_dataLastFreeze.size(); ++i)
124  lastData.append(m_dataLastFreeze[i](row));
125  qListVector.append(lastData);
126 
127  v.setValue(qListVector);
128  }
129  else
130  {
131  // data
132  QVector<float> data;
133  for(qint32 i = 0; i < m_dataCurrent.size(); ++i)
134  data.append(m_dataCurrent[i](row));
135  qListVector.append(data);
136 
137  // last data
138  QVector<float> lastData;
139  for(qint32 i=0; i < m_dataLast.size(); ++i)
140  lastData.append(m_dataLast[i](row));
141  qListVector.append(lastData);
142 
143  v.setValue(qListVector);
144  }
145  return v;
146  break;
147  }
148  case Qt::BackgroundRole: {
149 // if(m_fiffInfo.bads.contains(m_chInfolist[row].ch_name)) {
150 // QBrush brush;
151 // brush.setStyle(Qt::SolidPattern);
152 // // qDebug() << m_chInfolist[row].ch_name << "is marked as bad, index:" << row;
153 // brush.setColor(Qt::red);
154 // return QVariant(brush);
155 // }
156 // else
157  return QVariant();
158 
159  break;
160  }
161  } // end role switch
162  } // end column check
163 
164  } // end index.valid() check
165 
166  return QVariant();
167 }
168 
169 
170 //*************************************************************************************************************
171 
172 QVariant RealTimeMultiSampleArrayModel::headerData(int section, Qt::Orientation orientation, int role) const
173 {
174  if(role != Qt::DisplayRole && role != Qt::TextAlignmentRole)
175  return QVariant();
176 
177  if(orientation == Qt::Horizontal) {
178  switch(section) {
179  case 0: //chname column
180  return QVariant();
181  case 1: //data plot column
182  return QVariant("data plot");
183  switch(role) {
184  case Qt::DisplayRole:
185  return QVariant("data plot");
186  case Qt::TextAlignmentRole:
187  return QVariant(Qt::AlignLeft);
188  }
189  }
190  }
191  else if(orientation == Qt::Vertical) {
192  QModelIndex chname = createIndex(section,0);
193  switch(role) {
194  case Qt::DisplayRole:
195  return QVariant(data(chname).toString());
196  }
197  }
198 
199  return QVariant();
200 }
201 
202 
203 //*************************************************************************************************************
204 
205 void RealTimeMultiSampleArrayModel::setChannelInfo(QList<RealTimeSampleArrayChInfo> &chInfo)
206 {
207  beginResetModel();
208  m_qListChInfo = chInfo;
209  endResetModel();
210 
211  resetSelection();
212 }
213 
214 
215 //*************************************************************************************************************
216 
218 {
219  if(p_pFiffInfo)
220  {
221  RowVectorXi sel;// = RowVectorXi(0,0);
222  QStringList emptyExclude;
223 
224  if(p_pFiffInfo->bads.size() > 0)
225  sel = FiffInfoBase::pick_channels(p_pFiffInfo->ch_names, p_pFiffInfo->bads, emptyExclude);
226 
227  m_vecBadIdcs = sel;
228 
229  this->m_pFiffInfo = p_pFiffInfo;
230 
231  //
232  // Create the initial SSP projector
233  //
235  }
236  else
237  {
238  m_vecBadIdcs = RowVectorXi(0,0);
239  m_matProj = MatrixXd(0,0);
240  }
241 }
242 
243 
244 //*************************************************************************************************************
245 
246 void RealTimeMultiSampleArrayModel::setSamplingInfo(float sps, int T, float dest_sps)
247 {
248  beginResetModel();
249 
250  if(sps > dest_sps)
251  m_iDownsampling = (qint32)ceil(sps/dest_sps);
252  else
253  m_iDownsampling = 1;
254 
255  m_iT = T;
256 
257  float maxSamples = sps * T;
258  m_iMaxSamples = (qint32)ceil(maxSamples/(sps/dest_sps)); // Max Samples / Downsampling
259 
260  endResetModel();
261 }
262 
263 
264 //*************************************************************************************************************
265 
266 void RealTimeMultiSampleArrayModel::addData(const QList<MatrixXd> &data)
267 {
268  //Downsampling ->ToDo make this more accurate
269 
270  for(qint32 b = 0; b < data.size(); ++b)
271  {
272  qint32 i;
273  qint32 count = 0;
274  //Downsample the data
275  for(i = m_iCurrentSample; i < data[b].cols(); i += m_iDownsampling)
276  ++count;
277 
278  MatrixXd dsData(data[b].rows(),count);
279 
280  count = 0;
281  for(i = m_iCurrentSample; i < data[b].cols(); i += m_iDownsampling)
282  {
283  dsData.col(count) = data[b].col(i);
284  ++count;
285  }
286 
287 
288 // qDebug() << "nchan" << dsData.rows() << "proj rows" << m_matProj.rows();
289 
290 
291  //store for next buffer
292  m_iCurrentSample = i - data[b].cols();
293 
294 // m_dataCurrent.append(data[b].col(i));
295 
296  bool doProj = false;
297 
298  if(m_bProjActivated && dsData.cols() > 0 && dsData.rows() == m_matProj.cols())
299  doProj = true;
300 
301  //SSP
302  if(doProj)
303  {
304  //set bad channels to zero
305  for(qint32 j = 0; j < m_vecBadIdcs.cols(); ++j)
306  dsData.row(m_vecBadIdcs[j]).setZero();
307 
308  //Do SSP Projection
309  MatrixXd projDsData = m_matSparseProj * dsData;
310  for(i = 0; i < projDsData.cols(); ++i)
311  m_dataCurrent.append(projDsData.col(i));
312  }
313  else
314  {
315  //store data
316  for(i = 0; i < dsData.cols(); ++i)
317  m_dataCurrent.append(dsData.col(i));
318  }
319 
320  // - old -
321 // //SSP
322 // //set bad channels to zero
323 // for(qint32 j = 0; j < m_vecBadIdcs.cols(); ++j)
324 // m_dataCurrent.last()[m_vecBadIdcs[j]] = 0;
325 
326 // //apply projector
327 // if(doProj)
328 // m_dataCurrent.last() = m_matProj * m_dataCurrent.last();
329 
330 // //Downsampling
331 // for(i = m_iCurrentSample; i < data[b].cols(); i += m_iDownsampling)
332 // m_dataCurrent.append(data[b].col(i));
333 
334 // //store for next buffer
335 // m_iCurrentSample = i - data[b].cols();
336  }
337 
338  //ToDo separate worker thread? ToDo 2000 -> size of screen
339  if(m_dataCurrent.size() > m_iMaxSamples)
340  {
341  m_dataLast = m_dataCurrent.mid(0,m_iMaxSamples); // Store last data to keep as background in the display
342  m_dataCurrent.remove(0, m_iMaxSamples);
343  }
344 
345  //Update data content
346  QModelIndex topLeft = this->index(0,1);
347  QModelIndex bottomRight = this->index(m_qListChInfo.size()-1,1);
348  QVector<int> roles; roles << Qt::DisplayRole;
349  emit dataChanged(topLeft, bottomRight, roles);
350 }
351 
352 
353 //*************************************************************************************************************
354 
355 fiff_int_t RealTimeMultiSampleArrayModel::getKind(qint32 row) const
356 {
357  if(row < m_qMapIdxRowSelection.size())
358  {
359  qint32 chRow = m_qMapIdxRowSelection[row];
360  return m_qListChInfo[chRow].getKind();;
361  }
362  else
363  return 0;
364 
365 }
366 
367 
368 //*************************************************************************************************************
369 
370 fiff_int_t RealTimeMultiSampleArrayModel::getUnit(qint32 row) const
371 {
372  if(row < m_qMapIdxRowSelection.size())
373  {
374  qint32 chRow = m_qMapIdxRowSelection[row];
375  return m_qListChInfo[chRow].getUnit();;
376  }
377  else
378  return FIFF_UNIT_NONE;
379 }
380 
381 
382 //*************************************************************************************************************
383 
384 fiff_int_t RealTimeMultiSampleArrayModel::getCoil(qint32 row) const
385 {
386  if(row < m_qMapIdxRowSelection.size())
387  {
388  qint32 chRow = m_qMapIdxRowSelection[row];
389  return m_qListChInfo[chRow].getCoil();;
390  }
391  else
392  return FIFFV_COIL_NONE;
393 }
394 
395 
396 //*************************************************************************************************************
397 
398 void RealTimeMultiSampleArrayModel::selectRows(const QList<qint32> &selection)
399 {
400  beginResetModel();
401 
402  m_qMapIdxRowSelection.clear();
403 
404  qint32 count = 0;
405  for(qint32 i = 0; i < selection.size(); ++i)
406  {
407  if(selection[i] < m_qListChInfo.size())
408  {
409  m_qMapIdxRowSelection.insert(count,selection[i]);
410  ++count;
411  }
412  }
413 
414  emit newSelection(selection);
415 
416  endResetModel();
417 }
418 
419 
420 //*************************************************************************************************************
421 
423 {
424  beginResetModel();
425 
426  m_qMapIdxRowSelection.clear();
427 
428  for(qint32 i = 0; i < m_qListChInfo.size(); ++i)
429  m_qMapIdxRowSelection.insert(i,i);
430 
431  endResetModel();
432 }
433 
434 
435 //*************************************************************************************************************
436 
438 {
439  m_bIsFreezed = !m_bIsFreezed;
440 
441  if(m_bIsFreezed)
442  {
443  m_dataCurrentFreeze = m_dataCurrent;
444  m_dataLastFreeze = m_dataLast;
445  }
446 
447  //Update data content
448  QModelIndex topLeft = this->index(0,1);
449  QModelIndex bottomRight = this->index(m_qListChInfo.size()-1,1);
450  QVector<int> roles; roles << Qt::DisplayRole;
451  emit dataChanged(topLeft, bottomRight, roles);
452 }
453 
454 
455 //*************************************************************************************************************
456 
457 void RealTimeMultiSampleArrayModel::setScaling(const QMap< qint32,float >& p_qMapChScaling)
458 {
459  beginResetModel();
460  m_qMapChScaling = p_qMapChScaling;
461  endResetModel();
462 }
463 
464 
465 //*************************************************************************************************************
466 
468 {
469  //
470  // Update the SSP projector
471  //
472  if(m_pFiffInfo)
473  {
474  m_bProjActivated = false;
475  for(qint32 i = 0; i < this->m_pFiffInfo->projs.size(); ++i)
476  if(this->m_pFiffInfo->projs[i].active)
477  m_bProjActivated = true;
478 
479  this->m_pFiffInfo->make_projector(m_matProj);
480  qDebug() << "updateProjection :: New projection calculated.";
481 
482 // std::cout << "Bads\n" << m_vecBadIdcs << std::endl;
483 // std::cout << "Proj\n";
484 // std::cout << m_matProj.block(0,0,10,10) << std::endl;
485 
486  qint32 nchan = this->m_pFiffInfo->nchan;
487  qint32 i, k;
488 
489  typedef Eigen::Triplet<double> T;
490  std::vector<T> tripletList;
491  tripletList.reserve(nchan);
492 
493  //
494  // Make proj sparse
495  //
496  tripletList.clear();
497  tripletList.reserve(m_matProj.rows()*m_matProj.cols());
498  for(i = 0; i < m_matProj.rows(); ++i)
499  for(k = 0; k < m_matProj.cols(); ++k)
500  if(m_matProj(i,k) != 0)
501  tripletList.push_back(T(i, k, m_matProj(i,k)));
502 
503  m_matSparseProj = SparseMatrix<double>(m_matProj.rows(),m_matProj.cols());
504  if(tripletList.size() > 0)
505  m_matSparseProj.setFromTriplets(tripletList.begin(), tripletList.end());
506  }
507 }
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
void setSamplingInfo(float sps, int T, float dest_sps=128.0f)
void setFiffInfo(FIFFLIB::FiffInfo::SPtr &p_pFiffInfo)
QSharedPointer< FiffInfo > SPtr
Definition: fiff_info.h:99
void newSelection(QList< qint32 > selection)
Declaration of the RealTimeMultiSampleArrayModel Class.
virtual QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
void setScaling(const QMap< qint32, float > &p_qMapChScaling)
void setChannelInfo(QList< RealTimeSampleArrayChInfo > &chInfo)
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const
void selectRows(const QList< qint32 > &selection)
static RowVectorXi pick_channels(const QStringList &ch_names, const QStringList &include=defaultQStringList, const QStringList &exclude=defaultQStringList)
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
#define FIFFV_COIL_NONE