MNE-CPP  0.1.9
A Framework for Electrophysiology
fiff_coord_trans_old.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //=============================================================================================================
38 // INCLUDES
39 //=============================================================================================================
40 
41 #include "fiff_coord_trans_old.h"
42 
43 #include <fiff/fiff_tag.h>
44 
45 #include <QFile>
46 
47 #include <Eigen/Dense>
48 
49 //=============================================================================================================
50 // USED NAMESPACES
51 //=============================================================================================================
52 
53 using namespace Eigen;
54 using namespace FIFFLIB;
55 using 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 
81 static 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 
98 float **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 
137 void 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
148 Eigen::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 
159 void 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 
165 void 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 
172 int 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 
216 void 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 
247 float **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 
255 static 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 
273 static int whitespace(int c)
274 
275 {
276  if (c == '\t' || c == '\n' || c == ' ')
277  return TRUE;
278  else
279  return FALSE;
280 }
281 
282 static 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 
291 static 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 
327 static 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 
347 FiffCoordTransOld::FiffCoordTransOld()
348 {
349 }
350 
351 //=============================================================================================================
352 
353 FiffCoordTransOld::FiffCoordTransOld(const FiffCoordTransOld &p_FiffCoordTransOld)
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 
370 FiffCoordTransOld *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 
393 FiffCoordTransOld::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 
408 FiffCoordTransOld::~FiffCoordTransOld()
409 {
410 }
411 
412 //=============================================================================================================
413 
414 FiffCoordTrans 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 
429 int 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 
446 FiffCoordTransOld *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 
460 void 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 
479 FiffCoordTransOld *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 
544 void 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 
563 namespace FIFFLIB
564 {
565 
566 typedef struct {
567  int frame;
568  const char *name;
569 } frameNameRec;
570 
571 }
572 
573 const 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 
603 void 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 
628 void FiffCoordTransOld::mne_print_coord_transform(FILE *log, FiffCoordTransOld *t)
629 {
630  mne_print_coord_transform_label(log,NULL,t);
631 }
632 
633 //=============================================================================================================
634 
635 FiffCoordTransOld *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 
684 out : {
685  // FREE(tag.data);
686  // fiff_close(in);
687  stream->close();
688  return res;
689  }
690 
691  return res;
692 }
693 
694 //=============================================================================================================
695 
696 FiffCoordTransOld *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 
734 out : {
735  // FREE(tag.data);
736  return res;
737  }
738 }
739 
740 //=============================================================================================================
741 
742 FiffCoordTransOld *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 
752 FiffCoordTransOld *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 
762 FiffCoordTransOld *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 
798 noread : {
799  qCritical("Cannot read the coordinate transformation");
800  goto bad;
801  }
802 
803 bad : {
804  if(t)
805  delete t;
806  if (in != NULL)
807  fclose(in);
808  return NULL;
809  }
810 }
811 
812 //=============================================================================================================
813 
814 FiffCoordTransOld *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 
821 FiffCoordTransOld *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 
832 FiffCoordTransOld * 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 
885 FiffCoordTransOld* 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 
1013 FiffCoordTransOld *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 }
FIFFV_MNE_COORD_MRI_VOXEL
#define FIFFV_MNE_COORD_MRI_VOXEL
Definition: fiff_constants.h:482
FIFFV_MNE_COORD_CTF_HEAD
#define FIFFV_MNE_COORD_CTF_HEAD
Definition: fiff_constants.h:481
FIFFLIB::FiffCoordTransOld::to
FIFFLIB::fiff_int_t to
Definition: fiff_coord_trans_old.h:196
FIFFV_MNE_COORD_CTF_DEVICE
#define FIFFV_MNE_COORD_CTF_DEVICE
Definition: fiff_constants.h:480
fiff_tag.h
FiffTag class declaration, which provides fiff tag I/O and processing methods.
FIFFLIB::FiffStream::SPtr
QSharedPointer< FiffStream > SPtr
Definition: fiff_stream.h:107
FIFFLIB::FiffDirNode::SPtr
QSharedPointer< FiffDirNode > SPtr
Definition: fiff_dir_node.h:76
FIFFLIB::FiffCoordTransOld::from
FIFFLIB::fiff_int_t from
Definition: fiff_coord_trans_old.h:195
FIFFLIB::FiffCoordTransOld::invrot
Eigen::Matrix3f invrot
Definition: fiff_coord_trans_old.h:199
FIFFLIB::FiffCoordTransOld::rot
Eigen::Matrix3f rot
Definition: fiff_coord_trans_old.h:197
k
int k
Definition: fiff_tag.cpp:322
FIFFLIB::FiffCoordTransOld
Coordinate transformation descriptor.
Definition: fiff_coord_trans_old.h:80
FIFFV_MNE_COORD_MNI_TAL
#define FIFFV_MNE_COORD_MNI_TAL
Definition: fiff_constants.h:484
FIFF_COORD_TRANS
#define FIFF_COORD_TRANS
Definition: fiff_file.h:475
FIFFLIB::FiffCoordTrans::addInverse
static bool addInverse(FiffCoordTrans &t)
Definition: fiff_coord_trans.cpp:265
FIFFLIB::FiffTag::SPtr
QSharedPointer< FiffTag > SPtr
Definition: fiff_tag.h:152
FIFFLIB::FiffCoordTrans::from
fiff_int_t from
Definition: fiff_coord_trans.h:295
FIFFV_MNE_COORD_FS_TAL_LTZ
#define FIFFV_MNE_COORD_FS_TAL_LTZ
Definition: fiff_constants.h:486
FIFFV_MNE_COORD_RAS
#define FIFFV_MNE_COORD_RAS
Definition: fiff_constants.h:483
FIFFV_MNE_COORD_FS_TAL_GTZ
#define FIFFV_MNE_COORD_FS_TAL_GTZ
Definition: fiff_constants.h:485
FIFFLIB::FiffCoordTrans::to
fiff_int_t to
Definition: fiff_coord_trans.h:296
FIFFLIB::FiffStream
FIFF File I/O routines.
Definition: fiff_stream.h:104
FIFFLIB::FiffCoordTrans
Coordinate transformation description.
Definition: fiff_coord_trans.h:74
FIFFLIB::FiffCoordTransOld::invmove
Eigen::Vector3f invmove
Definition: fiff_coord_trans_old.h:200
FIFFLIB::FiffCoordTrans::trans
Eigen::Matrix< float, 4, 4, Eigen::DontAlign > trans
Definition: fiff_coord_trans.h:297
FIFFLIB::FiffCoordTransOld::move
Eigen::Vector3f move
Definition: fiff_coord_trans_old.h:198
fiff_coord_trans_old.h
FiffCoordTransOld class declaration.
FIFFLIB::frameNameRec
Definition: fiff_coord_trans_old.cpp:566