47 #include <Eigen/Dense>
53 using namespace Eigen;
54 using namespace FIFFLIB;
55 using namespace FIFFLIB;
77 #define FREE_20(x) if ((char *)(x) != NULL) free((char *)(x))
79 #define MALLOC_20(x,t) (t *)malloc((x)*sizeof(t))
81 static void matrix_error_20(
int kind,
int nr,
int nc)
85 printf(
"Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
87 printf(
"Failed to allocate memory for a %d x %d matrix\n",nr,nc);
89 printf(
"Allocation error for a %d x %d matrix\n",nr,nc);
90 if (
sizeof(
void *) == 4) {
91 printf(
"This is probably because you seem to be using a computer with 32-bit architecture.\n");
92 printf(
"Please consider moving to a 64-bit platform.");
94 printf(
"Cannot continue. Sorry.\n");
98 float **mne_cmatrix_20(
int nr,
int nc)
105 m = MALLOC_20(nr,
float *);
106 if (!m) matrix_error_20(1,nr,nc);
107 whole = MALLOC_20(nr*nc,
float);
108 if (!whole) matrix_error_20(2,nr,nc);
115 #define VEC_DIFF_20(from,to,diff) {\
116 (diff)[X_20] = (to)[X_20] - (from)[X_20];\
117 (diff)[Y_20] = (to)[Y_20] - (from)[Y_20];\
118 (diff)[Z_20] = (to)[Z_20] - (from)[Z_20];\
121 #define ALLOC_CMATRIX_20(x,y) mne_cmatrix_20((x),(y))
125 #define VEC_DOT_20(x,y) ((x)[X_20]*(y)[X_20] + (x)[Y_20]*(y)[Y_20] + (x)[Z_20]*(y)[Z_20])
127 #define VEC_LEN_20(x) sqrt(VEC_DOT_20(x,x))
129 #define CROSS_PRODUCT_20(x,y,xy) {\
130 (xy)[X_20] = (x)[Y_20]*(y)[Z_20]-(y)[Y_20]*(x)[Z_20];\
131 (xy)[Y_20] = -((x)[X_20]*(y)[Z_20]-(y)[X_20]*(x)[Z_20]);\
132 (xy)[Z_20] = (x)[X_20]*(y)[Y_20]-(y)[X_20]*(x)[Y_20];\
135 #define FREE_CMATRIX_20(m) mne_free_cmatrix_20((m))
137 void mne_free_cmatrix_20(
float **m)
145 #define MIN_20(a,b) ((a) < (b) ? (a) : (b))
148 Eigen::MatrixXf toFloatEigenMatrix_20(
float **mat,
const int m,
const int n)
150 Eigen::MatrixXf eigen_mat(m,n);
152 for (
int i = 0; i < m; ++i)
153 for (
int j = 0; j < n; ++j)
154 eigen_mat(i,j) = mat[i][j];
159 void fromFloatEigenVector_20(
const Eigen::VectorXf& from_vec,
float *to_vec,
const int n)
161 for (
int i = 0; i < n; ++i)
162 to_vec[i] = from_vec[i];
165 void fromFloatEigenMatrix_20(
const Eigen::MatrixXf& from_mat,
float **& to_mat,
const int m,
const int n)
167 for (
int i = 0; i < m; ++i)
168 for (
int j = 0; j < n; ++j)
169 to_mat[i][j] = from_mat(i,j);
172 int mne_svd_20(
float **mat,
197 int udim = MIN_20(m,n);
199 Eigen::MatrixXf eigen_mat = toFloatEigenMatrix_20(mat, m, n);
202 Eigen::JacobiSVD< Eigen::MatrixXf > svd(eigen_mat ,Eigen::ComputeFullU | Eigen::ComputeFullV);
204 fromFloatEigenVector_20(svd.singularValues(), sing, svd.singularValues().size());
207 fromFloatEigenMatrix_20(svd.matrixU().transpose(), uu, udim, m);
210 fromFloatEigenMatrix_20(svd.matrixV().transpose(), vv, m, n);
216 void mne_matt_mat_mult2_20 (
float **m1,
float **m2,
float **result,
217 int d1,
int d2,
int d3)
228 sgemm (transa,transb,&d3,&d1,&d2,
229 &one,m2[0],&d3,m1[0],&d1,&zero,result[0],&d3);
236 for (j = 0; j < d1; j++)
237 for (
k = 0;
k < d3;
k++) {
239 for (p = 0; p < d2; p++)
240 sum = sum + m1[p][j]*m2[p][
k];
247 float **mne_matt_mat_mult_20 (
float **m1,
float **m2,
int d1,
int d2,
int d3)
250 float **result = ALLOC_CMATRIX_20(d1,d3);
251 mne_matt_mat_mult2_20(m1,m2,result,d1,d2,d3);
255 static void skip_comments(FILE *in)
263 for (c = fgetc(in); c != EOF && c !=
'\n'; c = fgetc(in))
273 static int whitespace(
int c)
276 if (c ==
'\t' || c ==
'\n' || c ==
' ')
282 static int whitespace_quote(
int c,
int inquote)
288 return (c ==
'\t' || c ==
'\n' || c ==
' ');
291 static char *next_word_20(FILE *in)
294 char *next = MALLOC_20(MAXWORD,
char);
302 for (
k = 0, p = 0, c = fgetc(in); c != EOF && !whitespace_quote(c,inquote) ; c = fgetc(in),
k++) {
303 if (
k == 0 && c ==
'"')
308 if (c == EOF &&
k == 0) {
315 for (
k = 0, c = fgetc(in); whitespace(c) ; c = fgetc(in),
k++)
322 printf(
"<%s>\n",next);
327 static int get_fval_20(FILE *in,
float *fval)
329 char *next = next_word_20(in);
331 qWarning(
"bad integer");
334 else if (sscanf(next,
"%g",fval) != 1) {
335 qWarning(
"bad floating point number : %s",next);
347 FiffCoordTransOld::FiffCoordTransOld()
355 this->from = p_FiffCoordTransOld.
from;
356 this->to = p_FiffCoordTransOld.
to;
358 for (
int j = 0; j < 3; j++) {
359 this->move[j] = p_FiffCoordTransOld.
move[j];
360 this->invmove[j] = p_FiffCoordTransOld.
invmove[j];
361 for (
int k = 0;
k < 3;
k++) {
362 this->rot(j,
k) = p_FiffCoordTransOld.
rot(j,
k);
363 this->invrot(j,
k) = p_FiffCoordTransOld.
invrot(j,
k);
378 for (j = 0; j < 3; j++) {
380 for (
k = 0;
k < 3;
k++) {
383 for (p = 0; p < 3; p++)
393 FiffCoordTransOld::FiffCoordTransOld(
int from,
int to,
float rot[3][3],
float move[3])
398 for (
int j = 0; j < 3; j++) {
399 this->move[j] = move[j];
400 for (
int k = 0;
k < 3;
k++)
401 this->rot(j,
k) = rot[j][
k];
408 FiffCoordTransOld::~FiffCoordTransOld()
417 MatrixXf trans = MatrixXf::Identity(4,4);
418 trans.block(0,0,3,3) = this->rot;
419 trans.block(0,3,3,1) = this->move;
431 Matrix4f m = Matrix4f::Identity(4,4);
433 m.block(0,0,3,3) = t->
rot;
434 m.block(0,3,3,1) = t->
move;
436 m = m.inverse().eval();
438 t->
invrot = m.block(0,0,3,3);
449 ti->
move = this->invmove;
451 ti->
rot = this->invrot;
460 void FiffCoordTransOld::fiff_coord_trans(
float r[],
const FiffCoordTransOld *t,
int do_move)
468 for (j = 0; j < 3; j++) {
469 res[j] = (do_move ? t->
move[j] : 0.0);
470 for (
k = 0;
k < 3;
k++)
471 res[j] += t->
rot(j,
k)*r[
k];
473 for (j = 0; j < 3; j++)
497 if (t1->
to == to && t2->
from == from) {
502 else if (t1->
from == to && t2->
from == from) {
504 t1 = tmp_t1->fiff_invert_transform();
509 else if (t1->
to == to && t2->
to == from) {
512 t2 = tmp_t2->fiff_invert_transform();
516 else if (t1->
from == to && t2->
to == from) {
518 t1 = tmp_t1->fiff_invert_transform();
521 t2 = tmp_t2->fiff_invert_transform();
526 qCritical(
"Cannot combine coordinate transforms");
535 qCritical (
"Cannot combine coordinate transforms");
538 FREE_20(t1); FREE_20(t2);
544 void FiffCoordTransOld::fiff_coord_trans_inv(
float r[],
FiffCoordTransOld *t,
int do_move)
552 for (j = 0; j < 3; j++) {
553 res[j] = (do_move ? t->
invmove[j] : 0.0);
554 for (
k = 0;
k < 3;
k++)
557 for (j = 0; j < 3; j++)
573 const char *FiffCoordTransOld::mne_coord_frame_name(
int frame)
576 {FIFFV_COORD_UNKNOWN,
"unknown"},
577 {FIFFV_COORD_DEVICE,
"MEG device"},
578 {FIFFV_COORD_ISOTRAK,
"isotrak"},
579 {FIFFV_COORD_HPI,
"hpi"},
580 {FIFFV_COORD_HEAD,
"head"},
581 {FIFFV_COORD_MRI,
"MRI (surface RAS)"},
583 {FIFFV_COORD_MRI_SLICE,
"MRI slice"},
584 {FIFFV_COORD_MRI_DISPLAY,
"MRI display"},
594 for (
k = 0; frames[
k].frame != -1;
k++) {
595 if (frame == frames[
k].frame)
596 return frames[
k].name;
598 return frames[
k].name;
603 void FiffCoordTransOld::mne_print_coord_transform_label(FILE *log,
char *label,
FiffCoordTransOld *t)
607 if (!label || strlen(label) == 0)
608 fprintf(log,
"Coordinate transformation: ");
610 fprintf(log,
"%s",label);
611 for (frame = t->
from,
k = 0;
k < 2;
k++) {
613 fprintf(log,
"%s -> ",mne_coord_frame_name(frame));
617 fprintf(log,
"%s\n",mne_coord_frame_name(frame));
618 for (p = 0; p < 3; p++)
619 fprintf(log,
"\t% 8.6f % 8.6f % 8.6f\t% 7.2f mm\n",
620 t->
rot(p,X_20),t->
rot(p,Y_20),t->
rot(p,Z_20),1000*t->
move[p]);
621 fprintf(log,
"\t% 8.6f % 8.6f % 8.6f % 7.2f\n",0.0,0.0,0.0,1.0);
628 void FiffCoordTransOld::mne_print_coord_transform(FILE *log,
FiffCoordTransOld *t)
630 mne_print_coord_transform_label(log,NULL,t);
635 FiffCoordTransOld *FiffCoordTransOld::mne_read_transform(
const QString &name,
int from,
int to)
648 fiff_int_t kind, pos;
657 for (
k = 0;
k < stream->dir().size();
k++) {
658 kind = stream->dir()[
k]->kind;
659 pos = stream->dir()[
k]->pos;
664 if (!stream->read_tag(t_pTag,pos))
667 res = FiffCoordTransOld::read_helper( t_pTag );
668 if (res->
from == from && res->
to == to) {
672 else if (res->
from == to && res->
to == from) {
674 res = tmp_res->fiff_invert_transform();
681 qCritical(
"No suitable coordinate transformation found in %s.",name.toUtf8().data());
705 fiff_int_t kind, pos;
709 for (
k = 0;
k < node->nent();
k++)
710 kind = node->dir[
k]->kind;
711 pos = node->dir[
k]->pos;
716 if (!stream->read_tag(t_pTag,pos))
718 res = FiffCoordTransOld::read_helper( t_pTag );
719 if (res->
from == from && res->
to == to) {
723 else if (res->
from == to && res->
to == from) {
725 res = tmp_res->fiff_invert_transform();
731 printf(
"No suitable coordinate transformation found");
742 FiffCoordTransOld *FiffCoordTransOld::mne_read_mri_transform(
const QString &name)
747 return mne_read_transform(name,FIFFV_COORD_MRI,FIFFV_COORD_HEAD);
752 FiffCoordTransOld *FiffCoordTransOld::mne_read_meas_transform(
const QString &name)
757 return mne_read_transform(name,FIFFV_COORD_DEVICE,FIFFV_COORD_HEAD);
762 FiffCoordTransOld *FiffCoordTransOld::mne_read_transform_ascii(
char *name,
int from,
int to)
774 if ((in = fopen(name,
"r")) == NULL) {
775 qCritical(
"%s", name);
778 for (
k = 0;
k < 3;
k++) {
779 if (get_fval_20(in,rot[
k]+X_20) == FAIL)
781 if (get_fval_20(in,rot[
k]+Y_20) == FAIL)
783 if (get_fval_20(in,rot[
k]+Z_20) == FAIL)
785 if (get_fval_20(in,move+
k) == FAIL)
788 for (
k = 0;
k < 4;
k++) {
789 if (get_fval_20(in,&dum) == FAIL)
793 for (
k = 0;
k < 3;
k++)
794 move[
k] = move[
k]/1000.0;
799 qCritical(
"Cannot read the coordinate transformation");
816 return mne_read_transform_ascii(name,FIFFV_COORD_HEAD,FIFFV_COORD_MRI);
823 float rot[3][3] = { { 1.0, 0.0, 0.0 },
826 float move[] = { 0.0, 0.0, 0.0 };
832 FiffCoordTransOld * FiffCoordTransOld::fiff_make_transform_card (
int from,
int to,
842 float ex[3],ey[3],ez[3];
843 float alpha,alpha1,len;
844 float diff1[3],diff2[3];
850 for (
k = 0;
k < 3;
k++) {
851 diff1[
k] = rN[
k] - rL[
k];
852 diff2[
k] = rR[
k] - rL[
k];
854 alpha = VEC_DOT_20(diff1,diff2)/VEC_DOT_20(diff2,diff2);
855 len = VEC_LEN_20(diff2);
856 alpha1 = 1.0 - alpha;
858 for (
k = 0;
k < 3;
k++) {
859 r0[
k] = alpha1*rL[
k] + alpha*rR[
k];
860 ex[
k] = diff2[
k]/len;
861 ey[
k] = rN[
k] - r0[
k];
865 len = VEC_LEN_20(ey);
867 for (
k = 0;
k < 3;
k++)
870 CROSS_PRODUCT_20 (ex,ey,ez);
872 for (
k = 0;
k < 3;
k++) {
873 t->
rot(
k,X_20) = ex[
k];
874 t->
rot(
k,Y_20) = ey[
k];
875 t->
rot(
k,Z_20) = ez[
k];
896 float **from = ALLOC_CMATRIX_20(np,3);
897 float **to = ALLOC_CMATRIX_20(np,3);
898 float from0[3],to0[3],rr[3],diff[3];
906 for (c = 0; c < 3; c++)
907 from0[c] = to0[c] = 0.0;
908 for (j = 0; j < np; j++) {
909 for (c = 0; c < 3; c++) {
910 from0[c] += fromp[j][c];
914 for (c = 0; c < 3; c++) {
915 from0[c] = from0[c]/np;
918 for (j = 0; j < np; j++) {
919 for (c = 0; c < 3; c++) {
920 from[j][c] = fromp[j][c] - from0[c];
921 to[j][c] = top[j][c] - to0[c];
929 float **uu = ALLOC_CMATRIX_20(3,3);
930 float **vv = ALLOC_CMATRIX_20(3,3);
938 S = ALLOC_CMATRIX_20(3,3);
939 for (j = 0; j < 3; j++) {
940 for (
k = 0;
k < 3;
k++) {
942 for (p = 0; p < np; p++)
943 S[j][
k] += w[p]*from[p][j]*to[p][
k];
948 S = mne_matt_mat_mult_20(from,to,3,np,3);
949 if (mne_svd_20(S,3,3,sing,uu,vv) != 0) {
955 R = mne_matt_mat_mult_20(vv,uu,3,3,3);
956 for (j = 0; j < 3; j++)
957 for (
k = 0;
k < 3;
k++)
967 for (j = 0; j < 3; j++) {
969 for (
k = 0;
k < 3;
k++)
970 move[j] = move[j] - rot[j][
k]*from0[
k];
976 printf(
"Procrustes matching (desired vs. transformed) :\n");
978 for (p = 0; p < np; p++) {
979 for (j = 0; j < 3; j++) {
981 for (
k = 0;
k < 3;
k++)
982 rr[j] += rot[j][
k]*fromp[p][
k];
984 VEC_DIFF_20(top[p],rr,diff);
986 printf(
"\t%7.2f %7.2f %7.2f mm <-> %7.2f %7.2f %7.2f mm diff = %8.3f mm\n",
987 1000*top[p][0],1000*top[p][1],1000*top[p][2],
988 1000*rr[0],1000*rr[1],1000*rr[2],1000*VEC_LEN(diff));
990 if (VEC_LEN_20(diff) > max_diff) {
991 printf(
"To large difference in matching : %7.1f > %7.1f mm", 1000*VEC_LEN_20(diff),1000*max_diff);
999 FREE_CMATRIX_20(from);
1000 FREE_CMATRIX_20(to);
1005 FREE_CMATRIX_20(from);
1006 FREE_CMATRIX_20(to);
1016 if(tag->isMatrix() || tag->getType() != FIFFT_COORD_TRANS_STRUCT || tag->data() == NULL)
1017 return p_FiffCoordTrans;
1021 qint32* t_pInt32 = (qint32*)tag->data();
1022 p_FiffCoordTrans->
from = t_pInt32[0];
1023 p_FiffCoordTrans->
to = t_pInt32[1];
1025 float* t_pFloat = (
float*)tag->data();
1028 for (r = 0; r < 3; ++r) {
1029 p_FiffCoordTrans->
move[r] = t_pFloat[11+r];
1030 for (c = 0; c < 3; ++c) {
1031 p_FiffCoordTrans->
rot(r,c) = t_pFloat[2+count];
1037 for (r = 0; r < 3; ++r) {
1038 p_FiffCoordTrans->
invmove[r] = t_pFloat[23+r];
1039 for (c = 0; c < 3; ++c) {
1040 p_FiffCoordTrans->
invrot(r,c) = t_pFloat[14+count];
1045 return p_FiffCoordTrans;