63 #include <QCoreApplication>
64 #include <QtConcurrent>
66 #define _USE_MATH_DEFINES
69 #include <Eigen/Dense>
70 #include <Eigen/Sparse>
73 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
83 using namespace Eigen;
84 using namespace FIFFLIB;
85 using namespace MNELIB;
109 #define VEC_DOT_17(x,y) ((x)[X_17]*(y)[X_17] + (x)[Y_17]*(y)[Y_17] + (x)[Z_17]*(y)[Z_17])
111 #define VEC_LEN_17(x) sqrt(VEC_DOT_17(x,x))
113 #define VEC_DIFF_17(from,to,diff) {\
114 (diff)[X_17] = (to)[X_17] - (from)[X_17];\
115 (diff)[Y_17] = (to)[Y_17] - (from)[Y_17];\
116 (diff)[Z_17] = (to)[Z_17] - (from)[Z_17];\
119 #define VEC_COPY_17(to,from) {\
120 (to)[X_17] = (from)[X_17];\
121 (to)[Y_17] = (from)[Y_17];\
122 (to)[Z_17] = (from)[Z_17];\
125 #define CROSS_PRODUCT_17(x,y,xy) {\
126 (xy)[X_17] = (x)[Y_17]*(y)[Z_17]-(y)[Y_17]*(x)[Z_17];\
127 (xy)[Y_17] = -((x)[X_17]*(y)[Z_17]-(y)[X_17]*(x)[Z_17]);\
128 (xy)[Z_17] = (x)[X_17]*(y)[Y_17]-(y)[X_17]*(x)[Y_17];\
131 #define MALLOC_17(x,t) (t *)malloc((x)*sizeof(t))
133 #define REALLOC_17(x,y,t) (t *)((x == NULL) ? malloc((y)*sizeof(t)) : realloc((x),(y)*sizeof(t)))
135 #define ALLOC_INT_17(x) MALLOC_17(x,int)
137 #define ALLOC_CMATRIX_17(x,y) mne_cmatrix_17((x),(y))
139 static void matrix_error_17(
int kind,
int nr,
int nc)
143 printf(
"Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
145 printf(
"Failed to allocate memory for a %d x %d matrix\n",nr,nc);
147 printf(
"Allocation error for a %d x %d matrix\n",nr,nc);
148 if (
sizeof(
void *) == 4) {
149 printf(
"This is probably because you seem to be using a computer with 32-bit architecture.\n");
150 printf(
"Please consider moving to a 64-bit platform.");
152 printf(
"Cannot continue. Sorry.\n");
156 float** mne_cmatrix_17(
int numPoints,
int numDim)
161 m = MALLOC_17(numPoints,
float *);
164 matrix_error_17( 1, numPoints, numDim);
167 whole = MALLOC_17( numPoints * numDim,
float);
170 matrix_error_17(2, numPoints, numDim);
173 for(
int i = 0; i < numPoints; ++i)
175 m[i] = &whole[ i * numDim ];
181 #define FREE_17(x) if ((char *)(x) != NULL) free((char *)(x))
183 #define FREE_CMATRIX_17(m) mne_free_cmatrix_17((m))
185 #define FREE_ICMATRIX_17(m) mne_free_icmatrix_17((m))
187 void mne_free_cmatrix_17 (
float **m)
195 void mne_free_icmatrix_17 (
int **m)
204 #define NNEIGHBORS 26
206 #define CURVATURE_FILE_MAGIC_NUMBER (16777215)
208 #define TAG_MGH_XFORM 31
209 #define TAG_SURF_GEOM 21
210 #define TAG_OLD_USEREALRAS 2
211 #define TAG_COLORTABLE 5
212 #define TAG_OLD_MGH_XFORM 30
213 #define TAG_OLD_COLORTABLE 1
215 #define TAG_USEREALRAS 4
217 #define ALLOC_ICMATRIX_17(x,y) mne_imatrix_17((x),(y))
219 int **mne_imatrix_17(
int nr,
int nc)
225 m = MALLOC_17(nr,
int *);
226 if (!m) matrix_error_17(1,nr,nc);
227 whole = MALLOC_17(nr*nc,
int);
228 if (!whole) matrix_error_17(2,nr,nc);
235 Eigen::MatrixXf toFloatEigenMatrix_17(
float **mat,
const int m,
const int n)
237 Eigen::MatrixXf eigen_mat(m,n);
239 for (
int i = 0; i < m; ++i)
240 for (
int j = 0; j < n; ++j)
241 eigen_mat(i,j) = mat[i][j];
246 void fromFloatEigenMatrix_17(
const Eigen::MatrixXf& from_mat,
float **& to_mat,
const int m,
const int n)
248 for (
int i = 0; i < m; ++i)
249 for (
int j = 0; j < n; ++j)
250 to_mat[i][j] = from_mat(i,j);
253 void fromFloatEigenMatrix_17(
const Eigen::MatrixXf& from_mat,
float **& to_mat)
255 fromFloatEigenMatrix_17(from_mat, to_mat, from_mat.rows(), from_mat.cols());
258 void fromIntEigenMatrix_17(
const Eigen::MatrixXi& from_mat,
int **&to_mat,
const int m,
const int n)
260 for (
int i = 0; i < m; ++i)
261 for (
int j = 0; j < n; ++j)
262 to_mat[i][j] = from_mat(i,j);
265 void fromIntEigenMatrix_17(
const Eigen::MatrixXi& from_mat,
int **&to_mat)
267 fromIntEigenMatrix_17(from_mat, to_mat, from_mat.rows(), from_mat.cols());
280 float rot[3][3],move[3];
283 VEC_COPY_17(move,r0);
285 for (j = 0; j < 3; j++) {
286 rot[j][0] = x_ras[j];
287 rot[j][1] = y_ras[j];
288 rot[j][2] = z_ras[j];
291 for (j = 0; j < 3; j++)
292 for (
k = 0;
k < 3;
k++)
293 rot[j][
k] = voxel_size[
k]*rot[j][
k];
300 static int comp_points1(
const void *vp1,
const void *vp2)
306 if (v1->nearest > v2->nearest)
308 else if (v1->nearest == v2->nearest)
314 static int comp_points2(
const void *vp1,
const void *vp2)
320 if (v1->vert > v2->vert)
322 else if (v1->vert == v2->vert)
328 void mne_sort_nearest_by_nearest(
MneNearest* points,
int npoint)
331 if (npoint > 1 && points != NULL)
332 qsort(points,npoint,
sizeof(
MneNearest),comp_points1);
340 MneSurfaceOrVolume::MneSurfaceOrVolume()
346 MneSurfaceOrVolume::~MneSurfaceOrVolume()
349 FREE_CMATRIX_17(this->rr);
350 FREE_CMATRIX_17(this->nn);
351 FREE_17(this->inuse);
352 FREE_17(this->vertno);
354 FREE_ICMATRIX_17(this->itris);
356 FREE_17(this->use_tris);
357 FREE_ICMATRIX_17(this->use_itris);
358 if (this->neighbor_tri) {
359 for (
k = 0;
k < this->np;
k++)
360 FREE_17(this->neighbor_tri[
k]);
361 FREE_17(this->neighbor_tri);
363 FREE_17(this->nneighbor_tri);
366 if (this->neighbor_vert) {
367 for (
k = 0;
k < this->np;
k++)
368 FREE_17(this->neighbor_vert[
k]);
369 FREE_17(this->neighbor_vert);
371 FREE_17(this->nneighbor_vert);
372 if (this->vert_dist) {
373 for (
k = 0;
k < this->np;
k++)
374 FREE_17(this->vert_dist[
k]);
375 FREE_17(this->vert_dist);
377 FREE_17(this->nearest);
379 for (
k = 0;
k < this->npatch;
k++)
381 delete this->patches[
k];
382 FREE_17(this->patches);
386 FREE_17(this->voxel_surf_RAS_t);
387 FREE_17(this->MRI_voxel_surf_RAS_t);
388 FREE_17(this->MRI_surf_RAS_RAS_t);
389 if(this->interpolator)
390 delete this->interpolator;
391 this->MRI_volume.clear();
394 delete this->vol_geom;
397 if (this->user_data && this->user_data_free)
398 this->user_data_free(this->user_data);
403 double MneSurfaceOrVolume::solid_angle(
float *from,
MneTriangle* tri)
409 double v1[3],v2[3],v3[3];
410 double l1,l2,l3,s,triple;
413 VEC_DIFF_17 (from,tri->r1,v1);
414 VEC_DIFF_17 (from,tri->r2,v2);
415 VEC_DIFF_17 (from,tri->r3,v3);
417 CROSS_PRODUCT_17(v1,v2,cross);
418 triple = VEC_DOT_17(cross,v3);
423 s = (l1*l2*l3+VEC_DOT_17(v1,v2)*l3+VEC_DOT_17(v1,v3)*l2+VEC_DOT_17(v2,v3)*l1);
425 return (2.0*atan2(triple,s));
430 double MneSurfaceOrVolume::sum_solids(
float *from,
MneSurfaceOld* surf)
433 double tot_angle, angle;
434 for (
k = 0, tot_angle = 0.0;
k < surf->ntri;
k++) {
435 angle = solid_angle(from,surf->tris+
k);
451 float mindist,dist,diff[3];
453 int omit,omit_outside;
458 if (spaces[0]->coord_frame == FIFFV_COORD_HEAD && mri_head_t == NULL) {
459 printf(
"Source spaces are in head coordinates and no coordinate transform was provided!");
465 printf(
"Source spaces are in ");
466 if (spaces[0]->coord_frame == FIFFV_COORD_HEAD)
467 printf(
"head coordinates.\n");
468 else if (spaces[0]->coord_frame == FIFFV_COORD_MRI)
469 printf(
"MRI coordinates.\n");
471 printf(
"unknown (%d) coordinates.\n",spaces[0]->coord_frame);
472 printf(
"Checking that the sources are inside the bounding surface ");
474 printf(
"and at least %6.1f mm away",1000*limit);
475 printf(
" (will take a few...)\n");
478 for (
k = 0;
k < nspace;
k++) {
480 for (p1 = 0; p1 < s->np; p1++)
482 VEC_COPY_17(r1,s->rr[p1]);
483 if (s->coord_frame == FIFFV_COORD_HEAD)
484 FiffCoordTransOld::fiff_coord_trans_inv(r1,mri_head_t,FIFFV_MOVE);
488 tot_angle = sum_solids(r1,surf)/(4*M_PI);
489 if (std::fabs(tot_angle-1.0) > 1e-5) {
491 s->inuse[p1] = FALSE;
494 fprintf(filtered,
"%10.3f %10.3f %10.3f\n",
495 1000*r1[X_17],1000*r1[Y_17],1000*r1[Z_17]);
497 else if (limit > 0.0) {
503 for (p2 = 0; p2 < surf->np; p2++) {
504 VEC_DIFF_17(r1,surf->rr[p2],diff);
505 dist = VEC_LEN_17(diff);
506 if (dist < mindist) {
511 if (mindist < limit) {
513 s->inuse[p1] = FALSE;
516 fprintf(filtered,
"%10.3f %10.3f %10.3f\n",
517 1000*r1[X_17],1000*r1[Y_17],1000*r1[Z_17]);
523 if (omit_outside > 0)
524 printf(
"%d source space points omitted because they are outside the inner skull surface.\n",
527 printf(
"%d source space points omitted because of the %6.1f-mm distance limit.\n",
529 printf(
"Thank you for waiting.\n");
542 printf(
"Computing patch statistics...\n");
543 if (!s->neighbor_tri)
544 if (mne_source_space_add_geometry_info(s,FALSE) != OK)
547 if (s->nearest == NULL) {
548 qCritical(
"The patch information is not available.");
560 printf(
"\tareas, average normals, and mean deviations...");
561 mne_sort_nearest_by_nearest(nearest,s->np);
563 for (p = 1, q = 0; p < s->np; p++) {
564 if (nearest[p].nearest != nearest[p-1].nearest) {
566 qCritical(
"No vertices belong to the patch of vertex %d",nearest[p-1].nearest);
569 if (s->vertno[q] == nearest[p-1].nearest) {
572 pinfo[q]->vert = nearest[p-1].nearest;
573 this_patch = nearest+p-nave;
574 pinfo[q]->memb_vert = MALLOC_17(nave,
int);
575 pinfo[q]->nmemb = nave;
576 for (
k = 0;
k < nave;
k++) {
577 pinfo[q]->memb_vert[
k] = this_patch[
k].vert;
578 this_patch[
k].patch = pinfo[q];
580 MnePatchInfo::calculate_patch_area(s,pinfo[q]);
581 MnePatchInfo::calculate_normal_stats(s,pinfo[q]);
589 qCritical(
"No vertices belong to the patch of vertex %d",nearest[p-1].nearest);
592 if (s->vertno[q] == nearest[p-1].nearest) {
594 pinfo[q]->vert = nearest[p-1].nearest;
595 this_patch = nearest+p-nave;
596 pinfo[q]->memb_vert = MALLOC_17(nave,
int);
597 pinfo[q]->nmemb = nave;
598 for (
k = 0;
k < nave;
k++) {
599 pinfo[q]->memb_vert[
k] = this_patch[
k].vert;
600 this_patch[
k].patch = pinfo[q];
602 MnePatchInfo::calculate_patch_area(s,pinfo[q]);
603 MnePatchInfo::calculate_normal_stats(s,pinfo[q]);
606 printf(
" %d/%d [done]\n",q,s->nuse);
609 for (
k = 0;
k < s->npatch;
k++)
611 delete s->patches[
k];
631 for (
k = 0, s->nuse = 0; k < s->np;
k++)
640 s->vertno = REALLOC_17(s->vertno,s->nuse,
int);
641 for (
k = 0, p = 0;
k < s->np;
k++)
646 mne_add_patch_stats(s);
652 void *MneSurfaceOrVolume::filter_source_space(
void *arg)
657 int omit,omit_outside;
659 float mindist,dist,diff[3];
665 for (p1 = 0; p1 < a->s->np; p1++) {
666 if (a->s->inuse[p1]) {
667 VEC_COPY_17(r1,a->s->rr[p1]);
668 if (a->s->coord_frame == FIFFV_COORD_HEAD)
669 FiffCoordTransOld::fiff_coord_trans_inv(r1,a->mri_head_t,FIFFV_MOVE);
673 tot_angle = sum_solids(r1,a->surf)/(4*M_PI);
674 if (std::fabs(tot_angle-1.0) > 1e-5) {
676 a->s->inuse[p1] = FALSE;
679 fprintf(a->filtered,
"%10.3f %10.3f %10.3f\n",
680 1000*r1[X_17],1000*r1[Y_17],1000*r1[Z_17]);
682 else if (a->limit > 0.0) {
688 for (p2 = 0; p2 < a->surf->np; p2++) {
689 VEC_DIFF_17(r1,a->surf->rr[p2],diff);
690 dist = VEC_LEN_17(diff);
691 if (dist < mindist) {
696 if (mindist < a->limit) {
698 a->s->inuse[p1] = FALSE;
701 fprintf(a->filtered,
"%10.3f %10.3f %10.3f\n",
702 1000*r1[X_17],1000*r1[Y_17],1000*r1[Z_17]);
708 if (omit_outside > 0)
709 printf(
"%d source space points omitted because they are outside the inner skull surface.\n",
712 printf(
"%d source space points omitted because of the %6.1f-mm distance limit.\n",
720 int MneSurfaceOrVolume::filter_source_spaces(
float limit,
char *bemfile,
FiffCoordTransOld *mri_head_t,
MneSourceSpaceOld* *spaces,
int nspace, FILE *filtered,
bool use_threads)
727 int nproc = QThread::idealThreadCount();
733 if ((surf = MneSurfaceOld::read_bem_surface(bemfile,FIFFV_BEM_SURF_ID_BRAIN,FALSE,NULL)) == NULL) {
734 qCritical(
"BEM model does not have the inner skull triangulation!");
740 printf(
"Source spaces are in ");
741 if (spaces[0]->coord_frame == FIFFV_COORD_HEAD)
742 printf(
"head coordinates.\n");
743 else if (spaces[0]->coord_frame == FIFFV_COORD_MRI)
744 printf(
"MRI coordinates.\n");
746 printf(
"unknown (%d) coordinates.\n",spaces[0]->coord_frame);
747 printf(
"Checking that the sources are inside the inner skull ");
749 printf(
"and at least %6.1f mm away",1000*limit);
750 printf(
" (will take a few...)\n");
751 if (nproc < 2 || nspace == 1 || !use_threads) {
755 for (
k = 0;
k < nspace;
k++) {
758 a->mri_head_t = mri_head_t;
761 a->filtered = filtered;
762 filter_source_space(a);
765 rearrange_source_space(spaces[
k]);
772 QList<FilterThreadArg*> args;
774 for (
k = 0;
k < nspace;
k++) {
777 a->mri_head_t = mri_head_t;
780 a->filtered = filtered;
786 QtConcurrent::blockingMap(args, filter_source_space);
788 for (
k = 0;
k < nspace;
k++) {
789 rearrange_source_space(spaces[
k]);
796 printf(
"Thank you for waiting.\n\n");
808 float min[3],max[3],cm[3];
810 float *node,maxdist,dist,diff[3];
819 cm[X_17] = cm[Y_17] = cm[Z_17] = 0.0;
821 for (c = 0; c < 3; c++)
822 min[c] = max[c] = node[c];
824 for (
k = 0;
k < surf->np;
k++) {
826 for (c = 0; c < 3; c++) {
828 if (node[c] < min[c])
830 if (node[c] > max[c])
834 for (c = 0; c < 3; c++)
835 cm[c] = cm[c]/surf->np;
840 for (
k = 0;
k < surf->np;
k++) {
841 VEC_DIFF_17(cm,surf->rr[
k],diff);
842 dist = VEC_LEN_17(diff);
846 printf(
"Surface CM = (%6.1f %6.1f %6.1f) mm\n",
847 1000*cm[X_17], 1000*cm[Y_17], 1000*cm[Z_17]);
848 printf(
"Surface fits inside a sphere with radius %6.1f mm\n",1000*maxdist);
849 printf(
"Surface extent:\n"
850 "\tx = %6.1f ... %6.1f mm\n"
851 "\ty = %6.1f ... %6.1f mm\n"
852 "\tz = %6.1f ... %6.1f mm\n",
853 1000*min[X_17],1000*max[X_17],
854 1000*min[Y_17],1000*max[Y_17],
855 1000*min[Z_17],1000*max[Z_17]);
856 for (c = 0; c < 3; c++) {
858 maxn[c] = floor(std::fabs(max[c])/grid)+1;
860 maxn[c] = -floor(std::fabs(max[c])/grid)-1;
862 minn[c] = floor(std::fabs(min[c])/grid)+1;
864 minn[c] = -floor(std::fabs(min[c])/grid)-1;
866 printf(
"Grid extent:\n"
867 "\tx = %6.1f ... %6.1f mm\n"
868 "\ty = %6.1f ... %6.1f mm\n"
869 "\tz = %6.1f ... %6.1f mm\n",
870 1000*(minn[X_17]*grid),1000*(maxn[X_17]*grid),
871 1000*(minn[Y_17]*grid),1000*(maxn[Y_17]*grid),
872 1000*(minn[Z_17]*grid),1000*(maxn[Z_17]*grid));
877 for (c = 0; c < 3; c++)
878 np = np*(maxn[c]-minn[c]+1);
879 nplane = (maxn[X_17]-minn[X_17]+1)*(maxn[Y_17]-minn[Y_17]+1);
880 nrow = (maxn[X_17]-minn[X_17]+1);
881 sp = MneSurfaceOrVolume::mne_new_source_space(np);
882 sp->type = MNE_SOURCE_SPACE_VOLUME;
883 sp->nneighbor_vert = MALLOC_17(sp->np,
int);
884 sp->neighbor_vert = MALLOC_17(sp->np,
int *);
885 for (
k = 0;
k < sp->np;
k++) {
888 sp->nn[
k][X_17] = sp->nn[
k][Y_17] = 0.0;
889 sp->nn[
k][Z_17] = 1.0;
890 sp->neighbor_vert[
k] = neigh = MALLOC_17(NNEIGHBORS,
int);
891 sp->nneighbor_vert[
k] = nneigh = NNEIGHBORS;
892 for (c = 0; c < nneigh; c++)
896 for (
k = 0, z = minn[Z_17]; z <= maxn[Z_17]; z++) {
897 for (y = minn[Y_17]; y <= maxn[Y_17]; y++) {
898 for (x = minn[X_17]; x <= maxn[X_17]; x++,
k++) {
899 sp->rr[
k][X_17] = x*grid;
900 sp->rr[
k][Y_17] = y*grid;
901 sp->rr[
k][Z_17] = z*grid;
906 neigh = sp->neighbor_vert[
k];
908 neigh[0] =
k - nplane;
918 neigh[5] =
k + nplane;
923 if (z > minn[Z_17]) {
924 if (x < maxn[X_17]) {
925 neigh[6] =
k + 1 - nplane;
927 neigh[7] =
k + 1 + nrow - nplane;
930 neigh[8] =
k + nrow - nplane;
931 if (x > minn[X_17]) {
933 neigh[9] =
k - 1 + nrow - nplane;
934 neigh[10] =
k - 1 - nplane;
936 neigh[11] =
k - 1 - nrow - nplane;
938 if (y > minn[Y_17]) {
939 neigh[12] =
k - nrow - nplane;
941 neigh[13] =
k + 1 - nrow - nplane;
947 if (x < maxn[X_17] && y < maxn[Y_17])
948 neigh[14] =
k + 1 + nrow;
949 if (x > minn[X_17]) {
951 neigh[15] =
k - 1 + nrow;
953 neigh[16] =
k - 1 - nrow;
955 if (y > minn[Y_17] && x < maxn[X_17])
956 neigh[17] =
k + 1 - nrow - nplane;
960 if (z < maxn[Z_17]) {
961 if (x < maxn[X_17]) {
962 neigh[18] =
k + 1 + nplane;
964 neigh[19] =
k + 1 + nrow + nplane;
967 neigh[20] =
k + nrow + nplane;
968 if (x > minn[X_17]) {
970 neigh[21] =
k - 1 + nrow + nplane;
971 neigh[22] =
k - 1 + nplane;
973 neigh[23] =
k - 1 - nrow + nplane;
975 if (y > minn[Y_17]) {
976 neigh[24] =
k - nrow + nplane;
978 neigh[25] =
k + 1 - nrow + nplane;
984 printf(
"%d sources before omitting any.\n",sp->nuse);
988 for (
k = 0;
k < sp->np;
k++) {
989 VEC_DIFF_17(cm,sp->rr[
k],diff);
990 dist = VEC_LEN_17(diff);
991 if (dist < exclude || dist > maxdist) {
992 sp->inuse[
k] = FALSE;
996 printf(
"%d sources after omitting infeasible sources.\n",sp->nuse);
997 if (mne_filter_source_spaces(surf,mindist,NULL,&sp,1,NULL) != OK)
999 printf(
"%d sources remaining after excluding the sources outside the surface and less than %6.1f mm inside.\n",sp->nuse,1000*mindist);
1003 printf(
"Adjusting the neighborhood info...");
1004 for (
k = 0;
k < sp->np;
k++) {
1005 neigh = sp->neighbor_vert[
k];
1006 nneigh = sp->nneighbor_vert[
k];
1008 for (c = 0; c < nneigh; c++)
1009 if (!sp->inuse[neigh[c]])
1013 for (c = 0; c < nneigh; c++)
1022 float r0[3],voxel_size[3],x_ras[3],y_ras[3],z_ras[3];
1023 int width,height,depth;
1025 r0[X_17] = minn[X_17]*grid;
1026 r0[Y_17] = minn[Y_17]*grid;
1027 r0[Z_17] = minn[Z_17]*grid;
1029 voxel_size[0] = grid;
1030 voxel_size[1] = grid;
1031 voxel_size[2] = grid;
1033 width = (maxn[X_17]-minn[X_17]+1);
1034 height = (maxn[Y_17]-minn[Y_17]+1);
1035 depth = (maxn[Z_17]-minn[Z_17]+1);
1037 for (
k = 0;
k < 3;
k++)
1038 x_ras[
k] = y_ras[
k] = z_ras[
k] = 0.0;
1044 if ((sp->voxel_surf_RAS_t = make_voxel_ras_trans(r0,x_ras,y_ras,z_ras,voxel_size)) == NULL)
1047 sp->vol_dims[0] = width;
1048 sp->vol_dims[1] = height;
1049 sp->vol_dims[2] = depth;
1050 VEC_COPY_17(sp->voxel_size,voxel_size);
1072 res->rr = ALLOC_CMATRIX_17(np,3);
1073 res->nn = ALLOC_CMATRIX_17(np,3);
1074 res->inuse = ALLOC_INT_17(np);
1075 res->vertno = ALLOC_INT_17(np);
1087 res->tot_area = 0.0;
1090 res->use_tris = NULL;
1091 res->use_itris = NULL;
1093 res->neighbor_tri = NULL;
1094 res->nneighbor_tri = NULL;
1098 res->neighbor_vert = NULL;
1099 res->nneighbor_vert = NULL;
1100 res->vert_dist = NULL;
1102 res->coord_frame = FIFFV_COORD_MRI;
1103 res->id = FIFFV_MNE_SURF_UNKNOWN;
1104 res->subject.clear();
1105 res->type = FIFFV_MNE_SPACE_SURFACE;
1107 res->nearest = NULL;
1108 res->patches = NULL;
1112 res->dist_limit = -1.0;
1114 res->voxel_surf_RAS_t = NULL;
1115 res->vol_dims[0] = res->vol_dims[1] = res->vol_dims[2] = 0;
1117 res->MRI_volume.clear();
1118 res->MRI_surf_RAS_RAS_t = NULL;
1119 res->MRI_voxel_surf_RAS_t = NULL;
1120 res->MRI_vol_dims[0] = res->MRI_vol_dims[1] = res->MRI_vol_dims[2] = 0;
1121 res->interpolator = NULL;
1123 res->vol_geom = NULL;
1124 res->mgh_tags = NULL;
1125 res->user_data = NULL;
1126 res->user_data_free = NULL;
1128 res->cm[X_17] = res->cm[Y_17] = res->cm[Z_17] = 0.0;
1135 MneSurfaceOld* MneSurfaceOrVolume::read_bem_surface(
const QString &name,
int which,
int add_geometry,
float *sigmap)
1137 return read_bem_surface(name,which,add_geometry,sigmap,
true);
1142 MneSurfaceOld* MneSurfaceOrVolume::mne_read_bem_surface2(
char *name,
int which,
int add_geometry,
float *sigmap)
1144 return read_bem_surface(name,which,add_geometry,sigmap,FALSE);
1149 MneSurfaceOld* MneSurfaceOrVolume::read_bem_surface(
const QString &name,
int which,
int add_geometry,
float *sigmap,
bool check_too_many_neighbors)
1157 QList<FiffDirNode::SPtr> surfs;
1158 QList<FiffDirNode::SPtr> bems;
1163 float **nodes = NULL;
1164 float **node_normals = NULL;
1165 int **triangles = NULL;
1169 int coord_frame = FIFFV_COORD_MRI;
1172 MatrixXi tmp_triangles;
1179 bems = stream->dirtree()->dir_tree_find(
FIFFB_BEM);
1180 if (bems.size() > 0) {
1183 coord_frame = *t_pTag->toInt();
1187 if (surfs.size() == 0) {
1188 printf (
"No BEM surfaces found in %s",name.toUtf8().constData());
1192 for (
k = 0;
k < surfs.size(); ++
k) {
1198 id = *t_pTag->toInt();
1204 printf(
"Desired surface not found in %s",name.toUtf8().constData());
1215 nnode = *t_pTag->toInt();
1219 ntri = *t_pTag->toInt();
1223 tmp_nodes = t_pTag->toFloatMatrix().transpose();
1224 nodes = ALLOC_CMATRIX_17(tmp_nodes.rows(),tmp_nodes.cols());
1225 fromFloatEigenMatrix_17(tmp_nodes, nodes);
1228 MatrixXf tmp_node_normals = t_pTag->toFloatMatrix().transpose();
1229 node_normals = ALLOC_CMATRIX_17(tmp_node_normals.rows(),tmp_node_normals.cols());
1230 fromFloatEigenMatrix_17(tmp_node_normals, node_normals);
1235 tmp_triangles = t_pTag->toIntMatrix().transpose();
1236 triangles = (
int **)malloc(tmp_triangles.rows() *
sizeof(
int *));
1237 for (
int i = 0; i < tmp_triangles.rows(); ++i)
1238 triangles[i] = (
int *)malloc(tmp_triangles.cols() *
sizeof(
int));
1239 fromIntEigenMatrix_17(tmp_triangles, triangles);
1242 coord_frame = *t_pTag->toInt();
1245 coord_frame = *t_pTag->toInt();
1248 sigma = *t_pTag->toFloat();
1254 for (
k = 0;
k < ntri;
k++) {
1259 s->itris = triangles;
1261 s->coord_frame = coord_frame;
1262 s->rr = nodes; nodes = NULL;
1263 s->nn = node_normals; node_normals = NULL;
1270 if (check_too_many_neighbors) {
1279 else if (s->nn == NULL) {
1287 s->inuse = MALLOC_17(s->np,
int);
1288 s->vertno = MALLOC_17(s->np,
int);
1289 for (
k = 0;
k < s->np;
k++) {
1299 FREE_CMATRIX_17(nodes);
1300 FREE_CMATRIX_17(node_normals);
1301 FREE_ICMATRIX_17(triangles);
1309 void MneSurfaceOrVolume::mne_triangle_coords(
float *r,
MneSurfaceOld* s,
int tri,
float *x,
float *y,
float *z)
1315 double a,b,c,v1,v2,det;
1318 this_tri = s->tris+tri;
1320 VEC_DIFF_17(this_tri->r1,r,rr);
1321 *z = VEC_DOT_17(rr,this_tri->nn);
1323 a = VEC_DOT_17(this_tri->r12,this_tri->r12);
1324 b = VEC_DOT_17(this_tri->r13,this_tri->r13);
1325 c = VEC_DOT_17(this_tri->r12,this_tri->r13);
1327 v1 = VEC_DOT_17(rr,this_tri->r12);
1328 v2 = VEC_DOT_17(rr,this_tri->r13);
1332 *x = (b*v1 - c*v2)/det;
1333 *y = (a*v2 - c*v1)/det;
1340 int MneSurfaceOrVolume::nearest_triangle_point(
float *r,
MneSurfaceOld* s,
void *user,
int tri,
float *x,
float *y,
float *z)
1346 double p,q,p0,q0,t0;
1348 double a,b,c,v1,v2,det;
1349 double best,dist,dist0;
1353 this_tri = s->tris+tri;
1354 VEC_DIFF_17(this_tri->r1,r,rr);
1355 dist = VEC_DOT_17(rr,this_tri->nn);
1365 a = VEC_DOT_17(this_tri->r12,this_tri->r12);
1366 b = VEC_DOT_17(this_tri->r13,this_tri->r13);
1367 c = VEC_DOT_17(this_tri->r12,this_tri->r13);
1370 v1 = VEC_DOT_17(rr,this_tri->r12);
1371 v2 = VEC_DOT_17(rr,this_tri->r13);
1375 p = (b*v1 - c*v2)/det;
1376 q = (a*v2 - c*v1)/det;
1380 if (p >= 0.0 && p <= 1.0 &&
1381 q >= 0.0 && q <= 1.0 &&
1396 p0 = p + 0.5*(q * c)/a;
1402 dist0 = sqrt((p-p0)*(p-p0)*a +
1413 t0 = 0.5*((2.0*a-c)*(1.0-p) + (2.0*b-c)*q)/(a+b-c);
1420 dist0 = sqrt((p-p0)*(p-p0)*a +
1434 q0 = q + 0.5*(p * c)/b;
1439 dist0 = sqrt((p-p0)*(p-p0)*a +
1454 void MneSurfaceOrVolume::project_to_triangle(
MneSurfaceOld* s,
int tri,
float p,
float q,
float *r)
1459 this_tri = s->tris+tri;
1461 for (
k = 0;
k < 3;
k++)
1462 r[
k] = this_tri->r1[
k] + p*this_tri->r12[
k] + q*this_tri->r13[
k];
1469 int MneSurfaceOrVolume::mne_nearest_triangle_point(
float *r,
MneSurfaceOld* s,
int tri,
float *x,
float *y,
float *z)
1474 return nearest_triangle_point(r,s,NULL,tri,x,y,z);
1479 int MneSurfaceOrVolume::mne_project_to_surface(
MneSurfaceOld* s,
void *proj_data,
float *r,
int project_it,
float *distp)
1492 for (best = -1,
k = 0;
k < s->ntri;
k++) {
1493 if (nearest_triangle_point(r,s,proj_data,
k,&p,&q,&dist)) {
1494 if (best < 0 || std::fabs(dist) < std::fabs(dist0)) {
1502 if (best >= 0 && project_it)
1503 project_to_triangle(s,best,p0,q0,r);
1511 void MneSurfaceOrVolume::mne_project_to_triangle(
MneSurfaceOld* s,
1521 mne_nearest_triangle_point(r,s,best,&p,&q,&dist);
1522 project_to_triangle(s,best,p,q,proj);
1529 void MneSurfaceOrVolume::mne_find_closest_on_surface_approx(
MneSurfaceOld* s,
float **r,
int np,
int *nearest,
float *dist,
int nstep)
1539 printf(
"%s for %d points %d steps...",nearest[0] < 0 ?
"Closest" :
"Approx closest",np,nstep);
1541 for (
k = 0;
k < np;
k++) {
1543 decide_search_restriction(s,p,nearest[
k],nstep,r[
k]);
1544 nearest[
k] = mne_project_to_surface(s,p,r[
k],0,dist ? dist+
k : &mydist);
1545 if (nearest[
k] < 0) {
1546 decide_search_restriction(s,p,-1,nstep,r[
k]);
1547 nearest[
k] = mne_project_to_surface(s,p,r[
k],0,dist ? dist+
k : &mydist);
1559 void MneSurfaceOrVolume::decide_search_restriction(
MneSurfaceOld* s,
1570 float diff[3],dist,mindist;
1573 for (
k = 0;
k < s->ntri;
k++)
1576 if (approx_best < 0) {
1582 for (
k = 0;
k < s->np;
k++) {
1583 VEC_DIFF_17(r,s->rr[
k],diff);
1584 dist = VEC_LEN_17(diff);
1585 if (dist < mindist && s->nneighbor_tri[
k] > 0) {
1597 this_tri = s->tris+approx_best;
1598 VEC_DIFF_17(r,this_tri->r1,diff);
1599 mindist = VEC_LEN_17(diff);
1600 minvert = this_tri->vert[0];
1602 VEC_DIFF_17(r,this_tri->r2,diff);
1603 dist = VEC_LEN_17(diff);
1604 if (dist < mindist) {
1606 minvert = this_tri->vert[1];
1608 VEC_DIFF_17(r,this_tri->r3,diff);
1609 dist = VEC_LEN_17(diff);
1610 if (dist < mindist) {
1612 minvert = this_tri->vert[2];
1618 activate_neighbors(s,minvert,p->act,nstep);
1620 for (
k = 0, p->nactive = 0; k < s->ntri;
k++)
1628 void MneSurfaceOrVolume::activate_neighbors(
MneSurfaceOld* s,
int start,
int *act,
int nstep)
1638 for (
k = 0;
k < s->nneighbor_tri[start];
k++)
1639 act[s->neighbor_tri[start][
k]] = TRUE;
1640 for (
k = 0;
k < s->nneighbor_vert[start];
k++)
1641 activate_neighbors(s,s->neighbor_vert[start][
k],act,nstep-1);
1648 int MneSurfaceOrVolume::mne_read_source_spaces(
const QString &name,
MneSourceSpaceOld* **spacesp,
int *nspacep)
1659 QList<FiffDirNode::SPtr> sources;
1664 int *nearest = NULL;
1665 float *nearest_dist = NULL;
1666 int *nneighbors = NULL;
1667 int *neighbors = NULL;
1668 int *vol_dims = NULL;
1673 sources = stream->dirtree()->dir_tree_find(FIFFB_MNE_SOURCE_SPACE);
1674 if (sources.size() == 0) {
1675 printf(
"No source spaces available here");
1678 for (j = 0; j < sources.size(); j++) {
1679 new_space = MneSurfaceOrVolume::mne_new_source_space(0);
1687 new_space->np = *t_pTag->toInt();
1688 if (new_space->np == 0) {
1689 printf(
"No points in this source space");
1695 MatrixXf tmp_rr = t_pTag->toFloatMatrix().transpose();
1696 new_space->rr = ALLOC_CMATRIX_17(tmp_rr.rows(),tmp_rr.cols());
1697 fromFloatEigenMatrix_17(tmp_rr,new_space->rr);
1701 MatrixXf tmp_nn = t_pTag->toFloatMatrix().transpose();
1702 new_space->nn = ALLOC_CMATRIX_17(tmp_nn.rows(),tmp_nn.cols());
1703 fromFloatEigenMatrix_17(tmp_nn,new_space->nn);
1705 new_space->coord_frame = FIFFV_COORD_MRI;
1708 new_space->coord_frame = *t_pTag->toInt();
1711 new_space->id = *t_pTag->toInt();
1714 new_space->subject = (
char *)t_pTag->data();
1717 new_space->type = *t_pTag->toInt();
1721 ntri = *t_pTag->toInt();
1724 ntri = *t_pTag->toInt();
1735 MatrixXi tmp_itris = t_pTag->toIntMatrix().transpose();
1736 itris = (
int **)malloc(tmp_itris.rows() *
sizeof(
int *));
1737 for (
int i = 0; i < tmp_itris.rows(); ++i)
1738 itris[i] = (
int *)malloc(tmp_itris.cols() *
sizeof(
int));
1739 fromIntEigenMatrix_17(tmp_itris, itris);
1741 for (p = 0; p < ntri; p++) {
1746 new_space->itris = itris; itris = NULL;
1747 new_space->ntri = ntri;
1750 if (new_space->type == FIFFV_MNE_SPACE_VOLUME) {
1754 new_space->nuse = new_space->np;
1755 new_space->inuse = MALLOC_17(new_space->nuse,
int);
1756 new_space->vertno = MALLOC_17(new_space->nuse,
int);
1757 for (
k = 0;
k < new_space->nuse;
k++) {
1758 new_space->inuse[
k] = TRUE;
1759 new_space->vertno[
k] =
k;
1767 new_space->nuse = 0;
1768 new_space->inuse = MALLOC_17(new_space->np,
int);
1769 new_space->vertno = NULL;
1770 for (
k = 0;
k < new_space->np;
k++)
1771 new_space->inuse[
k] = FALSE;
1775 new_space->nuse = *t_pTag->toInt();
1780 qDebug() <<
"ToDo: Check whether new_space->inuse contains the right stuff!!! - use VectorXi instead";
1782 new_space->inuse = MALLOC_17(new_space->np,
int);
1783 if (new_space->nuse > 0) {
1784 new_space->vertno = MALLOC_17(new_space->nuse,
int);
1785 for (
k = 0, p = 0;
k < new_space->np;
k++) {
1786 new_space->inuse[
k] = t_pTag->toInt()[
k];
1787 if (new_space->inuse[
k])
1788 new_space->vertno[p++] =
k;
1792 FREE_17(new_space->vertno);
1793 new_space->vertno = NULL;
1800 ntri = *t_pTag->toInt();
1809 MatrixXi tmp_itris = t_pTag->toIntMatrix().transpose();
1810 itris = (
int **)malloc(tmp_itris.rows() *
sizeof(
int *));
1811 for (
int i = 0; i < tmp_itris.rows(); ++i)
1812 itris[i] = (
int *)malloc(tmp_itris.cols() *
sizeof(
int));
1813 fromIntEigenMatrix_17(tmp_itris, itris);
1814 for (p = 0; p < ntri; p++) {
1819 new_space->use_itris = itris; itris = NULL;
1820 new_space->nuse_tri = ntri;
1826 nearest = t_pTag->toInt();
1827 new_space->nearest = MALLOC_17(new_space->np,
MneNearest);
1828 for (
k = 0;
k < new_space->np;
k++) {
1829 new_space->nearest[
k].vert =
k;
1830 new_space->nearest[
k].nearest = nearest[
k];
1831 new_space->nearest[
k].patch = NULL;
1837 qDebug() <<
"ToDo: Check whether nearest_dist contains the right stuff!!! - use VectorXf instead";
1838 nearest_dist = t_pTag->toFloat();
1839 for (
k = 0;
k < new_space->np;
k++) {
1840 new_space->nearest[
k].dist = nearest_dist[
k];
1849 new_space->dist_limit = *t_pTag->toFloat();
1852 FiffSparseMatrix* dist = FiffSparseMatrix::fiff_get_float_sparse_matrix(t_pTag);
1853 new_space->dist = dist->mne_add_upper_triangle_rcs();
1855 if (!new_space->dist) {
1860 new_space->dist_limit = 0.0;
1866 if (new_space->type == FIFFV_MNE_SPACE_VOLUME) {
1867 int ntot,nvert,ntot_count,nneigh;
1870 nneighbors = neighbors = NULL;
1872 if (node->find_tag(stream, FIFF_MNE_SOURCE_SPACE_NEIGHBORS, t_pTag)) {
1873 qDebug() <<
"ToDo: Check whether neighbors contains the right stuff!!! - use VectorXi instead";
1874 neighbors = t_pTag->toInt();
1875 ntot = t_pTag->size()/
sizeof(fiff_int_t);
1877 if (node->find_tag(stream, FIFF_MNE_SOURCE_SPACE_NNEIGHBORS, t_pTag)) {
1878 qDebug() <<
"ToDo: Check whether nneighbors contains the right stuff!!! - use VectorXi instead";
1879 nneighbors = t_pTag->toInt();
1880 nvert = t_pTag->size()/
sizeof(fiff_int_t);
1882 if (neighbors && nneighbors) {
1883 if (nvert != new_space->np) {
1884 printf(
"Inconsistent neighborhood data in file.");
1887 for (
k = 0, ntot_count = 0;
k < nvert;
k++)
1888 ntot_count += nneighbors[
k];
1889 if (ntot_count != ntot) {
1890 printf(
"Inconsistent neighborhood data in file.");
1893 new_space->nneighbor_vert = MALLOC_17(nvert,
int);
1894 new_space->neighbor_vert = MALLOC_17(nvert,
int *);
1895 for (
k = 0, q = 0;
k < nvert;
k++) {
1896 new_space->nneighbor_vert[
k] = nneigh = nneighbors[
k];
1897 new_space->neighbor_vert[
k] = neigh = MALLOC_17(nneigh,
int);
1898 for (p = 0; p < nneigh; p++,q++)
1899 neigh[p] = neighbors[q];
1903 FREE_17(nneighbors);
1904 nneighbors = neighbors = NULL;
1908 new_space->voxel_surf_RAS_t = FiffCoordTransOld::mne_read_transform_from_node(stream, node,
FIFFV_MNE_COORD_MRI_VOXEL, FIFFV_MNE_COORD_SURFACE_RAS);
1910 qDebug() <<
"ToDo: Check whether vol_dims contains the right stuff!!! - use VectorXi instead";
1911 vol_dims = t_pTag->toInt();
1914 VEC_COPY_17(new_space->vol_dims,vol_dims);
1916 QList<FiffDirNode::SPtr> mris = node->dir_tree_find(FIFFB_MNE_PARENT_MRI_FILE);
1918 if (mris.size() == 0) {
1919 new_space->MRI_surf_RAS_RAS_t = FiffCoordTransOld::mne_read_transform_from_node(stream, node, FIFFV_MNE_COORD_SURFACE_RAS,
FIFFV_MNE_COORD_RAS);
1921 qDebug() <<
"ToDo: Check whether new_space->MRI_volume contains the right stuff!!! - use QString instead";
1922 new_space->MRI_volume = (
char *)t_pTag->data();
1925 new_space->interpolator = FiffSparseMatrix::fiff_get_float_sparse_matrix(t_pTag);
1930 new_space->MRI_volume = (
char *)t_pTag->data();
1932 new_space->MRI_surf_RAS_RAS_t = FiffCoordTransOld::mne_read_transform_from_node(stream, mris[0], FIFFV_MNE_COORD_SURFACE_RAS,
FIFFV_MNE_COORD_RAS);
1933 new_space->MRI_voxel_surf_RAS_t = FiffCoordTransOld::mne_read_transform_from_node(stream, mris[0],
FIFFV_MNE_COORD_MRI_VOXEL, FIFFV_MNE_COORD_SURFACE_RAS);
1936 new_space->interpolator = FiffSparseMatrix::fiff_get_float_sparse_matrix(t_pTag);
1938 if (mris[0]->find_tag(stream, FIFF_MRI_WIDTH, t_pTag)) {
1939 new_space->MRI_vol_dims[0] = *t_pTag->toInt();
1941 if (mris[0]->find_tag(stream, FIFF_MRI_HEIGHT, t_pTag)) {
1942 new_space->MRI_vol_dims[1] = *t_pTag->toInt();
1944 if (mris[0]->find_tag(stream, FIFF_MRI_DEPTH, t_pTag)) {
1945 new_space->MRI_vol_dims[2] = *t_pTag->toInt();
1950 mne_add_triangle_data(new_space);
1952 spaces[nspace++] = new_space;
1965 for (
k = 0;
k < nspace;
k++)
1969 FREE_17(nearest_dist);
1971 FREE_17(nneighbors);
1980 void MneSurfaceOrVolume::mne_source_space_update_inuse(
MneSourceSpaceOld* s,
int *new_inuse)
1990 FREE_17(s->inuse); s->inuse = new_inuse;
1992 for (
k = 0, nuse = 0;
k < s->np;
k++)
1998 s->vertno = REALLOC_17(s->vertno,s->nuse,
int);
1999 for (
k = 0, p = 0;
k < s->np;
k++)
2020 for (
k = 0, xave = 0.0;
k < s->np;
k++)
2021 xave += s->rr[
k][0];
2038 if (ss->coord_frame == t->
to)
2040 if (ss->coord_frame != t->
from) {
2041 printf(
"Coordinate transformation does not match with the source space coordinate system.");
2044 for (
k = 0;
k < ss->np;
k++) {
2045 FiffCoordTransOld::fiff_coord_trans(ss->rr[
k],t,FIFFV_MOVE);
2046 FiffCoordTransOld::fiff_coord_trans(ss->nn[
k],t,FIFFV_NO_MOVE);
2049 for (
k = 0;
k < ss->ntri;
k++)
2050 FiffCoordTransOld::fiff_coord_trans(ss->tris[
k].nn,t,FIFFV_NO_MOVE);
2052 ss->coord_frame = t->
to;
2067 for (
k = 0;
k < nspace;
k++) {
2069 if (s->coord_frame != coord_frame) {
2071 if (s->coord_frame == t->
from && t->
to == coord_frame) {
2072 if (mne_transform_source_space(s,t) != OK)
2075 else if (s->coord_frame == t->
to && t->
from == coord_frame) {
2076 my_t = t->fiff_invert_transform();
2077 if (mne_transform_source_space(s,my_t) != OK) {
2084 printf(
"Could not transform a source space because of transformation incompatibility.");
2089 printf(
"Could not transform a source space because of missing coordinate transformation.");
2102 for (
k = 0;
k < s->np;
k++)
2110 #define LH_LABEL_TAG "-lh.label"
2111 #define RH_LABEL_TAG "-rh.label"
2113 int MneSurfaceOrVolume::restrict_sources_to_labels(
MneSourceSpaceOld* *spaces,
int nspace,
const QStringList& labels,
int nlabel)
2121 int *lh_inuse = NULL;
2122 int *rh_inuse = NULL;
2131 for (
k = 0;
k < nspace;
k++) {
2132 if (mne_is_left_hemi_source_space(spaces[
k])) {
2135 lh_inuse = MALLOC_17(lh->np,
int);
2136 for (p = 0; p < lh->np; p++)
2142 rh_inuse = MALLOC_17(rh->np,
int);
2143 for (p = 0; p < rh->np; p++)
2150 for (
k = 0;
k < nlabel;
k++) {
2154 if (labels[
k].contains(LH_LABEL_TAG)){
2158 else if (labels[
k].contains(RH_LABEL_TAG)){
2163 printf(
"\tWarning: cannot assign label file %s to a hemisphere.\n",labels[
k].toUtf8().constData());
2167 if (mne_read_label(labels[
k],NULL,&sel,&nsel) == FAIL)
2169 for (p = 0; p < nsel; p++) {
2170 if (sel[p] >= 0 && sel[p] < sp->np)
2171 inuse[sel[p]] = sp->inuse[sel[p]];
2173 printf(
"vertex number out of range in %s (%d vs %d)\n",
2174 labels[
k].toUtf8().constData(),sel[p],sp->np);
2176 FREE_17(sel); sel = NULL;
2177 printf(
"Processed label file %s\n",labels[
k].toUtf8().constData());
2180 mne_source_space_update_inuse(lh,lh_inuse);
2181 mne_source_space_update_inuse(rh,rh_inuse);
2194 int MneSurfaceOrVolume::mne_find_sources_in_label(
char *label,
MneSourceSpaceOld* s,
int off,
int **selp,
int *nselp)
2205 int k,p,pp,nlabel,q;
2211 if ((in = fopen(label,
"r")) == NULL) {
2212 qCritical(
"%s", label);
2217 qCritical(
"Label file does not start correctly.");
2220 for (c = fgetc(in); c !=
'\n'; c = fgetc(in))
2222 if (fscanf(in,
"%d",&nlabel) != 1) {
2223 qCritical(
"Could not read the number of labelled points.");
2227 printf(
"\t%d points in label %s\n",nlabel,label);
2229 for (
k = 0;
k < nlabel;
k++) {
2230 if (fscanf(in,
"%d %g %g %g %g",&p,
2231 &fdum, &fdum, &fdum, &fdum) != 5) {
2232 qCritical(
"Could not read label point # %d",
k+1);
2235 if (p < 0 || p >= s->np) {
2236 qCritical(
"Source index out of range %d (range 0..%d)\n",p,s->np-1);
2240 for (pp = 0, q = 0; pp < p; pp++) {
2244 sel = REALLOC_17(sel,nsel+1,
int);
2245 sel[nsel++] = q + off;
2266 int MneSurfaceOrVolume::mne_read_label(
const QString& label,
char **commentp,
int **selp,
int *nselp)
2279 char *comment = NULL;
2284 if ((in = fopen(label.toUtf8().constData(),
"r")) == NULL) {
2285 qCritical() << label;
2288 for (
k = 0;
k < 2;
k++) {
2292 qCritical(
"Label file does not start correctly.");
2295 for (c = fgetc(in); c ==
' ' && c !=
'\n'; c = fgetc(in))
2299 for (c = fgetc(in), p = 0; c !=
'\n'; c = fgetc(in), p++)
2303 for (c = fgetc(in); c !=
'\n'; c = fgetc(in))
2314 *commentp = comment = MALLOC_17(p+1,
char);
2316 if (fscanf(in,
"%d",&nlabel) != 1) {
2317 qCritical(
"Could not read the number of labelled points.");
2320 for (
k = 0;
k < nlabel;
k++) {
2321 if (fscanf(in,
"%d %g %g %g %g",&p,
2322 &fdum, &fdum, &fdum, &fdum) != 5) {
2323 qCritical(
"Could not read label point # %d",
k+1);
2326 sel = REALLOC_17(sel,nsel+1,
int);
2347 int MneSurfaceOrVolume::mne_write_label(
char *label,
char *comment,
int *sel,
int nsel,
float **rr)
2359 if ((out = fopen(label,
"w")) == NULL) {
2360 qCritical(
"%s", label);
2363 if (comment == NULL)
2364 fprintf(out,
"# Label file created by the MNE software\n");
2366 fprintf(out,
"# %s\n",comment);
2368 fprintf(out,
"%d\n",nsel);
2370 for (
k = 0;
k < nsel;
k++)
2371 fprintf(out,
"%d %.2f %.2f %.2f %g\n",sel[
k],
2374 1000*rr[sel[
k]][2],fdum);
2376 for (
k = 0;
k < nsel;
k++)
2377 fprintf(out,
"%d %.2f %.2f %.2f %g\n",sel[
k],fdum,fdum,fdum,fdum);
2399 if (!s || s->type != MNE_SOURCE_SPACE_SURFACE)
2402 FREE_17(s->tris); s->tris = NULL;
2403 FREE_17(s->use_tris); s->use_tris = NULL;
2407 if (s->itris && s->ntri > 0) {
2410 for (
k = 0, tri = s->tris; k < s->ntri;
k++, tri++) {
2411 tri->vert = s->itris[
k];
2412 tri->r1 = s->rr[tri->vert[0]];
2413 tri->r2 = s->rr[tri->vert[1]];
2414 tri->r3 = s->rr[tri->vert[2]];
2415 MneTriangle::add_triangle_data(tri);
2416 s->tot_area += tri->area;
2418 #ifdef TRIANGLE_SIZE_WARNING
2419 for (
k = 0, tri = s->tris; k < s->ntri;
k++, tri++)
2420 if (tri->area < 1e-5*s->tot_area/s->ntri)
2421 printf(
"Warning: Triangle area is only %g um^2 (%.5f %% of expected average)\n",
2422 1e12*tri->area,100*s->ntri*tri->area/s->tot_area);
2426 printf(
"\ttotal area = %-.1f cm^2\n",1e4*s->tot_area);
2431 if (s->use_itris && s->nuse_tri > 0) {
2433 for (
k = 0, tri = s->use_tris; k < s->nuse_tri;
k++, tri++) {
2434 tri->vert = s->use_itris[
k];
2435 tri->r1 = s->rr[tri->vert[0]];
2436 tri->r2 = s->rr[tri->vert[1]];
2437 tri->r3 = s->rr[tri->vert[2]];
2438 MneTriangle::add_triangle_data(tri);
2446 void MneSurfaceOrVolume::mne_compute_cm(
float **rr,
int np,
float *cm)
2452 cm[0] = cm[1] = cm[2] = 0.0;
2453 for (q = 0; q < np; q++) {
2468 void MneSurfaceOrVolume::mne_compute_surface_cm(
MneSurfaceOld *s)
2476 mne_compute_cm(s->rr,s->np,s->cm);
2485 float *dist,diff[3];
2488 if (!s->neighbor_vert || !s->nneighbor_vert)
2492 for (
k = 0;
k < s->np;
k++)
2493 FREE_17(s->vert_dist[
k]);
2494 FREE_17(s->vert_dist);
2496 s->vert_dist = MALLOC_17(s->np,
float *);
2497 printf(
"\tDistances between neighboring vertices...");
2498 for (
k = 0, ndist = 0;
k < s->np;
k++) {
2499 s->vert_dist[
k] = dist = MALLOC_17(s->nneighbor_vert[
k],
float);
2500 neigh = s->neighbor_vert[
k];
2501 nneigh = s->nneighbor_vert[
k];
2502 for (p = 0; p < nneigh; p++) {
2503 if (neigh[p] >= 0) {
2504 VEC_DIFF_17(s->rr[
k],s->rr[neigh[p]],diff);
2505 dist[p] = VEC_LEN_17(diff);
2512 printf(
"[%d distances done]\n",ndist);
2525 if (!s || s->type != MNE_SOURCE_SPACE_SURFACE)
2530 FREE_CMATRIX_17(s->nn);
2531 s->nn = ALLOC_CMATRIX_17(s->np,3);
2533 for (
k = 0;
k < s->np;
k++) {
2534 s->nn[
k][X_17] = s->nn[
k][Y_17] = s->nn[
k][Z_17] = 0.0;
2539 MneSurfaceOrVolume::mne_add_triangle_data(s);
2540 for (p = 0, tri = s->tris; p < s->ntri; p++, tri++) {
2546 for (
k = 0;
k < 3;
k++)
2547 for (c = 0; c < 3; c++)
2548 s->nn[ii[
k]][c] += w*tri->nn[c];
2550 for (
k = 0;
k < s->np;
k++) {
2551 size = VEC_LEN_17(s->nn[
k]);
2553 for (c = 0; c < 3; c++)
2554 s->nn[
k][c] = s->nn[
k][c]/size;
2562 int MneSurfaceOrVolume::add_geometry_info(
MneSourceSpaceOld* s,
int do_normals,
int *border,
int check_too_many_neighbors)
2570 int *neighbors,nneighbors;
2573 int nfix_distinct,nfix_no_neighbors,nfix_defect;
2579 if (s->type == MNE_SOURCE_SPACE_VOLUME) {
2580 calculate_vertex_distances(s);
2583 if (s->type != MNE_SOURCE_SPACE_SURFACE)
2589 FREE_CMATRIX_17(s->nn);
2590 s->nn = ALLOC_CMATRIX_17(s->np,3);
2592 if (s->neighbor_tri) {
2593 for (
k = 0;
k < s->np;
k++)
2594 FREE_17(s->neighbor_tri[
k]);
2595 FREE_17(s->neighbor_tri);
2597 FREE_17(s->nneighbor_tri);
2598 s->neighbor_tri = MALLOC_17(s->np,
int *);
2599 s->nneighbor_tri = MALLOC_17(s->np,
int);
2601 for (
k = 0;
k < s->np;
k++) {
2602 s->neighbor_tri[
k] = NULL;
2603 s->nneighbor_tri[
k] = 0;
2605 s->nn[
k][X_17] = s->nn[
k][Y_17] = s->nn[
k][Z_17] = 0.0;
2610 mne_add_triangle_data(s);
2611 for (p = 0, tri = s->tris; p < s->ntri; p++, tri++)
2613 printf(
"\tWarning : zero size triangle # %d\n",p);
2614 printf(
"\tTriangle ");
2616 printf(
"and vertex ");
2617 printf(
"normals and neighboring triangles...");
2618 for (p = 0, tri = s->tris; p < s->ntri; p++, tri++) {
2621 for (
k = 0;
k < 3;
k++) {
2626 for (c = 0; c < 3; c++)
2627 s->nn[ii[
k]][c] += w*tri->nn[c];
2631 s->neighbor_tri[ii[
k]] = REALLOC_17(s->neighbor_tri[ii[
k]],
2632 s->nneighbor_tri[ii[
k]]+1,
int);
2633 s->neighbor_tri[ii[
k]][s->nneighbor_tri[ii[
k]]] = p;
2634 s->nneighbor_tri[ii[
k]]++;
2637 nfix_no_neighbors = 0;
2639 for (
k = 0;
k < s->np;
k++) {
2640 if (s->nneighbor_tri[
k] <= 0) {
2641 if (!border || !border[
k]) {
2643 err_printf_set_error(
"Vertex %d does not have any neighboring triangles!",
k);
2646 #ifdef REPORT_WARNINGS
2647 printf(
"Warning: Vertex %d does not have any neighboring triangles!\n",
k);
2650 nfix_no_neighbors++;
2653 else if (s->nneighbor_tri[
k] < 3 && !border) {
2654 #ifdef REPORT_WARNINGS
2655 printf(
"\n\tTopological defect: Vertex %d has only %d neighboring triangle%s Vertex omitted.\n\t",
2656 k,s->nneighbor_tri[
k],s->nneighbor_tri[
k] > 1 ?
"s." :
".");
2659 s->nneighbor_tri[
k] = 0;
2660 FREE_17(s->neighbor_tri[
k]);
2661 s->neighbor_tri[
k] = NULL;
2667 for (
k = 0;
k < s->np;
k++)
2668 if (s->nneighbor_tri[
k] > 0) {
2669 size = VEC_LEN_17(s->nn[
k]);
2671 for (c = 0; c < 3; c++)
2672 s->nn[
k][c] = s->nn[
k][c]/size;
2678 printf(
"\tVertex neighbors...");
2679 if (s->neighbor_vert) {
2680 for (
k = 0;
k < s->np;
k++)
2681 FREE_17(s->neighbor_vert[
k]);
2682 FREE_17(s->neighbor_vert);
2684 FREE_17(s->nneighbor_vert);
2685 s->neighbor_vert = MALLOC_17(s->np,
int *);
2686 s->nneighbor_vert = MALLOC_17(s->np,
int);
2691 for (
k = 0;
k < s->np;
k++) {
2692 if (s->nneighbor_tri[
k] > 0) {
2694 s->neighbor_vert[
k] = MALLOC_17(s->nneighbor_tri[
k]+1,
int);
2695 s->nneighbor_vert[
k] = s->nneighbor_tri[
k]+1;
2698 s->neighbor_vert[
k] = MALLOC_17(s->nneighbor_tri[
k],
int);
2699 s->nneighbor_vert[
k] = s->nneighbor_tri[
k];
2703 s->neighbor_vert[
k] = NULL;
2704 s->nneighbor_vert[
k] = 0;
2709 for (
k = 0;
k < s->np;
k++) {
2710 if (s->nneighbor_tri[
k] > 0) {
2711 s->neighbor_vert[
k] = MALLOC_17(s->nneighbor_tri[
k],
int);
2712 s->nneighbor_vert[
k] = s->nneighbor_tri[
k];
2715 s->neighbor_vert[
k] = NULL;
2716 s->nneighbor_vert[
k] = 0;
2721 for (
k = 0;
k < s->np;
k++) {
2722 neighbors = s->neighbor_vert[
k];
2724 for (p = 0; p < s->nneighbor_tri[
k]; p++) {
2728 for (c = 0; c < 3; c++) {
2729 vert = s->tris[s->neighbor_tri[
k][p]].vert[c];
2731 for (q = 0, found = FALSE; q < nneighbors; q++) {
2732 if (neighbors[q] == vert) {
2738 if (nneighbors < s->nneighbor_vert[
k])
2739 neighbors[nneighbors++] = vert;
2740 else if (!border || !border[
k]) {
2741 if (check_too_many_neighbors) {
2742 printf(
"Too many neighbors for vertex %d.",
k);
2746 printf(
"\tWarning: Too many neighbors for vertex %d\n",
k);
2752 if (nneighbors != s->nneighbor_vert[
k]) {
2753 #ifdef REPORT_WARNINGS
2754 printf(
"\n\tIncorrect number of distinct neighbors for vertex %d (%d instead of %d) [fixed].",
2755 k,nneighbors,s->nneighbor_vert[
k]);
2758 s->nneighbor_vert[
k] = nneighbors;
2765 calculate_vertex_distances(s);
2770 if (nfix_defect > 0)
2771 printf(
"\tWarning: %d topological defects were fixed.\n",nfix_defect);
2772 if (nfix_distinct > 0)
2773 printf(
"\tWarning: %d vertices had incorrect number of distinct neighbors (fixed).\n",nfix_distinct);
2774 if (nfix_no_neighbors > 0)
2775 printf(
"\tWarning: %d vertices did not have any neighboring triangles (fixed)\n",nfix_no_neighbors);
2777 for (
k = 0;
k < s->np;
k++) {
2778 if (s->nneighbor_vert[
k] <= 0)
2779 printf(
"No neighbors for vertex %d\n",
k);
2780 if (s->nneighbor_tri[
k] <= 0)
2781 printf(
"No neighbor tris for vertex %d\n",
k);
2789 int MneSurfaceOrVolume::mne_source_space_add_geometry_info(
MneSourceSpaceOld* s,
int do_normals)
2791 return add_geometry_info(s,do_normals,NULL,TRUE);
2796 int MneSurfaceOrVolume::mne_source_space_add_geometry_info2(
MneSourceSpaceOld* s,
int do_normals)
2799 return add_geometry_info(s,do_normals,NULL,FALSE);
2804 int MneSurfaceOrVolume::mne_label_area(
char *label,
MneSourceSpaceOld* s,
float *areap)
2812 int k,q,nneigh,*neigh;
2815 qCritical(
"Source space not specified for mne_label_area");
2818 if (mne_read_label(label,NULL,&sel,&nsel))
2822 for (
k = 0;
k < nsel;
k++) {
2823 if (sel[
k] < 0 || sel[
k] >= s->np) {
2824 qCritical(
"Label vertex index out of range in mne_label_area");
2827 nneigh = s->nneighbor_tri[sel[
k]];
2828 neigh = s->neighbor_tri[sel[
k]];
2829 for (q = 0; q < nneigh; q++)
2830 area += s->tris[neigh[q]].area/3.0;
2854 float *head_fid[3],*mri_fid[3],**fid;
2858 float nasion_weight = 5.0;
2861 qCritical(
"MEG head coordinate system digitizer data not available");
2865 qCritical(
"MRI coordinate system digitizer data not available");
2869 for (j = 0; j < 2; j++) {
2870 dig = j == 0 ? head_dig : mri_dig;
2871 fid = j == 0 ? head_fid : mri_fid;
2873 for (
k = 0;
k < 3;
k++) {
2877 for (
k = 0;
k < dig->npoint;
k++) {
2879 if (p.
kind == FIFFV_POINT_CARDINAL) {
2880 if (p.
ident == FIFFV_POINT_LPA) {
2881 fid[0] = dig->points[
k].r;
2883 else if (p.
ident == FIFFV_POINT_NASION) {
2884 fid[1] = dig->points[
k].r;
2886 else if (p.
ident == FIFFV_POINT_RPA) {
2887 fid[2] = dig->points[
k].r;
2893 for (
k = 0;
k < 3;
k++) {
2895 qCritical(
"Some of the MEG fiducials were missing");
2900 qCritical(
"Some of the MRI fiducials were missing");
2906 get_head_scale(head_dig,mri_fid,head_surf,scales);
2907 printf(
"xscale = %.3f yscale = %.3f zscale = %.3f\n",scales[0],scales[1],scales[2]);
2909 for (j = 0; j < 3; j++)
2910 for (
k = 0;
k < 3;
k++)
2911 mri_fid[j][
k] = mri_fid[j][
k]*scales[
k];
2913 scale_display_surface(head_surf,scales);
2917 FREE_17(head_dig->head_mri_t_adj);
2918 head_dig->head_mri_t_adj = FIFFLIB::FiffCoordTransOld::fiff_make_transform_card(FIFFV_COORD_HEAD,FIFFV_COORD_MRI,
2919 mri_fid[0],mri_fid[1],mri_fid[2]);
2921 for (
k = 0;
k < head_dig->nfids;
k++)
2922 VEC_COPY_17(head_dig->mri_fids[
k].
r,mri_fid[
k]);
2923 FiffCoordTransOld::mne_print_coord_transform_label(stdout,QString(
"After simple alignment : ").toLatin1().data(),head_dig->head_mri_t_adj);
2926 discard_outlier_digitizer_points(head_dig,head_surf,omit_dist);
2929 if (niter > 0 && head_surf) {
2930 for (
k = 0;
k < niter;
k++) {
2931 if (iterate_alignment_once(head_dig,head_surf,nasion_weight,mri_fid[1],
k == niter-1 && niter > 1) == FAIL)
2935 printf(
"%d / %d iterations done. RMS dist = %7.1f mm\n",
k,niter,
2936 1000.0*rms_digitizer_distance(head_dig,head_surf));
2937 FiffCoordTransOld::mne_print_coord_transform_label(stdout,QString(
"After refinement :").toLatin1().data(),head_dig->head_mri_t_adj);
2954 float **dig_rr = NULL;
2955 float **head_rr = NULL;
2957 float simplex_size = 2e-2;
2958 float r0[3],Rdig,Rscalp;
2959 float LR[3],LN[3],len,norm[3],diff[3];
2961 scales[0] = scales[1] = scales[2] = 1.0;
2962 if (!dig || !head_surf || !mri_fid){
2966 dig_rr = MALLOC_17(dig->npoint,
float *);
2967 head_rr = MALLOC_17(head_surf->s->np,
float *);
2970 for (
k = 0, ndig = 0;
k < dig->npoint;
k++) {
2971 if (dig->points[
k].r[Z_17] > 0) {
2972 dig_rr[ndig++] = dig->points[
k].r;
2980 printf(
"Polhemus : (%.1f %.1f %.1f) mm R = %.1f mm\n",1000*r0[X_17],1000*r0[Y_17],1000*r0[Z_17],1000*Rdig);
2983 VEC_DIFF_17(mri_fid[0],mri_fid[2],LR);
2984 VEC_DIFF_17(mri_fid[0],mri_fid[1],LN);
2985 CROSS_PRODUCT_17(LR,LN,norm);
2986 len = VEC_LEN_17(norm);
2987 norm[0] = norm[0]/len;
2988 norm[1] = norm[1]/len;
2989 norm[2] = norm[2]/len;
2991 for (
k = 0, nhead = 0;
k < head_surf->s->np;
k++) {
2992 VEC_DIFF_17(mri_fid[0],head_surf->s->rr[
k],diff);
2993 if (VEC_DOT_17(diff,norm) > 0) {
2994 head_rr[nhead++] = head_surf->s->rr[
k];
3002 printf(
"Scalp : (%.1f %.1f %.1f) mm R = %.1f mm\n",1000*r0[X_17],1000*r0[Y_17],1000*r0[Z_17],1000*Rscalp);
3004 scales[0] = scales[1] = scales[2] = Rdig/Rscalp;
3026 d->dist_valid = FALSE;
3027 calculate_digitizer_distances(d,head,TRUE,TRUE);
3028 for (
k = 0;
k < d->npoint;
k++) {
3029 d->discard[
k] = FALSE;
3033 if (std::fabs(d->dist[
k]) > maxdist &&
3034 d->points[
k].kind != FIFFV_POINT_CARDINAL &&
3035 d->points[
k].kind != FIFFV_POINT_HPI) {
3037 d->discard[
k] = TRUE;
3040 printf(
"%d points discarded (maxdist = %6.1f mm).\n",discarded,1000*maxdist);
3048 int do_all,
int do_approx)
3053 float** rr = ALLOC_CMATRIX_17(dig->npoint,3);
3058 FiffCoordTransOld* t = dig->head_mri_t_adj ? dig->head_mri_t_adj : dig->head_mri_t;
3061 if (dig->dist_valid)
3063 FREE_CMATRIX_17(rr);
3067 dig->dist = REALLOC_17(dig->dist,dig->npoint,
float);
3068 if (!dig->closest) {
3072 dig->closest = MALLOC_17(dig->npoint,
int);
3073 for (
k = 0;
k < dig->npoint;
k++)
3074 dig->closest[
k] = -1;
3076 FREE_CMATRIX_17(dig->closest_point);
3078 dig->closest_point = ALLOC_CMATRIX_17(dig->npoint,3);
3079 closest = MALLOC_17(dig->npoint,
int);
3080 dist = MALLOC_17(dig->npoint,
float);
3082 for (
k = 0, nactive = 0;
k < dig->npoint;
k++) {
3083 if ((dig->active[
k] && !dig->discard[
k]) || do_all) {
3084 point = dig->points.at(
k);
3085 VEC_COPY_17(rr[nactive],point.
r);
3086 FiffCoordTransOld::fiff_coord_trans(rr[nactive],t,FIFFV_MOVE);
3088 closest[nactive] = dig->closest[
k];
3089 if (closest[nactive] < 0)
3093 closest[nactive] = -1;
3098 mne_find_closest_on_surface_approx(head->s,rr,nactive,closest,dist,nstep);
3103 printf(
"Inside or outside for %d points...",nactive);
3104 for (
k = 0, nactive = 0;
k < dig->npoint;
k++) {
3105 if ((dig->active[
k] && !dig->discard[
k]) || do_all) {
3106 dig->dist[
k] = dist[nactive];
3107 dig->closest[
k] = closest[nactive];
3108 mne_project_to_triangle(head->s,dig->closest[
k],rr[nactive],dig->closest_point[
k]);
3113 if (!do_approx && FALSE) {
3114 if (sum_solids(rr[nactive],head->s)/(4*M_PI) > 0.9)
3115 dig->dist[
k] = - std::fabs(dig->dist[
k]);
3117 dig->dist[
k] = std::fabs(dig->dist[
k]);
3126 FREE_CMATRIX_17(rr);
3129 dig->dist_valid = TRUE;
3146 float **rr_head = NULL;
3147 float **rr_mri = NULL;
3152 float max_diff = 40e-3;
3154 if (!dig->head_mri_t_adj) {
3155 qCritical()<<
"Not adjusting the transformation";
3161 calculate_digitizer_distances(dig,head,FALSE,TRUE);
3166 rr_head = ALLOC_CMATRIX_17(dig->npoint,3);
3167 rr_mri = ALLOC_CMATRIX_17(dig->npoint,3);
3168 w = MALLOC_17(dig->npoint,
float);
3170 for (
k = 0, nactive = 0;
k < dig->npoint;
k++) {
3171 if (dig->active[
k] && !dig->discard[
k]) {
3172 point = dig->points.at(
k);
3173 VEC_COPY_17(rr_head[nactive],point.
r);
3174 VEC_COPY_17(rr_mri[nactive],dig->closest_point[
k]);
3178 if (point.
kind == FIFFV_POINT_CARDINAL &&
3179 point.
ident == FIFFV_POINT_NASION) {
3180 w[nactive] = nasion_weight;
3182 VEC_COPY_17(rr_mri[nactive],nasion_mri);
3183 VEC_COPY_17(rr_head[nactive],nasion_mri);
3184 FiffCoordTransOld::fiff_coord_trans_inv(rr_head[nactive],
3185 dig->head_mri_t_adj ? dig->head_mri_t_adj : dig->head_mri_t,
3195 qCritical() <<
"Not enough points to do the alignment";
3198 if ((t = FiffCoordTransOld::procrustes_align(FIFFV_COORD_HEAD, FIFFV_COORD_MRI,
3199 rr_head, rr_mri, w, nactive, max_diff)) == NULL)
3202 if (dig->head_mri_t_adj)
3203 *dig->head_mri_t_adj = *t;
3208 dig->dist_valid = FALSE;
3209 calculate_digitizer_distances(dig,head,FALSE,!last_step);
3214 FREE_CMATRIX_17(rr_head);
3215 FREE_CMATRIX_17(rr_mri);
3228 calculate_digitizer_distances(dig,head,FALSE,TRUE);
3230 for (
k = 0, rms = 0.0, nactive = 0;
k < dig->npoint;
k++)
3231 if (dig->active[
k] && !dig->discard[
k]) {
3232 rms = rms + dig->dist[
k]*dig->dist[
k];
3236 rms = rms/(nactive-1);
3250 if (!surf || !scales)
3253 for (
k = 0;
k < 3;
k++) {
3254 surf->minv[
k] = scales[
k]*surf->minv[
k];
3255 surf->maxv[
k] = scales[
k]*surf->maxv[
k];
3257 for (j = 0; j < surf->s->np; j++)
3258 for (
k = 0;
k < 3;
k++)
3259 surf->s->rr[j][
k] = surf->s->rr[j][
k]*scales[
k];
3272 s->curv = MALLOC_17(s->np,
float);
3273 for (
k = 0;
k < s->np;
k++)
3280 char * MneSurfaceOrVolume::mne_compose_surf_name(
const char *subj,
3288 char *subjects_dir = getenv(
"SUBJECTS_DIR");
3290 if (!subjects_dir || strlen(subjects_dir) == 0) {
3291 qCritical()<<
"SUBJECTS_DIR not set. Cannot continue.";
3294 if (!subj || strlen(subj) == 0) {
3295 subj = getenv(
"SUBJECT");
3296 if (subj == NULL || strlen(subj) == 0) {
3297 qCritical()<<
"SUBJECT not set. Cannot continue.";
3301 if (prefix && strlen(prefix) > 0) {
3302 res = MALLOC_17(strlen(subjects_dir)+strlen(subj)+strlen(name)+strlen(prefix)+20,
char);
3303 sprintf(res,
"%s/%s/surf/%s.%s",subjects_dir,subj,prefix,name);
3306 res = MALLOC_17(strlen(subjects_dir)+strlen(subj)+strlen(name)+20,
char);
3307 sprintf(res,
"%s/%s/surf/%s",subjects_dir,subj,name);
3317 return mne_load_surface_geom(surf_file,curv_file,TRUE,TRUE);
3325 int check_too_many_neighbors)
3330 float **verts = Q_NULLPTR;
3331 float *curvs = Q_NULLPTR;
3332 int **tris = Q_NULLPTR;
3338 void *tags = Q_NULLPTR;
3340 if (mne_read_triangle_file(surf_file,
3348 if (curv_file != Q_NULLPTR) {
3349 if (mne_read_curvature_file(curv_file,&curvs,&ncurv) == -1)
3351 if (ncurv != nvert) {
3352 qCritical()<<
"Incorrect number of vertices in the curvature file.";
3358 s->rr = verts; verts = Q_NULLPTR;
3359 s->itris = tris; tris = Q_NULLPTR;
3362 s->curv = curvs; curvs = Q_NULLPTR;
3363 s->val = MALLOC_17(s->np,
float);
3365 if (check_too_many_neighbors) {
3366 if (mne_source_space_add_geometry_info(s,TRUE) != OK)
3370 if (mne_source_space_add_geometry_info2(s,TRUE) != OK)
3374 else if (s->nn == Q_NULLPTR) {
3375 if (mne_add_vertex_normals(s) != OK)
3379 mne_add_triangle_data(s);
3381 s->inuse = MALLOC_17(s->np,
int);
3382 s->vertno = MALLOC_17(s->np,
int);
3383 for (
k = 0;
k < s->np;
k++) {
3389 s->vol_geom = mne_get_volume_geom_from_tag(tags);
3395 FREE_CMATRIX_17(verts);
3397 FREE_ICMATRIX_17(tris);
3405 int MneSurfaceOrVolume::mne_read_triangle_file(
char *fname,
3415 FILE *fp = fopen(fname,
"r");
3419 qint32 nvert,ntri,nquad;
3420 float **vert = NULL;
3429 qCritical(
"%s", fname);
3432 if (mne_read_int3(fp,&magic) != 0) {
3433 printf(
"Bad magic in %s",fname);
3436 if (magic != TRIANGLE_FILE_MAGIC_NUMBER &&
3437 magic != QUAD_FILE_MAGIC_NUMBER &&
3438 magic != NEW_QUAD_FILE_MAGIC_NUMBER) {
3439 printf(
"Bad magic in %s (%x vs %x)",fname,magic,
3440 TRIANGLE_FILE_MAGIC_NUMBER);
3443 if (magic == TRIANGLE_FILE_MAGIC_NUMBER) {
3447 printf(
"Triangle file : ");
3448 for (c = fgetc(fp); c !=
'\n'; c = fgetc(fp)) {
3450 qCritical()<<
"Bad triangle file.";
3459 if (mne_read_int(fp,&nvert) != 0)
3461 if (mne_read_int(fp,&ntri) != 0)
3463 printf(
" nvert = %d ntri = %d\n",nvert,ntri);
3464 vert = ALLOC_CMATRIX_17(nvert,3);
3465 tri = ALLOC_ICMATRIX_17(ntri,3);
3469 for (
k = 0;
k < nvert;
k++) {
3470 if (mne_read_float(fp,vert[
k]+X_17) != 0)
3472 if (mne_read_float(fp,vert[
k]+Y_17) != 0)
3474 if (mne_read_float(fp,vert[
k]+Z_17) != 0)
3480 for (
k = 0;
k < ntri;
k++) {
3481 if (mne_read_int(fp,tri[
k]+X_17) != 0)
3483 if (check_vertex(tri[
k][X_17],nvert) != OK)
3485 if (mne_read_int(fp,tri[
k]+Y_17) != 0)
3487 if (check_vertex(tri[
k][Y_17],nvert) != OK)
3489 if (mne_read_int(fp,tri[
k]+Z_17) != 0)
3491 if (check_vertex(tri[
k][Z_17],nvert) != OK)
3495 else if (magic == QUAD_FILE_MAGIC_NUMBER ||
3496 magic == NEW_QUAD_FILE_MAGIC_NUMBER) {
3497 if (mne_read_int3(fp,&nvert) != 0)
3499 if (mne_read_int3(fp,&nquad) != 0)
3501 printf(
"%s file : nvert = %d nquad = %d\n",
3502 magic == QUAD_FILE_MAGIC_NUMBER ?
"Quad" :
"New quad",
3504 vert = ALLOC_CMATRIX_17(nvert,3);
3505 if (magic == QUAD_FILE_MAGIC_NUMBER) {
3506 for (
k = 0;
k < nvert;
k++) {
3507 if (mne_read_int2(fp,&val) != 0)
3509 vert[
k][X_17] = val/100.0;
3510 if (mne_read_int2(fp,&val) != 0)
3512 vert[
k][Y_17] = val/100.0;
3513 if (mne_read_int2(fp,&val) != 0)
3515 vert[
k][Z_17] = val/100.0;
3519 for (
k = 0;
k < nvert;
k++) {
3520 if (mne_read_float(fp,vert[
k]+X_17) != 0)
3522 if (mne_read_float(fp,vert[
k]+Y_17) != 0)
3524 if (mne_read_float(fp,vert[
k]+Z_17) != 0)
3529 tri = ALLOC_ICMATRIX_17(ntri,3);
3530 for (
k = 0, ntri = 0;
k < nquad;
k++) {
3531 for (p = 0; p < 4; p++) {
3532 if (mne_read_int3(fp,quad+p) != 0)
3534 rr[p] = vert[quad[p]];
3536 rr[4] = vert[quad[0]];
3537 if (check_quad(rr) != OK)
3544 #define EVEN(n) ((((n) / 2) * 2) == n)
3546 #define WHICH_FACE_SPLIT(vno0, vno1) \
3547 (1*nearbyint(sqrt(1.9*vno0) + sqrt(3.5*vno1)))
3549 which = WHICH_FACE_SPLIT(quad[0], quad[1]) ;
3557 tri[ntri][X_17] = quad[0];
3558 tri[ntri][Y_17] = quad[1];
3559 tri[ntri][Z_17] = quad[3];
3562 tri[ntri][X_17] = quad[2];
3563 tri[ntri][Y_17] = quad[3];
3564 tri[ntri][Z_17] = quad[1];
3568 tri[ntri][X_17] = quad[0];
3569 tri[ntri][Y_17] = quad[1];
3570 tri[ntri][Z_17] = quad[2];
3573 tri[ntri][X_17] = quad[0];
3574 tri[ntri][Y_17] = quad[2];
3575 tri[ntri][Z_17] = quad[3];
3585 if (mne_read_mgh_tags(fp, &tags) == FAIL) {
3596 for (
k = 0;
k < nvert;
k++) {
3597 vert[
k][X_17] = vert[
k][X_17]/1000.0;
3598 vert[
k][Y_17] = vert[
k][Y_17]/1000.0;
3599 vert[
k][Z_17] = vert[
k][Z_17]/1000.0;
3605 for (
k = 0;
k < ntri;
k++) {
3606 help = tri[
k][X_17];
3607 tri[
k][X_17] = tri[
k][Y_17];
3608 tri[
k][Y_17] = help;
3616 FREE_CMATRIX_17(vert);
3617 FREE_ICMATRIX_17(tri);
3624 int MneSurfaceOrVolume::mne_read_curvature_file(
char *fname,
3629 FILE *fp = fopen(fname,
"r");
3632 float *curvs = NULL;
3633 float curvmin,curvmax;
3635 int nface,val_pervert;
3639 qCritical(
"%s", fname);
3642 if (mne_read_int3(fp,&magic) != 0) {
3643 printf(
"Bad magic in %s",fname);
3646 if (magic == CURVATURE_FILE_MAGIC_NUMBER) {
3650 if (mne_read_int(fp,&ncurv) != 0)
3652 if (mne_read_int(fp,&nface) != 0)
3655 printf(
"nvert = %d nface = %d\n",ncurv,nface);
3657 if (mne_read_int(fp,&val_pervert) != 0)
3659 if (val_pervert != 1) {
3660 qCritical(
"Values per vertex not equal to one.");
3666 curvs = MALLOC_17(ncurv,
float);
3667 curvmin = curvmax = 0.0;
3668 for (
k = 0;
k < ncurv;
k++) {
3669 if (mne_read_float(fp,curvs+
k) != 0)
3671 if (curvs[
k] > curvmax)
3673 if (curvs[
k] < curvmin)
3682 if (mne_read_int3(fp,&nface) != 0)
3685 printf(
"nvert = %d nface = %d\n",ncurv,nface);
3690 curvs = MALLOC_17(ncurv,
float);
3691 curvmin = curvmax = 0.0;
3692 for (
k = 0;
k < ncurv;
k++) {
3693 if (mne_read_int2(fp,&val) != 0)
3695 curvs[
k] = (float)val/100.0;
3696 if (curvs[
k] > curvmax)
3698 if (curvs[
k] < curvmin)
3704 printf(
"Curvature range: %f...%f\n",curvmin,curvmax);
3720 int MneSurfaceOrVolume::check_quad(
float **rr)
3729 for (
k = 0;
k < 4;
k++) {
3730 VEC_DIFF_17(rr[
k],rr[
k+1],diff);
3731 size = VEC_LEN_17(diff);
3733 printf(
"Degenerate quad found. size length = %f mm",size);
3742 int MneSurfaceOrVolume::check_vertex(
int no,
int maxno)
3745 if (no < 0 || no > maxno-1) {
3746 printf(
"Illegal vertex number %d (max %d).",no,maxno);
3754 MneVolGeom* MneSurfaceOrVolume::mne_get_volume_geom_from_tag(
void *tagsp)
3762 for (
k = 0;
k < tags->ntags;
k++)
3763 if (tags->tags[
k]->tag == TAG_OLD_SURF_GEOM) {
3764 tag = tags->tags[
k];
3768 vg = mne_dup_vol_geom((
MneVolGeom*)tag->data);
3781 dup->filename = g->filename;
3788 int MneSurfaceOrVolume::mne_read_mgh_tags(FILE *fp,
void **tagsp)
3795 unsigned char *tag_data;
3799 if (read_next_tag(fp,&tag,&len,&tag_data) == FAIL)
3803 *tags = mne_add_mgh_tag_to_group(*tags,tag,len,tag_data);
3805 tagsp = (
void **)tags;
3811 int MneSurfaceOrVolume::read_next_tag(FILE *fp,
int *tagp,
long long *lenp,
unsigned char **datap)
3819 if (mne_read_int(fp,&tag) == FAIL) {
3828 case TAG_OLD_MGH_XFORM:
3829 if (mne_read_int(fp,&ilen) == FAIL)
3833 case TAG_OLD_SURF_GEOM:
3834 case TAG_OLD_USEREALRAS:
3835 case TAG_OLD_COLORTABLE:
3839 if (mne_read_long(fp,&len) == FAIL)
3845 if (read_tag_data(fp,tag,len,datap,lenp) == FAIL)
3852 int MneSurfaceOrVolume::read_tag_data(FILE *fp,
int tag,
long long nbytes,
unsigned char **val,
long long *nbytesp)
3857 unsigned char *dum = NULL;
3858 size_t snbytes = nbytes;
3862 dum = MALLOC_17(nbytes+1,
unsigned char);
3863 if (fread(dum,
sizeof(
unsigned char),nbytes,fp) != snbytes) {
3864 printf(
"Failed to read %d bytes of tag data",
static_cast<int>(nbytes));
3873 if (tag == TAG_OLD_SURF_GEOM) {
3877 *val = (
unsigned char *)g;
3880 else if (tag == TAG_OLD_USEREALRAS || tag == TAG_USEREALRAS) {
3881 int *vi = MALLOC_17(1,
int);
3882 if (mne_read_int(fp,vi) == FAIL)
3884 *val = (
unsigned char *)vi;
3885 *nbytesp =
sizeof(int);
3888 printf(
"Encountered an unknown tag with no length specification : %d\n",tag);
3904 g->tags = REALLOC_17(g->tags,g->ntags+1,
MneMghTag*);
3905 g->tags[g->ntags++] = new_tag =
new MneMghTag();
3908 new_tag->data = data;
3915 MneVolGeom* MneSurfaceOrVolume::read_vol_geom(FILE *fp)
3932 while ((p = fgets(line,
sizeof(line), fp)) && counter < 8)
3936 sscanf(line,
"%s %s %*s", param, eq);
3937 if (!strcmp(param,
"valid")) {
3938 sscanf(line,
"%s %s %d \n", param, eq, &vg->valid);
3942 else if (!strcmp(param,
"filename")) {
3943 if (sscanf(line,
"%s %s %s\n", param, eq, buf) >= 3)
3944 vg->filename = mne_strdup(buf);
3947 else if (!strcmp(param,
"volume")) {
3948 sscanf(line,
"%s %s %d %d %d\n",
3949 param, eq, &vg->width, &vg->height, &vg->depth);
3952 else if (!strcmp(param,
"voxelsize")) {
3953 sscanf(line,
"%s %s %f %f %f\n",
3954 param, eq, &vg->xsize, &vg->ysize, &vg->zsize);
3958 vg->xsize = vg->xsize/1000.0;
3959 vg->ysize = vg->ysize/1000.0;
3960 vg->zsize = vg->zsize/1000.0;
3963 else if (!strcmp(param,
"xras")) {
3964 sscanf(line,
"%s %s %f %f %f\n",
3965 param, eq, vg->x_ras, vg->x_ras+1, vg->x_ras+2);
3968 else if (!strcmp(param,
"yras")) {
3969 sscanf(line,
"%s %s %f %f %f\n",
3970 param, eq, vg->y_ras, vg->y_ras+1, vg->y_ras+2);
3973 else if (!strcmp(param,
"zras")) {
3974 sscanf(line,
"%s %s %f %f %f\n",
3975 param, eq, vg->z_ras, vg->z_ras+1, vg->z_ras+2);
3978 else if (!strcmp(param,
"cras")) {
3979 sscanf(line,
"%s %s %f %f %f\n",
3980 param, eq, vg->c_ras, vg->c_ras+1, vg->c_ras+2);
3981 vg->c_ras[0] = vg->c_ras[0]/1000.0;
3982 vg->c_ras[1] = vg->c_ras[1]/1000.0;
3983 vg->c_ras[2] = vg->c_ras[2]/1000.0;
3991 fail = fseek(fp, pos, SEEK_SET);
4004 int MneSurfaceOrVolume::mne_read_int3(FILE *in,
int *ival)
4011 if (fread (&s,3,1,in) != 1) {
4013 qCritical(
"mne_read_int3");
4015 qCritical(
"mne_read_int3 could not read data");
4019 *ival = ((s >> 8) & 0xffffff);
4025 int MneSurfaceOrVolume::mne_read_int(FILE *in, qint32 *ival)
4031 if (fread (&s,
sizeof(qint32),1,in) != 1) {
4033 qCritical(
"mne_read_int");
4035 qCritical(
"mne_read_int could not read data");
4044 int MneSurfaceOrVolume::mne_read_int2(FILE *in,
int *ival)
4050 if (fread (&s,
sizeof(
short),1,in) != 1) {
4052 qCritical(
"mne_read_int2");
4054 qCritical(
"mne_read_int2 could not read data");
4063 int MneSurfaceOrVolume::mne_read_float(FILE *in,
float *fval)
4069 if (fread (&f,
sizeof(
float),1,in) != 1) {
4071 qCritical(
"mne_read_float");
4073 qCritical(
"mne_read_float could not read data");
4082 int MneSurfaceOrVolume::mne_read_long(FILE *in,
long long *lval)
4088 if (fread (&s,
sizeof(
long long),1,in) != 1) {
4090 qCritical(
"mne_read_long");
4092 qCritical(
"mne_read_long could not read data");
4101 char *MneSurfaceOrVolume::mne_strdup(
const char *s)
4106 res = MALLOC_17(strlen(s)+1,
char);