MNE-CPP  beta 1.0
cluststcmodel.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //*************************************************************************************************************
38 //=============================================================================================================
39 // INCLUDES
40 //=============================================================================================================
41 
42 #include "cluststcmodel.h"
43 #include <mne/mne_sourceestimate.h>
44 #include <iostream>
45 
46 
47 //*************************************************************************************************************
48 //=============================================================================================================
49 // Qt INCLUDES
50 //=============================================================================================================
51 
52 #include <QDebug>
53 #include <QColor>
54 
55 
56 //*************************************************************************************************************
57 //=============================================================================================================
58 // USED NAMESPACES
59 //=============================================================================================================
60 
61 using namespace DISP3DLIB;
62 using namespace MNELIB;
63 
64 
65 //*************************************************************************************************************
66 //=============================================================================================================
67 // DEFINE MEMBER METHODS
68 //=============================================================================================================
69 
70 ClustStcModel::ClustStcModel(QObject *parent)
71 : QAbstractTableModel(parent)
72 , m_pWorker(new ClustStcWorker)
73 , m_bRTMode(true)
74 , m_bModelInit(false)
75 , m_bDataInit(false)
76 , m_bIntervallSet(false)
77 , m_dStcNormMax(10.0)
78 , m_dStcNorm(1.0)
79 {
80  qRegisterMetaType<MatrixXd>("MatrixXd");
81  qRegisterMetaType<VectorXd>("VectorXd");
82  qRegisterMetaType<Matrix3Xf>("Matrix3Xf");
83 
84  connect(m_pWorker.data(), &ClustStcWorker::stcSample, this, &ClustStcModel::setStcSample);
85 
86 // m_pWorker->setLoop(true);
87 
88  m_pWorker->start();
89 }
90 
91 
92 //*************************************************************************************************************
93 
94 ClustStcModel::~ClustStcModel()
95 {
96 }
97 
98 
99 //*************************************************************************************************************
100 //virtual functions
101 int ClustStcModel::rowCount(const QModelIndex & /*parent*/) const
102 {
103  if(!m_qListLabels.empty())
104  return m_qListLabels.size();
105  else
106  return 0;
107 }
108 
109 
110 //*************************************************************************************************************
111 
112 int ClustStcModel::columnCount(const QModelIndex & /*parent*/) const
113 {
114  return 7;
115 }
116 
117 
118 //*************************************************************************************************************
119 
120 QVariant ClustStcModel::data(const QModelIndex &index, int role) const
121 {
122  if(role != Qt::DisplayRole && role != Qt::BackgroundRole)
123  return QVariant();
124 
125  if (index.isValid()) {
126  qint32 row = index.row();
127 
128  switch(index.column()) {
129  case 0: { // index
130  if(role == Qt::DisplayRole)
131  return QVariant(row);
132  break;
133  }
134  case 1: { // vertex
135  if(m_bDataInit && role == Qt::DisplayRole)
136  return QVariant(m_qListLabels[row].label_id);//m_vertLabelIds(row));
137  break;
138  }
139  case 2: // stc data
140  case 3: // relative stc data
141  {
142  if(m_bDataInit && role == Qt::DisplayRole)
143  {
144  QList<qint32> selVec;
145  QVariant v;
146  if(row < m_iLHSize)
147  selVec = m_qMapLabelIdChannelLH.values(m_qListLabels[row].label_id);
148  else
149  selVec = m_qMapLabelIdChannelRH.values(m_qListLabels[row].label_id);
150 
151  VectorXd valVec(selVec.size());
152 
153  if(index.column() == 2) //stc data
154  for(qint32 i = 0; i < selVec.size(); ++i)
155  valVec(i) = m_vecCurStc(selVec[i]);
156  else // relative stc data
157  for(qint32 i = 0; i < selVec.size(); ++i)
158  valVec(i) = m_vecCurRelStc(selVec[i]);
159  v.setValue(valVec);
160  return v;//m_vecCurStc(row));
161  }
162  break;
163  }
164  case 4: { // Label
165  if(role == Qt::DisplayRole)
166  {
167  QVariant v;
168  v.setValue(m_qListLabels[row]);
169  return v;
170  }
171  break;
172  }
173  case 5: { // Color
174  if(role == Qt::DisplayRole)
175  return QVariant(QColor(m_qListRGBAs[row](0),m_qListRGBAs[row](1),m_qListRGBAs[row](2),255));
176  break;
177  }
178  case 6: { // Tri RRs
179  if(role == Qt::DisplayRole)
180  {
181  QVariant v;
182  v.setValue(m_qListTriRRs[row]);
183  return v;
184  }
185  break;
186  }
187  }
188  } // end index.valid() check
189 
190  return QVariant();
191 }
192 
193 
194 //*************************************************************************************************************
195 
196 QVariant ClustStcModel::headerData(int section, Qt::Orientation orientation, int role) const
197 {
198  if(role != Qt::DisplayRole)// && role != Qt::TextAlignmentRole)
199  return QVariant();
200 
201  if(orientation == Qt::Horizontal) {
202  switch(section) {
203  case 0: //index column
204  return QVariant("Index");
205  case 1: //vertex column
206  return QVariant("Vertex/Label ID");
207  case 2: //stc data column
208  return QVariant("STC");
209  case 3: //realtive stc data column
210  return QVariant("Relative STC");
211  case 4: //roi name column
212  return QVariant("Label");
213  case 5: //roi color column
214  return QVariant("Color");
215  case 6: //roi Tri Coords
216  return QVariant("Tri Coords");
217  }
218  }
219  else if(orientation == Qt::Vertical) {
220  QModelIndex mdlIdx = createIndex(section,0);
221  switch(role) {
222  case Qt::DisplayRole:
223  return QVariant(data(mdlIdx).toString());
224  }
225  }
226 
227  return QVariant();
228 }
229 
230 
231 //*************************************************************************************************************
232 
233 void ClustStcModel::addData(const MNESourceEstimate &stc)
234 {
235  if(!m_bModelInit || stc.isEmpty())
236  return;
237 
238  if(m_vertLabelIds.size() != stc.data.rows())
239  {
240  //TODO MAP data 416 to labels 150!!!!!!!!
241  //ToDo Map the indices to the regions
242  setVertLabelIDs(stc.vertices);
243  m_bDataInit = true;
244  }
245 
246  QList<VectorXd> data;
247  for(qint32 i = 0; i < stc.data.cols(); ++i)
248  data.append(stc.data.col(i));
249 
250  if(!m_bIntervallSet)
251  {
252  int usec = floor(stc.tstep*1000000);
253  if(usec <= 0)
254  return;
255  m_pWorker->setInterval(usec);
256  m_bIntervallSet = true;
257  }
258 
259  m_pWorker->addData(data);
260 }
261 
262 
263 //*************************************************************************************************************
264 
265 void ClustStcModel::init(const AnnotationSet &annotationSet, const SurfaceSet &surfSet)
266 {
267  beginResetModel();
268  m_annotationSet = annotationSet;
269  m_surfSet = surfSet;
270  m_annotationSet.toLabels(m_surfSet, m_qListLabels, m_qListRGBAs);
271 
272  float lhOffset = 0;
273  float rhOffset = 0;
274  // MIN MAX
275  for(qint32 h = 0; h < m_annotationSet.size(); ++h)
276  {
277  if(h == 0)
278  {
279  if(QString::compare(surfSet.surf(),"inflated") == 0)
280  lhOffset = m_surfSet[h].rr().col(0).maxCoeff(); // X
281 
282  m_vecMinRR.setX(m_surfSet[h].rr().col(0).minCoeff()-lhOffset); // X
283  m_vecMinRR.setY(m_surfSet[h].rr().col(1).minCoeff()); // Y
284  m_vecMinRR.setZ(m_surfSet[h].rr().col(2).minCoeff()); // Z
285  m_vecMaxRR.setX(m_surfSet[h].rr().col(0).maxCoeff()-lhOffset); // X
286  m_vecMaxRR.setY(m_surfSet[h].rr().col(1).maxCoeff()); // Y
287  m_vecMaxRR.setZ(m_surfSet[h].rr().col(2).maxCoeff()); // Z
288  }
289  else
290  {
291  if(QString::compare(surfSet.surf(),"inflated") == 0)
292  rhOffset = m_surfSet[h].rr().col(0).maxCoeff(); // X
293 
294  m_vecMinRR.setX(m_vecMinRR.x() < m_surfSet[h].rr().col(0).minCoeff()+rhOffset ? m_vecMinRR.x() : m_surfSet[h].rr().col(0).minCoeff()+rhOffset); // X
295  m_vecMinRR.setY(m_vecMinRR.y() < m_surfSet[h].rr().col(1).minCoeff() ? m_vecMinRR.y() : m_surfSet[h].rr().col(1).minCoeff()); // Y
296  m_vecMinRR.setZ(m_vecMinRR.z() < m_surfSet[h].rr().col(2).minCoeff() ? m_vecMinRR.z() : m_surfSet[h].rr().col(2).minCoeff()); // Z
297  m_vecMaxRR.setX(m_vecMaxRR.x() > m_surfSet[h].rr().col(0).maxCoeff()+rhOffset ? m_vecMaxRR.x() : m_surfSet[h].rr().col(0).maxCoeff()+rhOffset); // X
298  m_vecMaxRR.setY(m_vecMaxRR.y() > m_surfSet[h].rr().col(1).maxCoeff() ? m_vecMaxRR.y() : m_surfSet[h].rr().col(1).maxCoeff()); // Y
299  m_vecMaxRR.setZ(m_vecMaxRR.z() > m_surfSet[h].rr().col(2).maxCoeff() ? m_vecMaxRR.z() : m_surfSet[h].rr().col(2).maxCoeff()); // Z
300  }
301  }
302 
303  QVector3D vecCenterRR;
304  vecCenterRR.setX((m_vecMinRR.x()+m_vecMaxRR.x())/2.0f);
305  vecCenterRR.setY((m_vecMinRR.y()+m_vecMaxRR.y())/2.0f);
306  vecCenterRR.setZ((m_vecMinRR.z()+m_vecMaxRR.z())/2.0f);
307 
308  // Regions -> ToDo QtConcurrent
309 // qDebug() << "Before ROI";
310  for(qint32 h = 0; h < m_annotationSet.size(); ++h)
311  {
312  MatrixX3i tris;
313  MatrixX3f rr = m_surfSet[h].rr();
314 
315  //Centralize
316  if(QString::compare(surfSet.surf(),"inflated") == 0)
317  {
318  if(h == 0) //X
319  rr.col(0) = (rr.col(0).array() - lhOffset) - vecCenterRR.x();
320  else
321  rr.col(0) = (rr.col(0).array() + rhOffset) - vecCenterRR.x();
322  }
323  else
324  rr.col(0) = rr.col(0).array() - vecCenterRR.x(); // X
325 
326  rr.col(1) = rr.col(1).array() - vecCenterRR.y(); // Y
327  rr.col(2) = rr.col(2).array() - vecCenterRR.z(); // Z
328 
329 
330  //
331  // Create each ROI
332  //
333  for(qint32 k = 0; k < m_qListLabels.size(); ++k)
334  {
335  //check if label hemi fits current hemi
336  if(m_qListLabels[k].hemi != h)
337  continue;
338 
339  //Generate label tri information
340  tris = m_qListLabels[k].selectTris(m_surfSet[h]); //ToDO very slow -> QtConcurrent
341 
342 
343  Matrix3Xf triCoords(3,3*tris.rows());
344 
345  for(qint32 i = 0; i < tris.rows(); ++i)
346  {
347  triCoords.col(i*3) = rr.row( tris(i,0) ).transpose();
348  triCoords.col(i*3+1) = rr.row( tris(i,1) ).transpose();
349  triCoords.col(i*3+2) = rr.row( tris(i,2) ).transpose();
350  }
351 
352  m_qListTriRRs.append(triCoords);
353  }
354  }
355 // qDebug() << "After ROI";
356 
357  m_iLHSize = 0;
358  for(qint32 k = 0; k < m_qListLabels.size(); ++k)
359  if(m_qListLabels[k].hemi == 0)
360  ++m_iLHSize;
361 
362  m_vecCurStc = VectorXd::Zero(416);//m_qListLabels.size(),1);
363  m_vecCurRelStc = VectorXd::Zero(416);//m_qListLabels.size(),1);;
364  endResetModel();
365  m_bModelInit = true;
366 }
367 
368 
369 //*************************************************************************************************************
370 
371 void ClustStcModel::setAverage(qint32 samples)
372 {
373  m_pWorker->setAverage(samples);
374 }
375 
376 
377 //*************************************************************************************************************
378 
379 void ClustStcModel::setLoop(bool looping)
380 {
381  m_pWorker->setLoop(looping);
382 }
383 
384 
385 //*************************************************************************************************************
386 
387 void ClustStcModel::setNormalization(qint32 fraction)
388 {
389  m_dStcNorm = (m_dStcNormMax/100.0) * (double)fraction;
390 }
391 
392 
393 //*************************************************************************************************************
394 
395 void ClustStcModel::setStcSample(const VectorXd &sample)
396 {
397  m_vecCurStc = sample;
398 
399  m_vecCurRelStc = sample/m_dStcNorm;
400 
401  //Update data content -> Bug in QTableView which updates the whole table http://qt-project.org/forums/viewthread/14723
402  QModelIndex topLeft = this->index(0,2);
403  QModelIndex bottomRight = this->index(m_qListLabels.size()-1,3);
404  QVector<int> roles; roles << Qt::DisplayRole;
405  emit dataChanged(topLeft, bottomRight, roles);
406 
407  //Alternative for Table View -> Do update per item instead
408 // QModelIndex topLeft, bottomRight;
409 // QVector<int> roles; roles << Qt::DisplayRole;
410 // for(qint32 i = 0; i < m_qListLabels.size(); ++i)
411 // {
412 // topLeft = this->index(i,2);
413 // bottomRight = this->index(i,2);
414 // emit dataChanged(topLeft, bottomRight, roles);
415 // topLeft = this->index(i,3);
416 // bottomRight = this->index(i,3);
417 // emit dataChanged(topLeft, bottomRight, roles);
418 // }
419 }
420 
421 
422 //*************************************************************************************************************
423 
424 void ClustStcModel::setVertLabelIDs(const VectorXi &vertLabelIDs)
425 {
426  QMap<qint32, qint32> t_qMapLabelIdChannel;
427  for(qint32 i = 0; i < vertLabelIDs.size(); ++i)
428  t_qMapLabelIdChannel.insertMulti(vertLabelIDs(i),i);
429 
430 
431  QList<qint32> qListLastIdcs = t_qMapLabelIdChannel.values(vertLabelIDs(vertLabelIDs.size() - 1));
432 
433  qint32 lhIdx = 0;
434  qint32 maxIdx = qListLastIdcs[0];
435  qint32 minIdx = qListLastIdcs[0];
436 
437  for(qint32 i = 0; i < qListLastIdcs.size(); ++i)
438  {
439  if(maxIdx < qListLastIdcs[i])
440  maxIdx = qListLastIdcs[i];
441  if(minIdx > qListLastIdcs[i])
442  minIdx = qListLastIdcs[i];
443  }
444 
445  qint32 upperBound = maxIdx - (maxIdx*0.25);
446  for(qint32 i = 0; i < qListLastIdcs.size(); ++i)
447  {
448  if(lhIdx < qListLastIdcs[i] && qListLastIdcs[i] < upperBound)
449  lhIdx = qListLastIdcs[i];
450  }
451 
452  m_qMapLabelIdChannelLH.clear();
453  m_qMapLabelIdChannelRH.clear();
454 
455 
456  QMap<qint32, qint32>::iterator it;
457  for (it = t_qMapLabelIdChannel.begin(); it != t_qMapLabelIdChannel.end(); ++it)
458  {
459  if(it.value() <= lhIdx)
460  m_qMapLabelIdChannelLH.insertMulti(it.key(),it.value());
461  else
462  m_qMapLabelIdChannelRH.insertMulti(it.key(),it.value());
463  }
464 
465  m_vertLabelIds = vertLabelIDs;
466 }
467 
QString surf() const
Definition: surfaceset.h:269
QVariant data(int row, int column, int role=Qt::DisplayRole) const
ClustStcModel class declaration.
bool toLabels(const SurfaceSet &p_surfSet, QList< Label > &p_qListLabels, QList< RowVector4i > &p_qListLabelRGBAs) const
Annotation set.
Definition: annotationset.h:96
qint32 size() const
MNESourceEstimate class declaration.
A hemisphere set of surfaces.
Definition: surfaceset.h:83