46 #include <QtAlgorithms>
51 #include <Eigen/Dense>
57 using namespace Eigen;
58 using namespace UTILSLIB;
59 using namespace FWDLIB;
61 #define MIN_1(a,b) ((a) < (b) ? (a) : (b))
70 #define VEC_DOT_1(x,y) ((x)[X_1]*(y)[X_1] + (x)[Y_1]*(y)[Y_1] + (x)[Z_1]*(y)[Z_1])
71 #define VEC_LEN_1(x) sqrt(VEC_DOT_1(x,x))
75 #define VEC_DIFF_1(from,to,diff) {\
76 (diff)[X_1] = (to)[X_1] - (from)[X_1];\
77 (diff)[Y_1] = (to)[Y_1] - (from)[Y_1];\
78 (diff)[Z_1] = (to)[Z_1] - (from)[Z_1];\
81 #define VEC_COPY_1(to,from) {\
82 (to)[X_1] = (from)[X_1];\
83 (to)[Y_1] = (from)[Y_1];\
84 (to)[Z_1] = (from)[Z_1];\
87 #define CROSS_PRODUCT_1(x,y,xy) {\
88 (xy)[X_1] = (x)[Y_1]*(y)[Z_1]-(y)[Y_1]*(x)[Z_1];\
89 (xy)[Y_1] = -((x)[X_1]*(y)[Z_1]-(y)[X_1]*(x)[Z_1]);\
90 (xy)[Z_1] = (x)[X_1]*(y)[Y_1]-(y)[X_1]*(x)[Y_1];\
93 #define MALLOC_1(x,t) (t *)malloc((x)*sizeof(t))
95 #define REALLOC_1(x,y,t) (t *)((x == NULL) ? malloc((y)*sizeof(t)) : realloc((x),(y)*sizeof(t)))
97 #define FREE(x) if ((char *)(x) != NULL) free((char *)(x))
99 #define ALLOC_DCMATRIX_1(x,y) mne_dmatrix_1((x),(y))
100 #define FREE_DCMATRIX_1(m) mne_free_dcmatrix_1((m))
102 #define ALLOC_CMATRIX_1(x,y) mne_cmatrix_1((x),(y))
107 #define FREE_CMATRIX_1(m) mne_free_cmatrix_1((m))
125 static void matrix_error_1(
int kind,
int nr,
int nc)
129 printf(
"Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
131 printf(
"Failed to allocate memory for a %d x %d matrix\n",nr,nc);
133 printf(
"Allocation error for a %d x %d matrix\n",nr,nc);
134 if (
sizeof(
void *) == 4) {
135 printf(
"This is probably because you seem to be using a computer with 32-bit architecture.\n");
136 printf(
"Please consider moving to a 64-bit platform.");
138 printf(
"Cannot continue. Sorry.\n");
142 float **mne_cmatrix_1(
int nr,
int nc)
149 m = MALLOC_1(nr,
float *);
150 if (!m) matrix_error_1(1,nr,nc);
151 whole = MALLOC_1(nr*nc,
float);
152 if (!whole) matrix_error_1(2,nr,nc);
159 double **mne_dmatrix_1(
int nr,
int nc)
166 m = MALLOC_1(nr,
double *);
167 if (!m) matrix_error_1(1,nr,nc);
168 whole = MALLOC_1(nr*nc,
double);
169 if (!whole) matrix_error_1(2,nr,nc);
176 void mne_free_cmatrix_1 (
float **m)
184 void mne_free_dcmatrix_1 (
double **m)
193 #define MAXTERMS 1000
197 static int terms = 0;
204 FwdEegSphereModel::FwdEegSphereModel()
223 if (!p_FwdEegSphereModel.
name.isEmpty())
224 this->
name = p_FwdEegSphereModel.
name;
225 if (p_FwdEegSphereModel.nlayer() > 0) {
226 for (
k = 0;
k < p_FwdEegSphereModel.nlayer();
k++)
229 VEC_COPY_1(this->
r0,p_FwdEegSphereModel.
r0);
230 if (p_FwdEegSphereModel.
nterms > 0) {
231 this->
fn = VectorXd(p_FwdEegSphereModel.
nterms);
233 for (
k = 0;
k < p_FwdEegSphereModel.
nterms;
k++)
234 this->
fn[k] = p_FwdEegSphereModel.
fn[
k];
236 if (p_FwdEegSphereModel.
nfit > 0) {
237 this->
mu = VectorXf(p_FwdEegSphereModel.
nfit);
238 this->lambda = VectorXf(p_FwdEegSphereModel.
nfit);
239 this->
nfit = p_FwdEegSphereModel.
nfit;
240 for (
k = 0;
k < p_FwdEegSphereModel.
nfit;
k++) {
241 this->
mu[
k] = p_FwdEegSphereModel.
mu[
k];
242 this->lambda[
k] = p_FwdEegSphereModel.lambda[
k];
250 FwdEegSphereModel* FwdEegSphereModel::fwd_create_eeg_sphere_model(
const QString& name,
252 const VectorXf& rads,
253 const VectorXf& sigmas)
262 for (
int k = 0;
k < nlayer;
k++) {
266 new_model->
layers.append(layer);
271 std::sort(new_model->
layers.begin(), new_model->
layers.end(), FwdEegSphereLayer::comp_layers);
276 float R = new_model->
layers[nlayer-1].rad;
277 float rR = new_model->
layers[nlayer-1].rel_rad;
278 for (
int k = 0;
k < nlayer;
k++) {
298 if (eeg_model_name.isEmpty())
299 eeg_model_name = QString(
"Default");
309 printf(
"Using EEG sphere model \"%s\" with scalp radius %7.1f mm\n",
310 eeg_model->
name.toUtf8().constData(),1000*eeg_sphere_rad);
324 fitUser FwdEegSphereModel::new_fit_user(
int nfit,
int nterms)
328 u->y = MALLOC_1(
nterms-1,
double);
329 u->resi = MALLOC_1(
nterms-1,
double);
332 u->vv = ALLOC_DCMATRIX_1(
nfit-1,
nfit-1);
333 u->sing = MALLOC_1(
nfit,
double);
334 u->fn = MALLOC_1(
nterms,
double);
335 u->w = MALLOC_1(
nterms,
double);
345 MatrixXd M,Mn,help,Mm;
346 static MatrixXd mat1;
347 static MatrixXd mat2;
348 static MatrixXd mat3;
352 static VectorXd cr_mult;
361 if (this->nlayer() == 0 || this->nlayer() == 1)
367 if (this->nlayer() == 2) {
370 div_mult = 2.0*n + 1;
371 b = pow(this->
layers[0].rel_rad,div_mult);
372 return div_mult/((n1 + n*rel1) +
b*n1*(rel1-1.0));
374 else if (this->nlayer() == 3) {
378 div_mult = 2.0*n + 1.0;
379 b = pow(this->
layers[0].rel_rad,div_mult);
380 c = pow(this->
layers[1].rel_rad,div_mult);
381 div_mult = div_mult*div_mult;
382 div = (
b*n*n1*(rel1-1.0)*(rel2-1.0) + c*(rel1*n + n1)*(rel2*n + n1))/c +
383 n1*(
b*(rel1-1.0)*(rel2*n1 + n) + c*(rel1*n + n1)*(rel2-1.0));
391 c1.resize(this->nlayer()-1);
392 c2.resize(this->nlayer()-1);
393 cr.resize(this->nlayer()-1);
394 cr_mult.resize(this->nlayer()-1);
395 for (
k = 0;
k < this->nlayer()-1;
k++) {
398 cr_mult[
k] = this->
layers[
k].rel_rad;
400 cr_mult[
k] = cr_mult[
k]*cr_mult[
k];
402 if (mat1.cols() == 0)
403 mat1 = MatrixXd(2,2);
404 if (mat2.cols() == 0)
405 mat2 = MatrixXd(2,2);
406 if (mat3.cols() == 0)
407 mat3 = MatrixXd(2,2);
412 for (
k = 0;
k < this->nlayer()-1;
k++)
413 cr[
k] = cr[
k]*cr_mult[
k];
420 M(0,0) = M(1,1) = 1.0;
421 M(0,1) = M(1,0) = 0.0;
423 div_mult = 2.0*n + 1.0;
426 for (
k = this->nlayer()-2;
k >= 0;
k--) {
428 Mm(0,0) = (n + n1*c1[
k]);
429 Mm(0,1) = n1*c2[
k]/cr[
k];
430 Mm(1,0) = n*c2[
k]*cr[
k];
431 Mm(1,1) = n1 + n*c1[
k];
433 Mn(0,0) = Mm(0,0)*M(0,0) + Mm(0,1)*M(1,0);
434 Mn(0,1) = Mm(0,0)*M(0,1) + Mm(0,1)*M(1,1);
435 Mn(1,0) = Mm(1,0)*M(0,0) + Mm(1,1)*M(1,0);
436 Mn(1,1) = Mm(1,0)*M(0,1) + Mm(1,1)*M(1,1);
443 return n*div/(n*M(1,1) + n1*M(1,0));
448 void FwdEegSphereModel::next_legen(
int n,
double x,
double *p0,
double *p01,
double *p1,
double *p11)
462 *p0 = ((2*n-1)*x*help0 - (n-1)*(*p01))/n;
463 *p1 = ((2*n-1)*x*help1 - n*(*p11))/(n-1);
482 void FwdEegSphereModel::calc_pot_components(
double beta,
double cgamma,
double *Vrp,
double *Vtp,
const Eigen::VectorXd& fn,
int nterms)
486 double p0,p01,p1,p11;
491 p0 = p01 = p1 = p11 = 0.0;
492 for (n = 1; n <=
nterms; n++) {
498 next_legen (n,cgamma,&p0,&p01,&p1,&p11);
499 multn = betan*
fn[n-1];
501 Vt = Vt + multn*p1/n;
511 int FwdEegSphereModel::fwd_eeg_multi_spherepot(
float *rd,
float *Q,
float **el,
int neeg,
float *Vval,
void *client)
534 float my_rd[3],pos[3];
536 float pos2,rd_len,pos_len;
537 double beta,cos_gamma,Vr,Vt;
538 float vec1[3],vec2[3],v1,v2;
539 float cos_beta,Qr,Qt,Q2,c;
540 float pi4_inv = 0.25/M_PI;
545 if (m->
fn.size() == 0 || m->
nterms != MAXTERMS) {
546 m->
fn.resize(MAXTERMS);
548 for (
k = 0;
k < MAXTERMS;
k++)
554 for (p = 0; p < 3; p++)
555 my_rd[p] = rd[p] - m->
r0[p];
557 rd_len = VEC_LEN_1(rd);
562 if (rd_len >= m->
layers[0].rad) {
563 for (
k = 0;
k < neeg;
k++)
570 c = VEC_DOT_1(rd,Q)/(rd_len*sqrt(Q2));
571 if ((1.0-c*c) < SIN_EPS) {
577 vec1[0] = vec1[1] = vec1[2] = 0.0;
580 CROSS_PRODUCT_1(rd,Q,vec1);
581 v1 = VEC_LEN_1(vec1);
585 for (
k = 0;
k < neeg;
k++) {
586 for (p = 0; p < 3; p++)
587 pos[p] = el[
k][p] - m->
r0[p];
592 pos_len = m->
layers[m->nlayer()-1].rad/VEC_LEN_1(pos);
594 printf(
"%10.4f %10.4f %10.4f %10.4f\n",pos_len,1000*pos[0],1000*pos[1],1000*pos[2]);
596 for (p = 0; p < 3; p++)
597 pos[p] = pos_len*pos[p];
599 pos2 = VEC_DOT_1(pos,pos);
600 pos_len = sqrt(pos2);
604 cos_gamma = VEC_DOT_1(pos,rd)/(rd_len*pos_len);
605 beta = rd_len/pos_len;
606 calc_pot_components(beta,cos_gamma,&Vr,&Vt,m->
fn,m->
nterms);
611 CROSS_PRODUCT_1(rd,pos,vec2);
612 v2 = VEC_LEN_1(vec2);
615 cos_beta = VEC_DOT_1(vec1,vec2)/(v1*v2);
619 Qr = VEC_DOT_1(Q,rd)/rd_len;
620 Qt = sqrt(Q2 - Qr*Qr);
622 Vval[
k] = pi4_inv*(Qr*Vr + Qt*cos_beta*Vt)/pos2;
628 if (m->nlayer() > 0) {
629 sigmaM_inv = 1.0/m->
layers[m->nlayer()-1].sigma;
630 for (
k = 0;
k < neeg;
k++)
631 Vval[
k] = Vval[
k]*sigmaM_inv;
638 int FwdEegSphereModel::fwd_eeg_multi_spherepot_coil1(
float *rd,
float *Q,
FwdCoilSet *els,
float *Vval,
void *client)
647 float *vval_one = NULL,val;
652 for (
k = 0;
k < els->ncoil;
k++, el++) {
655 if (el->
np > nvval) {
656 vval_one = REALLOC_1(vval_one,el->
np,
float);
659 if (fwd_eeg_multi_spherepot(rd,Q,el->
rmag,el->
np,vval_one,client) != OK) {
663 for (c = 0, val = 0.0; c < el->
np; c++)
664 val += el->
w[c]*vval_one[c];
678 float fact = 0.25f/(float)M_PI;
681 float rrd,rd2,rd2_inv,r,r2,ra,rda;
686 float orig_rd[3],scaled_rd[3];
687 float pos[3],pos_len;
691 for (p = 0; p < 3; p++)
692 orig_rd[p] = rd[p] - m->
r0[p];
697 for (
k = 0 ;
k < neeg ;
k++) {
698 Vval_vec[X_1][
k] = 0.0;
699 Vval_vec[Y_1][
k] = 0.0;
700 Vval_vec[Z_1][
k] = 0.0;
705 if (VEC_LEN_1(orig_rd) >= m->
layers[0].rad)
712 eeg_set_homog_sphere_model();
717 for (eq = 0; eq < m->
nfit; eq++) {
721 for (p = 0; p < 3; p++)
722 rd[p] = m->
mu[eq]*orig_rd[p];
724 rd2 = VEC_DOT_1(rd,rd);
730 for (
k = 0;
k < neeg ;
k++) {
733 for (p = 0; p < 3; p++)
734 pos[p] = this_pos[p] - m->
r0[p];
739 pos_len = m->
layers[m->nlayer()-1].rad/VEC_LEN_1(pos);
740 for (p = 0; p < 3; p++)
741 pos[p] = pos_len*pos[p];
747 VEC_DIFF_1 (rd,this_pos,a_vec);
751 a2 = VEC_DOT_1(a_vec,a_vec); a = sqrt(a2);
753 r2 = VEC_DOT_1(this_pos,this_pos); r = sqrt(r2);
754 rrd = VEC_DOT_1(this_pos,rd);
761 c1 = a3*rda + 1.0/a - 1.0/r;
762 c2 = a3 + (a+r)/(r*F);
769 Vval_vec[X_1][
k] = Vval_vec[X_1][
k] + m->lambda[eq]*rd2_inv*(m1*rd[X_1] + m2*this_pos[X_1]);
770 Vval_vec[Y_1][
k] = Vval_vec[Y_1][
k] + m->lambda[eq]*rd2_inv*(m1*rd[Y_1] + m2*this_pos[Y_1]);
771 Vval_vec[Z_1][
k] = Vval_vec[Z_1][
k] + m->lambda[eq]*rd2_inv*(m1*rd[Z_1] + m2*this_pos[Z_1]);
777 for (
k = 0;
k < neeg;
k++) {
778 Vval_vec[X_1][
k] = fact*Vval_vec[X_1][
k];
779 Vval_vec[Y_1][
k] = fact*Vval_vec[Y_1][
k];
780 Vval_vec[Z_1][
k] = fact*Vval_vec[Z_1][
k];
789 float **vval_one = NULL;
795 for (
k = 0;
k < els->ncoil;
k++, el++) {
798 if (el->
np > nvval) {
799 FREE_CMATRIX_1(vval_one);
800 vval_one = ALLOC_CMATRIX_1(3,el->
np);
804 FREE_CMATRIX_1(vval_one);
807 for (p = 0; p < 3; p++) {
808 for (c = 0, val = 0.0; c < el->
np; c++)
809 val += el->
w[c]*vval_one[p][c];
810 Vval_vec[p][
k] = val;
814 FREE_CMATRIX_1(vval_one);
820 int FwdEegSphereModel::fwd_eeg_spherepot_grad_coil(
float *rd,
float Q[],
FwdCoilSet *coils,
float Vval[],
float xgrad[],
float ygrad[],
float zgrad[],
void *client)
831 float step2 = 2*step;
839 for (p = 0; p < 3; p++) {
840 VEC_COPY_1(my_rd,rd);
841 my_rd[p] = my_rd[p] + step;
844 VEC_COPY_1(my_rd,rd);
845 my_rd[p] = my_rd[p] - step;
848 for (q = 0; q < coils->ncoil; q++)
849 grads[p][q] = (grads[p][q]-Vval[q])/step2;
874 float fact = 0.25f/M_PI;
877 float rrd,rd2,rd2_inv,r,r2,ra,rda;
879 float c1,c2,m1,m2,f1,f2;
882 float orig_rd[3],scaled_rd[3];
883 float pos[3],pos_len;
887 for (p = 0; p < 3; p++)
888 orig_rd[p] = rd[p] - m->
r0[p];
893 for (
k = 0 ;
k < neeg ;
k++)
898 if (VEC_LEN_1(orig_rd) >= m->
layers[0].rad)
905 eeg_set_homog_sphere_model();
910 for (eq = 0; eq < m->
nfit; eq++) {
914 for (p = 0; p < 3; p++)
915 rd[p] = m->
mu[eq]*orig_rd[p];
917 rd2 = VEC_DOT_1(rd,rd);
920 f1 = VEC_DOT_1(rd,Q);
924 for (
k = 0;
k < neeg ;
k++) {
927 for (p = 0; p < 3; p++)
928 pos[p] = this_pos[p] - m->
r0[p];
933 pos_len = m->
layers[m->nlayer()-1].rad/VEC_LEN_1(pos);
934 for (p = 0; p < 3; p++)
935 pos[p] = pos_len*pos[p];
941 VEC_DIFF_1 (rd,this_pos,a_vec);
945 a2 = VEC_DOT_1(a_vec,a_vec); a = sqrt(a2);
947 r2 = VEC_DOT_1(this_pos,this_pos); r = sqrt(r2);
948 rrd = VEC_DOT_1(this_pos,rd);
955 c1 = a3*rda + 1.0/a - 1.0/r;
956 c2 = a3 + (a+r)/(r*F);
963 f2 = VEC_DOT_1(this_pos,Q);
964 Vval[
k] = Vval[
k] + m->lambda[eq]*rd2_inv*(m1*f1 + m2*f2);
970 for (
k = 0;
k < neeg;
k++)
971 Vval[
k] = fact*Vval[
k];
985 for (
k = 0;
k < els->ncoil;
k++, el++) {
988 if (el->
np > nvval) {
989 vval_one.resize(el->
np);
995 for (c = 0, val = 0.0; c < el->
np; c++)
996 val += el->
w[c]*vval_one[c];
1014 for (
int k = 0;
k < this->nlayer();
k++)
1017 if (fit_berg_scherg) {
1019 printf(
"Equiv. model fitting -> ");
1020 printf(
"RV = %g %%\n",100*rv);
1021 for (
int k = 0;
k <
nfit;
k++)
1022 printf(
"mu%d = %g\tlambda%d = %g\n",
k+1,this->
mu[k],
k+1,this->
layers[this->nlayer()-1].sigma*this->lambda[
k]);
1028 printf(
"Defined EEG sphere model with rad = %7.2f mm\n", 1000.0*rad);
1032 Eigen::MatrixXd toDoubleEigenMatrix(
double **mat,
const int m,
const int n)
1034 Eigen::MatrixXd eigen_mat(m,n);
1036 for (
int i = 0; i < m; ++i)
1037 for (
int j = 0; j < n; ++j)
1038 eigen_mat(i,j) = mat[i][j];
1043 void fromDoubleEigenMatrix(
const Eigen::MatrixXd& from_mat,
double **to_mat,
const int m,
const int n)
1045 for (
int i = 0; i < m; ++i)
1046 for (
int j = 0; j < n; ++j)
1047 to_mat[i][j] = from_mat(i,j);
1050 void fromDoubleEigenMatrix(
const Eigen::MatrixXd& from_mat,
double **to_mat)
1052 fromDoubleEigenMatrix(from_mat, to_mat, from_mat.rows(), from_mat.cols());
1055 void fromDoubleEigenVector(
const Eigen::VectorXd& from_vec,
double *to_vec,
const int n)
1057 for (
int i = 0; i < n; ++i)
1058 to_vec[i] = from_vec[i];
1061 void fromDoubleEigenVector(
const Eigen::VectorXd& from_vec,
double *to_vec)
1063 fromDoubleEigenVector(from_vec, to_vec, from_vec.size());
1067 static double dot_dvectors (
double *v1,
1071 double result = 0.0;
1074 for (
k = 0;
k < nn;
k++)
1075 result = result + v1[
k]*v2[
k];
1079 static int c_dsvd(
double **mat,
1102 int udim = MIN_1(m,n);
1104 Eigen::MatrixXd eigen_mat = toDoubleEigenMatrix(mat, m, n);
1107 Eigen::JacobiSVD< Eigen::MatrixXd > svd(eigen_mat,Eigen::ComputeFullU | Eigen::ComputeFullV);
1109 fromDoubleEigenVector(svd.singularValues(), sing, svd.singularValues().size());
1112 fromDoubleEigenMatrix(svd.matrixU().transpose(), uu, udim, m);
1115 fromDoubleEigenMatrix(svd.matrixV().transpose(), vv, n, n);
1140 static int comp_pars(
const void *p1,
const void *p2)
1148 if (v1->mu > v2->mu)
1150 else if (v1->mu < v2->mu)
1157 static void sort_parameters(VectorXd& mu,VectorXd& lambda,
int nfit)
1164 for (
int k = 0;
k < nfit;
k++) {
1166 pars[
k].lambda = lambda[
k];
1171 for (
int k = 0;
k < nfit;
k++) {
1173 lambda[
k] = pars[
k].lambda;
1180 static bool report_fit(
int loop,
1181 const VectorXd &fitpar,
1189 for (
int k = 0;
k < fitpar.size();
k++)
1190 printf(
"%g ",mu[
k]);
1191 printf(
"%g\n",Smin);
1197 static MatrixXd get_initial_simplex(
const VectorXd &pars,
1198 double simplex_size)
1201 int npar = pars.size();
1203 MatrixXd simplex = MatrixXd::Zero(npar+1,npar);
1205 simplex.rowwise() += pars.transpose();
1207 for (
int k = 1;
k < npar+1;
k++)
1208 simplex(
k,
k-1) += simplex_size;
1213 void FwdEegSphereModel::compose_linear_fitting_data(
const VectorXd& mu,
fitUser u)
1221 for (
k = 0;
k < u->nterms-1;
k++) {
1223 mu1n = pow(
mu[0],k1);
1224 u->y[
k] = u->w[
k]*(u->fn[
k+1] - mu1n*u->fn[0]);
1225 for (p = 0; p < u->nfit-1; p++)
1226 u->M[
k][p] = u->w[
k]*(pow(
mu[p+1],k1)-mu1n);
1231 double FwdEegSphereModel::compute_linear_parameters(
const VectorXd& mu,
1240 VectorXd vec(u->nfit-1);
1243 compose_linear_fitting_data(
mu,u);
1245 c_dsvd(u->M,u->nterms-1,u->nfit-1,u->sing,u->uu,u->vv);
1249 for (
k = 0;
k < u->nterms-1;
k++)
1250 u->resi[
k] = u->y[
k];
1252 for (p = 0; p < u->nfit-1; p++) {
1253 vec[p] = dot_dvectors(u->uu[p],u->y,u->nterms-1);
1254 for (
k = 0;
k < u->nterms-1;
k++)
1255 u->resi[
k] = u->resi[
k] - u->uu[p][
k]*vec[p];
1256 vec[p] = vec[p]/u->sing[p];
1259 for (p = 0; p < u->nfit-1; p++) {
1260 for (q = 0, sum = 0.0; q < u->nfit-1; q++)
1261 sum += u->vv[q][p]*vec[q];
1264 for (p = 1, sum = 0.0; p < u->nfit; p++)
1266 lambda[0] = u->fn[0] - sum;
1267 return dot_dvectors(u->resi,u->resi,u->nterms-1)/dot_dvectors(u->y,u->y,u->nterms-1);
1271 double FwdEegSphereModel::one_step (
const VectorXd& mu,
const void *user_data)
1281 for (
k = 0;
k < u->nfit;
k++) {
1282 if (std::fabs(
mu[
k]) > 1.0)
1288 compose_linear_fitting_data(
mu,u);
1292 c_dsvd(u->M,u->nterms-1,u->nfit-1,u->sing,u->uu,NULL);
1296 for (
k = 0;
k < u->nterms-1;
k++)
1297 u->resi[
k] = u->y[
k];
1298 for (p = 0; p < u->nfit-1; p++) {
1299 dot = dot_dvectors(u->uu[p],u->y,u->nterms-1);
1300 for (
k = 0;
k < u->nterms-1;
k++)
1301 u->resi[
k] = u->resi[
k] - u->uu[p][
k]*dot;
1306 return dot_dvectors(u->resi,u->resi,u->nterms-1);
1323 double simplex_size = 0.01;
1330 int max_eval = 1000;
1335 printf(
"fwd_fit_berg_scherg does not work with less than two equivalent sources.");
1343 u->fn[
k] = this->fwd_eeg_get_multi_sphere_model_coeff(
k+1);
1348 rd = R = this->
layers[0].rad;
1349 for (k = 1;
k < this->nlayer();
k++) {
1350 if (this->
layers[k].rad > R)
1352 if (this->
layers[k].rad < rd)
1362 u->w[
k-1] = pow(f,
k);
1368 u->w[
k-1] = sqrt((2.0*
k+1)*(3.0*
k+1.0)/
k)*pow(f,(
k-1.0));
1374 func_val = VectorXd(
nfit+1);
1375 lambda = VectorXd(
nfit);
1384 mu[
k] = (rand() / (RAND_MAX + 1.0))*f;
1387 simplex = get_initial_simplex(
mu,simplex_size);
1389 func_val[
k] = one_step(
static_cast<VectorXd
>(simplex.row(
k)),u);
1394 if (!(res = SimplexAlgorithm::simplex_minimize<double>( simplex,
1406 mu[
k] = simplex(0,
k);
1411 rv = compute_linear_parameters(
mu,lambda,u);
1413 sort_parameters(
mu,lambda,
nfit);
1415 printf(
"RV = %g %%\n",100*rv);
1417 this->mu.resize(
nfit);
1418 this->lambda.resize(
nfit);
1421 this->mu[
k] =
mu[
k];
1425 this->lambda[
k] = lambda[
k]/this->
layers[this->nlayer()-1].sigma;
1427 printf(
"lambda%d = %g\tmu%d = %g\n",
k+1,lambda[
k],
k+1,
mu[
k]);
1437 FREE_DCMATRIX_1(u->M);
1438 FREE_DCMATRIX_1(u->uu);
1439 FREE_DCMATRIX_1(u->vv);