/*****************************************************************************
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 "mrilib.h"
/*---------------------------------------------------------------------------------*/
#define NPMAX 128
int main( int argc , char * argv[] )
{
int iarg ;
THD_3dim_dataset * dset ;
float bper = 60.0 , bmin = 1 ;
int nxyz , ii , kk , nbin , sval , sum , nbot , a,b,c , nbase,npeak,ntop , nvox ;
int * fbin ;
short * sfim ;
int kmin[NPMAX] , kmax[NPMAX] ;
int nmin , nmax ;
/*-- help? --*/
if( argc < 2 || strncmp(argv[1],"-help",4) == 0 ){
fprintf(stderr,
"Find the clipping point on a histogram of a 3D brick\n"
"Usage: 3dhclip [options] dataset\n"
"\n"
"Options:\n"
" -bper bb Means to take the base percentage point\n"
" on the cumulative histogram as 'bb'\n"
" [default bb = 60]\n"
" -bmin cc Means to take the minimum value to consider\n"
" as 'cc' [default cc = 1]\n"
) ;
printf("\n" MASTER_SHORTHELP_STRING ) ;
exit(0) ;
}
/*-- process options --*/
iarg = 1 ;
while( iarg < argc && argv[iarg][0] == '-' ){
if( strcmp(argv[iarg],"-bper") == 0 ){
bper = strtod( argv[++iarg] , NULL ) ;
if(bper<1 || bper>99){fprintf(stderr,"** Illegal -bper value\n");exit(1);}
iarg++ ; continue ;
}
if( strcmp(argv[iarg],"-bmin") == 0 ){
bmin = strtod( argv[++iarg] , NULL ) ;
if(bmin<0){fprintf(stderr,"** Illegal -bmin value\n");exit(1);}
iarg++ ; continue ;
}
fprintf(stderr,"** Illegal option: %s\n",argv[iarg]) ; exit(1) ;
}
/*-- load dataset --*/
if( iarg >= argc ){fprintf(stderr,"** No dataset?!\n");exit(1);}
dset = THD_open_dataset(argv[iarg]) ;
if( dset == NULL ){
fprintf(stderr,"** Can't open dataset %s\n",argv[iarg]) ;
exit(1) ;
}
if( DSET_BRICK_TYPE(dset,0) != MRI_short || DSET_BRICK_FACTOR(dset,0) != 0.0 ){
fprintf(stderr,"** Program only works with short-value datasets!\n") ;
exit(1) ;
}
DSET_load(dset) ;
sfim = DSET_ARRAY(dset,0) ;
if( sfim == NULL ){fprintf(stderr,"** Can't load dataset brick\n");exit(1);}
/*-- make histogram of shorts --*/
fbin = (int *) malloc( sizeof(int) * 32768 ) ;
for( kk=0 ; kk < 32768 ; kk++ ) fbin[kk] = 0 ;
nvox = 0 ; nxyz = DSET_NVOX(dset) ;
for( ii=0 ; ii < nxyz ; ii++ ){
kk = sfim[ii] ; if( kk >= 0 ){ fbin[kk]++ ; nvox++ ; }
}
DSET_unload(dset) ;
/*-- find largest value --*/
for( kk=32767 ; kk > 0 ; kk-- ) if( fbin[kk] > 0 ) break ;
if( kk == 0 ){fprintf(stderr,"** All voxels are zero!\n");exit(1);}
nbin = kk+1 ;
/*-- find bper point in cumulative distribution --*/
sval = 0.01 * bper * nvox ;
sum = 0 ;
for( kk=0 ; kk < nbin ; kk++ ){
sum += fbin[kk] ; if( sum >= sval ) break ;
}
nbot = kk ; if( nbot == 0 ) nbot = 1 ; if( bmin > nbot ) nbot = bmin ;
if( nbot >= nbin-9 ){fprintf(stderr,"** Base point on histogram too high\n");exit(1);}
/*-- smooth histogram --*/
b = fbin[nbot-1] ; c = fbin[nbot] ;
for( kk=nbot ; kk < nbin ; kk++ ){
a = b ; b = c ; c = fbin[kk+1] ; fbin[kk] = 0.25*(a+c+2*b) ;
}
/*-- find minima and maxima above bper point --*/
nmin = nmax = 0 ;
for( kk=nbot+1 ; kk < nbin ; kk++ ){
if( fbin[kk] < fbin[kk-1] && fbin[kk] < fbin[kk+1] && nmin < NPMAX ){
kmin[nmin++] = kk ;
} else if( fbin[kk] > fbin[kk-1] && fbin[kk] > fbin[kk+1] && nmax < NPMAX ){
kmax[nmax++] = kk ;
}
}
#if 0
for( kk=0 ; kk < nmin ; kk++ )
printf("Min: %d has %d\n",kmin[kk],fbin[kmin[kk]]) ;
for( kk=0 ; kk < nmax ; kk++ )
printf("Max: %d has %d\n",kmax[kk],fbin[kmax[kk]]) ;
#endif
/*-- find the largest two maxima --*/
if( nmax == 0 ){fprintf(stderr,"** No maxima above base point\n");exit(1);}
if( nmax <= 2 ){
npeak = kmax[0] ; ntop = 0 ;
} else {
int f1,f2 , k1,k2 , fk , klow,kup ;
k1 = 0 ; f1 = fbin[kmax[0]] ;
k2 = 1 ; f2 = fbin[kmax[1]] ;
if( f1 < f2 ){
k1 = 1 ; f1 = fbin[kmax[1]] ;
k2 = 0 ; f2 = fbin[kmax[0]] ;
}
for( kk=2 ; kk < nmax ; kk++ ){
fk = fbin[kmax[kk]] ;
if( fk > f1 ){
f2 = f1 ; k2 = k1 ;
f1 = fk ; k1 = kk ;
} else if( fk > f2 ){
f2 = fk ; k2 = kk ;
}
}
npeak = MIN( kmax[k1] , kmax[k2] ) ; /* smaller bin of the 2 top peaks */
/* find valley between 2 peaks */
ntop = MAX( kmax[k1] , kmax[k2] ) ;
fk = fbin[ntop] ; klow = ntop ;
for( kk=ntop-1 ; kk >= npeak ; kk-- ){
if( fbin[kk] < fk ){ fk = fbin[kk] ; klow = kk ; }
}
fk = 0.16 * fk ; kup = MIN( nbin-1 , ntop+3*(ntop-klow+2) ) ;
for( kk=ntop+1 ; kk <= kup ; kk++ ) if( fbin[kk] < fk ) break ;
ntop = kk ;
}
for( kk=npeak-1 ; kk > 0 ; kk-- )
if( fbin[kk] < fbin[kk-1] && fbin[kk] < fbin[kk+1] ) break ;
nbase = kk ;
printf("dataset: %s -- ",argv[iarg]) ;
printf("base = %d peak = %d top = %d\n",nbase,npeak,ntop) ;
exit(0) ;
}
syntax highlighted by Code2HTML, v. 0.9.1