7#include "../fwd_coil_set.h"
8#include "../fwd_comp_data.h"
10#include "../fwd_eeg_sphere_model_set.h"
11#include "../fwd_bem_model.h"
26#include <QCoreApplication>
31using namespace FWDLIB;
32using namespace FIFFLIB;
33using namespace MNELIB;
55#define ALLOC_ICMATRIX_41(x,y) mne_imatrix_41((x),(y))
57#define MALLOC_41(x,t) (t *)malloc((x)*sizeof(t))
58#define REALLOC_41(x,y,t) (t *)((x == Q_NULLPTR) ? malloc((y)*sizeof(t)) : realloc((x),(y)*sizeof(t)))
60#define FREE_41(x) if ((char *)(x) != Q_NULLPTR) free((char *)(x))
62#define VEC_COPY_41(to,from) {\
63 (to)[X_41] = (from)[X_41];\
64 (to)[Y_41] = (from)[Y_41];\
65 (to)[Z_41] = (from)[Z_41];\
68#define VEC_DOT_41(x,y) ((x)[X_41]*(y)[X_41] + (x)[Y_41]*(y)[Y_41] + (x)[Z_41]*(y)[Z_41])
70#define VEC_LEN_41(x) sqrt(VEC_DOT_41(x,x))
72#define ALLOC_CMATRIX_41(x,y) mne_cmatrix_41((x),(y))
73#define FREE_CMATRIX_41(m) mne_free_cmatrix_41((m))
74#define FREE_ICMATRIX_41(m) mne_free_icmatrix_41((m))
76static void matrix_error_41(
int kind,
int nr,
int nc)
80 printf(
"Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
82 printf(
"Failed to allocate memory for a %d x %d matrix\n",nr,nc);
84 printf(
"Allocation error for a %d x %d matrix\n",nr,nc);
85 if (
sizeof(
void *) == 4) {
86 printf(
"This is probably because you seem to be using a computer with 32-bit architecture.\n");
87 printf(
"Please consider moving to a 64-bit platform.");
89 printf(
"Cannot continue. Sorry.\n");
93float **mne_cmatrix_41(
int nr,
int nc)
100 m = MALLOC_41(nr,
float *);
101 if (!m) matrix_error_41(1,nr,nc);
102 whole = MALLOC_41(nr*nc,
float);
103 if (!whole) matrix_error_41(2,nr,nc);
110int **mne_imatrix_41(
int nr,
int nc)
116 m = MALLOC_41(nr,
int *);
117 if (!m) matrix_error_41(1,nr,nc);
118 whole = MALLOC_41(nr*nc,
int);
119 if (!whole) matrix_error_41(2,nr,nc);
125void mne_free_cmatrix_41 (
float **m)
133void mne_free_icmatrix_41 (
int **m)
142fiffId get_file_id(
const QString& name)
147 if(!stream->open()) {
153 id->version = stream->id().version;
154 id->machid[0] = stream->id().machid[0];
155 id->machid[1] = stream->id().machid[1];
156 id->time = stream->id().time;
331 QList<FiffChInfo>& listMegCh,
333 QList<FiffChInfo>& listMegComp,
335 QList<FiffChInfo>& listEegCh,
340 int iNumCh = pFiffInfoBase->nchan;
341 for (
int k = 0;
k < iNumCh;
k++) {
342 if (pFiffInfoBase->chs[
k].kind == FIFFV_MEG_CH) {
343 listMegCh.append(pFiffInfoBase->chs[
k]);
346 listMegComp.append(pFiffInfoBase->chs[
k]);
348 }
else if (pFiffInfoBase->chs[
k].kind == FIFFV_EEG_CH) {
349 listEegCh.append(pFiffInfoBase->chs[
k]);
354 if(!m_pSettings->meg_head_t) {
357 *transDevHeadOld = m_pSettings->meg_head_t;
360 qCritical(
"MEG -> head coordinate transformation not found.");
363 id = pFiffInfoBase->meas_id;
367int mne_check_chinfo(
const QList<FiffChInfo>& chs,
377 for (
k = 0;
k < nch;
k++) {
378 if (chs.at(
k).kind == FIFFV_EEG_CH) {
379 if (chs.at(
k).chpos.r0.norm() < close) {
380 qCritical(
"Some EEG channels do not have locations assigned.");
399 srand ( time(Q_NULLPTR) );
400 double rand_1 = (double)(rand() % 100);rand_1 /= 100;
401 double rand_2 = (double)(rand() % 100);rand_2 /= 100;
404 seconds = time (Q_NULLPTR);
408 t_id->
machid[0] = 65536*rand_1;
409 t_id->
machid[1] = 65536*rand_2;
416 fiff_int_t datasize = 5*4;
418 *t_pStream << (qint32)kind;
419 *t_pStream << (qint32)FIFFT_ID_STRUCT;
420 *t_pStream << (qint32)datasize;
421 *t_pStream << (qint32)FIFFV_NEXT_SEQ;
427 data[1] = t_id->
machid[0];
428 data[2] = t_id->
machid[1];
432 for(qint32 i = 0; i < 5; ++i)
433 *t_pStream << data[i];
448 fiff_int_t datasize = 4*2*12 + 4*2;
451 *t_pStream << (qint32)FIFFT_COORD_TRANS_STRUCT;
452 *t_pStream << (qint32)datasize;
453 *t_pStream << (qint32)FIFFV_NEXT_SEQ;
458 *t_pStream << (qint32)trans->
from;
459 *t_pStream << (qint32)trans->to;
465 for (r = 0; r < 3; ++r)
466 for (c = 0; c < 3; ++c)
467 *t_pStream << (
float)trans->rot(r,c);
468 for (r = 0; r < 3; ++r)
469 *t_pStream << (
float)trans->move[r];
474 for (r = 0; r < 3; ++r)
475 for (c = 0; c < 3; ++c)
476 *t_pStream << (
float)trans->invrot(r,c);
477 for (r = 0; r < 3; ++r)
478 *t_pStream << (
float)trans->invmove[r];
481static int **make_file_triangle_list_41(
int **tris,
int ntri)
486 int **res = ALLOC_ICMATRIX_41(ntri,3);
489 for (j = 0; j < ntri; j++)
490 for (
k = 0;
k < 3;
k++)
491 res[j][
k] = tris[j][
k]+1;
495void mne_write_bad_channel_list_new(
FiffStream::SPtr& t_pStream,
const QStringList& t_badList)
498 t_pStream->start_block(FIFFB_MNE_BAD_CHANNELS);
499 t_pStream->write_name_list(FIFF_MNE_CH_NAME_LIST,t_badList);
500 t_pStream->end_block(FIFFB_MNE_BAD_CHANNELS);
544 MatrixXf mat(rows,cols);
546 for (
int i = 0; i < rows; ++i) {
547 for(
int j = 0; j < cols; ++j) {
548 mat(i,j) = data[i][j];
552 t_pStream->write_float_matrix(kind, mat);
618 MatrixXi mat(rows,cols);
620 for (
int i = 0; i < rows; ++i) {
621 for(
int j = 0; j < cols; ++j) {
622 mat(i,j) = data[i][j];
626 t_pStream->write_int_matrix(kind, mat);
691 int datasize,idxsize,ptrsize;
694 datasize = mat->
nz *
sizeof(fiff_float_t);
695 idxsize = mat->
nz *
sizeof(fiff_int_t);
696 if (mat->
coding == FIFFTS_MC_CCS)
697 ptrsize = (mat->
n+1) *
sizeof(fiff_int_t);
698 else if (mat->
coding == FIFFTS_MC_RCS)
699 ptrsize = (mat->
m+1) *
sizeof(fiff_int_t);
701 qCritical(
"Incomprehensible sparse matrix coding");
705 if (datasize <= 0 || idxsize <= 0 || ptrsize <= 0) {
706 qCritical(
"fiff_write_float_ccs_matrix: negative vector size(s) in sparse matrix!\n");
711 if (mat->
coding == FIFFTS_MC_CCS)
712 type = FIFFT_FLOAT | FIFFT_CCS_MATRIX;
713 else if (mat->
coding == FIFFTS_MC_RCS)
714 type = FIFFT_FLOAT | FIFFT_RCS_MATRIX;
716 qCritical(
"Incomprehensible sparse matrix coding");
725 *t_pStream << (qint32)kind;
726 *t_pStream << (qint32)type;
727 *t_pStream << (qint32)(datasize+idxsize+ptrsize+4*
sizeof(fiff_int_t));
728 *t_pStream << (qint32)FIFFV_NEXT_SEQ;
735 for(
k = 0;
k < mat->
nz; ++
k)
736 *t_pStream << mat->
data[
k];
756 for(
k = 0;
k < mat->
nz; ++
k)
757 *t_pStream << mat->
inds[
k];
774 if (mat->
coding == FIFFTS_MC_CCS) {
776 for(
k = 0;
k < mat->
n+1; ++
k)
777 *t_pStream << mat->
ptrs[
k];
793 for(
k = 0;
k < mat->
m+1; ++
k)
794 *t_pStream << mat->
ptrs[
k];
811 *t_pStream << (qint32)mat->
nz;
816 *t_pStream << (qint32)mat->
m;
821 *t_pStream << (qint32)mat->
n;
826 *t_pStream << (qint32)two;
841static int comp_points2(
const void *vp1,
const void *vp2)
847 if (v1->vert > v2->vert)
849 else if (v1->vert == v2->vert)
855void mne_sort_nearest_by_vertex(
MneNearest* points,
int npoint)
858 if (npoint > 1 && points != Q_NULLPTR)
859 qsort(points,npoint,
sizeof(
MneNearest),comp_points2);
872 int j,
k,nz,ptr,size,ind;
873 int stor_type = FIFFTS_MC_RCS;
875 for (j = 0, nz = 0; j < nrow; j++)
879 qCritical(
"No nonzero elements specified.");
882 size = nz*(
sizeof(fiff_float_t) +
sizeof(fiff_int_t)) +
883 (nrow+1)*(
sizeof(fiff_int_t));
886 sparse->
coding = stor_type;
890 sparse->
data = (
float *)malloc(size);
891 sparse->
inds = (
int *)(sparse->
data+nz);
894 for (j = 0, nz = 0; j < nrow; j++) {
896 for (
k = 0;
k < nnz[j];
k++) {
899 ind = sparse->
inds[nz] = colindex[j][
k];
900 if (ind < 0 || ind >= ncol) {
901 qCritical(
"Column index out of range in mne_create_sparse_rcs");
905 sparse->
data[nz] = vals[j][
k];
907 sparse->
data[nz] = 0.0;
910 sparse->
ptrs[j] = ptr;
912 sparse->
ptrs[nrow] = nz;
913 for (j = nrow-1; j >= 0; j--)
914 if (sparse->
ptrs[j] < 0)
915 sparse->
ptrs[j] = sparse->
ptrs[j+1];
930 int *nnz = Q_NULLPTR;
931 int **colindex = Q_NULLPTR;
932 float **vals = Q_NULLPTR;
936 if (mat->
coding != FIFFTS_MC_RCS) {
937 qCritical(
"The input matrix to mne_add_upper_triangle_rcs must be in RCS format");
940 if (mat->
m != mat->
n) {
941 qCritical(
"The input matrix to mne_pick_lower_triangle_rcs must be square");
947 nnz = MALLOC_41(mat->
m,
int);
948 colindex = MALLOC_41(mat->
m,
int *);
949 vals = MALLOC_41(mat->
m,
float *);
950 for (i = 0; i < mat->
m; i++) {
951 nnz[i] = mat->
ptrs[i+1] - mat->
ptrs[i];
953 colindex[i] = MALLOC_41(nnz[i],
int);
954 vals[i] = MALLOC_41(nnz[i],
float);
955 for (j = mat->
ptrs[i],
k = 0; j < mat->
ptrs[i+1]; j++) {
956 if (mat->
inds[j] <= i) {
957 vals[i][
k] = mat->
data[j];
958 colindex[i][
k] = mat->
inds[j];
965 colindex[i] = Q_NULLPTR;
972 res = mne_create_sparse_rcs(mat->
m,mat->
n,nnz,colindex,vals);
975 for (i = 0; i < mat->
m; i++) {
976 FREE_41(colindex[i]);
992 int *nneighbors = Q_NULLPTR;
993 int *neighbors = Q_NULLPTR;
994 int *inuse_map = Q_NULLPTR;
999 if (ss->type != FIFFV_MNE_SPACE_VOLUME)
1001 if (!ss->neighbor_vert || !ss->nneighbor_vert)
1003 if (selected_only) {
1004 inuse_map = MALLOC_41(ss->np,
int);
1005 for (
k = 0,p = 0, ntot = 0;
k < ss->np;
k++) {
1007 ntot += ss->nneighbor_vert[
k];
1013 nneighbors = MALLOC_41(ss->nuse,
int);
1014 neighbors = MALLOC_41(ntot,
int);
1019 for (
k = 0, nvert = 0, ntot = 0;
k < ss->np;
k++) {
1021 neigh = ss->neighbor_vert[
k];
1022 nneigh = ss->nneighbor_vert[
k];
1023 nneighbors[nvert++] = nneigh;
1024 for (p = 0; p < nneigh; p++)
1025 neighbors[ntot++] = neigh[p] < 0 ? -1 : inuse_map[neigh[p]];
1030 for (
k = 0, ntot = 0;
k < ss->np;
k++)
1031 ntot += ss->nneighbor_vert[
k];
1032 nneighbors = MALLOC_41(ss->np,
int);
1033 neighbors = MALLOC_41(ntot,
int);
1035 for (
k = 0, ntot = 0;
k < ss->np;
k++) {
1036 neigh = ss->neighbor_vert[
k];
1037 nneigh = ss->nneighbor_vert[
k];
1038 nneighbors[
k] = nneigh;
1039 for (p = 0; p < nneigh; p++)
1040 neighbors[ntot++] = neigh[p];
1044 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NNEIGHBORS,nneighbors,nvert);
1053 t_pStream->write_int(FIFF_MNE_SOURCE_SPACE_NEIGHBORS,neighbors,ntot);
1065 if (!selected_only) {
1066 if (ss->voxel_surf_RAS_t) {
1067 write_coord_trans_old(t_pStream, ss->voxel_surf_RAS_t);
1078 if (ss->interpolator && !ss->MRI_volume.isEmpty()) {
1079 t_pStream->start_block(FIFFB_MNE_PARENT_MRI_FILE);
1080 if (ss->MRI_surf_RAS_RAS_t)
1081 write_coord_trans_old(t_pStream, ss->MRI_surf_RAS_RAS_t);
1082 if (ss->MRI_voxel_surf_RAS_t)
1083 write_coord_trans_old(t_pStream, ss->MRI_voxel_surf_RAS_t);
1085 if (ss->interpolator)
1087 if (ss->MRI_vol_dims[0] > 0 && ss->MRI_vol_dims[1] > 0 && ss->MRI_vol_dims[2] > 0) {
1088 t_pStream->write_int(FIFF_MRI_WIDTH,&ss->MRI_vol_dims[0]);
1089 t_pStream->write_int(FIFF_MRI_HEIGHT,&ss->MRI_vol_dims[1]);
1090 t_pStream->write_int(FIFF_MRI_DEPTH,&ss->MRI_vol_dims[2]);
1092 t_pStream->end_block(FIFFB_MNE_PARENT_MRI_FILE);
1096 if (ss->interpolator && !ss->MRI_volume.isEmpty()) {
1098 qCritical(
"Cannot write the interpolator for selection yet");
1107 FREE_41(nneighbors);
1115 float **sel = Q_NULLPTR;
1116 int **tris = Q_NULLPTR;
1117 int *nearest = Q_NULLPTR;
1118 float *nearest_dist = Q_NULLPTR;
1122 qCritical(
"No points in the source space being saved");
1126 t_pStream->start_block(FIFFB_MNE_SOURCE_SPACE);
1131 if (ss->type != FIFFV_MNE_SPACE_UNKNOWN)
1133 if (ss->id != FIFFV_MNE_SURF_UNKNOWN)
1135 if (!ss->subject.isEmpty() && ss->subject.size() > 0) {
1136 QString subj(ss->subject);
1142 if (selected_only) {
1143 if (ss->nuse == 0) {
1144 qCritical(
"No vertices in use. Cannot write active-only vertices from this source space");
1147 sel = ALLOC_CMATRIX_41(ss->nuse,3);
1149 for (p = 0, pp = 0; p < ss->np; p++) {
1151 sel[pp][X_41] = ss->rr[p][X_41];
1152 sel[pp][Y_41] = ss->rr[p][Y_41];
1153 sel[pp][Z_41] = ss->rr[p][Z_41];
1159 for (p = 0, pp = 0; p < ss->np; p++) {
1161 sel[pp][X_41] = ss->nn[p][X_41];
1162 sel[pp][Y_41] = ss->nn[p][Y_41];
1163 sel[pp][Z_41] = ss->nn[p][Z_41];
1168 FREE_CMATRIX_41(sel); sel = Q_NULLPTR;
1173 if (ss->nuse_tri > 0) {
1179 tris = make_file_triangle_list(ss->use_itris,ss->nuse_tri);
1181 ss->nuse_tri,3) == FIFF_FAIL)
1187 ss->nuse_tri,3) == FIFF_FAIL)
1189 FREE_ICMATRIX(tris); tris = Q_NULLPTR;
1201 if (ss->nuse > 0 && ss->inuse) {
1218 tris = make_file_triangle_list_41(ss->itris,ss->ntri);
1224 FREE_ICMATRIX_41(tris); tris = Q_NULLPTR;
1226 if (ss->nuse_tri > 0) {
1230 tris = make_file_triangle_list_41(ss->use_itris,ss->nuse_tri);
1236 FREE_ICMATRIX_41(tris); tris = Q_NULLPTR;
1239 nearest = MALLOC_41(ss->np,
int);
1240 nearest_dist = MALLOC_41(ss->np,
float);
1242 mne_sort_nearest_by_vertex(ss->nearest,ss->np);
1243 for (p = 0; p < ss->np; p++) {
1244 nearest[p] = ss->nearest[p].nearest;
1245 nearest_dist[p] = ss->nearest[p].dist;
1266 FREE_41(nearest); nearest = Q_NULLPTR;
1267 FREE_41(nearest_dist); nearest_dist = Q_NULLPTR;
1290 t_pStream->end_block(FIFFB_MNE_SOURCE_SPACE);
1294 FREE_ICMATRIX_41(tris);
1295 FREE_CMATRIX_41(sel);
1297 FREE_41(nearest_dist);
1302QString mne_name_list_to_string_41(
const QStringList& list)
1307 int nlist = list.size();
1309 if (nlist == 0 || list.isEmpty())
1312 for (
int k = 0;
k < nlist-1;
k++) {
1316 res += list[nlist-1];
1329 t_pStream->start_block(FIFFB_MNE_NAMED_MATRIX);
1331 t_pStream->write_int(FIFF_MNE_NROW,&mat->nrow);
1332 t_pStream->write_int(FIFF_MNE_NCOL,&mat->ncol);
1333 if (!mat->rowlist.isEmpty()) {
1334 names = mne_name_list_to_string_41(mat->rowlist);
1335 t_pStream->write_string(FIFF_MNE_ROW_NAMES,names);
1337 if (!mat->collist.isEmpty()) {
1338 names = mne_name_list_to_string_41(mat->collist);
1339 t_pStream->write_string(FIFF_MNE_COL_NAMES,names);
1341 fiff_write_float_matrix_old (t_pStream,kind,mat->data,mat->nrow,mat->ncol);
1343 t_pStream->end_block(FIFFB_MNE_NAMED_MATRIX);
1348bool fiff_put_dir (
FiffStream::SPtr& t_pStream,
const QList<FiffDirEntry::SPtr>& dir)
1353 int nent = dir.size();
1358 for (
k = 0;
k < nent;
k++) {
1359 if (dir[
k]->kind == FIFF_DIR_POINTER) {
1363 if (!t_pStream->read_tag(t_pTag,dir[
k]->pos)) {
1364 fprintf (stderr,
"Could not read FIFF_DIR_POINTER!\n");
1370 dirpos = *t_pTag->toInt();
1376 dirpos = (fiff_int_t)t_pStream->write_dir_entries(dir);
1378 printf (
"Could not update directory!\n");
1380 t_pTag->setNum(dirpos);
1383 t_pStream->write_dir_pointer(dirpos, dir[
k]->pos);
1400 printf (
"Could not find place for directory!\n");
1406bool write_solution(
const QString& name,
1409 const QString& mri_file,
1412 const QString& meas_file,
1415 QList<FiffChInfo> meg_chs,
1417 QList<FiffChInfo> eeg_chs,
1443 t_pStream->start_block(FIFFB_MNE);
1449 t_pStream->start_block(FIFFB_MNE_PARENT_MRI_FILE);
1452 if (mri_id != Q_NULLPTR)
1453 write_id_old(t_pStream, FIFF_PARENT_FILE_ID, mri_id);
1454 write_coord_trans_old(t_pStream, mri_head_t);
1456 t_pStream->end_block(FIFFB_MNE_PARENT_MRI_FILE);
1463 QStringList file_bads;
1465 t_pStream->start_block(FIFFB_MNE_PARENT_MEAS_FILE);
1469 t_pStream->write_id(FIFF_PARENT_BLOCK_ID, meas_id);
1471 write_coord_trans_old(t_pStream, meg_head_t);
1473 int nchan = nmeg+neeg;
1478 for (
k = 0, p = 0;
k < nmeg;
k++) {
1502 t_pStream->write_ch_info(meg_chs[
k]);
1505 for (
k = 0;
k < neeg;
k++) {
1529 t_pStream->write_ch_info(eeg_chs[
k]);
1538 QFile fileBad(meas_file);
1540 if(!t_pStreamBads->open())
1542 file_bads = t_pStreamBads->read_bad_channels(t_pStreamBads->dirtree());
1547 mne_write_bad_channel_list_new(t_pStream,file_bads);
1549 t_pStream->end_block(FIFFB_MNE_PARENT_MEAS_FILE);
1555 for (
k = 0, nvert = 0;
k < nspace;
k++) {
1556 if (mne_write_one_source_space(t_pStream,spaces[
k],FALSE) == FIFF_FAIL)
1558 nvert += spaces[
k]->nuse;
1565 t_pStream->start_block(FIFFB_MNE_FORWARD_SOLUTION);
1567 int val = FIFFV_MNE_MEG;
1568 t_pStream->write_int(FIFF_MNE_INCLUDED_METHODS,&val);
1570 val = fixed_ori ? FIFFV_MNE_FIXED_ORI : FIFFV_MNE_FREE_ORI;
1576 t_pStream->write_named_matrix(FIFF_MNE_FORWARD_SOLUTION,meg_solution);
1582 t_pStream->write_named_matrix(FIFF_MNE_FORWARD_SOLUTION_GRAD,meg_solution_grad);
1588 t_pStream->end_block(FIFFB_MNE_FORWARD_SOLUTION);
1594 t_pStream->start_block(FIFFB_MNE_FORWARD_SOLUTION);
1596 int val = FIFFV_MNE_EEG;
1597 t_pStream->write_int(FIFF_MNE_INCLUDED_METHODS,&val);
1599 val = fixed_ori ? FIFFV_MNE_FIXED_ORI : FIFFV_MNE_FREE_ORI;
1605 t_pStream->write_named_matrix(FIFF_MNE_FORWARD_SOLUTION,eeg_solution);
1611 t_pStream->write_named_matrix(FIFF_MNE_FORWARD_SOLUTION_GRAD,eeg_solution_grad);
1617 t_pStream->end_block(FIFFB_MNE_FORWARD_SOLUTION);
1620 t_pStream->end_block(FIFFB_MNE);
1621 t_pStream->end_file();
1630 if (!fiff_put_dir(t_pStreamIn,t_pStreamIn->dir()))
1633 t_pStreamIn->close();
1641 t_pStreamIn->close();
1650bool mne_attach_env(
const QString& name,
const QString& command)
1656 QString cwd = QDir::currentPath();
1661 QFile fileInOut(name);
1675 if (!fileInOut.exists()) {
1676 qCritical(
"File %s does not exist. Cannot attach env info.",name.toUtf8().constData());
1691 for (insert = -1, b = 0; insert_blocks[b] >= 0; b++) {
1692 for (
k = 0;
k < t_pStreamInOut->nent();
k++) {
1693 if (t_pStreamInOut->dir()[
k]->kind == FIFF_BLOCK_START) {
1694 if (!t_pStreamInOut->read_tag(t_pTag, t_pStreamInOut->dir()[
k]->pos))
1696 if (*(t_pTag->toInt()) == insert_blocks[b]) {
1706 qCritical(
"Suitable place for environment insertion not found.");
1720 if (where < 0 || where >= t_pStreamInOut->nent()-1) {
1721 qCritical(
"illegal insertion point in fiff_insert_after!");
1726 QList<FiffDirEntry::SPtr> old_dir = t_pStreamInOut->dir();
1727 QList<FiffDirEntry::SPtr> this_ent = old_dir.mid(where);
1729 if (!t_pStreamInOut->read_tag(t_pTagNext, this_ent[0]->pos))
1734 qint64 next_tmp = t_pStreamInOut->device()->pos();
1738 t_pStreamInOut->device()->seek(fileInOut.size());
1743 QList<FiffDirEntry::SPtr> new_dir = old_dir.mid(0,where+1);
1748 qint64 old_end = t_pStreamInOut->device()->pos();
1757 new_this->kind = FIFF_BLOCK_START;
1758 new_this->type = FIFFT_INT;
1759 new_this->size = 1 * 4;
1760 new_this->pos = t_pStreamInOut->start_block(FIFFB_MNE_ENV);
1761 new_dir.append(new_this);
1764 new_this->kind = FIFF_BLOCK_ID;
1765 new_this->type = FIFFT_ID_STRUCT;
1766 new_this->size = 5 * 4;
1767 new_this->pos = t_pStreamInOut->write_id(FIFF_BLOCK_ID,
id);
1768 new_dir.append(new_this);
1772 new_this->type = FIFFT_STRING;
1773 new_this->size = cwd.size();
1775 new_dir.append(new_this);
1779 new_this->type = FIFFT_STRING;
1780 new_this->size = command.size();
1782 new_dir.append(new_this);
1785 new_this->kind = FIFF_BLOCK_END;
1786 new_this->type = FIFFT_INT;
1787 new_this->size = 1 * 4;
1789 new_this->pos = t_pStreamInOut->end_block(FIFFB_MNE_ENV,next_tmp);
1790 new_dir.append(new_this);
1795 new_dir.append(old_dir.mid(where+1));
1801 t_pTagNext->next = (qint32)old_end;
1802 t_pStreamInOut->write_tag(t_pTagNext,this_ent[0]->pos);
1807 t_pStreamInOut->dir() = new_dir;
1829 , m_pSettings(pSettings)
1839 for (
int k = 0;
k < m_iNSpace;
k++)
1843 delete m_mri_head_t;
1845 delete m_meg_head_t;
1856void ComputeFwd::initFwd()
1859 m_spaces = Q_NULLPTR;
1863 m_mri_head_t = Q_NULLPTR;
1864 m_meg_head_t = Q_NULLPTR;
1866 m_listMegChs = QList<FiffChInfo>();
1867 m_listEegChs = QList<FiffChInfo>();
1868 m_listCompChs = QList<FiffChInfo>();
1874 m_templates = Q_NULLPTR;
1875 m_megcoils = Q_NULLPTR;
1876 m_compcoils = Q_NULLPTR;
1877 m_compData = Q_NULLPTR;
1878 m_eegels = Q_NULLPTR;
1879 m_eegModels = Q_NULLPTR;
1883 m_mri_id = Q_NULLPTR;
1886 FILE* out = Q_NULLPTR;
1888 m_eegModel = Q_NULLPTR;
1889 m_bemModel = Q_NULLPTR;
1896 printf(
"Source space : %s\n",m_pSettings->srcname.toUtf8().constData());
1897 if (!(m_pSettings->transname.isEmpty()) || !(m_pSettings->mriname.isEmpty())) {
1898 printf(
"MRI -> head transform source : %s\n",!(m_pSettings->mriname.isEmpty()) ? m_pSettings->mriname.toUtf8().constData() : m_pSettings->transname.toUtf8().constData());
1900 printf(
"MRI and head coordinates are assumed to be identical.\n");
1902 printf(
"Measurement data : %s\n",m_pSettings->measname.toUtf8().constData());
1903 if (!m_pSettings->bemname.isEmpty()) {
1904 printf(
"BEM model : %s\n",m_pSettings->bemname.toUtf8().constData());
1906 printf(
"Sphere model : origin at (% 7.2f % 7.2f % 7.2f) mm\n",
1907 1000.0f*m_pSettings->r0[X_41],1000.0f*m_pSettings->r0[Y_41],1000.0f*m_pSettings->r0[Z_41]);
1908 if (m_pSettings->include_eeg) {
1911 if (m_pSettings->eeg_model_file.isEmpty()) {
1912 qCritical(
"!!!!!!!!!!TODO: default_eeg_model_file();");
1918 if (m_pSettings->eeg_model_name.isEmpty()) {
1919 m_pSettings->eeg_model_name = QString(
"Default");
1929 printf(
"Using EEG sphere model \"%s\" with scalp radius %7.1f mm\n",
1930 m_pSettings->eeg_model_name.toUtf8().constData(),1000*m_pSettings->eeg_sphere_rad);
1931 printf(
"%s the electrode locations to scalp\n",m_pSettings->scale_eeg_pos ?
"Scale" :
"Do not scale");
1933 m_eegModel->
scale_pos = m_pSettings->scale_eeg_pos;
1934 VEC_COPY_41(m_eegModel->
r0,m_pSettings->r0);
1939 printf(
"%s field computations\n",m_pSettings->accurate ?
"Accurate" :
"Standard");
1940 printf(
"Do computations in %s coordinates.\n",FiffCoordTransOld::mne_coord_frame_name(m_pSettings->coord_frame));
1941 printf(
"%s source orientations\n",m_pSettings->fixed_ori ?
"Fixed" :
"Free");
1942 if (m_pSettings->compute_grad) {
1943 printf(
"Compute derivatives with respect to source location coordinates\n");
1945 printf(
"Destination for the solution : %s\n",m_pSettings->solname.toUtf8().constData());
1946 if (m_pSettings->do_all) {
1947 printf(
"Calculate solution for all source locations.\n");
1949 if (m_pSettings->nlabel > 0) {
1950 printf(
"Source space will be restricted to sources in %d labels\n",m_pSettings->nlabel);
1956 printf(
"Reading %s...\n",m_pSettings->srcname.toUtf8().constData());
1957 if (MneSurfaceOrVolume::mne_read_source_spaces(m_pSettings->srcname,&m_spaces,&m_iNSpace) != OK) {
1960 for (
k = 0, m_iNSource = 0;
k < m_iNSpace;
k++) {
1961 if (m_pSettings->do_all) {
1962 MneSurfaceOrVolume::enable_all_sources(m_spaces[
k]);
1964 m_iNSource += m_spaces[
k]->nuse;
1966 if (m_iNSource == 0) {
1967 qCritical(
"No sources are active in these source spaces. --all option should be used.");
1970 printf(
"Read %d source spaces a total of %d active source locations\n", m_iNSpace,m_iNSource);
1971 if (MneSurfaceOrVolume::restrict_sources_to_labels(m_spaces,m_iNSpace,m_pSettings->labels,m_pSettings->nlabel) == FAIL) {
1977 if (!m_pSettings->mriname.isEmpty()) {
1978 if ((m_mri_head_t = FiffCoordTransOld::mne_read_mri_transform(m_pSettings->mriname)) == Q_NULLPTR) {
1981 if ((m_mri_id = get_file_id(m_pSettings->mriname)) == Q_NULLPTR) {
1982 qCritical(
"Couln't read MRI file id (How come?)");
1986 else if (!m_pSettings->transname.isEmpty()) {
1988 if ((t = FiffCoordTransOld::mne_read_FShead2mri_transform(m_pSettings->transname.toUtf8().data())) == Q_NULLPTR) {
1991 m_mri_head_t = t->fiff_invert_transform();
1996 m_mri_head_t = FiffCoordTransOld::mne_identity_transform(FIFFV_COORD_MRI,FIFFV_COORD_HEAD);
1998 FiffCoordTransOld::mne_print_coord_transform(stdout,m_mri_head_t);
2003 if(!m_pSettings->pFiffInfo) {
2005 QFile measname(m_pSettings->measname);
2009 if(!pStream->open()) {
2010 qCritical() <<
"Could not open Stream.";
2015 if(!pStream->read_meas_info(pStream->dirtree(), fiffInfo, DirNode)){
2016 qCritical() <<
"Could not find the channel information.";
2020 m_pInfoBase = QSharedPointer<FIFFLIB::FiffInfo>(
new FiffInfo(fiffInfo));
2022 m_pInfoBase = m_pSettings->pFiffInfo;
2025 qCritical (
"ComputeFwd::initFwd(): no FiffInfo");
2028 if (mne_read_meg_comp_eeg_ch_info_41(m_pInfoBase,
2040 m_iNChan = iNMeg + iNEeg;
2044 printf(
"Read %3d MEG channels from %s\n",iNMeg,m_pSettings->measname.toUtf8().constData());
2047 printf(
"Read %3d MEG compensation channels from %s\n",iNComp,m_pSettings->measname.toUtf8().constData());
2050 printf(
"Read %3d EEG channels from %s\n",iNEeg,m_pSettings->measname.toUtf8().constData());
2052 if (!m_pSettings->include_meg) {
2053 printf(
"MEG not requested. MEG channels omitted.\n");
2054 m_listMegChs.clear();
2055 m_listCompChs.clear();
2060 FiffCoordTransOld::mne_print_coord_transform(stdout,m_meg_head_t);
2061 if (!m_pSettings->include_eeg) {
2062 printf(
"EEG not requested. EEG channels omitted.\n");
2063 m_listEegChs.clear();
2066 if (mne_check_chinfo(m_listEegChs,iNEeg) != OK) {
2073 if (m_pSettings->include_meg) {
2074 qPath = QString(QCoreApplication::applicationDirPath() +
"/../resources/general/coilDefinitions/coil_def.dat");
2075 file.setFileName(qPath);
2076 if ( !QCoreApplication::startingUp() ) {
2077 qPath = QCoreApplication::applicationDirPath() + QString(
"/../resources/general/coilDefinitions/coil_def.dat");
2078 }
else if (!file.exists()) {
2079 qPath =
"../resources/general/coilDefinitions/coil_def.dat";
2089 if ((m_compData = MneCTFCompDataSet::mne_read_ctf_comp_data(m_pSettings->measname)) == Q_NULLPTR) {
2093 if (m_compData->ncomp > 0) {
2094 printf(
"%d compensation data sets in %s\n",m_compData->ncomp,m_pSettings->measname.toUtf8().constData());
2096 m_listCompChs.clear();
2102 m_compData = Q_NULLPTR;
2105 if (m_pSettings->coord_frame == FIFFV_COORD_MRI) {
2107 FiffCoordTransOld* meg_mri_t = FiffCoordTransOld::fiff_combine_transforms(FIFFV_COORD_DEVICE,FIFFV_COORD_MRI,m_meg_head_t,head_mri_t);
2108 if (meg_mri_t == Q_NULLPTR) {
2113 m_pSettings->accurate ? FWD_COIL_ACCURACY_ACCURATE : FWD_COIL_ACCURACY_NORMAL,
2114 meg_mri_t)) == Q_NULLPTR) {
2120 FWD_COIL_ACCURACY_NORMAL,
2121 meg_mri_t)) == Q_NULLPTR) {
2127 head_mri_t)) == Q_NULLPTR) {
2131 FREE_41(head_mri_t);
2132 printf(
"MRI coordinate coil definitions created.\n");
2136 m_pSettings->accurate ? FWD_COIL_ACCURACY_ACCURATE : FWD_COIL_ACCURACY_NORMAL,
2137 m_meg_head_t)) == Q_NULLPTR) {
2144 FWD_COIL_ACCURACY_NORMAL,m_meg_head_t)) == Q_NULLPTR) {
2150 Q_NULLPTR)) == Q_NULLPTR) {
2153 printf(
"Head coordinate coil definitions created.\n");
2158 if (MneSurfaceOrVolume::mne_transform_source_spaces_to(m_pSettings->coord_frame,m_mri_head_t,m_spaces,m_iNSpace) != OK) {
2161 printf(
"Source spaces are now in %s coordinates.\n",FiffCoordTransOld::mne_coord_frame_name(m_pSettings->coord_frame));
2165 if (!m_pSettings->bemname.isEmpty()) {
2168 m_pSettings->bemname = bemsolname;
2170 printf(
"\nSetting up the BEM model using %s...\n",m_pSettings->bemname.toUtf8().constData());
2171 printf(
"\nLoading surfaces...\n");
2172 m_bemModel = FwdBemModel::fwd_bem_load_three_layer_surfaces(m_pSettings->bemname);
2175 printf(
"Three-layer model surfaces loaded.\n");
2178 m_bemModel = FwdBemModel::fwd_bem_load_homog_surface(m_pSettings->bemname);
2182 printf(
"Homogeneous model surface loaded.\n");
2184 if (iNEeg > 0 && m_bemModel->nsurf == 1) {
2185 qCritical(
"Cannot use a homogeneous model in EEG calculations.");
2188 printf(
"\nLoading the solution matrix...\n");
2189 if (FwdBemModel::fwd_bem_load_recompute_solution(m_pSettings->bemname.toUtf8().data(),FWD_BEM_UNKNOWN,FALSE,m_bemModel) == FAIL) {
2192 if (m_pSettings->coord_frame == FIFFV_COORD_HEAD) {
2193 printf(
"Employing the head->MRI coordinate transform with the BEM model.\n");
2194 if (FwdBemModel::fwd_bem_set_head_mri_t(m_bemModel,m_mri_head_t) == FAIL) {
2198 printf(
"BEM model %s is now set up\n",m_bemModel->sol_name.toUtf8().constData());
2200 printf(
"Using the sphere model.\n");
2206 if (m_pSettings->filter_spaces) {
2207 if (!m_pSettings->mindistoutname.isEmpty()) {
2208 out = fopen(m_pSettings->mindistoutname.toUtf8().constData(),
"w");
2209 if (out == Q_NULLPTR) {
2210 qCritical() << m_pSettings->mindistoutname;
2213 printf(
"Omitted source space points will be output to : %s\n",m_pSettings->mindistoutname.toUtf8().constData());
2215 MneSurfaceOrVolume::filter_source_spaces(m_pSettings->mindist,
2216 m_pSettings->bemname.toUtf8().data(),
2219 m_iNSpace,out,m_pSettings->use_threads);
2220 if(out != Q_NULLPTR)
2233 iNMeg = m_megcoils->ncoil;
2236 iNEeg = m_eegels->ncoil;
2239 m_pSettings->use_threads =
false;
2243 if(m_spaces[0]->coord_frame != FIFFV_COORD_HEAD) {
2244 if (MneSurfaceOrVolume::mne_transform_source_spaces_to(m_pSettings->coord_frame,m_mri_head_t,m_spaces,m_iNSpace) != OK) {
2256 m_pSettings->fixed_ori,
2259 m_pSettings->use_threads,
2262 m_pSettings->compute_grad)) == FAIL) {
2270 m_pSettings->fixed_ori,
2273 m_pSettings->use_threads,
2276 m_pSettings->compute_grad))== FAIL) {
2280 if(iNMeg > 0 && iNEeg > 0) {
2282 qWarning() <<
"The MEG and EEG forward solutions do not match";
2291 }
else if (iNMeg > 0) {
2297 if(m_pSettings->compute_grad) {
2298 if(iNMeg > 0 && iNEeg > 0) {
2300 qWarning() <<
"The MEG and EEG forward solutions do not match";
2309 }
else if (iNMeg > 0) {
2324 iNMeg = m_megcoils->ncoil;
2329 iNComp = m_compcoils->ncoil;
2372 if (m_pSettings->coord_frame == FIFFV_COORD_MRI) {
2374 FiffCoordTransOld* meg_mri_t = FiffCoordTransOld::fiff_combine_transforms(FIFFV_COORD_DEVICE,FIFFV_COORD_MRI,transDevHeadOld,head_mri_t);
2375 if (meg_mri_t == Q_NULLPTR) {
2380 m_pSettings->accurate ? FWD_COIL_ACCURACY_ACCURATE : FWD_COIL_ACCURACY_NORMAL,
2381 meg_mri_t)) == Q_NULLPTR) {
2387 FWD_COIL_ACCURACY_NORMAL,
2388 meg_mri_t)) == Q_NULLPTR) {
2395 m_pSettings->accurate ? FWD_COIL_ACCURACY_ACCURATE : FWD_COIL_ACCURACY_NORMAL,
2396 transDevHeadOld)) == Q_NULLPTR) {
2403 FWD_COIL_ACCURACY_NORMAL,transDevHeadOld)) == Q_NULLPTR) {
2410 if(m_spaces[0]->coord_frame != FIFFV_COORD_HEAD) {
2411 if (MneSurfaceOrVolume::mne_transform_source_spaces_to(m_pSettings->coord_frame,m_mri_head_t,m_spaces,m_iNSpace) != OK) {
2422 m_pSettings->fixed_ori,
2425 m_pSettings->use_threads,
2428 m_pSettings->compute_grad)) == FAIL) {
2436 if(m_pSettings->compute_grad) {
2447 if (MneSourceSpaceOld::mne_transform_source_spaces_to(FIFFV_COORD_MRI,m_mri_head_t,m_spaces,m_iNSpace) != OK) {
2451 int iNMeg = m_megcoils->ncoil;
2452 int iNEeg = m_eegels->ncoil;
2456 if(sSolName ==
"default") {
2457 sName = m_pSettings->solname;
2462 printf(
"\nwriting %s...",sSolName.toUtf8().constData());
2464 if (!write_solution(sName,
2467 m_pSettings->mriname,m_mri_id,
2469 m_pSettings->measname,m_meas_id,
2475 m_pSettings->fixed_ori,
2476 m_pSettings->coord_frame,
2481 m_pSettings->compute_grad)) {
2485 if (!mne_attach_env(m_pSettings->solname,m_pSettings->command)) {
2489 printf(
"\nFinished.\n");
FIFF class declaration, which provides static wrapper functions to stay consistent with mne matlab to...
#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 FIFF_MNE_SOURCE_ORIENTATION
#define FIFF_MNE_SOURCE_SPACE_TYPE
#define FIFF_MNE_SOURCE_SPACE_SELECTION
#define FIFF_MNE_SOURCE_SPACE_USE_TRIANGLES
#define FIFF_MNE_SOURCE_SPACE_NUSE_TRI
#define FIFF_MNE_SOURCE_SPACE_INTERPOLATOR
#define FIFF_MNE_SOURCE_SPACE_NORMALS
#define FIFF_MNE_SOURCE_SPACE_NEAREST_DIST
#define FIFF_MNE_SOURCE_SPACE_DIST
#define FIFF_MNE_SOURCE_SPACE_POINTS
#define FIFF_MNE_SOURCE_SPACE_NTRI
#define FIFF_MNE_SOURCE_SPACE_MRI_FILE
#define FIFF_MNE_ENV_WORKING_DIR
#define FIFF_MNE_ENV_COMMAND_LINE
#define FIFF_MNE_SOURCE_SPACE_NPOINTS
#define FIFF_MNE_SOURCE_SPACE_TRIANGLES
#define FIFF_MNE_SOURCE_SPACE_NUSE
#define FIFF_MNE_FILE_NAME
#define FIFF_MNE_SOURCE_SPACE_NEAREST
FiffCoordTransOld class declaration.
FiffSparseMatrix class declaration.
Definitions for describing the objects in a FIFF file.
MNEForwardSolution class declaration, which provides the forward solution including the source space ...
MneCTFCompDataSet class declaration.
MneSourceSpaceOld class declaration.
MNE Named Matrix (MneNamedMatrix) class declaration.
MneNearest class declaration.
Compute Forward Setting class declaration.
Coordinate transformation descriptor.
Data associated with MNE computations for each mneMeasDataSet.
FIFFLIB::fiff_int_t * inds
FIFFLIB::fiff_int_t * ptrs
FIFFLIB::fiff_float_t * data
FIFFLIB::fiff_int_t coding
ToDo Old implementation use new fiff_id.h instead.
Directory entry description.
QSharedPointer< FiffDirEntry > SPtr
QSharedPointer< FiffDirNode > SPtr
Universially unique identifier.
static FiffId new_file_id()
FIFF measurement file information.
QSharedPointer< FiffInfoBase > SPtr
void transpose_named_matrix()
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
static FiffStream::SPtr open_update(QIODevice &p_IODevice)
QSharedPointer< FiffStream > SPtr
QSharedPointer< FiffTag > SPtr
void updateHeadPos(FIFFLIB::FiffCoordTransOld *transDevHeadOld)
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
ComputeFwd(ComputeFwdSettings::SPtr pSettings)
QSharedPointer< ComputeFwdSettings > SPtr
static QString fwd_bem_make_bem_sol_name(const QString &name)
static int compute_forward_meg(MNELIB::MneSourceSpaceOld **spaces, int nspace, 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 int compute_forward_eeg(MNELIB::MneSourceSpaceOld **spaces, int nspace, FwdCoilSet *els, bool fixed_ori, FwdBemModel *bem_model, FwdEegSphereModel *m, bool use_threads, FIFFLIB::FiffNamedMatrix &resp, FIFFLIB::FiffNamedMatrix &resp_grad, bool bDoGrad)
FwdCoilSet * create_meg_coils(const QList< FIFFLIB::FiffChInfo > &chs, int nch, int acc, const FIFFLIB::FiffCoordTransOld *t)
static FwdCoilSet * create_eeg_els(const QList< FIFFLIB::FiffChInfo > &chs, int nch, const FIFFLIB::FiffCoordTransOld *t)
static FwdCoilSet * read_coil_defs(const QString &name)
bool fwd_setup_eeg_sphere_model(float rad, bool fit_berg_scherg, int nfit)
FwdEegSphereModel * fwd_select_eeg_sphere_model(const QString &p_sName)
void fwd_list_eeg_sphere_models(FILE *f)
static FwdEegSphereModelSet * fwd_load_eeg_sphere_models(const QString &p_sFileName, FwdEegSphereModelSet *now)
Matrix specification with a channel list.
This is used in the patch definitions.
This defines a source space.