/*----------------------------------------------------------------------
* afni_vol2surf.c - afni's interface to the vol2surf library
*
* AFNI_vol2surf_func_overlay() - similar to AFNI_vnlist_func_overlay()
*----------------------------------------------------------------------
*/
/*----------------------------------------------------------------------
* R. Reynolds September, 2004
*
* history:
*
* 08 Oct 2004 [rickr]:
* - AFNI_vol2surf_func_overlay() has new params, surfA,surfB,use_defaults
* - pass use_defaults to afni_vol2surf()
* 25 Oct 2004 [rickr]:
* - accept Rdata and Rthr pointers, for optionally returning the data
* and global threshold
* - make threshold masks absolute
* 09 Aug 2006 [rickr]:
* - set the surface volume dataset in the global v2s_plugin_opts struct
* - also store the index and threshold value of the threshold sub-brick
*----------------------------------------------------------------------
*/
#include "afni.h"
#include "vol2surf.h"
static int map_v2s_results(v2s_results *res, Three_D_View *im3d,
SUMA_irgba **map, int debug, int dnode );
/*-----------------------------------------------------------------------*/
/*! Create a nodal color overlay from a voxel map.
- Surface index(es) come from global v2s_plugin_opts struct
- Return value is number of nodes overlaid:
- 0 return ==> no overlay was computed
- -1 return ==> some error (e.g., no surface nodes on this dataset)
= positive ==> can use *map
- *map is set to a newly malloc()-ed array (if return > 0)
- if (Rdata) return data from results structure
- if (Rthr) return overlay threshold from afni
Sample usage:
- SUMA_irgba * map;
- int nmap;
- nmap = AFNI_vnlist_func_overlay( im3d, &map );
- if( nmap < 0 ){ ** error ** }
- else if( nmap == 0 ){ ** nothing to show ** }
- else { ** show map[0..nmap-1] ** }
* based on AFNI_vnlist_func_overlay()
-------------------------------------------------------------------------*/
int AFNI_vol2surf_func_overlay(Three_D_View *im3d, SUMA_irgba **map,
int surfA, int surfB, int use_defaults, float ** Rdata, float * Rthr )
{
THD_3dim_dataset * oset; /* overlay dataset */
THD_slist_find find;
THD_session * ss;
SUMA_surface * sA, * sB;
MRI_IMAGE * im_oim;
v2s_plugin_opts * go;
v2s_results * results;
byte * cmask;
int nout, oind, debug;
ENTRY("AFNI_vol2surf_func_overlay") ;
/* check inputs */
if ( map == NULL || !IM3D_VALID(im3d) ) RETURN(-1);
go = &gv2s_plug_opts;
if ( ! use_defaults && ! go->ready ) RETURN(-1);
debug = go->sopt.debug; /* because I'm lazy */
ss = im3d->ss_now; /* session must have needed surface(s) */
if( ss == NULL ||
ss->su_num <= 0 ||
surfA < 0 ||
ss->su_num <= surfA ||
ss->su_num <= surfB ||
ss->su_surf[surfA] == NULL ||
(surfB >= 0 && ss->su_surf[surfB] == NULL) )
{
if ( debug > 1 )
{
if ( !ss ) fprintf(stderr,"** v2s: NULL session\n");
else
fprintf(stderr,"** v2s: bad session data:\n"
" su_num, surfA, surfB = %d, %d, %d\n",
ss->su_num, surfA, surfB);
}
RETURN(-1);
}
/* init return values */
if ( Rdata ) *Rdata = NULL;
if ( Rthr ) *Rthr = 0.0;
/* set surface pointers */
sA = ss->su_surf[surfA];
sB = ( surfB >= 0 ) ? ss->su_surf[surfB] : NULL;
/* store the surface volume pointer 9 Aug 2006 [rickr] */
find = PLUTO_dset_finder(sA->idcode_dset);
go->sv_dset = find.dset;
if ( debug )
{
fprintf(stderr,"++ v2s overlay: sa,sb = %d,%d\n", surfA, surfB);
if ( debug > 1 )
fprintf(stderr," surfA is %s, surfB is %s\n",
sA->label[0] ? sA->label : "<no label>",
sB ? (sB->label[0] ? sB->label : "<no label>") : "<not used>");
}
/*-------------------- overlay image --------------------*/
oset = im3d->fim_now;
oind = im3d->vinfo->fim_index; /* overlay sub-brick index */
if( oset == NULL )
{
if ( debug > 1 ) fprintf(stderr,"** v2s: no overlay dset\n");
RETURN(-1);
}
im_oim = DSET_BRICK(oset,oind);
if( ! im_oim || ! AFNI_GOOD_FUNC_DTYPE(im_oim->kind) )
{
if ( debug > 1 ) fprintf(stderr,"** v2s: no overlay image\n");
RETURN(-1);
}
DSET_load(oset); /* to be sure */
if( !DSET_LOADED(oset) ) RETURN(-1);
/*-------------------- mask from threshold --------------------*/
go->gpt_index = -1; go->gpt_thresh = 0.0; /* init threshold options */
cmask = NULL;
if( im3d->vinfo->func_threshold > 0.0 ) /* then want a threshold */
{
MRI_IMAGE * im_thr;
float thresh;
int tind = im3d->vinfo->thr_index;
im_thr = DSET_BRICK(oset,tind);
/* note real threshold */
thresh = im3d->vinfo->func_threshold * im3d->vinfo->func_thresh_top;
/* maybe we want to return this */
if ( Rthr ) *Rthr = thresh;
if( im_thr && !AFNI_GOOD_FUNC_DTYPE(im_thr->kind) )
im_thr = NULL;
/* create the mask, if this fails, just continue... */
if( im_thr != NULL )
{
int nset;
if ( debug > 1 )
fprintf(stderr,"++ mask from index %d and thresh %f\n",
tind,thresh);
nset = thd_mask_from_brick(oset, tind, thresh, &cmask, 1);
if ( debug > 1 )
{
if ( ! cmask )
fprintf(stderr,"-- no mask created\n");
else
fprintf(stderr,"++ mask has %d set voxels\n", nset);
}
}
else if ( debug > 1 )
fprintf(stderr,"-- no threshold mask\n");
/* note mask options for v2s command output 9 Aug 2006 [rickr] */
if( cmask ) { go->gpt_index = tind; go->gpt_thresh = thresh; }
}
/*-------------------- vol2surf computation --------------------*/
results = afni_vol2surf(oset, oind, sA, sB, cmask, use_defaults);
if ( cmask ) free(cmask); /* we're done with the mask */
if ( ! results )
{
if ( debug ) fprintf(stderr,"-- vol2surf failure\n");
RETURN(-1); /* failure? */
}
/*-------------------- lose old vnlist --------------------*/
/* vol2surf has no method for counting voxels (right now) */
if( sA->vn )
{
if ( debug > 1 ) fprintf(stderr,"-- destroying vnlist\n");
SUMA_destroy_vnlist( sA->vn ) ;
sA->vn = NULL;
}
/*-------------------- set overlay colors --------------------*/
nout = map_v2s_results(results, im3d, map, debug, go->sopt.dnode);
/* before free()ing results, check whether we want to return the values */
if ( Rdata )
{
*Rdata = results->vals[0];
results->vals[0] = NULL; /* do not let free_v2s_results() free it */
}
free_v2s_results(results);
if ( debug > 1 ) fprintf(stderr,"++ map_v2s_results: nout = %d\n", nout);
/* check failure */
if ( ! *map ) RETURN(-1);
RETURN(nout);
}
/*! given vol2surf results, fill SUMA_irgba struct */
static int map_v2s_results(v2s_results *res, Three_D_View *im3d,
SUMA_irgba **map, int debug, int dnode )
{
SUMA_irgba * mptr;
MCW_pbar * pbar;
rgbyte * cmap;
float * result_vals;
float bbot, btop, fac, fval;
float pane_scale = 1.0;
byte r, g, b;
int nindex, node, npanes, ival;
int map_index = 0; /* counter for results */
ENTRY("map_v2s_results");
/*-------------------- create output node list --------------------*/
mptr = (SUMA_irgba *) malloc(sizeof(SUMA_irgba) * res->nused);
if ( ! mptr )
{
fprintf(stderr,"** malloc failure: %d irgba's\n", res->nused);
RETURN(-1);
}
*map = mptr; /* and store the address */
pbar = im3d->vwid->func->inten_pbar;
npanes = pbar->num_panes;
pane_scale = im3d->vinfo->fim_range;
if ( pane_scale == 0.0 ) pane_scale = im3d->vinfo->fim_autorange;
if ( pane_scale == 0.0 ) pane_scale = 1.0;
if ( debug > 1 )
fprintf(stderr,"+d mvr: npanes = %d, pane_scale = %f\n",
pbar->bigmode ? NPANE_BIG : npanes, pane_scale);
result_vals = res->vals[0]; /* for typing and potential speed */
if( pbar->bigmode ) /* colorscale */
{
int zbot;
bbot = pane_scale*pbar->bigbot;
btop = pane_scale*pbar->bigtop;
fac = NPANE_BIG / (btop-bbot);
cmap = pbar->bigcolor;
zbot = (bbot == 0.0);
if ( debug > 1 )
fprintf(stderr,"+d bigmode: bbot,btop,fac, zbot = %f,%f,%f, %d\n",
bbot, btop, fac, zbot);
for ( nindex = 0; nindex < res->nused; nindex++ )
{
if ( res->nodes ) node = res->nodes[nindex];
else node = nindex;
/* note value, and check to ignore */
fval = result_vals[nindex];
if ( debug > 1 && node == dnode )
fprintf(stderr, "+d dnode %d, fval %f\n", dnode, fval);
if ( zbot && fval < 0 ) continue;
/* note the color panel index, and bound it in [0,NPANE_BIG-1] */
ival = (int)(fac * (btop - fval) + 0.49);
if ( ival < 0 ) ival = 0;
if ( ival >= NPANE_BIG ) ival = NPANE_BIG - 1;
/* get color map, and check if non-zero */
r = cmap[ival].r; g = cmap[ival].g; b = cmap[ival].b;
if ( debug > 1 && node == dnode )
fprintf(stderr, "+d pane, r,g,b = %d, %d,%d,%d\n",ival,r,g,b);
if ( r == 0 && g == 0 && b == 0 ) continue;
/* we are set, fill the SUMA_irgba struct */
mptr->id = res->nodes[nindex];
mptr->r = r; mptr->g = g; mptr->b = b; mptr->a = 255;
/* increment pointer and counter (okay, so counter is unneeded) */
mptr++; map_index++;
}
}
else /* indexed colors */
{
float othr[NPANE_MAX]; /* threshold */
short ovc[NPANE_MAX+1]; /* color */
byte ovc_r[NPANE_MAX+1], ovc_g[NPANE_MAX+1], ovc_b[NPANE_MAX+1];
/* set the overlay color indices */
for( ival=0 ; ival < npanes ; ival++ )
ovc[ival] = pbar->ov_index[ival]; /* from top of pbar down */
ovc[npanes] = im3d->vinfo->use_posfunc ? 0 : ovc[npanes-1];
/* get the actual RGB colors of each pane on the pbar */
for( ival=0 ; ival < npanes ; ival++ )
{
ovc_r[ival] = DCOV_REDBYTE (im3d->dc,ovc[ival]);
ovc_g[ival] = DCOV_GREENBYTE(im3d->dc,ovc[ival]);
ovc_b[ival] = DCOV_BLUEBYTE (im3d->dc,ovc[ival]);
}
/* compute the thresholds */
for( ival=0 ; ival < npanes ; ival++ )
othr[ival] = pane_scale * pbar->pval[ival+1];
if ( debug > 2 )
{
for( ival=0 ; ival <= npanes ; ival++ )
fprintf(stderr,"+d pane #%2d, ovc = %d, othr = %f\n",
ival, ovc[ival], othr[ival]);
}
for ( nindex = 0; nindex < res->nused; nindex++ )
{
if ( res->nodes ) node = res->nodes[nindex];
else node = nindex;
/* note value, and check to ignore */
fval = result_vals[nindex];
if ( debug > 1 && node == dnode )
fprintf(stderr, "+d dnode %d, fval %f\n", dnode, fval);
if ( fval == 0.0 ) continue;
for ( ival = 0; ival < npanes && fval < othr[ival]; ival++ )
;
if ( ovc[ival] == 0 ) continue; /* no color in this pane */
r = ovc_r[ival]; g = ovc_g[ival]; b = ovc_b[ival];
/* we are set, fill the SUMA_irgba struct */
mptr->id = res->nodes[nindex];
mptr->r = r; mptr->g = g; mptr->b = b; mptr->a = 255;
if ( debug > 1 && node == dnode )
fprintf(stderr, "+d pane, r,g,b = %d, %d,%d,%d\n",ival,r,g,b);
if ( r == 0 && g == 0 && b == 0 ) continue;
/* increment pointer and counter (okay, so counter is unneeded) */
mptr++; map_index++;
}
}
if ( debug > 0 )
fprintf(stderr,"+d mvr v2s map size = %d\n", map_index);
/* forfeit unused memory */
*map = (SUMA_irgba *)realloc(*map, sizeof(SUMA_irgba)*map_index);
if ( ! *map )
{
fprintf(stderr,"** mvr: failed realloc of map, %d irgba's\n",map_index);
map_index = -1;
}
RETURN(map_index) ; /* number of entries in map */
}
syntax highlighted by Code2HTML, v. 0.9.1