#include "SUMA_suma.h"
#define MAIN /* need this to read in color info from afni.h */
#include "../afni.h"
#undef MAIN
#ifdef STAND_ALONE
/* these global variables must be declared even if they will not be used by this main */
SUMA_SurfaceViewer *SUMAg_cSV; /*!< Global pointer to current Surface Viewer structure*/
SUMA_SurfaceViewer *SUMAg_SVv; /*!< Global pointer to the vector containing the various Surface Viewer Structures
SUMAg_SVv contains SUMA_MAX_SURF_VIEWERS structures */
int SUMAg_N_SVv = 0; /*!< Number of SVs realized by X */
SUMA_DO *SUMAg_DOv; /*!< Global pointer to Displayable Object structure vector*/
int SUMAg_N_DOv = 0; /*!< Number of DOs stored in DOv */
SUMA_CommonFields *SUMAg_CF; /*!< Global pointer to structure containing info common to all viewers */
#else
extern SUMA_CommonFields *SUMAg_CF;
extern SUMA_DO *SUMAg_DOv;
extern SUMA_SurfaceViewer *SUMAg_SVv;
extern int SUMAg_N_SVv;
extern int SUMAg_N_DOv;
#endif
/*! The set of functions deals with node colors
*/
/*!
This function creates an RGB colormap containing Ncols that vary linearily
from the first color in Fiducials to the last.
SM = SUMA_MakeColorMap (Fiducials, N , N_cols, SkipLast, Name)
\param Fiducials (float **) N x 3 matrix containing RGB values (range 0..1)
of fiducial colours which will be equally spaced on the color map
\param N (int) number of fiducial colors in Fiducials
\param Ncols (int) total number of colors in the map.
You are somewhat restricted in the total number of
colours you choose. You must choose a number that
allows you to have the same number of colours between
successive fiducials. The function will complain if that's not the case
\param SkipLast (SUMA_Boolean) if set to NOPE (0), then the last color specified in
Fiducials is the last color in M. If set to 1, the last
color in M represents the color that would come right
before the last one in Fifucials. This last option is
usefull when you're crating cyclical color maps where
the last color in Fiduciasl is like the first.
\param Name (char *) name of colormap
\ret SM (SUMA_COLOR_MAP *) see help for SUMA_COLOR_MAP for more info
\sa based on my matlab function MakeColorMap.m
\sa SUMA_Free_ColorMap
\sa SUMA_MakeColorMap_v2
*/
SUMA_COLOR_MAP* SUMA_MakeColorMap (float **Fiducials, int Nfid, int Ncols, SUMA_Boolean SkipLast, char *Name)
{
static char FuncName[]={"SUMA_MakeColorMap"};
float **M, dFid[3];
int i, j, Ninter, Ngap, im, Ncolsgood, Npergap;
SUMA_COLOR_MAP * SM;
SUMA_ENTRY;
/* check for bad input */
for (i=0; i < Nfid; ++i) {
for (j=0; j < 3; ++j) {
if (Fiducials[i][j] < 0 || Fiducials[i][j] > 1) {
fprintf (SUMA_STDERR,"Error %s: Fiducial colors must be between 0 & 1 (found %f)\n", FuncName, Fiducials[i][j]);
SUMA_RETURN (NULL);
}
}
}
/* determine the number of intermediate colors */
if (SkipLast) Ninter = Ncols - (Nfid - 1);
else Ninter = Ncols - Nfid;
Ngap = Nfid - 1;
/* you must have an equal number of colours in each gap */
if (Ninter % Ngap) {
/* bad, sugeest a better number */
if (SkipLast) Ncolsgood = (int)(rint((float)Ninter/Ngap) * Ngap + Nfid + 1);
else Ncolsgood = (int)(rint((float)Ninter/Ngap) * Ngap + Nfid);
fprintf (SUMA_STDERR,"Error %s: The choice of Ncols does not work with the number\nof fiducial colours.\nTry Ncols = %d\n", \
FuncName, Ncolsgood);
SUMA_RETURN (NULL);
}
/* allocate for M */
M = (float **)SUMA_allocate2D (Ncols, 3, sizeof(float));
if (M == NULL) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for M.\n", FuncName);
SUMA_RETURN (NULL);
}
/* start forming M */
im = 0;
Npergap = Ninter / Ngap;
for (i=0; i < Ngap; ++i) {
dFid[0] = (Fiducials[i+1][0] - Fiducials[i][0])/(Npergap+1);
dFid[1] = (Fiducials[i+1][1] - Fiducials[i][1])/(Npergap+1);
dFid[2] = (Fiducials[i+1][2] - Fiducials[i][2])/(Npergap+1);
/*fprintf (SUMA_STDERR,"%s: dFid = %f %f %f\n", FuncName, dFid[0], dFid[1] , dFid[2]);*/
for (j=0; j < Npergap+1; ++ j) {
if (im < Ncols) {
M[im][0] = Fiducials[i][0] + j*dFid[0];
M[im][1] = Fiducials[i][1] + j*dFid[1];
M[im][2] = Fiducials[i][2] + j*dFid[2];
/*fprintf (SUMA_STDERR,"%s: M[%d][:] = %f %f %f\n", FuncName, im, M[im][0], M[im][1], M[im][2]); */
}
++im;
}
}
if (!SkipLast) {
if (im >= Ncols) {
SUMA_S_Crit("Unexpected logic error");
} else {
M[im][0] = Fiducials[Ngap][0];
M[im][1] = Fiducials[Ngap][1];
M[im][2] = Fiducials[Ngap][2];
}
}
/* package the resutls */
SM = (SUMA_COLOR_MAP *)SUMA_malloc(sizeof(SUMA_COLOR_MAP));
if (SM == NULL) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for SM.\n", FuncName);
SUMA_RETURN (NULL);
}
SM->top_frac = 0.0f;
SM->Name = (char *)SUMA_calloc(strlen(Name)+1, sizeof(char));
if (SM->Name == NULL) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for SM->Name.\n", FuncName);
SUMA_RETURN (NULL);
}
sprintf(SM->Name, "%s",Name);
SM->M = M;
SM->N_Col = Ncols;
SM->frac = NULL; /* a linear map */
SM->cname = NULL;
SM->Sgn = 0; /* setup for linear maps with no signing, mapping a la old ScaleToMap*/
SM->SO = NULL; /* created when needed */
SUMA_RETURN (SM);
}
/*!
This function creates an RGB colormap containing Ncols that vary linearily
from the first color in Fiducials to the last.
SM = SUMA_MakeColorMap_v2 (Fiducials, NFid, Nin , SkipLast, Name)
\param Fiducials (float **) NFid x 3 matrix containing RGB values (range 0..1)
of fiducial colours which will be equally spaced on the color map
\param NFid (int) number of fiducial colors
\param Nin (int*) NFid x 1 vector indicating the number of interpolations to perform
between successive colors e.g.:
Fiducials Nin
1 0 0 2
0 1 0 5
0 0 1 0
The map will start with 1 0 0 then place 2 colors interpolated
between 1 0 0 and 0 1 0. The last color of this map is 0 0 1.
If the last entry in Nin was 4 then 4 colors are added after 0 0 1 wich
are interpolated between the last and 1st color. This is good
for cyclical color maps
\param SkipLast (SUMA_Boolean) YUP/NOPE keep last color in Fiducials out of the final map
\param Name (char *) name of colormap
\ret SM (SUMA_COLOR_MAP *) see help for SUMA_COLOR_MAP for more info
\sa SUMA_Free_ColorMap
\sa SUMA_MakeColorMap
*/
SUMA_COLOR_MAP* SUMA_MakeColorMap_v2 (float **Fiducials, int Nfid, int *Nint, SUMA_Boolean SkipLast, char *Name)
{
static char FuncName[]={"SUMA_MakeColorMap_v2"};
float **M, dFid[3];
int i, j, im, Ncols;
SUMA_COLOR_MAP * SM;
SUMA_ENTRY;
/* check for bad input and calculate the total number of colors*/
if (Nint[0]) {
fprintf (SUMA_STDERR,"Error %s: The index of the first color (%d) must be 0, indexing starts at 0 not 1.\n", FuncName, Nint[0]);
SUMA_RETURN (NULL);
}
for (i=0; i < Nfid; ++i) {
for (j=0; j < 3; ++j) {
if (Fiducials[i][j] < 0 || Fiducials[i][j] > 1) {
fprintf (SUMA_STDERR,"Error %s: Fiducial colors must be between 0 & 1 (found %f)\n", FuncName, Fiducials[i][j]);
SUMA_RETURN (NULL);
}
}
}
Ncols = Nint[Nfid-1]+1;
if (SkipLast) Ncols = Ncols - 1;
/* allocate for M */
M = (float **)SUMA_allocate2D (Ncols, 3, sizeof(float));
if (M == NULL) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for M.\n", FuncName);
SUMA_RETURN (NULL);
}
/* start forming M */
im = 0;
for (i=0; i < Nfid-1; ++i) {
dFid[0] = (Fiducials[i+1][0] - Fiducials[i][0])/(Nint[i+1]-Nint[i]);
dFid[1] = (Fiducials[i+1][1] - Fiducials[i][1])/(Nint[i+1]-Nint[i]);
dFid[2] = (Fiducials[i+1][2] - Fiducials[i][2])/(Nint[i+1]-Nint[i]);
/*fprintf (SUMA_STDERR,"%s: dFid = %f %f %f\n", FuncName, dFid[0], dFid[1] , dFid[2]);*/
for (j=0; j < (Nint[i+1]- Nint[i]); ++ j) {
M[im][0] = Fiducials[i][0] + j*dFid[0];
M[im][1] = Fiducials[i][1] + j*dFid[1];
M[im][2] = Fiducials[i][2] + j*dFid[2];
/*fprintf (SUMA_STDERR,"%s: M[%d][:] = %f %f %f\n", FuncName, im, M[im][0], M[im][1], M[im][2]); */
++im;
}
}
if (!SkipLast){
M[im][0] = Fiducials[Nfid-1][0];
M[im][1] = Fiducials[Nfid-1][1];
M[im][2] = Fiducials[Nfid-1][2];
}
/* package the resutls */
SM = (SUMA_COLOR_MAP *)SUMA_malloc(sizeof(SUMA_COLOR_MAP));
if (SM == NULL) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for SM.\n", FuncName);
SUMA_RETURN (NULL);
}
SM->top_frac = 0.0f;
SM->Name = (char *)SUMA_calloc(strlen(Name)+1, sizeof(char));
if (SM->Name == NULL) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for SM->Name.\n", FuncName);
SUMA_RETURN (NULL);
}
sprintf(SM->Name, "%s",Name);
SM->M = M;
SM->N_Col = Ncols;
SM->frac = NULL; /* a linear map */
SM->cname = NULL;
SM->Sgn = 0; /* setup for linear maps with no signing, mapping a la old ScaleToMap*/
SM->SO = NULL; /* created when needed */
SUMA_RETURN (SM);
}
/*! function to free memory allocated for SUMA_COLOR_MAP */
void SUMA_Free_ColorMap (SUMA_COLOR_MAP* SM)
{
static char FuncName[]={"SUMA_Free_ColorMap"};
int i = 0;
SUMA_ENTRY;
if (SM->Name) SUMA_free(SM->Name);
if (SM->M) SUMA_free2D((char **)SM->M, SM->N_Col);
if (SM->cname) {
for (i=0; i<SM->N_Col; ++i) { if (SM->cname[i]) SUMA_free(SM->cname[i]); }
SUMA_free(SM->cname);
}
if (SM->frac) SUMA_free(SM->frac);
if (SM->SO) SUMA_Free_Surface_Object(SM->SO);
if (SM) SUMA_free(SM);
SUMA_RETURNe;
}
/*!
\brief Builds the SUMA_AFNI_COLORS structure which
contains the Named colors and colormaps defined in AFNI
The colors and colormaps loaded are the ones that
are found in AFNI when AFNI is first started.
- Continuous colormaps are NOT loaded.
- Colors and colormaps defined in the .afnirc are loaded
\sa SUMA_DestroyAfniColors (for deleting returned structure)
*/
SUMA_AFNI_COLORS *SUMA_Get_AFNI_Default_Color_Maps ()
{
static char FuncName[]={"SUMA_Get_AFNI_Default_Color_Maps"};
float rgb[3];
SUMA_RGB_NAME *Cv = NULL;
SUMA_COLOR_MAP **CMv=NULL;
SUMA_COLOR_MAP *CMp=NULL, *CMn=NULL;
SUMA_AFNI_COLORS *SAC=NULL;
int i, j, icol;
int N_maps, N_cols;
int ival , ii,jj ;
float fval ;
float pthr[NPANE_MAX+1] ;
int pov[NPANE_MAX+1] ;
char *homeenv=NULL, *sumarc=NULL;
struct stat stbuf;
SUMA_Boolean LocalHead_Detail = NOPE;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
/* initilialize*/
N_maps = -1;
N_cols = -1;
/* add the none color first */
Cv = SUMA_Add_Color ("none",
-1.0, -1.0, -1.0, 1.0,
Cv, &N_cols);
/* get the rgb, floats of each color defined DEFAULT_NCOLOVR */
for (i=0; i<DEFAULT_NCOLOVR; ++i) {
if (!SUMA_Interpret_AFNIColor (INIT_def_colovr[i], rgb)) {
fprintf(SUMA_STDERR,"Error %s: Failed to interpret color %s : %s\n", FuncName, INIT_def_labovr[i], INIT_def_colovr[i]);
} else {
if (LocalHead_Detail) fprintf(SUMA_STDERR,"%s: Adding color %s : %s [%.3f %.3f %.3f]\n",
FuncName, INIT_def_labovr[i], INIT_def_colovr[i], rgb[0], rgb[1], rgb[2]);
Cv = SUMA_Add_Color (INIT_def_labovr[i],
rgb[0], rgb[1], rgb[2], 1.0,
Cv, &N_cols);
}
}
/* Now create the afni color maps with more than 10 panes (excerpts from afni.c)*/
/* start with positive panes */
for( ii=NPANE_INIT+1 ; ii <= NPANE_MAX ; ii++ ){
fval = 1.0 / ii ;
pthr[0] = 1.0 ;
pthr[ii] = 0.0 ;
for( jj=1 ; jj < ii ; jj++ ) pthr[jj] = fval * (ii-jj) ;
for( jj=0 ; jj < ii ; jj++ ) pov[jj] = (jj % INIT_ncolovr) + 1 ;
for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_pos[ii][jj] = pthr[jj] ;
for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_pos[ii][jj] = pov[jj] ;
}
/** initialize signed pbar panes **/
for( ii=NPANE_INIT+1 ; ii <= NPANE_MAX ; ii++ ){
fval = 1.0 / ii ;
pthr[0] = 1.0 ;
pthr[ii] = -1.0 ;
for( jj=1 ; jj < ii ; jj++ ) pthr[jj] = fval * (ii-2*jj) ;
for( jj=0 ; jj < ii ; jj++ ) pov[jj] = (jj % INIT_ncolovr) + 1 ;
for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_sgn[ii][jj] = pthr[jj] ;
for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_sgn[ii][jj] = pov[jj] ;
}
#if defined(RGBCYC_COUNT) && RGBCYC_COUNT <= NPANE_MAX
ii = RGBCYC_COUNT ;
for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_pos[ii][jj] = RGBCYC_FIRST+jj+1 ;
for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_sgn[ii][jj] = RGBCYC_FIRST+jj+1 ;
#endif
/* now create AFNI's colormaps */
for (i = NPANE_MIN; i<= NPANE_MAX; ++i) {
CMp = (SUMA_COLOR_MAP *)SUMA_malloc(sizeof(SUMA_COLOR_MAP));
CMn = (SUMA_COLOR_MAP *)SUMA_malloc(sizeof(SUMA_COLOR_MAP));
if (CMp == NULL || CMn == NULL) {
SUMA_SL_Crit ("Failed to allocate for CMp &/| CMn.");
SUMA_RETURN(NULL);
}
CMp->top_frac = 0.0f;
CMn->top_frac = 0.0f;
CMp->SO = NULL;
CMn->SO = NULL;
CMp->cname = NULL;
CMn->cname = NULL;
CMp->N_Col = i;
CMn->N_Col = i;
CMp->Sgn = 1;
CMn->Sgn = -1;
CMp->Name = (char *)SUMA_calloc(25, sizeof(char));
CMn->Name = (char *)SUMA_calloc(25, sizeof(char));
CMp->frac = (float *)SUMA_calloc(i, sizeof(float));
CMn->frac = (float *)SUMA_calloc(i, sizeof(float));
CMp->M = (float**)SUMA_allocate2D (CMp->N_Col, 3, sizeof(float));
CMn->M = (float**)SUMA_allocate2D (CMn->N_Col, 3, sizeof(float));
if ( CMp->frac == NULL || CMn->frac == NULL
|| CMp->M == NULL || CMn->M == NULL
|| CMp->Name == NULL || CMn->Name == NULL ) {
SUMA_SL_Crit ("Failed to allocate for fields of CMp &/| CMn.");
SUMA_RETURN (NULL);
}
sprintf(CMp->Name, "afni_p%d",i);
sprintf(CMn->Name, "afni_n%d",i);
if (LocalHead_Detail) fprintf (SUMA_STDERR,"%s: Building colormap POS #%d (%s)\n", FuncName, i, CMp->Name);
for ( j = 0; j < i; ++j) {
if (!INIT_ovin_pos[i][j]) {
if (LocalHead_Detail) {
fprintf (SUMA_STDERR,"\t[i%d] NoColor\t%f\n",
INIT_ovin_pos[i][j],
INIT_pval_pos[i][j]);
}
CMp->M[i - j - 1][0] = CMp->M[i - j - 1][1] = CMp->M[i - j - 1][2] = -1.0;
} else {
if (LocalHead_Detail) {
fprintf (SUMA_STDERR,"\t[i%d] %s\t%f\n",
INIT_ovin_pos[i][j],
INIT_def_labovr[INIT_ovin_pos[i][j]-1], INIT_pval_pos[i][j]);
}
/* find out which color this is */
icol = SUMA_Find_Color (INIT_def_labovr[INIT_ovin_pos[i][j]-1], Cv, N_cols);
if (icol < 0) {
fprintf (SUMA_STDERR,"Error%s: Failed to find color %s\nUsing no-color in its place\n",
FuncName, INIT_def_labovr[INIT_ovin_pos[i][j]-1]);
CMp->M[i - j - 1][0] = CMp->M[i - j - 1][1] = CMp->M[i - j - 1][2] = -1.0;
} else {
CMp->M[i - j - 1][0] = Cv[icol].r;
CMp->M[i - j - 1][1] = Cv[icol].g;
CMp->M[i - j - 1][2] = Cv[icol].b;
}
}
CMp->frac[i - j - 1] = INIT_pval_pos[i][j];
}
if (CMp->frac[CMp->N_Col-1] != 1.0f) {
SUMA_LH("top_frac not 1 for positive map");
CMp->top_frac = CMp->frac[CMp->N_Col-1];
}
/* add the positive map to the list */
CMv = SUMA_Add_ColorMap (CMp, CMv, &N_maps);
if (!CMv) {
SUMA_SL_Crit("Failed in SUMA_Add_ColorMap");
SUMA_RETURN(NULL);
}
if (LocalHead_Detail) fprintf (SUMA_STDERR,"%s: Building colormap SGN #%d (%s)\n", FuncName, i, CMn->Name);
for ( j = 0; j < i; ++j) {
if (!INIT_ovin_sgn[i][j]) {
if (LocalHead_Detail) {
fprintf (SUMA_STDERR,"\t[i%d] NoColor\t%f\n",
INIT_ovin_sgn[i][j],
INIT_pval_sgn[i][j]);
}
CMn->M[i - j - 1][0] = CMn->M[i - j - 1][1] = CMn->M[i - j - 1][2] = -1.0;
} else {
if (LocalHead_Detail) {
fprintf (SUMA_STDERR,"\t[i%d] %s\t%f\n",
INIT_ovin_sgn[i][j],
INIT_def_labovr[INIT_ovin_sgn[i][j]-1], INIT_pval_sgn[i][j]);
}
icol = SUMA_Find_Color (INIT_def_labovr[INIT_ovin_sgn[i][j]-1], Cv, N_cols);
if (icol < 0) {
fprintf (SUMA_STDERR,"Error%s: Failed to find color %s\nUsing no-color in its place",
FuncName, INIT_def_labovr[INIT_ovin_sgn[i][j]-1]);
CMn->M[i - j - 1][0] = CMn->M[i - j - 1][1] = CMn->M[i - j - 1][2] = -1.0;
} else {
CMn->M[i - j - 1][0] = Cv[icol].r;
CMn->M[i - j - 1][1] = Cv[icol].g;
CMn->M[i - j - 1][2] = Cv[icol].b;
}
}
CMn->frac[i - j - 1] = INIT_pval_sgn[i][j];
}
if (CMn->frac[CMn->N_Col-1] != 1.0f) {
SUMA_LH("top_frac not 1 for negative map");
CMn->top_frac = CMn->frac[CMp->N_Col-1];
}
/* add the negative map to the list */
CMv = SUMA_Add_ColorMap (CMn, CMv, &N_maps);
if (!CMv) {
SUMA_SL_Crit("Failed in SUMA_Add_ColorMap");
SUMA_RETURN(NULL);
}
}
/* perhaps someday include the continuous color maps from AFNI too.
(see pbar.c file, search for colorscale) */
SAC = (SUMA_AFNI_COLORS *) SUMA_malloc(sizeof(SUMA_AFNI_COLORS));
SAC->CMv = CMv;
SAC->N_maps = N_maps;
SAC->Cv = Cv;
SAC->N_cols = N_cols;
/* load whatever's lurking in the .afnirc files */
/* passing NULL for dc (the last parameter) because I
am not using the continuous color maps yet */
SUMA_LH("Calling Process setup");
homeenv = getenv("HOME");
if (!homeenv) sumarc = SUMA_copy_string(".afnirc");
else sumarc = SUMA_append_string (homeenv, "/.afnirc");
if (stat(sumarc, &stbuf) != -1) {
if (LocalHead) fprintf (SUMA_STDERR,"%s: Loading %s ...\n", FuncName, sumarc);
if (SUMA_AFNI_Extract_Colors ( sumarc, SAC ) < 0) {
fprintf(SUMA_STDERR,"Error %s: Failed scanning .afnirc for colors and colormaps.\nProceeding ...\n", FuncName);
}
} else {
if (LocalHead) fprintf (SUMA_STDERR,"%s: No rc files found.\n", FuncName);
}
if (sumarc) SUMA_free(sumarc);
/* Show me the results: */
if (LocalHead_Detail) {
SUMA_Show_ColorVec (SAC->Cv, SAC->N_cols, NULL);
}
if (LocalHead_Detail) {
SUMA_Show_ColorMapVec (SAC->CMv, SAC->N_maps, NULL, 1);
}
SUMA_LH("Returning");
SUMA_RETURN(SAC);
}
/*!
\brief creates the colormaps available for SUMA
*/
SUMA_AFNI_COLORS *SUMA_Build_Color_maps(void)
{
static char FuncName[]={"SUMA_Build_Color_maps"};
SUMA_RGB_NAME *Cv = NULL;
int i;
SUMA_COLOR_MAP **CMv=NULL;
SUMA_COLOR_MAP *CM=NULL;
SUMA_AFNI_COLORS *SAC=NULL;
SUMA_ENTRY;
SAC = SUMA_Get_AFNI_Default_Color_Maps();
/* Now add SUMA's colormaps */
for (i=SUMA_CMAP_UNDEFINED+1; i<SUMA_CMAP_N_MAPS; ++i) {
CM = SUMA_GetStandardMap (i);
if (!CM) {
SUMA_SL_Crit("Failed to create standard maps");
SUMA_RETURN(NULL);
}
SAC->CMv = SUMA_Add_ColorMap (CM, SAC->CMv, &(SAC->N_maps));
if (!SAC->CMv) {
SUMA_SL_Crit("Failed in SUMA_Add_ColorMap");
SUMA_RETURN(NULL);
}
}
SUMA_RETURN(SAC);
}
/*! \brief A function to add a new color to the color vector
\param Name (char *) name of new color to be added
\param r (float) r color ( 0 <= r <= 1)
\param g (float) g color ( 0 <= g <= 1)
\param b (float) b color ( 0 <= b <= 1)
\param a (float) a color ( 0 <= a <= 1)
- You are allowed to pass -1.0, -1.0, -1.0 for r g b to define the No-Color
\param oCv (SUMA_RGB_NAME*) old vector containing color structs
\param N_cols (int *) number of colors in oCv
When the function returns, this number will include the added
color
\return NewCv (SUMA_RGB_NAME *) you know what.
If the color being added exists (by Name), it will replace
the preexisting one
- New space is allocated for each new color (realloc).
- This process is not terribly efficient by not many colors
are loaded in this manner.
- You can send NULL for oCv if this vector has yet to be created
*/
SUMA_RGB_NAME * SUMA_Add_Color (char *Name, float r, float g, float b, float a, SUMA_RGB_NAME *oCv, int *N_cols)
{
static char FuncName[]={"SUMA_Add_Color"};
SUMA_RGB_NAME *NewCv = NULL;
int iadd;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!(r == -1.0 && g == -1.0 && b == -1.0)) {
if ( r < 0 || r > 1 ||
g < 0 || g > 1 ||
b < 0 || b > 1 ||
a < 0 || a > 1 ) {
SUMA_S_Err("Bad r, g, b and/or a values.\nMust be between 0 and 1.Nothing done.");
SUMA_RETURN(oCv);
}
}else {
SUMA_LH("No color");
}
if (strlen(Name) > SUMA_MAX_COLOR_NAME -1 ) {
SUMA_S_Err("Too long a color name\n(> SUMA_MAX_COLOR_NAME)\nNothing done.");
SUMA_RETURN(oCv);
}
if (!oCv) {
SUMA_LH("New color vector, allocating");
NewCv = (SUMA_RGB_NAME *) SUMA_calloc(1, sizeof(SUMA_RGB_NAME));
*N_cols = 1;
NewCv[*N_cols-1].r = r;
NewCv[*N_cols-1].g = g;
NewCv[*N_cols-1].b = b;
NewCv[*N_cols-1].a = a;
sprintf(NewCv[*N_cols-1].Name, "%s", Name);
SUMA_RETURN(NewCv);
}
/* not new, check to see if color exists already */
iadd = SUMA_Find_Color (Name, oCv, *N_cols);
if (iadd >= 0) {
SUMA_LH("Replacing old color");
NewCv = oCv;
NewCv[iadd].r = r;
NewCv[iadd].g = g;
NewCv[iadd].b = b;
NewCv[iadd].a = a;
SUMA_RETURN(oCv);
}
/* a new map altogether */
SUMA_LH("Adding new color");
*N_cols += 1;
NewCv = (SUMA_RGB_NAME *) SUMA_realloc(oCv, *N_cols * sizeof(SUMA_RGB_NAME));
NewCv[*N_cols-1].r = r;
NewCv[*N_cols-1].g = g;
NewCv[*N_cols-1].b = b;
NewCv[*N_cols-1].a = a;
sprintf(NewCv[*N_cols-1].Name, "%s", Name);
SUMA_RETURN(NewCv);
}
/*! \brief A function to add a new colormap to the colormap vector
\param CM (SUMA_COLOR_MAP *) new color map to be added
\param OldCMv (SUMA_COLOR_MAP **) old vector containing pointers to colormaps
\param N_map (int *) number of maps in OldCMv
When the function returns, this number will include the added
map
\return NewCMv (SUMA_COLOR_MAP **) you know what.
If the map being added exists (by Name), it will replace
the preexisting one
- New space is allocated for each new map (realloc).
- This process is not terribly efficient by not many maps
are loaded in this manner.
- You can send NULL for OldCMv if this vector has yet to be created
- Color map structure is copied by reference. Do not free it.
*/
SUMA_COLOR_MAP ** SUMA_Add_ColorMap (SUMA_COLOR_MAP *CM, SUMA_COLOR_MAP **OldCMv, int *N_maps)
{
static char FuncName[]={"SUMA_Add_ColorMap"};
SUMA_COLOR_MAP ** NewCMv = NULL;
int iadd;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!CM) {
SUMA_S_Warn("Null CM, nothing to do");
SUMA_RETURN(OldCMv);
}
if (!OldCMv) {
SUMA_LH("New color vector, allocating");
NewCMv = (SUMA_COLOR_MAP **) SUMA_calloc(1, sizeof(SUMA_COLOR_MAP *));
*N_maps = 1;
NewCMv[0] = CM;
SUMA_RETURN(NewCMv);
}
/* not new, check to see if map exists already */
iadd = SUMA_Find_ColorMap (CM->Name, OldCMv, *N_maps, CM->Sgn);
if (iadd >= 0) {
SUMA_LH("Replacing old colormap");
SUMA_Free_ColorMap (OldCMv[iadd]);
OldCMv[iadd] = CM;
SUMA_RETURN(OldCMv);
}
/* a new map altogether */
SUMA_LH("Adding new color map");
*N_maps += 1;
NewCMv = (SUMA_COLOR_MAP **) SUMA_realloc(OldCMv, *N_maps * sizeof(SUMA_COLOR_MAP *));
NewCMv[*N_maps - 1] = CM;
SUMA_RETURN(NewCMv);
}
/*!
\brief Cleans up and destroys the contents of the SUMA_AFNI_COLORS
\sa SUMA_Get_AFNI_Default_Color_Maps
*/
SUMA_AFNI_COLORS *SUMA_DestroyAfniColors (SUMA_AFNI_COLORS *SAC)
{
static char FuncName[]={"SUMA_DestroyAfniColors"};
int i;
SUMA_ENTRY;
if (!SAC) SUMA_RETURN(NULL);
/* Now clean the colormap vector */
for (i=0; i < SAC->N_maps; ++i) {
if (SAC->CMv[i]) SUMA_Free_ColorMap(SAC->CMv[i]);
}
SUMA_free(SAC->CMv);
SAC->N_maps = -1;
/* Now clean the color vector */
SUMA_free(SAC->Cv);
SAC->N_cols = -1;
/* Now destroy SAC */
SUMA_free(SAC);
SUMA_RETURN(NULL);
}
/*!
\brief List the colors in the vector
\sa char *SUMA_Show_ColorVec
*/
char *SUMA_ColorVec_Info (SUMA_RGB_NAME *Cv, int N_cols)
{
static char FuncName[]={"SUMA_ColorVec_Info"};
int i;
char stmp[100], *s = NULL;
SUMA_STRING *SS = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
SS = SUMA_StringAppend (NULL, NULL);
if (Cv) {
for (i=0; i < N_cols; ++i) {
if (Cv[i].r == -1) {
sprintf (stmp, "%d/%d: color(%d) No Color(%s): [%f %f %f %f]\n",
i+1, N_cols, i, Cv[i].Name, Cv[i].r, Cv[i].g, Cv[i].b, Cv[i].a);
SS = SUMA_StringAppend (SS, stmp);
} else {
sprintf (stmp, "%d/%d: color(%d) %s: [%f %f %f %f]\n",
i+1, N_cols, i, Cv[i].Name, Cv[i].r, Cv[i].g, Cv[i].b, Cv[i].a);
SS = SUMA_StringAppend (SS, stmp);
}
}
} else {
sprintf (stmp, "NULL Cv.\n");
SS = SUMA_StringAppend (SS, stmp);
}
/* clean SS */
SS = SUMA_StringAppend (SS, NULL);
/* copy s pointer and free SS */
s = SS->s;
SUMA_free(SS);
SUMA_RETURN(s);
}
/*!
return a color in acol (4 floats) from colormap name color index i % Ncolors
if name is NULL a random color is returned
*/
int SUMA_a_good_col(char *name, int i, float *acol)
{
static char FuncName[]={"SUMA_a_good_col"};
int ic, icmap, dorand;
SUMA_COLOR_MAP *CM;
SUMA_ENTRY;
dorand = 0;
if (i<0 || !acol) {
SUMA_S_Err("Give me a break!");
SUMA_RETURN(0);
}
if (!name || !(SUMAg_CF && SUMAg_CF->scm && SUMAg_CF->scm->CMv && SUMAg_CF->scm->N_maps)) {
dorand = 1;
} else {
/* have colormaps, get me something decent */
icmap = SUMA_Find_ColorMap(name, SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps,-2);
if (icmap < 0) {
SUMA_S_Warnv("No colormap named %s was found, returning random colors.\n", name);
dorand = 1;
}
}
if (dorand) {
/* GIMME SOME RANDOM */
srand(i);
acol[0] = (float) (double)rand()/(double)RAND_MAX;
acol[1] = (float) (double)rand()/(double)RAND_MAX;
acol[2] = (float) (double)rand()/(double)RAND_MAX;
acol[3] = 1.0;
SUMA_RETURN(1);
} else {
CM = SUMAg_CF->scm->CMv[icmap];
ic = i % CM->N_Col;
acol[0] = CM->M[ic][0];
acol[1] = CM->M[ic][1];
acol[2] = CM->M[ic][2];
acol[3] = 1.0;
}
SUMA_RETURN(1);
}
/*!
\brief List the colormaps in the vector
\param CMv (SUMA_COLOR_MAP **) an array of pointers to colormap structures
\param N_maps (int) the number of colormaps in CMv
\param detail (int) 0, just the name of the colormaps
1, up to 5 of the colors listed
2, complete colormap listed
\sa char *SUMA_Show_ColorMapVec
*/
char *SUMA_ColorMapVec_Info (SUMA_COLOR_MAP **CMv, int N_maps, int detail)
{
static char FuncName[]={"SUMA_ColorMapVec_Info"};
int i, j, jmax;
char stmp[256], *s = NULL;
SUMA_STRING *SS = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
SUMA_LH("Entered");
SS = SUMA_StringAppend (NULL, NULL);
if (CMv) {
for (i=0; i < N_maps; ++i) {
if (!CMv[i]) {
sprintf (stmp, "%d/%d: cmap(%d) NULL\n", i+1, N_maps, i);
SS = SUMA_StringAppend (SS, stmp);
} else {
switch (CMv[i]->Sgn) {
case 0:
sprintf (stmp, "%d/%d: cmap(%d) %s(.), %d cols.", i+1, N_maps, i, CMv[i]->Name, CMv[i]->N_Col);
break;
case 1:
sprintf (stmp, "%d/%d: cmap(%d) %s(+), %d cols.", i+1, N_maps, i, CMv[i]->Name, CMv[i]->N_Col);
break;
case -1:
sprintf (stmp, "%d/%d: cmap(%d) %s(-), %d cols.", i+1, N_maps, i, CMv[i]->Name, CMv[i]->N_Col);
break;
default:
sprintf (stmp, "%d/%d: cmap(%d) %s(?), %d cols.\n\tSgn field of colormap is not acceptable (%d)\n",
i+1, N_maps, i, CMv[i]->Name, CMv[i]->N_Col, CMv[i]->Sgn);
break;
}
SS = SUMA_StringAppend (SS, stmp);
if (CMv[i]->frac) {
SS = SUMA_StringAppend (SS, " Possibly non-linear\n");
} else {
SS = SUMA_StringAppend (SS, " Linear\n");
}
switch (detail) {
case 0:
jmax = 0;
break;
case 1:
if (CMv[i]->N_Col < 5) jmax = CMv[i]->N_Col;
else jmax = 5;
break;
case 2:
jmax = CMv[i]->N_Col;
break;
default:
SUMA_SL_Err("Bad detail value\nUsing detail = 2");
jmax = CMv[i]->N_Col;
break;
}
if (jmax) {
for (j=jmax-1; j >= 0; --j) {
if (CMv[i]->frac) {
if (j == jmax -1) {
sprintf (stmp, "rank (i)[R \tG \tB \t\tf]\n");
SS = SUMA_StringAppend (SS,stmp);
}
sprintf (stmp, "%03d:\t[% .3f\t% .3f\t% .3f\t\t% .3f]\n",
j, CMv[i]->M[j][0], CMv[i]->M[j][1], CMv[i]->M[j][2], CMv[i]->frac[j]);
} else {
if (j == jmax - 1) {
sprintf (stmp, "rank (i):[R \tG \tB ]\n");
SS = SUMA_StringAppend (SS,stmp);
}
sprintf (stmp, "%03d:\t[% .3f\t% .3f\t% .3f]\n",
j, CMv[i]->M[j][0], CMv[i]->M[j][1], CMv[i]->M[j][2]);
}
SS = SUMA_StringAppend (SS,stmp);
}
if (jmax < CMv[i]->N_Col - 1) {
if (CMv[i]->frac) SS = SUMA_StringAppend (SS,"..:\t [.....\t....\t....\t\t....]\n");
else SS = SUMA_StringAppend (SS,"..:\t [.....\t....\t....]\n");
}
if (jmax < CMv[i]->N_Col) {
j = CMv[i]->N_Col - 1;
if (CMv[i]->frac) {
sprintf (stmp, "%03d:\t [% .3f\t% .3f\t% .3f\t\t% .3f]\n",
j, CMv[i]->M[j][0], CMv[i]->M[j][1], CMv[i]->M[j][2], CMv[i]->frac[j]);
} else {
sprintf (stmp, "%03d:\t [% .3f\t% .3f\t% .3f]\n",
j, CMv[i]->M[j][0], CMv[i]->M[j][1], CMv[i]->M[j][2]);
}
SS = SUMA_StringAppend (SS,stmp);
}
}
}
}
} else {
sprintf (stmp, "NULL CMv.\n");
SS = SUMA_StringAppend (SS, stmp);
}
/* clean SS */
SS = SUMA_StringAppend (SS, NULL);
/* copy s pointer and free SS */
s = SS->s;
SUMA_free(SS);
SUMA_LH("Left");
SUMA_RETURN(s);
}
/*!
\brief Shows the contents of the color vector
\sa SUMA_ColorVec_Info
*/
void SUMA_Show_ColorVec (SUMA_RGB_NAME *CMv, int N_maps, FILE *Out)
{
static char FuncName[]={"SUMA_Show_ColorVec"};
char *s;
SUMA_ENTRY;
if (Out == NULL) Out = stdout;
s = SUMA_ColorVec_Info(CMv, N_maps);
if (s) {
fprintf (Out, "%s", s);
SUMA_free(s);
}else {
fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_ColorVec_Info.\n", FuncName);
}
SUMA_RETURNe;
}
/*!
\brief Shows the contents of the colormaps vector
\sa SUMA_ColorMapVec_Info
*/
void SUMA_Show_ColorMapVec (SUMA_COLOR_MAP **CMv, int N_maps, FILE *Out, int detail)
{
static char FuncName[]={"SUMA_Show_ColorMapVec"};
char *s;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (Out == NULL) Out = stdout;
s = SUMA_ColorMapVec_Info(CMv, N_maps, detail);
if (s) {
fprintf (Out, "%s", s);
SUMA_free(s);
}else {
fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_ColorMapVec_Info.\n", FuncName);
}
SUMA_RETURNe;
}
/*!
\brief Locate a color in the color vector
\param Name (char *) Name ('\0' terminated) name of color to be found
\param Cv (SUMA_RGB_NAME *) vector of color structs to be searched
\param N_cols (int) number of colors in Cv
\return icol (int) the index into Cv where the color named Name was found
(-1) if no such color was found
*/
int SUMA_Find_Color ( char *Name, SUMA_RGB_NAME *Cv, int N_cols)
{
static char FuncName[]={"SUMA_Find_Color"};
int icol = -1, i;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!Cv) {
SUMA_S_Warn("Nothing to do. NULL Cv");
SUMA_RETURN(icol);
}
for (i=0; i < N_cols; ++i) {
if (strcmp(Cv[i].Name, Name) == 0) {
SUMA_LH("Found Color");
icol = i;
SUMA_RETURN(icol);
}
}
SUMA_LH("Failed to find color");
SUMA_RETURN(icol);
}
/*!
\brief Locate a colormap in the colormap vector
\param Name (char *) Name ('\0' terminated) name of colormap to be found
\param CMv (SUMA_COLOR_MAP **) vector of pointers to colormaps to be searched
\param N_maps (int) number of maps in CMv
\param sgn (int) the sign of the map (-1, 0, +1)
if sign = -2 then the sign is completely ignored and
only Name is used for a match
\return imap (int) the index into CMv where the colormap named Name was found
(-1) if no such map was found
*/
int SUMA_Find_ColorMap ( char *Name, SUMA_COLOR_MAP **CMv, int N_maps, int sgn)
{
static char FuncName[]={"SUMA_Find_ColorMap"};
int imap = -1, i;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!CMv) {
SUMA_S_Warn("Nothing to do. NULL CMv");
SUMA_RETURN(imap);
}
for (i=0; i < N_maps; ++i) {
if (CMv[i]) {
if (sgn != -2) {
if (strcmp(CMv[i]->Name, Name) == 0 && CMv[i]->Sgn == sgn) {
SUMA_LH("Found Map");
imap = i;
SUMA_RETURN(imap);
}
} else {
/* don't care about sign */
if (strcmp(CMv[i]->Name, Name) == 0 ) {
SUMA_LH("Found Map");
imap = i;
SUMA_RETURN(imap);
}
}
}
}
SUMA_LH("Failed to find map");
SUMA_RETURN(imap);
}
/*!
function that reads in a 1D format color map file
1D format contains 3 or 4 columns:
3 columns: R G B
4 columns: R G B frac
R G B are float values between 0 and 1.0 specifying the R G B colors
frac is the fraction of the color map assigned to each color. These
are the same numbers shown to the right of the colormap in AFNI
Sept 22 04: you can specify integer values between 0 and 255 for
the RGB values if you wish
The colormap files are specified in the order adopted in AFNI's palette files
The last row in the file is the first color (bottom color) in the map.
If you specify frac then the lowest fraction must be at the bottom row
*/
SUMA_COLOR_MAP *SUMA_Read_Color_Map_1D (char *Name)
{
static char FuncName[]={"SUMA_Read_Color_Map_1D"};
MRI_IMAGE *im = NULL;
float *far=NULL;
float ColSum;
int i=0;
SUMA_COLOR_MAP* SM = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!Name) {
SUMA_S_Err("NULL file name");
SUMA_RETURN(SM);
}
/* read the colormap 1D file */
im = mri_read_1D (Name);
if (!im) {
SUMA_S_Err("Failed to read file");
SUMA_RETURN(NULL);
}
/* check for sizes */
if (im->ny != 3 && im->ny != 4) {
SUMA_S_Err("File must contain 3 or 4 columns only");
SUMA_RETURN(NULL);
}
/* allocate for SM */
SM = (SUMA_COLOR_MAP*) SUMA_malloc(sizeof(SUMA_COLOR_MAP));
SM->top_frac = 0.0f;
SM->SO = NULL;
SM->cname = NULL;
SM->N_Col = im->nx;
SM->Name = (char *)SUMA_malloc(sizeof(char)*(strlen(Name)+1));
sprintf(SM->Name, "%s", Name);
if (im->ny == 4) {
SM->frac = (float*) SUMA_calloc(im->nx, sizeof(float));
} else {
SM->frac = NULL;
}
SM->M = (float**)SUMA_allocate2D (SM->N_Col, 3, sizeof(float));
far = MRI_FLOAT_PTR(im);
ColSum = 0;
if (im->ny == 4) {
SM->Sgn = 1;
for (i=0; i < im->nx; ++i) {
SM->M[SM->N_Col - i - 1][0] = far[i]; ColSum += far[i];
SM->M[SM->N_Col - i - 1][1] = far[i+im->nx]; ColSum += far[i+im->nx];
SM->M[SM->N_Col - i - 1][2] = far[i+2*im->nx]; ColSum += far[i+2*im->nx];
SM->frac[SM->N_Col - i - 1] = far[i+3*im->nx];
if (SM->frac[SM->N_Col - i - 1] < 0.0) SM->Sgn = -1;
}
} else {
SM->Sgn = 0;
for (i=0; i < im->nx; ++i) {
SM->M[SM->N_Col - i - 1][0] = far[i]; ColSum += far[i];
SM->M[SM->N_Col - i - 1][1] = far[i+im->nx]; ColSum += far[i+im->nx];
SM->M[SM->N_Col - i - 1][2] = far[i+2*im->nx]; ColSum += far[i+2*im->nx];
}
}
ColSum = ColSum / (3.0 * SM->N_Col);
if (ColSum > 1) {
/* looks like colormap values are between 0 and 255 */
for (i=0; i < SM->N_Col; ++i) {
SM->M[i][0] /= 255.0; SM->M[i][1] /= 255.0; SM->M[i][2] /= 255.0;
}
}
/* check on craziness in frac */
if (SM->frac && SM->N_Col > 1) {
for (i=0; i < im->nx-1; ++i) {
if (SM->frac[i] > SM->frac[i+1]) {
SUMA_S_Err("Fractions must be specified in monotonic\n descending order from the top to the bottom of the column");
SUMA_Free_ColorMap (SM); mri_free(im);
SUMA_RETURN(NULL);
}
}
}
mri_free(im); im = NULL;
if (LocalHead) {
fprintf (SUMA_STDERR,"%s: Colormap read:\n", FuncName);
if (SM->frac) {
for (i=0; i < SM->N_Col; ++i) {
fprintf (SUMA_STDOUT,"%f\t%f\t%f\t%f\n", SM->M[i][0], SM->M[i][1], SM->M[i][2], SM->frac[i]);
}
} else SUMA_disp_mat (SM->M, SM->N_Col, 3, 1);
}
SUMA_RETURN (SM);
}
/*! function that turns a non-linear color map into a linear one
The larger the number of colors in the linear color map, the close the
approximation to the non-linear map.
\param SM (SUMA_COLOR_MAP*) a non-linear colormap (i.e. SM->frac != NULL)
\param N_Lin (int) number of colors to use in the linear version of the map
if N_Lin = -1, N_Lin is set to 1024
\return LSM (SUMA_COLOR_MAP*) linear version of the colormap
NULL if SM is already linear
NULL if SM is NULL
*/
SUMA_COLOR_MAP *SUMA_Linearize_Color_Map (SUMA_COLOR_MAP* SM, int N_lin)
{
static char FuncName[]={"SUMA_Linearize_Color_Map"};
SUMA_COLOR_MAP* LSM = NULL;
int ilin = 0, i = 0, ilin_stp = -1;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!SM) {
SUMA_S_Err("NULL color map");
SUMA_RETURN(LSM);
}
if (!SM->frac) {
SUMA_S_Err("NULL SM->frac!\nMap is linear");
SUMA_RETURN(LSM);
}
if (N_lin < 0) N_lin = 2048; /* 2048 set default linear map length */
if (!N_lin) {
SUMA_S_Err("N_lin = 0");
SUMA_RETURN(LSM);
}
/* allocate for new map */
SUMA_LH("Allocating for new map");
LSM = (SUMA_COLOR_MAP *)SUMA_malloc(sizeof(SUMA_COLOR_MAP));
if (LSM == NULL) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for LSM.\n", FuncName);
SUMA_RETURN (NULL);
}
LSM->top_frac = 0.0f;
LSM->SO = NULL;
LSM->Name = (char *)SUMA_calloc(strlen(SM->Name)+10, sizeof(char));
if (LSM->Name == NULL) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for LSM->Name.\n", FuncName);
SUMA_free(LSM);
SUMA_RETURN (NULL);
}
sprintf(LSM->Name, "%s_lin",SM->Name);
LSM->N_Col = N_lin;
LSM->frac = NULL;
LSM->cname = NULL;
LSM->Sgn = SM->Sgn;
SUMA_LHv("Allocating for %d cols\n", LSM->N_Col);
LSM->M = (float **)SUMA_allocate2D (LSM->N_Col, 3, sizeof(float));
if (LSM->M == NULL) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for LSM->M.\n", FuncName);
SUMA_free(LSM->Name);
SUMA_free(LSM);
SUMA_RETURN (NULL);
}
if (SM->frac[SM->N_Col-1] != 1.0f) {
LSM->top_frac = SM->frac[SM->N_Col-1];
}
ilin = 0;
for (i=0; i < SM->N_Col; ++i) {
SUMA_LHv("SM->frac[%d]=%f, tf = %f , [%f %f %f]", i, SM->frac[i], SM->frac[SM->N_Col-1], SM->M[i][0], SM->M[i][1], SM->M[i][2]);
if (LSM->Sgn >= 0) {
ilin_stp = (int)(ceil((double)(SM->frac[i]/SM->frac[SM->N_Col-1]) * (double)LSM->N_Col)) - 1;
} else {
ilin_stp = (int)(ceil( (1.0 + (double)(SM->frac[i]/SM->frac[SM->N_Col-1])) * (double)LSM->N_Col/2 ) ) - 1;
}
while (ilin < ilin_stp && ilin < LSM->N_Col) {
LSM->M[ilin][0] = SM->M[i][0];
LSM->M[ilin][1] = SM->M[i][1];
LSM->M[ilin][2] = SM->M[i][2];
++ilin;
}
}
/* copy last value */
LSM->M[LSM->N_Col-1][0] = SM->M[SM->N_Col-1][0];
LSM->M[LSM->N_Col-1][1] = SM->M[SM->N_Col-1][1];
LSM->M[LSM->N_Col-1][2] = SM->M[SM->N_Col-1][2];
if (LocalHead) {
for (i=0; i < LSM->N_Col; ++i) {
fprintf (SUMA_STDOUT,"%d:\t%f\t%f\t%f\n", i, LSM->M[i][0], LSM->M[i][1], LSM->M[i][2]);
}
fprintf (SUMA_STDOUT,"%s: ilin_stp = %d\n", FuncName, ilin_stp);
}
SUMA_RETURN(LSM);
}
/*!----------------------------------------------------------------------
* sprintf_long_to_hex - write hex chars to a string
*
* return number of hex pairs written (should equal bytes)
*----------------------------------------------------------------------
*/
int r_sprintf_long_to_hex
(
char * dest, /* location of output string */
unsigned long lsrc, /* number to translate */
int bytes, /* total bytes (hex pairs) */
int pad /* pad the result? */
)
{
static char hexstring[] = "0123456789ABCDEF";
unsigned char ub;
char * cp = dest;
int posn, size, ret;
if ( (bytes <= 0) || (bytes > 4) )
{
*cp = '\0';
return 0;
}
size = r_ulong_size( lsrc );
if ( (size < bytes) && !pad )
ret = size;
else
ret = bytes;
for ( posn = ret-1; posn >= 0; posn-- )
{
/* write one hex pair for this byte */
ub = ( lsrc >> (posn << 3) ) & 0xff; /* current ubyte */
*cp++ = hexstring[(ub>>4) & 0xf]; /* upper nibble */
*cp++ = hexstring[ ub & 0xf]; /* lower nibble */
}
*cp = '\0';
return ret;
}
/* return number of bytes needed to represent a long - return at least 1 */
int r_ulong_size ( unsigned long l )
{
if ( l & 0xff000000 )
return 4;
if ( l & 0xff0000 )
return 3;
if ( l & 0xff00 )
return 2;
return 1;
}
/*!
\brief Find the colormap associated with a colorplane
\return SUMA_COLOR_MAP * NULL if error or if cmap is explicit
*/
SUMA_COLOR_MAP *SUMA_CmapOfPlane (SUMA_OVERLAYS *Sover )
{
static char FuncName[]={"SUMA_CmapOfPlane"};
SUMA_COLOR_MAP *ColMap = NULL;
int icmap;
SUMA_ENTRY;
if (!Sover) { SUMA_SL_Err("NULL Sover"); SUMA_RETURN(ColMap); }
if (!Sover->cmapname) { SUMA_SL_Err("NULL Colormap name"); SUMA_RETURN(ColMap); }
if (strcmp(Sover->cmapname, "explicit") == 0) {
SUMA_RETURN(NULL);
}
if (!SUMAg_CF->scm) {
SUMAg_CF->scm = SUMA_Build_Color_maps();
if (!SUMAg_CF->scm) {
SUMA_SL_Err("Can't build color maps");
SUMA_RETURN(ColMap);
}
}
icmap = SUMA_Find_ColorMap ( Sover->cmapname, SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps, -2 );
if (icmap < 0) { SUMA_SL_Err("Failed to find ColMap"); SUMA_RETURN(ColMap); }
ColMap = SUMAg_CF->scm->CMv[icmap];
SUMA_RETURN(ColMap);
}
/* Removes pre-existing bias
DOES NOT free bias vector
DOES NOT SET OptScl->DoBias to SW_CoordBias_None
The last two operations should be carried out once the bias is removed from all surfaces
to which they'd been applied. In this case it will be in SUMA_RemoveCoordBias
This function should not be called directly, only from SUMA_RemoveCoordBias
*/
SUMA_Boolean SUMA_RemoveSO_CoordBias(SUMA_SurfaceObject *SO, SUMA_OVERLAYS *ovr)
{
static char FuncName[]={"SUMA_RemoveSO_CoordBias"};
int i, i3, x_i3;
SUMA_ENTRY;
if (!SO || !ovr) {
SUMA_SL_Err("Dim dim diM");
SUMA_RETURN(NOPE);
}
x_i3 = 3*SO->N_Node;
if (ovr->OptScl->BiasVect) { /* something to be removed */
switch (ovr->OptScl->DoBias) {
case SW_CoordBias_X:
/* Remove X bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i];
if (i3 < x_i3) SO->NodeList[i3] -= ovr->OptScl->BiasVect[i];
}
break;
case SW_CoordBias_Y:
/* Remove Y bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i]+1;
if (i3 < x_i3) SO->NodeList[i3] -= ovr->OptScl->BiasVect[i];
}
break;
case SW_CoordBias_Z:
/* Remove Z bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i]+2;
if (i3 < x_i3) SO->NodeList[i3] -= ovr->OptScl->BiasVect[i];
}
break;
case SW_CoordBias_N:
/* Remove Normal bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i];
if (i3 < x_i3) {
SO->NodeList[i3] -= ovr->OptScl->BiasVect[i] * SO->NodeNormList[i3]; ++i3;
SO->NodeList[i3] -= ovr->OptScl->BiasVect[i] * SO->NodeNormList[i3]; ++i3;
SO->NodeList[i3] -= ovr->OptScl->BiasVect[i] * SO->NodeNormList[i3];
}
}
break;
default:
SUMA_SL_Err("This should not be");
SUMA_RETURN(NOPE);
}
} else {
SUMA_SL_Err("DO not call me with no bias!");
SUMA_RETURN(NOPE);
}
/* Update surface geometry properties */
SUMA_NewSurfaceGeometry(SO);
SUMA_RETURN(YUP);
}
/* Removes pre-existing bias to old dimension
Add same bias to BiasDim dimension
sets OptScl->DoBias to BiasDim
*/
SUMA_Boolean SUMA_TransferCoordBias(SUMA_OVERLAYS *ovr, SUMA_WIDGET_INDEX_COORDBIAS BiasDim)
{
static char FuncName[]={"SUMA_TransferCoordBias"};
SUMA_SurfaceObject *SO=NULL;
int iso;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!ovr) SUMA_RETURN(YUP);
for (iso=0; iso<SUMAg_N_DOv; ++iso) {
if (SUMA_isSO(SUMAg_DOv[iso])) {
SO = (SUMA_SurfaceObject *)SUMAg_DOv[iso].OP;
if (SUMA_isOverlayOfSO(SO, ovr)) {
SUMA_TransferSO_CoordBias(SO, ovr, BiasDim);
}
}
}
SUMA_LH("Setting bias flag");
ovr->OptScl->DoBias = BiasDim;
SUMA_RETURN(YUP);
}
/*!
Single surface version of SUMA_TransferCoordBias DO NOT CALL THIS FUNCTION OUTSIDE OF SUMA_TransferCoordBias
*/
SUMA_Boolean SUMA_TransferSO_CoordBias(SUMA_SurfaceObject *SO, SUMA_OVERLAYS *ovr, SUMA_WIDGET_INDEX_COORDBIAS BiasDim)
{
static char FuncName[]={"SUMA_TransferSO_CoordBias"};
SUMA_Boolean LocalHead = NOPE;
int i, i3;
SUMA_ENTRY;
SUMA_LH("Called");
if (ovr->OptScl->BiasVect) {
SUMA_LH("Removing old bias");
/* Remove old bias */
switch (ovr->OptScl->DoBias) {
case SW_CoordBias_X:
/* Remove X bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i];
SO->NodeList[i3] -= ovr->OptScl->BiasVect[i];
}
break;
case SW_CoordBias_Y:
/* Remove Y bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i]+1;
SO->NodeList[i3] -= ovr->OptScl->BiasVect[i];
}
break;
case SW_CoordBias_Z:
/* Remove Z bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i]+2;
SO->NodeList[i3] -= ovr->OptScl->BiasVect[i];
}
break;
case SW_CoordBias_N:
/* Remove Normal bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i];
SO->NodeList[i3] -= ovr->OptScl->BiasVect[i] * SO->NodeNormList[i3]; ++i3;
SO->NodeList[i3] -= ovr->OptScl->BiasVect[i] * SO->NodeNormList[i3]; ++i3;
SO->NodeList[i3] -= ovr->OptScl->BiasVect[i] * SO->NodeNormList[i3];
}
break;
default:
SUMA_SL_Err("This should not be");
SUMA_RETURN(NOPE);
}
SUMA_LH("Adding new bias");
#if 0
/* Add same bias to other direction */
switch (BiasDim) {
case SW_CoordBias_X:
/* Add X bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i];
SO->NodeList[i3] += ovr->OptScl->BiasVect[i];
}
break;
case SW_CoordBias_Y:
/* Add Y bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i]+1;
SO->NodeList[i3] += ovr->OptScl->BiasVect[i];
}
break;
case SW_CoordBias_Z:
/* Add Z bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i]+2;
SO->NodeList[i3] += ovr->OptScl->BiasVect[i];
}
break;
case SW_CoordBias_N:
/* Add Normal bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i];
SO->NodeList[i3] += ovr->OptScl->BiasVect[i] * SO->NodeNormList[i3]; ++i3;
SO->NodeList[i3] += ovr->OptScl->BiasVect[i] * SO->NodeNormList[i3]; ++i3;
SO->NodeList[i3] += ovr->OptScl->BiasVect[i] * SO->NodeNormList[i3];
}
break;
default:
SUMA_SL_Err("This should not be.\nWhy, oh why ?");
SUMA_RETURN(NOPE);
}
#else
/* Add same bias to other direction */
SUMA_ADD_COORD_BIAS_VECT(SO, ovr, BiasDim, ovr->OptScl->BiasVect);
#endif
}
/* Update surface geometry properties */
SUMA_NewSurfaceGeometry(SO);
SUMA_RETURN(YUP);
}
/*!
Function called when a surface's geometry is changed (currently due to a change in the CoordBias)
*/
SUMA_Boolean SUMA_NewSurfaceGeometry(SUMA_SurfaceObject *SO)
{
static char FuncName[]={"SUMA_NewSurfaceGeometry"};
int ii, i;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
/* first recompute the bounding box of the surface */
/* Calculate Min, Max, Mean */
SUMA_MIN_MAX_SUM_VECMAT_COL (SO->NodeList, SO->N_Node, SO->NodeDim, SO->MinDims, SO->MaxDims, SO->Center);
SO->Center[0] /= SO->N_Node;
SO->Center[1] /= SO->N_Node;
SO->Center[2] /= SO->N_Node;
SUMA_MIN_VEC (SO->MinDims, 3, SO->aMinDims );
SUMA_MAX_VEC (SO->MaxDims, 3, SO->aMaxDims);
/* find out what viewers this surface is registered with and which viewers show it */
for (ii=0; ii<SUMAg_N_SVv; ++ii) {
if (!SUMAg_SVv[ii].isShaded && SUMAg_SVv[ii].X->TOPLEVEL) {
for (i=0; i< SUMAg_SVv[ii].N_DO; ++i) {
if (SUMA_isSO_G(SUMAg_DOv[SUMAg_SVv[ii].RegisteredDO[i]], SUMAg_SVv[ii].CurGroupName)) {
/* is this surface the same as SO ? */
if (SUMA_findSO_inDOv(SO->idcode_str, SUMAg_DOv, SUMAg_N_DOv) == SUMAg_SVv[ii].RegisteredDO[i]) {
/* This surface is visible in this viewer, mark that viewer */
SUMA_LH("Marking Viewer ");
SUMAg_SVv[ii].NewGeom = YUP;
}
}
}
}
}
SUMA_RETURN(YUP);
}
/*
- adds new bias
- DOES NOT copy NewBias to OptScl->BiasVect
- DOES NOT set OptScl->DoBias to BiasDim
The previous 2 operations are to be done in SUMA_SetCoordBias which call this function for all
surfaces using this overlay plane
*/
SUMA_Boolean SUMA_SetSO_CoordBias(SUMA_SurfaceObject *SO, SUMA_OVERLAYS *ovr, float *NewBias, SUMA_WIDGET_INDEX_COORDBIAS BiasDim)
{
static char FuncName[]={"SUMA_SetSO_CoordBias"};
int i, i3;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!ovr) {
SUMA_SL_Err("NULL ovr");
SUMA_RETURN(NOPE);
}
if (!ovr->NodeDef) {
SUMA_SL_Err("NULL ovr->NodeDef");
SUMA_RETURN(NOPE);
}
/* Now add the new one */
if (NewBias) {
#if 0
switch (BiasDim) {
case SW_CoordBias_X:
/* Add X bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i];
SO->NodeList[i3] += NewBias[i];
}
break;
case SW_CoordBias_Y:
/* Add Y bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i]+1;
SO->NodeList[i3] += NewBias[i];
}
break;
case SW_CoordBias_Z:
/* Add Z bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i]+2;
SO->NodeList[i3] += NewBias[i];
}
break;
case SW_CoordBias_N:
/* Add Normal bias */
for (i=0; i < ovr->N_NodeDef; ++i) {
i3 = 3*ovr->NodeDef[i];
SO->NodeList[i3] += NewBias[i] * SO->NodeNormList[i3]; ++i3;
SO->NodeList[i3] += NewBias[i] * SO->NodeNormList[i3]; ++i3;
SO->NodeList[i3] += NewBias[i] * SO->NodeNormList[i3];
}
break;
case SW_CoordBias_None:
/* That should not be if NewBias is not NULL */
SUMA_SL_Err("Why are you calling me with SW_CoordBias_None and a non-null NewBias?");
SUMA_RETURN(NOPE);
break;
default:
SUMA_SL_Err("This should not be.\nNot at all.");
SUMA_RETURN(NOPE);
}
#else
/* Add bias to direction */
SUMA_ADD_COORD_BIAS_VECT(SO, ovr, BiasDim, NewBias);
#endif
} else {/* nothing to add (0 bias)*/
}
/* Update surface geometry properties */
SUMA_NewSurfaceGeometry(SO);
SUMA_RETURN(YUP);
}
/*!
Sets the coordinate bias for surfaces using a particular overlay plane
Do NOT free NewBias upon return since this pointer will replace OptScl->BiasVect
DO NOT CALL THIS FUNCTION IF ovr->NodeDef has been modified, otherwise SUMA_RemoveSO_CoordBias will fail
*/
SUMA_Boolean SUMA_SetCoordBias(SUMA_OVERLAYS *ovr, float *NewBias, SUMA_WIDGET_INDEX_COORDBIAS BiasDim)
{
static char FuncName[]={"SUMA_SetCoordBias"};
int i, i3, iso;
SUMA_SurfaceObject *SO=NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!ovr) SUMA_RETURN(YUP);
if (ovr->OptScl->BiasVect ) {
SUMA_SL_Err("Can't have Non NULL bias here");
SUMA_Show_ColorOverlayPlanes(&ovr,1,1);
SUMA_RETURN(NOPE);
}
for (iso=0; iso<SUMAg_N_DOv; ++iso) {
if (SUMA_isSO(SUMAg_DOv[iso])) {
SO = (SUMA_SurfaceObject *)SUMAg_DOv[iso].OP;
if (SUMA_isOverlayOfSO(SO, ovr)) {
SUMA_LH(SO->Label);
SUMA_SetSO_CoordBias(SO, ovr, NewBias, BiasDim);
}
}
}
ovr->OptScl->BiasVect = NewBias;
ovr->OptScl->DoBias = BiasDim;
SUMA_RETURN(YUP);
}
SUMA_Boolean SUMA_RemoveCoordBias(SUMA_OVERLAYS *ovr)
{
static char FuncName[]={"SUMA_RemoveCoordBias"};
int i, i3, iso;
SUMA_SurfaceObject *SO=NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!ovr) SUMA_RETURN(YUP);
if (ovr->OptScl->BiasVect) { /* something to be removed */
for (iso=0; iso<SUMAg_N_DOv; ++iso) {
if (SUMA_isSO(SUMAg_DOv[iso])) {
SO = (SUMA_SurfaceObject *)SUMAg_DOv[iso].OP;
if (SUMA_isOverlayOfSO(SO, ovr)) {
SUMA_LH(SO->Label);
SUMA_RemoveSO_CoordBias(SO, ovr);
}
}
}
/* Now free BiasVect */
SUMA_free(ovr->OptScl->BiasVect);
}
ovr->OptScl->BiasVect = NULL;
ovr->OptScl->DoBias = SW_CoordBias_None;
SUMA_RETURN(YUP);
}
/*!
- Some of the fields of SUMA_SCALE_TO_MAP_OPT are ignored here.
1- Find the colormap structure
2- Linearize the colormap if need be
3- Apply a global brightness coefficient (if any) on the colors in the colormap
4- Loop accross each node in the intensity column
if its threshold meets the cut-off,
colorize it
*/
SUMA_Boolean SUMA_ScaleToMap_Interactive ( SUMA_OVERLAYS *Sover )
{
static char FuncName[]={"SUMA_ScaleToMap_Interactive"};
float *V=NULL, *T=NULL, *B=NULL;
int i, icmap, i3, cnt, cnt3, loc[2], *nd=NULL;
float Range[2], minV, maxV, minB, maxB, fact=0.0, floc = 0.0;
SUMA_COLOR_MAP *ColMap = NULL;
SUMA_SCALE_TO_MAP_OPT *Opt = NULL;
SUMA_COLOR_SCALED_VECT * SV = NULL;
float *junk;
SUMA_WIDGET_INDEX_COORDBIAS HoldBiasOpt;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!Sover) { SUMA_SL_Err("NULL Sover"); SUMA_RETURN(NOPE); }
if (!Sover->cmapname) { SUMA_SL_Err("NULL Colormap name"); SUMA_RETURN(NOPE); }
if (!SUMAg_CF->scm) {
SUMAg_CF->scm = SUMA_Build_Color_maps();
if (!SUMAg_CF->scm) {
SUMA_SL_Err("Can't build color maps");
SUMA_RETURN(NOPE);
}
}
SUMA_LH("Finding ColorMap");
icmap = SUMA_Find_ColorMap ( Sover->cmapname, SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps, -2 );
if (icmap < 0) { SUMA_SL_Err("Failed to find ColMap"); SUMA_RETURN(NOPE); }
ColMap = SUMAg_CF->scm->CMv[icmap];
Opt = Sover->OptScl;
SUMA_LH("Creating a scaled color vect");
/* manually create a SUMA_COLOR_SCALED_VECT * */
SV = SUMA_Create_ColorScaledVect(SDSET_VECFILLED(Sover->dset_link));
SUMA_LH("Fetching vetors from dset");
T = NULL; V = NULL; B = NULL;
/* Thresholding ? */
if (Opt->tind >= 0 && Opt->UseThr) {
SUMA_LH("Fetching Threshold column");
/* got to copy values into float vectors 'cause of possible types */
T = SUMA_DsetCol2Float (Sover->dset_link, Opt->tind, 0);
if (!T) { SUMA_SL_Err("Failed to get T"); SUMA_RETURN(NOPE); }
switch (Opt->ThrMode) {
case SUMA_LESS_THAN:
for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
if (T[i] < Opt->ThreshRange[0]) {
SV->isMasked[i] = YUP; /* Mask */
}
}
break;
case SUMA_ABS_LESS_THAN:
for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
if (T[i] < Opt->ThreshRange[0] && T[i] > -Opt->ThreshRange[0]) {
SV->isMasked[i] = YUP; /* Mask */
}
}
break;
case SUMA_THRESH_OUTSIDE_RANGE:
for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
if (T[i] < Opt->ThreshRange[0] || T[i] > Opt->ThreshRange[1]) {
SV->isMasked[i] = YUP; /* Mask */
}
}
break;
case SUMA_THRESH_INSIDE_RANGE:
for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
if (T[i] > Opt->ThreshRange[0] && T[i] < Opt->ThreshRange[1]) {
SV->isMasked[i] = YUP; /* Mask */
}
}
break;
default:
SUMA_SL_Err("Wrond threshold mode");
SUMA_RETURN(NOPE);
break;
}
/* T is no longer needed */
if (T) SUMA_free(T); T = NULL;
}
SUMA_LH("Fetching Intensity column");
if (Opt->find < 0) { SUMA_SL_Crit("Bad column index.\n"); SUMA_RETURN(NOPE); }
else {
/* got to copy values into float vectors 'cause of possible types */
V = SUMA_DsetCol2Float (Sover->dset_link, Opt->find, 0);
if (!V) { SUMA_SL_Err("Failed to get V"); SUMA_RETURN(NOPE); }
}
/* colorizing */
if (Opt->alaAFNI) {
/* a la AFNI */
SUMA_LH("Scaling a la AFNI");
if (!SUMA_ScaleToMap_alaAFNI (V, SDSET_VECFILLED(Sover->dset_link),
SUMA_LARG_ABS(Opt->IntRange[0], Opt->IntRange[1]),
ColMap, Opt,
SV) ) {
SUMA_SL_Err("Failed in SUMA_ScaleToMap_alaAFNI");
SUMA_RETURN(NOPE);
}
} else {
/* a la SUMA */
SUMA_LH("Scaling a la SUMA");
if (!SUMA_ScaleToMap( V, SDSET_VECFILLED(Sover->dset_link),
Opt->IntRange[0], Opt->IntRange[1],
ColMap, Opt,
SV) ){
SUMA_SL_Err("Failed in SUMA_ScaleToMap");
SUMA_RETURN(NOPE);
}
}
if (Opt->bind >= 0 && Opt->UseBrt) {
SUMA_LH("Brightness modulation needed");
/* got to copy values into float vectors 'cause of possible types */
B = SUMA_DsetCol2Float (Sover->dset_link, Opt->bind, 0);
if (!B) { SUMA_SL_Err("Failed to get B"); SUMA_RETURN(NOPE); }
/* go over B and clip it, if needed */
if (Opt->BrightRange[0] && Opt->BrightRange[1]) {
/* need to clip B */
minB = Opt->BrightRange[0]; maxB = Opt->BrightRange[1];
for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
if (!SV->isMasked[i]) {
/* worry only about unmasked colors */
if (B[i] < Opt->BrightRange[0]) B[i] = Opt->BrightRange[0];
else if (B[i] > Opt->BrightRange[1]) B[i] = Opt->BrightRange[1];
}
}
} else {
if (!SUMA_GetDsetColRange(Sover->dset_link, Opt->bind, Range, loc)) { SUMA_SL_Err("Failed to get ColRange!"); SUMA_RETURN(NOPE); }
minB = Range[0]; maxB = Range[1];
}
/* Now scale B and modulate colors in SV*/
SUMA_LH("Scaling by B");
fact = (Opt->BrightMap[1] - Opt->BrightMap[0]) / (maxB - minB);
for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
if (!SV->isMasked[i]) {
/* B[i] = (B[i] - minB) * fact; SV->cV[i] = SV->cV[i] * B[i]; */
i3 = 3*i;
floc = (B[i] - minB) * fact + Opt->BrightMap[0];
SV->cV[i3 ] = SV->cV[i3 ] * floc;
SV->cV[i3 +1] = SV->cV[i3 +1] * floc;
SV->cV[i3 +2] = SV->cV[i3 +2] * floc;
}
}
}
/* remove any bias before NodeDef is modified */
HoldBiasOpt = Opt->DoBias; /* This field gets wiped (by SUMA_RemoveCoordBias) from Opt (which is inside Sover) */
if (Opt->DoBias == SW_CoordBias_X || Opt->DoBias == SW_CoordBias_Y || Opt->DoBias == SW_CoordBias_Z || Opt->DoBias == SW_CoordBias_N ) {
SUMA_RemoveCoordBias(Sover);
}
/* finally copy results */
SUMA_LH("Copying into NodeDef");
nd = SUMA_GetNodeDef(Sover->dset_link);
if (nd) {
cnt = 0;
for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
if (!SV->isMasked[i]) {
cnt3 = 3*cnt; i3 = 3*i;
Sover->NodeDef[cnt] = nd[i];
Sover->ColVec[cnt3 ] = SV->cV[i3 ];
Sover->ColVec[cnt3 +1] = SV->cV[i3 +1];
Sover->ColVec[cnt3 +2] = SV->cV[i3 +2];
if (SV->BiasCoordVec) SV->BiasCoordVec[cnt] = SV->BiasCoordVec[i]; /* a compression of BiasCoordVec vector to match NodeDef */
++cnt;
}
}
} else {
cnt = 0;
for (i=0; i<SDSET_VECFILLED(Sover->dset_link); ++i) {
if (!SV->isMasked[i]) {
cnt3 = 3*cnt; i3 = 3*i;
Sover->NodeDef[cnt] = i;
Sover->ColVec[cnt3 ] = SV->cV[i3 ];
Sover->ColVec[cnt3 +1] = SV->cV[i3 +1];
Sover->ColVec[cnt3 +2] = SV->cV[i3 +2];
if (SV->BiasCoordVec) SV->BiasCoordVec[cnt] = SV->BiasCoordVec[i]; /* a compression of BiasCoordVec vector to match NodeDef */
++cnt;
}
}
}
Sover->N_NodeDef = cnt;
Sover->FullList = NOPE;
/* Add any coord bias ? */
switch (HoldBiasOpt) {
case SW_CoordBias_X:
SUMA_LH("Bias X");
SUMA_SetCoordBias(Sover, SV->BiasCoordVec, SW_CoordBias_X);
SV->BiasCoordVec = NULL; /* set SV->BiasCoordVec to NULL to keep it from getting freed below */
break;
case SW_CoordBias_Y:
SUMA_LH("Bias Y");
SUMA_SetCoordBias(Sover, SV->BiasCoordVec, SW_CoordBias_Y);
SV->BiasCoordVec = NULL; /* set SV->BiasCoordVec to NULL to keep it from getting freed below */
break;
case SW_CoordBias_Z:
SUMA_LH("Bias Z");
SUMA_SetCoordBias(Sover, SV->BiasCoordVec, SW_CoordBias_Z);
SV->BiasCoordVec = NULL; /* set SV->BiasCoordVec to NULL to keep it from getting freed below */
break;
case SW_CoordBias_N:
SUMA_LH("Bias N");
SUMA_SetCoordBias(Sover, SV->BiasCoordVec, SW_CoordBias_N);
SV->BiasCoordVec = NULL; /* set SV->BiasCoordVec to NULL to keep it from getting freed below */
break;
default:
SUMA_LH("Bias None");
break;
}
if (LocalHead) {
SUMA_LH("In Scale_Interactive\n**********************");
/* SUMA_Show_ColorOverlayPlanes (&Sover, 1, 1); */
}
/* clean up */
SUMA_LH("Cleanup, cleanup, everybody cleanup");
if (T) SUMA_free(T); T = NULL;
if (V) SUMA_free(V); V = NULL;
if (B) SUMA_free(B); B = NULL;
if (SV) SUMA_Free_ColorScaledVect (SV); SV = NULL;
SUMA_RETURN(YUP);
}
SUMA_Boolean 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)
{
static char FuncName[]={"SUMA_ScaleToMap_alaAFNI"};
int i,j, i0, i1, i3, mxColindex;
float Vmin, Vmax, MinCol, MaxCol, Vrange, Vscl, r, **Mbuf= NULL;
SUMA_Boolean NewMap = NOPE;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
/* Autorange ?*/
if (range == 0.0) {
/* autorange, find min-max values */
Vmin = V[0]; Vmax = V[0];
for (i=0; i < N_V; ++i) {
if (V[i] > Vmax) Vmax = V[i];
else if (V[i] < Vmin) Vmin = V[i];
}
} else {
if (ColMap->Sgn >= 0) {
Vmin = 0.0;
Vmax = range;
}else {
Vmin = -range;
Vmax = range;
}
}
if (ColMap->top_frac > 0.0f) {
SUMA_LH("Using top_frac, not commonly used. ");
Vmax *= ColMap->top_frac;
Vmin *= ColMap->top_frac;
}
/* find the values to be masked out */
if (Opt->ApplyMask){
if (Opt->MaskZero) {
/* mask zeros and values in range */
for (i=0; i < N_V; ++i) {
if (!V[i] || (V[i] >= Opt->MaskRange[0] && V[i] <= Opt->MaskRange[1]) ) SV->isMasked[i] = YUP;
}
} else {
/* don't mask zeros, just range */
for (i=0; i < N_V; ++i) {
if (V[i] >= Opt->MaskRange[0] && V[i] <= Opt->MaskRange[1]) SV->isMasked[i] = YUP;
}
}
} else {
if (Opt->MaskZero) {
/* mask zeros */
for (i=0; i < N_V; ++i) {
if (!V[i]) SV->isMasked[i] = YUP;
}
}
}
/* go through and clip values in V to those specified in the range */
if (Opt->ApplyClip) {
SUMA_S_Warn("Option Opt->ApplyClip not applicable here.\nOption ignored.");
}
for (i=0; i < N_V; ++i) {
if (!SV->isMasked[i]) { /* don't waist time on masked stuff */
if (V[i] > Vmin) {
/* that's cool */
} else {
V[i] = Vmin;
}
if (V[i] < Vmax) {
/* that's cool */
} else {
V[i] = Vmax;
}
}
}
/* is the colormap non-linear ? */
if (ColMap->frac) {
/* linearize color map */
SUMA_LH("Linearizing colormap ...");
NewMap = YUP;
if (ColMap->frac[0] > 0 && ColMap->Sgn == -1) {
SUMA_S_Warn ("Color map fractions are positive with Sgn flag = -1");
}
if (ColMap->frac[0] < 0 && ColMap->Sgn == 1) {
SUMA_S_Warn ("Color map fractions are negative with Sgn flag = 1");
}
ColMap = SUMA_Linearize_Color_Map (ColMap, -1);
if (LocalHead) {
FILE *lincmap=NULL;
int ii = 0;
lincmap=fopen("./lincmap.1D", "w");
if (lincmap) {
SUMA_LH("Linearized map written to ./lincmap.1D");
/* use simple format to allow for easy read in matlab */
/* SUMA_Show_ColorMapVec (&ColMap, 1, lincmap, 2); */
for (ii=ColMap->N_Col-1; ii >=0; --ii) {
fprintf (lincmap, "%d\t%f\t%f\t%f\n", ii, ColMap->M[ii][0], ColMap->M[ii][1],ColMap->M[ii][2]);
}
fclose (lincmap); lincmap = NULL;
}else {
SUMA_SL_Err("Failed to write linearized colormap to file.\nProceeding...");
}
}
}else {
SUMA_LH("NO Linearizing of colormap deemed necessary...");
NewMap = NOPE;
}
/* if brightness factor is given, apply it to color map and mask color */
Mbuf = NULL;
if (Opt->BrightFact <= 0 || Opt->BrightFact > 1) {
fprintf (SUMA_STDERR,"Error %s: Opt->BrightFact must be between ]0 1]\n", FuncName);
SUMA_RETURN (NOPE);
}else {
if (Opt->BrightFact != 1) {
Mbuf = ColMap->M; /* save pointer */
ColMap->M = (float **)SUMA_allocate2D(ColMap->N_Col, 3, sizeof(float));
for (i=0; i < ColMap->N_Col; ++i) {
ColMap->M[i][0] = Mbuf[i][0] * Opt->BrightFact;
ColMap->M[i][1] = Mbuf[i][1] * Opt->BrightFact;
ColMap->M[i][2] = Mbuf[i][2] * Opt->BrightFact;
}
/* now for the mask color */
Opt->MaskColor[0] *= Opt->BrightFact;
Opt->MaskColor[1] *= Opt->BrightFact;
Opt->MaskColor[2] *= Opt->BrightFact;
}
}
if (Opt->interpmode != SUMA_DIRECT && Opt->interpmode != SUMA_NO_INTERP && Opt->interpmode != SUMA_INTERP) {
fprintf (SUMA_STDERR,"Error %s: Opt->interpmode is incorrectly specifed (%d).\n", FuncName, Opt->interpmode);
SUMA_RETURN(NOPE);
}
if (Opt->interpmode == SUMA_INTERP || Opt->interpmode == SUMA_NO_INTERP) {
/* Now go through values and interpolate onto index of colormap */
MinCol = 0.0; MaxCol = (float)ColMap->N_Col;
Vrange = Vmax - Vmin;
if (LocalHead) fprintf(SUMA_STDERR,"%s: [Vrange, Vmax, Vmin] = [%f, %f, %f]\nInterpMode=%d\n",
FuncName, Vrange, Vmax, Vmin, Opt->interpmode);
if (Vrange < 0) {
fprintf (SUMA_STDERR,"Error %s: Vmax (%f)< Vmin(%f).\n", FuncName, Vmax, Vmin);
SUMA_RETURN (NOPE);
}
if (Vrange > 0) {
mxColindex = ColMap->N_Col -1;
if (Opt->interpmode == SUMA_NO_INTERP) {
SUMA_LH("No_Interp mode");
for (i=0; i < N_V; ++i) {
i3 = 3*i;
if (!SV->isMasked[i]) {
Vscl = (V[i] - Vmin) / Vrange * ColMap->N_Col; /* used mxColindex instead of N_Col (wrong!) prior to Oct 22, 03 */
if (Vscl < 0) Vscl = 0; if (Vscl > ColMap->N_Col) Vscl = ColMap->N_Col; /* This happens when your Min--Max are within the boundaries of the data's (V[i]) min to max */
i0 = (int)(Vscl);
if (i0 > mxColindex) i0 = mxColindex; /* No need, Vscl's clipping takes care of that: if (i0 < 0) i0 = 0; */
if (LocalHead) {
fprintf(SUMA_STDERR,"%s: %f-->%f: Colmap index is %d\n", FuncName, V[i], Vscl, i0);
}
if (ColMap->M[i0][0] >= 0) { /* good color */
SV->cV[i3 ] = ColMap->M[i0][0];
SV->cV[i3+1] = ColMap->M[i0][1];
SV->cV[i3+2] = ColMap->M[i0][2];
} else { /* mask color */
SV->isMasked[i] = YUP;
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
} else {
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
if (LocalHead) {
fprintf(SUMA_STDERR,"%s: %f-->[%f %f %f]\n", FuncName, V[i], SV->cV[i3 ], SV->cV[i3+1], SV->cV[i3+2]);
}
}
} else {
SUMA_LH("Interp mode");
for (i=0; i < N_V; ++i) {
i3 = 3*i;
if (!SV->isMasked[i]) {
Vscl = (V[i] - Vmin) / Vrange * ColMap->N_Col; /* used mxColindex instead of N_Col (wrong!) prior to Oct 22, 03 */
if (Vscl < 0) Vscl = 0; if (Vscl > ColMap->N_Col) Vscl = ColMap->N_Col; /* This happens when your Min--Max are within the boundaries of the data's (V[i]) min to max */
/*now linearly interpolate between the two closest colors in the color map */
i0 = (int)(Vscl);
if (i0 > mxColindex) i0 = mxColindex; /* No need, Vscl's clipping takes care of that: if (i0 < 0) i0 = 0; */
i1=i0+1;
if (ColMap->M[i0][0] >= 0) { /* good color */
if (i1 < ColMap->N_Col) {
r = Vscl - i0;
/*fprintf (SUMA_STDERR,"i0 = %d, i1 = %d, Vscl = %f, r= %f Col[i0] = %f %f %f\n", \
i0, i1, Vscl, r, ColMap->M[i0][0], ColMap->M[i0][1], ColMap->M[i0][2]);*/
SV->cV[i3 ] = ColMap->M[i0][0] + r * (ColMap->M[i1][0] - ColMap->M[i0][0]);
SV->cV[i3+1] = ColMap->M[i0][1] + r * (ColMap->M[i1][1] - ColMap->M[i0][1]);
SV->cV[i3+2] = ColMap->M[i0][2] + r * (ColMap->M[i1][2] - ColMap->M[i0][2]);
} else {
SV->cV[i3 ] = ColMap->M[i0][0];
SV->cV[i3+1] = ColMap->M[i0][1];
SV->cV[i3+2] = ColMap->M[i0][2];
}
} else { /* mask color */
SV->isMasked[i] = YUP;
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
} else {
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
}
}
} else { /* all values are equal, use the middle color in the colormap */
if (LocalHead) fprintf (SUMA_STDOUT,"Warning %s: Node value range is 0, using middle color in colormap.\n", FuncName);
i0 = (ColMap->N_Col - 1)/2;
for (i=0; i < N_V; ++i) {
i3 = 3*i;
if (!SV->isMasked[i]) {
if (ColMap->M[i0][0] >= 0) {
SV->cV[i3 ] = ColMap->M[i0][0];
SV->cV[i3+1] = ColMap->M[i0][1];
SV->cV[i3+2] = ColMap->M[i0][2];
} else {
SV->isMasked[i] = YUP;
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
} else {
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
}
}
} else {
/* direct color mapping */
SUMA_LH("Direct colormapping");
if (Opt->interpmode != SUMA_DIRECT) {
fprintf (SUMA_STDOUT,"Error %s: Logic error, should never get here with Opt->interpmode != SUMA_DIRECT\n", FuncName);
SUMA_RETURN(NOPE);
}
for (i=0; i < N_V; ++i) {
i3 = 3*i;
if (!SV->isMasked[i]) {
i0 = (int)V[i];
if (i0 < 0) i0 = 0;
else if (i0 >= ColMap->N_Col) i0 = ColMap->N_Col -1;
if (ColMap->M[i0][0] >= 0) {
SV->cV[i3 ] = ColMap->M[i0][0];
SV->cV[i3+1] = ColMap->M[i0][1];
SV->cV[i3+2] = ColMap->M[i0][2];
} else {
SV->isMasked[i] = YUP;
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
} else {
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
}
}
if (Mbuf) {
/* free what is in ColMap->M */
SUMA_free2D((char **)ColMap->M, ColMap->N_Col);
ColMap->M = Mbuf; Mbuf = NULL;
}
if (NewMap) {
SUMA_LH("Freeing linearized colormap.");
SUMA_Free_ColorMap (ColMap);
}
SUMA_RETURN (YUP);
}
/*!
This function maps the values in a vector to colors on a color map
Res = SUMA_ScaleToMap (V, N_V, Vmin, Vmax, ColMap, Opt, SV);
\param V (float *) N_V x1 vector containing the values to be colorized by the map in ColMap.
\param N_V (int) number of elements in V
\param Vmin (float) minimum value in V
\param Vmax (float) maximum value in V
\param ColMap (SUMA_COLOR_MAP *) pointer to the color map
\param Opt (SUMA_SCALE_TO_MAP_OPT *) is a structure containing the options for SUMA_ScaleToMap
see help on SUMA_SCALE_TO_MAP_OPT for info on various options
\param SV (SUMA_COLOR_SCALED_VECT *) is a pre-allocated structure that will contain the
color mapped version of V. See the definition of SUMA_COLOR_SCALED_VECT for more info.
\ret Res (SUMA_Boolean) good/bad
\sa SUMA_Create_ColorScaledVect and SUMA_Free_ColorScaledVect
\sa SUMA_ScaleToMapOptInit
\sa SUMA_MakeColorMap
NOTES:
+The brightness factor Opt->BrightFact is applied to the colormap in ColMap and the MaskColor in Opt
+How Clipping is done:
if (V[i] < Clip[0]) V[i] = Clip[0];
if (V[i] > Clip[1]) V[i] = Clip[1];
+Values in Mask Range are applied BEFORE the clipping is done
IF (Mask[0] <= V[i] <= Mask[1]) V[i] is masked
*/
SUMA_Boolean 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)
{
static char FuncName[]={"SUMA_ScaleToMap"};
int i,j, i0, i1, mxColindex, i3=0;
float MinCol, MaxCol, Vrange, Vscl, r, **Mbuf= NULL, top_frac;
static int nwarn = 0;
SUMA_Boolean NewMap = NOPE;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!ColMap) {
SUMA_SL_Err("NULL ColMap");
SUMA_RETURN(NOPE);
}
if (!Opt) {
SUMA_SL_Err("NULL Opt");
SUMA_RETURN(NOPE);
}
if (!SV) {
SUMA_SL_Err("NULL SV");
SUMA_RETURN(NOPE);
}
if (!V) {
SUMA_SL_Err("NULL V");
SUMA_RETURN(NOPE);
}
/* No negative colormaps here */
if (ColMap->Sgn < 0) {
/* proceed, in SUMA options were given to the user to make the range symmetric about 0.
They can shoot themselves in the foot if they want to */
SUMA_LH("Colormap is split into positive and negative.\n Make sure your range is from -a to + a to have the mapping resemble AFNI's");
}
/* find the values to be masked out */
if (Opt->ApplyMask){
SUMA_LH("Applying Mask");
if (Opt->MaskZero) {
/* mask zeros and values in range */
for (i=0; i < N_V; ++i) {
if (!V[i] || (V[i] >= Opt->MaskRange[0] && V[i] <= Opt->MaskRange[1])) SV->isMasked[i] = YUP;
}
} else {
/* don't mask zeros, just range */
for (i=0; i < N_V; ++i) {
if (V[i] >= Opt->MaskRange[0] && V[i] <= Opt->MaskRange[1]) SV->isMasked[i] = YUP;
}
}
}else {
if (Opt->MaskZero) {
SUMA_LH("Masking Zeros");
/* mask zeros */
for (i=0; i < N_V; ++i) {
if (!V[i]) SV->isMasked[i] = YUP;
}
}
}
/* refuse to deal with top_frac here, SUMA does not allow for colormaps to have a top != 1
First pass at implementing top != 1 does exist below but is now turned off. I don't feel
like testing it... */
top_frac = ColMap->top_frac;
if (top_frac > 0.0f) {
if (!(nwarn % 25)) {
SUMA_SL_Warn( "\n" /* don't want to deal with this because */
"Colormaps for SUMA usage must have 1 for top value.\n" /* suma colormap interface does not yet */
"Any scaling should be done using the range options.\n" /* have a way to show a top value for the */
"The top value for this colormap will be forced to 1.0\n" /* colormap and it is assumed that the top */
"This warning will be shown intermittently when using.\n" /* is 1. Allowing maps where the top is not */
"SUMA's GUI.\n"); /* 1 is dealt with below but is cause for */
/* confusion. You can remove this restriction */
} /* the colormap. */
++nwarn; /* when SUMA clearly shows the top value of */
top_frac = 0.0f;
}
/* go through and clip values in V to those specified in the range */
if (Opt->ApplyClip) {
SUMA_LH( "Applying Clip \n"
"(This one's not used in\n"
" interactive mode anymore \n"
" because clipping is handled \n"
" in the colormapping part)");
if (top_frac > 0.0f) {
SUMA_S_Note("Using top_frac, not fully tested.");
Opt->IntRange[0] *= top_frac;
Opt->IntRange[1] *= top_frac;
}
for (i=0; i < N_V; ++i) {
if (!SV->isMasked[i]) { /* don't waist time on masked stuff */
if (V[i] > Opt->IntRange[0]) {
/* that's cool */
} else {
V[i] = Opt->IntRange[0];
}
if (V[i] < Opt->IntRange[1]) {
/* that's cool */
} else {
V[i] = Opt->IntRange[1];
}
}
}
Vmin = Opt->IntRange[0];
Vmax = Opt->IntRange[1];
if (top_frac > 0.0f) {
/* SUMA_S_Note("Using top_frac, not fully tested."); */
Opt->IntRange[0] /= top_frac;
Opt->IntRange[1] /= top_frac;
}
} else {
if (top_frac > 0.0f) {
SUMA_S_Note("Using top_frac, not fully tested.");
Vmin *= top_frac;
Vmax *= top_frac;
}
SUMA_LHv("No Clip, Opt->IntRange ignored.\nVmin..Vmax= %f..%f", Vmin, Vmax);
}
/* Add any coord bias ? */
if (Opt->DoBias == SW_CoordBias_X || Opt->DoBias == SW_CoordBias_Y || Opt->DoBias == SW_CoordBias_Z || Opt->DoBias == SW_CoordBias_N) {
SUMA_LH("Coord Bias requested");
if (!SV->BiasCoordVec) {
SUMA_LH("Allocating for BiasCoordVec");
SV->BiasCoordVec = (float *)SUMA_calloc(N_V, sizeof(float));
if (!SV->BiasCoordVec) { SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(NOPE); }
}else {
SUMA_SL_Err("Do not expect this not to be null here ... ");
SUMA_RETURN(NOPE);
}
} else {
SUMA_LH("No Coord Bias requested");
if (SV->BiasCoordVec) {
SUMA_SL_Err("Do NOT expect this not to be null here ... ");
SUMA_RETURN(NOPE);
}
}
/* is the colormap non-linear ? */
if (ColMap->frac) {
if (Opt->interpmode == SUMA_NO_INTERP || Opt->interpmode == SUMA_INTERP) {
/* linearize color map */
SUMA_LH("Linearizing colormap ...");
NewMap = YUP;
if (ColMap->frac[0] > 0 && ColMap->Sgn == -1) {
SUMA_S_Warn ("Color map fractions are positive with Sgn flag = -1");
}
if (ColMap->frac[0] < 0 && ColMap->Sgn == 1) {
SUMA_S_Warn ("Color map fractions are negative with Sgn flag = 1");
}
ColMap = SUMA_Linearize_Color_Map (ColMap, -1);
} else {
if (Opt->interpmode != SUMA_DIRECT) {
SUMA_SL_Err("Not expected interpmode.");
/* Do nothing to the colormap, direct mapping mode in gear */
NewMap = NOPE;
}
}
}else {
SUMA_LH("NO Linearizing of colormap deemed necessary...");
NewMap = NOPE;
}
/* if brightness factor is given, apply it to color map and mask color */
Mbuf = NULL;
if (Opt->BrightFact <= 0 || Opt->BrightFact > 1) {
fprintf (SUMA_STDERR,"Error %s: Opt->BrightFact must be between ]0 1]\n", FuncName);
SUMA_RETURN (NOPE);
}else {
if (Opt->BrightFact != 1) {
SUMA_LH("Modulating brightness of map");
Mbuf = ColMap->M; /* save pointer */
ColMap->M = (float **)SUMA_allocate2D(ColMap->N_Col, 3, sizeof(float));
for (i=0; i < ColMap->N_Col; ++i) {
ColMap->M[i][0] = Mbuf[i][0] * Opt->BrightFact;
ColMap->M[i][1] = Mbuf[i][1] * Opt->BrightFact;
ColMap->M[i][2] = Mbuf[i][2] * Opt->BrightFact;
}
/* now for the mask color */
Opt->MaskColor[0] *= Opt->BrightFact;
Opt->MaskColor[1] *= Opt->BrightFact;
Opt->MaskColor[2] *= Opt->BrightFact;
}
}
if (Opt->interpmode != SUMA_DIRECT && Opt->interpmode != SUMA_NO_INTERP && Opt->interpmode != SUMA_INTERP) {
fprintf (SUMA_STDERR,"Error %s: Opt->interpmode is incorrectly specifed (%d).\n", FuncName, Opt->interpmode);
SUMA_RETURN(NOPE);
}
if (Opt->interpmode == SUMA_NO_INTERP || Opt->interpmode == SUMA_INTERP) {
/* Now go through values and interpolate onto index of colormap */
MinCol = 0.0; MaxCol = (float)ColMap->N_Col;
Vrange = Vmax - Vmin;
if (Vrange < 0) {
fprintf (SUMA_STDERR,"Error %s: Vmax (%f)< Vmin(%f).\n", FuncName, Vmax, Vmin);
SUMA_RETURN (NOPE);
}
if (Vrange > 0) {
mxColindex = ColMap->N_Col -1;
if (Opt->interpmode == SUMA_NO_INTERP) { /* no interpolation between colours */
SUMA_LH("No Interp Mode");
for (i=0; i < N_V; ++i) {
i3 = 3*i;
if (!SV->isMasked[i]) {
Vscl = (V[i] - Vmin) / Vrange * ColMap->N_Col; /* used mxColindex instead of N_Col (wrong!) prior to Oct 22, 03 */
if (Vscl < 0) Vscl = 0; if (Vscl > ColMap->N_Col) Vscl = ColMap->N_Col; /* This happens when your Min--Max are within the boundaries of the data's (V[i]) min to max */
i0 = (int)(Vscl);
if (i0 > mxColindex) i0 = mxColindex; /* No need, Vscl's clipping takes care of that: if (i0 < 0) i0 = 0; */
if (SV->BiasCoordVec) SV->BiasCoordVec[i] = Vscl;
if (ColMap->M[i0][0] >= 0) { /* good color */
SV->cV[i3 ] = ColMap->M[i0][0];
SV->cV[i3+1] = ColMap->M[i0][1];
SV->cV[i3+2] = ColMap->M[i0][2];
} else { /* mask color */
SV->isMasked[i] = YUP;
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
} else {
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
}
} else { /* interpolation mode */
SUMA_LH("Interp Mode");
for (i=0; i < N_V; ++i) {
i3 = 3*i;
if (!SV->isMasked[i]) {
Vscl = (V[i] - Vmin) / Vrange * ColMap->N_Col; /* used mxColindex instead of N_Col (wrong!) prior to Oct 22, 03 */
if (Vscl < 0) Vscl = 0; if (Vscl > ColMap->N_Col) Vscl = ColMap->N_Col; /* This happens when your Min--Max are within the boundaries of the data's (V[i]) min to max */
/*now linearly interpolate between the two closest colors in the color map */
i0 = (int)(Vscl);
if (i0 > mxColindex) i0 = mxColindex; /* No need, Vscl's clipping takes care of that: if (i0 < 0) i0 = 0; */
i1=i0+1;
if (SV->BiasCoordVec) {
SV->BiasCoordVec[i] = Vscl;
}
if (ColMap->M[i0][0] >= 0) { /* good color */
if (i1 < ColMap->N_Col) {
r = Vscl - i0;
SV->cV[i3 ] = ColMap->M[i0][0] + r * (ColMap->M[i1][0] - ColMap->M[i0][0]);
SV->cV[i3+1] = ColMap->M[i0][1] + r * (ColMap->M[i1][1] - ColMap->M[i0][1]);
SV->cV[i3+2] = ColMap->M[i0][2] + r * (ColMap->M[i1][2] - ColMap->M[i0][2]);
} else {
SV->cV[i3 ] = ColMap->M[i0][0];
SV->cV[i3+1] = ColMap->M[i0][1];
SV->cV[i3+2] = ColMap->M[i0][2];
}
} else { /* mask color */
SV->isMasked[i] = YUP;
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
} else {
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
}
}
}else { /* all values are equal, use the middle color in the colormap */
if (LocalHead) fprintf (SUMA_STDOUT,"Warning %s: Node value range is 0, using middle color in colormap.\n", FuncName);
i0 = (ColMap->N_Col - 1)/2;
for (i=0; i < N_V; ++i) {
i3 = 3 * i;
if (!SV->isMasked[i]) {
if (SV->BiasCoordVec) SV->BiasCoordVec[i] = i0;
SV->cV[i3 ] = ColMap->M[i0][0];
SV->cV[i3+1] = ColMap->M[i0][1];
SV->cV[i3+2] = ColMap->M[i0][2];
} else {
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
}
}
} else {
/* direct color mapping */
SUMA_LH( "Direct colormapping.\n"
"Opt->IntRange values are \n"
"meaningless" );
if (Opt->interpmode != SUMA_DIRECT) {
fprintf (SUMA_STDOUT,"Error %s: Logic error, should never get here with Opt->interpmode != SUMA_DIRECT\n", FuncName);
SUMA_RETURN(NOPE);
}
for (i=0; i < N_V; ++i) {
i3 = 3*i;
if (!SV->isMasked[i]) {
i0 = (int)V[i];
if (i0 < 0) i0 = 0;
else if (i0 >= ColMap->N_Col) i0 = ColMap->N_Col -1;
if (ColMap->M[i0][0] >= 0) {
SV->cV[i3 ] = ColMap->M[i0][0];
SV->cV[i3+1] = ColMap->M[i0][1];
SV->cV[i3+2] = ColMap->M[i0][2];
if (SV->BiasCoordVec) SV->BiasCoordVec[i] = i0;
} else {
SV->isMasked[i] = YUP;
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
} else {
SV->cV[i3 ] = Opt->MaskColor[0]; SV->cV[i3+1] = Opt->MaskColor[1]; SV->cV[i3+2] = Opt->MaskColor[2];
}
}
}
/* change range for coord bias */
Vrange = (Opt->CoordBiasRange[1] - Opt->CoordBiasRange[0]) / ColMap->N_Col;
if (SV->BiasCoordVec) {
SUMA_LH("Adding the CoordBias");
for (i=0; i < N_V; ++i) {
if (!SV->isMasked[i]) {
SV->BiasCoordVec[i] = Opt->CoordBiasRange[0] + SV->BiasCoordVec[i] * Vrange;
/* if (LocalHead) fprintf(SUMA_STDERR,"%s: %f\n", FuncName, SV->BiasCoordVec[i]); */
} else SV->BiasCoordVec[i] = 0.0;
}
}
if (Mbuf) {
/* free what is in ColMap->M */
SUMA_free2D((char **)ColMap->M, ColMap->N_Col);
ColMap->M = Mbuf; Mbuf = NULL;
}
if (NewMap) {
SUMA_LH("Freeing linearized colormap.");
SUMA_Free_ColorMap (ColMap);
}
SUMA_RETURN (YUP);
}
/*! function to create a linear colormap out of a non-linear one
*/
/*! function to allocate and initialize a structure of the type SUMA_COLOR_SCALED_VECT
S = SUMA_Create_ColorScaledVect();
\param N_Node (int) number of nodes for which colors will be assigned
\ret S (SUMA_COLOR_SCALED_VECT * ) pointer to structure that will contain the color map of N_Node nodes
*/
SUMA_COLOR_SCALED_VECT * SUMA_Create_ColorScaledVect(int N_Node)
{
static char FuncName[]={"SUMA_Create_ColorScaledVect"};
SUMA_COLOR_SCALED_VECT * S;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (LocalHead) fprintf (SUMA_STDERR,"%s:\n Allocate for %d nodes ...\n", FuncName, N_Node);
S = (SUMA_COLOR_SCALED_VECT *)SUMA_malloc(sizeof(SUMA_COLOR_SCALED_VECT));
if (S == NULL) {
fprintf(SUMA_STDERR, "Error %s: Failed to allocate for S.\n", FuncName);
SUMA_RETURN (S);
}
/* S->cM = (float **) SUMA_allocate2D(N_Node, 3, sizeof(float)); */
S->cV = (float *) SUMA_calloc(N_Node * 3, sizeof(float));
S->isMasked = (SUMA_Boolean *)SUMA_calloc(N_Node, sizeof(SUMA_Boolean));
S->BiasCoordVec = NULL; /* That is created in the scaleToMap functions if needed */
if (!S->cV || !S->isMasked) {
fprintf(SUMA_STDERR, "Error %s: Failed to allocate for S->cV or S->isMasked.\n", FuncName);
SUMA_free(S); S = NULL;
SUMA_RETURN (S);
}
S->N_Node = N_Node;
SUMA_RETURN(S);
}
/*! function to free structures of the type SUMA_COLOR_SCALED_VECT
SUMA_Free_ColorScaledVect (S)
\param S (SUMA_COLOR_SCALED_VECT * ) pointer to structure being deleted
\ret void
*/
void SUMA_Free_ColorScaledVect (SUMA_COLOR_SCALED_VECT * S)
{
static char FuncName[]={"SUMA_Free_ColorScaledVect"};
SUMA_ENTRY;
if (S->cV) SUMA_free(S->cV);
if (S->isMasked) SUMA_free(S->isMasked);
if (S->BiasCoordVec) SUMA_free(S->BiasCoordVec);
if (S) SUMA_free(S);
SUMA_RETURNe;
}
/*!
This function allocates for and initializes the Options structure for the function SUMA_ScaleToMap
Opt = SUMA_ScaleToMapOptInit();
\ret Opt (SUMA_SCALE_TO_MAP_OPT *) options structure with its fields initialized to the following:
ApplyMask = NOPE;
MaskRange[0] = MaskRange[1] = 0.0;
MaskColor[0] = MaskColor[1] = MaskColor[2] = 0.0;
Range[0] = Range[1] = 0.0;
BrightFact = 1;
interpmode = SUMA_INTERP;
NULL is returned in the case of failure
You can free Opt with the free function
*/
SUMA_SCALE_TO_MAP_OPT * SUMA_ScaleToMapOptInit(void)
{
SUMA_SCALE_TO_MAP_OPT * Opt;
static char FuncName[]={"SUMA_ScaleToMapOptInit"};
SUMA_ENTRY;
Opt = (SUMA_SCALE_TO_MAP_OPT *)SUMA_malloc(sizeof(SUMA_SCALE_TO_MAP_OPT));
if (Opt == NULL) {
fprintf (SUMA_STDERR, "Error %s: Could not allocate for Opt.\n", FuncName);
SUMA_RETURN (NULL);
}
Opt->ApplyMask = NOPE;
Opt->MaskRange[0] = Opt->MaskRange[1] = 0.0;
Opt->MaskColor[0] = Opt->MaskColor[1] = Opt->MaskColor[2] = 0.0;
Opt->ApplyClip = NOPE;
Opt->IntRange[0] = Opt->IntRange[1] = 0.0;
Opt->ThreshRange[0] = Opt->ThreshRange[1] = 0.0;
Opt->BrightRange[0] = 0.0; Opt->BrightRange[1] = 0.0;
Opt->BrightMap[0] = 0.3; Opt->BrightMap[1] = 0.8;
Opt->BrightFact = 1.0;
Opt->interpmode = SUMA_INTERP;
Opt->alaAFNI = NOPE;
Opt->AutoIntRange = YUP;
Opt->AutoBrtRange = YUP;
{
char *eee = getenv("SUMA_MaskZero");
if (eee) {
if (strcmp(eee,"NO") == 0) Opt->MaskZero = NOPE;
else if (strcmp(eee,"YES") == 0) Opt->MaskZero = YUP;
else {
fprintf (SUMA_STDERR, "Warning %s:\n"
"Bad value for environment variable SUMA_MaskZero\n"
"Assuming default of YES", FuncName);
Opt->MaskZero = YUP;
}
} else Opt->MaskZero = YUP;
}
Opt->find = 0;
Opt->tind = 0;
Opt->bind = 0;
Opt->UseThr = NOPE;
{
char *eee = getenv("SUMA_AbsThreshold");
if (eee) {
if (strcmp(eee,"NO") == 0) Opt->ThrMode = SUMA_LESS_THAN;
else if (strcmp(eee,"YES") == 0) Opt->ThrMode = SUMA_ABS_LESS_THAN;
else {
fprintf (SUMA_STDERR, "Warning %s:\n"
"Bad value for environment variable SUMA_AbsThresh_tbold\n"
"Assuming default of YES", FuncName);
Opt->ThrMode = SUMA_ABS_LESS_THAN;
}
} else Opt->ThrMode = SUMA_ABS_LESS_THAN;
}
Opt->UseBrt = NOPE;
Opt->DoBias = SW_CoordBias_None;
Opt->BiasVect = NULL;
Opt->CoordBiasRange[0] = 0.0; Opt->CoordBiasRange[1] = 10.0;
SUMA_RETURN (Opt);
}
/*!
\brief the interpmode value to a string.
*/
char *SUMA_CmapModeName (SUMA_COLORMAP_INTERP_MODE mapmode)
{
static char FuncName[]={"SUMA_CmapModeName"};
SUMA_ENTRY;
switch (mapmode) {
case SUMA_UNDEFINED_MODE:
SUMA_RETURN("Undefined");
break;
case SUMA_DIRECT:
SUMA_RETURN("Direct");
break;
case SUMA_NO_INTERP:
SUMA_RETURN("NearestNeighbor");
break;
case SUMA_INTERP:
SUMA_RETURN("Interpolate");
break;
default:
SUMA_RETURN("Unexpected business");
break;
}
}
/*!
\brief Returns the ascii name of a Suma standard map.
\param mapcode (SUMA_STANDARD_CMAP)
\param N_col (int *) to contain the number of colors in the map
-1 if no map was found
\return ans (char *) ascii version of mapcode
\sa SUMA_StandardMapCode
*/
char *SUMA_StandardMapName (SUMA_STANDARD_CMAP mapcode, int *N_col)
{
static char FuncName[]={"SUMA_StandardMapName"};
SUMA_ENTRY;
*N_col = -1;
switch (mapcode) {
case SUMA_CMAP_ERROR:
SUMA_RETURN("Error");
break;
case SUMA_CMAP_UNDEFINED:
SUMA_RETURN("Undefined");
break;
case SUMA_CMAP_RGYBR20:
*N_col = 20;
SUMA_RETURN("rgybr20");
break;
case SUMA_CMAP_nGRAY20:
*N_col = 20;
SUMA_RETURN("ngray20");
break;
case SUMA_CMAP_GRAY02:
*N_col = 02;
SUMA_RETURN("gray02");
break;
case SUMA_CMAP_flpGRAY02:
*N_col = 02;
SUMA_RETURN("gray_i02");
break;
case SUMA_CMAP_GRAY20:
*N_col = 20;
SUMA_RETURN("gray20");
break;
case SUMA_CMAP_BW20:
*N_col = 20;
SUMA_RETURN("bw20");
break;
case SUMA_CMAP_BGYR19:
*N_col = 19;
SUMA_RETURN("bgyr19");
break;
case SUMA_CMAP_MATLAB_DEF_BYR64:
*N_col = 64;
SUMA_RETURN("byr64");
break;
case SUMA_CMAP_BGYR64:
*N_col = 64;
SUMA_RETURN("bgyr64");
break;
case SUMA_CMAP_ROI256:
*N_col = 256;
SUMA_RETURN("roi256");
break;
case SUMA_CMAP_ROI128:
*N_col = 128;
SUMA_RETURN("roi128");
break;
case SUMA_CMAP_ROI64:
*N_col = 64;
SUMA_RETURN("roi64");
break;
default:
SUMA_RETURN("Cowabonga-x321");
break;
}
}
/*!
\brief Returns the code corresponding to a colormap name
\sa SUMA_StandardMapName
*/
SUMA_STANDARD_CMAP SUMA_StandardMapCode (char *Name)
{
static char FuncName[]={"SUMA_StandardMapCode"};
SUMA_ENTRY;
if (!Name) SUMA_RETURN(SUMA_CMAP_ERROR);
SUMA_TO_LOWER(Name);
if (!strcmp(Name, "undefined")) SUMA_RETURN(SUMA_CMAP_UNDEFINED);
if (!strcmp(Name, "rgybr20")) SUMA_RETURN(SUMA_CMAP_RGYBR20);
if (!strcmp(Name, "ngray20")) SUMA_RETURN(SUMA_CMAP_nGRAY20);
if (!strcmp(Name, "gray20")) SUMA_RETURN(SUMA_CMAP_GRAY20);
if (!strcmp(Name, "gray02")) SUMA_RETURN(SUMA_CMAP_GRAY02);
if (!strcmp(Name, "gray_i02")) SUMA_RETURN(SUMA_CMAP_flpGRAY02);
if (!strcmp(Name, "bw20")) SUMA_RETURN(SUMA_CMAP_BW20);
if (!strcmp(Name, "bgyr19")) SUMA_RETURN(SUMA_CMAP_BGYR19);
if (!strcmp(Name, "matlab_default_byr64")) SUMA_RETURN(SUMA_CMAP_MATLAB_DEF_BYR64);
if (!strcmp(Name, "byr64")) SUMA_RETURN(SUMA_CMAP_MATLAB_DEF_BYR64);
if (!strcmp(Name, "bgyr64")) SUMA_RETURN(SUMA_CMAP_BGYR64);
if (!strcmp(Name, "ygbrp64")) SUMA_RETURN(SUMA_CMAP_ROI64);
if (!strcmp(Name, "roi64")) SUMA_RETURN(SUMA_CMAP_ROI64);
if (!strcmp(Name, "ygbrp128")) SUMA_RETURN(SUMA_CMAP_ROI128);
if (!strcmp(Name, "ygbrp256")) SUMA_RETURN(SUMA_CMAP_ROI256);
if (!strcmp(Name, "roi128")) SUMA_RETURN(SUMA_CMAP_ROI128);
if (!strcmp(Name, "roi256")) SUMA_RETURN(SUMA_CMAP_ROI256);
/* if (!strcmp(Name, "")) SUMA_RETURN(); */
SUMA_RETURN(SUMA_CMAP_ERROR);
}
/*!
Returns one of a bunch of standard SUMA colormaps
CM = SUMA_GetStandardMap (mapname);
\param mapname (SUMA_STANDARD_CMAP) type of color map, choose from
SUMA_CMAP_RGYBR20
SUMA_CMAP_BGYR19
SUMA_CMAP_GRAY20
SUMA_CMAP_GRAY02
SUMA_CMAP_nGRAY20
SUMA_CMAP_BW20
SUMA_CMAP_MATLAB_DEF_BYR64
\return CM (SUMA_COLOR_MAP*) color map structure (NULL in case of error)
*/
SUMA_COLOR_MAP * SUMA_GetStandardMap (SUMA_STANDARD_CMAP mapcode)
{ static char FuncName[]={"SUMA_GetStandardMap"};
float **Fiducials;
int k, nc;
int *Nind;
int Ncols, NFid;
SUMA_COLOR_MAP * CM;
SUMA_ENTRY;
switch (mapcode) {
case SUMA_CMAP_RGYBR20:
{
Fiducials = (float **)SUMA_allocate2D(5, 3, sizeof(float));
if (!Fiducials) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; ++k;/* Red */
Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0; ++k;/* Green */
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 1.0; ++k;/* Blue */
Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0; ++k;/* Yellow */
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; ++k;/* Red */
/* generate 20 colors colormap */
CM = SUMA_MakeColorMap (Fiducials, k, 20, YUP, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials */
SUMA_free2D((char **)Fiducials, k);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_BGYR19:
{
Fiducials = (float **)SUMA_allocate2D(4, 3, sizeof(float));
if (!Fiducials) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 1.0; ++k;/* Blue */
Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0; ++k;/* Green */
Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0; ++k;/* Yellow */
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; ++k;/* Red */
/* generate 20 colors colormap */
CM = SUMA_MakeColorMap (Fiducials, k, 19, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials */
SUMA_free2D((char **)Fiducials, k);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_GRAY02:
{
Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
if (!Fiducials) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.4; ++k;/* 0.4 gray */
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.7; ++k;/* 0.8 gray */
/* generate 2 colors colormap */
CM = SUMA_MakeColorMap (Fiducials, k, 2, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials */
SUMA_free2D((char **)Fiducials, k);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_flpGRAY02:
{
Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
if (!Fiducials) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.7; ++k;
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.4; ++k;
/* generate 2 colors colormap */
CM = SUMA_MakeColorMap (Fiducials, k, 2, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials */
SUMA_free2D((char **)Fiducials, k);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_GRAY20:
{
Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
if (!Fiducials) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.3; ++k;/* 0.3 gray */
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.8; ++k;/* 0.8 gray */
/* generate 20 colors colormap */
CM = SUMA_MakeColorMap (Fiducials, k, 20, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials */
SUMA_free2D((char **)Fiducials, k);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_nGRAY20:
{
Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
if (!Fiducials) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.3; ++k;/* 0.3 gray */
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.8; ++k;/* 0.8 gray */
/* generate 20 colors colormap */
CM = SUMA_MakeColorMap (Fiducials, k, 20, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials */
SUMA_free2D((char **)Fiducials, k);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_BW20:
{
Fiducials = (float **)SUMA_allocate2D(2, 3, sizeof(float));
if (!Fiducials) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 0.0; ++k;/* black */
Fiducials[k][0] = Fiducials[k][1] = Fiducials[k][2] = 1.0; ++k;/* white */
/* generate 20 colors colormap */
CM = SUMA_MakeColorMap (Fiducials, k, 20, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials */
SUMA_free2D((char **)Fiducials, k);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_MATLAB_DEF_BYR64:
{
/* default matlab color map */
Ncols = 64;
NFid = 10;
Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
Nind = (int *) SUMA_calloc (NFid, sizeof (int));
if (!Fiducials || !Nind) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials or Nind.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.5625; Nind[k] = 0; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 1.0; Nind[k] = 7; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 1.0; Nind[k] = 15; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1.0; Nind[k] = 23; ++k;
Fiducials[k][0] = 0.5; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.5625; Nind[k] = 31; ++k;
Fiducials[k][0] = 0.5625; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.5; Nind[k] = 32; ++k;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0; Nind[k] = 40; ++k;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 0.0; Nind[k] = 48; ++k;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; Nind[k] = 56; ++k;
Fiducials[k][0] = 0.5625; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; Nind[k] = 63; ++k;
/* generate 20 colors colormap */
CM = SUMA_MakeColorMap_v2 (Fiducials, k, Nind, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials & Nind*/
SUMA_free2D((char **)Fiducials, k);
SUMA_free(Nind);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_BGYR64:
{
/* default matlab color map */
Ncols = 64;
NFid = 10;
Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
Nind = (int *) SUMA_calloc (NFid, sizeof (int));
if (!Fiducials || !Nind) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials or Nind.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.5625; Nind[k] = 0; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 1.0; Nind[k] = 7; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 1.0; Nind[k] = 15; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1.0; Nind[k] = 18; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 0.0; Nind[k] = 24; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0; Nind[k] = 32; ++k;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0.0; Nind[k] = 43; ++k;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.5; Fiducials[k][2] = 0.0; Nind[k] = 48; ++k;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; Nind[k] = 56; ++k;
Fiducials[k][0] = 0.5625; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; Nind[k] = 63; ++k;
/* generate 64 colors colormap */
CM = SUMA_MakeColorMap_v2 (Fiducials, k, Nind, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials & Nind*/
SUMA_free2D((char **)Fiducials, k);
SUMA_free(Nind);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_ROI256:
{
/* a large colormap for lots of ROI drawing */
Ncols = 256;
NFid = 6;
Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
Nind = (int *) SUMA_calloc (NFid, sizeof (int));
if (!Fiducials || !Nind) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials or Nind.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0; Nind[k] = 0; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0; Nind[k] = 50; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0; Fiducials[k][2] = 1.0; Nind[k] = 100; ++k;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; Nind[k] = 150; ++k;
Fiducials[k][0] = 0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1; Nind[k] = 200; ++k;
Fiducials[k][0] = 1; Fiducials[k][1] = 0; Fiducials[k][2] = 1; Nind[k] = 255; ++k;
/* generate colormap */
CM = SUMA_MakeColorMap_v2 (Fiducials, k, Nind, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials & Nind*/
SUMA_free2D((char **)Fiducials, k);
SUMA_free(Nind);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_ROI128:
{
/* a large colormap for lots of ROI drawing */
Ncols = 128;
NFid = 6;
Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
Nind = (int *) SUMA_calloc (NFid, sizeof (int));
if (!Fiducials || !Nind) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials or Nind.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0; Nind[k] = 0; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0; Nind[k] = 25; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0; Fiducials[k][2] = 1.0; Nind[k] = 50; ++k;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; Nind[k] = 75; ++k;
Fiducials[k][0] = 0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1; Nind[k] = 100; ++k;
Fiducials[k][0] = 1; Fiducials[k][1] = 0; Fiducials[k][2] = 1; Nind[k] = 127; ++k;
/* generate colormap */
CM = SUMA_MakeColorMap_v2 (Fiducials, k, Nind, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials & Nind*/
SUMA_free2D((char **)Fiducials, k);
SUMA_free(Nind);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
case SUMA_CMAP_ROI64:
{
/* a large colormap for lots of ROI drawing */
Ncols = 64;
NFid = 6;
Fiducials = (float **)SUMA_allocate2D(NFid, 3, sizeof(float));
Nind = (int *) SUMA_calloc (NFid, sizeof (int));
if (!Fiducials || !Nind) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Fiducials or Nind.\n", FuncName);
SUMA_RETURN (NULL);
}
/* create the fiducial colors */
k = 0;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0; Nind[k] = 0; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 0; Nind[k] = 12; ++k;
Fiducials[k][0] = 0.0; Fiducials[k][1] = 0; Fiducials[k][2] = 1.0; Nind[k] = 25; ++k;
Fiducials[k][0] = 1.0; Fiducials[k][1] = 0.0; Fiducials[k][2] = 0.0; Nind[k] = 33; ++k;
Fiducials[k][0] = 0; Fiducials[k][1] = 1.0; Fiducials[k][2] = 1; Nind[k] = 50; ++k;
Fiducials[k][0] = 1; Fiducials[k][1] = 0; Fiducials[k][2] = 1; Nind[k] = 63; ++k;
/* generate colormap */
CM = SUMA_MakeColorMap_v2 (Fiducials, k, Nind, NOPE, SUMA_StandardMapName(mapcode,&nc));
/* free Fiducials & Nind*/
SUMA_free2D((char **)Fiducials, k);
SUMA_free(Nind);
if (!CM) {
fprintf (SUMA_STDERR,"Error %s: Failed to create CM.\n", FuncName);
SUMA_RETURN (NULL);
}
break;
}
default:
fprintf (SUMA_STDERR,"Error %s: Unrecognized color map name.\n", FuncName);
SUMA_RETURN (NULL);
}
SUMA_RETURN (CM);
}
/*!
\brief flips a color map upside down
\param CM (SUMA_COLOR_MAP *) to be flipped
*/
void SUMA_Flip_Color_Map (SUMA_COLOR_MAP *CM)
{
static char FuncName[] = {"SUMA_Flip_Color_Map"};
int lim, i, j, c;
float t;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!CM) SUMA_RETURNe;
if (!CM->M) SUMA_RETURNe;
lim = CM->N_Col/2;
for (j=0; j < 3; ++j) { /* loop accross R,G,B columns */
for (i=0; i < lim; ++i) {
t = CM->M[i][j]; /* store color at i to be flipped */
c = CM->N_Col - i - 1; /* index of color to replace one at i */
CM->M[i][j] = CM->M[c][j]; /* replace color at i */
CM->M[c][j] = t; /* put old color of i ar c */
}
}
if (CM->frac) { /* got to flip fractions */
for (i=0; i < lim; ++i) {
t = CM->frac[i]; /* store fraction at i to be flipped */
c = CM->N_Col - i - 1; /* index of fraction to replace one at i */
CM->frac[i] = CM->frac[c]; /* replace fraction at i */
CM->frac[c] = t; /* put old fraction of i at c */
}
}
SUMA_RETURNe;
}
/*!
A function to compute the percentile range.
Vsort = SUMA_PercRange (V, Vsort, N_V, PercRange, PercRangeVal, iPercRangeVal)
\param V (float *) pointer to vector containing N_V values
\param Vsort (float *) pointer to sorted version of V.
NOTE: If you want the function to sort V for you then pass NULL here and
expect the pointer to Vsort to be returned
\param N_V (int) number of values in V
\param PercRange (float *) 2x1 vector with percentile range desired (values between 0 and 100)
\param PercRangeVal (float *) 2x1 vector with values in V corresponding the percentile range
\param iPercRangeVal (int *) 2 x 1 vector containing indices into Vsort of PercRangeVal.
i.e. PercRangeVal[0] = Vsort[iPercRangeVal[0]];
PercRangeVal[1] = Vsort[iPercRangeVal[1]];
pass NULL if you do not care for it.
\ret Vsort, pointer to the sorted version of V. NULL in case of error.
NOTE: Before a NULL is returned, Vsort is freed.
This function only allocates space for Vsort if a null is passed for Vsort in the function call
\sa SUMA_dPercRange
*/
float * SUMA_PercRange (float *V, float *Vsort, int N_V, float *PercRange, float *PercRangeVal, int *iPercRangeVal)
{
static char FuncName[] = {"SUMA_PercRange"};
int *isort, il, ih;
SUMA_ENTRY;
if (PercRange[0] < 0 || PercRange[0] > 100 || PercRange[1] < 0 || PercRange[1] > 100) {
fprintf (SUMA_STDERR, "Error %s: Values in PercRange must be between 0 and 100.\nVsort will be freed.\n", FuncName);
if (Vsort) SUMA_free(Vsort);
SUMA_RETURN (NULL);
}
if (!Vsort) {
/* need to create my own sorted version */
Vsort = (float *)SUMA_calloc (N_V, sizeof(float));
if (!Vsort) {
fprintf (SUMA_STDERR, "Error %s: Failed to allocate for Vsort.\n", FuncName);
SUMA_RETURN (NULL);
}
/* copy V to Vsort */
SUMA_COPY_VEC (V, Vsort, N_V, float, float);
/* sort Vsort */
isort = SUMA_z_qsort (Vsort , N_V ); SUMA_free(isort);
}
/* choose the index for the lower range */
il = (int)rint((N_V-1)*PercRange[0]/100.0);
ih = (int)rint((N_V-1)*PercRange[1]/100.0);
PercRangeVal[0] = Vsort[il];
PercRangeVal[1] = Vsort[ih];
if (iPercRangeVal) {
iPercRangeVal[0] = il; iPercRangeVal[1] = ih;
}
SUMA_RETURN (Vsort);
}
/*!
Vsort = SUMA_dPercRange (V, Vsort, N_V, PercRange, PercRangeVal, iPercRangeVal)
the double version of SUMA_PercRange, working with double instead of float data
\sa SUMA_PercRange
*/
double * SUMA_dPercRange (double *V, double *Vsort, int N_V, double *PercRange, double *PercRangeVal, int *iPercRangeVal)
{
static char FuncName[] = {"SUMA_dPercRange"};
int *isort, il, ih;
SUMA_ENTRY;
if (PercRange[0] < 0 || PercRange[0] > 100 || PercRange[1] < 0 || PercRange[1] > 100) {
fprintf (SUMA_STDERR, "Error %s: Values in PercRange must be between 0 and 100.\nVsort will be freed.\n", FuncName);
if (Vsort) SUMA_free(Vsort);
SUMA_RETURN (NULL);
}
if (!Vsort) {
/* need to create my own sorted version */
Vsort = (double *)SUMA_calloc (N_V, sizeof(double));
if (!Vsort) {
fprintf (SUMA_STDERR, "Error %s: Failed to allocate for Vsort.\n", FuncName);
SUMA_RETURN (NULL);
}
/* copy V to Vsort */
SUMA_COPY_VEC (V, Vsort, N_V, double, double);
/* sort Vsort */
isort = SUMA_z_doubqsort (Vsort , N_V ); SUMA_free(isort);
}
/* choose the index for the lower range */
il = (int)rint((N_V-1)*PercRange[0]/100.0);
ih = (int)rint((N_V-1)*PercRange[1]/100.0);
PercRangeVal[0] = Vsort[il];
PercRangeVal[1] = Vsort[ih];
if (iPercRangeVal) {
iPercRangeVal[0] = il; iPercRangeVal[1] = ih;
}
SUMA_RETURN (Vsort);
}
/*!
Function to allocate and initialize an Overlays pointer
ans = SUMA_CreateOverlayPointer (N_Nodes, Name, SUMA_DSET *dset, char *ownerid, SUMA_OVERLAYS *recycle);
\param N_Nodes (int): The number of nodes for which color is assigned
\param Name (char *): A character string containing the name of the color overlay
\param dset (SUMA_DSET *): Pointer to data set structure that this plane gets its
data from.
\param ownerid (char *) idcode of owner of colorplane. Can set it to NULL if you
don't care.
\param recycle (SUMA_OVERLAYS *): Reuse this overlays pointer (used to replace current overlay pointer.
\ret ans (SUMA_OVERLAYS *): a pointer to the structure containing the color overlay
NULL is returned in case of trouble.
The following fields are set to these defaults:
Show = NOPE;
GlobalOpacity = -1.0;
LocalOpacity vector is all zeros except the first value is -1.0
FullList = 1
PlaneOrder = -1; i.e. not set
isBackGrnd = 0 ; i.e. none
SymIrange = 0;
\sa SUMA_FreeOverlayPointer
*/
SUMA_OVERLAYS * SUMA_CreateOverlayPointerIdentifiers(int N_Nodes, const char *Name, SUMA_DSET *dset, char *ownerid)
{
static char FuncName[]={"SUMA_CreateOverlayPointerIdentifiers"};
SUMA_OVERLAYS *Sover=NULL;
SUMA_FileName sfn;
int N_Alloc = -1, i=0;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
Sover = (SUMA_OVERLAYS *)SUMA_malloc(sizeof(SUMA_OVERLAYS));
if (!Sover) {
fprintf (SUMA_STDERR,"Error %s: Could not allocate for Sover.\n", FuncName);
SUMA_RETURN (NULL);
}
Sover->N_links = 0;
if (ownerid) sprintf(Sover->owner_id, "%s", ownerid);
else Sover->owner_id[0] = '\0';
Sover->LinkedPtrType = SUMA_LINKED_OVERLAY_TYPE;
/* make a link to dset */
SUMA_LH("Linking to Dset");
Sover->dset_link = (SUMA_DSET *)SUMA_LinkToPointer ((void *)dset);
/* N_Nodes is no longer used, use it for sanity check only */
if (Sover->dset_link->dnel) {
if (N_Nodes != SDSET_VECLEN(Sover->dset_link)) {
SUMA_SL_Err("N_Nodes not equal to vec_len.");
SUMA_RETURN(NULL);
}
} else { SUMA_SL_Err ("No nel yet !"); SUMA_RETURN(NULL);}
/* copy the name */
Sover->Name = (char *)SUMA_calloc (strlen(Name)+1, sizeof(char));
Sover->Name = strcpy(Sover->Name, Name);
/* create a label */
sfn = SUMA_StripPath((char *)Name);
Sover->Label = sfn.FileName;
if (sfn.Path) SUMA_free(sfn.Path); /* get rid of path */
SUMA_RETURN(Sover);
}
SUMA_OVERLAYS * SUMA_CreateOverlayPointer (int N_Nodes, const char *Name, SUMA_DSET *dset, char *ownerid, SUMA_OVERLAYS *Recycle)
{
static char FuncName[]={"SUMA_CreateOverlayPointer"};
SUMA_OVERLAYS *Sover=NULL;
SUMA_FileName sfn;
int N_Alloc = -1, i=0;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!dset) {
SUMA_SL_Err("Need dset");
SUMA_RETURN(NULL);
}
if (!Recycle) { /* a new puppy */
if (!(Sover = SUMA_CreateOverlayPointerIdentifiers(N_Nodes, Name, dset, ownerid))) {
SUMA_S_Err("Failed to create overlay pointer identifiers.");
SUMA_RETURN(NULL);
}
} else {
Sover = Recycle;
/* cleanup things to be replaced */
if (!SUMA_FreeOverlayPointerRecyclables (Sover)) {
SUMA_SL_Err("Recycling failed!\nEarth is doomed.");
SUMA_FreeOverlayPointer(Sover);
SUMA_RETURN(NULL);
}
}
/* not here anymore */
SUMA_LH("Allocating for vectors");
N_Alloc = COLP_N_ALLOC(Sover);
if (N_Alloc != N_Nodes) {
SUMA_SL_Err("This is not supposed to be.");
SUMA_RETURN(NULL);
}
Sover->N_NodeDef = N_Nodes;
Sover->NodeDef = (int *) SUMA_calloc(N_Alloc, sizeof(int));
for (i=0; i < Sover->N_NodeDef; ++i) Sover->NodeDef[i] = i;
Sover->FullList = 1;
/* Sover->ColMat = (float **) SUMA_allocate2D(Sover->N_Alloc, 3, sizeof(float)); NO MORE 2D ! Mar 17 04*/
Sover->ColVec = (float *)SUMA_calloc(N_Alloc*3, sizeof(float));
Sover->LocalOpacity = (float *)SUMA_calloc(N_Alloc, sizeof(float));
Sover->LocalOpacity[0] = -1.0; /* flag indicating local facts have not been initialized */
if (!Sover->ColVec || !Sover->LocalOpacity || !Sover->NodeDef) {
fprintf (SUMA_STDERR,"Error %s: Could not allocate for Sover fields.\n", FuncName);
SUMA_FreeOverlayPointer(Sover);
SUMA_RETURN (NULL);
}
if (!Recycle) {
Sover->GlobalOpacity = -1.0; /* no factor applied */
Sover->Show = NOPE;
Sover->PlaneOrder = -1; /* No order is specified */
Sover->isBackGrnd = 0; /* no brightness modulation effects */
Sover->DimFact = 0.3;
Sover->ForceIntRange[0] = 0.0; Sover->ForceIntRange[1] = 0.0; /* force nothing */
/* new, from Feb 20 */
/* default, choose something */
SUMA_LH("SCM stuff");
if (!SUMAg_CF->scm) { /* try building it */
SUMAg_CF->scm = SUMA_Build_Color_maps();
}
if (!SUMAg_CF->scm) {
SUMA_LH("SUMA color maps not set up.");
Sover->cmapname = NULL;
Sover->OptScl = NULL;
} else {
Sover->cmapname = SUMA_copy_string("bgyr64");
Sover->OptScl = SUMA_ScaleToMapOptInit();
if (!Sover->OptScl) {
fprintf (SUMA_STDERR,"Error %s: Could not get scaling option structure.\n", FuncName);
SUMA_RETURN (NOPE);
}
}
Sover->SymIrange = 0;
}
SUMA_RETURN (Sover);
}
/*!
\brief releases an overlay pointer (decrement its inode count and free it if necessary)
*/
SUMA_Boolean SUMA_ReleaseOverlay (SUMA_OVERLAYS * Overlays, SUMA_INODE *Overlays_Inode)
{
static char FuncName[]={"SUMA_ReleaseOverlay"};
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
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. */
if (SUMA_ReleaseLink(Overlays_Inode)) {
/* some links are left, do not free memory */
} else {
if (LocalHead) fprintf (SUMA_STDERR,"%s: Overlay plane %s is free of links, freeing allocated memory ...\n", FuncName, Overlays->Name);
if (Overlays) SUMA_FreeOverlayPointer (Overlays);
if (Overlays_Inode) SUMA_free(Overlays_Inode);
}
}
SUMA_RETURN(YUP);
}
/*!
Function to free an overlay structure
ans = SUMA_FreeOverlayPointer (Sover);
\param Sover (SUMA_OVERLAYS * )
\ret ans (SUMA_Boolean) (YUP/NOPE)
-WARNING, If YOU CREATED AN INODE FOR THIS POINTER, YOU NEED TO RELASE IT BEFORE YOU FREE Sover
Perhaps you should use SUMA_FreeOverlay (SUMA_OVERLAYS * Sover, SUMA_INODE *Sover_Inode);
If you free one overlay structure at a time, take care to make sure the plane orders still make sense
*/
SUMA_Boolean SUMA_FreeOverlayPointerRecyclables (SUMA_OVERLAYS * Sover)
{
static char FuncName[]={"SUMA_FreeOverlayPointerRecyclables"};
SUMA_ENTRY;
if (Sover == NULL) {
fprintf (SUMA_STDERR,"Error %s: Sover is NULL, nothing to do. Returning OK flag.\n", FuncName);
SUMA_RETURN (YUP);
}
if (Sover->NodeDef) SUMA_free(Sover->NodeDef); Sover->NodeDef = NULL;
Sover->N_NodeDef = -1;
Sover->FullList = -1;
/* if (Sover->ColMat) SUMA_free2D ((char **)Sover->ColMat, Sover->N_Alloc); Sover->ColMat = NULL*/
if (Sover->ColVec) SUMA_free(Sover->ColVec); Sover->ColVec = NULL;
if (Sover->LocalOpacity) SUMA_free(Sover->LocalOpacity); Sover->LocalOpacity = NULL;
SUMA_RETURN (YUP);
}
SUMA_Boolean SUMA_FreeOverlayPointer (SUMA_OVERLAYS * Sover)
{
static char FuncName[]={"SUMA_FreeOverlayPointer"};
SUMA_ENTRY;
if (Sover == NULL) {
fprintf (SUMA_STDERR,"Error %s: Sover is NULL, nothing to do. Returning OK flag.\n", FuncName);
SUMA_RETURN (YUP);
}
/* is this pointer used by others ? */
if (Sover->N_links) {
Sover = (SUMA_OVERLAYS*)SUMA_UnlinkFromPointer((void *)Sover);
SUMA_RETURN (YUP);
}
/* No more links, go for it */
if (Sover->dset_link) Sover->dset_link = (SUMA_DSET *)SUMA_UnlinkFromPointer((void *)Sover->dset_link);
if (Sover->Label) SUMA_free(Sover->Label);
if (Sover->Name) SUMA_free(Sover->Name);
if (Sover->cmapname) SUMA_free(Sover->cmapname);
if (Sover->OptScl) SUMA_free(Sover->OptScl);
SUMA_free(Sover); Sover = NULL;
SUMA_RETURN (YUP);
}
/*!
function to fetch a certain overlay pointer
ptr = SUMA_Fetch_OverlayPointer (Overlays, N_Overlays, Name, OverInd);
if an overlay pointer of the name Name exists in SO then it is returned in ptr
else ptr is null
\param Overlays (SUMA_OVERLAYS **) vector of overlay plane pointers
\param N_Overlays (int) number of overlay planes
\param Name (const char *) name of overlay plane to fetch
\param OverInd (int *) index of overlay plane in Overlays that is fetched (-1 if plane not found)
\ret ptr (SUMA_OVERLAYS *) pointer of overlay plane (= Overlays[*OverInd]) NULL if Name is not found
*/
SUMA_OVERLAYS * SUMA_Fetch_OverlayPointer (SUMA_OVERLAYS **Overlays, int N_Overlays, const char * Name, int * OverInd)
{
static char FuncName[]={"SUMA_Fetch_OverlayPointer"};
int i, ifound =-1, nfound = 0;
SUMA_OVERLAYS *ptr= NULL;
SUMA_PARSED_NAME *pn=NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!Name) SUMA_RETURN(NULL);
for (i=0; i < N_Overlays; ++i) {
SUMA_LHv("Comparing\n>%s<\nto>%s<\n", Overlays[i]->Name, Name);
if (!strcmp(Overlays[i]->Name, Name)) {
*OverInd = i;
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Found overlay plane %s, indexed %d.\n", FuncName, Name, i);
SUMA_RETURN (Overlays[i]);
}
}
/* failed to find name, perhaps name is missing the path which would be OK as long as there is no conflict */
nfound = 0;
for (i=0; i < N_Overlays; ++i) {
if (strlen(Overlays[i]->Name) > strlen(Name)) {
if((pn = SUMA_ParseFname(Overlays[i]->Name, NULL))) {
if (!strcmp(pn->FileName, Name)) {
ifound = i; ++nfound;
}
SUMA_Free_Parsed_Name(pn); pn = NULL;
}
}
}
if (nfound == 1) {
i = ifound;
*OverInd = i;
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Found overlay plane %s in secondary search, indexed %d.\n", FuncName, Name, i);
SUMA_RETURN (Overlays[i]);
} else if (nfound > 1) {
SUMA_LHv("Found %d possible matches for %s\n", nfound, Name);
}
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Overlay plane %s was not found.\n", FuncName, Name);
*OverInd = -1;
SUMA_RETURN (NULL);
}
/*!
Look for overlay pointers for a particular dset
*/
SUMA_OVERLAYS * SUMA_Fetch_OverlayPointerByDset (SUMA_OVERLAYS **Overlays, int N_Overlays, SUMA_DSET *dset, int * OverInd)
{
static char FuncName[]={"SUMA_Fetch_OverlayPointerByDset"};
int i, nfound;
SUMA_OVERLAYS *ptr= NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!dset) {
SUMA_SL_Warn("NULL dset");
SUMA_RETURN(NULL);
}
if (LocalHead) {
fprintf(SUMA_STDERR,"%s: Seaching from %d overlays for dset_link = %p\n", FuncName, N_Overlays, dset);
}
nfound = 0;
*OverInd = -1;
for (i=0; i < N_Overlays; ++i) {
if (LocalHead) fprintf(SUMA_STDERR,"%s: %p ?= %p\n", FuncName, Overlays[i]->dset_link, dset);
if (Overlays[i]->dset_link == dset) {
*OverInd = i;
++nfound;
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Found overlay plane %s, indexed %d.\n", FuncName, Overlays[i]->Name, i);
}
}
if (*OverInd >= 0) {
if (nfound == 1) {
SUMA_RETURN (Overlays[*OverInd]);
} else {
SUMA_SL_Err("Multiple overlays found for dset!");
*OverInd = -1;
SUMA_RETURN(NULL);
}
}
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Overlay plane for dset %p (%s) not found.\n", FuncName, dset,SDSET_LABEL(dset));
*OverInd = -1;
SUMA_RETURN (NULL);
}
/*!
function to turn color overlay planes into GL color array
--- usage prior to Fri Nov 7 15:58:57 EST 2003 ---
ans = SUMA_Overlays_2_GLCOLAR4(Overlays, N_Overlays, glar_ColorList, N_Node, Back_Modfact, ShowBackground, ShowForeground);
\param Overlays (SUMA_OVERLAYS **) a pointer to the vector of overlay planes structure pointers
\param N_Overlays (int) number of overlay plane structures
\param glar_ColorList (GLfloat *) pointer to vector (4*SO->N_Node long) that contains the node colors
\param N_Node (int) total number of nodes in Surface NOT in color overlay plane
\param Back_Modfact (float) Background brightness modulation factor typically SAFNIg_cSV->Back_Modfact
\param ShowBackground (SUMA_Boolean) flag for showing/hiding background (brightness modulating) colors
\param ShowForeground (SUMA_Boolean) flag for showing/hiding foreground colors
\ret YUP/NOPE
\sa SUMA_MixOverlays
--- current usage ---
ans = SUMA_Overlays_2_GLCOLAR4(SO, SV, glar_ColorList)
\param SO (SUMA_SurfaceObject *) surface structure with all the parameters listed in the old usage needed, and more
\param SV (SUMA_SurfaceViewer *) surface viewer structure with all the parameters listed in the old usage needed, and more
\param glar_ColorList (GLfloat *) pointer to vector (4*SO->N_Node long) that contains the node colors
*/
SUMA_Boolean SUMA_Overlays_2_GLCOLAR4(SUMA_SurfaceObject *SO, SUMA_SurfaceViewer *SV, GLfloat *glcolar)
{
static char FuncName[]={"SUMA_Overlays_2_GLCOLAR4"};
int ShowOverLays[SUMA_MAX_OVERLAYS], ShowOverLays_Back[SUMA_MAX_OVERLAYS];
int ShowOverLays_sort[SUMA_MAX_OVERLAYS], ShowOverLays_Back_sort[SUMA_MAX_OVERLAYS], iloc[SUMA_MAX_OVERLAYS];
int OverlayOrder_Back[SUMA_MAX_OVERLAYS], OverlayOrder[SUMA_MAX_OVERLAYS];
int i, j, NshowOverlays, NshowOverlays_Back, *isort, i4, i4_0, i4_1, i4_2;
SUMA_Boolean *isColored, *isColored_Fore, *isColored_Back;
GLfloat *glcolar_Fore , *glcolar_Fore_tmp, *glcolar_Back;
float avg_Back, avgfact;
SUMA_OVERLAYS ** Overlays;
int N_Overlays;
int N_Node;
float Back_Modfact;
SUMA_Boolean ShowBackground;
SUMA_Boolean ShowForeground;
SUMA_Boolean LocalHead = NOPE; /* local headline debugging messages */
SUMA_ENTRY;
if (!SO || !SV || !glcolar) {
SUMA_SL_Err("Null input to SUMA_Overlays_2_GLCOLAR4!");
SUMA_RETURN(NOPE);
}
/* old variable names */
Overlays = SO->Overlays;
N_Overlays = SO->N_Overlays;
N_Node = SO->N_Node;
Back_Modfact = SV->Back_Modfact;
ShowBackground = SV->ShowBackground;
ShowForeground = SV->ShowForeground;
if (LocalHead) {
fprintf (SUMA_STDOUT, "%s: Showing all overlay planes.\n", FuncName);
SUMA_Show_ColorOverlayPlanes (Overlays, N_Overlays, 0);
}
/* get the indices into the color structure vector of overlays to be shown */
NshowOverlays = 0;
NshowOverlays_Back = 0;
for (j=0; j < N_Overlays; ++j) {
if (Overlays[j]->Show && Overlays[j]->GlobalOpacity != 0) {
if (Overlays[j]->isBackGrnd) {
ShowOverLays_Back[NshowOverlays_Back] = j;
OverlayOrder_Back[NshowOverlays_Back] = Overlays[j]->PlaneOrder;
++ NshowOverlays_Back;
}else {
if (SO->SurfCont->ShowCurOnly) {
if (SO->SurfCont->curColPlane == Overlays[j]) {
SUMA_LH("Le ShowCurOnly in action");
ShowOverLays[NshowOverlays] = j;
OverlayOrder[NshowOverlays] = Overlays[j]->PlaneOrder;
++ NshowOverlays;
}
} else {
ShowOverLays[NshowOverlays] = j;
OverlayOrder[NshowOverlays] = Overlays[j]->PlaneOrder;
++ NshowOverlays;
}
}
}
}
if (LocalHead) fprintf (SUMA_STDERR,"%s: Found %d Mix overlays and %d Mix-Brightmod overlays.\n", FuncName, NshowOverlays, NshowOverlays_Back);
/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv allocate space ------------------------------------*/
isColored = (SUMA_Boolean *) SUMA_calloc (N_Node, sizeof(SUMA_Boolean));/* allocate for flag indicating the a node is colored */
if (!isColored) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for isColored.\n", FuncName);
SUMA_RETURN (NOPE);
}
glcolar_Back = NULL;
isColored_Back = NULL;
if (ShowBackground) {
if (NshowOverlays_Back) {
glcolar_Back = (GLfloat *) SUMA_calloc (4*N_Node, sizeof(GLfloat));
isColored_Back = (SUMA_Boolean *) SUMA_calloc (N_Node, sizeof(SUMA_Boolean));
if (!isColored_Back || !glcolar_Back) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for isColored_Back || glcolar_Back.\n", FuncName);
SUMA_RETURN (NOPE);
}
}
}
isColored_Fore = NULL;
glcolar_Fore = NULL;
if (ShowForeground) {
if (NshowOverlays) {
glcolar_Fore = (GLfloat *) SUMA_calloc (4*N_Node, sizeof(GLfloat));
isColored_Fore = (SUMA_Boolean *) SUMA_calloc (N_Node, sizeof(SUMA_Boolean));
if (!isColored_Fore || !glcolar_Fore) {
fprintf (SUMA_STDERR,"Error %s: Failed to allocate for isColored_Fore || glcolar_Fore.\n", FuncName);
SUMA_RETURN (NOPE);
}
}
}
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ allocate space ------------------------------------*/
/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Background colors ------------------------------*/
if (ShowBackground) {
/* arrange Background color planes by plane order in preparation for mixing them */
/* sort plane order */
if (NshowOverlays_Back > 1) {
isort = SUMA_z_dqsort (OverlayOrder_Back, NshowOverlays_Back );
/* use sorting by plane order to reorder ShowOverlays */
for (j=0; j < NshowOverlays_Back; ++j) {
ShowOverLays_Back_sort[j] = ShowOverLays_Back[isort[j]];
}
/* done with isort, free it */
SUMA_free(isort);
}
if (NshowOverlays_Back == 1) {
ShowOverLays_Back_sort[0] = ShowOverLays_Back[0];
}
/* mix the colors that will constitute background*/
if (NshowOverlays_Back) {
if (LocalHead) fprintf (SUMA_STDERR,"%s: Mixing Background colors ...\n", FuncName);
if (!SUMA_MixOverlays (Overlays, N_Overlays, ShowOverLays_Back_sort, NshowOverlays_Back, glcolar_Back, N_Node, isColored_Back, NOPE)) {
fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_MixOverlays.\n", FuncName);
SUMA_RETURN (NOPE);
}
} else {
ShowBackground = NOPE;
}
} else {
NshowOverlays_Back = 0;
}
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Background colors ------------------------------*/
/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Foreground colors ------------------------------*/
if (ShowForeground) {
/* arrange foreground color planes by plane order */
/* sort plane order */
if (NshowOverlays > 1) {
isort = SUMA_z_dqsort (OverlayOrder, NshowOverlays );
/* use sorting by plane order to reorder ShowOverlays */
for (j=0; j < NshowOverlays; ++j) {
ShowOverLays_sort[j] = ShowOverLays[isort[j]];
}
/* done with isort, free it */
SUMA_free(isort);
}
if (NshowOverlays == 1) {
ShowOverLays_sort[0] = ShowOverLays[0];
}
/* Now mix the foreground colors */
if (NshowOverlays) {
if (LocalHead) fprintf (SUMA_STDERR,"%s: Mixing Foreground colors ....\n", FuncName);
if (!SUMA_MixOverlays (Overlays, N_Overlays, ShowOverLays_sort, NshowOverlays, glcolar_Fore, N_Node, isColored_Fore, NOPE)) {
fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_MixOverlays.\n", FuncName);
SUMA_RETURN (NOPE);
}
if (SUMAg_CF->X->NumForeSmoothing > 0) {
glcolar_Fore_tmp = NULL;
glcolar_Fore_tmp = SUMA_SmoothAttr_Neighb_Rec (glcolar_Fore, 4*SO->N_Node, NULL, SO->FN, 4, SUMAg_CF->X->NumForeSmoothing);
if (!glcolar_Fore_tmp) {
SUMA_SL_Err("Smoothing failed.\n");
} else {
SUMA_free(glcolar_Fore); glcolar_Fore = glcolar_Fore_tmp; glcolar_Fore_tmp = NULL;
}
}
} else {
ShowForeground = NOPE;
}
} else {
NshowOverlays = 0;
}
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Foreground colors ------------------------------*/
/* time to modulate the mixed colors with the average brightness */
if (NshowOverlays && NshowOverlays_Back) {
if (LocalHead) fprintf (SUMA_STDERR,"%s: Modulating Brightness of Foreground colors ...\n", FuncName);
for (i=0; i < N_Node; ++i) {
avgfact = Back_Modfact / 3.0;
if (isColored_Fore[i] && isColored_Back[i]) { /* colors from both sides, adjust brightness */
i4_0 = 4 * i; i4_1 = i4_0 + 1; i4_2 = i4_0 + 2;
if (!Back_Modfact) {
glcolar[i4_0] = glcolar_Fore[i4_0];
glcolar[i4_1] = glcolar_Fore[i4_1];
glcolar[i4_2] = glcolar_Fore[i4_2];
} else {
avg_Back = (glcolar_Back[i4_0] + glcolar_Back[i4_1] + glcolar_Back[i4_2]) * avgfact ;
glcolar[i4_0] = avg_Back * glcolar_Fore[i4_0];
glcolar[i4_1] = avg_Back * glcolar_Fore[i4_1];
glcolar[i4_2] = avg_Back * glcolar_Fore[i4_2];
}
isColored[i] = YUP;
continue;
}
if (isColored_Fore[i]) {
i4 = 4 * i;
glcolar[i4] = glcolar_Fore[i4]; ++i4;
glcolar[i4] = glcolar_Fore[i4]; ++i4;
glcolar[i4] = glcolar_Fore[i4]; ++i4;
isColored[i] = YUP;
continue;
}
if (isColored_Back[i]) {
i4 = 4 * i;
glcolar[i4] = glcolar_Back[i4]; ++i4;
glcolar[i4] = glcolar_Back[i4]; ++i4;
glcolar[i4] = glcolar_Back[i4]; ++i4;
isColored[i] = YUP;
continue;
} else {
/* has never been colored, put defaults */
i4 = 4 * i;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
isColored[i] = NOPE;
}
}
if (LocalHead) fprintf (SUMA_STDERR,"%s: Done Modulating Brightness of overlay colors.\n", FuncName);
}
if (NshowOverlays && !NshowOverlays_Back) {
if (LocalHead) fprintf (SUMA_STDERR,"%s: Only Foreground colors.\n", FuncName);
for (i=0; i < N_Node; ++i) {
if (isColored_Fore[i]) {
i4 = 4 * i;
glcolar[i4] = glcolar_Fore[i4]; ++i4;
glcolar[i4] = glcolar_Fore[i4]; ++i4;
glcolar[i4] = glcolar_Fore[i4]; ++i4;
isColored[i] = YUP;
continue;
} else {
i4 = 4 * i;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
isColored[i] = NOPE;
}
}
}
if (!NshowOverlays && NshowOverlays_Back) {
if (LocalHead) fprintf (SUMA_STDERR,"%s: Only Background colors.\n", FuncName);
for (i=0; i < N_Node; ++i) {
if (isColored_Back[i]) {
i4 = 4 * i;
glcolar[i4] = glcolar_Back[i4]; ++i4;
glcolar[i4] = glcolar_Back[i4]; ++i4;
glcolar[i4] = glcolar_Back[i4]; ++i4;
isColored[i] = YUP;
continue;
} else {
i4 = 4 * i;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
isColored[i] = NOPE;
}
}
}
if (!(ShowBackground) && !ShowForeground) {
for (i=0; i < N_Node; ++i) {
i4 = 4 * i;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
glcolar[i4] = SUMA_GRAY_NODE_COLOR; ++i4;
}
}
/* free this mess and get out */
if (isColored) SUMA_free(isColored);
if (isColored_Back) SUMA_free(isColored_Back);
if (glcolar_Back) SUMA_free(glcolar_Back);
if (isColored_Fore) SUMA_free(isColored_Fore);
if (glcolar_Fore) SUMA_free(glcolar_Fore);
SUMA_RETURN (YUP);
}
/*!
function to mix overlay plane colors
ans = SUMA_MixOverlays (SUMA_OVERLAYS ** Overlays, int N_Overlays, int *ShowOvelays, int N_ShowOverlays, GLfloat *glcolar, int N_Node, SUMA_Boolean *isColored, SUMA_Boolean FILL)
Overlays (SUMA_OVERLAYS **) a pointer to the vector of overlay planes structure pointers
N_Overlays (int) number of overlay plane structures
ShowOvelays (int *) vector of Overlay plane indices to be used. The plane indices must be sorted by plane order.
N_ShowOverlays (int) number of ovrlay planes used in the mixing
glar_ColorList (GLfloat *) pointer to vector (4*SO->N_Node long) that contains the node colors
N_Node (int) total number of nodes in Surface NOT in color overlay plane
\param isColored (SUMA_Boolean *) N_Node x1 vector containing flags indicating if a node received a color or not
\param FILL (SUMA_Boolean) top off nodes that received no color with default gray
\sa SUMA_Overlays_2_GLCOLAR4
*/
SUMA_Boolean SUMA_MixOverlays ( SUMA_OVERLAYS ** Overlays, int N_Overlays,
int *ShowOverlays, int NshowOverlays,
GLfloat *glcolar, int N_Node,
SUMA_Boolean *isColored, SUMA_Boolean FILL)
{
static char FuncName[] = {"SUMA_MixOverlays"};
int i, j;
int *NodeDef, N_NodeDef = -1;
SUMA_Boolean Full, Fill, Locl, Glob;
SUMA_Boolean LocalHead = NOPE; /* local headline debugging messages */
SUMA_ENTRY;
if (!Overlays) {
SUMA_SL_Err("Null Overlays!");
SUMA_RETURN(NOPE);
}
if (!glcolar) {
SUMA_SL_Err("Null glcolar!");
SUMA_RETURN(NOPE);
}
if (!isColored) {
fprintf (SUMA_STDERR, "Error %s: isColored is NULL.\n", FuncName);
SUMA_RETURN (NOPE);
}
if (!ShowOverlays) {
SUMA_SL_Err("NULL ShowOverlays");
SUMA_RETURN (NOPE);
}
if (!NshowOverlays) { /* nothing to see here */
fprintf (SUMA_STDERR, "Warning %s: Nothing to do.\n", FuncName);
if (FILL) {
fprintf (SUMA_STDERR, "Warning %s: Filling with blank default color\n", FuncName);
SUMA_FillBlanks_GLCOLAR4(isColored, N_Node, SUMA_GRAY_NODE_COLOR, SUMA_GRAY_NODE_COLOR, SUMA_GRAY_NODE_COLOR, glcolar);
}
SUMA_RETURN (YUP);
}
/* start building the node colors */
Full = YUP;
Glob = YUP;
Locl = YUP;
Fill = YUP;
for (j=0; j<NshowOverlays; ++j) {
Full = YUP;
Glob = YUP;
Locl = YUP;
Fill = YUP;
i = ShowOverlays[j];
if (!Overlays[i]) {
fprintf(SUMA_STDERR,"Error %s:\nNULL ShowOverlays[%d]\n", FuncName, i);
SUMA_RETURN (NOPE);
}
/* is this a full listing */
if (LocalHead) fprintf (SUMA_STDOUT, "%s: Full listing flag: %d\n", FuncName, Overlays[i]->FullList);
if (Overlays[i]->FullList) { Fill = NOPE; /* Full list, no need to fill up unvisited nodes at the end */ }
else { Full = NOPE; /* Not a full list */ }
if (j > 0) { /* opacity plays a role when you are overlaying one plane on top of the other */
/* is this a Global Factor */
if (Overlays[i]->GlobalOpacity < 0.0) { Glob = NOPE; }
/* is this a Local Factor */
if (!Overlays[i]->LocalOpacity) {
fprintf(SUMA_STDERR,"Error %s:\nNULL Overlays[%d]->LocalOpacity\n", FuncName, i);
SUMA_RETURN (NOPE);
}
if (Overlays[i]->LocalOpacity[0] < 0) { Locl = NOPE; }
} else {
Glob = NOPE; Locl = NOPE;
}
NodeDef = COLP_NODEDEF(Overlays[i]);
N_NodeDef = COLP_N_NODEDEF(Overlays[i]);
if (LocalHead)
fprintf (SUMA_STDOUT,"%s: Building color layer %d Overlay #%d: %s ...\nFull=%d, Glob=%d (Globopacity %f), Locl=%d,Fill=%d\n", \
FuncName, j, i, Overlays[i]->Name, (int)Full, (int)Glob, Overlays[i]->GlobalOpacity, (int)Locl, (int)Fill);
/* call the appropriate macro to add the overlay */
if (Full && Glob && Locl) {
if (SUMAg_CF->ColMixMode == SUMA_ORIG_MIX_MODE) {
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_FGL_AR4op ...\n", FuncName);
/* This macro used to be called: SUMA_RGBmat_FullGlobLoc2_GLCOLAR4_opacity
but name was too long for some compilers */
SUMA_RGBv_FGL_AR4op(\
Overlays[i]->ColVec, glcolar, N_Node, Overlays[i]->GlobalOpacity, Overlays[i]->LocalOpacity, isColored);
} else if (SUMAg_CF->ColMixMode == SUMA_4AML) {
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_FGL_AR4op2 ...\n", FuncName);
SUMA_RGBv_FGL_AR4op2(\
Overlays[i]->ColVec, glcolar, N_Node, Overlays[i]->GlobalOpacity, Overlays[i]->LocalOpacity, isColored);
}
}
if (!Full && Glob && Locl) {
if (SUMAg_CF->ColMixMode == SUMA_ORIG_MIX_MODE) {
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_PGL_AR4op ...\n", FuncName);
/* This macro used to be called: SUMA_RGBmat_PartGlobLoc2_GLCOLAR4_opacity */
SUMA_RGBv_PGL_AR4op(\
Overlays[i]->ColVec, NodeDef, glcolar, N_NodeDef, isColored, Overlays[i]->GlobalOpacity, Overlays[i]->LocalOpacity, N_Node);
} else if (SUMAg_CF->ColMixMode == SUMA_4AML) {
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_PGL_AR4op2 ...\n", FuncName);
SUMA_RGBv_PGL_AR4op2(\
Overlays[i]->ColVec, NodeDef, glcolar, N_NodeDef, isColored, Overlays[i]->GlobalOpacity, Overlays[i]->LocalOpacity, N_Node);
}
}
if (Full && !Glob && Locl) {
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_FnGL_AR4op...\n", FuncName);
/* This macro used to be called: SUMA_RGBmat_FullNoGlobLoc2_GLCOLAR4_opacity */
SUMA_RGBv_FnGL_AR4op(\
Overlays[i]->ColVec, glcolar, N_Node, Overlays[i]->LocalOpacity, isColored);
}
if (!Full && !Glob && Locl) {
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_PnGL_AR4op ...\n", FuncName);
/* This macro used to be called: SUMA_RGBmat_PartNoGlobLoc2_GLCOLAR4_opacity*/
SUMA_RGBv_PnGL_AR4op(\
Overlays[i]->ColVec, NodeDef, glcolar, N_NodeDef, isColored, Overlays[i]->LocalOpacity, N_Node);
}
if (Full && !Glob && !Locl) {
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_FnGnL_AR4op ...\n", FuncName);
/* This macro used to be called: SUMA_RGBmat_FullNoGlobNoLoc2_GLCOLAR4_opacity*/
SUMA_RGBv_FnGnL_AR4op(\
Overlays[i]->ColVec, glcolar, N_Node, isColored);
}
if (!Full && !Glob && !Locl) {
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_PnGnL_AR4op ...\n", FuncName);
/* This macro used to be called: SUMA_RGBmat_PartNoGlobNoLoc2_GLCOLAR4_opacity */
SUMA_RGBv_PnGnL_AR4op(\
Overlays[i]->ColVec, NodeDef, glcolar, N_NodeDef, isColored, N_Node);
}
if (Full && Glob && !Locl) {
if (SUMAg_CF->ColMixMode == SUMA_ORIG_MIX_MODE) {
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_FGnL_AR4op...\n", FuncName);
/* This macro used to be called: SUMA_RGBmat_FullGlobNoLoc2_GLCOLAR4_opacity*/
SUMA_RGBv_FGnL_AR4op(\
Overlays[i]->ColVec, glcolar, N_Node, Overlays[i]->GlobalOpacity, isColored);
} else if (SUMAg_CF->ColMixMode == SUMA_4AML){
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_FGnL_AR4op2...\n", FuncName);
SUMA_RGBv_FGnL_AR4op2(\
Overlays[i]->ColVec, glcolar, N_Node, Overlays[i]->GlobalOpacity, isColored);
}
}
if (!Full && Glob && !Locl) {
if (SUMAg_CF->ColMixMode == SUMA_ORIG_MIX_MODE) {
if (LocalHead) {
fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_PGnL_AR4op...\n"
" N_NodeDef = %d, N_Node = %d\n", FuncName, N_NodeDef, N_Node);
}
/* This macro used to be called: SUMA_RGBmat_PartGlobNoLoc2_GLCOLAR4_opacity*/
SUMA_RGBv_PGnL_AR4op(\
Overlays[i]->ColVec, NodeDef, glcolar, N_NodeDef, isColored, Overlays[i]->GlobalOpacity, N_Node);
} else if (SUMAg_CF->ColMixMode == SUMA_4AML){
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Calling SUMA_RGBv_PGnL_AR4op2...\n", FuncName);
SUMA_RGBv_PGnL_AR4op2(\
Overlays[i]->ColVec, NodeDef, glcolar, N_NodeDef, isColored, Overlays[i]->GlobalOpacity, N_Node);
}
}
}
if (FILL && Fill) { /* nothing to see here */
if (LocalHead) fprintf (SUMA_STDOUT,"%s: Some nodes received no colors from any of the overplanes, filling them with background color ...\n", FuncName);
SUMA_FillBlanks_GLCOLAR4(isColored, N_Node, SUMA_GRAY_NODE_COLOR, SUMA_GRAY_NODE_COLOR, SUMA_GRAY_NODE_COLOR, glcolar);
SUMA_RETURN (YUP);
}
SUMA_RETURN (YUP);
}
/*!
Function that shows the contents of overlay planes
ans = SUMA_Show_ColorOverlayPlanes (SUMA_OVERLAYS **Overlays, int N_Overlays) ;
\param Overlays (SUMA_OVERLAYS **) vector of pointers to overlay structures
\param N_Overlays (int) number of overlay structures
\ret ans (SUMA_Boolean)
*/
SUMA_Boolean SUMA_Show_ColorOverlayPlanes (SUMA_OVERLAYS **Overlays, int N_Overlays, int detail)
{
static char FuncName[]={"SUMA_Show_ColorOverlayPlanes"};
char *s;
SUMA_ENTRY;
s = SUMA_ColorOverlayPlane_Info (Overlays, N_Overlays, detail);
if (s) {
fprintf (SUMA_STDERR,"%s\n", s);
SUMA_free(s);
}
SUMA_RETURN (YUP);
}
/*!
\brief Shows the contents of the color overlay planes
\sa SUMA_Show_ColorOverlayPlanes (for backward compat.)
*/
char *SUMA_ColorOverlayPlane_Info (SUMA_OVERLAYS **Overlays, int N_Overlays, int detail)
{
static char FuncName[]={"SUMA_ColorOverlayPlane_Info"};
char stmp[1000], *s = NULL, *s2 = NULL;
int i, j, ShowN, icmap;
SUMA_COLOR_MAP *ColMap=NULL;
int N_Alloc = -1, *NodeDef=NULL, N_NodeDef = -1;
SUMA_STRING *SS = NULL;
SUMA_ENTRY;
SS = SUMA_StringAppend (NULL, NULL);
sprintf (stmp,"Info on %d color overlay planes:\n---------------------------------\n", N_Overlays);
SS = SUMA_StringAppend (SS,stmp);
for (i=0; i < N_Overlays; ++i) {
if (Overlays[i]) {
sprintf (stmp,"\n---> Overlay plane %s:\npointer %p, dset_link %p\norder %d, indexed %d\nDimFact %f, global opacity %f, isBackGrnd (isBackground) %d.\n ForceIntRange %f, %f.\nSymIrange = %d\n",
Overlays[i]->Name, Overlays[i], Overlays[i]->dset_link, Overlays[i]->PlaneOrder, i, Overlays[i]->DimFact, Overlays[i]->GlobalOpacity, Overlays[i]->isBackGrnd,
Overlays[i]->ForceIntRange[0], Overlays[i]->ForceIntRange[1], Overlays[i]->SymIrange);
SS = SUMA_StringAppend (SS,stmp);
SS = SUMA_StringAppend_va (SS, "N_links = %d\n", Overlays[i]->N_links);
SS = SUMA_StringAppend_va (SS, "LinkedPtrType = %d\n", Overlays[i]->LinkedPtrType);
SS = SUMA_StringAppend_va (SS, "owner_id = %s\n", Overlays[i]->owner_id);
NodeDef = COLP_NODEDEF(Overlays[i]);
N_NodeDef = COLP_N_NODEDEF(Overlays[i]);
N_Alloc = COLP_N_ALLOC(Overlays[i]);
sprintf (stmp,"Show=%d, N_Alloc=%d, N_NodeDef=%d\n", (int)Overlays[i]->Show, N_Alloc, N_NodeDef);
SS = SUMA_StringAppend (SS,stmp);
if (detail > 1) {
ShowN = N_NodeDef;
} else {
if (N_NodeDef > 5) ShowN = 5;
else ShowN = N_NodeDef;
}
SS = SUMA_StringAppend (SS,"\n");
sprintf (stmp,"\tindex\tR\tG\tB\tLocOp\n");
SS = SUMA_StringAppend (SS,stmp);
for (j=0; j < ShowN; ++j) {
SS = SUMA_StringAppend_va (SS, "\t%d\t%.3f\t%.3f\t%.3f\t%.3f\n",
NodeDef[j], Overlays[i]->ColVec[3*j],
Overlays[i]->ColVec[3*j+1], Overlays[i]->ColVec[3*j+2],
Overlays[i]->LocalOpacity[j]);
}
SS = SUMA_StringAppend (SS,"\n");
if (!Overlays[i]->cmapname) SS = SUMA_StringAppend (SS,"cmapname = NULL\n");
else SS = SUMA_StringAppend_va (SS,"cmapname = %s\n", Overlays[i]->cmapname);
/* get the color map */
if (!SUMAg_CF->scm) { /* try creating since it is no longer created at initialization */
static int try_once=0;
if (!try_once) { SUMAg_CF->scm = SUMA_Build_Color_maps(); ++ try_once; }
}
if (SUMAg_CF->scm) {
icmap = SUMA_Find_ColorMap ( Overlays[i]->cmapname, SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps, -2 );
if (icmap < 0) { SS = SUMA_StringAppend (SS,"cmap not found.\n"); }
else {
ColMap = SUMAg_CF->scm->CMv[icmap];
s2 = SUMA_ColorMapVec_Info(&ColMap, 1, detail);
SS = SUMA_StringAppend (SS, s2); SUMA_free(s2); s2 = NULL;
}
s2 = SUMA_ScaleToMapOpt_Info (Overlays[i]->OptScl, 0);
SS = SUMA_StringAppend (SS, s2); SUMA_free(s2); s2 = NULL;
} else {
SS = SUMA_StringAppend (SS,"\tNULL SUMA color maps.\n");
}
} else {
SS = SUMA_StringAppend (SS,"\tNULL overlay plane.\n");
}
}
/* clean SS */
SS = SUMA_StringAppend (SS, NULL);
/* copy s pointer and free SS */
s = SS->s;
SUMA_free(SS);
SUMA_RETURN(s);
}
SUMA_Boolean SUMA_ShowScaleToMapOpt(SUMA_SCALE_TO_MAP_OPT *OptScl, FILE *Out, int detail)
{
static char FuncName[]={"SUMA_ShowScaleToMapOpt"};
char *s=NULL;
SUMA_ENTRY;
if (!Out) Out = stdout;
s = SUMA_ScaleToMapOpt_Info(OptScl, detail);
fprintf (Out, "%s\n", s);
if (s) SUMA_free(s); s = NULL;
SUMA_RETURN(YUP);
}
char *SUMA_ScaleToMapOpt_Info (SUMA_SCALE_TO_MAP_OPT *OptScl, int detail)
{
static char FuncName[]={"SUMA_ScaleToMapOpt_Info"};
char *s = NULL;
SUMA_STRING *SS = NULL;
SUMA_ENTRY;
SS = SUMA_StringAppend (NULL, NULL);
if (!OptScl) { SS = SUMA_StringAppend (SS, "NULL ScaleToMap options\n"); }
else {
SS = SUMA_StringAppend (SS, "ScaleToMap options:\n");
SS = SUMA_StringAppend_va (SS, "ApplyMask = %d\n", OptScl->ApplyMask);
SS = SUMA_StringAppend_va (SS, "MaskRange = %f %f\n",
OptScl->MaskRange[0], OptScl->MaskRange[1]);
SS = SUMA_StringAppend_va (SS, "MaskColor = %f %f %f\n",
OptScl->MaskColor[0], OptScl->MaskColor[1], OptScl->MaskColor[2]);
SS = SUMA_StringAppend_va (SS, "ApplyClip = %d\n", OptScl->ApplyClip);
SS = SUMA_StringAppend_va (SS, "BrightFact = %f\n", OptScl->BrightFact);
SS = SUMA_StringAppend_va (SS, "MaskZero = %d\n", OptScl->MaskZero);
SS = SUMA_StringAppend_va (SS, "find = %d\n", OptScl->find);
SS = SUMA_StringAppend_va (SS, "IntRange = %f %f\n",
OptScl->IntRange[0], OptScl->IntRange[1]);
SS = SUMA_StringAppend_va (SS, "AutoIntRange = %d\n", OptScl->AutoIntRange);
SS = SUMA_StringAppend_va (SS, "tind = %d (use:%d). Mode %d\n", OptScl->tind, OptScl->UseThr, OptScl->ThrMode);
SS = SUMA_StringAppend_va (SS, "ThreshRange = %f %f\n",
OptScl->ThreshRange[0], OptScl->ThreshRange[1]);
SS = SUMA_StringAppend_va (SS, "bind = %d (use:%d)\n", OptScl->bind, OptScl->UseBrt);
SS = SUMA_StringAppend_va (SS, "BrightRange = %f %f\n",
OptScl->BrightRange[0], OptScl->BrightRange[1]);
SS = SUMA_StringAppend_va (SS, "BrightMap = %f %f\n",
OptScl->BrightMap[0], OptScl->BrightMap[1]);
SS = SUMA_StringAppend_va (SS, "AutoBrtRange = %d\n", OptScl->AutoBrtRange);
SS = SUMA_StringAppend_va (SS, "alaAFNI = %d\n", OptScl->alaAFNI);
SS = SUMA_StringAppend_va (SS, "interpmode = %d (%s)\n", OptScl->interpmode, SUMA_CmapModeName(OptScl->interpmode));
SS = SUMA_StringAppend_va (SS, "BiasMode = %d, Range=%f, %f \n",
OptScl->DoBias, OptScl->CoordBiasRange[0], OptScl->CoordBiasRange[1]);
if (OptScl->BiasVect) SS = SUMA_StringAppend_va (SS, "BiasVect is NOT NULL\n");
else SS = SUMA_StringAppend_va (SS, "BiasVect is NULL\n");
}
SUMA_SS2S(SS, s);
SUMA_RETURN(s);
}
/*!
\brief Frees SUMA_OVERLAY_LIST_DATUM * used in the linked list
*/
void SUMA_FreeOverlayListDatum (void *OLDv)
{
static char FuncName[]={"SUMA_FreeOverlayListDatum"};
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (OLDv) SUMA_free(OLDv);
SUMA_RETURNe;
}
/*!
\brief Create an ordered list of the colorplanes in Overlays
the sorting of the list is done based on BackMod followed by the order
The function makes sure colorplane orders span 0 to N_Overlays-1
\param SO (SUMA_SurfaceObject *)
\param Opt (int) -1 for background plane list only
1 for foreground plane list only
0 for both background followed by foreground
\return list (DList *) a doubly linked list of the ordered color planes.
NULL is returned in case of error.
to free this list when you no longer need it, do:
dlist_destroy(list); SUMA_free(list);
*/
DList * SUMA_OverlaysToOrderedList (SUMA_SurfaceObject *SO, int Opt)
{
static char FuncName[]={"SUMA_OverlaysToOrderedList"};
DList *listop = NULL;
DListElmt *Elmop=NULL;
SUMA_OVERLAY_LIST_DATUM *OvD = NULL, *oOvD = NULL;
int i, Shift, ShftPlaneOrder, oShftPlaneOrder;
SUMA_OVERLAYS *oPlane=NULL;
SUMA_Boolean Found, LocalHead = NOPE;
SUMA_ENTRY;
listop = (DList *)SUMA_malloc(sizeof(DList));
dlist_init(listop, SUMA_FreeOverlayListDatum);
SUMA_LH("Considering loop");
for (i=0; i < SO->N_Overlays; ++i) {
SUMA_LH("In Loop");
OvD = (SUMA_OVERLAY_LIST_DATUM *)SUMA_malloc(sizeof(SUMA_OVERLAY_LIST_DATUM));
OvD->Overlay = SO->Overlays[i];
if (!OvD->Overlay) {
SUMA_LH("NULL Overlay");
}
SUMA_LH("Here");
if (OvD->Overlay->isBackGrnd && Opt == 1) continue; /* that was an unwanted background */
if (!OvD->Overlay->isBackGrnd && Opt == -1) continue; /* that was an unwanted foreground */
if (!listop->size) {
SUMA_LH("Very first");
dlist_ins_next(listop, dlist_tail(listop), (void*)OvD);
}else { /* must sort first */
Elmop = NULL;
do {
SUMA_LH("Searching");
Found = NOPE;
if (!Elmop) {
Elmop = dlist_head(listop);
} else {
Elmop = dlist_next(Elmop);
}
oOvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
/* transform PlaneOrder so that is reflects the Background modulation */
Shift = SO->N_Overlays;
if (OvD->Overlay->isBackGrnd) ShftPlaneOrder = OvD->Overlay->PlaneOrder - Shift;
else ShftPlaneOrder = OvD->Overlay->PlaneOrder;
if (oOvD->Overlay->isBackGrnd) oShftPlaneOrder = oOvD->Overlay->PlaneOrder - Shift;
else oShftPlaneOrder = oOvD->Overlay->PlaneOrder;
if (ShftPlaneOrder <= oShftPlaneOrder) {
SUMA_LH ("Ins Prev");
dlist_ins_prev(listop, Elmop, (void *)OvD);
Found = YUP;
} else if (Elmop == dlist_tail(listop)) {
SUMA_LH ("Ins Next");
/* reached the end, append */
dlist_ins_next(listop, Elmop, (void *)OvD);
Found = YUP;
}
} while (!Found);
}
}
/* Now the list is sorted
Go through the planes and make sure that the orders
span 0 to N_Overlays -1 */
SUMA_LH("Changing list order to plane order");
SUMA_ListOrderToPlaneOrder (listop);
SUMA_RETURN(listop);
}
/*!
\brief sets the values of PlaneOrder to reflect the location of the color planes in list
*/
SUMA_Boolean SUMA_ListOrderToPlaneOrder (DList *listop)
{
static char FuncName[]={"SUMA_ListOrderToPlaneOrder"};
SUMA_OVERLAY_LIST_DATUM *OvD = NULL;
int i, fg_shift = 0;
DListElmt *Elmop=NULL;
SUMA_ENTRY;
/* First pass, do background */
if (listop->size) {
Elmop = NULL;
i = 0;
do {
if (!Elmop) Elmop = dlist_head(listop);
else Elmop = Elmop->next;
OvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
if (OvD->Overlay->isBackGrnd) {
OvD->Overlay->PlaneOrder = i;
++i;
}
} while (!dlist_is_tail(Elmop));
}
/* second pass, do foreground */
if (listop->size) {
Elmop = NULL;
i = 0;
do {
if (!Elmop) Elmop = dlist_head(listop);
else Elmop = Elmop->next;
OvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
if (!OvD->Overlay->isBackGrnd) {
OvD->Overlay->PlaneOrder = i;
++i;
}
} while (!dlist_is_tail(Elmop));
}
SUMA_RETURN(YUP);
}
/*!
\brief returns the largest background order in the list of verlay planes
*/
int SUMA_GetLargestBackroundOrder (DList *listop)
{
static char FuncName[]={"SUMA_GetLargestBackroundOrder"};
int Order, i;
DListElmt *Elmop=NULL;
SUMA_OVERLAY_LIST_DATUM *OvD = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
Order = 0;
Elmop = NULL;
do {
if (!Elmop) Elmop = dlist_head(listop);
else Elmop = Elmop->next;
OvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
if (OvD->Overlay->isBackGrnd) {
if (OvD->Overlay->PlaneOrder > Order) Order = OvD->Overlay->PlaneOrder;
}
++i;
} while (!dlist_is_tail(Elmop));
if (LocalHead) {
fprintf (SUMA_STDERR,"%s: Highest background order found is %d\n", FuncName, Order);
}
SUMA_RETURN(Order);
}
/*!
\brief returns the lowest foreground plane order in the list of overlay planes
*/
int SUMA_GetSmallestForegroundOrder (DList *listop)
{
static char FuncName[]={"SUMA_GetSmallestForegroundOrder"};
int Order, i;
DListElmt *Elmop=NULL;
SUMA_OVERLAY_LIST_DATUM *OvD = NULL, *oOvD = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
Order = listop->size -1 ;
Elmop = NULL;
do {
if (!Elmop) Elmop = dlist_head(listop);
else Elmop = Elmop->next;
OvD = (SUMA_OVERLAY_LIST_DATUM *)Elmop->data;
if (!OvD->Overlay->isBackGrnd) {
if (OvD->Overlay->PlaneOrder < Order) Order = OvD->Overlay->PlaneOrder;
}
++i;
} while (!dlist_is_tail(Elmop));
if (LocalHead) {
fprintf (SUMA_STDERR,"%s: Lowest foreground order found is %d\n", FuncName, Order);
}
SUMA_RETURN(Order);
}
/*!
Is a color overlay plane registered in SO
*/
SUMA_Boolean SUMA_isOverlayOfSO (SUMA_SurfaceObject *SO, SUMA_OVERLAYS *Plane)
{
static char FuncName[]={"SUMA_isOverlayOfSO"};
int i;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
for (i=0; i< SO->N_Overlays; ++i) if (SO->Overlays[i] == Plane) { SUMA_LHv("Found plane at ind: %d\n", i); SUMA_RETURN(YUP); }
SUMA_LH("Plane not found");
SUMA_RETURN(NOPE);
}
void SUMA_Print_PlaneOrder (SUMA_SurfaceObject *SO, FILE *Out)
{
static char FuncName[]={"SUMA_Print_PlaneOrder"};
char *s;
SUMA_ENTRY;
if (Out == NULL) Out = stdout;
s = SUMA_PlaneOrder_Info(SO);
if (s) {
fprintf (Out, "%s", s);
SUMA_free(s);
}else {
fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_PlaneOrder_Info.\n", FuncName);
}
SUMA_RETURNe;
}
/*!
\brief Shows the overlay plane order
*/
char * SUMA_PlaneOrder_Info (SUMA_SurfaceObject *SO)
{
static char FuncName[]={"SUMA_PlaneOrder_Info"};
char stmp[1000], *s = NULL;
SUMA_STRING *SS = NULL;
DList *list=NULL;
DListElmt *Elm=NULL;
SUMA_OVERLAY_LIST_DATUM *OvD=NULL;
SUMA_ENTRY;
/* get the background and foreground lists */
SS = SUMA_StringAppend (NULL, NULL);
if (!(list = SUMA_OverlaysToOrderedList (SO, -1))) {
SS = SUMA_StringAppend (SS,"NULL Background list\n");
}else if (!list->size) {
SS = SUMA_StringAppend (SS,"Empty Background list\n");
} else {
Elm=NULL;
do {
if (!Elm) Elm = dlist_head(list);
else Elm = Elm->next;
OvD = (SUMA_OVERLAY_LIST_DATUM *)Elm->data;
sprintf (stmp,"BK: %s o%d (%s)\n", OvD->Overlay->Label, OvD->Overlay->PlaneOrder, OvD->Overlay->Name );
SS = SUMA_StringAppend (SS,stmp);
} while (Elm != dlist_tail(list));
}
if (!(list = SUMA_OverlaysToOrderedList (SO, 1))) {
SS = SUMA_StringAppend (SS,"NULL Foreground list\n");
}else if (!list->size) {
SS = SUMA_StringAppend (SS,"Empty Foreground list\n");
} else {
Elm=NULL;
do {
if (!Elm) Elm = dlist_head(list);
else Elm = Elm->next;
OvD = (SUMA_OVERLAY_LIST_DATUM *)Elm->data;
sprintf (stmp,"FG: %s o%d (%s)\n", OvD->Overlay->Label, OvD->Overlay->PlaneOrder, OvD->Overlay->Name );
SS = SUMA_StringAppend (SS,stmp);
} while (Elm != dlist_tail(list));
}
s = SS->s;
SUMA_free(SS);
SUMA_RETURN (s);
}
/*!
\brief Moves a plane up one order
*/
SUMA_Boolean SUMA_MovePlaneUp (SUMA_SurfaceObject *SO, char *Name)
{
static char FuncName[]={"SUMA_MovePlaneUp"};
SUMA_OVERLAYS *Overlay=NULL;
SUMA_OVERLAY_LIST_DATUM *OvD=NULL;
DList *list=NULL;
DListElmt *Elm = NULL;
int junk=0;
SUMA_Boolean Found = NOPE, LocalHead = NOPE;
SUMA_ENTRY;
/* search for the plane by name */
SUMA_LH("Searching for plane");
if (!(Overlay = SUMA_Fetch_OverlayPointer(SO->Overlays, SO->N_Overlays, Name, &junk))) {
SUMA_S_Err("Plane does not exist in SO->Overlays. (identified by name)");
SUMA_RETURN (NOPE);
}
/* get the list of planes */
SUMA_LH("Creating list");
if (Overlay->isBackGrnd) list = SUMA_OverlaysToOrderedList (SO, -1);
else list = SUMA_OverlaysToOrderedList (SO, 1);
if (!list) {
SUMA_S_Err("NULL list");
SUMA_RETURN (NOPE);
}
/* Now search through the list until you find Overlay */
SUMA_LH("Searching for plane in list");
Found = NOPE;
Elm = NULL;
do {
if (!Elm) Elm = dlist_head(list);
else Elm = Elm->next;
OvD = (SUMA_OVERLAY_LIST_DATUM *) Elm->data;
if (OvD->Overlay == Overlay) Found = YUP;
}while (Elm != dlist_tail(list) && !Found);
if (!Found) {
SUMA_S_Err("Strange, real strange.");
SUMA_RETURN(NOPE);
}
SUMA_LH("Found element, inserting at new position");
if (Elm != dlist_tail(list)) { /* not on top, can move up */
/* add Elm's data ahead of Elm->next */
dlist_ins_next (list, Elm->next, Elm->data);
/* remove Elm BUT NOT ITS DATA STRUCTURE!*/
dlist_remove (list, Elm, (void *)(&OvD));
} else {
SUMA_LH("Reached the top");
}
SUMA_LH("Compacting");
/* now compact the order just for good measure */
SUMA_ListOrderToPlaneOrder (list);
SUMA_LH("Clean up");
dlist_destroy(list); SUMA_free(list);
SUMA_RETURN(YUP);
}
/*!
\brief Moves a plane up one order
*/
SUMA_Boolean SUMA_MovePlaneDown (SUMA_SurfaceObject *SO, char *Name)
{
static char FuncName[]={"SUMA_MovePlaneDown"};
SUMA_OVERLAYS *Overlay=NULL;
SUMA_OVERLAY_LIST_DATUM *OvD=NULL;
DList *list=NULL;
DListElmt *Elm = NULL;
int junk=0;
SUMA_Boolean Found = NOPE, LocalHead = NOPE;
SUMA_ENTRY;
/* search for the plane by name */
SUMA_LH("Searching for plane");
if (!(Overlay = SUMA_Fetch_OverlayPointer(SO->Overlays, SO->N_Overlays, Name, &junk))) {
SUMA_S_Err("Plane does not exist in SO->Overlays. (identified by name)");
SUMA_RETURN (NOPE);
}
/* get the list of planes */
SUMA_LH("Creating list");
if (Overlay->isBackGrnd) list = SUMA_OverlaysToOrderedList (SO, -1);
else list = SUMA_OverlaysToOrderedList (SO, 1);
if (!list) {
SUMA_S_Err("NULL list");
SUMA_RETURN (NOPE);
}
/* Now search through the list until you find Overlay */
SUMA_LH("Searching for plane in list");
Found = NOPE;
Elm = NULL;
do {
if (!Elm) Elm = dlist_head(list);
else Elm = Elm->next;
OvD = (SUMA_OVERLAY_LIST_DATUM *) Elm->data;
if (OvD->Overlay == Overlay) Found = YUP;
}while (Elm != dlist_tail(list) && !Found);
if (!Found) {
SUMA_S_Err("Strange, real strange.");
SUMA_RETURN(NOPE);
}
SUMA_LH("Found element, inserting at new position");
if (Elm != dlist_head(list)) { /* not on bottom, can move down */
/* add Elm's data before of Elm->prev */
dlist_ins_prev (list, Elm->prev, Elm->data);
/* remove Elm BUT NOT ITS DATA STRUCTURE!*/
dlist_remove (list, Elm, (void *)(&OvD));
} else {
SUMA_LH("Reached the bottom");
}
SUMA_LH("Compacting");
/* now compact the order just for good measure */
SUMA_ListOrderToPlaneOrder (list);
SUMA_LH("Clean up");
dlist_destroy(list); SUMA_free(list);
SUMA_RETURN(YUP);
}
SUMA_OVERLAYS * SUMA_NewPlaneSearch(SUMA_SurfaceObject *SO, SUMA_OVERLAYS *Overlay)
{
static char FuncName[]={"SUMA_NewPlaneSearch"};
int junk = 0;
SUMA_ENTRY;
if (!Overlay || !SO) {
SUMA_S_Err("You sent me NULLS!");
SUMA_RETURN (NULL);
}
if (SUMA_isOverlayOfSO(SO, Overlay)) {
SUMA_RETURN(Overlay);
}
/* also try looking for plane by name */
SUMA_RETURN(SUMA_Fetch_OverlayPointer(SO->Overlays, SO->N_Overlays, Overlay->Name, &junk));
}
/*!
\brief Adds a new plane to SO->Overlays.
If plane exists, you get an error message
Adds plane to related surfaces if dov is not NULL
DuplicateFlag == 0 return with error if plane already exists
1 return with warning if plane already exists
*/
SUMA_Boolean SUMA_AddNewPlane (SUMA_SurfaceObject *SO, SUMA_OVERLAYS *Overlay, SUMA_DO *dov, int N_dov, int DuplicateFlag)
{
static char FuncName[]={"SUMA_AddNewPlane"};
DList *ForeList=NULL, *BackList = NULL;
SUMA_OVERLAY_LIST_DATUM *OvD=NULL;
int junk=0, i, OverInd, kin = 1;
SUMA_SurfaceObject *SO2 = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY_LH;
if (!Overlay) {
SUMA_S_Err("You sent me NULLS!");
SUMA_RETURN (NOPE);
}
if (SUMA_NewPlaneSearch(SO, Overlay)) {
if (DuplicateFlag == 0) {
SUMA_S_Errv("Plane exists in SO->Overlays either by pointer %p or by name (%s).\nBoth of these must be unique because DuplicateFlag=%d\n", Overlay, Overlay->Name, DuplicateFlag);
SUMA_RETURN (NOPE);
} else {
SUMA_S_Note("Plane exists in SO->Overlays. Preserving old one.");
SUMA_RETURN (YUP);
}
}
/* make sure that overlay plane does not have bias in it */
if (Overlay->OptScl) {
if (Overlay->OptScl->BiasVect) {
SUMA_SL_Err("New overlay plane cannot have coordinate bias.\nNot yet at least.\n");
/* If you want to support this feature, you'll have to call SUMA_ADD_COORD_BIAS_VECT
on any surface the plane gets assigned to. That means SO and SO2 below.
Search for macro SUMA_ADD_COORD_BIAS_VECT in SUMA_SwitchState in file SUMA_Engine.c
for the example */
SUMA_RETURN(NOPE);
}
}
/* make sure there's enough room for the new plane */
if (SO->N_Overlays+1 >= SUMA_MAX_OVERLAYS) {
SUMA_SL_Crit("Too many color overlays.");
SUMA_RETURN (NOPE);
}
/* Now add the plane where it belongs */
if (!(ForeList = SUMA_OverlaysToOrderedList (SO, 1))) {
SUMA_S_Err("NULL ForeList");
SUMA_RETURN (NOPE);
}
if (!(BackList = SUMA_OverlaysToOrderedList (SO, -1))) {
SUMA_S_Err("NULL BackList");
SUMA_RETURN (NOPE);
}
SUMA_LH("Adding to list...");
OvD = (SUMA_OVERLAY_LIST_DATUM *) SUMA_malloc(sizeof(SUMA_OVERLAY_LIST_DATUM));
OvD->Overlay = Overlay;
if (Overlay->isBackGrnd) {
SUMA_LH("Back dude...");
dlist_ins_next(BackList, dlist_tail(BackList), (void *)OvD);
Overlay->PlaneOrder = BackList->size - 1;
} else {
SUMA_LH("Front dude...");
dlist_ins_next(ForeList, dlist_tail(ForeList), (void *)OvD);
Overlay->PlaneOrder = ForeList->size - 1;
}
SUMA_LH("Out dude...");
/* place the Overlay plane and its inode in SO */
SO->Overlays[SO->N_Overlays] = Overlay;
/* Now increment the number of overlays to be in SO */
++SO->N_Overlays;
SUMA_LH("Destruction...");
dlist_destroy(ForeList); SUMA_free(ForeList);
dlist_destroy(BackList); SUMA_free(BackList);
/* Now register plane with surfaces deserving it*/
if (AFNI_yesenv("SUMA_ShareGrandChildrenOverlays")) {
SUMA_S_Warn("Option needs polishing before\n"
"public usage. Nothing is done\n"
"to reflect changes to overlay coloring\n"
"from one group of LocalDom. to another\n"
"that share the same DomainGrandParentID\n");
kin = 2;
} else kin = 1;
if (dov) {
SUMA_LH("Registering plane with surfaces deserving it");
/* Now that you have the color overlay plane set, go about all the surfaces, searching for ones related to SO
and make sure they have this colorplane, otherwise, create a link to it. */
for (i=0; i < N_dov; ++i) {
if (SUMA_isSO(dov[i])) {
SO2 = (SUMA_SurfaceObject *)dov[i].OP;
if (SUMA_isRelated(SO, SO2, kin) && SO != SO2) { /* only 1st order kinship allowed */
/* surfaces related and not identical, check on colorplanes */
if (!SUMA_Fetch_OverlayPointer (SO2->Overlays, SO2->N_Overlays, Overlay->Name, &OverInd)) {
/* color plane not found, link to that of SO */
SO2->Overlays[SO2->N_Overlays] = (SUMA_OVERLAYS *)SUMA_LinkToPointer((void*)SO->Overlays[SO->N_Overlays-1]);
/*increment the number of overlay planes */
++SO2->N_Overlays;
} else {
/* colorplane found OK */
}
}
}
}
}
SUMA_RETURN (YUP);
}
/*!
\brief ans = SUMA_MixColors (sv);
this functions mixes the colors for surface objects that ask for it
\param sv (SUMA_SurfaceViewer *)
\return YUP/NOPE
*/
SUMA_Boolean SUMA_MixColors (SUMA_SurfaceViewer *sv)
{
static char FuncName[]={"SUMA_MixColors"};
int i, dov_id;
SUMA_Boolean LocalHead = NOPE;
SUMA_SurfaceObject *SO = NULL;
SUMA_ENTRY;
for (i=0; i<sv->N_ColList; ++i) {
if (sv->ColList[i].Remix) {
if (LocalHead) fprintf(SUMA_STDERR, "%s: Mixing colors (%s)...\n", FuncName, sv->ColList[i].idcode_str);
dov_id = SUMA_findSO_inDOv (sv->ColList[i].idcode_str, SUMAg_DOv, SUMAg_N_DOv);
if (dov_id < 0) {
fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_findSO_inDOv.\n", FuncName);
SUMA_RETURN(NOPE);
}
SO = (SUMA_SurfaceObject *)SUMAg_DOv[dov_id].OP;
if (!SUMA_Overlays_2_GLCOLAR4(SO, sv, sv->ColList[i].glar_ColorList)) {
fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_Overlays_2_GLCOLAR4.\n", FuncName);
SUMA_RETURN(NOPE);
}
sv->ColList[i].Remix = NOPE;
}
}
SUMA_RETURN (YUP);
}
/*!
\brief A function that looks up an overlay plane by its name.
If the plane is found its index is returned, otherwise
a new one is created. The function also sets up pointers to
that plane for all related surfaces in dov and places node colors
in that plane.
\param SO (SUMA_SurfaceObject *) Surface Object
\param Name (char *) Name of color plane
\param sopd (SUMA_OVERLAY_PLANE_DATA *) Data to put in overlay plane
\param PlaneInd (int *) index of created or found color plane
(that's set by the function )
\param dov (SUMA_DO *) vector of displayable objects
\param N_dov (int ) number of displayable objects
*/
SUMA_Boolean SUMA_iRGB_to_OverlayPointer (SUMA_SurfaceObject *SO,
char *Name, SUMA_OVERLAY_PLANE_DATA *sopd,
int *PlaneInd, SUMA_DO *dov, int N_dov,
DList *DsetList)
{
static char FuncName[]={"SUMA_iRGB_to_OverlayPointer"}, stmp[500];
char *DsetName_tmp=NULL;
int i, OverInd = -1, i_max, wrn_cnt = 0, i3 = 0, N_NodeDef = -1, *NodeDef = NULL;
SUMA_SurfaceObject *SO2 = NULL;
SUMA_OVERLAYS *Overlay=NULL;
SUMA_DSET *dset = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
SUMA_LH("Fetching Overlay Pointer");
/* if plane exists use it, else create a new one on the mappable surface */
if (!SUMA_Fetch_OverlayPointer (SO->Overlays, SO->N_Overlays, Name, &OverInd)) {
SUMA_LH("pointer not found");
/* overlay plane not found, create a new one on the mappable surface*/
if (!SUMA_isLocalDomainParent(SO)) {
if (sopd->Source == SES_Afni) {
/* unexpected, surfaces coming from AFNI with a map should be a local domain parent */
fprintf(SUMA_STDERR,"Error %s: Surface %s (ID: %s) received from AFNI is not a local domain parent.\n", FuncName, SO->Label, SO->idcode_str);
SUMA_RETURN(NOPE);
} else {
SUMA_SL_Warn ("Placing colors on surface \nnot a local domain parent.\nCase not tested.");
}
}
DsetName_tmp = SUMA_append_string(Name, SO->LocalDomainParentID);
dset = SUMA_CreateDsetPointer (DsetName_tmp,
SUMA_NODE_RGB,
NULL,
SO->idcode_str,
SO->N_Node); /* first create a dataset that will go with that colorplane */
SUMA_free(DsetName_tmp); DsetName_tmp = NULL;
/* insert that element into DaList */
if (!SUMA_InsertDsetPointer(&dset, DsetList, 0)) {
SUMA_SL_Err("Failed to insert dset into list");
SUMA_RETURN(NOPE);
}
/* We'll be using NodeDef here so begin by allocating space for the various entries */
SUMA_AddDsetNelCol (dset, "node index", SUMA_NODE_INDEX, NULL, NULL, 1);
SUMA_AddDsetNelCol (dset, "red", SUMA_NODE_R, NULL, NULL, 1);
SUMA_AddDsetNelCol (dset, "green", SUMA_NODE_G, NULL, NULL, 1);
SUMA_AddDsetNelCol (dset, "blue", SUMA_NODE_B, NULL, NULL, 1);
Overlay = SUMA_CreateOverlayPointer (SO->N_Node, Name, dset, SO->idcode_str, NULL);
if (!Overlay) {
fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateOverlayPointer.\n", FuncName);
SUMA_RETURN(NOPE);
}
/* set up some defaults for the overlap plane */
Overlay->Show = sopd->Show;
Overlay->GlobalOpacity = sopd->GlobalOpacity;
Overlay->isBackGrnd = sopd->isBackGrnd;
Overlay->OptScl->BrightFact = sopd->DimFact;
OverInd = SO->N_Overlays;
/* Add this plane to SO->Overlays */
if (!SUMA_AddNewPlane (SO, Overlay, dov, N_dov, 0)) {
SUMA_SL_Crit("Failed in SUMA_AddNewPlane");
SUMA_FreeOverlayPointer(Overlay);
SUMA_RETURN (NOPE);
}
}else {
SUMA_LH("Pointer found");
}
if (LocalHead) fprintf (SUMA_STDERR, "%s: OverInd = %d, Loading colors to Overlay Plane...\n", FuncName, OverInd);
if (sopd->N > SO->N_Node) {
sprintf(stmp,"Number of nodes in colorplane (%d)\n" \
"is larger than number of nodes in surface (%d)\n" \
"Proceed if you know what you're doing.\n" \
"Data from high node indices will be ignored.",
sopd->N, SO->N_Node);
SUMA_SLP_Warn(stmp);
i_max = SO->N_Node;
} else {
i_max = sopd->N;
}
SO->Overlays[OverInd]->DimFact = sopd->DimFact;
SO->Overlays[OverInd]->cmapname = SUMA_copy_string("explicit"); /* explict color definition in data */
SO->Overlays[OverInd]->FullList = 0; /*!< This type of planes is not usually a full list because it has the nodes defined*/
/* Now put the colors in the overlay plane */
if (LocalHead) fprintf (SUMA_STDERR,
"%s: %d node colors are to be inserted.\n",
FuncName, i_max);
COLP_N_NODEDEF(SO->Overlays[OverInd]) = i_max; /* set the number of nodes filled IN THE OVERLAY PLANE*/
SDSET_VECFILLED(SO->Overlays[OverInd]->dset_link) = i_max; /* set the number of nodes filled IN THE DSET, For this
type of dsets, the N_NodeDef is the same for both OVERLAY
and DSET*/
if (COLP_N_NODEDEF(SO->Overlays[OverInd])) {
int *iv, N_i,*Nv;
float *Rv, *Gv, *Bv;
SUMA_DSET *dset;
dset = SO->Overlays[OverInd]->dset_link;
/* find the columns you need to fill. You can't use SUMA_FillNelCol directly because
columns (vectors) are of different types */
if (!(Nv = SUMA_GetNodeDef(dset))) { SUMA_SL_Err("Failed to find node indices."); SUMA_RETURN(NOPE); }
if (LocalHead) SUMA_ShowDset(dset, 0, NULL);
iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_R, &N_i);
if (N_i != 1) { SUMA_SL_Err("Failed to find one column."); SUMA_free(iv); SUMA_RETURN(NOPE); }
Rv = (float *)dset->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_G, &N_i);
if (N_i != 1) { SUMA_SL_Err("Failed to find one column."); SUMA_free(iv); SUMA_RETURN(NOPE); }
Gv = (float *)dset->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_B, &N_i);
if (N_i != 1) { SUMA_SL_Err("Failed to find one column."); SUMA_free(iv); SUMA_RETURN(NOPE); }
Bv = (float *)dset->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
/* Now store these colors into the dataset */
switch (sopd->Type) {
case SOPT_ibbb:
{
int *inel=NULL;
byte *r=NULL, *g=NULL, *b=NULL, *a=NULL;
inel = (int *)sopd->i;
r = (byte *)sopd->r;
g = (byte *)sopd->g;
b = (byte *)sopd->b;
for (i=0; i < i_max; ++i) {
/*fprintf(SUMA_STDERR,"Node %d: r%d, g%d, b%d\n", inel[i], r[i], g[i], b[i]);*/
if (SO->N_Node > inel[i]) {
Nv[i] = inel[i];
Rv[i] = (float)(r[i]) / 255.0;
Gv[i] = (float)(g[i]) / 255.0;
Bv[i] = (float)(b[i]) / 255.0;
} else {
if (!wrn_cnt) {
sprintf(stmp, "Color plane includes node indices (%d at %d)\n" \
"that are >= number of nodes in surface (%d).\n"\
"Other similar warnings will be muted.", inel[i], i, SO->N_Node);
SUMA_SLP_Warn(stmp);
}
++wrn_cnt;
}
}
}
break;
case SOPT_ifff:
{
int *inel=NULL;
float *r=NULL, *g=NULL, *b=NULL, *a=NULL;
inel = (int *)sopd->i;
r = (float *)sopd->r;
g = (float *)sopd->g;
b = (float *)sopd->b;
for (i=0; i < i_max; ++i) {
/*fprintf(SUMA_STDERR,"Node %d: r%f, g%f, b%f\n", inel[i], r[i], g[i], b[i]);*/
if (SO->N_Node > inel[i]) {
Nv[i] = inel[i];
Rv[i] = (float)(r[i]) ;
Gv[i] = (float)(g[i]) ;
Bv[i] = (float)(b[i]) ;
} else {
if (!wrn_cnt) {
SUMA_SLP_Warn("Color plane includes node indices\n" \
"that are >= number of nodes in surface.\n");
}
++wrn_cnt;
}
}
}
break;
default:
SUMA_SLP_Err("Unknown color plane type");
SUMA_RETURN(NOPE);
break;
}
}
/* Now you want to create the colors of that plane based on the data in dset */
if (!SUMA_ColorizePlane (SO->Overlays[OverInd])) {
SUMA_SLP_Err("Failed to colorize plane.\n");
SUMA_RETURN(NOPE);
}
/* store overlay plane index here, OverInd will get mango-ed further down */
if (LocalHead) fprintf (SUMA_STDERR, "%s: OverInd = %d. Returning.\n", FuncName, OverInd);
*PlaneInd = OverInd;
SUMA_RETURN (YUP);
}
/*!
\brief SUMA_FlushPlaneNotInUse (char *PlaneName, SUMA_SurfaceObject *SO, SUMA_DO *dov, int N_dov)
Searches all DrawnROIs in dov.
If no ROI related to SO has PlaneName for a color plane
then that colorplane is flushed (ie no node colors are left in it, not deleted)
*/
SUMA_Boolean SUMA_FlushPlaneNotInUse (char *PlaneName, SUMA_SurfaceObject *SO, SUMA_DO *dov, int N_dov)
{
static char FuncName[]={"SUMA_FlushPlaneNotInUse"};
SUMA_DRAWN_ROI *D_ROI = NULL;
int i, OverInd;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!PlaneName) SUMA_RETURN(YUP);
/* search all dov for ROIs that use the same plane */
for (i=0; i < N_dov; ++i) {
switch (dov[i].ObjectType) { /* case Object Type */
case ROIdO_type:
D_ROI = (SUMA_DRAWN_ROI *)dov[i].OP;
break;
default:
D_ROI = NULL;
break;
}
if (D_ROI && SUMA_isdROIrelated (D_ROI, SO)) {
if (strcmp(PlaneName, D_ROI->ColPlaneName) == 0) {
/* found one, do nothing and return */
SUMA_RETURN (YUP);
}
}
}
/* looks like no other ROIs use that plane, flush it */
if (!SUMA_Fetch_OverlayPointer (SO->Overlays, SO->N_Overlays, PlaneName, &OverInd)) {
SUMA_SLP_Warn("No Overlay Plane Found!");
SUMA_RETURN (YUP);
}
SUMA_LH("Flushing meadows");
#if 0
SO->Overlays[OverInd]->N_NodeDef = 0; /* Flushed */
#else
COLP_N_NODEDEF(SO->Overlays[OverInd]) = 0;
#endif
SUMA_RETURN (YUP);
}
/*!
\brief refreshes a colorplane list.
A combo of SUMA_AssembleColorPlaneList and SUMA_CreateScrolledList.
*/
void SUMA_RefreshDsetList (SUMA_SurfaceObject *SO)
{
static char FuncName[]={"SUMA_RefreshDsetList"};
SUMA_LIST_WIDGET *LW = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
LW = SO->SurfCont->SwitchDsetlst;
if (!LW) SUMA_RETURNe;
if (LW->ALS) {
/* free that old hag */
if (LocalHead) SUMA_S_Err("Freeing the hag.");
LW->ALS = SUMA_FreeAssembleListStruct(LW->ALS);
}
/* assemble the ColorPlane list */
LW->ALS = SUMA_AssembleColorPlaneList (SO);
if (!LW->ALS) {
SUMA_SLP_Err("Error assembling list.");
SUMA_RETURNe;
}
if (LW->ALS->N_clist < 0) {
SUMA_SL_Err("Failed in SUMA_AssembleColorPlaneList");
SUMA_RETURNe;
}
if (!LW->ALS->N_clist) {
SUMA_SLP_Note ("No Color planes to choose from.");
SUMA_RETURNe;
}
if (LocalHead) {
int i;
for (i=0; i < LW->ALS->N_clist; ++i) fprintf (SUMA_STDERR,"%s: %s\n", FuncName, LW->ALS->clist[i]);
}
SUMA_CreateScrolledList ( LW->ALS->clist, LW->ALS->N_clist, NOPE,
LW);
SUMA_RETURNe;
}
/*!
\brief Returns a list of the Colorplanes belonging to a certain surface.
\param SO (SUMA_SurfaceObject *) pointer to surface object
\return clist (SUMA_ASSEMBLE_LIST_STRUCT *) pointer to structure containing results
\sa SUMA_FreeAssembleListStruct
\sa SUMA_CreateAssembleListStruct
*/
SUMA_ASSEMBLE_LIST_STRUCT * SUMA_AssembleColorPlaneList (SUMA_SurfaceObject *SO)
{
static char FuncName[]={"SUMA_AssembleColorPlaneList"};
int i=-1, N_clist=-1;
DList *list=NULL, *listop = NULL, *OverlayPlanelist = NULL;
DListElmt *Elm = NULL, *Elmop = NULL, *Elm_OverlayPlanelist = NULL;
char Label[SUMA_MAX_NAME_LENGTH], *store=NULL;
char **clist=NULL;
void **oplist=NULL;
SUMA_ASSEMBLE_LIST_STRUCT *clist_str = NULL;
SUMA_OVERLAY_LIST_DATUM *OvD=NULL, *oOvD=NULL;
SUMA_Boolean SortByOrder = YUP;
SUMA_Boolean Found = NOPE;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
/* get list of all Overlay planes */
OverlayPlanelist = SUMA_OverlaysToOrderedList (SO, 0);
/* need a list to store new names */
list = (DList *)SUMA_malloc(sizeof(DList));
dlist_init(list, NULL); /* you don't want to free the strings */
/* need a list to store the pointers, it is useless when SortByOrder is used, but I leave it in to keep the code simple */
listop = (DList *)SUMA_malloc(sizeof(DList));
dlist_init(listop, NULL); /* you don't want to free the data as it is copied from OverlayPlanelist*/
clist = NULL;
N_clist = -1;
Elm_OverlayPlanelist = NULL;
do {
if (!Elm_OverlayPlanelist) Elm_OverlayPlanelist = dlist_head(OverlayPlanelist);
else Elm_OverlayPlanelist = Elm_OverlayPlanelist->next;
OvD = (SUMA_OVERLAY_LIST_DATUM *) Elm_OverlayPlanelist->data;
if (!OvD->Overlay->Label) sprintf (Label,"NULL");
else sprintf (Label,"%s", OvD->Overlay->Label);
SUMA_LH(Label);
/* Now allocate space for that label */
store = (char *)SUMA_calloc(strlen(Label)+10, sizeof(char));
if (OvD->Overlay->isBackGrnd) {
sprintf(store,"bk:%s", Label);
} else {
sprintf(store,"fg:%s", Label);
}
if (SortByOrder) {
SUMA_LH("Sorting by order");
/* list is already sorted, just copy the string and object structure pointers to lists */
dlist_ins_next(list, dlist_tail(list), (void*)store);
/* this line is redundant with SortByOrder but it don't hoyt */
dlist_ins_next(listop, dlist_tail(listop), (void*)OvD);
} else { /* sort the list by aplhpabetical order */
SUMA_LH("Sorting by name");
if (!list->size) {
dlist_ins_next(list, dlist_tail(list), (void*)store);
dlist_ins_next(listop, dlist_tail(listop), (void*)OvD);
}else { /* must sort first */
Elm = NULL;
Elmop = NULL;
do {
Found = NOPE;
if (!Elm) {
Elm = dlist_head(list);
Elmop = dlist_head(listop);
} else {
Elm = Elm->next;
Elmop = Elmop->next;
}
if (strcmp(store, (char*)Elm->data) <= 0) {
dlist_ins_prev(list, Elm, (void *)store);
dlist_ins_prev(listop, Elmop, (void *)OvD);
Found = YUP;
} else if (Elm == dlist_tail(list)) {
/* reached the end, append */
dlist_ins_next(list, Elm, (void *)store);
dlist_ins_next(listop, Elmop, (void *)OvD);
Found = YUP;
}
} while (!Found);
}
}
} while (Elm_OverlayPlanelist != dlist_tail(OverlayPlanelist));
SUMA_LH("saving list.");
if (!list->size) { /* Nothing found */
SUMA_LH("Empty list");
N_clist = 0;
}else {
Elm = NULL;
Elmop = NULL;
clist = (char **)SUMA_calloc(list->size, sizeof(char *));
oplist = (void **)SUMA_calloc(list->size, sizeof(void *));
for (i=0; i< list->size; ++i) {
if (!Elm) {
Elm = dlist_head(list);
Elmop = dlist_head(listop);
} else {
Elm = dlist_next(Elm);
Elmop = dlist_next(Elmop);
}
clist[i] = (char*)Elm->data;
OvD = (SUMA_OVERLAY_LIST_DATUM *) Elmop->data;
oplist[i] = (void *)OvD->Overlay;
if (LocalHead) fprintf (SUMA_STDERR,"%s: Inserting %s with %s (%s).\n",
FuncName, clist[i], OvD->Overlay->Label, OvD->Overlay->Name);
}
N_clist = list->size;
/* destroy list */
dlist_destroy(list);
dlist_destroy(listop);
dlist_destroy(OverlayPlanelist);
SUMA_free(list);
SUMA_free(listop);
SUMA_free(OverlayPlanelist);
}
clist_str = SUMA_CreateAssembleListStruct();
clist_str->clist = clist;
clist_str->oplist = oplist;
clist_str->N_clist = N_clist;
/* return */
SUMA_RETURN (clist_str);
}
/*!
\brief determines if a Dset is related to a surface
*/
SUMA_Boolean SUMA_isDsetRelated(SUMA_DSET *dset, SUMA_SurfaceObject *SO)
{
static char FuncName[]={"SUMA_isDsetRelated"};
char *mp = NULL;
int lmp = 0;
SUMA_ENTRY;
if (!dset) SUMA_RETURN(NOPE);
if (!SO) SUMA_RETURN(NOPE);
mp = SDSET_IDMDOM(dset); if (mp) lmp = strlen(mp); else lmp = 0;
if (mp && lmp) {
if (strcmp(mp, SO->idcode_str) == 0) SUMA_RETURN(YUP);
if (SO->DomainGrandParentID) {
if (strcmp(mp, SO->DomainGrandParentID) == 0) SUMA_RETURN(YUP);
}
if (SO->LocalDomainParentID) {
if (strcmp(mp, SO->LocalDomainParentID) == 0) SUMA_RETURN(YUP);
}
}
SUMA_RETURN(NOPE);
}
SUMA_Boolean SUMA_isDsetColumn_inferred(SUMA_DSET *dset, int icol)
{
static char FuncName[]={"SUMA_isDsetColumn_inferred"};
char *lblcp=NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
lblcp = SUMA_DsetColLabelCopy(dset, icol, 0);
SUMA_LH(lblcp);
if (lblcp) {
if (strstr(lblcp, "(inferred)")) SUMA_RETURN(YUP);
}
SUMA_free(lblcp);
SUMA_RETURN(NOPE);
}
/*!
\brief determines if a Dset can be assigned to a surface object
*/
SUMA_Boolean SUMA_OKassign(SUMA_DSET *dset, SUMA_SurfaceObject *SO)
{
static char FuncName[]={"SUMA_OKassign"};
float range[2];
int loc[2], *ind = NULL, lnp = 0;
char *np = NULL, stmp[201];
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!dset) SUMA_RETURN(NOPE);
if (!SO) SUMA_RETURN(NOPE);
/* does dset have a mesh parent ? */
np = SDSET_IDMDOM(dset); if (np) lnp = strlen(np); else lnp = 0;
if (np && lnp) {
SUMA_LH("Has IDMDOM");
/* has parent, verify against SO*/
if (SUMA_isDsetRelated(dset, SO)) { SUMA_LH("Is Related"); SUMA_RETURN(YUP); }
else { SUMA_LH("Is NOT Related"); SUMA_RETURN(NOPE); }
}
SUMA_LH("Has no parent, trying adoption");
/* has no parent, check if you can adopt it*/
ind = SUMA_GetNodeDef(dset);
if (!ind) {
SUMA_LH("No node index column");
/* No node index. Make sure vec_len <= SO->N_Node */
if (SDSET_VECLEN(dset) <= SO->N_Node) {
SUMA_LH("Number of values per column\n"
"is less than the number \n"
"of nodes in the surface.\n");
if (SDSET_VECFILLED(dset) != SO->N_Node) {
SUMA_LH("Need to attach a node index column, if possible");
/* attempt to assign a node index column */
if (!SUMA_AddNodeIndexColumn(dset, SO->N_Node)) {
SUMA_LH(" Failed to add a node index column");
SUMA_RETURN(NOPE);
} else {
SUMA_LH("Added Index Column");
SUMA_RETURN(YUP);
}
}else {
SUMA_LH( "Looks like a full list of values\n"
"Techincally, there's no need for explicit node column.\n"
"But at times, the data are not ordered by ascending node \n"
"index which causes trouble.\nSo now I add a node index column"
" always which would help point to the problem if it arises");
/* Sept 21 04, call SUMA_AddNodeIndexColumn, it is good for you. Might add an unecessary index column when none exit but makes things clear*/
if (!SUMA_AddNodeIndexColumn(dset, SO->N_Node)) {
SUMA_LH(" Failed to add a node index column");
SUMA_RETURN(NOPE);
}
SUMA_LH("Added Index Column");
SUMA_RETURN(YUP);
}
} else {
snprintf(stmp, 200*sizeof(char),
"Number of values per column (%d)\n"
"is larger than the number \n"
"of nodes (%d) in the surface.", SDSET_VECLEN(dset), SO->N_Node);
SUMA_SLP_Warn(stmp);
SUMA_RETURN(NOPE);
}
} else {
SUMA_LH("Node index column found");
/* there is a node index column, see if the range is OK */
if (!SUMA_GetDsetNodeIndexColRange(dset, range, loc, 1)) {
SUMA_SLP_Err("Unexpect error in SUMA_GetDsetColRange");
SUMA_RETURN(NOPE);
}
if (range[0] < 0 || range[1] > SO->N_Node) {
SUMA_SLP_Err("Node index range outside\n"
"0 and SO->N_Node");
SUMA_RETURN(NOPE);
}
/* Now we're OK to return on a positive note */
SUMA_RETURN(YUP);
}
SUMA_SL_Err("Should not get here");
SUMA_RETURN(NOPE);
}
/*!
\brief Loads a Dset file and adds it to the list of datasets
\param dlg (SUMA_SELECTION_DIALOG_STRUCT *) struture from selection dialogue
*/
void SUMA_LoadDsetFile (char *filename, void *data)
{
static char FuncName[]={"SUMA_LoadDsetFile"};
SUMA_SurfaceObject *SO = NULL;
SUMA_IRGB *irgb=NULL;
int OverInd = -1, lnp=-1, loc[2], OKdup = 0;
char *np=NULL;
SUMA_DSET_FORMAT form;
DList *list=NULL;
SUMA_LIST_WIDGET *LW=NULL;
SUMA_DSET *dset = NULL, *dsetpre = NULL;
SUMA_OVERLAYS *NewColPlane = NULL, *colplanepre = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!data) {
SUMA_SLP_Err("Null data");
SUMA_RETURNe;
}
SO = (SUMA_SurfaceObject *)data;
if (LocalHead) {
fprintf (SUMA_STDERR,"%s: Received request to load %s for surface %s.\n", FuncName, filename, SO->Label);
}
/* find out if file exists and how many values it contains */
if (!SUMA_filexists(filename)) {
SUMA_SLP_Err("File not found");
SUMA_RETURNe;
}
/* take a stab at the format */
form = SUMA_GuessFormatFromExtension(filename);
/* load the dude */
/* first, set the parent ID of the dset to be loaded,
This parent ID is only used when generating an ID for those dsets
that have no ID attached, like the 1D ones */
if (SO->LocalDomainParentID) SUMA_SetParent_DsetToLoad(SO->LocalDomainParentID);
else if (SO->idcode_str) SUMA_SetParent_DsetToLoad(SO->idcode_str);
else SUMA_SetParent_DsetToLoad(NULL);
dset = SUMA_LoadDset_s (filename, &form, 0);
SUMA_LHv("Dset as loaded is %p\n", dset);
if (!dset) { SUMA_SLP_Err( "Failed to load dataset.\n"
"Make sure file exists\n"
"and is of a supported\n"
"format."); SUMA_RETURNe; }
SUMA_SetParent_DsetToLoad(NULL); /* reset the parent surface flag */
if (LocalHead) {
char *si = NULL;
si = SUMA_DsetInfo(dset, 0);
fprintf(SUMA_STDERR,"%s:\n----------------dset loaded ----------\n%s\n",FuncName, si);
SUMA_free(si); si = NULL;
}
/* Check if the domain order is SO or not .
If not specified, assign it */
np = SDSET_IDMDOM(dset); if (np) lnp = strlen(np) ; else lnp = 0;
if (!np || lnp == 0) {
SUMA_SL_Note("dset has no mesh parent, assigning SO");
if (!SUMA_OKassign(dset, SO)) {
SUMA_SurfaceObject *SOldp = SUMA_findSOp_inDOv(SO->LocalDomainParentID,SUMAg_DOv, SUMAg_N_DOv);
if (SOldp) {
SUMA_SLP_Note("Could not assign dset to SO.\nTrying to assign to domain parent.");
if (!SUMA_OKassign(dset, SOldp)) {
SUMA_SLP_Err("Cannot assign dset to SO \nor its local domain parent");
SUMA_FreeDset(dset); dset=NULL;
SUMA_RETURNe;
}
/* from that point on, treat dset as if being loaded onto SOpar*/
SO = SOldp;
} else {
SUMA_SLP_Err("Cannot assign dset to SO.");
SUMA_FreeDset(dset); dset=NULL;
SUMA_RETURNe;
}
}
NI_set_attribute(dset->ngr,"domain_parent_idcode", SO->idcode_str);
NI_set_attribute(dset->ngr,"geometry_parent_idcode", SO->idcode_str);
} else {
SUMA_SL_Note("dset has a mesh parent, Checking relationship");
if (!SUMA_isDsetRelated(dset, SO)) {
SUMA_SLP_Err("Dset not related to SO");
SUMA_FreeDset(dset); dset=NULL;
SUMA_RETURNe;
}
}
/* add the dset to the list SUMAg_CF->DsetList*/
dsetpre = dset;
if (LocalHead) {
fprintf(SUMA_STDERR,"%s: New dset (%s) has pointer %p\n", FuncName, SDSET_LABEL(dset), dset);
}
if (!SUMA_InsertDsetPointer(&dset, SUMAg_CF->DsetList, SUMAg_CF->Allow_Dset_Replace)) {
SUMA_SLP_Err("Failed to add new dset to list");
/* is there not a function to replace a dset yet? */
SUMA_FreeDset(dset); dset = NULL;
SUMA_RETURNe;
}
if (LocalHead) {
fprintf(SUMA_STDERR,"%s: Now dset (%s) is pointer %p\n", FuncName, SDSET_LABEL(dset), dset);
}
OverInd = -1;
{
SUMA_LH("Forget not the cleanup ");
if (dset != dsetpre) { /* dset was pre-existing in the list */
if (LocalHead) {
fprintf(SUMA_STDERR,"%s: Dset %s (%p) pre-existing, finding its pre-existing overlays.\n", FuncName, SDSET_LABEL(dset), dset);
}
if (!(colplanepre = SUMA_Fetch_OverlayPointerByDset (SO->Overlays, SO->N_Overlays, dset, &OverInd))) {
SUMA_SLP_Err("Failed to fetch existing dset's overlay pointer");
/* is there not a function to replace a dset yet? */
/* SUMA_FreeDset(dset); dset = NULL; do not free existing dset */
SUMA_RETURNe;
}
/* have bias? REMOVE IT! */
if (!SUMA_RemoveCoordBias(colplanepre)) {
SUMA_SLP_Err("Failed to remove coord bias");
SUMA_RETURNe;
}
OKdup = 1;
} else { /* dset is considered new */
colplanepre = NULL;
/* The overlay index for that plane is SO->N_Overlays */
OverInd = SO->N_Overlays;
OKdup = 0;
}
/* set up the colormap for this dset */
NewColPlane = SUMA_CreateOverlayPointer (SDSET_VECLEN(dset), filename, dset, SO->idcode_str, colplanepre);
if (!NewColPlane) {
fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_CreateOverlayPointer.\n", FuncName);
SUMA_RETURNe;
}
/* Add this plane to SO->Overlays */
if (!SUMA_AddNewPlane (SO, NewColPlane, SUMAg_DOv, SUMAg_N_DOv, OKdup)) {
SUMA_SL_Crit("Failed in SUMA_AddNewPlane");
SUMA_FreeOverlayPointer(NewColPlane);
SUMA_FreeDset(dset); dset = NULL;
SUMA_RETURNe;
}
}
/* set the opacity, index column and the range */
NewColPlane->GlobalOpacity = YUP;
NewColPlane->Show = YUP;
NewColPlane->OptScl->find = 0;
NewColPlane->OptScl->tind = 0;
NewColPlane->OptScl->bind = 0;
SUMA_GetDsetColRange(dset, 0, NewColPlane->OptScl->IntRange, loc);
/* stick a colormap onto that plane ? */
/* don't worry, there's a default one */
/* colorize the plane */
SUMA_ColorizePlane(NewColPlane);
/* SUMA_Show_ColorOverlayPlanes(&NewColPlane, 1, 1); */
/* set the new curColPlane to the newly loaded plane,
you need to do this before you remix the colors in case
you are only showing the curColPlane.
curColPlane is normally set in SUMA_InitializeColPlaneShell
but when SO->SurfCont->ShowCurOnly = YUP, curColPlane
is used in the RemixRedisplay function.
NOTE: You can't call SUMA_InitializeColPlaneShell
before remixing because colors are reported in Lbl block
June 28 04*/
SO->SurfCont->curColPlane = SO->Overlays[OverInd];
/* remix-redisplay for surface */
if (!SUMA_RemixRedisplay (SO)) {
SUMA_RETURNe;
}
SUMA_LH("Refreshing Dset list");
/*update the list widget if open */
LW = SO->SurfCont->SwitchDsetlst;
if (LW) {
if (!LW->isShaded) SUMA_RefreshDsetList (SO);
}
if (LocalHead) fprintf (SUMA_STDERR,"%s: Updating Dset frame, OverInd=%d\n",
FuncName, OverInd);
/* update the Dset frame */
if (OverInd >= 0)
SUMA_InitializeColPlaneShell(SO, SO->Overlays[OverInd]);
SUMA_RETURNe;
}
/*!
\brief Loads a color plane file and adds it to a surface's list of colorplanes
\param dlg (SUMA_SELECTION_DIALOG_STRUCT *) struture from selection dialogue
*/
void SUMA_LoadColorPlaneFile (char *filename, void *data)
{
static char FuncName[]={"SUMA_LoadColorPlaneFile"};
SUMA_SurfaceObject *SO = NULL;
SUMA_OVERLAY_PLANE_DATA sopd;
SUMA_IRGB *irgb=NULL;
int OverInd = -1;
DList *list=NULL;
SUMA_LIST_WIDGET *LW=NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!data) {
SUMA_SLP_Err("Null data");
SUMA_RETURNe;
}
SO = (SUMA_SurfaceObject *)data;
if (LocalHead) {
fprintf (SUMA_STDERR,"%s: Received request to load %s for surface %s.\n", FuncName, filename, SO->Label);
}
/* find out if file exists and how many values it contains */
if (!SUMA_filexists(filename)) {
SUMA_SLP_Err("File not found");
SUMA_RETURNe;
}
irgb = SUMA_Read_IRGB_file(filename);
if (!irgb) {
SUMA_SLP_Err("Failed to read file.");
SUMA_RETURNe;
}
sopd.N = irgb->N;
sopd.Type = SOPT_ifff;
sopd.Source = SES_Suma;
sopd.GlobalOpacity = 0.3;
sopd.isBackGrnd = NOPE;
sopd.Show = YUP;
/* dim colors from maximum intensity to preserve surface shape highlights, division by 255 is to scale color values between 1 and 0 */
sopd.DimFact = 0.5;
sopd.i = (void *)irgb->i;
sopd.r = (void *)irgb->r;
sopd.g = (void *)irgb->g;
sopd.b = (void *)irgb->b;
sopd.a = NULL;
if (!SUMA_iRGB_to_OverlayPointer ( SO, filename, &sopd, &OverInd,
SUMAg_DOv, SUMAg_N_DOv, SUMAg_CF->DsetList)) {
SUMA_SLP_Err("Failed to fetch or create overlay pointer.");
SUMA_RETURNe;
}
/* values were copied, dump structure */
irgb = SUMA_Free_IRGB(irgb);
/* See note before similar line in SUMA_LoadDsetFile */
SO->SurfCont->curColPlane = SO->Overlays[OverInd];
if (!SUMA_RemixRedisplay (SO)) {
SUMA_RETURNe;
}
SUMA_LH("Refreshing color plane list");
/*update the list widget if open */
LW = SO->SurfCont->SwitchDsetlst;
if (LW) {
if (!LW->isShaded) SUMA_RefreshDsetList (SO);
}
if (LocalHead) fprintf (SUMA_STDERR,"%s: Updating color plane frame, OverInd=%d\n",
FuncName, OverInd);
/* update the color plane frame */
if (OverInd >= 0)
SUMA_InitializeColPlaneShell(SO, SO->Overlays[OverInd]);
SUMA_RETURNe;
}
/*** AFNI setup functions taken and trimmed from afni_setup.c
Reason for duplicating the functions is the complicated dependencies
of some functions in afni_setup */
/*-----------------------------------------------------------------------
Process an AFNI setup file.
-------------------------------------------------------------------------*/
#define SUMA_ISTARRED(s) ( (s)[0]=='*' && (s)[1]=='*' && (s)[2]=='*' )
#define SUMA_EOLSKIP \
do{ for( ; fptr[0] != '\n' && fptr[0] != '\0' ; fptr++ ) ; /* nada */ \
if( fptr[0] == '\0' ){ if (fbuf) free(fbuf) ; fbuf = NULL; goto donesection; } \
fptr++ ; } while(0)
#define SUMA_GETSSS \
do{ int nu=0,qq; \
if( fptr-fbuf >= nbuf || fptr[0] == '\0' ){ if (fbuf) free(fbuf); fbuf = NULL; goto donesection; } \
str[0]='\0'; qq=sscanf(fptr,"%127s%n",str,&nu); nused+=nu;fptr+=nu; \
if( str[0]=='\0' || qq==0 || nu==0 ){ if (fbuf) free(fbuf); fbuf = NULL; goto donesection; } \
} while(0)
#define SUMA_GETSTR \
do{ SUMA_GETSSS ; \
while(str[0]=='!' || (str[0]=='/' && str[1]=='/')){SUMA_EOLSKIP; SUMA_GETSSS;} \
} while(0)
#define SUMA_GETEQN \
do{ SUMA_GETSTR ; if(SUMA_ISTARRED(str)) goto SkipSection ; \
strcpy(left,str) ; \
SUMA_GETSTR ; if(SUMA_ISTARRED(str)) goto SkipSection ; \
strcpy(middle,str) ; \
SUMA_GETSTR ; if(SUMA_ISTARRED(str)) goto SkipSection ; \
strcpy(right,str) ; } while(0)
#define SUMA_NSBUF 256
/*!
\brief Extracts colors and colormaps from AFNI formatted .pal files
Also used to extract such info from .afnirc file
\param fname (char *) name of file containing colors.
either .afnirc or a .pal file
\param SAC (SUMA_AFNI_COLORS *) pointer to structure that will contain
the default afni colors and colormaps.
This structure must have been previously initialized
in SUMA_Get_AFNI_Default_Color_Maps which also
automatically scans ~/.afnirc then ./afnirc if the former
one was not found.
\return N_palsRead (int) number of palettes found and read
-1 if trouble reading at least one of the palettes
*/
int SUMA_AFNI_Extract_Colors ( char *fname, SUMA_AFNI_COLORS *SAC )
{
static char FuncName[]={"SUMA_AFNI_Extract_Colors"};
int nbuf , nused , ii, ngood = -1;
float rgb[3];
char * fbuf , * fptr ;
char str[SUMA_NSBUF] , left[SUMA_NSBUF] , middle[SUMA_NSBUF] , right[SUMA_NSBUF] ;
SUMA_STRING *SS = NULL;
SUMA_COLOR_MAP *CM=NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
fbuf = AFNI_suck_file( fname ) ; if( fbuf == NULL ) {
SUMA_SL_Warn("File could not be read");
SUMA_RETURN(-1) ; }
nbuf = strlen(fbuf) ; if( nbuf == 0 ) {
SUMA_SL_Warn("Empty file");
SUMA_RETURN(-1) ; }
fptr = fbuf ; nused = 0 ;
/** scan for section strings, which start with "***" **/
ngood = 0; /* assume none will be found */
str[0] = '\0' ; /* initialize string */
if(LocalHead) {
fprintf(SUMA_STDERR,"Reading AFNI setup file = %s (%d bytes)",fname,nbuf) ;
}
while( nused < nbuf ){
/**----------------------------------------**/
/**-- skip ahead to next section keyword --**/
SkipSection: while( ! SUMA_ISTARRED(str) ){ SUMA_GETSTR; SUMA_LH(str);}
/*- 04 Jun 1999 -*/
if( strcmp(str, "***COLORS") != 0 && strcmp(str, "***PALETTES") != 0){
SUMA_GETSTR ;
goto SkipSection ;
}
SS = SUMA_StringAppend (NULL, NULL);
/**--------------------**/
/**-- COLORS section --**/
if( strcmp(str,"***COLORS") == 0 ){
char label[SUMA_NSBUF] , defn[SUMA_NSBUF] ;
if (LocalHead) fprintf (SUMA_STDERR,"%s: Found ***COLORS\n", FuncName);
while(1){ /* loop, looking for 'label = color' */
SUMA_GETEQN ;
if (LocalHead) {
fprintf (SUMA_STDERR,"\t %s%s%s\n", left, middle, right);
}
if( !THD_filename_pure(left) ) continue ;
/* don't allow 'none' to be redefined! */
if( strcmp(left,"none")==0 || strcmp(right,"none")==0 ) {
sprintf(left,"none");
rgb[0] = rgb[1] = rgb[2] =-1.0;
} else {
if (!SUMA_Interpret_AFNIColor (right, rgb)) {
fprintf(SUMA_STDERR,"Error %s: Failed to interpret color %s\n", FuncName, right);
SUMA_RETURN(-1);
}
}
SAC->Cv = SUMA_Add_Color (left,
rgb[0], rgb[1], rgb[2], 1.0,
SAC->Cv, &(SAC->N_cols));
}
continue ; /* skip to end of outer while loop */
} /* end of COLORS */
/**----------------------**/
/**-- PALETTES section --**/
if( strcmp(str,"***PALETTES") == 0 ){ /* loop, looking for palettes */
char label[SUMA_NSBUF] = "NoThing" , ccc , * cpt ;
PBAR_palette_array * ppar=NULL ;
PBAR_palette ** ppp ;
PBAR_palette * ppnew ;
int npane , pmode , icol=0 , jj ;
float val ;
if (LocalHead) fprintf (SUMA_STDERR,"enter ***PALETTES\n");
/* loop, looking for palettes */
while(1){
SUMA_GETSTR ; if( SUMA_ISTARRED(str) ) goto SkipSection ;
if( fptr-fbuf >= nbuf ){ if (fbuf) free(fbuf) ; fbuf = NULL; SUMA_RETURN(-1) ; }
if( str[0] != '[' ){ /* found a palette label */
strcpy(label,str) ;
if( !THD_filename_ok(label) ){
fprintf(SUMA_STDERR,"Error %s: In setup file %s, bad palette label: %s.\n Ignoring palette.\n",
FuncName, fname,label) ;
if (fbuf) free(fbuf) ; fbuf = NULL;
SUMA_RETURN(-1) ;
}
if (LocalHead) {
fprintf (SUMA_STDERR,"%s: found palette label=%s. [len=%d label[0]=%d]\nnbuf=%d fptr-fbuf=%d\n",
FuncName, label,(int)strlen(label),(int)label[0],
nbuf,fptr-fbuf);
}
SUMA_GETSTR ; if( SUMA_ISTARRED(str) ) goto SkipSection ;
}
if( str[0] != '[' ){ /* bad news! */
fprintf(SUMA_STDERR,"Error %s: In setup file %s, expected palette '[n]' here: %s.\n",
FuncName, fname , str ) ;
SUMA_RETURN(-1) ;
}
/* decide how big the new palette is to be, and what mode */
ii = sscanf( str , "[%d%c" , &npane , &ccc ) ;
if( ii < 2 ){
fprintf(SUMA_STDERR,"%s: In setup file %s, can't interpret palette %s\n",
FuncName, fname , str ) ;
SUMA_RETURN(-1) ;
} else if( npane < NPANE_MIN || npane > NPANE_MAX ){
fprintf(SUMA_STDERR,"%s: In setup file %s, illegal palette count %s.\n",
FuncName, fname , str ) ;
SUMA_RETURN(-1) ;
}
/* at this point, now loop to read parameters for new palette */
if (LocalHead) {
fprintf(SUMA_STDERR,"%s: About to read %d panes.\n", FuncName, npane);
}
/* prepare the colormap */
CM = (SUMA_COLOR_MAP *)SUMA_malloc(sizeof(SUMA_COLOR_MAP));
if (CM == NULL) {
SUMA_SL_Crit ("Failed to allocate for CM");
SUMA_RETURN(-1);
}
CM->top_frac = 0.0f;
CM->SO = NULL;
CM->N_Col = npane;
CM->cname = NULL;
if (ccc == '+') CM->Sgn = 1;
else CM->Sgn = -1;
CM->Name = (char *)SUMA_calloc(strlen(label)+10, sizeof(char));
CM->frac = (float *)SUMA_calloc(CM->N_Col, sizeof(float));
CM->M = (float**)SUMA_allocate2D (CM->N_Col, 3, sizeof(float));
if ( CM->frac == NULL || CM->M == NULL || CM->Name == NULL ) {
SUMA_SL_Crit ("Failed to allocate for fields of CM.");
SUMA_RETURN (-1);
}
if (CM->Sgn == 1) sprintf(CM->Name, "%s_p%d", label, CM->N_Col);
else sprintf(CM->Name, "%s_n%d", label, CM->N_Col);
for( ii=0 ; ii < npane ; ii++ ){
SUMA_GETEQN ;
if (LocalHead) {
fprintf(SUMA_STDERR,"%s: SUMA_GETEQN: %s %s %s\n",FuncName, left,middle,right) ;
}
/* find that color */
icol = SUMA_Find_Color (right, SAC->Cv, SAC->N_cols);
if (icol < 0) {
fprintf(SUMA_STDERR,"Error %s: Color %s not found in dbase.\nUsing no-color in its place\n", FuncName, right);
CM->M[npane - ii - 1][0] = CM->M[npane - ii - 1][1] = CM->M[npane - ii - 1][2] = -1.0;
} else {
CM->M[npane - ii - 1][0] = SAC->Cv[icol].r;
CM->M[npane - ii - 1][1] = SAC->Cv[icol].g;
CM->M[npane - ii - 1][2] = SAC->Cv[icol].b;
}
CM->frac[npane - ii - 1] = atof(left);
}
if (CM->frac[CM->N_Col-1] != 1.0f) {
CM->top_frac = CM->frac[CM->N_Col-1];
}
/* add the map to the list */
SAC->CMv = SUMA_Add_ColorMap (CM, SAC->CMv, &(SAC->N_maps));
if (SAC->CMv) ++ngood;
continue ; /* to end of outer while */
}
} /* end of PALETTES */
SUMA_GETSTR ; goto SkipSection ; /* find another section */
} /* end of while loop */
donesection:
if (LocalHead) fprintf(SUMA_STDERR,"%s: Returning\n", FuncName);
if (fbuf) free(fbuf) ;
SUMA_RETURN (ngood);
}
/*!
\brief turns a color defined by it's Xname or AFNI Hex formulation
into good old RGB
- The function is not particularly efficient for parsing numerous
Xnamed colors...
*/
SUMA_Boolean SUMA_Interpret_AFNIColor (char *Name, float RGB[3])
{
static char FuncName[]={"SUMA_Interpret_AFNIColor"};
char *vargv[1]={ "SCALE_TO_MAP" };
int cargc = 1;
int r, g, b;
char stmp[10];
XVisualInfo vtmp, *vislist;
XtAppContext app;
Widget tl;
Display *dpy=NULL;
XColor color_closest, color_exact;
Colormap cmap;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (Name[0] == '#') { /* explicitly defined */
sprintf(stmp,"0x%c%c", Name[1], Name[2]);
sscanf (stmp, "%x", &r);
sprintf(stmp,"0x%c%c", Name[3], Name[4]);
sscanf (stmp, "%x", &g);
sprintf(stmp,"0x%c%c", Name[5], Name[6]);
sscanf (stmp, "%x", &b);
RGB[0] = (float)r/255.0;
RGB[1] = (float)g/255.0;
RGB[2] = (float)b/255.0;
} else { /* named */
/* XtAppInitialize (at least on mac osx) forces the application to quit if display cannot be opened
So you must decide ahead of time whether to call it or not! */
if (SUMAg_CF->isGraphical) {
/* tl = XtAppInitialize(&app, "ScaleToMap", NULL, 0, &cargc, vargv,
SUMA_get_fallbackResources(), NULL, 0); Superseded by XtOpenApplication */
tl = XtOpenApplication(&app, "ScaleToMap", NULL, 0, &cargc, vargv,
SUMA_get_fallbackResources(),topLevelShellWidgetClass, NULL, 0);
dpy = XtDisplay(tl);
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
XParseColor(dpy, cmap, Name, &color_exact);
/* You need to divide by color_exact.red ,green and blue by 257
to bring the numbers in the 0..255 range as listed in the rgb.txt file */
RGB[0] = (float)color_exact.red/255.0/257.0;
RGB[1] = (float)color_exact.green/255.0/257.0;
RGB[2] = (float)color_exact.blue/255.0/257.0;
XFreeColormap(dpy, cmap);
/* These 2 lines cause a crash on Fedora Core 4, but Core 4 crashes at XmCreateMainWindow anyway so we're doomed.*/
XtDestroyWidget(tl);
XtDestroyApplicationContext(app);
} else {
if (LocalHead) fprintf(SUMA_STDERR,"%s: \n"
"Xcolor %s cannot be resolved without \n"
"trying to open X display.\n"
"Returning color 0.5 0.5 0.5", FuncName, Name);
RGB[0] = RGB[1] = RGB[2] = 0.5;
}
}
if (LocalHead) {
fprintf (SUMA_STDERR,"%s: %s = %f %f %f\n",
FuncName, Name, RGB[0], RGB[1], RGB[2]);
}
SUMA_RETURN (YUP);
}
/*!
\brief colorize the data of the colorplane
*/
int SUMA_ColorizePlane (SUMA_OVERLAYS *cp)
{
static char FuncName[]={"SUMA_ColorizePlane"};
int i, i3, N_i, *iv, *Nv;
float *Rv, *Bv, *Gv;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (LocalHead) {
SUMA_LH("Color Plane Pre Colorizing");
SUMA_Show_ColorOverlayPlanes ( &cp, 1, 0);
}
if (!cp) { SUMA_SL_Err("NULL cp"); SUMA_RETURN(NOPE); }
if (!cp->dset_link) { SUMA_SL_Err("Where's your dset_link?"); SUMA_RETURN(NOPE); }
if (!cp->cmapname) { SUMA_SL_Err("Where's your cmapname?"); SUMA_RETURN(NOPE); }
if (!cp->ColVec) { SUMA_SL_Err("NULL cV"); SUMA_RETURN(NOPE); }
/* is the coloring direct ? */
if (strcmp(cp->cmapname, "explicit") == 0) {
SUMA_LH("Explicit color specification");
/* make sure dataset is of type NODE_RGB */
if (SDSET_TYPE(cp->dset_link) != SUMA_NODE_RGB) {
SUMA_SL_Err("Direct mapping is only supported for SUMA_NODE_RGB types");
SUMA_RETURN(NOPE);
}
if (!(Nv = SUMA_GetNodeDef(cp->dset_link))) { SUMA_SL_Err("Failed to find index column."); SUMA_RETURN(NOPE); }
iv = SUMA_GetDsetColIndex (cp->dset_link, SUMA_NODE_R, &N_i);
if (N_i != 1) { SUMA_SL_Err("Failed to find red column."); SUMA_free(iv); SUMA_RETURN(NOPE); }
Rv = (float *)cp->dset_link->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
iv = SUMA_GetDsetColIndex (cp->dset_link, SUMA_NODE_G, &N_i);
if (N_i != 1) { SUMA_SL_Err("Failed to find green column."); SUMA_free(iv); SUMA_RETURN(NOPE); }
Gv = (float *)cp->dset_link->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
iv = SUMA_GetDsetColIndex (cp->dset_link, SUMA_NODE_B, &N_i);
if (N_i != 1) { SUMA_SL_Err("Failed to find blue column."); SUMA_free(iv); SUMA_RETURN(NOPE); }
Bv = (float *)cp->dset_link->dnel->vec[iv[0]];SUMA_free(iv); iv = NULL;
/* go ahead and populate cV */
if (LocalHead) {
char *s = NULL;
s = SUMA_DsetInfo(cp->dset_link, 0);
SUMA_S_Note(s);
SUMA_free(s);
}
if (cp->DimFact == 1.0) {
for (i=0; i < SDSET_VECFILLED(cp->dset_link); ++i) {
i3 = 3 * i;
cp->NodeDef[i] = Nv[i];
cp->ColVec[i3] = Rv[i]; ++i3;
cp->ColVec[i3] = Gv[i]; ++i3;
cp->ColVec[i3] = Bv[i];
}
} else {
for (i=0; i < SDSET_VECFILLED(cp->dset_link); ++i) {
i3 = 3 * i;
cp->NodeDef[i] = Nv[i];
cp->ColVec[i3] = Rv[i] * cp->DimFact; ++i3;
cp->ColVec[i3] = Gv[i] * cp->DimFact; ++i3;
cp->ColVec[i3] = Bv[i] * cp->DimFact;
}
}
cp->N_NodeDef = SDSET_VECFILLED(cp->dset_link);
} else {
/* indirect mapping */
if (!SUMA_ScaleToMap_Interactive (cp)) {
SUMA_SL_Err("Failed in SUMA_ScaleToMap_Interactive.");
SUMA_RETURN(0);
}
/* cp->N_NodeDef is taken care of inside SUMA_ScaleToMap_Interactive */
}
if (LocalHead) {
SUMA_LH("Color Plane Post Colorizing");
SUMA_Show_ColorOverlayPlanes ( &cp, 1, 0);
}
SUMA_RETURN(1);
}
/*!
\brief Sets up the defaults for the convexity plane.
\param SO (SUMA_SurfaceObject *) pointer to surface object that the convexity dataset
is attributed to.
\param ConvPlane (SUMA_OVERLAYS *)
*/
SUMA_Boolean SUMA_SetConvexityPlaneDefaults(SUMA_SurfaceObject *SO, DList *DsetList)
{
static char FuncName[]={"SUMA_SetConvexityPlaneDefaults"};
float IntRange[2], *Vsort = NULL;
float *Cx=NULL;
int junk;
char *eee = NULL;
int icmap;
SUMA_OVERLAYS *ConvPlane;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!SUMAg_CF->scm) { /* colors not setup, go back */
SUMAg_CF->scm = SUMA_Build_Color_maps();
if (!SUMAg_CF->scm) {
SUMA_SL_Warn("No color maps set up.\n");
SUMA_RETURN(YUP);
}
}
if (!(ConvPlane = SUMA_Fetch_OverlayPointer(SO->Overlays, SO->N_Overlays, "Convexity", &junk))) {
SUMA_SL_Err("Failed to find overlay plane 'Convexity'");
SUMA_RETURN(NOPE);
}
if (SO->Group && strcmp(SO->Group,SUMA_DEF_TOY_GROUP_NAME) == 0) {
SUMA_LH("Adriano");
/* fun times, gimme a random colormap */
if (1) {
icmap = rand()%SUMAg_CF->scm->N_maps;
SUMA_STRING_REPLACE(ConvPlane->cmapname, SUMAg_CF->scm->CMv[icmap]->Name);
/* SUMA_S_Notev("Cmap %s\n", ConvPlane->cmapname); */
} else { /* Used here to force crash on linux, bug should now be fixed
See comment in SUMA_GimmeSomeSOs (also other 20 maps...)*/
SUMA_STRING_REPLACE(ConvPlane->cmapname, "rgybr20");
}
} else {
/* decide on the color map */
eee = getenv("SUMA_ConvColorMap");
if (eee) {
icmap = SUMA_Find_ColorMap ( eee, SUMAg_CF->scm->CMv, SUMAg_CF->scm->N_maps, -2 );
if (icmap < 0) {
SUMA_SL_Err("Colormap specified in\n"
"environment variable SUMA_ConvColorMap\n"
"was not found. Using ngray20.\n");
SUMA_STRING_REPLACE(ConvPlane->cmapname, "ngray20");
} else {
SUMA_STRING_REPLACE(ConvPlane->cmapname, eee);
}
} else {
SUMA_STRING_REPLACE(ConvPlane->cmapname, "ngray20");
}
}
SUMA_LH("Deciding on brightness factor");
/* decide on the convexity brightness factor */
eee = getenv("SUMA_ConvBrightFactor");
if (eee) {
ConvPlane->OptScl->BrightFact = (float)strtod(eee, NULL);
if (ConvPlane->OptScl->BrightFact < 0) {
SUMA_SL_Err("Brightness factor specified in\n"
"environment variable SUMA_ConvColorMap\n"
"is negative. Using default.\n");
ConvPlane->OptScl->BrightFact = SUMA_DIM_CONVEXITY_COLOR_FACTOR;
}
} else {
ConvPlane->OptScl->BrightFact = SUMA_DIM_CONVEXITY_COLOR_FACTOR;
}
/* Now place the color map in the Coloroverlay structure */
ConvPlane->GlobalOpacity = SUMA_CONVEXITY_COLORPLANE_OPACITY;
ConvPlane->Show = YUP;
ConvPlane->isBackGrnd = YUP;
SUMA_LH("Smoothing Cx");
/* work the options for creating the scaled color mapping a bit */
ConvPlane->OptScl->interpmode = SUMA_NO_INTERP;
ConvPlane->OptScl->ApplyClip = YUP;
IntRange[0] = 5; IntRange[1] = 95; /* percentile clipping range*/
Cx = (float *)SUMA_GetCx(SO->idcode_str, DsetList, 0);
if (!Cx) { SUMA_SL_Err("Failed to find Cx\n"); SUMA_RETURN (NOPE); }
Vsort = SUMA_PercRange (Cx, NULL, SO->N_Node, IntRange, IntRange, NULL);
if (Vsort[0] < 0 && Vsort[SO->N_Node -1] > 0 ) {
/* the new method */
if (fabs(IntRange[0]) > IntRange[1]) {
IntRange[1] = -IntRange[0];
} else {
IntRange[0] = -IntRange[1];
}
} else {
/* The old method, do nothing here */
}
if (Vsort) SUMA_free(Vsort); Vsort = NULL;
ConvPlane->OptScl->find = 0; /* the intensity column */
ConvPlane->OptScl->tind = 0; /* the threshold column */
ConvPlane->OptScl->bind = 0; /* the brightness modulation column */
ConvPlane->OptScl->IntRange[0] = IntRange[0]; ConvPlane->OptScl->IntRange[1] = IntRange[1];
/* Force Auto Range to these percentile values */
ConvPlane->ForceIntRange[0] = IntRange[0]; ConvPlane->ForceIntRange[1] = IntRange[1];
SUMA_RETURN(YUP);
}
/*!
\brief j = SUMA_GetNodeOverInd(Sover, node);
returns the index, into Sover->NodeDef such
that Sover->NodeDef[j] = node;
\sa SUMA_GetNodeRow_FromNodeIndex
*/
int SUMA_GetNodeOverInd (SUMA_OVERLAYS *Sover, int node)
{
static char FuncName[]={"SUMA_GetNodeOverInd"};
int Found, i;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
/* Now look for the node's location in the color overlay plane.
Nodes that are not colored will be absent ... */
Found = -1;
if (SDSET_VECFILLED(Sover->dset_link) > node) { /* try the straight shot */
if (Sover->NodeDef[node] == node) {
SUMA_LH("Good, found it easily");
/* make sure node is not outside number of defined nodes */
if (node >= Sover->N_NodeDef) {
/* this one's masked but it was left over from the previous pass
Must go search below to make sure whether it is truly masked or not*/
SUMA_LH("Can't tell for sure");
} else {
SUMA_RETURN(node);
}
}
}
if (Found < 0) {
SUMA_LH("The hard way");
i=0;
while (Found <0 && i<Sover->N_NodeDef) {
if (Sover->NodeDef[i] == node) Found = i;
++i;
}
}
SUMA_RETURN(Found);
}
/*-----------------------------------------------------------------*/
syntax highlighted by Code2HTML, v. 0.9.1