MNE-CPP  beta 1.0
fiff_stream.cpp
Go to the documentation of this file.
1 //=============================================================================================================
36 //*************************************************************************************************************
37 //=============================================================================================================
38 // INCLUDES
39 //=============================================================================================================
40 
41 #include "fiff_stream.h"
42 #include "fiff_tag.h"
43 #include "fiff_dir_tree.h"
44 #include "fiff_ctf_comp.h"
45 #include "fiff_info.h"
46 #include "fiff_info_base.h"
47 #include "fiff_raw_data.h"
48 #include "fiff_cov.h"
49 
50 #include <utils/mnemath.h>
51 
52 
53 //*************************************************************************************************************
54 //=============================================================================================================
55 // Qt INCLUDES
56 //=============================================================================================================
57 
58 #include <QFile>
59 
60 
61 //*************************************************************************************************************
62 //=============================================================================================================
63 // USED NAMESPACES
64 //=============================================================================================================
65 
66 using namespace FIFFLIB;
67 using namespace UTILSLIB;
68 
69 
70 //*************************************************************************************************************
71 //=============================================================================================================
72 // DEFINE MEMBER METHODS
73 //=============================================================================================================
74 
75 FiffStream::FiffStream(QIODevice *p_pIODevice)
76 : QDataStream(p_pIODevice)
77 {
78  this->setFloatingPointPrecision(QDataStream::SinglePrecision);
79  this->setByteOrder(QDataStream::BigEndian);
80  this->setVersion(QDataStream::Qt_5_0);
81 }
82 
83 
84 //*************************************************************************************************************
85 
86 FiffStream::FiffStream(QByteArray * a, QIODevice::OpenMode mode)
87 : QDataStream(a, mode)
88 {
89  this->setFloatingPointPrecision(QDataStream::SinglePrecision);
90  this->setByteOrder(QDataStream::BigEndian);
91  this->setVersion(QDataStream::Qt_5_0);
92 }
93 
94 
95 //*************************************************************************************************************
96 
98 {
99  //ToDo check if all IO devices are closed outside --> don't do this here!!
100 // printf("DEBUG: check if FiffStream::IODevice is closed else where. Cause here it's not anymore.");
101 
102 // if(this->device()->isOpen())
103 // {
104 // printf("DEBUG: Closing FiffStream %s.\n\n", this->streamName().toUtf8().constData());
105 // this->device()->close();
106 // }
107 }
108 
109 
110 //*************************************************************************************************************
111 
112 void FiffStream::end_block(fiff_int_t kind)
113 {
114  this->write_int(FIFF_BLOCK_END,&kind);
115 }
116 
117 
118 //*************************************************************************************************************
119 
121 {
122  fiff_int_t datasize = 0;
123 
124  *this << (qint32)FIFF_NOP;
125  *this << (qint32)FIFFT_VOID;
126  *this << (qint32)datasize;
127  *this << (qint32)FIFFV_NEXT_NONE;
128 }
129 
130 
131 //*************************************************************************************************************
132 
134 {
135  this->end_block(FIFFB_RAW_DATA);
136  this->end_block(FIFFB_MEAS);
137  this->end_file();
138  this->device()->close();
139 }
140 
141 
142 //*************************************************************************************************************
143 
144 bool FiffStream::get_evoked_entries(const QList<FiffDirTree> &evoked_node, QStringList &comments, QList<fiff_int_t> &aspect_kinds, QString &t)
145 {
146  comments.clear();
147  aspect_kinds.clear();
148  QList<FiffDirTree>::ConstIterator ev;
149 
150  FiffTag::SPtr t_pTag;
151  qint32 kind, pos, k;
152 
153  for(ev = evoked_node.begin(); ev != evoked_node.end(); ++ev)
154  {
155  for(k = 0; k < ev->nent; ++k)
156  {
157  kind = ev->dir[k].kind;
158  pos = ev->dir[k].pos;
159  if (kind == FIFF_COMMENT)
160  {
161  FiffTag::read_tag(this,t_pTag,pos);
162  comments.append(t_pTag->toString());
163  }
164  }
165  FiffDirTree my_aspect = ev->dir_tree_find(FIFFB_ASPECT)[0];
166  for(k = 0; k < my_aspect.nent; ++k)
167  {
168  kind = my_aspect.dir[k].kind;
169  pos = my_aspect.dir[k].pos;
170  if (kind == FIFF_ASPECT_KIND)
171  {
172  FiffTag::read_tag(this,t_pTag,pos);
173  aspect_kinds.append(*t_pTag->toInt());
174  }
175  }
176  }
177 
178  if(comments.size() != aspect_kinds.size() || comments.size() == 0)
179  {
180  qWarning("Dataset names in FIF file could not be found.");
181  return false;
182  }
183 
184  t = QString();
185  for(k = 0; k < aspect_kinds.size(); ++k)
186  {
187  t += QString("%1 - \"%2\" (").arg(k).arg(comments[k]);
188  if(aspect_kinds[k] == FIFFV_ASPECT_AVERAGE)
189  t += QString("FIFFV_ASPECT_AVERAGE)\n");
190  else if(aspect_kinds[k] == FIFFV_ASPECT_STD_ERR)
191  t += QString("FIFFV_ASPECT_STD_ERR)\n");
192  else
193  t += QString("unknown)\n");
194  }
195 
196  return true;
197 }
198 
199 
200 //*************************************************************************************************************
201 
202 bool FiffStream::open(FiffDirTree& p_Tree, QList<FiffDirEntry>& p_Dir)
203 {
204  QString t_sFileName = this->streamName();
205 
206  if (!this->device()->open(QIODevice::ReadOnly))
207  {
208  printf("Cannot open %s\n", t_sFileName.toUtf8().constData());//consider throw
209  return false;
210  }
211 
212  FiffTag::SPtr t_pTag;
213  FiffTag::read_tag_info(this, t_pTag);
214 
215  if (t_pTag->kind != FIFF_FILE_ID)
216  {
217  printf("Fiff::open: file does not start with a file id tag");//consider throw
218  return false;
219  }
220 
221  if (t_pTag->type != FIFFT_ID_STRUCT)
222  {
223  printf("Fiff::open: file does not start with a file id tag");//consider throw
224  return false;
225  }
226  if (t_pTag->size() != 20)
227  {
228  printf("Fiff::open: file does not start with a file id tag");//consider throw
229  return false;
230  }
231 
232  FiffTag::read_tag(this, t_pTag);
233 
234  if (t_pTag->kind != FIFF_DIR_POINTER)
235  {
236  printf("Fiff::open: file does have a directory pointer");//consider throw
237  return false;
238  }
239 
240  //
241  // Read or create the directory tree
242  //
243  printf("\nCreating tag directory for %s...", t_sFileName.toUtf8().constData());
244 
245  p_Dir.clear();
246  qint32 dirpos = *t_pTag->toInt();
247  if (dirpos > 0)
248  {
249  FiffTag::read_tag(this, t_pTag, dirpos);
250  p_Dir = t_pTag->toDirEntry();
251  }
252  else
253  {
254  qint32 k = 0;
255  this->device()->seek(0);//fseek(fid,0,'bof');
256  FiffDirEntry t_fiffDirEntry;
257  while (t_pTag->next >= 0)
258  {
259  t_fiffDirEntry.pos = this->device()->pos();//pos = ftell(fid);
260  FiffTag::read_tag_info(this, t_pTag);
261  ++k;
262  t_fiffDirEntry.kind = t_pTag->kind;
263  t_fiffDirEntry.type = t_pTag->type;
264  t_fiffDirEntry.size = t_pTag->size();
265  p_Dir.append(t_fiffDirEntry);
266  }
267  }
268  //
269  // Create the directory tree structure
270  //
271 
272  FiffDirTree::make_dir_tree(this, p_Dir, p_Tree);
273 
274  printf("[done]\n");
275 
276  //
277  // Back to the beginning
278  //
279  this->device()->seek(0); //fseek(fid,0,'bof');
280  return true;
281 }
282 
283 
284 //*************************************************************************************************************
285 
286 QStringList FiffStream::read_bad_channels(const FiffDirTree& p_Node)
287 {
288  QList<FiffDirTree> node = p_Node.dir_tree_find(FIFFB_MNE_BAD_CHANNELS);
289  FiffTag::SPtr t_pTag;
290 
291  QStringList bads;
292 
293  if (node.size() > 0)
294  if(node[0].find_tag(this, FIFF_MNE_CH_NAME_LIST, t_pTag))
295  bads = split_name_list(t_pTag->toString());
296 
297  return bads;
298 }
299 
300 
301 //*************************************************************************************************************
302 
303 bool FiffStream::read_cov(const FiffDirTree& p_Node, fiff_int_t cov_kind, FiffCov& p_covData)
304 {
305  p_covData.clear();
306 
307  //
308  // Find all covariance matrices
309  //
310  QList<FiffDirTree> covs = p_Node.dir_tree_find(FIFFB_MNE_COV);
311  if (covs.size() == 0)
312  {
313  printf("No covariance matrices found");
314  return false;
315  }
316  //
317  // Is any of the covariance matrices a noise covariance
318  //
319  qint32 p = 0;
320  FiffTag::SPtr tag;
321  bool success = false;
322  fiff_int_t dim, nfree, nn;
323  QStringList names;
324  bool diagmat = false;
325  VectorXd eig;
326  MatrixXd eigvec;
327  VectorXd cov_diag;
328  MatrixXd cov;
329  VectorXd cov_sparse;
330  QStringList bads;
331  for(p = 0; p < covs.size(); ++p)
332  {
333  success = covs[p].find_tag(this, FIFF_MNE_COV_KIND, tag);
334  if (success && *tag->toInt() == cov_kind)
335  {
336  FiffDirTree* current = &covs[p];
337  //
338  // Find all the necessary data
339  //
340  if (!current->find_tag(this, FIFF_MNE_COV_DIM, tag))
341  {
342  printf("Covariance matrix dimension not found.\n");
343  return false;
344  }
345  dim = *tag->toInt();
346  if (!current->find_tag(this, FIFF_MNE_COV_NFREE, tag))
347  nfree = -1;
348  else
349  nfree = *tag->toInt();
350 
351  if (current->find_tag(this, FIFF_MNE_ROW_NAMES, tag))
352  {
353  names = FiffStream::split_name_list(tag->toString());
354  if (names.size() != dim)
355  {
356  printf("Number of names does not match covariance matrix dimension\n");
357  return false;
358  }
359  }
360  if (!current->find_tag(this, FIFF_MNE_COV, tag))
361  {
362  if (!current->find_tag(this, FIFF_MNE_COV_DIAG, tag))
363  {
364  printf("No covariance matrix data found\n");
365  return false;
366  }
367  else
368  {
369  //
370  // Diagonal is stored
371  //
372  if (tag->type == FIFFT_DOUBLE)
373  {
374  cov_diag = Map<VectorXd>(tag->toDouble(),dim);
375  }
376  else if (tag->type == FIFFT_FLOAT)
377  {
378  cov_diag = Map<VectorXf>(tag->toFloat(),dim).cast<double>();
379  }
380  else {
381  printf("Illegal data type for covariance matrix\n");
382  return false;
383  }
384 
385  diagmat = true;
386  printf("\t%d x %d diagonal covariance (kind = %d) found.\n", dim, dim, cov_kind);
387  }
388  }
389  else
390  {
391  VectorXd vals;
392  nn = dim*(dim+1)/2;
393  if (tag->type == FIFFT_DOUBLE)
394  {
395  vals = Map<VectorXd>(tag->toDouble(),nn);
396  }
397  else if (tag->type == FIFFT_FLOAT)
398  {
399  vals = Map<VectorXf>(tag->toFloat(),nn).cast<double>();
400  }
401  else
402  {
403  qDebug() << tag->getInfo();
404  return false;
405  }
406 
407  if(!MNEMath::issparse(vals))
408  {
409  //
410  // Lower diagonal is stored
411  //
412  cov = MatrixXd::Zero(dim,dim);
413 
414  // XXX : should remove for loops
415  qint32 q = 0;
416  for(qint32 j = 0; j < dim; ++j)
417  {
418  for(qint32 k = 0; k <= j; ++k)
419  {
420  cov(j,k) = vals(q);
421  ++q;
422  }
423  }
424  for(qint32 j = 0; j < dim; ++j)
425  for(qint32 k = j+1; k < dim; ++k)
426  cov(j,k) = cov(k,j);
427 
428  diagmat = false;
429  printf("\t%d x %d full covariance (kind = %d) found.\n", dim, dim, cov_kind);
430 
431  }
432  else
433  {
434  diagmat = false;
435  qDebug() << "ToDo: FiffStream::read_cov - this needs to be debugged.\n";
436  cov = vals;
437  printf("\t%d x %d sparse covariance (kind = %d) found.\n", dim, dim, cov_kind);
438  }
439 //MATLAB
440 // if ~issparse(tag.data)
441 // //
442 // // Lower diagonal is stored
443 // //
444 // qDebug() << tag->getInfo();
445 // vals = tag.data;
446 // data = zeros(dim,dim);
447 // % XXX : should remove for loops
448 // q = 1;
449 // for j = 1:dim
450 // for k = 1:j
451 // data(j,k) = vals(q);
452 // q = q + 1;
453 // end
454 // end
455 // for j = 1:dim
456 // for k = j+1:dim
457 // data(j,k) = data(k,j);
458 // end
459 // end
460 // diagmat = false;
461 // fprintf('\t%d x %d full covariance (kind = %d) found.\n',dim,dim,cov_kind);
462 // else
463 // diagmat = false;
464 // data = tag.data;
465 // fprintf('\t%d x %d sparse covariance (kind = %d) found.\n',dim,dim,cov_kind);
466 // end
467 //MATLAB END
468  }
469  //
470  // Read the possibly precomputed decomposition
471  //
472  FiffTag::SPtr tag1;
473  FiffTag::SPtr tag2;
474  if (current->find_tag(this, FIFF_MNE_COV_EIGENVALUES, tag1) && current->find_tag(this, FIFF_MNE_COV_EIGENVECTORS, tag2))
475  {
476  eig = VectorXd(Map<VectorXd>(tag1->toDouble(),dim));
477  eigvec = tag2->toFloatMatrix().cast<double>();
478  eigvec.transposeInPlace();
479  }
480  //
481  // Read the projection operator
482  //
483  QList<FiffProj> projs = this->read_proj(*current);
484  //
485  // Read the bad channel list
486  //
487  bads = this->read_bad_channels(*current);
488  //
489  // Put it together
490  //
491  p_covData.clear();
492 
493  p_covData.kind = cov_kind;
494  p_covData.diag = diagmat;
495  p_covData.dim = dim;
496  p_covData.names = names;
497 
498  if(cov_diag.size() > 0)
499  p_covData.data = cov_diag;
500  else if(cov.size() > 0)
501  p_covData.data = cov;
502  else if(cov_sparse.size() > 0)
503  p_covData.data = cov_sparse;
504 
505  p_covData.projs = projs;
506  p_covData.bads = bads;
507  p_covData.nfree = nfree;
508  p_covData.eig = eig;
509  p_covData.eigvec = eigvec;
510 
511  //
512  return true;
513  }
514  }
515 
516  printf("Did not find the desired covariance matrix\n");
517  return false;
518 }
519 
520 
521 //*************************************************************************************************************
522 
523 QList<FiffCtfComp> FiffStream::read_ctf_comp(const FiffDirTree& p_Node, const QList<FiffChInfo>& p_Chs)
524 {
525  QList<FiffCtfComp> compdata;
526  QList<FiffDirTree> t_qListComps = p_Node.dir_tree_find(FIFFB_MNE_CTF_COMP_DATA);
527 
528  qint32 i, k, p, col, row;
529  fiff_int_t kind, pos;
530  FiffTag::SPtr t_pTag;
531  for (k = 0; k < t_qListComps.size(); ++k)
532  {
533  FiffDirTree* node = &t_qListComps[k];
534  //
535  // Read the data we need
536  //
538  this->read_named_matrix(*node, FIFF_MNE_CTF_COMP_DATA, *mat.data());
539  for(p = 0; p < node->nent; ++p)
540  {
541  kind = node->dir.at(p).kind;
542  pos = node->dir.at(p).pos;
543  if (kind == FIFF_MNE_CTF_COMP_KIND)
544  {
545  FiffTag::read_tag(this, t_pTag, pos);
546  break;
547  }
548  }
549  if (!t_pTag)
550  {
551  printf("Compensation type not found\n");
552  return compdata;
553  }
554  //
555  // Get the compensation kind and map it to a simple number
556  //
557  FiffCtfComp one;
558  one.ctfkind = *t_pTag->toInt();
559 
560  t_pTag.clear();
561 
562  one.kind = -1;
563  if (one.ctfkind == 1194410578) //hex2dec('47314252')
564  one.kind = 1;
565  else if (one.ctfkind == 1194476114) //hex2dec('47324252')
566  one.kind = 2;
567  else if (one.ctfkind == 1194541650) //hex2dec('47334252')
568  one.kind = 3;
569  else
570  one.kind = one.ctfkind;
571 
572  for (p = 0; p < node->nent; ++p)
573  {
574  kind = node->dir.at(p).kind;
575  pos = node->dir.at(p).pos;
576  if (kind == FIFF_MNE_CTF_COMP_CALIBRATED)
577  {
578  FiffTag::read_tag(this, t_pTag, pos);
579  break;
580  }
581  }
582  bool calibrated;
583  if (!t_pTag)
584  calibrated = false;
585  else
586  calibrated = (bool)*t_pTag->toInt();
587 
588  one.save_calibrated = calibrated;
589  one.rowcals = MatrixXd::Ones(1,mat->data.rows());//ones(1,size(mat.data,1));
590  one.colcals = MatrixXd::Ones(1,mat->data.cols());//ones(1,size(mat.data,2));
591  if (!calibrated)
592  {
593  //
594  // Calibrate...
595  //
596  //
597  // Do the columns first
598  //
599  QStringList ch_names;
600  for (p = 0; p < p_Chs.size(); ++p)
601  ch_names.append(p_Chs[p].ch_name);
602 
603  qint32 count;
604  MatrixXd col_cals(mat->data.cols(), 1);
605  col_cals.setZero();
606  for (col = 0; col < mat->data.cols(); ++col)
607  {
608  count = 0;
609  for (i = 0; i < ch_names.size(); ++i)
610  {
611  if (QString::compare(mat->col_names.at(col),ch_names.at(i)) == 0)
612  {
613  count += 1;
614  p = i;
615  }
616  }
617  if (count == 0)
618  {
619  printf("Channel %s is not available in data",mat->col_names.at(col).toUtf8().constData());
620  return compdata;
621  }
622  else if (count > 1)
623  {
624  printf("Ambiguous channel %s",mat->col_names.at(col).toUtf8().constData());
625  return compdata;
626  }
627  col_cals(col,0) = 1.0f/(p_Chs[p].range*p_Chs[p].cal);
628  }
629  //
630  // Then the rows
631  //
632  MatrixXd row_cals(mat->data.rows(), 1);
633  row_cals.setZero();
634  for (row = 0; row < mat->data.rows(); ++row)
635  {
636  count = 0;
637  for (i = 0; i < ch_names.size(); ++i)
638  {
639  if (QString::compare(mat->row_names.at(row),ch_names.at(i)) == 0)
640  {
641  count += 1;
642  p = i;
643  }
644  }
645 
646  if (count == 0)
647  {
648  printf("Channel %s is not available in data",mat->row_names.at(row).toUtf8().constData());
649  return compdata;
650  }
651  else if (count > 1)
652  {
653  printf("Ambiguous channel %s",mat->row_names.at(row).toUtf8().constData());
654  return compdata;
655  }
656 
657  row_cals(row, 0) = p_Chs[p].range*p_Chs[p].cal;
658  }
659  mat->data = row_cals.asDiagonal()* mat->data *col_cals.asDiagonal();
660  one.rowcals = row_cals;
661  one.colcals = col_cals;
662  }
663  one.data = mat;
664  compdata.append(one);
665  }
666 
667  if (compdata.size() > 0)
668  printf("\tRead %d compensation matrices\n",compdata.size());
669 
670  return compdata;
671 }
672 
673 
674 //*************************************************************************************************************
675 
676 bool FiffStream::read_meas_info_base(const FiffDirTree& p_Node, FiffInfoBase& p_InfoForward)
677 {
678  p_InfoForward.clear();
679 
680  //
681  // Find the desired blocks
682  //
683  QList<FiffDirTree> parent_meg = p_Node.dir_tree_find(FIFFB_MNE_PARENT_MEAS_FILE);
684 
685  if (parent_meg.size() == 0)
686  {
687  printf("No parent MEG information found in operator\n");
688  return false;
689  }
690 
691  FiffTag::SPtr t_pTag;
692 
693  QList<FiffChInfo> chs;
694  FiffCoordTrans cand;
695  fiff_int_t kind = -1;
696  fiff_int_t pos = -1;
697 
698  for (qint32 k = 0; k < parent_meg[0].nent; ++k)
699  {
700  kind = parent_meg[0].dir[k].kind;
701  pos = parent_meg[0].dir[k].pos;
702  if (kind == FIFF_CH_INFO)
703  {
704  FiffTag::read_tag(this, t_pTag, pos);
705  chs.append( t_pTag->toChInfo() );
706  }
707  }
708 
709  //
710  // Add the channel information and make a list of channel names
711  // for convenience
712  //
713  p_InfoForward.chs = chs;
714  for (qint32 c = 0; c < p_InfoForward.chs.size(); ++c)
715  p_InfoForward.ch_names << p_InfoForward.chs[c].ch_name;
716 
717  p_InfoForward.nchan = chs.size();
718 
719  //
720  // Get the MEG device <-> head coordinate transformation
721  //
722  if(parent_meg[0].find_tag(this, FIFF_COORD_TRANS, t_pTag))
723  {
724  cand = t_pTag->toCoordTrans();
725  if(cand.from == FIFFV_COORD_DEVICE && cand.to == FIFFV_COORD_HEAD)
726  p_InfoForward.dev_head_t = cand;
727  else if (cand.from == FIFFV_MNE_COORD_CTF_HEAD && cand.to == FIFFV_COORD_HEAD)
728  p_InfoForward.ctf_head_t = cand;
729  else
730  printf("MEG device/head coordinate transformation not found");
731  }
732  else
733  printf("MEG/head coordinate transformation not found.\n");
734 
735  //
736  // Load the bad channel list
737  //
738  p_InfoForward.bads = this->read_bad_channels(p_Node);
739 
740  return true;
741 }
742 
743 
744 //*************************************************************************************************************
745 
746 bool FiffStream::read_meas_info(const FiffDirTree& p_Node, FiffInfo& info, FiffDirTree& p_NodeInfo)
747 {
748 // if (info)
749 // delete info;
750  info.clear();
751  //
752  // Find the desired blocks
753  //
754  QList<FiffDirTree> meas = p_Node.dir_tree_find(FIFFB_MEAS);
755 
756  if (meas.size() == 0)
757  {
758  printf("Could not find measurement data\n");
759  return false;
760  }
761  //
762  QList<FiffDirTree> meas_info = meas[0].dir_tree_find(FIFFB_MEAS_INFO);
763  if (meas_info.count() == 0)
764  {
765  printf("Could not find measurement info\n");
766 // delete meas[0];
767  return false;
768  }
769  //
770  // Read measurement info
771  //
772  FiffTag::SPtr t_pTag;
773 
774  fiff_int_t nchan = -1;
775  float sfreq = -1.0f;
776  QList<FiffChInfo> chs;
777  float lowpass = -1.0f;
778  float highpass = -1.0f;
779 
780  FiffChInfo t_chInfo;
781 
782  FiffCoordTrans cand;// = NULL;
783  FiffCoordTrans dev_head_t;// = NULL;
784  FiffCoordTrans ctf_head_t;// = NULL;
785 
786  fiff_int_t meas_date[2];
787  meas_date[0] = -1;
788  meas_date[1] = -1;
789 
790  fiff_int_t kind = -1;
791  fiff_int_t pos = -1;
792 
793  for (qint32 k = 0; k < meas_info[0].nent; ++k)
794  {
795  kind = meas_info[0].dir[k].kind;
796  pos = meas_info[0].dir[k].pos;
797  switch (kind)
798  {
799  case FIFF_NCHAN:
800  FiffTag::read_tag(this, t_pTag, pos);
801  nchan = *t_pTag->toInt();
802  break;
803  case FIFF_SFREQ:
804  FiffTag::read_tag(this, t_pTag, pos);
805  sfreq = *t_pTag->toFloat();
806  break;
807  case FIFF_CH_INFO:
808  FiffTag::read_tag(this, t_pTag, pos);
809  chs.append( t_pTag->toChInfo() );
810  break;
811  case FIFF_LOWPASS:
812  FiffTag::read_tag(this, t_pTag, pos);
813  lowpass = *t_pTag->toFloat();
814  break;
815  case FIFF_HIGHPASS:
816  FiffTag::read_tag(this, t_pTag, pos);
817  highpass = *t_pTag->toFloat();
818  break;
819  case FIFF_MEAS_DATE:
820  FiffTag::read_tag(this, t_pTag, pos);
821  meas_date[0] = t_pTag->toInt()[0];
822  meas_date[1] = t_pTag->toInt()[1];
823  break;
824  case FIFF_COORD_TRANS:
825  //ToDo: This has to be debugged!!
826  FiffTag::read_tag(this, t_pTag, pos);
827  cand = t_pTag->toCoordTrans();
828  if(cand.from == FIFFV_COORD_DEVICE && cand.to == FIFFV_COORD_HEAD)
829  dev_head_t = cand;
830  else if (cand.from == FIFFV_MNE_COORD_CTF_HEAD && cand.to == FIFFV_COORD_HEAD)
831  ctf_head_t = cand;
832  break;
833  }
834  }
835  //
836  // Check that we have everything we need
837  //
838  if (nchan < 0)
839  {
840  printf("Number of channels in not defined\n");
841  return false;
842  }
843  if (sfreq < 0)
844  {
845  printf("Sampling frequency is not defined\n");
846  return false;
847  }
848  if (chs.size() == 0)
849  {
850  printf("Channel information not defined\n");
851  return false;
852  }
853  if (chs.size() != nchan)
854  {
855  printf("Incorrect number of channel definitions found\n");
856  return false;
857  }
858 
859  if (dev_head_t.isEmpty() || ctf_head_t.isEmpty())
860  {
861  QList<FiffDirTree> hpi_result = meas_info[0].dir_tree_find(FIFFB_HPI_RESULT);
862  if (hpi_result.size() == 1)
863  {
864  for( qint32 k = 0; k < hpi_result[0].nent; ++k)
865  {
866  kind = hpi_result[0].dir[k].kind;
867  pos = hpi_result[0].dir[k].pos;
868  if (kind == FIFF_COORD_TRANS)
869  {
870  FiffTag::read_tag(this, t_pTag, pos);
871  cand = t_pTag->toCoordTrans();
872  if (cand.from == FIFFV_COORD_DEVICE && cand.to == FIFFV_COORD_HEAD)
873  dev_head_t = cand;
874  else if (cand.from == FIFFV_MNE_COORD_CTF_HEAD && cand.to == FIFFV_COORD_HEAD)
875  ctf_head_t = cand;
876  }
877  }
878  }
879  }
880  //
881  // Locate the Polhemus data
882  //
883  QList<FiffDirTree> isotrak = meas_info[0].dir_tree_find(FIFFB_ISOTRAK);
884 
885  QList<FiffDigPoint> dig;
886  fiff_int_t coord_frame = FIFFV_COORD_HEAD;
887  FiffCoordTrans dig_trans;
888  qint32 k = 0;
889 
890  if (isotrak.size() == 1)
891  {
892  for (k = 0; k < isotrak[0].nent; ++k)
893  {
894  kind = isotrak[0].dir[k].kind;
895  pos = isotrak[0].dir[k].pos;
896  if (kind == FIFF_DIG_POINT)
897  {
898  FiffTag::read_tag(this, t_pTag, pos);
899  dig.append(t_pTag->toDigPoint());
900  }
901  else
902  {
903  if (kind == FIFF_MNE_COORD_FRAME)
904  {
905  FiffTag::read_tag(this, t_pTag, pos);
906  qDebug() << "NEEDS To BE DEBBUGED: FIFF_MNE_COORD_FRAME" << t_pTag->getType();
907  coord_frame = *t_pTag->toInt();
908  }
909  else if (kind == FIFF_COORD_TRANS)
910  {
911  FiffTag::read_tag(this, t_pTag, pos);
912  qDebug() << "NEEDS To BE DEBBUGED: FIFF_COORD_TRANS" << t_pTag->getType();
913  dig_trans = t_pTag->toCoordTrans();
914  }
915  }
916  }
917  }
918  for(k = 0; k < dig.size(); ++k)
919  dig[k].coord_frame = coord_frame;
920 
921  if (!dig_trans.isEmpty()) //if exist('dig_trans','var')
922  if (dig_trans.from != coord_frame && dig_trans.to != coord_frame)
923  dig_trans.clear();
924 
925  //
926  // Locate the acquisition information
927  //
928  QList<FiffDirTree> acqpars = meas_info[0].dir_tree_find(FIFFB_DACQ_PARS);
929  QString acq_pars;
930  QString acq_stim;
931  if (acqpars.size() == 1)
932  {
933  for( k = 0; k < acqpars[0].nent; ++k)
934  {
935  kind = acqpars[0].dir.at(k).kind;
936  pos = acqpars[0].dir.at(k).pos;
937  if (kind == FIFF_DACQ_PARS)
938  {
939  FiffTag::read_tag(this, t_pTag, pos);
940  acq_pars = t_pTag->toString();
941  }
942  else if (kind == FIFF_DACQ_STIM)
943  {
944  FiffTag::read_tag(this, t_pTag, pos);
945  acq_stim = t_pTag->toString();
946  }
947  }
948  }
949  //
950  // Load the SSP data
951  //
952  QList<FiffProj> projs = this->read_proj(meas_info[0]);//ToDo Member Function
953  //
954  // Load the CTF compensation data
955  //
956  QList<FiffCtfComp> comps = this->read_ctf_comp(meas_info[0], chs);//ToDo Member Function
957  //
958  // Load the bad channel list
959  //
960  QStringList bads = this->read_bad_channels(p_Node);
961  //
962  // Put the data together
963  //
964 // info = new FiffInfo();
965  if (p_Node.id.version != -1)
966  info.file_id = p_Node.id;
967  else
968  info.file_id.version = -1;
969 
970  //
971  // Make the most appropriate selection for the measurement id
972  //
973  if (meas_info[0].parent_id.version == -1)
974  {
975  if (meas_info[0].id.version == -1)
976  {
977  if (meas[0].id.version == -1)
978  {
979  if (meas[0].parent_id.version == -1)
980  info.meas_id = info.file_id;
981  else
982  info.meas_id = meas[0].parent_id;
983  }
984  else
985  info.meas_id = meas[0].id;
986  }
987  else
988  info.meas_id = meas_info[0].id;
989  }
990  else
991  info.meas_id = meas_info[0].parent_id;
992 
993  if (meas_date[0] == -1)
994  {
995  info.meas_date[0] = info.meas_id.time.secs;
996  info.meas_date[1] = info.meas_id.time.usecs;
997  }
998  else
999  {
1000  info.meas_date[0] = meas_date[0];
1001  info.meas_date[1] = meas_date[1];
1002  }
1003 
1004  info.nchan = nchan;
1005  info.sfreq = sfreq;
1006  if (highpass != -1.0f)
1007  info.highpass = highpass;
1008  else
1009  info.highpass = 0.0f;
1010 
1011  if (lowpass != -1.0f)
1012  info.lowpass = lowpass;
1013  else
1014  info.lowpass = info.sfreq/2.0;
1015 
1016  //
1017  // Add the channel information and make a list of channel names
1018  // for convenience
1019  //
1020  info.chs = chs;
1021  for (qint32 c = 0; c < info.nchan; ++c)
1022  info.ch_names << info.chs[c].ch_name;
1023 
1024  //
1025  // Add the coordinate transformations
1026  //
1027  info.dev_head_t = dev_head_t;
1028  info.ctf_head_t = ctf_head_t;
1029  if ((!info.dev_head_t.isEmpty()) && (!info.ctf_head_t.isEmpty())) //~isempty(info.dev_head_t) && ~isempty(info.ctf_head_t)
1030  {
1031  info.dev_ctf_t = info.dev_head_t;
1032  info.dev_ctf_t.to = info.ctf_head_t.from;
1033  info.dev_ctf_t.trans = ctf_head_t.trans.inverse()*info.dev_ctf_t.trans;
1034  }
1035  else
1036  info.dev_ctf_t.clear();
1037 
1038  //
1039  // All kinds of auxliary stuff
1040  //
1041  info.dig = dig;
1042  if (!dig_trans.isEmpty())
1043  info.dig_trans = dig_trans;
1044 
1045  info.bads = bads;
1046  info.projs = projs;
1047  info.comps = comps;
1048  info.acq_pars = acq_pars;
1049  info.acq_stim = acq_stim;
1050 
1051  p_NodeInfo = meas[0];
1052 
1053  return true;
1054 }
1055 
1056 
1057 //*************************************************************************************************************
1058 
1059 bool FiffStream::read_named_matrix(const FiffDirTree& p_Node, fiff_int_t matkind, FiffNamedMatrix& mat)
1060 {
1061  mat.clear();
1062 
1063  FiffDirTree node = p_Node;
1064  //
1065  // Descend one level if necessary
1066  //
1067  bool found_it = false;
1068  if (node.block != FIFFB_MNE_NAMED_MATRIX)
1069  {
1070  for (int k = 0; k < node.nchild; ++k)
1071  {
1072  if (node.children[k].block == FIFFB_MNE_NAMED_MATRIX)
1073  {
1074  if(node.children[k].has_tag(matkind))
1075  {
1076  node = node.children[k];
1077  found_it = true;
1078  break;
1079  }
1080  }
1081  }
1082  if (!found_it)
1083  {
1084  printf("Fiff::read_named_matrix: Desired named matrix (kind = %d) not available\n",matkind);
1085  return false;
1086  }
1087  }
1088  else
1089  {
1090  if (!node.has_tag(matkind))
1091  {
1092  printf("Desired named matrix (kind = %d) not available",matkind);
1093  return false;
1094  }
1095  }
1096 
1097  FiffTag::SPtr t_pTag;
1098  //
1099  // Read everything we need
1100  //
1101  if(!node.find_tag(this, matkind, t_pTag))
1102  {
1103  printf("Matrix data missing.\n");
1104  return false;
1105  }
1106  else
1107  {
1108  //qDebug() << "Is Matrix" << t_pTag->isMatrix() << "Special Type:" << t_pTag->getType();
1109  mat.data = t_pTag->toFloatMatrix().cast<double>();
1110  mat.data.transposeInPlace();
1111  }
1112 
1113  mat.nrow = mat.data.rows();
1114  mat.ncol = mat.data.cols();
1115 
1116  if(node.find_tag(this, FIFF_MNE_NROW, t_pTag))
1117  if (*t_pTag->toInt() != mat.nrow)
1118  {
1119  printf("Number of rows in matrix data and FIFF_MNE_NROW tag do not match");
1120  return false;
1121  }
1122  if(node.find_tag(this, FIFF_MNE_NCOL, t_pTag))
1123  if (*t_pTag->toInt() != mat.ncol)
1124  {
1125  printf("Number of columns in matrix data and FIFF_MNE_NCOL tag do not match");
1126  return false;
1127  }
1128 
1129  QString row_names;
1130  if(node.find_tag(this, FIFF_MNE_ROW_NAMES, t_pTag))
1131  row_names = t_pTag->toString();
1132 
1133  QString col_names;
1134  if(node.find_tag(this, FIFF_MNE_COL_NAMES, t_pTag))
1135  col_names = t_pTag->toString();
1136 
1137  //
1138  // Put it together
1139  //
1140  if (!row_names.isEmpty())
1141  mat.row_names = split_name_list(row_names);
1142 
1143  if (!col_names.isEmpty())
1144  mat.col_names = split_name_list(col_names);
1145 
1146  return true;
1147 }
1148 
1149 
1150 //*************************************************************************************************************
1151 
1152 QList<FiffProj> FiffStream::read_proj(const FiffDirTree& p_Node)
1153 {
1154  QList<FiffProj> projdata;// = struct('kind',{},'active',{},'desc',{},'data',{});
1155  //
1156  // Locate the projection data
1157  //
1158  QList<FiffDirTree> t_qListNodes = p_Node.dir_tree_find(FIFFB_PROJ);
1159  if ( t_qListNodes.size() == 0 )
1160  return projdata;
1161 
1162 
1163  FiffTag::SPtr t_pTag;
1164  t_qListNodes[0].find_tag(this, FIFF_NCHAN, t_pTag);
1165  fiff_int_t global_nchan = 0;
1166  if (t_pTag)
1167  global_nchan = *t_pTag->toInt();
1168 
1169 
1170  fiff_int_t nchan;
1171  QList<FiffDirTree> t_qListItems = t_qListNodes[0].dir_tree_find(FIFFB_PROJ_ITEM);
1172  for ( qint32 i = 0; i < t_qListItems.size(); ++i)
1173  {
1174  //
1175  // Find all desired tags in one item
1176  //
1177  FiffDirTree* t_pFiffDirTreeItem = &t_qListItems[i];
1178  t_pFiffDirTreeItem->find_tag(this, FIFF_NCHAN, t_pTag);
1179  if (t_pTag)
1180  nchan = *t_pTag->toInt();
1181  else
1182  nchan = global_nchan;
1183 
1184  t_pFiffDirTreeItem->find_tag(this, FIFF_DESCRIPTION, t_pTag);
1185  QString desc; // maybe, in some cases this has to be a struct.
1186  if (t_pTag)
1187  {
1188  qDebug() << "read_proj: this has to be debugged";
1189  desc = t_pTag->toString();
1190  }
1191  else
1192  {
1193  t_pFiffDirTreeItem->find_tag(this, FIFF_NAME, t_pTag);
1194  if (t_pTag)
1195  desc = t_pTag->toString();
1196  else
1197  {
1198  printf("Projection item description missing\n");
1199  return projdata;
1200  }
1201  }
1202 // t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_CH_NAME_LIST, t_pTag);
1203 // QString namelist;
1204 // if (t_pTag)
1205 // {
1206 // namelist = t_pTag->toString();
1207 // }
1208 // else
1209 // {
1210 // printf("Projection item channel list missing\n");
1211 // return projdata;
1212 // }
1213  t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_KIND, t_pTag);
1214  fiff_int_t kind;
1215  if (t_pTag)
1216  {
1217  kind = *t_pTag->toInt();
1218  }
1219  else
1220  {
1221  printf("Projection item kind missing");
1222  return projdata;
1223  }
1224  t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_NVEC, t_pTag);
1225  fiff_int_t nvec;
1226  if (t_pTag)
1227  {
1228  nvec = *t_pTag->toInt();
1229  }
1230  else
1231  {
1232  printf("Number of projection vectors not specified\n");
1233  return projdata;
1234  }
1235  t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_CH_NAME_LIST, t_pTag);
1236  QStringList names;
1237  if (t_pTag)
1238  {
1239  names = split_name_list(t_pTag->toString());
1240  }
1241  else
1242  {
1243  printf("Projection item channel list missing\n");
1244  return projdata;
1245  }
1246  t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_VECTORS, t_pTag);
1247  MatrixXd data;// = NULL;
1248  if (t_pTag)
1249  {
1250  data = t_pTag->toFloatMatrix().cast<double>();
1251  data.transposeInPlace();
1252  }
1253  else
1254  {
1255  printf("Projection item data missing\n");
1256  return projdata;
1257  }
1258  t_pFiffDirTreeItem->find_tag(this, FIFF_MNE_PROJ_ITEM_ACTIVE, t_pTag);
1259  bool active;
1260  if (t_pTag)
1261  active = *t_pTag->toInt();
1262  else
1263  active = false;
1264 
1265  if (data.cols() != names.size())
1266  {
1267  printf("Number of channel names does not match the size of data matrix\n");
1268  return projdata;
1269  }
1270 
1271 
1272 
1273  //
1274  // create a named matrix for the data
1275  //
1276  QStringList defaultList;
1277  FiffNamedMatrix t_fiffNamedMatrix(nvec, nchan, defaultList, names, data);
1278 
1279  FiffProj one(kind, active, desc, t_fiffNamedMatrix);
1280  //
1281  projdata.append(one);
1282  }
1283 
1284  if (projdata.size() > 0)
1285  {
1286  printf("\tRead a total of %d projection items:\n", projdata.size());
1287  for(qint32 k = 0; k < projdata.size(); ++k)
1288  {
1289  printf("\t\t%s (%d x %d)",projdata[k].desc.toUtf8().constData(), projdata[k].data->nrow, projdata[k].data->ncol);
1290  if (projdata[k].active)
1291  printf(" active\n");
1292  else
1293  printf(" idle\n");
1294  }
1295  }
1296 
1297  return projdata;
1298 }
1299 
1300 //*************************************************************************************************************
1301 
1302 bool FiffStream::setup_read_raw(QIODevice &p_IODevice, FiffRawData& data, bool allow_maxshield)
1303 {
1304  //
1305  // Open the file
1306  //
1307  FiffStream::SPtr p_pStream(new FiffStream(&p_IODevice));
1308  QString t_sFileName = p_pStream->streamName();
1309 
1310  printf("Opening raw data %s...\n",t_sFileName.toUtf8().constData());
1311 
1312  FiffDirTree t_Tree;
1313  QList<FiffDirEntry> t_Dir;
1314 
1315  if(!p_pStream->open(t_Tree, t_Dir))
1316  return false;
1317 
1318  //
1319  // Read the measurement info
1320  //
1321  FiffInfo info;// = NULL;
1322  FiffDirTree meas;
1323  if(!p_pStream->read_meas_info(t_Tree, info, meas))
1324  return false;
1325 
1326  //
1327  // Locate the data of interest
1328  //
1329  QList<FiffDirTree> raw = meas.dir_tree_find(FIFFB_RAW_DATA);
1330  if (raw.size() == 0)
1331  {
1332  raw = meas.dir_tree_find(FIFFB_CONTINUOUS_DATA);
1333  if(allow_maxshield)
1334  {
1335 // for (qint32 i = 0; i < raw.size(); ++i)
1336 // if(raw[i])
1337 // delete raw[i];
1338  raw = meas.dir_tree_find(FIFFB_SMSH_RAW_DATA);
1339  if (raw.size() == 0)
1340  {
1341  printf("No raw data in %s\n", t_sFileName.toUtf8().constData());
1342  return false;
1343  }
1344  }
1345  else
1346  {
1347  if (raw.size() == 0)
1348  {
1349  printf("No raw data in %s\n", t_sFileName.toUtf8().constData());
1350  return false;
1351  }
1352  }
1353  }
1354  //
1355  // Set up the output structure
1356  //
1357  info.filename = t_sFileName;
1358 
1359  data.clear();
1360  data.file = p_pStream;// fid;
1361  data.info = info;
1362  data.first_samp = 0;
1363  data.last_samp = 0;
1364  //
1365  // Process the directory
1366  //
1367 
1368  QList<FiffDirEntry> dir = raw[0].dir;
1369  fiff_int_t nent = raw[0].nent;
1370  fiff_int_t nchan = info.nchan;
1371  fiff_int_t first = 0;
1372  fiff_int_t first_samp = 0;
1373  fiff_int_t first_skip = 0;
1374  //
1375  // Get first sample tag if it is there
1376  //
1377  FiffTag::SPtr t_pTag;
1378  if (dir[first].kind == FIFF_FIRST_SAMPLE)
1379  {
1380  FiffTag::read_tag(p_pStream.data(), t_pTag, dir[first].pos);
1381  first_samp = *t_pTag->toInt();
1382  ++first;
1383  }
1384 
1385  //
1386  // Omit initial skip
1387  //
1388  if (dir.at(first).kind == FIFF_DATA_SKIP)
1389  {
1390  //
1391  // This first skip can be applied only after we know the buffer size
1392  //
1393  FiffTag::read_tag(p_pStream.data(), t_pTag, dir[first].pos);
1394  first_skip = *t_pTag->toInt();
1395  ++first;
1396  }
1397  data.first_samp = first_samp;
1398  //
1399  // Go through the remaining tags in the directory
1400  //
1401  QList<FiffRawDir> rawdir;
1402 // rawdir = struct('ent',{},'first',{},'last',{},'nsamp',{});
1403  fiff_int_t nskip = 0;
1404  fiff_int_t ndir = 0;
1405  fiff_int_t nsamp = 0;
1406  for (qint32 k = first; k < nent; ++k)
1407  {
1408  FiffDirEntry ent = dir.at(k);
1409  if (ent.kind == FIFF_DATA_SKIP)
1410  {
1411  FiffTag::read_tag(p_pStream.data(), t_pTag, ent.pos);
1412  nskip = *t_pTag->toInt();
1413  }
1414  else if(ent.kind == FIFF_DATA_BUFFER)
1415  {
1416  //
1417  // Figure out the number of samples in this buffer
1418  //
1419  switch(ent.type)
1420  {
1421  case FIFFT_DAU_PACK16:
1422  nsamp = ent.size/(2*nchan);
1423  break;
1424  case FIFFT_SHORT:
1425  nsamp = ent.size/(2*nchan);
1426  break;
1427  case FIFFT_FLOAT:
1428  nsamp = ent.size/(4*nchan);
1429  break;
1430  case FIFFT_INT:
1431  nsamp = ent.size/(4*nchan);
1432  break;
1433  default:
1434  printf("Cannot handle data buffers of type %d\n",ent.type);
1435  return false;
1436  }
1437  //
1438  // Do we have an initial skip pending?
1439  //
1440  if (first_skip > 0)
1441  {
1442  first_samp += nsamp*first_skip;
1443  data.first_samp = first_samp;
1444  first_skip = 0;
1445  }
1446  //
1447  // Do we have a skip pending?
1448  //
1449  if (nskip > 0)
1450  {
1451  FiffRawDir t_RawDir;
1452  t_RawDir.first = first_samp;
1453  t_RawDir.last = first_samp + nskip*nsamp - 1;//ToDo -1 right or is that MATLAB syntax
1454  t_RawDir.nsamp = nskip*nsamp;
1455  rawdir.append(t_RawDir);
1456  first_samp = first_samp + nskip*nsamp;
1457  nskip = 0;
1458  ++ndir;
1459  }
1460  //
1461  // Add a data buffer
1462  //
1463  FiffRawDir t_RawDir;
1464  t_RawDir.ent = ent;
1465  t_RawDir.first = first_samp;
1466  t_RawDir.last = first_samp + nsamp - 1;//ToDo -1 right or is that MATLAB syntax
1467  t_RawDir.nsamp = nsamp;
1468  rawdir.append(t_RawDir);
1469  first_samp += nsamp;
1470  ++ndir;
1471  }
1472  }
1473  data.last_samp = first_samp - 1;//ToDo -1 right or is that MATLAB syntax
1474  //
1475  // Add the calibration factors
1476  //
1477  RowVectorXd cals(data.info.nchan);
1478  cals.setZero();
1479  for (qint32 k = 0; k < data.info.nchan; ++k)
1480  cals[k] = data.info.chs[k].range*data.info.chs[k].cal;
1481  //
1482  data.cals = cals;
1483  data.rawdir = rawdir;
1484  //data->proj = [];
1485  //data.comp = [];
1486  //
1487  printf("\tRange : %d ... %d = %9.3f ... %9.3f secs\n",
1488  data.first_samp,data.last_samp,
1489  (double)data.first_samp/data.info.sfreq,
1490  (double)data.last_samp/data.info.sfreq);
1491  printf("Ready.\n");
1492  data.file->device()->close();
1493 
1494  return true;
1495 }
1496 
1497 
1498 //*************************************************************************************************************
1499 
1500 QStringList FiffStream::split_name_list(QString p_sNameList)
1501 {
1502  return p_sNameList.split(":");
1503 }
1504 
1505 //*************************************************************************************************************
1506 
1507 void FiffStream::start_block(fiff_int_t kind)
1508 {
1509  this->write_int(FIFF_BLOCK_START,&kind);
1510 }
1511 
1512 
1513 //*************************************************************************************************************
1514 
1516 {
1517  FiffStream::SPtr p_pStream(new FiffStream(&p_IODevice));
1518  QString t_sFileName = p_pStream->streamName();
1519 
1520  if(!p_pStream->device()->open(QIODevice::WriteOnly))
1521  {
1522  printf("Cannot write to %s\n", t_sFileName.toUtf8().constData());//consider throw
1523  FiffStream::SPtr p_pEmptyStream;
1524  return p_pEmptyStream;
1525  }
1526 
1527  //
1528  // Write the compulsory items
1529  //
1530  p_pStream->write_id(FIFF_FILE_ID);//1
1531  qint32 data = -1;
1532  p_pStream->write_int(FIFF_DIR_POINTER,&data);//2
1533  p_pStream->write_int(FIFF_FREE_LIST,&data);//3
1534  //
1535  // Ready for more
1536  //
1537  return p_pStream;
1538 }
1539 
1540 
1541 //*************************************************************************************************************
1542 
1543 FiffStream::SPtr FiffStream::start_writing_raw(QIODevice &p_IODevice, const FiffInfo& info, RowVectorXd& cals, MatrixXi sel)
1544 {
1545  //
1546  // We will always write floats
1547  //
1548  fiff_int_t data_type = 4;
1549  qint32 k;
1550 
1551  if(sel.cols() == 0)
1552  {
1553  sel.resize(1,info.nchan);
1554  for (k = 0; k < info.nchan; ++k)
1555  sel(0, k) = k; //+1 when MATLAB notation
1556  }
1557 
1558  QList<FiffChInfo> chs;
1559 
1560  for(k = 0; k < sel.cols(); ++k)
1561  chs << info.chs.at(sel(0,k));
1562 
1563  fiff_int_t nchan = chs.size();
1564 
1565  //
1566  // Create the file and save the essentials
1567  //
1568  FiffStream::SPtr t_pStream = start_file(p_IODevice);//1, 2, 3
1569  t_pStream->start_block(FIFFB_MEAS);//4
1570  t_pStream->write_id(FIFF_BLOCK_ID);//5
1571  if(info.meas_id.version != -1)
1572  {
1573  t_pStream->write_id(FIFF_PARENT_BLOCK_ID,info.meas_id);//6
1574  }
1575  //
1576  //
1577  // Measurement info
1578  //
1579  t_pStream->start_block(FIFFB_MEAS_INFO);//7
1580  //
1581  // Blocks from the original
1582  //
1583  QList<fiff_int_t> blocks;
1584  blocks << FIFFB_SUBJECT << FIFFB_HPI_MEAS << FIFFB_HPI_RESULT << FIFFB_ISOTRAK << FIFFB_PROCESSING_HISTORY;
1585  bool have_hpi_result = false;
1586  bool have_isotrak = false;
1587  if (blocks.size() > 0 && !info.filename.isEmpty())
1588  {
1589  QFile t_qFile(info.filename);//ToDo this has to be adapted for TCPSocket
1590  FiffStream::SPtr t_pStream2(new FiffStream(&t_qFile));
1591 
1592  FiffDirTree t_Tree;
1593  QList<FiffDirEntry> t_Dir;
1594  t_pStream2->open(t_Tree, t_Dir);
1595 
1596  for(qint32 k = 0; k < blocks.size(); ++k)
1597  {
1598  QList<FiffDirTree> nodes = t_Tree.dir_tree_find(blocks[k]);
1599  FiffDirTree::copy_tree(t_pStream2,t_Tree.id,nodes,t_pStream);
1600  if(blocks[k] == FIFFB_HPI_RESULT && nodes.size() > 0)
1601  have_hpi_result = true;
1602 
1603  if(blocks[k] == FIFFB_ISOTRAK && nodes.size() > 0)
1604  have_isotrak = true;
1605  }
1606 
1607  t_pStream2 = FiffStream::SPtr();
1608  }
1609  //
1610  // megacq parameters
1611  //
1612  if (!info.acq_pars.isEmpty() || !info.acq_stim.isEmpty())
1613  {
1614  t_pStream->start_block(FIFFB_DACQ_PARS);
1615  if (!info.acq_pars.isEmpty())
1616  t_pStream->write_string(FIFF_DACQ_PARS, info.acq_pars);
1617 
1618  if (!info.acq_stim.isEmpty())
1619  t_pStream->write_string(FIFF_DACQ_STIM, info.acq_stim);
1620 
1621  t_pStream->end_block(FIFFB_DACQ_PARS);
1622  }
1623  //
1624  // Coordinate transformations if the HPI result block was not there
1625  //
1626  if (!have_hpi_result)
1627  {
1628  if (!info.dev_head_t.isEmpty())
1629  t_pStream->write_coord_trans(info.dev_head_t);
1630 
1631  if (!info.ctf_head_t.isEmpty())
1632  t_pStream->write_coord_trans(info.ctf_head_t);
1633  }
1634  //
1635  // Polhemus data
1636  //
1637  if (info.dig.size() > 0 && !have_isotrak)
1638  {
1639  t_pStream->start_block(FIFFB_ISOTRAK);
1640  for (qint32 k = 0; k < info.dig.size(); ++k)
1641  t_pStream->write_dig_point(info.dig[k]);
1642 
1643  t_pStream->end_block(FIFFB_ISOTRAK);
1644  }
1645  //
1646  // Projectors
1647  //
1648  t_pStream->write_proj(info.projs);
1649  //
1650  // CTF compensation info
1651  //
1652  t_pStream->write_ctf_comp(info.comps);
1653  //
1654  // Bad channels
1655  //
1656  if (info.bads.size() > 0)
1657  {
1658  t_pStream->start_block(FIFFB_MNE_BAD_CHANNELS);
1659  t_pStream->write_name_list(FIFF_MNE_CH_NAME_LIST,info.bads);
1660  t_pStream->end_block(FIFFB_MNE_BAD_CHANNELS);
1661  }
1662  //
1663  // General
1664  //
1665  t_pStream->write_float(FIFF_SFREQ,&info.sfreq);
1666  t_pStream->write_float(FIFF_HIGHPASS,&info.highpass);
1667  t_pStream->write_float(FIFF_LOWPASS,&info.lowpass);
1668  t_pStream->write_int(FIFF_NCHAN,&nchan);
1669  t_pStream->write_int(FIFF_DATA_PACK,&data_type);
1670  if (info.meas_date[0] != -1)
1671  t_pStream->write_int(FIFF_MEAS_DATE,info.meas_date, 2);
1672  //
1673  // Channel info
1674  //
1675  cals = RowVectorXd(nchan);
1676 
1677  for(k = 0; k < nchan; ++k)
1678  {
1679  //
1680  // Scan numbers may have been messed up
1681  //
1682  chs[k].scanno = k+1;//+1 because
1683  //chs[k].range = 1.0f;//Why? -> cause its already calibrated through reading
1684  cals[k] = chs[k].cal;
1685  t_pStream->write_ch_info(&chs[k]);
1686  }
1687  //
1688  //
1689  t_pStream->end_block(FIFFB_MEAS_INFO);
1690  //
1691  // Start the raw data
1692  //
1693  t_pStream->start_block(FIFFB_RAW_DATA);
1694 
1695  return t_pStream;
1696 }
1697 
1698 
1699 //*************************************************************************************************************
1700 
1702 {
1703  QFile* t_pFile = qobject_cast<QFile*>(this->device());
1704  QString p_sFileName;
1705  if(t_pFile)
1706  p_sFileName = t_pFile->fileName();
1707  else
1708  p_sFileName = QString("TCPSocket");
1709 
1710  return p_sFileName;
1711 }
1712 
1713 
1714 //*************************************************************************************************************
1715 
1717 {
1718  //typedef struct _fiffChPosRec {
1719  // fiff_int_t coil_type; /*!< What kind of coil. */
1720  // fiff_float_t r0[3]; /*!< Coil coordinate system origin */
1721  // fiff_float_t ex[3]; /*!< Coil coordinate system x-axis unit vector */
1722  // fiff_float_t ey[3]; /*!< Coil coordinate system y-axis unit vector */
1723  // fiff_float_t ez[3]; /*!< Coil coordinate system z-axis unit vector */
1724  //} fiffChPosRec,*fiffChPos; /*!< Measurement channel position and coil type */
1725 
1726 
1727  //typedef struct _fiffChInfoRec {
1728  // fiff_int_t scanNo; /*!< Scanning order # */
1729  // fiff_int_t logNo; /*!< Logical channel # */
1730  // fiff_int_t kind; /*!< Kind of channel */
1731  // fiff_float_t range; /*!< Voltmeter range (only applies to raw data ) */
1732  // fiff_float_t cal; /*!< Calibration from volts to... */
1733  // fiff_ch_pos_t chpos; /*!< Channel location */
1734  // fiff_int_t unit; /*!< Unit of measurement */
1735  // fiff_int_t unit_mul; /*!< Unit multiplier exponent */
1736  // fiff_char_t ch_name[16]; /*!< Descriptive name for the channel */
1737  //} fiffChInfoRec,*fiffChInfo; /*!< Description of one channel */
1738  fiff_int_t datasize= 4*13 + 4*7 + 16;
1739 
1740  *this << (qint32)FIFF_CH_INFO;
1741  *this << (qint32)FIFFT_CH_INFO_STRUCT;
1742  *this << (qint32)datasize;
1743  *this << (qint32)FIFFV_NEXT_SEQ;
1744 
1745  //
1746  // Start writing fiffChInfoRec
1747  //
1748  *this << (qint32)ch->scanno;
1749  *this << (qint32)ch->logno;
1750  *this << (qint32)ch->kind;
1751 
1752  *this << ch->range;
1753  *this << ch->cal;
1754 
1755  //
1756  // fiffChPosRec follows
1757  //
1758  *this << (qint32)ch->coil_type;
1759  qint32 i;
1760  for(i = 0; i < 12; ++i)
1761  *this << ch->loc(i,0);
1762 
1763  //
1764  // unit and unit multiplier
1765  //
1766  *this << (qint32)ch->unit;
1767  *this << (qint32)ch->unit_mul;
1768 
1769  //
1770  // Finally channel name
1771  //
1772  fiff_int_t len = ch->ch_name.size();
1773  QString ch_name;
1774  if(len > 15)
1775  ch_name = ch->ch_name.mid(0, 15);
1776  else
1777  ch_name = ch->ch_name;
1778 
1779  len = ch_name.size();
1780 
1781  this->writeRawData(ch_name.toUtf8().constData(),len);
1782 
1783  if (len < 16)
1784  {
1785  const char* chNull = "";
1786  for(i = 0; i < 16-len; ++i)
1787  this->writeRawData(chNull,1);
1788  }
1789 }
1790 
1791 
1792 //*************************************************************************************************************
1793 
1795 {
1796  //?typedef struct _fiffCoordTransRec {
1797  // fiff_int_t from; /*!< Source coordinate system. */
1798  // fiff_int_t to; /*!< Destination coordinate system. */
1799  // fiff_float_t rot[3][3]; /*!< The forward transform (rotation part) */
1800  // fiff_float_t move[3]; /*!< The forward transform (translation part) */
1801  // fiff_float_t invrot[3][3]; /*!< The inverse transform (rotation part) */
1802  // fiff_float_t invmove[3]; /*!< The inverse transform (translation part) */
1803  //} *fiffCoordTrans, fiffCoordTransRec; /*!< Coordinate transformation descriptor */
1804  fiff_int_t datasize = 4*2*12 + 4*2;
1805 
1806  *this << (qint32)FIFF_COORD_TRANS;
1807  *this << (qint32)FIFFT_COORD_TRANS_STRUCT;
1808  *this << (qint32)datasize;
1809  *this << (qint32)FIFFV_NEXT_SEQ;
1810 
1811  //
1812  // Start writing fiffCoordTransRec
1813  //
1814  *this << (qint32)trans.from;
1815  *this << (qint32)trans.to;
1816 
1817  //
1818  // The transform...
1819  //
1820  qint32 r, c;
1821  for (r = 0; r < 3; ++r)
1822  for (c = 0; c < 3; ++c)
1823  *this << (float)trans.trans(r,c);
1824  for (r = 0; r < 3; ++r)
1825  *this << (float)trans.trans(r,3);
1826 
1827  //
1828  // ...and its inverse
1829  //
1830  for (r = 0; r < 3; ++r)
1831  for (c = 0; c < 3; ++c)
1832  *this << (float)trans.invtrans(r,c);
1833  for (r = 0; r < 3; ++r)
1834  *this << (float)trans.invtrans(r,3);
1835 }
1836 
1837 
1838 //*************************************************************************************************************
1839 
1840 void FiffStream::write_cov(const FiffCov &p_FiffCov)
1841 {
1842  this->start_block(FIFFB_MNE_COV);
1843 
1844  //
1845  // Dimensions etc.
1846  //
1847  this->write_int(FIFF_MNE_COV_KIND, &p_FiffCov.kind);
1848  this->write_int(FIFF_MNE_COV_DIM, &p_FiffCov.dim);
1849  if (p_FiffCov.nfree > 0)
1850  this->write_int(FIFF_MNE_COV_NFREE, &p_FiffCov.nfree);
1851  //
1852  // Channel names
1853  //
1854  if(p_FiffCov.names.size() > 0)
1855  this->write_name_list(FIFF_MNE_ROW_NAMES, p_FiffCov.names);
1856  //
1857  // Data
1858  //
1859  if(p_FiffCov.diag)
1860  this->write_double(FIFF_MNE_COV_DIAG, p_FiffCov.data.col(0).data(), p_FiffCov.data.rows());
1861  else
1862  {
1863 // if issparse(cov.data)
1864 // fiff_write_float_sparse_rcs(fid,FIFF.FIFF_MNE_COV,cov.data);
1865 // else
1866 // {
1867  // Store only lower part of covariance matrix
1868  qint32 dim = p_FiffCov.dim;
1869  qint32 n = ((dim*dim) - dim)/2;
1870 
1871  VectorXd vals(n);
1872  qint32 count = 0;
1873  for(qint32 i = 1; i < dim; ++i)
1874  for(qint32 j = 0; j < i; ++j)
1875  vals(count) = p_FiffCov.data(i,j);
1876 
1877  this->write_double(FIFF_MNE_COV, vals.data(), vals.size());
1878 // }
1879  }
1880  //
1881  // Eigenvalues and vectors if present
1882  //
1883  if(p_FiffCov.eig.size() > 0 && p_FiffCov.eigvec.size() > 0)
1884  {
1885  this->write_float_matrix(FIFF_MNE_COV_EIGENVECTORS, p_FiffCov.eigvec.cast<float>());
1886  this->write_double(FIFF_MNE_COV_EIGENVALUES, p_FiffCov.eig.data(), p_FiffCov.eig.size());
1887  }
1888  //
1889  // Projection operator
1890  //
1891  this->write_proj(p_FiffCov.projs);
1892  //
1893  // Bad channels
1894  //
1895  if(p_FiffCov.bads.size() > 0)
1896  {
1897  this->start_block(FIFFB_MNE_BAD_CHANNELS);
1898  this->write_name_list(FIFF_MNE_CH_NAME_LIST, p_FiffCov.bads);
1899  this->end_block(FIFFB_MNE_BAD_CHANNELS);
1900  }
1901  //
1902  // Done!
1903  //
1904  this->end_block(FIFFB_MNE_COV);
1905 }
1906 
1907 
1908 //*************************************************************************************************************
1909 
1910 void FiffStream::write_ctf_comp(const QList<FiffCtfComp>& comps)
1911 {
1912  if (comps.size() <= 0)
1913  return;
1914  //
1915  // This is very simple in fact
1916  //
1917  this->start_block(FIFFB_MNE_CTF_COMP);
1918  for(qint32 k = 0; k < comps.size(); ++k)
1919  {
1920  FiffCtfComp comp(comps[k]);
1921  this->start_block(FIFFB_MNE_CTF_COMP_DATA);
1922  //
1923  // Write the compensation kind
1924  //
1926  qint32 save_calibrated = comp.save_calibrated;
1927  this->write_int(FIFF_MNE_CTF_COMP_CALIBRATED, &save_calibrated);
1928  //
1929  // Write an uncalibrated or calibrated matrix
1930  //
1931  comp.data->data = (comp.rowcals.diagonal()).inverse()* comp.data->data * (comp.colcals.diagonal()).inverse();
1932  this->write_named_matrix(FIFF_MNE_CTF_COMP_DATA,*comp.data.data());
1933  this->end_block(FIFFB_MNE_CTF_COMP_DATA);
1934  }
1935  this->end_block(FIFFB_MNE_CTF_COMP);
1936 
1937  return;
1938 }
1939 
1940 
1941 //*************************************************************************************************************
1942 
1944 {
1945  //?typedef struct _fiffDigPointRec {
1946  // fiff_int_t kind; /*!< FIFF_POINT_CARDINAL,
1947  // * FIFF_POINT_HPI, or
1948  // * FIFF_POINT_EEG */
1949  // fiff_int_t ident; /*!< Number identifying this point */
1950  // fiff_float_t r[3]; /*!< Point location */
1951  //} *fiffDigPoint,fiffDigPointRec; /*!< Digitization point description */
1952  fiff_int_t datasize = 5*4;
1953 
1954  *this << (qint32)FIFF_DIG_POINT;
1955  *this << (qint32)FIFFT_DIG_POINT_STRUCT;
1956  *this << (qint32)datasize;
1957  *this << (qint32)FIFFV_NEXT_SEQ;
1958 
1959  //
1960  // Start writing fiffDigPointRec
1961  //
1962  *this << (qint32)dig.kind;
1963  *this << (qint32)dig.ident;
1964  for(qint32 i = 0; i < 3; ++i)
1965  *this << dig.r[i];
1966 }
1967 
1968 
1969 //*************************************************************************************************************
1970 
1971 void FiffStream::write_double(fiff_int_t kind, const double* data, fiff_int_t nel)
1972 {
1973  qint32 datasize = nel * 8;
1974 
1975  *this << (qint32)kind;
1976  *this << (qint32)FIFFT_DOUBLE;
1977  *this << (qint32)datasize;
1978  *this << (qint32)FIFFV_NEXT_SEQ;
1979 
1980 // this->setFloatingPointPrecision(QDataStream::SinglePrecision);
1981 
1982  for(qint32 i = 0; i < nel; ++i)
1983  *this << data[i];
1984 }
1985 
1986 
1987 //*************************************************************************************************************
1988 
1989 void FiffStream::write_float(fiff_int_t kind, const float* data, fiff_int_t nel)
1990 {
1991  qint32 datasize = nel * 4;
1992 
1993  *this << (qint32)kind;
1994  *this << (qint32)FIFFT_FLOAT;
1995  *this << (qint32)datasize;
1996  *this << (qint32)FIFFV_NEXT_SEQ;
1997 
1998 // this->setFloatingPointPrecision(QDataStream::SinglePrecision);
1999 
2000  for(qint32 i = 0; i < nel; ++i)
2001  *this << data[i];
2002 }
2003 
2004 
2005 //*************************************************************************************************************
2006 
2007 void FiffStream::write_float_matrix(fiff_int_t kind, const MatrixXf& mat)
2008 {
2009  qint32 FIFFT_MATRIX = 1 << 30;
2010  qint32 FIFFT_MATRIX_FLOAT = FIFFT_FLOAT | FIFFT_MATRIX;
2011 
2012  qint32 numel = mat.rows() * mat.cols();
2013 
2014  fiff_int_t datasize = 4*numel + 4*3;
2015 
2016  *this << (qint32)kind;
2017  *this << (qint32)FIFFT_MATRIX_FLOAT;
2018  *this << (qint32)datasize;
2019  *this << (qint32)FIFFV_NEXT_SEQ;
2020 
2021  qint32 i;
2022  for(i = 0; i < numel; ++i)
2023  *this << mat.data()[i];
2024 
2025  qint32 dims[3];
2026  dims[0] = mat.cols();
2027  dims[1] = mat.rows();
2028  dims[2] = 2;
2029 
2030  for(i = 0; i < 3; ++i)
2031  *this << dims[i];
2032 }
2033 
2034 
2035 //*************************************************************************************************************
2036 
2037 void FiffStream::write_float_sparse_ccs(fiff_int_t kind, const SparseMatrix<float>& mat)
2038 {
2039  qint32 FIFFT_MATRIX = 16400 << 16; // 4010
2040  qint32 FIFFT_MATRIX_FLOAT_CCS = FIFFT_FLOAT | FIFFT_MATRIX;
2041 
2042  //
2043  // nnz values
2044  // nnz row indices
2045  // ncol+1 pointers
2046  // dims
2047  // nnz
2048  // ndim
2049  //
2050  qint32 nnzm = mat.nonZeros();
2051  qint32 ncol = mat.cols();
2052  fiff_int_t datasize = 4*nnzm + 4*nnzm + 4*(ncol+1) + 4*4;
2053  //
2054  // Nonzero entries
2055  //
2056  typedef Eigen::Triplet<float> T;
2057  std::vector<T> s;
2058  s.reserve(mat.nonZeros());
2059  for (int k=0; k < mat.outerSize(); ++k)
2060  for (SparseMatrix<float>::InnerIterator it(mat,k); it; ++it)
2061  s.push_back(T(it.row(), it.col(), it.value()));
2062 
2063  s = MNEMath::sortrows<float>(s, 1);
2064 
2065  //[ rows, starts ] = unique(s(:,1),'first');
2066  std::vector<qint32> cols, starts;
2067  qint32 v_old = -1;
2068  quint32 i;
2069  for(i = 0; i < s.size(); ++i)
2070  {
2071  if((signed) s[i].col() != v_old)
2072  {
2073  v_old = s[i].col();
2074  cols.push_back(s[i].col());
2075  starts.push_back(i);
2076  }
2077  }
2078 
2079  *this << (qint32)kind;
2080  *this << (qint32)FIFFT_MATRIX_FLOAT_CCS;
2081  *this << (qint32)datasize;
2082  *this << (qint32)FIFFV_NEXT_SEQ;
2083 
2084  //
2085  // The data values
2086  //
2087  for(i = 0; i < s.size(); ++i)
2088  *this << s[i].value();
2089 
2090  //
2091  // Row indices
2092  //
2093  for(i = 0; i < s.size(); ++i)
2094  *this << s[i].row();
2095 
2096  //
2097  // Pointers
2098  //
2099  RowVectorXi ptrs = RowVectorXi::Ones(ncol+1);
2100  ptrs.array() *= -1;
2101  quint32 k;
2102  for(k = 0; k < cols.size(); ++k)
2103  ptrs[cols[k]] = starts[k];
2104  ptrs[ncol] = nnzm;
2105  //
2106  // Fill in pointers for empty columns
2107  //
2108  for(k = ncol; k >= 1; --k)
2109  if(ptrs[k-1] < 0)
2110  ptrs[k-1] = ptrs[k];
2111  //
2112  for(i = 0; i < (quint32)ptrs.size(); ++i)
2113  *this << ptrs[i];
2114  //
2115  // Dimensions
2116  //
2117  qint32 dims[4];
2118  dims[0] = mat.nonZeros();
2119  dims[1] = mat.rows();
2120  dims[2] = mat.cols();
2121  dims[3] = 2;
2122 
2123  for(i = 0; i < 4; ++i)
2124  *this << dims[i];
2125 }
2126 
2127 
2128 //*************************************************************************************************************
2129 
2130 void FiffStream::write_float_sparse_rcs(fiff_int_t kind, const SparseMatrix<float>& mat)
2131 {
2132  qint32 FIFFT_MATRIX = 16416 << 16; // 4020
2133  qint32 FIFFT_MATRIX_FLOAT_RCS = FIFFT_FLOAT | FIFFT_MATRIX;
2134 
2135  //
2136  // nnz values
2137  // nnz column indices
2138  // nrow+1 pointers
2139  // dims
2140  // nnz
2141  // ndim
2142  //
2143  qint32 nnzm = mat.nonZeros();
2144  qint32 nrow = mat.rows();
2145  fiff_int_t datasize = 4*nnzm + 4*nnzm + 4*(nrow+1) + 4*4;
2146  //
2147  // Nonzero entries
2148  //
2149  typedef Eigen::Triplet<float> T;
2150  std::vector<T> s;
2151  s.reserve(mat.nonZeros());
2152  for (int k=0; k < mat.outerSize(); ++k)
2153  for (SparseMatrix<float>::InnerIterator it(mat,k); it; ++it)
2154  s.push_back(T(it.row(), it.col(), it.value()));
2155 
2156  s = MNEMath::sortrows<float>(s);
2157 
2158  //[ rows, starts ] = unique(s(:,1),'first');
2159  std::vector<qint32> rows, starts;
2160  qint32 v_old = -1;
2161  quint32 i;
2162  for(i = 0; i < s.size(); ++i)
2163  {
2164  if((signed) s[i].row() != v_old)
2165  {
2166  v_old = s[i].row();
2167  rows.push_back(s[i].row());
2168  starts.push_back(i);
2169  }
2170  }
2171 
2172  *this << (qint32)kind;
2173  *this << (qint32)FIFFT_MATRIX_FLOAT_RCS;
2174  *this << (qint32)datasize;
2175  *this << (qint32)FIFFV_NEXT_SEQ;
2176 
2177  //
2178  // The data values
2179  //
2180  for(i = 0; i < s.size(); ++i)
2181  *this << s[i].value();
2182 
2183  //
2184  // Column indices
2185  //
2186  for(i = 0; i < s.size(); ++i)
2187  *this << s[i].col();
2188 
2189  //
2190  // Pointers
2191  //
2192  RowVectorXi ptrs = RowVectorXi::Ones(nrow+1);
2193  ptrs.array() *= -1;
2194  quint32 k;
2195  for(k = 0; k < rows.size(); ++k)
2196  ptrs[rows[k]] = starts[k];
2197  ptrs[nrow] = nnzm;
2198 
2199  //
2200  // Fill in pointers for empty rows
2201  //
2202  for(k = nrow; k >= 1; --k)
2203  if(ptrs[k-1] < 0)
2204  ptrs[k-1] = ptrs[k];
2205 
2206  //
2207  for(i = 0; i < (quint32)ptrs.size(); ++i)
2208  *this << ptrs[i];
2209 
2210  //
2211  // Dimensions
2212  //
2213  qint32 dims[4];
2214  dims[0] = mat.nonZeros();
2215  dims[1] = mat.rows();
2216  dims[2] = mat.cols();
2217  dims[3] = 2;
2218 
2219  for(i = 0; i < 4; ++i)
2220  *this << dims[i];
2221 }
2222 
2223 
2224 //*************************************************************************************************************
2225 
2226 void FiffStream::write_id(fiff_int_t kind, const FiffId& id)
2227 {
2228  FiffId t_id = id;
2229  if(t_id.version == -1)
2230  {
2231  /* initialize random seed: */
2232  srand ( time(NULL) );
2233  double rand_1 = (double)(rand() % 100);rand_1 /= 100;
2234  double rand_2 = (double)(rand() % 100);rand_2 /= 100;
2235 
2236  time_t seconds;
2237  seconds = time (NULL);
2238 
2239  //fiff_int_t timezone = 5; // Matlab does not know the timezone
2240  t_id.version = (1 << 16) | 2; // Version (1 << 16) | 2
2241  t_id.machid[0] = 65536*rand_1; // Machine id is random for now
2242  t_id.machid[1] = 65536*rand_2; // Machine id is random for now
2243  t_id.time.secs = (int)seconds; //seconds since January 1, 1970 //3600*(24*(now-datenum(1970,1,1,0,0,0))+timezone);
2244  t_id.time.usecs = 0; // Do not know how we could get this
2245  }
2246 
2247  //
2248  //
2249  fiff_int_t datasize = 5*4; // The id comprises five integers
2250 
2251  *this << (qint32)kind;
2252  *this << (qint32)FIFFT_ID_STRUCT;
2253  *this << (qint32)datasize;
2254  *this << (qint32)FIFFV_NEXT_SEQ;
2255  //
2256  // Collect the bits together for one write
2257  //
2258  qint32 data[5];
2259  data[0] = t_id.version;
2260  data[1] = t_id.machid[0];
2261  data[2] = t_id.machid[1];
2262  data[3] = t_id.time.secs;
2263  data[4] = t_id.time.usecs;
2264 
2265  for(qint32 i = 0; i < 5; ++i)
2266  *this << data[i];
2267 }
2268 
2269 
2270 //*************************************************************************************************************
2271 
2272 void FiffStream::write_info_base(const FiffInfoBase & p_FiffInfoBase)
2273 {
2274  //
2275  // Information from the MEG file
2276  //
2277  this->start_block(FIFFB_MNE_PARENT_MEAS_FILE);
2278  this->write_string(FIFF_MNE_FILE_NAME, p_FiffInfoBase.filename);
2279  if(!p_FiffInfoBase.meas_id.isEmpty())
2280  this->write_id(FIFF_PARENT_BLOCK_ID, p_FiffInfoBase.meas_id);
2281 
2282  //
2283  // General
2284  //
2285  this->write_int(FIFF_NCHAN,&p_FiffInfoBase.nchan);
2286 
2287  //
2288  // Channel info
2289  //
2290  qint32 k;
2291  QList<FiffChInfo> chs;
2292  for(k = 0; k < p_FiffInfoBase.nchan; ++k)
2293  chs << p_FiffInfoBase.chs[k];
2294 
2295  for(k = 0; k < p_FiffInfoBase.nchan; ++k)
2296  {
2297  //
2298  // Scan numbers may have been messed up
2299  //
2300  chs[k].scanno = k+1;//+1 because
2301  //chs[k].range = 1.0f;//Why? -> cause its already calibrated through reading
2302  this->write_ch_info(&chs[k]);
2303  }
2304 
2305  //
2306  // Blocks from the original -> skip this
2307  //
2308  bool have_hpi_result = false;
2309 
2310  //
2311  // Coordinate transformations if the HPI result block was not there
2312  //
2313  if (!have_hpi_result)
2314  {
2315  if (!p_FiffInfoBase.dev_head_t.isEmpty())
2316  this->write_coord_trans(p_FiffInfoBase.dev_head_t);
2317  if (!p_FiffInfoBase.ctf_head_t.isEmpty())
2318  this->write_coord_trans(p_FiffInfoBase.ctf_head_t);
2319  }
2320 
2321  //
2322  // Bad channels
2323  //
2324  if (p_FiffInfoBase.bads.size() > 0)
2325  {
2326  this->start_block(FIFFB_MNE_BAD_CHANNELS);
2327  this->write_name_list(FIFF_MNE_CH_NAME_LIST,p_FiffInfoBase.bads);
2328  this->end_block(FIFFB_MNE_BAD_CHANNELS);
2329  }
2330 
2331  this->end_block(FIFFB_MNE_PARENT_MEAS_FILE);
2332 }
2333 
2334 
2335 //*************************************************************************************************************
2336 
2337 void FiffStream::write_int(fiff_int_t kind, const fiff_int_t* data, fiff_int_t nel)
2338 {
2339  fiff_int_t datasize = nel * 4;
2340 
2341  *this << (qint32)kind;
2342  *this << (qint32)FIFFT_INT;
2343  *this << (qint32)datasize;
2344  *this << (qint32)FIFFV_NEXT_SEQ;
2345 
2346  for(qint32 i = 0; i < nel; ++i)
2347  *this << data[i];
2348 }
2349 
2350 
2351 //*************************************************************************************************************
2352 
2353 void FiffStream::write_int_matrix(fiff_int_t kind, const MatrixXi& mat)
2354 {
2355  qint32 FIFFT_MATRIX = 1 << 30;
2356  qint32 FIFFT_MATRIX_INT = FIFFT_INT | FIFFT_MATRIX;
2357 
2358  qint32 numel = mat.rows() * mat.cols();
2359 
2360  fiff_int_t datasize = 4*numel + 4*3;
2361 
2362  *this << (qint32)kind;
2363  *this << (qint32)FIFFT_MATRIX_INT;
2364  *this << (qint32)datasize;
2365  *this << (qint32)FIFFV_NEXT_SEQ;
2366 
2367  qint32 i;
2368  for(i = 0; i < numel; ++i)
2369  *this << mat.data()[i];
2370 
2371  qint32 dims[3];
2372  dims[0] = mat.cols();
2373  dims[1] = mat.rows();
2374  dims[2] = 2;
2375 
2376  for(i = 0; i < 3; ++i)
2377  *this << dims[i];
2378 }
2379 
2380 
2381 //*************************************************************************************************************
2382 
2383 void FiffStream::write_name_list(fiff_int_t kind, const QStringList& data)
2384 {
2385  QString all = data.join(":");
2386  this->write_string(kind,all);
2387 }
2388 
2389 
2390 //*************************************************************************************************************
2391 
2392 void FiffStream::write_named_matrix(fiff_int_t kind, const FiffNamedMatrix& mat)
2393 {
2394  this->start_block(FIFFB_MNE_NAMED_MATRIX);
2395  this->write_int(FIFF_MNE_NROW, &mat.nrow);
2396  this->write_int(FIFF_MNE_NCOL, &mat.ncol);
2397  if (mat.row_names.size() > 0)
2398  this->write_name_list(FIFF_MNE_ROW_NAMES, mat.row_names);
2399  if (mat.col_names.size() > 0)
2400  this->write_name_list(FIFF_MNE_COL_NAMES, mat.col_names);
2401  this->write_float_matrix(kind,mat.data.cast<float>());
2402  this->end_block(FIFFB_MNE_NAMED_MATRIX);
2403 }
2404 
2405 
2406 //*************************************************************************************************************
2407 
2408 void FiffStream::write_proj(const QList<FiffProj>& projs)
2409 {
2410  if (projs.size() <= 0)
2411  return;
2412 
2413  this->start_block(FIFFB_PROJ);
2414 
2415  for(qint32 k = 0; k < projs.size(); ++k)
2416  {
2417  this->start_block(FIFFB_PROJ_ITEM);
2418  this->write_string(FIFF_NAME,projs[k].desc);
2419  this->write_int(FIFF_PROJ_ITEM_KIND,&projs[k].kind);
2420  if (projs[k].kind == FIFFV_PROJ_ITEM_FIELD)
2421  {
2422  float fValue = 0.0f;
2423  this->write_float(FIFF_PROJ_ITEM_TIME, &fValue);
2424  }
2425 
2426  this->write_int(FIFF_NCHAN, &projs[k].data->ncol);
2427  this->write_int(FIFF_PROJ_ITEM_NVEC, &projs[k].data->nrow);
2428  qint32 bValue = (qint32)projs[k].active;
2429  this->write_int(FIFF_MNE_PROJ_ITEM_ACTIVE, &bValue);
2430  this->write_name_list(FIFF_PROJ_ITEM_CH_NAME_LIST, projs[k].data->col_names);
2431  this->write_float_matrix(FIFF_PROJ_ITEM_VECTORS, projs[k].data->data.cast<float>());//rows == length(names)
2432  this->end_block(FIFFB_PROJ_ITEM);
2433  }
2434  this->end_block(FIFFB_PROJ);
2435 }
2436 
2437 
2438 //*************************************************************************************************************
2439 
2440 bool FiffStream::write_raw_buffer(const MatrixXd& buf, const RowVectorXd& cals)
2441 {
2442  if (buf.rows() != cals.cols())
2443  {
2444  printf("buffer and calibration sizes do not match\n");
2445  return false;
2446  }
2447 
2448  typedef Eigen::Triplet<double> T;
2449  std::vector<T> tripletList;
2450  tripletList.reserve(cals.cols());
2451  for(qint32 i = 0; i < cals.cols(); ++i)
2452  tripletList.push_back(T(i, i, 1.0/cals[i]));
2453 
2454  SparseMatrix<double> inv_calsMat(cals.cols(), cals.cols());
2455  inv_calsMat.setFromTriplets(tripletList.begin(), tripletList.end());
2456 
2457  MatrixXf tmp = (inv_calsMat*buf).cast<float>();
2458  this->write_float(FIFF_DATA_BUFFER,tmp.data(),tmp.rows()*tmp.cols());
2459  return true;
2460 }
2461 
2462 
2463 //*************************************************************************************************************
2464 
2465 bool FiffStream::write_raw_buffer(const MatrixXd& buf, const SparseMatrix<double>& mult)
2466 {
2467  if (buf.rows() != mult.cols()) {
2468  printf("buffer and mult sizes do not match\n");
2469  return false;
2470  }
2471 
2472  SparseMatrix<double> inv_mult(mult.rows(), mult.cols());
2473  for (int k=0; k<inv_mult.outerSize(); ++k)
2474  for (SparseMatrix<double>::InnerIterator it(mult,k); it; ++it)
2475  inv_mult.coeffRef(it.row(),it.col()) = 1/it.value();
2476 
2477  MatrixXf tmp = (inv_mult*buf).cast<float>();
2478  this->write_float(FIFF_DATA_BUFFER,tmp.data(),tmp.rows()*tmp.cols());
2479  return true;
2480 }
2481 
2482 
2483 //*************************************************************************************************************
2484 
2485 bool FiffStream::write_raw_buffer(const MatrixXd& buf)
2486 {
2487  MatrixXf tmp = buf.cast<float>();
2488  this->write_float(FIFF_DATA_BUFFER,tmp.data(),tmp.rows()*tmp.cols());
2489  return true;
2490 }
2491 
2492 
2493 //*************************************************************************************************************
2494 
2495 void FiffStream::write_string(fiff_int_t kind, const QString& data)
2496 {
2497  fiff_int_t datasize = data.size();
2498  *this << (qint32)kind;
2499  *this << (qint32)FIFFT_STRING;
2500  *this << (qint32)datasize;
2501  *this << (qint32)FIFFV_NEXT_SEQ;
2502 
2503  this->writeRawData(data.toUtf8().constData(),datasize);
2504 }
2505 
2506 
2507 //*************************************************************************************************************
2508 
2509 void FiffStream::write_rt_command(fiff_int_t command, const QString& data)
2510 {
2511  fiff_int_t datasize = data.size();
2512  *this << (qint32)FIFF_MNE_RT_COMMAND;
2513  *this << (qint32)FIFFT_VOID;
2514  *this << 4+(qint32)datasize;
2515  *this << (qint32)FIFFV_NEXT_SEQ;
2516  *this << command;
2517 
2518  this->writeRawData(data.toUtf8().constData(),datasize);
2519 }
void write_int_matrix(fiff_int_t kind, const MatrixXi &mat)
#define FIFF_MNE_CTF_COMP_KIND
#define FIFF_MNE_COV
void write_string(fiff_int_t kind, const QString &data)
static bool copy_tree(QSharedPointer< FiffStream > p_pStreamIn, FiffId &in_id, QList< FiffDirTree > &p_Nodes, QSharedPointer< FiffStream > p_pStreamOut)
MatrixXd data
Definition: fiff_cov.h:211
QList< FiffCtfComp > comps
Definition: fiff_info.h:267
bool isEmpty() const
Definition: fiff_id.h:147
fiff_int_t kind
FIFF measurement file information.
Definition: fiff_info.h:96
QList< FiffDirTree > children
bool write_raw_buffer(const MatrixXd &buf, const RowVectorXd &cals)
fiff_int_t meas_date[2]
Definition: fiff_info.h:259
#define FIFF_DATA_SKIP
static bool read_tag_info(FiffStream *p_pStream, FiffTag::SPtr &p_pTag, bool p_bDoSkip=true)
Definition: fiff_tag.cpp:137
void write_cov(const FiffCov &p_FiffCov)
QString acq_stim
Definition: fiff_info.h:269
bool find_tag(FiffStream *p_pStream, fiff_int_t findkind, QSharedPointer< FiffTag > &p_pTag) const
QList< FiffCtfComp > read_ctf_comp(const FiffDirTree &p_Node, const QList< FiffChInfo > &p_Chs)
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
Directory entry description.
fiff_int_t kind
Definition: fiff_cov.h:207
QStringList read_bad_channels(const FiffDirTree &p_Node)
static QStringList split_name_list(QString p_sNameList)
fiff_int_t version
Definition: fiff_id.h:127
QList< FiffProj > projs
Definition: fiff_info.h:266
QList< FiffDirTree > dir_tree_find(fiff_int_t p_kind) const
Digitization point description.
void write_named_matrix(fiff_int_t kind, const FiffNamedMatrix &mat)
QList< FiffProj > read_proj(const FiffDirTree &p_Node)
fiff_float_t range
Definition: fiff_ch_info.h:125
QSharedDataPointer< FiffNamedMatrix > SDPtr
FiffDirTree class declaration, which provides fiff dir tree processing methods.
Universially unique identifier.
Definition: fiff_id.h:78
static qint32 make_dir_tree(FiffStream *p_pStream, QList< FiffDirEntry > &p_Dir, FiffDirTree &p_Tree, qint32 start=0)
fiff_int_t nfree
Definition: fiff_cov.h:214
QSharedPointer< FiffTag > SPtr
Definition: fiff_tag.h:166
FiffCoordTrans ctf_head_t
#define FIFF_MNE_COV_NFREE
fiff_float_t cal
Definition: fiff_ch_info.h:126
Raw Directory entry.
Definition: fiff_raw_dir.h:81
void write_rt_command(fiff_int_t command, const QString &data)
#define FIFF_MNE_COV_DIAG
FiffDirEntry ent
Definition: fiff_raw_dir.h:108
void write_float_sparse_ccs(fiff_int_t kind, const SparseMatrix< float > &mat)
static bool read_tag(FiffStream *p_pStream, FiffTag::SPtr &p_pTag, qint64 pos=-1)
Definition: fiff_tag.cpp:204
QStringList names
Definition: fiff_cov.h:210
QStringList bads
Definition: fiff_cov.h:213
#define FIFF_MNE_CTF_COMP_CALIBRATED
bool open(FiffDirTree &p_Tree, QList< FiffDirEntry > &p_Dir)
#define FIFF_MNE_CTF_COMP_DATA
#define FIFF_MNE_COV_EIGENVALUES
void write_dig_point(const FiffDigPoint &dig)
QList< FiffRawDir > rawdir
#define FIFF_MNE_PROJ_ITEM_ACTIVE
QSharedPointer< FiffStream > SPtr
Definition: fiff_stream.h:132
FiffStream(QIODevice *p_pIODevice)
Definition: fiff_stream.cpp:75
fiff_int_t pos
FIFF raw measurement data.
Definition: fiff_raw_data.h:94
bool read_named_matrix(const FiffDirTree &p_Node, fiff_int_t matkind, FiffNamedMatrix &mat)
SSP projector data.
Definition: fiff_proj.h:89
#define FIFF_MNE_FILE_NAME
void write_float(fiff_int_t kind, const float *data, fiff_int_t nel=1)
FiffInfo class declaration.
FiffInfoBase class declaration.
FiffStream::SPtr file
fiff_int_t size
static bool setup_read_raw(QIODevice &p_IODevice, FiffRawData &data, bool allow_maxshield=false)
Matrix< float, 4, 4, DontAlign > invtrans
void write_int(fiff_int_t kind, const fiff_int_t *data, fiff_int_t nel=1)
void start_block(fiff_int_t kind)
bool get_evoked_entries(const QList< FiffDirTree > &evoked_node, QStringList &comments, QList< fiff_int_t > &aspect_kinds, QString &t)
void write_info_base(const FiffInfoBase &p_FiffInfoBase)
FiffCtfComp class declaration.
FiffNamedMatrix::SDPtr data
void write_double(fiff_int_t kind, const double *data, fiff_int_t nel=1)
FiffStream class declaration.
void write_ctf_comp(const QList< FiffCtfComp > &comps)
Directory tree structure.
Definition: fiff_dir_tree.h:80
#define FIFFV_ASPECT_AVERAGE
bool has_tag(fiff_int_t findkind)
QList< FiffDirEntry > dir
Channel info descriptor.
Definition: fiff_ch_info.h:87
void write_ch_info(FiffChInfo *ch)
QList< FiffChInfo > chs
fiff_int_t dim
Definition: fiff_cov.h:209
covariance data
Definition: fiff_cov.h:94
#define FIFF_MNE_RT_COMMAND
MatrixXd eigvec
Definition: fiff_cov.h:216
#define FIFF_MNE_COORD_FRAME
Definition: fiff.h:98
fiff_int_t type
FiffCoordTrans dev_head_t
void write_proj(const QList< FiffProj > &projs)
void write_coord_trans(const FiffCoordTrans &trans)
#define FIFF_DATA_BUFFER
#define FIFFV_ASPECT_STD_ERR
fiff_int_t machid[2]
Definition: fiff_id.h:128
void write_float_matrix(fiff_int_t kind, const MatrixXf &mat)
QList< FiffDigPoint > dig
Definition: fiff_info.h:264
FiffCoordTrans dev_ctf_t
Definition: fiff_info.h:263
Coordinate transformation description.
void write_id(fiff_int_t kind, const FiffId &id=defaultFiffId)
fiffTimeRec time
Definition: fiff_id.h:129
CTF software compensation data.
Definition: fiff_ctf_comp.h:87
FiffRawData class declaration.
FiffTag class declaration, which provides fiff tag I/O and processing methods.
MNEMath class declaration.
QList< FiffProj > projs
Definition: fiff_cov.h:212
#define FIFFV_MNE_COORD_CTF_HEAD
light measurement info
fiff_int_t coil_type
Definition: fiff_ch_info.h:128
void write_name_list(fiff_int_t kind, const QStringList &data)
bool read_cov(const FiffDirTree &p_Node, fiff_int_t cov_kind, FiffCov &p_covData)
void write_float_sparse_rcs(fiff_int_t kind, const SparseMatrix< float > &mat)
bool read_meas_info_base(const FiffDirTree &p_Node, FiffInfoBase &p_InfoForward)
#define FIFF_MNE_COV_DIM
VectorXd eig
Definition: fiff_cov.h:215
void end_block(fiff_int_t kind)
QString acq_pars
Definition: fiff_info.h:268
FiffCoordTrans dig_trans
Definition: fiff_info.h:265
Matrix< double, 12, 1, DontAlign > loc
Definition: fiff_ch_info.h:130
static FiffStream::SPtr start_writing_raw(QIODevice &p_IODevice, const FiffInfo &info, RowVectorXd &cals, MatrixXi sel=defaultMatrixXi)
Matrix< float, 4, 4, DontAlign > trans
bool read_meas_info(const FiffDirTree &p_Node, FiffInfo &p_Info, FiffDirTree &p_NodeInfo)
#define FIFF_MNE_COV_KIND
FiffCov class declaration.