59#include <QtConcurrent>
61#define _USE_MATH_DEFINES
66static float Qx[] = {1.0,0.0,0.0};
67static float Qy[] = {0.0,1.0,0.0};
68static float Qz[] = {0.0,0.0,1.0};
90#define VEC_DIFF_40(from,to,diff) {\
91 (diff)[X_40] = (to)[X_40] - (from)[X_40];\
92 (diff)[Y_40] = (to)[Y_40] - (from)[Y_40];\
93 (diff)[Z_40] = (to)[Z_40] - (from)[Z_40];\
96#define VEC_COPY_40(to,from) {\
97 (to)[X_40] = (from)[X_40];\
98 (to)[Y_40] = (from)[Y_40];\
99 (to)[Z_40] = (from)[Z_40];\
102#define VEC_DOT_40(x,y) ((x)[X_40]*(y)[X_40] + (x)[Y_40]*(y)[Y_40] + (x)[Z_40]*(y)[Z_40])
104#define VEC_LEN_40(x) sqrt(VEC_DOT_40(x,x))
106#define CROSS_PRODUCT_40(x,y,xy) {\
107 (xy)[X_40] = (x)[Y_40]*(y)[Z_40]-(y)[Y_40]*(x)[Z_40];\
108 (xy)[Y_40] = -((x)[X_40]*(y)[Z_40]-(y)[X_40]*(x)[Z_40]);\
109 (xy)[Z_40] = (x)[X_40]*(y)[Y_40]-(y)[X_40]*(x)[Y_40];\
112#define MALLOC_40(x,t) (t *)malloc((x)*sizeof(t))
114#define ALLOC_CMATRIX_40(x,y) mne_cmatrix_40((x),(y))
116#define FREE_40(x) if ((char *)(x) != NULL) free((char *)(x))
118#define FREE_CMATRIX_40(m) mne_free_cmatrix_40((m))
128static void matrix_error_40(
int kind,
int nr,
int nc)
132 printf(
"Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
134 printf(
"Failed to allocate memory for a %d x %d matrix\n",nr,nc);
136 printf(
"Allocation error for a %d x %d matrix\n",nr,nc);
137 if (
sizeof(
void *) == 4) {
138 printf(
"This is probably because you seem to be using a computer with 32-bit architecture.\n");
139 printf(
"Please consider moving to a 64-bit platform.");
141 printf(
"Cannot continue. Sorry.\n");
153 if (!m) matrix_error_40(1,nr,nc);
155 if (!whole) matrix_error_40(2,nr,nc);
165 Eigen::MatrixXf eigen_mat(m,n);
167 for (
int i = 0; i < m; ++i)
168 for (
int j = 0; j < n; ++j)
169 eigen_mat(i,j) = mat[i][j];
176 for (
int i = 0; i < m; ++i)
177 for (
int j = 0; j < n; ++j)
178 to_mat[i][j] = from_mat(i,j);
193 Eigen::MatrixXf eigen_mat_inv = eigen_mat.inverse();
206 for (j = 1; j < n; j++)
207 for (k = 0; k < j; k++) {
209 mat[j][k] = mat[k][j];
222 float res = sdot(&nn,v1,&one,v2,&one);
228 for (k = 0; k < nn; k++)
229 res = res + v1[k]*v2[k];
238 float fscale = scale;
240 saxpy(&nn,&fscale,v1,&one,v2,&one);
243 for (k = 0; k < nn; k++)
244 v2[k] = v2[k] + scale*v1[k];
253 float fscale = scale;
255 sscal(&nn,&fscale,v,&one);
258 for (k = 0; k < nn; k++)
264using namespace Eigen;
281 sgemm (transa,transb,&d3,&d1,&d2,
282 &one,m2[0],&d3,m1[0],&d2,&zero,result[0],&d3);
294 for (j = 0; j < d1; j++) {
295 for (k = 0; k < d2; k++) {
300 for (j = 0; j < d2; j++) {
301 for (k = 0; k < d3; k++) {
306 MatrixXf resultMat = a * b;
308 for (j = 0; j < d1; j++) {
309 for (k = 0; k < d3; k++) {
310 result[j][k] = resultMat(j,k);
345#define BEM_SUFFIX "-bem.fif"
346#define BEM_SOL_SUFFIX "-bem-sol.fif"
350static QString strip_from(
const QString& s,
const QString& suffix)
354 if (s.endsWith(suffix)) {
356 res.chop(suffix.size());
401 for (k = 0; frames[k].
frame != -1; k++) {
402 if (frame == frames[k].frame)
403 return frames[k].
name;
405 return frames[k].
name;
412using namespace Eigen;
443 for (
int k = 0; k < this->
nsurf; k++)
444 delete this->
surfs[k];
476 s1 = strip_from(
name,
".fif");
477 s2 = strip_from(s1,
"-sol");
478 s1 = strip_from(s2,
"-bem");
489 for (k = 0; surf_expl[k].kind >= 0; k++)
491 return surf_expl[k].name;
493 return surf_expl[k].name;
503 for (k = 0; method_expl[k].method >= 0; k++)
505 return method_expl[k].name;
507 return method_expl[k].name;
518 if(node->find_tag(stream, what, t_pTag)) {
520 printf(
"Expected an integer tag : %d (found data type %d instead)\n",what,t_pTag->getType() );
523 *res = *t_pTag->toInt();
537 for (
int k = 0; k < this->
nsurf; k++)
539 return this->
surfs[k];
551 QList<MNESurface*>
surfs;
558 qCritical(
"No surfaces specified to fwd_bem_load_surfaces");
567 for (k = 0; k < nkind; k++) {
569 if (
surfs[k] == NULL)
573 if (
sigma[k] < 0.0) {
578 qCritical(
"Surface %s not specified in MRI coordinates.",
fwd_bem_explain_surface(kinds[k]).toUtf8().constData());
599 for (k = 0; k < m->
nsurf; k++)
604 for (j = 0; j < m->
nsurf; j++) {
609 for (k = 0; k < m->
nsurf; k++)
618 for (k = 0; k <
surfs.size(); k++)
682 QList<FiffDirNode::SPtr> nodes = stream->dirtree()->dir_tree_find(
FIFFB_BEM);
684 if (nodes.size() == 0) {
685 printf (
"No BEM data in %s",
name.toUtf8().constData());
700 printf (
"Cannot handle BEM approximation method : %d",
method);
713 QVector<qint32> dims;
714 t_pTag->getMatrixDimensions(ndim, dims);
717 printf(
"Expected a two-dimensional solution matrix instead of a %d dimensional one",ndim);
720 for (k = 0, dim = 0; k < m->
nsurf; k++)
722 if (dims[0] != dim || dims[1] != dim) {
723 printf(
"Expected a %d x %d solution matrix instead of a %d x %d one",dim,dim,dims[0],dims[1]);
727 MatrixXf tmp_sol = t_pTag->toFloatMatrix().transpose();
771 printf (
"Improper coordinate transform delivered to fwd_bem_set_head_mri_t");
784 char *bemname = NULL;
789 float r0[] = { 0.0, 0.0, 0.0 };
795 printf(
"Making a spherical guess space with radius %7.1f mm...\n",1000*guessrad);
805 QFile bemFile(QString(QCoreApplication::applicationDirPath() +
"/../resources/general/surf2bem/icos.fif"));
806 if ( !QCoreApplication::startingUp() )
807 bemFile.setFileName(QCoreApplication::applicationDirPath() + QString(
"/../resources/general/surf2bem/icos.fif"));
808 else if (!bemFile.exists())
809 bemFile.setFileName(
"../resources/general/surf2bem/icos.fif");
811 if( !bemFile.exists () ){
812 qDebug() << bemFile.fileName() <<
"does not exists.";
816 bemname =
MALLOC_40(strlen(bemFile.fileName().toUtf8().data())+1,
char);
817 strcpy(bemname,bemFile.fileName().toUtf8().data());
822 for (k = 0; k < sphere->
np; k++) {
833 printf(
"Guess surface (%d = %s) is in %s coordinates\n",
837 printf(
"Filtering (grid = %6.f mm)...\n",1000*grid);
872 double y1[3],y2[3],y3[3];
881 double beta[3],bbeta[3];
886 static const double solid_eps = 4.0*
M_PI/1.0E6;
910 solid = 2.0*atan2(triple,ss);
911 if (std::fabs(solid) < solid_eps) {
912 for (k = 0; k < 3; k++)
919 for (j = 0; j < 3; j++)
921 bbeta[0] = beta[2] - beta[0];
922 bbeta[1] = beta[0] - beta[1];
923 bbeta[2] = beta[1] - beta[2];
925 for (j = 0; j < 3; j++)
927 for (j = 0; j < 3; j++)
928 for (k = 0; k < 3; k++)
929 vec_omega[k] = vec_omega[k] + bbeta[j]*yy[j][k];
933 area2 = 2.0*to->
area;
934 n2 = 1.0/(area2*area2);
935 for (k = 0; k < 3; k++) {
948 rel1 = (solid + omega[
X_40]+omega[
Y_40]+omega[
Z_40])/solid;
952 for (j = 0; j < 3; j++)
954 for (k = 0; k < 3; k++) {
956 for (j = 0; j < 3; j++)
957 check[j] = check[j] + omega[k]*z[j];
959 for (j = 0; j < 3; j++)
960 check[j] = -area2*check[j]/triple;
961 fprintf (stderr,
"(%g,%g,%g) =? (%g,%g,%g)\n",
964 for (j = 0; j < 3; j++)
965 check[j] = check[j] - vec_omega[j];
967 fprintf (stderr,
"err1 = %g, err2 = %g\n",100*rel1,100*rel2);
981 int nnode = surf->
np;
985 float pi2 = 2.0*
M_PI;
989 for (j = 0; j < nnode; j++) {
992 for (k = 0; k < nnode; k++)
994 fprintf (stderr,
"row %d sum = %g missing = %g\n",j+1,sum/pi2,
999 for (j = 0; j < nnode; j++) {
1005 for (k = 0; k < nnode; k++)
1016 miss = miss/(4.0*nmemb);
1017 for (k = 0,tri = surf->
tris.data(); k <
ntri; k++,tri++) {
1018 if (tri->
vert[0] == j) {
1019 row[tri->
vert[1]] = row[tri->
vert[1]] + miss;
1020 row[tri->
vert[2]] = row[tri->
vert[2]] + miss;
1022 else if (tri->
vert[1] == j) {
1023 row[tri->
vert[0]] = row[tri->
vert[0]] + miss;
1024 row[tri->
vert[2]] = row[tri->
vert[2]] + miss;
1026 else if (tri->
vert[2] == j) {
1027 row[tri->
vert[0]] = row[tri->
vert[0]] + miss;
1028 row[tri->
vert[1]] = row[tri->
vert[1]] + miss;
1051 float **sub_mat = NULL;
1052 int np1,np2,
ntri,np_tot,np_max;
1062 for (p = 0, np_tot = np_max = 0; p <
surfs.size(); p++) {
1063 np_tot +=
surfs[p]->np;
1065 np_max =
surfs[p]->np;
1069 for (j = 0; j < np_tot; j++)
1070 for (k = 0; k < np_tot; k++)
1074 for (p = 0, joff = 0; p <
surfs.size(); p++, joff = joff + np1) {
1078 for (q = 0, koff = 0; q <
surfs.size(); q++, koff = koff + np2) {
1083 printf(
"\t\t%s (%d) -> %s (%d) ... ",
1087 for (j = 0; j < np1; j++) {
1088 for (k = 0; k < np2; k++)
1090 for (k = 0, tri = surf2->
tris.data(); k <
ntri; k++,tri++) {
1095 if (p == q && (tri->
vert[0] == j || tri->
vert[1] == j || tri->
vert[2] == j))
1101 for (c = 0; c < 3; c++)
1102 row[tri->
vert[c]] = row[tri->
vert[c]] - omega[c];
1104 for (k = 0; k < np2; k++)
1105 mat[j+joff][k+koff] = row[k];
1108 for (j = 0; j < np1; j++)
1109 sub_mat[j] = mat[j+joff]+koff;
1127 float **coeff = NULL;
1134 printf(
"\nComputing the linear collocation solution...\n");
1135 fprintf (stderr,
"\tMatrix coefficients...\n");
1139 for (k = 0, m->
nsol = 0; k < m->
nsurf; k++)
1142 fprintf (stderr,
"\tInverting the coefficient matrix...\n");
1149 if ((m->
nsurf == 3) &&
1151 float **ip_solution = NULL;
1153 fprintf (stderr,
"IP approach required...\n");
1155 fprintf (stderr,
"\tMatrix coefficients (homog)...\n");
1156 QList<MNESurface*> last_surfs;
1157 last_surfs << m->
surfs.last();
1161 fprintf (stderr,
"\tInverting the coefficient matrix (homog)...\n");
1165 fprintf (stderr,
"\tModify the original solution to incorporate IP approach...\n");
1172 printf(
"Solution ready.\n");
1195 float pi2 = 1.0/(2*
M_PI);
1197 int joff,koff,jup,kup,ntot;
1199 for (j = 0,ntot = 0; j <
nsurf; j++)
1205 for (p = 0, joff = 0; p <
nsurf; p++) {
1206 jup =
ntri[p] + joff;
1207 for (q = 0, koff = 0; q <
nsurf; q++) {
1208 kup =
ntri[q] + koff;
1209 mult = (
gamma == NULL) ? pi2 : pi2*
gamma[p][q];
1210 for (j = joff; j < jup; j++)
1211 for (k = koff; k < kup; k++)
1212 solids[j][k] = defl - solids[j][k]*mult;
1217 for (k = 0; k < ntot; k++)
1218 solids[k][k] = solids[k][k] + 1.0;
1244 int j,k,joff,koff,ntot,nlast;
1249 for (s = 0, koff = 0; s <
nsurf-1; s++)
1250 koff = koff +
ntri[s];
1252 ntot = koff + nlast;
1256 mult = (1.0 + ip_mult)/ip_mult;
1258 printf(
"\t\tCombining...");
1263 for (s = 0, joff = 0; s <
nsurf; s++) {
1268 for (j = 0; j <
ntri[s]; j++)
1274 for (j = 0; j <
ntri[s]; j++) {
1275 for (k = 0; k < nlast; k++) {
1276 res = mne_dot_vectors_skip_skip(sub[j],1,ip_solution[0]+k,nlast,nlast);
1277 row[k] = sub[j][k] - 2.0*res;
1279 for (k = 0; k < nlast; k++)
1283 for (j = 0; j <
ntri[s]; j++) {
1284 for (k = 0; k < nlast; k++)
1289 joff = joff+
ntri[s];
1299 for (j = 0; j < nlast; j++)
1300 for (k = 0; k < nlast; k++)
1301 sub[j][k] = sub[j][k] + mult*ip_solution[j][k];
1305 printf(
"done.\n\t\tScaling...");
1324 for (j = 0; j < ntri1; j++) {
1326 for (k = 0; k < ntri2; k++)
1327 sum = sum + angles[j][k];
1328 sums[j] = sum/(2*
M_PI);
1330 for (j = 0; j < ntri1; j++)
1337 if (std::fabs(sums[j]-desired) > 1e-4) {
1338 printf(
"solid angle matrix: rowsum[%d] = 2PI*%g",
1357 int ntri1,ntri2,ntri_tot;
1362 float **sub_solids = NULL;
1365 for (p = 0,ntri_tot = 0; p <
surfs.size(); p++)
1368 sub_solids =
MALLOC_40(ntri_tot,
float *);
1370 for (p = 0, joff = 0; p <
surfs.size(); p++, joff = joff + ntri1) {
1372 ntri1 = surf1->
ntri;
1373 for (q = 0, koff = 0; q <
surfs.size(); q++, koff = koff + ntri2) {
1375 ntri2 = surf2->
ntri;
1377 for (j = 0; j < ntri1; j++)
1378 for (k = 0, tri = surf2->
tris.data(); k < ntri2; k++, tri++) {
1379 if (p == q && j == k)
1383 solids[j+joff][k+koff] = result;
1385 for (j = 0; j < ntri1; j++)
1386 sub_solids[j] = solids[j+joff]+koff;
1412 float **solids = NULL;
1419 printf(
"\nComputing the constant collocation solution...\n");
1420 printf(
"\tSolid angles...\n");
1424 for (k = 0, m->
nsol = 0; k < m->
nsurf; k++)
1427 fprintf (stderr,
"\tInverting the coefficient matrix...\n");
1433 if ((m->
nsurf == 3) &&
1435 float **ip_solution = NULL;
1437 fprintf (stderr,
"IP approach required...\n");
1439 fprintf (stderr,
"\tSolid angles (homog)...\n");
1440 QList<MNESurface*> last_surfs;
1441 last_surfs << m->
surfs.last();
1445 fprintf (stderr,
"\tInverting the coefficient matrix (homog)...\n");
1449 fprintf (stderr,
"\tModify the original solution to incorporate IP approach...\n");
1454 fprintf (stderr,
"Solution ready.\n");
1483 printf (
"Unknown BEM method: %d\n",
bem_method);
1497 printf (
"No model specified for fwd_bem_load_recompute_solution");
1501 if (!force_recompute) {
1505 if (solres ==
TRUE) {
1509 else if (solres ==
FAIL)
1513 printf(
"Desired BEM solution not available in %s (%s)\n",
name,err_get_error());
1529 float diff[3],diff2,cross[3];
1535 return (
VEC_DOT_40(cross,dir)/(diff2*sqrt(diff2)));
1562 float *one_sol,*pick_sol;
1563 float r[3],w[3],dist;
1570 printf(
"Model missing in fwd_bem_specify_els");
1574 printf(
"Solution not computed in fwd_bem_specify_els");
1577 if (!els || els->
ncoil == 0)
1592 for (k = 0; k < els->
ncoil; k++) {
1595 for (q = 0; q < m->
nsol; q++)
1597 scalp = m->
surfs[0];
1601 for (p = 0; p < el->
np; p++) {
1607 printf(
"One of the electrodes could not be projected onto the scalp surface. How come?");
1615 for (q = 0; q < m->
nsol; q++)
1616 one_sol[q] += el->
w[p]*pick_sol[q];
1622 tri = &scalp->
tris[best];
1623 scalp->
triangle_coords(Eigen::Map<const Eigen::Vector3f>(r),best,x,y,z);
1625 w[
X_40] = el->
w[p]*(1.0 - x - y);
1626 w[
Y_40] = el->
w[p]*x;
1627 w[
Z_40] = el->
w[p]*y;
1628 for (v = 0; v < 3; v++) {
1630 for (q = 0; q < m->
nsol; q++)
1631 one_sol[q] += w[v]*pick_sol[q];
1635 printf(
"Unknown BEM approximation method : %d\n",m->
bem_method);
1661 float mri_rd[3],mri_Q[3];
1680 for (pp = 0; pp < 3; pp++) {
1683 for (p = 0; p < 3; p++)
1684 ee[p] = p == pp ? 1.0 : 0.0;
1688 for (s = 0, p = 0; s < m->
nsurf; s++) {
1690 tri = m->
surfs[s]->tris.data();
1692 for (k = 0; k <
ntri; k++, tri++)
1704 for (k = 0; k <
nsol; k++)
1721 float mult,mri_rd[3],mri_Q[3];
1736 for (s = 0, p = 0; s < m->
nsurf; s++) {
1739 for (k = 0; k <
np; k++)
1751 for (k = 0; k <
nsol; k++)
1766 float mult,mri_rd[3],mri_Q[3];
1788 for (pp = 0; pp < 3; pp++) {
1791 for (p = 0; p < 3; p++)
1792 ee[p] = p == pp ? 1.0 : 0.0;
1796 for (s = 0, p = 0; s < m->
nsurf; s++) {
1799 for (k = 0; k <
np; k++)
1811 for (k = 0; k <
nsol; k++)
1830 float mri_rd[3],mri_Q[3];
1842 for (s = 0, p = 0; s < m->
nsurf; s++) {
1844 tri = m->
surfs[s]->tris.data();
1846 for (k = 0; k <
ntri; k++, tri++)
1858 for (k = 0; k <
nsol; k++)
1874 printf(
"No BEM model specified to fwd_bem_pot_els");
1878 printf(
"No solution available for fwd_bem_pot_els");
1882 printf(
"No appropriate electrode-specific data available in fwd_bem_pot_coils");
1890 printf(
"Unknown BEM method : %d",m->
bem_method);
1907 qCritical(
"No BEM model specified to fwd_bem_pot_els");
1911 qCritical(
"No solution available for fwd_bem_pot_els");
1915 qCritical(
"No appropriate electrode-specific data available in fwd_bem_pot_coils");
1929 qCritical(
"Unknown BEM method : %d",m->
bem_method);
1937#define ARSINH(x) log((x) + sqrt(1.0+(x)*(x)))
1957 for (k = 0; k < 3; k++) {
1971 double B2 = 1.0 + B*B;
1972 double ABu = A + B*u;
1973 *D = sqrt(u*u + z*z + ABu*ABu);
1974 beta[0] = ABu/sqrt(u*u + z*z);
1975 beta[1] = (A*B + B2*u)/sqrt(A*A + B2*z*z);
1976 beta[2] = (B*z*z - A*u)/(z*(*D));
1983 double y1[3],y2[3],y3[3];
1986 double beta[3],I1,Tx,Ty,Txx,Tyy,Sxx,mult;
1987 double S1x,S1y,S2x,S2y;
2031 for (k = 0; k < 2; k++) {
2032 dx = xx[k+1] - xx[k];
2033 A = (yy[k]*xx[k+1] - yy[k+1]*xx[k])/dx;
2034 B = (yy[k+1]-yy[k])/dx;
2040 I1 = I1 - xx[k+1]*
ARSINH(beta[0]) - (A/sqrt(1.0+B*B))*
ARSINH(beta[1])
2042 Txx =
ARSINH(beta[1])/sqrt(B2);
2045 Sxx = (D1 - A*B*Txx)/B2;
2048 Sxx = (B*D1 + A*Txx)/B2;
2054 I1 = I1 + xx[k]*
ARSINH(beta[0]) + (A/sqrt(1.0+B*B))*
ARSINH(beta[1])
2056 Txx =
ARSINH(beta[1])/sqrt(B2);
2059 Sxx = (D1 - A*B*Txx)/B2;
2062 Sxx = (B*D1 + A*Txx)/B2;
2068 mult = 1.0/sqrt(xx[k]*xx[k]+z*z);
2072 Tyy =
ARSINH(mult*yy[k+1]);
2074 S1y = S1y + xx[k]*Tyy;
2078 Tyy =
ARSINH(mult*yy[k]);
2080 S1y = S1y - xx[k]*Tyy;
2103 double y1[3],y2[3],y3[3];
2116 for (j = 0; j < 3; j++)
2118 bbeta[0] = beta[2] - beta[0];
2119 bbeta[1] = beta[0] - beta[1];
2120 bbeta[2] = beta[1] - beta[2];
2122 for (j = 0; j < 3; j++)
2124 for (j = 0; j < 3; j++)
2125 for (k = 0; k < 3; k++)
2126 coeff[k] = coeff[k] + yy[j][k]*bbeta[j];
2142 float **coeff = NULL;
2148 printf(
"Solution matrix missing in fwd_bem_field_coeff");
2152 printf(
"BEM method should be constant collocation for fwd_bem_field_coeff");
2158 printf(
"head -> mri coordinate transform missing in fwd_bem_field_coeff");
2163 qWarning(
"No coils to duplicate");
2175 printf(
"Incompatible coil coordinate frame %d for fwd_bem_field_coeff",coils->
coord_frame);
2182 for (s = 0, off = 0; s < m->
nsurf; s++) {
2185 tri = surf->
tris.data();
2188 for (k = 0; k <
ntri; k++,tri++) {
2189 for (j = 0; j < coils->
ncoil; j++) {
2190 coil = coils->
coils[j];
2192 for (p = 0; p < coil->
np; p++)
2194 coeff[j][k+off] = mult*res;
2226 double c1[3],c2[3],c3[3];
2227 double y1[3],y2[3],y3[3];
2228 double *yy[4],*cc[4];
2230 double cross[3],triple,l1,l2,l3,solid,clen;
2231 double common,sum,beta,
gamma;
2234 yy[0] = y1; cc[0] = c1;
2235 yy[1] = y2; cc[1] = c2;
2236 yy[2] = y3; cc[2] = c3;
2237 yy[3] = y1; cc[3] = c1;
2243 for (k = 0; k < 3; k++) {
2244 y1[k] = tri->
r1[k] - dest[k];
2245 y2[k] = tri->
r2[k] - dest[k];
2246 y3[k] = tri->
r3[k] - dest[k];
2249 for (k = 0; k < 3; k++) {
2250 c[k] = clen*tri->
nn[k];
2251 A[k] = dest[k] + c[k];
2252 c1[k] = tri->
r1[k] - A[k];
2253 c2[k] = tri->
r2[k] - A[k];
2254 c3[k] = tri->
r3[k] - A[k];
2259 for (sum = 0.0, k = 0; k < 3; k++) {
2263 sum = sum + beta*
gamma;
2274 solid = 2.0*atan2(triple,
2282 common = (sum-clen*solid)/(2.0*tri->
area);
2283 for (k = 0; k < 3; k++)
2292 double I1,T[2],S1[2],S2[2];
2293 double f0[3],fx[3],fy[3];
2312 for (k = 0; k < 3; k++) {
2313 res_x = f0[k]*T[
X_40] + fx[k]*S1[
X_40] + fy[k]*S2[
X_40] + fy[k]*I1;
2314 res_y = f0[k]*T[
Y_40] + fx[k]*S1[
Y_40] + fy[k]*S2[
Y_40] - fx[k]*I1;
2315 res[k] = x_fac*res_x + y_fac*res_y;
2328 float vec_result[3];
2337 for (k = 0; k < 3; k++) {
2341 res[k] = source->
area*
VEC_DOT_40(vec_result,normal)/(3.0*dl*sqrt(dl));
2359 float **coeff = NULL;
2361 double res[3],one[3];
2366 printf(
"Solution matrix missing in fwd_bem_lin_field_coeff");
2370 printf(
"BEM method should be linear collocation for fwd_bem_lin_field_coeff");
2376 printf(
"head -> mri coordinate transform missing in fwd_bem_lin_field_coeff");
2381 qWarning(
"No coils to duplicate");
2393 printf(
"Incompatible coil coordinate frame %d for fwd_bem_field_coeff",coils->
coord_frame);
2405 for (k = 0; k < m->
nsol; k++)
2406 for (j = 0; j < coils->
ncoil; j++)
2411 for (s = 0, off = 0; s < m->
nsurf; s++) {
2414 tri = surf->
tris.data();
2417 for (k = 0; k <
ntri; k++,tri++) {
2418 for (j = 0; j < coils->
ncoil; j++) {
2419 coil = coils->
coils[j];
2420 for (pp = 0; pp < 3; pp++)
2425 for (p = 0; p < coil->
np; p++) {
2427 for (pp = 0; pp < 3; pp++)
2428 res[pp] = res[pp] + coil->
w[p]*one[pp];
2434 for (pp = 0; pp < 3; pp++)
2435 coeff[j][tri->
vert[pp]+off] = coeff[j][tri->
vert[pp]+off] + mult*res[pp];
2438 off = off + surf->
np;
2458 printf(
"Model missing in fwd_bem_specify_coils");
2462 printf(
"Solution not computed in fwd_bem_specify_coils");
2467 if (!coils || coils->
ncoil == 0)
2474 printf(
"Unknown BEM method in fwd_bem_specify_coils : %d",m->
bem_method);
2509 float my_rd[3],my_Q[3];
2529 for (s = 0, p = 0; s < m->
nsurf; s++) {
2532 for (k = 0; k <
np; k++)
2539 for (k = 0; k < coils->
ncoil; k++) {
2540 coil = coils->
coils[k];
2542 for (p = 0; p < coil->
np; p++)
2548 for (k = 0; k < coils->
ncoil; k++)
2553 for (k = 0; k < coils->
ncoil; k++)
2570 float my_rd[3],my_Q[3];
2590 for (s = 0, p = 0; s < m->
nsurf; s++) {
2592 tri = m->
surfs[s]->tris.data();
2594 for (k = 0; k <
ntri; k++, tri++)
2601 for (k = 0; k < coils->
ncoil; k++) {
2602 coil = coils->
coils[k];
2604 for (p = 0; p < coil->
np; p++)
2610 for (k = 0; k < coils->
ncoil; k++)
2615 for (k = 0; k < coils->
ncoil; k++)
2633 float *grads[3],ee[3],mri_ee[3],mri_rd[3],mri_Q[3];
2654 for (pp = 0; pp < 3; pp++) {
2659 for (p = 0; p < 3; p++)
2660 ee[p] = p == pp ? 1.0 : 0.0;
2667 for (s = 0, p = 0; s < m->
nsurf; s++) {
2669 tri = m->
surfs[s]->tris.data();
2671 for (k = 0; k <
ntri; k++, tri++) {
2679 for (k = 0; k < coils->
ncoil; k++) {
2680 coil = coils->
coils[k];
2682 for (p = 0; p < coil->
np; p++)
2688 for (k = 0; k < coils->
ncoil; k++)
2693 for (k = 0; k < coils->
ncoil; k++)
2707 float diff[3],diff2,diff3,diff5,cross[3],crossn[3],res;
2711 diff3 = sqrt(diff2)*diff2;
2712 diff5 = diff3*diff2;
2729 float diff2,diff5,diff3;
2734 diff3 = sqrt(diff2)*diff2;
2735 diff5 = diff3*diff2;
2738 return (res/(4.0*
M_PI));
2754 float ee[3],mri_ee[3],mri_rd[3],mri_Q[3];
2776 for (pp = 0; pp < 3; pp++) {
2781 for (p = 0; p < 3; p++)
2782 ee[p] = p == pp ? 1.0 : 0.0;
2789 for (s = 0, p = 0; s < m->
nsurf; s++) {
2793 for (k = 0; k <
np; k++)
2800 for (k = 0; k < coils->
ncoil; k++) {
2801 coil = coils->
coils[k];
2803 for (p = 0; p < coil->
np; p++)
2809 for (k = 0; k < coils->
ncoil; k++)
2814 for (k = 0; k < coils->
ncoil; k++)
2833 printf(
"No BEM model specified to fwd_bem_field");
2837 printf(
"No appropriate coil-specific data available in fwd_bem_field");
2845 printf(
"Unknown BEM method : %d",m->
bem_method);
2866 qCritical(
"No BEM model specified to fwd_bem_field");
2871 qCritical(
"No appropriate coil-specific data available in fwd_bem_field");
2908 qCritical(
"Unknown BEM method : %d",m->
bem_method);
2932 for (j = 0; j < s->
np; j++) {
2949 for (j = 0; j < s->
np; j++)
2961 for (j = 0; j < s->
np; j++) {
2995 else if (a->
comp == 0) {
3009 else if (a->
comp == 1) {
3023 else if (a->
comp == 2) {
3041 for (j = 0; j < s->
np; j++) {
3044 xyz[0] = a->
res[p++];
3045 xyz[1] = a->
res[p++];
3046 xyz[2] = a->
res[p++];
3059 else if (a->
comp == 0) {
3064 else if (a->
comp == 1) {
3070 else if (a->
comp == 2) {
3108 float **res_grad = NULL;
3110 MatrixXd matResGrad;
3117 int nmeg = coils->
ncoil;
3119 int nspace =
static_cast<int>(spaces.size());
3124 int nproc = QThread::idealThreadCount();
3125 QStringList emptyList;
3133 printf(
"Using differences.\n");
3156 qDebug() <<
"!!!TODO Speed the following with Eigen up!";
3157 printf(
"Composing the field computation matrix...");
3163 printf(
"Composing the field computation matrix (compensation coils)...");
3179 printf(
"Using differences.\n");
3183 my_sphere_field_grad,
3202 for (k = 0, nsource = 0; k < nspace; k++)
3203 nsource += spaces[k]->nuse;
3225 one_arg->
client = client;
3233 use_threads =
false;
3236 int nthread = (fixed_ori || vec_field || nproc < 6) ? nspace : 3*nspace;
3237 QList <FwdThreadArg*> args;
3242 if (fixed_ori || vec_field || nproc < 6) {
3243 for (k = 0, off = 0; k < nthread; k++) {
3245 t_arg->
s = spaces[k].get();
3247 off = fixed_ori ? off + spaces[k]->nuse : off + 3*spaces[k]->nuse;
3250 printf(
"%d processors. I will use one thread for each of the %d source spaces.\n",
3254 for (k = 0, off = 0, q = 0; k < nspace; k++) {
3255 for (p = 0; p < 3; p++,q++) {
3257 t_arg->
s = spaces[k].get();
3262 off = fixed_ori ? off + spaces[k]->nuse : off + 3*spaces[k]->nuse;
3264 printf(
"%d processors. I will use %d threads : %d source spaces x 3 source components.\n",
3265 nproc,nthread,nspace);
3267 printf(
"Computing MEG at %d source locations (%s orientations)...",
3268 nsource,fixed_ori ?
"fixed" :
"free");
3276 for (k = 0, stat =
OK; k < nthread; k++)
3277 if (args[k]->stat !=
OK) {
3281 for (k = 0; k < args.size(); k++)
3287 printf(
"Computing MEG at %d source locations (%s orientations, no threads)...",
3288 nsource,fixed_ori ?
"fixed" :
"free");
3289 for (k = 0, off = 0; k < nspace; k++) {
3290 one_arg->
s = spaces[k].get();
3295 off = fixed_ori ? off + one_arg->
s->
nuse : off + 3*one_arg->
s->
nuse;
3300 QStringList orig_names;
3301 for (k = 0; k < nmeg; k++)
3311 nrow = fixed_ori ? nsource : 3*nsource;
3312 matRes.conservativeResize(nrow,nmeg);
3313 for(
int i = 0; i < nrow; i++) {
3314 for(
int j = 0; j < nmeg; j++) {
3315 matRes(i,j) = res[i][j];
3325 if (bDoGrad && res_grad) {
3326 nrow = fixed_ori ? 3*nsource : 3*3*nsource;
3327 matResGrad = MatrixXd::Zero(nrow,nmeg);
3328 for(
int i = 0; i < nrow; i++) {
3329 for(
int j = 0; j < nmeg; j++) {
3330 matResGrad(i,j) = res_grad[i][j];
3333 resp_grad.
nrow = nrow;
3334 resp_grad.
ncol = nmeg;
3337 resp_grad.
data = matResGrad;
3370 float **res_grad = NULL;
3372 MatrixXd matResGrad;
3379 int nspace =
static_cast<int>(spaces.size());
3380 int neeg = els->
ncoil;
3385 int nproc = QThread::idealThreadCount();
3386 QStringList emptyList;
3390 for (k = 0, nsource = 0; k < nspace; k++)
3391 nsource += spaces[k]->nuse;
3400 printf(
"Using differences.\n");
3401 pot_grad = my_bem_pot_grad;
3408 printf(
"Using the standard series expansion for a multilayer sphere model for EEG\n");
3414 printf(
"Using the equivalent source approach in the homogeneous sphere for EEG\n");
3430 qCritical(
"EEG gradient calculation function not available");
3446 one_arg->
client = client;
3454 use_threads =
false;
3457 int nthread = (fixed_ori || vec_pot || nproc < 6) ? nspace : 3*nspace;
3458 QList <FwdThreadArg*> args;
3463 if (fixed_ori || vec_pot || nproc < 6) {
3464 for (k = 0, off = 0; k < nthread; k++) {
3466 t_arg->
s = spaces[k].get();
3468 off = fixed_ori ? off + spaces[k]->nuse : off + 3*spaces[k]->nuse;
3471 printf(
"%d processors. I will use one thread for each of the %d source spaces.\n",nproc,nspace);
3474 for (k = 0, off = 0, q = 0; k < nspace; k++) {
3475 for (p = 0; p < 3; p++,q++) {
3477 t_arg->
s = spaces[k].get();
3482 off = fixed_ori ? off + spaces[k]->nuse : off + 3*spaces[k]->nuse;
3484 printf(
"%d processors. I will use %d threads : %d source spaces x 3 source components.\n",nproc,nthread,nspace);
3486 printf(
"Computing EEG at %d source locations (%s orientations)...",
3487 nsource,fixed_ori ?
"fixed" :
"free");
3495 for (k = 0, stat =
OK; k < nthread; k++)
3496 if (args[k]->stat !=
OK) {
3500 for (k = 0; k < args.size(); k++)
3506 printf(
"Computing EEG at %d source locations (%s orientations, no threads)...",
3507 nsource,fixed_ori ?
"fixed" :
"free");
3508 for (k = 0, off = 0; k < nspace; k++) {
3509 one_arg->
s = spaces[k].get();
3514 off = fixed_ori ? off + one_arg->
s->
nuse : off + 3*one_arg->
s->
nuse;
3519 QStringList orig_names;
3520 for (k = 0; k < neeg; k++)
3528 nrow = fixed_ori ? nsource : 3*nsource;
3529 matRes.conservativeResize(nrow,neeg);
3530 for(
int i = 0; i < nrow; i++) {
3531 for(
int j = 0; j < neeg; j++) {
3532 matRes(i,j) = res[i][j];
3542 if (bDoGrad && res_grad) {
3543 matResGrad = MatrixXd::Zero(fixed_ori ? 3*nsource : 3*3*nsource,neeg);
3544 for(
int i = 0; i < nrow; i++) {
3545 for(
int j = 0; j < neeg; j++) {
3546 matResGrad(i,j) = res_grad[i][j];
3549 resp_grad.
nrow = nrow;
3550 resp_grad.
ncol = neeg;
3553 resp_grad.
data = matResGrad;
3590 float *r0 = (
float *)client;
3591 float v[3],a_vec[3];
3595 float F,g0,gr,result,sum;
3598 float *this_pos,*this_dir;
3605 for (p = 0; p < 3; p++)
3606 myrd[p] = rd[p] - r0[p];
3611 for (k = 0 ; k < coils->
ncoil ; k++)
3619 for (k = 0; k < coils->
ncoil; k++) {
3620 this_coil = coils->
coils[k];
3625 for (j = 0, sum = 0.0; j <
np; j++) {
3627 this_pos = this_coil->
rmag[j];
3628 this_dir = this_coil->
cosmag[j];
3630 for (p = 0; p < 3; p++)
3631 pos[p] = this_pos[p] - r0[p];
3644 r2 =
VEC_DOT_40(this_pos,this_pos); r = sqrt(r2);
3648 if (std::fabs(ar/(a*r)+1.0) >
CEPS) {
3658 gr = a2/r + ar0 + 2.0*(a+r);
3663 sum = sum + this_coil->
w[j]*(ve*F + vr*(g0*r0e - gr*re))/(F*F);
3699 float *r0 = (
float *)client;
3700 float a_vec[3],v1[3],v2[3];
3704 float F,g0,gr,g,sum[3];
3707 float *this_pos,*this_dir;
3714 for (p = 0; p < 3; p++)
3715 myrd[p] = rd[p] - r0[p];
3721 for (k = 0; k < coils->
ncoil; k++) {
3722 this_coil = coils->
coils[k];
3725 Bval[0][k] = Bval[1][k] = Bval[2][k] = 0.0;
3730 sum[0] = sum[1] = sum[2] = 0.0;
3732 for (j = 0; j <
np; j++) {
3734 this_pos = this_coil->
rmag[j];
3735 this_dir = this_coil->
cosmag[j];
3737 for (p = 0; p < 3; p++)
3738 pos[p] = this_pos[p] - r0[p];
3750 r2 =
VEC_DOT_40(this_pos,this_pos); r = sqrt(r2);
3754 if (std::fabs(ar/(a*r)+1.0) >
CEPS) {
3761 gr = a2/r + ar0 + 2.0*(a+r);
3768 g = (g0*r0e - gr*re)/(F*F);
3772 for (p = 0; p < 3; p++)
3773 sum[p] = sum[p] + this_coil->
w[j]*(v1[p]/F + v2[p]*g);
3778 for (p = 0; p < 3; p++)
3809 float v[3],a_vec[3];
3813 float F,g0,gr,result,G,F2;
3817 float ggr[3],gg0[3];
3825 float *this_pos,*this_dir;
3829 float *r0 = (
float *)client;
3833 for (p = 0; p < 3; p++)
3834 myrd[p] = rd[p] - r0[p];
3843 for (k = 0; k < coils->
ncoil ; k++) {
3858 for (k = 0 ; k < coils->
ncoil ; k++) {
3860 this_coil = coils->
coils[k];
3866 for (j = 0; j <
np; j++) {
3868 this_pos = this_coil->
rmag[j];
3872 for (p = 0; p < 3; p++)
3873 pos[p] = this_pos[p] - r0[p];
3876 this_dir = this_coil->
cosmag[j];
3887 r2 =
VEC_DOT_40(this_pos,this_pos); r = sqrt(r2);
3908 F = a*(r*a + r2 - rr0);
3910 gr = a2/r + ar + 2.0*(a+r);
3911 g0 = a + 2.0*r + ar;
3916 result = (ve*F + vr*G)/F2;
3920 huu = 2.0 + 2.0*a/r;
3922 ga[p] = -a_vec[p]/a;
3923 gar[p] = -(ga[p]*ar + this_pos[p])/a;
3924 gg0[p] = ga[p] + gar[p];
3925 ggr[p] = huu*ga[p] + gar[p];
3926 gFF[p] = ga[p]/a - (r*a_vec[p] + a*this_pos[p])/F;
3927 gresult[p] = -2.0*result*gFF[p] + (eQ[p]+gFF[p]*ve)/F +
3928 (rQ[p]*G + vr*(gg0[p]*r0e + g0*this_dir[p] - ggr[p]*re))/F2;
3932 Bval[k] = Bval[k] + this_coil->
w[j]*result;
3933 xgrad[k] = xgrad[k] + this_coil->
w[j]*gresult[
X_40];
3934 ygrad[k] = ygrad[k] + this_coil->
w[j]*gresult[
Y_40];
3935 zgrad[k] = zgrad[k] + this_coil->
w[j]*gresult[
Z_40];
3957 float sum,diff[3],dist,dist2,dist5,*dir;
3959 for (k = 0; k < coils->
ncoil; k++) {
3960 this_coil = coils->
coils[k];
3966 for (j = 0, sum = 0.0; j <
np; j++) {
3967 dir = this_coil->
cosmag[j];
3972 dist5 = dist2*dist2*dist;
3994 float sum[3],diff[3],dist,dist2,dist5,*dir;
3996 for (k = 0; k < coils->
ncoil; k++) {
3997 this_coil = coils->
coils[k];
4000 sum[0] = sum[1] = sum[2] = 0.0;
4004 for (j = 0; j <
np; j++) {
4005 dir = this_coil->
cosmag[j];
4010 dist5 = dist2*dist2*dist;
4011 for (p = 0; p < 3; p++)
4012 sum[p] = sum[p] + this_coil->
w[j]*(3*diff[p]*
VEC_DOT_40(diff,dir) - dist2*dir[p])/dist5;
4015 for (p = 0; p < 3; p++)
4019 for (p = 0; p < 3; p++)
#define FIFFV_MNE_COORD_MNI_TAL
#define FIFFV_MNE_COORD_FS_TAL_LTZ
#define FIFFV_COORD_MRI_SLICE
#define FIFFV_MNE_COORD_CTF_DEVICE
#define FIFFV_COORD_DEVICE
#define FIFFV_COORD_MRI_DISPLAY
#define FIFFV_MNE_COORD_MRI_VOXEL
#define FIFFV_MNE_COORD_CTF_HEAD
#define FIFFV_COORD_ISOTRAK
#define FIFFV_COORD_UNKNOWN
#define FIFFV_MNE_COORD_FS_TAL_GTZ
#define FIFFV_MNE_COORD_RAS
FiffNamedMatrix class declaration.
FiffStream class declaration.
#define FIFFV_BEM_APPROX_LINEAR
#define FIFFV_BEM_SURF_ID_SKULL
#define FIFFV_BEM_APPROX_CONST
#define FIFFV_BEM_SURF_ID_HEAD
#define FIFFV_BEM_SURF_ID_BRAIN
#define FIFF_BEM_POT_SOLUTION
MNETriangle class declaration.
MNESurface class declaration.
MNESourceSpace class declaration.
Forward BEM Solution (FwdBemSolution) class declaration.
int(* fwdFieldFunc)(float *rd, float *Q, FWDLIB::FwdCoilSet *coils, float *res, void *client)
int(* fwdVecFieldFunc)(float *rd, FWDLIB::FwdCoilSet *coils, float **res, void *client)
int(* fwdFieldGradFunc)(float *rd, float *Q, FWDLIB::FwdCoilSet *coils, float *res, float *xgrad, float *ygrad, float *zgrad, void *client)
FwdCompData class declaration.
#define FWD_IS_MEG_COIL(x)
void fromFloatEigenMatrix_40(const Eigen::MatrixXf &from_mat, float **&to_mat, const int m, const int n)
void mne_transpose_square_40(float **mat, int n)
void mne_add_scaled_vector_to_40(float *v1, float scale, float *v2, int nn)
float ** mne_lu_invert_40(float **mat, int dim)
#define VEC_COPY_40(to, from)
#define ALLOC_CMATRIX_40(x, y)
Eigen::MatrixXf toFloatEigenMatrix_40(float **mat, const int m, const int n)
#define FREE_CMATRIX_40(m)
const QString mne_coord_frame_name_40(int frame)
float mne_dot_vectors_40(float *v1, float *v2, int nn)
float ** mne_mat_mat_mult_40(float **m1, float **m2, int d1, int d2, int d3)
#define VEC_DIFF_40(from, to, diff)
void mne_scale_vector_40(double scale, float *v, int nn)
#define CROSS_PRODUCT_40(x, y, xy)
float ** mne_cmatrix_40(int nr, int nc)
void mne_free_cmatrix_40(float **m)
FwdEegSphereModel class declaration.
Fwd Thread Argument (FwdThreadArg) class declaration.
FwdBemModel class declaration.
#define FWD_BEM_CONSTANT_COLL
#define FWD_BEM_LIN_FIELD_URANKAR
#define FWD_BEM_IP_APPROACH_LIMIT
#define FWD_BEM_LIN_FIELD_FERGUSON
#define FWD_BEM_LINEAR_COLL
#define FWD_BEM_LIN_FIELD_SIMPLE
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
Forward modelling (BEM, MEG/EEG lead fields).
Coordinate transformation description.
FiffCoordTrans inverted() const
QSharedPointer< FiffDirNode > SPtr
void transpose_named_matrix()
QSharedPointer< FiffStream > SPtr
QSharedPointer< FiffTag > SPtr
Lookup record mapping a FIFF coordinate frame integer ID to its human-readable name.
static int fwd_mag_dipole_field_vec(float *rm, FwdCoilSet *coils, float **Bval, void *client)
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 int fwd_sphere_field_grad(float *rd, float Q[], FwdCoilSet *coils, float Bval[], float xgrad[], float ygrad[], float zgrad[], void *client)
static float ** fwd_bem_field_coeff(FwdBemModel *m, FwdCoilSet *coils)
static FwdBemModel * fwd_bem_load_homog_surface(const QString &name)
static int get_int(FIFFLIB::FiffStream::SPtr &stream, const FIFFLIB::FiffDirNode::SPtr &node, int what, int *res)
static int fwd_sphere_field_vec(float *rd, FwdCoilSet *coils, float **Bval, void *client)
static float ** fwd_bem_multi_solution(float **solids, float **gamma, int nsurf, int *ntri)
static double calc_beta(double *rk, double *rk1)
static void * meg_eeg_fwd_one_source_space(void *arg)
static void correct_auto_elements(MNELIB::MNESurface *surf, float **mat)
static void fwd_bem_field_grad_calc(float *rd, float *Q, FwdCoilSet *coils, FwdBemModel *m, float *xgrad, float *ygrad, float *zgrad)
static int fwd_bem_set_head_mri_t(FwdBemModel *m, const FIFFLIB::FiffCoordTrans &t)
static int fwd_bem_constant_collocation_solution(FwdBemModel *m)
static void fwd_bem_one_lin_field_coeff_uran(float *dest, float *dir, MNELIB::MNETriangle *tri, double *res)
static int fwd_bem_field(float *rd, float *Q, FwdCoilSet *coils, float *B, void *client)
static void fwd_bem_ip_modify_solution(float **solution, float **ip_solution, float ip_mult, int nsurf, int *ntri)
static double one_field_coeff(float *dest, float *normal, MNELIB::MNETriangle *tri)
static int fwd_bem_check_solids(float **angles, int ntri1, int ntri2, float desired)
static int fwd_bem_pot_grad_els(float *rd, float *Q, FwdCoilSet *els, float *pot, float *xgrad, float *ygrad, float *zgrad, void *client)
static float ** fwd_bem_solid_angles(const QList< MNELIB::MNESurface * > &surfs)
static float ** fwd_bem_lin_pot_coeff(const QList< MNELIB::MNESurface * > &surfs)
static FwdBemModel * fwd_bem_load_surfaces(const QString &name, int *kinds, int nkind)
static int fwd_bem_load_solution(const QString &name, int bem_method, FwdBemModel *m)
static void fwd_bem_lin_field_grad_calc(float *rd, float *Q, FwdCoilSet *coils, FwdBemModel *m, float *xgrad, float *ygrad, float *zgrad)
static void calc_f(double *xx, double *yy, double *f0, double *fx, double *fy)
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 float ** fwd_bem_homog_solution(float **solids, int ntri)
static double calc_gamma(double *rk, double *rk1)
static void fwd_bem_pot_grad_calc(float *rd, float *Q, FwdBemModel *m, FwdCoilSet *els, int all_surfs, float *xgrad, float *ygrad, float *zgrad)
MNELIB::MNESurface * fwd_bem_find_surface(int kind)
static void field_integrals(float *from, MNELIB::MNETriangle *to, double *I1p, double *T, double *S1, double *S2, double *f0, double *fx, double *fy)
void fwd_bem_free_solution()
static float fwd_bem_inf_pot(float *rd, float *Q, float *rp)
static void lin_pot_coeff(float *from, MNELIB::MNETriangle *to, double omega[3])
static float fwd_bem_inf_field_der(float *rd, float *Q, float *rp, float *dir, float *comp)
static const QString & fwd_bem_explain_method(int method)
static float ** fwd_bem_lin_field_coeff(FwdBemModel *m, FwdCoilSet *coils, int method)
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 int fwd_bem_linear_collocation_solution(FwdBemModel *m)
static int fwd_bem_specify_coils(FwdBemModel *m, FwdCoilSet *coils)
static void fwd_bem_field_calc(float *rd, float *Q, FwdCoilSet *coils, FwdBemModel *m, float *B)
static void fwd_bem_lin_field_calc(float *rd, float *Q, FwdCoilSet *coils, FwdBemModel *m, float *B)
static int fwd_bem_field_grad(float *rd, float Q[], FwdCoilSet *coils, float Bval[], float xgrad[], float ygrad[], float zgrad[], void *client)
static const QString & fwd_bem_explain_surface(int kind)
static int fwd_sphere_field(float *rd, float Q[], FwdCoilSet *coils, float Bval[], void *client)
static void fwd_bem_one_lin_field_coeff_simple(float *dest, float *normal, MNELIB::MNETriangle *source, double *res)
static void fwd_bem_pot_calc(float *rd, float *Q, FwdBemModel *m, FwdCoilSet *els, int all_surfs, float *pot)
void(* linFieldIntFunc)(float *dest, float *dir, MNELIB::MNETriangle *tri, double *res)
QList< MNELIB::MNESurface * > surfs
static void fwd_bem_lin_pot_grad_calc(float *rd, float *Q, FwdBemModel *m, FwdCoilSet *els, int all_surfs, float *xgrad, float *ygrad, float *zgrad)
static MNELIB::MNESurface * make_guesses(MNELIB::MNESurface *guess_surf, float guessrad, float *guess_r0, float grid, float exclude, float mindist)
static int fwd_bem_specify_els(FwdBemModel *m, FwdCoilSet *els)
static FwdBemModel * fwd_bem_load_three_layer_surfaces(const QString &name)
static void calc_magic(double u, double z, double A, double B, double *beta, double *D)
static int fwd_bem_pot_els(float *rd, float *Q, FwdCoilSet *els, float *pot, void *client)
static void fwd_bem_lin_pot_calc(float *rd, float *Q, FwdBemModel *m, FwdCoilSet *els, int all_surfs, float *pot)
static int fwd_mag_dipole_field(float *rm, float M[], FwdCoilSet *coils, float Bval[], void *client)
static int fwd_bem_compute_solution(FwdBemModel *m, int bem_method)
FIFFLIB::FiffCoordTrans head_mri_t
static float fwd_bem_inf_field(float *rd, float *Q, float *rp, float *dir)
static float fwd_bem_inf_pot_der(float *rd, float *Q, float *rp, float *comp)
static void fwd_bem_one_lin_field_coeff_ferg(float *dest, float *dir, MNELIB::MNETriangle *tri, double *res)
Mapping from infinite medium potentials to a particular set of coils or electrodes.
static void fwd_bem_free_coil_solution(void *user)
Single MEG or EEG sensor coil with integration points, weights, and coordinate frame.
Collection of FwdCoil objects representing a full MEG or EEG sensor array.
void fwd_free_coil_set_user_data()
FwdCoilSet * dup_coil_set(const FIFFLIB::FiffCoordTrans &t=FIFFLIB::FiffCoordTrans()) const
fwdUserFreeFunc user_data_free
This structure is used in the compensated field calculations.
MNELIB::MNECTFCompDataSet * set
static FwdCompData * fwd_make_comp_data(MNELIB::MNECTFCompDataSet *set, FwdCoilSet *coils, FwdCoilSet *comp_coils, fwdFieldFunc field, fwdVecFieldFunc vec_field, fwdFieldGradFunc field_grad, void *client, fwdUserFreeFunc client_free)
static int fwd_comp_field_grad(float *rd, float *Q, FwdCoilSet *coils, float *res, float *xgrad, float *ygrad, float *zgrad, void *client)
static int fwd_comp_field_vec(float *rd, FwdCoilSet *coils, float **res, void *client)
static int fwd_comp_field(float *rd, float *Q, FwdCoilSet *coils, float *res, void *client)
Multi-layer spherical head model for EEG forward computation.
static int fwd_eeg_multi_spherepot_coil1(float *rd, float *Q, FwdCoilSet *els, float *Vval, void *client)
static int fwd_eeg_spherepot_coil_vec(float *rd, FwdCoilSet *els, float **Vval_vec, void *client)
static int fwd_eeg_spherepot_coil(float *rd, float *Q, FwdCoilSet *els, float *Vval, void *client)
static int fwd_eeg_spherepot_grad_coil(float *rd, float Q[], FwdCoilSet *coils, float Vval[], float xgrad[], float ygrad[], float zgrad[], void *client)
Thread-local arguments for parallel forward field computation (source range, coils,...
fwdFieldGradFunc field_pot_grad
static void free_meg_multi_thread_duplicate(FwdThreadArg *one, bool bem_model)
static FwdThreadArg * create_eeg_multi_thread_duplicate(FwdThreadArg *one, bool bem_model)
static void free_eeg_multi_thread_duplicate(FwdThreadArg *one, bool bem_model)
fwdVecFieldFunc vec_field_pot
static FwdThreadArg * create_meg_multi_thread_duplicate(FwdThreadArg *one, bool bem_model)
MNELIB::MNESourceSpace * s
Collection of CTF third-order gradient compensation operators.
std::unique_ptr< MNECTFCompData > current
This defines a source space.
static MNESourceSpace * make_volume_source_space(const MNESurface &surf, float grid, float exclude, float mindist)
void triangle_coords(const Eigen::Vector3f &r, int tri, float &x, float &y, float &z) const
int project_to_surface(const MNEProjData *proj_data, const Eigen::Vector3f &r, float &distp) const
static MNESurface * read_bem_surface(const QString &name, int which, int add_geometry, float *sigmap)
int add_geometry_info(int do_normals, int check_too_many_neighbors)
Eigen::VectorXi nneighbor_tri
static double solid_angle(const Eigen::Vector3f &from, const MNELIB::MNETriangle &tri)
std::vector< MNETriangle > tris
Per-triangle geometric data for a cortical or BEM surface.
Eigen::MatrixX3f apply_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const