v2.0.0
Loading...
Searching...
No Matches
compute_fwd.cpp
Go to the documentation of this file.
1
2
3#include "compute_fwd.h"
4
5#include <fiff/fiff.h>
7#include "../fwd_coil_set.h"
8#include "../fwd_comp_data.h"
11#include "../fwd_bem_model.h"
12
14#include <mne/mne_nearest.h>
17
19
20#include <fiff/fiff_types.h>
21
22#include <time.h>
23
24#include <Eigen/Dense>
25
26#include <algorithm>
27
28#include <QCoreApplication>
29#include <QFile>
30#include <QDir>
31#include <QTextStream>
32
33using namespace Eigen;
34using namespace FWDLIB;
35using namespace FIFFLIB;
36using namespace MNELIB;
37
38#ifndef TRUE
39#define TRUE 1
40#endif
41
42#ifndef FALSE
43#define FALSE 0
44#endif
45
46#ifndef FAIL
47#define FAIL -1
48#endif
49
50#ifndef OK
51#define OK 0
52#endif
53
54#define X_41 0
55#define Y_41 1
56#define Z_41 2
57
58#define ALLOC_ICMATRIX_41(x,y) mne_imatrix_41((x),(y))
59
60#define MALLOC_41(x,t) (t *)malloc((x)*sizeof(t))
61#define REALLOC_41(x,y,t) (t *)((x == Q_NULLPTR) ? malloc((y)*sizeof(t)) : realloc((x),(y)*sizeof(t)))
62
63#define FREE_41(x) if ((char *)(x) != Q_NULLPTR) free((char *)(x))
64
65#define VEC_COPY_41(to,from) {\
66 (to)[X_41] = (from)[X_41];\
67 (to)[Y_41] = (from)[Y_41];\
68 (to)[Z_41] = (from)[Z_41];\
69 }
70
71#define VEC_DOT_41(x,y) ((x)[X_41]*(y)[X_41] + (x)[Y_41]*(y)[Y_41] + (x)[Z_41]*(y)[Z_41])
72
73#define VEC_LEN_41(x) sqrt(VEC_DOT_41(x,x))
74
75#define ALLOC_CMATRIX_41(x,y) mne_cmatrix_41((x),(y))
76#define FREE_CMATRIX_41(m) mne_free_cmatrix_41((m))
77#define FREE_ICMATRIX_41(m) mne_free_icmatrix_41((m))
78
79static void matrix_error_41(int kind, int nr, int nc)
80
81{
82 if (kind == 1)
83 printf("Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
84 else if (kind == 2)
85 printf("Failed to allocate memory for a %d x %d matrix\n",nr,nc);
86 else
87 printf("Allocation error for a %d x %d matrix\n",nr,nc);
88 if (sizeof(void *) == 4) {
89 printf("This is probably because you seem to be using a computer with 32-bit architecture.\n");
90 printf("Please consider moving to a 64-bit platform.");
91 }
92 printf("Cannot continue. Sorry.\n");
93 exit(1);
94}
95
96float **mne_cmatrix_41(int nr,int nc)
97
98{
99 int i;
100 float **m;
101 float *whole;
102
103 m = MALLOC_41(nr,float *);
104 if (!m) matrix_error_41(1,nr,nc);
105 whole = MALLOC_41(nr*nc,float);
106 if (!whole) matrix_error_41(2,nr,nc);
107
108 for(i=0;i<nr;i++)
109 m[i] = whole + i*nc;
110 return m;
111}
112
113int **mne_imatrix_41(int nr,int nc)
114
115{
116 int i,**m;
117 int *whole;
118
119 m = MALLOC_41(nr,int *);
120 if (!m) matrix_error_41(1,nr,nc);
121 whole = MALLOC_41(nr*nc,int);
122 if (!whole) matrix_error_41(2,nr,nc);
123 for(i=0;i<nr;i++)
124 m[i] = whole + i*nc;
125 return m;
126}
127
128void mne_free_cmatrix_41 (float **m)
129{
130 if (m) {
131 FREE_41(*m);
132 FREE_41(m);
133 }
134}
135
137
138{
139 if (m) {
140 FREE_41(*m);
141 FREE_41(m);
142 }
143}
144
145fiffId get_file_id(const QString& name)
146{
147 QFile file(name);
148 FiffStream::SPtr stream(new FiffStream(&file));
149 fiffId id;
150 if(!stream->open()) {
151 stream->close();
152 return Q_NULLPTR;
153 }
154 else {
155 id = MALLOC_41(1,fiffIdRec);
156 id->version = stream->id().version;
157 id->machid[0] = stream->id().machid[0];
158 id->machid[1] = stream->id().machid[1];
159 id->time = stream->id().time;
160
161 stream->close();
162 return id;
163 }
164}
165
166//============================= mne_read_forward_solution.c =============================
167
168//int mne_read_meg_comp_eeg_ch_info_41(const QString& name,
169// QList<FiffChInfo>& megp, /* MEG channels */
170// int* nmegp,
171// QList<FiffChInfo>& meg_compp,
172// int* nmeg_compp,
173// QList<FiffChInfo>& eegp, /* EEG channels */
174// int* neegp,
175// FiffCoordTransOld** meg_head_t,
176// fiffId* idp) /* The measurement ID */
178// * Read the channel information and split it into three arrays,
179// * one for MEG, one for MEG compensation channels, and one for EEG
180// */
181//{
182// QFile file(name);
183// FiffStream::SPtr stream(new FiffStream(&file));
184
185// QList<FiffChInfo> chs;
186// int nchan = 0;
187// QList<FiffChInfo> meg;
188// int nmeg = 0;
189// QList<FiffChInfo> meg_comp;
190// int nmeg_comp = 0;
191// QList<FiffChInfo> eeg;
192// int neeg = 0;
193// fiffId id = Q_NULLPTR;
194// QList<FiffDirNode::SPtr> nodes;
195// FiffDirNode::SPtr info;
196// FiffTag::SPtr t_pTag;
197// FiffChInfo this_ch;
198// FiffCoordTransOld* t = Q_NULLPTR;
199// fiff_int_t kind, pos;
200// int j,k,to_find;
201
202// if(!stream->open())
203// goto bad;
204
205// nodes = stream->dirtree()->dir_tree_find(FIFFB_MNE_PARENT_MEAS_FILE);
206
207// if (nodes.size() == 0) {
208// nodes = stream->dirtree()->dir_tree_find(FIFFB_MEAS_INFO);
209// if (nodes.size() == 0) {
210// qCritical ("Could not find the channel information.");
211// goto bad;
212// }
213// }
214// info = nodes[0];
215// to_find = 0;
216// for (k = 0; k < info->nent(); k++) {
217// kind = info->dir[k]->kind;
218// pos = info->dir[k]->pos;
219// switch (kind) {
220// case FIFF_NCHAN :
221// if (!stream->read_tag(t_pTag,pos))
222// goto bad;
223// nchan = *t_pTag->toInt();
224
225// for (j = 0; j < nchan; j++) {
226// chs.append(FiffChInfo());
227// chs[j].scanNo = -1;
228// }
229// to_find = nchan;
230// break;
231
232// case FIFF_PARENT_BLOCK_ID :
233// if(!stream->read_tag(t_pTag, pos))
234// goto bad;
235// // id = t_pTag->toFiffID();
236// *id = *(fiffId)t_pTag->data();
237// break;
238
239// case FIFF_COORD_TRANS :
240// if(!stream->read_tag(t_pTag, pos))
241// goto bad;
242// // t = t_pTag->toCoordTrans();
243// t = FiffCoordTransOld::read_helper( t_pTag );
244// if (t->from != FIFFV_COORD_DEVICE || t->to != FIFFV_COORD_HEAD)
245// t = Q_NULLPTR;
246// break;
247
248// case FIFF_CH_INFO : /* Information about one channel */
249// if(!stream->read_tag(t_pTag, pos))
250// goto bad;
251// this_ch = t_pTag->toChInfo();
252// if (this_ch.scanNo <= 0 || this_ch.scanNo > nchan) {
253// printf ("FIFF_CH_INFO : scan # out of range %d (%d)!",this_ch.scanNo,nchan);
254// goto bad;
255// }
256// else
257// chs[this_ch.scanNo-1] = this_ch;
258// to_find--;
259// break;
260// }
261// }
262// if (to_find != 0) {
263// qCritical("Some of the channel information was missing.");
264// goto bad;
265// }
266// if (t == Q_NULLPTR && meg_head_t != Q_NULLPTR) {
267// /*
268// * Try again in a more general fashion
269// */
270// if ((t = FiffCoordTransOld::mne_read_meas_transform(name)) == Q_NULLPTR) {
271// qCritical("MEG -> head coordinate transformation not found.");
272// goto bad;
273// }
274// }
275// /*
276// * Sort out the channels
277// */
278// for (k = 0; k < nchan; k++) {
279// if (chs[k].kind == FIFFV_MEG_CH) {
280// meg.append(chs[k]);
281// nmeg++;
282// } else if (chs[k].kind == FIFFV_REF_MEG_CH) {
283// meg_comp.append(chs[k]);
284// nmeg_comp++;
285// } else if (chs[k].kind == FIFFV_EEG_CH) {
286// eeg.append(chs[k]);
287// neeg++;
288// }
289// }
290// // fiff_close(in);
291
292// stream->close();
293
294// megp = meg;
295// if(nmegp) {
296// *nmegp = nmeg;
297// }
298
299// meg_compp = meg_comp;
300// if(nmeg_compp) {
301// *nmeg_compp = nmeg_comp;
302// }
303
304// eegp = eeg;
305// if(neegp) {
306// *neegp = neeg;
307// }
308
309// if (idp == Q_NULLPTR) {
310// FREE_41(id);
311// } else {
312// *idp = id;
313// }
314
315// if (meg_head_t == Q_NULLPTR) {
316// FREE_41(t);
317// } else {
318// *meg_head_t = t;
319// }
320
321// return FIFF_OK;
322
323//bad : {
324// // fiff_close(in);
325// stream->close();
326// FREE_41(id);
327// // FREE_41(tag.data);
328// FREE_41(t);
329// return FIFF_FAIL;
330// }
331//}
332
333int ComputeFwd::mne_read_meg_comp_eeg_ch_info_41(FIFFLIB::FiffInfoBase::SPtr pFiffInfoBase,
334 QList<FiffChInfo>& listMegCh,
335 int& iNMeg,
336 QList<FiffChInfo>& listMegComp,
337 int& iNMegCmp,
338 QList<FiffChInfo>& listEegCh,
339 int &iNEeg,
340 FiffCoordTrans& transDevHead,
341 FiffId& id)
342{
343 int iNumCh = pFiffInfoBase->nchan;
344 for (int k = 0; k < iNumCh; k++) {
345 if (pFiffInfoBase->chs[k].kind == FIFFV_MEG_CH) {
346 listMegCh.append(pFiffInfoBase->chs[k]);
347 iNMeg++;
348 } else if (pFiffInfoBase->chs[k].kind == FIFFV_REF_MEG_CH) {
349 listMegComp.append(pFiffInfoBase->chs[k]);
350 iNMegCmp++;
351 } else if (pFiffInfoBase->chs[k].kind == FIFFV_EEG_CH) {
352 listEegCh.append(pFiffInfoBase->chs[k]);
353 iNEeg++;
354 }
355 }
356
357 if(m_pSettings->meg_head_t.isEmpty()) {
358 transDevHead = pFiffInfoBase->dev_head_t;
359 } else {
360 transDevHead = m_pSettings->meg_head_t;
361 }
362 if(m_meg_head_t.isEmpty()) {
363 qCritical("MEG -> head coordinate transformation not found.");
364 return FIFF_FAIL;
365 }
366 id = pFiffInfoBase->meas_id;
367 return OK;
368}
369
370int mne_check_chinfo(const QList<FiffChInfo>& chs,
371 int nch)
372/*
373 * Check that all EEG channels have reasonable locations
374 */
375{
376 int k;
377 FiffChInfo ch;
378 float close = 0.02f;
379
380 for (k = 0; k < nch; k++) {
381 if (chs.at(k).kind == FIFFV_EEG_CH) {
382 if (chs.at(k).chpos.r0.norm() < close) {
383 qCritical("Some EEG channels do not have locations assigned.");
384 return FAIL;
385 }
386 }
387 }
388
389 return OK;
390}
391
392//=============================================================================================================
393// Temporary Helpers
394//=============================================================================================================
395
397{
398 fiffId t_id = id;
399 if(t_id->version == -1)
400 {
401 /* initialize random seed: */
402 srand ( time(Q_NULLPTR) );
403 double rand_1 = (double)(rand() % 100);rand_1 /= 100;
404 double rand_2 = (double)(rand() % 100);rand_2 /= 100;
405
406 time_t seconds;
407 seconds = time (Q_NULLPTR);
408
409 //fiff_int_t timezone = 5; // Matlab does not know the timezone
410 t_id->version = (1 << 16) | 2; // Version (1 << 16) | 2
411 t_id->machid[0] = 65536*rand_1; // Machine id is random for now
412 t_id->machid[1] = 65536*rand_2; // Machine id is random for now
413 t_id->time.secs = (int)seconds; //seconds since January 1, 1970 //3600*(24*(now-datenum(1970,1,1,0,0,0))+timezone);
414 t_id->time.usecs = 0; // Do not know how we could get this
415 }
416
417 //
418 //
419 fiff_int_t datasize = 5*4; // The id comprises five integers
420
421 *t_pStream << (qint32)kind;
422 *t_pStream << (qint32)FIFFT_ID_STRUCT;
423 *t_pStream << (qint32)datasize;
424 *t_pStream << (qint32)FIFFV_NEXT_SEQ;
425 //
426 // Collect the bits together for one write
427 //
428 qint32 data[5];
429 data[0] = t_id->version;
430 data[1] = t_id->machid[0];
431 data[2] = t_id->machid[1];
432 data[3] = t_id->time.secs;
433 data[4] = t_id->time.usecs;
434
435 for(qint32 i = 0; i < 5; ++i)
436 *t_pStream << data[i];
437}
438
439//=============================================================================================================
440
442{
443 //?typedef struct _fiffCoordTransRec {
444 // fiff_int_t from; /*!< Source coordinate system. */
445 // fiff_int_t to; /*!< Destination coordinate system. */
446 // fiff_float_t rot[3][3]; /*!< The forward transform (rotation part) */
447 // fiff_float_t move[3]; /*!< The forward transform (translation part) */
448 // fiff_float_t invrot[3][3]; /*!< The inverse transform (rotation part) */
449 // fiff_float_t invmove[3]; /*!< The inverse transform (translation part) */
450 //} *fiffCoordTrans, fiffCoordTransRec; /*!< Coordinate transformation descriptor */
451 fiff_int_t datasize = 4*2*12 + 4*2;
452
453 *t_pStream << (qint32)FIFF_COORD_TRANS;
454 *t_pStream << (qint32)FIFFT_COORD_TRANS_STRUCT;
455 *t_pStream << (qint32)datasize;
456 *t_pStream << (qint32)FIFFV_NEXT_SEQ;
457
458 //
459 // Start writing fiffCoordTransRec
460 //
461 *t_pStream << (qint32)trans.from;
462 *t_pStream << (qint32)trans.to;
463
464 //
465 // The transform...
466 //
467 qint32 r, c;
468 for (r = 0; r < 3; ++r)
469 for (c = 0; c < 3; ++c)
470 *t_pStream << (float)trans.rot()(r,c);
471 for (r = 0; r < 3; ++r)
472 *t_pStream << (float)trans.move()(r);
473
474 //
475 // ...and its inverse
476 //
477 for (r = 0; r < 3; ++r)
478 for (c = 0; c < 3; ++c)
479 *t_pStream << (float)trans.invrot()(r,c);
480 for (r = 0; r < 3; ++r)
481 *t_pStream << (float)trans.invmove()(r);
482}
483
484// Write a coordinate transform to a FIFF stream.
486{
487 if (trans.isEmpty()) return;
488 write_coord_trans_old(t_pStream, trans);
489}
490
491static int **make_file_triangle_list_41(int **tris, int ntri)
492/*
493 * In the file the numbering starts from one
494 */
495{
496 int **res = ALLOC_ICMATRIX_41(ntri,3);
497 int j,k;
498
499 for (j = 0; j < ntri; j++)
500 for (k = 0; k < 3; k++)
501 res[j][k] = tris[j][k]+1;
502 return res;
503}
504
505void mne_write_bad_channel_list_new(FiffStream::SPtr& t_pStream, const QStringList& t_badList)//FILE *out, char **list, int nlist)
506{
507
508 t_pStream->start_block(FIFFB_MNE_BAD_CHANNELS);
509 t_pStream->write_name_list(FIFF_MNE_CH_NAME_LIST,t_badList);
510 t_pStream->end_block(FIFFB_MNE_BAD_CHANNELS);
511
513
514 // fiff_int_t bad_channel_block = FIFFB_MNE_BAD_CHANNELS;
515 // fiffTagRec bad_channel_block_tags[] = {
516 // { FIFF_BLOCK_START, FIFFT_INT, 0, FIFFV_NEXT_SEQ, Q_NULLPTR },
517 // { FIFF_MNE_CH_NAME_LIST, FIFFT_STRING, 0, FIFFV_NEXT_SEQ, Q_NULLPTR },
518 // { FIFF_BLOCK_END, FIFFT_INT, 0, FIFFV_NEXT_SEQ, Q_NULLPTR }};
519 // int nbad_channel_block_tags = 3;
520 // char *names = Q_NULLPTR;
521 // int k;
522
523 // if (nlist <= 0)
524 // return OK;
525
526 // names = mne_name_list_to_string(list,nlist);
527 // bad_channel_block_tags[0].size = sizeof(fiff_int_t);
528 // bad_channel_block_tags[0].data = &bad_channel_block;
529
530 // bad_channel_block_tags[1].size = strlen(names);
531 // bad_channel_block_tags[1].data = names;
532
533 // bad_channel_block_tags[2].size = sizeof(fiff_int_t);
534 // bad_channel_block_tags[2].data = &bad_channel_block;
535
536 // for (k = 0; k < nbad_channel_block_tags; k++)
537 // if (fiff_write_tag(out,bad_channel_block_tags+k) == FIFF_FAIL) {
538 // FREE(names);
539 // return FAIL;
540 // }
541 // FREE(names);
542 // return OK;
543}
544
545void fiff_write_float_matrix_old ( FiffStream::SPtr& t_pStream, /* Destination file name */
546 int kind, /* What kind of tag */
547 fiff_float_t **data, /* The data to write */
548 int rows,
549 int cols) /* Number of rows and columns */
550/*
551 * Write out a 2D floating-point matrix
552 */
553{
554 MatrixXf mat(rows,cols);
555
556 for (int i = 0; i < rows; ++i) {
557 for(int j = 0; j < cols; ++j) {
558 mat(i,j) = data[i][j];
559 }
560 }
561
562 t_pStream->write_float_matrix(kind, mat);
563
564 // int res,*dims;
565 // fiffTagRec tag;
566 //#ifdef INTEL_X86_ARCH
567 // int c;
568 //#endif
569 // int k;
570 // int rowsize;
571
572 // tag.kind = kind;
573 // tag.type = FIFFT_FLOAT | FIFFT_MATRIX;
574 // tag.size = rows*cols*sizeof(fiff_float_t) + 3*sizeof(fiff_int_t);
575 // tag.data = Q_NULLPTR;
576 // tag.next = FIFFV_NEXT_SEQ;
577
578 // if ((res = fiff_write_tag_info(out,&tag)) == -1)
579 // return FIFF_FAIL;
580
581 // rowsize = cols*sizeof(fiff_float_t);
582 // for (k = 0; k < rows; k++) {
583 //#ifdef INTEL_X86_ARCH
584 // for (c = 0; c < cols; c++)
585 // swap_float(data[k]+c);
586 //#endif
587 // if (fwrite (data[k],rowsize,1,out) != 1) {
588 // if (ferror(out))
589 // err_set_sys_error("fwrite");
590 // else
591 // err_set_error("fwrite failed");
592 //#ifdef INTEL_X86_ARCH
593 // for (c = 0; c < cols; c++)
594 // swap_float(data[k]+c);
595 //#endif
596 // return FIFF_FAIL;
597 // }
598 //#ifdef INTEL_X86_ARCH
599 // for (c = 0; c < cols; c++)
600 // swap_float(data[k]+c);
601 //#endif
602 // }
603 // dims = MALLOC_41(3,fiff_int_t);
604 // dims[0] = swap_int(cols);
605 // dims[1] = swap_int(rows);
606 // dims[2] = swap_int(2);
607 // if (fwrite (dims,3*sizeof(fiff_int_t),1,out) != 1) {
608 // if (ferror(out))
609 // err_set_sys_error("fwrite");
610 // else
611 // err_set_error("fwrite failed");
612 // FREE(dims);
613 // return FIFF_FAIL;
614 // }
615 // FREE(dims);
616 // return res;
617}
618
620 int kind, /* What kind of tag */
621 fiff_int_t **data, /* The data to write */
622 int rows,
623 int cols) /* Number of rows and columns */
624/*
625 * Write out a 2D integer matrix
626 */
627{
628 MatrixXi mat(rows,cols);
629
630 for (int i = 0; i < rows; ++i) {
631 for(int j = 0; j < cols; ++j) {
632 mat(i,j) = data[i][j];
633 }
634 }
635
636 t_pStream->write_int_matrix(kind, mat);
637
638 // int res,*dims;
639 // fiffTagRec tag;
640 //#ifdef INTEL_X86_ARCH
641 // int c;
642 //#endif
643 // int k;
644 // int rowsize;
645
646 // tag.kind = kind;
647 // tag.type = FIFFT_INT | FIFFT_MATRIX;
648 // tag.size = rows*cols*sizeof(fiff_int_t) + 3*sizeof(fiff_int_t);
649 // tag.data = Q_NULLPTR;
650 // tag.next = FIFFV_NEXT_SEQ;
651
652 // if ((res = fiff_write_tag_info(out,&tag)) == -1)
653 // return -1;
654
655 // rowsize = cols*sizeof(fiff_int_t);
656 // for (k = 0; k < rows; k++) {
657 //#ifdef INTEL_X86_ARCH
658 // for (c = 0; c < cols; c++)
659 // data[k][c] = swap_int(data[k][c]);
660 //#endif
661 // if (fwrite (data[k],rowsize,1,out) != 1) {
662 // if (ferror(out))
663 // err_set_sys_error("fwrite");
664 // else
665 // err_set_error("fwrite failed");
666 // return -1;
667 //#ifdef INTEL_X86_ARCH
668 // for (c = 0; c < cols; c++)
669 // data[k][c] = swap_int(data[k][c]);
670 //#endif
671 // }
672 //#ifdef INTEL_X86_ARCH
673 // for (c = 0; c < cols; c++)
674 // data[k][c] = swap_int(data[k][c]);
675 //#endif
676 // }
677 // dims = MALLOC_41(3,fiff_int_t);
678 // dims[0] = swap_int(cols);
679 // dims[1] = swap_int(rows);
680 // dims[2] = swap_int(2);
681 // if (fwrite (dims,3*sizeof(fiff_int_t),1,out) != 1) {
682 // if (ferror(out))
683 // err_set_sys_error("fwrite");
684 // else
685 // err_set_error("fwrite failed");
686 // FREE(dims);
687 // return -1;
688 // }
689 // FREE(dims);
690 // return res;
691}
692
694/*
695 * Write a sparse matrix
696 */
697{
698 FiffTag::SPtr tag;
699 int k;
700 int type;
701 int datasize,idxsize,ptrsize;
702 int two = 2;
703
704 datasize = mat->nz * sizeof(fiff_float_t);
705 idxsize = mat->nz * sizeof(fiff_int_t);
706 if (mat->coding == FIFFTS_MC_CCS)
707 ptrsize = (mat->n+1) * sizeof(fiff_int_t);
708 else if (mat->coding == FIFFTS_MC_RCS)
709 ptrsize = (mat->m+1) * sizeof(fiff_int_t);
710 else {
711 qCritical("Incomprehensible sparse matrix coding");
712 return FIFF_FAIL;
713 }
714
715 if (datasize <= 0 || idxsize <= 0 || ptrsize <= 0) {
716 qCritical("fiff_write_float_ccs_matrix: negative vector size(s) in sparse matrix!\n");
717 return FIFF_FAIL;
718 }
719
720// tag.kind = kind;
721 if (mat->coding == FIFFTS_MC_CCS)
722 type = FIFFT_FLOAT | FIFFT_CCS_MATRIX;//tag.type = FIFFT_FLOAT | FIFFT_CCS_MATRIX;
723 else if (mat->coding == FIFFTS_MC_RCS)
724 type = FIFFT_FLOAT | FIFFT_RCS_MATRIX;//tag.type = FIFFT_FLOAT | FIFFT_RCS_MATRIX;
725 else {
726 qCritical("Incomprehensible sparse matrix coding");
727 return FIFF_FAIL;
728 }
729
730// tag.size = datasize+idxsize+ptrsize+4*sizeof(fiff_int_t);
731// tag.data = Q_NULLPTR;
732// tag.next = FIFFV_NEXT_SEQ;
733
734 //Write Tag Info
735 *t_pStream << (qint32)kind;
736 *t_pStream << (qint32)type;
737 *t_pStream << (qint32)(datasize+idxsize+ptrsize+4*sizeof(fiff_int_t));
738 *t_pStream << (qint32)FIFFV_NEXT_SEQ;
739// if (fiff_write_tag_info(out,&tag) == FIFF_FAIL)
740// return FIFF_FAIL;
741
742 /*
743 * Write data
744 */
745 for(k = 0; k < mat->nz; ++k)
746 *t_pStream << mat->data[k];
747
748// /*
749// * Write data with swapping
750// */
751//#ifdef INTEL_X86_ARCH
752// for (k = 0; k < mat->nz; k++)
753// swap_floatp(mat->data+k);
754//#endif
755// res = fwrite (mat->data,datasize,1,out);
756//#ifdef INTEL_X86_ARCH
757// for (k = 0; k < mat->nz; k++)
758// swap_floatp(mat->data+k);
759//#endif
760// if (res != 1)
761// goto fwrite_error;
762
763 /*
764 * Write indexes
765 */
766 for(k = 0; k < mat->nz; ++k)
767 *t_pStream << mat->inds[k];
768
769// /*
770// * Write indexes with swapping
771// */
772//#ifdef INTEL_X86_ARCH
773// for (k = 0; k < mat->nz; k++)
774// swap_intp(mat->inds+k);
775//#endif
776// res = fwrite (mat->inds,idxsize,1,out);
777//#ifdef INTEL_X86_ARCH
778// for (k = 0; k < mat->nz; k++)
779// swap_intp(mat->inds+k);
780//#endif
781// if (res != 1)
782// goto fwrite_error;
783
784 if (mat->coding == FIFFTS_MC_CCS) {
785
786 for(k = 0; k < mat->n+1; ++k)
787 *t_pStream << mat->ptrs[k];
788
789//#ifdef INTEL_X86_ARCH
790// for (k = 0; k < mat->n+1; k++)
791// swap_intp(mat->ptrs+k);
792//#endif
793// res = fwrite (mat->ptrs,ptrsize,1,out);
794//#ifdef INTEL_X86_ARCH
795// for (k = 0; k < mat->n+1; k++)
796// swap_intp(mat->ptrs+k);
797//#endif
798// if (res != 1)
799// goto fwrite_error;
800 }
801 else { /* Row-compressed format */
802
803 for(k = 0; k < mat->m+1; ++k)
804 *t_pStream << mat->ptrs[k];
805
806//#ifdef INTEL_X86_ARCH
807// for (k = 0; k < mat->m+1; k++)
808// swap_intp(mat->ptrs+k);
809//#endif
810// res = fwrite (mat->ptrs,ptrsize,1,out);
811//#ifdef INTEL_X86_ARCH
812// for (k = 0; k < mat->m+1; k++)
813// swap_intp(mat->ptrs+k);
814//#endif
815// if (res != 1)
816// goto fwrite_error;
817 }
818 /*
819 * Write the dimensions
820 */
821 *t_pStream << (qint32)mat->nz;
822// val = swap_int(mat->nz);
823// if (fwrite (&val,sizeof(fiff_int_t),1,out) != 1)
824// goto fwrite_error;
825
826 *t_pStream << (qint32)mat->m;
827// val = swap_int(mat->m);
828// if (fwrite (&val,sizeof(fiff_int_t),1,out) != 1)
829// goto fwrite_error;
830
831 *t_pStream << (qint32)mat->n;
832// val = swap_int(mat->n);
833// if (fwrite (&val,sizeof(fiff_int_t),1,out) != 1)
834// goto fwrite_error;
835
836 *t_pStream << (qint32)two;
837// val = swap_int(two);
838// if (fwrite (&val,sizeof(fiff_int_t),1,out) != 1)
839// goto fwrite_error;
840 return FIFF_OK;
841
842//fwrite_error : {
847// return FIFF_FAIL;
848// }
849}
850
851FiffSparseMatrix* mne_create_sparse_rcs(int nrow, /* Number of rows */
852 int ncol, /* Number of columns */
853 int *nnz, /* Number of non-zero elements on each row */
854 int **colindex, /* Column indices of non-zero elements on each row */
855 float **vals) /* The nonzero elements on each row
856 * If Q_NULLPTR, the matrix will be all zeroes */
857
858{
859 int j,k,nz,ptr,ind;
860
861 for (j = 0, nz = 0; j < nrow; j++)
862 nz = nz + nnz[j];
863
864 if (nz <= 0) {
865 qCritical("No nonzero elements specified.");
866 return Q_NULLPTR;
867 }
868
870 sparse->coding = FIFFTS_MC_RCS;
871 sparse->m = nrow;
872 sparse->n = ncol;
873 sparse->nz = nz;
874 sparse->data.resize(nz);
875 sparse->data.setZero();
876 sparse->inds.resize(nz);
877 sparse->inds.setZero();
878 sparse->ptrs.resize(nrow + 1);
879 sparse->ptrs.setZero();
880
881 for (j = 0, nz = 0; j < nrow; j++) {
882 ptr = -1;
883 for (k = 0; k < nnz[j]; k++) {
884 if (ptr < 0)
885 ptr = nz;
886 ind = sparse->inds[nz] = colindex[j][k];
887 if (ind < 0 || ind >= ncol) {
888 qCritical("Column index out of range in mne_create_sparse_rcs");
889 delete sparse;
890 return Q_NULLPTR;
891 }
892 if (vals)
893 sparse->data[nz] = vals[j][k];
894 else
895 sparse->data[nz] = 0.0;
896 nz++;
897 }
898 sparse->ptrs[j] = ptr;
899 }
900 sparse->ptrs[nrow] = nz;
901 for (j = nrow-1; j >= 0; j--) /* Take care of the empty rows */
902 if (sparse->ptrs[j] < 0)
903 sparse->ptrs[j] = sparse->ptrs[j+1];
904 return sparse;
905}
906
908/*
909 * Fill in upper triangle with the lower triangle values
910 */
911{
912 int i,j,k;
913
914 if (mat->coding != FIFFTS_MC_RCS) {
915 qCritical("The input matrix to mne_add_upper_triangle_rcs must be in RCS format");
916 return Q_NULLPTR;
917 }
918 if (mat->m != mat->n) {
919 qCritical("The input matrix to mne_pick_lower_triangle_rcs must be square");
920 return Q_NULLPTR;
921 }
922 /*
923 * Pick the lower triangle elements
924 */
925 std::vector<int> nnz(mat->m);
926 std::vector<std::vector<int>> colindex(mat->m);
927 std::vector<std::vector<float>> vals(mat->m);
928
929 for (i = 0; i < mat->m; i++) {
930 nnz[i] = mat->ptrs[i+1] - mat->ptrs[i];
931 if (nnz[i] > 0) {
932 colindex[i].resize(nnz[i]);
933 vals[i].resize(nnz[i]);
934 for (j = mat->ptrs[i], k = 0; j < mat->ptrs[i+1]; j++) {
935 if (mat->inds[j] <= i) {
936 vals[i][k] = mat->data[j];
937 colindex[i][k] = mat->inds[j];
938 k++;
939 }
940 }
941 nnz[i] = k;
942 }
943 }
944 /*
945 * Assemble the matrix — build raw pointer arrays for the C-style interface
946 */
947 std::vector<int*> ci_ptrs(mat->m);
948 std::vector<float*> val_ptrs(mat->m);
949 for (i = 0; i < mat->m; i++) {
950 ci_ptrs[i] = colindex[i].empty() ? nullptr : colindex[i].data();
951 val_ptrs[i] = vals[i].empty() ? nullptr : vals[i].data();
952 }
953
954 return mne_create_sparse_rcs(mat->m, mat->n, nnz.data(), ci_ptrs.data(), val_ptrs.data());
955}
956
957static int write_volume_space_info(FiffStream::SPtr& t_pStream, MNESourceSpace* ss, int selected_only)
958/*
959 * Write the vertex neighbors and other information for a volume source space
960 */
961{
962 int ntot,nvert;
963 int *nneighbors = Q_NULLPTR;
964 int *neighbors = Q_NULLPTR;
965 int *inuse_map = Q_NULLPTR;
966 int nneigh;
967 int k,p;
968 int res = FAIL;
969
970 if (ss->type != FIFFV_MNE_SPACE_VOLUME)
971 return OK;
972 if (ss->neighbor_vert.empty() || ss->nneighbor_vert.size() == 0)
973 return OK;
974 if (selected_only) {
975 inuse_map = MALLOC_41(ss->np,int);
976 for (k = 0,p = 0, ntot = 0; k < ss->np; k++) {
977 if (ss->inuse[k]) {
978 ntot += ss->nneighbor_vert[k];
979 inuse_map[k] = p++;
980 }
981 else
982 inuse_map[k] = -1;
983 }
984 nneighbors = MALLOC_41(ss->nuse,int);
985 neighbors = MALLOC_41(ntot,int);
986 /*
987 * Pick the neighbors and fix the vertex numbering to refer
988 * to the vertices in use only
989 */
990 for (k = 0, nvert = 0, ntot = 0; k < ss->np; k++) {
991 if (ss->inuse[k]) {
992 const Eigen::VectorXi& neigh = ss->neighbor_vert[k];
993 nneigh = ss->nneighbor_vert[k];
994 nneighbors[nvert++] = nneigh;
995 for (p = 0; p < nneigh; p++)
996 neighbors[ntot++] = neigh[p] < 0 ? -1 : inuse_map[neigh[p]];
997 }
998 }
999 }
1000 else {
1001 for (k = 0, ntot = 0; k < ss->np; k++)
1002 ntot += ss->nneighbor_vert[k];
1003 nneighbors = MALLOC_41(ss->np,int);
1004 neighbors = MALLOC_41(ntot,int);
1005 nvert = ss->np;
1006 for (k = 0, ntot = 0; k < ss->np; k++) {
1007 const Eigen::VectorXi& neigh = ss->neighbor_vert[k];
1008 nneigh = ss->nneighbor_vert[k];
1009 nneighbors[k] = nneigh;
1010 for (p = 0; p < nneigh; p++)
1011 neighbors[ntot++] = neigh[p];
1012 }
1013 }
1014
1015 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NNEIGHBORS,nneighbors,nvert);
1016 // tag.next = FIFFV_NEXT_SEQ;
1017 // tag.kind = FIFF_MNE_SOURCE_SPACE_NNEIGHBORS;
1018 // tag.type = FIFFT_INT;
1019 // tag.size = nvert*sizeof(fiff_int_t);
1020 // tag.data = (fiff_byte_t *)nneighbors;
1021 // if (fiff_write_tag(out,&tag) == FIFF_FAIL)
1022 // goto out;
1023
1024 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NEIGHBORS,neighbors,ntot);
1025 // tag.next = FIFFV_NEXT_SEQ;
1026 // tag.kind = FIFF_MNE_SOURCE_SPACE_NEIGHBORS;
1027 // tag.type = FIFFT_INT;
1028 // tag.size = ntot*sizeof(fiff_int_t);
1029 // tag.data = (fiff_byte_t *)neighbors;
1030 // if (fiff_write_tag(out,&tag) == FIFF_FAIL)
1031 // goto out;
1032
1033 /*
1034 * Write some additional stuff
1035 */
1036 if (!selected_only) {
1037 if (ss->voxel_surf_RAS_t && !ss->voxel_surf_RAS_t->isEmpty()) {
1038 write_coord_trans_old(t_pStream, *ss->voxel_surf_RAS_t);//t_pStream->write_coord_trans(ss->voxel_surf_RAS_t);
1039
1040 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_VOXEL_DIMS,ss->vol_dims,3);
1041 // tag.next = FIFFV_NEXT_SEQ;
1042 // tag.kind = FIFF_MNE_SOURCE_SPACE_VOXEL_DIMS;
1043 // tag.type = FIFFT_INT;
1044 // tag.size = 3*sizeof(fiff_int_t);
1045 // tag.data = (fiff_byte_t *)ss->vol_dims;
1046 // if (fiff_write_tag(out,&tag) == FIFF_FAIL)
1047 // goto out;
1048 }
1049 if (ss->interpolator && !ss->MRI_volume.isEmpty()) {
1050 t_pStream->start_block(FIFFB_MNE_PARENT_MRI_FILE);
1051 if (ss->MRI_surf_RAS_RAS_t && !ss->MRI_surf_RAS_RAS_t->isEmpty())
1052 write_coord_trans_old(t_pStream, *ss->MRI_surf_RAS_RAS_t);//t_pStream->write_coord_trans(ss->MRI_surf_RAS_RAS_t);
1053 if (ss->MRI_voxel_surf_RAS_t && !ss->MRI_voxel_surf_RAS_t->isEmpty())
1054 write_coord_trans_old(t_pStream, *ss->MRI_voxel_surf_RAS_t);//t_pStream->write_coord_trans(ss->MRI_voxel_surf_RAS_t);
1055 t_pStream->write_string(FIFF_MNE_FILE_NAME,ss->MRI_volume);
1056 if (ss->interpolator)
1058 if (ss->MRI_vol_dims[0] > 0 && ss->MRI_vol_dims[1] > 0 && ss->MRI_vol_dims[2] > 0) {
1059 t_pStream->write_int(FIFF_MRI_WIDTH,&ss->MRI_vol_dims[0]);
1060 t_pStream->write_int(FIFF_MRI_HEIGHT,&ss->MRI_vol_dims[1]);
1061 t_pStream->write_int(FIFF_MRI_DEPTH,&ss->MRI_vol_dims[2]);
1062 }
1063 t_pStream->end_block(FIFFB_MNE_PARENT_MRI_FILE);
1064 }
1065 }
1066 else {
1067 if (ss->interpolator && !ss->MRI_volume.isEmpty()) {
1068 t_pStream->write_string(FIFF_MNE_SOURCE_SPACE_MRI_FILE,ss->MRI_volume);
1069 qCritical("Cannot write the interpolator for selection yet");
1070 goto out;
1071 }
1072 }
1073 res = OK;
1074 goto out;
1075
1076out : {
1077 FREE_41(inuse_map);
1078 FREE_41(nneighbors);
1079 FREE_41(neighbors);
1080 return res;
1081 }
1082}
1083
1084int mne_write_one_source_space(FiffStream::SPtr& t_pStream, MNESourceSpace* ss,bool selected_only)
1085{
1086 float **sel = Q_NULLPTR;
1087 int **tris = Q_NULLPTR;
1088 int *nearest = Q_NULLPTR;
1089 float *nearest_dist = Q_NULLPTR;
1090 int p,pp;
1091
1092 if (ss->np <= 0) {
1093 qCritical("No points in the source space being saved");
1094 goto bad;
1095 }
1096
1097 t_pStream->start_block(FIFFB_MNE_SOURCE_SPACE);
1098
1099 /*
1100 * General information
1101 */
1102 if (ss->type != FIFFV_MNE_SPACE_UNKNOWN)
1103 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_TYPE,&ss->type);
1104 if (ss->id != FIFFV_MNE_SURF_UNKNOWN)
1105 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_ID,&ss->id);
1106 if (!ss->subject.isEmpty() && ss->subject.size() > 0) {
1107 QString subj(ss->subject);
1108 t_pStream->write_string(FIFF_SUBJ_HIS_ID,subj);
1109 }
1110
1111 t_pStream->write_int(FIFF_MNE_COORD_FRAME,&ss->coord_frame);
1112
1113 if (selected_only) {
1114 if (ss->nuse == 0) {
1115 qCritical("No vertices in use. Cannot write active-only vertices from this source space");
1116 goto bad;
1117 }
1118 sel = ALLOC_CMATRIX_41(ss->nuse,3);
1119 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NPOINTS,&ss->nuse);
1120 for (p = 0, pp = 0; p < ss->np; p++) {
1121 if (ss->inuse[p]) {
1122 sel[pp][X_41] = ss->rr(p,X_41);
1123 sel[pp][Y_41] = ss->rr(p,Y_41);
1124 sel[pp][Z_41] = ss->rr(p,Z_41);
1125 pp++;
1126 }
1127 }
1129
1130 for (p = 0, pp = 0; p < ss->np; p++) {
1131 if (ss->inuse[p]) {
1132 sel[pp][X_41] = ss->nn(p,X_41);
1133 sel[pp][Y_41] = ss->nn(p,Y_41);
1134 sel[pp][Z_41] = ss->nn(p,Z_41);
1135 pp++;
1136 }
1137 }
1139 FREE_CMATRIX_41(sel); sel = Q_NULLPTR;
1140#ifdef WRONG
1141 /*
1142 * This code is incorrect because the numbering in the nuse triangulation refers to the complete source space
1143 */
1144 if (ss->nuse_tri > 0) { /* Write the triangulation information */
1145 /*
1146 * The 'use' triangulation is identical to the complete one
1147 */
1148 if (fiff_write_int_tag(out,FIFF_MNE_SOURCE_SPACE_NTRI,ss->nuse_tri) == FIFF_FAIL)
1149 goto bad;
1150 tris = make_file_triangle_list(ss->use_itris,ss->nuse_tri);
1151 if (fiff_write_int_matrix(out,FIFF_MNE_SOURCE_SPACE_TRIANGLES,tris,
1152 ss->nuse_tri,3) == FIFF_FAIL)
1153 goto bad;
1154
1155 if (fiff_write_int_tag(out,FIFF_MNE_SOURCE_SPACE_NUSE_TRI,ss->nuse_tri) == FIFF_FAIL)
1156 goto bad;
1157 if (fiff_write_int_matrix(out,FIFF_MNE_SOURCE_SPACE_USE_TRIANGLES,tris,
1158 ss->nuse_tri,3) == FIFF_FAIL)
1159 goto bad;
1160 FREE_ICMATRIX(tris); tris = Q_NULLPTR;
1161 }
1162#endif
1163 }
1164 else {
1165 // fiffTagRec tag;
1166 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NPOINTS,&ss->np);
1167
1168 t_pStream->write_float_matrix(FIFF_MNE_SOURCE_SPACE_POINTS, Eigen::MatrixXf(ss->rr));
1169
1170 t_pStream->write_float_matrix(FIFF_MNE_SOURCE_SPACE_NORMALS, Eigen::MatrixXf(ss->nn));
1171
1172 if (ss->nuse > 0 && ss->inuse.size() > 0) {
1173 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_SELECTION,ss->inuse.data(),ss->np);
1174 // tag.next = 0;
1175 // tag.kind = FIFF_MNE_SOURCE_SPACE_SELECTION;
1176 // tag.type = FIFFT_INT;
1177 // tag.size = (ss->np)*sizeof(fiff_int_t);
1178 // tag.data = (fiff_byte_t *)(ss->inuse);
1179 // if (fiff_write_tag(out,&tag) == FIFF_FAIL)
1180 // goto bad;
1181 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NUSE,&ss->nuse);
1182 // if (fiff_write_int_tag (out, FIFF_MNE_SOURCE_SPACE_NUSE,ss->nuse) == FIFF_FAIL)
1183 // goto bad;
1184 }
1185 if (ss->ntri > 0) { /* Write the triangulation information */
1186 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NTRI,&ss->ntri);
1187 // if (fiff_write_int_tag(out,FIFF_MNE_SOURCE_SPACE_NTRI,ss->ntri) == FIFF_FAIL)
1188 // goto bad;
1189 Eigen::MatrixXi file_tris = ss->itris.array() + 1;
1190 t_pStream->write_int_matrix(FIFF_MNE_SOURCE_SPACE_TRIANGLES, file_tris);
1191 // if (fiff_write_int_matrix(out,FIFF_MNE_SOURCE_SPACE_TRIANGLES,tris,
1192 // ss->ntri,3) == FIFF_FAIL)
1193 // goto bad;
1194 }
1195 if (ss->nuse_tri > 0) { /* Write the triangulation information for the vertices in use */
1196 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NUSE_TRI,&ss->nuse_tri);
1197 // if (fiff_write_int_tag(out,FIFF_MNE_SOURCE_SPACE_NUSE_TRI,ss->nuse_tri) == FIFF_FAIL)
1198 // goto bad;
1199 Eigen::MatrixXi file_use_tris = ss->use_itris.array() + 1;
1200 t_pStream->write_int_matrix(FIFF_MNE_SOURCE_SPACE_USE_TRIANGLES, file_use_tris);
1201 // if (fiff_write_int_matrix(out,FIFF_MNE_SOURCE_SPACE_USE_TRIANGLES,tris,
1202 // ss->nuse_tri,3) == FIFF_FAIL)
1203 // goto bad;
1204 }
1205 if (!ss->nearest.empty()) { /* Write the patch information */
1206 nearest = MALLOC_41(ss->np,int);
1207 nearest_dist = MALLOC_41(ss->np,float);
1208
1209 std::sort(ss->nearest.begin(), ss->nearest.end(),
1210 [](const MNENearest& a, const MNENearest& b) { return a.vert < b.vert; });
1211 for (p = 0; p < ss->np; p++) {
1212 nearest[p] = ss->nearest[p].nearest;
1213 nearest_dist[p] = ss->nearest[p].dist;
1214 }
1215
1216 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NEAREST,nearest,ss->np);
1217 // tag.next = FIFFV_NEXT_SEQ;
1218 // tag.kind = FIFF_MNE_SOURCE_SPACE_NEAREST;
1219 // tag.type = FIFFT_INT;
1220 // tag.size = (ss->np)*sizeof(fiff_int_t);
1221 // tag.data = (fiff_byte_t *)(nearest);
1222 // if (fiff_write_tag(out,&tag) == FIFF_FAIL)
1223 // goto bad;
1224
1225 t_pStream->write_float(FIFF_MNE_SOURCE_SPACE_NEAREST_DIST,nearest_dist,ss->np);
1226 // tag.next = FIFFV_NEXT_SEQ;
1227 // tag.kind = FIFF_MNE_SOURCE_SPACE_NEAREST_DIST;
1228 // tag.type = FIFFT_FLOAT;
1229 // tag.size = (ss->np)*sizeof(fiff_float_t);
1230 // tag.data = (fiff_byte_t *)(nearest_dist);
1231 // if (fiff_write_tag(out,&tag) == FIFF_FAIL)
1232 // goto bad;
1233
1234 FREE_41(nearest); nearest = Q_NULLPTR;
1235 FREE_41(nearest_dist); nearest_dist = Q_NULLPTR;
1236 }
1237 if (!ss->dist.is_empty()) { /* Distance information */
1239 if (!m)
1240 goto bad;
1242 if(m)
1243 delete m;
1244 goto bad;
1245 }
1246 if(m)
1247 delete m;
1248
1249 t_pStream->write_float(FIFF_MNE_SOURCE_SPACE_DIST_LIMIT,&ss->dist_limit);
1250 }
1251 }
1252 /*
1253 * Volume source spaces have additional information
1254 */
1255 // if (write_volume_space_info(out,ss,selected_only) == FIFF_FAIL)
1256 // goto bad;
1257
1258 t_pStream->end_block(FIFFB_MNE_SOURCE_SPACE);
1259 return FIFF_OK;
1260
1261bad : {
1262 FREE_ICMATRIX_41(tris);
1263 FREE_CMATRIX_41(sel);
1264 FREE_41(nearest);
1265 FREE_41(nearest_dist);
1266 return FIFF_FAIL;
1267 }
1268}
1269
1270QString mne_name_list_to_string_41(const QStringList& list)
1271/*
1272 * Convert a string array to a colon-separated string
1273 */
1274{
1275 int nlist = list.size();
1276 QString res;
1277 if (nlist == 0 || list.isEmpty())
1278 return res;
1279// res[0] = '\0';
1280 for (int k = 0; k < nlist-1; k++) {
1281 res += list[k];
1282 res += ":";
1283 }
1284 res += list[nlist-1];
1285 return res;
1286}
1287
1289 int kind,
1290 MNENamedMatrix* mat)
1291/*
1292 * Write a block which contains information about one named matrix
1293 */
1294{
1295 QString names;
1296
1297 t_pStream->start_block(FIFFB_MNE_NAMED_MATRIX);
1298
1299 t_pStream->write_int(FIFF_MNE_NROW,&mat->nrow);
1300 t_pStream->write_int(FIFF_MNE_NCOL,&mat->ncol);
1301 if (!mat->rowlist.isEmpty()) {
1302 names = mne_name_list_to_string_41(mat->rowlist);
1303 t_pStream->write_string(FIFF_MNE_ROW_NAMES,names);
1304 }
1305 if (!mat->collist.isEmpty()) {
1306 names = mne_name_list_to_string_41(mat->collist);
1307 t_pStream->write_string(FIFF_MNE_COL_NAMES,names);
1308 }
1309 t_pStream->write_float_matrix(kind, mat->data);
1310
1311 t_pStream->end_block(FIFFB_MNE_NAMED_MATRIX);
1312
1313 return FIFF_OK;
1314}
1315
1316bool fiff_put_dir (FiffStream::SPtr& t_pStream, const QList<FiffDirEntry::SPtr>& dir)
1317/*
1318 * Put in new directory
1319 */
1320{
1321 int nent = dir.size();
1322 int k;
1323 FiffTag::SPtr t_pTag;
1324 fiff_int_t dirpos;
1325
1326 for (k = 0; k < nent; k++) {
1327 if (dir[k]->kind == FIFF_DIR_POINTER) {
1328 /*
1329 * Read current value of directory pointer
1330 */
1331 if (!t_pStream->read_tag(t_pTag,dir[k]->pos)) {
1332 fprintf (stderr,"Could not read FIFF_DIR_POINTER!\n");
1333 return false;
1334 }
1335 /*
1336 * If there is no directory, append the new one
1337 */
1338 dirpos = *t_pTag->toInt();//2GB restriction
1339 if (dirpos <= 0)
1340 dirpos = -1;
1341 /*
1342 * Put together the directory tag
1343 */
1344 dirpos = (fiff_int_t)t_pStream->write_dir_entries(dir);//2GB restriction
1345 if (dirpos < 0)
1346 printf ("Could not update directory!\n");
1347 else {
1348 t_pTag->setNum(dirpos);
1349// t_pStream->write_tag(t_pTag,dir[k]->pos);
1350
1351 t_pStream->write_dir_pointer(dirpos, dir[k]->pos);
1352
1353// t_pStream->device()->seek(dir[k]->pos);
1354
1355// fiff_int_t datasize = 1 * 4;
1356
1357// *t_pStream << (qint32)t_pTag->kind;
1358// *t_pStream << (qint32)t_pTag->type;
1359// *t_pStream << (qint32)datasize;
1360// *t_pStream << (qint32)t_pTag->next;
1361
1362// *t_pStream << dirpos;
1363
1364 }
1365 return true;
1366 }
1367 }
1368 printf ("Could not find place for directory!\n");
1369 return false;
1370}
1371
1372//============================= write_solution.c =============================
1373
1374bool write_solution(const QString& name, /* Destination file */
1375 std::vector<std::unique_ptr<MNESourceSpace>>& spaces, /* The source spaces */
1376 const QString& mri_file, /* MRI file and data obtained from there */
1377 fiffId mri_id,
1378 const FiffCoordTrans& mri_head_t,
1379 const QString& meas_file, /* MEG file and data obtained from there */
1380 FiffId meas_id,
1381 const FiffCoordTrans& meg_head_t,
1382 QList<FiffChInfo> meg_chs,
1383 int nmeg,
1384 QList<FiffChInfo> eeg_chs,
1385 int neeg,
1386 int fixed_ori, /* Fixed orientation dipoles? */
1387 int coord_frame, /* Coordinate frame employed in the forward calculations */
1388 FiffNamedMatrix& meg_solution,
1389 FiffNamedMatrix& eeg_solution,
1390 FiffNamedMatrix& meg_solution_grad,
1391 FiffNamedMatrix& eeg_solution_grad,
1392 bool bDoGrad)
1393{
1394 // New Stuff
1395 QFile file(name);
1396
1397 QFile fileIn(name);
1398 FiffStream::SPtr t_pStreamIn;
1399
1400 int nvert;
1401 int k;
1402
1403 //
1404 // Open the file, create directory
1405 //
1406
1407 // Create the file and save the essentials
1408 FiffStream::SPtr t_pStream = FiffStream::start_file(file);
1409
1410 t_pStream->start_block(FIFFB_MNE);
1411
1412 /*
1413 * Information from the MRI file
1414 */
1415 {
1416 t_pStream->start_block(FIFFB_MNE_PARENT_MRI_FILE);
1417
1418 t_pStream->write_string(FIFF_MNE_FILE_NAME, mri_file);
1419 if (mri_id != Q_NULLPTR)
1420 write_id_old(t_pStream, FIFF_PARENT_FILE_ID, mri_id);//t_pStream->write_id(FIFF_PARENT_FILE_ID, mri_id);
1421 write_coord_trans_old(t_pStream, mri_head_t);//t_pStream->write_coord_trans(mri_head_t);
1422
1423 t_pStream->end_block(FIFFB_MNE_PARENT_MRI_FILE);
1424 }
1425
1426 /*
1427 * Information from the MEG file
1428 */
1429 {
1430 QStringList file_bads;
1431
1432 t_pStream->start_block(FIFFB_MNE_PARENT_MEAS_FILE);
1433
1434 t_pStream->write_string(FIFF_MNE_FILE_NAME, meas_file);
1435 if (!meas_id.isEmpty()) {
1436 t_pStream->write_id(FIFF_PARENT_BLOCK_ID, meas_id);
1437 }
1438 write_coord_trans_old(t_pStream, meg_head_t);//t_pStream->write_coord_trans(meg_head_t);
1439
1440 int nchan = nmeg+neeg;
1441 t_pStream->write_int(FIFF_NCHAN,&nchan);
1442
1443 int k, p;
1444 for (k = 0, p = 0; k < nmeg; k++) {
1445 meg_chs[k].scanNo = ++p;
1446 t_pStream->write_ch_info(meg_chs[k]);
1447 }
1448
1449 for (k = 0; k < neeg; k++) {
1450 eeg_chs[k].scanNo = ++p;
1451 if (k == 0) fprintf(stderr, "[write_solution] EEG[0] scanNo=%d, p=%d, nmeg=%d, neeg=%d\n", eeg_chs[k].scanNo, p, nmeg, neeg);
1452 t_pStream->write_ch_info(eeg_chs[k]);
1453 }
1454 fprintf(stderr, "[write_solution] after loops: nmeg=%d, neeg=%d, p=%d, meg_chs.size=%lld, eeg_chs.size=%lld\n", nmeg, neeg, p, (long long)meg_chs.size(), (long long)eeg_chs.size());
1455 /*
1456 * Copy the bad channel list from the measurement file
1457 */
1458
1459 //
1460 // mne_read_bad_channel_list replacement
1461 //
1462 QFile fileBad(meas_file);
1463 FiffStream::SPtr t_pStreamBads(new FiffStream(&fileBad));
1464 if(!t_pStreamBads->open())
1465 return false;
1466 file_bads = t_pStreamBads->read_bad_channels(t_pStreamBads->dirtree());
1467
1468 //
1469 // mne_write_bad_channel_list replacement
1470 //
1471 mne_write_bad_channel_list_new(t_pStream,file_bads);
1472
1473 t_pStream->end_block(FIFFB_MNE_PARENT_MEAS_FILE);
1474 }
1475
1476 /*
1477 * Write the source spaces (again)
1478 */
1479 for (k = 0, nvert = 0; k < static_cast<int>(spaces.size()); k++) {
1480 if (mne_write_one_source_space(t_pStream,spaces[k].get(),FALSE) == FIFF_FAIL)
1481 goto bad;
1482 nvert += spaces[k]->nuse;
1483 }
1484
1485 /*
1486 * MEG forward solution
1487 */
1488 if (nmeg > 0) {
1489 t_pStream->start_block(FIFFB_MNE_FORWARD_SOLUTION);
1490
1491 int val = FIFFV_MNE_MEG;
1492 t_pStream->write_int(FIFF_MNE_INCLUDED_METHODS,&val);
1493 t_pStream->write_int(FIFF_MNE_COORD_FRAME,&coord_frame);
1494 val = fixed_ori ? FIFFV_MNE_FIXED_ORI : FIFFV_MNE_FREE_ORI;
1495 t_pStream->write_int(FIFF_MNE_SOURCE_ORIENTATION,&val);
1496 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NPOINTS,&nvert);
1497 t_pStream->write_int(FIFF_NCHAN,&nmeg);
1498
1499 meg_solution.transpose_named_matrix();
1500 t_pStream->write_named_matrix(FIFF_MNE_FORWARD_SOLUTION,meg_solution);
1501 meg_solution.transpose_named_matrix();
1502// if (mne_write_named_matrix(t_pStream,FIFF_MNE_FORWARD_SOLUTION,meg_solution) == FIFF_FAIL)
1503// goto bad;
1504 if (bDoGrad) {
1505 meg_solution_grad.transpose_named_matrix();
1506 t_pStream->write_named_matrix(FIFF_MNE_FORWARD_SOLUTION_GRAD,meg_solution_grad);
1507 meg_solution_grad.transpose_named_matrix();
1508 }
1509
1510// if (mne_write_named_matrix(t_pStream,FIFF_MNE_FORWARD_SOLUTION_GRAD,meg_solution_grad) == FIFF_FAIL)
1511// goto bad;
1512 t_pStream->end_block(FIFFB_MNE_FORWARD_SOLUTION);
1513 }
1514 /*
1515 * EEG forward solution
1516 */
1517 if (neeg > 0) {
1518 t_pStream->start_block(FIFFB_MNE_FORWARD_SOLUTION);
1519
1520 int val = FIFFV_MNE_EEG;
1521 t_pStream->write_int(FIFF_MNE_INCLUDED_METHODS,&val);
1522 t_pStream->write_int(FIFF_MNE_COORD_FRAME,&coord_frame);
1523 val = fixed_ori ? FIFFV_MNE_FIXED_ORI : FIFFV_MNE_FREE_ORI;
1524 t_pStream->write_int(FIFF_MNE_SOURCE_ORIENTATION,&val);
1525 t_pStream->write_int(FIFF_NCHAN,&neeg);
1526 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NPOINTS,&nvert);
1527
1528 eeg_solution.transpose_named_matrix();
1529 t_pStream->write_named_matrix(FIFF_MNE_FORWARD_SOLUTION,eeg_solution);
1530// if (mne_write_named_matrix(t_pStream,FIFF_MNE_FORWARD_SOLUTION,eeg_solution) == FIFF_FAIL)
1531 eeg_solution.transpose_named_matrix();
1532// goto bad;
1533 if (bDoGrad) {
1534 eeg_solution_grad.transpose_named_matrix();
1535 t_pStream->write_named_matrix(FIFF_MNE_FORWARD_SOLUTION_GRAD,eeg_solution_grad);
1536 eeg_solution_grad.transpose_named_matrix();
1537 }
1538// if (mne_write_named_matrix(t_pStream,FIFF_MNE_FORWARD_SOLUTION_GRAD,eeg_solution_grad) == FIFF_FAIL)
1539// goto bad;
1540
1541 t_pStream->end_block(FIFFB_MNE_FORWARD_SOLUTION);
1542 }
1543
1544 t_pStream->end_block(FIFFB_MNE);
1545 t_pStream->end_file();
1546 t_pStream->close();
1547 t_pStream.clear();
1548
1549 /*
1550 * Add directory
1551 */
1552 t_pStreamIn = FiffStream::open_update(fileIn);
1553
1554 if (!fiff_put_dir(t_pStreamIn,t_pStreamIn->dir()))
1555 goto bad;
1556 if(t_pStreamIn)
1557 t_pStreamIn->close();
1558
1559 return true;
1560
1561bad : {
1562 if(t_pStream)
1563 t_pStream->close();
1564 if(t_pStreamIn)
1565 t_pStreamIn->close();
1566 return false;
1567 }
1568}
1569
1570/*
1571 * Process the environment information
1572 */
1573
1574bool mne_attach_env(const QString& name, const QString& command)
1575/*
1576 * Add the environment info for future reference
1577 */
1578{
1579 int insert_blocks[] = { FIFFB_MNE , FIFFB_MEAS, FIFFB_MRI, FIFFB_BEM, -1 };
1580 QString cwd = QDir::currentPath();
1581
1582 int b,k, insert;
1583 FiffTag::SPtr t_pTag;
1584// QList<FiffTag::SPtr> tags;
1585 QFile fileInOut(name);
1586 FiffStream::SPtr t_pStreamInOut;
1587
1588// if (fiff_new_file_id(&id) == FIFF_FAIL)
1589// return false;
1591
1592//#ifdef DEBUG
1593// printf("\n");
1594// printf("cwd = %s\n",cwd);
1595// printf("com = %s\n",command);
1596// printf("envid = %s\n",mne_format_file_id(&id));
1597//#endif
1598
1599 if (!fileInOut.exists()) {
1600 qCritical("File %s does not exist. Cannot attach env info.",name.toUtf8().constData());
1601 return false;
1602 }
1603// if (!fileInOut.isWritable()) {
1604// qCritical("File %s is not writable. Cannot attach env info.",name.toUtf8().constData());
1605// return false;
1606// }
1607 /*
1608 * Open the file to modify
1609 */
1610 if (!(t_pStreamInOut = FiffStream::open_update(fileInOut)))
1611 return false;
1612 /*
1613 * Find an appropriate position to insert
1614 */
1615 for (insert = -1, b = 0; insert_blocks[b] >= 0; b++) {
1616 for (k = 0; k < t_pStreamInOut->nent(); k++) {
1617 if (t_pStreamInOut->dir()[k]->kind == FIFF_BLOCK_START) {
1618 if (!t_pStreamInOut->read_tag(t_pTag, t_pStreamInOut->dir()[k]->pos))
1619 return false;
1620 if (*(t_pTag->toInt()) == insert_blocks[b]) {
1621 insert = k;
1622 break;
1623 }
1624 }
1625 }
1626 if (insert >= 0)
1627 break;
1628 }
1629 if (insert < 0) {
1630 qCritical("Suitable place for environment insertion not found.");
1631 return false;
1632 }
1633
1634 /*
1635 * Do not build the list of tags to insert -> Do insertion right away
1636 */
1637
1638 // Modified of fiff_insert_after
1639 int where = insert;
1640 /*
1641 * Insert new tags into a file
1642 * The directory information in dest is updated
1643 */
1644 if (where < 0 || where >= t_pStreamInOut->nent()-1) {
1645 qCritical("illegal insertion point in fiff_insert_after!");
1646 return false;
1647 }
1648
1649 FiffTag::SPtr t_pTagNext;
1650 QList<FiffDirEntry::SPtr> old_dir = t_pStreamInOut->dir();
1651 QList<FiffDirEntry::SPtr> this_ent = old_dir.mid(where);//this_ent = old_dir + where;
1652
1653 if (!t_pStreamInOut->read_tag(t_pTagNext, this_ent[0]->pos))
1654 return false;
1655 /*
1656 * Update next info to be sequential
1657 */
1658 qint64 next_tmp = t_pStreamInOut->device()->pos();
1659 /*
1660 * Go to the end of the file
1661 */
1662 t_pStreamInOut->device()->seek(fileInOut.size());//SEEK_END
1663 /*
1664 * Allocate new directory
1665 * Copy the beginning of old directory
1666 */
1667 QList<FiffDirEntry::SPtr> new_dir = old_dir.mid(0,where+1);
1668
1669 /*
1670 * Save the old size for future purposes
1671 */
1672 qint64 old_end = t_pStreamInOut->device()->pos();
1673 /*
1674 * Write tags, check for errors
1675 */
1676
1677 //Don't use the for loop here instead do it explicitly for specific tags
1678 FiffDirEntry::SPtr new_this;
1679
1680 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
1681 new_this->kind = FIFF_BLOCK_START;
1682 new_this->type = FIFFT_INT;
1683 new_this->size = 1 * 4;
1684 new_this->pos = t_pStreamInOut->start_block(FIFFB_MNE_ENV);
1685 new_dir.append(new_this);
1686
1687 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
1688 new_this->kind = FIFF_BLOCK_ID;
1689 new_this->type = FIFFT_ID_STRUCT;
1690 new_this->size = 5 * 4;
1691 new_this->pos = t_pStreamInOut->write_id(FIFF_BLOCK_ID,id);
1692 new_dir.append(new_this);
1693
1694 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
1695 new_this->kind = FIFF_MNE_ENV_WORKING_DIR;
1696 new_this->type = FIFFT_STRING;
1697 new_this->size = cwd.size();
1698 new_this->pos = t_pStreamInOut->write_string(FIFF_MNE_ENV_WORKING_DIR,cwd);
1699 new_dir.append(new_this);
1700
1701 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
1702 new_this->kind = FIFF_MNE_ENV_COMMAND_LINE;
1703 new_this->type = FIFFT_STRING;
1704 new_this->size = command.size();
1705 new_this->pos = t_pStreamInOut->write_string(FIFF_MNE_ENV_COMMAND_LINE,command);
1706 new_dir.append(new_this);
1707
1708 new_this = FiffDirEntry::SPtr(new FiffDirEntry);
1709 new_this->kind = FIFF_BLOCK_END;
1710 new_this->type = FIFFT_INT;
1711 new_this->size = 1 * 4;
1712
1713 new_this->pos = t_pStreamInOut->end_block(FIFFB_MNE_ENV,next_tmp);
1714 new_dir.append(new_this);
1715
1716 /*
1717 * Copy the rest of the old directory
1718 */
1719 new_dir.append(old_dir.mid(where+1));
1720 /*
1721 * Now, it is time to update the braching tag
1722 * If something goes wrong here, we cannot be sure that
1723 * the file is readable. Let's hope for the best...
1724 */
1725 t_pTagNext->next = (qint32)old_end;//2GB cut of
1726 t_pStreamInOut->write_tag(t_pTagNext,this_ent[0]->pos);
1727
1728 /*
1729 * Update
1730 */
1731 t_pStreamInOut->dir() = new_dir;
1732
1733 // Finished fiff_insert_after
1734
1735 return true;
1736}
1737
1738//=============================================================================================================
1739// STATIC DEFINITIONS
1740//=============================================================================================================
1741
1742//=============================================================================================================
1743// DEFINE MEMBER METHODS
1744//=============================================================================================================
1745
1747 : sol(new FiffNamedMatrix)
1753 , m_pSettings(pSettings)
1754{
1755 initFwd();
1756}
1757
1758//=============================================================================================================
1759
1761{
1762 //ToDo Garbage collection
1763 if(m_megcoils)
1764 delete m_megcoils;
1765 if(m_eegels)
1766 delete m_eegels;
1767 if(m_eegModel)
1768 delete m_eegModel;
1769}
1770
1771//=============================================================================================================
1772
1773void ComputeFwd::initFwd()
1774{
1775 // TODO: This only temporary until we have the fwd dlibrary refactored. This is only done in order to provide easy testing in test_forward_solution.
1776 m_spaces.clear();
1777 m_iNSource = 0;
1778
1779 m_mri_head_t = FiffCoordTrans();
1780 m_meg_head_t = FiffCoordTrans();
1781
1782 m_listMegChs = QList<FiffChInfo>();
1783 m_listEegChs = QList<FiffChInfo>();
1784 m_listCompChs = QList<FiffChInfo>();
1785
1786 int iNMeg = 0;
1787 int iNEeg = 0;
1788 int iNComp = 0;
1789
1790 m_templates = Q_NULLPTR;
1791 m_megcoils = Q_NULLPTR;
1792 m_compcoils = Q_NULLPTR;
1793 m_eegels = Q_NULLPTR;
1794 m_eegModels = Q_NULLPTR;
1795 m_iNChan = 0;
1796
1797 int k;
1798 m_mri_id = Q_NULLPTR;
1799 m_meas_id.clear();
1800
1801 QFile filteredFile;
1802 QTextStream *filteredStream = Q_NULLPTR;
1803
1804 m_eegModel = Q_NULLPTR;
1805 m_bemModel = Q_NULLPTR;
1806
1807 // Report the setup
1808
1809 // printf("\n");
1810 // mne_print_version_info(stderr,argv[0],PROGRAM_VERSION,__DATE__,__TIME__);
1811 printf("\n");
1812 printf("Source space : %s\n",m_pSettings->srcname.toUtf8().constData());
1813 if (!(m_pSettings->transname.isEmpty()) || !(m_pSettings->mriname.isEmpty())) {
1814 printf("MRI -> head transform source : %s\n",!(m_pSettings->mriname.isEmpty()) ? m_pSettings->mriname.toUtf8().constData() : m_pSettings->transname.toUtf8().constData());
1815 } else {
1816 printf("MRI and head coordinates are assumed to be identical.\n");
1817 }
1818 printf("Measurement data : %s\n",m_pSettings->measname.toUtf8().constData());
1819 if (!m_pSettings->bemname.isEmpty()) {
1820 printf("BEM model : %s\n",m_pSettings->bemname.toUtf8().constData());
1821 } else {
1822 printf("Sphere model : origin at (% 7.2f % 7.2f % 7.2f) mm\n",
1823 1000.0f*m_pSettings->r0[X_41],1000.0f*m_pSettings->r0[Y_41],1000.0f*m_pSettings->r0[Z_41]);
1824 if (m_pSettings->include_eeg) {
1825 printf("\n");
1826
1827 if (m_pSettings->eeg_model_file.isEmpty()) {
1828 qCritical("!!!!!!!!!!TODO: default_eeg_model_file();");
1829 // m_pSettings->eeg_model_file = default_eeg_model_file();
1830 }
1831 m_eegModels = FwdEegSphereModelSet::fwd_load_eeg_sphere_models(m_pSettings->eeg_model_file,m_eegModels);
1832 m_eegModels->fwd_list_eeg_sphere_models(stderr);
1833
1834 if (m_pSettings->eeg_model_name.isEmpty()) {
1835 m_pSettings->eeg_model_name = QString("Default");
1836 }
1837 if ((m_eegModel = m_eegModels->fwd_select_eeg_sphere_model(m_pSettings->eeg_model_name)) == Q_NULLPTR) {
1838 return;
1839 }
1840
1841 if (!m_eegModel->fwd_setup_eeg_sphere_model(m_pSettings->eeg_sphere_rad,m_pSettings->use_equiv_eeg,3)) {
1842 return;
1843 }
1844
1845 printf("Using EEG sphere model \"%s\" with scalp radius %7.1f mm\n",
1846 m_pSettings->eeg_model_name.toUtf8().constData(),1000*m_pSettings->eeg_sphere_rad);
1847 printf("%s the electrode locations to scalp\n",m_pSettings->scale_eeg_pos ? "Scale" : "Do not scale");
1848
1849 m_eegModel->scale_pos = m_pSettings->scale_eeg_pos;
1850 VEC_COPY_41(m_eegModel->r0,m_pSettings->r0);
1851
1852 printf("\n");
1853 }
1854 }
1855 printf("%s field computations\n",m_pSettings->accurate ? "Accurate" : "Standard");
1856 printf("Do computations in %s coordinates.\n",FiffCoordTrans::frame_name(m_pSettings->coord_frame).toUtf8().constData());
1857 printf("%s source orientations\n",m_pSettings->fixed_ori ? "Fixed" : "Free");
1858 if (m_pSettings->compute_grad) {
1859 printf("Compute derivatives with respect to source location coordinates\n");
1860 }
1861 printf("Destination for the solution : %s\n",m_pSettings->solname.toUtf8().constData());
1862 if (m_pSettings->do_all) {
1863 printf("Calculate solution for all source locations.\n");
1864 }
1865 if (m_pSettings->nlabel > 0) {
1866 printf("Source space will be restricted to sources in %d labels\n",m_pSettings->nlabel);
1867 }
1868
1869 // Read the source locations
1870
1871 printf("\n");
1872 printf("Reading %s...\n",m_pSettings->srcname.toUtf8().constData());
1873 if (MNESourceSpace::read_source_spaces(m_pSettings->srcname,m_spaces) != OK) {
1874 return;
1875 }
1876 for (k = 0, m_iNSource = 0; k < static_cast<int>(m_spaces.size()); k++) {
1877 if (m_pSettings->do_all) {
1878 m_spaces[k]->enable_all_sources();
1879 }
1880 m_iNSource += m_spaces[k]->nuse;
1881 }
1882 if (m_iNSource == 0) {
1883 qCritical("No sources are active in these source spaces. --all option should be used.");
1884 return;
1885 }
1886 printf("Read %d source spaces a total of %d active source locations\n", static_cast<int>(m_spaces.size()),m_iNSource);
1887 if (MNESourceSpace::restrict_sources_to_labels(m_spaces,m_pSettings->labels,m_pSettings->nlabel) == FAIL) {
1888 return;
1889 }
1890
1891 // Read the MRI -> head coordinate transformation
1892 printf("\n");
1893 if (!m_pSettings->mriname.isEmpty()) {
1894 m_mri_head_t = FiffCoordTrans::readMriTransform(m_pSettings->mriname);
1895 if (m_mri_head_t.isEmpty()) {
1896 return;
1897 }
1898 if ((m_mri_id = get_file_id(m_pSettings->mriname)) == Q_NULLPTR) {
1899 qCritical("Couln't read MRI file id (How come?)");
1900 return;
1901 }
1902 }
1903 else if (!m_pSettings->transname.isEmpty()) {
1904 FiffCoordTrans t = FiffCoordTrans::readFShead2mriTransform(m_pSettings->transname.toUtf8().data());
1905 if (t.isEmpty()) {
1906 return;
1907 }
1908 m_mri_head_t = t.inverted();
1909 } else {
1911 }
1912 m_mri_head_t.print();
1913
1914 // Read the channel information and the MEG device -> head coordinate transformation
1915 // replace mne_read_meg_comp_eeg_ch_info_41()
1916
1917 if(!m_pSettings->pFiffInfo) {
1918
1919 QFile measname(m_pSettings->measname);
1921 FiffStream::SPtr pStream(new FiffStream(&measname));
1922 FIFFLIB::FiffInfo fiffInfo;
1923 if(!pStream->open()) {
1924 qCritical() << "Could not open Stream.";
1925 return;
1926 }
1927
1928 //Get Fiff info
1929 if(!pStream->read_meas_info(pStream->dirtree(), fiffInfo, DirNode)){
1930 qCritical() << "Could not find the channel information.";
1931 return;
1932 }
1933 pStream->close();
1934 m_pInfoBase = QSharedPointer<FIFFLIB::FiffInfo>(new FiffInfo(fiffInfo));
1935 } else {
1936 m_pInfoBase = m_pSettings->pFiffInfo;
1937 }
1938 if(!m_pInfoBase) {
1939 qCritical ("ComputeFwd::initFwd(): no FiffInfo");
1940 return;
1941 }
1942 if (mne_read_meg_comp_eeg_ch_info_41(m_pInfoBase,
1943 m_listMegChs,
1944 iNMeg,
1945 m_listCompChs,
1946 iNComp,
1947 m_listEegChs,
1948 iNEeg,
1949 m_meg_head_t,
1950 m_meas_id) != OK) {
1951 return;
1952 }
1953
1954 m_iNChan = iNMeg + iNEeg;
1955
1956 printf("\n");
1957 if (iNMeg > 0) {
1958 printf("Read %3d MEG channels from %s\n",iNMeg,m_pSettings->measname.toUtf8().constData());
1959 }
1960 if (iNComp > 0) {
1961 printf("Read %3d MEG compensation channels from %s\n",iNComp,m_pSettings->measname.toUtf8().constData());
1962 }
1963 if (iNEeg > 0) {
1964 printf("Read %3d EEG channels from %s\n",iNEeg,m_pSettings->measname.toUtf8().constData());
1965 }
1966 if (!m_pSettings->include_meg) {
1967 printf("MEG not requested. MEG channels omitted.\n");
1968 m_listMegChs.clear();
1969 m_listCompChs.clear();
1970 iNMeg = 0;
1971 iNComp = 0;
1972 }
1973 else
1974 m_meg_head_t.print();
1975 if (!m_pSettings->include_eeg) {
1976 printf("EEG not requested. EEG channels omitted.\n");
1977 m_listEegChs.clear();
1978 iNEeg = 0;
1979 } else {
1980 if (mne_check_chinfo(m_listEegChs,iNEeg) != OK) {
1981 return;
1982 }
1983 }
1984
1985 // Create coil descriptions with transformation to head or MRI frame
1986
1987 if (m_pSettings->include_meg) {
1988 qPath = QString(QCoreApplication::applicationDirPath() + "/../resources/general/coilDefinitions/coil_def.dat");
1989 file.setFileName(qPath);
1990 if ( !QCoreApplication::startingUp() ) {
1991 qPath = QCoreApplication::applicationDirPath() + QString("/../resources/general/coilDefinitions/coil_def.dat");
1992 } else if (!file.exists()) {
1993 qPath = "../resources/general/coilDefinitions/coil_def.dat";
1994 }
1995
1996 m_templates = FwdCoilSet::read_coil_defs(qPath);
1997 if (!m_templates) {
1998 return;
1999 }
2000
2001 // Compensation data
2002
2003 m_compData = MNECTFCompDataSet::read(m_pSettings->measname);
2004 if (!m_compData) {
2005 return;
2006 }
2007 // Compensation channel information may be needed
2008 if (m_compData->ncomp > 0) {
2009 printf("%d compensation data sets in %s\n",m_compData->ncomp,m_pSettings->measname.toUtf8().constData());
2010 } else {
2011 m_listCompChs.clear();
2012 iNComp = 0;
2013
2014 m_compData.reset();
2015 }
2016 }
2017 if (m_pSettings->coord_frame == FIFFV_COORD_MRI) {
2018 FiffCoordTrans head_mri_t = m_mri_head_t.inverted();
2019 FiffCoordTrans meg_mri_t = FiffCoordTrans::combine(FIFFV_COORD_DEVICE,FIFFV_COORD_MRI,m_meg_head_t,head_mri_t);
2020 if (meg_mri_t.isEmpty()) {
2021 return;
2022 }
2023 if ((m_megcoils = m_templates->create_meg_coils(m_listMegChs,
2024 iNMeg,
2025 m_pSettings->accurate ? FWD_COIL_ACCURACY_ACCURATE : FWD_COIL_ACCURACY_NORMAL,
2026 meg_mri_t)) == Q_NULLPTR) {
2027 return;
2028 }
2029 if (iNComp > 0) {
2030 if ((m_compcoils = m_templates->create_meg_coils(m_listCompChs,
2031 iNComp,
2033 meg_mri_t)) == Q_NULLPTR) {
2034 return;
2035 }
2036 }
2037 if ((m_eegels = FwdCoilSet::create_eeg_els(m_listEegChs,
2038 iNEeg,
2039 head_mri_t)) == Q_NULLPTR) {
2040 return;
2041 }
2042
2043 printf("MRI coordinate coil definitions created.\n");
2044 } else {
2045 if ((m_megcoils = m_templates->create_meg_coils(m_listMegChs,
2046 iNMeg,
2047 m_pSettings->accurate ? FWD_COIL_ACCURACY_ACCURATE : FWD_COIL_ACCURACY_NORMAL,
2048 m_meg_head_t)) == Q_NULLPTR) {
2049 return;
2050 }
2051
2052 if (iNComp > 0) {
2053 if ((m_compcoils = m_templates->create_meg_coils(m_listCompChs,
2054 iNComp,
2055 FWD_COIL_ACCURACY_NORMAL,m_meg_head_t)) == Q_NULLPTR) {
2056 return;
2057 }
2058 }
2059 if ((m_eegels = FwdCoilSet::create_eeg_els(m_listEegChs,
2060 iNEeg)) == Q_NULLPTR) {
2061 return;
2062 }
2063 printf("Head coordinate coil definitions created.\n");
2064 }
2065
2066 // Transform the source spaces into the appropriate coordinates
2067 {
2068 if (MNESourceSpace::transform_source_spaces_to(m_pSettings->coord_frame,m_mri_head_t,m_spaces) != OK) {
2069 return;
2070 }
2071 }
2072 printf("Source spaces are now in %s coordinates.\n",FiffCoordTrans::frame_name(m_pSettings->coord_frame).toUtf8().constData());
2073
2074 // Prepare the BEM model if necessary
2075
2076 if (!m_pSettings->bemname.isEmpty()) {
2077 QString bemsolname = FwdBemModel::fwd_bem_make_bem_sol_name(m_pSettings->bemname);
2078 // FREE(bemname);
2079 m_pSettings->bemname = bemsolname;
2080
2081 printf("\nSetting up the BEM model using %s...\n",m_pSettings->bemname.toUtf8().constData());
2082 printf("\nLoading surfaces...\n");
2083 m_bemModel = FwdBemModel::fwd_bem_load_three_layer_surfaces(m_pSettings->bemname);
2084
2085 if (m_bemModel) {
2086 printf("Three-layer model surfaces loaded.\n");
2087 }
2088 else {
2089 m_bemModel = FwdBemModel::fwd_bem_load_homog_surface(m_pSettings->bemname);
2090 if (!m_bemModel) {
2091 return;
2092 }
2093 printf("Homogeneous model surface loaded.\n");
2094 }
2095 if (iNEeg > 0 && m_bemModel->nsurf == 1) {
2096 qCritical("Cannot use a homogeneous model in EEG calculations.");
2097 return;
2098 }
2099 printf("\nLoading the solution matrix...\n");
2100 if (FwdBemModel::fwd_bem_load_recompute_solution(m_pSettings->bemname.toUtf8().data(),FWD_BEM_UNKNOWN,FALSE,m_bemModel) == FAIL) {
2101 return;
2102 }
2103 if (m_pSettings->coord_frame == FIFFV_COORD_HEAD) {
2104 printf("Employing the head->MRI coordinate transform with the BEM model.\n");
2105 if (FwdBemModel::fwd_bem_set_head_mri_t(m_bemModel,m_mri_head_t) == FAIL) {
2106 return;
2107 }
2108 }
2109 printf("BEM model %s is now set up\n",m_bemModel->sol_name.toUtf8().constData());
2110 } else {
2111 printf("Using the sphere model.\n");
2112 }
2113 printf ("\n");
2114
2115 // Try to circumvent numerical problems by excluding points too close our ouside the inner skull surface
2116
2117 if (m_pSettings->filter_spaces) {
2118 if (!m_pSettings->mindistoutname.isEmpty()) {
2119 filteredFile.setFileName(m_pSettings->mindistoutname);
2120 if (!filteredFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
2121 qCritical() << m_pSettings->mindistoutname;
2122 return;
2123 }
2124 filteredStream = new QTextStream(&filteredFile);
2125 printf("Omitted source space points will be output to : %s\n",m_pSettings->mindistoutname.toUtf8().constData());
2126 }
2127 MNESourceSpace::filter_source_spaces(m_pSettings->mindist,
2128 m_pSettings->bemname,
2129 m_mri_head_t,
2130 m_spaces,
2131 filteredStream,m_pSettings->use_threads);
2132 delete filteredStream;
2133 filteredStream = Q_NULLPTR;
2134 }
2135}
2136
2137//=========================================================================================================
2138
2140{
2141 int iNMeg = 0;
2142 int iNEeg = 0;
2143
2144 if(m_megcoils) {
2145 iNMeg = m_megcoils->ncoil;
2146 }
2147 if(m_eegels) {
2148 iNEeg = m_eegels->ncoil;
2149 }
2150 if (!m_bemModel) {
2151 m_pSettings->use_threads = false;
2152 }
2153
2154 // check if source spaces are still in head space
2155 if(m_spaces[0]->coord_frame != FIFFV_COORD_HEAD) {
2156 if (MNESourceSpace::transform_source_spaces_to(m_pSettings->coord_frame,m_mri_head_t,m_spaces) != OK) {
2157 return;
2158 }
2159 }
2160
2161 // Do the actual computation
2162 if (iNMeg > 0) {
2164 m_megcoils,
2165 m_compcoils,
2166 m_compData.get(),
2167 m_pSettings->fixed_ori,
2168 m_bemModel,
2169 &m_pSettings->r0,
2170 m_pSettings->use_threads,
2171 *m_meg_forward.data(),
2172 *m_meg_forward_grad.data(),
2173 m_pSettings->compute_grad)) == FAIL) {
2174 return;
2175 }
2176 }
2177 if (iNEeg > 0) {
2179 m_eegels,
2180 m_pSettings->fixed_ori,
2181 m_bemModel,
2182 m_eegModel,
2183 m_pSettings->use_threads,
2184 *m_eeg_forward.data(),
2185 *m_eeg_forward_grad.data(),
2186 m_pSettings->compute_grad))== FAIL) {
2187 return;
2188 }
2189 }
2190 if(iNMeg > 0 && iNEeg > 0) {
2191 if(m_meg_forward->data.cols() != m_eeg_forward->data.cols()) {
2192 qWarning() << "The MEG and EEG forward solutions do not match";
2193 return;
2194 }
2195 sol->clear();
2196 sol->data = MatrixXd(m_meg_forward->nrow + m_eeg_forward->nrow, m_meg_forward->ncol);
2197 sol->data.block(0,0,m_meg_forward->nrow,m_meg_forward->ncol) = m_meg_forward->data;
2198 sol->data.block(m_meg_forward->nrow,0,m_eeg_forward->nrow,m_eeg_forward->ncol) = m_eeg_forward->data;
2199 sol->nrow = m_meg_forward->nrow + m_eeg_forward->nrow;
2200 sol->row_names.append(m_meg_forward->row_names);
2201 } else if (iNMeg > 0) {
2203 } else {
2205 }
2206
2207 if(m_pSettings->compute_grad) {
2208 if(iNMeg > 0 && iNEeg > 0) {
2209 if(m_meg_forward_grad->data.cols() != m_eeg_forward_grad->data.cols()) {
2210 qWarning() << "The MEG and EEG forward solutions do not match";
2211 return;
2212 }
2213 sol_grad->clear();
2214 sol_grad->data = MatrixXd(m_meg_forward_grad->nrow + m_eeg_forward_grad->nrow, m_meg_forward_grad->ncol);
2215 sol_grad->data.block(0,0,m_meg_forward_grad->nrow,m_meg_forward_grad->ncol) = m_meg_forward_grad->data;
2217 sol_grad->nrow = m_meg_forward_grad->nrow + m_eeg_forward_grad->nrow;
2218 sol_grad->row_names.append(m_meg_forward_grad->row_names);
2219 } else if (iNMeg > 0) {
2221 } else {
2223 }
2224 }
2225}
2226
2227//=========================================================================================================
2228
2230{
2231
2232 int iNMeg = 0;
2233 if(m_megcoils) {
2234 iNMeg = m_megcoils->ncoil;
2235 }
2236
2237 int iNComp = 0;
2238 if(m_compcoils) {
2239 iNComp = m_compcoils->ncoil;
2240 }
2241
2242 // create new coilset with updated head position
2243 if (m_pSettings->coord_frame == FIFFV_COORD_MRI) {
2244 FiffCoordTrans head_mri_t = m_mri_head_t.inverted();
2245 FiffCoordTrans meg_mri_t = FiffCoordTrans::combine(FIFFV_COORD_DEVICE,FIFFV_COORD_MRI,transDevHead,head_mri_t);
2246 if (meg_mri_t.isEmpty()) {
2247 return;
2248 }
2249 if ((m_megcoils = m_templates->create_meg_coils(m_listMegChs,
2250 iNMeg,
2251 m_pSettings->accurate ? FWD_COIL_ACCURACY_ACCURATE : FWD_COIL_ACCURACY_NORMAL,
2252 meg_mri_t)) == Q_NULLPTR) {
2253 return;
2254 }
2255 if (iNComp > 0) {
2256 if ((m_compcoils = m_templates->create_meg_coils(m_listCompChs,
2257 iNComp,
2259 meg_mri_t)) == Q_NULLPTR) {
2260 return;
2261 }
2262 }
2263 } else {
2264 if ((m_megcoils = m_templates->create_meg_coils(m_listMegChs,
2265 iNMeg,
2266 m_pSettings->accurate ? FWD_COIL_ACCURACY_ACCURATE : FWD_COIL_ACCURACY_NORMAL,
2267 transDevHead)) == Q_NULLPTR) {
2268 return;
2269 }
2270
2271 if (iNComp > 0) {
2272 if ((m_compcoils = m_templates->create_meg_coils(m_listCompChs,
2273 iNComp,
2274 FWD_COIL_ACCURACY_NORMAL,transDevHead)) == Q_NULLPTR) {
2275 return;
2276 }
2277 }
2278 }
2279
2280 // check if source spaces are still in head space
2281 if(m_spaces[0]->coord_frame != FIFFV_COORD_HEAD) {
2282 if (MNESourceSpace::transform_source_spaces_to(m_pSettings->coord_frame,m_mri_head_t,m_spaces) != OK) {
2283 return;
2284 }
2285 }
2286
2287 // recompute meg forward
2289 m_megcoils,
2290 m_compcoils,
2291 m_compData.get(), // we might have to update this too
2292 m_pSettings->fixed_ori,
2293 m_bemModel,
2294 &m_pSettings->r0,
2295 m_pSettings->use_threads,
2296 *m_meg_forward.data(),
2297 *m_meg_forward_grad.data(),
2298 m_pSettings->compute_grad)) == FAIL) {
2299 return;
2300 }
2301
2302 // Update new Transformation Matrix
2303 m_meg_head_t = transDevHead;
2304 // update solution
2305 sol->data.block(0,0,m_meg_forward->nrow,m_meg_forward->ncol) = m_meg_forward->data;
2306 if(m_pSettings->compute_grad) {
2307 sol_grad->data.block(0,0,m_meg_forward_grad->nrow,m_meg_forward_grad->ncol) = m_meg_forward_grad->data;
2308 }
2309}
2310
2311//=========================================================================================================
2312
2313void ComputeFwd::storeFwd(const QString& sSolName)
2314{
2315 // We are ready to spill it out
2316 // Transform the source spaces back into MRI coordinates
2317 {
2318 if (MNESourceSpace::transform_source_spaces_to(FIFFV_COORD_MRI,m_mri_head_t,m_spaces) != OK) {
2319 return;
2320 }
2321 }
2322
2323 int iNMeg = m_megcoils->ncoil;
2324 int iNEeg = m_eegels->ncoil;
2325
2326 QString sName;
2327
2328 if(sSolName == "default") {
2329 sName = m_pSettings->solname;
2330 } else {
2331 sName = sSolName;
2332 }
2333
2334 printf("\nwriting %s...",sSolName.toUtf8().constData());
2335
2336 if (!write_solution(sName, /* Destination file */
2337 m_spaces, /* The source spaces */
2338 m_pSettings->mriname,m_mri_id, /* MRI file and data obtained from there */
2339 m_mri_head_t,
2340 m_pSettings->measname,m_meas_id, /* MEG file and data obtained from there */
2341 m_meg_head_t,
2342 m_listMegChs,
2343 iNMeg,
2344 m_listEegChs,
2345 iNEeg,
2346 m_pSettings->fixed_ori, /* Fixed orientation dipoles? */
2347 m_pSettings->coord_frame, /* Coordinate frame */
2348 *m_meg_forward.data(),
2349 *m_eeg_forward.data(),
2350 *m_meg_forward_grad.data(),
2351 *m_eeg_forward_grad.data(),
2352 m_pSettings->compute_grad)) {
2353 return;
2354 }
2355
2356 if (!mne_attach_env(m_pSettings->solname,m_pSettings->command)) {
2357 return;
2358 }
2359 printf("done\n");
2360 printf("\nFinished.\n");
2361}
FIFF class declaration, which provides static wrapper functions to stay consistent with mne matlab to...
#define FIFFB_MNE_ENV
#define FIFF_MNE_SOURCE_SPACE_ID
#define FIFF_MNE_SOURCE_SPACE_DIST_LIMIT
#define FIFF_MNE_SOURCE_SPACE_VOXEL_DIMS
#define FIFF_MNE_COORD_FRAME
#define FIFFV_EEG_CH
#define FIFF_MNE_FORWARD_SOLUTION_GRAD
#define FIFF_OK
#define FIFF_MNE_SOURCE_ORIENTATION
#define FIFF_MNE_SOURCE_SPACE_TYPE
#define FIFFV_MNE_SURF_UNKNOWN
#define FIFF_MNE_SOURCE_SPACE_SELECTION
#define FIFFV_COORD_DEVICE
#define FIFF_MNE_SOURCE_SPACE_USE_TRIANGLES
#define FIFF_MNE_FORWARD_SOLUTION
#define FIFF_MNE_SOURCE_SPACE_NUSE_TRI
#define FIFF_MNE_SOURCE_SPACE_INTERPOLATOR
#define FIFF_MNE_SOURCE_SPACE_NORMALS
#define FIFF_MNE_ROW_NAMES
#define FIFF_MNE_SOURCE_SPACE_NEAREST_DIST
#define FIFF_MNE_SOURCE_SPACE_DIST
#define FIFF_MNE_SOURCE_SPACE_POINTS
#define FIFF_FAIL
#define FIFFV_REF_MEG_CH
#define FIFF_MNE_SOURCE_SPACE_NTRI
#define FIFF_MNE_SOURCE_SPACE_MRI_FILE
#define FIFFV_MEG_CH
#define FIFF_MNE_COL_NAMES
#define FIFF_MNE_ENV_WORKING_DIR
#define FIFF_MNE_INCLUDED_METHODS
#define FIFF_MNE_ENV_COMMAND_LINE
#define FIFFB_MNE_SOURCE_SPACE
#define FIFF_MNE_SOURCE_SPACE_NPOINTS
#define FIFFV_MNE_SPACE_VOLUME
#define FIFFV_COORD_HEAD
#define FIFFV_MNE_FIXED_ORI
#define FIFFV_COORD_MRI
#define FIFF_MNE_CH_NAME_LIST
#define FIFF_MNE_SOURCE_SPACE_TRIANGLES
#define FIFF_MNE_NCOL
#define FIFFB_MNE_FORWARD_SOLUTION
#define FIFFB_MNE_PARENT_MEAS_FILE
#define FIFFV_MNE_SPACE_UNKNOWN
#define FIFFV_MNE_MEG
#define FIFF_MNE_SOURCE_SPACE_NUSE
#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_SOURCE_SPACE_NEAREST
#define FIFFV_MNE_EEG
#define FIFFB_MNE_PARENT_MRI_FILE
#define FIFFV_MNE_FREE_ORI
#define FIFF_PARENT_BLOCK_ID
Definition fiff_file.h:333
#define FIFF_NCHAN
Definition fiff_file.h:453
#define FIFFT_ID_STRUCT
Definition fiff_file.h:248
#define FIFFTS_MC_RCS
Definition fiff_file.h:270
#define FIFF_BLOCK_END
Definition fiff_file.h:328
#define FIFF_BLOCK_START
Definition fiff_file.h:327
#define FIFFT_INT
Definition fiff_file.h:231
#define FIFF_DIR_POINTER
Definition fiff_file.h:324
#define FIFFB_MEAS
Definition fiff_file.h:362
#define FIFF_MRI_DEPTH
Definition fiff_file.h:657
#define FIFFB_BEM
Definition fiff_file.h:403
#define FIFF_MRI_HEIGHT
Definition fiff_file.h:655
#define FIFF_BLOCK_ID
Definition fiff_file.h:326
#define FIFFTS_MC_CCS
Definition fiff_file.h:269
#define FIFF_COORD_TRANS
Definition fiff_file.h:475
#define FIFFT_RCS_MATRIX
Definition fiff_file.h:274
#define FIFFT_FLOAT
Definition fiff_file.h:232
#define FIFFT_STRING
Definition fiff_file.h:238
#define FIFF_SUBJ_HIS_ID
Definition fiff_file.h:573
#define FIFFT_CCS_MATRIX
Definition fiff_file.h:273
#define FIFFB_MRI
Definition fiff_file.h:390
#define FIFF_PARENT_FILE_ID
Definition fiff_file.h:332
#define FIFFT_COORD_TRANS_STRUCT
Definition fiff_file.h:252
#define FIFF_MRI_WIDTH
Definition fiff_file.h:653
Old fiff_type declarations - replace them.
FiffSparseMatrix class declaration.
FiffCoordTrans class declaration.
MNECTFCompDataSet class declaration.
MNEForwardSolution class declaration, which provides the forward solution including the source space ...
MNENamedMatrix class declaration.
MNENearest class declaration.
MNESourceSpace class declaration.
#define FIFF_MNE_SOURCE_SPACE_NEIGHBORS
#define FIFF_MNE_SOURCE_SPACE_NNEIGHBORS
FwdEegSphereModelSet class declaration.
FwdCompData class declaration.
Compute Forward Setting class declaration.
int mne_write_named_matrix(FiffStream::SPtr &t_pStream, int kind, MNENamedMatrix *mat)
#define FREE_41(x)
void fiff_write_float_matrix_old(FiffStream::SPtr &t_pStream, int kind, fiff_float_t **data, int rows, int cols)
void write_id_old(FiffStream::SPtr &t_pStream, fiff_int_t kind, fiffId id)
#define Z_41
void mne_write_bad_channel_list_new(FiffStream::SPtr &t_pStream, const QStringList &t_badList)
bool mne_attach_env(const QString &name, const QString &command)
int ** mne_imatrix_41(int nr, int nc)
QString mne_name_list_to_string_41(const QStringList &list)
#define FREE_ICMATRIX_41(m)
void fiff_write_int_matrix_old(FiffStream::SPtr &t_pStream, int kind, fiff_int_t **data, int rows, int cols)
int mne_write_one_source_space(FiffStream::SPtr &t_pStream, MNESourceSpace *ss, bool selected_only)
FiffSparseMatrix * mne_pick_lower_triangle_rcs(FiffSparseMatrix *mat)
#define X_41
void mne_free_cmatrix_41(float **m)
#define MALLOC_41(x, t)
void write_coord_trans_old(FiffStream::SPtr &t_pStream, const FiffCoordTrans &trans)
int fiff_write_float_sparse_matrix_old(FiffStream::SPtr &t_pStream, int kind, FiffSparseMatrix *mat)
#define ALLOC_CMATRIX_41(x, y)
bool write_solution(const QString &name, std::vector< std::unique_ptr< MNESourceSpace > > &spaces, const QString &mri_file, fiffId mri_id, const FiffCoordTrans &mri_head_t, const QString &meas_file, FiffId meas_id, const FiffCoordTrans &meg_head_t, QList< FiffChInfo > meg_chs, int nmeg, QList< FiffChInfo > eeg_chs, int neeg, int fixed_ori, int coord_frame, FiffNamedMatrix &meg_solution, FiffNamedMatrix &eeg_solution, FiffNamedMatrix &meg_solution_grad, FiffNamedMatrix &eeg_solution_grad, bool bDoGrad)
int mne_check_chinfo(const QList< FiffChInfo > &chs, int nch)
#define FALSE
bool fiff_put_dir(FiffStream::SPtr &t_pStream, const QList< FiffDirEntry::SPtr > &dir)
#define OK
#define FAIL
#define Y_41
FiffSparseMatrix * mne_create_sparse_rcs(int nrow, int ncol, int *nnz, int **colindex, float **vals)
fiffId get_file_id(const QString &name)
#define VEC_COPY_41(to, from)
#define ALLOC_ICMATRIX_41(x, y)
void write_coord_trans(FiffStream::SPtr &t_pStream, const FiffCoordTrans &trans)
void mne_free_icmatrix_41(int **m)
#define FREE_CMATRIX_41(m)
float ** mne_cmatrix_41(int nr, int nc)
#define FWD_COIL_ACCURACY_ACCURATE
Definition fwd_coil.h:71
#define FWD_COIL_ACCURACY_NORMAL
Definition fwd_coil.h:70
FwdCoilSet class declaration.
FwdBemModel class declaration.
#define FWD_BEM_UNKNOWN
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
qint32 fiff_int_t
Definition fiff_types.h:89
FiffId * fiffId
Backward-compatible pointer typedef for the old fiffId pointer.
Definition fiff_types.h:130
float fiff_float_t
Definition fiff_types.h:93
FiffId fiffIdRec
Backward-compatible typedef for the old fiffIdRec struct.
Definition fiff_types.h:126
Forward modelling (BEM, MEG/EEG lead fields).
Definition compute_fwd.h:95
const QString name
Channel info descriptor.
Coordinate transformation description.
FiffCoordTrans inverted() const
Directory entry description.
QSharedPointer< FiffDirEntry > SPtr
QSharedPointer< FiffDirNode > SPtr
Universally unique identifier.
Definition fiff_id.h:67
fiff_int_t machid[2]
Definition fiff_id.h:167
bool isEmpty() const
Definition fiff_id.h:176
FiffTime time
Definition fiff_id.h:168
static FiffId new_file_id()
Definition fiff_id.cpp:85
fiff_int_t version
Definition fiff_id.h:166
QSharedPointer< FiffInfoBase > SPtr
FIFF sparse matrix storage.
FIFF File I/O routines.
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
static FiffStream::SPtr open_update(QIODevice &p_IODevice)
QSharedPointer< FiffStream > SPtr
QSharedPointer< FiffTag > SPtr
Definition fiff_tag.h:155
QSharedDataPointer< FIFFLIB::FiffNamedMatrix > m_eeg_forward
QSharedDataPointer< FIFFLIB::FiffNamedMatrix > sol
void storeFwd(const QString &sSolName="default")
QSharedDataPointer< FIFFLIB::FiffNamedMatrix > m_meg_forward_grad
QSharedDataPointer< FIFFLIB::FiffNamedMatrix > m_meg_forward
QSharedDataPointer< FIFFLIB::FiffNamedMatrix > sol_grad
QSharedDataPointer< FIFFLIB::FiffNamedMatrix > m_eeg_forward_grad
void updateHeadPos(const FIFFLIB::FiffCoordTrans &transDevHead)
ComputeFwd(ComputeFwdSettings::SPtr pSettings)
QSharedPointer< ComputeFwdSettings > SPtr
static int compute_forward_eeg(std::vector< std::unique_ptr< MNELIB::MNESourceSpace > > &spaces, FwdCoilSet *els, bool fixed_ori, FwdBemModel *bem_model, FwdEegSphereModel *m, bool use_threads, FIFFLIB::FiffNamedMatrix &resp, FIFFLIB::FiffNamedMatrix &resp_grad, bool bDoGrad)
static FwdBemModel * fwd_bem_load_homog_surface(const QString &name)
static int fwd_bem_set_head_mri_t(FwdBemModel *m, const FIFFLIB::FiffCoordTrans &t)
static QString fwd_bem_make_bem_sol_name(const QString &name)
static int fwd_bem_load_recompute_solution(const QString &name, int bem_method, int force_recompute, FwdBemModel *m)
static int compute_forward_meg(std::vector< std::unique_ptr< MNELIB::MNESourceSpace > > &spaces, FwdCoilSet *coils, FwdCoilSet *comp_coils, MNELIB::MNECTFCompDataSet *comp_data, bool fixed_ori, FwdBemModel *bem_model, Eigen::Vector3f *r0, bool use_threads, FIFFLIB::FiffNamedMatrix &resp, FIFFLIB::FiffNamedMatrix &resp_grad, bool bDoGRad)
static FwdBemModel * fwd_bem_load_three_layer_surfaces(const QString &name)
static FwdCoilSet * create_eeg_els(const QList< FIFFLIB::FiffChInfo > &chs, int nch, const FIFFLIB::FiffCoordTrans &t=FIFFLIB::FiffCoordTrans())
static FwdCoilSet * read_coil_defs(const QString &name)
static FwdEegSphereModelSet * fwd_load_eeg_sphere_models(const QString &p_sFileName, FwdEegSphereModelSet *now)
static std::unique_ptr< MNECTFCompDataSet > read(const QString &name)
A dense matrix with named rows and columns.
This is used in the patch definitions.
Definition mne_nearest.h:78
This defines a source space.
static int restrict_sources_to_labels(std::vector< std::unique_ptr< MNESourceSpace > > &spaces, const QStringList &labels, int nlabel)
static int filter_source_spaces(const MNESurface &surf, float limit, const FIFFLIB::FiffCoordTrans &mri_head_t, std::vector< std::unique_ptr< MNESourceSpace > > &spaces, QTextStream *filtered)
static int read_source_spaces(const QString &name, std::vector< std::unique_ptr< MNESourceSpace > > &spaces)
static int transform_source_spaces_to(int coord_frame, const FIFFLIB::FiffCoordTrans &t, std::vector< std::unique_ptr< MNESourceSpace > > &spaces)
std::vector< Eigen::VectorXi > neighbor_vert
std::optional< FIFFLIB::FiffCoordTrans > MRI_surf_RAS_RAS_t
FIFFLIB::FiffSparseMatrix dist
std::vector< MNENearest > nearest
std::optional< FIFFLIB::FiffSparseMatrix > interpolator
std::optional< FIFFLIB::FiffCoordTrans > MRI_voxel_surf_RAS_t
std::optional< FIFFLIB::FiffCoordTrans > voxel_surf_RAS_t
static FiffCoordTrans combine(int from, int to, const FiffCoordTrans &t1, const FiffCoordTrans &t2)
static FiffCoordTrans identity(int from, int to)
static FiffCoordTrans readMriTransform(const QString &name)
static FiffCoordTrans readFShead2mriTransform(const QString &name)
static QString frame_name(int frame)