v2.0.0
Loading...
Searching...
No Matches
fiff_stream.cpp
Go to the documentation of this file.
1//=============================================================================================================
37
38//=============================================================================================================
39// INCLUDES
40//=============================================================================================================
41
42#include "fiff_stream.h"
43#include "fiff_tag.h"
44#include "fiff_dir_node.h"
45#include "fiff_ctf_comp.h"
46#include "fiff_info.h"
47#include "fiff_info_base.h"
48#include "fiff_raw_data.h"
49#include "fiff_cov.h"
50#include "fiff_evoked_set.h"
51#include "fiff_coord_trans.h"
52#include "fiff_ch_info.h"
53#include "fiff_ch_pos.h"
54#include "fiff_dig_point.h"
55#include "fiff_id.h"
56#include "fiff_digitizer_data.h"
57#include "fiff_dig_point.h"
58
59#include <math/linalg.h>
60#include <math/numerics.h>
61#include <utils/ioutils.h>
62
63#include <iostream>
64#include <time.h>
65
66//=============================================================================================================
67// EIGEN INCLUDES
68//=============================================================================================================
69
70#include <Eigen/LU>
71#include <Eigen/Dense>
72
73//=============================================================================================================
74// QT INCLUDES
75//=============================================================================================================
76
77#include <QFile>
78#include <QTcpSocket>
79#include <QDebug>
80
81//=============================================================================================================
82// USED NAMESPACES
83//=============================================================================================================
84
85using namespace FIFFLIB;
86using namespace UTILSLIB;
87using namespace Eigen;
88
89//=============================================================================================================
90// DEFINE MEMBER METHODS
91//=============================================================================================================
92
93FiffStream::FiffStream(QIODevice *p_pIODevice)
94: QDataStream(p_pIODevice)
95{
96 this->setFloatingPointPrecision(QDataStream::SinglePrecision);
97 this->setByteOrder(QDataStream::BigEndian);
98 this->setVersion(QDataStream::Qt_5_0);
99}
100
101//=============================================================================================================
102
104 QIODevice::OpenMode mode)
105: QDataStream(a, mode)
106{
107 this->setFloatingPointPrecision(QDataStream::SinglePrecision);
108 this->setByteOrder(QDataStream::BigEndian);
109 this->setVersion(QDataStream::Qt_5_0);
110}
111
112//=============================================================================================================
113
115{
116 QFile* t_pFile = qobject_cast<QFile*>(this->device());
117 QString p_sFileName;
118 if(t_pFile)
119 p_sFileName = t_pFile->fileName();
120 else
121 p_sFileName = QString("TCPSocket");
122
123 return p_sFileName;
124}
125
126//=============================================================================================================
127
129{
130 return m_id;
131}
132
133//=============================================================================================================
134
135QList<FiffDirEntry::SPtr>& FiffStream::dir()
136{
137 return m_dir;
138}
139
140//=============================================================================================================
141
142const QList<FiffDirEntry::SPtr>& FiffStream::dir() const
143{
144 return m_dir;
145}
146
147//=============================================================================================================
148
150{
151 return m_dir.size();
152}
153
154//=============================================================================================================
155
157{
158 return m_dirtree;
159}
160
161//=============================================================================================================
162
164{
165 return this->write_int(FIFF_BLOCK_END,&kind,1,next);
166}
167
168//=============================================================================================================
169
171{
172 fiff_int_t datasize = 0;
173
174 *this << (qint32)FIFF_NOP;
175 *this << (qint32)FIFFT_VOID;
176 *this << (qint32)datasize;
177 *this << (qint32)FIFFV_NEXT_NONE;
178}
179
180//=============================================================================================================
181
183{
185 this->end_block(FIFFB_MEAS);
186 this->end_file();
187 this->close();
188}
189
190//=============================================================================================================
191
192bool FiffStream::get_evoked_entries(const QList<FiffDirNode::SPtr> &evoked_node, QStringList &comments, QList<fiff_int_t> &aspect_kinds, QString &t)
193{
194 comments.clear();
195 aspect_kinds.clear();
196 QList<FiffDirNode::SPtr>::ConstIterator ev;
197
198 FiffTag::UPtr t_pTag;
199 qint32 kind, pos, k;
200
201 for(ev = evoked_node.begin(); ev != evoked_node.end(); ++ev)
202 {
203 for(k = 0; k < (*ev)->nent(); ++k)
204 {
205 kind = (*ev)->dir[k]->kind;
206 pos = (*ev)->dir[k]->pos;
207 if (kind == FIFF_COMMENT)
208 {
209 this->read_tag(t_pTag,pos);
210 comments.append(t_pTag->toString());
211 }
212 }
213 FiffDirNode::SPtr my_aspect = (*ev)->dir_tree_find(FIFFB_ASPECT)[0];
214 for(k = 0; k < my_aspect->nent(); ++k)
215 {
216 kind = my_aspect->dir[k]->kind;
217 pos = my_aspect->dir[k]->pos;
218 if (kind == FIFF_ASPECT_KIND)
219 {
220 this->read_tag(t_pTag,pos);
221 aspect_kinds.append(*t_pTag->toInt());
222 }
223 }
224 }
225
226 if(comments.size() != aspect_kinds.size() || comments.size() == 0)
227 {
228 qWarning("Dataset names in FIF file could not be found.");
229 return false;
230 }
231
232 t = QString();
233 for(k = 0; k < aspect_kinds.size(); ++k)
234 {
235 t += QString("%1 - \"%2\" (").arg(k).arg(comments[k]);
236 if(aspect_kinds[k] == FIFFV_ASPECT_AVERAGE)
237 t += QString("FIFFV_ASPECT_AVERAGE)\n");
238 else if(aspect_kinds[k] == FIFFV_ASPECT_STD_ERR)
239 t += QString("FIFFV_ASPECT_STD_ERR)\n");
240 else
241 t += QString("unknown)\n");
242 }
243
244 return true;
245}
246
247//=============================================================================================================
248
249bool FiffStream::open(QIODevice::OpenModeFlag mode)
250{
251 QString t_sFileName = this->streamName();
252 FiffTag::UPtr t_pTag;
253
254 /*
255 * Try to open...
256 */
257 if (!this->device()->open(mode))
258 {
259 qCritical("Cannot open %s\n", t_sFileName.toUtf8().constData());//consider throw
260 return false;
261 }
262
263 if(!check_beginning(t_pTag)) // Supposed to get the id already in the beginning - read once approach - for TCP/IP support
264 return false;
265
266 /*
267 * Read id and directory pointer
268 */
269 if (t_pTag->kind != FIFF_FILE_ID) {
270 qCritical("FIFF file should start with FIFF_FILE_ID!");//consider throw
271 this->device()->close();
272 return false;
273 }
274 m_id = t_pTag->toFiffID();
275
276 this->read_tag(t_pTag);
277 if (t_pTag->kind != FIFF_DIR_POINTER) {
278 qWarning("Fiff::open: file does have a directory pointer");//consider throw
279 this->device()->close();
280 return false;
281 }
282
283 //
284 // Read or create the directory tree
285 //
286 qInfo("Creating tag directory for %s...", t_sFileName.toUtf8().constData());
287 m_dir.clear();
288 qint32 dirpos = *t_pTag->toInt();
289 /*
290 * Do we have a directory or not?
291 */
292 if (dirpos <= 0) { /* Must do it in the hard way... */
293 bool ok = false;
294 m_dir = this->make_dir(&ok);
295 if (!ok) {
296 qCritical ("Could not create tag directory!");
297 return false;
298 }
299 }
300 else { /* Just read the directory */
301 if(!this->read_tag(t_pTag, dirpos)) {
302 qCritical("Could not read the tag directory (file probably damaged)!");
303 return false;
304 }
305 m_dir = t_pTag->toDirEntry();
306 }
307
308 /*
309 * Check for a mistake
310 */
311 if (m_dir[m_dir.size()-2]->kind == FIFF_DIR) {
312 m_dir.removeLast();
313 m_dir[m_dir.size()-1]->kind = -1;
314 m_dir[m_dir.size()-1]->type = -1;
315 m_dir[m_dir.size()-1]->size = -1;
316 m_dir[m_dir.size()-1]->pos = -1;
317 }
318
319 //
320 // Create the directory tree structure
321 //
322 if((this->m_dirtree = this->make_subtree(m_dir)) == nullptr)
323 return false;
324 else
325 this->m_dirtree->parent.clear();
326
327 //
328 // Back to the beginning
329 //
330 this->device()->seek(SEEK_SET); //fseek(fid,0,'bof');
331 return true;
332}
333
334//=============================================================================================================
335
337{
338 if(this->device()->isOpen())
339 this->device()->close();
340
341 return true;
342}
343
344//=============================================================================================================
345
346FiffDirNode::SPtr FiffStream::make_subtree(QList<FiffDirEntry::SPtr> &dentry)
347{
348 FiffDirNode::SPtr defaultNode;
350 FiffDirNode::SPtr child;
351 FiffTag::UPtr t_pTag;
352 QList<FiffDirEntry::SPtr> dir;
353 qint32 current = 0;
354
355 node->dir_tree = dentry;
356 node->nent_tree = 1;
357 node->parent = FiffDirNode::SPtr();
358 node->type = FIFFB_ROOT;
359
360 if (dentry[current]->kind == FIFF_BLOCK_START) {
361 if (!this->read_tag(t_pTag,dentry[current]->pos))
362 return defaultNode;
363 else
364 node->type = *t_pTag->toInt();
365 }
366 else {
367 node->id = this->id();
368 }
369
370 ++current;
371 int level = 0;
372 for (; current < dentry.size(); ++current) {
373 ++node->nent_tree;
374 if (dentry[current]->kind == FIFF_BLOCK_START) {
375 level++;
376 if (level == 1) {
377 QList<FiffDirEntry::SPtr> sub_dentry = dentry.mid(current);
378 if (!(child = this->make_subtree(sub_dentry)))
379 return defaultNode;
380 child->parent = node;
381 node->children.append(child);
382 }
383 }
384 else if (dentry[current]->kind == FIFF_BLOCK_END) {
385 level--;
386 if (level < 0)
387 break;
388 }
389 else if (dentry[current]->kind == -1)
390 break;
391 else if (level == 0) {
392 /*
393 * Take the node id from the parent block id,
394 * block id, or file id. Let the block id
395 * take precedence over parent block id and file id
396 */
397 if (((dentry[current]->kind == FIFF_PARENT_BLOCK_ID || dentry[current]->kind == FIFF_FILE_ID) && node->id.isEmpty()) || dentry[current]->kind == FIFF_BLOCK_ID) {
398 if (!this->read_tag(t_pTag,dentry[current]->pos))
399 return defaultNode;
400 node->id = t_pTag->toFiffID();
401 }
402 dir.append(FiffDirEntry::SPtr(new FiffDirEntry(*dentry[current])));//Memcopy necessary here - or is a pointer fine?
403 }
404 }
405 /*
406 * Strip unused entries
407 */
408 node->dir = dir;
409 return node;
410}
411
412//=============================================================================================================
413
415{
416 QList<FiffDirNode::SPtr> node = p_Node->dir_tree_find(FIFFB_MNE_BAD_CHANNELS);
417 FiffTag::UPtr t_pTag;
418
419 QStringList bads;
420
421 if (node.size() > 0)
422 if(node[0]->find_tag(this, FIFF_MNE_CH_NAME_LIST, t_pTag))
423 bads = split_name_list(t_pTag->toString());
424
425 return bads;
426}
427
428//=============================================================================================================
429
436
437//=============================================================================================================
438
439bool FiffStream::attach_env(const QString& workingDir, const QString& command)
440{
441 int insert_blocks[] = { FIFFB_MNE , FIFFB_MEAS, FIFFB_MRI, FIFFB_BEM, -1 };
442
443 int b, k, insert;
444 FiffTag::UPtr t_pTag;
445
447
448 /*
449 * Find an appropriate position to insert
450 */
451 for (insert = -1, b = 0; insert_blocks[b] >= 0; b++) {
452 for (k = 0; k < nent(); k++) {
453 if (dir()[k]->kind == FIFF_BLOCK_START) {
454 if (!read_tag(t_pTag, dir()[k]->pos))
455 return false;
456 if (*(t_pTag->toInt()) == insert_blocks[b]) {
457 insert = k;
458 break;
459 }
460 }
461 }
462 if (insert >= 0)
463 break;
464 }
465 if (insert < 0) {
466 qCritical("Suitable place for environment insertion not found.");
467 return false;
468 }
469
470 /*
471 * Inline fiff_insert_after logic
472 */
473 int where = insert;
474 if (where < 0 || where >= nent()-1) {
475 qCritical("illegal insertion point in fiff_insert_after!");
476 return false;
477 }
478
479 FiffTag::UPtr t_pTagNext;
480 QList<FiffDirEntry::SPtr> old_dir = dir();
481 QList<FiffDirEntry::SPtr> this_ent = old_dir.mid(where);
482
483 if (!read_tag(t_pTagNext, this_ent[0]->pos))
484 return false;
485 /*
486 * Update next info to be sequential
487 */
488 qint64 next_tmp = device()->pos();
489 /*
490 * Go to the end of the file
491 */
492 device()->seek(device()->size());
493 /*
494 * Copy the beginning of old directory
495 */
496 QList<FiffDirEntry::SPtr> new_dir = old_dir.mid(0, where+1);
497
498 qint64 old_end = device()->pos();
499 /*
500 * Write the MNE_ENV block tags
501 */
502 FiffDirEntry::SPtr new_this;
503
504 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
505 new_this->kind = FIFF_BLOCK_START;
506 new_this->type = FIFFT_INT;
507 new_this->size = 1 * 4;
508 new_this->pos = start_block(FIFFB_MNE_ENV);
509 new_dir.append(new_this);
510
511 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
512 new_this->kind = FIFF_BLOCK_ID;
513 new_this->type = FIFFT_ID_STRUCT;
514 new_this->size = 5 * 4;
515 new_this->pos = write_id(FIFF_BLOCK_ID, id);
516 new_dir.append(new_this);
517
518 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
519 new_this->kind = FIFF_MNE_ENV_WORKING_DIR;
520 new_this->type = FIFFT_STRING;
521 new_this->size = workingDir.size();
522 new_this->pos = write_string(FIFF_MNE_ENV_WORKING_DIR, workingDir);
523 new_dir.append(new_this);
524
525 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
526 new_this->kind = FIFF_MNE_ENV_COMMAND_LINE;
527 new_this->type = FIFFT_STRING;
528 new_this->size = command.size();
529 new_this->pos = write_string(FIFF_MNE_ENV_COMMAND_LINE, command);
530 new_dir.append(new_this);
531
532 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
533 new_this->kind = FIFF_BLOCK_END;
534 new_this->type = FIFFT_INT;
535 new_this->size = 1 * 4;
536 new_this->pos = end_block(FIFFB_MNE_ENV, next_tmp);
537 new_dir.append(new_this);
538
539 /*
540 * Copy the rest of the old directory
541 */
542 new_dir.append(old_dir.mid(where+1));
543 /*
544 * Update the branching tag
545 */
546 t_pTagNext->next = (qint32)old_end;
547 write_tag(t_pTagNext, this_ent[0]->pos);
548
549 dir() = new_dir;
550
551 return true;
552}
553
554//=============================================================================================================
555
556bool FiffStream::read_cov(const FiffDirNode::SPtr& p_Node, fiff_int_t cov_kind, FiffCov& p_covData)
557{
558 p_covData.clear();
559
560 //
561 // Find all covariance matrices
562 //
563 QList<FiffDirNode::SPtr> covs = p_Node->dir_tree_find(FIFFB_MNE_COV);
564 if (covs.size() == 0)
565 {
566 qWarning("No covariance matrices found");
567 return false;
568 }
569 //
570 // Is any of the covariance matrices a noise covariance
571 //
572 qint32 p = 0;
573 FiffTag::UPtr tag;
574 bool success = false;
575 fiff_int_t dim, nfree, nn;
576 QStringList names;
577 bool diagmat = false;
578 VectorXd eig;
579 MatrixXd eigvec;
580 VectorXd cov_diag;
581 MatrixXd cov;
582 VectorXd cov_sparse;
583 QStringList bads;
584 for(p = 0; p < covs.size(); ++p)
585 {
586 success = covs[p]->find_tag(this, FIFF_MNE_COV_KIND, tag);
587 if (success && *tag->toInt() == cov_kind)
588 {
589 FiffDirNode::SPtr current = covs[p];
590 //
591 // Find all the necessary data
592 //
593 if (!current->find_tag(this, FIFF_MNE_COV_DIM, tag))
594 {
595 qWarning("Covariance matrix dimension not found.\n");
596 return false;
597 }
598 dim = *tag->toInt();
599 if (!current->find_tag(this, FIFF_MNE_COV_NFREE, tag))
600 nfree = -1;
601 else
602 nfree = *tag->toInt();
603
604 if (current->find_tag(this, FIFF_MNE_ROW_NAMES, tag))
605 {
606 names = FiffStream::split_name_list(tag->toString());
607 if (names.size() != dim)
608 {
609 qWarning("Number of names does not match covariance matrix dimension\n");
610 return false;
611 }
612 }
613 if (!current->find_tag(this, FIFF_MNE_COV, tag))
614 {
615 if (!current->find_tag(this, FIFF_MNE_COV_DIAG, tag))
616 {
617 qWarning("No covariance matrix data found\n");
618 return false;
619 }
620 else
621 {
622 //
623 // Diagonal is stored
624 //
625 if (tag->type == FIFFT_DOUBLE)
626 {
627 cov_diag = Map<VectorXd>(tag->toDouble(),dim);
628 }
629 else if (tag->type == FIFFT_FLOAT)
630 {
631 cov_diag = Map<VectorXf>(tag->toFloat(),dim).cast<double>();
632 }
633 else {
634 qCritical("Illegal data type for covariance matrix\n");
635 return false;
636 }
637
638 diagmat = true;
639 qInfo("\t%d x %d diagonal covariance (kind = %d) found.\n", dim, dim, cov_kind);
640 }
641 }
642 else
643 {
644 VectorXd vals;
645 nn = dim*(dim+1)/2;
646 if (tag->type == FIFFT_DOUBLE)
647 {
648 vals = Map<VectorXd>(tag->toDouble(),nn);
649 }
650 else if (tag->type == FIFFT_FLOAT)
651 {
652 vals = Map<VectorXf>(tag->toFloat(),nn).cast<double>();
653 }
654 else
655 {
656 qDebug() << tag->getInfo();
657 return false;
658 }
659
660 if(!Numerics::issparse(vals))
661 {
662 //
663 // Lower diagonal is stored
664 //
665 cov = MatrixXd::Zero(dim,dim);
666
667 // XXX : should remove for loops
668 qint32 q = 0;
669 for(qint32 j = 0; j < dim; ++j)
670 {
671 for(qint32 k = 0; k <= j; ++k)
672 {
673 cov(j,k) = vals(q);
674 ++q;
675 }
676 }
677 for(qint32 j = 0; j < dim; ++j)
678 for(qint32 k = j+1; k < dim; ++k)
679 cov(j,k) = cov(k,j);
680
681 diagmat = false;
682 qInfo("\t%d x %d full covariance (kind = %d) found.\n", dim, dim, cov_kind);
683
684 }
685 else
686 {
687 diagmat = false;
688 qDebug() << "ToDo: FiffStream::read_cov - this needs to be debugged.\n";
689 cov = vals;
690 qInfo("\t%d x %d sparse covariance (kind = %d) found.\n", dim, dim, cov_kind);
691 }
692//MATLAB
693// if ~issparse(tag.data)
694// //
695// // Lower diagonal is stored
696// //
697// qDebug() << tag->getInfo();
698// vals = tag.data;
699// data = zeros(dim,dim);
700// % XXX : should remove for loops
701// q = 1;
702// for j = 1:dim
703// for k = 1:j
704// data(j,k) = vals(q);
705// q = q + 1;
706// end
707// end
708// for j = 1:dim
709// for k = j+1:dim
710// data(j,k) = data(k,j);
711// end
712// end
713// diagmat = false;
714// fprintf('\t%d x %d full covariance (kind = %d) found.\n',dim,dim,cov_kind);
715// else
716// diagmat = false;
717// data = tag.data;
718// fprintf('\t%d x %d sparse covariance (kind = %d) found.\n',dim,dim,cov_kind);
719// end
720//MATLAB END
721 }
722 //
723 // Read the possibly precomputed decomposition
724 //
725 FiffTag::UPtr tag1;
726 FiffTag::UPtr tag2;
727 if (current->find_tag(this, FIFF_MNE_COV_EIGENVALUES, tag1) && current->find_tag(this, FIFF_MNE_COV_EIGENVECTORS, tag2))
728 {
729 eig = VectorXd(Map<VectorXd>(tag1->toDouble(),dim));
730 eigvec = tag2->toFloatMatrix().cast<double>();
731 eigvec.transposeInPlace();
732 }
733 //
734 // Read the projection operator
735 //
736 QList<FiffProj> projs = this->read_proj(current);
737 //
738 // Read the bad channel list
739 //
740 bads = this->read_bad_channels(current);
741 //
742 // Put it together
743 //
744 p_covData.clear();
745
746 p_covData.kind = cov_kind;
747 p_covData.diag = diagmat;
748 p_covData.dim = dim;
749 p_covData.names = names;
750
751 if(cov_diag.size() > 0)
752 p_covData.data = cov_diag;
753 else if(cov.size() > 0)
754 p_covData.data = cov;
755 else if(cov_sparse.size() > 0)
756 p_covData.data = cov_sparse;
757
758 p_covData.projs = projs;
759 p_covData.bads = bads;
760 p_covData.nfree = nfree;
761 p_covData.eig = eig;
762 p_covData.eigvec = eigvec;
763
764 //
765 return true;
766 }
767 }
768
769 qInfo("Did not find the desired covariance matrix\n");
770 return false;
771}
772
773//=============================================================================================================
774
775QList<FiffCtfComp> FiffStream::read_ctf_comp(const FiffDirNode::SPtr& p_Node, const QList<FiffChInfo>& p_Chs)
776{
777 QList<FiffCtfComp> compdata;
778 QList<FiffDirNode::SPtr> t_qListComps = p_Node->dir_tree_find(FIFFB_MNE_CTF_COMP_DATA);
779
780 qint32 i, k, p, col, row;
781 fiff_int_t kind, pos;
782 FiffTag::UPtr t_pTag;
783 for (k = 0; k < t_qListComps.size(); ++k)
784 {
785 FiffDirNode::SPtr node = t_qListComps[k];
786 //
787 // Read the data we need
788 //
790 this->read_named_matrix(node, FIFF_MNE_CTF_COMP_DATA, *mat.data());
791 for(p = 0; p < node->nent(); ++p)
792 {
793 kind = node->dir[p]->kind;
794 pos = node->dir[p]->pos;
795 if (kind == FIFF_MNE_CTF_COMP_KIND)
796 {
797 this->read_tag(t_pTag, pos);
798 break;
799 }
800 }
801 if (!t_pTag)
802 {
803 qWarning("Compensation type not found\n");
804 return compdata;
805 }
806 //
807 // Get the compensation kind and map it to a simple number
808 //
809 FiffCtfComp one;
810 one.ctfkind = *t_pTag->toInt();
811
812 t_pTag.reset();
813
814 one.kind = -1;
815 if (one.ctfkind == 1194410578) //hex2dec('47314252')
816 one.kind = 1;
817 else if (one.ctfkind == 1194476114) //hex2dec('47324252')
818 one.kind = 2;
819 else if (one.ctfkind == 1194541650) //hex2dec('47334252')
820 one.kind = 3;
821 else if (one.ctfkind == 1194479433)
822 one.kind = 4;
823 else if (one.ctfkind == 1194544969)
824 one.kind = 5;
825 else
826 one.kind = one.ctfkind;
827
828 for (p = 0; p < node->nent(); ++p)
829 {
830 kind = node->dir[p]->kind;
831 pos = node->dir[p]->pos;
833 {
834 this->read_tag(t_pTag, pos);
835 break;
836 }
837 }
838 bool calibrated;
839 if (!t_pTag)
840 calibrated = false;
841 else
842 calibrated = (bool)*t_pTag->toInt();
843
844 one.save_calibrated = calibrated;
845 one.rowcals = MatrixXd::Ones(1,mat->data.rows());//ones(1,size(mat.data,1));
846 one.colcals = MatrixXd::Ones(1,mat->data.cols());//ones(1,size(mat.data,2));
847 if (!calibrated)
848 {
849 //
850 // Calibrate...
851 //
852 //
853 // Do the columns first
854 //
855 QStringList ch_names;
856 for (p = 0; p < p_Chs.size(); ++p)
857 ch_names.append(p_Chs[p].ch_name);
858
859 qint32 count;
860 MatrixXd col_cals(mat->data.cols(), 1);
861 col_cals.setZero();
862 for (col = 0; col < mat->data.cols(); ++col)
863 {
864 count = 0;
865 for (i = 0; i < ch_names.size(); ++i)
866 {
867 if (QString::compare(mat->col_names.at(col),ch_names.at(i)) == 0)
868 {
869 count += 1;
870 p = i;
871 }
872 }
873 if (count == 0)
874 {
875 qWarning("Channel %s is not available in data",mat->col_names.at(col).toUtf8().constData());
876 return compdata;
877 }
878 else if (count > 1)
879 {
880 qWarning("Ambiguous channel %s",mat->col_names.at(col).toUtf8().constData());
881 return compdata;
882 }
883 col_cals(col,0) = 1.0f/(p_Chs[p].range*p_Chs[p].cal);
884 }
885 //
886 // Then the rows
887 //
888 MatrixXd row_cals(mat->data.rows(), 1);
889 row_cals.setZero();
890 for (row = 0; row < mat->data.rows(); ++row)
891 {
892 count = 0;
893 for (i = 0; i < ch_names.size(); ++i)
894 {
895 if (QString::compare(mat->row_names.at(row),ch_names.at(i)) == 0)
896 {
897 count += 1;
898 p = i;
899 }
900 }
901
902 if (count == 0)
903 {
904 qWarning("Channel %s is not available in data",mat->row_names.at(row).toUtf8().constData());
905 return compdata;
906 }
907 else if (count > 1)
908 {
909 qWarning("Ambiguous channel %s",mat->row_names.at(row).toUtf8().constData());
910 return compdata;
911 }
912
913 row_cals(row, 0) = p_Chs[p].range*p_Chs[p].cal;
914 }
915 mat->data = row_cals.asDiagonal()* mat->data *col_cals.asDiagonal();
916 one.rowcals = row_cals;
917 one.colcals = col_cals;
918 }
919 one.data = mat;
920 compdata.append(one);
921 }
922
923 if (compdata.size() > 0)
924 qInfo("\tRead %lld compensation matrices\n",compdata.size());
925
926 return compdata;
927}
928
929//=============================================================================================================
930
932{
934 fiff_int_t kind = -1;
935 fiff_int_t pos = -1;
936 int npoint = 0;
937 FiffTag::UPtr t_pTag;
938
939 QList<FiffDirNode::SPtr> t_qListDigData = p_Node->dir_tree_find(FIFFB_ISOTRAK);
940
941 //Check if digitizer data is available
942 if(t_qListDigData.isEmpty()) {
943 t_qListDigData = p_Node->dir_tree_find(FIFFB_MRI_SET);
944
945 if(t_qListDigData.isEmpty()) {
946 qWarning( "No Isotrak data found in %s", this->streamName().toLatin1().data());
947 return false;
948 } else {
949 p_digData.coord_frame = FIFFV_COORD_MRI;
950 }
951 } else {
952 p_digData.coord_frame = FIFFV_COORD_HEAD;
953 }
954
955 // Read actual data and store it
956 for (int k = 0; k < t_qListDigData.first()->nent(); ++k) {
957 kind = t_qListDigData.first()->dir[k]->kind;
958 pos = t_qListDigData.first()->dir[k]->pos;
959
960 switch(kind) {
961 case FIFF_DIG_POINT:
962 this->read_tag(t_pTag, pos);
963 p_digData.points.append(t_pTag->toDigPoint());
964 break;
966 this->read_tag(t_pTag, pos);
967 p_digData.coord_frame = *t_pTag->toInt();
968 break;
969 }
970 }
971
972 npoint = p_digData.points.size();
973
974 if (npoint == 0) {
975 qWarning( "No digitizer data in %s", this->streamName().toLatin1().data());
976 return false;
977 }
978
979 for (auto& dig : p_digData.points){
980 dig.coord_frame = p_digData.coord_frame;
981 }
982
983 //Add other information as default
984 p_digData.filename = this->streamName();
985 p_digData.npoint = npoint;
986
987 for (int k = 0; k < p_digData.npoint; k++) {
988 p_digData.active.append(1);
989 p_digData.discard.append(0);
990 }
991
992 return true;
993}
994
995//=============================================================================================================
996
998{
999 p_InfoForward.clear();
1000
1001 //
1002 // Find the desired blocks
1003 //
1004 QList<FiffDirNode::SPtr> parent_meg = p_Node->dir_tree_find(FIFFB_MNE_PARENT_MEAS_FILE);
1005
1006 if (parent_meg.size() == 0)
1007 {
1008 qWarning("No parent MEG information found in operator\n");
1009 return false;
1010 }
1011
1012 FiffTag::UPtr t_pTag;
1013
1014 QList<FiffChInfo> chs;
1015 FiffCoordTrans cand;
1016 fiff_int_t kind = -1;
1017 fiff_int_t pos = -1;
1018
1019 for (qint32 k = 0; k < parent_meg[0]->nent(); ++k)
1020 {
1021 kind = parent_meg[0]->dir[k]->kind;
1022 pos = parent_meg[0]->dir[k]->pos;
1023 if (kind == FIFF_CH_INFO)
1024 {
1025 this->read_tag(t_pTag, pos);
1026 chs.append( t_pTag->toChInfo() );
1027 }
1028 }
1029
1030 //
1031 // Add the channel information and make a list of channel names
1032 // for convenience
1033 //
1034 p_InfoForward.chs = chs;
1035 for (qint32 c = 0; c < p_InfoForward.chs.size(); ++c)
1036 p_InfoForward.ch_names << p_InfoForward.chs[c].ch_name;
1037
1038 p_InfoForward.nchan = chs.size();
1039
1040 //
1041 // Get the MEG device <-> head coordinate transformation
1042 //
1043 if(parent_meg[0]->find_tag(this, FIFF_COORD_TRANS, t_pTag))
1044 {
1045 cand = t_pTag->toCoordTrans();
1046 if(cand.from == FIFFV_COORD_DEVICE && cand.to == FIFFV_COORD_HEAD)
1047 p_InfoForward.dev_head_t = cand;
1048 else if (cand.from == FIFFV_MNE_COORD_CTF_HEAD && cand.to == FIFFV_COORD_HEAD)
1049 p_InfoForward.ctf_head_t = cand;
1050 else
1051 qWarning("MEG device/head coordinate transformation not found");
1052 }
1053 else
1054 qWarning("MEG/head coordinate transformation not found.\n");
1055
1056 //
1057 // Load the bad channel list
1058 //
1059 p_InfoForward.bads = this->read_bad_channels(p_Node);
1060
1061 return true;
1062}
1063
1064//=============================================================================================================
1065
1067{
1068// if (info)
1069// delete info;
1070 info.clear();
1071 //
1072 // Find the desired blocks
1073 //
1074 QList<FiffDirNode::SPtr> meas = p_Node->dir_tree_find(FIFFB_MEAS);
1075
1076 if (meas.size() == 0)
1077 {
1078 qWarning("Could not find measurement data\n");
1079 return false;
1080 }
1081 //
1082 QList<FiffDirNode::SPtr> meas_info = meas[0]->dir_tree_find(FIFFB_MEAS_INFO);
1083 if (meas_info.count() == 0) {
1084 qWarning("Could not find measurement info\n");
1085// delete meas[0];
1086 return false;
1087 }
1088 //
1089 // Read measurement info
1090 //
1091 FiffTag::UPtr t_pTag;
1092
1093 fiff_int_t nchan = -1;
1094 float sfreq = -1.0f;
1095 float linefreq = -1.0f;
1096 QList<FiffChInfo> chs;
1097 float lowpass = -1.0f;
1098 float highpass = -1.0f;
1099
1100 int proj_id = 0;
1101 QString proj_name = "";
1102 QString xplotter_layout = "";
1103
1104 QString utc_offset = "";
1105 fiff_int_t gantry_angle = -1;
1106
1107 QString experimenter = "";
1108 QString description = "";
1109
1110 FiffChInfo t_chInfo;
1111
1112 FiffCoordTrans cand;// = nullptr;
1113 FiffCoordTrans dev_head_t;// = nullptr;
1114 FiffCoordTrans ctf_head_t;// = nullptr;
1115
1116 fiff_int_t meas_date[2];
1117 meas_date[0] = -1;
1118 meas_date[1] = -1;
1119
1120 fiff_int_t kind = -1;
1121 fiff_int_t pos = -1;
1122
1123 for (qint32 k = 0; k < meas_info[0]->nent(); ++k)
1124 {
1125 kind = meas_info[0]->dir[k]->kind;
1126 pos = meas_info[0]->dir[k]->pos;
1127 switch (kind)
1128 {
1129 case FIFF_NCHAN:
1130 this->read_tag(t_pTag, pos);
1131 nchan = *t_pTag->toInt();
1132 break;
1133 case FIFF_SFREQ:
1134 this->read_tag(t_pTag, pos);
1135 sfreq = *t_pTag->toFloat();
1136 break;
1137 case FIFF_LINE_FREQ:
1138 this->read_tag(t_pTag, pos);
1139 linefreq = *t_pTag->toFloat();
1140 break;
1141 case FIFF_CH_INFO:
1142 this->read_tag(t_pTag, pos);
1143 chs.append( t_pTag->toChInfo() );
1144 break;
1145 case FIFF_LOWPASS:
1146 this->read_tag(t_pTag, pos);
1147 lowpass = *t_pTag->toFloat();
1148 break;
1149 case FIFF_HIGHPASS:
1150 this->read_tag(t_pTag, pos);
1151 highpass = *t_pTag->toFloat();
1152 break;
1153 case FIFF_MEAS_DATE:
1154 this->read_tag(t_pTag, pos);
1155 meas_date[0] = t_pTag->toInt()[0];
1156 meas_date[1] = t_pTag->toInt()[1];
1157 break;
1158 case FIFF_COORD_TRANS:
1159 //ToDo: This has to be debugged!!
1160 this->read_tag(t_pTag, pos);
1161 cand = t_pTag->toCoordTrans();
1162 if(cand.from == FIFFV_COORD_DEVICE && cand.to == FIFFV_COORD_HEAD)
1163 dev_head_t = cand;
1164 else if (cand.from == FIFFV_MNE_COORD_CTF_HEAD && cand.to == FIFFV_COORD_HEAD)
1165 ctf_head_t = cand;
1166 break;
1167 case FIFF_PROJ_ID:
1168 this->read_tag(t_pTag,pos);
1169 proj_id = *t_pTag->toInt();
1170 break;
1171 case FIFF_PROJ_NAME:
1172 this->read_tag(t_pTag,pos);
1173 proj_name = t_pTag->toString();
1174 break;
1176 this->read_tag(t_pTag,pos);
1177 xplotter_layout = t_pTag->toString();
1178 break;
1179 case FIFF_EXPERIMENTER:
1180 this->read_tag(t_pTag,pos);
1181 experimenter = t_pTag->toString();
1182 break;
1183 case FIFF_DESCRIPTION:
1184 this->read_tag(t_pTag,pos);
1185 description = t_pTag->toString();
1186 break;
1187 case FIFF_GANTRY_ANGLE:
1188 this->read_tag(t_pTag,pos);
1189 gantry_angle = *t_pTag->toInt();
1190 break;
1191 case FIFF_UTC_OFFSET:
1192 this->read_tag(t_pTag,pos);
1193 utc_offset = t_pTag->toString();
1194 break;
1195 }
1196 }
1197 //
1198 // Check that we have everything we need
1199 //
1200 if (nchan < 0)
1201 {
1202 qWarning("Number of channels in not defined\n");
1203 return false;
1204 }
1205 if (sfreq < 0)
1206 {
1207 qWarning("Sampling frequency is not defined\n");
1208 return false;
1209 }
1210 if (linefreq < 0)
1211 {
1212 qWarning("Line frequency is not defined\n");
1213 }
1214 if (chs.size() == 0)
1215 {
1216 qWarning("Channel information not defined\n");
1217 return false;
1218 }
1219 if (chs.size() != nchan)
1220 {
1221 qWarning("Incorrect number of channel definitions found\n");
1222 return false;
1223 }
1224
1225 if (dev_head_t.isEmpty() || ctf_head_t.isEmpty())
1226 {
1227 QList<FiffDirNode::SPtr> hpi_result = meas_info[0]->dir_tree_find(FIFFB_HPI_RESULT);
1228 if (hpi_result.size() == 1)
1229 {
1230 for( qint32 k = 0; k < hpi_result[0]->nent(); ++k)
1231 {
1232 kind = hpi_result[0]->dir[k]->kind;
1233 pos = hpi_result[0]->dir[k]->pos;
1234 if (kind == FIFF_COORD_TRANS)
1235 {
1236 this->read_tag(t_pTag, pos);
1237 cand = t_pTag->toCoordTrans();
1238 if (cand.from == FIFFV_COORD_DEVICE && cand.to == FIFFV_COORD_HEAD)
1239 dev_head_t = cand;
1240 else if (cand.from == FIFFV_MNE_COORD_CTF_HEAD && cand.to == FIFFV_COORD_HEAD)
1241 ctf_head_t = cand;
1242 }
1243 }
1244 }
1245 }
1246 //
1247 // Locate the Polhemus data
1248 //
1249 QList<FiffDirNode::SPtr> isotrak = meas_info[0]->dir_tree_find(FIFFB_ISOTRAK);
1250
1251 QList<FiffDigPoint> dig;
1252 fiff_int_t coord_frame = FIFFV_COORD_HEAD;
1253 FiffCoordTrans dig_trans;
1254 qint32 k = 0;
1255
1256 if (isotrak.size() == 1)
1257 {
1258 for (k = 0; k < isotrak[0]->nent(); ++k)
1259 {
1260 kind = isotrak[0]->dir[k]->kind;
1261 pos = isotrak[0]->dir[k]->pos;
1262 if (kind == FIFF_DIG_POINT)
1263 {
1264 this->read_tag(t_pTag, pos);
1265 dig.append(t_pTag->toDigPoint());
1266 }
1267 else
1268 {
1269 if (kind == FIFF_MNE_COORD_FRAME)
1270 {
1271 this->read_tag(t_pTag, pos);
1272 qDebug() << "NEEDS To BE DEBBUGED: FIFF_MNE_COORD_FRAME" << t_pTag->getType();
1273 coord_frame = *t_pTag->toInt();
1274 }
1275 else if (kind == FIFF_COORD_TRANS)
1276 {
1277 this->read_tag(t_pTag, pos);
1278 qDebug() << "NEEDS To BE DEBBUGED: FIFF_COORD_TRANS" << t_pTag->getType();
1279 dig_trans = t_pTag->toCoordTrans();
1280 }
1281 }
1282 }
1283 }
1284 for(k = 0; k < dig.size(); ++k)
1285 dig[k].coord_frame = coord_frame;
1286
1287 if (!dig_trans.isEmpty()) //if exist('dig_trans','var')
1288 if (dig_trans.from != coord_frame && dig_trans.to != coord_frame)
1289 dig_trans.clear();
1290
1291 //
1292 // Locate the acquisition information
1293 //
1294 QList<FiffDirNode::SPtr> acqpars = meas_info[0]->dir_tree_find(FIFFB_DACQ_PARS);
1295 QString acq_pars;
1296 QString acq_stim;
1297 if (acqpars.size() == 1)
1298 {
1299 for( k = 0; k < acqpars[0]->nent(); ++k)
1300 {
1301 kind = acqpars[0]->dir[k]->kind;
1302 pos = acqpars[0]->dir[k]->pos;
1303 if (kind == FIFF_DACQ_PARS)
1304 {
1305 this->read_tag(t_pTag, pos);
1306 acq_pars = t_pTag->toString();
1307 }
1308 else if (kind == FIFF_DACQ_STIM)
1309 {
1310 this->read_tag(t_pTag, pos);
1311 acq_stim = t_pTag->toString();
1312 }
1313 }
1314 }
1315 //
1316 // Load the SSP data
1317 //
1318 QList<FiffProj> projs = this->read_proj(meas_info[0]);//ToDo Member Function
1319 //
1320 // Load the CTF compensation data
1321 //
1322 QList<FiffCtfComp> comps = this->read_ctf_comp(meas_info[0], chs);//ToDo Member Function
1323 //
1324 // Load the bad channel list
1325 //
1326 QStringList bads = this->read_bad_channels(p_Node);
1327 //
1328 // Put the data together
1329 //
1330// info = new FiffInfo();
1331 if (p_Node->id.version != -1)
1332 info.file_id = p_Node->id;
1333 else
1334 info.file_id.version = -1;
1335
1336 //
1337 // Make the most appropriate selection for the measurement id
1338 //
1339 if (meas_info[0]->parent_id.version == -1)
1340 {
1341 if (meas_info[0]->id.version == -1)
1342 {
1343 if (meas[0]->id.version == -1)
1344 {
1345 if (meas[0]->parent_id.version == -1)
1346 info.meas_id = info.file_id;
1347 else
1348 info.meas_id = meas[0]->parent_id;
1349 }
1350 else
1351 info.meas_id = meas[0]->id;
1352 }
1353 else
1354 info.meas_id = meas_info[0]->id;
1355 }
1356 else
1357 info.meas_id = meas_info[0]->parent_id;
1358
1359 if (meas_date[0] == -1)
1360 {
1361 info.meas_date[0] = info.meas_id.time.secs;
1362 info.meas_date[1] = info.meas_id.time.usecs;
1363 }
1364 else
1365 {
1366 info.meas_date[0] = meas_date[0];
1367 info.meas_date[1] = meas_date[1];
1368 }
1369
1370 info.nchan = nchan;
1371 info.sfreq = sfreq;
1372 info.linefreq = linefreq;
1373
1374 if (highpass != -1.0f)
1375 info.highpass = highpass;
1376 else
1377 info.highpass = 0.0f;
1378
1379 if (lowpass != -1.0f)
1380 info.lowpass = lowpass;
1381 else
1382 info.lowpass = info.sfreq/2.0;
1383
1384 //
1385 // Add the channel information and make a list of channel names
1386 // for convenience
1387 //
1388 info.chs = chs;
1389 for (qint32 c = 0; c < info.nchan; ++c)
1390 info.ch_names << info.chs[c].ch_name;
1391
1392 //
1393 // Add the coordinate transformations
1394 //
1395 info.dev_head_t = dev_head_t;
1396 info.ctf_head_t = ctf_head_t;
1397 if ((!info.dev_head_t.isEmpty()) && (!info.ctf_head_t.isEmpty())) //~isempty(info.dev_head_t) && ~isempty(info.ctf_head_t)
1398 {
1399 info.dev_ctf_t = info.dev_head_t;
1400 info.dev_ctf_t.to = info.ctf_head_t.from;
1401 info.dev_ctf_t.trans = ctf_head_t.trans.inverse()*info.dev_ctf_t.trans;
1402 }
1403 else
1404 info.dev_ctf_t.clear();
1405
1406 //
1407 // All kinds of auxliary stuff
1408 //
1409 info.dig = dig;
1410 if (!dig_trans.isEmpty())
1411 info.dig_trans = dig_trans;
1412
1413 info.experimenter = experimenter;
1414 info.description = description;
1415 info.proj_id = proj_id;
1416 info.proj_name = proj_name;
1417 info.xplotter_layout = xplotter_layout;
1418 info.gantry_angle = gantry_angle;
1419 info.utc_offset = utc_offset;
1420
1421 info.bads = bads;
1422 info.projs = projs;
1423 info.comps = comps;
1424 info.acq_pars = acq_pars;
1425 info.acq_stim = acq_stim;
1426
1427 p_NodeInfo = meas[0];
1428
1429 return true;
1430}
1431
1432//=============================================================================================================
1433
1435{
1436 mat.clear();
1437
1438 FiffDirNode::SPtr node = p_Node;
1439 //
1440 // Descend one level if necessary
1441 //
1442 bool found_it = false;
1443 if (node->type != FIFFB_MNE_NAMED_MATRIX)
1444 {
1445 for (int k = 0; k < node->nchild(); ++k)
1446 {
1447 if (node->children[k]->type == FIFFB_MNE_NAMED_MATRIX)
1448 {
1449 if(node->children[k]->has_tag(matkind))
1450 {
1451 node = node->children[k];
1452 found_it = true;
1453 break;
1454 }
1455 }
1456 }
1457 if (!found_it)
1458 {
1459 qWarning("Fiff::read_named_matrix: Desired named matrix (kind = %d) not available\n",matkind);
1460 return false;
1461 }
1462 }
1463 else
1464 {
1465 if (!node->has_tag(matkind))
1466 {
1467 qWarning("Desired named matrix (kind = %d) not available",matkind);
1468 return false;
1469 }
1470 }
1471
1472 FiffTag::UPtr t_pTag;
1473 //
1474 // Read everything we need
1475 //
1476 if(!node->find_tag(this, matkind, t_pTag))
1477 {
1478 qWarning("Matrix data missing.\n");
1479 return false;
1480 }
1481 else
1482 {
1483 //qDebug() << "Is Matrix" << t_pTag->isMatrix() << "Special Type:" << t_pTag->getType();
1484 mat.data = t_pTag->toFloatMatrix().cast<double>();
1485 mat.data.transposeInPlace();
1486 }
1487
1488 mat.nrow = mat.data.rows();
1489 mat.ncol = mat.data.cols();
1490
1491 if(node->find_tag(this, FIFF_MNE_NROW, t_pTag))
1492 if (*t_pTag->toInt() != mat.nrow)
1493 {
1494 qWarning("Number of rows in matrix data and FIFF_MNE_NROW tag do not match");
1495 return false;
1496 }
1497 if(node->find_tag(this, FIFF_MNE_NCOL, t_pTag))
1498 if (*t_pTag->toInt() != mat.ncol)
1499 {
1500 qWarning("Number of columns in matrix data and FIFF_MNE_NCOL tag do not match");
1501 return false;
1502 }
1503
1504 QString row_names;
1505 if(node->find_tag(this, FIFF_MNE_ROW_NAMES, t_pTag))
1506 row_names = t_pTag->toString();
1507
1508 QString col_names;
1509 if(node->find_tag(this, FIFF_MNE_COL_NAMES, t_pTag))
1510 col_names = t_pTag->toString();
1511
1512 //
1513 // Put it together
1514 //
1515 if (!row_names.isEmpty())
1516 mat.row_names = split_name_list(row_names);
1517
1518 if (!col_names.isEmpty())
1519 mat.col_names = split_name_list(col_names);
1520
1521 if (mat.row_names.size() != mat.nrow)
1522 {
1523 qWarning("FiffStream::read_named_matrix - Number of rows in matrix data and row names do not match\n");
1524 }
1525
1526 if (mat.col_names.size() != mat.ncol)
1527 {
1528 qWarning("FiffStream::read_named_matrix - Number of columns in matrix data and column names do not match\n");
1529 }
1530
1531 return true;
1532}
1533
1534//=============================================================================================================
1535
1536QList<FiffProj> FiffStream::read_proj(const FiffDirNode::SPtr& p_Node)
1537{
1538 QList<FiffProj> projdata;// = struct('kind',{},'active',{},'desc',{},'data',{});
1539 //
1540 // Locate the projection data
1541 //
1542 QList<FiffDirNode::SPtr> t_qListNodes = p_Node->dir_tree_find(FIFFB_PROJ);
1543 if ( t_qListNodes.size() == 0 )
1544 return projdata;
1545
1546 FiffTag::UPtr t_pTag;
1547 t_qListNodes[0]->find_tag(this, FIFF_NCHAN, t_pTag);
1548 fiff_int_t global_nchan = 0;
1549 if (t_pTag)
1550 global_nchan = *t_pTag->toInt();
1551
1552 fiff_int_t nchan;
1553 QList<FiffDirNode::SPtr> t_qListItems = t_qListNodes[0]->dir_tree_find(FIFFB_PROJ_ITEM);
1554 for ( qint32 i = 0; i < t_qListItems.size(); ++i)
1555 {
1556 //
1557 // Find all desired tags in one item
1558 //
1559 FiffDirNode::SPtr t_pFiffDirTreeItem = t_qListItems[i];
1560 t_pFiffDirTreeItem->find_tag(this, FIFF_NCHAN, t_pTag);
1561 if (t_pTag)
1562 nchan = *t_pTag->toInt();
1563 else
1564 nchan = global_nchan;
1565
1566 t_pFiffDirTreeItem->find_tag(this, FIFF_DESCRIPTION, t_pTag);
1567 QString desc; // maybe, in some cases this has to be a struct.
1568 if (t_pTag)
1569 {
1570 qDebug() << "read_proj: this has to be debugged";
1571 desc = t_pTag->toString();
1572 }
1573 else
1574 {
1575 t_pFiffDirTreeItem->find_tag(this, FIFF_NAME, t_pTag);
1576 if (t_pTag)
1577 desc = t_pTag->toString();
1578 else
1579 {
1580 qWarning("Projection item description missing\n");
1581 return projdata;
1582 }
1583 }
1584// t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_CH_NAME_LIST, t_pTag);
1585// QString namelist;
1586// if (t_pTag)
1587// {
1588// namelist = t_pTag->toString();
1589// }
1590// else
1591// {
1592// printf("Projection item channel list missing\n");
1593// return projdata;
1594// }
1595 t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_KIND, t_pTag);
1596 fiff_int_t kind;
1597 if (t_pTag)
1598 {
1599 kind = *t_pTag->toInt();
1600 }
1601 else
1602 {
1603 qWarning("Projection item kind missing");
1604 return projdata;
1605 }
1606 t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_NVEC, t_pTag);
1607 fiff_int_t nvec;
1608 if (t_pTag)
1609 {
1610 nvec = *t_pTag->toInt();
1611 }
1612 else
1613 {
1614 qWarning("Number of projection vectors not specified\n");
1615 return projdata;
1616 }
1617 t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_CH_NAME_LIST, t_pTag);
1618 QStringList names;
1619 if (t_pTag)
1620 {
1621 names = split_name_list(t_pTag->toString());
1622 }
1623 else
1624 {
1625 qWarning("Projection item channel list missing\n");
1626 return projdata;
1627 }
1628 t_pFiffDirTreeItem->find_tag(this, FIFF_PROJ_ITEM_VECTORS, t_pTag);
1629 MatrixXd data;// = nullptr;
1630 if (t_pTag)
1631 {
1632 data = t_pTag->toFloatMatrix().cast<double>();
1633 data.transposeInPlace();
1634 }
1635 else
1636 {
1637 qWarning("Projection item data missing\n");
1638 return projdata;
1639 }
1640 t_pFiffDirTreeItem->find_tag(this, FIFF_MNE_PROJ_ITEM_ACTIVE, t_pTag);
1641 bool active;
1642 if (t_pTag)
1643 active = *t_pTag->toInt();
1644 else
1645 active = false;
1646
1647 if (data.cols() != names.size())
1648 {
1649 qWarning("Number of channel names does not match the size of data matrix\n");
1650 return projdata;
1651 }
1652
1653 //
1654 // create a named matrix for the data
1655 //
1656 QStringList defaultList;
1657 FiffNamedMatrix t_fiffNamedMatrix(nvec, nchan, defaultList, names, data);
1658
1659 FiffProj one(kind, active, desc, t_fiffNamedMatrix);
1660 //
1661 projdata.append(one);
1662 }
1663
1664 if (projdata.size() > 0)
1665 {
1666 qInfo("\tRead a total of %lld projection items:\n", projdata.size());
1667 for(qint32 k = 0; k < projdata.size(); ++k)
1668 {
1669 qInfo("\t\t%s (%d x %d) %s\n",projdata[k].desc.toUtf8().constData(), projdata[k].data->nrow, projdata[k].data->ncol, projdata[k].active ? "active" : "idle");
1670 }
1671 }
1672
1673 return projdata;
1674}
1675
1676//=============================================================================================================
1677
1679{
1680 if(pos >= 0)
1681 {
1682 this->device()->seek(pos);
1683 }
1684
1685 if(!p_pTag)
1686 return false;
1687
1688 //
1689 // Read data when available
1690 //
1691 if (p_pTag->size() > 0)
1692 {
1693 this->readRawData(p_pTag->data(), p_pTag->size());
1695 }
1696
1697 if (p_pTag->next != FIFFV_NEXT_SEQ)
1698 this->device()->seek(p_pTag->next);//fseek(fid,tag.next,'bof');
1699
1700 return true;
1701}
1702
1703//=============================================================================================================
1704
1706{
1707 fiff_long_t pos = this->device()->pos();
1708
1709 p_pTag = std::make_unique<FiffTag>();
1710
1711 //Option 1
1712// t_DataStream.readRawData((char *)p_pTag, FIFFC_TAG_INFO_SIZE);
1713// p_pTag->kind = Fiff::swap_int(p_pTag->kind);
1714// p_pTag->type = Fiff::swap_int(p_pTag->type);
1715// p_pTag->size = Fiff::swap_int(p_pTag->size);
1716// p_pTag->next = Fiff::swap_int(p_pTag->next);
1717
1718 //Option 2
1719 *this >> p_pTag->kind;
1720 *this >> p_pTag->type;
1721 qint32 size;
1722 *this >> size;
1723 p_pTag->resize(size);
1724 *this >> p_pTag->next;
1725
1726// qDebug() << "read_tag_info" << " Kind:" << p_pTag->kind << " Type:" << p_pTag->type << " Size:" << p_pTag->size() << " Next:" << p_pTag->next;
1727
1728 if (p_bDoSkip)
1729 {
1730 QTcpSocket* t_qTcpSocket = qobject_cast<QTcpSocket*>(this->device());
1731 if(t_qTcpSocket)
1732 {
1733 this->skipRawData(p_pTag->size());
1734 }
1735 else
1736 {
1737 if (p_pTag->next > 0)
1738 {
1739 if(!this->device()->seek(p_pTag->next)) {
1740 qCritical("fseek"); //fseek(fid,tag.next,'bof');
1741 pos = -1;
1742 }
1743 }
1744 else if (p_pTag->size() > 0 && p_pTag->next == FIFFV_NEXT_SEQ)
1745 {
1746 if(!this->device()->seek(this->device()->pos()+p_pTag->size())) {
1747 qCritical("fseek"); //fseek(fid,tag.size,'cof');
1748 pos = -1;
1749 }
1750 }
1751 }
1752 }
1753 return pos;
1754}
1755
1756//=============================================================================================================
1757
1759{
1760 while(this->device()->bytesAvailable() < 16)
1761 this->device()->waitForReadyRead(10);
1762
1763// if(!this->read_tag_info(p_pTag, false))
1764// return false;
1765 this->read_tag_info(p_pTag, false);
1766
1767 while(this->device()->bytesAvailable() < p_pTag->size())
1768 this->device()->waitForReadyRead(10);
1769
1770 if(!this->read_tag_data(p_pTag))
1771 return false;
1772
1773 return true;
1774}
1775
1776//=============================================================================================================
1777
1779 fiff_long_t pos)
1780{
1781 if (pos >= 0) {
1782 this->device()->seek(pos);
1783 }
1784
1785 p_pTag = std::make_unique<FiffTag>();
1786
1787 //
1788 // Read fiff tag header from stream
1789 //
1790 *this >> p_pTag->kind;
1791 *this >> p_pTag->type;
1792 qint32 size;
1793 *this >> size;
1794 p_pTag->resize(size);
1795 *this >> p_pTag->next;
1796
1797// qDebug() << "read_tag" << " Kind:" << p_pTag->kind << " Type:" << p_pTag->type << " Size:" << p_pTag->size() << " Next:" << p_pTag->next;
1798
1799 //
1800 // Read data when available
1801 //
1802 int endian;
1803 if (this->byteOrder() == QDataStream::LittleEndian){
1804 endian = FIFFV_LITTLE_ENDIAN;
1805 //printf("Endian: Little\n");
1806 } else {
1807 endian = FIFFV_BIG_ENDIAN;
1808 //printf("Endian: Big\n");
1809 }
1810
1811 if (p_pTag->size() > 0)
1812 {
1813 this->readRawData(p_pTag->data(), p_pTag->size());
1814
1815 //FiffTag::convert_tag_data(p_pTag,FIFFV_BIG_ENDIAN,FIFFV_NATIVE_ENDIAN);
1817 }
1818
1819 if (p_pTag->next != FIFFV_NEXT_SEQ)
1820 this->device()->seek(p_pTag->next);//fseek(fid,tag.next,'bof');
1821
1822 return true;
1823}
1824
1825//=============================================================================================================
1826
1827bool FiffStream::setup_read_raw(QIODevice &p_IODevice,
1828 FiffRawData& data,
1829 bool allow_maxshield,
1830 bool is_littleEndian)
1831{
1832 //
1833 // Open the file
1834 //
1835 FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
1836 QString t_sFileName = t_pStream->streamName();
1837
1838 if(is_littleEndian){
1839 //printf("Setting stream to little Endian\n");
1840 t_pStream->setByteOrder(QDataStream::LittleEndian);
1841 }
1842
1843 qInfo("Opening raw data %s...\n",t_sFileName.toUtf8().constData());
1844
1845 if(!t_pStream->open()){
1846 return false;
1847 }
1848
1849 //
1850 // Read the measurement info
1851 //
1852 FiffInfo info;// = nullptr;
1853 FiffDirNode::SPtr meas;
1854 if(!t_pStream->read_meas_info(t_pStream->dirtree(), info, meas))
1855 return false;
1856
1857 //
1858 // Locate the data of interest
1859 //
1860 QList<FiffDirNode::SPtr> raw = meas->dir_tree_find(FIFFB_RAW_DATA);
1861 if (raw.size() == 0)
1862 {
1863 raw = meas->dir_tree_find(FIFFB_CONTINUOUS_DATA);
1864 if(allow_maxshield)
1865 {
1866// for (qint32 i = 0; i < raw.size(); ++i)
1867// if(raw[i])
1868// delete raw[i];
1869 raw = meas->dir_tree_find(FIFFB_SMSH_RAW_DATA);
1870 qInfo("Maxshield data found\n");
1871
1872 if (raw.size() == 0)
1873 {
1874 qWarning("No raw data in %s\n", t_sFileName.toUtf8().constData());
1875 return false;
1876 }
1877 }
1878 else
1879 {
1880 if (raw.size() == 0)
1881 {
1882 qWarning("No raw data in %s\n", t_sFileName.toUtf8().constData());
1883 return false;
1884 }
1885 }
1886 }
1887 //
1888 // Set up the output structure
1889 //
1890 info.filename = t_sFileName;
1891
1892 data.clear();
1893 data.file = t_pStream;// fid;
1894 data.info = info;
1895 data.first_samp = 0;
1896 data.last_samp = 0;
1897 //
1898 // Process the directory
1899 //
1900 QList<FiffDirEntry::SPtr> dir = raw[0]->dir;
1901 fiff_int_t nent = raw[0]->nent();
1902 fiff_int_t nchan = info.nchan;
1903 fiff_int_t first = 0;
1904 fiff_int_t first_samp = 0;
1905 fiff_int_t first_skip = 0;
1906 //
1907 // Get first sample tag if it is there
1908 //
1909 FiffTag::UPtr t_pTag;
1910 if (dir[first]->kind == FIFF_FIRST_SAMPLE)
1911 {
1912 t_pStream->read_tag(t_pTag, dir[first]->pos);
1913 first_samp = *t_pTag->toInt();
1914 ++first;
1915 }
1916 //
1917 // Omit initial skip
1918 //
1919 if (dir[first]->kind == FIFF_DATA_SKIP)
1920 {
1921 //
1922 // This first skip can be applied only after we know the buffer size
1923 //
1924 t_pStream->read_tag(t_pTag, dir[first]->pos);
1925 first_skip = *t_pTag->toInt();
1926 ++first;
1927 }
1928 data.first_samp = first_samp;
1929 //
1930 // Go through the remaining tags in the directory
1931 //
1932 QList<FiffRawDir> rawdir;
1933// rawdir = struct('ent',{},'first',{},'last',{},'nsamp',{});
1934 fiff_int_t nskip = 0;
1935 fiff_int_t ndir = 0;
1936 fiff_int_t nsamp = 0;
1937 for (qint32 k = first; k < nent; ++k)
1938 {
1939 FiffDirEntry::SPtr ent = dir[k];
1940 if (ent->kind == FIFF_DATA_SKIP)
1941 {
1942 t_pStream->read_tag(t_pTag, ent->pos);
1943 nskip = *t_pTag->toInt();
1944 }
1945 else if(ent->kind == FIFF_DATA_BUFFER)
1946 {
1947 //
1948 // Figure out the number of samples in this buffer
1949 //
1950 switch(ent->type)
1951 {
1952 case FIFFT_DAU_PACK16:
1953 nsamp = ent->size/(2*nchan);
1954 break;
1955 case FIFFT_SHORT:
1956 nsamp = ent->size/(2*nchan);
1957 break;
1958 case FIFFT_FLOAT:
1959 nsamp = ent->size/(4*nchan);
1960 break;
1961 case FIFFT_INT:
1962 nsamp = ent->size/(4*nchan);
1963 break;
1964 default:
1965 qWarning("Cannot handle data buffers of type %d\n",ent->type);
1966 return false;
1967 }
1968 //
1969 // Do we have an initial skip pending?
1970 //
1971 if (first_skip > 0)
1972 {
1973 first_samp += nsamp*first_skip;
1974 data.first_samp = first_samp;
1975 first_skip = 0;
1976 }
1977 //
1978 // Do we have a skip pending?
1979 //
1980 if (nskip > 0)
1981 {
1982 FiffRawDir t_RawDir;
1983 t_RawDir.first = first_samp;
1984 t_RawDir.last = first_samp + nskip*nsamp - 1;//ToDo -1 right or is that MATLAB syntax
1985 t_RawDir.nsamp = nskip*nsamp;
1986 rawdir.append(t_RawDir);
1987 first_samp = first_samp + nskip*nsamp;
1988 nskip = 0;
1989 ++ndir;
1990 }
1991 //
1992 // Add a data buffer
1993 //
1994 FiffRawDir t_RawDir;
1995 t_RawDir.ent = ent;
1996 t_RawDir.first = first_samp;
1997 t_RawDir.last = first_samp + nsamp - 1;//ToDo -1 right or is that MATLAB syntax
1998 t_RawDir.nsamp = nsamp;
1999 rawdir.append(t_RawDir);
2000 first_samp += nsamp;
2001 ++ndir;
2002 }
2003 }
2004 data.last_samp = first_samp - 1;//ToDo -1 right or is that MATLAB syntax
2005 //
2006 // Add the calibration factors
2007 //
2008 RowVectorXd cals(data.info.nchan);
2009 cals.setZero();
2010 for (qint32 k = 0; k < data.info.nchan; ++k)
2011 cals[k] = data.info.chs[k].range*data.info.chs[k].cal;
2012 //
2013 data.cals = cals;
2014 data.rawdir = rawdir;
2015 //data->proj = [];
2016 //data.comp = [];
2017 //
2018 qInfo("\tRange : %d ... %d = %9.3f ... %9.3f secs",
2019 data.first_samp,data.last_samp,
2020 static_cast<double>(data.first_samp)/data.info.sfreq,
2021 static_cast<double>(data.last_samp)/data.info.sfreq);
2022 qInfo("Ready.");
2023 data.file->close();
2024
2025 return true;
2026}
2027
2028//=============================================================================================================
2029
2030QStringList FiffStream::split_name_list(QString p_sNameList)
2031{
2032 return p_sNameList.replace(" ","").split(":");
2033}
2034
2035//=============================================================================================================
2036
2041
2042//=============================================================================================================
2043
2045{
2046 FiffStream::SPtr p_pStream(new FiffStream(&p_IODevice));
2047 QString t_sFileName = p_pStream->streamName();
2048
2049 if(!p_IODevice.isOpen())
2050 {
2051 if(!p_pStream->device()->open(QIODevice::WriteOnly))
2052 {
2053 qWarning("Cannot write to %s\n", t_sFileName.toUtf8().constData());//consider throw
2054 FiffStream::SPtr p_pEmptyStream;
2055 return p_pEmptyStream;
2056 }
2057 }
2058
2059 //
2060 // Write the compulsory items
2061 //
2062 p_pStream->write_id(FIFF_FILE_ID);//1
2063 int null_pointer = FIFFV_NEXT_NONE;
2064 p_pStream->write_int(FIFF_DIR_POINTER,&null_pointer);//2
2065 p_pStream->write_int(FIFF_FREE_LIST,&null_pointer);//3
2066 //
2067 // Ready for more
2068 //
2069 return p_pStream;
2070}
2071
2072//=============================================================================================================
2073
2075{
2076
2077 FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
2078 QString t_sFileName = t_pStream->streamName();
2079
2080 /*
2081 * Try to open...
2082 */
2083 if(!t_pStream->open(QIODevice::ReadWrite)) {
2084 qCritical("Cannot open %s\n", t_sFileName.toUtf8().constData());//consider throw
2085 return FiffStream::SPtr();
2086 }
2087
2088 FiffTag::UPtr t_pTag;
2089 long dirpos,pointerpos;
2090
2091 QFile *file = qobject_cast<QFile *>(t_pStream->device());
2092
2093 if (file != nullptr) {
2094 /*
2095 * Ensure that the last tag in the directory has next set to FIFF_NEXT_NONE
2096 */
2097 pointerpos = t_pStream->dir()[t_pStream->nent()-2]->pos;
2098 if(!t_pStream->read_tag(t_pTag,pointerpos)){
2099 qCritical("Could not read last tag in the directory list!");
2100 t_pStream->close();
2101 return FiffStream::SPtr();
2102 }
2103 if (t_pTag->next != FIFFV_NEXT_NONE) {
2104 t_pTag->next = FIFFV_NEXT_NONE;
2105 t_pStream->write_tag(t_pTag,pointerpos);
2106 }
2107 /*
2108 * Read directory pointer
2109 */
2110 pointerpos = t_pStream->dir()[1]->pos;
2111 if(!t_pStream->read_tag(t_pTag,pointerpos)){
2112 qCritical("Could not read directory pointer!");
2113 t_pStream->close();
2114 return FiffStream::SPtr();
2115 }
2116 /*
2117 * Do we have a directory?
2118 */
2119 dirpos = *t_pTag->toInt();
2120 if (dirpos > 0) {
2121 /*
2122 * Yes! We will ignore it.
2123 */
2124 t_pStream->write_dir_pointer(-1, pointerpos);
2125 /*
2126 * Clean up the trailing end
2127 */
2128 file->resize(dirpos);//truncate file to new size
2129 }
2130 /*
2131 * Seek to end for writing
2132 */
2133 t_pStream->device()->seek(file->size());//SEEK_END
2134 }
2135 return t_pStream;
2136}
2137
2138//=============================================================================================================
2139
2141 const FiffInfo& info,
2142 RowVectorXd& cals,
2143 MatrixXi sel,
2144 bool bResetRange)
2145{
2146 //
2147 // We will always write floats
2148 //
2149 fiff_int_t data_type = 4;
2150 qint32 k;
2151
2152 if(sel.cols() == 0)
2153 {
2154 sel.resize(1,info.nchan);
2155 for (k = 0; k < info.nchan; ++k)
2156 sel(0, k) = k; //+1 when MATLAB notation
2157 }
2158
2159 QList<FiffChInfo> chs;
2160
2161 for(k = 0; k < sel.cols(); ++k)
2162 chs << info.chs.at(sel(0,k));
2163
2164 fiff_int_t nchan = chs.size();
2165
2166 //
2167 // Create the file and save the essentials
2168 //
2169 FiffStream::SPtr t_pStream = start_file(p_IODevice);//1, 2, 3
2170 t_pStream->start_block(FIFFB_MEAS);//4
2171 t_pStream->write_id(FIFF_BLOCK_ID);//5
2172 if(info.meas_id.version != -1)
2173 {
2174 t_pStream->write_id(FIFF_PARENT_BLOCK_ID,info.meas_id);//6
2175 }
2176 //
2177 //
2178 // Measurement info
2179 //
2180 t_pStream->start_block(FIFFB_MEAS_INFO);//7
2181
2182 #ifndef WASMBUILD
2183 //
2184 // Blocks from the original
2185 //
2186 QList<fiff_int_t> blocks;
2188 bool have_hpi_result = false;
2189 bool have_isotrak = false;
2190 if (blocks.size() > 0 && !info.filename.isEmpty())
2191 {
2192 QFile t_qFile(info.filename);//ToDo this has to be adapted for TCPSocket
2193 FiffStream::SPtr t_pStream2(new FiffStream(&t_qFile));
2194
2195 if(!t_pStream2->open()){
2196 qDebug() << "Failed to open file. Returning early";
2197 return t_pStream;
2198 }
2199
2200 for(qint32 k = 0; k < blocks.size(); ++k)
2201 {
2202 QList<FiffDirNode::SPtr> nodes = t_pStream2->dirtree()->dir_tree_find(blocks[k]);
2203 FiffDirNode::copy_tree(t_pStream2,t_pStream2->dirtree()->id,nodes,t_pStream);
2204 if(blocks[k] == FIFFB_HPI_RESULT && nodes.size() > 0)
2205 have_hpi_result = true;
2206
2207 if(blocks[k] == FIFFB_ISOTRAK && nodes.size() > 0)
2208 have_isotrak = true;
2209 }
2210
2211 t_pStream2 = FiffStream::SPtr();
2212 }
2213 #endif
2214
2215 //
2216 // megacq parameters
2217 //
2218 if (!info.acq_pars.isEmpty() || !info.acq_stim.isEmpty())
2219 {
2220 t_pStream->start_block(FIFFB_DACQ_PARS);
2221 if (!info.acq_pars.isEmpty())
2222 t_pStream->write_string(FIFF_DACQ_PARS, info.acq_pars);
2223
2224 if (!info.acq_stim.isEmpty())
2225 t_pStream->write_string(FIFF_DACQ_STIM, info.acq_stim);
2226
2227 t_pStream->end_block(FIFFB_DACQ_PARS);
2228 }
2229
2230 #ifndef WASMBUILD
2231 //
2232 // Coordinate transformations if the HPI result block was not there
2233 //
2234 if (!have_hpi_result)
2235 {
2236 if (!info.dev_head_t.isEmpty())
2237 t_pStream->write_coord_trans(info.dev_head_t);
2238
2239 if (!info.ctf_head_t.isEmpty())
2240 t_pStream->write_coord_trans(info.ctf_head_t);
2241 }
2242 //
2243 // Polhemus data
2244 //
2245 if (info.dig.size() > 0 && !have_isotrak)
2246 {
2247 t_pStream->start_block(FIFFB_ISOTRAK);
2248 for (qint32 k = 0; k < info.dig.size(); ++k)
2249 t_pStream->write_dig_point(info.dig[k]);
2250
2251 t_pStream->end_block(FIFFB_ISOTRAK);
2252 }
2253 #endif
2254
2255 //
2256 // Projectors
2257 //
2258 t_pStream->write_proj(info.projs);
2259 //
2260 // CTF compensation info
2261 //
2262 t_pStream->write_ctf_comp(info.comps);
2263 //
2264 // Bad channels
2265 //
2266 if (info.bads.size() > 0)
2267 {
2268 t_pStream->start_block(FIFFB_MNE_BAD_CHANNELS);
2269 t_pStream->write_name_list(FIFF_MNE_CH_NAME_LIST,info.bads);
2270 t_pStream->end_block(FIFFB_MNE_BAD_CHANNELS);
2271 }
2272 //
2273 // General
2274 //
2275 t_pStream->write_float(FIFF_SFREQ,&info.sfreq);
2276 t_pStream->write_float(FIFF_HIGHPASS,&info.highpass);
2277 t_pStream->write_float(FIFF_LOWPASS,&info.lowpass);
2278 t_pStream->write_float(FIFF_LINE_FREQ,&info.linefreq);
2279 t_pStream->write_int(FIFF_GANTRY_ANGLE,&info.gantry_angle);
2280 t_pStream->write_int(FIFF_NCHAN,&nchan);
2281 t_pStream->write_int(FIFF_DATA_PACK,&data_type);
2282 t_pStream->write_int(FIFF_PROJ_ID,&info.proj_id);
2283 t_pStream->write_string(FIFF_EXPERIMENTER,info.experimenter);
2284 t_pStream->write_string(FIFF_DESCRIPTION,info.description);
2285 t_pStream->write_string(FIFF_PROJ_NAME,info.proj_name);
2286 t_pStream->write_string(FIFF_XPLOTTER_LAYOUT,info.xplotter_layout);
2287 if (info.meas_date[0] != -1)
2288 t_pStream->write_int(FIFF_MEAS_DATE,info.meas_date, 2);
2289 //
2290 // Channel info
2291 //
2292 cals = RowVectorXd(nchan);
2293 for(k = 0; k < nchan; ++k)
2294 {
2295 //
2296 // Scan numbers may have been messed up
2297 //
2298 chs[k].scanNo = k+1;
2299 if(bResetRange) {
2300 chs[k].range = 1.0; // Reset to 1.0 because we always write floats.
2301 }
2302 cals[k] = chs[k].cal;
2303 t_pStream->write_ch_info(chs[k]);
2304 }
2305 //
2306 //
2307 t_pStream->end_block(FIFFB_MEAS_INFO);
2308 //
2309 // Start the raw data
2310 //
2311 t_pStream->start_block(FIFFB_RAW_DATA);
2312
2313 return t_pStream;
2314}
2315
2316//=============================================================================================================
2317
2319{
2320 /*
2321 * Write tag to specified position
2322 */
2323 if (pos >= 0) {
2324 this->device()->seek(pos);
2325 }
2326 else { //SEEK_END
2327 QFile* file = qobject_cast<QFile*> (this->device());
2328 if(file)
2329 this->device()->seek(file->size());
2330 }
2331 pos = this->device()->pos();
2332
2333 fiff_int_t datasize = p_pTag->size();
2334
2335 *this << static_cast<qint32>(p_pTag->kind);
2336 *this << static_cast<qint32>(p_pTag->type);
2337 *this << static_cast<qint32>(datasize);
2338 *this << static_cast<qint32>(p_pTag->next);
2339
2340 /*
2341 * Do we have data?
2342 */
2343 if (datasize > 0) {
2344 /*
2345 * Data exists...
2346 */
2347 this->writeRawData(p_pTag->data(),datasize);
2348 }
2349
2350 return pos;
2351}
2352
2353//=============================================================================================================
2354
2356{
2357 fiff_long_t pos = this->device()->pos();
2358
2359 //typedef struct _fiffChPosRec {
2360 // fiff_int_t coil_type; /*!< What kind of coil. */
2361 // fiff_float_t r0[3]; /*!< Coil coordinate system origin */
2362 // fiff_float_t ex[3]; /*!< Coil coordinate system x-axis unit vector */
2363 // fiff_float_t ey[3]; /*!< Coil coordinate system y-axis unit vector */
2364 // fiff_float_t ez[3]; /*!< Coil coordinate system z-axis unit vector */
2365 //} fiffChPosRec,*fiffChPos; /*!< Measurement channel position and coil type */
2366
2367 //typedef struct _fiffChInfoRec {
2368 // fiff_int_t scanNo; /*!< Scanning order # */
2369 // fiff_int_t logNo; /*!< Logical channel # */
2370 // fiff_int_t kind; /*!< Kind of channel */
2371 // fiff_float_t range; /*!< Voltmeter range (only applies to raw data ) */
2372 // fiff_float_t cal; /*!< Calibration from volts to... */
2373 // fiff_ch_pos_t chpos; /*!< Channel location */
2374 // fiff_int_t unit; /*!< Unit of measurement */
2375 // fiff_int_t unit_mul; /*!< Unit multiplier exponent */
2376 // fiff_char_t ch_name[16]; /*!< Descriptive name for the channel */
2377 //} fiffChInfoRec,*fiffChInfo; /*!< Description of one channel */
2378 fiff_int_t datasize= 4*13 + 4*7 + 16;
2379
2380 *this << (qint32)FIFF_CH_INFO;
2381 *this << (qint32)FIFFT_CH_INFO_STRUCT;
2382 *this << (qint32)datasize;
2383 *this << (qint32)FIFFV_NEXT_SEQ;
2384
2385 //
2386 // Start writing fiffChInfoRec
2387 //
2388 *this << (qint32)ch.scanNo;
2389 *this << (qint32)ch.logNo;
2390 *this << (qint32)ch.kind;
2391
2392 *this << ch.range;
2393 *this << ch.cal;
2394
2395 //
2396 // FiffChPos follows
2397 //
2398 write_ch_pos(ch.chpos);
2399
2400 //
2401 // unit and unit multiplier
2402 //
2403 *this << (qint32)ch.unit;
2404 *this << (qint32)ch.unit_mul;
2405
2406 //
2407 // Finally channel name
2408 //
2409 fiff_int_t len = ch.ch_name.size();
2410 QString ch_name;
2411 if(len > 15)
2412 ch_name = ch.ch_name.mid(0, 15);
2413 else
2414 ch_name = ch.ch_name;
2415
2416 len = ch_name.size();
2417
2418 this->writeRawData(ch_name.toUtf8().constData(),len);
2419
2420 if (len < 16) {
2421 const char* chNull = "";
2422 for(qint32 i = 0; i < 16-len; ++i)
2423 this->writeRawData(chNull,1);
2424 }
2425
2426 return pos;
2427}
2428
2429//=============================================================================================================
2430
2432{
2433 fiff_long_t pos = this->device()->pos();
2434
2435 //
2436 // FiffChPos
2437 //
2438 *this << (qint32)chpos.coil_type;
2439
2440 qint32 i;
2441 // r0
2442 for(i = 0; i < 3; ++i)
2443 *this << chpos.r0[i];
2444 // ex
2445 for(i = 0; i < 3; ++i)
2446 *this << chpos.ex[i];
2447 // ey
2448 for(i = 0; i < 3; ++i)
2449 *this << chpos.ey[i];
2450 // ez
2451 for(i = 0; i < 3; ++i)
2452 *this << chpos.ez[i];
2453
2454 return pos;
2455}
2456
2457//=============================================================================================================
2458
2460{
2461 fiff_long_t pos = this->device()->pos();
2462
2463 //?typedef struct _fiffCoordTransRec {
2464 // fiff_int_t from; /*!< Source coordinate system. */
2465 // fiff_int_t to; /*!< Destination coordinate system. */
2466 // fiff_float_t rot[3][3]; /*!< The forward transform (rotation part) */
2467 // fiff_float_t move[3]; /*!< The forward transform (translation part) */
2468 // fiff_float_t invrot[3][3]; /*!< The inverse transform (rotation part) */
2469 // fiff_float_t invmove[3]; /*!< The inverse transform (translation part) */
2470 //} *fiffCoordTrans, fiffCoordTransRec; /*!< Coordinate transformation descriptor */
2471 fiff_int_t datasize = 4*2*12 + 4*2;
2472
2473 *this << (qint32)FIFF_COORD_TRANS;
2474 *this << (qint32)FIFFT_COORD_TRANS_STRUCT;
2475 *this << (qint32)datasize;
2476 *this << (qint32)FIFFV_NEXT_SEQ;
2477
2478 //
2479 // Start writing fiffCoordTransRec
2480 //
2481 *this << (qint32)trans.from;
2482 *this << (qint32)trans.to;
2483
2484 //
2485 // The transform...
2486 //
2487 qint32 r, c;
2488 for (r = 0; r < 3; ++r)
2489 for (c = 0; c < 3; ++c)
2490 *this << static_cast<float>(trans.trans(r,c));
2491 for (r = 0; r < 3; ++r)
2492 *this << static_cast<float>(trans.trans(r,3));
2493
2494 //
2495 // ...and its inverse
2496 //
2497 for (r = 0; r < 3; ++r)
2498 for (c = 0; c < 3; ++c)
2499 *this << static_cast<float>(trans.invtrans(r,c));
2500 for (r = 0; r < 3; ++r)
2501 *this << static_cast<float>(trans.invtrans(r,3));
2502
2503 return pos;
2504}
2505
2506//=============================================================================================================
2507
2509{
2510 fiff_long_t pos = this->device()->pos();
2511
2513
2514 //
2515 // Dimensions etc.
2516 //
2517 this->write_int(FIFF_MNE_COV_KIND, &p_FiffCov.kind);
2518 this->write_int(FIFF_MNE_COV_DIM, &p_FiffCov.dim);
2519 if (p_FiffCov.nfree > 0)
2520 this->write_int(FIFF_MNE_COV_NFREE, &p_FiffCov.nfree);
2521 //
2522 // Channel names
2523 //
2524 if(p_FiffCov.names.size() > 0)
2525 this->write_name_list(FIFF_MNE_ROW_NAMES, p_FiffCov.names);
2526 //
2527 // Data
2528 //
2529 if(p_FiffCov.diag)
2530 this->write_double(FIFF_MNE_COV_DIAG, p_FiffCov.data.col(0).data(), p_FiffCov.data.rows());
2531 else
2532 {
2533// if issparse(cov.data)
2534// fiff_write_float_sparse_rcs(fid,FIFF.FIFF_MNE_COV,cov.data);
2535// else
2536// {
2537 // Store lower triangle including diagonal (matches read_cov format)
2538 qint32 dim = p_FiffCov.dim;
2539 qint32 n = dim*(dim+1)/2;
2540
2541 VectorXd vals(n);
2542 qint32 count = 0;
2543 for(qint32 i = 0; i < dim; ++i)
2544 for(qint32 j = 0; j <= i; ++j)
2545 vals(count++) = p_FiffCov.data(i,j);
2546
2547 this->write_double(FIFF_MNE_COV, vals.data(), vals.size());
2548// }
2549 }
2550 //
2551 // Eigenvalues and vectors if present
2552 //
2553 if(p_FiffCov.eig.size() > 0 && p_FiffCov.eigvec.size() > 0)
2554 {
2555 this->write_float_matrix(FIFF_MNE_COV_EIGENVECTORS, p_FiffCov.eigvec.cast<float>());
2556 this->write_double(FIFF_MNE_COV_EIGENVALUES, p_FiffCov.eig.data(), p_FiffCov.eig.size());
2557 }
2558 //
2559 // Projection operator
2560 //
2561 this->write_proj(p_FiffCov.projs);
2562 //
2563 // Bad channels
2564 //
2565 if(p_FiffCov.bads.size() > 0)
2566 {
2568 this->write_name_list(FIFF_MNE_CH_NAME_LIST, p_FiffCov.bads);
2570 }
2571 //
2572 // Done!
2573 //
2574 this->end_block(FIFFB_MNE_COV);
2575
2576 return pos;
2577}
2578
2579//=============================================================================================================
2580
2581fiff_long_t FiffStream::write_ctf_comp(const QList<FiffCtfComp>& comps)
2582{
2583 fiff_long_t pos = this->device()->pos();
2584
2585 if (comps.size() <= 0)
2586 return -1;
2587 //
2588 // This is very simple in fact
2589 //
2591 for(qint32 k = 0; k < comps.size(); ++k)
2592 {
2593 FiffCtfComp comp(comps[k]);
2595 //
2596 // Write the compensation kind
2597 //
2599 qint32 save_calibrated = comp.save_calibrated;
2600 this->write_int(FIFF_MNE_CTF_COMP_CALIBRATED, &save_calibrated);
2601 //
2602 // Write an uncalibrated or calibrated matrix
2603 // If compensators where calibrated undo this here
2604 //
2605 if(comps[k].save_calibrated) {
2606 comp.data->data = (comp.rowcals.asDiagonal()).inverse()* comp.data->data * (comp.colcals.asDiagonal()).inverse();
2607 }
2608
2611 }
2613
2614 return pos;
2615}
2616
2617//=============================================================================================================
2618
2620{
2621 fiff_long_t pos = this->device()->pos();
2622
2623 //?typedef struct _fiffDigPointRec {
2624 // fiff_int_t kind; /*!< FIFF_POINT_CARDINAL,
2625 // * FIFF_POINT_HPI, or
2626 // * FIFF_POINT_EEG */
2627 // fiff_int_t ident; /*!< Number identifying this point */
2628 // fiff_float_t r[3]; /*!< Point location */
2629 //} *fiffDigPoint,fiffDigPointRec; /*!< Digitization point description */
2630 fiff_int_t datasize = 5*4;
2631
2632 *this << (qint32)FIFF_DIG_POINT;
2633 *this << (qint32)FIFFT_DIG_POINT_STRUCT;
2634 *this << (qint32)datasize;
2635 *this << (qint32)FIFFV_NEXT_SEQ;
2636
2637 //
2638 // Start writing fiffDigPointRec
2639 //
2640 *this << (qint32)dig.kind;
2641 *this << (qint32)dig.ident;
2642 for(qint32 i = 0; i < 3; ++i)
2643 *this << dig.r[i];
2644
2645 return pos;
2646}
2647
2648//=============================================================================================================
2649
2651{
2652 /*
2653 * Write entires to specified position
2654 */
2655 if (pos >= 0) {
2656 this->device()->seek(pos);
2657 }
2658 else { //SEEK_END
2659 QFile* file = qobject_cast<QFile*> (this->device());
2660 if(file)
2661 this->device()->seek(file->size());
2662 }
2663 pos = this->device()->pos();
2664
2665 fiff_int_t datasize = 1 * 4;
2666
2667 *this << (qint32)FIFF_DIR_POINTER;
2668 *this << (qint32)FIFFT_INT;
2669 *this << (qint32)datasize;
2670 *this << (qint32)next;
2671
2672 *this << dirpos;
2673
2674 return pos;
2675}
2676
2677//=============================================================================================================
2678
2679fiff_long_t FiffStream::write_dir_entries(const QList<FiffDirEntry::SPtr> &dir, fiff_long_t pos)
2680{
2681// /** Directories are composed of these structures. *
2682// typedef struct _fiffDirEntryRec {
2683// fiff_int_t kind; /**< Tag number *
2684// fiff_int_t type; /**< Data type *
2685// fiff_int_t size; /**< How many bytes *
2686// fiff_int_t pos; /**< Location in file
2687// * Note: the data is located at pos +
2688// * FIFFC_DATA_OFFSET *
2689// } fiffDirEntryRec,*fiffDirEntry;/**< Directory is composed of these *
2690
2691 /*
2692 * Write entires to specified position
2693 */
2694 if (pos >= 0) {
2695 this->device()->seek(pos);
2696 }
2697 else { //SEEK_END
2698 QFile* file = qobject_cast<QFile*> (this->device());
2699 if(file)
2700 this->device()->seek(file->size());
2701 }
2702
2703 pos = this->device()->pos();
2704
2705 fiff_int_t nent = dir.size();
2706 fiff_int_t datasize = nent * (fiff_int_t)sizeof(FiffDirEntry);
2707
2708 *this << (qint32)FIFF_DIR;
2709 *this << (qint32)FIFFT_DIR_ENTRY_STRUCT;
2710 *this << (qint32)datasize;
2711 *this << (qint32)FIFFV_NEXT_NONE;
2712
2713 //
2714 // Start writing FiffDirEntries
2715 //
2716 for(qint32 i = 0; i < nent; ++i) {
2717 *this << (qint32)dir[i]->kind;
2718 *this << (qint32)dir[i]->type;
2719 *this << (qint32)dir[i]->size;
2720 *this << (qint32)dir[i]->pos;
2721 }
2722
2723 return pos;
2724}
2725
2726//=============================================================================================================
2727
2729{
2730 fiff_long_t pos = this->device()->pos();
2731
2732 qint32 datasize = nel * 8;
2733
2734 *this << (qint32)kind;
2735 *this << (qint32)FIFFT_DOUBLE;
2736 *this << (qint32)datasize;
2737 *this << (qint32)FIFFV_NEXT_SEQ;
2738
2739 //
2740 // Write doubles as raw 8-byte big-endian values.
2741 // FiffStream sets QDataStream::SinglePrecision, which causes
2742 // operator<<(double) to write only 4 bytes. We must bypass that
2743 // to emit the full 8-byte IEEE 754 representation.
2744 //
2745 for(qint32 i = 0; i < nel; ++i)
2746 {
2747 qint64 bits;
2748 memcpy(&bits, &data[i], sizeof(double));
2749 *this << bits;
2750 }
2751
2752 return pos;
2753}
2754
2755//=============================================================================================================
2756
2758{
2759 fiff_long_t pos = this->device()->pos();
2760
2761 qint32 datasize = nel * 4;
2762
2763 *this << (qint32)kind;
2764 *this << (qint32)FIFFT_FLOAT;
2765 *this << (qint32)datasize;
2766 *this << (qint32)FIFFV_NEXT_SEQ;
2767
2768 for(qint32 i = 0; i < nel; ++i)
2769 *this << data[i];
2770
2771 return pos;
2772}
2773
2774//=============================================================================================================
2775
2777{
2778 fiff_long_t pos = this->device()->pos();
2779
2780 qint32 numel = mat.rows() * mat.cols();
2781
2782 fiff_int_t datasize = 4*numel + 4*3;
2783
2784 *this << (qint32)kind;
2785 *this << (qint32)FIFFT_MATRIX_FLOAT;
2786 *this << (qint32)datasize;
2787 *this << (qint32)FIFFV_NEXT_SEQ;
2788
2789 qint32 i, j;
2790 // Storage order: row-major
2791 for(i = 0; i < mat.rows(); ++i)
2792 for(j = 0; j < mat.cols(); ++j)
2793 *this << mat(i,j);
2794
2795 qint32 dims[3];
2796 dims[0] = mat.cols();
2797 dims[1] = mat.rows();
2798 dims[2] = 2;
2799
2800 for(i = 0; i < 3; ++i)
2801 *this << dims[i];
2802
2803 return pos;
2804}
2805
2806//=============================================================================================================
2807
2808fiff_long_t FiffStream::write_float_sparse_ccs(fiff_int_t kind, const SparseMatrix<float>& mat)
2809{
2810 fiff_long_t pos = this->device()->pos();
2811
2812 //
2813 // nnz values
2814 // nnz row indices
2815 // ncol+1 pointers
2816 // dims
2817 // nnz
2818 // ndim
2819 //
2820 qint32 nnzm = mat.nonZeros();
2821 qint32 ncol = mat.cols();
2822 fiff_int_t datasize = 4*nnzm + 4*nnzm + 4*(ncol+1) + 4*4;
2823 //
2824 // Nonzero entries
2825 //
2826 using T = Eigen::Triplet<float>;
2827 std::vector<T> s;
2828 s.reserve(mat.nonZeros());
2829 for (int k=0; k < mat.outerSize(); ++k)
2830 for (SparseMatrix<float>::InnerIterator it(mat,k); it; ++it)
2831 s.push_back(T(it.row(), it.col(), it.value()));
2832
2833 s = Linalg::sortrows<float>(s, 1);
2834
2835 //[ rows, starts ] = unique(s(:,1),'first');
2836 std::vector<qint32> cols, starts;
2837 qint32 v_old = -1;
2838 quint32 i;
2839 for(i = 0; i < s.size(); ++i)
2840 {
2841 if((signed) s[i].col() != v_old)
2842 {
2843 v_old = s[i].col();
2844 cols.push_back(s[i].col());
2845 starts.push_back(i);
2846 }
2847 }
2848
2849 *this << (qint32)kind;
2850 *this << (qint32)FIFFT_CCS_MATRIX_FLOAT;
2851 *this << (qint32)datasize;
2852 *this << (qint32)FIFFV_NEXT_SEQ;
2853
2854 //
2855 // The data values
2856 //
2857 for(i = 0; i < s.size(); ++i)
2858 *this << s[i].value();
2859
2860 //
2861 // Row indices
2862 //
2863 for(i = 0; i < s.size(); ++i)
2864 *this << s[i].row();
2865
2866 //
2867 // Pointers
2868 //
2869 RowVectorXi ptrs = RowVectorXi::Ones(ncol+1);
2870 ptrs.array() *= -1;
2871 quint32 k;
2872 for(k = 0; k < cols.size(); ++k)
2873 ptrs[cols[k]] = starts[k];
2874 ptrs[ncol] = nnzm;
2875 //
2876 // Fill in pointers for empty columns
2877 //
2878 for(k = ncol; k >= 1; --k)
2879 if(ptrs[k-1] < 0)
2880 ptrs[k-1] = ptrs[k];
2881 //
2882 for(i = 0; i < (quint32)ptrs.size(); ++i)
2883 *this << ptrs[i];
2884 //
2885 // Dimensions
2886 //
2887 qint32 dims[4];
2888 dims[0] = mat.nonZeros();
2889 dims[1] = mat.rows();
2890 dims[2] = mat.cols();
2891 dims[3] = 2;
2892
2893 for(i = 0; i < 4; ++i)
2894 *this << dims[i];
2895
2896 return pos;
2897}
2898
2899//=============================================================================================================
2900
2901fiff_long_t FiffStream::write_float_sparse_rcs(fiff_int_t kind, const SparseMatrix<float>& mat)
2902{
2903 fiff_long_t pos = this->device()->pos();
2904
2905 //
2906 // nnz values
2907 // nnz column indices
2908 // nrow+1 pointers
2909 // dims
2910 // nnz
2911 // ndim
2912 //
2913 qint32 nnzm = mat.nonZeros();
2914 qint32 nrow = mat.rows();
2915 fiff_int_t datasize = 4*nnzm + 4*nnzm + 4*(nrow+1) + 4*4;
2916 //
2917 // Nonzero entries
2918 //
2919 using T = Eigen::Triplet<float>;
2920 std::vector<T> s;
2921 s.reserve(mat.nonZeros());
2922 for (int k=0; k < mat.outerSize(); ++k)
2923 for (SparseMatrix<float>::InnerIterator it(mat,k); it; ++it)
2924 s.push_back(T(it.row(), it.col(), it.value()));
2925
2927
2928 //[ rows, starts ] = unique(s(:,1),'first');
2929 std::vector<qint32> rows, starts;
2930 qint32 v_old = -1;
2931 quint32 i;
2932 for(i = 0; i < s.size(); ++i)
2933 {
2934 if((signed) s[i].row() != v_old)
2935 {
2936 v_old = s[i].row();
2937 rows.push_back(s[i].row());
2938 starts.push_back(i);
2939 }
2940 }
2941
2942 //
2943 // Write tag info header
2944 //
2945 *this << (qint32)kind;
2946 *this << (qint32)FIFFT_RCS_MATRIX_FLOAT;
2947 *this << (qint32)datasize;
2948 *this << (qint32)FIFFV_NEXT_SEQ;
2949
2950 //
2951 // The data values
2952 //
2953 for(i = 0; i < s.size(); ++i)
2954 *this << s[i].value();
2955
2956 //
2957 // Column indices
2958 //
2959 for(i = 0; i < s.size(); ++i)
2960 *this << s[i].col();
2961
2962 //
2963 // Pointers
2964 //
2965 RowVectorXi ptrs = RowVectorXi::Ones(nrow+1);
2966 ptrs.array() *= -1;
2967 quint32 k;
2968 for(k = 0; k < rows.size(); ++k)
2969 ptrs[rows[k]] = starts[k];
2970 ptrs[nrow] = nnzm;
2971
2972 //
2973 // Fill in pointers for empty rows
2974 //
2975 for(k = nrow; k >= 1; --k)
2976 if(ptrs[k-1] < 0)
2977 ptrs[k-1] = ptrs[k];
2978
2979 //
2980 for(i = 0; i < (quint32)ptrs.size(); ++i)
2981 *this << ptrs[i];
2982
2983 //
2984 // Dimensions
2985 //
2986 qint32 dims[4];
2987 dims[0] = mat.nonZeros();
2988 dims[1] = mat.rows();
2989 dims[2] = mat.cols();
2990 dims[3] = 2;
2991
2992 for(i = 0; i < 4; ++i)
2993 *this << dims[i];
2994
2995 return pos;
2996}
2997
2998//=============================================================================================================
2999
3001{
3002 fiff_long_t pos = this->device()->pos();
3003
3004 FiffId t_id = id;
3005
3006 if(t_id.isEmpty()) {
3007 //
3008 // Create a new one
3009 //
3010 t_id = FiffId::new_file_id();
3011 }
3012
3013 //
3014 //
3015 fiff_int_t datasize = 5*4; // The id comprises five integers
3016
3017 *this << (qint32)kind;
3018 *this << (qint32)FIFFT_ID_STRUCT;
3019 *this << (qint32)datasize;
3020 *this << (qint32)FIFFV_NEXT_SEQ;
3021 //
3022 // Collect the bits together for one write
3023 //
3024 qint32 data[5];
3025 data[0] = t_id.version;
3026 data[1] = t_id.machid[0];
3027 data[2] = t_id.machid[1];
3028 data[3] = t_id.time.secs;
3029 data[4] = t_id.time.usecs;
3030
3031 for(qint32 i = 0; i < 5; ++i)
3032 *this << data[i];
3033
3034 return pos;
3035}
3036
3037//=============================================================================================================
3038
3040{
3041 fiff_long_t pos = this->device()->pos();
3042
3043 //
3044 // Information from the MEG file
3045 //
3047 this->write_string(FIFF_MNE_FILE_NAME, p_FiffInfoBase.filename);
3048 if(!p_FiffInfoBase.meas_id.isEmpty())
3049 this->write_id(FIFF_PARENT_BLOCK_ID, p_FiffInfoBase.meas_id);
3050
3051 //
3052 // General
3053 //
3054 this->write_int(FIFF_NCHAN,&p_FiffInfoBase.nchan);
3055
3056 //
3057 // Channel info
3058 //
3059 qint32 k;
3060 QList<FiffChInfo> chs;
3061 for(k = 0; k < p_FiffInfoBase.nchan; ++k)
3062 chs << p_FiffInfoBase.chs[k];
3063
3064 for(k = 0; k < p_FiffInfoBase.nchan; ++k)
3065 {
3066 //
3067 // Scan numbers may have been messed up
3068 //
3069 chs[k].scanNo = k+1;//+1 because
3070 this->write_ch_info(chs[k]);
3071 }
3072
3073 //
3074 // Blocks from the original -> skip this
3075 //
3076 bool have_hpi_result = false;
3077
3078 //
3079 // Coordinate transformations if the HPI result block was not there
3080 //
3081 if (!have_hpi_result)
3082 {
3083 if (!p_FiffInfoBase.dev_head_t.isEmpty())
3084 this->write_coord_trans(p_FiffInfoBase.dev_head_t);
3085 if (!p_FiffInfoBase.ctf_head_t.isEmpty())
3086 this->write_coord_trans(p_FiffInfoBase.ctf_head_t);
3087 }
3088
3089 //
3090 // Bad channels
3091 //
3092 if (p_FiffInfoBase.bads.size() > 0)
3093 {
3095 this->write_name_list(FIFF_MNE_CH_NAME_LIST,p_FiffInfoBase.bads);
3097 }
3098
3100
3101 return pos;
3102}
3103
3104//=============================================================================================================
3105
3107{
3108 fiff_long_t pos = this->device()->pos();
3109
3110 fiff_int_t datasize = nel * 4;
3111
3112 *this << (qint32)kind;
3113 *this << (qint32)FIFFT_INT;
3114 *this << (qint32)datasize;
3115 *this << (qint32)next;
3116
3117 for(qint32 i = 0; i < nel; ++i)
3118 *this << data[i];
3119
3120 return pos;
3121}
3122
3123//=============================================================================================================
3124
3126{
3127 fiff_long_t pos = this->device()->pos();
3128
3129// qint32 FIFFT_MATRIX = 1 << 30;
3130// qint32 FIFFT_MATRIX_INT = FIFFT_INT | FIFFT_MATRIX;
3131
3132 qint32 numel = mat.rows() * mat.cols();
3133
3134 fiff_int_t datasize = 4*numel + 4*3;
3135
3136 *this << (qint32)kind;
3137 *this << (qint32)FIFFT_MATRIX_INT;
3138 *this << (qint32)datasize;
3139 *this << (qint32)FIFFV_NEXT_SEQ;
3140
3141 qint32 i, j;
3142 // Storage order: row-major
3143 for(i = 0; i < mat.rows(); ++i)
3144 for(j = 0; j < mat.cols(); ++j)
3145 *this << mat(i,j);
3146
3147 qint32 dims[3];
3148 dims[0] = mat.cols();
3149 dims[1] = mat.rows();
3150 dims[2] = 2;
3151
3152 for(i = 0; i < 3; ++i)
3153 *this << dims[i];
3154
3155 return pos;
3156}
3157
3158//=============================================================================================================
3159
3161{
3162 QString all = data.join(":");
3163 return this->write_string(kind,all);
3164}
3165
3166//=============================================================================================================
3167
3169{
3170 fiff_long_t pos = this->device()->pos();
3171
3173 this->write_int(FIFF_MNE_NROW, &mat.nrow);
3174 this->write_int(FIFF_MNE_NCOL, &mat.ncol);
3175 if (mat.row_names.size() > 0)
3177 if (mat.col_names.size() > 0)
3179 this->write_float_matrix(kind,mat.data.cast<float>());
3181
3182 return pos;
3183}
3184
3185//=============================================================================================================
3186
3187fiff_long_t FiffStream::write_proj(const QList<FiffProj>& projs)
3188{
3189 fiff_long_t pos = this->device()->pos();
3190
3191 if (projs.size() <= 0)
3192 return -1;
3193
3194 this->start_block(FIFFB_PROJ);
3195
3196 for(qint32 k = 0; k < projs.size(); ++k)
3197 {
3199 this->write_string(FIFF_NAME,projs[k].desc);
3200 this->write_int(FIFF_PROJ_ITEM_KIND,&projs[k].kind);
3201 if (projs[k].kind == FIFFV_PROJ_ITEM_FIELD)
3202 {
3203 float fValue = 0.0f;
3204 this->write_float(FIFF_PROJ_ITEM_TIME, &fValue);
3205 }
3206
3207 this->write_int(FIFF_NCHAN, &projs[k].data->ncol);
3208 this->write_int(FIFF_PROJ_ITEM_NVEC, &projs[k].data->nrow);
3209 qint32 bValue = (qint32)projs[k].active;
3210 this->write_int(FIFF_MNE_PROJ_ITEM_ACTIVE, &bValue);
3211 this->write_name_list(FIFF_PROJ_ITEM_CH_NAME_LIST, projs[k].data->col_names);
3212 this->write_float_matrix(FIFF_PROJ_ITEM_VECTORS, projs[k].data->data.cast<float>());//rows == length(names)
3214 }
3215 this->end_block(FIFFB_PROJ);
3216
3217 return pos;
3218}
3219
3220//=============================================================================================================
3221
3223{
3224 fiff_long_t pos = this->device()->pos();
3225
3226 if (p_FiffEvokedSet.evoked.isEmpty())
3227 return -1;
3228
3229 this->start_block(FIFFB_MEAS);
3230 this->write_id(FIFF_BLOCK_ID);
3231
3232 if (p_FiffEvokedSet.info.meas_id.version != -1)
3233 this->write_id(FIFF_PARENT_BLOCK_ID, p_FiffEvokedSet.info.meas_id);
3234
3235 this->write_info_base(p_FiffEvokedSet.info);
3236
3237 for (int j = 0; j < p_FiffEvokedSet.evoked.size(); ++j) {
3238 const FiffEvoked &evoked = p_FiffEvokedSet.evoked[j];
3239
3242
3243 this->write_string(FIFF_COMMENT, evoked.comment);
3244
3246
3247 int aspectKind = FIFFV_ASPECT_AVERAGE;
3248 this->write_int(FIFF_ASPECT_KIND, &aspectKind);
3249
3250 int nave = evoked.nave;
3251 this->write_int(FIFF_NAVE, &nave);
3252
3253 int first = evoked.first;
3254 this->write_int(FIFF_FIRST_SAMPLE, &first);
3255
3256 int last = evoked.last;
3257 this->write_int(FIFF_LAST_SAMPLE, &last);
3258
3259 Eigen::MatrixXf floatData = evoked.data.cast<float>();
3260 for (int ch = 0; ch < floatData.rows(); ++ch) {
3261 this->write_float(FIFF_EPOCH, floatData.row(ch).data(),
3262 static_cast<int>(floatData.cols()));
3263 }
3264
3265 this->end_block(FIFFB_ASPECT);
3266 this->end_block(FIFFB_EVOKED);
3268 }
3269
3270 this->end_block(FIFFB_MEAS);
3271
3272 return pos;
3273}
3274
3275//=============================================================================================================
3276
3277bool FiffStream::write_raw_buffer(const MatrixXd& buf,
3278 const RowVectorXd& cals)
3279{
3280 if (buf.rows() != cals.cols())
3281 {
3282 qWarning("buffer and calibration sizes do not match\n");
3283 return false;
3284 }
3285
3286 using T = Eigen::Triplet<double>;
3287 std::vector<T> tripletList;
3288 tripletList.reserve(cals.cols());
3289 for(qint32 i = 0; i < cals.cols(); ++i)
3290 tripletList.push_back(T(i, i, 1.0/cals[i]));
3291
3292 SparseMatrix<double> inv_calsMat(cals.cols(), cals.cols());
3293 inv_calsMat.setFromTriplets(tripletList.begin(), tripletList.end());
3294
3295 MatrixXf tmp = (inv_calsMat*buf).cast<float>();
3296 this->write_float(FIFF_DATA_BUFFER,tmp.data(),tmp.rows()*tmp.cols());
3297 return true;
3298}
3299
3300//=============================================================================================================
3301
3302bool FiffStream::write_raw_buffer(const MatrixXd& buf,
3303 const SparseMatrix<double>& mult)
3304{
3305 if (buf.rows() != mult.cols()) {
3306 qWarning("buffer and mult sizes do not match\n");
3307 return false;
3308 }
3309
3310 SparseMatrix<double> inv_mult(mult.rows(), mult.cols());
3311 for (int k=0; k<inv_mult.outerSize(); ++k)
3312 for (SparseMatrix<double>::InnerIterator it(mult,k); it; ++it)
3313 inv_mult.coeffRef(it.row(),it.col()) = 1/it.value();
3314
3315 MatrixXf tmp = (inv_mult*buf).cast<float>();
3316 this->write_float(FIFF_DATA_BUFFER,tmp.data(),tmp.rows()*tmp.cols());
3317 return true;
3318}
3319
3320//=============================================================================================================
3321
3322bool FiffStream::write_raw_buffer(const MatrixXd& buf)
3323{
3324 MatrixXf tmp = buf.cast<float>();
3325 this->write_float(FIFF_DATA_BUFFER,tmp.data(),tmp.rows()*tmp.cols());
3326 return true;
3327}
3328
3329//=============================================================================================================
3330
3332 const QString& data)
3333{
3334 fiff_long_t pos = this->device()->pos();
3335
3336 fiff_int_t datasize = data.size();
3337 *this << (qint32)kind;
3338 *this << (qint32)FIFFT_STRING;
3339 *this << (qint32)datasize;
3340 *this << (qint32)FIFFV_NEXT_SEQ;
3341
3342 this->writeRawData(data.toUtf8().constData(),datasize);
3343
3344 return pos;
3345}
3346
3347//=============================================================================================================
3348
3349void FiffStream::write_rt_command(fiff_int_t command, const QString& data)
3350{
3351 fiff_int_t datasize = data.size();
3352 *this << (qint32)FIFF_MNE_RT_COMMAND;
3353 *this << (qint32)FIFFT_VOID;
3354 *this << 4+(qint32)datasize;
3355 *this << (qint32)FIFFV_NEXT_SEQ;
3356 *this << command;
3357
3358 this->writeRawData(data.toUtf8().constData(),datasize);
3359}
3360
3361//=============================================================================================================
3362
3363QList<FiffDirEntry::SPtr> FiffStream::make_dir(bool *ok)
3364{
3365 FiffTag::UPtr t_pTag;
3366 QList<FiffDirEntry::SPtr> dir;
3367 FiffDirEntry::SPtr t_pFiffDirEntry;
3368 fiff_long_t pos;
3369 if(ok) *ok = false;
3370 /*
3371 * Start from the very beginning...
3372 */
3373 if(!this->device()->seek(SEEK_SET))
3374 return dir;
3375 while ((pos = this->read_tag_info(t_pTag)) != -1) {
3376 /*
3377 * Guard against reading past EOF. When QDataStream reaches the
3378 * end of the device every subsequent read silently returns zero,
3379 * so read_tag_info never returns -1. Detect this by checking
3380 * whether the stream is still healthy after the header read.
3381 */
3382 if (this->status() != QDataStream::Ok) {
3383 this->resetStatus();
3384 break;
3385 }
3386 /*
3387 * Check that we haven't run into the directory
3388 */
3389 if (t_pTag->kind == FIFF_DIR)
3390 break;
3391 /*
3392 * Put in the new entry
3393 */
3394 t_pFiffDirEntry = FiffDirEntry::SPtr(new FiffDirEntry);
3395 t_pFiffDirEntry->kind = t_pTag->kind;
3396 t_pFiffDirEntry->type = t_pTag->type;
3397 t_pFiffDirEntry->size = t_pTag->size();
3398 t_pFiffDirEntry->pos = (fiff_long_t)pos;
3399
3400 dir.append(t_pFiffDirEntry);
3401 if (t_pTag->next < 0)
3402 break;
3403 }
3404 /*
3405 * Put in the new the terminating entry
3406 */
3407 t_pFiffDirEntry = FiffDirEntry::SPtr(new FiffDirEntry);
3408 t_pFiffDirEntry->kind = -1;
3409 t_pFiffDirEntry->type = -1;
3410 t_pFiffDirEntry->size = -1;
3411 t_pFiffDirEntry->pos = -1;
3412 dir.append(t_pFiffDirEntry);
3413
3414 if(ok) *ok = true;
3415 return dir;
3416}
3417
3418//=============================================================================================================
3419
3420bool FiffStream::check_beginning(FiffTag::UPtr &p_pTag)
3421{
3422 this->read_tag(p_pTag);
3423
3424 if (p_pTag->kind != FIFF_FILE_ID)
3425 {
3426 qWarning("Fiff::open: file does not start with a file id tag\n");//consider throw
3427 return false;
3428 }
3429
3430 if (p_pTag->type != FIFFT_ID_STRUCT)
3431 {
3432 qWarning("Fiff::open: file does not start with a file id tag\n");//consider throw
3433 return false;
3434 }
3435 if (p_pTag->size() != 20)
3436 {
3437 qWarning("Fiff::open: file does not start with a file id tag\n");//consider throw
3438 return false;
3439 }
3440 //do not rewind since the data is contained in the returned tag; -> done for TCP IP reasosn, no rewind possible there
3441 return true;
3442}
FiffChPos class declaration.
FiffTag class declaration, which provides fiff tag I/O and processing methods.
FiffInfo class declaration.
#define FIFF_MNE_COV_KIND
#define FIFFB_MNE_ENV
#define FIFF_MNE_COORD_FRAME
#define FIFF_MNE_CTF_COMP_KIND
#define FIFF_MNE_COV
#define FIFFV_COORD_DEVICE
#define FIFF_MNE_COV_DIAG
#define FIFFB_MNE_CTF_COMP_DATA
#define FIFF_MNE_CTF_COMP_CALIBRATED
#define FIFF_MNE_ROW_NAMES
#define FIFFV_NEXT_NONE
#define FIFF_MNE_COV_EIGENVALUES
#define FIFF_MNE_PROJ_ITEM_ACTIVE
#define FIFFV_MNE_COORD_CTF_HEAD
#define FIFF_MNE_COL_NAMES
#define FIFF_MNE_ENV_WORKING_DIR
#define FIFF_MNE_ENV_COMMAND_LINE
#define FIFF_MNE_RT_COMMAND
#define FIFF_MNE_CTF_COMP_DATA
#define FIFFV_COORD_HEAD
#define FIFFV_COORD_MRI
#define FIFFB_MNE_COV
#define FIFF_MNE_CH_NAME_LIST
#define FIFF_MNE_NCOL
#define FIFFB_MNE_CTF_COMP
#define FIFF_MNE_COV_NFREE
#define FIFFB_MNE_PARENT_MEAS_FILE
#define FIFF_MNE_COV_EIGENVECTORS
#define FIFFV_COORD_UNKNOWN
#define FIFFB_MNE
#define FIFF_MNE_NROW
#define FIFFB_MNE_BAD_CHANNELS
#define FIFFB_MNE_NAMED_MATRIX
#define FIFFV_NEXT_SEQ
#define FIFF_MNE_FILE_NAME
#define FIFF_MNE_COV_DIM
FiffStream class declaration.
FiffDigitizerData class declaration.
FiffInfoBase class declaration.
FiffRawData class declaration.
FiffDirNode class declaration, which provides fiff dir tree processing methods.
FiffCtfComp class declaration.
FiffChInfo class declaration.
FiffId class declaration.
FiffCov class declaration.
FiffEvokedSet class declaration.
#define FIFF_DATA_BUFFER
Definition fiff_file.h:556
#define FIFF_GANTRY_ANGLE
Definition fiff_file.h:555
#define FIFF_DACQ_STIM
Definition fiff_file.h:351
#define FIFF_PARENT_BLOCK_ID
Definition fiff_file.h:333
#define FIFFV_PROJ_ITEM_FIELD
Definition fiff_file.h:823
#define FIFFB_PROJ
Definition fiff_file.h:409
#define FIFF_NCHAN
Definition fiff_file.h:453
#define FIFFT_ID_STRUCT
Definition fiff_file.h:248
#define FIFF_DIR
Definition fiff_file.h:325
#define FIFF_BLOCK_END
Definition fiff_file.h:328
#define FIFF_XPLOTTER_LAYOUT
Definition fiff_file.h:837
#define FIFFB_SUBJECT
Definition fiff_file.h:369
#define FIFFB_PROCESSING_HISTORY
Definition fiff_file.h:627
#define FIFFT_MATRIX_FLOAT
Definition fiff_file.h:277
#define FIFF_PROJ_ID
Definition fiff_file.h:575
#define FIFFT_CH_INFO_STRUCT
Definition fiff_file.h:247
#define FIFF_FREE_LIST
Definition fiff_file.h:329
#define FIFFB_ISOTRAK
Definition fiff_file.h:370
#define FIFF_HIGHPASS
Definition fiff_file.h:476
#define FIFFB_HPI_MEAS
Definition fiff_file.h:371
#define FIFF_EXPERIMENTER
Definition fiff_file.h:465
#define FIFF_BLOCK_START
Definition fiff_file.h:327
#define FIFFT_RCS_MATRIX_FLOAT
Definition fiff_file.h:280
#define FIFFT_VOID
Definition fiff_file.h:228
#define FIFF_PROJ_NAME
Definition fiff_file.h:576
#define FIFF_NAME
Definition fiff_file.h:485
#define FIFFT_INT
Definition fiff_file.h:231
#define FIFFT_CCS_MATRIX_FLOAT
Definition fiff_file.h:279
#define FIFFT_SHORT
Definition fiff_file.h:230
#define FIFF_DATA_PACK
Definition fiff_file.h:455
#define FIFF_DIR_POINTER
Definition fiff_file.h:324
#define FIFFB_ASPECT
Definition fiff_file.h:368
#define FIFF_FIRST_SAMPLE
Definition fiff_file.h:461
#define FIFF_DESCRIPTION
Definition fiff_file.h:486
#define FIFFV_ASPECT_AVERAGE
Definition fiff_file.h:438
#define FIFF_LINE_FREQ
Definition fiff_file.h:489
#define FIFFB_MEAS
Definition fiff_file.h:362
#define FIFF_NAVE
Definition fiff_file.h:460
#define FIFF_UTC_OFFSET
Definition fiff_file.h:451
#define FIFF_FILE_ID
Definition fiff_file.h:323
#define FIFFB_RAW_DATA
Definition fiff_file.h:364
#define FIFF_COMMENT
Definition fiff_file.h:459
#define FIFFB_SMSH_RAW_DATA
Definition fiff_file.h:382
#define FIFF_ASPECT_KIND
Definition fiff_file.h:463
#define FIFF_PROJ_ITEM_TIME
Definition fiff_file.h:801
#define FIFFB_BEM
Definition fiff_file.h:403
#define FIFFV_LITTLE_ENDIAN
Definition fiff_file.h:898
#define FIFFB_PROJ_ITEM
Definition fiff_file.h:410
#define FIFFB_DACQ_PARS
Definition fiff_file.h:379
#define FIFF_BLOCK_ID
Definition fiff_file.h:326
#define FIFFT_DAU_PACK16
Definition fiff_file.h:243
#define FIFFB_PROCESSED_DATA
Definition fiff_file.h:365
#define FIFFV_ASPECT_STD_ERR
Definition fiff_file.h:439
#define FIFF_PROJ_ITEM_VECTORS
Definition fiff_file.h:805
#define FIFFB_MRI_SET
Definition fiff_file.h:391
#define FIFFT_DOUBLE
Definition fiff_file.h:233
#define FIFFT_MATRIX_INT
Definition fiff_file.h:276
#define FIFF_COORD_TRANS
Definition fiff_file.h:475
#define FIFF_EPOCH
Definition fiff_file.h:558
#define FIFF_PROJ_ITEM_KIND
Definition fiff_file.h:800
#define FIFF_DACQ_PARS
Definition fiff_file.h:350
#define FIFFB_EVENTS
Definition fiff_file.h:377
#define FIFFT_FLOAT
Definition fiff_file.h:232
#define FIFFB_HPI_SUBSYSTEM
Definition fiff_file.h:384
#define FIFFT_STRING
Definition fiff_file.h:238
#define FIFFB_CONTINUOUS_DATA
Definition fiff_file.h:375
#define FIFFV_NATIVE_ENDIAN
Definition fiff_file.h:897
#define FIFF_MEAS_DATE
Definition fiff_file.h:457
#define FIFFB_EVOKED
Definition fiff_file.h:366
#define FIFF_LAST_SAMPLE
Definition fiff_file.h:462
#define FIFF_NOP
Definition fiff_file.h:331
#define FIFF_CH_INFO
Definition fiff_file.h:456
#define FIFF_PROJ_ITEM_CH_NAME_LIST
Definition fiff_file.h:809
#define FIFF_DIG_POINT
Definition fiff_file.h:466
#define FIFFB_MRI
Definition fiff_file.h:390
#define FIFFT_DIR_ENTRY_STRUCT
Definition fiff_file.h:249
#define FIFFB_ROOT
Definition fiff_file.h:361
#define FIFFV_BIG_ENDIAN
Definition fiff_file.h:899
#define FIFFT_COORD_TRANS_STRUCT
Definition fiff_file.h:252
#define FIFF_DATA_SKIP
Definition fiff_file.h:557
#define FIFFT_DIG_POINT_STRUCT
Definition fiff_file.h:250
#define FIFFB_HPI_RESULT
Definition fiff_file.h:372
#define FIFF_LOWPASS
Definition fiff_file.h:472
#define FIFFB_MEAS_INFO
Definition fiff_file.h:363
#define FIFF_PROJ_ITEM_NVEC
Definition fiff_file.h:804
#define FIFF_SFREQ
Definition fiff_file.h:454
FiffCoordTrans class declaration.
FiffDigPoint class declaration.
IOUtils class declaration.
Linalg class declaration.
Numerics class declaration.
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
qint32 fiff_int_t
Definition fiff_types.h:89
qint64 fiff_long_t
Definition fiff_types.h:91
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Channel info descriptor.
Measurement channel position and coil type.
Definition fiff_ch_pos.h:68
Eigen::Vector3f r0
fiff_int_t coil_type
Eigen::Vector3f ey
Eigen::Vector3f ex
Eigen::Vector3f ez
Coordinate transformation description.
Eigen::Matrix< float, 4, 4, Eigen::DontAlign > trans
Eigen::Matrix< float, 4, 4, Eigen::DontAlign > invtrans
covariance data
Definition fiff_cov.h:85
QList< FiffProj > projs
Definition fiff_cov.h:255
fiff_int_t nfree
Definition fiff_cov.h:257
fiff_int_t dim
Definition fiff_cov.h:252
Eigen::MatrixXd eigvec
Definition fiff_cov.h:259
fiff_int_t kind
Definition fiff_cov.h:249
QStringList bads
Definition fiff_cov.h:256
QStringList names
Definition fiff_cov.h:253
Eigen::VectorXd eig
Definition fiff_cov.h:258
Eigen::MatrixXd data
Definition fiff_cov.h:254
CTF software compensation data.
Eigen::MatrixXd rowcals
Eigen::MatrixXd colcals
FiffNamedMatrix::SDPtr data
Digitization point description.
Digitization points container and description.
QList< FIFFLIB::FiffDigPoint > points
Directory entry description.
QSharedPointer< FiffDirEntry > SPtr
Directory node structure.
QSharedPointer< FiffDirNode > SPtr
static bool copy_tree(QSharedPointer< FiffStream > &p_pStreamIn, const FiffId &in_id, const QList< QSharedPointer< FiffDirNode > > &p_Nodes, QSharedPointer< FiffStream > &p_pStreamOut)
Eigen::MatrixXd data
QList< FiffEvoked > evoked
Universally unique identifier.
Definition fiff_id.h:68
fiff_int_t machid[2]
Definition fiff_id.h:180
bool isEmpty() const
Definition fiff_id.h:189
FiffTime time
Definition fiff_id.h:181
static FiffId new_file_id()
Definition fiff_id.cpp:88
fiff_int_t version
Definition fiff_id.h:179
FIFF measurement file information.
Definition fiff_info.h:86
QString description
Definition fiff_info.h:269
FiffCoordTrans dev_ctf_t
Definition fiff_info.h:272
fiff_int_t gantry_angle
Definition fiff_info.h:271
FiffCoordTrans dig_trans
Definition fiff_info.h:274
QList< FiffCtfComp > comps
Definition fiff_info.h:276
QString xplotter_layout
Definition fiff_info.h:267
fiff_int_t meas_date[2]
Definition fiff_info.h:260
QList< FiffDigPoint > dig
Definition fiff_info.h:273
QString experimenter
Definition fiff_info.h:268
QList< FiffProj > projs
Definition fiff_info.h:275
light measurement info
QList< FiffChInfo > chs
FiffCoordTrans ctf_head_t
FiffCoordTrans dev_head_t
QSharedDataPointer< FiffNamedMatrix > SDPtr
SSP projector data.
Definition fiff_proj.h:83
FIFF raw measurement data.
Eigen::RowVectorXd cals
FiffStream::SPtr file
QList< FiffRawDir > rawdir
Raw Directory entry.
FiffDirEntry::SPtr ent
bool write_raw_buffer(const Eigen::MatrixXd &buf, const Eigen::RowVectorXd &cals)
fiff_long_t write_cov(const FiffCov &p_FiffCov)
bool read_cov(const FiffDirNode::SPtr &p_Node, fiff_int_t cov_kind, FiffCov &p_covData)
fiff_long_t write_dir_entries(const QList< FiffDirEntry::SPtr > &dir, fiff_long_t pos=-1)
fiff_long_t start_block(fiff_int_t kind)
fiff_long_t write_float_matrix(fiff_int_t kind, const Eigen::MatrixXf &mat)
fiff_long_t write_proj(const QList< FiffProj > &projs)
fiff_long_t write_int_matrix(fiff_int_t kind, const Eigen::MatrixXi &mat)
QSharedPointer< FiffStream > SPtr
bool read_rt_tag(std::unique_ptr< FiffTag > &p_pTag)
bool read_tag_data(std::unique_ptr< FiffTag > &p_pTag, fiff_long_t pos=-1)
bool read_meas_info_base(const FiffDirNode::SPtr &p_Node, FiffInfoBase &p_InfoForward)
fiff_long_t write_tag(const std::unique_ptr< FiffTag > &p_pTag, fiff_long_t pos=-1)
void write_bad_channels(const QStringList &bads)
fiff_long_t write_dig_point(const FiffDigPoint &dig)
fiff_long_t write_int(fiff_int_t kind, const fiff_int_t *data, fiff_int_t nel=1, fiff_int_t next=FIFFV_NEXT_SEQ)
static bool setup_read_raw(QIODevice &p_IODevice, FiffRawData &data, bool allow_maxshield=true, bool is_littleEndian=false)
QList< FiffCtfComp > read_ctf_comp(const FiffDirNode::SPtr &p_Node, const QList< FiffChInfo > &p_Chs)
fiff_long_t write_float(fiff_int_t kind, const float *data, fiff_int_t nel=1)
fiff_long_t write_id(fiff_int_t kind, const FiffId &id=FiffId::getDefault())
fiff_long_t write_float_sparse_rcs(fiff_int_t kind, const Eigen::SparseMatrix< float > &mat)
fiff_long_t write_ch_pos(const FiffChPos &chpos)
void write_rt_command(fiff_int_t command, const QString &data)
fiff_long_t write_coord_trans(const FiffCoordTrans &trans)
bool get_evoked_entries(const QList< FiffDirNode::SPtr > &evoked_node, QStringList &comments, QList< fiff_int_t > &aspect_kinds, QString &t)
fiff_long_t write_name_list(fiff_int_t kind, const QStringList &data)
bool read_meas_info(const FiffDirNode::SPtr &p_Node, FiffInfo &p_Info, FiffDirNode::SPtr &p_NodeInfo)
bool open(QIODevice::OpenModeFlag mode=QIODevice::ReadOnly)
fiff_long_t read_tag_info(std::unique_ptr< FiffTag > &p_pTag, bool p_bDoSkip=true)
fiff_long_t write_named_matrix(fiff_int_t kind, const FiffNamedMatrix &mat)
FiffStream(QIODevice *p_pIODevice)
FiffId id() const
static QStringList split_name_list(QString p_sNameList)
fiff_long_t write_string(fiff_int_t kind, const QString &data)
QStringList read_bad_channels(const FiffDirNode::SPtr &p_Node)
fiff_long_t write_evoked_set(const FiffEvokedSet &p_FiffEvokedSet)
const FiffDirNode::SPtr & dirtree() const
bool read_digitizer_data(const FiffDirNode::SPtr &p_Node, FiffDigitizerData &p_digData)
static FiffStream::SPtr start_writing_raw(QIODevice &p_IODevice, const FiffInfo &info, Eigen::RowVectorXd &cals, Eigen::MatrixXi sel=defaultMatrixXi, bool bResetRange=true)
fiff_long_t write_dir_pointer(fiff_int_t dirpos, fiff_long_t pos=-1, fiff_int_t next=FIFFV_NEXT_SEQ)
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
fiff_long_t write_info_base(const FiffInfoBase &p_FiffInfoBase)
fiff_long_t end_block(fiff_int_t kind, fiff_int_t next=FIFFV_NEXT_SEQ)
fiff_long_t write_float_sparse_ccs(fiff_int_t kind, const Eigen::SparseMatrix< float > &mat)
fiff_long_t write_ch_info(const FiffChInfo &ch)
fiff_long_t write_ctf_comp(const QList< FiffCtfComp > &comps)
bool read_tag(std::unique_ptr< FiffTag > &p_pTag, fiff_long_t pos=-1)
fiff_long_t write_double(fiff_int_t kind, const double *data, fiff_int_t nel=1)
bool attach_env(const QString &workingDir, const QString &command)
QList< FiffProj > read_proj(const FiffDirNode::SPtr &p_Node)
static FiffStream::SPtr open_update(QIODevice &p_IODevice)
FiffDirNode::SPtr make_subtree(QList< FiffDirEntry::SPtr > &dentry)
bool read_named_matrix(const FiffDirNode::SPtr &p_Node, fiff_int_t matkind, FiffNamedMatrix &mat)
QList< FiffDirEntry::SPtr > & dir()
std::unique_ptr< FiffTag > UPtr
Definition fiff_tag.h:158
static void convert_tag_data(const FiffTag::UPtr &tag, int from_endian, int to_endian)
Definition fiff_tag.cpp:438
static std::vector< Eigen::Triplet< T > > sortrows(const std::vector< Eigen::Triplet< T > > &A, qint32 column=0)
Definition linalg.h:333
static bool issparse(Eigen::VectorXd &v)
Definition numerics.cpp:73