MNE-CPP 0.1.9
A Framework for Electrophysiology
Loading...
Searching...
No Matches
fiff_coord_trans_old.cpp
Go to the documentation of this file.
1//=============================================================================================================
37//=============================================================================================================
38// INCLUDES
39//=============================================================================================================
40
42
43#include <fiff/fiff_tag.h>
44
45#include <QFile>
46
47#include <Eigen/Dense>
48
49//=============================================================================================================
50// USED NAMESPACES
51//=============================================================================================================
52
53using namespace Eigen;
54using namespace FIFFLIB;
55using namespace FIFFLIB;
56
57#ifndef TRUE
58#define TRUE 1
59#endif
60
61#ifndef FALSE
62#define FALSE 0
63#endif
64
65#ifndef FAIL
66#define FAIL -1
67#endif
68
69#ifndef OK
70#define OK 0
71#endif
72
73#define X_20 0
74#define Y_20 1
75#define Z_20 2
76
77#define FREE_20(x) if ((char *)(x) != NULL) free((char *)(x))
78
79#define MALLOC_20(x,t) (t *)malloc((x)*sizeof(t))
80
81static void matrix_error_20(int kind, int nr, int nc)
82
83{
84 if (kind == 1)
85 printf("Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
86 else if (kind == 2)
87 printf("Failed to allocate memory for a %d x %d matrix\n",nr,nc);
88 else
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.");
93 }
94 printf("Cannot continue. Sorry.\n");
95 exit(1);
96}
97
98float **mne_cmatrix_20(int nr,int nc)
99
100{
101 int i;
102 float **m;
103 float *whole;
104
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);
109
110 for(i=0;i<nr;i++)
111 m[i] = whole + i*nc;
112 return m;
113}
114
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];\
119 }
120
121#define ALLOC_CMATRIX_20(x,y) mne_cmatrix_20((x),(y))
122
123#define MAXWORD 1000
124
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])
126
127#define VEC_LEN_20(x) sqrt(VEC_DOT_20(x,x))
128
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];\
133 }
134
135#define FREE_CMATRIX_20(m) mne_free_cmatrix_20((m))
136
137void mne_free_cmatrix_20(float **m)
138{
139 if (m) {
140 FREE_20(*m);
141 FREE_20(m);
142 }
143}
144
145#define MIN_20(a,b) ((a) < (b) ? (a) : (b))
146
147//float
148Eigen::MatrixXf toFloatEigenMatrix_20(float **mat, const int m, const int n)
149{
150 Eigen::MatrixXf eigen_mat(m,n);
151
152 for ( int i = 0; i < m; ++i)
153 for ( int j = 0; j < n; ++j)
154 eigen_mat(i,j) = mat[i][j];
155
156 return eigen_mat;
157}
158
159void fromFloatEigenVector_20(const Eigen::VectorXf& from_vec, float *to_vec, const int n)
160{
161 for ( int i = 0; i < n; ++i)
162 to_vec[i] = from_vec[i];
163}
164
165void fromFloatEigenMatrix_20(const Eigen::MatrixXf& from_mat, float **& to_mat, const int m, const int n)
166{
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);
170}
171
172int mne_svd_20(float **mat, /* The matrix */
173 int m,int n, /* m rows n columns */
174 float *sing, /* Singular values (must have size
175 * MIN(m,n)+1 */
176 float **uu, /* Left eigenvectors */
177 float **vv) /* Right eigenvectors */
178/*
179 * Compute the SVD of mat.
180 * The singular vector calculations depend on whether
181 * or not u and v are given.
182 *
183 * The allocations should be done as follows
184 *
185 * mat = ALLOC_CMATRIX_3(m,n);
186 * vv = ALLOC_CMATRIX_3(MIN(m,n),n);
187 * uu = ALLOC_CMATRIX_3(MIN(m,n),m);
188 * sing = MALLOC_3(MIN(m,n),float);
189 *
190 * mat is modified by this operation
191 *
192 * This simply allocates the workspace and calls the
193 * LAPACK Fortran routine
194 */
195
196{
197 int udim = MIN_20(m,n);
198
199 Eigen::MatrixXf eigen_mat = toFloatEigenMatrix_20(mat, m, n);
200
201 //ToDo Optimize computation depending of whether uu or vv are defined
202 Eigen::JacobiSVD< Eigen::MatrixXf > svd(eigen_mat ,Eigen::ComputeFullU | Eigen::ComputeFullV);
203
204 fromFloatEigenVector_20(svd.singularValues(), sing, svd.singularValues().size());
205
206 if (uu != NULL)
207 fromFloatEigenMatrix_20(svd.matrixU().transpose(), uu, udim, m);
208
209 if (vv != NULL)
210 fromFloatEigenMatrix_20(svd.matrixV().transpose(), vv, m, n);
211
212 return 0;
213 // return info;
214}
215
216void mne_matt_mat_mult2_20 (float **m1,float **m2,float **result,
217 int d1,int d2,int d3)
218 /* Matrix multiplication
219 * result(d1 x d3) = m1(d2 x d1)^T * m2(d2 x d3) */
220
221{
222 #ifdef BLAS
223 char *transa = "N";
224 char *transb = "T";
225 float zero = 0.0;
226 float one = 1.0;
227
228 sgemm (transa,transb,&d3,&d1,&d2,
229 &one,m2[0],&d3,m1[0],&d1,&zero,result[0],&d3);
230
231 return;
232 #else
233 int j,k,p;
234 float sum;
235
236 for (j = 0; j < d1; j++)
237 for (k = 0; k < d3; k++) {
238 sum = 0.0;
239 for (p = 0; p < d2; p++)
240 sum = sum + m1[p][j]*m2[p][k];
241 result[j][k] = sum;
242 }
243 return;
244 #endif
245}
246
247float **mne_matt_mat_mult_20 (float **m1,float **m2,int d1,int d2,int d3)
248
249{
250 float **result = ALLOC_CMATRIX_20(d1,d3);
251 mne_matt_mat_mult2_20(m1,m2,result,d1,d2,d3);
252 return result;
253}
254
255static void skip_comments(FILE *in)
256
257{
258 int c;
259
260 while (1) {
261 c = fgetc(in);
262 if (c == '#') {
263 for (c = fgetc(in); c != EOF && c != '\n'; c = fgetc(in))
264 ;
265 }
266 else {
267 ungetc(c,in);
268 return;
269 }
270 }
271}
272
273static int whitespace(int c)
274
275{
276 if (c == '\t' || c == '\n' || c == ' ')
277 return TRUE;
278 else
279 return FALSE;
280}
281
282static int whitespace_quote(int c, int inquote)
283
284{
285 if (inquote)
286 return (c == '"');
287 else
288 return (c == '\t' || c == '\n' || c == ' ');
289}
290
291static char *next_word_20(FILE *in)
292
293{
294 char *next = MALLOC_20(MAXWORD,char);
295 int c;
296 int p,k;
297 int inquote;
298
299 skip_comments(in);
300
301 inquote = FALSE;
302 for (k = 0, p = 0, c = fgetc(in); c != EOF && !whitespace_quote(c,inquote) ; c = fgetc(in), k++) {
303 if (k == 0 && c == '"')
304 inquote = TRUE;
305 else
306 next[p++] = c;
307 }
308 if (c == EOF && k == 0) {
309 FREE_20(next);
310 return NULL;
311 }
312 else
313 next[p] = '\0';
314 if (c != EOF) {
315 for (k = 0, c = fgetc(in); whitespace(c) ; c = fgetc(in), k++)
316 ;
317 if (c != EOF)
318 ungetc(c,in);
319 }
320#ifdef DEBUG
321 if (next)
322 printf("<%s>\n",next);
323#endif
324 return next;
325}
326
327static int get_fval_20(FILE *in, float *fval)
328{
329 char *next = next_word_20(in);
330 if (next == NULL) {
331 qWarning("bad integer");
332 return FAIL;
333 }
334 else if (sscanf(next,"%g",fval) != 1) {
335 qWarning("bad floating point number : %s",next);
336 FREE_20(next);
337 return FAIL;
338 }
339 FREE_20(next);
340 return OK;
341}
342
343//=============================================================================================================
344// DEFINE MEMBER METHODS
345//=============================================================================================================
346
350
351//=============================================================================================================
352
354{
355 this->from = p_FiffCoordTransOld.from;
356 this->to = p_FiffCoordTransOld.to;
357
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);
364 }
365 }
366}
367
368//=============================================================================================================
369
370FiffCoordTransOld *FiffCoordTransOld::catenate(FiffCoordTransOld *t1, FiffCoordTransOld *t2)
371{
373 int j,k,p;
374
375 t->to = t1->to;
376 t->from = t2->from;
377
378 for (j = 0; j < 3; j++) {
379 t->move[j] = t1->move[j];
380 for (k = 0; k < 3; k++) {
381 t->rot(j,k) = 0.0;
382 t->move[j] += t1->rot(j,k)*t2->move[k];
383 for (p = 0; p < 3; p++)
384 t->rot(j,k) += t1->rot(j,p)*t2->rot(p,k);
385 }
386 }
387 add_inverse(t);
388 return (t);
389}
390
391//=============================================================================================================
392
393FiffCoordTransOld::FiffCoordTransOld(int from, int to, float rot[3][3], float move[3])
394{
395 this->from = from;
396 this->to = to;
397
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];
402 }
403 add_inverse(this);
404}
405
406//=============================================================================================================
407
411
412//=============================================================================================================
413
414FiffCoordTrans FiffCoordTransOld::toNew()
415{
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;
420 t.to = this->to;
421 t.from = this->from;
422 t.trans = trans;
423 t.addInverse(t);
424 return t;
425}
426
427//=============================================================================================================
428
429int FiffCoordTransOld::add_inverse(FiffCoordTransOld *t)
430{
431 Matrix4f m = Matrix4f::Identity(4,4);
432
433 m.block(0,0,3,3) = t->rot;
434 m.block(0,3,3,1) = t->move;
435
436 m = m.inverse().eval();
437
438 t->invrot = m.block(0,0,3,3);
439 t->invmove = m.block(0,3,3,1);
440
441 return OK;
442}
443
444//=============================================================================================================
445
446FiffCoordTransOld *FiffCoordTransOld::fiff_invert_transform() const
447{
449 ti->move = this->invmove;
450 ti->invmove = this ->move;
451 ti->rot = this->invrot;
452 ti->invrot = this ->rot;
453 ti->from = this->to;
454 ti->to = this->from;
455 return (ti);
456}
457
458//=============================================================================================================
459
460void FiffCoordTransOld::fiff_coord_trans(float r[], const FiffCoordTransOld *t, int do_move)
461/*
462 * Apply coordinate transformation
463 */
464{
465 int j,k;
466 float res[3];
467
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];
472 }
473 for (j = 0; j < 3; j++)
474 r[j] = res[j];
475}
476
477//=============================================================================================================
478
479FiffCoordTransOld *FiffCoordTransOld::fiff_combine_transforms(int from, int to, FiffCoordTransOld *t1, FiffCoordTransOld *t2)
480/*
481 * Combine two coordinate transformations
482 * to yield a transform from 'from' system
483 * to 'to' system.
484 *
485 * Return NULL if this fails
486 *
487 */
488{
489 FiffCoordTransOld* t = NULL;
490 int swapped = 0;
491 FiffCoordTransOld* temp;
492 /*
493 * We have a total of eight possibilities:
494 * four without swapping and four with
495 */
496 while (1) {
497 if (t1->to == to && t2->from == from) {
498 t1 = new FiffCoordTransOld(*t1);
499 t2 = new FiffCoordTransOld(*t2);
500 break;
501 }
502 else if (t1->from == to && t2->from == from) {
503 FiffCoordTransOld* tmp_t1 = t1;
504 t1 = tmp_t1->fiff_invert_transform();//Memory leak here!!
505 delete tmp_t1;
506 t2 = new FiffCoordTransOld(*t2);
507 break;
508 }
509 else if (t1->to == to && t2->to == from) {
510 t1 = new FiffCoordTransOld(*t1);
511 FiffCoordTransOld* tmp_t2 = t2;
512 t2 = tmp_t2->fiff_invert_transform();//Memory leak here!!
513 delete tmp_t2;
514 break;
515 }
516 else if (t1->from == to && t2->to == from) {
517 FiffCoordTransOld* tmp_t1 = t1;
518 t1 = tmp_t1->fiff_invert_transform();//Memory leak here!!
519 delete tmp_t1;
520 FiffCoordTransOld* tmp_t2 = t2;
521 t2 = tmp_t2->fiff_invert_transform();//Memory leak here!!
522 delete tmp_t2;
523 break;
524 }
525 if (swapped) { /* Already swapped and not found */
526 qCritical("Cannot combine coordinate transforms");
527 return (t);
528 }
529 temp = t1; /* Try it swapped as well */
530 t1 = t2;
531 t2 = temp;
532 swapped = 1;
533 }
534 if (t1->from != t2->to) /* Transforms must match on the other side as well */
535 qCritical ("Cannot combine coordinate transforms");
536 else /* We can do it directly */
537 t = catenate(t1,t2);
538 FREE_20(t1); FREE_20(t2);
539 return (t);
540}
541
542//=============================================================================================================
543
544void FiffCoordTransOld::fiff_coord_trans_inv(float r[], FiffCoordTransOld *t, int do_move)
545/*
546 * Apply inverse coordinate transformation
547 */
548{
549 int j,k;
550 float res[3];
551
552 for (j = 0; j < 3; j++) {
553 res[j] = (do_move ? t->invmove[j] : 0.0);
554 for (k = 0; k < 3; k++)
555 res[j] += t->invrot(j,k)*r[k];
556 }
557 for (j = 0; j < 3; j++)
558 r[j] = res[j];
559}
560
561//=============================================================================================================
562
563namespace FIFFLIB
564{
565
566typedef struct {
567 int frame;
568 const char *name;
570
571}
572
573const char *FiffCoordTransOld::mne_coord_frame_name(int frame)
574{
575 static frameNameRec frames[] = {
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)"},
582 {FIFFV_MNE_COORD_MRI_VOXEL, "MRI voxel"},
583 {FIFFV_COORD_MRI_SLICE,"MRI slice"},
584 {FIFFV_COORD_MRI_DISPLAY,"MRI display"},
585 {FIFFV_MNE_COORD_CTF_DEVICE,"CTF MEG device"},
586 {FIFFV_MNE_COORD_CTF_HEAD,"CTF/4D/KIT head"},
587 {FIFFV_MNE_COORD_RAS,"RAS (non-zero origin)"},
588 {FIFFV_MNE_COORD_MNI_TAL,"MNI Talairach"},
589 {FIFFV_MNE_COORD_FS_TAL_GTZ,"Talairach (MNI z > 0)"},
590 {FIFFV_MNE_COORD_FS_TAL_LTZ,"Talairach (MNI z < 0)"},
591 {-1,"unknown"}
592 };
593 int k;
594 for (k = 0; frames[k].frame != -1; k++) {
595 if (frame == frames[k].frame)
596 return frames[k].name;
597 }
598 return frames[k].name;
599}
600
601//=============================================================================================================
602
603void FiffCoordTransOld::mne_print_coord_transform_label(FILE *log, char *label, FiffCoordTransOld *t)
604{
605 int k,p;
606 int frame;
607 if (!label || strlen(label) == 0)
608 fprintf(log,"Coordinate transformation: ");
609 else
610 fprintf(log,"%s",label);
611 for (frame = t->from, k = 0; k < 2; k++) {
612 if (k == 0) {
613 fprintf(log,"%s -> ",mne_coord_frame_name(frame));
614 frame = t->to;
615 }
616 else {
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);
622 }
623 }
624}
625
626//=============================================================================================================
627
628void FiffCoordTransOld::mne_print_coord_transform(FILE *log, FiffCoordTransOld *t)
629{
630 mne_print_coord_transform_label(log,NULL,t);
631}
632
633//=============================================================================================================
634
635FiffCoordTransOld *FiffCoordTransOld::mne_read_transform(const QString &name, int from, int to)
636/*
637 * Read the specified coordinate transformation
638 */
639{
640 QFile file(name);
641 FiffStream::SPtr stream(new FiffStream(&file));
642
643 FiffCoordTransOld* res = NULL;
644 // fiffFile in = NULL;
645 FiffTag::SPtr t_pTag;
646 // fiffTagRec tag;
647 // fiffDirEntry dir;
648 fiff_int_t kind, pos;
649 int k;
650
651 // tag.data = NULL;
652 // if ((in = fiff_open(name.toUtf8().data())) == NULL)
653 // goto out;
654 if(!stream->open())
655 goto out;
656
657 for (k = 0; k < stream->dir().size(); k++) {
658 kind = stream->dir()[k]->kind;
659 pos = stream->dir()[k]->pos;
660 if (kind == FIFF_COORD_TRANS) {
661 // if (fiff_read_this_tag (in->fd,dir->pos,&tag) == FIFF_FAIL)
662 // goto out;
663 // res = (fiffCoordTrans)tag.data;
664 if (!stream->read_tag(t_pTag,pos))
665 goto out;
666
667 res = FiffCoordTransOld::read_helper( t_pTag );
668 if (res->from == from && res->to == to) {
669 // tag.data = NULL;
670 goto out;
671 }
672 else if (res->from == to && res->to == from) {
673 FiffCoordTransOld* tmp_res = res;
674 res = tmp_res->fiff_invert_transform();//Memory leak here!!
675 delete tmp_res;
676 goto out;
677 }
678 res = NULL;
679 }
680 }
681 qCritical("No suitable coordinate transformation found in %s.",name.toUtf8().data());
682 goto out;
683
684out : {
685 // FREE(tag.data);
686 // fiff_close(in);
687 stream->close();
688 return res;
689 }
690
691 return res;
692}
693
694//=============================================================================================================
695
696FiffCoordTransOld *FiffCoordTransOld::mne_read_transform_from_node(FiffStream::SPtr &stream, const FiffDirNode::SPtr &node, int from, int to)
697/*
698 * Read the specified coordinate transformation
699 */
700{
701 FiffCoordTransOld* res = NULL;
702 FiffTag::SPtr t_pTag;
703 // fiffTagRec tag;
704 // fiffDirEntry dir;
705 fiff_int_t kind, pos;
706 int k;
707
708 // tag.data = NULL;
709 for (k = 0; k < node->nent(); k++)
710 kind = node->dir[k]->kind;
711 pos = node->dir[k]->pos;
712 if (kind == FIFF_COORD_TRANS) {
713 // if (fiff_read_this_tag (in->fd,dir->pos,&tag) == FIFF_FAIL)
714 // goto out;
715 // res = (fiffCoordTrans)tag.data;
716 if (!stream->read_tag(t_pTag,pos))
717 goto out;
718 res = FiffCoordTransOld::read_helper( t_pTag );
719 if (res->from == from && res->to == to) {
720 // tag.data = NULL;
721 goto out;
722 }
723 else if (res->from == to && res->to == from) {
724 FiffCoordTransOld* tmp_res = res;
725 res = tmp_res->fiff_invert_transform();//Memory leak here!!
726 delete tmp_res;
727 goto out;
728 }
729 res = NULL;
730 }
731 printf("No suitable coordinate transformation found");
732 goto out;
733
734out : {
735 // FREE(tag.data);
736 return res;
737 }
738}
739
740//=============================================================================================================
741
742FiffCoordTransOld *FiffCoordTransOld::mne_read_mri_transform(const QString &name)
743/*
744 * Read the MRI -> HEAD coordinate transformation
745 */
746{
747 return mne_read_transform(name,FIFFV_COORD_MRI,FIFFV_COORD_HEAD);
748}
749
750//=============================================================================================================
751
752FiffCoordTransOld *FiffCoordTransOld::mne_read_meas_transform(const QString &name)
753/*
754 * Read the MEG device -> HEAD coordinate transformation
755 */
756{
757 return mne_read_transform(name,FIFFV_COORD_DEVICE,FIFFV_COORD_HEAD);
758}
759
760//=============================================================================================================
761
762FiffCoordTransOld *FiffCoordTransOld::mne_read_transform_ascii(char *name, int from, int to)
763/*
764 * Read the Neuromag -> FreeSurfer transformation matrix
765 */
766{
767 FILE *in = NULL;
768 FiffCoordTransOld* t = NULL;
769 float rot[3][3];
770 float move[3];
771 int k;
772 float dum;
773
774 if ((in = fopen(name,"r")) == NULL) {
775 qCritical("%s", name);
776 goto bad;
777 }
778 for (k = 0; k < 3; k++) {
779 if (get_fval_20(in,rot[k]+X_20) == FAIL)
780 goto noread;
781 if (get_fval_20(in,rot[k]+Y_20) == FAIL)
782 goto noread;
783 if (get_fval_20(in,rot[k]+Z_20) == FAIL)
784 goto noread;
785 if (get_fval_20(in,move+k) == FAIL)
786 goto noread;
787 }
788 for (k = 0; k < 4; k++) {
789 if (get_fval_20(in,&dum) == FAIL)
790 goto noread;
791 }
792 fclose(in);
793 for (k = 0; k < 3; k++)
794 move[k] = move[k]/1000.0;
795 t = new FiffCoordTransOld(from, to, rot, move );
796 return t;
797
798noread : {
799 qCritical("Cannot read the coordinate transformation");
800 goto bad;
801 }
802
803bad : {
804 if(t)
805 delete t;
806 if (in != NULL)
807 fclose(in);
808 return NULL;
809 }
810}
811
812//=============================================================================================================
813
814FiffCoordTransOld *FiffCoordTransOld::mne_read_FShead2mri_transform(char *name)
815{
816 return mne_read_transform_ascii(name,FIFFV_COORD_HEAD,FIFFV_COORD_MRI);
817}
818
819//=============================================================================================================
820
821FiffCoordTransOld *FiffCoordTransOld::mne_identity_transform(int from, int to)
822{
823 float rot[3][3] = { { 1.0, 0.0, 0.0 },
824 { 0.0, 1.0, 0.0 },
825 { 0.0, 0.0, 1.0 } };
826 float move[] = { 0.0, 0.0, 0.0 };
827 return new FiffCoordTransOld(from,to,rot,move);
828}
829
830//=============================================================================================================
831
832FiffCoordTransOld * FiffCoordTransOld::fiff_make_transform_card (int from,int to,
833 float *rL,
834 float *rN,
835 float *rR)
836/* 'from' coordinate system
837 * cardinal points expressed in
838 * the 'to' system */
839
840{
842 float ex[3],ey[3],ez[3]; /* The unit vectors */
843 float alpha,alpha1,len;
844 float diff1[3],diff2[3];
845 int k;
846 float r0[3];
847
848 t->from = from;
849 t->to = to;
850 for (k = 0; k < 3; k++) {
851 diff1[k] = rN[k] - rL[k];
852 diff2[k] = rR[k] - rL[k];
853 }
854 alpha = VEC_DOT_20(diff1,diff2)/VEC_DOT_20(diff2,diff2);
855 len = VEC_LEN_20(diff2);
856 alpha1 = 1.0 - alpha;
857
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];
862 t->move[k] = r0[k];
863 }
864
865 len = VEC_LEN_20(ey);
866
867 for (k = 0; k < 3; k++)
868 ey[k] = ey[k]/len;
869
870 CROSS_PRODUCT_20 (ex,ey,ez);
871
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];
876 }
877
878 add_inverse (t);
879
880 return (t);
881}
882
883//=============================================================================================================
884
885FiffCoordTransOld* FiffCoordTransOld::procrustes_align(int from_frame, /* The coordinate frames */
886 int to_frame,
887 float **fromp, /* Point locations in these two coordinate frames */
888 float **top,
889 float *w, /* Optional weights */
890 int np, /* How many points */
891 float max_diff) /* Maximum allowed difference */
892/*
893 * Perform an alignment using the the solution of the orthogonal (weighted) Procrustes problem
894 */
895{
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];
899 int j,k,c,p;
900 float rot[3][3];
901 float move[3];
902
903 /*
904 * Calculate the centroids and subtract;
905 */
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];
911 to0[c] += top[j][c];
912 }
913 }
914 for (c = 0; c < 3; c++) {
915 from0[c] = from0[c]/np;
916 to0[c] = to0[c]/np;
917 }
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];
922 }
923 }
924 /*
925 * Compute the solution of the orthogonal Proscrustes problem
926 */
927 {
928 float **S;
929 float **uu = ALLOC_CMATRIX_20(3,3);
930 float **vv = ALLOC_CMATRIX_20(3,3);
931 float **R = NULL;
932 float sing[3];
933
934 if (w) {
935 /*
936 * This is the weighted version which allows multiplicity of points
937 */
938 S = ALLOC_CMATRIX_20(3,3);
939 for (j = 0; j < 3; j++) {
940 for (k = 0; k < 3; k++) {
941 S[j][k] = 0.0;
942 for (p = 0; p < np; p++)
943 S[j][k] += w[p]*from[p][j]*to[p][k];
944 }
945 }
946 }
947 else
948 S = mne_matt_mat_mult_20(from,to,3,np,3);
949 if (mne_svd_20(S,3,3,sing,uu,vv) != 0) {
950 FREE_CMATRIX_20(S);
951 FREE_CMATRIX_20(uu);
952 FREE_CMATRIX_20(vv);
953 goto bad;
954 }
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++)
958 rot[j][k] = R[j][k];
959 FREE_CMATRIX_20(R);
960 FREE_CMATRIX_20(S);
961 FREE_CMATRIX_20(uu);
962 FREE_CMATRIX_20(vv);
963 }
964 /*
965 * Now we need to generate a transformed translation vector
966 */
967 for (j = 0; j < 3; j++) {
968 move[j] = to0[j];
969 for (k = 0; k < 3; k++)
970 move[j] = move[j] - rot[j][k]*from0[k];
971 }
972 /*
973 * Test the transformation and print the results
974 */
975 #ifdef DEBUG
976 printf("Procrustes matching (desired vs. transformed) :\n");
977 #endif
978 for (p = 0; p < np; p++) {
979 for (j = 0; j < 3; j++) {
980 rr[j] = move[j];
981 for (k = 0; k < 3; k++)
982 rr[j] += rot[j][k]*fromp[p][k];
983 }
984 VEC_DIFF_20(top[p],rr,diff);
985 #ifdef DEBUG
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));
989 #endif
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);
992 goto bad;
993 }
994 }
995 #ifdef DEBUG
996 printf("\n");
997 #endif
998
999 FREE_CMATRIX_20(from);
1000 FREE_CMATRIX_20(to);
1001
1002 return new FiffCoordTransOld(from_frame,to_frame,rot,move);
1003
1004 bad : {
1005 FREE_CMATRIX_20(from);
1006 FREE_CMATRIX_20(to);
1007 return NULL;
1008 }
1009}
1010
1011//=============================================================================================================
1012
1013FiffCoordTransOld *FiffCoordTransOld::read_helper( FIFFLIB::FiffTag::SPtr& tag)
1014{
1015 FiffCoordTransOld* p_FiffCoordTrans = NULL;
1016 if(tag->isMatrix() || tag->getType() != FIFFT_COORD_TRANS_STRUCT || tag->data() == NULL)
1017 return p_FiffCoordTrans;
1018 else
1019 {
1020 p_FiffCoordTrans = new FiffCoordTransOld;
1021 qint32* t_pInt32 = (qint32*)tag->data();
1022 p_FiffCoordTrans->from = t_pInt32[0];
1023 p_FiffCoordTrans->to = t_pInt32[1];
1024
1025 float* t_pFloat = (float*)tag->data();
1026 int count = 0;
1027 int r, c;
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];
1032 ++count;
1033 }
1034 }
1035
1036 count = 0;
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];
1041 ++count;
1042 }
1043 }
1044
1045 return p_FiffCoordTrans;
1046 }
1047}
FiffTag class declaration, which provides fiff tag I/O and processing methods.
#define FIFFV_MNE_COORD_MNI_TAL
#define FIFFV_MNE_COORD_FS_TAL_LTZ
#define FIFFV_MNE_COORD_CTF_DEVICE
#define FIFFV_MNE_COORD_MRI_VOXEL
#define FIFFV_MNE_COORD_CTF_HEAD
#define FIFFV_MNE_COORD_FS_TAL_GTZ
#define FIFFV_MNE_COORD_RAS
FiffCoordTransOld class declaration.
int k
Definition fiff_tag.cpp:324
#define FIFF_COORD_TRANS
Definition fiff_file.h:475
Coordinate transformation descriptor.
Coordinate transformation description.
Eigen::Matrix< float, 4, 4, Eigen::DontAlign > trans
static bool addInverse(FiffCoordTrans &t)
QSharedPointer< FiffDirNode > SPtr
FIFF File I/O routines.
QSharedPointer< FiffStream > SPtr
QSharedPointer< FiffTag > SPtr
Definition fiff_tag.h:152