int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"SurfToSurf"}; SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt; SUMA_GENERIC_ARGV_PARSE *ps=NULL; SUMA_SurfaceObject *SO1=NULL, *SO2 = NULL; SUMA_SurfSpecFile *Spec = NULL; SUMA_M2M_STRUCT *M2M = NULL; int N_Spec=0, *nodeind = NULL, N_nodeind, icol, i, j; MRI_IMAGE *im = NULL, *im_data=NULL; int nvec=0, ncol=0, nvec_data=0, ncol_data=0, Nchar=0; float *far = NULL, *far_data=NULL, *dt = NULL, *projdir=NULL; char *outname = NULL, *s=NULL, sbuf[100]; void *SO_name = NULL; FILE *outptr=NULL; SUMA_Boolean exists = NOPE; SUMA_INDEXING_ORDER d_order = SUMA_NO_ORDER; SUMA_STRING *SS=NULL; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; /* Allocate space for DO structure */ SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-spec;-s;-sv;-o;"); Opt = SUMA_SurfToSurf_ParseInput (argv, argc, ps); if (argc < 2) { SUMA_S_Err("Too few options"); usage_SurfToSurf(ps, 0); exit (1); } /* if output surface requested, check on pre-existing file */ if (ps->o_N_surfnames) { SO_name = SUMA_Prefix2SurfaceName(ps->o_surfnames[0], NULL, NULL, ps->o_FT[0], &exists); if (exists) { fprintf(SUMA_STDERR, "Error %s:\nOutput file(s) %s* on disk.\n" "Will not overwrite.\n", FuncName, ps->o_surfnames[0]); exit(1); } } if (Opt->debug > 2) LocalHead = YUP; outname = SUMA_append_extension(Opt->out_prefix,".1D"); if (SUMA_filexists(outname) && !THD_ok_overwrite()) { fprintf(SUMA_STDERR,"Output file %s exists.\n", outname); exit(1); } /* Load the surfaces from command line*/ Spec = SUMA_IO_args_2_spec(ps, &N_Spec); if (N_Spec != 1) { SUMA_S_Err( "Multiple spec at input.\n" "Do not mix surface input types together\n"); exit(1); } if (Spec->N_Surfs != 2) { SUMA_S_Err("2 surfaces expected."); exit(1); } SO1 = SUMA_Load_Spec_Surf(Spec, 0, ps->sv[0], 0); if (!SO1) { fprintf (SUMA_STDERR,"Error %s:\n" "Failed to find surface\n" "in spec file. \n", FuncName ); exit(1); } if (!SUMA_SurfaceMetrics(SO1, "EdgeList|MemberFace", NULL)) { SUMA_SL_Err("Failed to create edge list for SO1"); exit(1); } if (Opt->fix_winding) { int orient, trouble; if (LocalHead) fprintf(SUMA_STDERR, "%s: Making sure S1 is consistently orientated\n", FuncName); if (!SUMA_MakeConsistent (SO1->FaceSetList, SO1->N_FaceSet, SO1->EL, Opt->debug, &trouble)) { SUMA_SL_Err("Failed in SUMA_MakeConsistent"); } if (trouble && LocalHead) { fprintf(SUMA_STDERR, "%s: trouble value of %d from SUMA_MakeConsistent.\n" "Inconsistencies were found and corrected unless \n" "stderr output messages from SUMA_MakeConsistent\n" "indicate otherwise.\n", FuncName, trouble); } if (LocalHead) fprintf(SUMA_STDERR,"%s: Checking orientation.\n", FuncName); orient = SUMA_OrientTriangles (SO1->NodeList, SO1->N_Node, SO1->FaceSetList, SO1->N_FaceSet, 1, 0, NULL, NULL); if (orient < 0) { /* flipping was done, dump the edge list since it is not automatically updated (should do that in function, just like in SUMA_MakeConsistent, shame on you) If you revisit this section, use the newer: SUMA_OrientSOTriangles */ if (SO1->EL) SUMA_free_Edge_List(SO1->EL); SO1->EL = NULL; if (!SUMA_SurfaceMetrics(SO1, "EdgeList", NULL)) { SUMA_SL_Err("Failed to create edge list for SO1"); exit(1); } /* free normals, new ones needed (Normals should be flipped inside of SUMA_OrientTriangles! (just like in SUMA_MakeConsistent) ) */ if (SO1->NodeNormList) SUMA_free(SO1->NodeNormList); SO1->NodeNormList = NULL; if (SO1->FaceNormList) SUMA_free(SO1->FaceNormList); SO1->FaceNormList = NULL; } if (!orient) { fprintf(SUMA_STDERR, "Error %s:\nFailed in SUMA_OrientTriangles\n", FuncName); } if (LocalHead) { if (orient < 0) { SUMA_SL_Note("S1 was reoriented"); } else { SUMA_SL_Note("S1 was properly oriented"); } } } if (!SO1->NodeNormList || !SO1->FaceNormList) { SUMA_LH("Node Normals"); SUMA_RECOMPUTE_NORMALS(SO1); } if (Opt->NodeDbg >= SO1->N_Node) { SUMA_SL_Warn( "node_debug index is larger than number " "of nodes in surface, ignoring -node_debug."); Opt->NodeDbg = -1; } SO2 = SUMA_Load_Spec_Surf(Spec, 1, ps->sv[1], 0); if (!SO2) { fprintf (SUMA_STDERR,"Error %s:\n" "Failed to find surface\n" "in spec file. \n", FuncName ); exit(1); } if (!SUMA_SurfaceMetrics(SO2, "EdgeList|MemberFace", NULL)) { SUMA_SL_Err("Failed to create edge list for SO2"); exit(1); } if (!SO2->NodeNormList || !SO2->FaceNormList) { SUMA_LH("Node Normals"); SUMA_RECOMPUTE_NORMALS(SO2); } if (LocalHead) { SUMA_LH("Surf1"); SUMA_Print_Surface_Object(SO1, NULL); SUMA_LH("Surf2"); SUMA_Print_Surface_Object(SO2, NULL); } /* a select list of nodes? */ nodeind = NULL; N_nodeind = 0; if (Opt->in_nodeindices) { im = mri_read_1D(Opt->in_nodeindices); if (!im) { SUMA_SL_Err("Failed to read 1D file of node indices"); exit(1);} far = MRI_FLOAT_PTR(im); N_nodeind = nvec = im->nx; ncol = im->ny; if (ncol != 1) { SUMA_SL_Err("More than one column in node index input file."); exit(1); } nodeind = (int *)SUMA_calloc(nvec, sizeof(int)); if (!nodeind) { SUMA_SL_Crit("Failed to allocate"); exit(1); } for (i=0;i<nvec;++i) { nodeind[i] = (int)far[i]; if (nodeind[i] < 0 || nodeind[i] >= SO1->N_Node) { fprintf(SUMA_STDERR, "Error %s:\n" "A node index of %d was found in input file %s, entry %d.\n" "Acceptable indices are positive and less than %d\n", FuncName, nodeind[i], Opt->in_nodeindices, i, SO1->N_Node); exit(1); } } mri_free(im); im = NULL; /* done with that baby */ } /* a preset directions vector ?*/ projdir = NULL; if (Opt->in_1D) { im = mri_read_1D(Opt->in_1D); if (!im) { SUMA_SL_Err("Failed to read 1D file of projection directions"); exit(1); } far = MRI_FLOAT_PTR(im); if (im->ny != 3) { SUMA_SL_Err("Need three columns in projection directions file."); exit(1); } if (im->nx != SO1->N_Node) { fprintf(SUMA_STDERR, "Error %s: You must have a direction for each node in SO1.\n" "%d directions found but SO1 has %d nodes.\n", FuncName, im->nx, SO1->N_Node); exit(1); } /* change to row major major and make it match nodeind */ projdir = (float *)SUMA_calloc(SO1->N_Node*3, sizeof(float)); if (!projdir) { SUMA_SL_Crit("Failed to allocate"); exit(1); } for (i=0; i<SO1->N_Node; ++i) { projdir[3*i ] = far[i ]; projdir[3*i+1] = far[i+ SO1->N_Node]; projdir[3*i+2] = far[i+2*SO1->N_Node]; } mri_free(im); im = NULL; /* done with that baby */ } if (SO_name) { /* user is interpolating surface coords, check on other input insanity */ if (nodeind) { fprintf( SUMA_STDERR, "Error %s: You cannot combine " "option -o_TYPE with -node_indices", FuncName); exit(1); } if (Opt->in_name) { fprintf(SUMA_STDERR, "Error %s: You cannot combine option -o_TYPE with -data", FuncName); exit(1); } } /* a 1D file containing data, or Data parameter (for XYZ)? */ if (Opt->Data > 0) { if (Opt->in_name) { /* When you are ready to work with dsets, you should checkout the function morphDsetToStd. It uses M2M */ im_data = mri_read_1D(Opt->in_name); if (!im_data) { SUMA_SL_Err("Failed to read 1D file of data"); exit(1);} far_data = MRI_FLOAT_PTR(im_data); nvec_data = im_data->nx; ncol_data = im_data->ny; if (nvec_data != SO2->N_Node) { SUMA_SL_Err("Your data file must have one row " "for each node in surface 2.\n"); exit(1); } d_order = SUMA_COLUMN_MAJOR; } else { im_data = NULL; far_data = SO2->NodeList; nvec_data = SO2->N_Node; ncol_data = 3; d_order = SUMA_ROW_MAJOR; } } else { /* just -dset */ } if (!Opt->s) { SUMA_LH("Going for the mapping of SO1 --> SO2"); M2M = SUMA_GetM2M_NN( SO1, SO2, nodeind, N_nodeind, projdir, 0, Opt->NodeDbg, Opt->iopt); SUMA_S_Notev("Saving M2M into %s\n\n", Opt->out_prefix); if (!(SUMA_Save_M2M(Opt->out_prefix, M2M))) { SUMA_S_Err("Failed to save M2M"); exit(1); } } else { SUMA_S_Notev("Reusing mapping of SO1 --> SO2 from %s\n\n", Opt->s); if (!(M2M = SUMA_Load_M2M(Opt->s))) { SUMA_S_Errv("Failed to load %s\n", Opt->s); exit(1); } } /* Now show the mapping results for a debug node ? */ if (Opt->NodeDbg >= 0) { char *s = NULL; s = SUMA_M2M_node_Info(M2M, Opt->NodeDbg); fprintf(SUMA_STDERR,"%s: Debug for node %d ([%f, %f, %f])of SO1:\n%s\n\n", FuncName, Opt->NodeDbg, SO1->NodeList[3*Opt->NodeDbg], SO1->NodeList[3*Opt->NodeDbg+1], SO1->NodeList[3*Opt->NodeDbg+2], s); SUMA_free(s); s = NULL; } /* Now please do the interpolation */ if (Opt->Data > 0) { if (Opt->NearestNode > 1) dt = SUMA_M2M_interpolate( M2M, far_data, ncol_data, nvec_data, d_order, 0 ); else if (Opt->NearestNode == 1) dt = SUMA_M2M_interpolate( M2M, far_data, ncol_data, nvec_data, d_order, 1 ); if (!dt) { SUMA_SL_Err("Failed to interpolate"); exit(1); } } else if (Opt->Data < 0) { SUMA_DSET *dset=NULL, *dseto=NULL; char *oname=NULL, *uname=NULL, *s1=NULL, *s2=NULL; int iform=SUMA_NO_DSET_FORMAT; if (Opt->NodeDbg>= 0) { SUMA_S_Notev("Processing dset %s\n", Opt->in_name); } iform = SUMA_NO_DSET_FORMAT; if (!(dset = SUMA_LoadDset_s (Opt->in_name, &iform, 0))) { SUMA_S_Errv("Failed to load %s\n", Opt->in_name); exit(1); } if (!(dseto = SUMA_morphDsetToStd ( dset, M2M, Opt->NearestNode == 1 ? 1:0))) { SUMA_S_Errv("Failed to map %s\n", Opt->in_name); exit(1); } s1 = SUMA_append_string( SUMA_FnameGet(Opt->in_name,"pa", SUMAg_CF->cwd), Opt->out_prefix); s2 = SUMA_RemoveDsetExtension_s( SUMA_FnameGet(Opt->in_name,"l",SUMAg_CF->cwd), SUMA_NO_DSET_FORMAT); uname = SUMA_append_extension(s1,s2); SUMA_free(s1); SUMA_free(s2); oname = SUMA_WriteDset_s (uname, dseto, Opt->oform, 1, 1); if (Opt->NodeDbg>= 0) SUMA_S_Notev("Wrote %s\n", oname); if (oname) SUMA_free(oname); oname=NULL; if (uname) SUMA_free(uname); oname=NULL; if (dseto) SUMA_FreeDset(dseto); dseto = NULL; if (dset) SUMA_FreeDset(dset); dset = NULL; } SUMA_LH("Forming the remaining output"); outptr = fopen(outname,"w"); if (!outptr) { SUMA_SL_Err("Failed to open file for output.\n"); exit(1); } /* first create the header of the output */ SS = SUMA_StringAppend(NULL, NULL); SS = SUMA_StringAppend_va(SS, "#Mapping from nodes on surf 1 (S1) to nodes on surf 2 (S2)\n" "# Surf 1 is labeled %s, idcode:%s\n" "# Surf 2 is labeled %s, idcode:%s\n", SO1->Label, SO1->idcode_str, SO2->Label, SO2->idcode_str); icol = 0; SS = SUMA_StringAppend_va(SS, "#Col. %d:\n" "# S1n (or nj): Index of node on S1\n" , icol); ++icol; if (Opt->NearestNode > 1) { SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# S2ne_S1n: Indices of %d nodes on S2 \n" "# that are closest neighbors of nj.\n" "# The first index is that of the node on S2 that is closest \n" "# to nj. If -1 then these values should be ignored because\n" "# in such cases, nj's projection failed.\n" , icol, icol+Opt->NearestNode-1, Opt->NearestNode); icol += Opt->NearestNode; SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# S2we_S1n: Weights assigned to nodes on surf 2 (S2) \n" "# that are closest neighbors of nj.\n" , icol, icol+Opt->NearestNode-1, Opt->NearestNode); icol += Opt->NearestNode; } else if (Opt->NearestNode == 1) { SS = SUMA_StringAppend_va(SS, "#Col. %d:\n" "# S2ne_S1n: Index of the node on S2 (label:%s idcode:%s)\n" "# that is the closest neighbor of nj.\n" "# If -1 then this value should be ignored because\n" "# nj's projection failed.\n" , icol, SO2->Label, SO2->idcode_str); ++icol; } if (Opt->NearestTriangle) { SS = SUMA_StringAppend_va(SS, "#Col. %d:\n" "# S2t_S1n: Index of the S2 triangle that hosts node nj on S1.\n" "# In other words, nj's closest projection onto S2 falls on \n" "# triangle S2t_S1n\n" "# If -1 then this value should be ignored because \n" "# nj's projection failed.\n" , icol); ++icol; } if (Opt->ProjectionOnMesh) { SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# S2p_S1n: Coordinates of projection of nj onto S2\n" , icol, icol+2); icol += 3; } if (Opt->DistanceToMesh) { SS = SUMA_StringAppend_va(SS, "#Col. %d:\n" "# Closest distance from nj to S2\n" , icol); ++icol; } if (Opt->NearestNodeCoords) { SS = SUMA_StringAppend_va(SS, "#Col. %d .. %d:\n" "# X Y Z coords of nearest node\n" , icol, icol+2); icol += 3; } if (Opt->Data > 0) { if (!Opt->in_name) { SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# Interpolation using XYZ coordinates of S2 nodes that neighbor nj\n" "# (same as coordinates of node's projection onto triangle in S2, \n" "# if using barycentric interpolation)\n" , icol, icol+2); icol += 3; } else { SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# Interpolation of data at nodes on S2 that neighbor nj\n" "# Data obtained from %s\n" , icol, icol+ncol_data-1, Opt->in_name); icol += ncol_data; } } s = SUMA_HistString("SurfToSurf", argc, argv, NULL); SS = SUMA_StringAppend_va(SS, "#History:\n" "#%s\n", s); SUMA_free(s); s = NULL; SUMA_SS2S(SS,s); fprintf(outptr,"%s\n",s); SUMA_free(s); s = NULL; /* put headers atop columns */ Nchar = 6; /* if you change this number you'll need to fix formats below */ for (i=0; i<icol; ++i) { sprintf(sbuf,"#%s", MV_format_fval2(i, Nchar -1)); fprintf(outptr,"%6s ", sbuf); } fprintf(outptr,"\n"); /* Now put in the values, make sure you parallel columns above! */ for (i=0; i<M2M->M1Nn; ++i) { fprintf(outptr,"%6s ", MV_format_fval2(M2M->M1n[i], Nchar)); if (Opt->NearestNode > 0) { for (j=0; j<Opt->NearestNode; ++j) { if (j < M2M->M2Nne_M1n[i]) fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2ne_M1n[i][j], Nchar)); else fprintf(outptr,"%6s ", "-1"); } /* Neighboring nodes */ } if (Opt->NearestNode > 1) { /* add the weights */ for (j=0; j<Opt->NearestNode; ++j) { if (j < M2M->M2Nne_M1n[i]) fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2we_M1n[i][j], Nchar)); else fprintf(outptr,"%6s ", "0.0"); } } if (Opt->NearestTriangle) { fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2t_M1n[i], Nchar)); } if (Opt->ProjectionOnMesh) { fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2p_M1n[3*i], Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2p_M1n[3*i+1], Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2p_M1n[3*i+2], Nchar)); } if (Opt->DistanceToMesh) { fprintf(outptr,"%6s ", MV_format_fval2(M2M->PD[i], Nchar)); } if (Opt->NearestNodeCoords) { float x=0.0,y=0.0,z=0.0; int n = M2M->M2ne_M1n[i][0]; if (n>0) { n = n * SO2->NodeDim; x = SO2->NodeList[n]; y = SO2->NodeList[n+1]; z = SO2->NodeList[n+2]; } fprintf(outptr,"%6s ", MV_format_fval2(x, Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(y, Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(z, Nchar)); } if (dt && Opt->Data > 0) { if (!Opt->in_name) { fprintf(outptr,"%6s ", MV_format_fval2(dt[3*i], Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(dt[3*i+1], Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(dt[3*i+2], Nchar)); } else { /* Column major business */ for (j=0; j<ncol_data; ++j) { fprintf(outptr,"%6s ", MV_format_fval2(dt[i+j*M2M->M1Nn], Nchar)); } } } fprintf(outptr,"\n"); } /* do they want an output surface ? */ if (SO_name) { float *tmpfv = NULL; SUMA_LH("Writing surface"); tmpfv = SO1->NodeList; SO1->NodeList = dt; if (!SUMA_Save_Surface_Object (SO_name, SO1, ps->o_FT[0], ps->o_FF[0], NULL)) { SUMA_S_Err("Failed to write surface object.\n"); exit (1); } SO1->NodeList = tmpfv; tmpfv = NULL; } if (N_Spec) { int k=0; for (k=0; k<N_Spec; ++k) { if (!SUMA_FreeSpecFields(&(Spec[k]))) { SUMA_S_Err("Failed to free spec fields"); } } SUMA_free(Spec); Spec = NULL; N_Spec = 0; } if (projdir) SUMA_free(projdir); projdir = NULL; if (SO_name) SUMA_free(SO_name); SO_name = NULL; if (outptr) fclose(outptr); outptr = NULL; if (dt) SUMA_free(dt); dt = NULL; if (s) SUMA_free(s); s = NULL; if (im_data) mri_free(im_data); im_data = NULL; /* done with the data */ if (nodeind) SUMA_free(nodeind); nodeind = NULL; if (M2M) M2M = SUMA_FreeM2M(M2M); if (SO1) SUMA_Free_Surface_Object(SO1); SO1 = NULL; if (SO2) SUMA_Free_Surface_Object(SO2); SO2 = NULL; if (Spec) SUMA_free(Spec); Spec = NULL; if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL; if (Opt) Opt = SUMA_Free_Generic_Prog_Options_Struct(Opt); if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1); exit(0); }
int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"SurfPatch"}; SUMA_GETPATCH_OPTIONS *Opt; char *ppref=NULL, ext[5]; float *far=NULL; MRI_IMAGE *im = NULL; int SO_read = -1; int *NodePatch=NULL, N_NodePatch=-1, *FaceSetList=NULL , N_FaceSet = -1, N_Node = -1, N_Spec=0; int i, inodeoff=-1, ilabeloff=-1, nvec, ncol, cnt; SUMA_SurfaceObject *SO = NULL; SUMA_PATCH *ptch = NULL; SUMA_SurfSpecFile *Spec; SUMA_INDEXING_ORDER d_order; void *SO_name = NULL; SUMA_Boolean exists = NOPE; SUMA_SO_File_Type typetmp; SUMA_SurfaceObject *SOnew = NULL; float *NodeList = NULL; SUMA_GENERIC_ARGV_PARSE *ps=NULL; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-spec;-s;-sv;"); /* Allocate space for DO structure */ SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); Opt = SUMA_GetPatch_ParseInput (argv, argc, ps); if (argc < 2) { SUMA_S_Err("Too few options"); usage_SUMA_getPatch(ps, 0); exit (1); } /* read all surfaces */ Spec = SUMA_IO_args_2_spec(ps, &N_Spec); if (N_Spec == 0) { SUMA_S_Err("No surfaces found."); exit(1); } if (N_Spec > 1 ) { SUMA_S_Err( "Mike, you cannot mix -spec with -i or -t options " "for specifying surfaces."); exit(1); } if (Spec->N_Surfs < 1) { SUMA_S_Err("No surfaces"); exit(1); } if (Opt->DoVol && Spec->N_Surfs != 2) { SUMA_S_Errv("Must specify 2 and only 2 surfaces with -vol options\n" "Have %d from the command line\n",Spec->N_Surfs); exit(1); } if (Opt->oType != SUMA_FT_NOT_SPECIFIED && !Opt->VolOnly) { for (i=0; i < Spec->N_Surfs; ++i) { if (Spec->N_Surfs > 1) { sprintf(ext, "_%c", 65+i); ppref = SUMA_append_string(Opt->out_prefix, ext); } else { ppref = SUMA_copy_string(Opt->out_prefix); } SO_name = SUMA_Prefix2SurfaceName(ppref, NULL, NULL, Opt->oType, &exists); if (exists && !THD_ok_overwrite()) { fprintf(SUMA_STDERR, "Error %s:\nOutput file(s) %s* on disk.\n" "Will not overwrite.\n", FuncName, ppref); exit(1); } if (ppref) SUMA_free(ppref); ppref = NULL; if (SO_name) SUMA_free(SO_name); SO_name = NULL; } } /* read in the file containing the node information */ im = mri_read_1D (Opt->in_name); if (!im) { SUMA_S_Errv("Failed to read 1D file '%s'\n", Opt->in_name); exit(1); } far = MRI_FLOAT_PTR(im); nvec = im->nx; ncol = im->ny; if (Opt->nodecol >= ncol || Opt->labelcol >= ncol) { fprintf(SUMA_STDERR, "\n" "Error %s: Input file has a total of %d columns.\n" "One or both user-specified node (%d) and \n" "label (%d) columns are too high. Maximum usable\n" "column index is %d.\n" , FuncName, ncol, Opt->nodecol, Opt->labelcol, ncol -1 ); exit(1); } d_order = SUMA_COLUMN_MAJOR; if (!nvec) { SUMA_SL_Err("Empty file"); exit(1); } /* form the node vector */ NodePatch = (int *)SUMA_malloc(sizeof(int)*nvec); if (!NodePatch) { SUMA_SL_Crit("Failed to allocate."); exit(1); } inodeoff = Opt->nodecol*nvec; if (Opt->labelcol < 0) { /* all listed nodes */ for (i=0; i<nvec; ++i) { NodePatch[i] = far[i+inodeoff]; } N_NodePatch = nvec; } else { ilabeloff = Opt->labelcol*nvec; if (Opt->thislabel < 0) { /* all nodes with non zero labels */ cnt = 0; for (i=0; i<nvec; ++i) { if (far[i+ilabeloff]) { NodePatch[cnt] = far[i+inodeoff]; ++cnt; } } N_NodePatch = cnt; } else { /* select labels */ cnt = 0; for (i=0; i<nvec; ++i) { if (far[i+ilabeloff] == Opt->thislabel) { NodePatch[cnt] = far[i+inodeoff]; ++cnt; } } N_NodePatch = cnt; } NodePatch = (int *) SUMA_realloc(NodePatch , sizeof(int)*N_NodePatch); } /* done with im, free it */ mri_free(im); im = NULL; if (Opt->DoVol) { SUMA_SurfaceObject *SO1 = SUMA_Load_Spec_Surf_with_Metrics(Spec, 0, ps->sv[0], 0); SUMA_SurfaceObject *SO2 = SUMA_Load_Spec_Surf_with_Metrics(Spec, 1, ps->sv[0], 0); double Vol = 0.0; SUMA_SurfaceObject *SOp = SUMA_Alloc_SurfObject_Struct(1); byte *adj_N=NULL; if (Opt->adjust_contour) adj_N = SUMA_calloc(SO1->N_Node, sizeof(byte)); if (!SO1 || !SO2) { SUMA_SL_Err("Failed to load surfaces."); exit(1); } /* a chunk used to test SUMA_Pattie_Volume */ Vol = SUMA_Pattie_Volume(SO1, SO2, NodePatch, N_NodePatch, SOp, Opt->minhits, Opt->FixBowTie, Opt->adjust_contour, adj_N, Opt->verb); fprintf (SUMA_STDOUT,"Volume = %f\n", fabs(Vol)); if (Opt->out_volprefix) { if (Opt->oType != SUMA_FT_NOT_SPECIFIED) SOp->FileType = Opt->oType; if (Opt->flip) { if (Opt->verb > 1) SUMA_S_Note("Flipping stitched surf's triangles\n"); SUMA_FlipSOTriangles (SOp); } if (!(SUMA_Save_Surface_Object_Wrap ( Opt->out_volprefix, NULL, SOp, SUMA_PLY, SUMA_ASCII, NULL))) { fprintf (SUMA_STDERR, "Error %s: Failed to write surface object.\n", FuncName); } if (Opt->adjust_contour && adj_N) { Opt->out_volprefix = SUMA_append_replace_string(Opt->out_volprefix, ".adjneighb","",1); ppref = SUMA_Extension(Opt->out_volprefix, ".1D.dset", NOPE); SUMA_WRITE_IND_ARRAY_1D(adj_N, NULL, SO1->N_Node, 1, ppref); SUMA_free(ppref); ppref=NULL; } } if (SOp) SUMA_Free_Surface_Object(SOp); SOp = NULL; } if (!Opt->VolOnly) { FaceSetList = NULL; N_FaceSet = -1; for (i=0; i < Spec->N_Surfs; ++i) {/* loop to read in surfaces */ /* now identify surface needed */ if (!(SO = SUMA_Load_Spec_Surf_with_Metrics(Spec, i, ps->sv[0], 0))) { SUMA_S_Err("Failed to load surface .\n"); exit(1); } if (SO->aSO) { /* otherwise, when you reset the number of FaceSets for example, and you still write in GIFTI, the old contents of aSO will prevail */ SO->aSO = SUMA_FreeAfniSurfaceObject(SO->aSO); } /* extract the patch */ ptch = SUMA_getPatch (NodePatch, N_NodePatch, SO->N_Node, SO->FaceSetList, SO->N_FaceSet, SO->MF, Opt->minhits, Opt->FixBowTie, (!i && !Opt->DoVol)); /* verbose only for first patch, and if no volume computation was required This is to keep the warnings to a minimum*/ if (!ptch) { SUMA_SL_Err("Failed to form patch."); exit(1); } if (LocalHead) SUMA_ShowPatch(ptch, NULL); /* Now create a surface with that patch */ if (Spec->N_Surfs > 1) { sprintf(ext, "_%c", 65+i); ppref = SUMA_append_string(Opt->out_prefix, ext); } else { ppref = SUMA_copy_string(Opt->out_prefix); } /* save the original type */ typetmp = SO->FileType; if (Opt->oType != SUMA_FT_NOT_SPECIFIED) SO->FileType = Opt->oType; SO_name = SUMA_Prefix2SurfaceName(ppref, NULL, NULL, SO->FileType, &exists); if (ppref) SUMA_free(ppref); ppref = NULL; /* save the original pointers to the facesets and their number */ FaceSetList = SO->FaceSetList; N_FaceSet = SO->N_FaceSet; NodeList = SO->NodeList; N_Node = SO->N_Node; /* replace with Patch */ SO->FaceSetList = ptch->FaceSetList; SO->N_FaceSet = ptch->N_FaceSet; if (Opt->Do_p2s) { if (LocalHead) fprintf (SUMA_STDERR, "%s: Changing patch to surface...\n", FuncName); SOnew = SUMA_Patch2Surf(SO->NodeList, SO->N_Node, SO->FaceSetList, SO->N_FaceSet, 3); if (!SOnew) { SUMA_S_Err("Failed to change patch to surface."); exit(1); } SO->FaceSetList = SOnew->FaceSetList; SO->N_FaceSet = SOnew->N_FaceSet; SO->N_Node = SOnew->N_Node; SO->NodeList = SOnew->NodeList; } if (SO->N_FaceSet <= 0) { SUMA_S_Warn("The patch is empty.\n" " Non existing surface not written to disk.\n"); } else { /* Is the gain wanted? */ if (Opt->coordgain) { SUMA_SL_Note("Applying coord gain to surface nodes!"); for (cnt=0; cnt < SO->NodeDim*SO->N_Node; ++cnt) SO->NodeList[cnt] *= Opt->coordgain; } if (Opt->flip) { if (Opt->verb > 1) SUMA_S_Note("Flipping triangles\n"); SUMA_FlipTriangles (SO->FaceSetList, SO->N_FaceSet); SUMA_RECOMPUTE_NORMALS(SO); } if (!SUMA_Save_Surface_Object (SO_name, SO, SO->FileType, SUMA_ASCII, NULL)) { fprintf (SUMA_STDERR, "Error %s: Failed to write surface object.\n", FuncName); exit (1); } } /* bring SO back to shape */ SO->FileType = typetmp; SO->FaceSetList = FaceSetList; FaceSetList = NULL; SO->N_FaceSet = N_FaceSet; N_FaceSet = -1; SO->NodeList = NodeList; NodeList = NULL; SO->N_Node = N_Node; N_Node = -1; if (SO_name) SUMA_free(SO_name); SO_name = NULL; if (ptch) SUMA_freePatch(ptch); ptch = NULL; if (SOnew) SUMA_Free_Surface_Object(SOnew); SOnew = NULL; /* get rid of old surface object */ } } SUMA_LH("clean up"); if (!SUMA_FreeSpecFields(Spec)) { SUMA_S_Err("Failed to free spec fields"); } SUMA_free(Spec); Spec = NULL; if (Opt->out_prefix) SUMA_free(Opt->out_prefix); Opt->out_prefix = NULL; if (Opt->out_volprefix) SUMA_free(Opt->out_volprefix); Opt->out_volprefix = NULL; if (Opt) SUMA_free(Opt); if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) { SUMA_SL_Err("DO Cleanup Failed!"); } if (!SUMA_Free_CommonFields(SUMAg_CF)) { SUMA_SL_Err("SUMAg_CF Cleanup Failed!"); } SUMA_RETURN(0); }