1 /*USE This sample to start writing standalone programs.
2 Change RetinoMap to the program name of your choosing.
3 */
4 #include "SUMA_suma.h"
5
SUMA_LocalRetinoGrad(SUMA_SurfaceObject * SO,int node,SUMA_DSET * decc,SUMA_DSET * dpol,float * pNodeList,float Gre[2],float Grp[2],int NodeDBG)6 float SUMA_LocalRetinoGrad (SUMA_SurfaceObject *SO,
7 int node,
8 SUMA_DSET *decc,
9 SUMA_DSET *dpol,
10 float *pNodeList,
11 float Gre[2],
12 float Grp[2],
13 int NodeDBG)
14 {
15 static char FuncName[]={"SUMA_LocalRetinoGrad"};
16 matrix X, XtXiXt;
17 vector Y, B;
18 SUMA_DSET *dset=NULL;
19 int in=0, in3=0, k;
20 float vfr = 0.0;
21 char *tp="not set";
22
23 SUMA_ENTRY;
24
25 /* phi(x,y) = b0 x + b1 y + const for each of the dsets */
26 /* PHI = X B + e */
27 matrix_initialize(&X);
28 matrix_create(SO->FN->N_Neighb[node]+1, 3, &X);
29 matrix_initialize(&XtXiXt);
30 matrix_create(SO->FN->N_Neighb[node]+1, 3, &XtXiXt);
31 vector_initialize(&Y);
32 vector_create(SO->FN->N_Neighb[node]+1, &Y);
33 vector_initialize(&B);
34 vector_create(3, &B);
35 for (in=0; in<=SO->FN->N_Neighb[node]; ++in) {
36 in3=3*in;
37 X.elts[in][0] = pNodeList[in3 ];
38 X.elts[in][1] = pNodeList[in3+1];
39 X.elts[in][2] = 1.0;
40 }
41
42 for (k=0; k<2; ++k) {
43 if (k==0) {
44 dset = decc;
45 tp = "eccentricity";
46 } else {
47 dset = dpol;
48 tp = "polar";
49 }
50 for (in=0; in<SO->FN->N_Neighb[node]; ++in) {
51 Y.elts[in] = SUMA_GetDsetNodeValInCol2(dset, 0,
52 SO->FN->FirstNeighb[node][in], -1);
53 }
54 Y.elts[SO->FN->N_Neighb[node]]
55 = SUMA_GetDsetNodeValInCol2(dset, 0, node, -1);
56
57 matrix_psinv(X, NULL, &XtXiXt);
58 vector_multiply(XtXiXt, Y, &B);
59
60 if (node == NodeDBG) {
61 SUMA_S_Notev("Gradient computations for node %d, dset %d/2 (%s)\n",
62 NodeDBG, k+1, k ? "pol":"ecc");
63 SUMA_S_Note("Nodes");
64 for (in=0; in<SO->FN->N_Neighb[node]; ++in)
65 fprintf(stderr,"%d\n", SO->FN->FirstNeighb[node][in]);
66 fprintf(stderr,"%d\n",node);
67 SUMA_S_Note("X");
68 matrix_print(X);
69 SUMA_S_Note("XtXiXt");
70 matrix_print(XtXiXt);
71 SUMA_S_Notev("Y, %s\n", tp);
72 vector_print(Y);
73 SUMA_S_Notev("B, %s (degrees/mm)\n", tp);
74 vector_print(B);
75 }
76
77 if (k==0) {
78 Gre[0] = B.elts[0];
79 Gre[1] = B.elts[1];
80 } else {
81 Grp[0] = B.elts[0];
82 Grp[1] = B.elts[1];
83 }
84 }
85
86 matrix_destroy(&X);
87 matrix_destroy(&XtXiXt);
88 vector_destroy(&Y);
89 vector_destroy(&B);
90
91 /* the VFR */
92
93 vfr = Grp[0]*Gre[1]-Grp[1]*Gre[0];
94
95 /* block ridiculously large values */
96 if (vfr < -100) vfr = -100.0;
97 else if (vfr > 100) vfr = 100.0;
98
99 SUMA_RETURN(vfr);
100 }
101
SUMA_RetinoMap(SUMA_SurfaceObject * SO,SUMA_DSET * decc,SUMA_DSET * dpol,byte * nmask,int NodeDBG,char * pref)102 SUMA_DSET * SUMA_RetinoMap (SUMA_SurfaceObject *SO,
103 SUMA_DSET * decc, SUMA_DSET *dpol,
104 byte *nmask, int NodeDBG, char *pref)
105 {
106 static char FuncName[]={"SUMA_RetinoMap"};
107 SUMA_DSET *dout=NULL;
108 int i=0, i3=0, in=0, neigh3, in3, j;
109 float *pNodeList=NULL, fv[3], **fm=NULL, *vfr=NULL, *mxxc=NULL, xc1, xc2;
110 float Gp[2]={0.0, 0.0}, Ge[2]={0.0, 0.0};
111 double Eq[4], proj[3], U[3], d,
112 P2[2][3]={ {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0} } ;
113 char *prefix=NULL;
114 FILE *ffgp=NULL, *ffge=NULL;
115 SUMA_Boolean LocalHead = NOPE;
116
117 SUMA_ENTRY;
118
119 if (!SO || !SO->NodeNormList || !SO->FN) {
120 SUMA_S_Err("Surface null or not ready for prime time");
121 goto CLEANOUT;
122 }
123 if (!dpol || !decc) {
124 SUMA_S_Err("NULL input");
125 goto CLEANOUT;
126 }
127
128 if (SDSET_VECNUM(dpol) == 3 && SDSET_VECNUM(decc) == 3) {
129 /* have correlations in these datasets at sb # 3 */
130 if (!(mxxc = (float *)SUMA_calloc(SO->N_Node, sizeof(float)))) {
131 SUMA_S_Err("Failed to allocate");
132 goto CLEANOUT;
133 }
134 }
135
136 if (!(pNodeList = (float *)
137 SUMA_calloc((SO->FN->N_Neighb_max+1)*SO->NodeDim, sizeof(float))) ||
138 !(fm = (float **)SUMA_allocate2D(4,4,sizeof(float))) ||
139 !(vfr = (float *)SUMA_calloc(SO->N_Node, sizeof(float))) ){
140 SUMA_S_Err("Failed to allocate");
141 goto CLEANOUT;
142 }
143
144 if (pref) {
145 prefix = SUMA_RemoveDsetExtension_s(pref,SUMA_NO_DSET_FORMAT);
146 prefix = SUMA_append_replace_string(prefix, "",".",1);
147 } else {
148 prefix = SUMA_copy_string("");
149 }
150
151 for (i=0; i<SO->N_Node; ++i) { if (!nmask || nmask[i]) {
152 if (!(i % 10000)) fprintf(SUMA_STDERR,".");
153 i3 = SO->NodeDim *i;
154 /* tangent plane at node */
155 SUMA_PLANE_NORMAL_POINT((SO->NodeNormList+i3),
156 (SO->NodeList+i3),
157 Eq);
158 for (in=0; in<SO->FN->N_Neighb[i]; ++in) {
159 in3 = 3*in;
160 neigh3 = SO->NodeDim *SO->FN->FirstNeighb[i][in];
161 SUMA_PROJECT_ONTO_PLANE(Eq, (SO->NodeList+neigh3), proj);
162 /* move projection so that it is equidistant from origin */
163 d = 0.0;
164 for (j=0; j<SO->NodeDim; ++j) {
165 U[j] = proj[j] - SO->NodeList[i3+j];
166 d += U[j]*U[j];
167 }
168 d = sqrt(d);
169 if (d != 0.0f) {
170 for (j=0; j<SO->NodeDim; ++j) U[j] /= d;
171 } else {
172 SUMA_S_Warn("zero edge length!");
173 }
174 SUMA_POINT_AT_DISTANCE_NORM(U, (SO->NodeList+i3), d, P2);
175 for (j=0; j<SO->NodeDim; ++j) pNodeList[in3+j] = P2[0][j];
176 }
177 /* add the dear node */
178 pNodeList[3*SO->FN->N_Neighb[i] ] = SO->NodeList[i3 ];
179 pNodeList[3*SO->FN->N_Neighb[i]+1] = SO->NodeList[i3+1];
180 pNodeList[3*SO->FN->N_Neighb[i]+2] = SO->NodeList[i3+2];
181
182 if (i == NodeDBG) {
183 FILE *ff=NULL;
184 char stmp[256];
185 SUMA_S_Notev("Debug files will be written for node %d\n",i);
186 sprintf(stmp,"%snorm.%d.1D.do", prefix, i);
187 ff = fopen(stmp,"w");
188 fprintf(ff,"#node-based_vectors\n");
189 fprintf(ff,"%d %f %f %f 1 0 0 1\n",
190 i, SO->EL->AvgLe*SO->NodeNormList[i3],
191 SO->EL->AvgLe*SO->NodeNormList[i3+1],
192 SO->EL->AvgLe*SO->NodeNormList[i3+2]);
193 fclose (ff);
194 sprintf(stmp,"%sinit.%d.1D.do", prefix,i);
195 ff = fopen(stmp,"w");
196 fprintf(SUMA_STDOUT,"Story for node %d \n", i);
197 fprintf(ff,"#spheres\n");
198 for (in=0; in<SO->FN->N_Neighb[i]; ++in) {
199 neigh3 = SO->NodeDim *SO->FN->FirstNeighb[i][in];
200 fprintf(ff,"#%d/%d Neighb[%d]=%d, projected to:\n",
201 in,SO->FN->N_Neighb[i], i,
202 SO->FN->FirstNeighb[i][in]);
203 fprintf(ff,"%f %f %f 1 0 0 1\n",
204 SO->NodeList[neigh3 ],
205 SO->NodeList[neigh3+1],
206 SO->NodeList[neigh3+2]);
207 }
208 fclose (ff);
209 sprintf(stmp,"%sproj.%d.1D.do", prefix,i);
210 ff = fopen(stmp,"w");
211 fprintf(ff,"#spheres\n");
212 for (in=0; in<SO->FN->N_Neighb[i]; ++in) {
213 in3=3*in;
214 fprintf(ff,"#%d/%d Neighb[%d]=%d, projected to:\n",
215 in,SO->FN->N_Neighb[i], i,
216 SO->FN->FirstNeighb[i][in]);
217 fprintf(ff,"%f %f %f 0 1 0 1\n",
218 pNodeList[in3],pNodeList[in3+1],pNodeList[in3+2]);
219 }
220 fclose (ff);
221 }
222 /* pNodeList contains all the neighbors projected onto the tangent plane */
223 /* Next, we rotate that plane so that it is parallel to the horiz. plane */
224 fv[0]=fv[1]=0.0; fv[2]=1.0; /* Z axis */
225 if (!SUMA_FromToRotation ((SO->NodeNormList+i3),fv, fm)) {
226 SUMA_S_Err("Failed to get rotation");
227 goto CLEANOUT;
228 }
229 /* Apply rotation to all elements, including the dear node */
230 for (in=0; in<=SO->FN->N_Neighb[i]; ++in) {
231 in3=3*in;
232 proj[0] = pNodeList[in3 ]*fm[0][0] +
233 pNodeList[in3+1]*fm[0][1] +
234 pNodeList[in3+2]*fm[0][2] ;
235 proj[1] = pNodeList[in3 ]*fm[1][0] +
236 pNodeList[in3+1]*fm[1][1] +
237 pNodeList[in3+2]*fm[1][2] ;
238 proj[2] = pNodeList[in3 ]*fm[2][0] +
239 pNodeList[in3+1]*fm[2][1] +
240 pNodeList[in3+2]*fm[2][2] ;
241 pNodeList[in3 ] = proj[0];
242 pNodeList[in3+1] = proj[1];
243 pNodeList[in3+2] = proj[2];
244 }
245 if (i == NodeDBG) {
246 FILE *ff=NULL;
247 char stmp[256];
248 sprintf(stmp,"%srotmat.%d.1D", prefix, i);
249 ff = fopen(stmp,"w");
250 for (in=0; in<3; ++in)
251 fprintf(ff,"%f %f %f\n",fm[in][0], fm[in][1], fm[in][2]);
252 fclose (ff);
253 sprintf(stmp,"%srotproj.%d.1D.do", prefix, i);
254 ff = fopen(stmp,"w");
255 fprintf(ff,"#spheres\n");
256 for (in=0; in<=SO->FN->N_Neighb[i]; ++in) {
257 in3=3*in;
258 fprintf(ff,"#%d/%d Neighb[%d]=%d, rotation of projection:\n",
259 in,SO->FN->N_Neighb[i], i,
260 SO->FN->FirstNeighb[i][in]);
261 fprintf(ff,"%f %f %f 0 0 1 1\n",
262 pNodeList[in3],pNodeList[in3+1],pNodeList[in3+2]);
263 }
264 fclose (ff);
265 }
266 /* Now you want to get the local gradients */
267 vfr[i] = SUMA_LocalRetinoGrad(SO, i, decc, dpol, pNodeList,
268 Ge, Gp, NodeDBG);
269
270 /* get a max correlation from two dsets */
271 if (mxxc) {
272 xc1 = SUMA_GetDsetNodeValInCol2(decc, 2, i, -1);
273 xc2 = SUMA_GetDsetNodeValInCol2(dpol, 2, i, -1);
274 if (xc2 > xc1) mxxc[i] = xc2; else mxxc[i] =xc1;
275 }
276
277 if (i==NodeDBG) {
278 SUMA_S_Notev("Node %d: Ge = [%f %f], Gp = [%f %f], VFR=%f\n",
279 i, Ge[0], Ge[1], Gp[0], Gp[1], vfr[i]);
280 }
281
282 #if 0 /* extreme debugging, output gradient estimates into dset */
283 if (i==0) {
284 char stmp[256];
285 SUMA_S_Note("DBG Stuff");
286 sprintf(stmp,"%sgradpol.1D.dset", prefix);
287 ffgp = fopen(stmp, "w");
288 sprintf(stmp,"%sgradecc.1D.dset", prefix);
289 ffge = fopen(stmp, "w");
290 }
291 fprintf(ffgp, "%f %f %f\n",
292 Gp[0], Gp[1],
293 sqrtf(Gp[0]*Gp[0]+Gp[1]*Gp[1]));
294 fprintf(ffge, "%f %f %f\n",
295 Ge[0], Ge[1],
296 sqrtf(Ge[0]*Ge[0]+Ge[1]*Ge[1]));
297 if (i==SO->N_Node) {
298 fclose(ffgp); ffgp=NULL;
299 fclose(ffge); ffge=NULL;
300 }
301 #endif
302
303 } }
304
305 fprintf(SUMA_STDERR,"\n");
306
307 SUMA_LH("Hard work over");
308 if (!(dout = SUMA_CreateDsetPointer(
309 "dodo", SUMA_NODE_BUCKET, NULL,
310 SDSET_IDMDOM(decc),
311 SO->N_Node ) ) ){
312 SUMA_S_Err("Failed to create dout");
313 goto CLEANOUT;
314 }else if (!SUMA_PopulateDsetNodeIndexNel(dout,0)) {
315 SUMA_S_Err("Failed populating node indices");
316 goto CLEANOUT;
317 }
318
319 if (!SUMA_AddDsetNelCol(dout, "VFR", SUMA_NODE_VFR, vfr, NULL, 1)) {
320 SUMA_S_Err("Failed to add column");
321 SUMA_FreeDset(dout); dout=NULL;
322 goto CLEANOUT;
323 }
324 if (mxxc) {
325 /* Not sure if we're getting power ratios or correlation coefficients
326 Just use generic term 'Thresh.'*/
327 if (!SUMA_AddDsetNelCol(dout, "Max.Thresh.",
328 SUMA_NODE_XCORR, mxxc, NULL, 1)) {
329 SUMA_S_Err("Failed to add column");
330 SUMA_FreeDset(dout); dout=NULL;
331 goto CLEANOUT;
332 }
333 }
334
335 CLEANOUT:
336 SUMA_LH("CLEANUP");
337 if (prefix) SUMA_free(prefix); prefix=NULL;
338 if (pNodeList) SUMA_free(pNodeList); pNodeList=NULL;
339 if (fm) SUMA_free2D((char **)fm, 2); fm = NULL;
340 if (vfr) SUMA_free(vfr); vfr = NULL;
341 if (mxxc) SUMA_free(mxxc); mxxc = NULL;
342
343 SUMA_LH("ADIOS");
344 SUMA_RETURN(dout);
345 }
346
usage_RetinoMap(SUMA_GENERIC_ARGV_PARSE * ps)347 void usage_RetinoMap (SUMA_GENERIC_ARGV_PARSE *ps)
348 {
349 static char FuncName[]={"usage_RetinoMap"};
350 char * s = NULL, *sio=NULL, *st = NULL, *sts = NULL;
351 int i;
352 s = SUMA_help_basics();
353 sio = SUMA_help_IO_Args(ps);
354 printf ( "\n"
355 "Usage: SurfRetinoMap <SURFACE> <-input POLAR ECCENTRICITY>\n"
356 " [<-prefix PREFIX>] [<-node_dbg NODE>]\n"
357 " \n"
358 " <SURFACE> : Surface on which distances are computed.\n"
359 " (For option's syntax, see \n"
360 " 'Specifying input surfaces' section below).\n"
361 " <-input POLAR ECCENTRICITY>: Retinotopic datasets.\n"
362 " POLAR is the polar angle dataset.\n"
363 " ECCENTRICITY is the eccentricity angle dataset.\n"
364 " Those datasets are produced by 3dRetinoPhase.\n"
365 " If the datasets are produced outside of 3dRetinoPhase, note that\n"
366 " The angle data is to be in the [0] sub-brick, and a thresholding\n"
367 " parameter, if any, is to be in the [2] sub-brick.\n"
368 "\n"
369 " [<-node_dbg NODE>]: Index of node number for which debugging\n"
370 " information is output.\n"
371 " [<-prefix PREFIX>]: Prefix for output datasets.\n"
372 " The program outputs the Visual Field Ratio (VFR),\n"
373 " the sign of which is used to differentiate between\n"
374 " adjacent areas. \n"
375 "\n"
376 " VFR computations based on paper by Warnking et al. Neuroimage 17, (2002)\n"
377 " 'FMRI Retinotopic Mapping - Step by Step\n"
378 "\n"
379 "A note on the output thresholding sub-brick:\n"
380 " In addition to VFR, you get a maximum threshold\n"
381 " sub-brick which retains the highest threshold at\n"
382 " each node in input datasets. This thresholding \n"
383 " parameter is like a union mask of input data \n"
384 " thresholded at the same level.\n"
385 " The signficance value is not provided on purpose.\n"
386 " I don't know of a good way to compute it, but \n"
387 " it serves its function or wedding out low SNR nodes.\n"
388 "\n"
389 "%s"
390 "%s"
391 "\n",
392 ps->hverb > 1 ? sio:"Use -help for more detail.\n",
393 ps->hverb > 1 ? s:"");
394 if (s) SUMA_free(s); s = NULL;
395 if (st) SUMA_free(st); st = NULL;
396 if (sio) SUMA_free(sio); sio = NULL;
397 s = SUMA_New_Additions(0, 1); printf("%s\n", s);SUMA_free(s); s = NULL;
398 printf(" Ziad S. Saad SSCC/NIMH/NIH saadz@mail.nih.gov \n");
399 return;
400 }
401
402 SUMA_GENERIC_PROG_OPTIONS_STRUCT *
SUMA_RetinoMap_ParseInput(char * argv[],int argc,SUMA_GENERIC_ARGV_PARSE * ps)403 SUMA_RetinoMap_ParseInput(
404 char *argv[], int argc, SUMA_GENERIC_ARGV_PARSE *ps)
405 {
406 static char FuncName[]={"SUMA_RetinoMap_ParseInput"};
407 SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt=NULL;
408 int kar;
409 SUMA_Boolean brk;
410 SUMA_Boolean LocalHead = NOPE;
411
412 SUMA_ENTRY;
413
414 Opt = SUMA_Alloc_Generic_Prog_Options_Struct();
415 Opt->ps = ps; /* just hold it there for convenience */
416 Opt->NodeDbg = -1;
417 Opt->out_prefix = NULL;
418 kar = 1;
419 brk = NOPE;
420 while (kar < argc) { /* loop accross command ine options */
421 /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/
422 if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
423 ps->hverb = strlen(argv[kar])>3?2:1;
424 usage_RetinoMap(ps);
425 exit (0);
426 }
427
428 SUMA_SKIP_COMMON_OPTIONS(brk, kar);
429
430 if (!brk && (strcmp(argv[kar], "-debug") == 0))
431 {
432 if (kar+1 >= argc)
433 {
434 fprintf (SUMA_STDERR, "need a number after -debug \n");
435 exit (1);
436 }
437
438 Opt->debug = atoi(argv[++kar]);
439 brk = YUP;
440 }
441
442 if (!brk && (strcmp(argv[kar], "-prefix") == 0))
443 {
444 if (kar+1 >= argc)
445 {
446 fprintf (SUMA_STDERR, "need a dset prefix after -prefix \n");
447 exit (1);
448 }
449
450 Opt->out_prefix = SUMA_copy_string(argv[++kar]);
451 brk = YUP;
452 }
453
454 if (!brk && ( (strcmp(argv[kar], "-node_dbg") == 0) ||
455 (strcmp(argv[kar], "-node_debug") == 0)) ) {
456 kar ++;
457 if (kar >= argc) {
458 fprintf (SUMA_STDERR, "need argument after -node_debug \n");
459 exit (1);
460 }
461 Opt->NodeDbg = atoi(argv[kar]);
462 if (Opt->NodeDbg < 0) {
463 fprintf (SUMA_STDERR, "%d is a bad node number.\n", Opt->NodeDbg);
464 exit (1);
465 }
466 brk = YUP;
467 }
468
469 if (!brk && !ps->arg_checked[kar]) {
470 SUMA_S_Errv("Option %s not understood.\n"
471 "Try -help for usage\n",
472 argv[kar]);
473 exit (1);
474 } else {
475 brk = NOPE;
476 kar ++;
477 }
478 }
479
480 SUMA_RETURN(Opt);
481 }
482
main(int argc,char * argv[])483 int main (int argc,char *argv[])
484 {/* Main */
485 static char FuncName[]={"SurfRetinoMap"};
486 SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt;
487 SUMA_GENERIC_ARGV_PARSE *ps=NULL;
488 SUMA_DSET_FORMAT iform = SUMA_NO_DSET_FORMAT;
489 SUMA_DSET *dpol=NULL, *decc=NULL, *dout=NULL;
490 SUMA_SurfSpecFile *Spec = NULL;
491 int ii, N_Spec, N_inmask = -1;
492 int oform= SUMA_NO_DSET_FORMAT;
493 SUMA_SurfaceObject *SO=NULL;
494 char *s=NULL;
495 SUMA_Boolean LocalHead = NOPE;
496
497 SUMA_STANDALONE_INIT;
498 SUMA_mainENTRY;
499
500 /* Allocate space for DO structure */
501 SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);
502 ps = SUMA_Parse_IO_Args(argc, argv, "-i;-spec;-s;-o;-talk;-mask;-dset;");
503
504 if (argc < 2) {
505 usage_RetinoMap(ps);
506 exit (1);
507 }
508
509 Opt = SUMA_RetinoMap_ParseInput (argv, argc, ps);
510
511 if (Opt->debug > 2) LocalHead = YUP;
512 if (Opt->ps->N_dsetname != 2) {
513 SUMA_S_Errv("Need two and only two dsets please.\n"
514 "Have %d on command line.\n",
515 Opt->ps->N_dsetname);
516 exit(1);
517 }
518 if (!(dpol = SUMA_LoadDset_s (Opt->ps->dsetname[0], &iform, 0))) {
519 SUMA_S_Errv("Failed to load dpol named %s\n", Opt->ps->dsetname[0]);
520 exit(1);
521 }
522 if (!SUMA_PopulateDsetNodeIndexNel(dpol,0)) {
523 SUMA_S_Err("Failed populating node indices");
524 exit(1);
525 }
526 if (!(decc = SUMA_LoadDset_s (Opt->ps->dsetname[1], &iform, 0))) {
527 SUMA_S_Errv("Failed to load decc named %s\n", Opt->ps->dsetname[1]);
528 exit(1);
529 }
530 if (!SUMA_PopulateDsetNodeIndexNel(decc,0)) {
531 SUMA_S_Err("Failed populating node indices");
532 exit(1);
533 }
534
535 Spec = SUMA_IO_args_2_spec(ps, &N_Spec);
536 if (N_Spec == 0) {
537 SUMA_S_Err("No surfaces found.");
538 exit(1);
539 }
540
541 SUMA_LH("Loading surface...");
542 SO = SUMA_Load_Spec_Surf(Spec, 0, ps->sv[0], Opt->debug);
543 if (!SO) {
544 fprintf (SUMA_STDERR,"Error %s:\n"
545 "Failed to find surface\n"
546 "in spec file. \n",
547 FuncName );
548 exit(1);
549
550 }
551 if (!SUMA_SurfaceMetrics_eng(SO, "EdgeList|PolyArea|",
552 NULL, Opt->debug, SUMAg_CF->DsetList)) {
553 SUMA_S_Err("Failed in SUMA_SurfaceMetrics.\n");
554 exit(1);
555 }
556
557 if (!(Opt->nmask = SUMA_load_all_command_masks(
558 Opt->ps->bmaskname, Opt->ps->nmaskname, Opt->ps->cmask,
559 SO->N_Node, &N_inmask))
560 && N_inmask < 0) {
561 SUMA_S_Err("Failed loading mask");
562 exit(1);
563 }
564 if (Opt->nmask) {
565 SUMA_LHv("%d nodes in mask for SO of %d nodes (%.2f perc. of surface)\n",
566 N_inmask, SO->N_Node, 100.0*N_inmask/SO->N_Node);
567 } else {
568 SUMA_LH("no mask");
569 }
570 if (!(dout = SUMA_RetinoMap (SO, decc, dpol, Opt->nmask,
571 Opt->NodeDbg, Opt->out_prefix))) {
572 SUMA_S_Err("Failed in RetinoMap");
573 exit(1);
574 }
575
576 if (Opt->out_prefix) {
577 s = SUMA_WriteDset_s (Opt->out_prefix, dout, oform, THD_ok_overwrite(), 0);
578 } else {
579 s = SUMA_WriteDset_s ("RetinoMap", dout, SUMA_ASCII_NIML, 1, 1);
580 }
581 SUMA_free(s);
582
583 if (!SUMA_FreeSpecFields(Spec)) {
584 SUMA_S_Err("Failed to free Spec fields");
585 } SUMA_free(Spec); Spec = NULL;
586 if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL;
587 if (Opt) Opt = SUMA_Free_Generic_Prog_Options_Struct(Opt);
588 if (!SUMA_Free_CommonFields(SUMAg_CF))
589 SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
590
591 exit(0);
592
593 }
594