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