1 #include "SUMA_suma.h"
2 #include "../afni.h"
3 #include "../pbardefs.h"
4
5
6 extern SUMA_CommonFields *SUMAg_CF;
7 extern SUMA_DO *SUMAg_DOv;
8 extern SUMA_SurfaceViewer *SUMAg_SVv;
9 extern int SUMAg_N_SVv;
10 extern int SUMAg_N_DOv;
11
12 #define DUMP_CMAP(cm) { \
13 int cm_ii; \
14 printf("%s\n", (cm)->Name); \
15 for(cm_ii=0;cm_ii < (cm)->N_M[0];cm_ii++) { \
16 printf(" %3d %.3f %.3f %.3f\n", cm_ii, \
17 (cm)->M[cm_ii][0], (cm)->M[cm_ii][1], (cm)->M[cm_ii][2]); \
18 } \
19 }
20
21 /*! The set of functions deals with node colors
22 */
23
24
25
26 /*!
27 This function creates an RGB colormap containing Ncols that vary linearly
28 from the first color in Fiducials to the last.
29
30 SM = SUMA_MakeColorMap (Fiducials, N , isRGBA, N_cols, SkipLast, Name)
31
32 \param Fiducials (float **) N x 3, or 4 matrix containing RGB or RGBA
33 values (range 0..1)
34 of fiducial colours which will be equally spaced on the color map
35 \param N (int) number of fiducial colors in Fiducials
36 \param isRGBA if 1 then Fiducials are RGBA else RGB
37 \param Ncols (int) total number of colors in the map.
38 You are somewhat restricted in the total number of
39 colours you choose. You must choose a number that
40 allows you to have the same number of colours between
41 successive fiducials. The function will complain if that's not the case
42 \param SkipLast (SUMA_Boolean) if set to NOPE (0), then the last color specified in
43 Fiducials is the last color in M. If set to 1, the last
44 color in M represents the color that would come right
45 before the last one in Fifucials. This last option is
46 usefull when you're crating cyclical color maps where
47 the last color in Fiduciasl is like the first.
48 \param Name (char *) name of colormap
49 \ret SM (SUMA_COLOR_MAP *) see help for SUMA_COLOR_MAP for more info
50
51 \sa based on my matlab function MakeColorMap.m
52 \sa SUMA_Free_ColorMap
53 \sa SUMA_MakeColorMap_v2
54
55 */
SUMA_MakeColorMap(float ** Fiducials,int Nfid,byte isRGBA,int Ncols,SUMA_Boolean SkipLast,char * Name)56 SUMA_COLOR_MAP* SUMA_MakeColorMap ( float **Fiducials, int Nfid, byte isRGBA,
57 int Ncols,
58 SUMA_Boolean SkipLast, char *Name)
59 {
60 static char FuncName[]={"SUMA_MakeColorMap"};
61 float **M, dFid[4];
62 int i, j, Ninter, Ngap, im, Ncolsgood, Npergap;
63 int Nrows;
64 SUMA_COLOR_MAP * SM;
65
66 SUMA_ENTRY;
67
68 // fprintf(stderr, "%s\n", FuncName);
69
70 if (isRGBA == 1) Nrows = 4;
71 else if (isRGBA == 0) Nrows = 3;
72 else {
73 SUMA_S_Errv("Not too good there %d\n", (int)isRGBA);
74 SUMA_RETURN (NULL);
75 }
76 /* check for bad input */
77 for (i=0; i < Nfid; ++i) {
78 for (j=0; j < Nrows; ++j) {
79 if (Fiducials[i][j] < 0 || Fiducials[i][j] > 1) {
80 fprintf (SUMA_STDERR,
81 "Error %s: Fiducial colors must be between 0 & 1 "
82 "(found %f)\n", FuncName, Fiducials[i][j]);
83 SUMA_RETURN (NULL);
84 }
85 }
86 }
87 /* determine the number of intermediate colors */
88 if (SkipLast) Ninter = Ncols - (Nfid - 1);
89 else Ninter = Ncols - Nfid;
90
91 Ngap = Nfid - 1;
92
93 /* you must have an equal number of colours in each gap */
94 if (Ninter % Ngap) {
95 /* bad, sugeest a better number */
96 if (SkipLast)
97 Ncolsgood = (int)(rint((float)Ninter/Ngap) * Ngap + Nfid + 1);
98 else Ncolsgood = (int)(rint((float)Ninter/Ngap) * Ngap + Nfid);
99
100 fprintf (SUMA_STDERR,
101 "Error %s: The choice of Ncols does not work with the number\n"
102 "of fiducial colours.\nTry Ncols = %d\n",
103 FuncName, Ncolsgood);
104 SUMA_RETURN (NULL);
105 }
106
107 /* allocate for M */
108 M = (float **)SUMA_allocate2D (Ncols, 4, sizeof(float));
109 if (M == NULL) {
110 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for M.\n", FuncName);
111 SUMA_RETURN (NULL);
112 }
113
114 /* start forming M */
115 im = 0;
116 Npergap = Ninter / Ngap;
117
118 for (i=0; i < Ngap; ++i) {
119 dFid[0] = (Fiducials[i+1][0] - Fiducials[i][0])/(Npergap+1);
120 dFid[1] = (Fiducials[i+1][1] - Fiducials[i][1])/(Npergap+1);
121 dFid[2] = (Fiducials[i+1][2] - Fiducials[i][2])/(Npergap+1);
122 if (Nrows == 4) {
123 dFid[3] = (Fiducials[i+1][3] - Fiducials[i][3])/(Npergap+1);
124 } else dFid[3] = 1.0;
125 /*fprintf (SUMA_STDERR,"%s: dFid = %f %f %f %f\n",
126 FuncName, dFid[0], dFid[1] , dFid[2], dFid[3]);*/
127
128 for (j=0; j < Npergap+1; ++ j) {
129
130 if (im < Ncols) {
131 M[im][0] = Fiducials[i][0] + j*dFid[0];
132 M[im][1] = Fiducials[i][1] + j*dFid[1];
133 M[im][2] = Fiducials[i][2] + j*dFid[2];
134 if (Nrows == 4) {
135 M[im][3] = Fiducials[i][3] + j*dFid[3];
136 } else M[im][3] = 1.0;
137 /*fprintf (SUMA_STDERR,"%s: M[%d][:] = %f %f %f %f\n",
138 FuncName, im, M[im][0], M[im][1], M[im][2], M[im][3]); */
139 }
140
141 ++im;
142 }
143 }
144 if (!SkipLast) {
145 if (im >= Ncols) {
146 SUMA_S_Crit("Unexpected logic error");
147 } else {
148 M[im][0] = Fiducials[Ngap][0];
149 M[im][1] = Fiducials[Ngap][1];
150 M[im][2] = Fiducials[Ngap][2];
151 if (Nrows == 4) {
152 M[im][3] = Fiducials[Ngap][3];
153 } else M[im][3] = 1.0;
154 }
155 }
156
157 /* package the resutls */
158 SM = (SUMA_COLOR_MAP *)SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
159 if (SM == NULL) {
160 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for SM.\n", FuncName);
161 SUMA_RETURN (NULL);
162 }
163 memset(SM, 0, sizeof(SUMA_COLOR_MAP));
164 SM->chd = NULL;
165 SM->idvec = NULL;
166 SM->top_frac = 0.0f;
167 SM->Name = (char *)SUMA_calloc(strlen(Name)+1, sizeof(char));
168 if (SM->Name == NULL) {
169 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for SM->Name.\n",
170 FuncName);
171 SUMA_RETURN (NULL);
172 }
173 sprintf(SM->Name, "%s",Name);
174 SM->M = M;
175 for (j=0; j< 4; ++j) SM->M0[j] = SM->M[0][j];
176 SM->N_M[0] = Ncols;
177 SM->N_M[1] = 4;
178 SM->frac = NULL; /* a linear map */
179 SM->cname = NULL;
180 SM->Sgn = 0; /* setup for linear maps with no signing,
181 mapping a la old ScaleToMap*/
182 SM->SO = NULL; /* created when needed */
183
184 SUMA_RETURN (SM);
185 }
186
187 /*!
188 This function creates an RGB colormap containing Ncols that vary linearily
189 from the first color in Fiducials to the last.
190
191 SM = SUMA_MakeColorMap_v2 (Fiducials, NFid, isRGBA, Nin , SkipLast, Name)
192
193 \param Fiducials (float **) NFid x 3 (or 4) matrix containing RGB
194 (or RGBA) values (range 0..1)
195 of fiducial colours which will be equally spaced on the color map
196 \param NFid (int) number of fiducial colors
197 \param isRGBA if 1 then Fiducials are RGBA else RGB
198 \param Nin (int*) NFid x 1 vector indicating the number of interpolations
199 to perform
200 between successive colors e.g.:
201 Fiducials Nin
202 1 0 0 2
203 0 1 0 5
204 0 0 1 0
205 The map will start with 1 0 0 then place 2 colors interpolated
206 between 1 0 0 and 0 1 0. The last color of this map is 0 0 1.
207 If the last entry in Nin was 4 then 4 colors are added after 0 0 1 wich
208 are interpolated between the last and 1st color. This is good
209 for cyclical color maps
210 \param SkipLast (SUMA_Boolean) YUP/NOPE keep last color in Fiducials out of the final map
211 \param Name (char *) name of colormap
212 \ret SM (SUMA_COLOR_MAP *) see help for SUMA_COLOR_MAP for more info
213
214 \sa SUMA_Free_ColorMap
215 \sa SUMA_MakeColorMap
216 */
217
SUMA_MakeColorMap_v2(float ** Fiducials,int Nfid,byte isRGBA,int * Nint,SUMA_Boolean SkipLast,char * Name)218 SUMA_COLOR_MAP* SUMA_MakeColorMap_v2 (float **Fiducials, int Nfid, byte isRGBA,
219 int *Nint, SUMA_Boolean SkipLast,
220 char *Name)
221 {
222 static char FuncName[]={"SUMA_MakeColorMap_v2"};
223 float **M, dFid[4]={1.0, 1.0, 1.0, 1.0};
224 int i, j, im, Ncols, Nrows;
225 SUMA_COLOR_MAP * SM;
226
227 SUMA_ENTRY;
228
229 // fprintf(stderr, "%s\n", FuncName);
230
231 if (isRGBA == 1) Nrows = 4;
232 else if (isRGBA == 0) Nrows = 3;
233 else {
234 SUMA_S_Errv("Not too good there %d\n", (int)isRGBA);
235 SUMA_RETURN (NULL);
236 }
237
238 /* check for bad input and calculate the total number of colors*/
239 if (Nint[0]) {
240 fprintf (SUMA_STDERR,
241 "Error %s: The index of the first color (%d) must be 0, \n"
242 "indexing starts at 0 not 1.\n", FuncName, Nint[0]);
243 SUMA_RETURN (NULL);
244 }
245 for (i=0; i < Nfid; ++i) {
246 for (j=0; j < Nrows; ++j) {
247 if (Fiducials[i][j] < 0 || Fiducials[i][j] > 1) {
248 fprintf (SUMA_STDERR,
249 "Error %s: Fiducial colors must be between 0 & 1 (found %f)\n",
250 FuncName, Fiducials[i][j]);
251 SUMA_RETURN (NULL);
252 }
253 }
254 }
255
256 Ncols = Nint[Nfid-1]+1;
257
258 if (SkipLast) Ncols = Ncols - 1;
259
260 /* allocate for M */
261 M = (float **)SUMA_allocate2D (Ncols, 4, sizeof(float));
262 if (M == NULL) {
263 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for M.\n", FuncName);
264 SUMA_RETURN (NULL);
265 }
266
267 /* start forming M */
268 im = 0;
269 for (i=0; i < Nfid-1; ++i) {
270 dFid[0] = (Fiducials[i+1][0] - Fiducials[i][0])/(Nint[i+1]-Nint[i]);
271 dFid[1] = (Fiducials[i+1][1] - Fiducials[i][1])/(Nint[i+1]-Nint[i]);
272 dFid[2] = (Fiducials[i+1][2] - Fiducials[i][2])/(Nint[i+1]-Nint[i]);
273 if (Nrows==4) {
274 dFid[2] = (Fiducials[i+1][3] - Fiducials[i][3])/(Nint[i+1]-Nint[i]);
275 } else dFid[3] = 1.0;
276 /*fprintf (SUMA_STDERR,"%s: dFid = %f %f %f %f\n",
277 FuncName, dFid[0], dFid[1] , dFid[2], dFid[3]);*/
278
279 for (j=0; j < (Nint[i+1]- Nint[i]); ++ j) {
280 M[im][0] = Fiducials[i][0] + j*dFid[0];
281 M[im][1] = Fiducials[i][1] + j*dFid[1];
282 M[im][2] = Fiducials[i][2] + j*dFid[2];
283 if (Nrows==4) {
284 M[im][3] = Fiducials[i][3] + j*dFid[3];
285 } else M[im][3] = 1.0;
286 /*fprintf (SUMA_STDERR,"%s: M[%d][:] = %f %f %f %f\n",
287 FuncName, im, M[im][0], M[im][1], M[im][2], M[im][3]); */
288 ++im;
289 }
290 }
291
292 if (!SkipLast){
293 M[im][0] = Fiducials[Nfid-1][0];
294 M[im][1] = Fiducials[Nfid-1][1];
295 M[im][2] = Fiducials[Nfid-1][2];
296 if (Nrows==4) {
297 M[im][3] = Fiducials[Nfid-1][3];
298 } else M[im][3] = 1.0;
299 }
300
301 /* package the resutls */
302 SM = (SUMA_COLOR_MAP *)SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
303 if (SM == NULL) {
304 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for SM.\n", FuncName);
305 SUMA_RETURN (NULL);
306 }
307 memset(SM, 0, sizeof(SUMA_COLOR_MAP));
308 SM->idvec = NULL;
309 SM->chd = NULL;
310 SM->top_frac = 0.0f;
311 SM->Name = (char *)SUMA_calloc(strlen(Name)+1, sizeof(char));
312 if (SM->Name == NULL) {
313 fprintf (SUMA_STDERR,
314 "Error %s: Failed to allocate for SM->Name.\n", FuncName);
315 SUMA_RETURN (NULL);
316 }
317 sprintf(SM->Name, "%s",Name);
318 SM->M = M;
319 for (j=0; j< 4; ++j) SM->M0[j] = SM->M[0][j];
320 SM->N_M[0] = Ncols;
321 SM->N_M[1] = 4;
322
323 SM->frac = NULL; /* a linear map */
324 SM->cname = NULL;
325 SM->Sgn = 0; /* setup for linear maps with no signing,
326 mapping a la old ScaleToMap*/
327 SM->SO = NULL; /* created when needed */
328 SUMA_RETURN (SM);
329 }
330
331 /*! function to free memory allocated for SUMA_COLOR_MAP */
SUMA_Free_ColorMap(SUMA_COLOR_MAP * SM)332 void SUMA_Free_ColorMap (SUMA_COLOR_MAP* SM)
333 {
334 static char FuncName[]={"SUMA_Free_ColorMap"};
335 int i = 0;
336
337 SUMA_ENTRY;
338
339 // fprintf(stderr, "%s\n", FuncName);
340
341 if (SM->Name) SUMA_free(SM->Name);
342 if (SM->M) SUMA_free2D((char **)SM->M, SM->N_M[0]);
343 if (SM->cname) {
344 for (i=0; i<SM->N_M[0]; ++i) { if (SM->cname[i]) SUMA_free(SM->cname[i]); }
345 SUMA_free(SM->cname);
346 }
347 if (SM->frac) SUMA_free(SM->frac);
348 if (SM->SO) SUMA_Free_Surface_Object(SM->SO);
349 if (SM->idvec) SUMA_free(SM->idvec);
350 if (SM->chd) SUMA_DestroyCmapHash(SM);
351 if (SM) SUMA_free(SM);
352
353 SUMA_RETURNe;
354 }
355
SUMA_DuplicateColorMap(SUMA_COLOR_MAP * cin,char * newname)356 SUMA_COLOR_MAP* SUMA_DuplicateColorMap (SUMA_COLOR_MAP *cin, char *newname)
357 {
358 static char FuncName[]={"SUMA_DuplicateColorMap"};
359 SUMA_COLOR_MAP *cmap=NULL;
360 int i, j;
361
362 SUMA_ENTRY;
363
364 // fprintf(stderr, "%s\n", FuncName);
365
366 if (!cin) SUMA_RETURN(cmap);
367
368 cmap = (SUMA_COLOR_MAP *)SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
369 if (cmap == NULL) {
370 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for SM.\n", FuncName);
371 SUMA_RETURN (NULL);
372 }
373
374 cmap->N_M[0] = cin->N_M[0];
375 cmap->N_M[1] = cin->N_M[1];
376 cmap->M = (float**)SUMA_allocate2D(cmap->N_M[0], cmap->N_M[1], sizeof(float));
377
378 for (i=0; i<cmap->N_M[0]; ++i) {
379 for (j=0; j<cmap->N_M[1]; ++j) {
380 cmap->M[i][j] = cin->M[i][j];
381 } }
382 for (j=0; j<4; ++j) { cmap->M0[j] = cin->M0[j]; }
383 cmap->flipped = cin->flipped;
384
385 if (cin->frac) {
386 cmap->frac = (float *)SUMA_calloc(cmap->N_M[0], sizeof(float));
387 memcpy(cmap->frac, cin->frac, cmap->N_M[0]*sizeof(float));
388 } else cmap->frac = NULL;
389 cmap->top_frac = cin->top_frac;
390 cmap->Sgn = cin->Sgn;
391 if (newname) cmap->Name = SUMA_copy_string(newname);
392 else cmap->Name = SUMA_copy_string(cin->Name);
393
394 if (cin->idvec) {
395 cmap->idvec = (int *)SUMA_calloc(cmap->N_M[0], sizeof(int));
396 memcpy(cmap->idvec, cin->idvec, cmap->N_M[0]*sizeof(int));
397 } else cmap->idvec = NULL;
398 cmap->chd = NULL;
399
400 if (cin->cname) {
401 cmap->cname = (char **)SUMA_calloc(cmap->N_M[0], sizeof(char *));
402 for (j=0; j<cmap->N_M[0]; ++j) {
403 cmap->cname[j] = SUMA_copy_string(cin->cname[j]);
404 }
405 } else cmap->cname = NULL;
406
407 cmap->SO = NULL; /* created when needed */
408
409 SUMA_RETURN(cmap);
410
411 }
412
413 /* based on AFNI's PBAR_define_bigmap */
SUMA_pbardef_to_CM(char * cmd)414 SUMA_COLOR_MAP * SUMA_pbardef_to_CM
415 (char *cmd)
416 {
417 static char FuncName[]={"SUMA_pbardef_to_CM"};
418 SUMA_COLOR_MAP *CM=NULL;
419 int ii , neq=0 , nonum=0, N_Col;
420 float val[NPANE_BIG+1],rgb[3]={0.0, 0.0, 0.0}, **M=NULL;
421 char name[NSBUF]="\0", eqn[NSBUF]="\0" , rhs[NSBUF]="\0" ;
422 SUMA_Boolean LocalHead = NOPE;
423
424 SUMA_ENTRY;
425
426 // fprintf(stderr, "%s\n", FuncName);
427
428 CM = (SUMA_COLOR_MAP *)SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
429 if (CM == NULL ) {
430 SUMA_SL_Crit ("Failed to allocate for CM");
431 SUMA_RETURN(NULL);
432 }
433 memset(CM, 0, sizeof(SUMA_COLOR_MAP));
434 CM->idvec = NULL;
435 CM->chd = NULL;
436 CM->top_frac = 0.0f;
437 CM->SO = NULL;
438 CM->cname = NULL;
439 CM->N_M[0] = NPANE_BIG;
440 CM->N_M[1] = 4;
441 CM->Sgn = 0;
442
443 CM->frac = NULL;
444 CM->M = (float**)SUMA_allocate2D (CM->N_M[0], CM->N_M[1], sizeof(float));
445 if ( CM->M == NULL ) {
446 SUMA_SL_Crit ("Failed to allocate for fields of CM.");
447 SUMA_RETURN (NULL);
448 }
449
450 /* most of it from the PBAR_define_bigmap chunk */
451 if (strncmp(cmd,"init_bigmaps", 12) == 0) {
452 static char **bmn = NULL;
453 static rgbyte **bm = NULL;
454 char sname[100], snamemax[100];
455 int iii, kkk, found;
456 SUMA_LHv("one big map %s\n", cmd);
457 if (!bm) {
458 SUMA_LH("Going to initialize bigmaps");
459 if (NJ_bigmaps_init(NBIGMAP_INIT, &bmn, &bm)) {
460 SUMA_S_Err("That Acela Sure Sucks!");
461 SUMA_RETURN(NULL);
462 }
463 }
464 sprintf(snamemax, "init_bigmaps_%d", NBIGMAP_INIT-1);
465 found = 0;
466 for (iii=0; iii<NBIGMAP_INIT; ++iii) {
467 SUMA_LHv("testing %d/(%d)...\n",iii, NBIGMAP_INIT);
468 sprintf(sname, "init_bigmaps_%d", iii);
469 if ( strcmp(cmd,sname) == 0 ) {
470 SUMA_LHv("found one %d\n", iii);
471 CM->Name = SUMA_copy_string(BIGMAP_NAMES[iii]);
472 for (kkk=0; kkk<NPANE_BIG; ++kkk) {
473 SUMA_LHv("%d [%d %d %d]\n",
474 kkk,
475 bm[iii][kkk].r, bm[iii][kkk].g, bm[iii][kkk].b);
476 #if 0
477
478 CM->M[kkk][0] = bm[iii][kkk].r / 255.0f ;
479 CM->M[kkk][1] = bm[iii][kkk].g / 255.0f ;
480 CM->M[kkk][2] = bm[iii][kkk].b / 255.0f ;
481 CM->M[kkk][3] = 1.0;
482
483 #endif
484 CM->M[NPANE_BIG-(kkk+1)][0] = bm[iii][kkk].r / 255.0f ;
485 CM->M[NPANE_BIG-(kkk+1)][1] = bm[iii][kkk].g / 255.0f ;
486 CM->M[NPANE_BIG-(kkk+1)][2] = bm[iii][kkk].b / 255.0f ;
487 CM->M[NPANE_BIG-(kkk+1)][3] = 1.0;
488 }
489 found = 1;
490 }
491 }
492 if (strcmp(cmd, snamemax)==0) {
493 SUMA_LHv("Freeing bigmaps (at %s)\n", snamemax);
494 for (iii=0; iii<NBIGMAP_INIT; ++iii) {
495 if (bmn[iii]) free(bmn[iii]);
496 if (bm[iii]) free(bm[iii]);
497 }
498 free(bmn); free(bm);
499 bmn = NULL;
500 bm= NULL;
501 }
502 if (found) {
503 CM->M0[0] = CM->M[0][0];
504 CM->M0[1] = CM->M[0][1];
505 CM->M0[2] = CM->M[0][2];
506 CM->M0[3] = CM->M[0][3];
507 SUMA_RETURN(CM);
508 } else{
509 SUMA_S_Err("Bad deal. No bigmap constructed.");
510 SUMA_RETURN(NULL);
511 }
512 } else {
513 name[0] = '\0' ; ii = 0 ;
514 sscanf(cmd,"%127s%n",name,&ii) ;
515 SUMA_LHv("name here = %s %d\n",name,ii);
516 CM->Name = SUMA_copy_string(name);
517
518 if( *name == '\0' || ii == 0 ) RETURN(NULL) ;
519 cmd += ii ;
520 /* get lines of form "value=colordef" */
521
522 while( neq < NPANE_BIG ){
523 eqn[0] = '\0' ; ii = 0 ;
524 sscanf(cmd,"%127s%n",eqn,&ii) ;
525 SUMA_LHv("%s %d\n",eqn,ii);
526 if( *eqn == '\0' || ii == 0 ) break ; /* exit loop */
527 cmd += ii ;
528 if( neq == 0 && (isalpha(eqn[0]) || eqn[0]=='#') ) nonum = 1 ;
529 rhs[0] = '\0' ; ii = 0 ;
530 if( !nonum ) sscanf(eqn,"%f=%s%n",val+neq,rhs,&ii) ;
531 else sscanf(eqn,"%s%n" ,rhs,&ii) ;
532 if( *rhs == '\0' || ii == 0 ) RETURN(NULL); /* bad */
533 SUMA_LHv("eqn=%s\n rhs=%s\n", eqn, rhs);
534 ii = !SUMA_Interpret_AFNIColor(rhs, rgb );
535 if (ii) {
536 SUMA_S_Errv("Failed to interpret AFNIColor %s\n", rhs);
537 RETURN(NULL);
538 }
539 SUMA_LHv("%s %f %f %f %d\n",rhs, rgb[0],rgb[1],rgb[2], ii);
540 CM->M[neq][0] = rgb[0];
541 CM->M[neq][1] = rgb[1];
542 CM->M[neq][2] = rgb[2];
543 CM->M[neq][3] = 1.0;
544 neq++;
545 }
546 SUMA_LHv("Map %s, neq = %d\n", name, neq);
547 /* in AFNI, all of these maps get interpolated to NPANE_BIG
548 but that is not needed in SUMA. Only some maps need the
549 interpolation to look good */
550 if (neq <= 20) { /* an arbitrary number, really */
551 SUMA_COLOR_MAP *CMn=NULL;
552 /* now do the interpolation to NPANE_BIG */
553 CMn = SUMA_MakeColorMap(CM->M, neq, 0, NPANE_BIG+1, 0, CM->Name);
554 SUMA_Free_ColorMap(CM); CM=CMn; CMn=NULL;
555 /* flip color map if it came from AFNI - short or long */
556 SUMA_Flip_Color_Map(CM);
557 } else { /* leave it like it is */
558 SUMA_LHv("Leaving map %s at %d colors\n", CM->Name, neq);
559 /* realloc */
560 N_Col = neq;
561 M = (float**)SUMA_allocate2D (N_Col, 4, sizeof(float));
562 for (ii=0; ii<N_Col; ++ii) {
563 M[N_Col-ii-1][0] = CM->M[ii][0];
564 M[N_Col-ii-1][1] = CM->M[ii][1];
565 M[N_Col-ii-1][2] = CM->M[ii][2];
566 M[N_Col-ii-1][3] = CM->M[ii][3];
567 }
568 SUMA_free2D((char**)CM->M, CM->N_M[0]); CM->M = M; M = NULL;
569 CM->N_M[0] = N_Col; CM->N_M[1] = 4;
570 }
571 }
572
573 SUMA_RETURN(CM);
574 }
575 /*!
576 \brief Builds the SUMA_AFNI_COLORS structure which
577 contains the Named colors and colormaps defined in AFNI
578 The colors and colormaps loaded are the ones that
579 are found in AFNI when AFNI is first started.
580
581 - Continuous colormaps are NOT loaded.
582 - Colors and colormaps defined in the .afnirc are loaded
583
584 \sa SUMA_DestroyAfniColors (for deleting returned structure)
585 */
586 #define SUMA_PBARDEF_ADD(mdmm) { \
587 SUMA_COLOR_MAP *m_CM=NULL; \
588 m_CM = SUMA_pbardef_to_CM( mdmm ); \
589 if (!(CMv = SUMA_Add_ColorMap (m_CM, CMv, &N_maps))) { \
590 SUMA_SL_Crit("Failed in SUMA_Add_ColorMap"); \
591 SUMA_RETURN(NULL); \
592 } \
593 }
594
SUMA_Get_AFNI_Default_Color_Maps()595 SUMA_AFNI_COLORS *SUMA_Get_AFNI_Default_Color_Maps ()
596 {
597 static char FuncName[]={"SUMA_Get_AFNI_Default_Color_Maps"};
598 float rgb[3]={0.0, 0.0, 0.0};
599 SUMA_RGB_NAME *Cv = NULL;
600 SUMA_COLOR_MAP **CMv=NULL;
601 SUMA_COLOR_MAP *CMp=NULL, *CMn=NULL;
602 SUMA_AFNI_COLORS *SAC=NULL;
603 int i=-1, j=-1, icol=-1;
604 int N_maps=-1, N_cols=-1;
605 int ival=-1 , ii=-1,jj=-1 ;
606 float fval =0.0;
607 float pthr[NPANE_MAX+1] ;
608 int pov[NPANE_MAX+1] ;
609 char *homeenv=NULL, *sumarc=NULL;
610 struct stat stbuf;
611 SUMA_Boolean LocalHead_Detail = NOPE;
612 SUMA_Boolean LocalHead = NOPE;
613
614 SUMA_ENTRY;
615
616 // fprintf(stderr, "%s\n", FuncName);
617
618
619 /* initilialize*/
620 N_maps = -1;
621 N_cols = -1;
622 for (i=0;i<NPANE_MAX+1;++i) { pthr[i] = 0.0; pov[i] = 0;}
623
624 /* add the none color first */
625 Cv = SUMA_Add_Color ("none",
626 -1.0, -1.0, -1.0, 1.0,
627 Cv, &N_cols);
628
629 /* get the rgb, floats of each color defined DEFAULT_NCOLOVR */
630 for (i=0; i<DEFAULT_NCOLOVR; ++i) {
631 if (!SUMA_Interpret_AFNIColor (INIT_def_colovr[i], rgb)) {
632 fprintf(SUMA_STDERR,
633 "Error %s: Failed to interpret color %s : %s\n",
634 FuncName, INIT_def_labovr[i], INIT_def_colovr[i]);
635 } else {
636 if (LocalHead_Detail)
637 fprintf(SUMA_STDERR,"%s: Adding color %s : %s [%.3f %.3f %.3f]\n",
638 FuncName, INIT_def_labovr[i], INIT_def_colovr[i],
639 rgb[0], rgb[1], rgb[2]);
640 Cv = SUMA_Add_Color (INIT_def_labovr[i],
641 rgb[0], rgb[1], rgb[2], 1.0,
642 Cv, &N_cols);
643 }
644 }
645
646 if (LocalHead_Detail)
647
648 #if 0
649 /* causes crash on Fedora Core 7 and core 6, not worth it */
650 SUMA_Interpret_AFNIColor (NULL, rgb);
651 #endif
652 /* Now create the afni color maps with more than 10
653 panes (excerpts from afni.c)*/
654
655 /* start with positive panes */
656 for( ii=NPANE_INIT+1 ; ii <= NPANE_MAX ; ii++ ){
657 fval = 1.0 / ii ;
658 pthr[0] = 1.0 ;
659 pthr[ii] = 0.0 ;
660 for( jj=1 ; jj < ii ; jj++ ) pthr[jj] = fval * (ii-jj) ;
661 for( jj=0 ; jj < ii ; jj++ ) pov[jj] = (jj % INIT_ncolovr) + 1 ;
662
663 for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_pos[ii][jj] = pthr[jj] ;
664 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_pos[ii][jj] = pov[jj] ;
665 }
666
667 /** initialize signed pbar panes **/
668 for( ii=NPANE_INIT+1 ; ii <= NPANE_MAX ; ii++ ){
669 fval = 1.0 / ii ;
670 pthr[0] = 1.0 ;
671 pthr[ii] = -1.0 ;
672 for( jj=1 ; jj < ii ; jj++ ) pthr[jj] = fval * (ii-2*jj) ;
673 for( jj=0 ; jj < ii ; jj++ ) pov[jj] = (jj % INIT_ncolovr) + 1 ;
674
675 for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_sgn[ii][jj] = pthr[jj] ;
676 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_sgn[ii][jj] = pov[jj] ;
677 }
678
679 #if defined(RGBCYC_COUNT) && RGBCYC_COUNT <= NPANE_MAX
680 ii = RGBCYC_COUNT ;
681 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_pos[ii][jj] = RGBCYC_FIRST+jj+1 ;
682 for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_sgn[ii][jj] = RGBCYC_FIRST+jj+1 ;
683 #endif
684
685
686 /* now create AFNI's colormaps */
687 for (i = NPANE_MIN; i<= NPANE_MAX; ++i) {
688 CMp = (SUMA_COLOR_MAP *)SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
689 CMn = (SUMA_COLOR_MAP *)SUMA_calloc(1, sizeof(SUMA_COLOR_MAP));
690 if (CMp == NULL || CMn == NULL) {
691 SUMA_SL_Crit ("Failed to allocate for CMp &/| CMn.");
692 SUMA_RETURN(NULL);
693 }
694 memset(CMp, 0, sizeof(SUMA_COLOR_MAP));
695 memset(CMn, 0, sizeof(SUMA_COLOR_MAP));
696 CMp->idvec = NULL;
697 CMn->idvec = NULL;
698 CMp->chd = NULL;
699 CMn->chd = NULL;
700 CMp->top_frac = 0.0f;
701 CMn->top_frac = 0.0f;
702 CMp->SO = NULL;
703 CMn->SO = NULL;
704 CMp->cname = NULL;
705 CMn->cname = NULL;
706 CMp->N_M[0] = i; CMp->N_M[1] = 4;
707 CMn->N_M[0] = i; CMn->N_M[1] = 4;
708 CMp->Sgn = 1;
709 CMn->Sgn = -1;
710
711 CMp->Name = (char *)SUMA_calloc(25, sizeof(char));
712 CMn->Name = (char *)SUMA_calloc(25, sizeof(char));
713 CMp->frac = (float *)SUMA_calloc(i, sizeof(float));
714 CMn->frac = (float *)SUMA_calloc(i, sizeof(float));
715 CMp->M = (float**)SUMA_allocate2D (CMp->N_M[0],CMp->N_M[1],sizeof(float));
716 CMn->M = (float**)SUMA_allocate2D (CMn->N_M[0],CMn->N_M[1],sizeof(float));
717 if ( CMp->frac == NULL || CMn->frac == NULL
718 || CMp->M == NULL || CMn->M == NULL
719 || CMp->Name == NULL || CMn->Name == NULL ) {
720 SUMA_SL_Crit ("Failed to allocate for fields of CMp &/| CMn.");
721 SUMA_RETURN (NULL);
722 }
723
724 sprintf(CMp->Name, "afni_p%d",i);
725 sprintf(CMn->Name, "afni_n%d",i);
726
727 if (LocalHead_Detail)
728 fprintf (SUMA_STDERR,"%s: Building colormap POS #%d (%s)\n",
729 FuncName, i, CMp->Name);
730
731 for ( j = 0; j < i; ++j) {
732 if (!INIT_ovin_pos[i][j]) {
733 if (LocalHead_Detail) {
734 fprintf (SUMA_STDERR,"\t[i%d] NoColor\t%f\n",
735 INIT_ovin_pos[i][j],
736 INIT_pval_pos[i][j]);
737 }
738 CMp->M[i - j - 1][0] = CMp->M[i - j - 1][1] =
739 CMp->M[i - j - 1][2] = -1.0;
740 CMp->M[i - j - 1][3] = 0.0;
741 } else {
742 if (LocalHead_Detail) {
743 fprintf (SUMA_STDERR,"\t[i%d] %s\t%f\n",
744 INIT_ovin_pos[i][j],
745 INIT_def_labovr[INIT_ovin_pos[i][j]-1],
746 INIT_pval_pos[i][j]);
747 }
748 /* find out which color this is */
749 icol = SUMA_Find_Color (INIT_def_labovr[INIT_ovin_pos[i][j]-1],
750 Cv, N_cols);
751 if (icol < 0) {
752 fprintf (SUMA_STDERR,
753 "Error%s: Failed to find color %s\n"
754 "Using no-color in its place\n",
755 FuncName, INIT_def_labovr[INIT_ovin_pos[i][j]-1]);
756 CMp->M[i - j - 1][0] = CMp->M[i - j - 1][1] =
757 CMp->M[i - j - 1][2] = -1.0;
758 CMp->M[i - j - 1][3] = 0.0;
759 } else {
760 CMp->M[i - j - 1][0] = Cv[icol].r;
761 CMp->M[i - j - 1][1] = Cv[icol].g;
762 CMp->M[i - j - 1][2] = Cv[icol].b;
763 CMp->M[i - j - 1][3] = 1.0;
764 }
765 }
766 CMp->frac[i - j - 1] = INIT_pval_pos[i][j];
767 }
768 if (CMp->frac[CMp->N_M[0]-1] != 1.0f) {
769 SUMA_LH("top_frac not 1 for positive map");
770 CMp->top_frac = CMp->frac[CMp->N_M[0]-1];
771 }
772 CMp->M0[0] = CMp->M[0][0];
773 CMp->M0[1] = CMp->M[0][1];
774 CMp->M0[2] = CMp->M[0][2];
775 CMp->M0[3] = CMp->M[0][3];
776
777 /* add the positive map to the list */
778 CMv = SUMA_Add_ColorMap (CMp, CMv, &N_maps);
779 if (!CMv) {
780 SUMA_SL_Crit("Failed in SUMA_Add_ColorMap");
781 SUMA_RETURN(NULL);
782 }
783
784 if (LocalHead_Detail)
785 fprintf (SUMA_STDERR,"%s: Building colormap SGN #%d (%s)\n",
786 FuncName, i, CMn->Name);
787
788 for ( j = 0; j < i; ++j) {
789 if (!INIT_ovin_sgn[i][j]) {
790 if (LocalHead_Detail) {
791 fprintf (SUMA_STDERR,"\t[i%d] NoColor\t%f\n",
792 INIT_ovin_sgn[i][j],
793 INIT_pval_sgn[i][j]);
794 }
795 CMn->M[i - j - 1][0] = CMn->M[i - j - 1][1] =
796 CMn->M[i - j - 1][2] = -1.0;
797 CMn->M[i - j - 1][3] = 0.0;
798 } else {
799 if (LocalHead_Detail) {
800 fprintf (SUMA_STDERR,"\t[i%d] %s\t%f\n",
801 INIT_ovin_sgn[i][j],
802 INIT_def_labovr[INIT_ovin_sgn[i][j]-1],
803 INIT_pval_sgn[i][j]);
804 }
805 icol = SUMA_Find_Color (INIT_def_labovr[INIT_ovin_sgn[i][j]-1],
806 Cv, N_cols);
807 if (icol < 0) {
808 fprintf (SUMA_STDERR,
809 "Error%s: Failed to find color %s\n"
810 "Using no-color in its place",
811 FuncName, INIT_def_labovr[INIT_ovin_sgn[i][j]-1]);
812 CMn->M[i - j - 1][0] = CMn->M[i - j - 1][1] =
813 CMn->M[i - j - 1][2] = -1.0;
814 CMn->M[i - j - 1][3] = 0.0;
815 } else {
816 CMn->M[i - j - 1][0] = Cv[icol].r;
817 CMn->M[i - j - 1][1] = Cv[icol].g;
818 CMn->M[i - j - 1][2] = Cv[icol].b;
819 CMn->M[i - j - 1][3] = 1.0;
820 }
821 }
822 CMn->frac[i - j - 1] = INIT_pval_sgn[i][j];
823 }
824 if (CMn->frac[CMn->N_M[0]-1] != 1.0f) {
825 SUMA_LH("top_frac not 1 for negative map");
826 CMn->top_frac = CMn->frac[CMp->N_M[0]-1];
827 }
828 CMn->M0[0] = CMn->M[0][0];
829 CMn->M0[1] = CMn->M[0][1];
830 CMn->M0[2] = CMn->M[0][2];
831 CMn->M0[3] = CMn->M[0][3];
832 /* add the negative map to the list */
833 CMv = SUMA_Add_ColorMap (CMn, CMv, &N_maps);
834 if (!CMv) {
835 SUMA_SL_Crit("Failed in SUMA_Add_ColorMap");
836 SUMA_RETURN(NULL);
837 }
838 }
839
840
841 /* perhaps someday include the continuous color maps from AFNI too.
842 (see pbar.c file, search for colorscale)
843 That day has come Dec 18 07*/
844 SUMA_PBARDEF_ADD("init_bigmaps_6");
845 SUMA_PBARDEF_ADD("init_bigmaps_5");
846 SUMA_PBARDEF_ADD("init_bigmaps_4");
847 SUMA_PBARDEF_ADD("init_bigmaps_3");
848 SUMA_PBARDEF_ADD("init_bigmaps_2");
849 SUMA_PBARDEF_ADD("init_bigmaps_1");
850 SUMA_PBARDEF_ADD("init_bigmaps_0");
851 SUMA_PBARDEF_ADD(R_AND_B_INV_256_CMD); // [PT: Aug 17, 2017]
852 SUMA_PBARDEF_ADD(CB_CS_35);
853 SUMA_PBARDEF_ADD(CB_CS);
854 SUMA_PBARDEF_ADD(CYTOARCH_ROI_256_CMD);
855 SUMA_PBARDEF_ADD(CYTOARCH_ROI_256_GAP_CMD);
856 SUMA_PBARDEF_ADD(FREESURFER_SEG_255_CMD);
857 SUMA_PBARDEF_ADD(GRAY_CS);
858 SUMA_PBARDEF_ADD(GRAY_CIRCLE_CS);
859 SUMA_PBARDEF_ADD(GRAY_INV_CIRCLE_CS);
860 SUMA_PBARDEF_ADD(AMBER_CS);
861 SUMA_PBARDEF_ADD(AMBER_CIRCLE_CS);
862 SUMA_PBARDEF_ADD(AMBER_INV_CIRCLE_CS);
863 SUMA_PBARDEF_ADD(GREEN_CS);
864 SUMA_PBARDEF_ADD(RED_CS);
865 SUMA_PBARDEF_ADD(BLUE_CS);
866 SUMA_PBARDEF_ADD(ROI_32_CMD);
867 SUMA_PBARDEF_ADD(ROI_64_CMD);
868 SUMA_PBARDEF_ADD(ROI_128_CMD);
869 SUMA_PBARDEF_ADD(ROI_256_CMD);
870 SUMA_PBARDEF_ADD(ROI_glasbey_256_CMD); // [PT: May 28, 2019]
871 SUMA_PBARDEF_ADD(ROI_glasbey_512_CMD); // [PT: May 28, 2019]
872 SUMA_PBARDEF_ADD(ROI_glasbey_1024_CMD); // [PT: May 28, 2019]
873 SUMA_PBARDEF_ADD(ROI_glasbey_2048_CMD); // [PT: May 28, 2019]
874 SUMA_PBARDEF_ADD(RedBlueGreen_CMD);
875
876 /* now wrap it up */
877 SAC = (SUMA_AFNI_COLORS *) SUMA_calloc(1,sizeof(SUMA_AFNI_COLORS));
878 SAC->CMv = CMv;
879 SAC->N_maps = N_maps;
880 SAC->Cv = Cv;
881 SAC->N_cols = N_cols;
882
883 /* load whatever's lurking in the .afnirc files */
884 /* passing NULL for dc (the last parameter) because I
885 am not using the continuous color maps yet */
886 SUMA_LH("Calling Process setup");
887 homeenv = getenv("HOME");
888
889 if (!homeenv) sumarc = SUMA_copy_string(".afnirc");
890 else sumarc = SUMA_append_string (homeenv, "/.afnirc");
891 if (stat(sumarc, &stbuf) != -1) {
892 if (LocalHead)
893 fprintf (SUMA_STDERR,"%s: Loading %s ...\n", FuncName, sumarc);
894 if (SUMA_AFNI_Extract_Colors ( sumarc, SAC ) < 0) {
895 fprintf(SUMA_STDERR,
896 "Error %s: Failed scanning .afnirc for colors and colormaps.\n"
897 "Proceeding ...\n", FuncName);
898 }
899 } else {
900 if (LocalHead) fprintf (SUMA_STDERR,"%s: No rc files found.\n", FuncName);
901 }
902 if (sumarc) SUMA_free(sumarc);
903
904 /* Show me the results: */
905 if (LocalHead_Detail) {
906 SUMA_Show_ColorVec (SAC->Cv, SAC->N_cols, NULL);
907 }
908
909 if (LocalHead_Detail) {
910 SUMA_Show_ColorMapVec (SAC->CMv, SAC->N_maps, NULL, 1);
911 }
912
913 SUMA_LH("Returning");
914
915 SUMA_RETURN(SAC);
916 }
917
918 /*! Load colormaps in directory dname */
SUMA_LoadUserCmapsDir(char * dname,SUMA_AFNI_COLORS * SAC)919 int SUMA_LoadUserCmapsDir( char * dname, SUMA_AFNI_COLORS *SAC)
920 {
921 static char FuncName[]={"SUMA_LoadUserCmapsDir"};
922 THD_string_array * flist , * rlist ;
923 int ir , ll , ii , k_read=0;
924 char * fname , * tname ;
925 float * far ;
926 MRI_IMARR * outar ;
927 MRI_IMAGE * outim , * flim ;
928 char * pat ;
929 SUMA_COLOR_MAP *Cmap=NULL;
930 SUMA_PARSED_NAME * pn=NULL;
931 SUMA_DSET_FORMAT form;
932 SUMA_Boolean LocalHead = NOPE;
933
934 SUMA_ENTRY;
935
936 // fprintf(stderr, "%s\n", FuncName);
937
938
939 /*----- sanity check and initialize -----*/
940
941 if( dname == NULL || strlen(dname) == 0 ) SUMA_RETURN(-1) ;
942 if(!SAC) {
943 SUMA_RETURN(-1) ;
944 }
945 /*----- find all *.cmap files -----*/
946
947 ii = strlen(dname) ;
948 pat = (char *) malloc(sizeof(char)*(ii+18)) ;
949 strcpy(pat,dname) ;
950 if( pat[ii-1] != '/' ) strcat(pat,"/") ;
951 strcat(pat,"*.cmap") ;
952 flist = THD_get_wildcard_filenames( pat ) ;
953 free(pat) ;
954
955 if( flist == NULL || flist->num <= 0 ){
956 DESTROY_SARR(flist) ;
957 SUMA_RETURN(0) ;
958 }
959
960 rlist = THD_extract_regular_files( flist ) ;
961 DESTROY_SARR(flist) ;
962 if( rlist == NULL || rlist->num <= 0 ){
963 DESTROY_SARR(rlist) ;
964 SUMA_RETURN(0) ;
965 }
966
967 for( ir=0 ; ir < rlist->num ; ir++ ){
968 fname = rlist->ar[ir] ; if( fname == NULL ) continue ;
969 SUMA_LHv("Loading %d-%s\n", ir, rlist->ar[ir]);
970
971 /* take a stab at the format */
972 form = SUMA_GuessFormatFromExtension(fname, NULL);
973
974 /* load the baby */
975 Cmap = NULL;
976 switch (form) {
977 case SUMA_1D:
978 Cmap = SUMA_Read_Color_Map_1D (fname);
979 if (Cmap == NULL) {
980 SUMA_S_Err("Could not load colormap.");
981 SUMA_RETURN(-1);
982 }
983 break;
984 case SUMA_ASCII_NIML:
985 case SUMA_BINARY_NIML:
986 case SUMA_NIML:
987 Cmap = SUMA_Read_Color_Map_NIML(fname);
988 break;
989 default:
990 SUMA_S_Err( "Format not recognized.\n"
991 "I won't try to guess.\n"
992 "Do use the proper extension.");
993 break;
994 }
995
996 if (Cmap) {
997 /* remove path from name for pretty purposes */
998 pn = SUMA_ParseFname(Cmap->Name, NULL);
999 SUMA_STRING_REPLACE(Cmap->Name, pn->FileName_NoExt);
1000 SUMA_Free_Parsed_Name(pn); pn = NULL;
1001 SAC->CMv = SUMA_Add_ColorMap (Cmap, SAC->CMv,
1002 &(SAC->N_maps));
1003
1004 ++k_read;
1005 }
1006 }
1007
1008 DESTROY_SARR(rlist) ;
1009
1010 SUMA_RETURN(k_read) ;
1011 }
1012
1013 /*!
1014 \brief creates the colormaps available for SUMA
1015 */
SUMA_Build_Color_maps(void)1016 SUMA_AFNI_COLORS *SUMA_Build_Color_maps(void)
1017 {
1018 static char FuncName[]={"SUMA_Build_Color_maps"};
1019 SUMA_RGB_NAME *Cv = NULL;
1020 int i;
1021 SUMA_COLOR_MAP **CMv=NULL;
1022 SUMA_COLOR_MAP *CM=NULL;
1023 SUMA_AFNI_COLORS *SAC=NULL;
1024 char *name;
1025 SUMA_ENTRY;
1026
1027 // fprintf(stderr, "%s\n", FuncName);
1028
1029 SAC = SUMA_Get_AFNI_Default_Color_Maps();
1030
1031 /* Now add SUMA's colormaps */
1032 i = 0;
1033 name = SUMA_COLOR_MAP_NAMES[0];
1034 while (name[0]) {
1035 CM = SUMA_MakeStandardMap (name);
1036 if (!CM) {
1037 SUMA_SL_Crit("Failed to create standard maps");
1038 SUMA_RETURN(NULL);
1039 }
1040 SAC->CMv = SUMA_Add_ColorMap (CM, SAC->CMv, &(SAC->N_maps));
1041 if (!SAC->CMv) {
1042 SUMA_SL_Crit("Failed in SUMA_Add_ColorMap");
1043 SUMA_RETURN(NULL);
1044 }
1045 ++i;
1046 name = SUMA_COLOR_MAP_NAMES[i];
1047 }
1048
1049 /* load cmaps from user's directory */
1050 if ((name = getenv("SUMA_CmapsDir")) && strcmp(name,"None")) {
1051 if (SUMA_LoadUserCmapsDir( name, SAC) < 0) {
1052 SUMA_S_Warn("Failed reading user colormaps\n");
1053 }
1054 }
1055
1056 /* load cmaps from current directory */
1057 if (SUMA_LoadUserCmapsDir( "./", SAC) < 0) {
1058 SUMA_S_Warn("Failed reading user colormaps\n");
1059 }
1060
1061 SUMA_RETURN(SAC);
1062 }
1063
1064
1065 /*! \brief A function to add a new color to the color vector
1066
1067 \param Name (char *) name of new color to be added
1068 \param r (float) r color ( 0 <= r <= 1)
1069 \param g (float) g color ( 0 <= g <= 1)
1070 \param b (float) b color ( 0 <= b <= 1)
1071 \param a (float) a color ( 0 <= a <= 1)
1072 - You are allowed to pass -1.0, -1.0, -1.0 for r g b to define the No-Color
1073 \param oCv (SUMA_RGB_NAME*) old vector containing color structs
1074 \param N_cols (int *) number of colors in oCv
1075 When the function returns, this number will include the added
1076 color
1077 \return NewCv (SUMA_RGB_NAME *) you know what.
1078 If the color being added exists (by Name), it will replace
1079 the preexisting one
1080 - New space is allocated for each new color (realloc).
1081 - This process is not terribly efficient by not many colors
1082 are loaded in this manner.
1083 - You can send NULL for oCv if this vector has yet to be created
1084
1085 */
SUMA_Add_Color(char * Name,float r,float g,float b,float a,SUMA_RGB_NAME * oCv,int * N_cols)1086 SUMA_RGB_NAME * SUMA_Add_Color (char *Name, float r, float g, float b, float a, SUMA_RGB_NAME *oCv, int *N_cols)
1087 {
1088 static char FuncName[]={"SUMA_Add_Color"};
1089 SUMA_RGB_NAME *NewCv = NULL;
1090 int iadd;
1091 SUMA_Boolean LocalHead = NOPE;
1092
1093 SUMA_ENTRY;
1094
1095 // fprintf(stderr, "%s\n", FuncName);
1096
1097 if (!(r == -1.0 && g == -1.0 && b == -1.0)) {
1098 if ( r < 0 || r > 1 ||
1099 g < 0 || g > 1 ||
1100 b < 0 || b > 1 ||
1101 a < 0 || a > 1 ) {
1102 SUMA_S_Err("Bad r, g, b and/or a values.\nMust be between 0 and 1.Nothing done.");
1103 SUMA_RETURN(oCv);
1104 }
1105 }else {
1106 SUMA_LH("No color");
1107 }
1108
1109 if (strlen(Name) > SUMA_MAX_COLOR_NAME -1 ) {
1110 SUMA_S_Err("Too long a color name\n(> SUMA_MAX_COLOR_NAME)\nNothing done.");
1111 SUMA_RETURN(oCv);
1112 }
1113
1114 if (!oCv) {
1115 SUMA_LH("New color vector, allocating");
1116 NewCv = (SUMA_RGB_NAME *) SUMA_calloc(1, sizeof(SUMA_RGB_NAME));
1117 *N_cols = 1;
1118 NewCv[*N_cols-1].r = r;
1119 NewCv[*N_cols-1].g = g;
1120 NewCv[*N_cols-1].b = b;
1121 NewCv[*N_cols-1].a = a;
1122 sprintf(NewCv[*N_cols-1].Name, "%s", Name);
1123 SUMA_RETURN(NewCv);
1124 }
1125
1126 /* not new, check to see if color exists already */
1127 iadd = SUMA_Find_Color (Name, oCv, *N_cols);
1128
1129 if (iadd >= 0) {
1130 SUMA_LH("Replacing old color");
1131 NewCv = oCv;
1132 NewCv[iadd].r = r;
1133 NewCv[iadd].g = g;
1134 NewCv[iadd].b = b;
1135 NewCv[iadd].a = a;
1136 SUMA_RETURN(oCv);
1137 }
1138
1139 /* a new map altogether */
1140 SUMA_LH("Adding new color");
1141 *N_cols += 1;
1142 NewCv = (SUMA_RGB_NAME *) SUMA_realloc(oCv, *N_cols * sizeof(SUMA_RGB_NAME));
1143 NewCv[*N_cols-1].r = r;
1144 NewCv[*N_cols-1].g = g;
1145 NewCv[*N_cols-1].b = b;
1146 NewCv[*N_cols-1].a = a;
1147 sprintf(NewCv[*N_cols-1].Name, "%s", Name);
1148
1149 SUMA_RETURN(NewCv);
1150 }
1151
1152 /*! \brief A function to add a new colormap to the colormap vector
1153
1154 \param CM (SUMA_COLOR_MAP *) new color map to be added
1155 \param OldCMv (SUMA_COLOR_MAP **) old vector containing pointers to colormaps
1156 \param N_map (int *) number of maps in OldCMv
1157 When the function returns, this number will include the added
1158 map
1159 \return NewCMv (SUMA_COLOR_MAP **) you know what.
1160 If the map being added exists (by Name), it will replace
1161 the preexisting one
1162 - New space is allocated for each new map (realloc).
1163 - This process is not terribly efficient by not many maps
1164 are loaded in this manner.
1165 - You can send NULL for OldCMv if this vector has yet to be created
1166 - Color map structure is copied by reference. Do not free it.
1167
1168 */
SUMA_Add_ColorMap(SUMA_COLOR_MAP * CM,SUMA_COLOR_MAP ** OldCMv,int * N_maps)1169 SUMA_COLOR_MAP ** SUMA_Add_ColorMap (SUMA_COLOR_MAP *CM,
1170 SUMA_COLOR_MAP **OldCMv, int *N_maps)
1171 {
1172 static char FuncName[]={"SUMA_Add_ColorMap"};
1173 SUMA_COLOR_MAP ** NewCMv = NULL;
1174 int iadd;
1175 SUMA_Boolean LocalHead = NOPE;
1176
1177 SUMA_ENTRY;
1178
1179 // fprintf(stderr, "%s\n", FuncName);
1180
1181 if (!CM) {
1182 SUMA_S_Warn("Null CM, nothing to do");
1183 SUMA_RETURN(OldCMv);
1184 }
1185 if (!OldCMv) {
1186 SUMA_LH("New color vector, allocating");
1187 NewCMv = (SUMA_COLOR_MAP **) SUMA_calloc(1, sizeof(SUMA_COLOR_MAP *));
1188 *N_maps = 1;
1189 NewCMv[0] = CM;
1190 SUMA_RETURN(NewCMv);
1191 }
1192
1193 /* not new, check to see if map exists already */
1194 iadd = SUMA_Find_ColorMap (CM->Name, OldCMv, *N_maps, CM->Sgn);
1195 if (iadd >= 0) {
1196 SUMA_LH("Replacing old colormap");
1197 SUMA_Free_ColorMap (OldCMv[iadd]);
1198 OldCMv[iadd] = CM;
1199 SUMA_RETURN(OldCMv);
1200 }
1201
1202 /* a new map altogether */
1203 SUMA_LH("Adding new color map");
1204 *N_maps += 1;
1205 NewCMv = (SUMA_COLOR_MAP **) SUMA_realloc( OldCMv, *N_maps *
1206 sizeof(SUMA_COLOR_MAP *));
1207 NewCMv[*N_maps - 1] = CM;
1208
1209 SUMA_RETURN(NewCMv);
1210 }
1211
1212 /*!
1213 \brief Cleans up and destroys the contents of the SUMA_AFNI_COLORS
1214 \sa SUMA_Get_AFNI_Default_Color_Maps
1215 */
SUMA_DestroyAfniColors(SUMA_AFNI_COLORS * SAC)1216 SUMA_AFNI_COLORS *SUMA_DestroyAfniColors (SUMA_AFNI_COLORS *SAC)
1217 {
1218 static char FuncName[]={"SUMA_DestroyAfniColors"};
1219 int i;
1220
1221 SUMA_ENTRY;
1222
1223 // fprintf(stderr, "%s\n", FuncName);
1224
1225 if (!SAC) SUMA_RETURN(NULL);
1226
1227 /* Now clean the colormap vector */
1228 for (i=0; i < SAC->N_maps; ++i) {
1229 if (SAC->CMv[i]) SUMA_Free_ColorMap(SAC->CMv[i]);
1230 }
1231 SUMA_free(SAC->CMv);
1232 SAC->N_maps = -1;
1233
1234 /* Now clean the color vector */
1235 SUMA_free(SAC->Cv);
1236 SAC->N_cols = -1;
1237
1238 /* Now destroy SAC */
1239 SUMA_free(SAC);
1240
1241 SUMA_RETURN(NULL);
1242 }
1243
1244 /*!
1245 \brief List the colors in the vector
1246 \sa char *SUMA_Show_ColorVec
1247 */
SUMA_ColorVec_Info(SUMA_RGB_NAME * Cv,int N_cols)1248 char *SUMA_ColorVec_Info (SUMA_RGB_NAME *Cv, int N_cols)
1249 {
1250 static char FuncName[]={"SUMA_ColorVec_Info"};
1251 int i;
1252 char stmp[100], *s = NULL;
1253 SUMA_STRING *SS = NULL;
1254 SUMA_Boolean LocalHead = NOPE;
1255
1256 SUMA_ENTRY;
1257
1258 // fprintf(stderr, "%s\n", FuncName);
1259
1260 SS = SUMA_StringAppend (NULL, NULL);
1261
1262 if (Cv) {
1263 for (i=0; i < N_cols; ++i) {
1264 if (Cv[i].r == -1) {
1265 sprintf (stmp, "%d/%d: color(%d) No Color(%s): [%f %f %f %f]\n",
1266 i+1, N_cols, i,
1267 Cv[i].Name, Cv[i].r, Cv[i].g, Cv[i].b, Cv[i].a);
1268 SS = SUMA_StringAppend (SS, stmp);
1269 } else {
1270 sprintf (stmp, "%d/%d: color(%d) %s: [%f %f %f %f]\n",
1271 i+1, N_cols, i,
1272 Cv[i].Name, Cv[i].r, Cv[i].g, Cv[i].b, Cv[i].a);
1273 SS = SUMA_StringAppend (SS, stmp);
1274 }
1275 }
1276 } else {
1277 sprintf (stmp, "NULL Cv.\n");
1278 SS = SUMA_StringAppend (SS, stmp);
1279 }
1280
1281 /* clean SS */
1282 SS = SUMA_StringAppend (SS, NULL);
1283 /* copy s pointer and free SS */
1284 s = SS->s;
1285 SUMA_free(SS);
1286
1287 SUMA_RETURN(s);
1288 }
1289
1290 /*!
1291 return a color in acol (4 floats) from colormap name color index i % Ncolors
1292 if name is NULL a random color is returned
1293 */
1294
SUMA_a_good_col(char * name,int i,float * acol)1295 int SUMA_a_good_col(char *name, int i, float *acol)
1296 {
1297 static char FuncName[]={"SUMA_a_good_col"};
1298 int ic, icmap=-1, dorand;
1299 SUMA_COLOR_MAP *CM;
1300
1301 SUMA_ENTRY;
1302
1303 // fprintf(stderr, "%s\n", FuncName);
1304
1305 dorand = 0;
1306 if (i<0 || !acol) {
1307 SUMA_S_Err("Give me a break!");
1308 SUMA_RETURN(0);
1309 }
1310
1311 if (name && !(SUMAg_CF && SUMAg_CF->scm && SUMAg_CF->scm->CMv &&
1312 SUMAg_CF->scm->N_maps)) {
1313 /* try building colormaps */
1314 if (!SUMAg_CF->scm) SUMAg_CF->scm = SUMA_Build_Color_maps();
1315 }
1316
1317 if (!name || !(SUMAg_CF && SUMAg_CF->scm && SUMAg_CF->scm->CMv &&
1318 SUMAg_CF->scm->N_maps)) {
1319 dorand = 1;
1320 } else {
1321 /* have colormaps, get me something decent */
1322 icmap = SUMA_Find_ColorMap(name, SUMAg_CF->scm->CMv,
1323 SUMAg_CF->scm->N_maps,-2);
1324 if (icmap < 0) {
1325 int d;
1326 char *endp;
1327 /* try again, maybe we just have an maximum number */
1328 d = (int)strtod(name, &endp);
1329 if (endp == name && d == 0) { /* no good */
1330 } else {
1331 if (d < 32) {
1332 icmap = SUMA_Find_ColorMap("ROI_i32", SUMAg_CF->scm->CMv,
1333 SUMAg_CF->scm->N_maps,-2);
1334 }else if (d < 64) {
1335 icmap = SUMA_Find_ColorMap("ROI_i64", SUMAg_CF->scm->CMv,
1336 SUMAg_CF->scm->N_maps,-2);
1337 }else if (d < 128) {
1338 icmap = SUMA_Find_ColorMap("ROI_i128", SUMAg_CF->scm->CMv,
1339 SUMAg_CF->scm->N_maps,-2);
1340 }else if (d < 256) {
1341 icmap = SUMA_Find_ColorMap("ROI_i256", SUMAg_CF->scm->CMv,
1342 SUMAg_CF->scm->N_maps,-2);
1343 }
1344 }
1345 }
1346
1347 }
1348
1349 if (name && icmap < 0) {
1350 SUMA_S_Warnv("No colormap named %s was found, "
1351 "returning random colors.\n", name);
1352 dorand = 1;
1353 }
1354
1355 if (dorand) {
1356 /* GIMME SOME RANDOM */
1357 SUMA_RAND_COL(i, acol[0], acol[1], acol[2], acol[3]);
1358 acol[3] = 1.0;
1359 SUMA_RETURN(1);
1360 } else {
1361 CM = SUMAg_CF->scm->CMv[icmap];
1362 ic = i % CM->N_M[0];
1363 acol[0] = CM->M[ic][0];
1364 acol[1] = CM->M[ic][1];
1365 acol[2] = CM->M[ic][2];
1366 if (CM->N_M[1]==4) acol[3] = CM->M[ic][3];
1367 else acol[3] = 1.0;
1368 }
1369
1370 SUMA_RETURN(1);
1371 }
1372
1373 /*!
1374 \brief List the colormaps in the vector
1375
1376 \param CMv (SUMA_COLOR_MAP **) an array of pointers to colormap structures
1377 \param N_maps (int) the number of colormaps in CMv
1378 \param detail (int) 0, just the name of the colormaps
1379 1, up to 5 of the colors listed
1380 2, complete colormap listed
1381
1382 \sa char *SUMA_Show_ColorMapVec
1383
1384 */
SUMA_ColorMapVec_Info(SUMA_COLOR_MAP ** CMv,int N_maps,int detail)1385 char *SUMA_ColorMapVec_Info (SUMA_COLOR_MAP **CMv, int N_maps, int detail)
1386 {
1387 static char FuncName[]={"SUMA_ColorMapVec_Info"};
1388 int i, j, jmax;
1389 char stmp[256], *s = NULL;
1390 SUMA_STRING *SS = NULL;
1391 SUMA_Boolean LocalHead = NOPE;
1392
1393 SUMA_ENTRY;
1394
1395 // fprintf(stderr, "%s\n", FuncName);
1396
1397 SUMA_LH("Entered");
1398 SS = SUMA_StringAppend (NULL, NULL);
1399
1400 if (CMv) {
1401 for (i=0; i < N_maps; ++i) {
1402 if (!CMv[i]) {
1403 sprintf (stmp, "%d/%d: cmap(%d) NULL\n", i+1, N_maps, i);
1404 SS = SUMA_StringAppend (SS, stmp);
1405 } else {
1406 switch (CMv[i]->Sgn) {
1407 case 0:
1408 sprintf (stmp, "%d/%d: cmap(%d) %s(.), %d (%d)cols.",
1409 i+1, N_maps, i, CMv[i]->Name,
1410 CMv[i]->N_M[0], CMv[i]->N_M[1]);
1411 break;
1412 case 1:
1413 sprintf (stmp, "%d/%d: cmap(%d) %s(+), %d (%d)cols.",
1414 i+1, N_maps, i, CMv[i]->Name,
1415 CMv[i]->N_M[0], CMv[i]->N_M[1]);
1416 break;
1417 case -1:
1418 sprintf (stmp, "%d/%d: cmap(%d) %s(-), %d (%d)cols.",
1419 i+1, N_maps, i, CMv[i]->Name,
1420 CMv[i]->N_M[0], CMv[i]->N_M[1]);
1421 break;
1422 default:
1423 sprintf (stmp,
1424 "%d/%d: cmap(%d) %s(?), %d (%d)cols.\n"
1425 "\tSgn field of colormap is not acceptable (%d)\n",
1426 i+1, N_maps, i, CMv[i]->Name,
1427 CMv[i]->N_M[0], CMv[i]->N_M[1], CMv[i]->Sgn);
1428 break;
1429 }
1430 SS = SUMA_StringAppend (SS, stmp);
1431 if (CMv[i]->frac) {
1432 SS = SUMA_StringAppend (SS, " Possibly non-linear.");
1433 } else {
1434 SS = SUMA_StringAppend (SS, " Linear.");
1435 }
1436 if (CMv[i]->idvec) {
1437 SS = SUMA_StringAppend (SS, " Has idvec.");
1438 } else {
1439 SS = SUMA_StringAppend (SS, " NULL idvec.");
1440 }
1441 if (CMv[i]->chd) {
1442 SS = SUMA_StringAppend (SS, " Has chd.");
1443 } else {
1444 SS = SUMA_StringAppend (SS, " NULL chd.");
1445 }
1446
1447 SS = SUMA_StringAppend (SS, "\n");
1448 switch (detail) {
1449 case 0:
1450 jmax = 0;
1451 break;
1452 case 1:
1453 if (CMv[i]->N_M[0] < 5) jmax = CMv[i]->N_M[0];
1454 else jmax = 5;
1455 break;
1456 case 2:
1457 jmax = CMv[i]->N_M[0];
1458 break;
1459 default:
1460 SUMA_SL_Err("Bad detail value\nUsing detail = 2");
1461 jmax = CMv[i]->N_M[0];
1462 break;
1463 }
1464
1465 if (jmax) {
1466 for (j=jmax-1; j >= 0; --j) {
1467 if (CMv[i]->frac) {
1468 if (j == jmax -1) {
1469 if (CMv[i]->N_M[1] == 3)
1470 sprintf (stmp,
1471 "rank (i):\tid\t"
1472 "[R \tG \tB \t\tf]\tName\n");
1473 else
1474 sprintf (stmp,
1475 "rank (i):\tid\t"
1476 "[R \tG \tB \tA\t\tf]\tName\n");
1477 SS = SUMA_StringAppend (SS,stmp);
1478 }
1479 if (CMv[i]->N_M[1] == 4)
1480 sprintf (stmp,
1481 "%03d:\t%6d\t [% .3f\t% .3f\t% .3f\t% .3f\t\t% .3f]\t%s\n",
1482 j, CMv[i]->idvec ? CMv[i]->idvec[j] : -1,
1483 CMv[i]->M[j][0], CMv[i]->M[j][1],
1484 CMv[i]->M[j][2], CMv[i]->M[j][3],
1485 CMv[i]->frac[j],
1486 CMv[i]->cname ? CMv[i]->cname[j] : "anonimo");
1487 else
1488 sprintf (stmp,
1489 "%03d:\t%6d\t [% .3f\t% .3f\t% .3f\t\t% .3f]\t%s\n",
1490 j, CMv[i]->idvec ? CMv[i]->idvec[j] : -1,
1491 CMv[i]->M[j][0], CMv[i]->M[j][1],
1492 CMv[i]->M[j][2], CMv[i]->frac[j],
1493 CMv[i]->cname ? CMv[i]->cname[j] : "anonimo");
1494 } else {
1495 if (j == jmax - 1) {
1496 if (CMv[i]->N_M[1] == 3)
1497 sprintf (stmp,
1498 "rank (i):\tid\t[R \tG \tB ]\n");
1499 else
1500 sprintf (stmp,
1501 "rank (i):\tid\t"
1502 "[R \tG \tB \tA ]\n");
1503 SS = SUMA_StringAppend (SS,stmp);
1504 }
1505 if (CMv[i]->N_M[1] == 4)
1506 sprintf (stmp,
1507 "%03d:\t%6d\t [% .3f\t% .3f\t% .3f\t% .3f]\t%s\n",
1508 j, CMv[i]->idvec ? CMv[i]->idvec[j] : -1,
1509 CMv[i]->M[j][0], CMv[i]->M[j][1],
1510 CMv[i]->M[j][2], CMv[i]->M[j][3],
1511 CMv[i]->cname ? CMv[i]->cname[j] : "anonimo");
1512 else
1513 sprintf (stmp,
1514 "%03d:\t%6d\t [% .3f\t% .3f\t% .3f]\t%s\n",
1515 j, CMv[i]->idvec ? CMv[i]->idvec[j] : -1,
1516 CMv[i]->M[j][0], CMv[i]->M[j][1],
1517 CMv[i]->M[j][2],
1518 CMv[i]->cname ? CMv[i]->cname[j] : "anonimo");
1519 }
1520 SS = SUMA_StringAppend (SS,stmp);
1521 }
1522 if (jmax < CMv[i]->N_M[0] - 1) {
1523 if (CMv[i]->frac)
1524 SS = SUMA_StringAppend (SS,
1525 "..:\t [.....\t....\t....\t\t....]\n");
1526 else SS = SUMA_StringAppend (SS,"..:\t [.....\t....\t....]\n");
1527 }
1528 if (jmax < CMv[i]->N_M[0]) {
1529 j = CMv[i]->N_M[0] - 1;
1530 if (CMv[i]->frac) {
1531 if (CMv[i]->N_M[1] == 4)
1532 sprintf (stmp,
1533 "%03d:\t%6d\t [% .3f\t% .3f\t% .3f\t\t% .3f\t\t% .3f]%s\n",
1534 j, CMv[i]->idvec ? CMv[i]->idvec[j] : -1,
1535 CMv[i]->M[j][0], CMv[i]->M[j][1],
1536 CMv[i]->M[j][2], CMv[i]->M[j][3], CMv[i]->frac[j],
1537 CMv[i]->cname ? CMv[i]->cname[j] : "anonimo");
1538 else
1539 sprintf (stmp,
1540 "%03d:\t%6d\t [% .3f\t% .3f\t% .3f\t\t% .3f]\t%s\n",
1541 j, CMv[i]->idvec ? CMv[i]->idvec[j] : -1,
1542 CMv[i]->M[j][0], CMv[i]->M[j][1],
1543 CMv[i]->M[j][2], CMv[i]->frac[j],
1544 CMv[i]->cname ? CMv[i]->cname[j] : "anonimo");
1545 } else {
1546 if (CMv[i]->N_M[1] == 4)
1547 sprintf (stmp,
1548 "%03d:\t%6d\t [% .3f\t% .3f\t% .3f\t% .3f]\t%s\n",
1549 j, CMv[i]->idvec ? CMv[i]->idvec[j] : -1,
1550 CMv[i]->M[j][0], CMv[i]->M[j][1],
1551 CMv[i]->M[j][2], CMv[i]->M[j][3],
1552 CMv[i]->cname ? CMv[i]->cname[j] : "anonimo");
1553 else
1554 sprintf (stmp,
1555 "%03d:\t%6d\t [% .3f\t% .3f\t% .3f]\t%s\n",
1556 j, CMv[i]->idvec ? CMv[i]->idvec[j] : -1,
1557 CMv[i]->M[j][0], CMv[i]->M[j][1],
1558 CMv[i]->M[j][2],
1559 CMv[i]->cname ? CMv[i]->cname[j] : "anonimo");
1560 }
1561 SS = SUMA_StringAppend (SS,stmp);
1562 }
1563 }
1564 }
1565 }
1566 } else {
1567 sprintf (stmp, "NULL CMv.\n");
1568 SS = SUMA_StringAppend (SS, stmp);
1569 }
1570
1571 /* clean SS */
1572 SS = SUMA_StringAppend (SS, NULL);
1573 /* copy s pointer and free SS */
1574 s = SS->s;
1575 SUMA_free(SS);
1576
1577 SUMA_LH("Left");
1578
1579 SUMA_RETURN(s);
1580 }
1581
1582 /*!
1583 \brief Shows the contents of the color vector
1584 \sa SUMA_ColorVec_Info
1585 */
SUMA_Show_ColorVec(SUMA_RGB_NAME * CMv,int N_maps,FILE * Out)1586 void SUMA_Show_ColorVec (SUMA_RGB_NAME *CMv, int N_maps, FILE *Out)
1587 {
1588 static char FuncName[]={"SUMA_Show_ColorVec"};
1589 char *s;
1590
1591 SUMA_ENTRY;
1592
1593 // fprintf(stderr, "%s\n", FuncName);
1594
1595 if (Out == NULL) Out = stdout;
1596
1597 s = SUMA_ColorVec_Info(CMv, N_maps);
1598
1599 if (s) {
1600 fprintf (Out, "%s", s);
1601 SUMA_free(s);
1602 }else {
1603 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_ColorVec_Info.\n", FuncName);
1604 }
1605
1606 SUMA_RETURNe;
1607 }
1608
1609 /*!
1610 \brief Shows the contents of the colormaps vector
1611 \sa SUMA_ColorMapVec_Info
1612 */
SUMA_Show_ColorMapVec(SUMA_COLOR_MAP ** CMv,int N_maps,FILE * Out,int detail)1613 void SUMA_Show_ColorMapVec (SUMA_COLOR_MAP **CMv, int N_maps,
1614 FILE *Out, int detail)
1615 {
1616 static char FuncName[]={"SUMA_Show_ColorMapVec"};
1617 char *s;
1618 SUMA_Boolean LocalHead = NOPE;
1619
1620 SUMA_ENTRY;
1621
1622 // fprintf(stderr, "%s\n", FuncName);
1623
1624
1625 if (Out == NULL) Out = stdout;
1626
1627 s = SUMA_ColorMapVec_Info(CMv, N_maps, detail);
1628
1629 if (s) {
1630 fprintf (Out, "%s", s);
1631 SUMA_free(s);
1632 }else {
1633 fprintf (SUMA_STDERR,
1634 "Error %s: Failed in SUMA_ColorMapVec_Info.\n", FuncName);
1635 }
1636
1637
1638 SUMA_RETURNe;
1639 }
1640
1641 /*!
1642 \brief Locate a color in the color vector
1643 \param Name (char *) Name ('\0' terminated) name of color to be found
1644 \param Cv (SUMA_RGB_NAME *) vector of color structs to be searched
1645 \param N_cols (int) number of colors in Cv
1646 \return icol (int) the index into Cv where the color named Name was found
1647 (-1) if no such color was found
1648 */
SUMA_Find_Color(char * Name,SUMA_RGB_NAME * Cv,int N_cols)1649 int SUMA_Find_Color ( char *Name, SUMA_RGB_NAME *Cv, int N_cols)
1650 {
1651 static char FuncName[]={"SUMA_Find_Color"};
1652 int icol = -1, i;
1653 SUMA_Boolean LocalHead = NOPE;
1654
1655 SUMA_ENTRY;
1656
1657 // fprintf(stderr, "%s\n", FuncName);
1658
1659 if (!Cv) {
1660 SUMA_S_Warn("Nothing to do. NULL Cv");
1661 SUMA_RETURN(icol);
1662 }
1663
1664 for (i=0; i < N_cols; ++i) {
1665 if (strcmp(Cv[i].Name, Name) == 0) {
1666 SUMA_LH("Found Color");
1667 icol = i;
1668 SUMA_RETURN(icol);
1669 }
1670 }
1671
1672 SUMA_LH("Failed to find color");
1673 SUMA_RETURN(icol);
1674 }
1675
1676 /*!
1677 \brief Locate a colormap in the colormap vector
1678 \param Name (char *) Name ('\0' terminated) name of colormap to be found
1679 \param CMv (SUMA_COLOR_MAP **) vector of pointers to colormaps to be searched
1680 \param N_maps (int) number of maps in CMv
1681 \param sgn (int) the sign of the map (-1, 0, +1)
1682 if sign = -2 then the sign is completely ignored and
1683 only Name is used for a match
1684 \return imap (int) the index into CMv where the colormap named Name was found
1685 (-1) if no such map was found
1686 */
SUMA_Find_ColorMap(char * Name,SUMA_COLOR_MAP ** CMv,int N_maps,int sgn)1687 int SUMA_Find_ColorMap ( char *Name, SUMA_COLOR_MAP **CMv, int N_maps, int sgn)
1688 {
1689 static char FuncName[]={"SUMA_Find_ColorMap"};
1690 int imap = -1, i;
1691 SUMA_Boolean LocalHead = NOPE;
1692
1693 SUMA_ENTRY;
1694
1695 // fprintf(stderr, "%s\n", FuncName);
1696
1697 if (!CMv) {
1698 SUMA_S_Warn("Nothing to do. NULL CMv");
1699 SUMA_RETURN(imap);
1700 }
1701
1702
1703 for (i=0; i < N_maps; ++i) {
1704 if (CMv[i]) {
1705 if (sgn != -2) {
1706 if (strcmp(CMv[i]->Name, Name) == 0 && CMv[i]->Sgn == sgn) {
1707 SUMA_LH("Found Map");
1708 imap = i;
1709 SUMA_RETURN(imap);
1710 }
1711 } else {
1712 /* don't care about sign */
1713 if (strcmp(CMv[i]->Name, Name) == 0 ) {
1714 SUMA_LH("Found Map");
1715 imap = i;
1716 SUMA_RETURN(imap);
1717 }
1718 }
1719 }
1720 }
1721
1722 SUMA_LH("Failed to find map");
1723 SUMA_RETURN(imap);
1724 }
1725
SUMA_FindNamedColMap(char * Name)1726 SUMA_COLOR_MAP *SUMA_FindNamedColMap(char *Name)
1727 {
1728 static char FuncName[]={"SUMA_FindNamedColMap"};
1729 int imap;
1730 SUMA_COLOR_MAP *CM = NULL;
1731
1732 SUMA_ENTRY;
1733
1734 // fprintf(stderr, "%s\n", FuncName);
1735
1736 if (!SUMAg_CF->scm) SUMAg_CF->scm = SUMA_Build_Color_maps();
1737 if (!SUMAg_CF->scm || !SUMAg_CF->scm->CMv) SUMA_RETURN(NULL);
1738 if ((imap = SUMA_Find_ColorMap(Name, SUMAg_CF->scm->CMv,
1739 SUMAg_CF->scm->N_maps, -2)) >= 0) {
1740 SUMA_RETURN(SUMAg_CF->scm->CMv[imap]);
1741 } else SUMA_RETURN(NULL);
1742 }
1743
SUMA_FindCodedColMap(int imap)1744 SUMA_COLOR_MAP *SUMA_FindCodedColMap(int imap)
1745 {
1746 static char FuncName[]={"SUMA_FindCodedColMap"};
1747 SUMA_COLOR_MAP *CM = NULL;
1748
1749 SUMA_ENTRY;
1750
1751 // fprintf(stderr, "%s\n", FuncName);
1752
1753 if (!SUMAg_CF->scm || !SUMAg_CF->scm->CMv) SUMA_RETURN(NULL);
1754 if (imap < 0 || imap > SUMAg_CF->scm->N_maps-1) SUMA_RETURN(NULL);
1755 SUMA_RETURN(SUMAg_CF->scm->CMv[imap]);
1756 }
1757 /*!
1758 function that reads in a 1D format color map file
1759 1D format contains 3 or 4 columns:
1760 3 columns: R G B
1761 4 columns: R G B frac
1762 R G B are float values between 0 and 1.0 specifying the R G B colors
1763 frac is the fraction of the color map assigned to each color. These
1764 are the same numbers shown to the right of the colormap in AFNI
1765 Sept 22 04: you can specify integer values between 0 and 255 for
1766 the RGB values if you wish
1767
1768 The colormap files are specified in the order adopted in AFNI's palette files
1769 The last row in the file is the first color (bottom color) in the map.
1770 If you specify frac then the lowest fraction must be at the bottom row
1771 */
SUMA_Read_Color_Map_1D(char * Name)1772 SUMA_COLOR_MAP *SUMA_Read_Color_Map_1D (char *Name)
1773 {
1774 static char FuncName[]={"SUMA_Read_Color_Map_1D"};
1775 MRI_IMAGE *im = NULL;
1776 float *far=NULL;
1777 float ColSum;
1778 int i=0, iwarn=0;
1779 SUMA_COLOR_MAP* SM = NULL;
1780
1781 SUMA_Boolean LocalHead = NOPE;
1782
1783 SUMA_ENTRY;
1784
1785 // fprintf(stderr, "%s\n", FuncName);
1786
1787 if (!Name) {
1788 SUMA_S_Err("NULL file name");
1789 SUMA_RETURN(SM);
1790 }
1791
1792 /* read the colormap 1D file */
1793 im = mri_read_1D (Name);
1794 if (!im) {
1795 SUMA_S_Err("Failed to read file");
1796 SUMA_RETURN(NULL);
1797 }
1798
1799 /* check for sizes */
1800 if (im->ny != 3 && im->ny != 4 && im->ny != 5) {
1801 SUMA_S_Errv("Colormap file %s must contain 3, 4, or 5 columns only.\n",
1802 Name);
1803 SUMA_RETURN(NULL);
1804
1805 }
1806
1807
1808 /* allocate for SM */
1809 SM = (SUMA_COLOR_MAP*) SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
1810 SM->idvec = NULL;
1811 SM->chd = NULL;
1812 SM->top_frac = 0.0f;
1813 SM->SO = NULL;
1814 SM->cname = NULL;
1815 SM->N_M[0] = im->nx;
1816 SM->N_M[1] = 4;
1817 SM->Name = (char *)SUMA_calloc((strlen(Name)+1),sizeof(char));
1818 sprintf(SM->Name, "%s", Name);
1819 if (im->ny == 4) {
1820 SM->frac = (float*) SUMA_calloc(im->nx, sizeof(float));
1821 } else {
1822 SM->frac = NULL;
1823 }
1824
1825 SM->M = (float**)SUMA_allocate2D (SM->N_M[0], 4, sizeof(float));
1826
1827
1828 far = MRI_FLOAT_PTR(im);
1829
1830 ColSum = 0;
1831 if (im->ny == 5) { /* assume it is the freesurfer colormap */
1832 /* if need be, can check that 1st column is a monotonically
1833 increasing index 0 ... Ncol -1 ...
1834 Last column is a key
1835 You encounter these colormaps in the SUMA/ directory
1836 They are created by @SUMA_Make_Spec_FS and get stuck inside
1837 annotation files. It does not hurt to load them here though.
1838 For now, just take colors */
1839 SM->Sgn = 1;
1840 for (i=0; i < im->nx; ++i) {
1841 if (!iwarn && SUMA_ABS(far[i]-(int)far[i])>SUMA_EPSILON) {
1842 SUMA_S_Warnv("Colormap %s does not appear to be a 1D version"
1843 "of a freesurfer colormap.\n"
1844 "Assuming format to be:\n"
1845 " icol r g b key \n"
1846 "Data line %d is:\n"
1847 " %f %f %f %f %f\n",
1848 Name, i, far[i], far[i+im->nx], far[i+2*im->nx],
1849 far[i+3*im->nx],far[i+4*im->nx]);
1850 ++iwarn;
1851 }
1852 SM->M[SM->N_M[0] - i - 1][0] = far[i+im->nx];
1853 ColSum += far[i];
1854 SM->M[SM->N_M[0] - i - 1][1] = far[i+2*im->nx];
1855 ColSum += far[i+im->nx];
1856 SM->M[SM->N_M[0] - i - 1][2] = far[i+3*im->nx];
1857 ColSum += far[i+2*im->nx];
1858 SM->M[SM->N_M[0] - i - 1][3] = 1.0;
1859 }
1860 } else if (im->ny == 4) {
1861 SM->Sgn = 1;
1862 for (i=0; i < im->nx; ++i) {
1863 SM->M[SM->N_M[0] - i - 1][0] = far[i];
1864 ColSum += far[i];
1865 SM->M[SM->N_M[0] - i - 1][1] = far[i+im->nx];
1866 ColSum += far[i+im->nx];
1867 SM->M[SM->N_M[0] - i - 1][2] = far[i+2*im->nx];
1868 ColSum += far[i+2*im->nx];
1869 SM->M[SM->N_M[0] - i - 1][3] = 1.0;
1870 SM->frac[SM->N_M[0] - i - 1] = far[i+3*im->nx];
1871 if (SM->frac[SM->N_M[0] - i - 1] < 0.0) SM->Sgn = -1;
1872 }
1873 } else {
1874 SM->Sgn = 0;
1875 for (i=0; i < im->nx; ++i) {
1876 SM->M[SM->N_M[0] - i - 1][0] = far[i];
1877 ColSum += far[i];
1878 SM->M[SM->N_M[0] - i - 1][1] = far[i+im->nx];
1879 ColSum += far[i+im->nx];
1880 SM->M[SM->N_M[0] - i - 1][2] = far[i+2*im->nx];
1881 ColSum += far[i+2*im->nx];
1882 SM->M[SM->N_M[0] - i - 1][3] = 1.0;
1883 }
1884 }
1885
1886 ColSum = ColSum / (3.0 * SM->N_M[0]);
1887 if (ColSum > 1) {
1888 /* looks like colormap values are between 0 and 255 */
1889 for (i=0; i < SM->N_M[0]; ++i) {
1890 SM->M[i][0] /= 255.0; SM->M[i][1] /= 255.0; SM->M[i][2] /= 255.0;
1891 }
1892 }
1893
1894 /* check on craziness in frac */
1895 if (SM->frac && SM->N_M[0] > 1) {
1896 for (i=0; i < im->nx-1; ++i) {
1897 if (SM->frac[i] > SM->frac[i+1]) {
1898 SUMA_S_Err( "Fractions must be specified in monotonic\n"
1899 " descending order from the top to the bottom of the column");
1900 SUMA_Free_ColorMap (SM); mri_free(im);
1901 SUMA_RETURN(NULL);
1902 }
1903 }
1904 }
1905
1906 mri_free(im); im = NULL;
1907
1908 if (LocalHead) {
1909 fprintf (SUMA_STDERR,"%s: Colormap read:\n", FuncName);
1910 if (SM->frac) {
1911 for (i=0; i < SM->N_M[0]; ++i) {
1912 fprintf (SUMA_STDOUT,"%f\t%f\t%f\t%f\t%f\n",
1913 SM->M[i][0], SM->M[i][1], SM->M[i][2], SM->M[i][3], SM->frac[i]);
1914 }
1915 } else SUMA_disp_mat (SM->M, SM->N_M[0], SM->N_M[1], 1);
1916 }
1917
1918 SM->M0[0] = SM->M[0][0];
1919 SM->M0[1] = SM->M[0][1];
1920 SM->M0[2] = SM->M[0][2];
1921 SM->M0[3] = SM->M[0][3];
1922
1923 SUMA_RETURN (SM);
1924 }
1925
1926
SUMA_Read_Color_Map_NIML(char * Name)1927 SUMA_COLOR_MAP *SUMA_Read_Color_Map_NIML (char *Name)
1928 {
1929 static char FuncName[]={"SUMA_Read_Color_Map_NIML"};
1930 SUMA_COLOR_MAP* SM = NULL;
1931 char *FullName = NULL, *niname = NULL;
1932 NI_stream ns = NULL;
1933 void *nini=NULL;
1934 SUMA_DSET *dset=NULL;
1935 int tt;
1936 SUMA_Boolean iselement = NOPE;
1937 SUMA_Boolean LocalHead = NOPE;
1938
1939 SUMA_ENTRY;
1940
1941 // fprintf(stderr, "%s\n", FuncName);
1942
1943
1944 if (!Name) { SUMA_SL_Err("Null Name"); SUMA_RETURN(SM); }
1945
1946 /* work the name */
1947 if (!SUMA_filexists(Name)) {
1948 /* try the extension game */
1949 FullName = SUMA_Extension(Name, ".niml.cmap", NOPE);
1950 if (!SUMA_filexists(FullName)) {
1951 SUMA_S_Errv("Failed to find cmap file %s or %s", Name, FullName);
1952 if (FullName) SUMA_free(FullName); FullName = NULL;
1953 SUMA_RETURN(SM);
1954 }
1955 }else {
1956 FullName = SUMA_copy_string(Name);
1957 }
1958
1959 /* got the name, now load it */
1960 niname = SUMA_append_string("file:", FullName);
1961
1962 ns = NI_stream_open(niname, "r");
1963 if (!ns) {
1964 SUMA_SL_Crit("Failed to open NI stream for reading.");
1965 if (FullName) SUMA_free(FullName); FullName = NULL;
1966 SUMA_RETURN(SM);
1967 }
1968 SUMA_free(niname); niname = NULL;
1969
1970 nini = NI_read_element(ns, 1) ;
1971 NI_stream_close( ns ) ; ns = NULL;
1972 tt = NI_element_type(nini);
1973
1974 SUMA_LH("Checking on nini type");
1975 /* check if group or element */
1976 if(tt == NI_GROUP_TYPE) {
1977 iselement = NOPE;
1978 SUMA_LH("Dealing with group");
1979 } else if (tt == NI_ELEMENT_TYPE) {
1980 iselement = YUP;
1981 SUMA_S_Err("Bad format");
1982 if (FullName) SUMA_free(FullName); FullName = NULL;
1983 NI_free_element(nini); SUMA_RETURN(SM);
1984 } else {
1985 fprintf(SUMA_STDERR, "Note %s: %s has no element and no group. \n",
1986 FuncName, Name);
1987 NI_free_element(nini); SUMA_RETURN(SM);
1988 if (FullName) SUMA_free(FullName); FullName = NULL;
1989 SUMA_RETURN(NULL);
1990 }
1991
1992
1993 /* change to cmap */
1994 SM = SUMA_NICmapToCmap((NI_group *)nini);
1995
1996 /* frees */
1997 NI_free_element(nini);
1998 if (FullName) SUMA_free(FullName); FullName = NULL;
1999
2000 SUMA_RETURN (SM);
2001 }
2002
SUMA_Write_Color_Map_1D(SUMA_COLOR_MAP * SM,char * Name)2003 SUMA_Boolean SUMA_Write_Color_Map_1D (SUMA_COLOR_MAP* SM, char *Name)
2004 {
2005 static char FuncName[]={"SUMA_Write_Color_Map_1D"};
2006 char *nameout=NULL;
2007 FILE *fout=NULL;
2008 int i, j;
2009
2010 SUMA_Boolean LocalHead = NOPE;
2011
2012 SUMA_ENTRY;
2013
2014 // fprintf(stderr, "%s\n", FuncName);
2015
2016 if (!SM) {
2017 SUMA_S_Err("NULL colmap");
2018 SUMA_RETURN(0);
2019 }
2020
2021 if (SUMA_NeedsLinearizing(SM))
2022 SM = SUMA_Linearize_Color_Map (SM, -1);
2023
2024 if (!Name) Name = SM->Name;
2025 nameout = SUMA_Extension(Name, ".1D.cmap", NOPE);
2026
2027 if (!(fout = fopen(nameout,"w"))) {
2028 SUMA_S_Errv("Failed to open %s for writing\n", nameout);
2029 SUMA_free(nameout);
2030 SUMA_RETURN(NOPE);
2031 }
2032
2033 for (i=SM->N_M[0]-1; i>=0; --i) {
2034 for (j=0; j<3; ++j) {
2035 fprintf(fout,"%.5f ", SM->M[i][j]);
2036 }
2037 fprintf(fout,"\n");
2038 }
2039
2040 SUMA_free(nameout); nameout = NULL;
2041 fclose(fout); fout = NULL;
2042 SUMA_RETURN(YUP);
2043
2044 }
2045
SUMA_Write_Color_Map_NIML(SUMA_COLOR_MAP * SM,char * Name)2046 SUMA_Boolean SUMA_Write_Color_Map_NIML (SUMA_COLOR_MAP* SM, char *Name)
2047 {
2048 static char FuncName[]={"SUMA_Write_Color_Map_NIML"};
2049 char stmp[129];
2050 SUMA_PARSED_NAME *sname=NULL;
2051 NI_group *NIcmap=NULL;
2052 int suc=0;
2053 SUMA_Boolean LocalHead = NOPE;
2054
2055 SUMA_ENTRY;
2056
2057 // fprintf(stderr, "%s\n", FuncName);
2058
2059 if (!SM) {
2060 SUMA_S_Err("NULL colmap");
2061 SUMA_RETURN(0);
2062 }
2063
2064 if (SUMA_NeedsLinearizing(SM))
2065 SM = SUMA_Linearize_Color_Map (SM, -1);
2066
2067 NIcmap = SUMA_CmapToNICmap (SM);
2068
2069 if (!Name) Name = SM->Name;
2070 sname = SUMA_ParseFname(Name, NULL);
2071 snprintf(stmp, 128*sizeof(char),
2072 "file:%s.niml.cmap", sname->FileName_NoExt);
2073
2074 NEL_WRITE_TX(NIcmap, stmp, suc);
2075 if (!suc) {
2076 SUMA_S_Errv("Failed to write %s\n", stmp);
2077 }
2078 SUMA_Free_Parsed_Name(sname); sname = NULL;
2079 NI_free_element(NIcmap); NIcmap = NULL;
2080
2081 SUMA_RETURN(YUP);
2082
2083 }
2084
2085 /*!
2086 Transform a set of strings, keys, and colors to a colormap
2087
2088 \param str (char **): Array of region names
2089 \param num (int): Number of regions
2090 \param keys (int *): Array of keys
2091 \param cols (float **): Array of color tuples (RGB, or RGBA)
2092 \param nc (int): Number of values per color (3 or 4)
2093 \param Name (char *): Name assigned to colormap.
2094
2095 \return a SUMA color map.
2096 If str is NULL, names are automatically regenerated using the keys
2097 if keys is NULL, the key is assumed to be the array index
2098 if cols is NULL, colors are taken from SUMA's roi 256 colormap
2099 if Name is NULL, the colormap is labeled by the function name
2100 */
SUMA_LabelsKeys2Cmap(char ** str,int num,int * keys,float ** cols,int nc,char * Name)2101 SUMA_COLOR_MAP *SUMA_LabelsKeys2Cmap (char **str, int num, int *keys,
2102 float **cols, int nc, char *Name)
2103 {
2104 static char FuncName[]={"SUMA_LabelsKeys2Cmap"};
2105 int i=0, k=0;
2106 char stmp[64];
2107 SUMA_COLOR_MAP* SM = NULL, *roi256=NULL;
2108
2109 SUMA_Boolean LocalHead = NOPE;
2110
2111 SUMA_ENTRY;
2112
2113 // fprintf(stderr, "%s\n", FuncName);
2114
2115 if (num < 1) {
2116 SUMA_S_Err("NULL or empty input");
2117 SUMA_RETURN(NULL);
2118 }
2119
2120 if (!cols) {
2121 if (!(roi256 = SUMA_FindNamedColMap("ROI_i256"))) {
2122 SUMA_S_Errv("Found no colmap %s in %p\n", "ROI_i256", SUMAg_CF->scm);
2123 SUMA_Show_ColorMapVec (SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps,
2124 NULL, 1);
2125 SUMA_RETURN(NULL);
2126 }
2127 }
2128 /* allocate for SM */
2129 SM = (SUMA_COLOR_MAP*) SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
2130 SM->N_M[0] = num;
2131 SM->N_M[1] = 4;
2132 SM->idvec = (int *)SUMA_calloc(SM->N_M[0], sizeof(int));
2133 SM->chd = NULL;
2134 SM->top_frac = 0.0f;
2135 SM->SO = NULL;
2136 SM->cname = (char **)SUMA_calloc(SM->N_M[0], sizeof(char *));;
2137 if (!Name) Name = FuncName;
2138 SM->Name = (char *)SUMA_calloc((strlen(Name)+1),sizeof(char));
2139 sprintf(SM->Name, "%s", Name);
2140 SM->frac = NULL;
2141
2142 SM->M = (float**)SUMA_allocate2D (SM->N_M[0], 4, sizeof(float));
2143
2144
2145 SM->Sgn = 1;
2146 for (i=0; i<SM->N_M[0]; ++i) {
2147 if (cols) {
2148 for (k=0; k<nc; ++k) SM->M[i][k] = cols[i][k];
2149 for (k=nc; k<4; ++k) SM->M[i][k] = 1.0;
2150 } else { /* use from ROI256 */
2151 for (k=0; k<4; ++k) SM->M[i][k] = roi256->M[i%256][k];
2152 }
2153 if (keys) {
2154 SM->idvec[i] = keys[i];
2155 } else {
2156 SM->idvec[i] = i;
2157 }
2158 if (str && str[i]) {
2159 SM->cname[i] = SUMA_copy_string(str[i]);
2160 } else {
2161 sprintf(stmp,"roi%03d", SM->idvec[i]);
2162 SM->cname[i] = SUMA_copy_string(stmp);
2163 }
2164 }
2165
2166
2167 if (LocalHead) {
2168 fprintf (SUMA_STDERR,"%s: Colormap read:\n", FuncName);
2169 SUMA_disp_mat (SM->M, SM->N_M[0], SM->N_M[1], 1);
2170 }
2171
2172 SM->M0[0] = SM->M[0][0];
2173 SM->M0[1] = SM->M[0][1];
2174 SM->M0[2] = SM->M[0][2];
2175 SM->M0[3] = SM->M[0][3];
2176
2177 /* create the hash */
2178 if (!SUMA_CreateCmapHash(SM)) {
2179 SUMA_S_Err("Cannot create hash!");
2180 SUMA_Free_ColorMap(SM);
2181 SUMA_RETURN(NULL);
2182 }
2183
2184 SUMA_RETURN (SM);
2185 }
2186
2187
2188 /*! function that turns a non-linear color map into a linear one
2189 The larger the number of colors in the linear color map, the close the
2190 approximation to the non-linear map.
2191 \param SM (SUMA_COLOR_MAP*) a non-linear colormap (i.e. SM->frac != NULL)
2192 \param N_Lin (int) number of colors to use in the linear version of the map
2193 if N_Lin = -1, N_Lin is set to 1024
2194 \return LSM (SUMA_COLOR_MAP*) linear version of the colormap
2195 NULL if SM is already linear
2196 NULL if SM is NULL
2197
2198 */
SUMA_Linearize_Color_Map(SUMA_COLOR_MAP * SM,int N_lin)2199 SUMA_COLOR_MAP *SUMA_Linearize_Color_Map (SUMA_COLOR_MAP* SM, int N_lin)
2200 {
2201 static char FuncName[]={"SUMA_Linearize_Color_Map"};
2202 SUMA_COLOR_MAP* LSM = NULL;
2203 int ilin = 0, i = 0, ilin_stp = -1;
2204 SUMA_Boolean LocalHead = NOPE;
2205
2206 SUMA_ENTRY;
2207
2208 // fprintf(stderr, "%s\n", FuncName);
2209
2210 if (!SM) {
2211 SUMA_S_Err("NULL color map");
2212 SUMA_RETURN(LSM);
2213 }
2214
2215 if (!SM->frac) {
2216 SUMA_S_Err("NULL SM->frac!\nMap is linear");
2217 SUMA_RETURN(LSM);
2218 }
2219
2220 if (SM->chd || SM->idvec) {
2221 SUMA_S_Err("No hash, and no idvecs please.");
2222 SUMA_RETURN(LSM);
2223 }
2224 if (N_lin < 0) N_lin = 2048; /* 2048 set default linear map length */
2225
2226 if (!N_lin) {
2227 SUMA_S_Err("N_lin = 0");
2228 SUMA_RETURN(LSM);
2229 }
2230
2231 /* allocate for new map */
2232 SUMA_LH("Allocating for new map");
2233 LSM = (SUMA_COLOR_MAP *)SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
2234 if (LSM == NULL) {
2235 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for LSM.\n", FuncName);
2236 SUMA_RETURN (NULL);
2237 }
2238 LSM->top_frac = 0.0f;
2239 LSM->SO = NULL;
2240
2241 LSM->Name = (char *)SUMA_calloc(strlen(SM->Name)+10, sizeof(char));
2242 if (LSM->Name == NULL) {
2243 fprintf (SUMA_STDERR,
2244 "Error %s: Failed to allocate for LSM->Name.\n", FuncName);
2245 SUMA_free(LSM);
2246 SUMA_RETURN (NULL);
2247 }
2248 sprintf(LSM->Name, "%s_lin",SM->Name);
2249 LSM->N_M[0] = N_lin; LSM->N_M[1] = SM->N_M[1];
2250 LSM->frac = NULL;
2251 LSM->cname = NULL;
2252 LSM->Sgn = SM->Sgn;
2253
2254 SUMA_LHv("Allocating for %d (%d)cols\n", LSM->N_M[0], LSM->N_M[1]);
2255 LSM->M = (float **)SUMA_allocate2D (LSM->N_M[0], LSM->N_M[1], sizeof(float));
2256 if (LSM->M == NULL) {
2257 fprintf (SUMA_STDERR,
2258 "Error %s: Failed to allocate for LSM->M.\n", FuncName);
2259 SUMA_free(LSM->Name);
2260 SUMA_free(LSM);
2261 SUMA_RETURN (NULL);
2262 }
2263
2264 if (SM->frac[SM->N_M[0]-1] != 1.0f) {
2265 LSM->top_frac = SM->frac[SM->N_M[0]-1];
2266 }
2267
2268 ilin = 0;
2269 for (i=0; i < SM->N_M[0]; ++i) {
2270 if (SM->N_M[1] == 4) {
2271 SUMA_LHv("SM->frac[%d]=%f, tf = %f , [%f %f %f %f]",
2272 i, SM->frac[i], SM->frac[SM->N_M[0]-1], SM->M[i][0],
2273 SM->M[i][1], SM->M[i][2], SM->M[i][3]);
2274 } else {
2275 SUMA_LHv("SM->frac[%d]=%f, tf = %f , [%f %f %f]",
2276 i, SM->frac[i], SM->frac[SM->N_M[0]-1], SM->M[i][0],
2277 SM->M[i][1], SM->M[i][2]);
2278 }
2279 if (LSM->Sgn >= 0) {
2280 ilin_stp = (int)( ceil((double)(SM->frac[i]/SM->frac[SM->N_M[0]-1]) *
2281 (double)LSM->N_M[0]) ) - 1;
2282 } else {
2283 ilin_stp = (int)(ceil((1.0 +
2284 (double)(SM->frac[i]/SM->frac[SM->N_M[0]-1])) *
2285 (double)LSM->N_M[0]/2) ) - 1;
2286 }
2287 while (ilin < ilin_stp && ilin < LSM->N_M[0]) {
2288 LSM->M[ilin][0] = SM->M[i][0];
2289 LSM->M[ilin][1] = SM->M[i][1];
2290 LSM->M[ilin][2] = SM->M[i][2];
2291 if (LSM->N_M[1] == 4) {
2292 LSM->M[ilin][3] = SM->M[i][3];
2293 }
2294 ++ilin;
2295 }
2296 }
2297
2298 /* copy last value */
2299 LSM->M[LSM->N_M[0]-1][0] = SM->M[SM->N_M[0]-1][0];
2300 LSM->M[LSM->N_M[0]-1][1] = SM->M[SM->N_M[0]-1][1];
2301 LSM->M[LSM->N_M[0]-1][2] = SM->M[SM->N_M[0]-1][2];
2302 if (LSM->N_M[1] == 4) {
2303 LSM->M[LSM->N_M[0]-1][3] = SM->M[SM->N_M[0]-1][3];
2304 }
2305 LSM->M0[0] = LSM->M[0][0];
2306 LSM->M0[1] = LSM->M[0][1];
2307 LSM->M0[2] = LSM->M[0][2];
2308 if (LSM->N_M[1] == 4)
2309 LSM->M0[3] = LSM->M[0][3];
2310 else
2311 LSM->M0[3] = 1.0;
2312
2313 if (LocalHead) {
2314 for (i=0; i < LSM->N_M[0]; ++i) {
2315 if (LSM->N_M[1] == 4)
2316 fprintf (SUMA_STDOUT,
2317 "%d:\t%f\t%f\t%f\t%f\n",
2318 i, LSM->M[i][0], LSM->M[i][1], LSM->M[i][2], LSM->M[i][3]);
2319 else
2320 fprintf (SUMA_STDOUT,
2321 "%d:\t%f\t%f\t%f\n",
2322 i, LSM->M[i][0], LSM->M[i][1], LSM->M[i][2]);
2323 }
2324 fprintf (SUMA_STDOUT,"%s: ilin_stp = %d\n", FuncName, ilin_stp);
2325 }
2326
2327 SUMA_RETURN(LSM);
2328 }
2329
2330 /*!
2331 \brief Find the colormap associated with a colorplane
2332 \return SUMA_COLOR_MAP * NULL if error or if cmap is explicit
2333 */
SUMA_CmapOfPlane(SUMA_OVERLAYS * Sover)2334 SUMA_COLOR_MAP *SUMA_CmapOfPlane (SUMA_OVERLAYS *Sover )
2335 {
2336 static char FuncName[]={"SUMA_CmapOfPlane"};
2337 SUMA_COLOR_MAP *ColMap = NULL;
2338 int icmap;
2339
2340 SUMA_ENTRY;
2341
2342 // fprintf(stderr, "%s\n", FuncName);
2343
2344 if (!Sover) { SUMA_SL_Err("NULL Sover"); SUMA_RETURN(ColMap); }
2345 if (!Sover->cmapname) {
2346 SUMA_SL_Err("NULL Colormap name");
2347 SUMA_RETURN(ColMap);
2348 }
2349
2350 if (strcmp(Sover->cmapname, "explicit") == 0) {
2351 SUMA_RETURN(NULL);
2352 }
2353
2354 if (!SUMAg_CF->scm) {
2355 SUMAg_CF->scm = SUMA_Build_Color_maps();
2356 if (!SUMAg_CF->scm) {
2357 SUMA_SL_Err("Can't build color maps");
2358 SUMA_RETURN(ColMap);
2359 }
2360 }
2361 icmap = SUMA_Find_ColorMap ( Sover->cmapname, SUMAg_CF->scm->CMv,
2362 SUMAg_CF->scm->N_maps, -2 );
2363 if (icmap < 0) { SUMA_SL_Err("Failed to find ColMap"); SUMA_RETURN(ColMap); }
2364 ColMap = SUMAg_CF->scm->CMv[icmap];
2365
2366 SUMA_RETURN(ColMap);
2367
2368 }
2369
2370 /* Removes pre-existing bias
2371 DOES NOT free bias vector
2372 DOES NOT SET OptScl->DoBias to SW_CoordBias_None
2373 The last two operations should be carried out once the bias is removed from all surfaces
2374 to which they'd been applied. In this case it will be in SUMA_RemoveCoordBias
2375 This function should not be called directly, only from SUMA_RemoveCoordBias
2376 */
SUMA_RemoveSO_CoordBias(SUMA_SurfaceObject * SO,SUMA_OVERLAYS * ovr)2377 SUMA_Boolean SUMA_RemoveSO_CoordBias(SUMA_SurfaceObject *SO, SUMA_OVERLAYS *ovr)
2378 {
2379 static char FuncName[]={"SUMA_RemoveSO_CoordBias"};
2380 int i, i3, x_i3;
2381 SUMA_VIS_XFORM_DATUM *x0=NULL;
2382
2383 SUMA_ENTRY;
2384
2385 // fprintf(stderr, "%s\n", FuncName);
2386
2387 if (!SO || !ovr) {
2388 SUMA_SL_Err("Dim dim diM");
2389 SUMA_RETURN(NOPE);
2390 }
2391
2392 /* get the coord bias displacement transform */
2393 /*This function gets called by default before there is a change in
2394 CoordBias, so make sure you add one if none existed */
2395 x0 = SUMA_Fetch_VisX_Datum ("CoordBias", SO->VisX.Xchain,
2396 ADD_BEFORE, "Prying");
2397
2398 /* free the displacement vector if it is allocated */
2399 if (x0->XformType != DISP) {
2400 SUMA_S_Warn("Did not expect CoordBias xform to be != displacement");
2401 }
2402 x0->XformType = ID;
2403 if (x0->dxyz) SUMA_free(x0->dxyz);
2404 x0->dxyz = NULL;
2405
2406 SUMA_RETURN(YUP);
2407 }
2408
2409
2410 /* Removes pre-existing bias to old dimension
2411 Add same bias to BiasDim dimension
2412 sets OptScl->DoBias to BiasDim
2413 */
SUMA_TransferCoordBias(SUMA_OVERLAYS * ovr,SUMA_WIDGET_INDEX_COORDBIAS BiasDim)2414 SUMA_Boolean SUMA_TransferCoordBias(SUMA_OVERLAYS *ovr,
2415 SUMA_WIDGET_INDEX_COORDBIAS BiasDim)
2416 {
2417 static char FuncName[]={"SUMA_TransferCoordBias"};
2418 SUMA_SurfaceObject *SO=NULL;
2419 int iso;
2420 SUMA_Boolean LocalHead = NOPE;
2421 SUMA_ENTRY;
2422
2423 // fprintf(stderr, "%s\n", FuncName);
2424
2425 if (!ovr) SUMA_RETURN(YUP);
2426
2427 for (iso=0; iso<SUMAg_N_DOv; ++iso) {
2428 if (SUMA_isSO(SUMAg_DOv[iso])) {
2429 SO = (SUMA_SurfaceObject *)SUMAg_DOv[iso].OP;
2430 if (SUMA_isOverlayOfDO((SUMA_ALL_DO *)SO, ovr)) {
2431 SUMA_LH("Setting bias flag");
2432 ovr->OptScl->DoBias = BiasDim;
2433 SUMA_TransferSO_CoordBias(SO, ovr, BiasDim);
2434 }
2435 }
2436 }
2437
2438
2439 SUMA_RETURN(YUP);
2440
2441 }
2442
SUMA_AddVisX_CoordBias(SUMA_SurfaceObject * SO,SUMA_OVERLAYS * ovr,SUMA_WIDGET_INDEX_COORDBIAS BiasDim,float * BiasVect)2443 SUMA_Boolean SUMA_AddVisX_CoordBias(SUMA_SurfaceObject *SO, SUMA_OVERLAYS *ovr,
2444 SUMA_WIDGET_INDEX_COORDBIAS BiasDim,
2445 float *BiasVect)
2446 {
2447 static char FuncName[]={"SUMA_AddVisX_CoordBias"};
2448 int m_i, m_i3, mx_i3 = 3*SO->N_Node;
2449 SUMA_VIS_XFORM_DATUM *x0=NULL;
2450 SUMA_Boolean LocalHead = NOPE;
2451
2452 SUMA_ENTRY;
2453
2454 // fprintf(stderr, "%s\n", FuncName);
2455
2456
2457 /* if CoordBias is to be added, it should be before Prying */
2458 x0 = SUMA_Fetch_VisX_Datum ("CoordBias", SO->VisX.Xchain,
2459 ADD_BEFORE, "Prying");
2460 if (!x0) {
2461 SUMA_S_Err("Did not expect to fail here");
2462 SUMA_RETURN(NOPE);
2463 }
2464
2465 /* Now compute the bias, I expect normals to be correctly
2466 set at this stage */
2467 if (!x0->dxyz) {
2468 if (!(x0->dxyz =
2469 (float *)SUMA_calloc(SO->N_Node*SO->NodeDim, sizeof(float)))){
2470 SUMA_S_Crit("Failed to allocate for coord bias!");
2471 SUMA_RETURN(NOPE);
2472 }
2473 }
2474 x0->XformType = DISP;
2475
2476
2477 switch (BiasDim) {
2478 case SW_CoordBias_X:
2479 /* Add X bias */
2480 for (m_i=0; m_i < ovr->N_NodeDef; ++m_i) {
2481 m_i3 = 3*ovr->NodeDef[m_i];
2482 if (m_i3 < mx_i3) x0->dxyz[m_i3] = BiasVect[m_i];
2483 }
2484 break;
2485 case SW_CoordBias_Y:
2486 /* Add Y bias */
2487 for (m_i=0; m_i < ovr->N_NodeDef; ++m_i) {
2488 m_i3 = 3*ovr->NodeDef[m_i]+1;
2489 if (m_i3 < mx_i3) x0->dxyz[m_i3] = BiasVect[m_i];
2490 }
2491 break;
2492 case SW_CoordBias_Z:
2493 /* Add Z bias */
2494 for (m_i=0; m_i < ovr->N_NodeDef; ++m_i) {
2495 m_i3 = 3*ovr->NodeDef[m_i]+2;
2496 if (m_i3 < mx_i3) x0->dxyz[m_i3] = BiasVect[m_i];
2497 }
2498 break;
2499 case SW_CoordBias_N:
2500 /* Add Normal bias */
2501 for (m_i=0; m_i < ovr->N_NodeDef; ++m_i) {
2502 m_i3 = 3*ovr->NodeDef[m_i];
2503 if (m_i3 < mx_i3) {
2504 x0->dxyz[m_i3] = BiasVect[m_i] * SO->NodeNormList[m_i3];
2505 ++m_i3;
2506 x0->dxyz[m_i3] = BiasVect[m_i] * SO->NodeNormList[m_i3];
2507 ++m_i3;
2508 x0->dxyz[m_i3] = BiasVect[m_i] * SO->NodeNormList[m_i3];
2509 }
2510 }
2511 break;
2512 default:
2513 SUMA_SL_Err("This should not be.\nWhy, oh why ?");
2514 }
2515
2516
2517 SUMA_RETURN(YUP);
2518 }
2519
2520
2521 /*!
2522 Single surface version of SUMA_TransferCoordBias DO NOT CALL THIS FUNCTION OUTSIDE OF SUMA_TransferCoordBias
2523 */
SUMA_TransferSO_CoordBias(SUMA_SurfaceObject * SO,SUMA_OVERLAYS * ovr,SUMA_WIDGET_INDEX_COORDBIAS BiasDim)2524 SUMA_Boolean SUMA_TransferSO_CoordBias(SUMA_SurfaceObject *SO,
2525 SUMA_OVERLAYS *ovr, SUMA_WIDGET_INDEX_COORDBIAS BiasDim)
2526 {
2527 static char FuncName[]={"SUMA_TransferSO_CoordBias"};
2528 SUMA_Boolean LocalHead = NOPE;
2529 int i, i3;
2530
2531 SUMA_ENTRY;
2532
2533 // fprintf(stderr, "%s\n", FuncName);
2534
2535 SUMA_LHv("Called overlay %p, (%p)\n", ovr, ovr->OptScl->BiasVect);
2536
2537
2538 if (ovr->OptScl->BiasVect) {
2539 SUMA_LH("Removing old bias");
2540
2541 SUMA_RemoveSO_CoordBias(SO, ovr);
2542
2543 SUMA_LH("Adding new bias");
2544
2545 /* Add same bias to other direction */
2546 SUMA_AddVisX_CoordBias(SO, ovr, BiasDim, ovr->OptScl->BiasVect);
2547 }
2548
2549 SUMA_RETURN(YUP);
2550 }
2551
2552
2553 /*!
2554 Function called when a surface's geometry is changed
2555 (Used to be called due to a change in the CoordBias,
2556 that is no longer needed with CoordBias handled through VisX)
2557 */
SUMA_NewSurfaceGeometry(SUMA_SurfaceObject * SO)2558 SUMA_Boolean SUMA_NewSurfaceGeometry(SUMA_SurfaceObject *SO)
2559 {
2560 static char FuncName[]={"SUMA_NewSurfaceGeometry"};
2561 int ii, i;
2562 SUMA_Boolean LocalHead = NOPE;
2563
2564 SUMA_ENTRY;
2565
2566 // fprintf(stderr, "%s\n", FuncName);
2567
2568 /* first recompute the bounding box of the surface */
2569 /* Calculate Min, Max, Mean */
2570 SUMA_MIN_MAX_SUM_VECMAT_COL ( SO->NodeList, SO->N_Node, SO->NodeDim,
2571 SO->MinDims, SO->MaxDims, SO->Center);
2572
2573 SO->Center[0] /= SO->N_Node;
2574 SO->Center[1] /= SO->N_Node;
2575 SO->Center[2] /= SO->N_Node;
2576
2577 SUMA_MIN_VEC (SO->MinDims, 3, SO->aMinDims );
2578 SUMA_MAX_VEC (SO->MaxDims, 3, SO->aMaxDims);
2579
2580 /* find out what viewers this surface is registered with
2581 and which viewers show it */
2582 for (ii=0; ii<SUMAg_N_SVv; ++ii) {
2583 if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
2584 for (i=0; i< SUMAg_SVv[ii].N_DO; ++i) {
2585 if (SUMA_isSO_G( SUMAg_DOv[SUMAg_SVv[ii].RegistDO[i].dov_ind],
2586 SUMAg_SVv[ii].CurGroupName)) {
2587 /* is this surface the same as SO ? */
2588 if (SUMA_findSO_inDOv(SO->idcode_str, SUMAg_DOv, SUMAg_N_DOv) ==
2589 SUMAg_SVv[ii].RegistDO[i].dov_ind) {
2590 /* This surface is visible in this viewer, mark that viewer */
2591 SUMA_LH("Marking Viewer ");
2592 SUMAg_SVv[ii].NewGeom = YUP;
2593 }
2594 }
2595 }
2596 }
2597 }
2598
2599 SUMA_RETURN(YUP);
2600 }
2601
2602
2603
2604 /*
2605 - adds new bias
2606 - DOES NOT copy NewBias to OptScl->BiasVect
2607 - DOES NOT set OptScl->DoBias to BiasDim
2608 The previous 2 operations are to be done in SUMA_SetCoordBias which call this function for all
2609 surfaces using this overlay plane
2610
2611 */
SUMA_SetSO_CoordBias(SUMA_SurfaceObject * SO,SUMA_OVERLAYS * ovr,float * NewBias,SUMA_WIDGET_INDEX_COORDBIAS BiasDim)2612 SUMA_Boolean SUMA_SetSO_CoordBias( SUMA_SurfaceObject *SO, SUMA_OVERLAYS *ovr, float *NewBias,
2613 SUMA_WIDGET_INDEX_COORDBIAS BiasDim)
2614 {
2615 static char FuncName[]={"SUMA_SetSO_CoordBias"};
2616 int i, i3;
2617 SUMA_Boolean LocalHead = NOPE;
2618
2619 SUMA_ENTRY;
2620
2621 // fprintf(stderr, "%s\n", FuncName);
2622
2623 if (!ovr) {
2624 SUMA_SL_Err("NULL ovr");
2625 SUMA_RETURN(NOPE);
2626 }
2627 if (!ovr->NodeDef) {
2628 SUMA_SL_Err("NULL ovr->NodeDef");
2629 SUMA_RETURN(NOPE);
2630 }
2631 /* Now add the new one */
2632 if (NewBias) {
2633 /* Add bias to direction */
2634 SUMA_LH("Adding VisX NewBias");
2635 SUMA_AddVisX_CoordBias(SO, ovr, BiasDim, NewBias);
2636 } else {/* nothing to add (0 bias)*/
2637 SUMA_LH("NULL NewBias");
2638 }
2639
2640 SUMA_RETURN(YUP);
2641 }
2642
2643
2644 /*!
2645 Sets the coordinate bias for surfaces using a particular overlay plane
2646 Do NOT free NewBias upon return since this pointer will replace OptScl->BiasVect
2647 DO NOT CALL THIS FUNCTION IF ovr->NodeDef has been modified, otherwise SUMA_RemoveSO_CoordBias will fail
2648 */
2649
SUMA_SetCoordBias(SUMA_OVERLAYS * ovr,float * NewBias,SUMA_WIDGET_INDEX_COORDBIAS BiasDim)2650 SUMA_Boolean SUMA_SetCoordBias(SUMA_OVERLAYS *ovr,
2651 float *NewBias, SUMA_WIDGET_INDEX_COORDBIAS BiasDim)
2652 {
2653 static char FuncName[]={"SUMA_SetCoordBias"};
2654 int i, i3, iso;
2655 SUMA_SurfaceObject *SO=NULL;
2656 SUMA_Boolean LocalHead = NOPE;
2657
2658 SUMA_ENTRY;
2659
2660 // fprintf(stderr, "%s\n", FuncName);
2661
2662 SUMA_LH("Called");
2663 if (!ovr) SUMA_RETURN(YUP);
2664
2665 if (ovr->OptScl->BiasVect ) {
2666 SUMA_SL_Err("Can't have Non NULL bias here");
2667 SUMA_Show_ColorOverlayPlanes(&ovr,1,1);
2668 SUMA_RETURN(NOPE);
2669 }
2670
2671 ovr->OptScl->BiasVect = NewBias;
2672 ovr->OptScl->DoBias = BiasDim;
2673 for (iso=0; iso<SUMAg_N_DOv; ++iso) {
2674 if (SUMA_isSO(SUMAg_DOv[iso])) {
2675 SO = (SUMA_SurfaceObject *)SUMAg_DOv[iso].OP;
2676 if (SUMA_isOverlayOfDO((SUMA_ALL_DO *)SO, ovr)) {
2677 SUMA_ApplyVisXform(SO, "VisX", UNDO_XFORM, 1);
2678 SUMA_SetSO_CoordBias(SO, ovr, NewBias, BiasDim);
2679 SUMA_ApplyVisXform(SO, "VisX", FORWARD_XFORM, 1);
2680 }
2681 }
2682 }
2683
2684
2685 SUMA_RETURN(YUP);
2686 }
2687
SUMA_RemoveCoordBias(SUMA_OVERLAYS * ovr)2688 SUMA_Boolean SUMA_RemoveCoordBias(SUMA_OVERLAYS *ovr)
2689 {
2690 static char FuncName[]={"SUMA_RemoveCoordBias"};
2691 int i, i3, iso;
2692 SUMA_SurfaceObject *SO=NULL;
2693 SUMA_Boolean LocalHead = NOPE;
2694 SUMA_ENTRY;
2695
2696 // fprintf(stderr, "%s\n", FuncName);
2697
2698 if (!ovr) SUMA_RETURN(YUP);
2699 if (ovr->OptScl->BiasVect) { /* something to be removed */
2700 for (iso=0; iso<SUMAg_N_DOv; ++iso) {
2701 if (SUMA_isSO(SUMAg_DOv[iso])) {
2702 SO = (SUMA_SurfaceObject *)SUMAg_DOv[iso].OP;
2703 if (SUMA_isOverlayOfDO((SUMA_ALL_DO *)SO, ovr)) {
2704 SUMA_ApplyVisXform(SO, "VisX", UNDO_XFORM, 1);
2705 SUMA_RemoveSO_CoordBias(SO, ovr);
2706 }
2707 }
2708 }
2709 /* Now free BiasVect */
2710 SUMA_free(ovr->OptScl->BiasVect);
2711 }
2712 ovr->OptScl->BiasVect = NULL;
2713 ovr->OptScl->DoBias = SW_CoordBias_None;
2714
2715 SUMA_RETURN(YUP);
2716 }
2717
SUMA_SO_of_ColPlane(SUMA_OVERLAYS * Sover)2718 SUMA_SurfaceObject *SUMA_SO_of_ColPlane(SUMA_OVERLAYS *Sover)
2719 {
2720 static char FuncName[]={"SUMA_SO_of_ColPlane"};
2721 SUMA_SurfaceObject *SO=NULL;
2722 SUMA_ENTRY;
2723
2724 // fprintf(stderr, "%s\n", FuncName);
2725
2726 if (!Sover || !Sover->dset_link) SUMA_RETURN(SO);
2727 SO = SUMA_findSOp_inDOv( SUMA_sdset_idmdom(Sover->dset_link),
2728 SUMAg_DOv, SUMAg_N_DOv);
2729 SUMA_RETURN(SO);
2730 }
2731
SUMA_PercFullRangeVol(float * V,int N_V,int p10,int exzero,int * Nvals)2732 float *SUMA_PercFullRangeVol(float *V, int N_V, int p10, int exzero, int *Nvals)
2733 {
2734 static char FuncName[]={"SUMA_PercFullRangeVol"};
2735 int nval = 0, ii;
2736 float *pr=NULL;
2737 float *Vsort=NULL, fac, *perc=NULL;
2738
2739 SUMA_ENTRY;
2740
2741 // fprintf(stderr, "%s\n", FuncName);
2742
2743 if (Nvals) *Nvals = -1;
2744
2745 if (!V) {
2746 SUMA_S_Err("NULL input");
2747 SUMA_RETURN(NULL);
2748 }
2749 if (p10 < 1 || p10 > 6) {
2750 SUMA_S_Err("I suspect you jest p10 = %d", p10);
2751 SUMA_RETURN(NULL);
2752 }
2753 nval = (int)pow(10.0, p10)+1;
2754 fac = 100.0/(nval-1);
2755
2756 if (!(pr = (float *)SUMA_calloc(nval, sizeof(float))) ||
2757 !(perc= (float *)SUMA_calloc(nval, sizeof(float))) ) {
2758 SUMA_S_Err("Failed to allocate");
2759 SUMA_ifree(pr); SUMA_ifree(perc);
2760 SUMA_RETURN(NULL);
2761 }
2762 for (ii=0; ii<nval; ++ii) pr[ii] = (float)ii*fac;
2763 if ((Vsort=SUMA_PercRangeVol(V, NULL, N_V,
2764 pr, nval, perc, NULL, exzero, NULL))) {
2765 SUMA_ifree(Vsort);
2766 SUMA_ifree(pr);
2767 } else {
2768 SUMA_S_Err("Failed to get percentiles");
2769 SUMA_ifree(pr); SUMA_ifree(perc);
2770 SUMA_RETURN(NULL);
2771 }
2772 if (Nvals) *Nvals = nval;
2773 SUMA_RETURN(perc);
2774 }
2775
SUMA_DSET_ClearOverlay_Vecs(SUMA_DSET * dset)2776 SUMA_Boolean SUMA_DSET_ClearOverlay_Vecs(SUMA_DSET *dset)
2777 {
2778 static char FuncName[]={"SUMA_DSET_ClearOverlay_Vecs"};
2779 SUMA_OVERLAYS **over=NULL;
2780 SUMA_ALL_DO *ado=NULL;
2781 int N_over, i, k;
2782
2783 SUMA_ENTRY;
2784
2785 // fprintf(stderr, "%s\n", FuncName);
2786
2787 if (!dset) SUMA_RETURN(NOPE);
2788
2789 for (i=0; i<SUMAg_N_DOv; ++i) {
2790 ado = iDO_ADO(i);
2791 if ((over = SUMA_ADO_Overlays(ado, &N_over))) {
2792 for (k=0; k<N_over; ++k) {
2793 if (over[k]->dset_link == dset) {
2794 SUMA_SetOverlay_Vecs(over[k],'A', -1, "clear", -1);
2795 }
2796 }
2797 }
2798 }
2799
2800 SUMA_RETURN(YUP);
2801 }
2802
2803 /*!
2804 A function that setsup vectors V, T and their ilk in the overlay plane.
2805 The function is intended to figure out whether the old version of the
2806 vector needs throwing away or whether it can be reused.
2807
2808 Sover (SUMA_OVERLAYS *): The overlay struct
2809 vec (char): Choose from 'V', 'T', or 'A' for both. Note that
2810 'A' is only OK with task = "clear"
2811 colind (int): Which column to copy from dset
2812 task (char *): What should be done?
2813 "update", make sure T, or V are ready for use.
2814 "clear", wipe T, V, etc.
2815 "reset", clear, then update
2816 perc (int): if non zero, then also update percentile vectors
2817 \return YUP OK, NOPE, BAD
2818 */
SUMA_SetOverlay_Vecs(SUMA_OVERLAYS * Sover,char vec,int colind,char * task,int perc)2819 SUMA_Boolean SUMA_SetOverlay_Vecs(SUMA_OVERLAYS *Sover, char vec,
2820 int colind, char *task, int perc)
2821 {
2822 static char FuncName[]={"SUMA_SetOverlay_Vecs"};
2823 char thisid[32+SUMA_IDCODE_LENGTH]={""}, *attr=NULL;
2824 SUMA_Boolean LocalHead = NOPE;
2825
2826 SUMA_ENTRY;
2827
2828 // fprintf(stderr, "%s\n", FuncName);
2829
2830 if (!task) task = "update"; /* Vanilla, recreate if necessary */
2831 if (!Sover) {
2832 SUMA_S_Err("NULL input");
2833 if (LocalHead) SUMA_DUMP_TRACE("NULL input");
2834 SUMA_RETURN(NOPE);
2835 }
2836 if (!Sover->dset_link) {
2837 /* Nothing to be done, no dset link. Can happen when freeing
2838 comes from standalone program like 3dVol2Surf. Return
2839 without complaining.*/
2840 SUMA_RETURN(YUP);
2841 } else {
2842 if (Sover->dset_link->dnel &&
2843 (attr=NI_get_attribute(Sover->dset_link->dnel, "ResetOverlay_Vecs"))) {
2844 if (!strcmp(attr,"yes")) {
2845 NI_set_attribute(Sover->dset_link->dnel,"ResetOverlay_Vecs", "nope");
2846 SUMA_DSET_ClearOverlay_Vecs(Sover->dset_link);
2847 }
2848 }
2849 }
2850
2851 if (!strcmp(task,"clear")) { /* just clear, and return */
2852 switch (vec) {
2853 case 'V':
2854 SUMA_ifree(Sover->V);
2855 Sover->N_V = -1;
2856 Sover->V_identifier[0]='\0';
2857 Sover->N_Vperc = -1;
2858 SUMA_ifree(Sover->Vperc);
2859 break;
2860 case 'T':
2861 SUMA_ifree(Sover->T);
2862 Sover->N_T = -1;
2863 Sover->T_identifier[0]='\0';
2864 Sover->N_Tperc = -1;
2865 SUMA_ifree(Sover->Tperc);
2866 break;
2867 case 'A':
2868 SUMA_SetOverlay_Vecs(Sover, 'T', colind, "clear", perc);
2869 SUMA_SetOverlay_Vecs(Sover, 'V', colind, "clear", perc);
2870 break;
2871 default:
2872 SUMA_S_Err("Bad vec=%c", vec);
2873 SUMA_RETURN(NOPE);
2874 }
2875 SUMA_RETURN(YUP);
2876 }
2877 if (vec != 'V' && vec != 'T') {
2878 SUMA_S_Err("vec of %c not valid down here", vec);
2879 SUMA_RETURN(NOPE);
2880 }
2881 if (!strcmp(task,"reset")) {
2882 if (!SUMA_SetOverlay_Vecs(Sover, vec, colind, "clear", perc)) {
2883 SUMA_S_Err("Failed to clear");
2884 SUMA_RETURN(NOPE);
2885 }
2886 if (!SUMA_SetOverlay_Vecs(Sover, vec, colind, "update", perc)) {
2887 SUMA_S_Err("Failed to update under reset");
2888 SUMA_RETURN(NOPE);
2889 }
2890 SUMA_RETURN(YUP);
2891 }
2892 if (!strcmp(task,"update")) {
2893 sprintf(thisid, "%c_%d_%s", vec, colind, SDSET_ID(Sover->dset_link));
2894 switch (vec) {
2895 case 'V':
2896 if (strcmp(thisid, Sover->V_identifier)) {
2897 SUMA_LH("Need new V copy col %d", colind);
2898 SUMA_SetOverlay_Vecs(Sover, vec, colind, "clear", perc);
2899 if (Sover->V) {
2900 SUMA_S_Err("Something seriously wrong with head!");
2901 SUMA_RETURN(NOPE);
2902 }
2903 if (!(Sover->V =
2904 SUMA_DsetCol2Float (Sover->dset_link, colind, 0))) {
2905 SUMA_SL_Err("Failed to get %c", vec);
2906 SUMA_RETURN(NOPE);
2907 }
2908 Sover->N_V = SDSET_VECFILLED(Sover->dset_link);
2909 if (perc) {
2910 Sover->Vperc =
2911 SUMA_PercFullRangeVol(Sover->V, Sover->N_V,
2912 3, 1, &(Sover->N_Vperc));
2913 }
2914 strcpy(Sover->V_identifier,thisid);
2915 } else {
2916 if (perc && !Sover->Vperc) {
2917 if (!(Sover->Vperc =
2918 SUMA_PercFullRangeVol(Sover->V, Sover->N_V,
2919 3, 1, &(Sover->N_Vperc)))) {
2920 SUMA_S_Err("Failed in SUMA_PercFullRangeVol for V");
2921 SUMA_RETURN(NOPE);
2922 }
2923 }
2924 SUMA_LH("All same for %c %d, do nothing", vec, colind);
2925 }
2926 break;
2927 case 'T':
2928 if (strcmp(thisid, Sover->T_identifier)) {
2929 SUMA_LH("Need new T copy, col %d", colind);
2930 SUMA_SetOverlay_Vecs(Sover, vec, colind, "clear", perc);
2931 if (Sover->T) {
2932 SUMA_S_Err("I dont't like ghosts!");
2933 SUMA_RETURN(NOPE);
2934 }
2935 if (!(Sover->T =
2936 SUMA_DsetCol2Float (Sover->dset_link, colind, 0))) {
2937 SUMA_SL_Err("Failed to get %c", vec);
2938 SUMA_RETURN(NOPE);
2939 }
2940 Sover->N_T = SDSET_VECFILLED(Sover->dset_link);
2941 if (perc) {
2942 Sover->Tperc =
2943 SUMA_PercFullRangeVol(Sover->T, Sover->N_T,
2944 3, 1, &(Sover->N_Tperc));
2945 }
2946 strcpy(Sover->T_identifier,thisid);
2947 } else {
2948 if (perc && !Sover->Tperc) {
2949 if (!(Sover->Tperc =
2950 SUMA_PercFullRangeVol(Sover->T, Sover->N_T,
2951 3, 1, &(Sover->N_Tperc)))) {
2952 SUMA_S_Err("Failed in SUMA_PercFullRangeVol for T");
2953 SUMA_RETURN(NOPE);
2954 }
2955 }
2956 SUMA_LH("All same for %c %d, do nothing", vec, colind);
2957 }
2958 break;
2959 default:
2960 SUMA_S_Err("Bad vec of %c at this point", vec);
2961 SUMA_RETURN(NOPE);
2962 break;
2963 }
2964 SUMA_RETURN(YUP);
2965 }
2966 SUMA_S_Err("Bad task %s", task);
2967 SUMA_RETURN(NOPE);
2968 }
2969
SUMA_OverlayPercentile(SUMA_OVERLAYS * Sover,char vec,float perc)2970 float SUMA_OverlayPercentile (SUMA_OVERLAYS *Sover, char vec, float perc)
2971 {
2972 static char FuncName[]={"SUMA_OverlayPercentile"};
2973 float pp=0.0, fac;
2974 int ii;
2975 SUMA_Boolean LocalHead=NOPE;
2976
2977 SUMA_ENTRY;
2978
2979 // fprintf(stderr, "%s\n", FuncName);
2980
2981 if (!Sover || perc < 0.0 || perc > 100.0 ||
2982 (vec != 'T' && vec != 'V') || !Sover->OptScl) {
2983 SUMA_S_Err("NULL or bad input %p, %c, %f, %p", Sover, vec,
2984 perc, Sover?Sover->OptScl:NULL);
2985 SUMA_RETURN(pp);
2986 }
2987 switch (vec) {
2988 case 'T':
2989 if (Sover->OptScl->tind < 0) {
2990 SUMA_S_Err("No tind?");
2991 SUMA_RETURN(pp);
2992 }
2993 if (!SUMA_SetOverlay_Vecs(Sover, vec, Sover->OptScl->tind,"update",1)) {
2994 SUMA_S_Err("Failed to update");
2995 SUMA_RETURN(pp);
2996 }
2997 fac = (Sover->N_Tperc-1)/100.0;
2998 ii = (int) (perc * fac);
2999 if (ii<0 || ii>=Sover->N_Tperc) {
3000 SUMA_S_Err("How can this be? ii=%d", ii);
3001 SUMA_RETURN(pp);
3002 }
3003 SUMA_LH("Am i here? %p, N_Tperc=%d, ii=%d, fac=%f perc=%f",
3004 Sover->Tperc, Sover->N_Tperc, ii, fac, perc);
3005 pp = Sover->Tperc[ii];
3006 SUMA_RETURN(pp);
3007 break;
3008 case 'V':
3009 if (Sover->OptScl->find < 0) {
3010 SUMA_S_Err("No find?");
3011 SUMA_RETURN(pp);
3012 }
3013 if (!SUMA_SetOverlay_Vecs(Sover, vec, Sover->OptScl->find,"update",1)) {
3014 SUMA_S_Err("Failed to update");
3015 SUMA_RETURN(pp);
3016 }
3017 fac = (Sover->N_Vperc-1)/100.0;
3018 ii = (int) (perc * fac);
3019 if (ii<0 || ii>=Sover->N_Vperc) {
3020 SUMA_S_Err("How can this be? ii=%d", ii);
3021 SUMA_RETURN(pp);
3022 }
3023 pp = Sover->Vperc[ii];
3024 SUMA_RETURN(pp);
3025 break;
3026 default:
3027 SUMA_S_Err("Why is vec %c here?", vec);
3028 break;
3029 }
3030 SUMA_RETURN(pp);
3031 }
3032
3033 /*!
3034
3035 - Some of the fields of SUMA_SCALE_TO_MAP_OPT are ignored here.
3036 1- Find the colormap structure
3037 2- Linearize the colormap if need be
3038 3- Apply a global brightness coefficient (if any) on the
3039 colors in the colormap
3040 4- Loop accross each node in the intensity column
3041 if its threshold meets the cut-off,
3042 colorize it
3043
3044 */
SUMA_ScaleToMap_Interactive(SUMA_OVERLAYS * Sover)3045 SUMA_Boolean SUMA_ScaleToMap_Interactive ( SUMA_OVERLAYS *Sover )
3046 {
3047 static char FuncName[]={"SUMA_ScaleToMap_Interactive"};
3048 float *B=NULL;
3049 int i, icmap, i3, cnt, cnt3, loc[2], *nd=NULL;
3050 float *nv = NULL, am = 0.0;
3051 double Range[2];
3052 double minB, maxB, fact=0.0, floc = 0.0;
3053 SUMA_COLOR_MAP *ColMap = NULL;
3054 SUMA_SCALE_TO_MAP_OPT *Opt = NULL;
3055 SUMA_COLOR_SCALED_VECT * SV = NULL;
3056 float *junk;
3057 byte *alphaval=NULL;
3058 static int nwarn=0;
3059 SUMA_ALL_DO *ado=NULL;
3060 SUMA_WIDGET_INDEX_COORDBIAS HoldBiasOpt;
3061 SUMA_Boolean LocalHead = NOPE;
3062
3063 SUMA_ENTRY;
3064
3065 // fprintf(stderr, "%s\n", FuncName);
3066
3067
3068 if (!Sover) { SUMA_SL_Err("NULL Sover"); SUMA_RETURN(NOPE); }
3069 if (!Sover->cmapname) {
3070 SUMA_SL_Err("NULL Colormap name"); SUMA_RETURN(NOPE);
3071 }
3072 if (!SUMAg_CF->scm) {
3073 SUMAg_CF->scm = SUMA_Build_Color_maps();
3074 if (!SUMAg_CF->scm) {
3075 SUMA_SL_Err("Can't build color maps");
3076 SUMA_RETURN(NOPE);
3077 }
3078 }
3079 SUMA_LH("Finding ColorMap %s", Sover->cmapname);
3080 icmap = SUMA_Find_ColorMap ( Sover->cmapname,
3081 SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps, -2 );
3082 if (icmap < 0) {
3083 SUMA_SL_Err("Failed to find ColMap");
3084 SUMA_S_Errv("Missing ColMap called %s\n", Sover->cmapname);
3085 SUMA_RETURN(NOPE);
3086 }
3087 ColMap = SUMAg_CF->scm->CMv[icmap];
3088
3089 Opt = Sover->OptScl;
3090
3091 SUMA_LH("Creating a scaled color vect");
3092 if (Sover->ShowMode == SW_SurfCont_DsetViewCon ||
3093 Sover->ShowMode == SW_SurfCont_DsetViewCaC ) {
3094 if (SUMA_NeedsLinearizing(ColMap)) {
3095 if (!nwarn) {
3096 SUMA_SLP_Note("Cannot do contouring with colormaps\n"
3097 "that panes of unequal sizes.\n"
3098 "Notice shown once per session.");
3099 ++nwarn;
3100 }
3101 Opt->ColsContMode = 0;
3102 } else {
3103 Opt->ColsContMode = 1;
3104 }
3105 } else {
3106 Opt->ColsContMode = 0;
3107 }
3108 SV = SUMA_Create_ColorScaledVect(SDSET_VECFILLED(Sover->dset_link),
3109 Opt->ColsContMode);
3110
3111 SUMA_LH("Fetching vetors from dset");
3112
3113 B = NULL;
3114 /* Thresholding ? */
3115 if (Opt->tind >= 0 && Opt->UseThr) {
3116 SUMA_LH("Fetching Threshold column");
3117 if ( !SUMA_SetOverlay_Vecs(Sover, 'T', Opt->tind, "update", 0) ||
3118 !Sover->T ) {
3119 SUMA_S_Err("Failed to get T");
3120 SUMA_RETURN(NOPE);
3121 }
3122 switch (Opt->ThrMode) {
3123 case SUMA_NO_THRESH:
3124 break;
3125 case SUMA_LESS_THAN:
3126 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3127 if (Sover->T[i] < Opt->ThreshRange[0]) {
3128 SV->isMasked[i] = YUP; /* Mask */
3129 }
3130 }
3131 break;
3132 case SUMA_ABS_LESS_THAN:
3133 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3134 if (Sover->T[i] < Opt->ThreshRange[0] &&
3135 Sover->T[i] > -Opt->ThreshRange[0]) {
3136 SV->isMasked[i] = YUP; /* Mask */
3137 }
3138 }
3139 break;
3140 case SUMA_THRESH_OUTSIDE_RANGE:
3141 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3142 if (Sover->T[i] >= Opt->ThreshRange[0] &&
3143 Sover->T[i] <= Opt->ThreshRange[1]) {
3144 SV->isMasked[i] = YUP; /* Mask */
3145 }
3146 }
3147 break;
3148 case SUMA_THRESH_INSIDE_RANGE:
3149 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3150 if (Sover->T[i] < Opt->ThreshRange[0] ||
3151 Sover->T[i] > Opt->ThreshRange[1]) {
3152 SV->isMasked[i] = YUP; /* Mask */
3153 }
3154 }
3155 break;
3156 default:
3157 SUMA_SL_Err("Wrond threshold mode");
3158 SUMA_RETURN(NOPE);
3159 break;
3160 }
3161 }
3162
3163
3164 SUMA_LH("Fetching Intensity column");
3165 if (Opt->find < 0) { SUMA_SL_Crit("Bad column index.\n"); SUMA_RETURN(NOPE); }
3166 else {
3167 if ( !SUMA_SetOverlay_Vecs(Sover, 'V', Opt->find, "update", 0) ||
3168 !Sover->V ) {
3169 SUMA_S_Err("Failed to get V");
3170 SUMA_RETURN(NOPE);
3171 }
3172 }
3173
3174 /* setup nodedef so that it can be used along with Sover->V
3175 for clusterinzing. Sover->V will get modified in subsequent
3176 calls so got to do it now */
3177 if (Opt->Clusterize && Opt->RecomputeClust) {
3178 if (!(nv = (float *)SUMA_calloc(SDSET_VECFILLED(Sover->dset_link),
3179 sizeof(float)))) {
3180 SUMA_S_Crit("Failed to alloate!");
3181 SUMA_RETURN(NOPE);
3182 }
3183 }
3184 nd = SUMA_GetNodeDef(Sover->dset_link);
3185 if (nd) {
3186 cnt = 0;
3187 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3188 if (!SV->isMasked[i]) {
3189 Sover->NodeDef[cnt] = nd[i];
3190 if (nv) nv[cnt] = Sover->V[i];
3191 ++cnt;
3192 }
3193 }
3194 } else {
3195 cnt = 0;
3196 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3197 if (!SV->isMasked[i]) {
3198 Sover->NodeDef[cnt] = i;
3199 if (nv) nv[cnt] = Sover->V[i];
3200 ++cnt;
3201 }
3202 }
3203 }
3204 Sover->N_NodeDef = cnt;
3205 Sover->FullList = NOPE;
3206
3207 /* Do we need clusterinzing ? */
3208 if (Opt->Clusterize) {
3209 if (Opt->RecomputeClust) {
3210 SUMA_SurfaceObject *SO = NULL;
3211 SUMA_LH("Clusterizing requested");
3212 if (Sover->ClustList) { /* kill it, to make way for new one*/
3213 SUMA_LH("Clearing old clusterlist");
3214 dlist_destroy(Sover->ClustList);
3215 SUMA_free(Sover->ClustList); Sover->ClustList = NULL;
3216 if (Sover->ClustOfNode) SUMA_free(Sover->ClustOfNode);
3217 Sover->ClustOfNode = NULL;
3218 }
3219
3220 if (!(SO = SUMA_SO_of_ColPlane(Sover))){
3221 SUMA_S_Errv("Can't find dset's domain parent(%s, %s).\n"
3222 " No cluster for you!\n",
3223 SUMA_sdset_idmdom(Sover->dset_link),
3224 SDSET_LABEL(Sover->dset_link));
3225 } else {
3226 char *s=NULL;
3227 if (!nv) {
3228 SUMA_S_Err("NULL nv, this should not happen");
3229 } else {
3230 SUMA_LH("Hold on now, creating clusters...");
3231 if (!Opt->ClustOpt) {
3232 Opt->ClustOpt = SUMA_create_SurfClust_Opt("InteractiveClust");
3233 }
3234 Sover->ClustList = SUMA_FindClusters (SO, Sover->NodeDef,
3235 nv, Sover->N_NodeDef, -1,
3236 Opt->ClustOpt, SO->NodeAreas);
3237 if (Sover->ClustList->size) {
3238 /* sort the list */
3239 SUMA_LH("Sorting List");
3240 if (!SUMA_Sort_ClustersList (Sover->ClustList,
3241 Opt->ClustOpt->SortMode)) {
3242 SUMA_S_Err("Failed to sort cluster list");
3243 }
3244 /* Now update what needs masking */
3245 if (!(Sover->ClustOfNode = SUMA_ClustList2Mask(
3246 Sover->ClustList, SO->N_Node))) {
3247 SUMA_S_Err("No masks. Mille milliards de mille sabords");
3248 } else {
3249 /* condensing of SV is done below */
3250 }
3251
3252 }
3253 /* mess around with options to create the equivalent
3254 command line */
3255 Opt->ClustOpt->labelcol = Opt->find;
3256 Opt->ClustOpt->in_name = SDSET_FILENAME(Sover->dset_link);
3257 Opt->ClustOpt->tind = Opt->tind;
3258 Opt->ClustOpt->DoThreshold = Opt->ThrMode;
3259 switch(Opt->ThrMode) {
3260 case SUMA_NO_THRESH:
3261 case SUMA_LESS_THAN:
3262 Opt->ClustOpt->ThreshR[0] = Opt->ThreshRange[0];
3263 break;
3264 case SUMA_ABS_LESS_THAN:
3265 Opt->ClustOpt->ThreshR[0] = Opt->ThreshRange[0];
3266 break;
3267 case SUMA_THRESH_OUTSIDE_RANGE:
3268 Opt->ClustOpt->ThreshR[0] = Opt->ThreshRange[0];
3269 Opt->ClustOpt->ThreshR[1] = Opt->ThreshRange[1];
3270 case SUMA_THRESH_INSIDE_RANGE:
3271 Opt->ClustOpt->ThreshR[0] = Opt->ThreshRange[0];
3272 Opt->ClustOpt->ThreshR[1] = Opt->ThreshRange[1];
3273 break;
3274 default:
3275 Opt->ClustOpt->DoThreshold = SUMA_NOT_SET;
3276 break;
3277 }
3278 if ((s = SUMA_ClustCommandLineFromOpt("SurfClust",
3279 SO, Opt->ClustOpt, NULL))) {
3280 fprintf(SUMA_STDOUT,"\nInteractive Clustering Output:\n");
3281 SUMA_Show_SurfClust_list(Sover->ClustList, NULL, 0,
3282 s,"No1DColHead");
3283 SUMA_free(s); s = NULL;
3284 }
3285 Opt->RecomputeClust = NOPE;
3286 }
3287 }
3288 } else {
3289 SUMA_LH("No need to muck about");
3290 }
3291 if (Sover->ClustOfNode) {
3292 SUMA_LHv("Modifying SV->isMasked, etc\n"
3293 " Have %d nodes defined \n"
3294 " Last node now: %d\n",
3295 Sover->N_NodeDef,
3296 Sover->NodeDef[Sover->N_NodeDef-1]);
3297 cnt = 0;
3298 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3299 if (!SV->isMasked[i]) {
3300 if (!Sover->ClustOfNode[Sover->NodeDef[cnt]]) {
3301 Sover->NodeDef[cnt] = -1;
3302 SV->isMasked[i] = 1; /* hide it */
3303 }
3304 ++cnt;
3305 }
3306 }
3307 /* Now condense Sover->NodeDef */
3308 i = 0; cnt = 0;
3309 for (cnt=0; cnt < Sover->N_NodeDef; ++cnt) {
3310 if (Sover->NodeDef[cnt] >= 0) {
3311 if (i<cnt) Sover->NodeDef[i] = Sover->NodeDef[cnt];
3312 ++i;
3313 }
3314 }
3315 Sover->N_NodeDef = i;
3316 SUMA_LHv(" Now at %d nodes after clustering. \n"
3317 " Last node now: %d\n",
3318 Sover->N_NodeDef,
3319 Sover->NodeDef[Sover->N_NodeDef-1]);
3320 } else { /* we have no clusters that make it, mow 'em down */
3321 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3322 if (!SV->isMasked[i]) {
3323 SV->isMasked[i] = 1;
3324 }
3325 }
3326 Sover->N_NodeDef = 0;
3327 }
3328 } else {
3329 SUMA_LH("No clustering wanted");
3330 if (Sover->ClustList) { /* kill it, not needed any more*/
3331 SUMA_LH("Clearing previous unloved clusterlist");
3332 dlist_destroy(Sover->ClustList);
3333 SUMA_free(Sover->ClustList); Sover->ClustList = NULL;
3334 if (Sover->ClustOfNode) SUMA_free(Sover->ClustOfNode);
3335 Sover->ClustOfNode = NULL;
3336 }
3337 }
3338 /* nv is no longer needed, only needed for clustering. */
3339 if (nv) SUMA_free(nv); nv = NULL;
3340
3341 /* Any need to mess with the range ? */
3342 switch(Opt->RangeUnits) {
3343 case SUMA_PERC_VALUE_UNITS:{
3344 float pr[2] = {2, 98}, prv[2], *Vsort=NULL;
3345 pr[0] = Opt->IntRange[0];
3346 pr[1] = Opt->IntRange[1];
3347 /* See comment about pre-storage of percentiles in the other
3348 place that SUMA_PercRangeVol() is used */
3349 if ((Vsort=SUMA_PercRangeVol(Sover->V, NULL, Sover->N_V, pr, 2,
3350 prv, NULL, 1, NULL))) {
3351 SUMA_ifree(Vsort);
3352 Opt->IntRange[0] = prv[0];
3353 Opt->IntRange[1] = prv[1];
3354 }
3355 Opt->RangeUnits = SUMA_NO_NUM_UNITS; /* Back to normal */
3356 break;}
3357 case SUMA_NO_NUM_UNITS:
3358 break;
3359 default:
3360 SUMA_S_Warn("Units on IntRange ignored!");
3361 break;
3362 }
3363
3364 /* colorizing */
3365 if ( (Opt->interpmode == SUMA_DIRECT)&&
3366 (SUMA_is_Label_dset(Sover->dset_link,NULL) ||
3367 SUMA_is_Label_dset_col(Sover->dset_link, Opt->find)) ) {
3368 SUMA_LH("Scaling a la HASH");
3369 if (!SUMA_ScaleToMap_alaHASH (Sover->V, SDSET_VECFILLED(Sover->dset_link),
3370 ColMap, Opt,
3371 SV) ) {
3372 SUMA_SL_Err("Failed in SUMA_ScaleToMap_alaHASH");
3373 SUMA_RETURN(NOPE);
3374 }
3375 } else if (Opt->alaAFNI) {
3376 /* a la AFNI */
3377 SUMA_LH("Scaling a la AFNI");
3378 if (!SUMA_ScaleToMap_alaAFNI (Sover->V, SDSET_VECFILLED(Sover->dset_link),
3379 SUMA_LARG_ABS(Opt->IntRange[0], Opt->IntRange[1]),
3380 ColMap, Opt,
3381 SV) ) {
3382 SUMA_SL_Err("Failed in SUMA_ScaleToMap_alaAFNI");
3383 SUMA_RETURN(NOPE);
3384 }
3385 } else {
3386 /* a la SUMA */
3387 SUMA_LHv("Scaling a la SUMA %f %f\n", Opt->IntRange[0], Opt->IntRange[1]);
3388 if (!SUMA_ScaleToMap( Sover->V, SDSET_VECFILLED(Sover->dset_link),
3389 Opt->IntRange[0], Opt->IntRange[1],
3390 ColMap, Opt,
3391 SV) ){
3392 SUMA_SL_Err("Failed in SUMA_ScaleToMap");
3393 SUMA_RETURN(NOPE);
3394 }
3395 }
3396
3397
3398 if (Opt->bind >= 0 &&
3399 (Opt->UseBrt || Sover->AlphaVal == SW_SurfCont_DsetAlphaVal_B)) {
3400 SUMA_LH("Brightness modulation needed");
3401 /* got to copy values into float vectors 'cause of possible types */
3402 B = SUMA_DsetCol2Float (Sover->dset_link, Opt->bind, 0);
3403 if (!B) { SUMA_SL_Err("Failed to get B"); SUMA_RETURN(NOPE); }
3404 /* go over B and clip it, if needed */
3405 if (Opt->BrightRange[0] && Opt->BrightRange[1]) {
3406 /* need to clip B */
3407 minB = Opt->BrightRange[0]; maxB = Opt->BrightRange[1];
3408 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3409 if (!SV->isMasked[i]) {
3410 /* worry only about unmasked colors */
3411 if (B[i] < Opt->BrightRange[0]) B[i] = Opt->BrightRange[0];
3412 else if (B[i] > Opt->BrightRange[1]) B[i] = Opt->BrightRange[1];
3413 }
3414 }
3415 } else {
3416 if (!SUMA_GetDsetColRange(Sover->dset_link, Opt->bind, Range, loc)) {
3417 SUMA_SL_Err("Failed to get ColRange!");
3418 SUMA_RETURN(NOPE);
3419 }
3420 minB = Range[0]; maxB = Range[1];
3421 }
3422 /* Now scale B and modulate colors in SV*/
3423 SUMA_LH("Scaling by B");
3424 fact = (Opt->BrightMap[1] - Opt->BrightMap[0]) / (maxB - minB);
3425 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3426 if (!SV->isMasked[i]) {
3427 /* B[i] = (B[i] - minB) * fact; SV->cV[i] = SV->cV[i] * B[i]; */
3428 i3 = 3*i;
3429 floc = (B[i] - minB) * fact + Opt->BrightMap[0];
3430 SV->cV[i3 ] = SV->cV[i3 ] * floc;
3431 SV->cV[i3 +1] = SV->cV[i3 +1] * floc;
3432 SV->cV[i3 +2] = SV->cV[i3 +2] * floc;
3433 }
3434 }
3435 }
3436
3437 /* remove any bias before NodeDef is modified */
3438 HoldBiasOpt = Opt->DoBias;
3439 /* This field gets wiped (by SUMA_RemoveCoordBias) from Opt
3440 (which is inside Sover) */
3441 if ( Opt->DoBias == SW_CoordBias_X ||
3442 Opt->DoBias == SW_CoordBias_Y ||
3443 Opt->DoBias == SW_CoordBias_Z ||
3444 Opt->DoBias == SW_CoordBias_N ) {
3445 SUMA_RemoveCoordBias(Sover);
3446 }
3447
3448 /* Do we need alpha from data (first used for Volume objects) ? */
3449 alphaval = NULL;
3450 ado = SUMA_Overlay_OwnerADO(Sover);
3451 SUMA_LH("Have ado %s of type %s, AlphaVal %d",
3452 ADO_LABEL(ado), ADO_TNAME(ado), Sover->AlphaVal);
3453 if (ado && ado->do_type == VO_type) {
3454 switch (Sover->AlphaVal) {
3455 case SW_SurfCont_DsetAlphaVal_I:
3456 if (Opt->find < 0 || !Sover->V) break;
3457 if (!(alphaval = (byte *)SUMA_calloc(
3458 SDSET_VECFILLED(Sover->dset_link), sizeof(byte)))){
3459 SUMA_S_Crit("Failed to allocate");
3460 SUMA_RETURN(NOPE);
3461 }
3462 fact = Opt->IntRange[1]-Opt->IntRange[0];
3463 if (fact == 0.0) fact = 1.0;
3464 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3465 if (!SV->isMasked[i]) {
3466 am = (Sover->V[i]-Opt->IntRange[0])/fact;
3467 if (am < 0.0) am = 0.0;
3468 else if (am > 1.0) am = 1.0;
3469 alphaval[i] = (byte)(am*255);
3470 }
3471 }
3472 break;
3473 case SW_SurfCont_DsetAlphaVal_T:
3474 if (Opt->tind < 0 || !Sover->T) break;
3475 if (!(alphaval = (byte *)SUMA_calloc(
3476 SDSET_VECFILLED(Sover->dset_link), sizeof(byte)))){
3477 SUMA_S_Crit("Failed to allocate");
3478 SUMA_RETURN(NOPE);
3479 }
3480 if (!SUMA_GetDsetColRange(Sover->dset_link, Opt->tind, Range, loc)) {
3481 SUMA_SL_Err("Failed to get ColRange!");
3482 SUMA_RETURN(NOPE);
3483 }
3484 fact = Range[1]-Range[0];
3485 if (fact == 0.0) fact = 1.0;
3486 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3487 if (!SV->isMasked[i]) {
3488 am = (Sover->T[i]-Range[0])/fact;
3489 if (am < 0.0) am = 0.0;
3490 else if (am > 1.0) am = 1.0;
3491 alphaval[i] = (byte)(am*255);
3492 }
3493 }
3494 break;
3495 case SW_SurfCont_DsetAlphaVal_B:
3496 if (Opt->bind < 0 || !B) break;
3497 if (!(alphaval = (byte *)SUMA_calloc(
3498 SDSET_VECFILLED(Sover->dset_link), sizeof(byte)))){
3499 SUMA_S_Crit("Failed to allocate");
3500 SUMA_RETURN(NOPE);
3501 }
3502 if (!SUMA_GetDsetColRange(Sover->dset_link, Opt->bind, Range, loc)) {
3503 SUMA_SL_Err("Failed to get ColRange!");
3504 SUMA_RETURN(NOPE);
3505 }
3506 fact = Range[1]-Range[0];
3507 if (fact == 0.0) fact = 1.0;
3508 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3509 if (!SV->isMasked[i]) {
3510 am = (B[i]-Range[0])/fact;
3511 if (am < 0.0) am = 0.0;
3512 else if (am > 1.0) am = 1.0;
3513 alphaval[i] = (byte)(am*255);
3514 }
3515 }
3516 break;
3517 default:
3518 /* Nothing needed */
3519 break;
3520 }
3521 }
3522 // fprintf(stderr, "%s\n", FuncName);
3523
3524
3525 /* finally copy results */
3526 SUMA_LH("Copying into NodeDef");
3527 if (nd) {
3528 cnt = 0;
3529 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3530 if (!SV->isMasked[i]) {
3531 cnt3 = 3*cnt; i3 = 3*i;
3532 Sover->NodeDef[cnt] = nd[i]; /*This is a redundant operation
3533 clustering is on. But I leave it here for clarity.
3534 Otherwise that line would have to be conditioned
3535 on the clustering options.*/
3536 Sover->ColVec[cnt3 ] = SV->cV[i3 ];
3537 Sover->ColVec[cnt3 +1] = SV->cV[i3 +1];
3538 Sover->ColVec[cnt3 +2] = SV->cV[i3 +2];
3539 if (SV->BiasCoordVec)
3540 SV->BiasCoordVec[cnt] = SV->BiasCoordVec[i];
3541 /* a compression of BiasCoordVec vector to match NodeDef */
3542 ++cnt;
3543 }
3544 }
3545 } else {
3546 cnt = 0;
3547 for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
3548 if (!SV->isMasked[i]) {
3549 cnt3 = 3*cnt; i3 = 3*i;
3550 Sover->NodeDef[cnt] = i; /* This is at times a redundant operation
3551 see above */
3552 Sover->ColVec[cnt3 ] = SV->cV[i3 ];
3553 Sover->ColVec[cnt3 +1] = SV->cV[i3 +1];
3554 Sover->ColVec[cnt3 +2] = SV->cV[i3 +2];
3555 if (SV->BiasCoordVec)
3556 SV->BiasCoordVec[cnt] = SV->BiasCoordVec[i];
3557 /* a compression of BiasCoordVec vector to match NodeDef */
3558 ++cnt;
3559 }
3560 }
3561 }
3562 Sover->N_NodeDef = cnt;
3563
3564 /* Alpha needed, only for volumes at the moment ... */
3565 if (ado && ado->do_type == VO_type) {
3566 if (!Sover->ColAlpha) {
3567 if (!(Sover->ColAlpha =
3568 (byte *)SUMA_malloc(COLP_N_ALLOC(Sover)*sizeof(byte)))) {
3569 SUMA_S_Crit("Failed to allocate");
3570 SUMA_RETURN(NOPE);
3571 }
3572 }
3573 SUMA_LH("Have AlphaVal of %d", Sover->AlphaVal);
3574 switch (Sover->AlphaVal) {
3575 default:
3576 case SW_SurfCont_DsetAlphaVal_Max:
3577 cnt=0;
3578 for(i = 0; i < SDSET_VECFILLED(Sover->dset_link); i++) {
3579 if (!SV->isMasked[i]) {
3580 i3 = 3*i;
3581 am = SUMA_MAX_PAIR(SV->cV[i3 ],SV->cV[i3+1]);
3582 am = SUMA_MAX_PAIR(am, SV->cV[i3+2]);
3583 Sover->ColAlpha[cnt] = (byte)(am*255); ++cnt;
3584 }
3585 }
3586 break;
3587 case SW_SurfCont_DsetAlphaVal_Min:
3588 cnt=0;
3589 for(i = 0; i < SDSET_VECFILLED(Sover->dset_link); i++) {
3590 if (!SV->isMasked[i]) {
3591 i3 = 3*i;
3592 am = SUMA_MIN_PAIR(SV->cV[i3 ],SV->cV[i3+1]);
3593 am = SUMA_MIN_PAIR(am, SV->cV[i3+2]);
3594 Sover->ColAlpha[cnt] = (byte)(am*255); ++cnt;
3595 }
3596 }
3597 break;
3598 case SW_SurfCont_DsetAlphaVal_Avg:
3599 cnt=0;
3600 for(i = 0; i < SDSET_VECFILLED(Sover->dset_link); i++) {
3601 if (!SV->isMasked[i]) {
3602 i3 = 3*i;
3603 am = SV->cV[i3 ]+SV->cV[i3+1]+SV->cV[i3+2];
3604 Sover->ColAlpha[cnt] = (byte)(am*85); ++cnt;
3605 }
3606 }
3607 break;
3608 case SW_SurfCont_DsetAlphaVal_I:
3609 case SW_SurfCont_DsetAlphaVal_T:
3610 case SW_SurfCont_DsetAlphaVal_B:
3611 if (alphaval) {
3612 cnt=0;
3613 for(i = 0; i < SDSET_VECFILLED(Sover->dset_link); i++) {
3614 if (!SV->isMasked[i]) {
3615 Sover->ColAlpha[cnt] = alphaval[i]; ++cnt;
3616 }
3617 }
3618 SUMA_free(alphaval); alphaval = NULL;
3619 }
3620 break;
3621 case SW_SurfCont_DsetAlphaVal_XXX:
3622 SUMA_S_Note("All zeros!");
3623 memset(Sover->ColAlpha, 0, sizeof(byte)*COLP_N_ALLOC(Sover));
3624 break;
3625 }
3626 }
3627
3628 /* Add any coord bias ? */
3629 switch (HoldBiasOpt) {
3630 case SW_CoordBias_X:
3631 SUMA_LH("Bias X");
3632 SUMA_SetCoordBias(Sover, SV->BiasCoordVec, SW_CoordBias_X);
3633 SV->BiasCoordVec = NULL;
3634 /* set SV->BiasCoordVec to NULL to keep it from being freed below */
3635 break;
3636 case SW_CoordBias_Y:
3637 SUMA_LH("Bias Y");
3638 SUMA_SetCoordBias(Sover, SV->BiasCoordVec, SW_CoordBias_Y);
3639 SV->BiasCoordVec = NULL;
3640 /* set SV->BiasCoordVec to NULL to keep it from being freed below */
3641 break;
3642 case SW_CoordBias_Z:
3643 SUMA_LH("Bias Z");
3644 SUMA_SetCoordBias(Sover, SV->BiasCoordVec, SW_CoordBias_Z);
3645 SV->BiasCoordVec = NULL;
3646 /* set SV->BiasCoordVec to NULL to keep it from being freed below */
3647 break;
3648 case SW_CoordBias_N:
3649 SUMA_LH("Bias N");
3650 SUMA_SetCoordBias(Sover, SV->BiasCoordVec, SW_CoordBias_N);
3651 SV->BiasCoordVec = NULL;
3652 /* set SV->BiasCoordVec to NULL to keep it from being freed below */
3653 break;
3654 default:
3655 SUMA_LH("Bias None");
3656 break;
3657 }
3658
3659
3660 /* Do we need to create contours */
3661 if (Opt->ColsContMode) {
3662 if (SUMA_is_Label_dset(Sover->dset_link,NULL))
3663 SUMA_ContourateDsetOverlay(Sover, NULL);
3664 else
3665 SUMA_ContourateDsetOverlay(Sover, SV);
3666 }
3667
3668
3669 if (LocalHead) {
3670 SUMA_LH("In Scale_Interactive\n**********************");
3671 /* SUMA_Show_ColorOverlayPlanes (&Sover, 1, 1); */
3672 }
3673
3674 /* update remix ID */
3675 ++Sover->RemixOID;
3676
3677 /* clean up */
3678 SUMA_LH("Cleanup, cleanup, everybody cleanup");
3679 if (B) SUMA_free(B); B = NULL;
3680 if (SV) SUMA_Free_ColorScaledVect (SV); SV = NULL;
3681 SUMA_RETURN(YUP);
3682
3683 }
3684
SUMA_ScaleToMap_alaAFNI(float * V,int N_V,float range,SUMA_COLOR_MAP * ColMap,SUMA_SCALE_TO_MAP_OPT * Opt,SUMA_COLOR_SCALED_VECT * SV)3685 SUMA_Boolean SUMA_ScaleToMap_alaAFNI ( float *V, int N_V,
3686 float range,
3687 SUMA_COLOR_MAP *ColMap,
3688 SUMA_SCALE_TO_MAP_OPT *Opt,
3689 SUMA_COLOR_SCALED_VECT * SV)
3690 {
3691 static char FuncName[]={"SUMA_ScaleToMap_alaAFNI"};
3692 int i,j, i0, i1, i3, mxColindex;
3693 float Vmin, Vmax, MinCol, MaxCol, Vrange, Vscl, r, **Mbuf= NULL;
3694 SUMA_Boolean NewMap = NOPE;
3695 SUMA_Boolean LocalHead = NOPE;
3696
3697 SUMA_ENTRY;
3698
3699 // fprintf(stderr, "%s\n", FuncName);
3700
3701 /* Autorange ?*/
3702
3703 if (range == 0.0) {
3704 /* autorange, find min-max values */
3705 Vmin = V[0]; Vmax = V[0];
3706 for (i=0; i < N_V; ++i) {
3707 if (V[i] > Vmax) Vmax = V[i];
3708 else if (V[i] < Vmin) Vmin = V[i];
3709 }
3710 } else {
3711 if (ColMap->Sgn >= 0) {
3712 Vmin = 0.0;
3713 Vmax = range;
3714 }else {
3715 Vmin = -range;
3716 Vmax = range;
3717 }
3718 }
3719
3720 if (ColMap->top_frac > 0.0f) {
3721 SUMA_LH("Using top_frac, not commonly used. ");
3722 Vmax *= ColMap->top_frac;
3723 Vmin *= ColMap->top_frac;
3724 }
3725
3726 /* find the values to be masked out */
3727 if (Opt->ApplyMask){
3728 if (Opt->MaskZero) {
3729 /* mask zeros and values in range */
3730 for (i=0; i < N_V; ++i) {
3731 if (!V[i] || ( V[i] >= Opt->MaskRange[0] &&
3732 V[i] <= Opt->MaskRange[1]) ) SV->isMasked[i] = YUP;
3733 }
3734 } else {
3735 /* don't mask zeros, just range */
3736 for (i=0; i < N_V; ++i) {
3737 if (V[i] >= Opt->MaskRange[0] && V[i] <= Opt->MaskRange[1])
3738 SV->isMasked[i] = YUP;
3739 }
3740 }
3741 } else {
3742 if (Opt->MaskZero) {
3743 /* mask zeros */
3744 for (i=0; i < N_V; ++i) {
3745 if (!V[i]) SV->isMasked[i] = YUP;
3746 }
3747 }
3748 }
3749
3750 /* go through and clip values in V to those specified in the range */
3751 if (Opt->ApplyClip) {
3752 SUMA_S_Warn("Option Opt->ApplyClip not applicable here.\nOption ignored.");
3753 }
3754 for (i=0; i < N_V; ++i) {
3755 if (!SV->isMasked[i]) { /* don't waist time on masked stuff */
3756 if (V[i] > Vmin) {
3757 /* that's cool */
3758 } else {
3759 V[i] = Vmin;
3760 }
3761
3762 if (V[i] < Vmax) {
3763 /* that's cool */
3764 } else {
3765 V[i] = Vmax;
3766 }
3767 }
3768 }
3769
3770 /* is the colormap non-linear ? */
3771 if (SUMA_NeedsLinearizing(ColMap)) {
3772 /* linearize color map */
3773 SUMA_LH("Linearizing colormap ...");
3774 NewMap = YUP;
3775 if (ColMap->frac[0] > 0 && ColMap->Sgn == -1) {
3776 SUMA_S_Warn ("Color map fractions are positive with Sgn flag = -1");
3777 }
3778 if (ColMap->frac[0] < 0 && ColMap->Sgn == 1) {
3779 SUMA_S_Warn ("Color map fractions are negative with Sgn flag = 1");
3780 }
3781 ColMap = SUMA_Linearize_Color_Map (ColMap, -1);
3782 if (LocalHead) {
3783 FILE *lincmap=NULL;
3784 int ii = 0;
3785 lincmap=fopen("./lincmap.1D", "w");
3786 if (lincmap) {
3787 SUMA_LH("Linearized map written to ./lincmap.1D");
3788 /* use simple format to allow for easy read in matlab */
3789 /* SUMA_Show_ColorMapVec (&ColMap, 1, lincmap, 2); */
3790 for (ii=ColMap->N_M[0]-1; ii >=0; --ii) {
3791 if (ColMap->N_M[1] == 4)
3792 fprintf (lincmap,
3793 "%d\t%f\t%f\t%f\t%f\n",
3794 ii, ColMap->M[ii][0], ColMap->M[ii][1],
3795 ColMap->M[ii][2], ColMap->M[ii][3]);
3796 else
3797 fprintf (lincmap,
3798 "%d\t%f\t%f\t%f\n",
3799 ii, ColMap->M[ii][0], ColMap->M[ii][1],ColMap->M[ii][2]);
3800 }
3801 fclose (lincmap); lincmap = NULL;
3802 }else {
3803 SUMA_SL_Err("Failed to write linearized colormap to file.\n"
3804 "Proceeding...");
3805 }
3806 }
3807
3808 }else {
3809 SUMA_LH("NO Linearizing of colormap deemed necessary...");
3810 NewMap = NOPE;
3811 }
3812
3813 /* if brightness factor is given, apply it to color map and mask color */
3814 Mbuf = NULL;
3815 if (Opt->BrightFact <= 0 || Opt->BrightFact > 2) {
3816 SUMA_S_Warn("Opt->BrightFact must be between ]0 2]. Defaulting to 1\n");
3817 Opt->BrightFact = 1.0f;
3818 }
3819 {
3820 if (Opt->BrightFact != 1.0f) {
3821 Mbuf = ColMap->M; /* save pointer */
3822 ColMap->M = (float **)SUMA_allocate2D( ColMap->N_M[0],
3823 ColMap->N_M[1], sizeof(float));
3824 for (i=0; i < ColMap->N_M[0]; ++i) {
3825 ColMap->M[i][0] = Mbuf[i][0] * Opt->BrightFact;
3826 if (ColMap->M[i][0] > 1.0) ColMap->M[i][0] = 1.0; /* Bright Fact
3827 could be > 1.0 now */
3828 ColMap->M[i][1] = Mbuf[i][1] * Opt->BrightFact;
3829 if (ColMap->M[i][1] > 1.0) ColMap->M[i][1] = 1.0;
3830 ColMap->M[i][2] = Mbuf[i][2] * Opt->BrightFact;
3831 if (ColMap->M[i][2] > 1.0) ColMap->M[i][2] = 1.0;
3832 if (ColMap->N_M[1] == 4) {
3833 ColMap->M[i][3] = Mbuf[i][3] * Opt->BrightFact;
3834 if (ColMap->M[i][3] > 1.0) ColMap->M[i][3] = 1.0;
3835 }
3836 }
3837 /* now for the mask color */
3838 Opt->MaskColor[0] *= Opt->BrightFact;
3839 if (Opt->MaskColor[0] > 1.0) Opt->MaskColor[0] = 1.0;
3840 Opt->MaskColor[1] *= Opt->BrightFact;
3841 if (Opt->MaskColor[1] > 1.0) Opt->MaskColor[1] = 1.0;
3842 Opt->MaskColor[2] *= Opt->BrightFact;
3843 if (Opt->MaskColor[2] > 1.0) Opt->MaskColor[2] = 1.0;
3844 if (ColMap->N_M[1] == 4) { /* MaskColor[3] is never used, oh well...*/
3845 Opt->MaskColor[3] *= Opt->BrightFact;
3846 if (Opt->MaskColor[3] > 1.0) Opt->MaskColor[3] = 1.0;
3847 }
3848 }
3849 }
3850
3851 if ( Opt->interpmode != SUMA_DIRECT &&
3852 Opt->interpmode != SUMA_NO_INTERP && Opt->interpmode != SUMA_INTERP) {
3853 fprintf (SUMA_STDERR,
3854 "Error %s: Opt->interpmode is incorrectly specifed (%d).\n",
3855 FuncName, Opt->interpmode);
3856 SUMA_RETURN(NOPE);
3857 }
3858
3859 if (Opt->interpmode == SUMA_INTERP || Opt->interpmode == SUMA_NO_INTERP) {
3860 /* Now go through values and interpolate onto index of colormap */
3861 MinCol = 0.0; MaxCol = (float)ColMap->N_M[0];
3862 Vrange = Vmax - Vmin;
3863 if (LocalHead)
3864 fprintf(SUMA_STDERR,
3865 "%s: [Vrange, Vmax, Vmin] = [%f, %f, %f]\nInterpMode=%d\n",
3866 FuncName, Vrange, Vmax, Vmin, Opt->interpmode);
3867 if (Vrange < 0) {
3868 fprintf (SUMA_STDERR,
3869 "Error %s: Vmax (%f)< Vmin(%f).\n", FuncName, Vmax, Vmin);
3870 SUMA_RETURN (NOPE);
3871 }
3872
3873 if (Vrange > 0) {
3874 mxColindex = ColMap->N_M[0] -1;
3875 if (Opt->interpmode == SUMA_NO_INTERP) {
3876 SUMA_LH("No_Interp mode");
3877 for (i=0; i < N_V; ++i) {
3878 i3 = 3*i;
3879 if (!SV->isMasked[i]) {
3880 Vscl = (V[i] - Vmin) / Vrange * ColMap->N_M[0];
3881 /* used mxColindex instead of N_M[0] (wrong!)
3882 prior to Oct 22, 03 */
3883 if (Vscl < 0) Vscl = 0;
3884 if (Vscl > ColMap->N_M[0]) Vscl = ColMap->N_M[0];
3885 /* This happens when your Min--Max are within the
3886 boundaries of the data's (V[i]) min to max */
3887 i0 = (int)(Vscl);
3888 if (i0 > mxColindex) i0 = mxColindex;
3889 /* No need, Vscl's clipping takes care of that:
3890 if (i0 < 0) i0 = 0; */
3891 if (LocalHead) {
3892 fprintf(SUMA_STDERR,
3893 "%s: %f-->%f: Colmap index is %d\n",
3894 FuncName, V[i], Vscl, i0);
3895 }
3896 if (ColMap->M[i0][0] >= 0) { /* good color */
3897 SV->cV[i3 ] = ColMap->M[i0][0];
3898 SV->cV[i3+1] = ColMap->M[i0][1];
3899 SV->cV[i3+2] = ColMap->M[i0][2];
3900 } else { /* mask color */
3901 SV->isMasked[i] = YUP;
3902 SV->cV[i3 ] = Opt->MaskColor[0];
3903 SV->cV[i3+1] = Opt->MaskColor[1];
3904 SV->cV[i3+2] = Opt->MaskColor[2];
3905 }
3906 } else {
3907 SV->cV[i3 ] = Opt->MaskColor[0];
3908 SV->cV[i3+1] = Opt->MaskColor[1];
3909 SV->cV[i3+2] = Opt->MaskColor[2];
3910 }
3911 if (LocalHead) {
3912 fprintf(SUMA_STDERR,
3913 "%s: %f-->[%f %f %f]\n", FuncName,
3914 V[i], SV->cV[i3 ], SV->cV[i3+1], SV->cV[i3+2]);
3915 }
3916 }
3917 } else {
3918 SUMA_LH("Interp mode");
3919 for (i=0; i < N_V; ++i) {
3920 i3 = 3*i;
3921 if (!SV->isMasked[i]) {
3922 Vscl = (V[i] - Vmin) / Vrange * ColMap->N_M[0];
3923 /* used mxColindex instead of N_M[0] (wrong!)
3924 prior to Oct 22, 03 */
3925 if (Vscl < 0) Vscl = 0;
3926 if (Vscl > ColMap->N_M[0]) Vscl = ColMap->N_M[0];
3927 /* This happens when your Min--Max are within the
3928 boundaries of the data's (V[i]) min to max */
3929 /*now linearly interpolate between the two closest colors
3930 in the color map */
3931 i0 = (int)(Vscl);
3932 if (i0 > mxColindex) i0 = mxColindex;
3933 /* No need, Vscl's clipping takes care of that:
3934 if (i0 < 0) i0 = 0; */
3935 i1=i0+1;
3936
3937 if (ColMap->M[i0][0] >= 0) { /* good color */
3938 if (i1 < ColMap->N_M[0]) {
3939 r = Vscl - i0;
3940 /*fprintf (SUMA_STDERR,
3941 "i0 = %d, i1 = %d, Vscl = %f, r= %f Col[i0] = %f %f %f\n",
3942 i0, i1, Vscl, r, ColMap->M[i0][0],
3943 ColMap->M[i0][1], ColMap->M[i0][2]);*/
3944
3945 SV->cV[i3 ] = ColMap->M[i0][0] + r *
3946 (ColMap->M[i1][0] - ColMap->M[i0][0]);
3947 SV->cV[i3+1] = ColMap->M[i0][1] + r *
3948 (ColMap->M[i1][1] - ColMap->M[i0][1]);
3949 SV->cV[i3+2] = ColMap->M[i0][2] + r *
3950 (ColMap->M[i1][2] - ColMap->M[i0][2]);
3951 } else {
3952 SV->cV[i3 ] = ColMap->M[i0][0];
3953 SV->cV[i3+1] = ColMap->M[i0][1];
3954 SV->cV[i3+2] = ColMap->M[i0][2];
3955 }
3956 } else { /* mask color */
3957 SV->isMasked[i] = YUP;
3958 SV->cV[i3 ] = Opt->MaskColor[0];
3959 SV->cV[i3+1] = Opt->MaskColor[1];
3960 SV->cV[i3+2] = Opt->MaskColor[2];
3961 }
3962 } else {
3963 SV->cV[i3 ] = Opt->MaskColor[0];
3964 SV->cV[i3+1] = Opt->MaskColor[1];
3965 SV->cV[i3+2] = Opt->MaskColor[2];
3966 }
3967 }
3968 }
3969 } else { /* all values are equal, use the middle color in the colormap */
3970 if (LocalHead)
3971 fprintf (SUMA_STDOUT,
3972 "Warning %s: Node value range is 0,"
3973 " using middle color in colormap.\n", FuncName);
3974 i0 = (ColMap->N_M[0] - 1)/2;
3975 for (i=0; i < N_V; ++i) {
3976 i3 = 3*i;
3977 if (!SV->isMasked[i]) {
3978 if (ColMap->M[i0][0] >= 0) {
3979 SV->cV[i3 ] = ColMap->M[i0][0];
3980 SV->cV[i3+1] = ColMap->M[i0][1];
3981 SV->cV[i3+2] = ColMap->M[i0][2];
3982 } else {
3983 SV->isMasked[i] = YUP;
3984 SV->cV[i3 ] = Opt->MaskColor[0];
3985 SV->cV[i3+1] = Opt->MaskColor[1];
3986 SV->cV[i3+2] = Opt->MaskColor[2];
3987 }
3988 } else {
3989 SV->cV[i3 ] = Opt->MaskColor[0];
3990 SV->cV[i3+1] = Opt->MaskColor[1];
3991 SV->cV[i3+2] = Opt->MaskColor[2];
3992 }
3993 }
3994 }
3995 } else {
3996 /* direct color mapping */
3997 SUMA_LH("Direct colormapping");
3998 if (Opt->interpmode != SUMA_DIRECT) {
3999 fprintf (SUMA_STDOUT,
4000 "Error %s: Logic error, should never get here with"
4001 " Opt->interpmode != SUMA_DIRECT\n", FuncName);
4002 SUMA_RETURN(NOPE);
4003 }
4004 for (i=0; i < N_V; ++i) {
4005 i3 = 3*i;
4006 if (!SV->isMasked[i]) {
4007 i0 = (int)V[i];
4008 if (i0 < 0) i0 = 0;
4009 else if (i0 >= ColMap->N_M[0]) i0 = ColMap->N_M[0] -1;
4010 if (ColMap->M[i0][0] >= 0) {
4011 SV->cV[i3 ] = ColMap->M[i0][0];
4012 SV->cV[i3+1] = ColMap->M[i0][1];
4013 SV->cV[i3+2] = ColMap->M[i0][2];
4014 } else {
4015 SV->isMasked[i] = YUP;
4016 SV->cV[i3 ] = Opt->MaskColor[0];
4017 SV->cV[i3+1] = Opt->MaskColor[1];
4018 SV->cV[i3+2] = Opt->MaskColor[2];
4019 }
4020 } else {
4021 SV->cV[i3 ] = Opt->MaskColor[0];
4022 SV->cV[i3+1] = Opt->MaskColor[1];
4023 SV->cV[i3+2] = Opt->MaskColor[2];
4024 }
4025
4026 }
4027 }
4028 if (Mbuf) {
4029 /* free what is in ColMap->M */
4030 SUMA_free2D((char **)ColMap->M, ColMap->N_M[0]);
4031 ColMap->M = Mbuf; Mbuf = NULL;
4032 }
4033 if (NewMap) {
4034 SUMA_LH("Freeing linearized colormap.");
4035 SUMA_Free_ColorMap (ColMap);
4036 }
4037
4038 SUMA_RETURN (YUP);
4039
4040 }
4041
4042 /* Change a colormap to NIML format */
SUMA_CmapToNICmap(SUMA_COLOR_MAP * CM)4043 NI_group *SUMA_CmapToNICmap(SUMA_COLOR_MAP *CM)
4044 {
4045 static char FuncName[]={"SUMA_CmapToNICmap"};
4046 NI_group *ngr=NULL;
4047 NI_element *nel = NULL;
4048 SUMA_DSET *dset=NULL;
4049 float *fbuf=NULL;
4050 int *ibuf = NULL;
4051 int i;
4052 SUMA_PARSED_NAME *sname = NULL;
4053 SUMA_Boolean LocalHead = NOPE;
4054
4055 SUMA_ENTRY;
4056
4057 // fprintf(stderr, "%s\n", FuncName);
4058
4059 if (!CM) SUMA_RETURN(ngr);
4060
4061 /* bufer space */
4062 fbuf = (float *)SUMA_calloc(CM->N_M[0],sizeof(float));
4063 ibuf = (int *)SUMA_calloc(CM->N_M[0],sizeof(int));
4064
4065 /* create group and name it */
4066 sname = SUMA_ParseFname(CM->Name, NULL);
4067 dset = SUMA_CreateDsetPointer(sname->FileName, SUMA_LABEL_TABLE_OBJECT,
4068 NULL, NULL, CM->N_M[0]);
4069
4070 /* Go for it */
4071 for (i=0; i<CM->N_M[0]; ++i) fbuf[i] = CM->M[i][0];
4072 if (!SUMA_AddDsetNelCol(dset, "R", SUMA_NODE_R, (void *)fbuf, NULL, 1)) {
4073 SUMA_S_Err("Failed to add R");
4074 SUMA_FreeDset(dset); dset = NULL;
4075 goto CLEANUP;
4076 }
4077
4078 for (i=0; i<CM->N_M[0]; ++i) fbuf[i] = CM->M[i][1];
4079 if (!SUMA_AddDsetNelCol(dset, "G", SUMA_NODE_G, (void *)fbuf, NULL, 1)) {
4080 SUMA_S_Err("Failed to add G");
4081 SUMA_FreeDset(dset); dset = NULL;
4082 goto CLEANUP;
4083 }
4084
4085 for (i=0; i<CM->N_M[0]; ++i) fbuf[i] = CM->M[i][2];
4086 if (!SUMA_AddDsetNelCol(dset, "B", SUMA_NODE_B, (void *)fbuf, NULL, 1)) {
4087 SUMA_S_Err("Failed to add B");
4088 SUMA_FreeDset(dset); dset = NULL;
4089 goto CLEANUP;
4090 }
4091
4092 if (CM->N_M[1] == 4) {
4093 for (i=0; i<CM->N_M[0]; ++i) fbuf[i] = CM->M[i][3];
4094 if (!SUMA_AddDsetNelCol(dset, "A", SUMA_NODE_A, (void *)fbuf, NULL, 1)) {
4095 SUMA_S_Err("Failed to add A");
4096 SUMA_FreeDset(dset); dset = NULL;
4097 goto CLEANUP;
4098 }
4099 }
4100
4101 if (CM->idvec) {
4102 if (!SUMA_AddDsetNelCol(dset, "key", SUMA_NODE_ILABEL,
4103 (void *)CM->idvec, NULL, 1)) {
4104 SUMA_S_Err("Failed to add idvec");
4105 SUMA_FreeDset(dset); dset = NULL;
4106 goto CLEANUP;
4107 }
4108 }
4109
4110 if (CM->cname) {
4111 if (!SUMA_AddDsetNelCol(dset, "name", SUMA_NODE_SLABEL,
4112 (void *)CM->cname, NULL, 1)) {
4113 SUMA_S_Err("Failed to add cname");
4114 SUMA_FreeDset(dset); dset = NULL;
4115 goto CLEANUP;
4116 }
4117 }
4118
4119 if (CM->frac) {
4120 if (!SUMA_AddDsetNelCol(dset, "fraction", SUMA_NODE_FLOAT,
4121 (void *)CM->frac, NULL, 1)) {
4122 SUMA_S_Err("Failed to add frac");
4123 SUMA_FreeDset(dset); dset = NULL;
4124 goto CLEANUP;
4125 }
4126 }
4127
4128 /* the little people */
4129 NI_SET_INT(dset->ngr, "flipped", (int)CM->flipped);
4130 NI_SET_INT(dset->ngr, "Sgn", CM->Sgn);
4131 NI_SET_FLOAT(dset->ngr, "top_frac", CM->top_frac);
4132 NI_SET_FLOATv(dset->ngr, "M0", CM->M0, CM->N_M[1]);
4133 NI_set_attribute(dset->ngr, "Name", sname->FileName_NoExt);
4134
4135 /* So this is not really a dset, but it was nice to make use of
4136 dset utility functions. Now cleanup a little */
4137 /* remove ugly inel */
4138 NI_remove_from_group(dset->ngr, dset->inel);
4139 NI_free_element(dset->inel); dset->inel=NULL;
4140
4141 /* grab ngr from dset, it is all we need */
4142 ngr = dset->ngr; dset->ngr = NULL;
4143 /* change name from AFNI_dataset to AFNI_labeltable */
4144 NI_rename_group(ngr, "AFNI_labeltable");
4145 /* get rid of dset */
4146 dset->dnel = NULL; SUMA_FreeDset(dset); dset=NULL;
4147
4148
4149 CLEANUP:
4150 if (fbuf) SUMA_free(fbuf);
4151 if (ibuf) SUMA_free(ibuf);
4152 if (sname) sname = SUMA_Free_Parsed_Name(sname);
4153
4154 SUMA_RETURN(ngr);
4155 }
4156
4157 /*! \brief Create a colormap for a label dset if one does not
4158 exist already
4159 dset is a legitimate Label Dset (is_Label_dset = 1)
4160 ThisCmap: If Not NULL, then use this colormap for sure
4161 If NULL, then pick a default one.
4162
4163 The function returns the colormap in NI format.
4164 But it is already stuck in dset.
4165
4166 If alaafni == 1, then the mapping of colors is done so that
4167 a volume (or labeled cortical areas) appear as they would
4168 when colored as an atlas in AFNI. In AFNI an atlas value
4169 of 1 maps to the very first color (0) or the colormap, while
4170 in SUMA, under direct mode, the very first color (0) maps to
4171 a value of 0. The problem with having alaafni always set to
4172 1 is that the plan only works if the maximum value is 255.
4173 Otherwise, you run out of colors, even if the number of
4174 unique values is less than 256
4175
4176 If alaafni == 0, then the mapping is done as it used to be
4177 before this option was added. This allows SUMA to displays 256 unique values
4178 regardless of whether or not they are <= 255.
4179
4180 If alaafni == -1, then try to match AFNI whenever possible
4181
4182 */
SUMA_CreateCmapForLabelDset(SUMA_DSET * dset,SUMA_COLOR_MAP * ThisCmap,int alaafni)4183 NI_group * SUMA_CreateCmapForLabelDset(SUMA_DSET *dset,
4184 SUMA_COLOR_MAP *ThisCmap, int alaafni)
4185 {
4186 static char FuncName[]={"SUMA_CreateCmapForLabelDset"};
4187 int *idvec_hold=NULL, iii;
4188 char **cname_hold=NULL, stmp[256], *buf=NULL;
4189 int cnt=0, i, N_unq, *unq=NULL, cc;
4190 NI_group *ngr = NULL, *NIcmap=NULL;
4191 NI_element *nel=NULL;
4192 SUMA_COLOR_MAP *cmap=NULL, *cmapi=NULL;
4193 SUMA_Boolean LocalHead = NOPE;
4194 ATLAS_POINT_LIST *apl=NULL;
4195
4196 SUMA_ENTRY;
4197
4198 // fprintf(stderr, "%s\n", FuncName);
4199
4200 if ((ngr = SUMA_NI_Cmap_of_Dset(dset))) {
4201 SUMA_RETURN(ngr);
4202 }
4203
4204 if (!ThisCmap) {
4205 SUMA_LH("Producing uniques");
4206 if ((nel = SUMA_FindDsetAttributeElement( dset, "ATLAS_LABEL_TABLE"))) {
4207 SUMA_NEL_GET_STRING(nel, 0, 0, buf);
4208 if (LocalHead) SUMA_ShowNel(nel);
4209 if (!(ngr = (NI_group *)NI_read_element_fromstring(buf))) {
4210 fprintf(stderr,"** WARNING: Poorly formatted ATLAS_LABEL_TABLE\n");
4211 } else {
4212 apl = niml_atlas_label_table_to_atlas_list(ngr);
4213 NI_free_element(ngr); ngr = NULL;
4214 }
4215 } else if ((nel = SUMA_FindDsetAttributeElement(
4216 dset, "VALUE_LABEL_DTABLE"))) {
4217 Dtable *dtbl = NULL;
4218 SUMA_NEL_GET_STRING(nel, 0, 0, buf);
4219 if (!(dtbl = Dtable_from_nimlstring(buf))) {
4220 fprintf(stderr,"** WARNING: Poorly formatted VALUE_LABEL_DTABLE");
4221 } else {
4222 apl = label_table_to_atlas_point_list(dtbl);
4223 destroy_Dtable(dtbl); dtbl = NULL;
4224 }
4225
4226 }
4227 unq = SUMA_UniqueValuesInLabelDset(dset, &N_unq);
4228 if (!(cmapi = SUMA_FindNamedColMap("ROI_i256"))) {
4229 SUMA_S_Errv("Found no colmap %s in %p\n", "ROI_i256", SUMAg_CF->scm);
4230 SUMA_Show_ColorMapVec (SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps,
4231 NULL, 1);
4232 SUMA_RETURN(NULL);
4233 }
4234 if (!unq || N_unq > cmapi->N_M[0]) {
4235 SUMA_S_Errv("Either no unique values or too many of them:\n"
4236 " %p, %d (%d)\n", unq, N_unq, cmapi->N_M[0]);
4237 SUMA_RETURN(NULL);
4238 }
4239
4240 if (alaafni == -1) {
4241 if (unq[N_unq-1]<255) alaafni = 1;
4242 else alaafni = 0;
4243 }
4244
4245 /* override */
4246 if (SUMA_isEnv("SUMA_Classic_Label_Colors","YES")) {
4247 alaafni = 0;
4248 }
4249
4250 if (!alaafni) cmap = cmapi;
4251 else {
4252 snprintf(stmp, 254,"%s_%s",SDSET_LABEL(dset),cmapi->Name);
4253 cmap = SUMA_DuplicateColorMap (cmapi, stmp);
4254 }
4255
4256 /* add a new key, and names. But first preserve the past. */
4257 SUMA_LH("Doing the key stuff");
4258 idvec_hold = cmap->idvec;
4259 cname_hold = cmap->cname;
4260 /* Now get a new key */
4261 cmap->idvec = (int *)SUMA_calloc(cmap->N_M[0], sizeof(int));
4262 cmap->cname = (char **)SUMA_calloc(cmap->N_M[0], sizeof(char *));
4263 cnt = 0;
4264 for (i=0; i<N_unq; ++i) {
4265 if (unq[i]) {
4266 cmap->idvec[cnt] = unq[i];
4267 if (!apl) {
4268 sprintf(stmp, "ROI_%04d", cmap->idvec[cnt]);
4269 cmap->cname[cnt] = SUMA_copy_string(stmp);
4270 } else {
4271 for (iii=0; iii<apl->n_points; ++iii) {
4272 if (apl->at_point[iii].okey == unq[i]) {
4273 cmap->cname[cnt] =
4274 SUMA_copy_string(apl->at_point[iii].name) ;
4275 SUMA_LH("Yeehaw %s", apl->at_point[iii].name);
4276 break;
4277 }
4278 }
4279 if (!cmap->cname[cnt]) {
4280 sprintf(stmp, "ROI_%04d", cmap->idvec[cnt]);
4281 cmap->cname[cnt] = SUMA_copy_string(stmp);
4282 }
4283 }
4284 if (alaafni) {
4285 cc = unq[i]-1; if (cc<0) cc=0; if (cc>255) cc=255;
4286 cc = 255-cc;
4287 cmap->M[cnt][0] = cmapi->M[cc][0];
4288 cmap->M[cnt][1] = cmapi->M[cc][1];
4289 cmap->M[cnt][2] = cmapi->M[cc][2];
4290 cmap->M[cnt][3] = cmapi->M[cc][3];
4291 }
4292 ++ cnt;
4293 }
4294 }
4295 /* fill the rest */
4296 SUMA_LH("padding");
4297 for (i=cnt; i<cmap->N_M[0]; ++i) {
4298 cmap->idvec[i] = cmap->idvec[i-1]+1;
4299 sprintf(stmp, "ROI_%04d", cmap->idvec[i]);
4300 cmap->cname[i] = SUMA_copy_string(stmp);
4301 }
4302
4303 /* change to NI form */
4304 NIcmap = SUMA_CmapToNICmap (cmap);
4305
4306 /* and put things back in place in cmap */
4307 SUMA_LH("tidy up");
4308 SUMA_free(cmap->idvec); cmap->idvec = idvec_hold; idvec_hold=NULL;
4309 for (i=0; i<cmap->N_M[0]; ++i) {
4310 if (cmap->cname[i]) SUMA_free(cmap->cname[i]);
4311 }
4312 SUMA_free(cmap->cname); cmap->cname = cname_hold; cname_hold=NULL;
4313
4314 if (cmapi != cmap) SUMA_Free_ColorMap(cmap);
4315 } else {
4316 cmap = ThisCmap;
4317 SUMA_LH("Got cmap, checking it out");
4318 /* check */
4319 if (!SUMA_IsCmapOKForLabelDset(dset, cmap)) {
4320 SUMA_S_Err("Provided cmap is no good ");
4321 SUMA_RETURN(NULL);
4322 }
4323 NIcmap = SUMA_CmapToNICmap (cmap);
4324 }
4325
4326 if (!NIcmap) {
4327 SUMA_S_Err("Have no cmap!");
4328 SUMA_RETURN(NULL);
4329 }
4330
4331 /* Now stick in the colormap */
4332 NI_add_to_group(dset->ngr, (void*)NIcmap);
4333
4334 SUMA_RETURN(NIcmap);
4335 }
4336
SUMA_IsCmapOKForLabelDset(SUMA_DSET * dset,SUMA_COLOR_MAP * cmap)4337 SUMA_Boolean SUMA_IsCmapOKForLabelDset(SUMA_DSET *dset, SUMA_COLOR_MAP *cmap)
4338 {
4339 static char FuncName[]={"SUMA_IsCmapOKForLabelDset"};
4340 int i, *unq=NULL, N_unq=0;
4341 SUMA_Boolean LocalHead = NOPE;
4342
4343 SUMA_ENTRY;
4344
4345 // fprintf(stderr, "%s\n", FuncName);
4346
4347 if (!cmap) {
4348 SUMA_LH("NULL cmap");
4349 SUMA_RETURN(NOPE);
4350 }
4351
4352 if (!cmap->idvec || !cmap->cname) {
4353 SUMA_LH("Submitted cmap has no cnames or idvec ");
4354 SUMA_RETURN(NOPE);
4355 }
4356
4357 if (!SUMA_is_Label_dset(dset, NULL)) {
4358 SUMA_LH("Not a label dset");
4359 SUMA_RETURN(NOPE);
4360 }
4361
4362 /* do not free unq */
4363 unq = SUMA_UniqueValuesInLabelDset(dset, &N_unq);
4364
4365 if (!unq) {
4366 SUMA_S_Err("Cannot get unique set ");
4367 SUMA_RETURN(NOPE);
4368 }
4369
4370 if (N_unq > cmap->N_M[0]) {
4371 SUMA_S_Errv( "Have %d unique values, \n"
4372 "have no colormap big enough for this\n", N_unq);
4373 SUMA_RETURN(NOPE);
4374 }
4375 if (!cmap->idvec || !cmap->cname) {
4376 SUMA_S_Err("Submitted cmap has no cnames or idvec ");
4377 SUMA_RETURN(NOPE);
4378 }
4379 /* check if all unique entries are covered .... */
4380 if (N_unq > cmap->N_M[0]) {
4381 SUMA_S_Errv( "Have %d unique values, \n"
4382 "Submitted colormap is bad\n", N_unq);
4383 SUMA_RETURN(NOPE);
4384 }
4385
4386 if (!cmap->chd) {
4387 if (!SUMA_CreateCmapHash(cmap)) {
4388 SUMA_S_Err("Cannot create hash.");
4389 SUMA_RETURN(NOPE);
4390 }
4391 }
4392 for (i=0; i<N_unq; ++i) {
4393 if (SUMA_ColMapKeyIndex(unq[i], cmap) < 0) {
4394 SUMA_S_Errv("Key[%d] %d has no entry in cmap %s\n", i, unq[i], cmap->Name);
4395 SUMA_RETURN(NOPE);
4396 }
4397 }
4398
4399 SUMA_RETURN(YUP);
4400 }
4401
4402 /* Change a dataset with one integer valued column to a
4403 Label type dset. Note that dset itself is modified.
4404 */
SUMA_dset_to_Label_dset_cmap(SUMA_DSET * dset,SUMA_COLOR_MAP * cmap)4405 int SUMA_dset_to_Label_dset_cmap(SUMA_DSET *dset, SUMA_COLOR_MAP *cmap)
4406 {
4407 static char FuncName[]={"SUMA_dset_to_Label_dset_cmap"};
4408 int ctp, vtp, i, *unq=NULL, N_unq=0;
4409 NI_group *NIcmap=NULL, *ngr=NULL;
4410 char stmp[256], *lbli=NULL, *attname=NULL;
4411 SUMA_Boolean LocalHead = NOPE;
4412
4413 SUMA_ENTRY;
4414
4415 // fprintf(stderr, "%s\n", FuncName);
4416
4417 if (!SUMA_dset_to_Label_dset(dset)) { SUMA_RETURN(0); }
4418
4419 /* Prep the colormap. */
4420 {
4421 if (!(ngr = SUMA_CreateCmapForLabelDset(dset, cmap, -1))) {
4422 SUMA_S_Err("Failed to add colormap");
4423 SUMA_RETURN(0);
4424 }
4425 }
4426
4427 SUMA_RETURN(1);
4428 }
4429
SUMA_NICmapToCmap(NI_group * ngr)4430 SUMA_COLOR_MAP *SUMA_NICmapToCmap(NI_group *ngr)
4431 {
4432 static char FuncName[]={"SUMA_NICmapToCmap"};
4433 int i, *id=NULL;
4434 float *r=NULL, *g=NULL, *b=NULL, *a=NULL;
4435 char **s=NULL;
4436 SUMA_COLOR_MAP *CM=NULL;
4437 SUMA_DSET dset;
4438 SUMA_Boolean LocalHead = NOPE;
4439
4440 SUMA_ENTRY;
4441
4442 // fprintf(stderr, "%s\n", FuncName);
4443
4444 if (!ngr) SUMA_RETURN(CM);
4445
4446 /* shoehorn into dset struct */
4447 dset.ngr = ngr;
4448 dset.inel = dset.dnel = NULL;
4449 dset.dnel = SUMA_FindDsetDataElement(&dset);
4450
4451 if (SDSET_TYPE((&dset)) != SUMA_LABEL_TABLE_OBJECT) {
4452 SUMA_S_Errv("Not a colormap object (%d,%d)\n",
4453 SDSET_TYPE((&dset)), SUMA_LABEL_TABLE_OBJECT);
4454 SUMA_RETURN(CM);
4455 }
4456 SUMA_LH("Alloc");
4457 CM = (SUMA_COLOR_MAP *)SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
4458 CM->N_M[0] = dset.dnel->vec_len;
4459 CM->N_M[1] = 0; /* don't know yet */
4460 SUMA_LH("locate");
4461 for (i=0; i<dset.dnel->vec_num; ++i) {
4462 switch (SUMA_TypeOfDsetColNumb(&dset, i)) {
4463 case SUMA_NODE_R:
4464 r = (float*)dset.dnel->vec[i];
4465 break;
4466 case SUMA_NODE_G:
4467 g = (float*)dset.dnel->vec[i];
4468 break;
4469 case SUMA_NODE_B:
4470 b = (float*)dset.dnel->vec[i];
4471 break;
4472 case SUMA_NODE_A:
4473 a = (float*)dset.dnel->vec[i];
4474 break;
4475 case SUMA_NODE_ILABEL:
4476 id = (int *)dset.dnel->vec[i];
4477 break;
4478 case SUMA_NODE_SLABEL:
4479 s = (char **)dset.dnel->vec[i];
4480 break;
4481 default:
4482 SUMA_S_Errv("Bad column (#%d) type %d for colormap\n",
4483 i, SUMA_TypeOfDsetColNumb(&dset, i));
4484 SUMA_Free_ColorMap(CM); CM = NULL;
4485 SUMA_RETURN(CM);
4486 }
4487 }
4488 if (a) CM->N_M[1] = 4; /*rgba*/
4489 else CM->N_M[1] = 3; /*rgb*/
4490 if (!r || !g || !b) {
4491 SUMA_S_Err("Missing columns");
4492 SUMA_Free_ColorMap(CM); CM = NULL;
4493 SUMA_RETURN(CM);
4494 }
4495
4496 SUMA_LH("Fill");
4497 CM->M = (float **)SUMA_allocate2D(CM->N_M[0], CM->N_M[1], sizeof(float));
4498 for (i=0; i<CM->N_M[0]; ++i) {
4499 CM->M[i][0] = r[i];
4500 CM->M[i][1] = g[i];
4501 CM->M[i][2] = b[i];
4502 }
4503 if (a) {
4504 for (i=0; i<CM->N_M[0]; ++i) CM->M[i][3] = a[i];
4505 }
4506 if (s) {
4507 CM->cname = (char **)SUMA_calloc(CM->N_M[0], sizeof(char *));
4508 for (i=0; i<CM->N_M[0]; ++i) CM->cname[i] = SUMA_copy_string(s[i]);
4509 }
4510 if (id) {
4511 CM->idvec = (int *)SUMA_calloc(CM->N_M[0], sizeof(int));
4512 for (i=0; i<CM->N_M[0]; ++i) CM->idvec[i] = id[i];
4513 }
4514
4515 NI_GET_INT(ngr, "flipped", i); CM->flipped = (byte)i;
4516 NI_GET_INT(ngr, "Sgn", CM->Sgn);
4517 NI_GET_FLOAT(ngr, "top_frac", CM->top_frac);
4518 NI_GET_FLOATv(ngr, "M0", CM->M0, CM->N_M[1], 1);
4519
4520 CM->Name = SUMA_copy_string(NI_get_attribute(ngr,"Name"));
4521
4522 SUMA_RETURN(CM);
4523 }
4524 /*!
4525 \brief Return the index into a colormap's color array
4526 given a color's key (or id).
4527 This function will be called a trillion times, do not
4528 put fancy stuff in it, or just use macro
4529 \sa faster macro SUMA_COLMAPKEYTOINDEX
4530 */
SUMA_ColMapKeyIndex(int key,SUMA_COLOR_MAP * CM)4531 int SUMA_ColMapKeyIndex(int key, SUMA_COLOR_MAP *CM)
4532 {
4533 static char FuncName[]={"SUMA_ColMapKeyIndex"};
4534 SUMA_COLOR_MAP_HASH_DATUM *hd=NULL;
4535 SUMA_ENTRY;
4536
4537 // fprintf(stderr, "%s\n", FuncName);
4538
4539 if (!CM || !CM->chd) SUMA_RETURN(-1);
4540
4541 SUMA_COLMAPKEYTOINDEX(key, CM->chd, hd);
4542
4543 SUMA_RETURN(key);
4544 }
4545 /* destroy the hash table of the colormap */
SUMA_DestroyCmapHash(SUMA_COLOR_MAP * SM)4546 SUMA_Boolean SUMA_DestroyCmapHash(SUMA_COLOR_MAP *SM)
4547 {
4548 static char FuncName[]={"SUMA_DestroyCmapHash"};
4549 SUMA_COLOR_MAP_HASH_DATUM *hd=NULL;
4550
4551 SUMA_ENTRY;
4552
4553 // fprintf(stderr, "%s\n", FuncName);
4554
4555 if (!SM || !SM->chd) SUMA_RETURN(YUP);
4556
4557 /* destroy all of the hash table */
4558 while (SM->chd) {
4559 hd = SM->chd; /* will delete the head of the hash table list */
4560 HASH_DEL( SM->chd, hd); /* remove the head from the list, after
4561 this macro, SM->chd points to the next
4562 item in the list; the new head */
4563 SUMA_free(hd); hd = NULL; /* free hd, no longer needed */
4564 }
4565
4566 SUMA_RETURN(YUP);
4567 }
4568 /* create a new or recreate a colormap's hashtable */
SUMA_CreateCmapHash(SUMA_COLOR_MAP * SM)4569 SUMA_Boolean SUMA_CreateCmapHash(SUMA_COLOR_MAP *SM)
4570 {
4571 static char FuncName[]={"SUMA_CreateCmapHash"};
4572 SUMA_COLOR_MAP_HASH_DATUM *hd=NULL;
4573 int ism = 0;
4574
4575 SUMA_ENTRY;
4576
4577 // fprintf(stderr, "%s\n", FuncName);
4578
4579 if (!SM || !SM->idvec) {
4580 SUMA_S_Err("Null colormap or no id vector");
4581 SUMA_DUMP_TRACE("%s",FuncName);
4582 SUMA_RETURN(NOPE);
4583 }
4584
4585 /* destroy old hash */
4586 SUMA_DestroyCmapHash(SM);
4587
4588 /* create new hash table */
4589 for (ism=0; ism < SM->N_M[0]; ++ism) {
4590 hd = (SUMA_COLOR_MAP_HASH_DATUM *)
4591 SUMA_calloc(1, sizeof(SUMA_COLOR_MAP_HASH_DATUM));
4592 hd->id = SM->idvec[ism];
4593 hd->colmapindex = ism;
4594 HASH_ADD_INT(SM->chd, id, hd);
4595 }
4596
4597 SUMA_RETURN(YUP);
4598 }
4599
SUMA_ScaleToMap_alaHASH(float * V,int N_V,SUMA_COLOR_MAP * ColMap,SUMA_SCALE_TO_MAP_OPT * Opt,SUMA_COLOR_SCALED_VECT * SV)4600 SUMA_Boolean SUMA_ScaleToMap_alaHASH ( float *V, int N_V,
4601 SUMA_COLOR_MAP *ColMap,
4602 SUMA_SCALE_TO_MAP_OPT *Opt,
4603 SUMA_COLOR_SCALED_VECT * SV)
4604 {
4605 static char FuncName[]={"SUMA_ScaleToMap_alaHASH"};
4606 int i,j, i0, i1, i3, mxColindex;
4607 float Vmin, Vmax, MinCol, MaxCol, Vrange, Vscl, r, **Mbuf= NULL;
4608 SUMA_Boolean NewMap = NOPE;
4609 SUMA_Boolean LocalHead = NOPE;
4610
4611 SUMA_ENTRY;
4612
4613 // fprintf(stderr, "%s\n", FuncName);
4614
4615
4616 SUMA_RETURN (SUMA_ScaleToMap(V, N_V, -1.0, -1.0, ColMap, Opt, SV));
4617
4618 }
4619 /* Does a colormap need linearization?*/
SUMA_NeedsLinearizing(SUMA_COLOR_MAP * ColMap)4620 SUMA_Boolean SUMA_NeedsLinearizing(SUMA_COLOR_MAP *ColMap)
4621 {
4622 static char FuncName[]={"SUMA_NeedsLinearizing"};
4623 float dfr = 0.0;
4624 int i = 0;
4625
4626 SUMA_ENTRY;
4627
4628 // fprintf(stderr, "%s\n", FuncName);
4629
4630 /* SUMA_Show_ColorMapVec(&ColMap, 1, NULL, 2); */
4631
4632 if (!ColMap->frac) SUMA_RETURN(NOPE);
4633
4634 if (ColMap->N_M[0]<2) SUMA_RETURN(NOPE);
4635
4636 dfr = ColMap->frac[0]-ColMap->frac[1];
4637 for (i=2; i<ColMap->N_M[0]; ++i) {
4638 if (SUMA_ABS((ColMap->frac[i-1]-ColMap->frac[i]) - dfr) > 0.0001) {
4639 SUMA_RETURN(YUP);
4640 }
4641 }
4642
4643 SUMA_RETURN(NOPE);
4644 }
4645
4646 /*!
4647 This function maps the values in a vector to colors on a color map
4648 Res = SUMA_ScaleToMap (V, N_V, Vmin, Vmax, ColMap, Opt, SV);
4649 \param V (float *) N_V x1 vector containing the values to be colorized by the map in ColMap.
4650 \param N_V (int) number of elements in V
4651 \param Vmin (float) minimum value in V
4652 \param Vmax (float) maximum value in V
4653 If both Vmin and Vmax are set to -1, and interpmode = SUMA_DIRECT then
4654 HashMode is turned on (see below)
4655 \param ColMap (SUMA_COLOR_MAP *) pointer to the color map
4656 \param Opt (SUMA_SCALE_TO_MAP_OPT *) is a structure containing the options for SUMA_ScaleToMap
4657 see help on SUMA_SCALE_TO_MAP_OPT for info on various options
4658 \param SV (SUMA_COLOR_SCALED_VECT *) is a pre-allocated structure that will contain the
4659 color mapped version of V. See the definition of SUMA_COLOR_SCALED_VECT for more info.
4660 \ret Res (SUMA_Boolean) good/bad
4661
4662 \sa SUMA_Create_ColorScaledVect and SUMA_Free_ColorScaledVect
4663 \sa SUMA_ScaleToMapOptInit
4664 \sa SUMA_MakeColorMap
4665
4666 NOTES:
4667 +The brightness factor Opt->BrightFact is applied to the colormap in ColMap and the MaskColor in Opt
4668 +How Clipping is done:
4669 if (V[i] < Clip[0]) V[i] = Clip[0];
4670 if (V[i] > Clip[1]) V[i] = Clip[1];
4671 +Values in Mask Range are applied BEFORE the clipping is done
4672 IF (Mask[0] <= V[i] <= Mask[1]) V[i] is masked
4673 */
SUMA_ScaleToMap(float * V,int N_V,float Vmin,float Vmax,SUMA_COLOR_MAP * ColMap,SUMA_SCALE_TO_MAP_OPT * Opt,SUMA_COLOR_SCALED_VECT * SV)4674 SUMA_Boolean SUMA_ScaleToMap (float *V, int N_V,
4675 float Vmin, float Vmax,
4676 SUMA_COLOR_MAP *ColMap,
4677 SUMA_SCALE_TO_MAP_OPT *Opt,
4678 SUMA_COLOR_SCALED_VECT * SV)
4679 {
4680 static char FuncName[]={"SUMA_ScaleToMap"};
4681 int i,j, i0, i1, mxColindex, i3=0, HashMode = 0, FillVCont = 0;
4682 float MinCol, MaxCol, Vrange, Vscl, r, **Mbuf= NULL, top_frac;
4683 static int nwarn = 0, nwarnvcont = 0;
4684 SUMA_COLOR_MAP_HASH_DATUM *hdbuf=NULL;
4685 SUMA_Boolean NewMap = NOPE;
4686 SUMA_Boolean LocalHead = NOPE;
4687
4688 SUMA_ENTRY;
4689
4690 // fprintf(stderr, "%s\n", FuncName);
4691
4692 if (!ColMap) {
4693 SUMA_SL_Err("NULL ColMap");
4694 SUMA_RETURN(NOPE);
4695 }
4696 if (!Opt) {
4697 SUMA_SL_Err("NULL Opt");
4698 SUMA_RETURN(NOPE);
4699 }
4700 if (!SV) {
4701 SUMA_SL_Err("NULL SV");
4702 SUMA_RETURN(NOPE);
4703 }
4704 if (!V) {
4705 SUMA_SL_Err("NULL V");
4706 SUMA_RETURN(NOPE);
4707 }
4708
4709 SUMA_LHv("Input Vmin..Vmax=%f..%f\n", Vmin, Vmax);
4710 /* No negative colormaps here */
4711 if (ColMap->Sgn < 0) {
4712 /* proceed, in SUMA options were given to the user to make
4713 the range symmetric about 0.
4714 They can shoot themselves in the foot if they want to */
4715 SUMA_LH( "Colormap is split into positive and negative.\n "
4716 "Make sure your range is from -a to + a to have "
4717 "the mapping resemble AFNI's");
4718 }
4719
4720 /* find the values to be masked out */
4721 if (Opt->ApplyMask){
4722 SUMA_LH("Applying Mask");
4723 if (Opt->MaskZero) {
4724 /* mask zeros and values in range */
4725 for (i=0; i < N_V; ++i) {
4726 if ( !V[i] || (V[i] >= Opt->MaskRange[0] &&
4727 V[i] <= Opt->MaskRange[1])) SV->isMasked[i] = YUP;
4728 }
4729 } else {
4730 /* don't mask zeros, just range */
4731 for (i=0; i < N_V; ++i) {
4732 if (V[i] >= Opt->MaskRange[0] && V[i] <= Opt->MaskRange[1])
4733 SV->isMasked[i] = YUP;
4734 }
4735 }
4736 }else {
4737 if (Opt->MaskZero) {
4738 SUMA_LH("Masking Zeros");
4739 /* mask zeros */
4740 for (i=0; i < N_V; ++i) {
4741 if (!V[i]) SV->isMasked[i] = YUP;
4742 }
4743 }
4744 }
4745
4746 /* refuse to deal with top_frac here, SUMA does not allow for
4747 colormaps to have a top != 1
4748 First pass at implementing top != 1 does exist below but is
4749 now turned off. I don't feel
4750 like testing it... */
4751 top_frac = ColMap->top_frac;
4752 if (top_frac > 0.0f) {
4753 if (!(nwarn % 25)) {
4754 SUMA_SL_Warn( "\n" /* don't want to deal with this because */
4755 "Colormaps for SUMA usage must have 1 for top value.\n" /* suma colormap interface does not yet */
4756 "Any scaling should be done using the range options.\n" /* have a way to show a top value for the */
4757 "The top value for this colormap will be forced to 1.0\n" /* colormap and it is assumed that the top */
4758 "This warning will be shown intermittently when using.\n" /* is 1. Allowing maps where the top is not */
4759 "SUMA's GUI.\n"); /* 1 is dealt with below but is cause for */
4760 /* confusion. You can remove this restriction */
4761 } /* the colormap. */
4762 ++nwarn; /* when SUMA clearly shows the top value of */
4763 top_frac = 0.0f;
4764 }
4765
4766 /* go through and clip values in V to those specified in the range */
4767 if (Opt->ApplyClip) {
4768 SUMA_LH( "Applying Clip \n"
4769 "(This one's not used in\n"
4770 " interactive mode anymore \n"
4771 " because clipping is handled \n"
4772 " in the colormapping part)");
4773 if (top_frac > 0.0f) {
4774 SUMA_S_Note("Using top_frac, not fully tested.");
4775 Opt->IntRange[0] *= top_frac;
4776 Opt->IntRange[1] *= top_frac;
4777 }
4778
4779 for (i=0; i < N_V; ++i) {
4780 if (!SV->isMasked[i]) { /* don't waist time on masked stuff */
4781 if (V[i] > Opt->IntRange[0]) {
4782 /* that's cool */
4783 } else {
4784 V[i] = Opt->IntRange[0];
4785 }
4786
4787 if (V[i] < Opt->IntRange[1]) {
4788 /* that's cool */
4789 } else {
4790 V[i] = Opt->IntRange[1];
4791 }
4792 }
4793 }
4794 Vmin = Opt->IntRange[0];
4795 Vmax = Opt->IntRange[1];
4796
4797 if (top_frac > 0.0f) {
4798 /* SUMA_S_Note("Using top_frac, not fully tested."); */
4799 Opt->IntRange[0] /= top_frac;
4800 Opt->IntRange[1] /= top_frac;
4801 }
4802 } else {
4803 if (top_frac > 0.0f) {
4804 SUMA_S_Notev("Using top_frac %f, not fully tested.", top_frac);
4805 Vmin *= top_frac;
4806 Vmax *= top_frac;
4807 }
4808 SUMA_LHv("No Clip, Opt->IntRange ignored.\nVmin..Vmax= %f..%f",
4809 Vmin, Vmax);
4810 }
4811
4812 /* Add any coord bias ? */
4813 if ( Opt->DoBias == SW_CoordBias_X ||
4814 Opt->DoBias == SW_CoordBias_Y ||
4815 Opt->DoBias == SW_CoordBias_Z ||
4816 Opt->DoBias == SW_CoordBias_N) {
4817 SUMA_LH("Coord Bias requested");
4818 if (!SV->BiasCoordVec) {
4819 SUMA_LH("Allocating for BiasCoordVec");
4820 SV->BiasCoordVec = (float *)SUMA_calloc(N_V, sizeof(float));
4821 if (!SV->BiasCoordVec) {
4822 SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(NOPE); }
4823 }else {
4824 SUMA_SL_Err("Do not expect this not to be null here ... ");
4825 SUMA_RETURN(NOPE);
4826 }
4827 } else {
4828 SUMA_LH("No Coord Bias requested");
4829 if (SV->BiasCoordVec) {
4830 SUMA_SL_Err("Do NOT expect this not to be null here ... ");
4831 SUMA_RETURN(NOPE);
4832 }
4833 }
4834
4835 /* is the colormap non-linear ? */
4836 FillVCont = Opt->ColsContMode; /* the default behaviour, but that does not
4837 work if colormaps are linearized because
4838 indices into the colormap do not match
4839 indices into non-linearized maps that are
4840 stored in memory. */
4841 if (SUMA_NeedsLinearizing(ColMap)) {
4842 if (Opt->interpmode == SUMA_NO_INTERP || Opt->interpmode == SUMA_INTERP) {
4843 /* linearize color map */
4844 SUMA_LH("Linearizing colormap ...");
4845 NewMap = YUP;
4846 if (ColMap->frac[0] > 0 && ColMap->Sgn == -1) {
4847 SUMA_S_Warn ("Color map fractions are positive with Sgn flag = -1");
4848 }
4849 if (ColMap->frac[0] < 0 && ColMap->Sgn == 1) {
4850 SUMA_S_Warn ("Color map fractions are negative with Sgn flag = 1");
4851 }
4852 ColMap = SUMA_Linearize_Color_Map (ColMap, -1);
4853 if (FillVCont && !nwarnvcont) {
4854 SUMA_SLP_Warn( "No contouring for colormaps that \n"
4855 "do not have equal size panes. \n"
4856 "This warning will be shown once this session.");
4857 ++nwarnvcont;
4858 }
4859 FillVCont = 0;
4860 } else {
4861 if (Opt->interpmode != SUMA_DIRECT) {
4862 SUMA_SL_Err("Not expected interpmode.");
4863 /* Do nothing to the colormap, direct mapping mode in gear */
4864 NewMap = NOPE;
4865 }
4866 }
4867 }else {
4868 SUMA_LH("NO Linearizing of colormap deemed necessary...");
4869 NewMap = NOPE;
4870 }
4871
4872 /* if brightness factor is given, apply it to color map and mask color */
4873 Mbuf = NULL;
4874 if (Opt->BrightFact <= 0 || Opt->BrightFact > 2) {
4875 SUMA_S_Warn("Opt->BrightFact must be between ]0 2], Defaulting to 1\n");
4876 Opt->BrightFact = 1.0;
4877 }
4878 {
4879 if (Opt->BrightFact != 1.0) {
4880 SUMA_LH("Modulating brightness of map");
4881 Mbuf = ColMap->M; /* save pointer */
4882 ColMap->M = (float **)
4883 SUMA_allocate2D(ColMap->N_M[0], ColMap->N_M[1], sizeof(float));
4884 for (i=0; i < ColMap->N_M[0]; ++i) {
4885 ColMap->M[i][0] = Mbuf[i][0] * Opt->BrightFact;
4886 if (ColMap->M[i][0] > 1.0) ColMap->M[i][0] = 1.0; /* Bright Fact
4887 could be > 1.0 now */
4888 ColMap->M[i][1] = Mbuf[i][1] * Opt->BrightFact;
4889 if (ColMap->M[i][1] > 1.0) ColMap->M[i][1] = 1.0;
4890 ColMap->M[i][2] = Mbuf[i][2] * Opt->BrightFact;
4891 if (ColMap->M[i][2] > 1.0) ColMap->M[i][2] = 1.0;
4892 if (ColMap->N_M[1] == 4) {
4893 ColMap->M[i][3] = Mbuf[i][3] * Opt->BrightFact;
4894 if (ColMap->M[i][3] > 1.0) ColMap->M[i][3] = 1.0;
4895 }
4896 }
4897 /* now for the mask color */
4898 Opt->MaskColor[0] *= Opt->BrightFact;
4899 if (Opt->MaskColor[0] > 1.0) Opt->MaskColor[0] = 1.0;
4900 Opt->MaskColor[1] *= Opt->BrightFact;
4901 if (Opt->MaskColor[1] > 1.0) Opt->MaskColor[1] = 1.0;
4902 Opt->MaskColor[2] *= Opt->BrightFact;
4903 if (Opt->MaskColor[2] > 1.0) Opt->MaskColor[2] = 1.0;
4904 }
4905 }
4906
4907
4908 if ( Opt->interpmode != SUMA_DIRECT &&
4909 Opt->interpmode != SUMA_NO_INTERP &&
4910 Opt->interpmode != SUMA_INTERP) {
4911 fprintf (SUMA_STDERR,
4912 "Error %s: Opt->interpmode is incorrectly specifed (%d).\n",
4913 FuncName, Opt->interpmode);
4914 SUMA_RETURN(NOPE);
4915 }
4916
4917 if (Opt->interpmode == SUMA_NO_INTERP || Opt->interpmode == SUMA_INTERP) {
4918 /* Now go through values and interpolate onto index of colormap */
4919 MinCol = 0.0; MaxCol = (float)ColMap->N_M[0];
4920 Vrange = Vmax - Vmin;
4921 if (Vrange < 0) {
4922 fprintf (SUMA_STDERR,
4923 "Error %s: Vmax (%f)< Vmin(%f).\n", FuncName, Vmax, Vmin);
4924 SUMA_RETURN (NOPE);
4925 }
4926
4927 if (Vrange > 0) {
4928 mxColindex = ColMap->N_M[0] -1;
4929 if (Opt->interpmode == SUMA_NO_INTERP) {
4930 /* no interpolation between colours */
4931 SUMA_LH("No Interp Mode");
4932 SV->N_VCont = 0;
4933 for (i=0; i < N_V; ++i) {
4934 i3 = 3*i;
4935 if (!SV->isMasked[i]) {
4936 Vscl = (V[i] - Vmin) / Vrange * ColMap->N_M[0];
4937 /* used mxColindex instead of N_M[0] (wrong!)
4938 prior to Oct 22, 03 */
4939 if (Vscl < 0) Vscl = 0;
4940 if (Vscl > ColMap->N_M[0]) Vscl = ColMap->N_M[0];
4941 /* This happens when your Min--Max are within the
4942 boundaries of the data's (V[i]) min to max */
4943 i0 = (int)(Vscl);
4944 if (i0 > mxColindex) i0 = mxColindex;
4945 /* No need, Vscl's clipping takes care of that:
4946 if (i0 < 0) i0 = 0; */
4947 if (SV->BiasCoordVec) SV->BiasCoordVec[i] = Vscl;
4948 if (ColMap->M[i0][0] >= 0) { /* good color */
4949 if (FillVCont) {
4950 SV->VCont[SV->N_VCont] = i0;
4951 ++SV->N_VCont;
4952 }
4953 SV->cV[i3 ] = ColMap->M[i0][0];
4954 SV->cV[i3+1] = ColMap->M[i0][1];
4955 SV->cV[i3+2] = ColMap->M[i0][2];
4956 } else { /* mask color */
4957 SV->isMasked[i] = YUP;
4958 SV->cV[i3 ] = Opt->MaskColor[0];
4959 SV->cV[i3+1] = Opt->MaskColor[1];
4960 SV->cV[i3+2] = Opt->MaskColor[2];
4961 }
4962 } else {
4963 SV->cV[i3 ] = Opt->MaskColor[0];
4964 SV->cV[i3+1] = Opt->MaskColor[1];
4965 SV->cV[i3+2] = Opt->MaskColor[2];
4966 }
4967 }
4968 } else { /* interpolation mode */
4969 SUMA_LHv("Interp Mode, Vmin %f, Vmax %f, Vrange %f\n",
4970 Vmin, Vmax, Vrange);
4971 SV->N_VCont = 0;
4972 for (i=0; i < N_V; ++i) {
4973 i3 = 3*i;
4974 if (!SV->isMasked[i]) {
4975 Vscl = (V[i] - Vmin) / Vrange * ColMap->N_M[0];
4976 /* used mxColindex instead of N_M[0] (wrong!)
4977 prior to Oct 22, 03 */
4978 if (Vscl < 0) Vscl = 0;
4979 if (Vscl > ColMap->N_M[0]) Vscl = ColMap->N_M[0];
4980 /* This happens when your Min--Max are within the
4981 boundaries of the data's (V[i]) min to max */
4982 /*now linearly interpolate between the two closest
4983 colors in the color map */
4984 i0 = (int)(Vscl);
4985 if (i0 > mxColindex) i0 = mxColindex;
4986 /* No need, Vscl's clipping takes care of that:
4987 if (i0 < 0) i0 = 0; */
4988 i1=i0+1;
4989 if (SV->BiasCoordVec) {
4990 SV->BiasCoordVec[i] = Vscl;
4991 }
4992 if (ColMap->M[i0][0] >= 0) { /* good color */
4993 if (FillVCont) {
4994 /* fprintf(SUMA_STDERR,"i0=%d (on %s)\t",
4995 i0, ColMap->Name); */
4996 SV->VCont[SV->N_VCont] = i0;
4997 ++SV->N_VCont;
4998 }
4999 if (i1 < ColMap->N_M[0]) {
5000 r = Vscl - i0;
5001 SV->cV[i3 ] = ColMap->M[i0][0] + r *
5002 (ColMap->M[i1][0] - ColMap->M[i0][0]);
5003 SV->cV[i3+1] = ColMap->M[i0][1] + r *
5004 (ColMap->M[i1][1] - ColMap->M[i0][1]);
5005 SV->cV[i3+2] = ColMap->M[i0][2] + r *
5006 (ColMap->M[i1][2] - ColMap->M[i0][2]);
5007 } else {
5008 SV->cV[i3 ] = ColMap->M[i0][0];
5009 SV->cV[i3+1] = ColMap->M[i0][1];
5010 SV->cV[i3+2] = ColMap->M[i0][2];
5011 }
5012 } else { /* mask color */
5013 SV->isMasked[i] = YUP;
5014 SV->cV[i3 ] = Opt->MaskColor[0];
5015 SV->cV[i3+1] = Opt->MaskColor[1];
5016 SV->cV[i3+2] = Opt->MaskColor[2];
5017 }
5018 } else {
5019 SV->cV[i3 ] = Opt->MaskColor[0];
5020 SV->cV[i3+1] = Opt->MaskColor[1];
5021 SV->cV[i3+2] = Opt->MaskColor[2];
5022 }
5023 }
5024 }
5025 }else { /* all values are equal, use the middle color in the colormap */
5026 if (LocalHead)
5027 fprintf (SUMA_STDOUT,
5028 "Warning %s: Node value range is 0, using middle color "
5029 "in colormap.\n", FuncName);
5030 i0 = (ColMap->N_M[0] - 1)/2;
5031 SV->N_VCont = 0;
5032 for (i=0; i < N_V; ++i) {
5033 i3 = 3 * i;
5034 if (!SV->isMasked[i]) {
5035 if (SV->BiasCoordVec) SV->BiasCoordVec[i] = i0;
5036 SV->cV[i3 ] = ColMap->M[i0][0];
5037 SV->cV[i3+1] = ColMap->M[i0][1];
5038 SV->cV[i3+2] = ColMap->M[i0][2];
5039 } else {
5040 SV->cV[i3 ] = Opt->MaskColor[0];
5041 SV->cV[i3+1] = Opt->MaskColor[1];
5042 SV->cV[i3+2] = Opt->MaskColor[2];
5043 }
5044 }
5045 }
5046 } else {
5047 /* direct color mapping */
5048 if ((int) Vmin == (int) Vmax && Vmin == -1) {
5049 HashMode = 1;
5050 } else HashMode = 0;
5051 SUMA_LHv( "Direct colormapping, HashMode = %d.\n"
5052 "Opt->IntRange values are useless, and\n"
5053 "Vmin, Vmax are used as To Hash or not To Hash flags\n",
5054 HashMode );
5055 if (Opt->interpmode != SUMA_DIRECT) {
5056 fprintf (SUMA_STDOUT,
5057 "Error %s: Logic error, should never get here with"
5058 " Opt->interpmode != SUMA_DIRECT\n", FuncName);
5059 SUMA_RETURN(NOPE);
5060 }
5061 if (HashMode && !ColMap->chd) {
5062 if (!SUMA_CreateCmapHash(ColMap)) {
5063 SUMA_SLP_Err("Cannot create hash. HashMode turned off.");
5064 HashMode = 0;
5065 }
5066 }
5067 SV->N_VCont = 0;
5068 for (i=0; i < N_V; ++i) {
5069 i3 = 3*i;
5070 if (!SV->isMasked[i]) {
5071 SUMA_COLMAP_INDEX_FROM_ID(V[i], ColMap, i0, HashMode);
5072 if (i0 >=0 && ColMap->M[i0][0] >= 0) {
5073 if (FillVCont) {
5074 SV->VCont[SV->N_VCont] = i0;
5075 ++SV->N_VCont;
5076 }
5077 SV->cV[i3 ] = ColMap->M[i0][0];
5078 SV->cV[i3+1] = ColMap->M[i0][1];
5079 SV->cV[i3+2] = ColMap->M[i0][2];
5080 if (SV->BiasCoordVec) SV->BiasCoordVec[i] = i0;
5081 } else {
5082 SV->isMasked[i] = YUP;
5083 SV->cV[i3 ] = Opt->MaskColor[0];
5084 SV->cV[i3+1] = Opt->MaskColor[1];
5085 SV->cV[i3+2] = Opt->MaskColor[2];
5086 }
5087 } else {
5088 SV->cV[i3 ] = Opt->MaskColor[0];
5089 SV->cV[i3+1] = Opt->MaskColor[1];
5090 SV->cV[i3+2] = Opt->MaskColor[2];
5091 }
5092
5093 }
5094
5095 }
5096
5097 /* change range for coord bias */
5098 Vrange = (Opt->CoordBiasRange[1] - Opt->CoordBiasRange[0]) / ColMap->N_M[0];
5099 if (SV->BiasCoordVec) {
5100 SUMA_LH("Adding the CoordBias");
5101 for (i=0; i < N_V; ++i) {
5102 if (!SV->isMasked[i]) {
5103 SV->BiasCoordVec[i] = Opt->CoordBiasRange[0] +
5104 SV->BiasCoordVec[i] * Vrange;
5105 /* if (LocalHead)
5106 fprintf( SUMA_STDERR,
5107 "%s: %f\n", FuncName, SV->BiasCoordVec[i]); */
5108 } else SV->BiasCoordVec[i] = 0.0;
5109 }
5110 }
5111
5112 if (Mbuf) {
5113 /* free what is in ColMap->M */
5114 SUMA_free2D((char **)ColMap->M, ColMap->N_M[0]);
5115 ColMap->M = Mbuf; Mbuf = NULL;
5116 }
5117 if (NewMap) {
5118 SUMA_LH("Freeing linearized colormap.");
5119 SUMA_Free_ColorMap (ColMap);
5120 }
5121
5122 SUMA_LH("Out");
5123 SUMA_RETURN (YUP);
5124 }
5125
5126 /*! function to create a linear colormap out of a non-linear one
5127
5128 */
5129
5130 /*! function to allocate and initialize a structure of the type SUMA_COLOR_SCALED_VECT
5131 S = SUMA_Create_ColorScaledVect();
5132 \param N_Node (int) number of nodes for which colors will be assigned
5133 \param ColsContMode (int) flag to indicate if contouring is to be done.
5134 \ret S (SUMA_COLOR_SCALED_VECT * ) pointer to structure that will contain the color map of N_Node nodes
5135 */
SUMA_Create_ColorScaledVect(int N_Node,int ColsContMode)5136 SUMA_COLOR_SCALED_VECT * SUMA_Create_ColorScaledVect(int N_Node,
5137 int ColsContMode)
5138 {
5139 static char FuncName[]={"SUMA_Create_ColorScaledVect"};
5140 SUMA_COLOR_SCALED_VECT * S;
5141 SUMA_Boolean LocalHead = NOPE;
5142
5143 // fprintf(stderr, "%s\n", FuncName);
5144
5145 SUMA_ENTRY;
5146 if (LocalHead)
5147 fprintf (SUMA_STDERR,
5148 "%s:\n Allocate for %d nodes ...\n", FuncName, N_Node);
5149 S = (SUMA_COLOR_SCALED_VECT *)SUMA_calloc(1,sizeof(SUMA_COLOR_SCALED_VECT));
5150 if (S == NULL) {
5151 fprintf(SUMA_STDERR, "Error %s: Failed to allocate for S.\n", FuncName);
5152 SUMA_RETURN (S);
5153 }
5154
5155 /* S->cM = (float **) SUMA_allocate2D(N_Node, 3, sizeof(float)); */
5156 S->cV = (float *) SUMA_calloc(N_Node * 3, sizeof(float));
5157 S->isMasked = (SUMA_Boolean *)SUMA_calloc(N_Node, sizeof(SUMA_Boolean));
5158 S->BiasCoordVec = NULL; /* That is created in the scaleToMap functions
5159 if needed */
5160 S->N_VCont = 0;
5161 S->VCont = NULL;
5162 if (ColsContMode) {
5163 S->VCont = (int *)SUMA_calloc(N_Node, sizeof(int));
5164 }
5165 if (!S->cV || !S->isMasked) {
5166 fprintf( SUMA_STDERR,
5167 "Error %s: Failed to allocate for S->cV or S->isMasked.\n",
5168 FuncName);
5169 SUMA_free(S); S = NULL;
5170 SUMA_RETURN (S);
5171 }
5172
5173 S->N_Node = N_Node;
5174
5175
5176 SUMA_RETURN(S);
5177 }
5178
5179 /*! function to free structures of the type SUMA_COLOR_SCALED_VECT
5180 SUMA_Free_ColorScaledVect (S)
5181 \param S (SUMA_COLOR_SCALED_VECT * ) pointer to structure being deleted
5182 \ret void
5183
5184 */
SUMA_Free_ColorScaledVect(SUMA_COLOR_SCALED_VECT * S)5185 void SUMA_Free_ColorScaledVect (SUMA_COLOR_SCALED_VECT * S)
5186 {
5187 static char FuncName[]={"SUMA_Free_ColorScaledVect"};
5188
5189 SUMA_ENTRY;
5190
5191 // fprintf(stderr, "%s\n", FuncName);
5192
5193 if (S->cV) SUMA_free(S->cV);
5194 if (S->isMasked) SUMA_free(S->isMasked);
5195 if (S->BiasCoordVec) SUMA_free(S->BiasCoordVec);
5196 if (S->VCont) SUMA_free(S->VCont);
5197 if (S) SUMA_free(S);
5198 SUMA_RETURNe;
5199 }
5200
5201 /*!
5202 This function allocates for and initializes the Options structure for the function SUMA_ScaleToMap
5203
5204 Opt = SUMA_ScaleToMapOptInit();
5205
5206 \ret Opt (SUMA_SCALE_TO_MAP_OPT *) options structure with its fields initialized to the following:
5207 ApplyMask = NOPE;
5208 MaskRange[0] = MaskRange[1] = 0.0;
5209 MaskColor[0] = MaskColor[1] = MaskColor[2] = 0.0;
5210 Range[0] = Range[1] = 0.0;
5211 BrightFact = 1;
5212 interpmode = SUMA_INTERP;
5213 NULL is returned in the case of failure
5214
5215 You can free Opt with the free function
5216 */
SUMA_ScaleToMapOptInit(void)5217 SUMA_SCALE_TO_MAP_OPT * SUMA_ScaleToMapOptInit(void)
5218 {
5219 SUMA_SCALE_TO_MAP_OPT * Opt;
5220 static char FuncName[]={"SUMA_ScaleToMapOptInit"};
5221
5222 SUMA_ENTRY;
5223
5224 // fprintf(stderr, "%s\n", FuncName);
5225
5226 Opt = (SUMA_SCALE_TO_MAP_OPT *)SUMA_malloc(sizeof(SUMA_SCALE_TO_MAP_OPT));
5227 memset (Opt, 0, sizeof(SUMA_SCALE_TO_MAP_OPT));
5228 if (Opt == NULL) {
5229 fprintf (SUMA_STDERR, "Error %s: Could not allocate for Opt.\n", FuncName);
5230 SUMA_RETURN (NULL);
5231 }
5232
5233 Opt->ApplyMask = NOPE;
5234 Opt->MaskRange[0] = Opt->MaskRange[1] = 0.0;
5235 Opt->MaskColor[0] = Opt->MaskColor[1] = Opt->MaskColor[2] = 0.0;
5236 Opt->ApplyClip = NOPE;
5237 Opt->IntRange[0] = Opt->IntRange[1] = 0.0;
5238 Opt->RangeUnits = SUMA_NO_NUM_UNITS;
5239 Opt->ThreshRange[0] = Opt->ThreshRange[1] = 0.0;
5240 Opt->ThreshStats[0] = Opt->ThreshStats[1] = -1.0;
5241 Opt->BrightRange[0] = 0.0; Opt->BrightRange[1] = 0.0;
5242 Opt->BrightMap[0] = 0.3; Opt->BrightMap[1] = 0.8;
5243 Opt->BrightFact = 1.0;
5244 Opt->interpmode = SUMA_INTERP;
5245 Opt->alaAFNI = NOPE;
5246 Opt->AutoIntRange = -1;
5247 Opt->AutoBrtRange = -1;
5248 Opt->ColsContMode = 0;
5249 {
5250 char *eee = getenv("SUMA_MaskZero");
5251 if (eee) {
5252 if (strcmp(eee,"NO") == 0) Opt->MaskZero = NOPE;
5253 else if (strcmp(eee,"YES") == 0) Opt->MaskZero = YUP;
5254 else {
5255 fprintf (SUMA_STDERR,
5256 "Warning %s:\n"
5257 "Bad value for environment variable SUMA_MaskZero\n"
5258 "Assuming default of YES", FuncName);
5259 Opt->MaskZero = YUP;
5260 }
5261 } else Opt->MaskZero = YUP;
5262 }
5263
5264 Opt->find = 0;
5265 Opt->tind = 0;
5266 Opt->bind = 0;
5267 Opt->UseThr = YUP;
5268 {
5269 char *eee = getenv("SUMA_AbsThreshold");
5270 if (eee) {
5271 if (strcmp(eee,"NO") == 0) Opt->ThrMode = SUMA_LESS_THAN;
5272 else if (strcmp(eee,"YES") == 0) Opt->ThrMode = SUMA_ABS_LESS_THAN;
5273 else {
5274 fprintf (SUMA_STDERR,
5275 "Warning %s:\n"
5276 "Bad value for environment variable SUMA_AbsThresh_tbold\n"
5277 "Assuming default of YES", FuncName);
5278 Opt->ThrMode = SUMA_ABS_LESS_THAN;
5279 }
5280 } else Opt->ThrMode = SUMA_ABS_LESS_THAN;
5281 }
5282
5283 Opt->UseBrt = NOPE;
5284 Opt->DoBias = SW_CoordBias_None;
5285 Opt->BiasVect = NULL;
5286 Opt->CoordBiasRange[0] = 0.0; Opt->CoordBiasRange[1] = 10.0;
5287
5288 Opt->ClustOpt = SUMA_create_SurfClust_Opt("InteractiveClust");
5289 Opt->Clusterize = NOPE;
5290 Opt->RecomputeClust = NOPE;
5291
5292
5293 SUMA_RETURN (Opt);
5294
5295 }
5296
5297 /*!
5298 \brief the interpmode value to a string.
5299 */
SUMA_CmapModeName(SUMA_COLORMAP_INTERP_MODE mapmode)5300 char *SUMA_CmapModeName (SUMA_COLORMAP_INTERP_MODE mapmode)
5301 {
5302 static char FuncName[]={"SUMA_CmapModeName"};
5303
5304 SUMA_ENTRY;
5305
5306 // fprintf(stderr, "%s\n", FuncName);
5307
5308 switch (mapmode) {
5309 case SUMA_UNDEFINED_MODE:
5310 SUMA_RETURN("Undefined");
5311 break;
5312 case SUMA_DIRECT:
5313 SUMA_RETURN("Direct");
5314 break;
5315 case SUMA_NO_INTERP:
5316 SUMA_RETURN("NearestNeighbor");
5317 break;
5318 case SUMA_INTERP:
5319 SUMA_RETURN("Interpolate");
5320 break;
5321 default:
5322 SUMA_RETURN("Unexpected business");
5323 break;
5324 }
5325 }
5326
5327
5328 /*!
5329 \brief Returns the ascii name of a Suma standard map.
5330
5331 \param mapcode (int)
5332 \param N_col (int *) to contain the number of colors in the map
5333 -1 if no map was found
5334 \return ans (char *) ascii version of mapcode
5335
5336 \sa SUMA_StandardMapCode, StandardMapIndex
5337 */
5338 #if 0
5339 char *SUMA_StandardMapName (SUMA_STANDARD_CMAP mapcode, int *N_col)
5340 {
5341 static char FuncName[]={"SUMA_StandardMapName"};
5342
5343 SUMA_ENTRY;
5344
5345 *N_col = -1;
5346 switch (mapcode) {
5347 case SUMA_CMAP_ERROR:
5348 SUMA_RETURN("Error");
5349 break;
5350 case SUMA_CMAP_UNDEFINED:
5351 SUMA_RETURN("Undefined");
5352 break;
5353 case SUMA_CMAP_RGYBR20:
5354 *N_col = 20;
5355 SUMA_RETURN("rgybr20");
5356 break;
5357 case SUMA_CMAP_nGRAY20:
5358 *N_col = 20;
5359 SUMA_RETURN("ngray20");
5360 break;
5361 case SUMA_CMAP_GRAY02:
5362 *N_col = 02;
5363 SUMA_RETURN("gray02");
5364 break;
5365 case SUMA_CMAP_flpGRAY02:
5366 *N_col = 02;
5367 SUMA_RETURN("gray_i02");
5368 break;
5369 case SUMA_CMAP_GRAY20:
5370 *N_col = 20;
5371 SUMA_RETURN("gray20");
5372 break;
5373 case SUMA_CMAP_BW20:
5374 *N_col = 20;
5375 SUMA_RETURN("bw20");
5376 break;
5377 case SUMA_CMAP_BGYR19:
5378 *N_col = 19;
5379 SUMA_RETURN("bgyr19");
5380 break;
5381 case SUMA_CMAP_MATLAB_DEF_BYR64:
5382 *N_col = 64;
5383 SUMA_RETURN("byr64");
5384 break;
5385 case SUMA_CMAP_BGYR64:
5386 *N_col = 64;
5387 SUMA_RETURN("bgyr64");
5388 break;
5389 case SUMA_CMAP_ROI256:
5390 *N_col = 256;
5391 SUMA_RETURN("roi256");
5392 break;
5393 case SUMA_CMAP_ROI128:
5394 *N_col = 128;
5395 SUMA_RETURN("roi128");
5396 break;
5397 case SUMA_CMAP_ROI64:
5398 *N_col = 64;
5399 SUMA_RETURN("roi64");
5400 break;
5401 default:
5402 SUMA_RETURN("Cowabonga-x321");
5403 break;
5404 }
5405 }
5406 #else
SUMA_StandardMapName(int mapindex,int * N_col)5407 char *SUMA_StandardMapName (int mapindex, int *N_col)
5408 {
5409 static char FuncName[]={"SUMA_StandardMapName"};
5410
5411 SUMA_ENTRY;
5412
5413 // fprintf(stderr, "%s\n", FuncName);
5414
5415 if (!SUMAg_CF->scm) SUMA_RETURN(NULL);
5416 if (mapindex < 0 || mapindex >SUMAg_CF->scm->N_maps-1) SUMA_RETURN(NULL);
5417 *N_col = SUMAg_CF->scm->CMv[mapindex]->N_M[0];
5418 SUMA_RETURN(SUMAg_CF->scm->CMv[mapindex]->Name);
5419 }
5420 #endif
5421 /*!
5422 \brief Returns the code corresponding to a colormap name
5423
5424 \sa SUMA_StandardMapName
5425 */
5426 #if 0
5427 SUMA_STANDARD_CMAP SUMA_StandardMapCode (char *Name)
5428 {
5429 static char FuncName[]={"SUMA_StandardMapCode"};
5430
5431 SUMA_ENTRY;
5432
5433 if (!Name) SUMA_RETURN(SUMA_CMAP_ERROR);
5434 SUMA_TO_LOWER(Name);
5435 if (!strcmp(Name, "undefined")) SUMA_RETURN(SUMA_CMAP_UNDEFINED);
5436 if (!strcmp(Name, "rgybr20")) SUMA_RETURN(SUMA_CMAP_RGYBR20);
5437 if (!strcmp(Name, "ngray20")) SUMA_RETURN(SUMA_CMAP_nGRAY20);
5438 if (!strcmp(Name, "gray20")) SUMA_RETURN(SUMA_CMAP_GRAY20);
5439 if (!strcmp(Name, "gray02")) SUMA_RETURN(SUMA_CMAP_GRAY02);
5440 if (!strcmp(Name, "gray_i02")) SUMA_RETURN(SUMA_CMAP_flpGRAY02);
5441 if (!strcmp(Name, "bw20")) SUMA_RETURN(SUMA_CMAP_BW20);
5442 if (!strcmp(Name, "bgyr19")) SUMA_RETURN(SUMA_CMAP_BGYR19);
5443 if (!strcmp(Name, "matlab_default_byr64"))
5444 SUMA_RETURN(SUMA_CMAP_MATLAB_DEF_BYR64);
5445 if (!strcmp(Name, "byr64")) SUMA_RETURN(SUMA_CMAP_MATLAB_DEF_BYR64);
5446 if (!strcmp(Name, "bgyr64")) SUMA_RETURN(SUMA_CMAP_BGYR64);
5447 if (!strcmp(Name, "ygbrp64")) SUMA_RETURN(SUMA_CMAP_ROI64);
5448 if (!strcmp(Name, "roi64")) SUMA_RETURN(SUMA_CMAP_ROI64);
5449 if (!strcmp(Name, "ygbrp128")) SUMA_RETURN(SUMA_CMAP_ROI128);
5450 if (!strcmp(Name, "ygbrp256")) SUMA_RETURN(SUMA_CMAP_ROI256);
5451 if (!strcmp(Name, "roi128")) SUMA_RETURN(SUMA_CMAP_ROI128);
5452 if (!strcmp(Name, "roi256")) SUMA_RETURN(SUMA_CMAP_ROI256);
5453 /* if (!strcmp(Name, "")) SUMA_RETURN(); */
5454 SUMA_RETURN(SUMA_CMAP_ERROR);
5455 }
5456 #else
SUMA_StandardMapIndex(char * Name)5457 int SUMA_StandardMapIndex (char *Name)
5458 {
5459 static char FuncName[]={"SUMA_StandardMapIndex"};
5460
5461 SUMA_ENTRY;
5462
5463 // fprintf(stderr, "%s\n", FuncName);
5464
5465 if (!Name) SUMA_RETURN(-1);
5466
5467 /* Kill these three lines once you start producing legitimate
5468 ROI colormaps */
5469 if (!strcmp(Name,"roi128")) Name = "ygbrp128"; /* Don't ask */
5470 else if (!strcmp(Name,"roi256")) Name = "ygbrp256"; /* Don't ask */
5471 else if (!strcmp(Name,"roi64")) Name = "ygbrp64"; /* Don't ask */
5472
5473 SUMA_RETURN(SUMA_Find_ColorMap(Name,
5474 SUMAg_CF->scm->CMv,
5475 SUMAg_CF->scm->N_maps, -2 ));
5476 }
5477 #endif
5478
5479 /*!
5480 Returns one of a bunch of standard SUMA colormaps
5481 CM = SUMA_MakeStandardMap (mapname);
5482
5483 \param mapname (int) type of color map, choose from
5484 SUMA_CMAP_RGYBR20
5485 SUMA_CMAP_BGYR19
5486 SUMA_CMAP_GRAY20
5487 SUMA_CMAP_GRAY02
5488 SUMA_CMAP_nGRAY20
5489 SUMA_CMAP_BW20
5490 SUMA_CMAP_MATLAB_DEF_BYR64
5491 \return CM (SUMA_COLOR_MAP*) color map structure (NULL in case of error)
5492 */
5493
SUMA_MakeStandardMap(char * mapname)5494 SUMA_COLOR_MAP * SUMA_MakeStandardMap (char *mapname)
5495 { static char FuncName[]={"SUMA_MakeStandardMap"};
5496 float **Fiducials;
5497 int k, nc;
5498 int *Nind;
5499 int Ncols, NFid;
5500 SUMA_COLOR_MAP * CM;
5501
5502 // fprintf(stderr, "%s\n", FuncName);
5503
5504 SUMA_ENTRY;
5505 if (!strcmp(mapname,"rgybr20")) {
5506 Fiducials = (float **)SUMA_allocate2D(5, 3, sizeof(float));
5507 if (!Fiducials) {
5508 fprintf (SUMA_STDERR,
5509 "Error %s: Failed to allocate for Fiducials.\n", FuncName);
5510 SUMA_RETURN (NULL);
5511 }
5512 /* create the fiducial colors */
5513 k = 0;
5514 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5515 ++k;/* Red */
5516 Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0;
5517 ++k;/* Green */
5518 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 1.0;
5519 ++k;/* Blue */
5520 Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0;
5521 ++k;/* Yellow */
5522 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5523 ++k;/* Red */
5524
5525 /* generate 20 colors colormap */
5526 CM = SUMA_MakeColorMap (Fiducials, k, 0, 20, YUP, mapname);
5527 /* free Fiducials */
5528 SUMA_free2D((char **)Fiducials, k);
5529
5530 if (!CM) {
5531 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5532 SUMA_RETURN (NULL);
5533 }
5534 }else if (!strcmp(mapname,"bgyr19")) {
5535 Fiducials = (float **)SUMA_allocate2D(4, 3, sizeof(float));
5536 if (!Fiducials) {
5537 fprintf (SUMA_STDERR,
5538 "Error %s: Failed to allocate for Fiducials.\n", FuncName);
5539 SUMA_RETURN (NULL);
5540 }
5541 /* create the fiducial colors */
5542 k = 0;
5543 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 1.0;
5544 ++k;/* Blue */
5545 Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0;
5546 ++k;/* Green */
5547 Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0;
5548 ++k;/* Yellow */
5549 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5550 ++k;/* Red */
5551
5552 /* generate 20 colors colormap */
5553 CM = SUMA_MakeColorMap (Fiducials, k, 0, 19, NOPE, mapname);
5554
5555 /* free Fiducials */
5556 SUMA_free2D((char **)Fiducials, k);
5557
5558 if (!CM) {
5559 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5560 SUMA_RETURN (NULL);
5561 }
5562 }else if (!strcmp(mapname,"gray02")) {
5563 Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
5564 if (!Fiducials) {
5565 fprintf (SUMA_STDERR,
5566 "Error %s: Failed to allocate for Fiducials.\n", FuncName);
5567 SUMA_RETURN (NULL);
5568 }
5569 /* create the fiducial colors */
5570 k = 0;
5571 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.4;
5572 ++k;/* 0.4 gray */
5573 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.7;
5574 ++k;/* 0.8 gray */
5575
5576 /* generate 2 colors colormap */
5577 CM = SUMA_MakeColorMap (Fiducials, k, 0, 2, NOPE, mapname);
5578 /* free Fiducials */
5579 SUMA_free2D((char **)Fiducials, k);
5580
5581 if (!CM) {
5582 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5583 SUMA_RETURN (NULL);
5584 }
5585 }else if (!strcmp(mapname,"gray_i02")) {
5586 Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
5587 if (!Fiducials) {
5588 fprintf (SUMA_STDERR,
5589 "Error %s: Failed to allocate for Fiducials.\n", FuncName);
5590 SUMA_RETURN (NULL);
5591 }
5592 /* create the fiducial colors */
5593 k = 0;
5594 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.7; ++k;
5595 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.4; ++k;
5596
5597 /* generate 2 colors colormap */
5598 CM = SUMA_MakeColorMap (Fiducials, k, 0, 2, NOPE, mapname);
5599 /* free Fiducials */
5600 SUMA_free2D((char **)Fiducials, k);
5601
5602 if (!CM) {
5603 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5604 SUMA_RETURN (NULL);
5605 }
5606 }else if (!strcmp(mapname,"gray20")) {
5607 Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
5608 if (!Fiducials) {
5609 fprintf (SUMA_STDERR,
5610 "Error %s: Failed to allocate for Fiducials.\n", FuncName);
5611 SUMA_RETURN (NULL);
5612 }
5613 /* create the fiducial colors */
5614 k = 0;
5615 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.3;
5616 ++k;/* 0.3 gray */
5617 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.8;
5618 ++k;/* 0.8 gray */
5619
5620 /* generate 20 colors colormap */
5621 CM = SUMA_MakeColorMap (Fiducials, k, 0, 20, NOPE, mapname);
5622 /* free Fiducials */
5623 SUMA_free2D((char **)Fiducials, k);
5624
5625 if (!CM) {
5626 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5627 SUMA_RETURN (NULL);
5628 }
5629 }else if (!strcmp(mapname,"ngray20")) {
5630 Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
5631 if (!Fiducials) {
5632 fprintf (SUMA_STDERR,
5633 "Error %s: Failed to allocate for Fiducials.\n", FuncName);
5634 SUMA_RETURN (NULL);
5635 }
5636 /* create the fiducial colors */
5637 k = 0;
5638 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.3;
5639 ++k;/* 0.3 gray */
5640 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.8;
5641 ++k;/* 0.8 gray */
5642
5643 /* generate 20 colors colormap */
5644 CM = SUMA_MakeColorMap (Fiducials, k, 0, 20, NOPE, mapname);
5645 /* free Fiducials */
5646 SUMA_free2D((char **)Fiducials, k);
5647
5648 if (!CM) {
5649 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5650 SUMA_RETURN (NULL);
5651 }
5652 }else if (!strcmp(mapname,"bw20")) {
5653 Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
5654 if (!Fiducials) {
5655 fprintf (SUMA_STDERR,
5656 "Error %s: Failed to allocate for Fiducials.\n", FuncName);
5657 SUMA_RETURN (NULL);
5658 }
5659 /* create the fiducial colors */
5660 k = 0;
5661 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.0;
5662 ++k;/* black */
5663 Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 1.0;
5664 ++k;/* white */
5665
5666 /* generate 20 colors colormap */
5667 CM = SUMA_MakeColorMap (Fiducials, k, 0, 20, NOPE, mapname);
5668 /* free Fiducials */
5669 SUMA_free2D((char **)Fiducials, k);
5670
5671 if (!CM) {
5672 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5673 SUMA_RETURN (NULL);
5674 }
5675 }else if (!strcmp(mapname,"matlab_default_byr64") ||
5676 !strcmp(mapname,"byr64")) {
5677 /* default matlab color map */
5678 Ncols = 64;
5679 NFid = 10;
5680
5681 Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
5682 Nind = (int *) SUMA_calloc (NFid, sizeof (int));
5683
5684 if (!Fiducials || !Nind) {
5685 fprintf (SUMA_STDERR,
5686 "Error %s: Failed to allocate for Fiducials or Nind.\n",
5687 FuncName);
5688 SUMA_RETURN (NULL);
5689 }
5690
5691 /* create the fiducial colors */
5692 k = 0;
5693 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.5625;
5694 Nind[k] = 0; ++k;
5695 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 1.0;
5696 Nind[k] = 7; ++k;
5697 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 1.0;
5698 Nind[k] = 15; ++k;
5699 Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1.0;
5700 Nind[k] = 23; ++k;
5701 Fiducials[k][0] = 0.5; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.5625;
5702 Nind[k] = 31; ++k;
5703 Fiducials[k][0] = 0.5625; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.5;
5704 Nind[k] = 32; ++k;
5705 Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0;
5706 Nind[k] = 40; ++k;
5707 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 0.0;
5708 Nind[k] = 48; ++k;
5709 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5710 Nind[k] = 56; ++k;
5711 Fiducials[k][0] = 0.5625; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5712 Nind[k] = 63; ++k;
5713
5714 /* generate 20 colors colormap */
5715 CM = SUMA_MakeColorMap_v2 (Fiducials, k, 0, Nind, NOPE, mapname);
5716
5717 /* free Fiducials & Nind*/
5718 SUMA_free2D((char **)Fiducials, k);
5719 SUMA_free(Nind);
5720
5721 if (!CM) {
5722 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5723 SUMA_RETURN (NULL);
5724 }
5725 }else if (!strcmp(mapname,"bgyr64")) {
5726 /* default matlab color map */
5727 Ncols = 64;
5728 NFid = 10;
5729
5730 Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
5731 Nind = (int *) SUMA_calloc (NFid, sizeof (int));
5732
5733 if (!Fiducials || !Nind) {
5734 fprintf (SUMA_STDERR,
5735 "Error %s: Failed to allocate for Fiducials or Nind.\n",
5736 FuncName);
5737 SUMA_RETURN (NULL);
5738 }
5739
5740 /* create the fiducial colors */
5741 k = 0;
5742 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.5625;
5743 Nind[k] = 0; ++k;
5744 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 1.0;
5745 Nind[k] = 7; ++k;
5746 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 1.0;
5747 Nind[k] = 15; ++k;
5748 Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1.0;
5749 Nind[k] = 18; ++k;
5750 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 0.0;
5751 Nind[k] = 24; ++k;
5752 Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0;
5753 Nind[k] = 32; ++k;
5754 Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0;
5755 Nind[k] = 43; ++k;
5756 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 0.0;
5757 Nind[k] = 48; ++k;
5758 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5759 Nind[k] = 56; ++k;
5760 Fiducials[k][0] = 0.5625; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5761 Nind[k] = 63; ++k;
5762
5763 /* generate 64 colors colormap */
5764 CM = SUMA_MakeColorMap_v2 (Fiducials, k, 0, Nind, NOPE, mapname);
5765
5766 /* free Fiducials & Nind*/
5767 SUMA_free2D((char **)Fiducials, k);
5768 SUMA_free(Nind);
5769
5770 if (!CM) {
5771 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5772 SUMA_RETURN (NULL);
5773 }
5774 }else if (!strcmp(mapname,"oldroi256") || !strcmp(mapname, "ygbrp256")) {
5775 /* a large colormap for lots of ROI drawing */
5776 Ncols = 256;
5777 NFid = 6;
5778
5779 Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
5780 Nind = (int *) SUMA_calloc (NFid, sizeof (int));
5781
5782 if (!Fiducials || !Nind) {
5783 fprintf (SUMA_STDERR,
5784 "Error %s: Failed to allocate for Fiducials or Nind.\n",
5785 FuncName);
5786 SUMA_RETURN (NULL);
5787 }
5788
5789 /* create the fiducial colors */
5790 k = 0;
5791 Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0;
5792 Nind[k] = 0; ++k;
5793 Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0;
5794 Nind[k] = 50; ++k;
5795 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0; Fiducials[k][2] = 1.0;
5796 Nind[k] = 100; ++k;
5797 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5798 Nind[k] = 150; ++k;
5799 Fiducials[k][0] = 0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1;
5800 Nind[k] = 200; ++k;
5801 Fiducials[k][0] = 1; Fiducials[k][1] = 0; Fiducials[k][2] = 1;
5802 Nind[k] = 255; ++k;
5803
5804
5805 /* generate colormap */
5806 CM = SUMA_MakeColorMap_v2 (Fiducials, k, 0, Nind, NOPE, mapname);
5807
5808 /* free Fiducials & Nind*/
5809 SUMA_free2D((char **)Fiducials, k);
5810 SUMA_free(Nind);
5811
5812 if (!CM) {
5813 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5814 SUMA_RETURN (NULL);
5815 }
5816 }else if (!strcmp(mapname,"oldroi128") || !strcmp(mapname,"ygbrp128")) {
5817 /* a large colormap for lots of ROI drawing */
5818 Ncols = 128;
5819 NFid = 6;
5820
5821 Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
5822 Nind = (int *) SUMA_calloc (NFid, sizeof (int));
5823
5824 if (!Fiducials || !Nind) {
5825 fprintf (SUMA_STDERR,
5826 "Error %s: Failed to allocate for Fiducials or Nind.\n",
5827 FuncName);
5828 SUMA_RETURN (NULL);
5829 }
5830
5831 /* create the fiducial colors */
5832 k = 0;
5833 Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0;
5834 Nind[k] = 0; ++k;
5835 Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0;
5836 Nind[k] = 25; ++k;
5837 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0; Fiducials[k][2] = 1.0;
5838 Nind[k] = 50; ++k;
5839 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5840 Nind[k] = 75; ++k;
5841 Fiducials[k][0] = 0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1;
5842 Nind[k] = 100; ++k;
5843 Fiducials[k][0] = 1; Fiducials[k][1] = 0; Fiducials[k][2] = 1;
5844 Nind[k] = 127; ++k;
5845
5846
5847 /* generate colormap */
5848 CM = SUMA_MakeColorMap_v2 (Fiducials, k, 0, Nind, NOPE, mapname);
5849
5850 /* free Fiducials & Nind*/
5851 SUMA_free2D((char **)Fiducials, k);
5852 SUMA_free(Nind);
5853
5854 if (!CM) {
5855 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5856 SUMA_RETURN (NULL);
5857 }
5858 }else if (!strcmp(mapname,"oldroi64") || !strcmp(mapname,"ygbrp64")) {
5859 /* a large colormap for lots of ROI drawing */
5860 Ncols = 64;
5861 NFid = 6;
5862
5863 Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
5864 Nind = (int *) SUMA_calloc (NFid, sizeof (int));
5865
5866 if (!Fiducials || !Nind) {
5867 fprintf (SUMA_STDERR,
5868 "Error %s: Failed to allocate for Fiducials or Nind.\n",
5869 FuncName);
5870 SUMA_RETURN (NULL);
5871 }
5872
5873 /* create the fiducial colors */
5874 k = 0;
5875 Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0;
5876 Nind[k] = 0; ++k;
5877 Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0;
5878 Nind[k] = 12; ++k;
5879 Fiducials[k][0] = 0.0; Fiducials[k][1] = 0; Fiducials[k][2] = 1.0;
5880 Nind[k] = 25; ++k;
5881 Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0;
5882 Nind[k] = 33; ++k;
5883 Fiducials[k][0] = 0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1;
5884 Nind[k] = 50; ++k;
5885 Fiducials[k][0] = 1; Fiducials[k][1] = 0; Fiducials[k][2] = 1;
5886 Nind[k] = 63; ++k;
5887
5888
5889 /* generate colormap */
5890 CM = SUMA_MakeColorMap_v2 (Fiducials, k, 0, Nind, NOPE, mapname);
5891
5892 /* free Fiducials & Nind*/
5893 SUMA_free2D((char **)Fiducials, k);
5894 SUMA_free(Nind);
5895
5896 if (!CM) {
5897 fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
5898 SUMA_RETURN (NULL);
5899 }
5900 }else {
5901 fprintf (SUMA_STDERR,
5902 "Error %s: Unrecognized color map name.\n", FuncName);
5903 SUMA_RETURN (NULL);
5904
5905 }
5906
5907 SUMA_RETURN (CM);
5908 }
5909
5910
5911 /*!
5912 \brief flips a color map upside down
5913
5914 \param CM (SUMA_COLOR_MAP *) to be flipped
5915 */
SUMA_Flip_Color_Map(SUMA_COLOR_MAP * CM)5916 void SUMA_Flip_Color_Map (SUMA_COLOR_MAP *CM)
5917 {
5918 static char FuncName[] = {"SUMA_Flip_Color_Map"};
5919 float orig[3]={ SUMA_CMAP_ORIGIN };
5920 float topright[3] = { SUMA_CMAP_TOPLEFT };
5921 int lim, i, j, c;
5922 float t;
5923 SUMA_Boolean LocalHead = NOPE;
5924
5925 SUMA_ENTRY;
5926
5927 if (!CM) SUMA_RETURNe;
5928
5929 if (!CM->M) SUMA_RETURNe;
5930
5931 lim = CM->N_M[0]/2;
5932 for (j=0; j < CM->N_M[1]; ++j) { /* loop accross R,G,B columns */
5933 for (i=0; i < lim; ++i) {
5934 t = CM->M[i][j]; /* store color at i to be flipped */
5935 c = CM->N_M[0] - i - 1; /* index of color to replace one at i */
5936 CM->M[i][j] = CM->M[c][j]; /* replace color at i */
5937 CM->M[c][j] = t; /* put old color of i ar c */
5938 }
5939 }
5940
5941 if (CM->SO) { /* Free it, and recreate it */
5942 SUMA_Free_Surface_Object(CM->SO);
5943 CM->SO = SUMA_Cmap_To_SO(CM, orig, topright, 0);;
5944 }
5945
5946 #if 0 /* not sure you want to do that. If you flip
5947 after rotation, you'll be lost */
5948 for (j=0; j < CM->N_M[1]; ++j)
5949 CM->M0[j] = CM->M[CM->N_M[0]-1][j];
5950 #endif
5951
5952 CM->flipped = !CM->flipped;
5953 SUMA_RETURNe;
5954 }
5955
5956 /*!
5957 \brief rotates a color map by a fraction of its
5958 length
5959 frac = 0, ET go home
5960 frac < 0 rotate down
5961 frac > 0 rotate up
5962 abs(frac) = 1, go one color at a time
5963 \param CM (SUMA_COLOR_MAP *) to be flipped
5964 */
SUMA_Rotate_Color_Map(SUMA_COLOR_MAP * CM,float frac)5965 int SUMA_Rotate_Color_Map (SUMA_COLOR_MAP *CM, float frac)
5966 {
5967 static char FuncName[] = {"SUMA_Rotate_Color_Map"};
5968 float orig[3]={ SUMA_CMAP_ORIGIN };
5969 float topright[3] = { SUMA_CMAP_TOPLEFT };
5970 float **orig_cols=NULL, tdist=0.0, tdistmin=0.0;
5971 int i, j, di, ic, dmin;
5972 SUMA_Boolean LocalHead = NOPE;
5973
5974 SUMA_ENTRY;
5975
5976 if (!CM) SUMA_RETURN(0);
5977
5978 if (!CM->M) SUMA_RETURN(0);
5979
5980 /* make copy */
5981 orig_cols = (float **)SUMA_allocate2D (CM->N_M[0], CM->N_M[1], sizeof(float));
5982 for (j=0; j < CM->N_M[1]; ++j) {
5983 for (i=0; i < CM->N_M[0]; ++i) {
5984 orig_cols[i][j] = CM->M[i][j];
5985 }
5986 }
5987
5988 /* shift */
5989 if (frac == 0.0f) { /* come back baby */
5990 tdistmin = 1000;
5991 dmin = 900;
5992 for (i=0; i < CM->N_M[0]; ++i) {
5993 tdist = 0.0;
5994 for (j=0; j< CM->N_M[1]; ++j) {
5995 tdist += SUMA_POW2(CM->M[i][j]-CM->M0[j]);
5996 }
5997 if (tdist <= tdistmin) {
5998 tdistmin = tdist;
5999 dmin = i;
6000 }
6001 }
6002 if (!CM->flipped) di = dmin;
6003 else di = dmin+1;
6004 } else if (SUMA_ABS(frac) == 1.0f) { /* one color at a time */
6005 di = 1;
6006 } else {
6007 di = SUMA_ROUND(SUMA_ABS(frac*CM->N_M[0]));
6008 if (di > CM->N_M[0]/2) di = CM->N_M[0]/2;
6009 if (di < 1) di = 1;
6010 }
6011 SUMA_LHv("A shift of %d colors (frac %f, N_M[0,1] [%d, %d])...\n",
6012 di, frac, CM->N_M[0], CM->N_M[1]);
6013 if (frac > 0) {
6014 for (i=0; i < CM->N_M[0]; ++i) {
6015 ic = (i+di) % CM->N_M[0];
6016 for (j=0; j < CM->N_M[1]; ++j) {
6017 CM->M[ic][j] = orig_cols[i][j];
6018 }
6019 }
6020 } else {
6021 for (i=0; i < CM->N_M[0]; ++i) {
6022 ic = (i+di) % CM->N_M[0];
6023 for (j=0; j < CM->N_M[1]; ++j) {
6024 CM->M[i][j] = orig_cols[ic][j];
6025 }
6026 }
6027 }
6028
6029 SUMA_free2D((char **)orig_cols, CM->N_M[0]); orig_cols = NULL;
6030
6031 if (CM->SO) { /* Free it, and recreate it here or suffer
6032 from asynchronous display related problems if you
6033 wait for that to happen when DrawCmap is
6034 doing it. */
6035 SUMA_Free_Surface_Object(CM->SO);
6036 CM->SO = SUMA_Cmap_To_SO(CM, orig, topright, 0);;
6037 }
6038
6039 SUMA_RETURN(di);
6040 }
6041
6042 /*!
6043 A function to compute the percentile range.
6044
6045 Vsort = SUMA_PercRange (V, Vsort, N_V, PercRange, PercRangeVal, iPercRangeVal)
6046
6047 \param V (float *) pointer to vector containing N_V values
6048 \param Vsort (float *) pointer to sorted version of V.
6049 NOTE: If you want the function to sort V for you then pass NULL here and
6050 expect the pointer to Vsort to be returned
6051 \param N_V (int) number of values in V
6052 \param PercRange (float *) 2x1 vector with percentile range desired (values between 0 and 100)
6053 \param PercRangeVal (float *) 2x1 vector with values in V corresponding the percentile range
6054 \param iPercRangeVal (int *) 2 x 1 vector containing indices into Vsort of PercRangeVal.
6055 i.e. PercRangeVal[0] = Vsort[iPercRangeVal[0]];
6056 PercRangeVal[1] = Vsort[iPercRangeVal[1]];
6057 pass NULL if you do not care for it.
6058 \ret Vsort, pointer to the sorted version of V. NULL in case of error.
6059 NOTE: Before a NULL is returned, Vsort is freed.
6060
6061 This function only allocates space for Vsort if a null is passed for Vsort in the function call
6062
6063 \sa SUMA_dPercRange, SUMA_PercRangeVol
6064 */
SUMA_PercRange(float * V,float * Vsort,int N_V,float * PercRange,float * PercRangeVal,int * iPercRangeVal)6065 float * SUMA_PercRange (float *V, float *Vsort, int N_V, float *PercRange,
6066 float *PercRangeVal, int *iPercRangeVal)
6067 {
6068 static char FuncName[] = {"SUMA_PercRange"};
6069 int *isort, il, ih;
6070
6071 SUMA_ENTRY;
6072
6073 if (PercRange[0] < 0 || PercRange[0] > 100 ||
6074 PercRange[1] < 0 || PercRange[1] > 100) {
6075 SUMA_S_Err("Values in PercRange must be between 0 and 100.\n"
6076 "Vsort will be freed.");
6077 if (Vsort) SUMA_free(Vsort);
6078 SUMA_RETURN (NULL);
6079 }
6080
6081 if (!Vsort) {
6082 /* need to create my own sorted version */
6083 Vsort = (float *)SUMA_calloc (N_V, sizeof(float));
6084 if (!Vsort) {
6085 fprintf (SUMA_STDERR,
6086 "Error %s: Failed to allocate for Vsort.\n", FuncName);
6087 SUMA_RETURN (NULL);
6088 }
6089 /* copy V to Vsort */
6090 SUMA_COPY_VEC (V, Vsort, N_V, float, float);
6091
6092 /* sort Vsort */
6093 isort = SUMA_z_qsort (Vsort , N_V ); SUMA_free(isort);
6094 }
6095
6096 /* choose the index for the lower range */
6097 il = (int)rint((N_V-1)*PercRange[0]/100.0);
6098 ih = (int)rint((N_V-1)*PercRange[1]/100.0);
6099 PercRangeVal[0] = Vsort[il];
6100 PercRangeVal[1] = Vsort[ih];
6101 if (iPercRangeVal) {
6102 iPercRangeVal[0] = il; iPercRangeVal[1] = ih;
6103 }
6104 SUMA_RETURN (Vsort);
6105 }
6106
6107 /*! \brief a variant on SUMA_PercRange.
6108
6109 Be careful with returned parameters they have a different meaning than
6110 those from SUMA_PercRange. The percentiles refer to the masked version
6111 of V, rather than V itself.
6112
6113 Vmsort = SUMA_PercRangeVol (V, mask, N_V, PercRange, N_PercRange,
6114 PercRangeVal, iPercRangeVal,
6115 exzero, N_Vmsort);
6116
6117 \param V (float *) pointer to vector containing N_V values
6118 \param mask (byte *) pointer to mask indicating which values of V to consider
6119 \param N_V (int) number of values in V (and in mask)
6120 \param PercRange (float *) N_PercRange x 1 vector with percentile values
6121 desired (values between 0 and 100)
6122 \param N_PercRange (int) Number of values
6123 \param PercRangeVal (float *) N_PercRange x 1 vector with values in V
6124 corresponding to the percentile range
6125 \param iPercRangeVal (int *) N_PercRange x 1 vector containing indices
6126 into Vmsort of PercRangeVal.
6127 i.e. PercRangeVal[0] = Vmsort[iPercRangeVal[0]];
6128 PercRangeVal[k] = Vmsort[iPercRangeVal[k]];
6129 pass NULL if you do not care for it.
6130 \param exzero (int) if (1) then exclude 0 from consideration. Else
6131 exact zero values are considered.
6132 \param N_Vmsort (int *) Pointer to integer to contain resultant number of
6133 values in Vmsort. If you pass a non null mask,
6134 and/or exzero == 1, *N_Vmsort <= N_V
6135 \ret Vmsort, pointer to the sorted MASKED version of V. NULL in case of error.
6136
6137 */
SUMA_PercRangeVol(float * V,byte * mask,int N_V,float * PercRange,int N_PercRange,float * PercRangeVal,int * iPercRangeVal,int exzero,int * N_Vmsort)6138 float * SUMA_PercRangeVol (float *V, byte *mask, int N_V,
6139 float *PercRange, int N_PercRange,
6140 float *PercRangeVal, int *iPercRangeVal,
6141 int exzero, int *N_Vmsort)
6142 {
6143 static char FuncName[] = {"SUMA_PercRangeVol"};
6144 int *isort, il, i, N_sorted;
6145 float *Vmsort=NULL;
6146 SUMA_Boolean LocalHead = NOPE;
6147
6148 SUMA_ENTRY;
6149
6150 if (N_Vmsort) *N_Vmsort = -1;
6151
6152 for (i=0; i<N_PercRange; ++i) {
6153 if (PercRange[i] < 0 || PercRange[i] > 100 ) {
6154 SUMA_S_Err("Values in PercRange (%d=%f) must be between 0 and 100.",
6155 i, PercRange[i]);
6156 SUMA_RETURN (NULL);
6157 }
6158 }
6159
6160 {
6161 N_sorted = 0;
6162 if (!mask && !exzero) N_sorted = N_V;
6163 else if (mask) {
6164 if (!exzero) {
6165 for (il=0; il<N_V; ++il) if (mask[il]) ++N_sorted;
6166 } else {
6167 for (il=0; il<N_V; ++il) {
6168 if (V[il] == 0.0f) mask[il]=0;
6169 if (mask[il]) ++N_sorted;
6170 }
6171 }
6172 } else if (exzero) {
6173 for (il=0; il<N_V; ++il) if (V[il] != 0.0f) ++N_sorted;
6174 }
6175 /* need to create my own sorted version */
6176 Vmsort = (float *)SUMA_calloc (N_sorted, sizeof(float));
6177 if (!Vmsort) {
6178 fprintf (SUMA_STDERR,
6179 "Error %s: Failed to allocate for Vmsort.\n", FuncName);
6180 SUMA_RETURN (NULL);
6181 }
6182
6183 if (!mask && !exzero) {
6184 /* copy V to Vmsort */
6185 SUMA_COPY_VEC (V, Vmsort, N_sorted, float, float);
6186 } else {
6187 if (mask) { /* exzero has been subsumed already */
6188 for (i=0, il=0; il<N_V; ++il) {
6189 if (mask[il]) Vmsort[i++] = V[il];
6190 }
6191 } else { /* only have exzero */
6192 for (i=0, il=0; il<N_V; ++il) {
6193 if (V[il] != 0.0f) Vmsort[i++] = V[il];
6194 }
6195 }
6196 }
6197 if (LocalHead && N_sorted < 1000) {
6198 SUMA_LH("Unsorted vector");
6199 for (i=0; i<N_sorted; ++i) {
6200 fprintf(SUMA_STDERR,"%.3f ", Vmsort[i]);
6201 }
6202 fprintf(SUMA_STDERR,"\n");
6203 }
6204 /* sort Vmsort */
6205 isort = SUMA_z_qsort (Vmsort , N_sorted ); SUMA_free(isort);
6206 }
6207 if (N_Vmsort) *N_Vmsort = N_sorted;
6208
6209 if (LocalHead && N_sorted < 1000) {
6210 SUMA_LH("Sorted vector");
6211 for (i=0; i<N_sorted; ++i) {
6212 fprintf(SUMA_STDERR,"%.3f ", Vmsort[i]);
6213 }
6214 fprintf(SUMA_STDERR,"\n");
6215 }
6216 /* choose the index for the lower range */
6217 for (i=0; i<N_PercRange; ++i) {
6218 il = (int)rint((N_sorted-1)*PercRange[i]/100.0);
6219 PercRangeVal[i] = Vmsort[il];
6220 if (LocalHead)
6221 fprintf(SUMA_STDERR,
6222 "%d: %.3f%% --> %f %.3f @ sample %d in sorted array\n",
6223 i, PercRange[i], PercRangeVal[i],
6224 (float)i*100.0/(N_PercRange-1), il);
6225 if (iPercRangeVal) {
6226 iPercRangeVal[i] = il;
6227 }
6228 }
6229
6230 SUMA_RETURN (Vmsort);
6231 }
6232
6233 /*!
6234 Vsort = SUMA_dPercRange (V, Vsort, N_V, PercRange, PercRangeVal, iPercRangeVal)
6235 the double version of SUMA_PercRange, working with double instead of float data
6236 \sa SUMA_PercRange
6237 */
SUMA_dPercRange(double * V,double * Vsort,int N_V,double * PercRange,double * PercRangeVal,int * iPercRangeVal)6238 double * SUMA_dPercRange (double *V, double *Vsort, int N_V, double *PercRange, double *PercRangeVal, int *iPercRangeVal)
6239 {
6240 static char FuncName[] = {"SUMA_dPercRange"};
6241 int *isort, il, ih;
6242
6243 SUMA_ENTRY;
6244
6245 if (PercRange[0] < 0 || PercRange[0] > 100 || PercRange[1] < 0 || PercRange[1] > 100) {
6246 fprintf (SUMA_STDERR, "Error %s: Values in PercRange must be between 0 and 100.\nVsort will be freed.\n", FuncName);
6247 if (Vsort) SUMA_free(Vsort);
6248 SUMA_RETURN (NULL);
6249 }
6250
6251 if (!Vsort) {
6252 /* need to create my own sorted version */
6253 Vsort = (double *)SUMA_calloc (N_V, sizeof(double));
6254 if (!Vsort) {
6255 fprintf (SUMA_STDERR, "Error %s: Failed to allocate for Vsort.\n", FuncName);
6256 SUMA_RETURN (NULL);
6257 }
6258 /* copy V to Vsort */
6259 SUMA_COPY_VEC (V, Vsort, N_V, double, double);
6260
6261 /* sort Vsort */
6262 isort = SUMA_z_doubqsort (Vsort , N_V ); SUMA_free(isort);
6263 }
6264
6265 /* choose the index for the lower range */
6266 il = (int)rint((N_V-1)*PercRange[0]/100.0);
6267 ih = (int)rint((N_V-1)*PercRange[1]/100.0);
6268 PercRangeVal[0] = Vsort[il];
6269 PercRangeVal[1] = Vsort[ih];
6270 if (iPercRangeVal) {
6271 iPercRangeVal[0] = il; iPercRangeVal[1] = ih;
6272 }
6273 SUMA_RETURN (Vsort);
6274 }
6275
SUMA_freeXformDatum(void * dd)6276 void SUMA_freeXformDatum (void *dd) {
6277 if (dd) NI_free_element(dd); return;
6278 }
6279
SUMA_freeCallbackDatum(void * dd)6280 void SUMA_freeCallbackDatum(void *dd) {
6281 if (dd) NI_free_element(dd); return;
6282 }
6283
6284 /*!
6285 Function to allocate and initialize an Overlays pointer
6286
6287 ans = SUMA_CreateOverlayPointer (Name, SUMA_DSET *dset, char *ownerid, SUMA_OVERLAYS *recycle);
6288
6289 \param Name (char *): A character string containing the name of the color overlay
6290 \param dset (SUMA_DSET *): Pointer to data set structure that this plane gets its
6291 data from.
6292 \param ownerid (char *) idcode of owner of colorplane. Can set it to NULL if you
6293 don't care.
6294 \param recycle (SUMA_OVERLAYS *): Reuse this overlays pointer (used to replace current overlay pointer.
6295 \ret ans (SUMA_OVERLAYS *): a pointer to the structure containing the color overlay
6296 NULL is returned in case of trouble.
6297
6298 The following fields are set to these defaults:
6299 Show = NOPE;
6300 GlobalOpacity = -1.0;
6301 LocalOpacity vector is all zeros except the first value is -1.0
6302 FullList = 1
6303 PlaneOrder = -1; i.e. not set
6304 isBackGrnd = 0 ; i.e. none
6305 SymIrange = 0;
6306 \sa SUMA_FreeOverlayPointer
6307
6308 */
SUMA_CreateOverlayPointerIdentifiers(int N_Nodes,const char * Name,SUMA_DSET * dset,char * ownerid)6309 SUMA_OVERLAYS * SUMA_CreateOverlayPointerIdentifiers(
6310 int N_Nodes, const char *Name,
6311 SUMA_DSET *dset, char *ownerid)
6312 {
6313 static char FuncName[]={"SUMA_CreateOverlayPointerIdentifiers"};
6314 SUMA_OVERLAYS *Sover=NULL;
6315 SUMA_FileName sfn;
6316 int N_Alloc = -1, i=0;
6317 SUMA_Boolean LocalHead = NOPE;
6318
6319 SUMA_ENTRY;
6320
6321 // fprintf(stderr, "%s\n", FuncName);
6322
6323 if (!Name) {
6324 SUMA_S_Err("Bad boy! Name should never be NULL here.");
6325 SUMA_RETURN(NULL);
6326 }
6327
6328 Sover = (SUMA_OVERLAYS *)SUMA_calloc(1, sizeof(SUMA_OVERLAYS));
6329 if (!Sover) {
6330 fprintf (SUMA_STDERR,
6331 "Error %s: Could not allocate for Sover.\n", FuncName);
6332 SUMA_RETURN (NULL);
6333 }
6334
6335 Sover->N_links = 0;
6336 if (ownerid) sprintf(Sover->owner_id, "%s", ownerid);
6337 else Sover->owner_id[0] = '\0';
6338 Sover->LinkedPtrType = SUMA_LINKED_OVERLAY_TYPE;
6339 Sover->do_type = not_DO_type;
6340
6341 /* make a link to dset */
6342 SUMA_LH("Linking to Dset");
6343 Sover->dset_link = (SUMA_DSET *)SUMA_LinkToPointer ((void *)dset);
6344 /* N_Nodes is no longer used, use it for sanity check only */
6345 if (Sover->dset_link->dnel) {
6346 if (N_Nodes != SDSET_VECLEN(Sover->dset_link)) {
6347 SUMA_S_Errv("N_Nodes (%d) not equal to vec_len (%d)",
6348 N_Nodes , SDSET_VECLEN(Sover->dset_link));
6349 SUMA_RETURN(NULL);
6350 }
6351 } else { SUMA_SL_Err ("No nel yet !"); SUMA_RETURN(NULL);}
6352 Sover->dtlvl = SDSET_DAT_LEVEL(dset);
6353
6354
6355 /* copy the name */
6356 Sover->Name = (char *)SUMA_calloc (strlen(Name)+1, sizeof(char));
6357 Sover->Name = strcpy(Sover->Name, Name);
6358
6359 /* create a label */
6360 sfn = SUMA_StripPath((char *)Name);
6361 Sover->Label = sfn.FileName;
6362 if (sfn.Path) SUMA_free(sfn.Path); /* get rid of path */
6363
6364 Sover->rowgraph_mtd=NULL;
6365 Sover->rowgraph_num=0;
6366
6367 Sover->N_Contours = 0;
6368 Sover->Contours = NULL;
6369
6370 Sover->LinkMode = SW_LinkMode_Stat;
6371 if (SUMA_EnvEquals("SUMA_IxT_LinkMode", "None",1,NULL)) {
6372 Sover->LinkMode = SW_LinkMode_None;
6373 } if (SUMA_EnvEquals("SUMA_IxT_LinkMode", "Pls1",1,NULL)) {
6374 Sover->LinkMode = SW_LinkMode_Pls1;
6375 } if (SUMA_EnvEquals("SUMA_IxT_LinkMode", "Same",1,NULL)) {
6376 Sover->LinkMode = SW_LinkMode_Same;
6377 } if (SUMA_EnvEquals("SUMA_IxT_LinkMode", "Stat",1,NULL)) {
6378 Sover->LinkMode = SW_LinkMode_Stat;
6379 }
6380
6381 Sover->ClustList = NULL;
6382 Sover->ClustOfNode = NULL;
6383
6384 if (!SUMA_SetOverlay_Vecs(Sover, 'A', -1, "clear", 0)) {
6385 SUMA_S_Err("Failed to clear T/V");
6386 }
6387
6388 Sover->AlphaThresh = 0.1;
6389 Sover->AlphaVal = SW_SurfCont_DsetAlphaVal_Max;
6390
6391 SUMA_RETURN(Sover);
6392 }
6393
SUMA_CreateOverlayPointer(const char * Name,SUMA_DSET * dset,char * ownerid,SUMA_OVERLAYS * Recycle)6394 SUMA_OVERLAYS * SUMA_CreateOverlayPointer (
6395 const char *Name,
6396 SUMA_DSET *dset, char *ownerid,
6397 SUMA_OVERLAYS *Recycle)
6398 {
6399 static char FuncName[]={"SUMA_CreateOverlayPointer"};
6400 SUMA_OVERLAYS *Sover=NULL;
6401 NI_group *ncmap=NULL;
6402 SUMA_FileName sfn;
6403 int N_Alloc = -1, i=0;
6404 int N_Nodes = 0, SymChosen=0;
6405 SUMA_Boolean LocalHead = NOPE;
6406
6407
6408 // fprintf(stderr, "%s\n", FuncName);
6409
6410
6411 SUMA_ENTRY;
6412
6413 if (LocalHead) {
6414 SUMA_DUMP_TRACE("Who just called?");
6415 }
6416 if (!dset || !Name) {
6417 SUMA_SL_Err("Need dset, need name.");
6418 SUMA_RETURN(NULL);
6419 }
6420
6421 N_Nodes = SDSET_VECLEN(dset); /* Mar. 2009 */
6422
6423 if (!Recycle) { /* a new puppy */
6424 if (!(Sover = SUMA_CreateOverlayPointerIdentifiers(N_Nodes, Name,
6425 dset, ownerid))) {
6426 SUMA_S_Err("Failed to create overlay pointer identifiers.");
6427 SUMA_RETURN(NULL);
6428 }
6429 } else {
6430 Sover = Recycle;
6431 /* cleanup things to be replaced */
6432 if (!SUMA_FreeOverlayPointerRecyclables (Sover)) {
6433 SUMA_SL_Err("Recycling failed!\nEarth is doomed.");
6434 SUMA_FreeOverlayPointer(Sover);
6435 SUMA_RETURN(NULL);
6436 }
6437 Sover->dtlvl = SDSET_DAT_LEVEL(dset);
6438 }
6439
6440 SUMA_LH("Allocating for vectors");
6441 N_Alloc = COLP_N_ALLOC(Sover);
6442
6443 if (N_Alloc != N_Nodes) {
6444 SUMA_SL_Err("This is not supposed to be.");
6445 SUMA_RETURN(NULL);
6446 }
6447 Sover->N_NodeDef = N_Nodes;
6448 Sover->NodeDef = (int *) SUMA_calloc(N_Alloc, sizeof(int));
6449 for (i=0; i < Sover->N_NodeDef; ++i) Sover->NodeDef[i] = i;
6450 Sover->FullList = 1;
6451
6452
6453 // fprintf(stderr, "%s\n", FuncName);
6454
6455 Sover->ColVec = (float *)SUMA_calloc(N_Alloc*3, sizeof(float));
6456 Sover->ColAlpha = NULL;
6457 Sover->RemixOID = 0;
6458 if (!SUMA_SetOverlay_Vecs(Sover, 'A', -1, "clear", 0)) {
6459 SUMA_S_Err("Failed to clear T/V");
6460 }
6461 Sover->LocalOpacity = (float *)SUMA_calloc(N_Alloc, sizeof(float));
6462 Sover->LocalOpacity[0] = -1.0; /* flag indicating local facts
6463 have not been initialized */
6464
6465 if (!Sover->ColVec || !Sover->LocalOpacity || !Sover->NodeDef) {
6466 fprintf (SUMA_STDERR,
6467 "Error %s: Could not allocate for Sover fields.\n", FuncName);
6468 SUMA_FreeOverlayPointer(Sover);
6469 SUMA_RETURN (NULL);
6470 }
6471
6472 if (!Recycle) {
6473 Sover->GlobalOpacity = -1.0; /* no factor applied */
6474 Sover->ShowMode = -SW_SurfCont_DsetViewCol;
6475 Sover->Font = SUMA_FontStr2FontMenuItem(SUMA_EnvVal("SUMA_Dset_Font"));
6476 Sover->NodeRad = SW_SurfCont_DsetNodeRadConst;
6477 Sover->Through =
6478 SUMA_ThroughStr2ThroughMenuItem(SUMA_EnvVal("SUMA_Dset_NodeConnections"));
6479 Sover->NodeRadGain = 1.0;
6480 Sover->NodeCol = SW_SurfCont_DsetNodeColYellow;
6481 Sover->BordFrac = SW_SurfCont_DsetGmatBord0;
6482 Sover->EdgeThick = SW_SurfCont_DsetEdgeThickConst;
6483 Sover->EdgeThickGain = 1.0;
6484 Sover->TxtShad = SW_SurfCont_DsetTxtShad1;
6485 Sover->EdgeStip = SW_SurfCont_DsetEdgeStipXXX;
6486 Sover->AlphaVal = SW_SurfCont_DsetAlphaVal_Max;
6487 Sover->PlaneOrder = -1; /* No order is specified */
6488 Sover->isBackGrnd = 0; /* no brightness modulation effects */
6489 Sover->DimFact = 0.3;
6490 Sover->ForceIntRange[0] = 0.0;
6491 Sover->ForceIntRange[1] = 0.0; /* force nothing */
6492 Sover->AlphaThresh = 0.1;
6493
6494 /* new, from Feb 20 */
6495 /* default, choose something */
6496 SUMA_LH("SCM stuff");
6497 if (!SUMAg_CF->scm) { /* try building it */
6498 SUMAg_CF->scm = SUMA_Build_Color_maps();
6499 }
6500 if (!SUMAg_CF->scm) {
6501 SUMA_LH("SUMA color maps not set up.");
6502 Sover->cmapname = NULL;
6503 Sover->OptScl = NULL;
6504 } else {
6505 if (SDSET_IS_VOL(dset)) {
6506 if (SUMA_is_Label_dset(dset, &ncmap)) {
6507 if (!ncmap) { /* have no colormap, throw one in */
6508 if (!(ncmap = SUMA_CreateCmapForLabelDset(dset, NULL, -1))) {
6509 SUMA_S_Err("Failed to create new label dset cmap");
6510 }
6511 /* stick color map in database */
6512 if (!SUMA_Insert_Cmap_of_Dset(dset)) {
6513 SUMA_S_Err("Failed to insert Cmap");
6514 SUMA_FreeDset(dset); dset = NULL;
6515 SUMA_RETURN(NOPE);
6516 }
6517 Sover->cmapname = SUMA_copy_string(
6518 NI_get_attribute(ncmap,"Name"));
6519 }
6520 Sover->SymIrange = 0; SymChosen = 1;
6521 } else {
6522 char *eee=getenv("SUMA_VO_ColorMap");
6523 if (eee) {
6524 if (!SUMA_FindNamedColMap(eee)) {
6525 Sover->cmapname = SUMA_copy_string("bw20");
6526 SUMA_S_Errv( "Colormap %s not found.\n"
6527 "Using bw20 instead.\n", eee);
6528 } else Sover->cmapname = SUMA_copy_string(eee);
6529 } else {
6530 Sover->cmapname = SUMA_copy_string("bw20");
6531 }
6532 Sover->SymIrange = 0; SymChosen = 1;
6533 }
6534 } else if (SUMA_is_VFR_dset(dset)) {
6535 char *eee=getenv("SUMA_VFR_DsetColorMap");
6536 if (eee) {
6537 if (!SUMA_FindNamedColMap(eee)) {
6538 Sover->cmapname = SUMA_copy_string("afni_n2");
6539 SUMA_S_Errv( "Colormap %s not found.\n"
6540 "Using afni_n2 instead.\n", eee);
6541 } else Sover->cmapname = SUMA_copy_string(eee);
6542 } else {
6543 Sover->cmapname = SUMA_copy_string("afni_n2");
6544 }
6545 Sover->SymIrange = 1; SymChosen = 1;
6546 } else if (SUMA_is_RetinoAngle_dset(dset)) {
6547 char *eee=getenv("SUMA_RetinoAngle_DsetColorMap");
6548 if (eee) {
6549 if (!SUMA_FindNamedColMap(eee)) {
6550 Sover->cmapname = SUMA_copy_string("rgybr20");
6551 SUMA_S_Errv( "Colormap %s not found.\n"
6552 "Using rgybr20 instead.\n", eee);
6553 } else Sover->cmapname = SUMA_copy_string(eee);
6554 } else {
6555 Sover->cmapname = SUMA_copy_string("rgybr20");
6556 }
6557 } else if (SUMA_is_Label_dset(dset, &ncmap)) {
6558 /* this is a label dset */
6559 if (!ncmap) { /* have no colormap, throw one in */
6560 if (!(ncmap = SUMA_CreateCmapForLabelDset(dset, NULL, -1))) {
6561 SUMA_S_Err("Failed to create new label dset cmap");
6562 }
6563 /* stick color map in database */
6564 if (!SUMA_Insert_Cmap_of_Dset(dset)) {
6565 SUMA_S_Err("Failed to insert Cmap");
6566 SUMA_FreeDset(dset); dset = NULL;
6567 SUMA_RETURN(NOPE);
6568 }
6569 Sover->cmapname = SUMA_copy_string(
6570 NI_get_attribute(ncmap,"Name"));
6571 }
6572 Sover->SymIrange = 0; SymChosen = 1;
6573 } else {
6574 char *eee=getenv("SUMA_DsetColorMap");
6575 if (eee) {
6576 if (!SUMA_FindNamedColMap(eee)) {
6577 Sover->cmapname = SUMA_copy_string("Spectrum:red_to_blue");
6578 SUMA_S_Errv( "Colormap %s not found.\n"
6579 "Using Spectrum:red_to_blue instead.\n", eee);
6580 } else Sover->cmapname = SUMA_copy_string(eee);
6581 } else {
6582 Sover->cmapname = SUMA_copy_string("Spectrum:red_to_blue");
6583 }
6584 }
6585
6586 Sover->OptScl = SUMA_ScaleToMapOptInit();
6587 if (!Sover->OptScl) {
6588 fprintf (SUMA_STDERR,
6589 "Error %s: Could not get scaling option structure.\n",
6590 FuncName);
6591 SUMA_RETURN (NOPE);
6592 }
6593 if (SUMA_is_VFR_dset(dset)) {
6594 Sover->OptScl->interpmode = SUMA_NO_INTERP;
6595 } else if (SUMA_is_Label_dset(dset, NULL) ||
6596 SUMA_is_Label_dset_col(dset, 0)) {
6597 Sover->OptScl->interpmode = SUMA_DIRECT; /* default for such dsets */
6598 }
6599 }
6600 if (SUMA_isEnv("SUMA_Sym_I_Range","FYES") ||
6601 SUMA_isEnv("SUMA_Sym_I_Range","FNO") ) {
6602 Sover->SymIrange = SUMA_isEnv("SUMA_Sym_I_Range","FYES")?1:0;
6603 } else if (!SymChosen) {
6604 Sover->SymIrange = SUMA_isEnv("SUMA_Sym_I_Range","YES")?1:0;
6605 }
6606 }
6607
6608 SUMA_RETURN (Sover);
6609 }
6610
6611 /*!
6612 \brief releases an overlay pointer (decrement its inode count and
6613 free it if necessary)
6614 */
SUMA_ReleaseOverlay(SUMA_OVERLAYS * Overlays,SUMA_INODE * Overlays_Inode)6615 SUMA_Boolean SUMA_ReleaseOverlay (SUMA_OVERLAYS * Overlays,
6616 SUMA_INODE *Overlays_Inode)
6617 {
6618 static char FuncName[]={"SUMA_ReleaseOverlay"};
6619 SUMA_Boolean LocalHead = NOPE;
6620
6621 SUMA_ENTRY;
6622
6623 // fprintf(stderr, "%s\n", FuncName);
6624
6625 if (Overlays_Inode || Overlays) { /* there should be no case where only one of two is null but if such a case existed, you'll get notified below. */
6626 if (SUMA_ReleaseLink(Overlays_Inode)) {
6627 /* some links are left, do not free memory */
6628 } else {
6629 if (LocalHead)
6630 fprintf (SUMA_STDERR,
6631 "%s: Overlay plane %s is free of links, "
6632 "freeing allocated memory ...\n", FuncName, Overlays->Name);
6633 if (Overlays) SUMA_FreeOverlayPointer (Overlays);
6634 if (Overlays_Inode) SUMA_free(Overlays_Inode);
6635 }
6636 }
6637 SUMA_RETURN(YUP);
6638 }
6639 /*!
6640 Function to free an overlay structure
6641 ans = SUMA_FreeOverlayPointer (Sover);
6642 \param Sover (SUMA_OVERLAYS * )
6643 \ret ans (SUMA_Boolean) (YUP/NOPE)
6644
6645 -WARNING, If YOU CREATED AN INODE FOR THIS POINTER, YOU NEED TO RELASE IT BEFORE YOU FREE Sover
6646 Perhaps you should use SUMA_FreeOverlay (SUMA_OVERLAYS * Sover, SUMA_INODE *Sover_Inode);
6647
6648 If you free one overlay structure at a time, take care to make sure the
6649 plane orders still make sense
6650 */
SUMA_FreeOverlayPointerRecyclables(SUMA_OVERLAYS * Sover)6651 SUMA_Boolean SUMA_FreeOverlayPointerRecyclables (SUMA_OVERLAYS * Sover)
6652 {
6653 static char FuncName[]={"SUMA_FreeOverlayPointerRecyclables"};
6654
6655 SUMA_ENTRY;
6656
6657 // fprintf(stderr, "%s\n", FuncName);
6658
6659 if (Sover == NULL) {
6660 fprintf (SUMA_STDERR,
6661 "Error %s: Sover is NULL, nothing to do. Returning OK flag.\n",
6662 FuncName);
6663 SUMA_RETURN (YUP);
6664 }
6665
6666 if (Sover->NodeDef) SUMA_free(Sover->NodeDef); Sover->NodeDef = NULL;
6667 Sover->N_NodeDef = -1;
6668 Sover->FullList = -1;
6669 /* if (Sover->ColMat) SUMA_free2D ((char **)Sover->ColMat, Sover->N_Alloc);
6670 Sover->ColMat = NULL*/
6671
6672 SUMA_ifree(Sover->ColVec);
6673 SUMA_ifree(Sover->ColAlpha);
6674 ++Sover->RemixOID; /* Does not hurt to change it */
6675
6676 if (!SUMA_SetOverlay_Vecs(Sover, 'A', -1, "clear", 0)) {
6677 SUMA_S_Err("Failed to clear T/V");
6678 }
6679
6680 if (Sover->LocalOpacity) SUMA_free(Sover->LocalOpacity);
6681 Sover->LocalOpacity = NULL;
6682
6683 if (Sover->ClustList) {
6684 dlist_destroy(Sover->ClustList);
6685 SUMA_free(Sover->ClustList); Sover->ClustList = NULL;
6686 if (Sover->ClustOfNode) SUMA_free(Sover->ClustOfNode);
6687 Sover->ClustOfNode = NULL;
6688 }
6689
6690 SUMA_RETURN (YUP);
6691 }
6692
SUMA_KillOverlayContours(SUMA_OVERLAYS * Sover)6693 void SUMA_KillOverlayContours(SUMA_OVERLAYS * Sover)
6694 {
6695
6696 int kkk=0;
6697
6698 if (Sover) {
6699 if (Sover->Contours) {
6700 for (kkk=0; kkk<Sover->N_Contours; ++kkk)
6701 if (Sover->Contours[kkk]) SUMA_freeDrawnROI(Sover->Contours[kkk]);
6702 SUMA_free(Sover->Contours);
6703 }
6704 Sover->Contours = NULL;
6705 Sover->N_Contours = 0;
6706 }
6707
6708 }
6709
SUMA_FreeOverlayPointer(SUMA_OVERLAYS * Sover)6710 SUMA_Boolean SUMA_FreeOverlayPointer (SUMA_OVERLAYS * Sover)
6711 {
6712 static char FuncName[]={"SUMA_FreeOverlayPointer"};
6713 int kkk=0;
6714
6715 SUMA_ENTRY;
6716
6717 // fprintf(stderr, "%s\n", FuncName);
6718
6719 if (Sover == NULL) {
6720 fprintf (SUMA_STDERR,
6721 "Error %s: Sover is NULL, nothing to do. Returning OK flag.\n",
6722 FuncName);
6723 SUMA_RETURN (YUP);
6724 }
6725 /* is this pointer used by others ? */
6726 if (Sover->N_links) {
6727 Sover = (SUMA_OVERLAYS*)SUMA_UnlinkFromPointer((void *)Sover);
6728 SUMA_RETURN (YUP);
6729 }
6730
6731 /* No more links, go for it */
6732 if (Sover->dset_link) Sover->dset_link =
6733 (SUMA_DSET *)SUMA_UnlinkFromPointer((void *)Sover->dset_link);
6734 if (Sover->Label) SUMA_free(Sover->Label);
6735 if (Sover->Name) SUMA_free(Sover->Name);
6736 if (Sover->cmapname) SUMA_free(Sover->cmapname);
6737 if (Sover->OptScl) {
6738 if (Sover->OptScl->ClustOpt) {
6739 SUMA_free_SurfClust_Opt(Sover->OptScl->ClustOpt);
6740 }
6741 SUMA_free(Sover->OptScl);
6742 }
6743 if (Sover->rowgraph_mtd) Sover->rowgraph_mtd = NULL; /* that struct is killed
6744 with delete_memplot
6745 which is called with
6746 donebut_CB in
6747 plot_motif.c*/
6748 SUMA_KillOverlayContours(Sover);
6749 if (Sover->ClustList) {
6750 dlist_destroy(Sover->ClustList);
6751 SUMA_free(Sover->ClustList); Sover->ClustList = NULL;
6752 if (Sover->ClustOfNode) SUMA_free(Sover->ClustOfNode);
6753 Sover->ClustOfNode = NULL;
6754 }
6755
6756 if (!SUMA_SetOverlay_Vecs(Sover, 'A', -1, "clear", 0)) {
6757 SUMA_S_Err("Failed to clear T/V");
6758 }
6759
6760 SUMA_free(Sover); Sover = NULL;
6761
6762 SUMA_RETURN (YUP);
6763 }
6764
6765 /*!
6766 function to fetch a certain overlay pointer for a displayable object
6767 ptr = SUMA_Fetch_OverlayPointer (ado, Name, OverInd);
6768
6769 if an overlay pointer named Name exists for ado then it is returned in ptr
6770 else ptr is null
6771 \param Overlays (SUMA_OVERLAYS **) vector of overlay plane pointers
6772 \param N_Overlays (int) number of overlay planes
6773 \param Name (const char *) name of overlay plane to fetch
6774 \param OverInd (int *) index of overlay plane in Overlays that is fetched (-1 if plane not found)
6775 \ret ptr (SUMA_OVERLAYS *) pointer of overlay plane (= Overlays[*OverInd]) NULL if Name is not found
6776 */
SUMA_Fetch_OverlayPointer(SUMA_ALL_DO * ado,const char * Name,int * OverInd)6777 SUMA_OVERLAYS * SUMA_Fetch_OverlayPointer (SUMA_ALL_DO *ado, const char * Name,
6778 int * OverInd)
6779 {
6780 static char FuncName[]={"SUMA_Fetch_OverlayPointer"};
6781 int i, ifound =-1, nfound = 0;
6782 SUMA_OVERLAYS *ptr= NULL;
6783 SUMA_PARSED_NAME *pn=NULL;
6784 SUMA_Boolean LocalHead = NOPE;
6785
6786 SUMA_ENTRY;
6787
6788 // fprintf(stderr, "%s\n", FuncName);
6789
6790 if (!ado || !Name) SUMA_RETURN(NULL);
6791
6792 switch (ado->do_type) {
6793 case SO_type: {
6794 SUMA_SurfaceObject *SO = (SUMA_SurfaceObject *)ado;
6795 SUMA_RETURN(SUMA_Fetch_OverlayPointer_arr(SO->Overlays, SO->N_Overlays,
6796 Name, OverInd));
6797 break; }
6798 case MD_DSET_type: {
6799 SUMA_S_Warn("You could get an overlay pointer associated with"
6800 " a subdomain, but that is usually not done with "
6801 "this function. One uses CDOM_type instead.");
6802 SUMA_RETURN(NULL);
6803 break; }
6804 case ANY_DSET_type:
6805 SUMA_S_Err("Why any here?");
6806 SUMA_RETURN(NULL);
6807 break;
6808 case GDSET_type: {
6809 SUMA_OVERLAYS *over = SUMA_ADO_Overlay(ado,0);
6810 SUMA_RETURN(SUMA_Fetch_OverlayPointer_arr (&over, 1, Name, OverInd));
6811 break; }
6812 case CDOM_type: {
6813 int N_over;
6814 SUMA_OVERLAYS **over=SUMA_ADO_Overlays(ado, &N_over);
6815 if (over) {
6816 SUMA_RETURN(SUMA_Fetch_OverlayPointer_arr( over, N_over,
6817 Name, OverInd));
6818 } else SUMA_RETURN(NULL);
6819 break; }
6820 case TRACT_type: {
6821 int N_over;
6822 SUMA_OVERLAYS **over=SUMA_ADO_Overlays(ado, &N_over);
6823 if (over) {
6824 SUMA_RETURN(SUMA_Fetch_OverlayPointer_arr( over, N_over,
6825 Name, OverInd));
6826 } else SUMA_RETURN(NULL);
6827 break; }
6828 case VO_type: {
6829 static int ncnt;
6830 if (!ncnt) {
6831 SUMA_LH("Not implemented yet, is this needed?");
6832 ++ncnt;
6833 }
6834 break; }
6835 default:
6836 SUMA_S_Errv("Not ready for type %s\n",
6837 SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
6838 break;
6839 }
6840
6841 SUMA_RETURN(NULL);
6842 }
6843
SUMA_Fetch_OverlayPointer_arr(SUMA_OVERLAYS ** Overlays,int N_Overlays,const char * Name,int * OverInd)6844 SUMA_OVERLAYS * SUMA_Fetch_OverlayPointer_arr (SUMA_OVERLAYS **Overlays,
6845 int N_Overlays, const char * Name, int * OverInd)
6846 {
6847 static char FuncName[]={"SUMA_Fetch_OverlayPointer_arr"};
6848 int i, ifound =-1, nfound = 0;
6849 SUMA_OVERLAYS *ptr= NULL;
6850 SUMA_PARSED_NAME *pn=NULL;
6851 SUMA_Boolean LocalHead = NOPE;
6852
6853 SUMA_ENTRY;
6854
6855 // fprintf(stderr, "%s\n", FuncName);
6856
6857 if (!Name || N_Overlays < 1 || !Overlays) SUMA_RETURN(NULL);
6858
6859 for (i=0; i < N_Overlays; ++i) {
6860 SUMA_LHv("Comparing\n>%s<\nto>%s<\n", Overlays[i]->Name, Name);
6861 if (!strcmp(Overlays[i]->Name, Name)) {
6862 *OverInd = i;
6863 SUMA_LHv("Found overlay plane %s, indexed %d.\n", Name, i);
6864 SUMA_RETURN (Overlays[i]);
6865 }
6866 }
6867
6868 /* failed to find name, perhaps name is missing the path which
6869 would be OK as long as there is no conflict */
6870 nfound = 0;
6871 for (i=0; i < N_Overlays; ++i) {
6872 if (strlen(Overlays[i]->Name) > strlen(Name)) {
6873 if((pn = SUMA_ParseFname(Overlays[i]->Name, NULL))) {
6874 if (!strcmp(pn->FileName, Name)) {
6875 ifound = i; ++nfound;
6876 }
6877 SUMA_Free_Parsed_Name(pn); pn = NULL;
6878 }
6879 }
6880 }
6881 if (nfound == 1) {
6882 i = ifound;
6883 *OverInd = i;
6884 SUMA_LHv("Found overlay plane %s in secondary search, indexed %d.\n",
6885 Name, i);
6886 SUMA_RETURN (Overlays[i]);
6887 } else if (nfound > 1) {
6888 SUMA_LHv("Found %d possible matches for %s\n", nfound, Name);
6889 }
6890
6891 SUMA_LHv("Overlay plane %s was not found.\n", Name);
6892
6893 *OverInd = -1;
6894
6895 SUMA_RETURN (NULL);
6896 }
6897
SUMA_Fetch_OverlayPointerByDset(SUMA_ALL_DO * ado,SUMA_DSET * dset,int * OverInd)6898 SUMA_OVERLAYS * SUMA_Fetch_OverlayPointerByDset (SUMA_ALL_DO *ado,
6899 SUMA_DSET *dset, int * OverInd)
6900 {
6901 static char FuncName[]={"SUMA_Fetch_OverlayPointerByDset"};
6902 int i, nfound, N_over;
6903 SUMA_OVERLAYS *ptr= NULL;
6904 SUMA_Boolean LocalHead = NOPE;
6905
6906 SUMA_ENTRY;
6907
6908 // fprintf(stderr, "%s\n", FuncName);
6909
6910 if (!dset || !ado) {
6911 SUMA_SL_Warn("NULL dset");
6912 // fprintf(stderr, "NULL\n");
6913 SUMA_RETURN(NULL);
6914 }
6915
6916 switch (ado->do_type) {
6917 case SO_type: {
6918 SUMA_SurfaceObject *SO = (SUMA_SurfaceObject *)ado;
6919 /*
6920 fprintf(stderr, "%p\n", SUMA_Fetch_OverlayPointerByDset_arr(SO->Overlays,
6921 SO->N_Overlays, dset, OverInd));
6922 */
6923 SUMA_RETURN(SUMA_Fetch_OverlayPointerByDset_arr(SO->Overlays,
6924 SO->N_Overlays, dset, OverInd));
6925 break; }
6926 case MD_DSET_type:
6927 SUMA_S_Err("Why MD?");
6928 SUMA_RETURN(NULL);
6929 break;
6930 case ANY_DSET_type:
6931 SUMA_S_Err("Why any?");
6932 SUMA_RETURN(NULL);
6933 break;
6934 case GDSET_type: {
6935 SUMA_OVERLAYS *over = SUMA_ADO_Overlay(ado,0);
6936 SUMA_RETURN(SUMA_Fetch_OverlayPointerByDset_arr(&over, 1,
6937 dset, OverInd));
6938 break; }
6939 case CDOM_type:
6940 case VO_type: {
6941 SUMA_OVERLAYS **over = SUMA_ADO_Overlays(ado, &N_over);
6942 SUMA_RETURN(SUMA_Fetch_OverlayPointerByDset_arr(over, N_over,
6943 dset, OverInd));
6944 break; }
6945 default:
6946 SUMA_S_Errv("Not ready for type %s (%d)\n",
6947 SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type), ado->do_type);
6948 if (LocalHead) SUMA_DUMP_TRACE("Bad object type");
6949 break;
6950 }
6951
6952 //fprintf(stderr, "NULL\n");
6953 SUMA_RETURN(NULL);
6954
6955
6956 }
6957 /*!
6958 Look for overlay pointers for a particular dset
6959 */
SUMA_Fetch_OverlayPointerByDset_arr(SUMA_OVERLAYS ** Overlays,int N_Overlays,SUMA_DSET * dset,int * OverInd)6960 SUMA_OVERLAYS * SUMA_Fetch_OverlayPointerByDset_arr (SUMA_OVERLAYS **Overlays,
6961 int N_Overlays, SUMA_DSET *dset, int * OverInd)
6962 {
6963 static char FuncName[]={"SUMA_Fetch_OverlayPointerByDset_arr"};
6964 int i, nfound;
6965 SUMA_OVERLAYS *ptr= NULL;
6966 SUMA_Boolean LocalHead = NOPE;
6967
6968 // fprintf(stderr, "%s\n", FuncName);
6969
6970 SUMA_ENTRY;
6971 if (!dset) {
6972 SUMA_SL_Warn("NULL dset");
6973 SUMA_RETURN(NULL);
6974 }
6975
6976 if (LocalHead) {
6977 fprintf( SUMA_STDERR,
6978 "%s: Seaching from %d overlays for dset_link = %p\n",
6979 FuncName, N_Overlays, dset);
6980 }
6981 nfound = 0;
6982 *OverInd = -1;
6983 for (i=0; i < N_Overlays; ++i) {
6984 if (LocalHead)
6985 fprintf( SUMA_STDERR,"%s: %p ?= %p\n",
6986 FuncName, Overlays[i]->dset_link, dset);
6987 if (Overlays[i]->dset_link == dset) {
6988 *OverInd = i;
6989 ++nfound;
6990 if (LocalHead)
6991 fprintf (SUMA_STDOUT,"%s: Found overlay plane %s, indexed %d.\n",
6992 FuncName, Overlays[i]->Name, i);
6993 }
6994 }
6995
6996 if (*OverInd >= 0) {
6997 if (nfound == 1) {
6998 SUMA_RETURN (Overlays[*OverInd]);
6999 } else {
7000 SUMA_SL_Err("Multiple overlays found for dset!");
7001 *OverInd = -1;
7002 SUMA_RETURN(NULL);
7003 }
7004 }
7005
7006 if (LocalHead)
7007 fprintf (SUMA_STDOUT,"%s: Overlay plane for dset %p (%s) not found.\n",
7008 FuncName, dset,SDSET_LABEL(dset));
7009
7010 *OverInd = -1;
7011
7012 SUMA_RETURN (NULL);
7013 }
7014
SUMA_Overlays_2_GLCOLAR4(SUMA_ALL_DO * ado,SUMA_SurfaceViewer * SV,GLfloat * glcolar)7015 SUMA_Boolean SUMA_Overlays_2_GLCOLAR4(SUMA_ALL_DO *ado,
7016 SUMA_SurfaceViewer *SV, GLfloat *glcolar)
7017 {
7018 static char FuncName[]={"SUMA_Overlays_2_GLCOLAR4"};
7019 SUMA_Boolean LocalHead = NOPE;
7020
7021 // fprintf(stderr, "%s\n", FuncName);
7022
7023 SUMA_ENTRY;
7024 if (!ado) SUMA_RETURN(NOPE);
7025 if (LocalHead) {
7026 SUMA_LH("Overlays 2 GLCOLAR viewer %i",
7027 SUMA_WhichSV (SV, SUMAg_SVv, SUMAg_N_SVv));
7028 SUMA_DUMP_TRACE("We were called from...");
7029 }
7030 switch(ado->do_type) {
7031 case SO_type:
7032 SUMA_RETURN(SUMA_Overlays_2_GLCOLAR4_SO((SUMA_SurfaceObject *)ado,
7033 SV, glcolar));
7034 break;
7035 case MD_DSET_type:
7036 SUMA_S_Err("A Multi Domain Dset. Why are you here with this?");
7037 SUMA_RETURN(NOPE);
7038 break;
7039 case ANY_DSET_type:
7040 SUMA_S_Err("Why are you here with this?");
7041 SUMA_RETURN(NOPE);
7042 break;
7043 case CDOM_type: {
7044 SUMA_CIFTI_DO *co = (SUMA_CIFTI_DO *)ado;
7045 SUMA_CIFTI_SAUX *CSaux = CDO_CSAUX(co);
7046 int N_dat = SUMA_ADO_N_Datum(ado);
7047 int ShowOverLays[SUMA_MAX_OVERLAYS];
7048 int ShowOverLays_sort[SUMA_MAX_OVERLAYS];
7049 int OverlayOrder[SUMA_MAX_OVERLAYS], j, i, i4, *isort, NshowOverlays;
7050 SUMA_X_SurfCont *SurfCont=NULL;
7051 float av, am;
7052 int ioff, k;
7053 byte *tex3ddata = NULL;
7054
7055 SUMA_S_Note("This is no longer in use. CIFTI datasets and DOs "
7056 "are elementarized and rendered thusly");
7057 break;
7058 #if 0
7059 /* delete soon, that was pass one */
7060 if (!CSaux || !CSaux->N_Overlays || !CSaux->Overlays) {
7061 SUMA_S_Errv("No CSaux or CSaux->Overlays for %s\n",
7062 ADO_LABEL(ado));
7063 SUMA_RETURN(NOPE);
7064 }
7065 if (!(SurfCont = SUMA_ADO_Cont(ado))) {
7066 SUMA_S_Err("No ADO controller");
7067 SUMA_RETURN(NOPE);
7068 }
7069 if (!CSaux->isColored) {
7070 if (!(CSaux->isColored =
7071 (SUMA_Boolean *)SUMA_calloc(N_dat,sizeof(SUMA_Boolean)))) {
7072 SUMA_S_Crit("Failed to allocate for iscolored");
7073 SUMA_RETURN(NOPE);
7074 }
7075 } else {
7076 memset(CSaux->isColored, 0, sizeof(SUMA_Boolean)*N_dat);
7077 }
7078
7079 NshowOverlays = 0;
7080 for (j=0; j < CSaux->N_Overlays; ++j) {
7081 SUMA_LH("overlay %d, %p, ShowMode %d",
7082 j, CSaux->Overlays[j], CSaux->Overlays[j]->ShowMode);
7083 if ( (CSaux->Overlays[j]->ShowMode == SW_SurfCont_DsetViewCol &&
7084 CSaux->Overlays[j]->GlobalOpacity != 0) ) {
7085 if (SurfCont->ShowCurForeOnly) {
7086 if (SurfCont->curColPlane == CSaux->Overlays[j]) {
7087 SUMA_LHv("Le ShowCurForeOnly %s , j=%d in action\n",
7088 CSaux->Overlays[j]->Label, j);
7089 ShowOverLays[NshowOverlays] = j;
7090 OverlayOrder[NshowOverlays] =
7091 CSaux->Overlays[j]->PlaneOrder;
7092 ++ NshowOverlays;
7093 }
7094 } else {
7095 ShowOverLays[NshowOverlays] = j;
7096 OverlayOrder[NshowOverlays] = CSaux->Overlays[j]->PlaneOrder;
7097 ++ NshowOverlays;
7098 }
7099 }
7100 }
7101 if (NshowOverlays > 1) {
7102 isort = SUMA_z_dqsort (OverlayOrder, NshowOverlays );
7103 /* use sorting by plane order to reorder ShowOverlays */
7104 for (j=0; j < NshowOverlays; ++j) {
7105 ShowOverLays_sort[j] = ShowOverLays[isort[j]];
7106 }
7107 /* done with isort, free it */
7108 SUMA_free(isort);
7109 } else if (NshowOverlays == 1) {
7110 ShowOverLays_sort[0] = ShowOverLays[0];
7111 } else { /* be safe */
7112 ShowOverLays_sort[0] = 0;
7113 }
7114 SUMA_LH("Have %d overlays to mix", NshowOverlays);
7115 if (NshowOverlays &&
7116 !SUMA_MixOverlays ( CSaux->Overlays, CSaux->N_Overlays,
7117 ShowOverLays_sort, NshowOverlays,
7118 glcolar, N_dat,
7119 CSaux->isColored, NOPE)) {
7120 SUMA_S_Err("Failed in SUMA_MixOverlays.");
7121 SUMA_RETURN (NOPE);
7122 }
7123
7124 ioff = 0;
7125 for (k=0; k<co->N_subdoms; ++k) {
7126 if (k>0) ioff += SUMA_ADO_N_Datum(co->subdoms[k-1]);
7127
7128 if (co->subdoms[k]->do_type == VO_type) {
7129 SUMA_VolumeObject *vo = (SUMA_VolumeObject *)co->subdoms[k];
7130 N_dat = SUMA_ADO_N_Datum(co->subdoms[k]);
7131 SUMA_LH("Loading into texture %d voxels.\n"
7132 "Using VE zero's (%p) textureonly, ioff=%d",
7133 N_dat, vo->VE ? vo->VE[0]:NULL, ioff);
7134 if (!(tex3ddata = vo->VE[0]->texvec)) {
7135 SUMA_S_Err("No texture vector?.");
7136 SUMA_RETURN (NOPE);
7137 }
7138 j=0;
7139 for(i = ioff; i < N_dat+ioff; i++) {
7140 if (CSaux->isColored[i]) {
7141 SUMA_S_Note("Voxel %d is colored", j/4);
7142 i4 = 4*(i); av = 0.0; am = 0;
7143 tex3ddata[j] = (byte)(glcolar[i4] * 255);
7144 av += tex3ddata[j]; am = tex3ddata[j]; ++j;
7145 tex3ddata[j] = (byte)(glcolar[i4+1] * 255);
7146 av += tex3ddata[j]; if (tex3ddata[j] > am)
7147 am = tex3ddata[j]; ++j;
7148 tex3ddata[j] = (byte)(glcolar[i4+2] * 255);
7149 av += tex3ddata[j]; if (tex3ddata[j] > am)
7150 am = tex3ddata[j]; ++j;
7151 if (0) tex3ddata[j] = (byte)(av/3.0);
7152 else tex3ddata[j] = am;
7153 ++j;
7154 } else {
7155 tex3ddata[j++] = 0;
7156 tex3ddata[j++] = 0;
7157 tex3ddata[j++] = 0;
7158 tex3ddata[j++] = 1;
7159 }
7160 }
7161 /* Set the alphas, for now this would work for one volume only.
7162 When mixing multiple overlays, may decide who will be doing
7163 the mixing and how, if at all ColAlpha is to play with
7164 LocalOpacity ...*/
7165 if (NshowOverlays > 0) {
7166 SUMA_OVERLAYS *Sover=CSaux->Overlays[ShowOverLays_sort[0]];
7167 int cnt;
7168 SUMA_LH("Have AlphaVal of %d (%d)",
7169 Sover ? Sover->AlphaVal:-999, ShowOverLays_sort[0]);
7170 if (Sover && Sover->ColAlpha && Sover->NodeDef) {
7171 if (NshowOverlays != 1) {
7172 SUMA_S_Warn(
7173 "ColAlpha has not been considered for multiple overlays\n"
7174 "Using alpha of zeroth volume.");
7175 }
7176 SUMA_LH("Doing the alphas %d", Sover->N_NodeDef);
7177 for(cnt = 0; cnt < Sover->N_NodeDef; cnt++) {
7178 #if 0
7179 /* We are not ready for the use of NodeDef in Sover
7180 quite yet. NodeDef has to have a Domain Definition
7181 accompanying it. */
7182 i = Sover->NodeDef[cnt];
7183 tex3ddata[4*i+3] = Sover->ColAlpha[cnt];
7184 /*if (cnt < 10) fprintf(stderr,"%d ",Sover->ColAlpha[cnt]);*/
7185 #endif
7186 }
7187 /* fprintf(stderr,"\n");*/
7188 }
7189 }
7190
7191 if (!SUMA_VE_LoadTexture(vo->VE, 0)){
7192 SUMA_S_Err("Failed to GL load texture");
7193 SUMA_RETURN(NOPE);
7194 }
7195 }
7196 }
7197 break;
7198 #endif
7199 SUMA_RETURN(YUP);
7200 }
7201 case GDSET_type: {
7202 SUMA_DSET *dset=(SUMA_DSET *)ado;
7203 SUMA_GRAPH_SAUX *GSaux = SDSET_GSAUX(dset);
7204 if (!GSaux || !GSaux->Overlay) {
7205 SUMA_S_Errv("No GSaux or GSaux->Overlay for %s\n",
7206 SDSET_LABEL(dset));
7207 SUMA_RETURN(NOPE);
7208 }
7209 if (!GSaux->isColored) {
7210 /* isColored might be too problematic for sparse graphs
7211 from very large networks... will see */
7212 if (!(GSaux->isColored =
7213 (SUMA_Boolean *)SUMA_calloc((1+SUMA_GDSET_Max_Edge_Index(dset)),
7214 sizeof(SUMA_Boolean)))) {
7215 SUMA_S_Crit("Failed to allocate for iscolored");
7216 SUMA_RETURN(NOPE);
7217 }
7218 } else {
7219 memset(GSaux->isColored, 0, sizeof(SUMA_Boolean)*
7220 (1+SUMA_GDSET_Max_Edge_Index(dset)));
7221 }
7222 if (!SUMA_MixOverlays ( &GSaux->Overlay, 1, NULL, 0,
7223 glcolar, (1+SUMA_GDSET_Max_Edge_Index(dset)),
7224 GSaux->isColored, NOPE)) {
7225 SUMA_S_Err("Failed in SUMA_MixOverlays.");
7226 SUMA_RETURN (NOPE);
7227 }
7228 SUMA_RETURN(YUP);
7229 break; }
7230 case MASK_type: {
7231 static int ncnt = 0;
7232 if (!ncnt) {
7233 SUMA_LH("Nothing to be done here."); ++ncnt;
7234 }
7235 SUMA_RETURN(YUP);
7236 break; }
7237 case TRACT_type: {
7238 SUMA_TractDO *tdo = (SUMA_TractDO *)ado;
7239 SUMA_TRACT_SAUX *TSaux = TDO_TSAUX(tdo);
7240 int N_dat = 1+SUMA_ADO_Max_Datum_Index_Lev(ado,SUMA_ELEM_DAT);
7241 int ShowOverLays[SUMA_MAX_OVERLAYS];
7242 int ShowOverLays_sort[SUMA_MAX_OVERLAYS];
7243 int OverlayOrder[SUMA_MAX_OVERLAYS], j, *isort, NshowOverlays;
7244 SUMA_X_SurfCont *SurfCont=NULL;
7245
7246 if (!TSaux || !TSaux->N_Overlays || !TSaux->Overlays) {
7247 SUMA_S_Errv("No TSaux or TSaux->Overlays for %s\n",
7248 ADO_LABEL(ado));
7249 SUMA_RETURN(NOPE);
7250 }
7251 if (!(SurfCont = SUMA_ADO_Cont(ado))) {
7252 SUMA_S_Err("No ADO controller");
7253 SUMA_RETURN(NOPE);
7254 }
7255 if (!TSaux->isColored) {
7256 if (!(TSaux->isColored =
7257 (SUMA_Boolean *)SUMA_calloc(N_dat,sizeof(SUMA_Boolean)))) {
7258 SUMA_S_Crit("Failed to allocate for iscolored");
7259 SUMA_RETURN(NOPE);
7260 }
7261 } else {
7262 memset(TSaux->isColored, 0, sizeof(SUMA_Boolean)*N_dat);
7263 }
7264
7265 NshowOverlays = 0;
7266 for (j=0; j < TSaux->N_Overlays; ++j) {
7267 SUMA_LH("overlay %d, %p, ShowMode %d",
7268 j, TSaux->Overlays[j], TSaux->Overlays[j]->ShowMode);
7269 if ( (TSaux->Overlays[j]->ShowMode == SW_SurfCont_DsetViewCol &&
7270 TSaux->Overlays[j]->GlobalOpacity != 0) ) {
7271 if (SurfCont->ShowCurForeOnly) {
7272 if (SurfCont->curColPlane == TSaux->Overlays[j]) {
7273 SUMA_LHv("Le ShowCurForeOnly %s , j=%d in action\n",
7274 TSaux->Overlays[j]->Label, j);
7275 ShowOverLays[NshowOverlays] = j;
7276 OverlayOrder[NshowOverlays] =
7277 TSaux->Overlays[j]->PlaneOrder;
7278 ++ NshowOverlays;
7279 }
7280 } else {
7281 ShowOverLays[NshowOverlays] = j;
7282 OverlayOrder[NshowOverlays] = TSaux->Overlays[j]->PlaneOrder;
7283 ++ NshowOverlays;
7284 }
7285 }
7286 }
7287 if (NshowOverlays > 1) {
7288 isort = SUMA_z_dqsort (OverlayOrder, NshowOverlays );
7289 /* use sorting by plane order to reorder ShowOverlays */
7290 for (j=0; j < NshowOverlays; ++j) {
7291 ShowOverLays_sort[j] = ShowOverLays[isort[j]];
7292 }
7293 /* done with isort, free it */
7294 SUMA_free(isort);
7295 }
7296 if (NshowOverlays == 1) {
7297 ShowOverLays_sort[0] = ShowOverLays[0];
7298 }
7299 SUMA_LH("Have %d overlays to mix", NshowOverlays);
7300 if (!SUMA_MixOverlays ( TSaux->Overlays, TSaux->N_Overlays,
7301 ShowOverLays_sort, NshowOverlays,
7302 glcolar, N_dat,
7303 TSaux->isColored, NOPE)) {
7304 SUMA_S_Err("Failed in SUMA_MixOverlays.");
7305 SUMA_RETURN (NOPE);
7306 }
7307 SUMA_RETURN(YUP);
7308 break; }
7309 case VO_type: {
7310 SUMA_VolumeObject *vo = (SUMA_VolumeObject *)ado;
7311 SUMA_VOL_SAUX *VSaux = VDO_VSAUX(vo);
7312 int N_dat = SUMA_ADO_N_Datum(ado);
7313 int ShowOverLays[SUMA_MAX_OVERLAYS];
7314 int ShowOverLays_sort[SUMA_MAX_OVERLAYS];
7315 int OverlayOrder[SUMA_MAX_OVERLAYS], j, i, i4, *isort, NshowOverlays;
7316 SUMA_X_SurfCont *SurfCont=NULL;
7317 float av, am;
7318 byte *tex3ddata = NULL;
7319
7320 if (!VSaux || !VSaux->N_Overlays || !VSaux->Overlays) {
7321 SUMA_S_Errv("No VSaux or VSaux->Overlays for %s\n",
7322 ADO_LABEL(ado));
7323 SUMA_RETURN(NOPE);
7324 }
7325 if (!(SurfCont = SUMA_ADO_Cont(ado))) {
7326 SUMA_S_Err("No ADO controller");
7327 SUMA_RETURN(NOPE);
7328 }
7329 if (!VSaux->isColored) {
7330 if (!(VSaux->isColored =
7331 (SUMA_Boolean *)SUMA_calloc(N_dat,sizeof(SUMA_Boolean)))) {
7332 SUMA_S_Crit("Failed to allocate for iscolored");
7333 SUMA_RETURN(NOPE);
7334 }
7335 } else {
7336 memset(VSaux->isColored, 0, sizeof(SUMA_Boolean)*N_dat);
7337 }
7338
7339 NshowOverlays = 0;
7340 for (j=0; j < VSaux->N_Overlays; ++j) {
7341 SUMA_LH("overlay %d, %p, ShowMode %d",
7342 j, VSaux->Overlays[j], VSaux->Overlays[j]->ShowMode);
7343 if ( (VSaux->Overlays[j]->ShowMode == SW_SurfCont_DsetViewCol &&
7344 VSaux->Overlays[j]->GlobalOpacity != 0) ) {
7345 if (SurfCont->ShowCurForeOnly) {
7346 if (SurfCont->curColPlane == VSaux->Overlays[j]) {
7347 SUMA_LHv("Le ShowCurForeOnly %s , j=%d in action\n",
7348 VSaux->Overlays[j]->Label, j);
7349 ShowOverLays[NshowOverlays] = j;
7350 OverlayOrder[NshowOverlays] =
7351 VSaux->Overlays[j]->PlaneOrder;
7352 ++ NshowOverlays;
7353 }
7354 } else {
7355 ShowOverLays[NshowOverlays] = j;
7356 OverlayOrder[NshowOverlays] = VSaux->Overlays[j]->PlaneOrder;
7357 ++ NshowOverlays;
7358 }
7359 }
7360 }
7361 if (NshowOverlays > 1) {
7362 isort = SUMA_z_dqsort (OverlayOrder, NshowOverlays );
7363 /* use sorting by plane order to reorder ShowOverlays */
7364 for (j=0; j < NshowOverlays; ++j) {
7365 ShowOverLays_sort[j] = ShowOverLays[isort[j]];
7366 }
7367 /* done with isort, free it */
7368 SUMA_free(isort);
7369 } else if (NshowOverlays == 1) {
7370 ShowOverLays_sort[0] = ShowOverLays[0];
7371 } else { /* be safe */
7372 ShowOverLays_sort[0] = 0;
7373 }
7374 SUMA_LH("Have %d overlays to mix", NshowOverlays);
7375 if (NshowOverlays &&
7376 !SUMA_MixOverlays ( VSaux->Overlays, VSaux->N_Overlays,
7377 ShowOverLays_sort, NshowOverlays,
7378 glcolar, N_dat,
7379 VSaux->isColored, NOPE)) {
7380 SUMA_S_Err("Failed in SUMA_MixOverlays.");
7381 SUMA_RETURN (NOPE);
7382 }
7383 SUMA_LH("Loading into texture %d voxels.\n"
7384 "Using VE zero's (%p) textureonly",
7385 N_dat, vo->VE ? vo->VE[0]:NULL);
7386 if (!(tex3ddata = vo->VE[0]->texvec)) {
7387 SUMA_S_Err("No texture vector?.");
7388 SUMA_RETURN (NOPE);
7389 }
7390
7391 j=0;
7392 for(i = 0; i < N_dat; i++) {
7393 if (VSaux->isColored[i]) {
7394 i4 = 4*i; av = 0.0; am = 0;
7395 tex3ddata[j] = (byte)(glcolar[i4] * 255);
7396 av += tex3ddata[j]; am = tex3ddata[j]; ++j;
7397 tex3ddata[j] = (byte)(glcolar[i4+1] * 255);
7398 av += tex3ddata[j]; if (tex3ddata[j] > am)
7399 am = tex3ddata[j]; ++j;
7400 tex3ddata[j] = (byte)(glcolar[i4+2] * 255);
7401 av += tex3ddata[j]; if (tex3ddata[j] > am)
7402 am = tex3ddata[j]; ++j;
7403 if (0) tex3ddata[j] = (byte)(av/3.0);
7404 else tex3ddata[j] = am;
7405 ++j;
7406 } else {
7407 tex3ddata[j++] = 0;
7408 tex3ddata[j++] = 0;
7409 tex3ddata[j++] = 0;
7410 tex3ddata[j++] = 0;
7411 }
7412 }
7413 /* Set the alphas, for now this would work for one volume only.
7414 When mixing multiple overlays, may decide who will be doing
7415 the mixing and how, if at all ColAlpha is to play with
7416 LocalOpacity ...*/
7417 if (NshowOverlays > 0) {
7418 SUMA_OVERLAYS *Sover=VSaux->Overlays[ShowOverLays_sort[0]];
7419 int cnt;
7420 SUMA_LH("Have AlphaVal of %d (%d)",
7421 Sover ? Sover->AlphaVal:-999, ShowOverLays_sort[0]);
7422 if (Sover && Sover->ColAlpha && Sover->NodeDef) {
7423 if (NshowOverlays != 1) {
7424 SUMA_S_Warn(
7425 "ColAlpha has not been considered for multiple overlays\n"
7426 "Using alpha of zeroth volume.");
7427 }
7428 SUMA_LH("Doing the alphas %d", Sover->N_NodeDef);
7429 for(cnt = 0; cnt < Sover->N_NodeDef; cnt++) {
7430 i = Sover->NodeDef[cnt];
7431 tex3ddata[4*i+3] = Sover->ColAlpha[cnt];
7432 }
7433 }
7434 }
7435
7436 if (!SUMA_VE_LoadTexture(vo->VE, 0)){
7437 SUMA_S_Err("Failed to GL load texture");
7438 SUMA_RETURN(NOPE);
7439 }
7440
7441 SUMA_RETURN(YUP);
7442 break; }
7443 default:
7444 SUMA_S_Errv("Not ready for type %d (%s)\n",
7445 ado->do_type, SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
7446 SUMA_DUMP_TRACE("Where did that type come from?");
7447 SUMA_RETURN(NOPE);
7448 }
7449 SUMA_RETURN(NOPE);
7450 }
7451
7452 /*!
7453
7454 function to turn color overlay planes into GL color array
7455
7456 --- usage prior to Fri Nov 7 15:58:57 EST 2003 ---
7457 ans = SUMA_Overlays_2_GLCOLAR4_SO(Overlays, N_Overlays, glar_ColorList,
7458 N_Node,
7459 Back_Modfact, ShowBackground, ShowForeground);
7460
7461
7462 \param Overlays (SUMA_OVERLAYS **) a pointer to the vector of overlay planes
7463 structure pointers
7464 \param N_Overlays (int) number of overlay plane structures
7465 \param glar_ColorList (GLfloat *) pointer to vector (4*SO->N_Node long) that
7466 contains the node colors
7467 \param N_Node (int) total number of nodes in Surface NOT in color overlay
7468 plane
7469 \param Back_Modfact (float) Background brightness modulation factor typically
7470 SAFNIg_cSV->Back_Modfact
7471 \param ShowBackground (SUMA_Boolean) flag for showing/hiding background
7472 (brightness modulating) colors
7473 \param ShowForeground (SUMA_Boolean) flag for showing/hiding foreground colors
7474 \ret YUP/NOPE
7475 \sa SUMA_MixOverlays
7476
7477 --- current usage ---
7478 ans = SUMA_Overlays_2_GLCOLAR4_SO(SO, SV, glar_ColorList)
7479 \param SO (SUMA_SurfaceObject *) surface structure with all the parameters
7480 listed in the old usage needed, and more
7481 \param SV (SUMA_SurfaceViewer *) surface viewer structure with all the
7482 parameters listed in the old usage needed, and more
7483 \param glar_ColorList (GLfloat *) pointer to vector (4*SO->N_Node long) that
7484 contains the node colors
7485 */
7486
SUMA_Overlays_2_GLCOLAR4_SO(SUMA_SurfaceObject * SO,SUMA_SurfaceViewer * SV,GLfloat * glcolar)7487 SUMA_Boolean SUMA_Overlays_2_GLCOLAR4_SO(SUMA_SurfaceObject *SO,
7488 SUMA_SurfaceViewer *SV, GLfloat *glcolar)
7489 {
7490 static char FuncName[]={"SUMA_Overlays_2_GLCOLAR4_SO"};
7491 int ShowOverLays[SUMA_MAX_OVERLAYS], ShowOverLays_Back[SUMA_MAX_OVERLAYS];
7492 int ShowOverLays_sort[SUMA_MAX_OVERLAYS],
7493 ShowOverLays_Back_sort[SUMA_MAX_OVERLAYS], iloc[SUMA_MAX_OVERLAYS];
7494 int OverlayOrder_Back[SUMA_MAX_OVERLAYS], OverlayOrder[SUMA_MAX_OVERLAYS];
7495 int i, j, NshowOverlays, NshowOverlays_Back, *isort, i4, i4_0, i4_1, i4_2;
7496 SUMA_Boolean *isColored, *isColored_Fore, *isColored_Back;
7497 GLfloat *glcolar_Fore , *glcolar_Fore_tmp, *glcolar_Back;
7498 float avg_Back, avgfact;
7499 SUMA_OVERLAYS ** Overlays;
7500 int N_Overlays;
7501 int N_Node;
7502 float Back_Modfact;
7503 SUMA_Boolean ShowBackground;
7504 SUMA_Boolean ShowForeground;
7505 SUMA_Boolean LocalHead = NOPE; /* local headline debugging messages */
7506
7507 // fprintf(stderr, "%s\n", FuncName);
7508
7509 SUMA_ENTRY;
7510
7511 if (!SO || !SV || !glcolar) {
7512 SUMA_SL_Err("Null input to SUMA_Overlays_2_GLCOLAR4_SO!");
7513 SUMA_RETURN(NOPE);
7514 }
7515
7516 /* old variable names */
7517 Overlays = SO->Overlays;
7518 N_Overlays = SO->N_Overlays;
7519 N_Node = SO->N_Node;
7520 Back_Modfact = SV->Back_Modfact;
7521 ShowBackground = SV->ShowBackground;
7522 ShowForeground = SV->ShowForeground;
7523
7524 if (LocalHead) {
7525 SUMA_LHv("Showing all overlay planes.\n"
7526 "SurfCont->curColPlane=%s\n",
7527 SO->SurfCont->curColPlane ?
7528 SO->SurfCont->curColPlane->Label:"NULL");
7529 if (0) {
7530 SUMA_Print_Surface_Object(SO, NULL);
7531 SUMA_Show_ColorOverlayPlanes (Overlays, N_Overlays, 0);
7532 }
7533 }
7534
7535 /* get the indices into the color structure vector of overlays to be shown */
7536 NshowOverlays = 0;
7537 NshowOverlays_Back = 0;
7538 for (j=0; j < N_Overlays; ++j) {
7539 if (!Overlays){
7540 SUMA_S_Err("NULL Overlays pointer.");
7541 SUMA_RETURN (NOPE);
7542 }
7543 if (Overlays == 0x1){
7544 SUMA_S_Err("Invalid Overlays pointer: 0x1.");
7545 SUMA_RETURN (NOPE);
7546 }
7547
7548 if ( (Overlays[j]->ShowMode == SW_SurfCont_DsetViewCol ||
7549 Overlays[j]->ShowMode == SW_SurfCont_DsetViewCaC ) &&
7550 Overlays[j]->GlobalOpacity != 0) {
7551 if (Overlays[j]->isBackGrnd) {
7552 if (0) { /* There is no
7553 SO->SurfCont->ShowCurBackOnly and I am not
7554 sure how useful it would be.
7555 Also, it makes little sense to use ShowCurForeOnly,
7556 because background colors are mixed separately,
7557 and attenuate the resultant foreground mixture
7558 even when just 'one' of the foreground is
7559 shown... */
7560 if (SO->SurfCont->curColPlane == Overlays[j]) {
7561 SUMA_LHv("Le ShowCurForeOnly %s in bg action\n",
7562 Overlays[j]->Label);
7563 ShowOverLays_Back[NshowOverlays_Back] = j;
7564 OverlayOrder_Back[NshowOverlays_Back] =
7565 Overlays[j]->PlaneOrder;
7566 ++ NshowOverlays_Back;
7567 }
7568 } else {
7569 ShowOverLays_Back[NshowOverlays_Back] = j;
7570 OverlayOrder_Back[NshowOverlays_Back] = Overlays[j]->PlaneOrder;
7571 ++ NshowOverlays_Back;
7572 }
7573 }else {
7574 if (SO->SurfCont->ShowCurForeOnly) {
7575 if (SO->SurfCont->curColPlane == Overlays[j]) {
7576 SUMA_LHv("Le ShowCurForeOnly %s in action\n",
7577 Overlays[j]->Label);
7578 ShowOverLays[NshowOverlays] = j;
7579 OverlayOrder[NshowOverlays] = Overlays[j]->PlaneOrder;
7580 ++ NshowOverlays;
7581 }
7582 } else {
7583 ShowOverLays[NshowOverlays] = j;
7584 OverlayOrder[NshowOverlays] = Overlays[j]->PlaneOrder;
7585 ++ NshowOverlays;
7586 }
7587 }
7588 }
7589 }
7590
7591 SUMA_LHv("Found %d Mix overlays and %d Mix-Brightmod overlays.\n",
7592 NshowOverlays, NshowOverlays_Back);
7593
7594 /* vvvvvvvvvvvvvvvvvvvvvvvvv allocate space ------------------------------*/
7595
7596 isColored = (SUMA_Boolean *) SUMA_calloc (N_Node, sizeof(SUMA_Boolean));
7597 /* allocate for flag indicating the a node is colored */
7598 if (!isColored) {
7599 fprintf (SUMA_STDERR,
7600 "Error %s: Failed to allocate for isColored.\n", FuncName);
7601 SUMA_RETURN (NOPE);
7602 }
7603
7604 glcolar_Back = NULL;
7605 isColored_Back = NULL;
7606 if (ShowBackground) {
7607 if (NshowOverlays_Back) {
7608 glcolar_Back = (GLfloat *) SUMA_calloc (4*N_Node, sizeof(GLfloat));
7609 isColored_Back = (SUMA_Boolean *)
7610 SUMA_calloc (N_Node, sizeof(SUMA_Boolean));
7611
7612 if (!isColored_Back || !glcolar_Back) {
7613 SUMA_S_Err("Failed to allocate for isColored_Back || glcolar_Back.");
7614 SUMA_RETURN (NOPE);
7615 }
7616 }
7617 }
7618
7619 isColored_Fore = NULL;
7620 glcolar_Fore = NULL;
7621 if (ShowForeground) {
7622 if (NshowOverlays) {
7623 glcolar_Fore = (GLfloat *) SUMA_calloc (4*N_Node, sizeof(GLfloat));
7624 isColored_Fore = (SUMA_Boolean *)
7625 SUMA_calloc (N_Node, sizeof(SUMA_Boolean));
7626
7627 if (!isColored_Fore || !glcolar_Fore) {
7628 SUMA_S_Err("Failed to allocate for isColored_Fore || glcolar_Fore");
7629 SUMA_RETURN (NOPE);
7630 }
7631 }
7632 }
7633 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^ allocate space ------------------------------*/
7634
7635 /* vvvvvvvvvvvvvvvvvvvvvvvvv Background colors -----------------------------*/
7636
7637 if (ShowBackground) {
7638 /* arrange Background color planes by plane order in preparation for
7639 mixing them */
7640 /* sort plane order */
7641 if (NshowOverlays_Back > 1) {
7642 isort = SUMA_z_dqsort (OverlayOrder_Back, NshowOverlays_Back );
7643 /* use sorting by plane order to reorder ShowOverlays */
7644 for (j=0; j < NshowOverlays_Back; ++j) {
7645 ShowOverLays_Back_sort[j] = ShowOverLays_Back[isort[j]];
7646 }
7647 /* done with isort, free it */
7648 SUMA_free(isort);
7649 }
7650 if (NshowOverlays_Back == 1) {
7651 ShowOverLays_Back_sort[0] = ShowOverLays_Back[0];
7652 }
7653
7654
7655 /* mix the colors that will constitute background*/
7656 if (NshowOverlays_Back) {
7657 if (LocalHead)
7658 fprintf (SUMA_STDERR,"%s: Mixing Background colors ...\n", FuncName);
7659
7660 if (!SUMA_MixOverlays ( Overlays, N_Overlays, ShowOverLays_Back_sort,
7661 NshowOverlays_Back, glcolar_Back, N_Node,
7662 isColored_Back, NOPE)) {
7663 SUMA_S_Err("Failed in SUMA_MixOverlays.");
7664 SUMA_RETURN (NOPE);
7665 }
7666 } else {
7667 ShowBackground = NOPE;
7668 }
7669 } else {
7670 NshowOverlays_Back = 0;
7671 }
7672 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^ Background colors --------------------------*/
7673
7674
7675 /* vvvvvvvvvvvvvvvvvvvvvvvvv Foreground colors ----------------------------*/
7676 if (ShowForeground) {
7677 /* arrange foreground color planes by plane order */
7678 /* sort plane order */
7679 if (NshowOverlays > 1) {
7680 isort = SUMA_z_dqsort (OverlayOrder, NshowOverlays );
7681 /* use sorting by plane order to reorder ShowOverlays */
7682 for (j=0; j < NshowOverlays; ++j) {
7683 ShowOverLays_sort[j] = ShowOverLays[isort[j]];
7684 }
7685 /* done with isort, free it */
7686 SUMA_free(isort);
7687 }
7688 if (NshowOverlays == 1) {
7689 ShowOverLays_sort[0] = ShowOverLays[0];
7690 }
7691
7692
7693 /* Now mix the foreground colors */
7694 if (NshowOverlays) {
7695 if (LocalHead)
7696 fprintf (SUMA_STDERR,
7697 "%s: Mixing Foreground colors ....\n", FuncName);
7698 if (!SUMA_MixOverlays ( Overlays, N_Overlays, ShowOverLays_sort,
7699 NshowOverlays, glcolar_Fore, N_Node,
7700 isColored_Fore, NOPE)) {
7701 fprintf (SUMA_STDERR,
7702 "Error %s: Failed in SUMA_MixOverlays.\n", FuncName);
7703 SUMA_RETURN (NOPE);
7704 }
7705 if (SUMAg_CF->X->NumForeSmoothing > 0) {
7706 glcolar_Fore_tmp = NULL;
7707 glcolar_Fore_tmp = SUMA_SmoothAttr_Neighb_Rec (glcolar_Fore,
7708 4*SO->N_Node, NULL, SO->FN, 4,
7709 SUMAg_CF->X->NumForeSmoothing, NULL, 1);
7710 if (!glcolar_Fore_tmp) {
7711 SUMA_SL_Err("Smoothing failed.\n");
7712 } else {
7713 SUMA_free(glcolar_Fore);
7714 glcolar_Fore = glcolar_Fore_tmp; glcolar_Fore_tmp = NULL;
7715 }
7716 }
7717 } else {
7718 ShowForeground = NOPE;
7719 }
7720 } else {
7721 NshowOverlays = 0;
7722 }
7723 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Foreground colors -------------------------*/
7724
7725 /* time to modulate the mixed colors with the average brightness */
7726 if (NshowOverlays && NshowOverlays_Back) {
7727 if (LocalHead)
7728 fprintf (SUMA_STDERR,
7729 "%s: Modulating Brightness of Foreground colors ...\n",
7730 FuncName);
7731
7732 for (i=0; i < N_Node; ++i) {
7733 avgfact = Back_Modfact / 3.0;
7734 if (isColored_Fore[i] && isColored_Back[i]) {
7735 /* colors from both sides, adjust brightness */
7736 i4_0 = 4 * i; i4_1 = i4_0 + 1; i4_2 = i4_0 + 2;
7737 if (!Back_Modfact) {
7738 glcolar[i4_0] = glcolar_Fore[i4_0];
7739 glcolar[i4_1] = glcolar_Fore[i4_1];
7740 glcolar[i4_2] = glcolar_Fore[i4_2];
7741 } else {
7742 avg_Back = (glcolar_Back[i4_0] + glcolar_Back[i4_1] +
7743 glcolar_Back[i4_2]) * avgfact ;
7744 glcolar[i4_0] = avg_Back * glcolar_Fore[i4_0];
7745 glcolar[i4_1] = avg_Back * glcolar_Fore[i4_1];
7746 glcolar[i4_2] = avg_Back * glcolar_Fore[i4_2];
7747 }
7748 isColored[i] = YUP;
7749 continue;
7750 }
7751 if (isColored_Fore[i]) {
7752 i4 = 4 * i;
7753 glcolar[i4] = glcolar_Fore[i4]; ++i4;
7754 glcolar[i4] = glcolar_Fore[i4]; ++i4;
7755 glcolar[i4] = glcolar_Fore[i4]; ++i4;
7756 isColored[i] = YUP;
7757 continue;
7758 }
7759 if (isColored_Back[i]) {
7760 i4 = 4 * i;
7761 glcolar[i4] = glcolar_Back[i4]; ++i4;
7762 glcolar[i4] = glcolar_Back[i4]; ++i4;
7763 glcolar[i4] = glcolar_Back[i4]; ++i4;
7764 isColored[i] = YUP;
7765 continue;
7766 } else {
7767 /* has never been colored, put defaults */
7768 i4 = 4 * i;
7769 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7770 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7771 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7772 isColored[i] = NOPE;
7773 }
7774 }
7775
7776 if (LocalHead)
7777 fprintf (SUMA_STDERR,
7778 "%s: Done Modulating Brightness of overlay colors.\n",
7779 FuncName);
7780 }
7781
7782 if (NshowOverlays && !NshowOverlays_Back) {
7783 if (LocalHead)
7784 fprintf (SUMA_STDERR,"%s: Only Foreground colors.\n", FuncName);
7785 for (i=0; i < N_Node; ++i) {
7786 if (isColored_Fore[i]) {
7787 i4 = 4 * i;
7788 glcolar[i4] = glcolar_Fore[i4]; ++i4;
7789 glcolar[i4] = glcolar_Fore[i4]; ++i4;
7790 glcolar[i4] = glcolar_Fore[i4]; ++i4;
7791 isColored[i] = YUP;
7792 continue;
7793 } else {
7794 i4 = 4 * i;
7795 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7796 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7797 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7798 isColored[i] = NOPE;
7799 }
7800 }
7801 }
7802
7803 if (!NshowOverlays && NshowOverlays_Back) {
7804 if (LocalHead)
7805 fprintf (SUMA_STDERR,"%s: Only Background colors.\n", FuncName);
7806 for (i=0; i < N_Node; ++i) {
7807 if (isColored_Back[i]) {
7808 i4 = 4 * i;
7809 glcolar[i4] = glcolar_Back[i4]; ++i4;
7810 glcolar[i4] = glcolar_Back[i4]; ++i4;
7811 glcolar[i4] = glcolar_Back[i4]; ++i4;
7812 isColored[i] = YUP;
7813 continue;
7814 } else {
7815 i4 = 4 * i;
7816 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7817 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7818 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7819 isColored[i] = NOPE;
7820 }
7821 }
7822 }
7823
7824 if (!(ShowBackground) && !ShowForeground) {
7825 for (i=0; i < N_Node; ++i) {
7826 i4 = 4 * i;
7827 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7828 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7829 glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
7830 }
7831 } else {
7832 /* any final airbrushing ? */
7833 if (SUMAg_CF->X->NumFinalSmoothing > 0) {
7834 glcolar_Fore_tmp = NULL;
7835 glcolar_Fore_tmp = SUMA_SmoothAttr_Neighb_Rec (glcolar,
7836 4*SO->N_Node, NULL, SO->FN, 4,
7837 SUMAg_CF->X->NumFinalSmoothing, NULL,1);
7838 if (!glcolar_Fore_tmp) {
7839 SUMA_SL_Err("Smoothing failed.\n");
7840 } else {
7841 memcpy(glcolar,glcolar_Fore_tmp, 4*SO->N_Node*sizeof(GLfloat));
7842 SUMA_free(glcolar_Fore_tmp);
7843 }
7844 }
7845 }
7846
7847 /* Set the alpha based on how gray things are.
7848 Might be a useful toy once I get around to doing
7849 depth sorting on all transparent objects*/
7850 if (0) {
7851 float l1, l2, l3, l1m2, l1m3, l2m3;
7852 for (i=0; i < N_Node; ++i) {
7853 i4 = 4 * i;
7854 l1 = glcolar[i4];
7855 l2 = glcolar[i4+1];
7856 l3 = glcolar[i4+2];
7857 l1m2 = (l1-l2); l1m3 = (l1-l3); l2m3 = (l2-l3);
7858 glcolar[i4+3] = 0.707*sqrt((l1m2*l1m2+l1m3*l1m3+l2m3*l2m3)/
7859 (l1*l1+l2*l2+l3*l3));
7860 if (i==2601 || i == 1888) {
7861 SUMA_S_Notev("Node %d, %f %f %f %f\n",
7862 i, l1, l2, l3, glcolar[i4+3]);
7863 }
7864 }
7865 }
7866
7867 /* free this mess and get out */
7868 if (isColored) SUMA_free(isColored);
7869 if (isColored_Back) SUMA_free(isColored_Back);
7870 if (glcolar_Back) SUMA_free(glcolar_Back);
7871 if (isColored_Fore) SUMA_free(isColored_Fore);
7872 if (glcolar_Fore) SUMA_free(glcolar_Fore);
7873
7874 SUMA_RETURN (YUP);
7875 }
7876
7877 /*
7878 Turn iOver into a version defined over the lowest level
7879 datum. If iOver is defined for the elementary datum then
7880 return it as is
7881 */
SUMA_ElementarizeOverlay(SUMA_OVERLAYS * iOver,float ** ColEVec,int ** NodeEDef,int * N_NodeEDef,float ** LocalEOpacity)7882 SUMA_Boolean SUMA_ElementarizeOverlay(SUMA_OVERLAYS *iOver,
7883 float **ColEVec, int **NodeEDef,
7884 int *N_NodeEDef, float **LocalEOpacity)
7885 {
7886 static char FuncName[]={"SUMA_ElementarizeOverlay"};
7887 SUMA_DATUM_LEVEL Lev = 0;
7888 SUMA_DSET *dset = NULL;
7889 SUMA_ALL_DO *ado = NULL;
7890 SUMA_Boolean LocalHead = NOPE;
7891
7892 SUMA_ENTRY;
7893 // fprintf(stderr, "%s\n", FuncName);
7894
7895
7896 if (!iOver || !ColEVec || !NodeEDef ||
7897 !N_NodeEDef || !LocalEOpacity ) {
7898 if (LocalHead) {
7899 SUMA_EDUMP_TRACE("NULL Overlay, or NULL return slots");
7900 } else SUMA_S_Err("NULL Overlay, or NULL return slots");
7901 SUMA_RETURN(NOPE);
7902 }
7903
7904 // fprintf(stderr, "%s\n", FuncName);
7905
7906 if (iOver->dtlvl == SUMA_ELEM_DAT) {
7907 *NodeEDef = COLP_NODEDEF(iOver);
7908 *N_NodeEDef = COLP_N_NODEDEF(iOver);
7909 *ColEVec = iOver->ColVec;
7910 *LocalEOpacity = iOver->LocalOpacity;
7911 SUMA_RETURN(YUP);
7912 }
7913
7914 SUMA_LH("Need elementerization for overlay");
7915 /* not elementary, need to elementarize it */
7916 if (!(ado = SUMA_Overlay_OwnerADO(iOver))) {
7917 SUMA_S_Err("Can't get owner ado");
7918 SUMA_RETURN(NOPE);
7919 }
7920
7921
7922 fprintf(stderr, "ado->do_type=%d\n", ado->do_type);
7923
7924
7925 switch (ado->do_type) {
7926 case TRACT_type: {
7927 SUMA_TractDO *tdo = (SUMA_TractDO *)ado;
7928 switch(iOver->dtlvl) {
7929 case SUMA_ELEM_DAT:
7930 SUMA_S_Err("Should not be here!");
7931 SUMA_RETURN(NOPE);
7932 break;
7933 case SUMA_LEV1_DAT: {
7934 int whine = 0, *tdef = NULL, N_tdef=-1,
7935 it, t, p0=0, p1=0, ip, ip3, it3, *nv=NULL;
7936 int N_E_Data = SUMA_ADO_Max_Datum_Index_Lev(ado, SUMA_ELEM_DAT)+1;
7937 float *cv=NULL, *ov=NULL;
7938 tdef = COLP_NODEDEF(iOver);
7939 if (!tdef) {
7940 SUMA_S_Err("No tract definition");
7941 SUMA_RETURN(NOPE);
7942 }
7943 N_tdef = COLP_N_NODEDEF(iOver);
7944 *ColEVec = (float *)SUMA_calloc(3*N_E_Data, sizeof (float));
7945 *NodeEDef = (int *)SUMA_calloc(N_E_Data, sizeof(int));
7946 *LocalEOpacity = (float *)SUMA_calloc(N_E_Data, sizeof(float));
7947 if (!ColEVec || !NodeEDef || !LocalEOpacity) {
7948 SUMA_S_Crit("Failed to allocate for about 5x%d values",
7949 N_E_Data);
7950 SUMA_RETURN(NOPE);
7951 }
7952 cv = *ColEVec;
7953 ov = *LocalEOpacity;
7954 nv = *NodeEDef;
7955 ip=0; ip3 = 0; *N_NodeEDef = 0;
7956 for (it=0; it<N_tdef; ++it) {
7957 t = tdef[it]; /* tract id */
7958 it3 = 3*it;
7959 if (Network_1T_to_TB(tdo->net, t, NULL, NULL, &p0, &p1) < 0) {
7960 if (!whine) SUMA_S_Err("Failed to map to p0, p1."
7961 "Further errors muted");
7962 ++whine;
7963 continue;
7964 }
7965 #if 0
7966 SUMA_LH( "Tract %d is from Points %d to %d, \n"
7967 "with cols [%.3f %.3f %.3f]",
7968 it, p0, p1, iOver->ColVec[it3],
7969 iOver->ColVec[it3+1], iOver->ColVec[it3+2]);
7970 #endif
7971
7972 // fprintf(stderr, "%s\n", FuncName);
7973
7974 while (p0 <= p1) {
7975 ip3 = 3*ip;
7976 cv[ip3 ] = iOver->ColVec[it3];
7977 cv[ip3+1] = iOver->ColVec[it3+1];
7978 cv[ip3+2] = iOver->ColVec[it3+2];
7979 ov[ip] = iOver->LocalOpacity[it];
7980 nv[ip] = p0;
7981 ++(*N_NodeEDef);
7982 ++ip; ++p0;
7983 }
7984 }
7985 if (whine) {
7986 SUMA_S_Warn("%d errors occurred when mapping %d tracts",
7987 whine, N_tdef);
7988 }
7989 break; }
7990 case SUMA_LEV2_DAT: {
7991 int whine = 0, *bdef = NULL, N_bdef=-1,
7992 ib, b, p0=0, p1=0, ip, ip3, ib3, *nv=NULL;
7993 int N_E_Data = SUMA_ADO_Max_Datum_Index_Lev(ado, SUMA_ELEM_DAT)+1;
7994 float *cv=NULL, *ov=NULL;
7995 bdef = COLP_NODEDEF(iOver);
7996 if (!bdef) {
7997 SUMA_S_Err("No bundle definition");
7998 SUMA_RETURN(NOPE);
7999 }
8000 N_bdef = COLP_N_NODEDEF(iOver);
8001 *ColEVec = (float *)SUMA_calloc(3*N_E_Data, sizeof (float));
8002 *NodeEDef = (int *)SUMA_calloc(N_E_Data, sizeof(int));
8003 *LocalEOpacity = (float *)SUMA_calloc(N_E_Data, sizeof(float));
8004 if (!ColEVec || !NodeEDef || !LocalEOpacity) {
8005 SUMA_S_Crit("Failed to allocate for about 5x%d values",
8006 N_E_Data);
8007 SUMA_RETURN(NOPE);
8008 }
8009
8010 cv = *ColEVec;
8011 ov = *LocalEOpacity;
8012 nv = *NodeEDef;
8013 ip=0; ip3 = 0; *N_NodeEDef = 0;
8014 for (ib=0; ib<N_bdef; ++ib) {
8015 b = bdef[ib]; /* bundle id */
8016 ib3 = 3*ib;
8017 if ((p0 = Network_1B_to_1P(tdo->net, ib, &p1)) < 0) {
8018 if (!whine) SUMA_S_Err("Failed to map bundle to p0, p1."
8019 "Further errors muted");
8020 ++whine;
8021 continue;
8022 }
8023 #if 0
8024 SUMA_LH( "Bundle %d is from Points %d to %d, \n"
8025 "with cols [%.3f %.3f %.3f]",
8026 ib, p0, p1, iOver->ColVec[ib3],
8027 iOver->ColVec[ib3+1], iOver->ColVec[ib3+2]);
8028 #endif
8029 while (p0 <= p1) {
8030 ip3 = 3*ip;
8031 cv[ip3 ] = iOver->ColVec[ib3];
8032 cv[ip3+1] = iOver->ColVec[ib3+1];
8033 cv[ip3+2] = iOver->ColVec[ib3+2];
8034 ov[ip] = iOver->LocalOpacity[ib];
8035 nv[ip] = p0;
8036 ++(*N_NodeEDef);
8037 ++ip; ++p0;
8038 }
8039 }
8040 if (whine) {
8041 SUMA_S_Warn("%d errors occurred when mapping %d bundles",
8042 whine, N_bdef);
8043 }
8044 break; }
8045 default:
8046 SUMA_S_Err("Willis!");
8047 SUMA_RETURN(NOPE);
8048 break;
8049 }
8050 break; }
8051 default:
8052 SUMA_S_Err("Not ready for non-elementary overlays for ado %s\n",
8053 ADO_LABEL(ado));
8054 SUMA_RETURN(NOPE);
8055 }
8056
8057 SUMA_RETURN(YUP);
8058 }
8059
8060 /*!
8061 function to mix overlay plane colors
8062
8063 ans = SUMA_MixOverlays (SUMA_OVERLAYS ** Overlays, int N_Overlays,
8064 int *ShowOvelays, int N_ShowOverlays,
8065 GLfloat *glcolar, int N_Node, SUMA_Boolean *isColored,
8066 SUMA_Boolean FILL)
8067
8068 Overlays (SUMA_OVERLAYS **) a pointer to the vector of overlay planes
8069 structure pointers
8070 N_Overlays (int) number of overlay plane structures
8071 ShowOvelays (int *) vector of Overlay plane indices to be used. The plane
8072 indices must be sorted by plane order.
8073 N_ShowOverlays (int) number of ovrlay planes used in the mixing
8074 glar_ColorList (GLfloat *) pointer to vector (4*SO->N_Node long) that
8075 contains the node colors
8076 N_Node (int) total number of nodes in Surface NOT in color overlay plane
8077 \param isColored (SUMA_Boolean *) N_Node x1 vector containing flags indicating if a node received a color or not
8078 \param FILL (SUMA_Boolean) top off nodes that received no color with
8079 default gray
8080
8081 \sa SUMA_Overlays_2_GLCOLAR4
8082 */
SUMA_MixOverlays(SUMA_OVERLAYS ** Overlays,int N_Overlays,int * ShowOverlays,int NshowOverlays,GLfloat * glcolar,int N_Node,SUMA_Boolean * isColored,SUMA_Boolean FILL)8083 SUMA_Boolean SUMA_MixOverlays ( SUMA_OVERLAYS ** Overlays, int N_Overlays,
8084 int *ShowOverlays, int NshowOverlays,
8085 GLfloat *glcolar, int N_Node,
8086 SUMA_Boolean *isColored, SUMA_Boolean FILL)
8087 {
8088 static char FuncName[] = {"SUMA_MixOverlays"};
8089 int i, j;
8090 int *NodeEDef=NULL, N_NodeEDef = -1;
8091 float *ColEVec=NULL, *LocalEOpacity=NULL;
8092 SUMA_OVERLAYS *Over=NULL;
8093 SUMA_Boolean Full, Fill, Locl, Glob;
8094 SUMA_Boolean LocalHead = NOPE;
8095
8096 SUMA_ENTRY;
8097
8098 if (!Overlays) {
8099 SUMA_SL_Err("Null Overlays!");
8100 SUMA_RETURN(NOPE);
8101 }
8102 if (!glcolar) {
8103 SUMA_SL_Err("Null glcolar!");
8104 SUMA_DUMP_TRACE("Null glcolar!");
8105 SUMA_RETURN(NOPE);
8106 }
8107 if (!isColored) {
8108 fprintf (SUMA_STDERR, "Error %s: isColored is NULL.\n", FuncName);
8109 SUMA_RETURN (NOPE);
8110 }
8111 if (!ShowOverlays) { /* default is to show all, in the order of Overlays */
8112 NshowOverlays = N_Overlays;
8113 }
8114 if (!NshowOverlays) { /* nothing to see here */
8115 if (FILL) {
8116 SUMA_LH("Nothing to show, Filling with blank default color\n");
8117 SUMA_FillBlanks_GLCOLAR4(isColored, N_Node, SUMA_GRAY_NODE_COLOR,
8118 SUMA_GRAY_NODE_COLOR, SUMA_GRAY_NODE_COLOR,
8119 glcolar);
8120 } else {
8121 SUMA_LH("Nothing to show, nothing filled.\n");
8122 }
8123 SUMA_RETURN (YUP);
8124 }
8125
8126 /* start building the node colors */
8127 Full = YUP;
8128 Glob = YUP;
8129 Locl = YUP;
8130 Fill = YUP;
8131
8132 for (j=0; j<NshowOverlays; ++j) {
8133 Full = YUP;
8134 Glob = YUP;
8135 Locl = YUP;
8136 Fill = YUP;
8137
8138 if (!ShowOverlays) i=j;
8139 else i = ShowOverlays[j];
8140
8141 Over = Overlays[i];
8142 if (!Over) {
8143 fprintf(SUMA_STDERR,"Error %s:\nNULL ShowOverlays[%d]\n", FuncName, i);
8144 SUMA_RETURN (NOPE);
8145 }
8146
8147 /* is this a full listing */
8148 SUMA_LHv("Full listing flag: %d\n", Over->FullList);
8149 if (Over->FullList) {
8150 Fill = NOPE;
8151 /* Full list, no need to fill up unvisited nodes at the end */
8152 } else {
8153 Full = NOPE; /* Not a full list */
8154 }
8155
8156 if (j > 0) { /* opacity plays a role when you are overlaying
8157 one plane on top of the other */
8158 /* is this a Global Factor */
8159 if (Over->GlobalOpacity < 0.0) { Glob = NOPE; }
8160
8161 /* is this a Local Factor */
8162 if (!Over->LocalOpacity) {
8163 SUMA_S_Errv("NULL Overlays[%d]->LocalOpacity\n", i);
8164 SUMA_RETURN (NOPE);
8165 }
8166 if (Over->LocalOpacity[0] < 0) { Locl = NOPE; }
8167 } else {
8168 Glob = NOPE; Locl = NOPE;
8169 }
8170
8171 /* Some datasets are defined over non-elementary data,
8172 think over a whole tract, instead of each tract point,
8173 this next call would make sure overlay is defined
8174 over each elementary datum */
8175 if (!SUMA_ElementarizeOverlay(Over, &ColEVec, &NodeEDef,
8176 &N_NodeEDef,&LocalEOpacity)) {
8177 SUMA_S_Err("Failed to elementarize overlay");
8178 SUMA_RETURN (NOPE);
8179 }
8180
8181 SUMA_LHv("Building color layer %d Overlay #%d: %s ...\n"
8182 "Full=%d, Glob=%d (Globopacity %f), Locl=%d,Fill=%d\n",
8183 j, i, Over->Name, (int)Full, (int)Glob,
8184 Over->GlobalOpacity, (int)Locl, (int)Fill);
8185
8186
8187 /* call the appropriate macro to add the overlay */
8188 if (Full && Glob && Locl) {
8189 if (SUMAg_CF->ColMixMode == SUMA_ORIG_MIX_MODE) {
8190 SUMA_LH("Calling SUMA_RGBv_FGL_AR4op ...");
8191 /* This macro used to be called:
8192 SUMA_RGBmat_FullGlobLoc2_GLCOLAR4_opacity
8193 but name was too long for some compilers */
8194 SUMA_RGBv_FGL_AR4op(ColEVec, glcolar, N_Node,
8195 Over->GlobalOpacity, LocalEOpacity, isColored);
8196 } else if (SUMAg_CF->ColMixMode == SUMA_4AML) {
8197 SUMA_LH("Calling SUMA_RGBv_FGL_AR4op2 ...");
8198 SUMA_RGBv_FGL_AR4op2(ColEVec, glcolar, N_Node,
8199 Over->GlobalOpacity, LocalEOpacity, isColored);
8200 }
8201 }
8202
8203 if (!Full && Glob && Locl) {
8204 if (SUMAg_CF->ColMixMode == SUMA_ORIG_MIX_MODE) {
8205 SUMA_LH("Calling SUMA_RGBv_PGL_AR4op ...");
8206 /* This macro used to be called:
8207 SUMA_RGBmat_PartGlobLoc2_GLCOLAR4_opacity */
8208 SUMA_RGBv_PGL_AR4op(ColEVec, NodeEDef, glcolar,
8209 N_NodeEDef, isColored, Over->GlobalOpacity,
8210 LocalEOpacity, N_Node);
8211 } else if (SUMAg_CF->ColMixMode == SUMA_4AML) {
8212 SUMA_LH("Calling SUMA_RGBv_PGL_AR4op2 ...");
8213 SUMA_RGBv_PGL_AR4op2(ColEVec, NodeEDef, glcolar,
8214 N_NodeEDef, isColored, Over->GlobalOpacity,
8215 LocalEOpacity, N_Node);
8216 }
8217 }
8218
8219 if (Full && !Glob && Locl) {
8220 SUMA_LH("Calling SUMA_RGBv_FnGL_AR4op...");
8221 /* This macro used to be called:
8222 SUMA_RGBmat_FullNoGlobLoc2_GLCOLAR4_opacity */
8223 SUMA_RGBv_FnGL_AR4op(ColEVec, glcolar, N_Node,
8224 LocalEOpacity, isColored);
8225 }
8226
8227 if (!Full && !Glob && Locl) {
8228 SUMA_LH("Calling SUMA_RGBv_PnGL_AR4op ...");
8229 /* This macro used to be called:
8230 SUMA_RGBmat_PartNoGlobLoc2_GLCOLAR4_opacity*/
8231 SUMA_RGBv_PnGL_AR4op( ColEVec, NodeEDef, glcolar, N_NodeEDef,
8232 isColored, LocalEOpacity, N_Node);
8233 }
8234
8235 if (Full && !Glob && !Locl) {
8236 SUMA_LH("Calling SUMA_RGBv_FnGnL_AR4op ...");
8237 /* This macro used to be called:
8238 SUMA_RGBmat_FullNoGlobNoLoc2_GLCOLAR4_opacity*/
8239 SUMA_RGBv_FnGnL_AR4op(ColEVec, glcolar, N_Node, isColored);
8240 }
8241
8242 if (!Full && !Glob && !Locl) {
8243 SUMA_LH("Calling SUMA_RGBv_PnGnL_AR4op ...");
8244 /* This macro used to be called:
8245 SUMA_RGBmat_PartNoGlobNoLoc2_GLCOLAR4_opacity */
8246 SUMA_RGBv_PnGnL_AR4op(ColEVec, NodeEDef, glcolar,
8247 N_NodeEDef, isColored, N_Node);
8248 }
8249
8250 if (Full && Glob && !Locl) {
8251 if (SUMAg_CF->ColMixMode == SUMA_ORIG_MIX_MODE) {
8252 SUMA_LH("Calling SUMA_RGBv_FGnL_AR4op...");
8253 /* This macro used to be called:
8254 SUMA_RGBmat_FullGlobNoLoc2_GLCOLAR4_opacity*/
8255 SUMA_RGBv_FGnL_AR4op(ColEVec, glcolar, N_Node,
8256 Over->GlobalOpacity, isColored);
8257 } else if (SUMAg_CF->ColMixMode == SUMA_4AML){
8258 SUMA_LH("Calling SUMA_RGBv_FGnL_AR4op2...");
8259 SUMA_RGBv_FGnL_AR4op2(ColEVec, glcolar, N_Node,
8260 Over->GlobalOpacity, isColored);
8261 }
8262
8263 }
8264
8265 if (!Full && Glob && !Locl) {
8266 if (SUMAg_CF->ColMixMode == SUMA_ORIG_MIX_MODE) {
8267 SUMA_LHv("Calling SUMA_RGBv_PGnL_AR4op...\n"
8268 " N_NodeEDef = %d, N_Node = %d\n",
8269 N_NodeEDef, N_Node);
8270 /* This macro used to be called:
8271 SUMA_RGBmat_PartGlobNoLoc2_GLCOLAR4_opacity*/
8272 SUMA_RGBv_PGnL_AR4op(ColEVec, NodeEDef, glcolar,
8273 N_NodeEDef, isColored, Over->GlobalOpacity, N_Node);
8274 } else if (SUMAg_CF->ColMixMode == SUMA_4AML){
8275 SUMA_LH("Calling SUMA_RGBv_PGnL_AR4op2...");
8276 SUMA_RGBv_PGnL_AR4op2(ColEVec, NodeEDef, glcolar,
8277 N_NodeEDef, isColored, Over->GlobalOpacity, N_Node);
8278 }
8279 }
8280
8281 if (ColEVec != Over->ColVec) SUMA_ifree(ColEVec);
8282 if (LocalEOpacity != Over->LocalOpacity) SUMA_ifree(LocalEOpacity);
8283 if (NodeEDef != COLP_NODEDEF(Over)) SUMA_ifree(NodeEDef);
8284 }
8285
8286 if (FILL && Fill) { /* nothing to see here */
8287 SUMA_LH("Some nodes received no colors from any of the overplanes, \n"
8288 "filling them with background color ...");
8289 SUMA_FillBlanks_GLCOLAR4(isColored, N_Node, SUMA_GRAY_NODE_COLOR,
8290 SUMA_GRAY_NODE_COLOR, SUMA_GRAY_NODE_COLOR, glcolar);
8291 SUMA_RETURN (YUP);
8292 }
8293
8294 SUMA_RETURN (YUP);
8295 }
8296
8297 /*!
8298 Function that shows the contents of overlay planes
8299 ans = SUMA_Show_ColorOverlayPlanes (SUMA_OVERLAYS **Overlays, int N_Overlays) ;
8300
8301 \param Overlays (SUMA_OVERLAYS **) vector of pointers to overlay structures
8302 \param N_Overlays (int) number of overlay structures
8303 \ret ans (SUMA_Boolean)
8304
8305
8306 */
SUMA_Show_ColorOverlayPlanes(SUMA_OVERLAYS ** Overlays,int N_Overlays,int detail)8307 SUMA_Boolean SUMA_Show_ColorOverlayPlanes (
8308 SUMA_OVERLAYS **Overlays, int N_Overlays, int detail)
8309 {
8310 static char FuncName[]={"SUMA_Show_ColorOverlayPlanes"};
8311 char *s;
8312
8313 SUMA_ENTRY;
8314
8315 // fprintf(stderr, "%s\n", FuncName);
8316
8317 s = SUMA_ColorOverlayPlane_Info (Overlays, N_Overlays, detail);
8318 if (s) {
8319 fprintf (SUMA_STDERR,"%s\n", s);
8320 SUMA_free(s);
8321 }
8322
8323 SUMA_RETURN (YUP);
8324 }
8325
8326 /*!
8327 \brief Shows the contents of the color overlay planes
8328 \sa SUMA_Show_ColorOverlayPlanes (for backward compat.)
8329 */
SUMA_ColorOverlayPlane_Info(SUMA_OVERLAYS ** Overlays,int N_Overlays,int detail)8330 char *SUMA_ColorOverlayPlane_Info (SUMA_OVERLAYS **Overlays,
8331 int N_Overlays, int detail)
8332 {
8333 static char FuncName[]={"SUMA_ColorOverlayPlane_Info"};
8334 char stmp[1000], *s = NULL, *s2 = NULL;
8335 int i, j, ShowN, icmap;
8336 SUMA_COLOR_MAP *ColMap=NULL;
8337 int N_Alloc = -1, *NodeDef=NULL, N_NodeDef = -1;
8338 DListElmt *el=NULL;
8339 NI_element *nel = NULL;
8340
8341 SUMA_STRING *SS = NULL;
8342
8343 // fprintf(stderr, "%s\n", FuncName);
8344
8345 SUMA_ENTRY;
8346
8347 SS = SUMA_StringAppend (NULL, NULL);
8348
8349 sprintf (stmp, "Info on %d color overlay planes:\n"
8350 "---------------------------------\n", N_Overlays);
8351 SS = SUMA_StringAppend (SS,stmp);
8352 if (!Overlays) SS = SUMA_StringAppend(SS,"NULL Overlays");
8353 for (i=0; Overlays && i < N_Overlays; ++i) {
8354 if (Overlays[i]) {
8355 sprintf (stmp,
8356 "\n---> Overlay plane %s:\n"
8357 "pointer %p, dset_link %p\n"
8358 "order %d, indexed %d, datum level %d\n"
8359 "DimFact %f, global opacity %f, isBackGrnd (isBackground) %d.\n"
8360 "ForceIntRange %f, %f.\n"
8361 "SymIrange = %d, LinkMode %d \n",
8362 Overlays[i]->Name,
8363 Overlays[i], Overlays[i]->dset_link,
8364 Overlays[i]->PlaneOrder, i, Overlays[i]->dtlvl,
8365 Overlays[i]->DimFact, Overlays[i]->GlobalOpacity,
8366 Overlays[i]->isBackGrnd,
8367 Overlays[i]->ForceIntRange[0], Overlays[i]->ForceIntRange[1],
8368 Overlays[i]->SymIrange, Overlays[i]->LinkMode);
8369 SS = SUMA_StringAppend (SS,stmp);
8370 SS = SUMA_StringAppend_va (SS, "N_links = %d\n", Overlays[i]->N_links);
8371 SS = SUMA_StringAppend_va (SS, "LinkedPtrType = %d\n",
8372 Overlays[i]->LinkedPtrType);
8373 SS = SUMA_StringAppend_va (SS, "owner_id = %s\n",
8374 Overlays[i]->owner_id);
8375 NodeDef = COLP_NODEDEF(Overlays[i]);
8376 N_NodeDef = COLP_N_NODEDEF(Overlays[i]);
8377 N_Alloc = COLP_N_ALLOC(Overlays[i]);
8378 sprintf (stmp,"ShowMode=%d, N_Alloc=%d, N_NodeDef=%d\n",
8379 (int)Overlays[i]->ShowMode, N_Alloc, N_NodeDef);
8380 SS = SUMA_StringAppend (SS,stmp);
8381 if (detail > 1) {
8382 ShowN = N_NodeDef;
8383 } else {
8384 if (N_NodeDef > 5) ShowN = 5;
8385 else ShowN = N_NodeDef;
8386 }
8387 SS = SUMA_StringAppend (SS,"\n");
8388 SS = SUMA_StringAppend_va (SS,
8389 "\tindex\tR\tG\tB\tLocOp\t\tDsetVal @RemixID %d\n",
8390 Overlays[i]->RemixOID);
8391
8392 // fprintf(stderr, "%s\n", FuncName);
8393
8394 if (Overlays[i]->ColVec &&
8395 Overlays[i]->LocalOpacity && Overlays[i]->V) {
8396 for (j=0; j < ShowN; ++j) {
8397 SS = SUMA_StringAppend_va(SS,
8398 "\t%d\t%.3f\t%.3f\t%.3f\t%.3f\t\t%.3f\n",
8399 NodeDef ? NodeDef[j]:-1, Overlays[i]->ColVec[3*j],
8400 Overlays[i]->ColVec[3*j+1], Overlays[i]->ColVec[3*j+2],
8401 Overlays[i]->LocalOpacity[j], Overlays[i]->V[j]);
8402 }
8403 SS = SUMA_StringAppend (SS,"\n");
8404 } else {
8405 SS = SUMA_StringAppend_va (SS,
8406 "No ColVec %p, or LocalOpacity %p, or V %p\n",
8407 Overlays[i]->ColVec,
8408 Overlays[i]->LocalOpacity, Overlays[i]->V);
8409 }
8410 if (!Overlays[i]->cmapname)
8411 SS = SUMA_StringAppend (SS,"cmapname = NULL\n");
8412 else SS = SUMA_StringAppend_va (SS,"cmapname = %s\n",
8413 Overlays[i]->cmapname);
8414 /* get the color map */
8415 if (!SUMAg_CF->scm) { /* try creating since it is no longer
8416 created at initialization */
8417 static int try_once=0;
8418 if (!try_once) {
8419 SUMAg_CF->scm = SUMA_Build_Color_maps(); ++ try_once;
8420 }
8421 }
8422 if (Overlays[i]->Contours) {
8423 SS = SUMA_StringAppend_va (SS, "%d contours, pointer %p\n",
8424 Overlays[i]->N_Contours,
8425 Overlays[i]->Contours);
8426 }else {
8427 SS = SUMA_StringAppend_va (SS, "%d contours, NULL pointer\n",
8428 Overlays[i]->N_Contours,
8429 Overlays[i]->Contours);
8430 }
8431 if (SUMAg_CF->scm) {
8432 icmap = SUMA_Find_ColorMap ( Overlays[i]->cmapname,
8433 SUMAg_CF->scm->CMv,
8434 SUMAg_CF->scm->N_maps, -2 );
8435 if (icmap < 0) { SS = SUMA_StringAppend (SS,"cmap not found.\n"); }
8436 else {
8437 ColMap = SUMAg_CF->scm->CMv[icmap];
8438 s2 = SUMA_ColorMapVec_Info(&ColMap, 1, detail);
8439 SS = SUMA_StringAppend (SS, s2); SUMA_free(s2); s2 = NULL;
8440 }
8441 s2 = SUMA_ScaleToMapOpt_Info (Overlays[i]->OptScl, 0);
8442 SS = SUMA_StringAppend (SS, s2); SUMA_free(s2); s2 = NULL;
8443 } else {
8444 SS = SUMA_StringAppend (SS,"\tNULL SUMA color maps.\n");
8445 }
8446
8447 if (Overlays[i]->ClustList) {
8448 s2 = SUMA_Show_SurfClust_list_Info(Overlays[i]->ClustList, 1,
8449 "Interactive Cluster Results", "No1DColHead");
8450 SS = SUMA_StringAppend(SS, s2);
8451 SUMA_free(s2); s2 = NULL;
8452 } else {
8453 SS = SUMA_StringAppend (SS, "NULL ClustList\n");
8454 }
8455
8456 } else {
8457 SS = SUMA_StringAppend (SS,"\tNULL overlay plane.\n");
8458 }
8459 }
8460 /* clean SS */
8461 SS = SUMA_StringAppend (SS, NULL);
8462 /* copy s pointer and free SS */
8463 s = SS->s;
8464 SUMA_free(SS);
8465
8466 SUMA_RETURN(s);
8467 }
8468
SUMA_ShowScaleToMapOpt(SUMA_SCALE_TO_MAP_OPT * OptScl,FILE * Out,int detail)8469 SUMA_Boolean SUMA_ShowScaleToMapOpt(SUMA_SCALE_TO_MAP_OPT *OptScl, FILE *Out,
8470 int detail)
8471 {
8472 static char FuncName[]={"SUMA_ShowScaleToMapOpt"};
8473 char *s=NULL;
8474
8475 SUMA_ENTRY;
8476
8477 // fprintf(stderr, "%s\n", FuncName);
8478
8479 if (!Out) Out = stdout;
8480
8481 s = SUMA_ScaleToMapOpt_Info(OptScl, detail);
8482
8483 fprintf (Out, "%s\n", s);
8484
8485 if (s) SUMA_free(s); s = NULL;
8486
8487 SUMA_RETURN(YUP);
8488 }
8489
SUMA_ScaleToMapOpt_Info(SUMA_SCALE_TO_MAP_OPT * OptScl,int detail)8490 char *SUMA_ScaleToMapOpt_Info (SUMA_SCALE_TO_MAP_OPT *OptScl, int detail)
8491 {
8492 static char FuncName[]={"SUMA_ScaleToMapOpt_Info"};
8493 char *s = NULL;
8494 SUMA_STRING *SS = NULL;
8495 SUMA_Boolean LocalHead = NOPE;
8496
8497 SUMA_ENTRY;
8498
8499 // fprintf(stderr, "%s\n", FuncName);
8500
8501 SS = SUMA_StringAppend (NULL, NULL);
8502
8503 if (LocalHead) SUMA_DUMP_TRACE("You rang?");
8504
8505 if (!OptScl) { SS = SUMA_StringAppend (SS, "NULL ScaleToMap options\n"); }
8506 else {
8507 SS = SUMA_StringAppend (SS, "ScaleToMap options:\n");
8508 SS = SUMA_StringAppend_va (SS, "ApplyMask = %d\n", OptScl->ApplyMask);
8509 SS = SUMA_StringAppend_va (SS, "MaskRange = %f %f\n",
8510 OptScl->MaskRange[0], OptScl->MaskRange[1]);
8511 SS = SUMA_StringAppend_va (SS, "MaskColor = %f %f %f\n",
8512 OptScl->MaskColor[0], OptScl->MaskColor[1], OptScl->MaskColor[2]);
8513 SS = SUMA_StringAppend_va (SS, "ApplyClip = %d\n", OptScl->ApplyClip);
8514 SS = SUMA_StringAppend_va (SS, "BrightFact = %f\n", OptScl->BrightFact);
8515 SS = SUMA_StringAppend_va (SS, "MaskZero = %d\n", OptScl->MaskZero);
8516 SS = SUMA_StringAppend_va (SS, "find = %d\n", OptScl->find);
8517 SS = SUMA_StringAppend_va (SS, "IntRange = %f %f\n",
8518 OptScl->IntRange[0], OptScl->IntRange[1]);
8519 SS = SUMA_StringAppend_va (SS, "AutoIntRange = %d\n",
8520 OptScl->AutoIntRange);
8521 SS = SUMA_StringAppend_va (SS, "tind = %d (use:%d). Mode %d\n",
8522 OptScl->tind, OptScl->UseThr,
8523 OptScl->ThrMode);
8524 SS = SUMA_StringAppend_va (SS, "ThreshRange = %f %f\n",
8525 OptScl->ThreshRange[0], OptScl->ThreshRange[1]);
8526 SS = SUMA_StringAppend_va (SS, "ThreshStats = %f %f\n",
8527 OptScl->ThreshStats[0], OptScl->ThreshStats[1]);
8528 SS = SUMA_StringAppend_va (SS, "bind = %d (use:%d)\n",
8529 OptScl->bind, OptScl->UseBrt);
8530 SS = SUMA_StringAppend_va (SS, "BrightRange = %f %f\n",
8531 OptScl->BrightRange[0], OptScl->BrightRange[1]);
8532 SS = SUMA_StringAppend_va (SS, "BrightMap = %f %f\n",
8533 OptScl->BrightMap[0], OptScl->BrightMap[1]);
8534 SS = SUMA_StringAppend_va (SS, "AutoBrtRange = %d\n",
8535 OptScl->AutoBrtRange);
8536 SS = SUMA_StringAppend_va (SS, "alaAFNI = %d\n", OptScl->alaAFNI);
8537 SS = SUMA_StringAppend_va (SS, "interpmode = %d (%s)\n",
8538 OptScl->interpmode,
8539 SUMA_CmapModeName(OptScl->interpmode));
8540 SS = SUMA_StringAppend_va (SS, "ColsContMode = %d \n",
8541 OptScl->ColsContMode);
8542 SS = SUMA_StringAppend_va (SS, "BiasMode = %d, Range=%f, %f \n",
8543 OptScl->DoBias, OptScl->CoordBiasRange[0],
8544 OptScl->CoordBiasRange[1]);
8545 if (OptScl->BiasVect)
8546 SS = SUMA_StringAppend_va (SS, "BiasVect is NOT NULL\n");
8547 else SS = SUMA_StringAppend_va (SS, "BiasVect is NULL\n");
8548
8549 SS = SUMA_StringAppend_va (SS,"Clusterize = %d, RecomputeCluseters = %d\n",
8550 OptScl->Clusterize, OptScl->RecomputeClust);
8551
8552 if (OptScl->ClustOpt) {
8553 SS = SUMA_StringAppend (SS, "Have ClustOpt, should show it ...\n");
8554 } else {
8555 SS = SUMA_StringAppend (SS, "NULL ClustOpt\n");
8556 }
8557
8558 }
8559 SUMA_SS2S(SS, s);
8560 SUMA_RETURN(s);
8561 }
8562
8563 /*!
8564 \brief Frees SUMA_OVERLAY_LIST_DATUM * used in the linked list
8565 */
SUMA_FreeOverlayListDatum(void * OLDv)8566 void SUMA_FreeOverlayListDatum (void *OLDv)
8567 {
8568 static char FuncName[]={"SUMA_FreeOverlayListDatum"};
8569 SUMA_Boolean LocalHead = NOPE;
8570
8571 SUMA_ENTRY;
8572
8573 // fprintf(stderr, "%s\n", FuncName);
8574
8575 if (OLDv) SUMA_free(OLDv);
8576
8577 SUMA_RETURNe;
8578 }
8579
8580 /*!
8581 \brief Create an ordered list of the colorplanes in Overlays
8582 the sorting of the list is done based on BackMod followed by the order
8583 The function makes sure colorplane orders span 0 to N_Overlays-1
8584
8585 \param SO (SUMA_SurfaceObject *)
8586 \param Opt (int) -1 for background plane list only
8587 1 for foreground plane list only
8588 0 for both background followed by foreground
8589 \return list (DList *) a doubly linked list of the ordered color planes.
8590 NULL is returned in case of error.
8591 to free this list when you no longer need it, do:
8592 dlist_destroy(list); SUMA_free(list);
8593
8594
8595
8596 */
SUMA_OverlaysToOrderedList(SUMA_ALL_DO * ado,int Opt)8597 DList * SUMA_OverlaysToOrderedList (SUMA_ALL_DO *ado, int Opt)
8598 {
8599 static char FuncName[]={"SUMA_OverlaysToOrderedList"};
8600 DList *listop = NULL;
8601 DListElmt *Elmop=NULL;
8602 SUMA_OVERLAY_LIST_DATUM *OvD = NULL, *oOvD = NULL;
8603 int i, Shift, ShftPlaneOrder, oShftPlaneOrder;
8604 SUMA_OVERLAYS *oPlane=NULL;
8605 SUMA_Boolean Found, LocalHead = NOPE;
8606
8607 SUMA_ENTRY;
8608
8609 // fprintf(stderr, "%s\n", FuncName);
8610
8611 listop = (DList *)SUMA_calloc(1,sizeof(DList));
8612
8613 dlist_init(listop, SUMA_FreeOverlayListDatum);
8614 SUMA_LH("Considering loop");
8615 for (i=0; i < SUMA_ADO_N_Overlays(ado); ++i) {
8616 SUMA_LH("In Loop");
8617 OvD = (SUMA_OVERLAY_LIST_DATUM *)
8618 SUMA_calloc(1,sizeof(SUMA_OVERLAY_LIST_DATUM));
8619 OvD->Overlay = SUMA_ADO_Overlay(ado,i);
8620 if (!OvD->Overlay) {
8621 SUMA_LH("NULL Overlay");
8622 }
8623 SUMA_LH("Here");
8624 if (OvD->Overlay->isBackGrnd && Opt == 1) continue;
8625 /* that was an unwanted background */
8626 if (!OvD->Overlay->isBackGrnd && Opt == -1) continue;
8627 /* that was an unwanted foreground */
8628 if (!listop->size) {
8629 SUMA_LH("Very first");
8630 dlist_ins_next(listop, dlist_tail(listop), (void*)OvD);
8631 }else { /* must sort first */
8632 Elmop = NULL;
8633 do {
8634 SUMA_LH("Searching");
8635 Found = NOPE;
8636 if (!Elmop) {
8637 Elmop = dlist_head(listop);
8638 } else {
8639 Elmop = dlist_next(Elmop);
8640 }
8641
8642 oOvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
8643
8644 /* transform PlaneOrder so that is
8645 reflects the Background modulation */
8646 Shift = SUMA_ADO_N_Overlays(ado);
8647
8648 if (OvD->Overlay->isBackGrnd)
8649 ShftPlaneOrder = OvD->Overlay->PlaneOrder - Shift;
8650 else ShftPlaneOrder = OvD->Overlay->PlaneOrder;
8651
8652 if (oOvD->Overlay->isBackGrnd)
8653 oShftPlaneOrder = oOvD->Overlay->PlaneOrder - Shift;
8654 else oShftPlaneOrder = oOvD->Overlay->PlaneOrder;
8655
8656 if (ShftPlaneOrder <= oShftPlaneOrder) {
8657 SUMA_LH ("Ins Prev");
8658 dlist_ins_prev(listop, Elmop, (void *)OvD);
8659 Found = YUP;
8660 } else if (Elmop == dlist_tail(listop)) {
8661 SUMA_LH ("Ins Next");
8662 /* reached the end, append */
8663 dlist_ins_next(listop, Elmop, (void *)OvD);
8664 Found = YUP;
8665 }
8666 } while (!Found);
8667 }
8668 }
8669
8670
8671 /* Now the list is sorted
8672 Go through the planes and make sure that the orders
8673 span 0 to N_Overlays -1 */
8674 SUMA_LH("Changing list order to plane order");
8675 SUMA_ListOrderToPlaneOrder (listop);
8676
8677 SUMA_RETURN(listop);
8678 }
8679
8680 /*!
8681 \brief sets the values of PlaneOrder to reflect the location of the color planes in list
8682 */
SUMA_ListOrderToPlaneOrder(DList * listop)8683 SUMA_Boolean SUMA_ListOrderToPlaneOrder (DList *listop)
8684 {
8685 static char FuncName[]={"SUMA_ListOrderToPlaneOrder"};
8686 SUMA_OVERLAY_LIST_DATUM *OvD = NULL;
8687 int i, fg_shift = 0;
8688 DListElmt *Elmop=NULL;
8689
8690 SUMA_ENTRY;
8691
8692 // fprintf(stderr, "%s\n", FuncName);
8693
8694 /* First pass, do background */
8695 if (listop->size) {
8696 Elmop = NULL;
8697 i = 0;
8698 do {
8699 if (!Elmop) Elmop = dlist_head(listop);
8700 else Elmop = Elmop->next;
8701 OvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
8702 if (OvD->Overlay->isBackGrnd) {
8703 OvD->Overlay->PlaneOrder = i;
8704 ++i;
8705 }
8706 } while (!dlist_is_tail(Elmop));
8707 }
8708
8709 /* second pass, do foreground */
8710 if (listop->size) {
8711 Elmop = NULL;
8712 i = 0;
8713 do {
8714 if (!Elmop) Elmop = dlist_head(listop);
8715 else Elmop = Elmop->next;
8716 OvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
8717 if (!OvD->Overlay->isBackGrnd) {
8718 OvD->Overlay->PlaneOrder = i;
8719 ++i;
8720 }
8721 } while (!dlist_is_tail(Elmop));
8722 }
8723
8724
8725 SUMA_RETURN(YUP);
8726 }
8727
8728 /*!
8729 \brief returns the largest background order in the list of verlay planes
8730 */
SUMA_GetLargestBackroundOrder(DList * listop)8731 int SUMA_GetLargestBackroundOrder (DList *listop)
8732 {
8733 static char FuncName[]={"SUMA_GetLargestBackroundOrder"};
8734 int Order, i=0;
8735 DListElmt *Elmop=NULL;
8736 SUMA_OVERLAY_LIST_DATUM *OvD = NULL;
8737 SUMA_Boolean LocalHead = NOPE;
8738
8739 SUMA_ENTRY;
8740
8741 // fprintf(stderr, "%s\n", FuncName);
8742
8743 Order = 0;
8744 Elmop = NULL;
8745 do {
8746 if (!Elmop) Elmop = dlist_head(listop);
8747 else Elmop = Elmop->next;
8748 OvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
8749 if (OvD->Overlay->isBackGrnd) {
8750 if (OvD->Overlay->PlaneOrder > Order) Order = OvD->Overlay->PlaneOrder;
8751 }
8752 ++i;
8753 } while (!dlist_is_tail(Elmop));
8754
8755 if (LocalHead) {
8756 fprintf (SUMA_STDERR,"%s: Highest background order found is %d\n", FuncName, Order);
8757 }
8758
8759 SUMA_RETURN(Order);
8760 }
8761
8762 /*!
8763 \brief returns the lowest foreground plane order in the list of overlay planes
8764 */
SUMA_GetSmallestForegroundOrder(DList * listop)8765 int SUMA_GetSmallestForegroundOrder (DList *listop)
8766 {
8767 static char FuncName[]={"SUMA_GetSmallestForegroundOrder"};
8768 int Order, i=0;
8769 DListElmt *Elmop=NULL;
8770 SUMA_OVERLAY_LIST_DATUM *OvD = NULL, *oOvD = NULL;
8771 SUMA_Boolean LocalHead = NOPE;
8772
8773 SUMA_ENTRY;
8774
8775 // fprintf(stderr, "%s\n", FuncName);
8776
8777 Order = listop->size -1 ;
8778 Elmop = NULL;
8779 do {
8780 if (!Elmop) Elmop = dlist_head(listop);
8781 else Elmop = Elmop->next;
8782 OvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
8783 if (!OvD->Overlay->isBackGrnd) {
8784 if (OvD->Overlay->PlaneOrder < Order) Order = OvD->Overlay->PlaneOrder;
8785 }
8786 ++i;
8787 } while (!dlist_is_tail(Elmop));
8788
8789 SUMA_LHv("Lowest foreground order found is %d\n", Order);
8790
8791 SUMA_RETURN(Order);
8792 }
8793
8794 /*!
8795 Is a color overlay plane registered in SO
8796 */
SUMA_isOverlayOfDO(SUMA_ALL_DO * ado,SUMA_OVERLAYS * Plane)8797 SUMA_Boolean SUMA_isOverlayOfDO (SUMA_ALL_DO *ado, SUMA_OVERLAYS *Plane)
8798 {
8799 static char FuncName[]={"SUMA_isOverlayOfDO"};
8800 int i;
8801 SUMA_Boolean LocalHead = NOPE;
8802
8803 SUMA_ENTRY;
8804
8805 // fprintf(stderr, "%s\n", FuncName);
8806
8807 for (i=0; i< SUMA_ADO_N_Overlays(ado); ++i) {
8808 if (SUMA_ADO_Overlay(ado,i) == Plane) {
8809 SUMA_LHv("Found plane at ind: %d\n", i);
8810 SUMA_RETURN(YUP);
8811 }
8812 }
8813
8814 SUMA_LH("Plane not found");
8815 SUMA_RETURN(NOPE);
8816 }
8817
SUMA_Overlay_OwnerADO(SUMA_OVERLAYS * Over)8818 SUMA_ALL_DO *SUMA_Overlay_OwnerADO(SUMA_OVERLAYS *Over)
8819 {
8820 static char FuncName[]={"SUMA_Overlay_OwnerADO"};
8821 SUMA_ALL_DO *ado=NULL;
8822 void *pp = NULL;
8823 SUMA_DO_Types tp;
8824
8825 // fprintf(stderr, "%s\n", FuncName);
8826
8827 SUMA_ENTRY;
8828
8829 if (!Over) SUMA_RETURN(NULL);
8830
8831 pp = SUMA_find_any_object(Over->owner_id, &tp);
8832 if (!pp) SUMA_RETURN(NULL);
8833 switch (tp) {
8834 case SO_type:
8835 case TRACT_type:
8836 case GRAPH_LINK_type:
8837 case GDSET_type:
8838 case CDOM_type:
8839 case VO_type:
8840 SUMA_RETURN((SUMA_ALL_DO *)pp);
8841 default:
8842 SUMA_S_Warn("Object type %d (%s) is not expected to have overlays.\n"
8843 "This comes up for CIFTI at the moment, need to think\n"
8844 "ramifications through...\n",
8845 tp , SUMA_ObjectTypeCode2ObjectTypeName(tp));
8846 SUMA_DUMP_TRACE("At Warning");
8847 break;
8848 }
8849 SUMA_RETURN(NULL);
8850 }
8851
SUMA_Print_PlaneOrder(SUMA_ALL_DO * ado,FILE * Out)8852 void SUMA_Print_PlaneOrder (SUMA_ALL_DO *ado, FILE *Out)
8853 {
8854 static char FuncName[]={"SUMA_Print_PlaneOrder"};
8855 char *s;
8856
8857 SUMA_ENTRY;
8858
8859 // fprintf(stderr, "%s\n", FuncName);
8860
8861 if (Out == NULL) Out = stdout;
8862
8863 s = SUMA_PlaneOrder_Info(ado);
8864
8865 if (s) {
8866 fprintf (Out, "%s", s);
8867 SUMA_free(s);
8868 }else {
8869 SUMA_S_Err("Failed in SUMA_PlaneOrder_Info.");
8870 }
8871
8872 SUMA_RETURNe;
8873 }
8874
8875 /*!
8876 \brief Shows the overlay plane order
8877 */
SUMA_PlaneOrder_Info(SUMA_ALL_DO * ado)8878 char * SUMA_PlaneOrder_Info (SUMA_ALL_DO *ado)
8879 {
8880 static char FuncName[]={"SUMA_PlaneOrder_Info"};
8881 char stmp[1000], *s = NULL;
8882 SUMA_STRING *SS = NULL;
8883 DList *list=NULL;
8884 DListElmt *Elm=NULL;
8885 SUMA_OVERLAY_LIST_DATUM *OvD=NULL;
8886
8887 // fprintf(stderr, "%s\n", FuncName);
8888
8889 SUMA_ENTRY;
8890
8891 /* get the background and foreground lists */
8892 SS = SUMA_StringAppend (NULL, NULL);
8893
8894 if (!(list = SUMA_OverlaysToOrderedList (ado, -1))) {
8895 SS = SUMA_StringAppend (SS,"NULL Background list\n");
8896 }else if (!list->size) {
8897 SS = SUMA_StringAppend (SS,"Empty Background list\n");
8898 } else {
8899 Elm=NULL;
8900 do {
8901 if (!Elm) Elm = dlist_head(list);
8902 else Elm = Elm->next;
8903 OvD = (SUMA_OVERLAY_LIST_DATUM *)Elm->data;
8904 sprintf (stmp,"BK: %s o%d (%s)\n",
8905 OvD->Overlay->Label, OvD->Overlay->PlaneOrder, OvD->Overlay->Name );
8906 SS = SUMA_StringAppend (SS,stmp);
8907 } while (Elm != dlist_tail(list));
8908 }
8909
8910 if (!(list = SUMA_OverlaysToOrderedList (ado, 1))) {
8911 SS = SUMA_StringAppend (SS,"NULL Foreground list\n");
8912 }else if (!list->size) {
8913 SS = SUMA_StringAppend (SS,"Empty Foreground list\n");
8914 } else {
8915 Elm=NULL;
8916 do {
8917 if (!Elm) Elm = dlist_head(list);
8918 else Elm = Elm->next;
8919 OvD = (SUMA_OVERLAY_LIST_DATUM *)Elm->data;
8920 sprintf (stmp,"FG: %s o%d (%s)\n",
8921 OvD->Overlay->Label, OvD->Overlay->PlaneOrder, OvD->Overlay->Name );
8922 SS = SUMA_StringAppend (SS,stmp);
8923 } while (Elm != dlist_tail(list));
8924 }
8925
8926 s = SS->s;
8927 SUMA_free(SS);
8928
8929 SUMA_RETURN (s);
8930 }
8931
8932 /*!
8933 \brief Moves a plane up one order
8934 */
SUMA_MovePlaneUp(SUMA_ALL_DO * ado,char * Name)8935 SUMA_Boolean SUMA_MovePlaneUp (SUMA_ALL_DO *ado, char *Name)
8936 {
8937 static char FuncName[]={"SUMA_MovePlaneUp"};
8938 SUMA_OVERLAYS *Overlay=NULL;
8939 SUMA_OVERLAY_LIST_DATUM *OvD=NULL;
8940 DList *list=NULL;
8941 DListElmt *Elm = NULL;
8942 int junk=0;
8943 SUMA_Boolean Found = NOPE, LocalHead = NOPE;
8944
8945 SUMA_ENTRY;
8946
8947 // fprintf(stderr, "%s\n", FuncName);
8948
8949 /* search for the plane by name */
8950 SUMA_LH("Searching for plane");
8951 if (!(Overlay = SUMA_Fetch_OverlayPointer(ado, Name, &junk))) {
8952 SUMA_S_Err("Plane does not exist in SO->Overlays. (identified by name)");
8953 SUMA_RETURN (NOPE);
8954 }
8955
8956 /* get the list of planes */
8957 SUMA_LH("Creating list");
8958 if (Overlay->isBackGrnd) list = SUMA_OverlaysToOrderedList (ado, -1);
8959 else list = SUMA_OverlaysToOrderedList (ado, 1);
8960 if (!list) {
8961 SUMA_S_Err("NULL list");
8962 SUMA_RETURN (NOPE);
8963 }
8964
8965 /* Now search through the list until you find Overlay */
8966 SUMA_LH("Searching for plane in list");
8967 Found = NOPE;
8968 Elm = NULL;
8969 do {
8970 if (!Elm) Elm = dlist_head(list);
8971 else Elm = Elm->next;
8972 OvD = (SUMA_OVERLAY_LIST_DATUM *) Elm->data;
8973 if (OvD->Overlay == Overlay) Found = YUP;
8974 }while (Elm != dlist_tail(list) && !Found);
8975
8976 if (!Found) {
8977 SUMA_S_Err("Strange, real strange.");
8978 SUMA_RETURN(NOPE);
8979 }
8980
8981 SUMA_LH("Found element, inserting at new position");
8982 if (Elm != dlist_tail(list)) { /* not on top, can move up */
8983 /* add Elm's data ahead of Elm->next */
8984 dlist_ins_next (list, Elm->next, Elm->data);
8985 /* remove Elm BUT NOT ITS DATA STRUCTURE!*/
8986 dlist_remove (list, Elm, (void *)(&OvD));
8987 } else {
8988 SUMA_LH("Reached the top");
8989 }
8990
8991 SUMA_LH("Compacting");
8992 /* now compact the order just for good measure */
8993 SUMA_ListOrderToPlaneOrder (list);
8994
8995
8996 SUMA_LH("Clean up");
8997 dlist_destroy(list); SUMA_free(list);
8998 SUMA_RETURN(YUP);
8999 }
9000
9001 /*!
9002 \brief Moves a plane up one order
9003 */
SUMA_MovePlaneDown(SUMA_ALL_DO * ado,char * Name)9004 SUMA_Boolean SUMA_MovePlaneDown (SUMA_ALL_DO *ado, char *Name)
9005 {
9006 static char FuncName[]={"SUMA_MovePlaneDown"};
9007 SUMA_OVERLAYS *Overlay=NULL;
9008 SUMA_OVERLAY_LIST_DATUM *OvD=NULL;
9009 DList *list=NULL;
9010 DListElmt *Elm = NULL;
9011 int junk=0;
9012 SUMA_Boolean Found = NOPE, LocalHead = NOPE;
9013
9014 SUMA_ENTRY;
9015
9016 // fprintf(stderr, "%s\n", FuncName);
9017
9018 /* search for the plane by name */
9019 SUMA_LH("Searching for plane");
9020 if (!(Overlay = SUMA_Fetch_OverlayPointer(ado,
9021 Name, &junk))) {
9022 SUMA_S_Err("Plane does not exist in Object's Overlays."
9023 " (identified by name)");
9024 SUMA_RETURN (NOPE);
9025 }
9026
9027 /* get the list of planes */
9028 SUMA_LH("Creating list");
9029 if (Overlay->isBackGrnd) list = SUMA_OverlaysToOrderedList (ado, -1);
9030 else list = SUMA_OverlaysToOrderedList (ado, 1);
9031 if (!list) {
9032 SUMA_S_Err("NULL list");
9033 SUMA_RETURN (NOPE);
9034 }
9035
9036 /* Now search through the list until you find Overlay */
9037 SUMA_LH("Searching for plane in list");
9038 Found = NOPE;
9039 Elm = NULL;
9040 do {
9041 if (!Elm) Elm = dlist_head(list);
9042 else Elm = Elm->next;
9043 OvD = (SUMA_OVERLAY_LIST_DATUM *) Elm->data;
9044 if (OvD->Overlay == Overlay) Found = YUP;
9045 }while (Elm != dlist_tail(list) && !Found);
9046
9047 if (!Found) {
9048 SUMA_S_Err("Strange, real strange.");
9049 SUMA_RETURN(NOPE);
9050 }
9051
9052 SUMA_LH("Found element, inserting at new position");
9053 if (Elm != dlist_head(list)) { /* not on bottom, can move down */
9054 /* add Elm's data before of Elm->prev */
9055 dlist_ins_prev (list, Elm->prev, Elm->data);
9056 /* remove Elm BUT NOT ITS DATA STRUCTURE!*/
9057 dlist_remove (list, Elm, (void *)(&OvD));
9058 } else {
9059 SUMA_LH("Reached the bottom");
9060 }
9061
9062 SUMA_LH("Compacting");
9063 /* now compact the order just for good measure */
9064 SUMA_ListOrderToPlaneOrder (list);
9065
9066
9067 SUMA_LH("Clean up");
9068 dlist_destroy(list); SUMA_free(list);
9069 SUMA_RETURN(YUP);
9070 }
9071
9072
SUMA_NewPlaneSearch(SUMA_ALL_DO * ado,SUMA_OVERLAYS * Overlay)9073 SUMA_OVERLAYS * SUMA_NewPlaneSearch(SUMA_ALL_DO *ado,
9074 SUMA_OVERLAYS *Overlay)
9075 {
9076 static char FuncName[]={"SUMA_NewPlaneSearch"};
9077 int junk = 0;
9078
9079 SUMA_ENTRY;
9080
9081 // fprintf(stderr, "%s\n", FuncName);
9082
9083 if (!Overlay || !ado) {
9084 SUMA_S_Err("You sent me NULLS!");
9085 SUMA_RETURN (NULL);
9086 }
9087
9088 if (SUMA_isOverlayOfDO(ado, Overlay)) {
9089 SUMA_RETURN(Overlay);
9090 }
9091
9092 /* also try looking for plane by name */
9093 SUMA_RETURN(SUMA_Fetch_OverlayPointer( ado, Overlay->Name, &junk));
9094 }
9095
9096 /*!
9097 \brief Adds a new plane to SO->Overlays.
9098 If plane exists, you get an error message
9099 Adds plane to related surfaces if dov is not NULL
9100
9101 DuplicateFlag == 0 return with error if plane already exists
9102 1 return with warning if plane already exists
9103 */
SUMA_AddNewPlane(SUMA_ALL_DO * ado,SUMA_OVERLAYS * Overlay,SUMA_DO * dov,int N_dov,int DuplicateFlag)9104 SUMA_Boolean SUMA_AddNewPlane (SUMA_ALL_DO *ado, SUMA_OVERLAYS *Overlay,
9105 SUMA_DO *dov, int N_dov, int DuplicateFlag)
9106 {
9107 static char FuncName[]={"SUMA_AddNewPlane"};
9108 DList *ForeList=NULL, *BackList = NULL;
9109 SUMA_OVERLAY_LIST_DATUM *OvD=NULL;
9110 int junk=0, i, OverInd, kin = 1;
9111 SUMA_SurfaceObject *SO2 = NULL;
9112 SUMA_Boolean LocalHead = NOPE;
9113
9114 SUMA_ENTRY_LH;
9115
9116 // fprintf(stderr, "%s\n", FuncName);
9117
9118 if (!Overlay) {
9119 SUMA_S_Err("You sent me NULLS!");
9120 SUMA_RETURN (NOPE);
9121 }
9122
9123 if (SUMA_NewPlaneSearch(ado, Overlay)) {
9124 if (DuplicateFlag == 0) {
9125 SUMA_S_Errv(
9126 "Plane exists in Overlays either \n"
9127 "by pointer %p or by name (%s).\n"
9128 "Both of these must be unique because DuplicateFlag=%d\n",
9129 Overlay, Overlay->Name, DuplicateFlag);
9130 SUMA_DUMP_TRACE("Allora");
9131 SUMA_RETURN (NOPE);
9132 } else {
9133 SUMA_S_Note("Plane exists in Overlays. Preserving old one.");
9134 SUMA_RETURN (YUP);
9135 }
9136 }
9137
9138 /* make sure that overlay plane does not have bias in it */
9139 if (Overlay->OptScl) {
9140 if (Overlay->OptScl->BiasVect) {
9141 SUMA_SL_Err("New overlay plane cannot have coordinate bias.\n"
9142 "Not yet at least.\n");
9143 /* If you want to support this feature,
9144 you'll have to call SUMA_AddVisX_CoordBias
9145 on any surface the plane gets assigned to.
9146 That means SO and SO2 below.
9147 Search for SUMA_AddVisX_CoordBias in
9148 SUMA_SwitchState in file SUMA_Engine.c
9149 for the example */
9150 SUMA_RETURN(NOPE);
9151 }
9152 }
9153
9154 /* make sure there's enough room for the new plane */
9155 if (SUMA_ADO_N_Overlays(ado)+1 >= SUMA_MAX_OVERLAYS) {
9156 SUMA_SL_Crit("Too many color overlays.");
9157 SUMA_RETURN (NOPE);
9158 }
9159
9160 /* Now add the plane where it belongs */
9161 if (!(ForeList = SUMA_OverlaysToOrderedList (ado, 1))) {
9162 SUMA_S_Err("NULL ForeList");
9163 SUMA_RETURN (NOPE);
9164 }
9165
9166 if (!(BackList = SUMA_OverlaysToOrderedList (ado, -1))) {
9167 SUMA_S_Err("NULL BackList");
9168 SUMA_RETURN (NOPE);
9169 }
9170
9171 SUMA_LH("Adding to list...");
9172 OvD = (SUMA_OVERLAY_LIST_DATUM *)
9173 SUMA_calloc(1,sizeof(SUMA_OVERLAY_LIST_DATUM));
9174 OvD->Overlay = Overlay;
9175
9176 if (Overlay->isBackGrnd) {
9177 SUMA_LH("Back dude...");
9178 dlist_ins_next(BackList, dlist_tail(BackList), (void *)OvD);
9179 Overlay->PlaneOrder = BackList->size - 1;
9180 } else {
9181 SUMA_LH("Front dude...");
9182 dlist_ins_next(ForeList, dlist_tail(ForeList), (void *)OvD);
9183 Overlay->PlaneOrder = ForeList->size - 1;
9184 }
9185
9186 SUMA_LH("Out dude...");
9187
9188 switch (ado->do_type) {
9189 case SO_type: {
9190
9191 SUMA_SurfaceObject *SO = (SUMA_SurfaceObject *)ado;
9192 /* place the Overlay plane and its inode in SO */
9193 SO->Overlays[SO->N_Overlays] = Overlay;
9194 /* Now increment the number of overlays to be in SO */
9195 ++SO->N_Overlays;
9196 /* Now register plane with surfaces deserving it*/
9197 if (AFNI_yesenv("SUMA_ShareGrandChildrenOverlays")) {
9198 SUMA_S_Warn("Option needs polishing before\n"
9199 "public usage. Nothing is done\n"
9200 "to reflect changes to overlay coloring\n"
9201 "from one group of LocalDom. to another\n"
9202 "that share the same DomainGrandParentID\n");
9203 kin = 2;
9204 } else kin = 1;
9205 if (dov) {
9206 SUMA_LH("Registering plane with surfaces deserving it");
9207 /* Now that you have the color overlay plane set,
9208 go about all the surfaces, searching for ones related to SO
9209 and make sure they have this colorplane,
9210 otherwise, create a link to it. */
9211 for (i=0; i < N_dov; ++i) {
9212 if (SUMA_isSO(dov[i])) {
9213 SO2 = (SUMA_SurfaceObject *)dov[i].OP;
9214 if (SUMA_isRelated_SO(SO, SO2, kin) && SO != SO2) {
9215 /* only 1st order kinship allowed */
9216 /* surfaces related and not identical, check colorplanes */
9217 if (!SUMA_Fetch_OverlayPointer ( (SUMA_ALL_DO *)SO2,
9218 Overlay->Name, &OverInd)) {
9219 /* color plane not found, link to that of SO */
9220 SO2->Overlays[SO2->N_Overlays] =
9221 (SUMA_OVERLAYS*)SUMA_LinkToPointer(
9222 (void*)SO->Overlays[SO->N_Overlays-1]);
9223 /*increment the number of overlay planes */
9224 ++SO2->N_Overlays;
9225 } else {
9226 /* colorplane found OK */
9227 }
9228 }
9229 }
9230 }
9231 }
9232 break; }
9233 case TRACT_type: {
9234 if (!(SUMA_ADO_Append_Overlay(ado, &Overlay))) {
9235 SUMA_S_Err("Failed to append Overlay");
9236 break;
9237 }
9238 break; }
9239 case CDOM_type: {
9240 if (!(SUMA_ADO_Append_Overlay(ado, &Overlay))) {
9241 SUMA_S_Err("Failed to append Overlay");
9242 break;
9243 }
9244 break; }
9245 case GDSET_type: {
9246 SUMA_S_Warn("Should not have multiple planes for graph dsets");
9247 break; }
9248 case VO_type: {
9249 if (!(SUMA_ADO_Append_Overlay(ado, &Overlay))) {
9250 SUMA_S_Err("Failed to append Overlay");
9251 break;
9252 }
9253 break; }
9254 default:
9255 SUMA_S_Errv("Not ready for type %s\n",
9256 SUMA_ObjectTypeCode2ObjectTypeName(ado->do_type));
9257 break;
9258 }
9259
9260 SUMA_LH("Destruction...");
9261 dlist_destroy(ForeList); SUMA_free(ForeList);
9262 dlist_destroy(BackList); SUMA_free(BackList);
9263
9264
9265 SUMA_RETURN (YUP);
9266 }
9267
9268 /*!
9269 \brief ans = SUMA_MixColors (sv);
9270 this functions mixes the colors for surface objects that ask for it
9271 \param sv (SUMA_SurfaceViewer *)
9272 \return YUP/NOPE
9273 */
SUMA_MixColors(SUMA_SurfaceViewer * sv)9274 SUMA_Boolean SUMA_MixColors (SUMA_SurfaceViewer *sv)
9275 {
9276 static char FuncName[]={"SUMA_MixColors"};
9277 int i, dov_id, isv, kk;
9278 void *pp=NULL;
9279 SUMA_DO_Types tp;
9280 SUMA_DSET *dset=NULL;
9281 SUMA_SurfaceObject *SO = NULL;
9282 SUMA_Boolean LocalHead = NOPE;
9283
9284 SUMA_ENTRY;
9285
9286 // fprintf(stderr, "%s\n", FuncName);
9287
9288 #if 0
9289 for (i=0; i<sv->N_ColList; ++i){
9290 fprintf(stderr, "sv->ColList[%d]->idcode_str = %s\n", i, sv->ColList[i]->idcode_str);
9291 fprintf(stderr, "(SUMA_SurfaceObject *)(SUMAg_DOv[%d].OP)->idcode_str = %s\n", i+1, ((SUMA_SurfaceObject *)(SUMAg_DOv[i+1].OP))->idcode_str);
9292 }
9293 #endif
9294 isv = SUMA_WhichSVg(sv);
9295
9296 if (LocalHead) SUMA_DUMP_TRACE("Mixing of the colors, sv %d, N_ColList = %d",
9297 isv, sv->N_ColList);
9298
9299 // fprintf(stderr, "sv->N_ColList = %d\n", sv->N_ColList);
9300 for (i=0; i<sv->N_ColList; ++i){
9301
9302 if (!(pp = SUMA_find_any_object(sv->ColList[i]->idcode_str, &tp))) {
9303 SUMA_S_Err("Zut alors, id %s not found!", sv->ColList[i]->idcode_str);
9304 SUMA_RETURN(NOPE);
9305 }
9306 if (sv->ColList[i]->Remix) {
9307 ++sv->ColList[i]->RemixID;
9308 switch (tp) {
9309 case SO_type:
9310 if (LocalHead)
9311 fprintf( SUMA_STDERR,
9312 "%s: Mixing colors (%s)...\n",
9313 FuncName, sv->ColList[i]->idcode_str);
9314 SO = (SUMA_SurfaceObject *)pp;
9315
9316 if (!SUMA_Overlays_2_GLCOLAR4((SUMA_ALL_DO *)SO, sv,
9317 SUMA_GetColorListPtr(sv->ColList[i]))) {
9318 SUMA_S_Err("Failed in SUMA_Overlays_2_GLCOLAR4.");
9319 SUMA_RETURN(NOPE);
9320 }
9321 sv->ColList[i]->Remix = NOPE;
9322 break;
9323 case GDSET_type:
9324 dset = (SUMA_DSET *)pp;
9325 SUMA_LHv("Mixing Graph Dset Colors (%s), Dset %s...\n",
9326 sv->ColList[i]->idcode_str, SDSET_LABEL(dset));
9327 if (!SUMA_Overlays_2_GLCOLAR4((SUMA_ALL_DO *)dset, sv,
9328 SUMA_GetColorListPtr(sv->ColList[i]))) {
9329 SUMA_S_Err("Failed in SUMA_Overlays_2_GLCOLAR4.");
9330 SUMA_RETURN(NOPE);
9331 }
9332 sv->ColList[i]->Remix = NOPE;
9333 break;
9334 case CDOM_type: {
9335 SUMA_CIFTI_DO *CO = (SUMA_CIFTI_DO *)pp;
9336 SUMA_LH("Now done separately for elementary datasets "
9337 "and domains. Nothing to do here.");
9338 break;
9339 #if 0
9340 /* delete soon */
9341 SUMA_LHv("Mixing CIFTI Object Colors (%s), CO %s, sv %d ...\n",
9342 sv->ColList[i]->idcode_str, ADO_LABEL((SUMA_ALL_DO *)CO), isv);
9343 if (!SUMA_Overlays_2_GLCOLAR4((SUMA_ALL_DO *)CO, sv,
9344 SUMA_GetColorListPtr(sv->ColList[i]))) {
9345 SUMA_S_Err("Failed in SUMA_Overlays_2_GLCOLAR4.");
9346 SUMA_RETURN(NOPE);
9347 }
9348 sv->ColList[i]->Remix = NOPE;
9349 SUMA_S_Warn("This block below is only needed if one of the"
9350 "domains is a volume");
9351 for(kk=0; kk<SUMA_MAX_SURF_VIEWERS; ++kk) {
9352 if (kk != isv) {
9353 sv->ColList[i]->per_sv_extra[kk] |= PSV_BIND_VOL;
9354 }
9355 }
9356 break;
9357 #endif
9358 }
9359 case VO_type: {
9360 SUMA_VolumeObject *VO = (SUMA_VolumeObject *)pp;
9361 SUMA_LHv("Mixing Volume Object Colors (%s), Dset %s, sv %d ...\n",
9362 sv->ColList[i]->idcode_str, ADO_LABEL((SUMA_ALL_DO *)VO), isv);
9363 if (!SUMA_Overlays_2_GLCOLAR4((SUMA_ALL_DO *)VO, sv,
9364 SUMA_GetColorListPtr(sv->ColList[i]))) {
9365 SUMA_S_Err("Failed in SUMA_Overlays_2_GLCOLAR4.");
9366 SUMA_RETURN(NOPE);
9367 }
9368 sv->ColList[i]->Remix = NOPE;
9369 for(kk=0; kk<SUMA_MAX_SURF_VIEWERS; ++kk) {
9370 if (kk != isv) {
9371 sv->ColList[i]->per_sv_extra[kk] |= PSV_BIND_VOL;
9372 }
9373 }
9374 break; }
9375 case TRACT_type: {
9376 SUMA_TractDO *tdo=(SUMA_TractDO *)pp;
9377 SUMA_LHv("Mixing Tract Colors (%s), Tract %s, ID %s...\n",
9378 sv->ColList[i]->idcode_str,
9379 ADO_LABEL((SUMA_ALL_DO *)pp), ADO_ID((SUMA_ALL_DO *)pp));
9380 if (!SUMA_Overlays_2_GLCOLAR4((SUMA_ALL_DO *)pp, sv,
9381 SUMA_GetColorListPtr(sv->ColList[i]))) {
9382 SUMA_S_Err("Failed in SUMA_Overlays_2_GLCOLAR4.");
9383 SUMA_RETURN(NOPE);
9384 }
9385 sv->ColList[i]->Remix = NOPE;
9386 break; }
9387 case MASK_type: {
9388 SUMA_MaskDO *mdo = (SUMA_MaskDO*)pp;
9389 SUMA_LHv("Mixing Mask Colors (%s), Mask %s, ID %s...\n",
9390 sv->ColList[i]->idcode_str,
9391 ADO_LABEL((SUMA_ALL_DO *)pp), ADO_ID((SUMA_ALL_DO *)pp));
9392 if (!SUMA_Overlays_2_GLCOLAR4((SUMA_ALL_DO *)pp, sv,
9393 SUMA_GetColorListPtr(sv->ColList[i]))) {
9394 SUMA_S_Err("Failed in SUMA_Overlays_2_GLCOLAR4.");
9395 SUMA_RETURN(NOPE);
9396 }
9397 sv->ColList[i]->Remix = NOPE;
9398 break; }
9399 default:
9400 SUMA_S_Errv("Type %d (%s) is not welcome here\n",
9401 tp, SUMA_ObjectTypeCode2ObjectTypeName(tp));
9402 SUMA_RETURN(NOPE);
9403 }
9404 }
9405 SUMA_LH("ColList[%d](%p)->per_sv_extra[%d]=%d",
9406 i, sv->ColList[i], isv, sv->ColList[i]->per_sv_extra[isv]);
9407 {/* Check on extras */
9408 switch (tp) {
9409 case VO_type: {
9410 SUMA_VolumeObject *vo = (SUMA_VolumeObject *)pp;
9411 if (sv->ColList[i]->per_sv_extra[isv] & PSV_BIND_VOL) {
9412 SUMA_LH("Loading texture for viewer %d", isv);
9413 if (!SUMA_VE_LoadTexture(vo->VE, 0)){
9414 SUMA_S_Err("Failed to GL load texture for sv %d", isv);
9415 SUMA_RETURN(NOPE);
9416 }
9417 sv->ColList[i]->per_sv_extra[isv] &= ~PSV_BIND_VOL;
9418 }
9419 break; }
9420 default:
9421 break;
9422 }
9423 }
9424 }
9425
9426 SUMA_RETURN (YUP);
9427
9428 }
9429
9430
9431
9432
SUMA_iRGB_to_OverlayPointer(SUMA_ALL_DO * ado,char * Name,SUMA_OVERLAY_PLANE_DATA * sopd,int * PlaneInd,SUMA_DO * dov,int N_dov,DList * DsetList)9433 SUMA_Boolean SUMA_iRGB_to_OverlayPointer (SUMA_ALL_DO *ado,
9434 char *Name, SUMA_OVERLAY_PLANE_DATA *sopd,
9435 int *PlaneInd, SUMA_DO *dov, int N_dov,
9436 DList *DsetList)
9437 {
9438 static char FuncName[]={"SUMA_iRGB_to_OverlayPointer"};
9439 SUMA_Boolean LocalHead = NOPE;
9440
9441 SUMA_ENTRY;
9442
9443 // fprintf(stderr, "%s\n", FuncName);
9444
9445 if (!ado) SUMA_RETURN(NOPE);
9446
9447 switch (ado->do_type) {
9448 case SO_type:
9449 SUMA_RETURN(SUMA_iRGB_to_SO_OverlayPointer((SUMA_SurfaceObject *)ado,
9450 Name, sopd, PlaneInd, dov, N_dov, DsetList));
9451 case TRACT_type:
9452 SUMA_RETURN(SUMA_iRGB_to_TDO_OverlayPointer((SUMA_TractDO *)ado,
9453 Name, sopd, PlaneInd, dov, N_dov, DsetList));
9454 default:
9455 SUMA_S_Err("Not ready to deal with type %s", ADO_TNAME(ado));
9456 SUMA_RETURN(NOPE);
9457 }
9458 SUMA_RETURN(NOPE);
9459 }
9460
9461 /*!
9462 \brief A function that looks up an overlay plane by its name for surfaces
9463 If the plane is found its index is returned, otherwise
9464 a new one is created. The function also sets up pointers to
9465 that plane for all related surfaces in dov and places node colors
9466 in that plane.
9467
9468 \param SO (SUMA_SurfaceObject *) Surface Object
9469 \param Name (char *) Name of color plane
9470 \param sopd (SUMA_OVERLAY_PLANE_DATA *) Data to put in overlay plane
9471 \param PlaneInd (int *) index of created or found color plane
9472 (that's set by the function )
9473 \param dov (SUMA_DO *) vector of displayable objects
9474 \param N_dov (int ) number of displayable objects
9475
9476 */
SUMA_iRGB_to_SO_OverlayPointer(SUMA_SurfaceObject * SO,char * Name,SUMA_OVERLAY_PLANE_DATA * sopd,int * PlaneInd,SUMA_DO * dov,int N_dov,DList * DsetList)9477 SUMA_Boolean SUMA_iRGB_to_SO_OverlayPointer (SUMA_SurfaceObject *SO,
9478 char *Name, SUMA_OVERLAY_PLANE_DATA *sopd,
9479 int *PlaneInd, SUMA_DO *dov, int N_dov,
9480 DList *DsetList)
9481 {
9482 static char FuncName[]={"SUMA_iRGB_to_SO_OverlayPointer"}, stmp[500];
9483 char *DsetName_tmp=NULL;
9484 int i, OverInd = -1, i_max, wrn_cnt = 0, i3 = 0;
9485 SUMA_OVERLAYS *Overlay=NULL;
9486 SUMA_DSET *dset = NULL;
9487 SUMA_Boolean LocalHead = NOPE;
9488
9489 SUMA_ENTRY;
9490
9491 // fprintf(stderr, "%s\n", FuncName);
9492
9493 SUMA_LH("Fetching Overlay Pointer");
9494 /* if plane exists use it, else create a new one on the mappable surface */
9495 if (!SUMA_Fetch_OverlayPointer ((SUMA_ALL_DO *)SO, Name, &OverInd)) {
9496 SUMA_LH("pointer not found");
9497 /* overlay plane not found, create a new one on the mappable surface*/
9498 if (!SUMA_isLocalDomainParent(SO)) {
9499 if (sopd->Source == SES_Afni) {
9500 /* unexpected, surfaces coming from AFNI with a map
9501 should be a local domain parent */
9502 fprintf( SUMA_STDERR,
9503 "Error %s: Surface %s (ID: %s) received from AFNI is "
9504 "not a local domain parent.\n",
9505 FuncName, SO->Label, SO->idcode_str);
9506 SUMA_RETURN(NOPE);
9507 } else {
9508 SUMA_SL_Warn ( "Placing colors on surface \n"
9509 "not a local domain parent.\nCase not tested.");
9510 }
9511 }
9512
9513 DsetName_tmp = SUMA_append_replace_string(Name,
9514 SO->LocalDomainParentID,TMP_NAME_SEP, 0);
9515 switch (sopd->dtlvl) {
9516 case SUMA_ELEM_DAT:
9517 dset = SUMA_CreateDsetPointer (DsetName_tmp,
9518 SUMA_NODE_RGB,
9519 NULL,
9520 SO->idcode_str,
9521 SO->N_Node); /* first create a dataset
9522 that will go with that colorplane */
9523 break;
9524 default:
9525 SUMA_S_Err("Not ready for datum level %d for surfaces",
9526 sopd->dtlvl);
9527 break;
9528 }
9529 SUMA_sdset_set_datum_level(dset,sopd->dtlvl);
9530
9531 SUMA_free(DsetName_tmp); DsetName_tmp = NULL;
9532 /* insert that element into DaList */
9533 if (!SUMA_InsertDsetPointer(&dset, DsetList, 0)) {
9534 SUMA_SL_Err("Failed to insert dset into list");
9535 SUMA_RETURN(NOPE);
9536 }
9537 /* We'll be using NodeDef here so begin by allocating space
9538 for the various entries */
9539 SUMA_AddDsetNelCol (dset, "node index", SUMA_NODE_INDEX, NULL, NULL, 1);
9540 SUMA_AddDsetNelCol (dset, "red", SUMA_NODE_R, NULL, NULL, 1);
9541 SUMA_AddDsetNelCol (dset, "green", SUMA_NODE_G, NULL, NULL, 1);
9542 SUMA_AddDsetNelCol (dset, "blue", SUMA_NODE_B, NULL, NULL, 1);
9543
9544 Overlay = SUMA_CreateOverlayPointer (Name, dset, SO->idcode_str, NULL);
9545 if (!Overlay) {
9546 SUMA_SL_Err("Failed in SUMA_CreateOverlayPointer.\n");
9547 SUMA_RETURN(NOPE);
9548 }
9549
9550 /* set up some defaults for the overlap plane */
9551 if (sopd->Show) Overlay->ShowMode = SW_SurfCont_DsetViewCol;
9552 else Overlay->ShowMode = -SW_SurfCont_DsetViewCol;
9553 Overlay->GlobalOpacity = sopd->GlobalOpacity;
9554 Overlay->isBackGrnd = sopd->isBackGrnd;
9555 Overlay->OptScl->BrightFact = sopd->DimFact;
9556 OverInd = SO->N_Overlays;
9557
9558 /* Add this plane to SO->Overlays */
9559 if (!SUMA_AddNewPlane ((SUMA_ALL_DO *)SO, Overlay, dov, N_dov, 0)) {
9560 SUMA_SL_Crit("Failed in SUMA_AddNewPlane");
9561 SUMA_FreeOverlayPointer(Overlay);
9562 SUMA_RETURN (NOPE);
9563 }
9564
9565
9566 }else {
9567 SUMA_LH("Pointer found");
9568 }
9569
9570 if (LocalHead)
9571 fprintf (SUMA_STDERR,
9572 "%s: OverInd = %d, Loading colors to Overlay Plane...\n",
9573 FuncName, OverInd);
9574 if (sopd->N > SO->N_Node) {
9575 SUMA_SLP_Warn("Number of nodes in colorplane (%d)\n"
9576 "is larger than number of nodes in surface (%d)\n"
9577 "Proceed if you know what you're doing.\n"
9578 "Data from high node indices will be ignored.",
9579 sopd->N, SO->N_Node);
9580 i_max = SO->N_Node;
9581 } else {
9582 i_max = sopd->N;
9583 }
9584
9585 SO->Overlays[OverInd]->DimFact = sopd->DimFact;
9586 SO->Overlays[OverInd]->cmapname = SUMA_copy_string("explicit");
9587 /* explict color definition in data */
9588 SO->Overlays[OverInd]->FullList = 0; /*!< This type of planes is not
9589 usually a full list because it has the nodes defined*/
9590
9591 /* Now put the colors in the overlay plane */
9592 if (LocalHead) fprintf (SUMA_STDERR,
9593 "%s: %d node colors are to be inserted.\n",
9594 FuncName, i_max);
9595
9596 COLP_N_NODEDEF(SO->Overlays[OverInd]) = i_max; /* set the number of nodes
9597 filled IN THE OVERLAY PLANE*/
9598 SDSET_VECFILLED(SO->Overlays[OverInd]->dset_link) = i_max; /* set the
9599 number of nodes filled IN THE DSET, For this
9600 type of dsets, the N_NodeDef is the same for
9601 both OVERLAY and for DSET*/
9602 if (COLP_N_NODEDEF(SO->Overlays[OverInd])) {
9603 int *iv, N_i,*Nv;
9604 float *Rv, *Gv, *Bv;
9605 SUMA_DSET *dset;
9606 dset = SO->Overlays[OverInd]->dset_link;
9607 /* find the columns you need to fill.
9608 You can't use SUMA_FillNelCol directly because
9609 columns (vectors) are of different types */
9610 if (!(Nv = SUMA_GetNodeDef(dset))) {
9611 SUMA_SL_Err("Failed to find node indices."); SUMA_RETURN(NOPE); }
9612 if (LocalHead) SUMA_ShowDset(dset, 0, NULL);
9613 iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_R, &N_i);
9614 if (N_i != 1) {
9615 SUMA_SL_Err("Failed to find one column.");
9616 SUMA_free(iv); SUMA_RETURN(NOPE); }
9617 Rv = (float *)dset->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
9618 iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_G, &N_i);
9619 if (N_i != 1) {
9620 SUMA_SL_Err("Failed to find one column.");
9621 SUMA_free(iv); SUMA_RETURN(NOPE); }
9622 Gv = (float *)dset->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
9623 iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_B, &N_i);
9624 if (N_i != 1) {
9625 SUMA_SL_Err("Failed to find one column.");
9626 SUMA_free(iv); SUMA_RETURN(NOPE); }
9627 Bv = (float *)dset->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
9628 /* Now store these colors into the dataset */
9629 switch (sopd->Type) {
9630 case SOPT_ibbb:
9631 {
9632 int *inel=NULL;
9633 byte *r=NULL, *g=NULL, *b=NULL, *a=NULL;
9634
9635 inel = (int *)sopd->i;
9636 r = (byte *)sopd->r;
9637 g = (byte *)sopd->g;
9638 b = (byte *)sopd->b;
9639 for (i=0; i < i_max; ++i) {
9640 /*fprintf(SUMA_STDERR,
9641 "Node %d: r%d, g%d, b%d\n",
9642 inel[i], r[i], g[i], b[i]);*/
9643 if (SO->N_Node > inel[i]) {
9644 Nv[i] = inel[i];
9645 Rv[i] = (float)(r[i]) / 255.0;
9646 Gv[i] = (float)(g[i]) / 255.0;
9647 Bv[i] = (float)(b[i]) / 255.0;
9648 } else {
9649 if (!wrn_cnt) {
9650 SUMA_SLP_Warn(
9651 "Color plane includes node indices (%d at %d)\n"
9652 "that are >= number of nodes in surface (%d).\n"
9653 "Other similar warnings will be muted.",
9654 inel[i], i, SO->N_Node);
9655 }
9656 ++wrn_cnt;
9657 }
9658 }
9659 }
9660 break;
9661 case SOPT_ifff:
9662 {
9663 int *inel=NULL;
9664 float *r=NULL, *g=NULL, *b=NULL, *a=NULL;
9665
9666 inel = (int *)sopd->i;
9667 r = (float *)sopd->r;
9668 g = (float *)sopd->g;
9669 b = (float *)sopd->b;
9670 for (i=0; i < i_max; ++i) {
9671 /*fprintf(SUMA_STDERR,
9672 "Node %d: r%f, g%f, b%f\n", inel[i], r[i], g[i], b[i]);*/
9673 if (SO->N_Node > inel[i]) {
9674 Nv[i] = inel[i];
9675 Rv[i] = (float)(r[i]) ;
9676 Gv[i] = (float)(g[i]) ;
9677 Bv[i] = (float)(b[i]) ;
9678 } else {
9679 if (!wrn_cnt) {
9680 SUMA_SLP_Warn("Color plane includes node indices\n"
9681 "that are >= number of nodes in surface.\n");
9682 }
9683 ++wrn_cnt;
9684 }
9685 }
9686 }
9687 break;
9688 default:
9689 SUMA_SLP_Err("Unknown color plane type");
9690 SUMA_RETURN(NOPE);
9691 break;
9692 }
9693 }
9694
9695 /* Now you want to create the colors of that plane based on
9696 the data in dset */
9697 if (!SUMA_ColorizePlane (SO->Overlays[OverInd])) {
9698 SUMA_SLP_Err("Failed to colorize plane.\n");
9699 SUMA_RETURN(NOPE);
9700 }
9701
9702 /* store overlay plane index here, OverInd will get mango-ed
9703 further down */
9704 if (LocalHead)
9705 fprintf (SUMA_STDERR,
9706 "%s: OverInd = %d. Returning.\n", FuncName, OverInd);
9707 *PlaneInd = OverInd;
9708
9709 SUMA_RETURN (YUP);
9710
9711 }
9712
9713 /*!
9714 \brief A function that looks up an overlay plane by its name for Tracts
9715 If the plane is found its index is returned, otherwise
9716 a new one is created. The function also sets up pointers to
9717 that plane for all related surfaces in dov and places node colors
9718 in that plane.
9719
9720 \param TDO (SUMA_TractDO *) Tract Object
9721 \param Name (char *) Name of color plane
9722 \param sopd (SUMA_OVERLAY_PLANE_DATA *) Data to put in overlay plane
9723 \param PlaneInd (int *) index of created or found color plane
9724 (that's set by the function )
9725 \param dov (SUMA_DO *) vector of displayable objects
9726 \param N_dov (int ) number of displayable objects
9727
9728 */
SUMA_iRGB_to_TDO_OverlayPointer(SUMA_TractDO * TDO,char * Name,SUMA_OVERLAY_PLANE_DATA * sopd,int * PlaneInd,SUMA_DO * dov,int N_dov,DList * DsetList)9729 SUMA_Boolean SUMA_iRGB_to_TDO_OverlayPointer (SUMA_TractDO *TDO,
9730 char *Name, SUMA_OVERLAY_PLANE_DATA *sopd,
9731 int *PlaneInd, SUMA_DO *dov, int N_dov,
9732 DList *DsetList)
9733 {
9734 static char FuncName[]={"SUMA_iRGB_to_TDO_OverlayPointer"};
9735 char *DsetName_tmp=NULL;
9736 int i, OverInd = -1, i_max, wrn_cnt = 0, i3 = 0, N_Dat;
9737 SUMA_ALL_DO *ado = (SUMA_ALL_DO *)TDO;
9738 SUMA_SurfaceObject *SO2 = NULL;
9739 SUMA_OVERLAYS *Overlay=NULL;
9740 SUMA_DSET *dset = NULL;
9741 SUMA_Boolean LocalHead = NOPE;
9742
9743 SUMA_ENTRY;
9744
9745 // fprintf(stderr, "%s\n", FuncName);
9746
9747 SUMA_LH("Fetching Overlay Pointer");
9748 /* if plane exists use it, else create a new one on the mappable surface */
9749 if (!SUMA_Fetch_OverlayPointer (ado, Name, &OverInd)) {
9750 /* overlay plane not found, create a new one on these tracts */
9751 DsetName_tmp = SUMA_append_replace_string(Name,
9752 SUMA_ADO_idcode(ado),TMP_NAME_SEP, 0);
9753 SUMA_LH("pointer not found, creating %s", DsetName_tmp);
9754 switch (sopd->dtlvl) {
9755 case SUMA_ELEM_DAT:
9756 dset = SUMA_CreateDsetPointer (DsetName_tmp,
9757 SUMA_NODE_RGB,
9758 NULL,
9759 SUMA_ADO_idcode(ado),
9760 SUMA_ADO_N_Datum(ado));
9761 break;
9762 case SUMA_LEV1_DAT:
9763 dset = SUMA_CreateDsetPointer (DsetName_tmp,
9764 SUMA_NODE_RGB,
9765 NULL,
9766 SUMA_ADO_idcode(ado),
9767 TDO_N_TRACTS(TDO));
9768 break;
9769 case SUMA_LEV2_DAT:
9770 dset = SUMA_CreateDsetPointer (DsetName_tmp,
9771 SUMA_NODE_RGB,
9772 NULL,
9773 SUMA_ADO_idcode(ado),
9774 TDO_N_BUNDLES(TDO));
9775 break;
9776 default:
9777 SUMA_S_Err("Not ready for this crazy level %d\n", sopd->dtlvl);
9778 SUMA_RETURN(NOPE);
9779 }
9780 SUMA_sdset_set_datum_level(dset,sopd->dtlvl);
9781 SUMA_ifree(DsetName_tmp);
9782 SUMA_LH("Inserting dset into list");
9783 /* insert that element into DaList */
9784 if (!SUMA_InsertDsetPointer(&dset, DsetList, 0)) {
9785 SUMA_SL_Err("Failed to insert dset into list");
9786 SUMA_RETURN(NOPE);
9787 }
9788 /* We'll be using NodeDef here so begin by allocating space
9789 for the various entries */
9790 SUMA_AddDsetNelCol (dset, "node index", SUMA_NODE_INDEX, NULL, NULL, 1);
9791 SUMA_AddDsetNelCol (dset, "red", SUMA_NODE_R, NULL, NULL, 1);
9792 SUMA_AddDsetNelCol (dset, "green", SUMA_NODE_G, NULL, NULL, 1);
9793 SUMA_AddDsetNelCol (dset, "blue", SUMA_NODE_B, NULL, NULL, 1);
9794
9795 Overlay = SUMA_CreateOverlayPointer (Name, dset, ADO_ID(ado), NULL);
9796 if (!Overlay) {
9797 SUMA_SL_Err("Failed in SUMA_CreateOverlayPointer.\n");
9798 SUMA_RETURN(NOPE);
9799 }
9800
9801 /* set up some defaults for the overlap plane */
9802 if (sopd->Show) Overlay->ShowMode = SW_SurfCont_DsetViewCol;
9803 else Overlay->ShowMode = -SW_SurfCont_DsetViewCol;
9804 Overlay->GlobalOpacity = sopd->GlobalOpacity;
9805 Overlay->isBackGrnd = sopd->isBackGrnd;
9806 Overlay->OptScl->BrightFact = sopd->DimFact;
9807 OverInd = SUMA_ADO_N_Overlays(ado);
9808
9809 /* Add this plane to TDO's overlays */
9810 if (!SUMA_AddNewPlane (ado, Overlay, dov, N_dov, 0)) {
9811 SUMA_SL_Crit("Failed in SUMA_AddNewPlane");
9812 SUMA_FreeOverlayPointer(Overlay);
9813 SUMA_RETURN (NOPE);
9814 }
9815 }else {
9816 SUMA_LH("Pointer found");
9817 }
9818
9819 if (LocalHead)
9820 fprintf (SUMA_STDERR,
9821 "%s: OverInd = %d, Loading colors to Overlay Plane...\n",
9822 FuncName, OverInd);
9823 if (sopd->N > SUMA_ADO_N_Datum_Lev(ado, sopd->dtlvl)) {
9824 SUMA_SLP_Warn("Number of nodes in colorplane (%d)\n"
9825 "is larger than number of datum targets in object (%d)\n"
9826 "Proceed if you know what you're doing.\n"
9827 "Data from high node indices will be ignored.",
9828 sopd->N, SUMA_ADO_N_Datum_Lev(ado, sopd->dtlvl));
9829 i_max = SUMA_ADO_N_Datum_Lev(ado, sopd->dtlvl);
9830 } else {
9831 i_max = sopd->N;
9832 }
9833
9834 Overlay = SUMA_ADO_Overlay(ado, OverInd);
9835 Overlay->DimFact = sopd->DimFact;
9836 Overlay->cmapname = SUMA_copy_string("explicit");
9837 /* explict color definition in data */
9838 Overlay->FullList = 0; /*!< This type of planes is not
9839 usually a full list because it has the nodes defined*/
9840
9841 /* Now put the colors in the overlay plane */
9842 SUMA_LH("%d node colors are to be inserted.", i_max);
9843
9844 COLP_N_NODEDEF(Overlay) = i_max; /* set the number of nodes
9845 filled IN THE OVERLAY PLANE*/
9846 SDSET_VECFILLED(Overlay->dset_link) = i_max; /* set the
9847 number of nodes filled IN THE DSET, For this
9848 type of dsets, the N_NodeDef is the same for
9849 both OVERLAY and for DSET*/
9850 if (COLP_N_NODEDEF(Overlay)) {
9851 int *iv, N_i,*Nv;
9852 float *Rv, *Gv, *Bv;
9853 SUMA_DSET *dset;
9854 dset = Overlay->dset_link;
9855 /* find the columns you need to fill.
9856 You can't use SUMA_FillNelCol directly because
9857 columns (vectors) are of different types */
9858 if (!(Nv = SUMA_GetNodeDef(dset))) {
9859 SUMA_SL_Err("Failed to find node indices."); SUMA_RETURN(NOPE); }
9860 if (LocalHead) SUMA_ShowDset(dset, 0, NULL);
9861 iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_R, &N_i);
9862 if (N_i != 1) {
9863 SUMA_SL_Err("Failed to find one column.");
9864 SUMA_free(iv); SUMA_RETURN(NOPE); }
9865 Rv = (float *)dset->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
9866 iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_G, &N_i);
9867 if (N_i != 1) {
9868 SUMA_SL_Err("Failed to find one column.");
9869 SUMA_free(iv); SUMA_RETURN(NOPE); }
9870 Gv = (float *)dset->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
9871 iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_B, &N_i);
9872 if (N_i != 1) {
9873 SUMA_SL_Err("Failed to find one column.");
9874 SUMA_free(iv); SUMA_RETURN(NOPE); }
9875 Bv = (float *)dset->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
9876 /* Now store these colors into the dataset */
9877 N_Dat = SUMA_ADO_N_Datum_Lev(ado, sopd->dtlvl);
9878 switch (sopd->Type) {
9879 case SOPT_ibbb:
9880 {
9881 int *inel=NULL;
9882 byte *r=NULL, *g=NULL, *b=NULL, *a=NULL;
9883
9884 inel = (int *)sopd->i;
9885 r = (byte *)sopd->r;
9886 g = (byte *)sopd->g;
9887 b = (byte *)sopd->b;
9888 for (i=0; i < i_max; ++i) {
9889 /* fprintf(SUMA_STDERR,
9890 "Node %d: r%d, g%d, b%d\n",
9891 inel[i], r[i], g[i], b[i]); */
9892 if (N_Dat > inel[i]) {
9893 Nv[i] = inel[i];
9894 Rv[i] = (float)(r[i]) / 255.0;
9895 Gv[i] = (float)(g[i]) / 255.0;
9896 Bv[i] = (float)(b[i]) / 255.0;
9897 } else {
9898 if (!wrn_cnt) {
9899 SUMA_SLP_Warn(
9900 "Color plane includes node indices (%d at %d)\n"
9901 "that are >= number of nodes in surface (%d).\n"
9902 "Other similar warnings will be muted.",
9903 inel[i], i, N_Dat);
9904 }
9905 ++wrn_cnt;
9906 }
9907 }
9908 }
9909 break;
9910 case SOPT_ifff:
9911 {
9912 int *inel=NULL;
9913 float *r=NULL, *g=NULL, *b=NULL, *a=NULL;
9914
9915 inel = (int *)sopd->i;
9916 r = (float *)sopd->r;
9917 g = (float *)sopd->g;
9918 b = (float *)sopd->b;
9919 for (i=0; i < i_max; ++i) {
9920 /*fprintf(SUMA_STDERR,
9921 "Node %d: r%f, g%f, b%f\n", inel[i], r[i], g[i], b[i]);*/
9922 if (N_Dat > inel[i]) {
9923 Nv[i] = inel[i];
9924 Rv[i] = (float)(r[i]) ;
9925 Gv[i] = (float)(g[i]) ;
9926 Bv[i] = (float)(b[i]) ;
9927 } else {
9928 if (!wrn_cnt) {
9929 SUMA_SLP_Warn("Color plane includes node indices\n"
9930 "that are >= number of nodes in surface.\n");
9931 }
9932 ++wrn_cnt;
9933 }
9934 }
9935 }
9936 break;
9937 default:
9938 SUMA_SLP_Err("Unknown color plane type");
9939 SUMA_RETURN(NOPE);
9940 break;
9941 }
9942 }
9943
9944 /* Now you want to create the colors of that plane based on
9945 the data in dset */
9946 if (!SUMA_ColorizePlane (Overlay)) {
9947 SUMA_SLP_Err("Failed to colorize plane.\n");
9948 SUMA_RETURN(NOPE);
9949 }
9950
9951 /* store overlay plane index here, OverInd will get mango-ed
9952 further down */
9953 SUMA_LH("OverInd = %d. Returning.", OverInd);
9954 *PlaneInd = OverInd;
9955
9956 SUMA_RETURN (YUP);
9957 }
9958
SUMA_is_NamedColPlane_ForROI(char * PlaneName)9959 SUMA_DRAWN_ROI * SUMA_is_NamedColPlane_ForROI(char *PlaneName)
9960 {
9961 static char FuncName[]={"SUMA_is_NamedColPlane_ForROI"};
9962 int i;
9963 SUMA_DRAWN_ROI *D_ROI=NULL;
9964 SUMA_Boolean LocalHead = NOPE;
9965
9966 SUMA_ENTRY;
9967
9968 // fprintf(stderr, "%s\n", FuncName);
9969
9970 if (!PlaneName) SUMA_RETURN(NULL);
9971
9972 /* search all dov for ROIs that use the same plane */
9973 for (i=0; i < SUMAg_N_DOv && !D_ROI; ++i) {
9974 switch (SUMAg_DOv[i].ObjectType) { /* case Object Type */
9975 case ROIdO_type:
9976 if ((D_ROI = (SUMA_DRAWN_ROI *)SUMAg_DOv[i].OP)) {
9977 if ( D_ROI->ColPlaneName &&
9978 !strcmp(D_ROI->ColPlaneName, PlaneName) ) {
9979 SUMA_RETURN(D_ROI);
9980 } else {
9981 D_ROI=NULL;
9982 }
9983 }
9984 break;
9985 default:
9986 D_ROI = NULL;
9987 break;
9988 }
9989 }
9990 SUMA_RETURN(NULL);
9991 }
9992
9993 /*!
9994 \brief SUMA_FlushPlaneNotInUse (char *PlaneName, SUMA_SurfaceObject *SO, SUMA_DO *dov, int N_dov)
9995 Searches all DrawnROIs in dov.
9996 If no ROI related to SO has PlaneName for a color plane
9997 then that colorplane is flushed (ie no node colors are left in it, not deleted)
9998 */
SUMA_FlushPlaneNotInUse(char * PlaneName,SUMA_ALL_DO * ado,SUMA_DO * dov,int N_dov)9999 SUMA_Boolean SUMA_FlushPlaneNotInUse (char *PlaneName, SUMA_ALL_DO *ado,
10000 SUMA_DO *dov, int N_dov)
10001 {
10002 static char FuncName[]={"SUMA_FlushPlaneNotInUse"};
10003 SUMA_DRAWN_ROI *D_ROI = NULL;
10004 int i, OverInd;
10005 SUMA_Boolean LocalHead = NOPE;
10006
10007 SUMA_ENTRY;
10008
10009 // fprintf(stderr, "%s\n", FuncName);
10010
10011 if (!PlaneName) SUMA_RETURN(YUP);
10012
10013 /* search all dov for ROIs that use the same plane */
10014 for (i=0; i < N_dov; ++i) {
10015 switch (dov[i].ObjectType) { /* case Object Type */
10016 case ROIdO_type:
10017 D_ROI = (SUMA_DRAWN_ROI *)dov[i].OP;
10018 break;
10019 default:
10020 D_ROI = NULL;
10021 break;
10022 }
10023 if (D_ROI && SUMA_isdROIrelated (D_ROI, ado)) {
10024 if (strcmp(PlaneName, D_ROI->ColPlaneName) == 0) {
10025 /* found one, do nothing and return */
10026 SUMA_RETURN (YUP);
10027 }
10028 }
10029 }
10030
10031 /* looks like no other ROIs use that plane, flush it */
10032 if (!SUMA_Fetch_OverlayPointer (ado, PlaneName, &OverInd)) {
10033 SUMA_SLP_Warn("No Overlay Plane Found!");
10034 SUMA_RETURN (YUP);
10035 }
10036
10037 SUMA_LH("Flushing meadows");
10038 COLP_N_NODEDEF(SUMA_ADO_Overlay(ado,OverInd)) = 0;
10039 SUMA_RETURN (YUP);
10040 }
10041
10042 /*!
10043 \brief refreshes a colorplane list.
10044 A combo of SUMA_AssembleColorPlaneList and SUMA_CreateScrolledList.
10045
10046 */
SUMA_RefreshDsetList(SUMA_ALL_DO * ado)10047 void SUMA_RefreshDsetList (SUMA_ALL_DO *ado)
10048 {
10049 static char FuncName[]={"SUMA_RefreshDsetList"};
10050 SUMA_LIST_WIDGET *LW = NULL;
10051 SUMA_X_SurfCont *SurfCont=NULL;
10052 SUMA_Boolean LocalHead = NOPE;
10053
10054 SUMA_ENTRY;
10055
10056 // fprintf(stderr, "%s\n", FuncName);
10057
10058 SurfCont = SUMA_ADO_Cont(ado);
10059 LW = SurfCont->SwitchDsetlst;
10060
10061 if (!LW) SUMA_RETURNe;
10062
10063 if (LW->ALS) {
10064 /* free that old hag */
10065 if (LocalHead) SUMA_S_Err("Freeing the hag.");
10066 LW->ALS = SUMA_FreeAssembleListStruct(LW->ALS);
10067 }
10068
10069
10070 /* assemble the ColorPlane list */
10071 LW->ALS = SUMA_AssembleColorPlaneList (ado);
10072
10073 if (!LW->ALS) {
10074 SUMA_SLP_Err("Error assembling list.");
10075 SUMA_RETURNe;
10076 }
10077
10078 if (LW->ALS->N_clist < 0) {
10079 SUMA_SL_Err("Failed in SUMA_AssembleColorPlaneList");
10080 SUMA_RETURNe;
10081 }
10082
10083 if (!LW->ALS->N_clist) {
10084 SUMA_SLP_Note ("No Color planes to choose from.");
10085 SUMA_RETURNe;
10086 }
10087
10088 if (LocalHead) {
10089 int i;
10090 for (i=0; i < LW->ALS->N_clist; ++i)
10091 fprintf (SUMA_STDERR,"%s: %s\n", FuncName, LW->ALS->clist[i]);
10092 }
10093 SUMA_CreateScrolledList ( LW->ALS->clist, LW->ALS->N_clist, NOPE,
10094 LW);
10095
10096 SUMA_RETURNe;
10097 }
10098
10099 /*!
10100 \brief Returns a list of the Colorplanes belonging to a certain surface.
10101
10102 \param SO (SUMA_SurfaceObject *) pointer to surface object
10103
10104 \return clist (SUMA_ASSEMBLE_LIST_STRUCT *) pointer to structure
10105 containing results
10106
10107 \sa SUMA_FreeAssembleListStruct
10108 \sa SUMA_CreateAssembleListStruct
10109
10110 */
SUMA_AssembleColorPlaneList(SUMA_ALL_DO * ado)10111 SUMA_ASSEMBLE_LIST_STRUCT * SUMA_AssembleColorPlaneList (SUMA_ALL_DO *ado)
10112 {
10113 static char FuncName[]={"SUMA_AssembleColorPlaneList"};
10114 int i=-1, N_clist=-1;
10115 DList *list=NULL, *listop = NULL, *OverlayPlanelist = NULL;
10116 DListElmt *Elm = NULL, *Elmop = NULL, *Elm_OverlayPlanelist = NULL;
10117 char Label[SUMA_MAX_NAME_LENGTH], *store=NULL;
10118 char **clist=NULL;
10119 void **oplist=NULL;
10120 SUMA_ASSEMBLE_LIST_STRUCT *clist_str = NULL;
10121 SUMA_OVERLAY_LIST_DATUM *OvD=NULL, *oOvD=NULL;
10122 SUMA_Boolean SortByOrder = YUP;
10123 SUMA_Boolean Found = NOPE;
10124 SUMA_Boolean LocalHead = NOPE;
10125
10126 SUMA_ENTRY;
10127
10128 // fprintf(stderr, "%s\n", FuncName);
10129
10130 /* get list of all Overlay planes */
10131 OverlayPlanelist = SUMA_OverlaysToOrderedList (ado, 0);
10132
10133 /* need a list to store new names */
10134 list = (DList *)SUMA_calloc(1,sizeof(DList));
10135 dlist_init(list, NULL); /* you don't want to free the strings */
10136 /* need a list to store the pointers, it is useless when SortByOrder
10137 is used, but I leave it in to keep the code simple */
10138 listop = (DList *)SUMA_calloc(1,sizeof(DList));
10139 dlist_init(listop, NULL); /* you don't want to free the data as it is
10140 copied from OverlayPlanelist*/
10141
10142 clist = NULL;
10143 N_clist = -1;
10144 Elm_OverlayPlanelist = NULL;
10145 do {
10146 if (!Elm_OverlayPlanelist)
10147 Elm_OverlayPlanelist = dlist_head(OverlayPlanelist);
10148 else Elm_OverlayPlanelist = Elm_OverlayPlanelist->next;
10149
10150 OvD = (SUMA_OVERLAY_LIST_DATUM *) Elm_OverlayPlanelist->data;
10151
10152 if (!OvD->Overlay->Label) sprintf (Label,"NULL");
10153 else sprintf (Label,"%s", OvD->Overlay->Label);
10154
10155 /* Now allocate space for that label */
10156 store = (char *)SUMA_calloc(strlen(Label)+10, sizeof(char));
10157 if (OvD->Overlay->isBackGrnd) {
10158 sprintf(store,"bk:%s", Label);
10159 } else {
10160 sprintf(store,"fg:%s", Label);
10161 }
10162
10163 if (SortByOrder) {
10164 SUMA_LH("Sorting by order");
10165 /* list is already sorted, just copy the string and object
10166 structure pointers to lists */
10167 dlist_ins_next(list, dlist_tail(list), (void*)store);
10168 /* this line is redundant with SortByOrder but it don't hoyt */
10169 dlist_ins_next(listop, dlist_tail(listop), (void*)OvD);
10170 } else { /* sort the list by aplhpabetical order */
10171 SUMA_LH("Sorting by name");
10172 if (!list->size) {
10173 dlist_ins_next(list, dlist_tail(list), (void*)store);
10174 dlist_ins_next(listop, dlist_tail(listop), (void*)OvD);
10175 }else { /* must sort first */
10176 Elm = NULL;
10177 Elmop = NULL;
10178 do {
10179 Found = NOPE;
10180 if (!Elm) {
10181 Elm = dlist_head(list);
10182 Elmop = dlist_head(listop);
10183 } else {
10184 Elm = Elm->next;
10185 Elmop = Elmop->next;
10186 }
10187
10188 if (strcmp(store, (char*)Elm->data) <= 0) {
10189 dlist_ins_prev(list, Elm, (void *)store);
10190 dlist_ins_prev(listop, Elmop, (void *)OvD);
10191 Found = YUP;
10192 } else if (Elm == dlist_tail(list)) {
10193 /* reached the end, append */
10194 dlist_ins_next(list, Elm, (void *)store);
10195 dlist_ins_next(listop, Elmop, (void *)OvD);
10196 Found = YUP;
10197 }
10198 } while (!Found);
10199 }
10200
10201 }
10202 } while (Elm_OverlayPlanelist != dlist_tail(OverlayPlanelist));
10203
10204 SUMA_LH("saving list.");
10205 if (!list->size) { /* Nothing found */
10206 SUMA_LH("Empty list");
10207 N_clist = 0;
10208 }else {
10209 Elm = NULL;
10210 Elmop = NULL;
10211 clist = (char **)SUMA_calloc(list->size, sizeof(char *));
10212 oplist = (void **)SUMA_calloc(list->size, sizeof(void *));
10213 for (i=0; i< list->size; ++i) {
10214 if (!Elm) {
10215 Elm = dlist_head(list);
10216 Elmop = dlist_head(listop);
10217 } else {
10218 Elm = dlist_next(Elm);
10219 Elmop = dlist_next(Elmop);
10220 }
10221 clist[i] = (char*)Elm->data;
10222 OvD = (SUMA_OVERLAY_LIST_DATUM *) Elmop->data;
10223 oplist[i] = (void *)OvD->Overlay;
10224 if (LocalHead) fprintf (SUMA_STDERR,"%s: Inserting %s with %s (%s).\n",
10225 FuncName, clist[i], OvD->Overlay->Label, OvD->Overlay->Name);
10226 }
10227
10228 N_clist = list->size;
10229 /* destroy list */
10230 dlist_destroy(list);SUMA_free(list);
10231 dlist_destroy(listop);SUMA_free(listop);
10232 dlist_destroy(OverlayPlanelist);SUMA_free(OverlayPlanelist);
10233
10234
10235
10236 }
10237
10238 clist_str = SUMA_CreateAssembleListStruct();
10239 clist_str->clist = clist;
10240 clist_str->oplist = oplist;
10241 clist_str->N_clist = N_clist;
10242
10243 /* return */
10244 SUMA_RETURN (clist_str);
10245 }
10246
10247 /*!
10248 \brief determines if a Dset is related to a surface
10249 */
SUMA_isDsetRelated(SUMA_DSET * dset,SUMA_SurfaceObject * SO)10250 SUMA_Boolean SUMA_isDsetRelated(SUMA_DSET *dset, SUMA_SurfaceObject *SO)
10251 {
10252 static char FuncName[]={"SUMA_isDsetRelated"};
10253 char *mp = NULL;
10254 int lmp = 0;
10255 SUMA_ENTRY;
10256
10257 // fprintf(stderr, "%s\n", FuncName);
10258
10259 if (!dset) SUMA_RETURN(NOPE);
10260 if (!SO) SUMA_RETURN(NOPE);
10261
10262 mp = SDSET_IDMDOM(dset); if (mp) lmp = strlen(mp); else lmp = 0;
10263
10264 if (mp && lmp) {
10265 if (strcmp(mp, SO->idcode_str) == 0){
10266 SUMA_RETURN(YUP);
10267 }
10268 if (SO->DomainGrandParentID) {
10269 if (strcmp(mp, SO->DomainGrandParentID) == 0){
10270 SUMA_RETURN(YUP);
10271 }
10272 }
10273 if (SO->LocalDomainParentID) {
10274 if (strcmp(mp, SO->LocalDomainParentID) == 0){
10275 SUMA_RETURN(YUP);
10276 }
10277 }
10278 }
10279
10280 SUMA_RETURN(NOPE);
10281 }
10282
SUMA_isDsetColumn_inferred(SUMA_DSET * dset,int icol)10283 SUMA_Boolean SUMA_isDsetColumn_inferred(SUMA_DSET *dset, int icol)
10284 {
10285 static char FuncName[]={"SUMA_isDsetColumn_inferred"};
10286 char *lblcp=NULL;
10287 SUMA_Boolean LocalHead = NOPE;
10288 SUMA_ENTRY;
10289
10290 // fprintf(stderr, "%s\n", FuncName);
10291
10292 lblcp = SUMA_DsetColLabelCopy(dset, icol, 0);
10293
10294 SUMA_LH("%s", lblcp);
10295 if (lblcp) {
10296 if (strstr(lblcp, "(inferred)")) SUMA_RETURN(YUP);
10297 }
10298 SUMA_free(lblcp);
10299 SUMA_RETURN(NOPE);
10300 }
10301
10302
10303 /*!
10304 \brief determines if a Dset can be assigned to a surface object
10305 */
SUMA_OKassign(SUMA_DSET * dset,SUMA_SurfaceObject * SO)10306 SUMA_Boolean SUMA_OKassign(SUMA_DSET *dset, SUMA_SurfaceObject *SO)
10307 {
10308 static char FuncName[]={"SUMA_OKassign"};
10309 double range[2];
10310 int loc[2], *ind = NULL, lnp = 0;
10311 char *np = NULL, stmp[201];
10312 SUMA_Boolean LocalHead = NOPE;
10313
10314 SUMA_ENTRY;
10315
10316 // fprintf(stderr, "%s\n", FuncName);
10317
10318 if (!dset) SUMA_RETURN(NOPE);
10319 if (!SO) SUMA_RETURN(NOPE);
10320
10321 /* does dset have a mesh parent ? */
10322 np = SDSET_IDMDOM(dset); if (np) lnp = strlen(np); else lnp = 0;
10323 if (np && lnp) {
10324 SUMA_LH("Has IDMDOM");
10325 /* has parent, verify against SO*/
10326 if (SUMA_isDsetRelated(dset, SO)) {
10327 SUMA_LH("Is Related"); SUMA_RETURN(YUP);
10328 }
10329 else { SUMA_LH("Is NOT Related"); SUMA_RETURN(NOPE); }
10330 }
10331
10332 SUMA_LH("Has no parent, trying adoption");
10333 /* has no parent, check if you can adopt it*/
10334 ind = SUMA_GetNodeDef(dset);
10335 if (!ind) {
10336 SUMA_LH("No node index column");
10337 /* No node index. Make sure vec_len <= SO->N_Node */
10338 if (SDSET_VECLEN(dset) <= SO->N_Node) {
10339 SUMA_LH("Number of values per column\n"
10340 "is less than the number \n"
10341 "of nodes in the surface.\n");
10342 if (SDSET_VECFILLED(dset) != SO->N_Node) {
10343 SUMA_LH("Need to attach a node index column, if possible");
10344 /* attempt to assign a node index column */
10345 if (!SUMA_AddNodeIndexColumn(dset, SO->N_Node)) {
10346 SUMA_LH(" Failed to add a node index column");
10347 SUMA_RETURN(NOPE);
10348 } else {
10349 SUMA_LH("Added Index Column");
10350 SUMA_RETURN(YUP);
10351 }
10352 }else {
10353 SUMA_LH(
10354 "Looks like a full list of values\n"
10355 "Techincally, there's no need for explicit node column.\n"
10356 "But at times, the data are not ordered by ascending node \n"
10357 "index which causes trouble.\nSo now I add a node index column"
10358 " always which would help point to the problem if it arises");
10359 /* Sept 21 04, call SUMA_AddNodeIndexColumn, it is good for you.
10360 Might add an unecessary index column when none exit but makes
10361 things clear*/
10362 if (!SUMA_AddNodeIndexColumn(dset, SO->N_Node)) {
10363 SUMA_LH(" Failed to add a node index column");
10364 SUMA_RETURN(NOPE);
10365 }
10366 SUMA_LH("Added Index Column");
10367 SUMA_RETURN(YUP);
10368 }
10369 } else {
10370 SUMA_SLP_Warn("Number of values per column (%d)\n"
10371 "is larger than the number \n"
10372 "of nodes (%d) in the surface.",
10373 SDSET_VECLEN(dset), SO->N_Node);
10374 SUMA_RETURN(NOPE);
10375 }
10376 } else {
10377 SUMA_LH("Node index column found");
10378 /* there is a node index column, see if the range is OK */
10379 if (!SUMA_GetDsetNodeIndexColRange(dset, range, loc, 1)) {
10380 SUMA_SLP_Err("Unexpect error in SUMA_GetDsetColRange");
10381 SUMA_RETURN(NOPE);
10382 }
10383 if (range[0] < 0 || range[1] > SO->N_Node) {
10384 SUMA_SLP_Err("Node index range outside\n"
10385 "0 and SO->N_Node");
10386 SUMA_RETURN(NOPE);
10387 }
10388 /* Now we're OK to return on a positive note */
10389 SUMA_RETURN(YUP);
10390 }
10391
10392 SUMA_SL_Err("Should not get here");
10393 SUMA_RETURN(NOPE);
10394 }
10395
10396 /*!
10397 \brief Loads a Dset file and adds it to the list of datasets
10398
10399 \param dlg (SUMA_SELECTION_DIALOG_STRUCT *) struture from selection dialogue
10400 */
SUMA_LoadDsetOntoSO(char * filename,void * data)10401 void SUMA_LoadDsetOntoSO (char *filename, void *data)
10402 {
10403 static char FuncName[]={"SUMA_LoadDsetOntoSO"};
10404 SUMA_SurfaceObject *SO = NULL, *SOC=NULL;
10405 char *fC=NULL;
10406
10407 SUMA_ENTRY;
10408
10409 // fprintf(stderr, "%s\n", FuncName);
10410
10411 if (!data || !filename) {
10412 SUMA_SLP_Err("Null data");
10413 SUMA_RETURNe;
10414 }
10415
10416 SO = (SUMA_SurfaceObject *)data;
10417
10418 if (!SUMA_LoadDsetOntoSO_eng(filename, SO, 1, 1, 1, NULL)) {
10419 SUMA_SLP_Err("Failed loading, and colorizing dset");
10420 SUMA_RETURNe;
10421 }
10422
10423 if (!(SOC = SUMA_Contralateral_SO(SO, SUMAg_DOv, SUMAg_N_DOv))) {
10424 SUMA_RETURNe;
10425 }
10426 if (!(fC = SUMA_Contralateral_file(filename))) {
10427 SUMA_RETURNe;
10428 }
10429
10430 /* have contralateral bunch, load 'em cowboy */
10431 if (!(SUMA_OpenCloseSurfaceCont(NULL, (SUMA_ALL_DO *)SOC, NULL))) {
10432 SUMA_free(fC);
10433 SUMA_S_Err("Failed initializing contraleteral controller");
10434 SUMA_RETURNe;
10435 }
10436 /* insist on a glXMakeCurrent for surface viewer,
10437 This is an effort to prevent a crash under certain conditions
10438 in OS X 10.7. See detailed comment SUMA_handleRedisplay().
10439 Forcing glXMakeCurrent here is better than doing it always
10440 in SUMA_handleRedisplay()*/
10441 SUMA_SiSi_I_Insist();
10442 if (!SUMA_LoadDsetOntoSO_eng(fC, SOC, 1, 1, 1, NULL)) {
10443 SUMA_free(fC);
10444 SUMA_S_Err("Failed loading, and colorizing contralateral dset");
10445 SUMA_RETURNe;
10446 }
10447
10448 SUMA_free(fC); fC=NULL;
10449
10450 SUMA_RETURNe;
10451 }
10452
10453 /*!
10454 Function originally meant to load dset and associate with SO.
10455 However it is not also used to load a graph dset which needs no SO */
SUMA_LoadDsetOntoSO_eng(char * filename,SUMA_SurfaceObject * SO,int SetupOverlay,int MakeOverlayCurrent,int LaunchDisplay,SUMA_OVERLAYS ** used_over)10456 SUMA_Boolean SUMA_LoadDsetOntoSO_eng (char *filename, SUMA_SurfaceObject *SO,
10457 int SetupOverlay, int MakeOverlayCurrent,
10458 int LaunchDisplay, SUMA_OVERLAYS **used_over)
10459 {
10460 static char FuncName[]={"SUMA_LoadDsetOntoSO_eng"};
10461 SUMA_IRGB *irgb=NULL;
10462 int OverInd = -1, lnp=-1, loc[2], OKdup = 0;
10463 char *np=NULL, *dsetcmap=NULL;
10464 SUMA_DSET_FORMAT form;
10465 DList *list=NULL;
10466 SUMA_LIST_WIDGET *LW=NULL;
10467 SUMA_DSET *dset = NULL, *dsetpre = NULL;
10468 SUMA_OVERLAYS *NewColPlane = NULL, *colplanepre = NULL;
10469 SUMA_Boolean LocalHead = NOPE;
10470
10471 SUMA_ENTRY;
10472
10473 // fprintf(stderr, "%s\n", FuncName);
10474
10475 if (!filename) {
10476 SUMA_S_Err("Null data");
10477 SUMA_RETURN(NOPE);
10478 }
10479
10480 if (LocalHead) {
10481 fprintf (SUMA_STDERR,
10482 "%s: Received request to load %s for surface %s.\n",
10483 FuncName, filename, SO ? SO->Label:"NULL");
10484 }
10485
10486 /* find out if file exists and how many values it contains */
10487 if (!SUMA_filexists(filename)) {
10488 SUMA_SLP_Err("File not found");
10489 SUMA_RETURN(NOPE);
10490 }
10491
10492 /* take a stab at the format */
10493 form = SUMA_GuessFormatFromExtension(filename, NULL);
10494
10495 /* load the dude */
10496 /* first, set the parent ID of the dset to be loaded,
10497 This parent ID is only used when generating an ID for those dsets
10498 that have no ID attached, like the 1D ones
10499 N.B: These setting will get ignored if the loaded dataset does
10500 not belong on a surface, like for a graph.
10501 */
10502 if (SO) {
10503 if (SO->LocalDomainParentID)
10504 SUMA_SetParent_DsetToLoad(SO->LocalDomainParentID);
10505 else if (SO->idcode_str)
10506 SUMA_SetParent_DsetToLoad(SO->idcode_str);
10507 else SUMA_SetParent_DsetToLoad(NULL);
10508 } else {
10509 SUMA_SetParent_DsetToLoad(NULL);
10510 }
10511
10512 /* Might have tracts in there */
10513 get_NI_tract_type();
10514
10515 dset = SUMA_LoadDset_s (filename, &form, 0);
10516 SUMA_LHv("Dset as loaded is %p\n", dset);
10517
10518 if (!dset) { SUMA_SLP_Err( "Failed to load dataset.\n"
10519 "Make sure file exists\n"
10520 "and is of a supported\n"
10521 "format. See command line\n"
10522 "for hints in other error\n"
10523 "messages."); SUMA_RETURN(NOPE); }
10524 SUMA_SetParent_DsetToLoad(NULL); /* reset the parent surface flag */
10525
10526 if (LocalHead > 1) {
10527 char *si = NULL;
10528 si = SUMA_DsetInfo(dset, 0);
10529 fprintf( SUMA_STDERR,
10530 "%s:\n----------------dset loaded ----------\n%s\n",
10531 FuncName, si);
10532 SUMA_free(si); si = NULL;
10533 }
10534
10535 if (!SUMA_isGraphDset(dset)) { /* Non Graph, take care of parenting */
10536 if (!SO) {
10537 SUMA_S_Err("Cannot load dset without parent SO, purging.");
10538 SUMA_FreeDset(dset); dset=NULL; SUMA_RETURN(NOPE);
10539 }
10540 /* Check if the domain order is SO or not .
10541 If not specified, assign it */
10542 np = SDSET_IDMDOM(dset); if (np) lnp = strlen(np) ; else lnp = 0;
10543
10544 if (np && lnp) {
10545 SUMA_SL_Note("dset has a mesh parent, Checking relationship");
10546 if (!SUMA_isDsetRelated(dset, SO)) {
10547 if (SUMA_isEnv("SUMA_AlwaysAssignSurface","Y")) {
10548 SUMA_LH("Setting domain_parent_idcode to NULL!");
10549 NI_set_attribute(dset->ngr, "domain_parent_idcode", NULL);
10550 np = NULL; lnp = 0;
10551 } else {
10552 SUMA_SLP_Err("Dset not related to SO");
10553 SUMA_FreeDset(dset); dset=NULL;
10554 SUMA_RETURN(NOPE);
10555 }
10556 }
10557
10558 }
10559
10560 if (!np || lnp == 0) {
10561 SUMA_LH("dset has no mesh parent, assigning SO");
10562 if (!SUMA_OKassign(dset, SO)) {
10563 SUMA_SurfaceObject *SOldp = SUMA_findSOp_inDOv(
10564 SO->LocalDomainParentID,SUMAg_DOv, SUMAg_N_DOv);
10565 if (SOldp) {
10566 SUMA_SLP_Note( "Could not assign dset to SO.\n"
10567 "Trying to assign to domain parent.");
10568 if (!SUMA_OKassign(dset, SOldp)) {
10569 SUMA_SLP_Err( "Cannot assign dset to SO \n"
10570 "or its local domain parent");
10571 SUMA_FreeDset(dset); dset=NULL;
10572 SUMA_RETURN(NOPE);
10573 }
10574 /* from that point on, treat dset as if being loaded onto SOpar*/
10575 SO = SOldp;
10576 } else {
10577 SUMA_SLP_Err("Cannot assign dset to SO.");
10578 SUMA_FreeDset(dset); dset=NULL;
10579 SUMA_RETURN(NOPE);
10580 }
10581 }
10582 NI_set_attribute(dset->ngr,"domain_parent_idcode", SO->idcode_str);
10583 NI_set_attribute(dset->ngr,"geometry_parent_idcode", SO->idcode_str);
10584 if (LocalHead > 1) SUMA_ShowDset(dset, 0, NULL);
10585 } else {
10586 SUMA_S_Warn("Why are you here?");
10587 }
10588 }
10589
10590 /* add the dset to the list SUMAg_CF->DsetList*/
10591 dsetpre = dset;
10592 if (LocalHead) {
10593 fprintf( SUMA_STDERR,
10594 "%s: New dset (%s) has pointer %p\n",
10595 FuncName, SDSET_LABEL(dset), dset);
10596 }
10597 if (!SUMA_InsertDsetPointer( &dset, SUMAg_CF->DsetList,
10598 SUMAg_CF->Allow_Dset_Replace)) {
10599 SUMA_SLP_Err("Failed to add new dset to list");
10600 /* is there not a function to replace a dset yet? */
10601 SUMA_FreeDset(dset); dset = NULL;
10602 SUMA_RETURN(NOPE);
10603 }
10604 if (LocalHead) {
10605 fprintf( SUMA_STDERR,
10606 "%s: Now dset (%s) is pointer %p\n",
10607 FuncName, SDSET_LABEL(dset), dset);
10608 }
10609
10610 /* Does this dset have a built in colormap?
10611 If it does, then loadit into SCM */
10612 if (!SUMA_Insert_Cmap_of_Dset(dset)) {
10613 SUMA_S_Err("Failed to insert Cmap");
10614 SUMA_FreeDset(dset); dset = NULL;
10615 SUMA_RETURN(NOPE);
10616 }
10617
10618 if (!SUMA_isGraphDset(dset)) {
10619 if (SetupOverlay) {
10620 SUMA_LH("Setting up overlay");
10621 OverInd = -1;
10622 {
10623 if (dset != dsetpre) { /* dset was pre-existing in the list */
10624 if (LocalHead) {
10625 fprintf( SUMA_STDERR,
10626 "%s: Dset %s (%p) pre-existing, "
10627 "finding its pre-existing overlays.\n",
10628 FuncName, SDSET_LABEL(dset), dset);
10629 }
10630 if (!(colplanepre = SUMA_Fetch_OverlayPointerByDset (
10631 (SUMA_ALL_DO *)SO, dset, &OverInd))) {
10632 SUMA_SLP_Err("Failed to fetch existing dset's "
10633 "overlay pointer");
10634 SUMA_RETURN(NOPE);
10635 }
10636 /* have bias? REMOVE IT! */
10637 if (!SUMA_RemoveCoordBias(colplanepre)) {
10638 SUMA_SLP_Err("Failed to remove coord bias");
10639 SUMA_RETURN(NOPE);
10640 }
10641 /* have clusterize? Recompute */
10642 if (colplanepre->OptScl->Clusterize)
10643 colplanepre->OptScl->RecomputeClust = 1;
10644 OKdup = 1;
10645 } else { /* dset is considered new */
10646 SUMA_LH("New");
10647 colplanepre = NULL;
10648 /* The overlay index for that plane is SO->N_Overlays */
10649 OverInd = SO->N_Overlays;
10650 OKdup = 0;
10651 }
10652 /* set up the colormap for this dset */
10653 NewColPlane = SUMA_CreateOverlayPointer ( filename,
10654 dset, SO->idcode_str,
10655 colplanepre);
10656 if (!NewColPlane) {
10657 fprintf (SUMA_STDERR,
10658 "Error %s: Failed in SUMA_CreateOverlayPointer.\n",
10659 FuncName);
10660 SUMA_RETURN(NOPE);
10661 }
10662 if (SetupOverlay < 0) NewColPlane->isBackGrnd = YUP;
10663 else NewColPlane->isBackGrnd = NOPE;
10664
10665
10666 /* Add this plane to SO->Overlays */
10667 SUMA_LH("Adding new plane to SO->Overlays");
10668 if (!SUMA_AddNewPlane ((SUMA_ALL_DO *)SO, NewColPlane, SUMAg_DOv,
10669 SUMAg_N_DOv, OKdup)) {
10670 SUMA_SL_Err("Failed in SUMA_AddNewPlane");
10671 SUMA_FreeOverlayPointer(NewColPlane);
10672 if (!SUMA_DeleteDsetPointer(&dset, SUMAg_CF->DsetList)) {
10673 SUMA_S_Err("Failed to delete dset pointer");
10674 }
10675
10676 SUMA_RETURN(NOPE);
10677 }
10678 }
10679
10680 /* Match the old settings? */
10681 SUMA_LH("Settings");
10682 if (colplanepre == NewColPlane) { /* old col plane found for this dset*/
10683 /* Don't change settings. Before Aug 2012, it would reset as below */
10684 } else if (SO->SurfCont &&
10685 SUMA_PreserveOverlaySettings(SO->SurfCont->curColPlane,
10686 NewColPlane)) {
10687 /* attempt to preserve current situation */
10688 SUMA_OVERLAYS *settingPlane = NULL;
10689 settingPlane = SO->SurfCont->curColPlane;
10690 NewColPlane->GlobalOpacity = settingPlane->GlobalOpacity;
10691 NewColPlane->ShowMode = settingPlane->ShowMode;
10692 NewColPlane->OptScl->BrightFact = settingPlane->OptScl->BrightFact;
10693 NewColPlane->OptScl->find = settingPlane->OptScl->find;
10694 NewColPlane->OptScl->tind = settingPlane->OptScl->tind;
10695 NewColPlane->OptScl->bind = settingPlane->OptScl->bind;
10696 NewColPlane->OptScl->UseThr = settingPlane->OptScl->UseThr;
10697 NewColPlane->OptScl->UseBrt = settingPlane->OptScl->UseBrt;
10698 NewColPlane->OptScl->ThrMode = settingPlane->OptScl->ThrMode;
10699 NewColPlane->OptScl->ThreshRange[0] =
10700 settingPlane->OptScl->ThreshRange[0];
10701 NewColPlane->OptScl->ThreshRange[1] =
10702 settingPlane->OptScl->ThreshRange[1];
10703 NewColPlane->OptScl->BrightRange[0] =
10704 settingPlane->OptScl->BrightRange[0];
10705 NewColPlane->OptScl->BrightRange[1] =
10706 settingPlane->OptScl->BrightRange[1];
10707 NewColPlane->OptScl->BrightMap[0] =
10708 settingPlane->OptScl->BrightMap[0];
10709 NewColPlane->OptScl->BrightMap[1] =
10710 settingPlane->OptScl->BrightMap[1];
10711 NewColPlane->SymIrange = settingPlane->SymIrange;
10712 NewColPlane->OptScl->IntRange[0] = settingPlane->OptScl->IntRange[0];
10713 NewColPlane->OptScl->IntRange[1] = settingPlane->OptScl->IntRange[1];
10714 dsetcmap = NI_get_attribute(dset->ngr,"SRT_use_this_cmap");
10715 if (dsetcmap) {
10716 SUMA_STRING_REPLACE(NewColPlane->cmapname, dsetcmap);
10717 } else {
10718 SUMA_STRING_REPLACE(NewColPlane->cmapname,
10719 settingPlane->cmapname);
10720 }
10721 NewColPlane->OptScl->Clusterize = settingPlane->OptScl->Clusterize;
10722 NewColPlane->OptScl->ClustOpt->AreaLim =
10723 settingPlane->OptScl->ClustOpt->AreaLim;
10724 NewColPlane->OptScl->ClustOpt->DistLim =
10725 settingPlane->OptScl->ClustOpt->DistLim;
10726 } else {
10727 SUMA_LH("New settings");
10728 /* set the opacity, index column and the range */
10729 NewColPlane->GlobalOpacity = YUP;
10730 NewColPlane->ShowMode = SW_SurfCont_DsetViewCol;
10731 if (!colplanepre) {/* only set this if first time creating plane*/
10732 NewColPlane->OptScl->BrightFact = 0.8;
10733 }
10734 NewColPlane->OptScl->find = 0;
10735 NewColPlane->OptScl->tind = 0;
10736 NewColPlane->OptScl->bind = 0;
10737 SUMA_GetDsetColRange(dset, 0, NewColPlane->OptScl->IntRange, loc);
10738 if (NewColPlane->SymIrange) {
10739 NewColPlane->OptScl->IntRange[0] =
10740 -fabs(SUMA_MAX_PAIR( NewColPlane->OptScl->IntRange[0],
10741 NewColPlane->OptScl->IntRange[1]));
10742 NewColPlane->OptScl->IntRange[1] =
10743 -NewColPlane->OptScl->IntRange[0];
10744 }
10745
10746 /* stick a colormap onto that plane ? */
10747 dsetcmap = NI_get_attribute(dset->ngr,"SRT_use_this_cmap");
10748 if (dsetcmap) {
10749 SUMA_STRING_REPLACE(NewColPlane->cmapname, dsetcmap);
10750 } else {
10751 /* don't worry, there's a default one */
10752 }
10753 }
10754 if (NewColPlane->OptScl->Clusterize)
10755 NewColPlane->OptScl->RecomputeClust = 1;
10756 /* colorize the plane */
10757 SUMA_LH("Colorizing Plane");
10758 SUMA_ColorizePlane(NewColPlane);
10759
10760 /* SUMA_Show_ColorOverlayPlanes(&NewColPlane, 1, 1); */
10761
10762 /* set the new curColPlane to the newly loaded plane,
10763 you need to do this before you remix the colors in case
10764 you are only showing the curColPlane.
10765 curColPlane is normally set in SUMA_InitializeColPlaneShell
10766 but when SO->SurfCont->ShowCurForeOnly = YUP, curColPlane
10767 is used in the Remixedisplay function.
10768 NOTE: You can't call SUMA_InitializeColPlaneShell
10769 before remixing because colors are reported in Lbl block
10770 June 28 04*/
10771 if (SO->SurfCont && MakeOverlayCurrent)
10772 SO->SurfCont->curColPlane = SO->Overlays[OverInd];
10773 }
10774
10775 if (SO->SurfCont && LaunchDisplay) {
10776 SUMA_LHv("Remix Redisplay %s\n", SO->Label);
10777 /* remix-redisplay for surface */
10778 if (!SUMA_Remixedisplay ((SUMA_ALL_DO*)SO)) {
10779 SUMA_RETURN(NOPE);
10780 }
10781
10782 SUMA_LH("Refreshing Dset list");
10783 /*update the list widget if open */
10784 LW = SO->SurfCont->SwitchDsetlst;
10785 if (LW) {
10786 if (!LW->isShaded) SUMA_RefreshDsetList ((SUMA_ALL_DO *)SO);
10787 }
10788
10789 SUMA_LH("Refreshing sub-brick selectors");
10790 /* if lists for switching sub-bricks are not shaded, update them too */
10791 if (SO->SurfCont->SwitchIntMenu) {
10792 if ((LW = SO->SurfCont->SwitchIntMenu->lw) && !LW->isShaded) {
10793 SUMA_DsetColSelectList((SUMA_ALL_DO*)SO, 0, 0, 1);
10794 }
10795 if ((LW = SO->SurfCont->SwitchThrMenu->lw) && !LW->isShaded) {
10796 SUMA_DsetColSelectList((SUMA_ALL_DO*)SO, 1, 0, 1);
10797 }
10798 if ((LW = SO->SurfCont->SwitchBrtMenu->lw) && !LW->isShaded) {
10799 SUMA_DsetColSelectList((SUMA_ALL_DO*)SO, 2, 0, 1);
10800 }
10801
10802 if (LocalHead)
10803 fprintf (SUMA_STDERR,
10804 "%s: Updating Dset frame, OverInd=%d\n",
10805 FuncName, OverInd);
10806 /* update the Dset frame */
10807 if (OverInd >= 0)
10808 SUMA_InitializeColPlaneShell((SUMA_ALL_DO *)SO,
10809 SO->Overlays[OverInd]);
10810 }
10811 }
10812
10813 if (used_over) *used_over = SO->Overlays[OverInd];
10814 } else {
10815 SUMA_NGR_INDEX_HASH_DATUM *hd = NULL;
10816 NI_element *nel=NULL;
10817 NI_group *ngrnet=NULL, *nilink;
10818 int ip, ei;
10819 char *ss=NULL;
10820 SUMA_GRAPH_SAUX *GSaux=NULL;
10821 if (SetupOverlay) {
10822 SUMA_LH("Setting up overlay for GRAPH dset");
10823 OverInd = -1; /* OverInd is irrelvant,
10824 just one overlay per graph dset, at least for now */
10825 {
10826 if (dset != dsetpre) { /* dset was pre-existing in the list */
10827 if (!(GSaux = SDSET_GSAUX(dset))) {
10828 SUMA_S_Warn("That is weird, should this happen?");
10829 if (!SUMA_AddDsetSaux(dset)) {
10830 SUMA_S_Err("Failed to create Saux struct");
10831 SUMA_RETURN(NOPE);
10832 }
10833 GSaux = SDSET_GSAUX(dset);
10834 }
10835 if (LocalHead) {
10836 fprintf( SUMA_STDERR,
10837 "%s: Dset %s (%p) pre-existing, "
10838 "finding its pre-existing overlays.\n",
10839 FuncName, SDSET_LABEL(dset), dset);
10840 }
10841 colplanepre = SDSET_GOVERLAY(dset);
10842 OKdup = 1;
10843 } else { /* dset is considered new */
10844 colplanepre = NULL;
10845 if (!SUMA_AddDsetSaux(dset)) {
10846 SUMA_S_Err("Failed to create Saux struct");
10847 SUMA_RETURN(NOPE);
10848 }
10849 GSaux = SDSET_GSAUX(dset);
10850 OKdup = 0;
10851 }
10852
10853 /* set up the colormap for this dset */
10854 GSaux->Overlay = SUMA_CreateOverlayPointer ( filename,
10855 dset, SDSET_ID(dset),
10856 colplanepre);
10857 if (!GSaux->Overlay) {
10858 fprintf (SUMA_STDERR,
10859 "Error %s: Failed in SUMA_CreateOverlayPointer.\n",
10860 FuncName);
10861 SUMA_RETURN(NOPE);
10862 }
10863
10864 /* setup hash table for attaching explicit tracts to certain segs */
10865 /* find a network element */
10866 /* First search for an element in the dataset */
10867 if (!(GSaux->net =
10868 (NI_group *)SUMA_FindNgrNamedAny(dset->ngr, "network"))) {
10869 /* Otherwise try for a file link */
10870 nilink =
10871 (NI_group *)SUMA_FindNgrNamedAny(dset->ngr, "network_link");
10872 if (nilink) {
10873 ss = find_afni_file(
10874 NI_get_attribute(nilink,"network_file"), 1,
10875 SUMA_FnameGet(SDSET_FILENAME(dset),"pa",NULL));
10876 if (ss[0] != '\0') {
10877 SUMA_LHv("Reading network from %s\n", ss);
10878 NEL_READ(GSaux->net, ss);
10879 if (strcmp(GSaux->net->name,"network")) {
10880 SUMA_S_Errv("Network link file does not contain network"
10881 "group. Got me %s instead.\n",
10882 GSaux->net->name);
10883 NI_free_element(GSaux->net); GSaux->net = NULL;
10884 }
10885 } else {
10886 if (ss=NI_get_attribute(nilink,"network_file")) {
10887 SUMA_S_Errv(
10888 "Could not find network_file \"%s\" "
10889 "on disk for dset %s\n", ss, SDSET_FILENAME(dset));
10890 } else {
10891 SUMA_S_Err("Could not find network_file attribute "
10892 "in network_link");
10893 }
10894 }
10895 }
10896 }
10897 if (GSaux->net) ngrnet = GSaux->net;
10898 else ngrnet = dset->ngr; /* old defunct style */
10899 for (ip=0; ip<ngrnet->part_num; ++ip) {
10900 switch( ngrnet->part_typ[ip] ){
10901 case NI_GROUP_TYPE:
10902 break ;
10903 case NI_ELEMENT_TYPE:
10904 nel = (NI_element *)ngrnet->part[ip] ;
10905 if (!strcmp(nel->name, "tracts")) {
10906 if (nel->vec_typ[0] != get_NI_tract_type()) {
10907 SUMA_S_Errv("Bad vec_type, have %d, expected %d\n",
10908 nel->vec_typ[0], get_NI_tract_type());
10909 } else {
10910 NI_GET_INT(nel, "Bundle_Tag", ei);
10911 if (NI_GOT) {
10912 hd = (SUMA_NGR_INDEX_HASH_DATUM *)
10913 SUMA_calloc(1, sizeof(SUMA_COLOR_MAP_HASH_DATUM));
10914 hd->id = ei;
10915 hd->ngrindex = ip;
10916 HASH_ADD_INT(GSaux->thd, id, hd);
10917 } else {
10918 SUMA_S_Warn("Loose tracts element in dataset");
10919 }
10920 NI_GET_INT(nel, "Bundle_Alt_Tag", ei);
10921 if (NI_GOT) {
10922 hd = (SUMA_NGR_INDEX_HASH_DATUM *)
10923 SUMA_calloc(1, sizeof(SUMA_COLOR_MAP_HASH_DATUM));
10924 hd->id = ei;
10925 hd->ngrindex = ip;
10926 HASH_ADD_INT(GSaux->thd, id, hd);
10927 }
10928 }
10929 }
10930 break;
10931 default:
10932 break;
10933 }
10934 }
10935
10936 }
10937
10938 /* Match the old settings? */
10939 if (colplanepre == GSaux->Overlay) { /* old col plane found */
10940 /* Don't change settings. */
10941 } else if (0) {
10942 /* This block would parallel what is after function
10943 call SUMA_PreserveOverlaySettings() above
10944 For now there is no 'curColPlane' for graph datasets */
10945 /* attempt to preserve current situation */
10946 SUMA_OVERLAYS *settingPlane = NULL;
10947 GSaux->Overlay->GlobalOpacity = settingPlane->GlobalOpacity;
10948 GSaux->Overlay->ShowMode = settingPlane->ShowMode;
10949 GSaux->Overlay->OptScl->BrightFact =
10950 settingPlane->OptScl->BrightFact;
10951 GSaux->Overlay->OptScl->find = settingPlane->OptScl->find;
10952 GSaux->Overlay->OptScl->tind = settingPlane->OptScl->tind;
10953 GSaux->Overlay->OptScl->bind = settingPlane->OptScl->bind;
10954 GSaux->Overlay->OptScl->UseThr = settingPlane->OptScl->UseThr;
10955 GSaux->Overlay->OptScl->UseBrt = settingPlane->OptScl->UseBrt;
10956 GSaux->Overlay->OptScl->ThrMode = settingPlane->OptScl->ThrMode;
10957 GSaux->Overlay->OptScl->ThreshRange[0] =
10958 settingPlane->OptScl->ThreshRange[0];
10959 GSaux->Overlay->OptScl->ThreshRange[1] =
10960 settingPlane->OptScl->ThreshRange[1];
10961 GSaux->Overlay->OptScl->BrightRange[0] =
10962 settingPlane->OptScl->BrightRange[0];
10963 GSaux->Overlay->OptScl->BrightRange[1] =
10964 settingPlane->OptScl->BrightRange[1];
10965 GSaux->Overlay->OptScl->BrightMap[0] =
10966 settingPlane->OptScl->BrightMap[0];
10967 GSaux->Overlay->OptScl->BrightMap[1] =
10968 settingPlane->OptScl->BrightMap[1];
10969 GSaux->Overlay->SymIrange = settingPlane->SymIrange;
10970 GSaux->Overlay->OptScl->IntRange[0] =
10971 settingPlane->OptScl->IntRange[0];
10972 GSaux->Overlay->OptScl->IntRange[1] =
10973 settingPlane->OptScl->IntRange[1];
10974 dsetcmap = NI_get_attribute(dset->ngr,"SRT_use_this_cmap");
10975 if (dsetcmap) {
10976 SUMA_STRING_REPLACE(GSaux->Overlay->cmapname, dsetcmap);
10977 } else {
10978 SUMA_STRING_REPLACE(GSaux->Overlay->cmapname,
10979 settingPlane->cmapname);
10980 }
10981 GSaux->Overlay->OptScl->Clusterize =
10982 settingPlane->OptScl->Clusterize;
10983 GSaux->Overlay->OptScl->ClustOpt->AreaLim =
10984 settingPlane->OptScl->ClustOpt->AreaLim;
10985 GSaux->Overlay->OptScl->ClustOpt->DistLim =
10986 settingPlane->OptScl->ClustOpt->DistLim;
10987 } else {
10988 /* set the opacity, index column and the range */
10989 GSaux->Overlay->GlobalOpacity = YUP;
10990 GSaux->Overlay->ShowMode = SW_SurfCont_DsetViewCol;
10991 if (!colplanepre) {/* only set this if first time creating plane*/
10992 GSaux->Overlay->OptScl->BrightFact = 0.8;
10993 }
10994 GSaux->Overlay->OptScl->find = 0;
10995 GSaux->Overlay->OptScl->tind = 0;
10996 GSaux->Overlay->OptScl->bind = 0;
10997 SUMA_GetDsetColRange(dset, 0, GSaux->Overlay->OptScl->IntRange, loc);
10998 if (GSaux->Overlay->SymIrange) {
10999 GSaux->Overlay->OptScl->IntRange[0] =
11000 -fabs(SUMA_MAX_PAIR( GSaux->Overlay->OptScl->IntRange[0],
11001 GSaux->Overlay->OptScl->IntRange[1]));
11002 GSaux->Overlay->OptScl->IntRange[1] =
11003 -GSaux->Overlay->OptScl->IntRange[0];
11004 }
11005
11006 /* stick a colormap onto that plane ? */
11007 dsetcmap = NI_get_attribute(dset->ngr,"SRT_use_this_cmap");
11008 if (dsetcmap) {
11009 SUMA_STRING_REPLACE(GSaux->Overlay->cmapname, dsetcmap);
11010 } else {
11011 /* don't worry, there's a default one */
11012 }
11013 }
11014 if (GSaux->Overlay->OptScl->Clusterize)
11015 GSaux->Overlay->OptScl->RecomputeClust = 1;
11016 /* colorize the plane */
11017 SUMA_LH("Colorizing Plane");
11018 SUMA_ColorizePlane(GSaux->Overlay);
11019
11020 if (LocalHead > 1) {
11021 SUMA_Show_ColorOverlayPlanes(&GSaux->Overlay, 1, 1);
11022 }
11023 }
11024 /* initialize matrix shape info */
11025 if (dset->Aux->matrix_shape == MAT_HEEHAW) {
11026 SUMA_GDSET_Set_Aux_matrix_shape(dset);
11027 }
11028 /* This is where you add the business about the DOs*/
11029 if (!SUMA_CreateGraphDOs(dset)) {
11030 SUMA_S_Err("Failed to create DOs for graph dset");
11031 SUMA_RETURN(NOPE);
11032 }
11033 /* register them with this viewer */
11034 if (!SUMA_RegisterGraphDOs(dset,NULL)) {
11035 SUMA_S_Err("Failed to register graph DO with all viewers ");
11036 SUMA_RETURN(NOPE);
11037 }
11038 if (LaunchDisplay) {
11039 if (!(GSaux = SDSET_GSAUX(dset))) {
11040 SUMA_S_Err("Come on now, should have GSaux by now!");
11041 SUMA_RETURN(NOPE);
11042 }
11043
11044 SUMA_LHv("Remix Redisplay %s (id %s) (dset %p)\n",
11045 SDSET_LABEL(dset), SDSET_ID(dset), dset);
11046 /* remix-redisplay for surface */
11047 if (!SUMA_Remixedisplay((SUMA_ALL_DO*)dset)) {
11048 SUMA_RETURN(NOPE);
11049 }
11050
11051 SUMA_LH("Refreshing sub-brick selectors");
11052 /* if lists for switching sub-bricks are not shaded, update them too */
11053 if (GSaux->DOCont->SwitchIntMenu) {
11054 if ((LW = GSaux->DOCont->SwitchIntMenu->lw) && !LW->isShaded) {
11055 SUMA_DsetColSelectList((SUMA_ALL_DO *)dset, 0, 0, 1);
11056 }
11057 if ((LW = GSaux->DOCont->SwitchThrMenu->lw) && !LW->isShaded) {
11058 SUMA_DsetColSelectList((SUMA_ALL_DO *)dset, 1, 0, 1);
11059 }
11060 if ((LW = GSaux->DOCont->SwitchBrtMenu->lw) && !LW->isShaded) {
11061 SUMA_DsetColSelectList((SUMA_ALL_DO *)dset, 2, 0, 1);
11062 }
11063
11064 SUMA_LH("Updating Dset frame");
11065 /* update the Dset frame */
11066 SUMA_InitializeColPlaneShell((SUMA_ALL_DO *)dset,
11067 SUMA_ADO_Overlay0((SUMA_ALL_DO *)dset));
11068 }
11069 }
11070
11071 }
11072 SUMA_RETURN(YUP);
11073 }
11074
11075 /*!
11076 \brief Loads a color plane file and adds it to a surface's list of colorplanes
11077
11078 \param dlg (SUMA_SELECTION_DIALOG_STRUCT *) struture from selection dialogue
11079 */
SUMA_LoadColorPlaneFile(char * filename,void * data)11080 void SUMA_LoadColorPlaneFile (char *filename, void *data)
11081 {
11082 static char FuncName[]={"SUMA_LoadColorPlaneFile"};
11083 SUMA_SurfaceObject *SO = NULL;
11084 SUMA_OVERLAY_PLANE_DATA sopd;
11085 SUMA_IRGB *irgb=NULL;
11086 int OverInd = -1;
11087 DList *list=NULL;
11088 SUMA_LIST_WIDGET *LW=NULL;
11089 SUMA_Boolean LocalHead = NOPE;
11090
11091 SUMA_ENTRY;
11092
11093 // fprintf(stderr, "%s\n", FuncName);
11094
11095 if (!data) {
11096 SUMA_SLP_Err("Null data");
11097 SUMA_RETURNe;
11098 }
11099
11100 SO = (SUMA_SurfaceObject *)data;
11101
11102 if (LocalHead) {
11103 fprintf (SUMA_STDERR,
11104 "%s: Received request to load %s for surface %s.\n",
11105 FuncName, filename, SO->Label);
11106 }
11107
11108 /* find out if file exists and how many values it contains */
11109 if (!SUMA_filexists(filename)) {
11110 SUMA_SLP_Err("File not found");
11111 SUMA_RETURNe;
11112 }
11113
11114 irgb = SUMA_Read_IRGB_file(filename);
11115 if (!irgb) {
11116 SUMA_SLP_Err("Failed to read file.");
11117 SUMA_RETURNe;
11118 }
11119
11120 memset(&sopd, 0, sizeof(SUMA_OVERLAY_PLANE_DATA));
11121 sopd.N = irgb->N;
11122 sopd.Type = SOPT_ifff;
11123 sopd.Source = SES_Suma;
11124 sopd.GlobalOpacity = 0.3;
11125 sopd.isBackGrnd = NOPE;
11126 sopd.Show = YUP;
11127 sopd.dtlvl = SUMA_ELEM_DAT;
11128 /* dim colors from maximum intensity to preserve surface shape
11129 highlights, division by 255 is to scale color values between 1 and 0 */
11130 sopd.DimFact = 0.5;
11131 sopd.i = (void *)irgb->i;
11132 sopd.r = (void *)irgb->r;
11133 sopd.g = (void *)irgb->g;
11134 sopd.b = (void *)irgb->b;
11135 sopd.a = NULL;
11136
11137 if (!SUMA_iRGB_to_OverlayPointer ( (SUMA_ALL_DO *)SO,
11138 filename, &sopd, &OverInd,
11139 SUMAg_DOv, SUMAg_N_DOv,
11140 SUMAg_CF->DsetList)) {
11141 SUMA_SLP_Err("Failed to fetch or create overlay pointer.");
11142 SUMA_RETURNe;
11143 }
11144
11145 /* values were copied, dump structure */
11146 irgb = SUMA_Free_IRGB(irgb);
11147
11148 /* See note before similar line in SUMA_LoadDsetOntoSO */
11149 SO->SurfCont->curColPlane = SO->Overlays[OverInd];
11150
11151 if (!SUMA_Remixedisplay ((SUMA_ALL_DO*)SO)) {
11152 SUMA_RETURNe;
11153 }
11154
11155 SUMA_LH("Refreshing color plane list");
11156 /*update the list widget if open */
11157 LW = SO->SurfCont->SwitchDsetlst;
11158 if (LW) {
11159 if (!LW->isShaded) SUMA_RefreshDsetList ((SUMA_ALL_DO *)SO);
11160 }
11161
11162 if (LocalHead)
11163 fprintf (SUMA_STDERR,
11164 "%s: Updating color plane frame, OverInd=%d\n",
11165 FuncName, OverInd);
11166 /* update the color plane frame */
11167 if (OverInd >= 0)
11168 SUMA_InitializeColPlaneShell((SUMA_ALL_DO *)SO, SO->Overlays[OverInd]);
11169
11170 SUMA_RETURNe;
11171 }
11172
11173 /*!
11174 Decide whether or not to keep Rick Reynolds happy and preserve
11175 the overlay settings for a newly loaded dset
11176 */
SUMA_PreserveOverlaySettings(SUMA_OVERLAYS * colplanepre,SUMA_OVERLAYS * NewColPlane)11177 SUMA_Boolean SUMA_PreserveOverlaySettings(SUMA_OVERLAYS *colplanepre,
11178 SUMA_OVERLAYS *NewColPlane)
11179 {
11180 static char FuncName[]={"SUMA_PreserveOverlaySettings"};
11181 SUMA_Boolean LocalHead = NOPE;
11182
11183 SUMA_ENTRY;
11184
11185 // fprintf(stderr, "%s\n", FuncName);
11186
11187 if (!colplanepre || !NewColPlane) SUMA_RETURN(NOPE);
11188 if (colplanepre == NewColPlane) SUMA_RETURN(YUP); /* happens in reload */
11189
11190 if (!colplanepre->dset_link || !NewColPlane->dset_link) SUMA_RETURN(NOPE);
11191
11192
11193 /* Now check the sub-brick types. They should all match */
11194 if (SUMA_isSameDsetColTypes(NewColPlane->dset_link, colplanepre->dset_link))
11195 SUMA_RETURN(YUP);
11196
11197 SUMA_RETURN(NOPE);
11198 }
11199
11200 /*** AFNI setup functions taken and trimmed from afni_setup.c
11201 Reason for duplicating the functions is the complicated dependencies
11202 of some functions in afni_setup */
11203 /*-----------------------------------------------------------------
11204 Process an AFNI setup file.
11205 -------------------------------------------------------------*/
11206
11207 #define SUMA_ISTARRED(s) ( (s)[0]=='*' && (s)[1]=='*' && (s)[2]=='*' )
11208
11209 #define SUMA_EOLSKIP \
11210 do{ for( ; fptr[0] != '\n' && fptr[0] != '\0' ; fptr++ ) ; /* nada */ \
11211 if( fptr[0] == '\0' ){ if (fbuf) free(fbuf) ; fbuf = NULL; goto donesection; } \
11212 fptr++ ; } while(0)
11213
11214 #define SUMA_GETSSS \
11215 do{ int nu=0,qq; \
11216 if( fptr-fbuf >= nbuf || fptr[0] == '\0' ){ if (fbuf) free(fbuf); fbuf = NULL; goto donesection; } \
11217 str[0]='\0'; qq=sscanf(fptr,"%127s%n",str,&nu); nused+=nu;fptr+=nu; \
11218 if( str[0]=='\0' || qq==0 || nu==0 ){ if (fbuf) free(fbuf); fbuf = NULL; goto donesection; } \
11219 } while(0)
11220
11221 #define SUMA_GETSTR \
11222 do{ SUMA_GETSSS ; \
11223 while(str[0]=='!' || (str[0]=='/' && str[1]=='/')){SUMA_EOLSKIP; SUMA_GETSSS;} \
11224 } while(0)
11225
11226 #define SUMA_GETEQN \
11227 do{ SUMA_GETSTR ; if(SUMA_ISTARRED(str)) goto SkipSection ; \
11228 strcpy(left,str) ; \
11229 SUMA_GETSTR ; if(SUMA_ISTARRED(str)) goto SkipSection ; \
11230 strcpy(middle,str) ; \
11231 SUMA_GETSTR ; if(SUMA_ISTARRED(str)) goto SkipSection ; \
11232 strcpy(right,str) ; } while(0)
11233
11234 #define SUMA_NSBUF 256
11235
11236 /*!
11237 \brief Extracts colors and colormaps from AFNI formatted .pal files
11238 Also used to extract such info from .afnirc file
11239
11240 \param fname (char *) name of file containing colors.
11241 either .afnirc or a .pal file
11242 \param SAC (SUMA_AFNI_COLORS *) pointer to structure that will contain
11243 the default afni colors and colormaps.
11244 This structure must have been previously initialized
11245 in SUMA_Get_AFNI_Default_Color_Maps which also
11246 automatically scans ~/.afnirc then ./afnirc if the former
11247 one was not found.
11248 \return N_palsRead (int) number of palettes found and read
11249 -1 if trouble reading at least one of the palettes
11250
11251 */
SUMA_AFNI_Extract_Colors(char * fname,SUMA_AFNI_COLORS * SAC)11252 int SUMA_AFNI_Extract_Colors ( char *fname, SUMA_AFNI_COLORS *SAC )
11253 {
11254 static char FuncName[]={"SUMA_AFNI_Extract_Colors"};
11255 int nbuf , nused , ii, ngood = -1;
11256 float rgb[3]={0.0, 0.0, 0.0};
11257 char * fbuf , * fptr ;
11258 char str[SUMA_NSBUF]="\0" , left[SUMA_NSBUF]="\0" ,
11259 middle[SUMA_NSBUF]="\0" , right[SUMA_NSBUF]="\0" ;
11260 SUMA_STRING *SS = NULL;
11261 SUMA_COLOR_MAP *CM=NULL;
11262 SUMA_Boolean LocalHead = NOPE;
11263
11264 SUMA_ENTRY;
11265
11266 // fprintf(stderr, "%s\n", FuncName);
11267
11268 fbuf = AFNI_suck_file( fname ) ; if( fbuf == NULL ) {
11269 SUMA_SL_Warn("File could not be read");
11270 SUMA_RETURN(-1) ; }
11271 nbuf = strlen(fbuf) ; if( nbuf == 0 ) {
11272 SUMA_SL_Warn("Empty file");
11273 SUMA_RETURN(-1) ; }
11274
11275 fptr = fbuf ; nused = 0 ;
11276
11277 /** scan for section strings, which start with "***" **/
11278 ngood = 0; /* assume none will be found */
11279
11280 str[0] = '\0' ; /* initialize string */
11281
11282 if(LocalHead) {
11283 fprintf(SUMA_STDERR,"Reading AFNI setup file = %s (%d bytes)",fname,nbuf) ;
11284 }
11285
11286 while( nused < nbuf ){
11287
11288 /**----------------------------------**/
11289 /**-- skip ahead to next section keyword --**/
11290
11291 SkipSection: while( ! SUMA_ISTARRED(str) ){
11292 SUMA_GETSTR; SUMA_LH("%s",str);}
11293
11294 /*- 04 Jun 1999 -*/
11295
11296 if( strcmp(str, "***COLORS") != 0 && strcmp(str, "***PALETTES") != 0){
11297 SUMA_GETSTR ;
11298 goto SkipSection ;
11299 }
11300
11301
11302 SS = SUMA_StringAppend (NULL, NULL);
11303
11304 /**--------------------**/
11305 /**-- COLORS section --**/
11306
11307 if( strcmp(str,"***COLORS") == 0 ){
11308 char label[SUMA_NSBUF]="\0" , defn[SUMA_NSBUF]="\0" ;
11309
11310 if (LocalHead) fprintf (SUMA_STDERR,"%s: Found ***COLORS\n", FuncName);
11311 while(1){ /* loop, looking for 'label = color' */
11312 SUMA_GETEQN ;
11313
11314 if (LocalHead) {
11315 fprintf (SUMA_STDERR,"\t %s%s%s\n", left, middle, right);
11316 }
11317
11318
11319
11320 if( !THD_filename_pure(left) ) continue ;
11321 /* don't allow 'none' to be redefined! */
11322 if( strcmp(left,"none")==0 || strcmp(right,"none")==0 ) {
11323 sprintf(left,"none");
11324 rgb[0] = rgb[1] = rgb[2] =-1.0;
11325 } else {
11326 if (!SUMA_Interpret_AFNIColor (right, rgb)) {
11327 fprintf( SUMA_STDERR,
11328 "Error %s: Failed to interpret color %s\n",
11329 FuncName, right);
11330 SUMA_RETURN(-1);
11331 }
11332 }
11333 SAC->Cv = SUMA_Add_Color (left,
11334 rgb[0], rgb[1], rgb[2], 1.0,
11335 SAC->Cv, &(SAC->N_cols));
11336 }
11337 continue ; /* skip to end of outer while loop */
11338 } /* end of COLORS */
11339 #if 0
11340 /* causes crash on Fedora Core 7 and core 6, not worth it */
11341 SUMA_Interpret_AFNIColor (NULL, rgb);
11342 #endif
11343
11344 /**----------------------**/
11345 /**-- PALETTES section --**/
11346
11347 if( strcmp(str,"***PALETTES") == 0 ){ /* loop, looking for palettes */
11348 char label[SUMA_NSBUF] = "NoThing" , ccc , * cpt ;
11349 PBAR_palette_array * ppar=NULL ;
11350 PBAR_palette ** ppp ;
11351 PBAR_palette * ppnew ;
11352 int npane , pmode , icol=0 , jj ;
11353 float val ;
11354
11355 if (LocalHead) fprintf (SUMA_STDERR,"enter ***PALETTES\n");
11356
11357 /* loop, looking for palettes */
11358
11359 while(1){
11360 SUMA_GETSTR ; if( SUMA_ISTARRED(str) ) goto SkipSection ;
11361 if( fptr-fbuf >= nbuf ){
11362 if (fbuf) free(fbuf) ; fbuf = NULL; SUMA_RETURN(-1) ;
11363 }
11364
11365 if( str[0] != '[' ){ /* found a palette label */
11366 strcpy(label,str) ;
11367 if( !THD_filename_ok(label) ){
11368 fprintf( SUMA_STDERR,
11369 "Error %s: In setup file %s, bad palette label: %s.\n"
11370 " Ignoring palette.\n",
11371 FuncName, fname,label) ;
11372 if (fbuf) free(fbuf) ; fbuf = NULL;
11373 SUMA_RETURN(-1) ;
11374 }
11375
11376 if (LocalHead) {
11377 fprintf (SUMA_STDERR,
11378 "%s: found palette label=%s. [len=%d label[0]=%d]\n"
11379 "nbuf=%d fptr-fbuf=%ld\n",
11380 FuncName, label,(int)strlen(label),(int)label[0],
11381 nbuf, (long int)(fptr-fbuf));
11382 }
11383
11384
11385
11386 SUMA_GETSTR ; if( SUMA_ISTARRED(str) ) goto SkipSection ;
11387 }
11388
11389
11390 if( str[0] != '[' ){ /* bad news! */
11391 fprintf(SUMA_STDERR,
11392 "Error %s: In setup file %s, expected palette "
11393 "'[n]' here: %s.\n",
11394 FuncName, fname , str ) ;
11395 SUMA_RETURN(-1) ;
11396 }
11397
11398 /* decide how big the new palette is to be, and what mode */
11399 ii = sscanf( str , "[%d%c" , &npane , &ccc ) ;
11400 if( ii < 2 ){
11401 fprintf( SUMA_STDERR,
11402 "%s: In setup file %s, can't interpret palette %s\n",
11403 FuncName, fname , str ) ;
11404 SUMA_RETURN(-1) ;
11405 } else if( npane < NPANE_MIN || npane > NPANE_MAX ){
11406 fprintf(SUMA_STDERR,
11407 "%s: In setup file %s, illegal palette count %s.\n",
11408 FuncName, fname , str ) ;
11409 SUMA_RETURN(-1) ;
11410 }
11411
11412 /* at this point, now loop to read parameters for new palette */
11413 if (LocalHead) {
11414 fprintf( SUMA_STDERR,
11415 "%s: About to read %d panes.\n",
11416 FuncName, npane);
11417 }
11418
11419 /* prepare the colormap */
11420 CM = (SUMA_COLOR_MAP *)SUMA_calloc(1,sizeof(SUMA_COLOR_MAP));
11421 if (CM == NULL) {
11422 SUMA_SL_Crit ("Failed to allocate for CM");
11423 SUMA_RETURN(-1);
11424 }
11425 CM->idvec = NULL;
11426 CM->chd = NULL;
11427 CM->top_frac = 0.0f;
11428 CM->SO = NULL;
11429 CM->N_M[0] = npane; CM->N_M[1] = 4;
11430 CM->cname = NULL;
11431
11432 if (ccc == '+') CM->Sgn = 1;
11433 else CM->Sgn = -1;
11434
11435
11436 CM->Name = (char *)SUMA_calloc(strlen(label)+10, sizeof(char));
11437 CM->frac = (float *)SUMA_calloc(CM->N_M[0], sizeof(float));
11438 CM->M = (float**)
11439 SUMA_allocate2D (CM->N_M[0], CM->N_M[1], sizeof(float));
11440 if ( CM->frac == NULL || CM->M == NULL || CM->Name == NULL ) {
11441 SUMA_SL_Crit ("Failed to allocate for fields of CM.");
11442 SUMA_RETURN (-1);
11443 }
11444 if (CM->Sgn == 1) sprintf(CM->Name, "%s_p%d", label, CM->N_M[0]);
11445 else sprintf(CM->Name, "%s_n%d", label, CM->N_M[0]);
11446
11447 for( ii=0 ; ii < npane ; ii++ ){
11448 SUMA_GETEQN ;
11449
11450 if (LocalHead) {
11451 fprintf(SUMA_STDERR,
11452 "%s: SUMA_GETEQN: %s %s %s\n",
11453 FuncName, left,middle,right) ;
11454 }
11455
11456 /* find that color */
11457 icol = SUMA_Find_Color (right, SAC->Cv, SAC->N_cols);
11458 if (icol < 0) {
11459 fprintf( SUMA_STDERR,
11460 "Error %s: Color %s not found in dbase.\n"
11461 "Using no-color in its place\n", FuncName, right);
11462 #if 0
11463 CM->M[ii][0] =
11464 CM->M[ii][1] =
11465 CM->M[ii][2] = -1.0;
11466 CM->M[ii][3] = 0.0;
11467 } else {
11468 CM->M[ii][0] = SAC->Cv[icol].r;
11469 CM->M[ii][1] = SAC->Cv[icol].g;
11470 CM->M[ii][2] = SAC->Cv[icol].b;
11471 CM->M[ii][3] = 1.0;
11472 }
11473 CM->frac[ii] = atof(left);
11474 #endif
11475
11476 CM->M[npane - ii - 1][0] =
11477 CM->M[npane - ii - 1][1] =
11478 CM->M[npane - ii - 1][2] = -1.0;
11479 CM->M[npane - ii - 1][3] = 0.0;
11480 } else {
11481 CM->M[npane - ii - 1][0] = SAC->Cv[icol].r;
11482 CM->M[npane - ii - 1][1] = SAC->Cv[icol].g;
11483 CM->M[npane - ii - 1][2] = SAC->Cv[icol].b;
11484 CM->M[npane - ii - 1][3] = 1.0;
11485 }
11486 CM->frac[npane - ii - 1] = atof(left);
11487 }
11488
11489
11490 if (CM->frac[CM->N_M[0]-1] != 1.0f) {
11491 CM->top_frac = CM->frac[CM->N_M[0]-1];
11492 }
11493
11494 CM->M0[0] = CM->M[0][0];
11495 CM->M0[1] = CM->M[0][1];
11496 CM->M0[2] = CM->M[0][2];
11497 CM->M0[3] = CM->M[0][3];
11498
11499 /* add the map to the list */
11500 SAC->CMv = SUMA_Add_ColorMap (CM, SAC->CMv, &(SAC->N_maps));
11501 if (SAC->CMv) ++ngood;
11502 continue ; /* to end of outer while */
11503 }
11504 } /* end of PALETTES */
11505 SUMA_GETSTR ; goto SkipSection ; /* find another section */
11506
11507 } /* end of while loop */
11508
11509 donesection:
11510
11511 if (LocalHead) fprintf(SUMA_STDERR,"%s: Returning\n", FuncName);
11512 if (fbuf) free(fbuf) ;
11513 SUMA_RETURN (ngood);
11514
11515 }
11516
11517
11518 /*!
11519 \brief turns a color defined by it's Xname or AFNI Hex formulation
11520 into good old RGB
11521
11522 - The function is not particularly efficient for parsing numerous
11523 Xnamed colors...
11524 */
SUMA_Interpret_AFNIColor(char * Name,float RGB[3])11525 SUMA_Boolean SUMA_Interpret_AFNIColor (char *Name, float RGB[3])
11526 {
11527 static char FuncName[]={"SUMA_Interpret_AFNIColor"};
11528 char *vargv[1]={ "SCALE_TO_MAP" };
11529 int cargc = 1;
11530 int r=0, g=0, b=0;
11531 char stmp[10]="\0";
11532 XVisualInfo *vislist=NULL;
11533 static XtAppContext *app=NULL;
11534 static Widget tl=NULL;
11535 static Display *dpy=NULL;
11536 XColor *color_exact=NULL;
11537 static Colormap cmap;
11538 static int iwarn = 0;
11539 SUMA_Boolean LocalHead = NOPE;
11540
11541 SUMA_ENTRY;
11542
11543 // fprintf(stderr, "%s\n", FuncName);
11544
11545 if (!app) {
11546 app = (XtAppContext *)XtCalloc(1, sizeof(XtAppContext));
11547 memset(app, 0, sizeof(XtAppContext));
11548 }
11549 color_exact = (XColor*)XtCalloc(1, sizeof(XColor));
11550 memset(color_exact, 0, sizeof(XColor));
11551
11552 if (!Name) {
11553 /* cleanup */
11554 if (tl && dpy) {
11555 SUMA_LH("Cleanup");
11556 XFreeColormap(dpy, cmap);
11557 /* These 2 lines cause a crash on Fedora Core 4,
11558 but Core 4 crashes at XmCreateMainWindow anyway so we're doomed.*/
11559 XtDestroyWidget(tl);
11560 XtDestroyApplicationContext(*app);
11561 tl = NULL;
11562 dpy = NULL;
11563 }
11564 SUMA_RETURN (YUP);
11565 }
11566
11567 if (Name[0] == '#') { /* explicitly defined */
11568 SUMA_LHv("Explicit %s\n", Name);
11569 sprintf(stmp,"0x%c%c", Name[1], Name[2]);
11570 sscanf (stmp, "%x", &r);
11571 sprintf(stmp,"0x%c%c", Name[3], Name[4]);
11572 sscanf (stmp, "%x", &g);
11573 sprintf(stmp,"0x%c%c", Name[5], Name[6]);
11574 sscanf (stmp, "%x", &b);
11575 RGB[0] = (float)r/255.0;
11576 RGB[1] = (float)g/255.0;
11577 RGB[2] = (float)b/255.0;
11578
11579 } else { /* named */
11580 /* XtAppInitialize (at least on mac osx) forces the application
11581 to quit if display cannot be opened
11582 So you must decide ahead of time whether to call it or not! */
11583 if (SUMAg_CF->isGraphical) {
11584 SUMA_LHv("Graphical, named %s\n", Name);
11585 if (!tl) {
11586 SUMA_LH("tl init\n");
11587 /* tl = XtAppInitialize(app, "ScaleToMap", NULL, 0, &cargc, vargv,
11588 SUMA_get_fallbackResources(), NULL, 0);
11589 Superseded by XtOpenApplication */
11590
11591 tl = XtOpenApplication( app, "ScaleToMap", NULL,
11592 0, &cargc, vargv,
11593 SUMA_get_fallbackResources(),
11594 topLevelShellWidgetClass,
11595 NULL, 0);
11596
11597 dpy = XtDisplay(tl);
11598 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
11599 }
11600
11601
11602 XParseColor(dpy, cmap, Name, color_exact);
11603
11604 /* You need to divide by color_exact.red ,green and blue by 257
11605 to bring the numbers in the 0..255 range as listed in the
11606 rgb.txt file */
11607 RGB[0] = (float)color_exact->red/255.0/257.0;
11608 RGB[1] = (float)color_exact->green/255.0/257.0;
11609 RGB[2] = (float)color_exact->blue/255.0/257.0;
11610 } else {
11611 SUMA_LH("Not graphical");
11612 if (0 && (LocalHead || !(iwarn % 10))) {
11613 fprintf(SUMA_STDERR,
11614 "%s: \n"
11615 "Xcolor %s cannot be resolved without \n"
11616 "trying to open X display.\n"
11617 "Returning color of %f %f %f.\n",
11618 FuncName, Name,
11619 SUMA_DUNNO_GRAY, SUMA_DUNNO_GRAY, SUMA_DUNNO_GRAY);
11620 iwarn = 0;
11621 }
11622 ++iwarn;
11623 RGB[0] = RGB[1] = RGB[2] = SUMA_DUNNO_GRAY;
11624 }
11625 }
11626
11627 if (color_exact) XtFree((char *)color_exact); color_exact=NULL;
11628
11629 if (LocalHead) {
11630 fprintf (SUMA_STDERR,"%s: %s = %f %f %f\n",
11631 FuncName, Name, RGB[0], RGB[1], RGB[2]);
11632 }
11633
11634 SUMA_RETURN (YUP);
11635 }
11636
SUMA_ContourateDsetOverlay(SUMA_OVERLAYS * cp,SUMA_COLOR_SCALED_VECT * SV)11637 SUMA_Boolean SUMA_ContourateDsetOverlay(SUMA_OVERLAYS *cp,
11638 SUMA_COLOR_SCALED_VECT *SV)
11639 {
11640 static char FuncName[]={"SUMA_ContourateDsetOverlay"};
11641 int kkk=0, *ind=NULL, *key=NULL;
11642 SUMA_Boolean LocalHead = NOPE;
11643
11644 SUMA_ENTRY;
11645
11646 // fprintf(stderr, "%s\n", FuncName);
11647
11648 if (!cp) SUMA_RETURN(NOPE);
11649 if (!cp->dset_link) SUMA_RETURN(NOPE);
11650
11651 if (!SV) {
11652 if (SUMA_is_Label_dset(cp->dset_link,NULL) ||
11653 SUMA_is_Label_dset_col(cp->dset_link, cp->OptScl->find)) {
11654 SUMA_LHv("Creating countours for %s\n",SDSET_LABEL(cp->dset_link));
11655 if (cp->Contours) {
11656 /* this should only happen when users reload a label dset.
11657 or maybe if it regenerated by a draw ROI move in the future.
11658 Not it is worth noting this event, to be sure it is not
11659 being done excessively */
11660 SUMA_S_Notev("Wiping out existing contours for label dset %s\n",
11661 SDSET_LABEL(cp->dset_link));
11662 SUMA_KillOverlayContours(cp);
11663 }
11664
11665 ind = SDSET_NODE_INDEX_COL(cp->dset_link);
11666 key = SDSET_VEC(cp->dset_link, cp->OptScl->find);
11667 cp->Contours =
11668 SUMA_MultiColumnsToDrawnROI( SDSET_VECLEN(cp->dset_link),
11669 (void *)ind, SUMA_int,
11670 (void *)key, SUMA_int,
11671 NULL, SUMA_notypeset,
11672 NULL, SUMA_notypeset,
11673 NULL, SUMA_notypeset,
11674 SUMA_FindNamedColMap (cp->cmapname), 1,
11675 cp->Label, SDSET_IDMDOM(cp->dset_link),
11676 &(cp->N_Contours), 1, 0);
11677 if (LocalHead) SUMA_Show_ColorOverlayPlanes(&cp, 1, 0);
11678 } else {
11679 SUMA_S_Err("Cannot create contours non-label dset types without SV");
11680 SUMA_RETURN(NOPE);
11681 }
11682 } else {
11683 if (!SV->VCont || !SV->N_VCont) {
11684 SUMA_RETURN(NOPE);
11685 } else {
11686 SUMA_LHv("Creating countours for %s\n",SDSET_LABEL(cp->dset_link));
11687 if (cp->Contours) {
11688 SUMA_LHv("Wiping out existing contours for label dset %s\n",
11689 SDSET_LABEL(cp->dset_link));
11690 SUMA_KillOverlayContours(cp);
11691 }
11692 if (SV->N_VCont != cp->N_NodeDef) {
11693 SUMA_S_Warn("I expected N_VCont and N_NodeDef to match!\n"
11694 "Bad things might happen.");
11695 }
11696 ind = cp->NodeDef;
11697 key = SV->VCont;
11698 /*for (kkk=0; kkk<cp->N_NodeDef; ++kkk)
11699 fprintf(SUMA_STDERR,"%d-->%d\t", ind[kkk], key[kkk]);*/
11700 cp->Contours =
11701 SUMA_MultiColumnsToDrawnROI( cp->N_NodeDef,
11702 (void *)ind, SUMA_int,
11703 (void *)key, SUMA_int,
11704 NULL, SUMA_notypeset,
11705 NULL, SUMA_notypeset,
11706 NULL, SUMA_notypeset,
11707 SUMA_FindNamedColMap (cp->cmapname), 1,
11708 cp->Label, SDSET_IDMDOM(cp->dset_link),
11709 &(cp->N_Contours), 1, 1);
11710 if (LocalHead) SUMA_Show_ColorOverlayPlanes(&cp, 1, 0);
11711 }
11712 }
11713
11714 SUMA_RETURN(YUP);
11715 }
11716
11717 /*!
11718 \brief colorize the data of the colorplane
11719 */
SUMA_ColorizePlane(SUMA_OVERLAYS * cp)11720 int SUMA_ColorizePlane (SUMA_OVERLAYS *cp)
11721 {
11722 static char FuncName[]={"SUMA_ColorizePlane"};
11723 int i, i3, N_i, *iv, *Nv;
11724 float *Rv, *Bv, *Gv;
11725 SUMA_Boolean LocalHead = NOPE;
11726
11727 SUMA_ENTRY;
11728
11729 // fprintf(stderr, "%s\n", FuncName);
11730
11731 if (LocalHead) {
11732 SUMA_LH("Color Plane Pre Colorizing");
11733 SUMA_DUMP_TRACE("Who called ColorizePlane?");
11734 SUMA_Show_ColorOverlayPlanes ( &cp, 1, 0);
11735 }
11736 if (!cp) { SUMA_SL_Err("NULL cp"); SUMA_RETURN(NOPE); }
11737 if (!cp->dset_link) {
11738 SUMA_SL_Err("Where's your dset_link?");
11739 SUMA_RETURN(NOPE);
11740 }
11741 if (!cp->cmapname) {
11742 SUMA_SL_Err("Where's your cmapname?");
11743 SUMA_RETURN(NOPE);
11744 }
11745
11746 // fprintf(stderr, "%s\n", FuncName);
11747
11748 if (!cp->ColVec) { SUMA_SL_Err("NULL cV"); SUMA_RETURN(NOPE); }
11749
11750 /* is the coloring direct ? */
11751 if (strcmp(cp->cmapname, "explicit") == 0) {
11752 SUMA_LH("Explicit color specification");
11753 /* make sure dataset is of type NODE_RGB */
11754 if (SDSET_TYPE(cp->dset_link) != SUMA_NODE_RGB) {
11755 SUMA_SL_Err("Direct mapping is only supported for SUMA_NODE_RGB types");
11756 SUMA_RETURN(NOPE);
11757 }
11758 if (!(Nv = SUMA_GetNodeDef(cp->dset_link))) {
11759 SUMA_SL_Err("Failed to find index column.");
11760 SUMA_RETURN(NOPE);
11761 }
11762 iv = SUMA_GetDsetColIndex (cp->dset_link, SUMA_NODE_R, &N_i);
11763 if (N_i != 1) {
11764 SUMA_SL_Err("Failed to find red column.");
11765 SUMA_free(iv);
11766 SUMA_RETURN(NOPE);
11767 }
11768 Rv = (float *)cp->dset_link->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
11769 iv = SUMA_GetDsetColIndex (cp->dset_link, SUMA_NODE_G, &N_i);
11770 if (N_i != 1) {
11771 SUMA_SL_Err("Failed to find green column.");
11772 SUMA_free(iv);
11773 SUMA_RETURN(NOPE);
11774 }
11775 Gv = (float *)cp->dset_link->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
11776 iv = SUMA_GetDsetColIndex (cp->dset_link, SUMA_NODE_B, &N_i);
11777 if (N_i != 1) {
11778 SUMA_SL_Err("Failed to find blue column.");
11779 SUMA_free(iv);
11780 SUMA_RETURN(NOPE);
11781 }
11782 Bv = (float *)cp->dset_link->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
11783 /* go ahead and populate cV */
11784
11785 if (LocalHead) {
11786 char *s = NULL;
11787 s = SUMA_DsetInfo(cp->dset_link, 0);
11788 SUMA_S_Note("%s",s);
11789 SUMA_free(s);
11790 }
11791 if (cp->DimFact == 1.0) {
11792 for (i=0; i < SDSET_VECFILLED(cp->dset_link); ++i) {
11793 i3 = 3 * i;
11794 cp->NodeDef[i] = Nv[i];
11795 cp->ColVec[i3] = Rv[i]; ++i3;
11796 cp->ColVec[i3] = Gv[i]; ++i3;
11797 cp->ColVec[i3] = Bv[i];
11798 }
11799 } else {
11800 for (i=0; i < SDSET_VECFILLED(cp->dset_link); ++i) {
11801 i3 = 3 * i;
11802 cp->NodeDef[i] = Nv[i];
11803 cp->ColVec[i3] = Rv[i] * cp->DimFact; ++i3;
11804 cp->ColVec[i3] = Gv[i] * cp->DimFact; ++i3;
11805 cp->ColVec[i3] = Bv[i] * cp->DimFact;
11806 }
11807 }
11808 cp->N_NodeDef = SDSET_VECFILLED(cp->dset_link);
11809 } else {
11810 /* indirect mapping */
11811 if (!SUMA_ScaleToMap_Interactive (cp)) {
11812 SUMA_SL_Err("Failed in SUMA_ScaleToMap_Interactive.");
11813 SUMA_RETURN(0);
11814 }
11815 /* cp->N_NodeDef is taken care of inside SUMA_ScaleToMap_Interactive */
11816 }
11817
11818
11819
11820 if (LocalHead) {
11821 SUMA_LH("Color Plane Post Colorizing");
11822 SUMA_Show_ColorOverlayPlanes ( &cp, 1, 0);
11823 }
11824 SUMA_RETURN(1);
11825 }
11826
11827 /*!
11828 \brief Sets up the defaults for the convexity plane.
11829
11830 \param SO (SUMA_SurfaceObject *)
11831 pointer to surface object that the convexity dataset
11832 is attributed to.
11833 \param ConvPlane (SUMA_OVERLAYS *)
11834 */
SUMA_SetConvexityPlaneDefaults(SUMA_SurfaceObject * SO,DList * DsetList)11835 SUMA_Boolean SUMA_SetConvexityPlaneDefaults(SUMA_SurfaceObject *SO,
11836 DList *DsetList)
11837 {
11838 static char FuncName[]={"SUMA_SetConvexityPlaneDefaults"};
11839 float IntRange[2], *Vsort = NULL;
11840 float *Cx=NULL;
11841 int junk;
11842 char *eee = NULL;
11843 int icmap;
11844 SUMA_OVERLAYS *ConvPlane;
11845 SUMA_Boolean LocalHead = NOPE;
11846
11847 SUMA_ENTRY;
11848
11849 // fprintf(stderr, "%s\n", FuncName);
11850
11851 if (!SUMAg_CF->scm) { /* colors not setup, go back */
11852 SUMAg_CF->scm = SUMA_Build_Color_maps();
11853 if (!SUMAg_CF->scm) {
11854 SUMA_SL_Warn("No color maps set up.\n");
11855 SUMA_RETURN(YUP);
11856 }
11857 }
11858
11859 if (!(ConvPlane =
11860 SUMA_Fetch_OverlayPointer((SUMA_ALL_DO*)SO, "Convexity", &junk))) {
11861 SUMA_SL_Err("Failed to find overlay plane 'Convexity'");
11862 SUMA_RETURN(NOPE);
11863 }
11864
11865 if (SO->Group && strcmp(SO->Group,SUMA_DEF_TOY_GROUP_NAME) == 0) {
11866 SUMA_LH("Adriano");
11867 /* fun times, gimme a random colormap */
11868 if (1) {
11869 icmap = rand()%SUMAg_CF->scm->N_maps;
11870 SUMA_STRING_REPLACE( ConvPlane->cmapname,
11871 SUMAg_CF->scm->CMv[icmap]->Name);
11872 /* SUMA_S_Notev("Cmap %s\n", ConvPlane->cmapname); */
11873 } else { /* Used here to force crash on linux, bug should now be fixed
11874 See comment in SUMA_GimmeSomeSOs (also other 20 maps...)*/
11875 SUMA_STRING_REPLACE(ConvPlane->cmapname, "rgybr20");
11876 }
11877 } else {
11878 /* decide on the color map */
11879 eee = getenv("SUMA_ConvColorMap");
11880 if (eee) {
11881 icmap = SUMA_Find_ColorMap ( eee, SUMAg_CF->scm->CMv,
11882 SUMAg_CF->scm->N_maps, -2 );
11883 if (icmap < 0) {
11884 SUMA_SL_Err("Colormap specified in\n"
11885 "environment variable SUMA_ConvColorMap\n"
11886 "was not found. Using ngray20.\n");
11887 SUMA_STRING_REPLACE(ConvPlane->cmapname, "ngray20");
11888 } else {
11889 SUMA_STRING_REPLACE(ConvPlane->cmapname, eee);
11890 }
11891 } else {
11892 SUMA_STRING_REPLACE(ConvPlane->cmapname, "ngray20");
11893 }
11894 }
11895
11896 SUMA_LH("Deciding on brightness factor");
11897 /* decide on the convexity brightness factor */
11898 eee = getenv("SUMA_ConvBrightFactor");
11899 if (eee) {
11900 ConvPlane->OptScl->BrightFact = (float)strtod(eee, NULL);
11901 if (ConvPlane->OptScl->BrightFact < 0) {
11902 SUMA_SL_Err("Brightness factor specified in\n"
11903 "environment variable SUMA_ConvColorMap\n"
11904 "is negative. Using default.\n");
11905 ConvPlane->OptScl->BrightFact = SUMA_DIM_CONVEXITY_COLOR_FACTOR;
11906 }
11907 } else {
11908 ConvPlane->OptScl->BrightFact = SUMA_DIM_CONVEXITY_COLOR_FACTOR;
11909 }
11910
11911 /* Now place the color map in the Coloroverlay structure */
11912 ConvPlane->GlobalOpacity = SUMA_floatEnv("SUMA_ConvexityDsetOpacity",
11913 SUMA_CONVEXITY_COLORPLANE_OPACITY);
11914 ConvPlane->ShowMode = SW_SurfCont_DsetViewCol;
11915 ConvPlane->isBackGrnd = YUP;
11916
11917 SUMA_LH("Smoothing Cx");
11918 /* work the options for creating the scaled color mapping a bit */
11919 ConvPlane->OptScl->interpmode = SUMA_NO_INTERP;
11920 ConvPlane->OptScl->ApplyClip = YUP;
11921
11922 IntRange[0] = 5; IntRange[1] = 95; /* percentile clipping range*/
11923 Cx = (float *)SUMA_GetCx(SO->idcode_str, DsetList, 0);
11924 if (!Cx) { SUMA_SL_Err("Failed to find Cx\n"); SUMA_RETURN (NOPE); }
11925 Vsort = SUMA_PercRange (Cx, NULL, SO->N_Node, IntRange, IntRange, NULL);
11926 if (Vsort[0] < 0 && Vsort[SO->N_Node -1] > 0 ) {
11927 /* the new method */
11928 if (fabs(IntRange[0]) > IntRange[1]) {
11929 IntRange[1] = -IntRange[0];
11930 } else {
11931 IntRange[0] = -IntRange[1];
11932 }
11933 } else {
11934 /* The old method, do nothing here */
11935 }
11936 if (Vsort) SUMA_free(Vsort); Vsort = NULL;
11937
11938 SUMA_LHv("Settled on range of %f to %f\n", IntRange[0], IntRange[1]);
11939 ConvPlane->OptScl->find = 0; /* the intensity column */
11940 ConvPlane->OptScl->tind = 0; /* the threshold column */
11941 ConvPlane->OptScl->bind = 0; /* the brightness modulation column */
11942 ConvPlane->OptScl->IntRange[0] = IntRange[0];
11943 ConvPlane->OptScl->IntRange[1] = IntRange[1];
11944 if (ConvPlane->SymIrange) {
11945 ConvPlane->OptScl->IntRange[1] =
11946 SUMA_LARG_ABS(ConvPlane->OptScl->IntRange[0],
11947 ConvPlane->OptScl->IntRange[1]);
11948 ConvPlane->OptScl->IntRange[0] = -ConvPlane->OptScl->IntRange[1];
11949 }
11950 /* Force Auto Range to these percentile values */
11951 ConvPlane->ForceIntRange[0] = IntRange[0];
11952 ConvPlane->ForceIntRange[1] = IntRange[1];
11953
11954
11955 SUMA_RETURN(YUP);
11956 }
11957
11958 /*!
11959 \brief j = SUMA_GetNodeOverInd(Sover, node);
11960 returns the index, into Sover->NodeDef such
11961 that Sover->NodeDef[j] = node;
11962 \sa SUMA_GetNodeRow_FromNodeIndex
11963 */
SUMA_GetNodeOverInd(SUMA_OVERLAYS * Sover,int node)11964 int SUMA_GetNodeOverInd (SUMA_OVERLAYS *Sover, int node)
11965 {
11966 static char FuncName[]={"SUMA_GetNodeOverInd"};
11967 int Found, i;
11968 SUMA_Boolean LocalHead = NOPE;
11969
11970 SUMA_ENTRY;
11971
11972 // fprintf(stderr, "%s\n", FuncName);
11973
11974 /* Now look for the node's location in the color overlay plane.
11975 Nodes that are not colored will be absent ... */
11976 if (node < 0) SUMA_RETURN(-1);
11977
11978 Found = -1;
11979 if (SDSET_VECFILLED(Sover->dset_link) > node) { /* try the straight shot */
11980 if (Sover->NodeDef[node] == node) {
11981 SUMA_LH("Good, found it easily");
11982 /* make sure node is not outside number of defined nodes */
11983 if (node >= Sover->N_NodeDef) {
11984 /* this one's masked but it was left over from the previous pass
11985 Must go search below to make sure whether it is truly masked or not*/
11986 SUMA_LH("Can't tell for sure");
11987 } else {
11988 SUMA_RETURN(node);
11989 }
11990 }
11991 }
11992 if (Found < 0) {
11993 SUMA_LH("The hard way");
11994 i=0;
11995 while (Found <0 && i<Sover->N_NodeDef) {
11996 if (Sover->NodeDef[i] == node) Found = i;
11997 ++i;
11998 }
11999 }
12000
12001 SUMA_RETURN(Found);
12002 }
12003
SUMA_GetSortedNodeOverInd(SUMA_OVERLAYS * Sover,int node)12004 int SUMA_GetSortedNodeOverInd (SUMA_OVERLAYS *Sover, int node)
12005 {
12006 static char FuncName[]={"SUMA_GetSortedNodeOverInd"};
12007 int Found, i;
12008 SUMA_Boolean LocalHead = NOPE;
12009
12010 SUMA_ENTRY;
12011
12012 // fprintf(stderr, "%s\n", FuncName);
12013
12014 /* Now look for the node's location in the color overlay plane.
12015 Nodes that are not colored will be absent ... */
12016 if (node < 0) SUMA_RETURN(-1);
12017
12018 Found = -1;
12019 if (SDSET_VECFILLED(Sover->dset_link) > node) { /* try the straight shot */
12020 if (Sover->NodeDef[node] == node) {
12021 SUMA_LH("Good, found it easily");
12022 /* make sure node is not outside number of defined nodes */
12023 if (node >= Sover->N_NodeDef) {
12024 /* this one's masked but it was left over from the previous pass
12025 Must go search below to make sure whether it is truly masked or not*/
12026 SUMA_LH("Can't tell for sure");
12027 } else {
12028 SUMA_RETURN(node);
12029 }
12030 }
12031 }
12032
12033 if (Found < 0) {
12034 SUMA_LH("The hard way, but sorted");
12035 SUMA_RETURN(SUMA_ibinFind(Sover->NodeDef, Sover->N_NodeDef, node));
12036 }
12037
12038 SUMA_RETURN(Found);
12039 }
12040
12041 /*-----------------------------------------------------------*/
12042 /*
12043 Activate callbacks pertinent to SO->SelectedNode and Sover
12044 This function should be called after SO->SelectedNode has been set
12045 \param SO
12046 \param Sover
12047 \param src
12048 \param ngr: a NI_group* containing crosshair data from AFNI
12049 */
SUMA_Selected_Node_Activate_Callbacks(SUMA_ALL_DO * ado,SUMA_OVERLAYS * Sover,SUMA_ENGINE_SOURCE Src,NI_group * ngr)12050 SUMA_Boolean SUMA_Selected_Node_Activate_Callbacks (
12051 SUMA_ALL_DO *ado, SUMA_OVERLAYS *Sover,
12052 SUMA_ENGINE_SOURCE Src, NI_group *ngr)
12053 {
12054 static char FuncName[]={"SUMA_Selected_Node_Activate_Callbacks"};
12055 NI_element*nelts = NULL, *nelts_s2v=NULL;
12056 char *ts_dset_id = NULL, *cbuf=NULL;
12057 SUMA_DSET *in_dset=NULL;
12058 float *fv3=NULL;
12059 DListElmt *el=NULL;
12060 NI_element *nel=NULL;
12061 SUMA_CALLBACK *cb=NULL;
12062 NI_element *nelpars=NULL;
12063 SUMA_X_SurfCont *SurfCont=NULL;
12064 SUMA_Boolean LocalHead = NOPE;
12065
12066 SUMA_ENTRY;
12067
12068 // fprintf(stderr, "%s\n", FuncName);
12069
12070 if (!ado || !(SurfCont = SUMA_ADO_Cont(ado)) || !Sover) {
12071 /* this can happen in normal cases where nothing is loaded or selected. */
12072 SUMA_LH("No Surface or Surface Controller, or other important stuff!");
12073 SUMA_RETURN(YUP);
12074 }
12075
12076 /* setup callback, if needed */
12077 if (SUMAg_CF->callbacks) {
12078 el = dlist_head(SUMAg_CF->callbacks);
12079 while (el) {
12080 cb = (SUMA_CALLBACK *)el->data;
12081 if ( cb->event == SUMA_NEW_NODE_ACTIVATE_EVENT &&
12082 cb->active > 0 &&
12083 (Sover && Sover->dset_link ) ) {
12084 SUMA_LHv("Looking for callback parents involved \n"
12085 "with dset %s\n",
12086 SDSET_ID(Sover->dset_link ));
12087 /* Is any of the parents involved here? */
12088 if (SUMA_is_CallbackParent(cb,
12089 SDSET_ID(Sover->dset_link ),
12090 NULL)){
12091 SUMA_SetCallbackPending(cb, 1, Src);
12092 /* setup event parameters
12093 YOU SHOULD NOT SET ANYTHING that THIS event
12094 call does not normally receive */
12095 if (!(nelpars = SUMA_FindNgrNamedElement(
12096 cb->FunctionInput, "event_parameters"))) {
12097 SUMA_S_Err("Failed to find parameters element!"); SUMA_RETURN(NOPE);
12098 }
12099 NI_SET_INT(nelpars, "event.new_node",
12100 SUMA_ADO_SelectedDatum(ado, NULL, NULL));
12101 NI_set_attribute( nelpars,
12102 "event.DO_idcode", SUMA_ADO_idcode(ado));
12103 NI_set_attribute(nelpars,
12104 "event.overlay_name",
12105 Sover->Name);
12106 if ((Src == SES_Afni ||
12107 Src == SES_SumaFromAfni) &&
12108 ngr) {
12109 /* See if there is a time series */
12110 nelts =
12111 SUMA_FindNgrNamedElement(ngr,
12112 "underlay_array");
12113 if ((nelts_s2v = SUMA_FindNgrNamedElement(ngr,
12114 "v2s_node_array"))) {
12115 if (AFNI_yesenv("SUMA_USE_V2S_TS")) {
12116 SUMA_LH("Using ts from v2s");
12117 nelts = nelts_s2v;
12118 }else {
12119 SUMA_LH("Ignoring ts from v2s");
12120 nelts_s2v = NULL;
12121 }
12122 }
12123
12124 if ( (nelts)){
12125 SUMA_LH("Have underlay time "
12126 "series from AFNI");
12127 /* check if length of time series matches dsets
12128 in question */
12129 ts_dset_id =
12130 SUMA_GetNgrColStringAttr( cb->FunctionInput,
12131 0, "ts_dsets_idcode");
12132 if (!(SUMA_is_ID_4_DSET(ts_dset_id,
12133 &in_dset))) {
12134 SUMA_S_Err("Could not find ts dset");
12135 SUMA_RETURN(NOPE);
12136 }
12137
12138 if (nelts->vec_len &&
12139 nelts->vec_len == SDSET_VECNUM(in_dset) &&
12140 NI_YES_ATTR(nelts,"has_taxis")) {
12141 nel = NI_new_data_element(
12142 "callback.data", nelts->vec_len);
12143 NI_set_attribute(nel,
12144 "atr_name", "ts_vec");
12145 NI_add_column(nel, NI_FLOAT, nelts->vec[0]);
12146 NI_add_to_group(cb->FunctionInput, nel);
12147 if (LocalHead) {
12148 char stmp[1000], *cbuf=NULL;
12149 float fv3[3], *fv=NULL;
12150 cbuf = NI_get_attribute(nelts, "vox_ijk");
12151 SUMA_StringToNum(cbuf, (void *)fv3,3,1);
12152 if (!nelts_s2v) {
12153 sprintf(stmp,"underlay_array.%d.%d.%d.1D",
12154 (int)fv3[0], (int)fv3[1],(int)fv3[2]);
12155 } else {
12156 sprintf(stmp,"v2s_array.%d.1D",
12157 SUMA_ADO_SelectedDatum(ado, NULL, NULL));
12158 }
12159 fv = (float *)nelts->vec[0];
12160 SUMA_LHv("Writing %s\n", stmp);
12161 SUMA_WRITE_ARRAY_1D( fv,
12162 nelts->vec_len,
12163 1, stmp);
12164 }
12165 } else {
12166 SUMA_LHv(
12167 "vec_len = %d\n"
12168 "SDSET_VECNUM = %d\n"
12169 "has_taxis = %s\n",
12170 nelts->vec_len,
12171 SDSET_VECNUM(in_dset),
12172 NI_get_attribute(nelts,"has_taxis") );
12173 }
12174 } else {
12175 SUMA_LH("No underlay time "
12176 "series from AFNI");
12177 if (LocalHead) SUMA_ShowNel(ngr);
12178 }
12179 }
12180 } else {
12181 SUMA_LH("No involved parents found");
12182 }
12183 } else {
12184 SUMA_LHv("Skipping callback for %s...\n",
12185 cb->FunctionName);
12186 }
12187 el = dlist_next(el);
12188 }
12189 }
12190 SUMA_RETURN(YUP);
12191 }
12192
SUMA_RGB_to_hex(float * fv,char * here)12193 char *SUMA_RGB_to_hex(float *fv, char *here)
12194 {
12195 static char FuncName[]={"SUMA_RGB_to_hex"};
12196 static char ans[10][32];
12197 static int icall=0;
12198 char *s;
12199
12200 // fprintf(stderr, "%s\n", FuncName);
12201
12202 if (here) s = here;
12203 else {
12204 ++icall;
12205 if (icall > 9) icall = 0;
12206 s = (char *)ans[icall];
12207 }
12208 s[0] = '\0';
12209
12210 if (!fv) return(s);
12211
12212 sprintf(s,"#");
12213 r_sprintf_long_to_hex (s+strlen(s),
12214 (unsigned long)rint((fv[0]*255)), 1, 0);
12215 r_sprintf_long_to_hex (s+strlen(s),
12216 (unsigned long)rint((fv[1]*255)), 1, 0);
12217 r_sprintf_long_to_hex (s+strlen(s),
12218 (unsigned long)rint((fv[2]*255)), 1, 0);
12219
12220 return(s);
12221 }
12222
12223