MNE-CPP  beta 1.0
rawmodel.cpp
Go to the documentation of this file.
1 //=============================================================================================================
38 //*************************************************************************************************************
39 //=============================================================================================================
40 // INCLUDES
41 //=============================================================================================================
42 
43 #include "rawmodel.h"
44 
45 
46 //*************************************************************************************************************
47 //=============================================================================================================
48 // USED NAMESPACES
49 //=============================================================================================================
50 
51 using namespace MNEBrowseRawQt;
52 
53 
54 //*************************************************************************************************************
55 //=============================================================================================================
56 // DEFINE MEMBER METHODS
57 //=============================================================================================================
58 
59 RawModel::RawModel(QObject *parent)
60 : QAbstractTableModel(parent)
61 , m_bFileloaded(false)
62 , m_bStartReached(false)
63 , m_bEndReached(false)
64 , m_bReloading(false)
65 , m_bProcessing(false)
66 , m_fiffInfo(FiffInfo())
67 , m_pfiffIO(QSharedPointer<FiffIO>(new FiffIO()))
68 , m_filterChType("All")
69 {
70  m_iWindowSize = MODEL_WINDOW_SIZE;
71  m_reloadPos = MODEL_RELOAD_POS;
72  m_maxWindows = MODEL_MAX_WINDOWS;
73  m_iFilterTaps = MODEL_NUM_FILTER_TAPS;
74 
75  //Set default sampling freq to 1024
76  m_fiffInfo.sfreq = 1024;
77 
78  // Generate default filter operator - This needs to be done here so that the filter design tool works without loading a file
79  genStdFilterOps();
80 
81  //connect data reloading - this is done concurrently
82  connect(&m_reloadFutureWatcher,&QFutureWatcher<QPair<MatrixXd,MatrixXd> >::finished,[this](){
83  insertReloadedData(m_reloadFutureWatcher.future().result());
84  });
85 
86  //connect filtering reloading - this is done after a new block has been loaded
87  connect(this,&RawModel::dataReloaded,[this](){
88  if(!m_assignedOperators.empty())
89  updateOperatorsConcurrently();
90  });
91 
92 // connect(&m_operatorFutureWatcher,&QFutureWatcher<QPair<int,RowVectorXd> >::resultReadyAt,[this](int index){
93 // insertProcessedData(index);
94 // });
95  connect(&m_operatorFutureWatcher,&QFutureWatcher<void>::finished,[this](){
96  insertProcessedDataAll();
97  });
98 // connect(&m_operatorFutureWatcher,&QFutureWatcher<QPair<int,RowVectorXd> >::progressValueChanged,[this](int progressValue){
99 // qDebug() << "RawModel: ProgressValue m_operatorFutureWatcher, " << progressValue << " items processed out of" << m_listTmpChData.size();
100 // });
101 }
102 
103 
104 //*************************************************************************************************************
105 
106 RawModel::RawModel(QFile &qFile, QObject *parent)
107 : QAbstractTableModel(parent)
108 , m_bFileloaded(false)
109 , m_bStartReached(false)
110 , m_bEndReached(false)
111 , m_bReloading(false)
112 , m_bProcessing(false)
113 , m_fiffInfo(FiffInfo())
114 , m_pfiffIO(QSharedPointer<FiffIO>(new FiffIO()))
115 , m_filterChType("All")
116 {
117  m_iWindowSize = MODEL_WINDOW_SIZE;
118  m_reloadPos = MODEL_RELOAD_POS;
119  m_maxWindows = MODEL_MAX_WINDOWS;
120  m_iFilterTaps = MODEL_NUM_FILTER_TAPS;
121 
122  //read fiff data
123  loadFiffData(&qFile);
124 
125  //generator FilterOperator objects
126  genStdFilterOps();
127 
128  //connect signal and slots
129  connect(&m_reloadFutureWatcher,&QFutureWatcher<QPair<MatrixXd,MatrixXd> >::finished,[this](){
130  insertReloadedData(m_reloadFutureWatcher.future().result());
131  });
132 
133  connect(this,&RawModel::dataReloaded,[this](){
134  if(!m_assignedOperators.empty())
135  updateOperatorsConcurrently();
136  });
137 
138 // connect(&m_operatorFutureWatcher,&QFutureWatcher<QPair<int,RowVectorXd> >::resultReadyAt,[this](int index){
139 // insertProcessedData(index);
140 // });
141  connect(&m_operatorFutureWatcher,&QFutureWatcher<void>::finished,[this](){
142  insertProcessedDataAll();
143  });
144 // connect(&m_operatorFutureWatcher,&QFutureWatcher<QPair<int,RowVectorXd> >::progressValueChanged,[this](int progressValue){
145 // qDebug() << "RawModel: ProgressValue m_operatorFutureWatcher, " << progressValue << " items processed out of" << m_listTmpChData.size();
146 // });
147 }
148 
149 
150 //*************************************************************************************************************
151 //virtual functions
152 int RawModel::rowCount(const QModelIndex & /*parent*/) const
153 {
154  if(!m_chInfolist.empty())
155  return m_chInfolist.size();
156  else return 0;
157 }
158 
159 
160 //*************************************************************************************************************
161 
162 int RawModel::columnCount(const QModelIndex & /*parent*/) const
163 {
164  return 3;
165 }
166 
167 
168 //*************************************************************************************************************
169 
170 QVariant RawModel::data(const QModelIndex &index, int role) const
171 {
172  if(role != Qt::DisplayRole && role != Qt::BackgroundRole && role != RawModelRoles::GetChannelMean)
173  return QVariant();
174 
175  if (index.isValid()) {
176  //******** first column (chname) ********
177  if(index.column()==0 && role == Qt::DisplayRole)
178  return QVariant(m_chInfolist[index.row()].ch_name);
179 
180  //******** second column (data plot) ********
181  if(index.column()==1) {
182  QVariant v;
183 
184  switch(role) {
185  case Qt::DisplayRole: {
186  //form RowVectorPair of pointer and length of RowVector
187  QPair<const double*,qint32> rowVectorPair;
188 
189  //pack all adjacent (after reload) RowVectorPairs into a QList
190  QList<RowVectorPair> listRowVectorPair;
191 
192  for(qint16 i=0; i < m_data.size(); ++i) {
193  //if channel is not filtered or background Processing pending...
194  if(!m_assignedOperators.contains(index.row()) || (m_bProcessing && m_bReloadBefore && i==0) || (m_bProcessing && !m_bReloadBefore && i==m_data.size()-1)) {
195  rowVectorPair.first = m_data[i]->dataRaw().data() + index.row()*m_data[i]->dataRaw().cols();
196  rowVectorPair.second = m_data[i]->dataRaw().cols();
197  }
198  else { //if channel IS filtered
199  rowVectorPair.first = m_data[i]->dataProc().data() + index.row()*m_data[i]->dataProc().cols();
200  rowVectorPair.second = m_data[i]->dataProc().cols();
201  }
202 
203  listRowVectorPair.append(rowVectorPair);
204  }
205 
206  v.setValue(listRowVectorPair);
207  return v;
208  break;
209  }
210 
211  case Qt::BackgroundRole: { //plot channel red if marked as red
212  if(m_fiffInfo.bads.contains(m_chInfolist[index.row()].ch_name)) {
213  QBrush brush;
214  brush.setStyle(Qt::SolidPattern);
215 // qDebug() << m_chInfolist[index.row()].ch_name << "is marked as bad, index:" << index.row();
216  brush.setColor(Qt::darkRed);
217  return QVariant(brush);
218  }
219  else
220  return QVariant();
221 
222  break;
223  }
224  }
225  }
226 
227  //******** third column (mean data of the channels plot) ********
228  if(index.column()==2) {
229  switch(role) {
230  case RawModelRoles::GetChannelMean: {
231  QVariant v;
232 
233  //if channel is not filtered or background Processing pending...
234  if(!m_assignedOperators.contains(index.row()) || (m_bProcessing && m_bReloadBefore) || (m_bProcessing && !m_bReloadBefore)) {
235  //Calculate the global mean of all loaded data in m_dataMean
236  double sum = 0;
237  for(int i = 0; i<m_data.size(); i++)
238  sum += m_data[i]->dataRawMean(index.row());
239 
240  v.setValue(sum/m_data.size());
241  }
242  else { //if channel IS filtered
243  //Calculate the global mean of all loaded data in m_dataMean
244  double sum = 0;
245  for(int i = 0; i<m_data.size(); i++)
246  sum += m_data[i]->dataProcMean(index.row());
247 
248  v.setValue(sum/m_data.size());
249  }
250 
251  return v;
252  break;
253  }
254  } // end role switch
255  } // end column check
256  } // end index.valid() check
257 
258  return QVariant();
259 }
260 
261 
262 //*************************************************************************************************************
263 
264 QVariant RawModel::headerData(int section, Qt::Orientation orientation, int role) const
265 {
266  if(role != Qt::DisplayRole && role != Qt::TextAlignmentRole)
267  return QVariant();
268 
269  if(orientation == Qt::Horizontal) {
270  switch(section) {
271  case 0: //chname column
272  return QVariant();
273  case 1: //data plot column
274  switch(role) {
275  case Qt::DisplayRole:
276  return QVariant("data plot");
277  case Qt::TextAlignmentRole:
278  return QVariant(Qt::AlignLeft);
279  }
280  }
281  }
282  else if(orientation == Qt::Vertical) {
283  QModelIndex chname = createIndex(section,0);
284  switch(role) {
285  case Qt::DisplayRole:
286  return QVariant(data(chname).toString());
287  }
288  }
289 
290  return QVariant();
291 }
292 
293 
294 //*************************************************************************************************************
295 
296 void RawModel::genStdFilterOps()
297 {
298  //clear operators
299  //m_Operators.clear();
300 
301  //regenerate them with the correct sampling frequency (only required for naming of filter)
302  double sfreq = (m_fiffInfo.sfreq>=0) ? m_fiffInfo.sfreq : 600.0;
303  double nyquist_freq = sfreq/2;
304 
305  int fftLength = m_iWindowSize;
306  int exp = ceil(MNEMath::log2(fftLength));
307  fftLength = pow(2, exp+1);
308  m_iCurrentFFTLength = fftLength;
309 
310  FilterOperator::DesignMethod dMethod = FilterOperator::Cosine;
311 
312  //HPF
313  double cutoffFreqHz = 50; //in Hz
314  QString name = QString("HPF_%1").arg(cutoffFreqHz);
315  m_Operators.insert(name,QSharedPointer<MNEOperator>(new FilterOperator(name,FilterOperator::HPF,m_iFilterTaps,cutoffFreqHz/nyquist_freq,5/nyquist_freq,1/nyquist_freq,sfreq,fftLength,dMethod)));
316 
317  //LPF
318  cutoffFreqHz = 30; //in Hz
319  name = QString("LPF_%1").arg(cutoffFreqHz);
320  m_Operators.insert(name,QSharedPointer<MNEOperator>(new FilterOperator(name,FilterOperator::LPF,m_iFilterTaps,cutoffFreqHz/nyquist_freq,5/nyquist_freq,1/nyquist_freq,sfreq,fftLength,dMethod)));
321  cutoffFreqHz = 10; //in Hz
322  name = QString("LPF_%1").arg(cutoffFreqHz);
323  m_Operators.insert(name,QSharedPointer<MNEOperator>(new FilterOperator(name,FilterOperator::LPF,m_iFilterTaps,cutoffFreqHz/nyquist_freq,5/nyquist_freq,1/nyquist_freq,sfreq,fftLength,dMethod)));
324 
325  //BPF
326  double from_freqHz = 30;
327  double to_freqHz = 40;
328  double trans_width = 5;
329  double bw = to_freqHz-from_freqHz; //double bw = to_freqHz/from_freqHz;
330  double center = from_freqHz+bw/2;
331 
332  name = QString("BPF_%1-%2").arg(from_freqHz).arg(to_freqHz);
333  m_Operators.insert(name,QSharedPointer<MNEOperator>(new FilterOperator(name,FilterOperator::BPF,80,(double)center/nyquist_freq,(double)bw/nyquist_freq,(double)trans_width/nyquist_freq,sfreq,fftLength,dMethod)));
334 
335  //Own/manual set filter - only an entry i nthe operator list generated which is called when the filterwindow is used
336  cutoffFreqHz = 40;
337  //only create if filter does not exist yet
338  if(!m_Operators.contains(QString("User defined (See 'Adjust/Filter')"))) {
339  name = QString("User defined (See 'Adjust/Filter')");
340  m_Operators.insert(name,QSharedPointer<MNEOperator>(new FilterOperator(name,FilterOperator::LPF,m_iFilterTaps,cutoffFreqHz/nyquist_freq,5/nyquist_freq,1/nyquist_freq,sfreq,(m_iWindowSize+m_iFilterTaps),dMethod)));
341  }
342 
343  //**********
344  //filter debugging -> store filter coefficients to plain text file
345 // QFile file("C:/Users/Flo/Desktop/matlab/filter.txt");
346 // file.open(QFile::WriteOnly | QFile::Text);
347 // QTextStream out(&file);
348 
349 // QSharedPointer<FilterOperator> filtPtr = m_Operators[name].staticCast<FilterOperator>();
350 // for(int i=0; i < filtPtr->m_dCoeffA.cols(); ++i)
351 // out << filtPtr->m_dCoeffA(0,i) << endl;
352 
353 // file.close();
354  //**********
355 
356  qDebug() << "RawModel: Standard FilterOperators generated and loaded.";
357 }
358 
359 
360 //*************************************************************************************************************
361 
362 bool RawModel::loadFiffData(QFile* qFile)
363 {
364  beginResetModel();
365  clearModel();
366 
367  MatrixXd t_data,t_times; //type is later on (when append to m_data) casted into MatrixXdR (Row-Major)
368  QSharedPointer<DataPackage> newDataPackage;
369 
370  m_pfiffIO = QSharedPointer<FiffIO>(new FiffIO(*qFile));
371  if(!m_pfiffIO->m_qlistRaw.empty()) {
372  m_iAbsFiffCursor = m_pfiffIO->m_qlistRaw[0]->first_samp; //Set cursor somewhere into fiff file [in samples]
373  m_bStartReached = true;
374 
375  int start = m_iAbsFiffCursor;
376  int end = start + m_iWindowSize - 1;
377 
378  if(!m_pfiffIO->m_qlistRaw[0]->read_raw_segment(t_data, t_times, start, end))
379  return false;
380 
381  newDataPackage = QSharedPointer<DataPackage>(new DataPackage(t_data, (MatrixXdR)t_times));
382 
383  m_bFileloaded = true;
384  }
385  else {
386  qDebug("RawModel: ERROR! Data set does not contain any fiff data!");
387  endResetModel();
388  m_bFileloaded = false;
389  return false;
390  }
391 
392  //set loaded fiff data
393  m_data.append(newDataPackage);
394 
395  loadFiffInfos();
396  genStdFilterOps();
397 
398  endResetModel();
399 
400  qFile->close();
401 
402  emit fileLoaded(m_fiffInfo);
403  emit assignedOperatorsChanged(m_assignedOperators);
404 
405  return true;
406 }
407 
408 
409 //*************************************************************************************************************
410 
411 bool RawModel::writeFiffData(QIODevice *p_IODevice)
412 {
413  RowVectorXd cals;
414  SparseMatrix<double> mult;
415  RowVectorXi sel;
416 
417 // std::cout << "Writing file " << QFile(&p_IODevice).fileName().toLatin1() << std::endl;
418  FiffStream::SPtr outfid = Fiff::start_writing_raw(*p_IODevice,m_fiffInfo,cals);
419 
420  //Setup reading parameters
421  fiff_int_t from = firstSample();
422  fiff_int_t to = lastSample();
423  float quantum_sec = 10.0f;//read and write in 10 sec junks
424  fiff_int_t quantum = ceil(quantum_sec*m_fiffInfo.sfreq);
425 
426  // Uncomment to read the whole file at once. Warning MAtrix may be none-initialisable because its huge
427  //quantum = to - from + 1;
428 
429  // Read and write all the data
430  bool first_buffer = true;
431 
432  fiff_int_t first, last;
433  MatrixXd data;
434  MatrixXd times;
435 
436  emit writeProgressRangeChanged(from, to);
437 
438  for(first = from; first < to; first+=quantum) {
439  last = first+quantum-1;
440  if (last > to)
441  last = to;
442 
443  if (!m_pfiffIO->m_qlistRaw[0]->read_raw_segment(data,times,mult,first,last,sel)) {
444  qDebug("error during read_raw_segment\n");
445  return false;
446  }
447 
448  qDebug("Writing...");
449  if (first_buffer) {
450  if (first > 0)
451  outfid->write_int(FIFF_FIRST_SAMPLE,&first);
452  first_buffer = false;
453  }
454  outfid->write_raw_buffer(data,mult);
455  qDebug("[done]\n");
456 
457  emit writeProgressChanged(first);
458  }
459 
460  outfid->finish_writing_raw();
461 
462  return true;
463 }
464 
465 
466 //*************************************************************************************************************
467 //non-virtual functions
468 //private
469 void RawModel::loadFiffInfos()
470 {
471  //loads chinfos
472  for(qint32 i=0; i < m_pfiffIO->m_qlistRaw[0]->info.nchan; ++i)
473  m_chInfolist.append(m_pfiffIO->m_qlistRaw[0]->info.chs[i]);
474 
475  //loads fiffInfo
476  m_fiffInfo = m_pfiffIO->m_qlistRaw[0]->info;
477 }
478 
479 
480 //*************************************************************************************************************
481 
482 void RawModel::clearModel()
483 {
484  //FiffIO object
485  m_pfiffIO.clear();
486  m_fiffInfo.clear();
487  m_chInfolist.clear();
488 
489  //data model structure
490  m_data.clear();
491 
492  //MNEOperators
493  m_assignedOperators.clear();
494 
495  //View parameters
496  m_iAbsFiffCursor = 0;
497  m_iCurAbsScrollPos = 0;
498  m_bStartReached = false;
499  m_bEndReached = false;
500 
501  qDebug("RawModel cleared.");
502 }
503 
504 
505 //*************************************************************************************************************
506 
507 void RawModel::resetPosition(qint32 position)
508 {
509  beginResetModel();
510 
511  //reset members
512  m_data.clear();
513 
514  m_bStartReached = false;
515  m_bEndReached = false;
516  m_bReloading = false;
517  m_bProcessing = false;
518 
519  //calculate multiple integer of m_iWindowSize from beginning of Fiff file (rounded down)
520  qint32 distance = position - firstSample();
521  qint32 mult = floor(distance / m_iWindowSize);
522 
523  m_iAbsFiffCursor = firstSample() + mult*m_iWindowSize;
524 
525  MatrixXd t_data,t_times; //type is later on (when append to m_data) casted into MatrixXdR (Row-Major)
526 
527  int start = m_iAbsFiffCursor;
528  int end = start + m_iWindowSize - 1;
529 
530  m_Mutex.lock();
531  if(!m_pfiffIO->m_qlistRaw[0]->read_raw_segment(t_data, t_times, start, end))
532  qDebug() << "RawModel: Error resetting position of Fiff file!";
533  m_Mutex.unlock();
534 
535  //build data package
536  QSharedPointer<DataPackage> newDataPackage;
537  newDataPackage = QSharedPointer<DataPackage>(new DataPackage((MatrixXdR)t_data, (MatrixXdR)t_times));
538 
539  //append loaded block
540  m_data.append(newDataPackage);
541 
542  if(!m_assignedOperators.empty())
543  updateOperators();
544 
545  endResetModel();
546 
547 // if(!(m_iAbsFiffCursor<=firstSample()))
548 // updateScrollPos(m_iCurAbsScrollPos-firstSample()); //little hack: if the m_iCurAbsScrollPos is now close to the edge -> force reloading w/o scrolling
549 
550  qDebug() << "RawModel: Model Position RESET, samples from " << m_iAbsFiffCursor << "to" << m_iAbsFiffCursor+m_iWindowSize-1 << "reloaded. actual loaded t_data cols: " << t_data.cols();
551 
552  emit dataChanged(createIndex(0,1),createIndex(m_chInfolist.size(),1));
553 }
554 
555 
556 //*************************************************************************************************************
557 
558 void RawModel::reloadFiffData(bool before)
559 {
560  m_bReloadBefore = before;
561 
562  //update scroll position
563  fiff_int_t start,end;
564  if(before) {
565  m_iAbsFiffCursor -= m_iWindowSize;
566  start = m_iAbsFiffCursor;
567  end = start + m_iWindowSize - 1;
568 
569  //check if start of fiff file is reached
570  if(start < firstSample()) {
571  m_bStartReached = true;
572  qDebug() << "RawModel: Start of fiff file reached.";
573 
574  m_iAbsFiffCursor = firstSample();
575  //resetPosition(m_iAbsFiffCursor);
576  return;
577  }
578  }
579  else {
580  start = m_iAbsFiffCursor + sizeOfPreloadedData();
581  end = start + m_iWindowSize - 1;
582 
583  //check if end of fiff file is reached
584  if(end > lastSample()) {
585  //Reload one more time
586  if(m_bEndReached)
587  return;
588  else
589  m_bEndReached = true;
590 
591  end = lastSample();
592  qDebug() << "RawModel: End of fiff file reached.";
593  }
594  }
595 
596  m_bReloading = true;
597 
598  //read data with respect to start and end point
599  QFuture<QPair<MatrixXd,MatrixXd> > future = QtConcurrent::run(this,&RawModel::readSegment,start,end);
600 
601  //Wait for thread reloading is finished, then insert reloaded data
602  //future.waitForFinished();
603  //insertReloadedData(future.result());
604 
605  m_reloadFutureWatcher.setFuture(future);
606 }
607 
608 
609 //*************************************************************************************************************
610 
611 QPair<MatrixXd,MatrixXd> RawModel::readSegment(fiff_int_t from, fiff_int_t to)
612 {
613  QPair<MatrixXd,MatrixXd> datatime;
614 
615  m_Mutex.lock();
616  if(!m_pfiffIO->m_qlistRaw[0]->read_raw_segment(datatime.first, datatime.second, from, to)) {
617  printf("RawModel: Error when reading raw data!");
618  return datatime;
619  }
620  m_Mutex.unlock();
621 
622  return datatime;
623 }
624 
625 
626 //*************************************************************************************************************
627 //public SLOTS
629 {
630  m_iCurAbsScrollPos = firstSample() + value;
631  qDebug() << "RawModel: absolute Fiff Scroll Cursor" << m_iCurAbsScrollPos << "(m_iAbsFiffCursor" << m_iAbsFiffCursor << ", sizeOfPreloadedData" << sizeOfPreloadedData() << ", firstSample()" << firstSample() << ")";
632 
633  //if a scroll position is selected, which is not within the loaded data range -> reset position of model
634  if(m_iCurAbsScrollPos > (m_iAbsFiffCursor+sizeOfPreloadedData()+m_iWindowSize) || m_iCurAbsScrollPos < m_iAbsFiffCursor) {
635  qDebug() << "RawModel: Reset position requested, m_iAbsFiffCursor:" << m_iAbsFiffCursor << "m_iCurAbsScrollPos:" << m_iCurAbsScrollPos;
636  resetPosition(m_iCurAbsScrollPos);
637  return;
638  }
639 
640  //reload data if end of loaded range is reached and no relaoding is currently active
641  //front
642  if(!m_bReloading && (m_iCurAbsScrollPos-m_iAbsFiffCursor < m_reloadPos) && !m_bStartReached) {
643  qDebug() << "RawModel: Reload requested at FRONT of loaded fiff data, m_iAbsFiffCursor:" << m_iAbsFiffCursor << "m_iCurAbsScrollPos:" << m_iCurAbsScrollPos;
644  reloadFiffData(1);
645  }
646  //end
647  else if(!m_bReloading && m_iCurAbsScrollPos > m_iAbsFiffCursor+sizeOfPreloadedData()-m_reloadPos && !m_bEndReached) {
648  qDebug() << "RawModel: Reload requested at END of loaded fiff data, m_iAbsFiffCursor:" << m_iAbsFiffCursor << "m_iCurAbsScrollPos:" << m_iCurAbsScrollPos;
649  reloadFiffData(0);
650  }
651 }
652 
653 
654 //*************************************************************************************************************
655 
656 void RawModel::markChBad(QModelIndexList chlist, bool status)
657 {
658  for(int i=0; i < chlist.size(); ++i) {
659  if(chlist[i].column() == 1) {//only process indexes corresponding to column 1 (data)
660  if(status) {
661  if(!m_fiffInfo.bads.contains(m_chInfolist[chlist[i].row()].ch_name))
662  m_fiffInfo.bads.append(m_chInfolist[chlist[i].row()].ch_name);
663  qDebug() << "RawModel:" << m_chInfolist[chlist[i].row()].ch_name << "marked as bad.";
664  }
665  else {
666  if(m_fiffInfo.bads.contains(m_chInfolist[chlist[i].row()].ch_name)) {
667  int index = m_fiffInfo.bads.indexOf(m_chInfolist[chlist[i].row()].ch_name);
668  m_fiffInfo.bads.removeAt(index);
669  qDebug() << "RawModel:" << m_chInfolist[chlist[i].row()].ch_name << "marked as good.";
670  }
671  }
672 
673  emit dataChanged(chlist[i],chlist[i]);
674  }
675  }
676 }
677 
678 
679 //*************************************************************************************************************
680 
681 void RawModel::applyOperator(QModelIndexList chlist, const QSharedPointer<MNEOperator>& operatorPtr, const QString &chType)
682 {
683  m_filterChType = chType;
684 
685  //clear channel list becuase we will generate a new one
686  chlist.clear();
687 
688  //filter only channels which include chType in their names
689  if(chType == "All") {
690  for(qint32 i=0; i < m_chInfolist.size(); ++i) {
691  if(!m_chInfolist.at(i).ch_name.contains("STI") && !m_chInfolist.at(i).ch_name.contains("MISC") && !m_chInfolist.at(i).ch_name.contains("TRG"))
692  if(!m_assignedOperators.values(i).contains(operatorPtr))
693  m_assignedOperators.insertMulti(i,operatorPtr);
694  }
695  }
696  else {
697  for(qint32 i=0; i < m_chInfolist.size(); ++i) {
698  if(!m_chInfolist.at(i).ch_name.contains("STI") && !m_chInfolist.at(i).ch_name.contains("MISC") && !m_chInfolist.at(i).ch_name.contains("TRG") && m_chInfolist.at(i).ch_name.contains(chType))
699  if(!m_assignedOperators.values(i).contains(operatorPtr))
700  m_assignedOperators.insertMulti(i,operatorPtr);
701  }
702  }
703 
704  m_bProcessing = true;
705 
706  for(int i=0; i<m_data.size(); i++)
707  updateOperatorsConcurrently(i);
708 
709  performOverlapAdd();
710 
711  m_bProcessing = false;
712 
713  emit assignedOperatorsChanged(m_assignedOperators);
714 
715  qDebug() << "RawModel: using FilterType" << operatorPtr->m_sName;
716 }
717 
718 
719 //*************************************************************************************************************
720 
721 void RawModel::applyOperator(QModelIndexList chlist, const QSharedPointer<MNEOperator>& operatorPtr)
722 {
723  //filter all when chlist is empty
724  if(chlist.empty()) {
725  for(qint32 i=0; i < m_chInfolist.size(); ++i) {
726  if(chlist.at(i).column()==1)
727  if(!m_chInfolist.at(i).ch_name.contains("STI") && !m_chInfolist.at(i).ch_name.contains("MISC") && !m_chInfolist.at(i).ch_name.contains("TRG"))
728  if(!m_assignedOperators.values(i).contains(operatorPtr))
729  m_assignedOperators.insertMulti(i,operatorPtr);
730  }
731  }
732 
733  for(qint32 i=0; i < chlist.size(); ++i) { //iterate through selected channels to filter
734  if(chlist.at(i).column()==1) {
735  QString chName = data(index(i,0)).toString();
736  if(!chName.contains("STI") && !chName.contains("MISC") && !chName.contains("TRG"))
737  if(!m_assignedOperators.values(chlist.at(i).row()).contains(operatorPtr))
738  m_assignedOperators.insertMulti(chlist.at(i).row(),operatorPtr);
739  }
740  }
741 
742  m_bProcessing = true;
743 
744  for(int i=0; i<m_data.size(); i++)
745  updateOperatorsConcurrently(i);
746 
747  performOverlapAdd();
748 
749  m_bProcessing = false;
750 
751  emit assignedOperatorsChanged(m_assignedOperators);
752 
753  qDebug() << "RawModel: using FilterType" << operatorPtr->m_sName;
754 }
755 
756 
757 //*************************************************************************************************************
758 
759 void RawModel::applyOperatorsConcurrently(QPair<int,RowVectorXd>& chdata) const
760 {
761  QSharedPointer<FilterOperator> filter;
762 
763  //QList<int> listFilteredChs = m_assignedOperators.keys();
764 
765  QList<QSharedPointer<MNEOperator> > ops = m_assignedOperators.values(chdata.first);
766  for(qint32 i=0; i < ops.size(); ++i) {
767  switch(ops[i]->m_OperatorType) {
768  case MNEOperator::FILTER: {
769  filter = ops[i].staticCast<FilterOperator>();
770  RowVectorXd tmp = filter->applyFFTFilter(chdata.second);
771  chdata.second = tmp;
772  }
773  case MNEOperator::PCA: {
774  //do something
775  }
776  }
777  }
778 // return chdata;
779 }
780 
781 
782 //*************************************************************************************************************
783 
784 void RawModel::updateOperators(QModelIndex chan)
785 {
786  for(qint32 i=0; i < m_assignedOperators.values(chan.row()).size(); ++i) {
787  for(qint32 j=0; j < m_assignedOperators.values(chan.row()).size(); ++j) {
788  if(!m_assignedOperators.values(chan.row()).contains(m_assignedOperators.values(chan.row())[j]))
789  m_assignedOperators.insertMulti(chan.row(), m_assignedOperators.values(chan.row())[j]);
790  }
791  }
792 
793  m_bProcessing = true;
794 
795  for(int i=0; i<m_data.size(); i++)
796  updateOperatorsConcurrently(i);
797 
798  performOverlapAdd();
799 
800  m_bProcessing = false;
801 
802  emit assignedOperatorsChanged(m_assignedOperators);
803 }
804 
805 
806 //*************************************************************************************************************
807 
808 void RawModel::updateOperators(QModelIndexList chlist)
809 {
810  if(chlist.empty())
811  for(qint32 i=0; i < m_chInfolist.size(); ++i)
812  chlist.append(createIndex(i,1));
813 
814  for(qint32 i=0; i < chlist.size(); ++i) {
815  for(qint32 j=0; j < m_assignedOperators.values(chlist[i].row()).size(); ++j) {
816  if(!m_assignedOperators.values(chlist[i].row()).contains(m_assignedOperators.values(chlist[i].row())[j]))
817  m_assignedOperators.insertMulti(chlist[i].row(), m_assignedOperators.values(chlist[i].row())[j]);
818  }
819  }
820 
821  m_bProcessing = true;
822 
823  for(int i=0; i<m_data.size(); i++)
824  updateOperatorsConcurrently(i);
825 
826  performOverlapAdd();
827 
828  m_bProcessing = false;
829 
830  emit assignedOperatorsChanged(m_assignedOperators);
831 }
832 
833 
834 //*************************************************************************************************************
835 
837 {
838  updateOperators(QModelIndexList());
839 }
840 
841 
842 //*************************************************************************************************************
843 
844 void RawModel::undoFilter(QModelIndexList chlist, const QSharedPointer<MNEOperator> &filterPtr)
845 {
846  for(qint32 i=0; i < chlist.size(); ++i) {
847  if(m_assignedOperators.contains(chlist[i].row()) && m_assignedOperators.values(chlist[i].row()).contains(filterPtr)) {
848  QMutableMapIterator<int,QSharedPointer<MNEOperator> > it(m_assignedOperators);
849  while(it.hasNext()) {
850  it.next();
851  if(it.key()==chlist[i].row() && it.value()==filterPtr) {
852  it.remove();
853  qDebug() << "RawModel: Filter operator removed of type" << filterPtr->m_sName << "for channel" << chlist[i].row();
854  updateOperators(chlist[i]);
855  continue;
856  }
857  }
858 
859  }
860  else {
861  qDebug() << "RawModel: No filter of type" << filterPtr->m_sName << "applied to channel" << chlist[i].row();
862  continue;
863  }
864  }
865 
866  emit assignedOperatorsChanged(m_assignedOperators);
867 }
868 
869 
870 //*************************************************************************************************************
871 
872 void RawModel::undoFilter(QModelIndexList chlist)
873 {
874  for(qint32 i=0; i < chlist.size(); ++i) {
875  m_assignedOperators.remove(chlist[i].row());
876  qDebug() << "RawModel: All filter operator removed of type for channel" << chlist[i].row();
877  }
878 
879  emit assignedOperatorsChanged(m_assignedOperators);
880 }
881 
882 
883 //*************************************************************************************************************
884 
885 void RawModel::undoFilter(const QString &chType)
886 {
887  if(chType == "All")
888  undoFilter();
889  else {
890  //filter only channels which include chType in their names
891  for(qint32 i=0; i < m_chInfolist.size(); ++i)
892  if(m_chInfolist.at(i).ch_name.contains(chType))
893  m_assignedOperators.remove(i);
894  }
895 
896  emit assignedOperatorsChanged(m_assignedOperators);
897 }
898 
899 
900 //*************************************************************************************************************
901 
903 {
904  m_assignedOperators.clear();
905 
906  emit assignedOperatorsChanged(m_assignedOperators);
907 }
908 
909 
910 //*************************************************************************************************************
911 //private SLOTS
912 void RawModel::insertReloadedData(QPair<MatrixXd,MatrixXd> dataTimesPair)
913 {
914  QSharedPointer<DataPackage> newDataPackage = QSharedPointer<DataPackage>(new DataPackage((MatrixXdR)dataTimesPair.first, (MatrixXdR)dataTimesPair.second));
915 
916  //extend m_data with reloaded data
917  if(m_bReloadBefore) {
918  m_data.prepend(newDataPackage);
919 
920  //maintain at maximum m_maxWindows data windows and drop the rest
921  if(m_data.size() > m_maxWindows) {
922  m_data.removeLast();
923  }
924  }
925  else {
926  m_data.append(newDataPackage);
927 
928  //maintain at maximum m_maxWindows data windows and drop the rest
929  if(m_data.size() > m_maxWindows) {
930  m_data.removeFirst();
931  m_iAbsFiffCursor += m_iWindowSize;
932  }
933  }
934 
935  m_bReloading = false;
936 
937  emit dataChanged(createIndex(0,1),createIndex(m_chInfolist.size()-1,1));
938  emit dataReloaded();
939 
940  qDebug() << "RawModel: Fiff data Reloaded from " << dataTimesPair.second.coeff(0) << "secs to" << dataTimesPair.second.coeff(dataTimesPair.second.cols()-1) << "secs";
941 }
942 
943 
944 //*************************************************************************************************************
945 
946 void RawModel::updateOperatorsConcurrently()
947 {
948  m_bProcessing = true;
949 
950  QList<int> listFilteredChs = m_assignedOperators.keys();
951  m_listTmpChData.clear();
952 
953  //get the rows which are to be filtered out of the m_data matrix. Note that this is done windows wise, hence jumps in the filtered signal might be visible
954  for(qint32 i=0; i < listFilteredChs.size(); ++i) {
955  if(m_bReloadBefore)
956  m_listTmpChData.append(QPair<int,RowVectorXd>(listFilteredChs[i],m_data.first()->dataRawOrig().row(listFilteredChs[i])));
957  else
958  m_listTmpChData.append(QPair<int,RowVectorXd>(listFilteredChs[i],m_data.last()->dataRawOrig().row(listFilteredChs[i])));
959  }
960 
961  qDebug() << "RawModel: Starting of concurrent PROCESSING operation of" << listFilteredChs.size() << "items";
962 
963  //************* here it could be also performed QtConcurrent::mapped() *************
964  // advantage: QFutureWatcher would give partial results -> signal resultsReadyAt(int idx)
965  // disadvantage: data needs to be copied twice (also to QFuture<QPair<int,RowVectorXd> > object) instead of once (to m_listTmpChData)
966 
967  //generate lambda function
968 // std::function<QPair<int,RowVectorXd> (QPair<int,RowVectorXd>&)> applyOps = [this](QPair<int,RowVectorXd>& chdata) -> QPair<int,RowVectorXd> {
969 // return applyOperatorsConcurrently(chdata);
970 // };
971 
972 // QFuture<QPair<int,RowVectorXd> > future = QtConcurrent::mapped(m_listTmpChData.begin(),m_listTmpChData.end(),applyOps);
973  //**************************************************************************************************************************************************************************
974 
975  QFuture<void > future = QtConcurrent::map(m_listTmpChData,[this](QPair<int,RowVectorXd>& chdata) {
976  return applyOperatorsConcurrently(chdata);
977  });
978 
979  m_operatorFutureWatcher.setFuture(future);
980 
981  //Wait for thread to be finished processig the data, then insert data
982  //future.waitForFinished();
983 
984  qDebug() << "RawModel: finished concurrent PROCESSING operation of" << listFilteredChs.size() << "items";
985 
986  //insertProcessedDataAll();
987 }
988 
989 
990 //*************************************************************************************************************
991 
992 void RawModel::updateOperatorsConcurrently(int windowIndex)
993 {
994  if(windowIndex >= m_data.size() || windowIndex < 0)
995  windowIndex = 0;
996 
997  QList<int> listFilteredChs = m_assignedOperators.keys();
998  m_listTmpChData.clear();
999 
1000  //get the rows which are to be filtered out of the m_data matrix. Note that this is done windows wise, hence jumps in the filtered signal might be visible
1001  for(qint32 i=0; i < listFilteredChs.size(); ++i) {
1002  if(m_bReloadBefore)
1003  m_listTmpChData.append(QPair<int,RowVectorXd>(listFilteredChs[i],m_data[windowIndex]->dataRawOrig().row(listFilteredChs[i])));
1004  else
1005  m_listTmpChData.append(QPair<int,RowVectorXd>(listFilteredChs[i],m_data[windowIndex]->dataRawOrig().row(listFilteredChs[i])));
1006  }
1007 
1008  qDebug() << "RawModel: Starting of concurrent PROCESSING operation of" << listFilteredChs.size() << "items in m_data block"<<windowIndex;
1009 
1010  //************* here it could be also performed QtConcurrent::mapped() *************
1011  // advantage: QFutureWatcher would give partial results -> signal resultsReadyAt(int idx)
1012  // disadvantage: data needs to be copied twice (also to QFuture<QPair<int,RowVectorXd> > object) instead of once (to m_listTmpChData)
1013 
1014  //generate lambda function
1015 // std::function<QPair<int,RowVectorXd> (QPair<int,RowVectorXd>&)> applyOps = [this](QPair<int,RowVectorXd>& chdata) -> QPair<int,RowVectorXd> {
1016 // return applyOperatorsConcurrently(chdata);
1017 // };
1018 
1019 // QFuture<QPair<int,RowVectorXd> > future = QtConcurrent::mapped(m_listTmpChData.begin(),m_listTmpChData.end(),applyOps);
1020  //**************************************************************************************************************************************************************************
1021 
1022  QFuture<void > future = QtConcurrent::map(m_listTmpChData,[this](QPair<int,RowVectorXd>& chdata) {
1023  return applyOperatorsConcurrently(chdata);
1024  });
1025 
1026  //Wait for thread to be finished processig the data, then insert data
1027  future.waitForFinished();
1028 
1029  qDebug() << "RawModel: finished concurrent PROCESSING operation of" << listFilteredChs.size() << "items";
1030 
1031  insertProcessedDataAll(windowIndex);
1032 }
1033 
1034 
1035 //*************************************************************************************************************
1036 
1037 void RawModel::insertProcessedDataRow(int rowIndex)
1038 {
1039  QList<int> listFilteredChs = m_assignedOperators.keys();
1040 
1041  int dataLength = m_iWindowSize;
1042  if(m_bReloadBefore)
1043  dataLength = m_data.first()->dataRaw().cols();
1044  else
1045  dataLength = m_data.last()->dataRaw().cols();
1046 
1047  int cutFront = m_iCurrentFFTLength/4;
1048  int cutBack = m_iCurrentFFTLength/4 + (m_listTmpChData[0].second.cols()-m_iCurrentFFTLength/2-dataLength);
1049 
1050  if(m_bReloadBefore)
1051  m_data.first()->setOrigProcData(m_listTmpChData[rowIndex].second, m_listTmpChData[rowIndex].first, cutFront, cutBack);
1052  else
1053  m_data.last()->setOrigProcData(m_listTmpChData[rowIndex].second, m_listTmpChData[rowIndex].first, cutFront, cutBack);
1054 
1055  performOverlapAdd();
1056 
1057  emit dataChanged(createIndex(listFilteredChs[rowIndex],1),createIndex(listFilteredChs[rowIndex],1));
1058 
1059  if(rowIndex == listFilteredChs.last())
1060  m_bProcessing = false;
1061 }
1062 
1063 
1064 //*************************************************************************************************************
1065 
1066 void RawModel::insertProcessedDataAll(int windowIndex)
1067 {
1068  if(windowIndex >= m_data.size() || windowIndex < 0 || m_assignedOperators.empty())
1069  windowIndex = 0;
1070 
1071  QList<int> listFilteredChs = m_assignedOperators.keys();
1072 
1073  int dataLength = m_data[windowIndex]->dataRaw().cols();;
1074 
1075  int cutFront = m_iCurrentFFTLength/4;
1076  int cutBack = m_iCurrentFFTLength/4 + (m_listTmpChData[0].second.cols()-m_iCurrentFFTLength/2-dataLength);
1077 
1078  //Set and cut original data to window size and calculate mean for filtered data
1079  for(int i=0; i < listFilteredChs.size(); ++i)
1080  m_data[windowIndex]->setOrigProcData(m_listTmpChData[i].second, listFilteredChs[i], cutFront, cutBack);
1081 
1082  emit dataChanged(createIndex(0,1),createIndex(m_chInfolist.size(),1));
1083 
1084  qDebug() << "RawModel: Finished inserting" << listFilteredChs.size() << "channels in window "<<windowIndex;
1085 }
1086 
1087 
1088 //*************************************************************************************************************
1089 
1090 void RawModel::insertProcessedDataAll()
1091 {
1092  QList<int> listFilteredChs = m_assignedOperators.keys();
1093 
1094  int dataLength = m_iWindowSize;
1095  if(m_bReloadBefore)
1096  dataLength = m_data.first()->dataRaw().cols();
1097  else
1098  dataLength = m_data.last()->dataRaw().cols();
1099 
1100  int cutFront = m_iCurrentFFTLength/4;
1101  int cutBack = m_iCurrentFFTLength/4 + (m_listTmpChData[0].second.cols()-m_iCurrentFFTLength/2-dataLength);
1102 
1103  //Set and cut original data to window size and calculate mean for filtered data
1104  for(int i=0; i < listFilteredChs.size(); ++i) {
1105  if(m_bReloadBefore)
1106  m_data.first()->setOrigProcData(m_listTmpChData[i].second, listFilteredChs[i], cutFront, cutBack);
1107  else
1108  m_data.last()->setOrigProcData(m_listTmpChData[i].second, listFilteredChs[i], cutFront, cutBack);
1109  }
1110 
1111  performOverlapAdd();
1112 
1113  emit dataChanged(createIndex(0,1),createIndex(m_chInfolist.size(),1));
1114 
1115  qDebug() << "RawModel: Finished inserting" << listFilteredChs.size() << "channels.";
1116  m_bProcessing = false;
1117 }
1118 
1119 
1120 //*************************************************************************************************************
1121 
1122 void RawModel::performOverlapAdd()
1123 {
1124  if(m_data.empty() || m_data.size()<2)
1125  return;
1126 
1127  QList<int> listFilteredChs = m_assignedOperators.keys();
1128 
1129  //Overlap add window data
1130  int numberWin = m_data.size();
1131  int cols = m_data[0]->dataProcOrig().cols();
1132  int filterLength = m_iCurrentFFTLength/2; //Total number of zeros which needed to be added to compensate the covolution size increasement. zeroTaper/2 zeros were added at front and back of the data
1133  int zeroFFT;
1134 
1135  //Iterate through window data
1136  for(int i = 0; i<numberWin; i++) {
1137  for(int j = 0; j<listFilteredChs.size(); j++) {
1138  RowVectorXd front = RowVectorXd::Zero(cols);
1139  RowVectorXd back = RowVectorXd::Zero(cols);
1140 
1141  //First window
1142  if(i==0) {
1143  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[i]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1144  back.segment(cols-filterLength-zeroFFT, filterLength) =
1145  m_data[i+1]->dataProcOrig().row(listFilteredChs[j]).segment(0, filterLength);
1146  }
1147 
1148  //Middle windows
1149  if(i > 0 && i < numberWin-1) {
1150  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[i-1]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1151  front.segment(0, filterLength) =
1152  m_data[i-1]->dataProcOrig().row(listFilteredChs[j]).segment(cols-filterLength-zeroFFT, filterLength);
1153 
1154  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[i]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1155  back.segment(cols-filterLength-zeroFFT, filterLength) =
1156  m_data[i+1]->dataProcOrig().row(listFilteredChs[j]).segment(0, filterLength);
1157  }
1158 
1159  //Last window
1160  if(i == numberWin-1) {
1161  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[i-1]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1162  front.segment(0, filterLength) =
1163  m_data[i-1]->dataProcOrig().row(listFilteredChs[j]).segment(cols-filterLength-zeroFFT, filterLength);
1164  }
1165 
1166  //Do the overlap add
1167  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[i]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1168  m_data[i]->setMappedProcData(m_data[i]->dataProcOrig().row(listFilteredChs[j])+front+back,
1169  listFilteredChs[j],
1170  filterLength/2,
1171  filterLength/2+zeroFFT);
1172 
1173 // QFile file("D:/inputData.txt");
1174 // file.open(QFile::WriteOnly | QFile::Text);
1175 // QTextStream out(&file);
1176 
1177 // for(int i=0; i < m_listTmpChData[0].second.cols(); ++i)
1178 // out << m_listTmpChData[0].second(0,i) << endl;
1179 
1180 // file.close();
1181 
1182 // QFile file1("D:/front.txt");
1183 // file1.open(QFile::WriteOnly | QFile::Text);
1184 // QTextStream out1(&file1);
1185 
1186 // for(int i=0; i < front.cols(); ++i)
1187 // out1 << front(0,i) << endl;
1188 
1189 // file1.close();
1190 
1191 // QFile file2("D:/back.txt");
1192 // file2.open(QFile::WriteOnly | QFile::Text);
1193 // QTextStream out2(&file2);
1194 
1195 // for(int i=0; i < back.cols(); ++i)
1196 // out2 << back(0,i) << endl;
1197 
1198 // file2.close();
1199 
1200 // RowVectorXd result = m_listTmpChData[j].second+front+back;
1201 // QFile file3("D:/result.txt");
1202 // file3.open(QFile::WriteOnly | QFile::Text);
1203 // QTextStream out3(&file3);
1204 
1205 // for(int i=0; i < result.cols(); ++i)
1206 // out3 << result(0,i) << endl;
1207 
1208 // file3.close();
1209  }
1210  }
1211 }
1212 
1213 
1214 //*************************************************************************************************************
1215 
1216 void RawModel::performOverlapAdd(int windowIndex)
1217 {
1218  if(windowIndex<0 || windowIndex>m_data.size()-1 || m_data.size()<2)
1219  return;
1220 
1221  QList<int> listFilteredChs = m_assignedOperators.keys();
1222 
1223  //Overlap add window data
1224  int numberWin = m_data.size();
1225  int cols = m_data[windowIndex]->dataProcOrig().cols();
1226  int filterLength = m_iCurrentFFTLength/2; //Total number of zeros which needed to be added to compensate the covolution size increasement. zeroTaper/2 zeros were added at front and back of the data
1227  int zeroFFT;
1228 
1229  for(int j = 0; j<listFilteredChs.size(); j++) {
1230  RowVectorXd front = RowVectorXd::Zero(cols);
1231  RowVectorXd back = RowVectorXd::Zero(cols);
1232 
1233  //First window
1234  if(windowIndex==0) {
1235  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[windowIndex]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1236  back.segment(cols-filterLength-zeroFFT, filterLength) =
1237  m_data[windowIndex+1]->dataProcOrig().row(listFilteredChs[j]).segment(0, filterLength);
1238  }
1239 
1240  //Middle windows
1241  if(windowIndex > 0 && windowIndex < numberWin-1) {
1242  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[windowIndex-1]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1243  front.segment(0, filterLength) =
1244  m_data[windowIndex-1]->dataProcOrig().row(listFilteredChs[j]).segment(cols-filterLength-zeroFFT, filterLength);
1245 
1246  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[windowIndex]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1247  back.segment(cols-filterLength-zeroFFT, filterLength) =
1248  m_data[windowIndex+1]->dataProcOrig().row(listFilteredChs[j]).segment(0, filterLength);
1249  }
1250 
1251  //Last window
1252  if(windowIndex == numberWin-1) {
1253  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[windowIndex-1]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1254  front.segment(0, filterLength) =
1255  m_data[windowIndex-1]->dataProcOrig().row(listFilteredChs[j]).segment(cols-filterLength-zeroFFT, filterLength);
1256  }
1257 
1258  //Do the overlap add
1259  zeroFFT = m_iCurrentFFTLength - filterLength - m_data[windowIndex]->dataRaw().cols(); //The total number of zeros added to compensate for multiple integer of 2^x
1260  m_data[windowIndex]->setMappedProcData(m_data[windowIndex]->dataProcOrig().row(listFilteredChs[j])+front+back,
1261  listFilteredChs[j],
1262  filterLength/2,
1263  filterLength/2+zeroFFT);
1264  }
1265 }
QSharedPointer< FiffIO > m_pfiffIO
Definition: rawmodel.h:182
void fileLoaded(const FiffInfo &)
FIFF measurement file information.
Definition: fiff_info.h:96
The DataPackage class provides central place to hold all program relevant data.
Definition: datapackage.h:88
QList< FiffChInfo > m_chInfolist
Definition: rawmodel.h:180
void updateScrollPos(int value)
Definition: rawmodel.cpp:628
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
Definition: rawmodel.cpp:152
void applyOperatorsConcurrently(QPair< int, RowVectorXd > &chdata) const
Definition: rawmodel.cpp:759
RowVectorXd applyFFTFilter(const RowVectorXd &data) const
void applyOperator(QModelIndexList chlist, const QSharedPointer< MNEOperator > &operatorPtr, const QString &chType)
Definition: rawmodel.cpp:681
void markChBad(QModelIndexList chlist, bool status)
Definition: rawmodel.cpp:656
QSharedPointer< FiffStream > SPtr
Definition: fiff_stream.h:132
QMap< QString, QSharedPointer< MNEOperator > > m_Operators
Definition: rawmodel.h:183
This class represents the model of the model/view framework of mne_browse_raw_qt application. It is derived from QAbstractTableModel so the virtual functions rowCount(),columnCount() and data() needed to be reimplemented. The delegate requests the data for any individual table cell by invoking data(QModelIndex index, int role) and a certain role. DisplayRole is the standard role for requesting the plain data. Other roles such as BackgroundRole are requested to fill a cell with a certain background color with respect to the individual index. For further information see [1].
bool writeFiffData(QIODevice *p_IODevice)
Definition: rawmodel.cpp:411
void assignedOperatorsChanged(const QMap< int, QSharedPointer< MNEOperator > > &)
qint32 firstSample() const
Definition: rawmodel.h:512
bool loadFiffData(QFile *qFile)
Definition: rawmodel.cpp:362
qint32 sizeOfPreloadedData() const
Definition: rawmodel.h:530
qint32 lastSample() const
Definition: rawmodel.h:521