#include "mrilib.h"

/*--------------------------------------------------------------------------*/
static float hbot1 =  1.0f ;
static float htop1 = -1.0f ;
static float hbot2 =  1.0f ;
static float htop2 = -1.0f ;
void mri_nbistat_setclip( float hb1, float ht1 , float hb2, float ht2 )
{
  hbot1 = hb1 ; htop1 = ht1 ; hbot2 = hb2 ; htop2 = ht2 ;
}

/*--------------------------------------------------------------------------*/
/*! Input = 2 1D images, and an NBISTAT_ code to compute some statistic.
   Output = statistic's value.
----------------------------------------------------------------------------*/

float mri_nbistat( int code , MRI_IMAGE *im , MRI_IMAGE *jm )
{
   MRI_IMAGE *fim , *gim ;
   float     *far , *gar ; float outval=0.0f ;
   int npt , ii ;

   if( im == NULL || jm == NULL || im->nvox == 0 || im->nvox != jm->nvox )
     return outval ;

   /* convert input to float format, if not already there */

   fim = (im->kind == MRI_float) ? im : mri_to_float(im) ;
   gim = (jm->kind == MRI_float) ? jm : mri_to_float(jm) ;
   far = MRI_FLOAT_PTR(fim) ;  /* array of values to statisticate */
   gar = MRI_FLOAT_PTR(gim) ;
   npt = fim->nvox ;           /* number of values */

   if( hbot1 < htop1 ){
     for( ii=0 ; ii < npt ; ii++ )
            if( far[ii] < hbot1 ) far[ii] = hbot1 ;
       else if( far[ii] > htop1 ) far[ii] = htop1 ;
   }
   if( hbot2 < htop2 ){
     for( ii=0 ; ii < npt ; ii++ )
            if( gar[ii] < hbot2 ) gar[ii] = hbot2 ;
       else if( gar[ii] > htop2 ) gar[ii] = htop2 ;
   }

   switch( code ){

     case NBISTAT_NUM: outval = (float)npt ; break ;  /* quite easy */

     case NBISTAT_SPEARMAN_CORR:
       outval = THD_spearman_corr( npt , far , gar ) ; break ;

     case NBISTAT_QUADRANT_CORR:
       outval = THD_quadrant_corr( npt , far , gar ) ; break ;

     case NBISTAT_PEARSON_CORR:
       outval = THD_pearson_corr( npt , far , gar ) ; break ;

     case NBISTAT_MUTUAL_INFO:
       outval = THD_mutual_info( npt , far , gar ) ; break ;

     case NBISTAT_NORMUT_INFO:
       outval = THD_norm_mutinf( npt , far , gar ) ;
       if( outval != 0.0f ) outval = 1.0f / outval ;
       break ;

     case NBISTAT_JOINT_ENTROPY:
       outval = THD_jointentrop( npt , far , gar ) ; break ;

     case NBISTAT_HELLINGER:
       outval = THD_hellinger( npt , far , gar ) ; break ;

     case NBISTAT_CORR_RATIO_M:
       THD_corr_ratio_mode(1) ;
       outval = THD_corr_ratio( npt , far , gar ) ; break ;

     case NBISTAT_CORR_RATIO_A:
       THD_corr_ratio_mode(2) ;
       outval = THD_corr_ratio( npt , far , gar ) ; break ;

     case NBISTAT_CORR_RATIO_U:
       THD_corr_ratio_mode(0) ;
       outval = THD_corr_ratio( npt , far , gar ) ; break ;
   }

   /* cleanup and exit */

   if( fim != im  ) mri_free(fim) ;
   if( gim != jm  ) mri_free(gim) ;
   return outval ;
}

/*--------------------------------------------------------------------------*/
/*! Compute a local statistic at each voxel of an image pair, possibly with
    a mask; 'local' is defined with a neighborhood; 'statistic' is defined
    by an NBISTAT_ code.
----------------------------------------------------------------------------*/

MRI_IMAGE * mri_localbistat( MRI_IMAGE *im, MRI_IMAGE *jm ,
                             byte *mask, MCW_cluster *nbhd, int code )
{
   MRI_IMAGE *outim , *nbim , *nbjm ;
   float     *outar ;
   int ii,jj,kk , nx,ny,nz , ijk ;

ENTRY("mri_localbistat") ;

   if( im == NULL || nbhd == NULL ) RETURN(NULL) ;

   outim = mri_new_conforming( im , MRI_float ) ;
   outar = MRI_FLOAT_PTR(outim) ;
   nx = outim->nx ; ny = outim->ny ; nz = outim->nz ;

   ijk = (int)pow((double)nbhd->num_pt,0.33333) ;  /* for entropy, etc. */
   set_2Dhist_hbin( ijk ) ;

   for( ijk=kk=0 ; kk < nz ; kk++ ){
    for( jj=0 ; jj < ny ; jj++ ){
     for( ii=0 ; ii < nx ; ii++ ){
       nbim = mri_get_nbhd( im , mask , ii,jj,kk , nbhd ) ;
       nbjm = mri_get_nbhd( jm , mask , ii,jj,kk , nbhd ) ;
       outar[ijk++] = mri_nbistat( code , nbim , nbjm ) ;
       mri_free(nbim) ; mri_free(nbjm) ;
   }}}

   RETURN(outim) ;
}

/*--------------------------------------------------------------------------*/

static int verb=0 , vn=0 ;
void THD_localbistat_verb(int i){ verb=i; vn=0; }

static void vstep_print(void)
{
   static char xx[10] = "0123456789" ;
   fprintf(stderr , "%c" , xx[vn%10] ) ;
   if( vn%10 == 9) fprintf(stderr,".") ;
   vn++ ;
}

/*--------------------------------------------------------------------------*/

THD_3dim_dataset * THD_localbistat( THD_3dim_dataset *dset ,
                                    THD_3dim_dataset *eset , byte *mask ,
                                    MCW_cluster *nbhd , int ncode, int *code )
{
   THD_3dim_dataset *oset ;
   MRI_IMAGE *nbim , *nbjm ;
   int iv,cc , nvin,nvout , nx,ny,nz,nxyz , ii,jj,kk,ijk ;
   float **aar ;
   int vstep ;

ENTRY("THD_localbistat") ;

   if( dset == NULL || eset == NULL ||
       nbhd == NULL || ncode < 1    || code == NULL ) RETURN(NULL);

   if( DSET_NVOX(dset) != DSET_NVOX(eset) )   RETURN(NULL) ;
   DSET_load(dset) ; if( !DSET_LOADED(dset) ) RETURN(NULL) ;
   DSET_load(eset) ; if( !DSET_LOADED(eset) ) RETURN(NULL) ;

   oset  = EDIT_empty_copy( dset ) ;
   nvin  = DSET_NVALS( dset ) ;
   nvout = nvin * ncode ;
   EDIT_dset_items( oset ,
                      ADN_nvals     , nvout         ,
                      ADN_datum_all , MRI_float     ,
                      ADN_ntt       , nvout         ,
                      ADN_nsl       , 0             ,
                      ADN_brick_fac , NULL          ,
                      ADN_prefix    , "localbistat" ,
                    ADN_none ) ;

   nx = DSET_NX(dset) ;
   ny = DSET_NY(dset) ;
   nz = DSET_NZ(dset) ; nxyz = nx*ny*nz ;

   vstep = (verb && nxyz > 66666) ? nxyz/50 : 0 ;
   if( vstep ) fprintf(stderr,"++ voxel loop:") ;

   aar = (float **)malloc(sizeof(float *)*ncode) ;

   for( iv=0 ; iv < nvin ; iv++ ){
     for( cc=0 ; cc < ncode ; cc++ ){
       aar[cc] = (float *)malloc(sizeof(float)*nxyz) ;
       if( aar[cc] == NULL )
         ERROR_exit("THD_localbistat: out of memory at iv=%d cc=%d",iv,cc);
     }

     for( ijk=kk=0 ; kk < nz ; kk++ ){
      for( jj=0 ; jj < ny ; jj++ ){
       for( ii=0 ; ii < nx ; ii++,ijk++ ){
         if( vstep && ijk%vstep==vstep-1 ) vstep_print() ;
         nbim = THD_get_dset_nbhd( dset,iv , mask,ii,jj,kk , nbhd ) ;
         nbjm = THD_get_dset_nbhd( eset,iv , mask,ii,jj,kk , nbhd ) ;
         for( cc=0 ; cc < ncode ; cc++ )
           aar[cc][ijk] = mri_nbistat( code[cc] , nbim,nbjm ) ;
         mri_free(nbim) ; mri_free(nbjm) ;
     }}}

     DSET_unload_one(dset,iv) ; DSET_unload_one(eset,iv)  ;

     for( cc=0 ; cc < ncode ; cc++ )
       EDIT_substitute_brick( oset , iv*ncode+cc , MRI_float , aar[cc] ) ;
   }

   if( vstep ) fprintf(stderr,"\n") ;
   free((void *)aar) ;
   RETURN(oset) ;
}


syntax highlighted by Code2HTML, v. 0.9.1