2 #include <fwd/fwd_types.h>
6 #include "../c/mne_meas_data.h"
7 #include "../c/mne_meas_data_set.h"
18 #include <Eigen/Dense>
21 #include <QCoreApplication>
24 #define _USE_MATH_DEFINES
27 using namespace Eigen;
28 using namespace FIFFLIB;
29 using namespace MNELIB;
30 using namespace FWDLIB;
31 using namespace INVERSELIB;
35 #ifndef FIFFV_COIL_CTF_GRAD
36 #define FIFFV_COIL_CTF_GRAD 5001
39 #ifndef FIFFV_COIL_CTF_REF_MAG
40 #define FIFFV_COIL_CTF_REF_MAG 5002
43 #ifndef FIFFV_COIL_CTF_REF_GRAD
44 #define FIFFV_COIL_CTF_REF_GRAD 5003
47 #ifndef FIFFV_COIL_CTF_OFFDIAG_REF_GRAD
48 #define FIFFV_COIL_CTF_OFFDIAG_REF_GRAD 5004
71 #define MALLOC_3(x,t) (t *)malloc((x)*sizeof(t))
72 #define REALLOC_3(x,y,t) (t *)((x == NULL) ? malloc((y)*sizeof(t)) : realloc((x),(y)*sizeof(t)))
73 #define FREE_3(x) if ((char *)(x) != NULL) free((char *)(x))
78 #define ALLOC_FLOAT_3(x) MALLOC_3(x,float)
80 #define ALLOC_DCMATRIX_3(x,y) mne_dmatrix_3((x),(y))
81 #define ALLOC_CMATRIX_3(x,y) mne_cmatrix_3((x),(y))
82 #define FREE_CMATRIX_3(m) mne_free_cmatrix_3((m))
83 #define FREE_DCMATRIX_3(m) mne_free_dcmatrix_3((m))
85 static void matrix_error_3(
int kind,
int nr,
int nc)
89 printf(
"Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
91 printf(
"Failed to allocate memory for a %d x %d matrix\n",nr,nc);
93 printf(
"Allocation error for a %d x %d matrix\n",nr,nc);
94 if (
sizeof(
void *) == 4) {
95 printf(
"This is probably because you seem to be using a computer with 32-bit architecture.\n");
96 printf(
"Please consider moving to a 64-bit platform.");
98 printf(
"Cannot continue. Sorry.\n");
102 float **mne_cmatrix_3 (
int nr,
int nc)
109 m = MALLOC_3(nr,
float *);
110 if (!m) matrix_error_3(1,nr,nc);
111 whole = MALLOC_3(nr*nc,
float);
112 if (!whole) matrix_error_3(2,nr,nc);
119 double **mne_dmatrix_3(
int nr,
int nc)
126 m = MALLOC_3(nr,
double *);
127 if (!m) matrix_error_3(1,nr,nc);
128 whole = MALLOC_3(nr*nc,
double);
129 if (!whole) matrix_error_3(2,nr,nc);
136 void mne_free_dcmatrix_3 (
double **m)
148 #define VEC_DOT_3(x,y) ((x)[X_3]*(y)[X_3] + (x)[Y_3]*(y)[Y_3] + (x)[Z_3]*(y)[Z_3])
149 #define VEC_LEN_3(x) sqrt(VEC_DOT_3(x,x))
155 #define VEC_DIFF_3(from,to,diff) {\
156 (diff)[X_3] = (to)[X_3] - (from)[X_3];\
157 (diff)[Y_3] = (to)[Y_3] - (from)[Y_3];\
158 (diff)[Z_3] = (to)[Z_3] - (from)[Z_3];\
161 #define VEC_COPY_3(to,from) {\
162 (to)[X_3] = (from)[X_3];\
163 (to)[Y_3] = (from)[Y_3];\
164 (to)[Z_3] = (from)[Z_3];\
167 #define CROSS_PRODUCT_3(x,y,xy) {\
168 (xy)[X_3] = (x)[Y_3]*(y)[Z_3]-(y)[Y_3]*(x)[Z_3];\
169 (xy)[Y_3] = -((x)[X_3]*(y)[Z_3]-(y)[X_3]*(x)[Z_3]);\
170 (xy)[Z_3] = (x)[X_3]*(y)[Y_3]-(y)[X_3]*(x)[Y_3];\
175 #define MIN_3(a,b) ((a) < (b) ? (a) : (b))
177 void mne_transpose_square_3(
float **mat,
int n)
185 for (j = 1; j < n; j++)
186 for (
k = 0;
k < j;
k++) {
188 mat[j][
k] = mat[
k][j];
194 float mne_dot_vectors_3(
float *v1,
201 float res = sdot(&nn,v1,&one,v2,&one);
207 for (
k = 0;
k < nn;
k++)
208 res = res + v1[
k]*v2[
k];
213 void mne_add_scaled_vector_to_3(
float *v1,
float scale,
float *v2,
int nn)
217 float fscale = scale;
219 saxpy(&nn,&fscale,v1,&one,v2,&one);
222 for (
k = 0;
k < nn;
k++)
223 v2[
k] = v2[
k] + scale*v1[
k];
228 double **mne_dmatt_dmat_mult2_3 (
double **m1,
double **m2,
int d1,
int d2,
int d3)
233 double **result = ALLOC_DCMATRIX_3(d1,d3);
240 dgemm (transa,transb,&d3,&d1,&d2,
241 &one,m2[0],&d3,m1[0],&d1,&zero,result[0],&d3);
248 for (j = 0; j < d1; j++)
249 for (
k = 0;
k < d3;
k++) {
251 for (p = 0; p < d2; p++)
252 sum = sum + m1[p][j]*m2[p][
k];
259 float **mne_mat_mat_mult_3 (
float **m1,
float **m2,
int d1,
int d2,
int d3)
265 float **result = ALLOC_CMATRIX_3(d1,d3);
270 sgemm (transa,transb,&d3,&d1,&d2,
271 &one,m2[0],&d3,m1[0],&d2,&zero,result[0],&d3);
274 float **result = ALLOC_CMATRIX_3(d1,d3);
278 for (j = 0; j < d1; j++)
279 for (
k = 0;
k < d3;
k++) {
281 for (p = 0; p < d2; p++)
282 sum = sum + m1[j][p]*m2[p][
k];
289 void mne_mat_vec_mult2_3(
float **m,
float *v,
float *result,
int d1,
int d2)
298 for (j = 0; j < d1; j++)
299 result[j] = mne_dot_vectors_3(m[j],v,d2);
305 QString mne_name_list_to_string_3(
const QStringList& list)
310 int nlist = list.size();
312 if (nlist == 0 || list.isEmpty())
315 for (
int k = 0;
k < nlist-1;
k++) {
319 res += list[nlist-1];
323 QString mne_channel_names_to_string_3(
const QList<FiffChInfo>& chs,
int nch)
334 for (
k = 0;
k < nch;
k++)
335 names.append(chs[
k].ch_name);
336 res = mne_name_list_to_string_3(names);
341 void mne_string_to_name_list_3(
const QString& s, QStringList& listp,
int &nlistp)
348 if (!s.isEmpty() && s.size() > 0) {
353 nlistp = list.size();
380 for (j = 0; j < nrow; j++)
381 for (
k = 0;
k < ncol;
k++) {
382 val = std::fabs(dense[j][
k]);
387 small = maxval * std::fabs(small);
389 small = std::fabs(small);
391 for (j = 0, nz = 0; j < nrow; j++)
392 for (
k = 0;
k < ncol;
k++) {
393 if (std::fabs(dense[j][
k]) > small)
398 printf(
"No nonzero elements found.");
401 if (stor_type == FIFFTS_MC_CCS) {
402 size = nz*(
sizeof(fiff_float_t) +
sizeof(fiff_int_t)) +
403 (ncol+1)*(
sizeof(fiff_int_t));
405 else if (stor_type == FIFFTS_MC_RCS) {
406 size = nz*(
sizeof(fiff_float_t) +
sizeof(fiff_int_t)) +
407 (nrow+1)*(
sizeof(fiff_int_t));
410 printf(
"Unknown sparse matrix storage type: %d",stor_type);
414 sparse->
coding = stor_type;
418 sparse->
data = (
float *)malloc(size);
419 sparse->
inds = (
int *)(sparse->
data+nz);
422 if (stor_type == FIFFTS_MC_RCS) {
423 for (j = 0, nz = 0; j < nrow; j++) {
425 for (
k = 0;
k < ncol;
k++)
426 if (std::fabs(dense[j][
k]) > small) {
427 sparse->
data[nz] = dense[j][
k];
430 sparse->
inds[nz++] =
k;
432 sparse->
ptrs[j] = ptr;
434 sparse->
ptrs[nrow] = nz;
435 for (j = nrow - 1; j >= 0; j--)
436 if (sparse->
ptrs[j] < 0)
437 sparse->
ptrs[j] = sparse->
ptrs[j+1];
439 else if (stor_type == FIFFTS_MC_CCS) {
440 for (
k = 0, nz = 0;
k < ncol;
k++) {
442 for (j = 0; j < nrow; j++)
443 if (std::fabs(dense[j][
k]) > small) {
444 sparse->
data[nz] = dense[j][
k];
447 sparse->
inds[nz++] = j;
449 sparse->
ptrs[
k] = ptr;
451 sparse->
ptrs[ncol] = nz;
452 for (
k = ncol-1;
k >= 0;
k--)
453 if (sparse->
ptrs[
k] < 0)
475 return c->cov_diag != NULL;
478 void mne_scale_vector_3 (
double scale,
float *v,
int nn)
482 float fscale = scale;
484 sscal(&nn,&fscale,v,&one);
487 for (
k = 0;
k < nn;
k++)
493 Eigen::MatrixXf toFloatEigenMatrix_3(
float **mat,
const int m,
const int n)
495 Eigen::MatrixXf eigen_mat(m,n);
497 for (
int i = 0; i < m; ++i)
498 for (
int j = 0; j < n; ++j)
499 eigen_mat(i,j) = mat[i][j];
504 void fromFloatEigenMatrix_3(
const Eigen::MatrixXf& from_mat,
float **& to_mat,
const int m,
const int n)
506 for (
int i = 0; i < m; ++i)
507 for (
int j = 0; j < n; ++j)
508 to_mat[i][j] = from_mat(i,j);
511 void fromFloatEigenMatrix_3(
const Eigen::MatrixXf& from_mat,
float **& to_mat)
513 fromFloatEigenMatrix_3(from_mat, to_mat, from_mat.rows(), from_mat.cols());
516 void fromFloatEigenVector_3(
const Eigen::VectorXf& from_vec,
float *to_vec,
const int n)
518 for (
int i = 0; i < n; ++i)
519 to_vec[i] = from_vec[i];
522 float **mne_lu_invert_3(
float **mat,
int dim)
528 Eigen::MatrixXf eigen_mat = toFloatEigenMatrix_3(mat, dim, dim);
529 Eigen::MatrixXf eigen_mat_inv = eigen_mat.inverse();
530 fromFloatEigenMatrix_3(eigen_mat_inv, mat);
534 void mne_free_cmatrix_3 (
float **m)
542 int mne_svd_3(
float **mat,
567 int udim = MIN_3(m,n);
569 Eigen::MatrixXf eigen_mat = toFloatEigenMatrix_3(mat, m, n);
572 Eigen::JacobiSVD< Eigen::MatrixXf > svd(eigen_mat ,Eigen::ComputeFullU | Eigen::ComputeFullV);
574 fromFloatEigenVector_3(svd.singularValues(), sing, svd.singularValues().size());
577 fromFloatEigenMatrix_3(svd.matrixU().transpose(), uu, udim, m);
580 fromFloatEigenMatrix_3(svd.matrixV().transpose(), vv, m, n);
596 delete c->cov_sparse;
598 FREE_CMATRIX_3(c->eigen);
600 FREE_3(c->inv_lambda);
614 int mne_get_values_from_data_3 (
float time,
634 for (ch = 0; ch < nch; ch++) {
638 if (std::fabs(sfreq*integ) < EPS_3) {
639 s1 = sfreq*(time - tmin);
642 if (n1 < 0 || n1 > nsamp-1) {
643 printf(
"Sample value out of range %d (0..%d)",n1,nsamp-1);
650 if (std::fabs(f1 - 1.0) < 1e-3)
653 if (f1 < 1.0 && n1 > nsamp-2) {
654 printf(
"Sample value out of range %d (0..%d) %.4f",n1,nsamp-1,f1);
659 sum = f1*std::fabs(data[n1][ch]) + (1.0-f1)*std::fabs(data[n1+1][ch]);
661 sum = f1*data[n1][ch] + (1.0-f1)*data[n1+1][ch];
665 sum = std::fabs(data[n1][ch]);
671 s1 = sfreq*(time - 0.5*integ - tmin);
672 s2 = sfreq*(time + 0.5*integ - tmin);
673 n1 = ceil(s1); n2 = floor(s2);
676 if (n1 < 0 || n1 > nsamp-2)
681 sum = 0.5*((f1+f2)*std::fabs(data[n1+1][ch]) + (2.0-f1-f2)*std::fabs(data[n1][ch]));
683 sum = 0.5*((f1+f2)*data[n1+1][ch] + (2.0-f1-f2)*data[n1][ch]);
688 if (n1 < 0 || n1 > nsamp-1) {
689 printf(
"Sample value out of range %d (0..%d)",n1,nsamp-1);
692 if (n2 < 0 || n2 > nsamp-1) {
693 printf(
"Sample value out of range %d (0..%d)",n2,nsamp-1);
696 if (f1 != 0.0 && n1 < 1)
698 if (f2 != 0.0 && n2 > nsamp-2)
704 sum = 0.5 * std::fabs(data[n1][ch]);
705 for (
k = n1+1;
k < n2;
k++)
706 sum = sum + std::fabs(data[
k][ch]);
707 sum = sum + 0.5 * std::fabs(data[n2][ch]);
710 sum = 0.5*data[n1][ch];
711 for (
k = n1+1;
k < n2;
k++)
712 sum = sum + data[
k][ch];
713 sum = sum + 0.5*data[n2][ch];
722 sum = sum + 0.5*f1*(f1*std::fabs(data[n1-1][ch]) + (2.0-f1)*std::fabs(data[n1][ch]));
724 sum = sum + 0.5*f2*(f2*std::fabs(data[n2+1][ch]) + (2.0-f2)*std::fabs(data[n2][ch]));
728 sum = sum + 0.5*f1*(f1*data[n1-1][ch] + (2.0-f1)*data[n1][ch]);
730 sum = sum + 0.5*f2*(f2*data[n2+1][ch] + (2.0-f2)*data[n2][ch]);
732 width = width + f1 + f2;
743 int mne_decompose_eigen_3(
double *mat,
754 int np = dim*(dim+1)/2;
755 double *w = MALLOC_3(dim,
double);
756 double *z = MALLOC_3(dim*dim,
double);
757 double *work = MALLOC_3(3*dim,
double);
758 double *dmat = MALLOC_3(np,
double);
759 float *vecp = vectors[0];
768 for(
int i = 0; i < np; ++i)
769 if (std::fabs(mat[i]) > std::fabs(mat[maxi]))
773 scale = 1.0/mat[maxi];
775 for (
k = 0;
k < np;
k++)
776 dmat[
k] = mat[
k]*scale;
780 MatrixXd dmat_tmp = MatrixXd::Zero(dim,dim);
782 for (
int i = 0; i < dim; ++i) {
783 for(
int j = 0; j <= i; ++j) {
784 dmat_tmp(i,j) = dmat[idx];
785 dmat_tmp(j,i) = dmat[idx];
789 SelfAdjointEigenSolver<MatrixXd> es;
790 es.compute(dmat_tmp);
791 for (
int i = 0; i < dim; ++i )
792 w[i] = es.eigenvalues()[i];
795 for (
int j = 0; j < dim; ++j ) {
796 for(
int i = 0; i < dim; ++i ) {
797 z[idx] = es.eigenvectors()(i,j);
805 qDebug() <<
"!!!DEBUG ToDo: dspev(compz,uplo,&dim,dmat,w,z,&dim,work,&info);";
809 printf(
"Eigenvalue decomposition failed (LAPACK info = %d)",info);
812 for (
k = 0;
k < dim;
k++)
813 lambda[
k] = scale*w[
k];
814 for (
k = 0;
k < dim*dim;
k++)
831 static int mne_lt_packed_index_3(
int j,
int k)
835 return k + j*(j+1)/2;
837 return j +
k*(
k+1)/2;
849 double *src = c->lambda ? c->lambda : c->cov_diag;
853 qCritical(
"Covariance matrix is not diagonal or not decomposed.");
856 c->inv_lambda = REALLOC_3(c->inv_lambda,c->ncov,
double);
857 for (
k = 0;
k < c->ncov;
k++) {
859 c->inv_lambda[
k] = 0.0;
861 c->inv_lambda[
k] = 1.0/sqrt(src[
k]);
866 static int condition_cov_3(
MneCovMatrix* c,
float rank_threshold,
int use_rank)
869 double *scale = NULL;
871 double *lambda = NULL;
872 float **eigen = NULL;
873 double **data1 = NULL;
874 double **data2 = NULL;
875 double magscale,gradscale,eegscale;
876 int nmag,ngrad,neeg,nok;
883 qCritical(
"Channels not classified. Rank cannot be determined.");
886 magscale = gradscale = eegscale = 0.0;
887 nmag = ngrad = neeg = 0;
888 for (
k = 0;
k < c->ncov;
k++) {
889 if (c->ch_class[
k] == MNE_COV_CH_MEG_MAG) {
890 magscale += c->cov[mne_lt_packed_index_3(
k,
k)]; nmag++;
892 else if (c->ch_class[
k] == MNE_COV_CH_MEG_GRAD) {
893 gradscale += c->cov[mne_lt_packed_index_3(
k,
k)]; ngrad++;
895 else if (c->ch_class[
k] == MNE_COV_CH_EEG) {
896 eegscale += c->cov[mne_lt_packed_index_3(
k,
k)]; neeg++;
899 fprintf(stdout,
"%d ",c->ch_class[
k]);
903 fprintf(stdout,
"\n");
906 magscale = magscale > 0.0 ? sqrt(nmag/magscale) : 0.0;
908 gradscale = gradscale > 0.0 ? sqrt(ngrad/gradscale) : 0.0;
910 eegscale = eegscale > 0.0 ? sqrt(neeg/eegscale) : 0.0;
912 fprintf(stdout,
"%d %g\n",nmag,magscale);
913 fprintf(stdout,
"%d %g\n",ngrad,gradscale);
914 fprintf(stdout,
"%d %g\n",neeg,eegscale);
916 scale = MALLOC_3(c->ncov,
double);
917 for (
k = 0;
k < c->ncov;
k++) {
918 if (c->ch_class[
k] == MNE_COV_CH_MEG_MAG)
920 else if (c->ch_class[
k] == MNE_COV_CH_MEG_GRAD)
921 scale[
k] = gradscale;
922 else if (c->ch_class[
k] == MNE_COV_CH_EEG)
927 cov = MALLOC_3(c->ncov*(c->ncov+1)/2.0,
double);
928 lambda = MALLOC_3(c->ncov,
double);
929 eigen = ALLOC_CMATRIX_3(c->ncov,c->ncov);
930 for (j = 0; j < c->ncov; j++)
931 for (
k = 0;
k <= j;
k++)
932 cov[mne_lt_packed_index_3(j,
k)] = c->cov[mne_lt_packed_index_3(j,
k)]*scale[j]*scale[
k];
933 if (mne_decompose_eigen_3(cov,lambda,eigen,c->ncov) == 0) {
935 for (
k = 0;
k < c->ncov;
k++)
936 fprintf(stdout,
"%g ",lambda[
k]/lambda[c->ncov-1]);
937 fprintf(stdout,
"\n");
940 for (
k = c->ncov-1;
k >= 0;
k--) {
941 if (lambda[
k] >= rank_threshold*lambda[c->ncov-1])
946 printf(
"\n\tEstimated covariance matrix rank = %d (%g)\n",nok,lambda[c->ncov-nok]/lambda[c->ncov-1]);
947 if (use_rank > 0 && use_rank < nok) {
949 printf(
"\tUser-selected covariance matrix rank = %d (%g)\n",nok,lambda[c->ncov-nok]/lambda[c->ncov-1]);
954 for (j = 0; j < c->ncov-nok; j++)
956 data1 = ALLOC_DCMATRIX_3(c->ncov,c->ncov);
957 for (j = 0; j < c->ncov; j++) {
959 mne_print_vector(stdout,NULL,eigen[j],c->ncov);
961 for (
k = 0;
k < c->ncov;
k++)
962 data1[j][
k] = sqrt(lambda[j])*eigen[j][
k];
964 data2 = mne_dmatt_dmat_mult2_3(data1,data1,c->ncov,c->ncov,c->ncov);
967 for (j = 0; j < c->ncov; j++)
968 mne_print_dvector(stdout,NULL,data2[j],c->ncov);
974 for (
k = 0;
k < c->ncov;
k++)
976 scale[
k] = 1.0/scale[
k];
977 for (j = 0; j < c->ncov; j++)
978 for (
k = 0;
k <= j;
k++)
979 if (c->cov[mne_lt_packed_index_3(j,
k)] != 0.0)
980 c->cov[mne_lt_packed_index_3(j,
k)] = scale[j]*scale[
k]*data2[j][
k];
986 FREE_CMATRIX_3(eigen);
987 FREE_DCMATRIX_3(data1);
988 FREE_DCMATRIX_3(data2);
992 static int check_cov_data(
double *vals,
int nval)
998 for (
k = 0, sum = 0.0;
k < nval;
k++)
1001 qCritical(
"Sum of covariance matrix elements is zero!");
1008 const QList<FiffChInfo>& chs,
1017 if (chs.isEmpty()) {
1018 qCritical(
"Channel information not available in mne_classify_channels_cov");
1021 cov->ch_class = REALLOC_3(cov->ch_class,cov->ncov,
int);
1022 for (
k = 0;
k < cov->ncov;
k++) {
1023 cov->ch_class[
k] = MNE_COV_CH_UNKNOWN;
1024 for (p = 0; p < nchan; p++) {
1025 if (QString::compare(chs[p].ch_name,cov->names[
k]) == 0) {
1027 if (ch.
kind == FIFFV_MEG_CH) {
1028 if (ch.
unit == FIFF_UNIT_T)
1029 cov->ch_class[
k] = MNE_COV_CH_MEG_MAG;
1031 cov->ch_class[
k] = MNE_COV_CH_MEG_GRAD;
1033 else if (ch.
kind == FIFFV_EEG_CH)
1034 cov->ch_class[
k] = MNE_COV_CH_EEG;
1046 FREE_3(cov->ch_class);
1047 cov->ch_class = NULL;
1052 static int mne_decompose_eigen_cov_small_3(
MneCovMatrix* c,
float small,
int use_rank)
1058 float rank_threshold = 1e-6;
1066 return mne_add_inv_cov_3(c);
1067 if (c->lambda && c->eigen) {
1068 printf(
"\n\tEigenvalue decomposition had been precomputed.\n");
1070 for (
k = 0;
k < c->ncov;
k++, c->nzero++)
1071 if (c->lambda[
k] > 0)
1075 FREE_3(c->lambda); c->lambda = NULL;
1076 FREE_CMATRIX_3(c->eigen); c->eigen = NULL;
1078 if ((rank = condition_cov_3(c,rank_threshold,use_rank)) < 0)
1081 np = c->ncov*(c->ncov+1)/2;
1082 c->lambda = MALLOC_3(c->ncov,
double);
1083 c->eigen = ALLOC_CMATRIX_3(c->ncov,c->ncov);
1084 if (mne_decompose_eigen_3(c->cov,c->lambda,c->eigen,c->ncov) != 0)
1086 c->nzero = c->ncov - rank;
1087 for (
k = 0;
k < c->nzero;
k++)
1093 float meglike,eeglike;
1097 for (
k = c->nzero; k < c->ncov;
k++) {
1098 meglike = eeglike = 0.0;
1099 for (p = 0; p < c->ncov; p++) {
1100 if (c->ch_class[p] == MNE_COV_CH_EEG)
1101 eeglike += std::fabs(c->eigen[
k][p]);
1102 else if (c->ch_class[p] == MNE_COV_CH_MEG_MAG || c->ch_class[p] == MNE_COV_CH_MEG_GRAD)
1103 meglike += std::fabs(c->eigen[
k][p]);
1105 if (meglike > eeglike)
1110 printf(
"\t%d MEG and %d EEG-like channels remain in the whitened data\n",nmeg,neeg);
1113 return mne_add_inv_cov_3(c);
1116 FREE_3(c->lambda); c->lambda = NULL;
1117 FREE_CMATRIX_3(c->eigen); c->eigen = NULL;
1125 return mne_decompose_eigen_cov_small_3(c,-1.0,-1);
1130 int mne_whiten_data(
float **data,
float **whitened_data,
int np,
int nchan,
MneCovMatrix* C)
1136 float *one = NULL,*orig,*white;
1139 if (data == NULL || np <= 0)
1142 if (C->ncov != nchan) {
1143 printf(
"Incompatible covariance matrix. Cannot whiten the data.");
1146 inv = C->inv_lambda;
1147 if (mne_is_diag_cov_3(C)) {
1149 for (j = 0; j < np; j++) {
1151 white = whitened_data[j];
1152 for (
k = 0;
k < nchan;
k++)
1153 white[
k] = orig[
k]*inv[
k];
1160 one = MALLOC_3(nchan,
float);
1161 for (j = 0; j < np; j++) {
1163 white = whitened_data[j];
1164 for (
k = C->nzero;
k < nchan;
k++)
1165 one[
k] = mne_dot_vectors_3(C->eigen[
k],orig,nchan);
1166 for (
k = 0;
k < C->nzero;
k++)
1168 for (
k = C->nzero;
k < nchan;
k++)
1169 white[
k] = one[
k]*inv[
k];
1176 int mne_whiten_one_data(
float *data,
float *whitened_data,
int nchan,
MneCovMatrix* C)
1180 float *whitened_datap[1];
1183 whitened_datap[0] = whitened_data;
1185 return mne_whiten_data(datap,whitened_datap,1,nchan,C);
1196 if (f->meg_client_free && f->meg_client)
1197 f->meg_client_free(f->meg_client);
1198 if (f->eeg_client_free && f->eeg_client)
1199 f->eeg_client_free(f->eeg_client);
1267 float sums[3],nn[3];
1270 if (!c->cov || !c->ch_class)
1273 for (j = 0; j < nkind; j++) {
1280 for (j = 0; j < c->ncov; j++) {
1281 if (c->ch_class[j] >= 0) {
1282 sums[c->ch_class[j]] += c->cov[mne_lt_packed_index_3(j,j)];
1283 nn[c->ch_class[j]]++;
1286 printf(
"Average noise-covariance matrix diagonals:\n");
1287 for (j = 0; j < nkind; j++) {
1289 sums[j] = sums[j]/nn[j];
1290 if (j == MNE_COV_CH_MEG_MAG)
1291 printf(
"\tMagnetometers : %-7.2f fT reg = %-6.2f\n",1e15*sqrt(sums[j]),regs[j]);
1292 else if (j == MNE_COV_CH_MEG_GRAD)
1293 printf(
"\tPlanar gradiometers : %-7.2f fT/cm reg = %-6.2f\n",1e13*sqrt(sums[j]),regs[j]);
1295 printf(
"\tEEG : %-7.2f uV reg = %-6.2f\n",1e6*sqrt(sums[j]),regs[j]);
1296 sums[j] = regs[j]*sums[j];
1302 for (j = 0; j < c->ncov; j++)
1303 if (c->ch_class[j] >= 0)
1304 c->cov[mne_lt_packed_index_3(j,j)] += sums[c->ch_class[j]];
1306 printf(
"Noise-covariance regularized as requested.\n");
1317 f->meg_field = NULL;
1319 f->meg_vec_field = NULL;
1320 f->eeg_vec_pot = NULL;
1321 f->meg_client = NULL;
1322 f->meg_client_free = NULL;
1323 f->eeg_client = NULL;
1324 f->eeg_client_free = NULL;
1339 static float tryit (
float **p,
1343 float (*func)(
float *x,
int npar,
void *user_data),
1351 float fac1,fac2,ytry,*ptry;
1353 ptry = ALLOC_FLOAT_3(ndim);
1354 fac1 = (1.0-fac)/ndim;
1356 for (j = 0; j < ndim; j++)
1357 ptry[j] = psum[j]*fac1-p[ihi][j]*fac2;
1358 ytry = (*func)(ptry,ndim,user_data);
1360 if (ytry < y[ihi]) {
1362 for (j = 0; j < ndim; j++) {
1363 psum[j] += ptry[j]-p[ihi][j];
1364 p[ihi][j] = ptry[j];
1371 int mne_simplex_minimize(
float **p,
1375 float (*func)(
float *x,
int npar,
void *user_data),
1380 int (*report_func)(
int loop,
1381 float *fitpar,
int npar,
1390 int i,j,ilo,ihi,inhi;
1392 float ytry,ysave,sum,rtol,*psum;
1397 psum = ALLOC_FLOAT_3(ndim);
1399 for (j = 0; j < ndim; j++) {
1400 for (i = 0,sum = 0.0; i<mpts; i++)
1404 if (report_func != NULL && report > 0)
1405 (void)report_func (0,p[0],ndim,-1.0);
1407 for (;;count++,loop++) {
1409 ihi = y[1]>y[2] ? (inhi = 2,1) : (inhi = 1,2);
1410 for (i = 0; i < mpts; i++) {
1411 if (y[i] < y[ilo]) ilo = i;
1412 if (y[i] > y[ihi]) {
1415 }
else if (y[i] > y[inhi])
1416 if (i != ihi) inhi = i;
1418 rtol = 2.0*std::fabs(y[ihi]-y[ilo])/(std::fabs(y[ihi])+std::fabs(y[ilo]));
1422 if (count == report && report_func != NULL) {
1423 if (report_func (loop,p[ilo],ndim,y[ilo])) {
1424 qWarning(
"Interation interrupted.");
1430 if (rtol < ftol)
break;
1431 if (*neval >= max_eval) {
1432 qWarning(
"Maximum number of evaluations exceeded.");
1436 ytry = tryit(p,y,psum,ndim,func,user_data,ihi,neval,-ALPHA);
1438 ytry = tryit(p,y,psum,ndim,func,user_data,ihi,neval,GAMMA);
1439 else if (ytry >= y[inhi]) {
1441 ytry = tryit(p,y,psum,ndim,func,user_data,ihi,neval,BETA);
1442 if (ytry >= ysave) {
1443 for (i = 0; i < mpts; i++) {
1445 for (j = 0; j < ndim; j++) {
1446 psum[j] = 0.5*(p[i][j]+p[ilo][j]);
1449 y[i] = (*func)(psum,ndim,user_data);
1453 for (j = 0; j < ndim; j++) {
1454 for (i = 0,sum = 0.0; i < mpts; i++)
1482 static int report_func(
int loop,
1493 printf(
"loop %d r0 %7.1f %7.1f %7.1f fval %g\n",
1494 loop,1000*r0[0],1000*r0[1],1000*r0[2],fval);
1499 static float fit_sphere_eval(
float *fitpar,
1511 float sum,sum2,one,F;
1514 for (
k = 0, sum = sum2 = 0.0;
k < user->np;
k++) {
1515 VEC_DIFF_3(r0,user->rr[
k],diff);
1516 one = VEC_LEN_3(diff);
1520 F = sum2 - sum*sum/user->np;
1523 printf(
"r0 %7.1f %7.1f %7.1f R %7.1f fval %g\n",
1524 1000*r0[0],1000*r0[1],1000*r0[2],1000*sum/user->np,F);
1532 float sum, diff[3], one;
1535 for (
k = 0, sum = 0.0;
k < user->np;
k++) {
1536 VEC_DIFF_3(r0,user->rr[
k],diff);
1537 one = VEC_LEN_3(diff);
1540 return sum/user->np;
1543 static void calculate_cm_ave_dist(
float **rr,
int np,
float *cm,
float *avep)
1549 for (q = 0; q < 3; q++)
1552 for (
k = 0;
k < np;
k++)
1553 for (q = 0; q < 3; q++)
1557 for (q = 0; q < 3; q++)
1560 for (
k = 0, ave = 0.0;
k < np;
k++) {
1561 for (q = 0; q < 3; q++)
1562 diff[q] = rr[
k][q] - cm[q];
1563 ave += VEC_LEN_3(diff);
1570 static float **make_initial_simplex(
float *pars,
1577 float **simplex = ALLOC_CMATRIX_3(npar+1,npar);
1580 for (
k = 0;
k < npar+1;
k++)
1581 memcpy (simplex[
k],pars,npar*
sizeof(
float));
1583 for (
k = 1;
k < npar+1;
k++)
1584 simplex[
k][
k-1] = simplex[
k][
k-1] + size;
1588 int fit_sphere_to_points(
float **rr,
1600 int report_interval = -1;
1602 float **init_simplex = NULL;
1603 float *init_vals = NULL;
1613 calculate_cm_ave_dist(rr,np,cm,&R0);
1616 printf(
"cm %7.1f %7.1f %7.1f R %7.1f\n",
1617 1000*cm[0],1000*cm[1],1000*cm[2],1000*R0);
1620 init_simplex = make_initial_simplex(cm,3,simplex_size);
1622 init_vals = MALLOC_3(4,
float);
1627 user.report = FALSE;
1630 for (
k = 0;
k < 4;
k++)
1631 init_vals[
k] = fit_sphere_eval(init_simplex[
k],3,&user);
1633 if (mne_simplex_minimize(init_simplex,
1645 r0[X_3] = init_simplex[0][X_3];
1646 r0[Y_3] = init_simplex[0][Y_3];
1647 r0[Z_3] = init_simplex[0][Z_3];
1648 *R = opt_rad(r0,&user);
1655 FREE_CMATRIX_3(init_simplex);
1662 void mne_proj_op_report_data_3(FILE *out,
const char *tag,
MneProjOp* op,
int list_data,
1663 char **exclude,
int nexclude)
1677 if (op->nitems <= 0) {
1678 fprintf(out,
"Empty operator\n");
1682 for (
k = 0;
k < op->nitems;
k++) {
1684 if (list_data && tag)
1685 fprintf(out,
"%s\n",tag);
1687 fprintf(out,
"%s",tag);
1688 fprintf(out,
"# %d : %s : %d vecs : %d chs %s %s\n",
1691 it->
active ?
"active" :
"idle");
1692 if (list_data && tag)
1693 fprintf(out,
"%s\n",tag);
1695 vecs = op->items[
k]->vecs;
1697 for (q = 0; q < vecs->ncol; q++) {
1698 fprintf(out,
"%-10s",vecs->collist[q].toUtf8().constData());
1699 fprintf(out,q < vecs->ncol-1 ?
" " :
"\n");
1701 for (p = 0; p < vecs->nrow; p++)
1702 for (q = 0; q < vecs->ncol; q++) {
1703 for (j = 0, found = 0; j < nexclude; j++) {
1704 if (QString::compare(exclude[j],vecs->collist[q]) == 0) {
1709 fprintf(out,
"%10.5g ",found ? 0.0 : vecs->data[p][q]);
1710 fprintf(out,q < vecs->ncol-1 ?
" " :
"\n");
1712 if (list_data && tag)
1713 fprintf(out,
"%s\n",tag);
1719 void mne_proj_op_report_3(FILE *out,
const char *tag,
MneProjOp* op)
1721 mne_proj_op_report_data_3(out,tag,op, FALSE, NULL, 0);
1726 int mne_pick_from_named_vector_3(
mneNamedVector vec,
const QStringList& names,
int nnames,
int require_all,
float *res)
1734 if (vec->names.size() == 0) {
1735 qCritical(
"No names present in vector. Cannot pick.");
1739 for (
k = 0;
k < nnames;
k++)
1742 for (
k = 0;
k < nnames;
k++) {
1744 for (p = 0; p < vec->nvec; p++) {
1745 if (QString::compare(vec->names[p],names[
k]) == 0) {
1746 res[
k] = vec->data[p];
1751 if (!found && require_all) {
1752 qCritical(
"All required elements not found in named vector.");
1761 MneProjOp* mne_read_proj_op_from_node_3(
1769 QList<FiffDirNode::SPtr> proj;
1771 QList<FiffDirNode::SPtr> items;
1774 QString item_desc, desc_tag;
1775 int global_nchan,item_nchan,nlist;
1776 QStringList item_names;
1778 float **item_vectors = NULL;
1783 QStringList emptyList;
1787 qCritical(
"File not open mne_read_proj_op_from_node");
1791 if (!start || start->isEmpty())
1792 start_node = stream->dirtree();
1797 proj = start_node->dir_tree_find(FIFFB_PROJ);
1798 if (proj.size() == 0 || proj[0]->isEmpty())
1803 items = proj[0]->dir_tree_find(FIFFB_PROJ_ITEM);
1804 if (items.size() == 0 || items[0]->isEmpty())
1810 if(!node->find_tag(stream,
FIFF_NCHAN, t_pTag))
1813 global_nchan = *t_pTag->toInt();
1819 for (
k = 0;
k < items.size();
k++) {
1826 if (node->find_tag(stream,
FIFF_NAME, t_pTag)) {
1827 item_desc += t_pTag->toString();
1834 desc_tag = t_pTag->toString();
1835 if((pos = desc_tag.indexOf(
"\n")) >= 0)
1836 desc_tag.truncate(pos);
1837 if (!item_desc.isEmpty())
1839 item_desc += desc_tag;
1844 if (!node->find_tag(stream,
FIFF_NCHAN, t_pTag)) {
1845 item_nchan = global_nchan;
1848 item_nchan = *t_pTag->toInt();
1850 if (item_nchan <= 0) {
1851 qCritical(
"Number of channels incorrectly specified for one of the projection items.");
1857 if (!node->find_tag(stream, FIFF_PROJ_ITEM_CH_NAME_LIST, t_pTag))
1860 mne_string_to_name_list_3(t_pTag->toString(),item_names,nlist);
1861 if (nlist != item_nchan) {
1862 printf(
"Channel name list incorrectly specified for proj item # %d",
k+1);
1869 if (!node->find_tag(stream, FIFF_PROJ_ITEM_KIND, t_pTag))
1871 item_kind = *t_pTag->toInt();
1875 if (!node->find_tag(stream,FIFF_PROJ_ITEM_NVEC, t_pTag))
1877 item_nvec = *t_pTag->toInt();
1881 if (!node->find_tag(stream,FIFF_PROJ_ITEM_VECTORS, t_pTag))
1884 MatrixXf tmp_item_vectors = t_pTag->toFloatMatrix().transpose();
1885 item_vectors = ALLOC_CMATRIX_3(tmp_item_vectors.rows(),tmp_item_vectors.cols());
1886 fromFloatEigenMatrix_3(tmp_item_vectors, item_vectors);
1892 item_active = *t_pTag->toInt();
1895 item_active = FALSE;
1899 item = MneNamedMatrix::build_named_matrix(item_nvec,item_nchan,emptyList,item_names,item_vectors);
1900 MneProjOp::mne_proj_op_add_item_act(op,item,item_kind,item_desc,item_active);
1902 op->items[op->nitems-1]->active_file = item_active;
1915 MneProjOp* mne_read_proj_op_3(
const QString& name)
1927 res = mne_read_proj_op_from_node_3(stream,t_default);
1934 int mne_proj_op_chs_3(
MneProjOp* op,
const QStringList& list,
int nlist)
1940 MneProjOp::mne_free_proj_op_proj(op);
1951 static void clear_these(
float *data,
const QStringList& names,
int nnames,
const QString& start)
1955 for (
k = 0;
k < nnames;
k++)
1956 if (names[
k].contains(start))
1960 #define USE_LIMIT 1e-5
1961 #define SMALL_VALUE 1e-4
1963 int mne_proj_op_make_proj_bad(
MneProjOp* op,
char **bad,
int nbad)
1972 float **vv_meg = NULL;
1973 float *sing_meg = NULL;
1974 float **vv_eeg = NULL;
1975 float *sing_eeg = NULL;
1976 float **mat_meg = NULL;
1977 float **mat_eeg = NULL;
1987 FREE_CMATRIX_3(op->proj_data);
1988 op->proj_data = NULL;
1993 if (op->nitems <= 0)
1996 nvec = MneProjOp::mne_proj_op_affect(op,op->names,op->nch);
2000 mat_meg = ALLOC_CMATRIX_3(nvec, op->nch);
2001 mat_eeg = ALLOC_CMATRIX_3(nvec, op->nch);
2004 fprintf(stdout,
"mne_proj_op_make_proj_bad\n");
2006 for (
k = 0, nvec_meg = nvec_eeg = 0;
k < op->nitems;
k++) {
2007 if (op->items[
k]->active && MneProjItem::mne_proj_item_affect(op->items[
k],op->names,op->nch)) {
2008 vec.nvec = op->items[
k]->vecs->ncol;
2009 vec.names = op->items[
k]->vecs->collist;
2010 if (op->items[
k]->has_meg) {
2011 for (p = 0; p < op->items[
k]->nvec; p++, nvec_meg++) {
2012 vec.data = op->items[
k]->vecs->data[p];
2013 if (mne_pick_from_named_vector_3(&vec,op->names,op->nch,FALSE,mat_meg[nvec_meg]) == FAIL)
2016 fprintf(stdout,
"Original MEG:\n");
2017 mne_print_vector(stdout,op->items[
k]->desc,mat_meg[nvec_meg],op->nch);
2022 else if (op->items[
k]->has_eeg) {
2023 for (p = 0; p < op->items[
k]->nvec; p++, nvec_eeg++) {
2024 vec.data = op->items[
k]->vecs->data[p];
2025 if (mne_pick_from_named_vector_3(&vec,op->names,op->nch,FALSE,mat_eeg[nvec_eeg]) == FAIL)
2028 fprintf (stdout,
"Original EEG:\n");
2029 mne_print_vector(stdout,op->items[
k]->desc,mat_eeg[nvec_eeg],op->nch);
2039 for (q = 0; q < nbad; q++)
2040 for (r = 0; r < op->nch; r++)
2041 if (QString::compare(op->names[r],bad[q]) == 0) {
2042 for (p = 0; p < nvec_meg; p++)
2043 mat_meg[p][r] = 0.0;
2044 for (p = 0; p < nvec_eeg; p++)
2045 mat_eeg[p][r] = 0.0;
2050 for (p = 0, nzero = 0; p < nvec_meg; p++) {
2051 size = sqrt(mne_dot_vectors_3(mat_meg[p],mat_meg[p],op->nch));
2053 for (
k = 0;
k < op->nch;
k++)
2054 mat_meg[p][
k] = mat_meg[p][
k]/size;
2059 if (nzero == nvec_meg) {
2060 FREE_CMATRIX_3(mat_meg); mat_meg = NULL; nvec_meg = 0;
2062 for (p = 0, nzero = 0; p < nvec_eeg; p++) {
2063 size = sqrt(mne_dot_vectors_3(mat_eeg[p],mat_eeg[p],op->nch));
2065 for (
k = 0;
k < op->nch;
k++)
2066 mat_eeg[p][
k] = mat_eeg[p][
k]/size;
2071 if (nzero == nvec_eeg) {
2072 FREE_CMATRIX_3(mat_eeg); mat_eeg = NULL; nvec_eeg = 0;
2074 if (nvec_meg + nvec_eeg == 0) {
2075 printf(
"No projection remains after excluding bad channels. Omitting projection.\n");
2082 fprintf(stdout,
"Before SVD:\n");
2086 fprintf(stdout,
"---->>\n");
2087 for (p = 0; p < nvec_meg; p++) {
2088 sprintf(name,
"MEG %02d",p+1);
2089 mne_print_vector(stdout,name,mat_meg[p],op->nch);
2091 fprintf(stdout,
"---->>\n");
2093 sing_meg = MALLOC_3(nvec_meg+1,
float);
2094 vv_meg = ALLOC_CMATRIX_3(nvec_meg,op->nch);
2095 if (mne_svd_3(mat_meg,nvec_meg,op->nch,sing_meg,NULL,vv_meg) != OK)
2100 fprintf(stdout,
"---->>\n");
2101 for (p = 0; p < nvec_eeg; p++) {
2102 sprintf(name,
"EEG %02d",p+1);
2103 mne_print_vector(stdout,name,mat_eeg[p],op->nch);
2105 fprintf(stdout,
"---->>\n");
2107 sing_eeg = MALLOC_3(nvec_eeg+1,
float);
2108 vv_eeg = ALLOC_CMATRIX_3(nvec_eeg,op->nch);
2109 if (mne_svd_3(mat_eeg,nvec_eeg,op->nch,sing_eeg,NULL,vv_eeg) != OK)
2115 for (p = 0, op->nvec = 0; p < nvec_meg; p++, op->nvec++)
2116 if (sing_meg[p]/sing_meg[0] < USE_LIMIT)
2118 for (p = 0; p < nvec_eeg; p++, op->nvec++)
2119 if (sing_eeg[p]/sing_eeg[0] < USE_LIMIT)
2122 printf(
"Number of linearly independent vectors = %d\n",op->nvec);
2124 op->proj_data = ALLOC_CMATRIX_3(op->nvec,op->nch);
2126 fprintf(stdout,
"Final projection data:\n");
2128 for (p = 0, op->nvec = 0; p < nvec_meg; p++, op->nvec++) {
2129 if (sing_meg[p]/sing_meg[0] < USE_LIMIT)
2131 for (
k = 0;
k < op->nch;
k++) {
2135 if (std::fabs(vv_meg[p][
k]) < SMALL_VALUE)
2136 op->proj_data[op->nvec][
k] = 0.0;
2138 op->proj_data[op->nvec][
k] = vv_meg[p][
k];
2143 clear_these(op->proj_data[op->nvec],op->names,op->nch,
"EEG");
2146 sprintf(name,
"MEG %02d",p+1);
2147 mne_print_vector(stdout,name,op->proj_data[op->nvec],op->nch);
2150 for (p = 0; p < nvec_eeg; p++, op->nvec++) {
2151 if (sing_eeg[p]/sing_eeg[0] < USE_LIMIT)
2153 for (
k = 0;
k < op->nch;
k++) {
2157 if (std::fabs(vv_eeg[p][
k]) < SMALL_VALUE)
2158 op->proj_data[op->nvec][
k] = 0.0;
2160 op->proj_data[op->nvec][
k] = vv_eeg[p][
k];
2164 clear_these(op->proj_data[op->nvec],op->names,op->nch,
"MEG");
2167 sprintf(name,
"EEG %02d",p+1);
2168 mne_print_vector(stdout,name,op->proj_data[op->nvec],op->nch);
2173 FREE_CMATRIX_3(vv_meg);
2174 FREE_CMATRIX_3(mat_meg);
2176 FREE_CMATRIX_3(vv_eeg);
2177 FREE_CMATRIX_3(mat_eeg);
2181 for (
k = 0;
k < op->nch;
k++)
2182 if (op->names[
k].contains(
"STI")){
2183 for (p = 0; p < op->nvec; p++)
2184 op->proj_data[p][
k] = 0.0;
2191 FREE_CMATRIX_3(vv_meg);
2192 FREE_CMATRIX_3(mat_meg);
2194 FREE_CMATRIX_3(vv_eeg);
2195 FREE_CMATRIX_3(mat_eeg);
2200 int mne_proj_op_make_proj(
MneProjOp* op)
2205 return mne_proj_op_make_proj_bad(op,NULL,0);
2210 int mne_read_meg_comp_eeg_ch_info_3(
const QString& name,
2211 QList<FiffChInfo>& megp,
2213 QList<FiffChInfo>& meg_compp,
2215 QList<FiffChInfo>& eegp,
2227 QList<FiffChInfo> chs;
2229 QList<FiffChInfo> meg;
2231 QList<FiffChInfo> meg_comp;
2233 QList<FiffChInfo> eeg;
2236 QList<FiffDirNode::SPtr> nodes;
2241 fiff_int_t kind, pos;
2247 nodes = stream->dirtree()->dir_tree_find(FIFFB_MNE_PARENT_MEAS_FILE);
2249 if (nodes.size() == 0) {
2250 nodes = stream->dirtree()->dir_tree_find(FIFFB_MEAS_INFO);
2251 if (nodes.size() == 0) {
2252 qCritical (
"Could not find the channel information.");
2258 for (
k = 0;
k < info->nent();
k++) {
2259 kind = info->dir[
k]->kind;
2260 pos = info->dir[
k]->pos;
2263 if (!stream->read_tag(t_pTag,pos))
2265 nchan = *t_pTag->toInt();
2267 for (j = 0; j < nchan; j++)
2273 case FIFF_PARENT_BLOCK_ID :
2274 if(!stream->read_tag(t_pTag, pos))
2276 *
id = *(
fiffId)t_pTag->data();
2280 if(!stream->read_tag(t_pTag, pos))
2282 t = FiffCoordTransOld::read_helper( t_pTag );
2283 if (t && (t->
from != FIFFV_COORD_DEVICE || t->
to != FIFFV_COORD_HEAD))
2291 if(!stream->read_tag(t_pTag, pos))
2293 this_ch = t_pTag->toChInfo();
2295 printf (
"FIFF_CH_INFO : scan # out of range %d (%d)!",this_ch.
scanNo,nchan);
2299 chs[this_ch.
scanNo-1] = this_ch;
2305 qCritical(
"Some of the channel information was missing.");
2308 if (t == NULL && meg_head_t != NULL) {
2312 if ((t = FiffCoordTransOld::mne_read_meas_transform(name)) == NULL) {
2313 qCritical(
"MEG -> head coordinate transformation not found.");
2320 for (
k = 0;
k < nchan;
k++) {
2321 if (chs[
k].kind == FIFFV_MEG_CH) {
2325 meg_comp.append(chs[
k]);
2327 }
else if (chs[
k].kind == FIFFV_EEG_CH) {
2340 meg_compp = meg_comp;
2341 *nmeg_compp = nmeg_comp;
2351 if (meg_head_t == NULL) {
2371 #if defined(_WIN32) || defined(_WIN64)
2372 #define snprintf _snprintf
2373 #define vsnprintf _vsnprintf
2374 #define strcasecmp _stricmp
2375 #define strncasecmp _strnicmp
2378 int is_selected_in_data(
mshMegEegData d,
const QString& ch_name)
2386 for (
k = 0;
k < d->meas->nchan;
k++)
2387 if (QString::compare(ch_name,d->meas->chs[
k].ch_name,Qt::CaseInsensitive) == 0) {
2396 static int whitespace_3(
char *text)
2399 if (text == NULL || strlen(text) == 0)
2401 if (strspn(text,
" \t\n\r") == strlen(text))
2406 static char *next_line_3(
char *line,
int n, FILE *in)
2410 for (res = fgets(line,n,in); res != NULL; res = fgets(line,n,in))
2411 if (!whitespace_3(res))
2419 int mne_read_bad_channels_3(
const QString& name, QStringList& listp,
int& nlistp)
2426 char line[MAXLINE+1];
2432 if ((in = fopen(name.toUtf8().data(),
"r")) == NULL) {
2433 qCritical() << name;
2436 while ((next = next_line_3(line,MAXLINE,in)) != NULL) {
2437 if (strlen(next) > 0) {
2438 if (next[strlen(next)-1] ==
'\n')
2439 next[strlen(next)-1] =
'\0';
2447 nlistp = list.size();
2465 QList<FiffDirNode::SPtr> temp;
2471 if (pNode->isEmpty())
2472 node = stream->dirtree();
2476 temp = node->dir_tree_find(FIFFB_MNE_BAD_CHANNELS);
2477 if (temp.size() > 0) {
2480 bad->find_tag(stream, FIFF_MNE_CH_NAME_LIST, t_pTag);
2482 names = t_pTag->toString();
2483 mne_string_to_name_list_3(names,list,nlist);
2487 nlistp = list.size();
2491 int mne_read_bad_channel_list_3(
const QString& name, QStringList& listp,
int& nlistp)
2502 res = mne_read_bad_channel_list_from_node_3(stream,stream->dirtree(),listp,nlistp);
2509 MneCovMatrix* mne_read_cov(
const QString& name,
int kind)
2518 QList<FiffDirNode::SPtr> nodes;
2524 double *cov_diag = NULL;
2526 double *lambda = NULL;
2527 float **eigen = NULL;
2544 nodes = stream->dirtree()->dir_tree_find(FIFFB_MNE_COV);
2546 if (nodes.size() == 0) {
2547 printf(
"No covariance matrix available in %s",name.toUtf8().data());
2553 for (
k = 0 ;
k < nodes.size(); ++
k) {
2557 if (*t_pTag->toInt() == kind) {
2562 if (covnode->isEmpty()) {
2563 printf(
"Desired covariance matrix not found from %s",name.toUtf8().data());
2571 ncov = *t_pTag->toInt();
2574 nfree = *t_pTag->toInt();
2576 if (covnode->find_tag(stream, FIFF_MNE_ROW_NAMES, t_pTag)) {
2577 mne_string_to_name_list_3(t_pTag->toString(),names,nnames);
2578 if (nnames != ncov) {
2579 qCritical(
"Incorrect number of channel names for a covariance matrix");
2587 if (t_pTag->getType() == FIFFT_DOUBLE) {
2588 cov_diag = MALLOC_3(ncov,
double);
2589 qDebug() <<
"ToDo: Check whether cov_diag contains the right stuff!!! - use VectorXd instead";
2590 d = t_pTag->toDouble();
2591 for (p = 0; p < ncov; p++)
2593 if (check_cov_data(cov_diag,ncov) != OK)
2596 else if (t_pTag->getType() == FIFFT_FLOAT) {
2597 cov_diag = MALLOC_3(ncov,
double);
2598 qDebug() <<
"ToDo: Check whether f contains the right stuff!!! - use VectorXf instead";
2599 f = t_pTag->toFloat();
2600 for (p = 0; p < ncov; p++)
2604 printf(
"Illegal data type for covariance matrix");
2610 nn = ncov*(ncov+1)/2;
2611 if (t_pTag->getType() == FIFFT_DOUBLE) {
2612 qDebug() <<
"ToDo: Check whether cov contains the right stuff!!! - use VectorXd instead";
2614 cov = MALLOC_3(nn,
double);
2615 d = t_pTag->toDouble();
2616 for (p = 0; p < nn; p++)
2618 if (check_cov_data(cov,nn) != OK)
2621 else if (t_pTag->getType() == FIFFT_FLOAT) {
2622 cov = MALLOC_3(nn,
double);
2623 f = t_pTag->toFloat();
2624 for (p = 0; p < nn; p++)
2627 else if ((cov_sparse = FiffSparseMatrix::fiff_get_float_sparse_matrix(t_pTag)) == NULL) {
2632 lambda = (
double *)t_pTag->toDouble();
2633 if (nodes[
k]->find_tag(stream, FIFF_MNE_COV_EIGENVECTORS, t_pTag))
2636 tmp_eigen = t_pTag->toFloatMatrix().transpose();
2637 eigen = ALLOC_CMATRIX_3(tmp_eigen.rows(),tmp_eigen.cols());
2638 fromFloatEigenMatrix_3(tmp_eigen, eigen);
2643 if ((op = mne_read_proj_op_from_node_3(stream,nodes[
k])) == NULL)
2648 if ((sss = MneSssData::read_sss_data_from_node(stream,nodes[
k])) == NULL)
2653 if (mne_read_bad_channel_list_from_node_3(stream,nodes[
k],bads,nbad) == FAIL)
2657 res = MneCovMatrix::mne_new_cov_sparse(kind,ncov,names,cov_sparse);
2659 res = MneCovMatrix::mne_new_cov_dense(kind,ncov,names,cov);
2661 res = MneCovMatrix::mne_new_cov_diag(kind,ncov,names,cov_diag);
2663 qCritical(
"mne_read_cov : covariance matrix data is not defined. How come?");
2670 res->lambda = lambda;
2679 for (
k = 0;
k < res->ncov;
k++, res->nzero++)
2680 if (res->lambda[
k] > 0)
2684 if (op && op->nitems > 0) {
2724 const char *mne_coord_frame_name_3(
int frame)
2728 {FIFFV_COORD_UNKNOWN,
"unknown"},
2729 {FIFFV_COORD_DEVICE,
"MEG device"},
2730 {FIFFV_COORD_ISOTRAK,
"isotrak"},
2731 {FIFFV_COORD_HPI,
"hpi"},
2732 {FIFFV_COORD_HEAD,
"head"},
2733 {FIFFV_COORD_MRI,
"MRI (surface RAS)"},
2735 {FIFFV_COORD_MRI_SLICE,
"MRI slice"},
2736 {FIFFV_COORD_MRI_DISPLAY,
"MRI display"},
2746 for (
k = 0; frames[
k].frame != -1;
k++) {
2747 if (frame == frames[
k].frame)
2748 return frames[
k].name;
2750 return frames[
k].name;
2755 void mne_merge_channels(
const QList<FiffChInfo>& chs1,
2757 const QList<FiffChInfo>& chs2,
2759 QList<FiffChInfo>& resp,
2764 resp.reserve(nch1+nch2);
2767 for (
k = 0;
k < nch1;
k++) {
2768 resp.append(chs1.at(
k));
2770 for (
k = 0;
k < nch2;
k++) {
2771 resp.append(chs2.at(
k));
2788 while (tmp_node->type != FIFFB_MEAS) {
2789 if (tmp_node->parent == NULL)
2791 tmp_node = tmp_node->parent;
2805 while (tmp_node->type != FIFFB_MEAS) {
2806 if (tmp_node->parent == NULL)
2808 tmp_node = tmp_node->parent;
2810 for (
k = 0;
k < tmp_node->nchild();
k++)
2811 if (tmp_node->children[
k]->type == FIFFB_MEAS_INFO)
2812 return (tmp_node->children[
k]);
2816 static int get_all_chs (
2820 QList<FiffChInfo>& chp,
2828 QList<FiffChInfo> ch;
2835 fiff_int_t kind, pos;
2842 if (!(meas = find_meas_3(p_node))) {
2843 qCritical(
"Meas. block not found!");
2847 if (!(meas_info = find_meas_info_3(p_node))) {
2848 qCritical (
"Meas. info not found!");
2854 if (!meas->id.isEmpty()) {
2856 (*id)->version = meas->id.version;
2857 (*id)->machid[0] = meas->id.machid[0];
2858 (*id)->machid[1] = meas->id.machid[1];
2859 (*id)->time = meas->id.time;
2864 for (
k = 0;
k < meas_info->nent();
k++) {
2865 kind = meas_info->dir[
k]->kind;
2866 pos = meas_info->dir[
k]->pos;
2869 if (!stream->read_tag(t_pTag,pos))
2871 nchan = *t_pTag->toInt();
2874 for (j = 0; j < nchan; j++) {
2879 to_find += nchan - 1;
2883 if (!stream->read_tag(t_pTag,pos))
2885 this_ch = t_pTag->toChInfo();
2887 qCritical (
"FIFF_CH_INFO : scan # out of range!");
2891 ch[this_ch.
scanNo-1] = this_ch;
2905 static int read_ch_info(
const QString& name,
2906 QList<FiffChInfo>& chsp,
2916 QList<FiffChInfo> chs;
2920 QList<FiffDirNode::SPtr> meas;
2926 meas = stream->dirtree()->dir_tree_find(FIFFB_MEAS);
2927 if (meas.size() == 0) {
2928 qCritical (
"%s : no MEG data available here",name.toUtf8().data());
2932 if (get_all_chs(stream,
2936 &nchan) == FIFF_FAIL)
2951 #define TOO_CLOSE 1e-4
2953 static int at_origin (
const Eigen::Vector3f& rr)
2955 return (rr.norm() < TOO_CLOSE);
2958 static int is_valid_eeg_ch(
const FiffChInfo& ch)
2963 if (ch.
kind == FIFFV_EEG_CH) {
2974 const QStringList& bads,
2979 for (
k = 0;
k < nbad;
k++)
2980 if (QString::compare(ch.
ch_name,bads[
k]) == 0)
2985 int read_meg_eeg_ch_info(
const QString& name,
2988 const QStringList& bads,
2990 QList<FiffChInfo>& chsp,
2998 QList<FiffChInfo> chs;
3000 QList<FiffChInfo> meg;
3002 QList<FiffChInfo> eeg;
3009 if (read_ch_info(name,
3017 for (
k = 0;
k < nchan;
k++) {
3018 if (accept_ch(chs[
k],bads,nbad)) {
3019 if (do_meg && chs[
k].kind == FIFFV_MEG_CH) {
3022 }
else if (do_eeg && chs[
k].kind == FIFFV_EEG_CH && is_valid_eeg_ch(chs[
k])) {
3029 mne_merge_channels(meg,
3059 #define REALLY_REVERT
3060 #ifdef REALLY_REVERT
3061 c->cov_diag = REALLOC_3(c->cov_diag,c->ncov,
double);
3063 for (
k = p = 0;
k < c->ncov;
k++) {
3064 c->cov_diag[
k] = c->cov[p];
3067 FREE_3(c->cov); c->cov = NULL;
3069 for (j = 0, p = 0; j < c->ncov; j++)
3070 for (
k = 0;
k <= j;
k++, p++)
3075 FREE_3(c->lambda); c->lambda = NULL;
3076 FREE_CMATRIX_3(c->eigen); c->eigen = NULL;
3081 const QStringList& new_names,
3084 const QList<FiffChInfo>& chs)
3092 double *cov_diag = NULL;
3099 qCritical(
"No channels specified for picking in mne_pick_chs_cov_omit");
3102 if (c->names.isEmpty()) {
3103 qCritical(
"No names in covariance matrix. Cannot do picking.");
3106 pick = MALLOC_3(ncov,
int);
3107 for (j = 0; j < ncov; j++)
3109 for (j = 0; j < ncov; j++)
3110 for (
k = 0;
k < c->ncov;
k++)
3111 if (QString::compare(c->names[
k],new_names[j]) == 0) {
3115 for (j = 0; j < ncov; j++) {
3117 printf(
"All desired channels not found in the covariance matrix (at least missing %s).", new_names[j].toUtf8().constData());
3123 is_meg = MALLOC_3(ncov,
int);
3124 if (!chs.isEmpty()) {
3125 for (j = 0; j < ncov; j++)
3126 if (chs[j].kind == FIFFV_MEG_CH)
3132 for (j = 0; j < ncov; j++)
3133 if (new_names[j].startsWith(
"MEG"))
3140 cov_diag = MALLOC_3(ncov,
double);
3141 for (j = 0; j < ncov; j++) {
3142 cov_diag[j] = c->cov_diag[pick[j]];
3143 names.append(c->names[pick[j]]);
3147 cov = MALLOC_3(ncov*(ncov+1)/2,
double);
3148 for (j = 0; j < ncov; j++) {
3149 names.append(c->names[pick[j]]);
3150 for (
k = 0;
k <= j;
k++) {
3151 from = mne_lt_packed_index_3(pick[j],pick[
k]);
3152 to = mne_lt_packed_index_3(j,
k);
3153 if (to < 0 || to > ncov*(ncov+1)/2-1) {
3154 printf(
"Wrong destination index in mne_pick_chs_cov : %d %d %d\n",j,
k,to);
3157 if (from < 0 || from > c->ncov*(c->ncov+1)/2-1) {
3158 printf(
"Wrong source index in mne_pick_chs_cov : %d %d %d\n",pick[j],pick[
k],from);
3161 cov[to] = c->cov[from];
3163 if (is_meg[j] != is_meg[
k])
3169 res = MneCovMatrix::mne_new_cov(c->kind,ncov,names,cov,cov_diag);
3171 res->bads = c->bads;
3172 res->nbad = c->nbad;
3173 res->proj = MneProjOp::mne_dup_proj_op(c->proj);
3174 res->sss = c->sss ?
new MneSssData(*(c->sss)) : NULL;
3177 res->ch_class = MALLOC_3(res->ncov,
int);
3178 for (
k = 0;
k < res->ncov;
k++)
3179 res->ch_class[
k] = c->ch_class[pick[
k]];
3186 int mne_proj_op_proj_dvector(
MneProjOp* op,
double *vec,
int nch,
int do_complement)
3199 if (op->nch != nch) {
3200 qCritical(
"Data vector size does not match projection operator");
3204 Eigen::VectorXd res = Eigen::VectorXd::Zero(op->nch);
3206 for (p = 0; p < op->nvec; p++) {
3207 pvec = op->proj_data[p];
3209 for (
k = 0;
k < op->nch;
k++)
3210 w += vec[
k]*pvec[
k];
3211 for (
k = 0;
k < op->nch;
k++)
3212 res[
k] = res[
k] + w*pvec[
k];
3215 if (do_complement) {
3216 for (
k = 0;
k < op->nch;
k++)
3217 vec[
k] = vec[
k] - res[
k];
3220 for (
k = 0;
k < op->nch;
k++)
3227 int mne_name_list_match(
const QStringList& list1,
int nlist1,
3228 const QStringList& list2,
int nlist2)
3234 if (list1.isEmpty() && list2.isEmpty())
3236 if (list1.isEmpty() || list2.isEmpty())
3238 if (nlist1 != nlist2)
3240 for (
k = 0;
k < nlist1;
k++)
3241 if (QString::compare(list1[
k],list2[
k]) != 0)
3246 void mne_transpose_dsquare(
double **mat,
int n)
3254 for (j = 1; j < n; j++)
3255 for (
k = 0;
k < j;
k++) {
3257 mat[j][
k] = mat[
k][j];
3268 double **dcov = NULL;
3270 int do_complement = TRUE;
3272 if (op == NULL || op->nitems == 0)
3275 if (mne_name_list_match(op->names,op->nch,c->names,c->ncov) != OK) {
3276 qCritical(
"Incompatible data in mne_proj_op_apply_cov");
3280 dcov = ALLOC_DCMATRIX_3(c->ncov,c->ncov);
3285 for (j = 0, p = 0; j < c->ncov; j++)
3286 for (
k = 0;
k < c->ncov;
k++)
3287 dcov[j][
k] = (j ==
k) ? c->cov_diag[j] : 0;
3290 for (j = 0, p = 0; j < c->ncov; j++)
3291 for (
k = 0;
k <= j;
k++)
3292 dcov[j][
k] = c->cov[p++];
3293 for (j = 0; j < c->ncov; j++)
3294 for (
k = j+1;
k < c->ncov;
k++)
3295 dcov[j][
k] = dcov[
k][j];
3301 for (
k = 0;
k < c->ncov;
k++) {
3302 if (mne_proj_op_proj_dvector(op,dcov[
k],c->ncov,do_complement) != OK)
3306 mne_transpose_dsquare(dcov,c->ncov);
3308 for (
k = 0;
k < c->ncov;
k++)
3309 if (mne_proj_op_proj_dvector(op,dcov[
k],c->ncov,do_complement) != OK)
3316 for (j = 0; j < c->ncov; j++) {
3317 c->cov_diag[j] = dcov[j][j];
3319 FREE_3(c->cov); c->cov = NULL;
3322 for (j = 0, p = 0; j < c->ncov; j++)
3323 for (
k = 0;
k <= j;
k++)
3324 c->cov[p++] = dcov[j][
k];
3327 FREE_DCMATRIX_3(dcov);
3329 c->nproj = MneProjOp::mne_proj_op_affect(op,c->names,c->ncov);
3337 DipoleFitData::DipoleFitData()
3340 , coord_frame(FIFFV_COORD_UNKNOWN)
3349 , sphere_funcs (NULL)
3352 , mag_dipole_funcs (NULL)
3353 , fixed_noise (FALSE)
3358 , column_norm (COLUMN_NORM_NONE)
3359 , fit_mag_dipoles (FALSE)
3384 mne_free_cov_3(
noise);
3415 int fit_sphere_to_bem = TRUE;
3421 QString bemsolname = FwdBemModel::fwd_bem_make_bem_sol_name(d->
bemname);
3424 printf(
"\nSetting up the BEM model using %s...\n",d->
bemname.toUtf8().constData());
3425 printf(
"\nLoading surfaces...\n");
3428 printf(
"Three-layer model surfaces loaded.\n");
3434 printf(
"Homogeneous model surface loaded.\n");
3437 qCritical(
"Cannot use a homogeneous model in EEG calculations.");
3440 printf(
"\nLoading the solution matrix...\n");
3441 if (FwdBemModel::fwd_bem_load_recompute_solution(d->
bemname,FWD_BEM_UNKNOWN,FALSE,d->
bem_model) == FAIL)
3443 printf(
"Employing the head->MRI coordinate transform with the BEM model.\n");
3446 printf(
"BEM model %s is now set up\n",d->
bem_model->sol_name.toUtf8().constData());
3450 if (fit_sphere_to_bem) {
3452 float simplex_size = 2e-2;
3455 if ((inner_skull = d->
bem_model->fwd_bem_find_surface(FIFFV_BEM_SURF_ID_BRAIN)) == NULL)
3458 if (fit_sphere_to_points(inner_skull->rr,inner_skull->np,simplex_size,d->
r0,&R) == FAIL)
3461 FiffCoordTransOld::fiff_coord_trans(d->
r0,d->
mri_head_t,TRUE);
3462 printf(
"Fitted sphere model origin : %6.1f %6.1f %6.1f mm rad = %6.1f mm.\n",
3463 1000*d->
r0[X_3],1000*d->
r0[Y_3],1000*d->
r0[Z_3],1000*R);
3465 d->
bem_funcs = f = new_dipole_fit_funcs();
3471 comp = FwdCompData::fwd_make_comp_data(comp_data,d->
meg_coils,comp_coils,
3472 FwdBemModel::fwd_bem_field,NULL,NULL,d->
bem_model,NULL);
3475 printf(
"Compensation setup done.\n");
3477 printf(
"MEG solution matrix...");
3480 if (FwdBemModel::fwd_bem_specify_coils(d->
bem_model,comp->comp_coils) == FAIL)
3484 f->meg_field = FwdCompData::fwd_comp_field;
3485 f->meg_vec_field = NULL;
3486 f->meg_client = comp;
3487 f->meg_client_free = FwdCompData::fwd_free_comp_data;
3490 printf(
"\tEEG solution matrix...");
3494 f->eeg_pot = FwdBemModel::fwd_bem_pot_els;
3495 f->eeg_vec_pot = NULL;
3500 qCritical(
"EEG sphere model not defined.");
3506 f->eeg_pot = FwdEegSphereModel::fwd_eeg_spherepot_coil;
3507 f->eeg_vec_pot = FwdEegSphereModel::fwd_eeg_spherepot_coil_vec;
3515 comp = FwdCompData::fwd_make_comp_data(comp_data,d->
meg_coils,comp_coils,
3516 FwdBemModel::fwd_sphere_field,
3517 FwdBemModel::fwd_sphere_field_vec,
3522 f->meg_field = FwdCompData::fwd_comp_field;
3523 f->meg_vec_field = FwdCompData::fwd_comp_field_vec;
3524 f->meg_client = comp;
3525 f->meg_client_free = FwdCompData::fwd_free_comp_data;
3527 printf(
"Sphere model origin : %6.1f %6.1f %6.1f mm.\n",
3528 1000*d->
r0[X_3],1000*d->
r0[Y_3],1000*d->
r0[Z_3]);
3538 comp = FwdCompData::fwd_make_comp_data(comp_data,d->
meg_coils,comp_coils,
3539 FwdBemModel::fwd_mag_dipole_field,
3540 FwdBemModel::fwd_mag_dipole_field_vec,
3545 f->meg_field = FwdCompData::fwd_comp_field;
3546 f->meg_vec_field = FwdCompData::fwd_comp_field_vec;
3547 f->meg_client = comp;
3548 f->meg_client_free = FwdCompData::fwd_free_comp_data;
3550 f->eeg_pot = FwdBemModel::fwd_mag_dipole_field;
3551 f->eeg_vec_pot = FwdBemModel::fwd_mag_dipole_field_vec;
3557 fprintf (stderr,
"\n");
3576 printf(
"Using standard noise values "
3577 "(MEG grad : %6.1f fT/cm MEG mag : %6.1f fT EEG : %6.1f uV)\n",
3578 1e13*grad_std,1e15*mag_std,1e6*eeg_std);
3582 nchan = nchan + meg->ncoil;
3584 nchan = nchan + eeg->ncoil;
3586 stds = MALLOC_3(nchan,
double);
3590 for (
k = 0;
k < meg->ncoil;
k++, n++) {
3592 stds[n] = mag_std*mag_std;
3596 meg->coils[
k]->
type == FIFFV_COIL_CTF_OFFDIAG_REF_GRAD)
3597 stds[n] = 1e6*stds[n];
3601 stds[n] = grad_std*grad_std;
3606 for (
k = 0;
k < eeg->ncoil;
k++, n++) {
3607 stds[n] = eeg_std*eeg_std;
3617 int DipoleFitData::make_projection(
const QList<QString> &projnames,
3618 const QList<FiffChInfo>& chs,
3630 for (
k = 0,
neeg = 0;
k < nch;
k++)
3631 if (
chs[
k].kind == FIFFV_EEG_CH)
3634 if (projnames.size() == 0 &&
neeg == 0)
3637 for (
k = 0;
k < projnames.size();
k++) {
3638 if ((one = mne_read_proj_op_3(projnames[
k])) == NULL)
3640 if (one->nitems == 0) {
3641 printf(
"No linear projection information in %s.\n",projnames[
k].toUtf8().data());
3647 printf(
"Loaded projection from %s:\n",projnames[
k].toUtf8().data());
3648 mne_proj_op_report_3(stderr,
"\t",one);
3649 all = MneProjOp::mne_proj_op_combine(all,one);
3659 for (
k = 0;
k < all->nitems;
k++)
3660 if (all->items[
k]->kind == FIFFV_MNE_PROJ_ITEM_EEG_AVREF) {
3666 if ((one = MneProjOp::mne_proj_op_average_eeg_ref(
chs,nch)) != NULL) {
3667 printf(
"Average EEG reference projection added:\n");
3668 mne_proj_op_report_3(stderr,
"\t",one);
3669 all = MneProjOp::mne_proj_op_combine(all,one);
3676 if (all && MneProjOp::mne_proj_op_affect_chs(all,
chs,nch) == 0) {
3677 printf(
"Projection will not have any effect on selected channels. Projection omitted.\n");
3694 int DipoleFitData::scale_noise_cov(
DipoleFitData *f,
int nave)
3696 float nave_ratio = ((float)f->
nave)/(float)
nave;
3702 if (f->
noise->cov != NULL) {
3703 printf(
"Decomposing the sensor noise covariance matrix...\n");
3704 if (mne_decompose_eigen_cov_3(f->
noise) == FAIL)
3709 for (
k = 0;
k < f->
noise->ncov;
k++) {
3711 if (f->
noise->lambda[
k] < 0.0)
3712 f->
noise->lambda[
k] = 0.0;
3714 if (mne_add_inv_cov_3(f->
noise) == FAIL)
3718 for (
k = 0;
k < f->
noise->ncov;
k++)
3719 f->
noise->cov_diag[
k] = nave_ratio*f->
noise->cov_diag[
k];
3720 printf(
"Decomposition not needed for a diagonal noise covariance matrix.\n");
3721 if (mne_add_inv_cov_3(f->
noise) == FAIL)
3724 printf(
"Effective nave is now %d\n",
nave);
3734 int DipoleFitData::scale_dipole_fit_noise_cov(
DipoleFitData *f,
int nave)
3736 float nave_ratio = ((float)f->
nave)/(float)
nave;
3744 if (f->
noise->cov) {
3748 printf(
"Decomposing the noise covariance...");
3749 if (f->
noise->cov) {
3750 if (mne_decompose_eigen_cov_3(f->
noise) == FAIL)
3752 for (
k = 0;
k < f->
noise->ncov;
k++) {
3753 if (f->
noise->lambda[
k] < 0.0)
3754 f->
noise->lambda[
k] = 0.0;
3759 for (
k = 0;
k < f->
noise->ncov;
k++) {
3761 if (f->
noise->lambda[
k] < 0.0)
3762 f->
noise->lambda[
k] = 0.0;
3764 if (mne_add_inv_cov_3(f->
noise) == FAIL)
3768 for (
k = 0;
k < f->
noise->ncov;
k++)
3769 f->
noise->cov_diag[
k] = nave_ratio*f->
noise->cov_diag[
k];
3770 printf(
"Decomposition not needed for a diagonal noise covariance matrix.\n");
3771 if (mne_add_inv_cov_3(f->
noise) == FAIL)
3774 printf(
"Effective nave is now %d\n",
nave);
3790 float nonsel_w = 30;
3799 nave = d->meas->current->nave;
3807 float *w = MALLOC_3(f->
noise_orig->ncov,
float);
3812 nomit_meg = nomit_eeg = 0;
3818 if (is_selected_in_data(d,f->
noise_orig->names[
k]))
3829 if (
nmeg > 0 &&
nmeg-nomit_meg > 0 &&
nmeg-nomit_meg < min_nchan) {
3830 qCritical(
"Too few MEG channels remaining");
3834 if (
neeg > 0 &&
neeg-nomit_eeg > 0 &&
neeg-nomit_eeg < min_nchan) {
3835 qCritical(
"Too few EEG channels remaining");
3840 if (nomit_meg+nomit_eeg > 0) {
3841 if (f->
noise->cov) {
3842 for (j = 0; j < f->
noise->ncov; j++)
3843 for (
k = 0;
k <= j;
k++) {
3844 val = f->
noise->cov+mne_lt_packed_index_3(j,
k);
3845 *val = w[j]*w[
k]*(*val);
3849 for (j = 0; j < f->
noise->ncov; j++) {
3850 val = f->
noise->cov_diag+j;
3851 *val = w[j]*w[j]*(*val);
3863 return scale_dipole_fit_noise_cov(f,
nave);
3869 const QString &measname,
3870 const QString& bemname,
3874 const QString &badname,
3875 const QString &noisename,
3883 const QList<QString> &projnames,
3892 QStringList badlist;
3894 QStringList file_bads;
3905 if (!mriname.isEmpty()) {
3906 if ((res->
mri_head_t = FiffCoordTransOld::mne_read_mri_transform(mriname)) == NULL)
3909 else if (!
bemname.isEmpty()) {
3910 qWarning(
"Source of MRI / head transform required for the BEM model is missing");
3914 float move[] = { 0.0, 0.0, 0.0 };
3915 float rot[3][3] = { { 1.0, 0.0, 0.0 },
3917 { 0.0, 0.0, 1.0 } };
3921 FiffCoordTransOld::mne_print_coord_transform(stdout,res->
mri_head_t);
3922 if ((res->
meg_head_t = FiffCoordTransOld::mne_read_meas_transform(measname)) == NULL)
3924 FiffCoordTransOld::mne_print_coord_transform(stdout,res->
meg_head_t);
3928 if (!badname.isEmpty()) {
3929 if (mne_read_bad_channels_3(badname,badlist,nbad) != OK)
3931 printf(
"%d bad channels read from %s.\n",nbad,badname.toUtf8().data());
3933 if (mne_read_bad_channel_list_3(measname,file_bads,file_nbad) == OK && file_nbad > 0) {
3934 if (badlist.isEmpty())
3936 for (
k = 0;
k < file_nbad;
k++) {
3937 badlist.append(file_bads[
k]);
3941 printf(
"%d bad channels read from the data file.\n",file_nbad);
3943 printf(
"%d bad channels total.\n",nbad);
3947 if (read_meg_eeg_ch_info(measname,
3958 printf(
"Will use %3d MEG channels from %s\n",res->
nmeg,measname.toUtf8().data());
3960 printf(
"Will use %3d EEG channels from %s\n",res->
neeg,measname.toUtf8().data());
3962 QString s = mne_channel_names_to_string_3(res->
chs,
3965 mne_string_to_name_list_3(s,res->
ch_names,n);
3981 QString qPath = QString(QCoreApplication::applicationDirPath() +
"/../resources/general/coilDefinitions/coil_def.dat");
3983 if ( !QCoreApplication::startingUp() )
3984 qPath = QCoreApplication::applicationDirPath() + QString(
"/../resources/general/coilDefinitions/coil_def.dat");
3985 else if (!file.exists())
3986 qPath =
"../resources/general/coilDefinitions/coil_def.dat";
3988 char *coilfile = MALLOC_3(strlen(qPath.toUtf8().data())+1,
char);
3989 strcpy(coilfile,qPath.toUtf8().data());
3994 if ((templates = FwdCoilSet::read_coil_defs(coilfile)) == NULL) {
4001 accurate_coils ? FWD_COIL_ACCURACY_ACCURATE : FWD_COIL_ACCURACY_NORMAL,
4004 if ((res->
eeg_els = FwdCoilSet::create_eeg_els(res->
chs.mid(res->
nmeg),
4008 printf(
"Head coordinate coil definitions created.\n");
4011 qWarning(
"Cannot handle computations in %s coordinates",mne_coord_frame_name_3(
coord_frame));
4019 res->
r0[0] = (*r0)[0];
4020 res->
r0[1] = (*r0)[1];
4021 res->
r0[2] = (*r0)[2];
4027 if ((comp_data = MneCTFCompDataSet::mne_read_ctf_comp_data(measname)) == NULL)
4029 if (comp_data->ncomp > 0) {
4030 QList<FiffChInfo> comp_chs;
4033 printf(
"%d compensation data sets in %s\n",comp_data->ncomp,measname.toUtf8().data());
4034 QList<FiffChInfo> temp;
4035 if (mne_read_meg_comp_eeg_ch_info_3(measname,
4048 FWD_COIL_ACCURACY_NORMAL,
4052 printf(
"%d compensation channels in %s\n",comp_coils->ncoil,measname.toUtf8().data());
4063 if (setup_forward_model(res,comp_data,comp_coils) == FAIL)
4069 if (make_projection(projnames,
4072 &res->
proj) == FAIL)
4074 if (res->
proj && res->
proj->nitems > 0) {
4075 printf(
"Final projection operator is:\n");
4076 mne_proj_op_report_3(stderr,
"\t",res->
proj);
4080 if (mne_proj_op_make_proj(res->
proj) == FAIL)
4084 printf(
"No projection will be applied to the data.\n");
4089 if (!noisename.isEmpty()) {
4090 if ((cov = mne_read_cov(noisename,FIFFV_MNE_SENSOR_COV)) == NULL)
4092 printf(
"Read a %s noise-covariance matrix from %s\n",
4093 cov->cov_diag ?
"diagonal" :
"full", noisename.toUtf8().data());
4096 if ((cov = ad_hoc_noise(res->
meg_coils,res->
eeg_els,grad_std,mag_std,eeg_std)) == NULL)
4099 res->
noise = mne_pick_chs_cov_omit(cov,
4104 if (res->
noise == NULL) {
4105 mne_free_cov_3(cov);
4109 printf(
"Picked appropriate channels from the noise-covariance matrix.\n");
4110 mne_free_cov_3(cov);
4115 if (res->
proj && res->
proj->nitems > 0 && res->
proj->nvec > 0) {
4116 if (mne_proj_op_apply_cov(res->
proj,res->
noise) == FAIL)
4118 printf(
"Projection applied to the covariance matrix.\n");
4125 mne_revert_to_diag_cov(res->
noise);
4126 printf(
"Using only the main diagonal of the noise-covariance matrix.\n");
4132 if (res->
noise->cov) {
4136 regs[MNE_COV_CH_MEG_MAG] = mag_reg;
4137 regs[MNE_COV_CH_MEG_GRAD] = grad_reg;
4138 regs[MNE_COV_CH_EEG] = eeg_reg;
4142 if (mne_classify_channels_cov(res->
noise,
4149 for (
k = 0, do_it = 0;
k < res->
noise->ncov;
k++) {
4150 if (res->
noise->ch_class[
k] != MNE_COV_CH_UNKNOWN &&
4151 regs[res->
noise->ch_class[
k]] > 0.0)
4158 mne_regularize_cov(res->
noise,regs);
4160 printf(
"No regularization applied to the noise-covariance matrix\n");
4166 printf(
"Decomposing the noise covariance...\n");
4167 if (res->
noise->cov) {
4168 if (mne_decompose_eigen_cov_3(res->
noise) == FAIL)
4170 printf(
"Eigenvalue decomposition done.\n");
4171 for (
k = 0;
k < res->
noise->ncov;
k++) {
4172 if (res->
noise->lambda[
k] < 0.0)
4173 res->
noise->lambda[
k] = 0.0;
4177 printf(
"Decomposition not needed for a diagonal covariance matrix.\n");
4178 if (mne_add_inv_cov_3(res->
noise) == FAIL)
4205 void print_fields(
float *rd,
4213 float *one = MALLOC_3(data->nchan,
float);
4217 if (mne_get_values_from_data_3(time,integ,data->current->data,data->current->np,data->nchan,data->current->tmin,
4218 1.0/data->current->tstep,FALSE,one) == FAIL) {
4219 printf(
"Cannot pick time: %7.1f ms\n",1000*time);
4222 for (
k = 0;
k < data->nchan;
k++)
4224 data->chs[
k].chpos.coil_type == FIFFV_COIL_CTF_OFFDIAG_REF_GRAD) {
4225 printf(
"%g ",1e15*one[
k]);
4229 fwd = ALLOC_CMATRIX_3(3,fit->
nmeg+fit->
neeg);
4230 if (DipoleFitData::compute_dipole_field(fit,rd,FALSE,fwd) == FAIL)
4233 for (
k = 0;
k < data->nchan;
k++)
4235 data->chs[
k].chpos.coil_type == FIFFV_COIL_CTF_OFFDIAG_REF_GRAD) {
4236 printf(
"%g ",1e15*(Q[X_3]*fwd[X_3][
k]+Q[Y_3]*fwd[Y_3][
k]+Q[Z_3]*fwd[Z_3][
k]));
4242 FREE_CMATRIX_3(fwd);
4268 delete old; old = NULL;
4270 res->
fwd = ALLOC_CMATRIX_3(3*ndip,d->
nmeg+d->
neeg);
4271 res->
uu = ALLOC_CMATRIX_3(3*ndip,d->
nmeg+d->
neeg);
4272 res->
vv = ALLOC_CMATRIX_3(3*ndip,3);
4273 res->
sing = MALLOC_3(3*ndip,
float);
4275 res->
rd = ALLOC_CMATRIX_3(ndip,3);
4276 res->
scales = MALLOC_3(3*ndip,
float);
4280 for (
k = 0;
k < ndip;
k++) {
4281 VEC_COPY_3(res->
rd[
k],rd[
k]);
4282 this_fwd = res->
fwd + 3*
k;
4286 if ((DipoleFitData::compute_dipole_field(d,rd[
k],TRUE,this_fwd)) == FAIL)
4293 for (p = 0; p < 3; p++)
4294 S[p] = mne_dot_vectors_3(res->
fwd[3*
k+p],res->
fwd[3*
k+p],res->
nch);
4296 for (p = 0; p < 3; p++)
4297 res->
scales[3*
k+p] = sqrt(S[p]);
4305 for (p = 0; p < 3; p++) {
4306 if (res->
scales[3*
k+p] > 0.0) {
4347 return dipole_forward(d,rds,1,old);
4352 static float fit_eval(
float *rd,
int npar,
void *user)
4364 fwd = fuser->fwd = DipoleFitData::dipole_forward_one(fit,rd,fuser->fwd);
4365 ncomp = fwd->
sing[2]/fwd->
sing[0] > fuser->limit ? 3 : 2;
4366 if (fuser->report_dim)
4367 printf(
"ncomp = %d\n",ncomp);
4369 for (c = 0, Bm2 = 0.0; c < ncomp; c++) {
4370 one = mne_dot_vectors_3(fwd->
uu[c],fuser->B,fwd->
nch);
4371 Bm2 = Bm2 + one*one;
4373 return fuser->B2-Bm2;
4376 static int find_best_guess(
float *B,
4387 double B2,Bm2,this_good,one;
4393 B2 = mne_dot_vectors_3(B,B,nch);
4396 if (fwd->
nch == nch) {
4397 ncomp = fwd->
sing[2]/fwd->
sing[0] > limit ? 3 : 2;
4398 for (c = 0, Bm2 = 0.0; c < ncomp; c++) {
4399 one = mne_dot_vectors_3(fwd->
uu[c],B,nch);
4400 Bm2 = Bm2 + one*one;
4402 this_good = 1.0 - (B2 - Bm2)/B2;
4403 if (this_good > good) {
4410 printf(
"No reasonable initial guess found.");
4418 static float **make_initial_dipole_simplex(
float *r0,
4430 float x = sqrt(3.0)/3.0;
4431 float r = sqrt(6.0)/12.0;
4434 float rr[][3] = { { x , 0.0, -r },
4439 float **simplex = ALLOC_CMATRIX_3(4,3);
4442 for (j = 0; j < 4; j++) {
4443 VEC_COPY_3(simplex[j],rr[j]);
4444 for (
k = 0;
k < 3;
k++)
4445 simplex[j][
k] = size*simplex[j][
k] + r0[
k];
4450 static int report_func(
int loop,
4462 fprintf(stdout,
"loop %d rd %7.2f %7.2f %7.2f fval %g %g par diff %g\n",
4463 loop,1000*r0[0],1000*r0[1],1000*r0[2],fval_lo,fval_hi,1000*par_diff);
4480 DipoleForward* fwd = DipoleFitData::dipole_forward_one(fit,rd,NULL);
4486 *ncomp = fwd->
sing[2]/fwd->
sing[0] > limit ? 3 : 2;
4488 Q[0] = Q[1] = Q[2] = 0.0;
4489 for (c = 0, Bm2 = 0.0; c < *ncomp; c++) {
4490 one = mne_dot_vectors_3(fwd->
uu[c],B,fwd->
nch);
4491 mne_add_scaled_vector_to_3(fwd->
vv[c],one/fwd->
sing[c],Q,3);
4492 Bm2 = Bm2 + one*one;
4497 for (c = 0; c < 3; c++)
4498 Q[c] = fwd->
scales[c]*Q[c];
4499 *res = mne_dot_vectors_3(B,B,fwd->
nch) - Bm2;
4506 static float rtol(
float *vals,
int nval)
4512 minv = maxv = vals[0];
4513 for (
k = 1;
k < nval;
k++) {
4519 return 2.0*(maxv-minv)/(maxv+minv);
4529 #define MIN_STOL_LOOP 5
4531 static float tryf (
float **p,
4535 float (*func)(
float *x,
int npar,
void *user_data),
4543 float fac1,fac2,ytry,*ptry;
4545 ptry = ALLOC_FLOAT_3(ndim);
4546 fac1 = (1.0-fac)/ndim;
4548 for (j = 0; j < ndim; j++)
4549 ptry[j] = psum[j]*fac1-p[ihi][j]*fac2;
4550 ytry = (*func)(ptry,ndim,user_data);
4552 if (ytry < y[ihi]) {
4554 for (j = 0; j < ndim; j++) {
4555 psum[j] += ptry[j]-p[ihi][j];
4556 p[ihi][j] = ptry[j];
4563 int simplex_minimize(
float **p,
4568 float (*func)(
float *x,
int npar,
void *user_data),
4573 int (*report_func)(
int loop,
4574 float *fitpar,
int npar,
4584 int i,j,ilo,ihi,inhi;
4586 float ytry,ysave,sum,rtol,*psum;
4592 psum = ALLOC_FLOAT_3(ndim);
4594 for (j = 0; j < ndim; j++) {
4595 for (i = 0,sum = 0.0; i<mpts; i++)
4599 if (report_func != NULL && report > 0)
4600 (void)report_func (0,p[0],ndim,-1.0,-1.0,0.0);
4603 for (;;count++,loop++) {
4605 ihi = y[1]>y[2] ? (inhi = 2,1) : (inhi = 1,2);
4606 for (i = 0; i < mpts; i++) {
4607 if (y[i] < y[ilo]) ilo = i;
4608 if (y[i] > y[ihi]) {
4611 }
else if (y[i] > y[inhi])
4612 if (i != ihi) inhi = i;
4614 rtol = 2.0*std::fabs(y[ihi]-y[ilo])/(std::fabs(y[ihi])+std::fabs(y[ilo]));
4618 if (count == report && report_func != NULL) {
4619 if (report_func (loop,p[ilo],ndim,y[ilo],y[ihi],sqrt(dsum))) {
4620 printf(
"Interation interrupted.");
4626 if (rtol < ftol)
break;
4627 if (*neval >= max_eval) {
4628 printf(
"Maximum number of evaluations exceeded.");
4633 for (dsum = 0.0, j = 0; j < ndim; j++) {
4634 diff = p[ilo][j] - p[ihi][j];
4637 if (loop > MIN_STOL_LOOP && sqrt(dsum) < stol)
4640 ytry = tryf(p,y,psum,ndim,func,user_data,ihi,neval,-ALPHA);
4642 ytry = tryf(p,y,psum,ndim,func,user_data,ihi,neval,GAMMA);
4643 else if (ytry >= y[inhi]) {
4645 ytry = tryf(p,y,psum,ndim,func,user_data,ihi,neval,BETA);
4646 if (ytry >= ysave) {
4647 for (i = 0; i < mpts; i++) {
4649 for (j = 0; j < ndim; j++) {
4650 psum[j] = 0.5*(p[i][j]+p[ilo][j]);
4653 y[i] = (*func)(psum,ndim,user_data);
4657 for (j = 0; j < ndim; j++) {
4658 for (i = 0,sum = 0.0; i < mpts; i++)
4679 float **simplex = NULL;
4683 float ftol[] = { 1e-2, 1e-2 };
4684 float atol[] = { 0.2e-3, 0.2e-3 };
4687 int max_eval = 1000;
4688 int report_interval = verbose ? 1 : -1;
4691 float good,rd_guess[3],rd_final[3],Q[3],final_val;
4693 int k,p,neval,neval_tot,nchan,ncomp;
4699 if (MneProjOp::mne_proj_op_proj_vector(fit->
proj,B,nchan,TRUE) == FAIL)
4702 if (mne_whiten_one_data(B,B,nchan,fit->
noise) == FAIL)
4707 if (find_best_guess(B,nchan,guess,limit,&best,&good) < 0)
4712 user.B2 = mne_dot_vectors_3(B,B,nchan);
4714 user.report_dim = FALSE;
4717 VEC_COPY_3(rd_guess,guess->
rr[best]);
4718 VEC_COPY_3(rd_final,guess->
rr[best]);
4722 for (
k = 0;
k < ntol;
k++) {
4731 simplex = make_initial_dipole_simplex(rd_guess,size);
4732 for (p = 0; p < 4; p++)
4733 vals[p] = fit_eval(simplex[p],3,fit);
4734 if (simplex_minimize(simplex,
4744 report_func) != OK) {
4748 printf(
"\nWarning (t = %8.1f ms) : g = %6.1f %% final val = %7.3f rtol = %f\n",
4749 1000*time,100*(1 - vals[0]/
user.B2),vals[0],rtol(vals,4));
4753 VEC_COPY_3(rd_final,simplex[0]);
4754 VEC_COPY_3(rd_guess,simplex[0]);
4755 FREE_CMATRIX_3(simplex); simplex = NULL;
4758 final_val = vals[0];
4766 if (fit_Q(fit,
user.B,rd_final,
user.limit,Q,&ncomp,&final_val) == OK) {
4769 for(
int i = 0; i < 3; ++i)
4770 res.
rd[i] = rd_final[i];
4771 for(
int i = 0; i < 3; ++i)
4773 res.
good = 1.0 - final_val/
user.B2;
4776 res.
khi2 = final_val;
4778 res.
nfree = nchan-3-ncomp-fit->
proj->nvec;
4780 res.
nfree = nchan-3-ncomp;
4781 res.
neval = neval_tot;
4786 FREE_CMATRIX_3(simplex);
4792 FREE_CMATRIX_3(simplex);
4799 int DipoleFitData::compute_dipole_field(
DipoleFitData* d,
float *rd,
int whiten,
float **fwd)
4805 static float Qx[] = {1.0,0.0,0.0};
4806 static float Qy[] = {0.0,1.0,0.0};
4807 static float Qz[] = {0.0,0.0,1.0};
4813 if (d->
funcs->meg_vec_field) {
4828 if (d->
funcs->eeg_vec_pot) {
4829 eeg_fwd[0] = fwd[0]+d->
nmeg;
4830 eeg_fwd[1] = fwd[1]+d->
nmeg;
4831 eeg_fwd[2] = fwd[2]+d->
nmeg;
4849 fprintf(stdout,
"orig : ");
4850 for (
k = 0;
k < 3;
k++)
4851 fprintf(stdout,
"%g ",sqrt(mne_dot_vectors_3(fwd[
k],fwd[
k],d->
nmeg+d->
neeg)));
4852 fprintf(stdout,
"\n");
4855 for (
k = 0;
k < 3;
k++)
4856 if (MneProjOp::mne_proj_op_proj_vector(d->
proj,fwd[
k],d->
nmeg+d->
neeg,TRUE) == FAIL)
4860 fprintf(stdout,
"proj : ");
4861 for (
k = 0;
k < 3;
k++)
4862 fprintf(stdout,
"%g ",sqrt(mne_dot_vectors_3(fwd[
k],fwd[
k],d->
nmeg+d->
neeg)));
4863 fprintf(stdout,
"\n");
4869 if (d->
noise && whiten) {
4870 if (mne_whiten_data(fwd,fwd,3,d->
nmeg+d->
neeg,d->
noise) == FAIL)
4875 fprintf(stdout,
"white : ");
4876 for (
k = 0;
k < 3;
k++)
4877 fprintf(stdout,
"%g ",sqrt(mne_dot_vectors_3(fwd[
k],fwd[
k],d->
nmeg+d->
neeg)));
4878 fprintf(stdout,
"\n");