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<const VectorXd>(tag->toDouble(),dim);
628 }
629 else if (tag->type == FIFFT_FLOAT)
630 {
631 cov_diag = Map<const 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<const VectorXd>(tag->toDouble(),nn);
649 }
650 else if (tag->type == FIFFT_FLOAT)
651 {
652 vals = Map<const 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<const 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 //
3236 // Write measurement info so that the file can be read back
3237 //
3239
3240 this->write_int(FIFF_NCHAN, &p_FiffEvokedSet.info.nchan);
3241
3242 float sfreq = p_FiffEvokedSet.info.sfreq;
3243 this->write_float(FIFF_SFREQ, &sfreq);
3244
3245 for (int k = 0; k < p_FiffEvokedSet.info.nchan; ++k) {
3246 FiffChInfo ch = p_FiffEvokedSet.info.chs[k];
3247 ch.scanNo = k + 1;
3248 this->write_ch_info(ch);
3249 }
3250
3251 if (!p_FiffEvokedSet.info.dev_head_t.isEmpty())
3252 this->write_coord_trans(p_FiffEvokedSet.info.dev_head_t);
3253
3254 if (!p_FiffEvokedSet.info.projs.isEmpty())
3255 this->write_proj(p_FiffEvokedSet.info.projs);
3256
3258
3259 for (int j = 0; j < p_FiffEvokedSet.evoked.size(); ++j) {
3260 const FiffEvoked &evoked = p_FiffEvokedSet.evoked[j];
3261
3264
3265 this->write_string(FIFF_COMMENT, evoked.comment);
3266
3267 int first = evoked.first;
3268 this->write_int(FIFF_FIRST_SAMPLE, &first);
3269
3270 int last = evoked.last;
3271 this->write_int(FIFF_LAST_SAMPLE, &last);
3272
3274
3275 int aspectKind = FIFFV_ASPECT_AVERAGE;
3276 this->write_int(FIFF_ASPECT_KIND, &aspectKind);
3277
3278 int nave = evoked.nave;
3279 this->write_int(FIFF_NAVE, &nave);
3280
3281 Eigen::MatrixXf floatData = evoked.data.cast<float>();
3282 this->write_float_matrix(FIFF_EPOCH, floatData);
3283
3284 this->end_block(FIFFB_ASPECT);
3285 this->end_block(FIFFB_EVOKED);
3287 }
3288
3289 this->end_block(FIFFB_MEAS);
3290
3291 return pos;
3292}
3293
3294//=============================================================================================================
3295
3296bool FiffStream::write_raw_buffer(const MatrixXd& buf,
3297 const RowVectorXd& cals)
3298{
3299 if (buf.rows() != cals.cols())
3300 {
3301 qWarning("buffer and calibration sizes do not match\n");
3302 return false;
3303 }
3304
3305 using T = Eigen::Triplet<double>;
3306 std::vector<T> tripletList;
3307 tripletList.reserve(cals.cols());
3308 for(qint32 i = 0; i < cals.cols(); ++i)
3309 tripletList.push_back(T(i, i, 1.0/cals[i]));
3310
3311 SparseMatrix<double> inv_calsMat(cals.cols(), cals.cols());
3312 inv_calsMat.setFromTriplets(tripletList.begin(), tripletList.end());
3313
3314 MatrixXf tmp = (inv_calsMat*buf).cast<float>();
3315 this->write_float(FIFF_DATA_BUFFER,tmp.data(),tmp.rows()*tmp.cols());
3316 return true;
3317}
3318
3319//=============================================================================================================
3320
3321bool FiffStream::write_raw_buffer(const MatrixXd& buf,
3322 const SparseMatrix<double>& mult)
3323{
3324 if (buf.rows() != mult.cols()) {
3325 qWarning("buffer and mult sizes do not match\n");
3326 return false;
3327 }
3328
3329 SparseMatrix<double> inv_mult(mult.rows(), mult.cols());
3330 for (int k=0; k<inv_mult.outerSize(); ++k)
3331 for (SparseMatrix<double>::InnerIterator it(mult,k); it; ++it)
3332 inv_mult.coeffRef(it.row(),it.col()) = 1/it.value();
3333
3334 MatrixXf tmp = (inv_mult*buf).cast<float>();
3335 this->write_float(FIFF_DATA_BUFFER,tmp.data(),tmp.rows()*tmp.cols());
3336 return true;
3337}
3338
3339//=============================================================================================================
3340
3341bool FiffStream::write_raw_buffer(const MatrixXd& buf)
3342{
3343 MatrixXf tmp = buf.cast<float>();
3344 this->write_float(FIFF_DATA_BUFFER,tmp.data(),tmp.rows()*tmp.cols());
3345 return true;
3346}
3347
3348//=============================================================================================================
3349
3351 const QString& data)
3352{
3353 fiff_long_t pos = this->device()->pos();
3354
3355 fiff_int_t datasize = data.size();
3356 *this << (qint32)kind;
3357 *this << (qint32)FIFFT_STRING;
3358 *this << (qint32)datasize;
3359 *this << (qint32)FIFFV_NEXT_SEQ;
3360
3361 this->writeRawData(data.toUtf8().constData(),datasize);
3362
3363 return pos;
3364}
3365
3366//=============================================================================================================
3367
3368void FiffStream::write_rt_command(fiff_int_t command, const QString& data)
3369{
3370 fiff_int_t datasize = data.size();
3371 *this << (qint32)FIFF_MNE_RT_COMMAND;
3372 *this << (qint32)FIFFT_VOID;
3373 *this << 4+(qint32)datasize;
3374 *this << (qint32)FIFFV_NEXT_SEQ;
3375 *this << command;
3376
3377 this->writeRawData(data.toUtf8().constData(),datasize);
3378}
3379
3380//=============================================================================================================
3381
3382QList<FiffDirEntry::SPtr> FiffStream::make_dir(bool *ok)
3383{
3384 FiffTag::UPtr t_pTag;
3385 QList<FiffDirEntry::SPtr> dir;
3386 FiffDirEntry::SPtr t_pFiffDirEntry;
3387 fiff_long_t pos;
3388 if(ok) *ok = false;
3389 /*
3390 * Start from the very beginning...
3391 */
3392 if(!this->device()->seek(SEEK_SET))
3393 return dir;
3394 while ((pos = this->read_tag_info(t_pTag)) != -1) {
3395 /*
3396 * Guard against reading past EOF. When QDataStream reaches the
3397 * end of the device every subsequent read silently returns zero,
3398 * so read_tag_info never returns -1. Detect this by checking
3399 * whether the stream is still healthy after the header read.
3400 */
3401 if (this->status() != QDataStream::Ok) {
3402 this->resetStatus();
3403 break;
3404 }
3405 /*
3406 * Check that we haven't run into the directory
3407 */
3408 if (t_pTag->kind == FIFF_DIR)
3409 break;
3410 /*
3411 * Put in the new entry
3412 */
3413 t_pFiffDirEntry = FiffDirEntry::SPtr(new FiffDirEntry);
3414 t_pFiffDirEntry->kind = t_pTag->kind;
3415 t_pFiffDirEntry->type = t_pTag->type;
3416 t_pFiffDirEntry->size = t_pTag->size();
3417 t_pFiffDirEntry->pos = (fiff_long_t)pos;
3418
3419 dir.append(t_pFiffDirEntry);
3420 if (t_pTag->next < 0)
3421 break;
3422 }
3423 /*
3424 * Put in the new the terminating entry
3425 */
3426 t_pFiffDirEntry = FiffDirEntry::SPtr(new FiffDirEntry);
3427 t_pFiffDirEntry->kind = -1;
3428 t_pFiffDirEntry->type = -1;
3429 t_pFiffDirEntry->size = -1;
3430 t_pFiffDirEntry->pos = -1;
3431 dir.append(t_pFiffDirEntry);
3432
3433 if(ok) *ok = true;
3434 return dir;
3435}
3436
3437//=============================================================================================================
3438
3439bool FiffStream::copyProcessingHistory(const QString& fromPath, const QString& toPath)
3440{
3441 // Open source file
3442 QFile srcFile(fromPath);
3443 if (!srcFile.open(QIODevice::ReadOnly)) {
3444 qWarning("FiffStream::copyProcessingHistory - Cannot open source file %s",
3445 fromPath.toUtf8().constData());
3446 return false;
3447 }
3448
3449 FiffStream srcStream(&srcFile);
3450 if (!srcStream.open()) {
3451 qWarning("FiffStream::copyProcessingHistory - Cannot parse source FIFF file %s",
3452 fromPath.toUtf8().constData());
3453 srcFile.close();
3454 return false;
3455 }
3456
3457 // Find the FIFFB_PROCESSING_HISTORY block in the directory tree
3458 QList<FiffDirNode::SPtr> histNodes = srcStream.dirtree()->dir_tree_find(FIFFB_PROCESSING_HISTORY);
3459 if (histNodes.isEmpty()) {
3460 qWarning("FiffStream::copyProcessingHistory - No processing history block found in %s",
3461 fromPath.toUtf8().constData());
3462 srcStream.close();
3463 return false;
3464 }
3465
3466 // Read all tags from the processing history block
3467 const FiffDirNode::SPtr& histNode = histNodes[0];
3468 std::vector<FiffTag::UPtr> histTags;
3469 for (int i = 0; i < histNode->nent(); ++i) {
3470 FiffTag::UPtr tag;
3471 if (srcStream.read_tag(tag, histNode->dir[i]->pos)) {
3472 histTags.push_back(std::move(tag));
3473 }
3474 }
3475 srcStream.close();
3476
3477 // Open destination file for update
3478 QFile dstFile(toPath);
3479 FiffStream::SPtr dstStream = FiffStream::open_update(dstFile);
3480 if (!dstStream) {
3481 qWarning("FiffStream::copyProcessingHistory - Cannot open destination file %s for update",
3482 toPath.toUtf8().constData());
3483 return false;
3484 }
3485
3486 // Write the processing history block
3487 dstStream->start_block(FIFFB_PROCESSING_HISTORY);
3488 for (const auto& tag : histTags) {
3489 dstStream->write_tag(tag);
3490 }
3491 dstStream->end_block(FIFFB_PROCESSING_HISTORY);
3492
3493 dstStream->close();
3494 return true;
3495}
3496
3497//=============================================================================================================
3498
3499bool FiffStream::check_beginning(FiffTag::UPtr &p_pTag)
3500{
3501 this->read_tag(p_pTag);
3502
3503 if (p_pTag->kind != FIFF_FILE_ID)
3504 {
3505 qWarning("Fiff::open: file does not start with a file id tag\n");//consider throw
3506 return false;
3507 }
3508
3509 if (p_pTag->type != FIFFT_ID_STRUCT)
3510 {
3511 qWarning("Fiff::open: file does not start with a file id tag\n");//consider throw
3512 return false;
3513 }
3514 if (p_pTag->size() != 20)
3515 {
3516 qWarning("Fiff::open: file does not start with a file id tag\n");//consider throw
3517 return false;
3518 }
3519 //do not rewind since the data is contained in the returned tag; -> done for TCP IP reasosn, no rewind possible there
3520 return true;
3521}
FiffChInfo class declaration.
FiffCtfComp class declaration.
FiffCoordTrans class declaration.
FiffDigPoint class declaration.
FiffCov class declaration.
FiffTag class declaration, which provides fiff tag I/O and processing methods.
FiffId class declaration.
FiffChPos class declaration.
FiffDirNode class declaration, which provides fiff dir tree processing methods.
FiffDigitizerData class declaration.
FiffRawData 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
FiffStream class declaration.
FiffInfoBase 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
FiffInfo class declaration.
FiffEvokedSet class declaration.
Numerics class declaration.
Linalg class declaration.
IOUtils 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:90
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)
static bool copyProcessingHistory(const QString &fromPath, const QString &toPath)
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