/*****************************************************************************
Major portions of this software are copyrighted by the Medical College
of Wisconsin, 1994-2000, and are released under the Gnu General Public
License, Version 2. See the file README.Copyright for details.
******************************************************************************/
#include <string.h>
#include "mrilib.h"
#include <stdlib.h>
#include <ctype.h>
/*-------------------------- global data --------------------------*/
/** inputs **/
static THD_3dim_dataset * UC_dset = NULL ; /* dataset */
static char UC_prefix[THD_MAX_PREFIX] = "uuu2" ;
static int UC_be_quiet = 1 ;
static byte * UC_mask = NULL ;
static int UC_mask_nvox = 0 ;
static int UC_mask_hits = 0 ;
static int UC_nvec = 0 ; /* # of vectors to use from dataset */
static int UC_vdim = 0 ; /* length of each vector */
static float ** UC_vec = NULL ; /* UC_vec[k][i] is the i-th component */
/* of the k-th vector 0 <= i < UC_vdim */
/* 0 <= k < UC_nvec */
static int * UC_iv = NULL ; /* UC_vec[k] comes from voxel # UC_iv[k] */
static float UC_ptail = 0.0001 ;
static int UC_mtail = 2 ;
void UC_syntax(char * msg) ;
#include "uuu3.c"
#include "graph_compon.c"
/*-------------------------------------------------------------------
detrend: routine to remove unwanted components from time series
---------------------------------------------------------------------*/
void detrend( int n , float vec[] )
{
register int ii ;
register float sum0 , sum1 , cf , lf ;
float sum2 , det ;
static int nold = -1 ; /* initialization flag */
static float cf0,cf1 , lf0,lf1 ; /* to be initialized */
/*** initialize coefficients for detrending ***/
if( n != nold ){
nold = n ; sum0 = sum1 = sum2 = 0.0 ;
for( ii=0 ; ii < n ; ii++ ){
sum0 += 1.0 ; sum1 += ii ; sum2 += ii*ii ;
}
det = sum0 * sum2 - sum1 * sum1 ;
cf0 = sum2 / det ; /* constant factor for sum0 */
cf1 = -sum1 / det ; /* constant factor for sum1 */
lf0 = cf1 ; /* linear factor for sum0 */
lf1 = sum0 / det ; /* linear factor for sum1 */
}
/*** remove mean and linear trend ***/
sum0 = sum1 = 0.0 ;
for( ii=0 ; ii < n ; ii++ ){
sum0 += vec[ii] ; sum1 += vec[ii] * ii ;
}
cf = cf0 * sum0 + cf1 * sum1 ;
lf = lf0 * sum0 + lf1 * sum1 ;
for( ii=0 ; ii < n ; ii++ ) vec[ii] -= cf + ii*lf ;
}
/*----------------------------------------------------------
normalize: routine to scale a time series to unit vector
------------------------------------------------------------*/
void normalize( int n , float vec[] )
{
register int ii ;
register float sqsum ;
detrend( n , vec ) ;
sqsum = 0.0 ;
for( ii=0 ; ii < n ; ii++ ) sqsum += vec[ii] * vec[ii] ;
if( sqsum < 1.e-10 ){
for( ii=0 ; ii < n ; ii++ ) vec[ii] = 0.0 ;
} else {
sqsum = 1.0 / sqrt(sqsum) ;
for( ii=0 ; ii < n ; ii++ ) vec[ii] *= sqsum ;
}
}
/*------------------------------------------------------------------*/
void UC_read_opts( int argc , char * argv[] )
{
int nopt = 1 ;
float val ;
int kk, nxyz, mm,nn ;
float * vv , * bb ;
while( nopt < argc && argv[nopt][0] == '-' ){
/**** -verbose ****/
if( strncmp(argv[nopt],"-verbose",5) == 0 ){
UC_be_quiet = 0 ;
nopt++ ; continue ;
}
/**** -prefix prefix ****/
if( strncmp(argv[nopt],"-prefix",6) == 0 ){
nopt++ ;
if( nopt >= argc ) UC_syntax("-prefix needs an argument!") ;
MCW_strncpy( UC_prefix , argv[nopt++] , THD_MAX_PREFIX ) ;
continue ;
}
/**** -mask mset ****/
if( strncmp(argv[nopt],"-mask",5) == 0 ){
THD_3dim_dataset * mset ; int ii,nn ;
nopt++ ;
if( nopt >= argc ) UC_syntax("need arguments after -mask!") ;
mset = THD_open_dataset( argv[nopt] ) ;
if( mset == NULL ) UC_syntax("can't open -mask dataset!") ;
UC_mask = THD_makemask( mset , 0 , 1.0,0.0 ) ;
UC_mask_nvox = DSET_NVOX(mset) ;
DSET_delete(mset) ;
if( UC_mask == NULL ) UC_syntax("can't use -mask dataset!") ;
UC_mask_hits = THD_countmask( UC_mask_nvox , UC_mask ) ;
if( UC_mask_hits == 0 ) UC_syntax("mask is all zeros!") ;
if( !UC_be_quiet ) printf("--- %d voxels in mask\n",UC_mask_hits) ;
UC_iv = (int *) malloc( sizeof(int) * UC_mask_hits ) ;
for( nn=ii=0 ; ii < UC_mask_nvox ; ii++ )
if( UC_mask[ii] ) UC_iv[nn++] = ii ;
nopt++ ; continue ;
}
/**** -ptail p ****/
if( strcmp(argv[nopt],"-ptail") == 0 ){
if( ++nopt >= argc ) UC_syntax("-ptail needs an argument!") ;
UC_ptail = strtod( argv[nopt] , NULL ) ;
if( UC_ptail <= 0.0 || UC_ptail >= 0.499 )
UC_syntax("value after -ptail is illegal!") ;
nopt++ ; continue ;
}
/**** -mtail m ****/
if( strcmp(argv[nopt],"-mtail") == 0 ){
if( ++nopt >= argc ) UC_syntax("-mtail needs an argument!") ;
UC_mtail = strtod( argv[nopt] , NULL ) ;
nopt++ ; continue ;
}
/**** unknown switch ****/
fprintf(stderr,"\n*** unrecognized option %s\n",argv[nopt]) ;
exit(1) ;
} /* end of loop over options */
/*--- a simple consistency check ---*/
/*--- last input is dataset name ---*/
if( nopt >= argc ) UC_syntax("no input dataset name?") ;
UC_dset = THD_open_dataset( argv[nopt] ) ;
if( !ISVALID_3DIM_DATASET(UC_dset) ){
fprintf(stderr,"\n*** can't open dataset file %s\n",argv[nopt]) ;
exit(1) ;
}
nxyz = DSET_NVOX(UC_dset) ;
if( UC_mask != NULL && nxyz != UC_mask_nvox )
UC_syntax("mask and input dataset size mismatch!") ;
/*--- load vectors ---*/
UC_nvec = (UC_mask_hits > 0) ? UC_mask_hits : nxyz ;
UC_vdim = DSET_NVALS(UC_dset) ;
if( UC_vdim < 4 )
UC_syntax("input dataset needs at least 4 sub-bricks!") ;
vv = (float *) malloc( sizeof(float) * UC_nvec * UC_vdim ) ;
UC_vec = (float **) malloc( sizeof(float *) * UC_nvec ) ;
for( kk=0 ; kk < UC_nvec ; kk++ ) UC_vec[kk] = vv + (kk*UC_vdim) ;
if( !UC_be_quiet ) printf("--- reading input dataset\n") ;
DSET_load(UC_dset) ;
if( ! DSET_LOADED(UC_dset) )
UC_syntax("Can't load input dataset bricks!") ;
/* copy brick data into float storage */
if( !UC_be_quiet ) printf("--- loading vectors\n") ;
bb = (float *) malloc( sizeof(float) * nxyz ) ;
for( mm=0 ; mm < UC_vdim ; mm++ ){
EDIT_coerce_type( nxyz ,
DSET_BRICK_TYPE(UC_dset,mm) , DSET_ARRAY(UC_dset,mm) ,
MRI_float , bb ) ;
DSET_unload_one( UC_dset , mm ) ;
if( UC_mask == NULL ){
for( kk=0 ; kk < nxyz ; kk++ ) UC_vec[kk][mm] = bb[kk] ;
} else {
for( nn=kk=0 ; kk < nxyz ; kk++ )
if( UC_mask[kk] ) UC_vec[nn++][mm] = bb[kk] ;
}
}
free(bb) ; DSET_unload( UC_dset ) ;
/* detrend and normalize vectors */
if( !UC_be_quiet ) printf("--- normalizing vectors\n") ;
for( kk=0 ; kk < UC_nvec ; kk++ )
normalize( UC_vdim , UC_vec[kk] ) ;
return ;
}
/*-----------------------------------------------------------------------
Compute the unusuality index of a reference vector in a set of vectors
-------------------------------------------------------------------------*/
static int * UC_ihi = NULL ; /* cheap, but it works */
int UC_unusuality( int ndim , float * ref , int nvec , float ** vec )
{
register int ii , kk ;
register float psum , * vv ;
int nhi ;
static int nvold = -1 ;
static float * zval = NULL ;
if( ndim < 4 || nvec < 4 || ref == NULL || vec == NULL ) return 0 ;
/* initialize if number of vectors has changed */
if( nvold != nvec ){
if( zval != NULL ) free(zval) ;
if( UC_ihi != NULL ) free(UC_ihi) ;
zval = (float *) malloc(sizeof(float)*nvec) ;
UC_ihi = (int *) malloc(sizeof(int) *nvec) ;
nvold = nvec ;
}
/* compute dot products */
for( kk=0 ; kk < nvec ; kk++ ){
psum = 0.0 ; vv = vec[kk] ;
for( ii=0 ; ii < ndim ; ii++ ) psum += ref[ii] * vv[ii] ;
zval[kk] = psum ;
}
find_unusual_correlations( nvec , zval , &nhi , UC_ihi ) ;
return (short) nhi ;
}
/*---------------------------------------------------------------------------*/
void UC_syntax(char * msg)
{
if( msg != NULL ){ fprintf(stderr,"\n*** %s\n",msg) ; exit(1) ; }
printf(
"Usage: 3duuu2 [options] dataset ...\n"
"\n"
"The input dataset may have a sub-brick selector list.\n"
"Otherwise, all sub-bricks from a dataset will be used.\n"
"\n"
"OPTIONS:\n"
" -prefix pname \n"
" -verbose\n"
" -mask mset\n"
" -ptail p\n"
" -mtail m\n"
) ;
exit(0) ;
}
/*------------------------------------------------------------------*/
int main( int argc , char * argv[] )
{
int kk , nvox , ii , jj , uval,ncom , aa ;
THD_3dim_dataset * oset ;
short * sar ;
int ** gmat , ** cmat ;
/*-- read command line arguments --*/
if( argc < 2 || strncmp(argv[1],"-help",5) == 0 ) UC_syntax(NULL) ;
(void) my_getenv("junk") ;
UC_read_opts( argc , argv ) ;
set_unusuality_tail( UC_ptail ) ;
oset = EDIT_empty_copy( UC_dset ) ;
EDIT_dset_items( oset ,
ADN_prefix , UC_prefix ,
ADN_ntt , 0 ,
ADN_nvals , 1 ,
ADN_func_type , ANAT_BUCK_TYPE ,
ADN_datum_all , MRI_short ,
ADN_malloc_type , DATABLOCK_MEM_MALLOC ,
ADN_none ) ;
nvox = DSET_NVOX(oset) ;
sar = (short *) calloc( nvox , sizeof(short) ) ;
EDIT_substitute_brick( oset , 0 , MRI_short , sar ) ;
gmat = (int **) malloc( sizeof(int *) * UC_nvec ) ;
if( !UC_be_quiet ){ printf("--- computing u") ; fflush(stdout) ; }
for( kk=0 ; kk < UC_nvec ; kk++ ){
ii = (UC_iv == NULL) ? kk : UC_iv[kk] ;
uval = UC_unusuality( UC_vdim, UC_vec[kk], UC_nvec, UC_vec ) ;
if( uval < UC_mtail ) uval = 0 ;
sar[ii] = uval ;
/* make graph data */
gmat[kk] = (int *) malloc( sizeof(int) * (uval+1) ) ;
gmat[kk][0] = uval ;
for( jj=0 ; jj < uval ; jj++ ) gmat[kk][jj+1] = UC_ihi[jj] ;
if( !UC_be_quiet && kk%1000==999 ){
printf("%d",(kk/1000)%10);fflush(stdout);
}
}
if( !UC_be_quiet ) printf("\n") ;
if( !UC_be_quiet ) printf("--- fixing graph\n") ;
#undef ADDTHEM
for( kk=0 ; kk < UC_nvec ; kk++ ){ /* loop over pts */
uval = gmat[kk][0] ; /* # pts connected to kk */
for( jj=0 ; jj < uval ; jj++ ){ /* loop over pts connected to kk */
ii = gmat[kk][jj+1] ; /* jj-th pt connected to kk */
for( aa=1 ; aa <= gmat[ii][0] ; aa++ ) /* see if kk is in ii's list */
if( gmat[ii][aa] == kk ) break ;
if( aa > gmat[ii][0] ){ /* wasn't in list */
#ifdef ADDTHEM
/* add kk to ii's list */
gmat[ii] = (int *) realloc( sizeof(int)*(gmat[ii][0]+2) ) ;
gmat[ii][++(gmat[ii][0])] = kk ;
#else
/* remove ii from kk's list */
gmat[kk][jj+1] = -1 ; /* flag as a bad connection */
#endif
}
} /* end of loop over pts connected to kk */
} /* end of loop over pts */
if( !UC_be_quiet ) printf("--- finding components\n") ;
GRAPH_find_components( UC_nvec , gmat , &ncom , &cmat ) ;
if( !UC_be_quiet ) printf("--- found %d components\n",ncom) ;
sar = (short *) calloc( nvox , sizeof(short) ) ;
EDIT_add_brick( oset , MRI_short , 0.0 , sar ) ;
for( kk=0 ; kk < ncom ; kk++ ){
if( !UC_be_quiet )
printf("--- component %d has %d voxels\n",kk,cmat[kk][0]) ;
if( cmat[kk][0] < 2 ) break ;
for( ii=1 ; ii <= cmat[kk][0] ; ii++ ){
jj = (UC_iv == NULL) ? cmat[kk][ii] : UC_iv[cmat[kk][ii]] ;
sar[jj] = (kk+1) ;
}
}
if( !UC_be_quiet ) printf("--- writing output\n") ;
DSET_write(oset) ;
exit(0) ;
}
syntax highlighted by Code2HTML, v. 0.9.1