63#include <QCoreApplication>
64#include <QtConcurrent>
66#define _USE_MATH_DEFINES
70#include <Eigen/Sparse>
73#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
84using namespace FIFFLIB;
85using 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))
139static 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");
156float** 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))
187void mne_free_cmatrix_17 (
float **m)
195void mne_free_icmatrix_17 (
int **m)
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))
219int **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);
235Eigen::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];
246void 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);
253void fromFloatEigenMatrix_17(
const Eigen::MatrixXf& from_mat,
float **& to_mat)
255 fromFloatEigenMatrix_17(from_mat, to_mat, from_mat.rows(), from_mat.cols());
258void 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);
265void 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];
300static int comp_points1(
const void *vp1,
const void *vp2)
306 if (v1->nearest > v2->nearest)
308 else if (v1->nearest == v2->nearest)
314static int comp_points2(
const void *vp1,
const void *vp2)
320 if (v1->vert > v2->vert)
322 else if (v1->vert == v2->vert)
328void mne_sort_nearest_by_nearest(
MneNearest* points,
int npoint)
331 if (npoint > 1 && points != NULL)
332 qsort(points,npoint,
sizeof(
MneNearest),comp_points1);
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);
403double 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));
430double 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];
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];
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);
652void *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",
720int 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;
1135MneSurfaceOld* 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);
1142MneSurfaceOld* 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);
1149MneSurfaceOld* 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);
1309void 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;
1340int 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 +
1454void 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];
1469int 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);
1479int 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);
1511void 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);
1529void 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);
1559void 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++)
1628void 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);
1648int 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);
1980void 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"
2113int 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);
2194int 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;
2266int 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);
2347int 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);
2446void 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++) {
2468void 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;
2562int 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);
2789int MneSurfaceOrVolume::mne_source_space_add_geometry_info(
MneSourceSpaceOld* s,
int do_normals)
2791 return add_geometry_info(s,do_normals,NULL,TRUE);
2796int MneSurfaceOrVolume::mne_source_space_add_geometry_info2(
MneSourceSpaceOld* s,
int do_normals)
2799 return add_geometry_info(s,do_normals,NULL,FALSE);
2804int 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++)
3280char * 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);
3405int 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);
3624int 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);
3720int 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);
3742int MneSurfaceOrVolume::check_vertex(
int no,
int maxno)
3745 if (no < 0 || no > maxno-1) {
3746 printf(
"Illegal vertex number %d (max %d).",no,maxno);
3754MneVolGeom* 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;
3788int 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;
3811int 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)
3852int 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;
3915MneVolGeom* 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);
4004int 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);
4025int 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");
4044int 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");
4063int 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");
4082int 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");
4101char *MneSurfaceOrVolume::mne_strdup(
const char *s)
4106 res = MALLOC_17(strlen(s)+1,
char);
#define FIFF_MNE_SOURCE_SPACE_ID
#define FIFF_MNE_SOURCE_SPACE_DIST_LIMIT
#define FIFF_MNE_SOURCE_SPACE_VOXEL_DIMS
#define FIFF_MNE_COORD_FRAME
#define FIFF_MNE_SOURCE_SPACE_TYPE
#define FIFF_MNE_SOURCE_SPACE_SELECTION
#define FIFF_MNE_SOURCE_SPACE_USE_TRIANGLES
#define FIFF_MNE_SOURCE_SPACE_NUSE_TRI
#define FIFF_MNE_SOURCE_SPACE_INTERPOLATOR
#define FIFF_MNE_SOURCE_SPACE_NORMALS
#define FIFFV_MNE_COORD_MRI_VOXEL
#define FIFF_MNE_SOURCE_SPACE_NEAREST_DIST
#define FIFF_MNE_SOURCE_SPACE_DIST
#define FIFF_MNE_SOURCE_SPACE_POINTS
#define FIFF_MNE_SOURCE_SPACE_NTRI
#define FIFF_MNE_SOURCE_SPACE_MRI_FILE
#define FIFF_MNE_SOURCE_SPACE_NPOINTS
#define FIFF_MNE_SOURCE_SPACE_TRIANGLES
#define FIFF_MNE_SOURCE_SPACE_NUSE
#define FIFFV_MNE_COORD_RAS
#define FIFF_MNE_FILE_NAME
#define FIFF_MNE_SOURCE_SPACE_NEAREST
FiffStream class declaration.
FiffDigitizerData class declaration.
#define FIFF_BEM_SURF_NNODE
#define FIFF_BEM_SURF_NODES
#define FIFF_BEM_SURF_TRIANGLES
#define FIFF_BEM_COORD_FRAME
#define FIFF_BEM_SURF_NTRI
#define FIFF_BEM_SURF_NORMALS
FiffDigPoint class declaration.
IOUtils class declaration.
Sphere class declaration.
MneTriangle class declaration.
MneMghTagGroup class declaration.
MneVolGeom class declaration.
Filter Thread Argument (FilterThreadArg) class declaration.
MNE Patch Information (MnePatchInfo) class declaration.
MneMghTag class declaration.
MneSourceSpaceOld class declaration.
MneMshDisplaySurface class declaration.
MneProjData class declaration.
MneNearest class declaration.
MneSurfaceOld class declaration.
MNE Surface or Volume (MneSurfaceOrVolume) class declaration.
Coordinate transformation descriptor.
Digitization points container and description.
Data associated with MNE computations for each mneMeasDataSet.
Digitization point description.
QSharedPointer< FiffDirNode > SPtr
QSharedPointer< FiffStream > SPtr
QSharedPointer< FiffTag > SPtr
Filter Thread Argument Description.
The MneMghTagGroup class.
The MNE Msh Display Surface class holds information about a surface to be rendered.
This is used in the patch definitions.
One item in a derivation data set.
static void calculate_patch_area(MneSourceSpaceOld *s, MnePatchInfo *p)
static void calculate_normal_stats(MneSourceSpaceOld *s, MnePatchInfo *p)
This defines a source space.
virtual ~MneSurfaceOrVolume()
MRI data volume geometry information like FreeSurfer keeps it.
static qint32 swap_int(qint32 source)
static qint64 swap_long(qint64 source)
static float swap_float(float source)
static qint16 swap_short(qint16 source)
static bool fit_sphere_to_points(const Eigen::MatrixXf &rr, float simplex_size, Eigen::VectorXf &r0, float &R)