#include "mrilib.h"

#define SPEARMAN 1
#define QUADRANT 2
#define PEARSON  3

int main( int argc , char *argv[] )
{
   THD_3dim_dataset *xset , *yset , *cset ;
   int nopt=1 , method=PEARSON , do_autoclip=0 ;
   int nvox , nvals , ii , polort=1 ;
   MRI_IMAGE *xsim , *ysim ;
   float     *xsar , *ysar , *car ;
   char * prefix = "Tcorr" ;
   byte * mmm=NULL ;
   MRI_IMAGE *im_ort=NULL ;            /* 13 Mar 2003 */
   int nort=0 ; float **fort=NULL ;

   /*----*/

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
      printf("Usage: 3dTcorrelate [options] xset yset\n"
             "Computes the correlation coefficient between corresponding voxel\n"
             "time series in two input 3D+time datasets 'xset' and 'yset', and\n"
             "stores the output in a new 1 sub-brick dataset.\n"
             "\n"
             "Options:\n"
             "  -pearson  = Correlation is the normal Pearson (product moment)\n"
             "                correlation coefficient [default].\n"
             "  -spearman = Correlation is the Spearman (rank) correlation\n"
             "                coefficient.\n"
             "  -quadrant = Correlation is the quadrant correlation coefficient.\n"
             "\n"
             "  -polort m = Remove polynomical trend of order 'm', for m=-1..3.\n"
             "                [default is m=1; removal is by least squares].\n"
             "                Using m=-1 means no detrending; this is only useful\n"
             "                for data/information that has been pre-processed.\n"
             "\n"
             "  -ort r.1D = Also detrend using the columns of the 1D file 'r.1D'.\n"
             "                Only one -ort option can be given.  If you want to use\n"
             "                more than one, create a temporary file using 1dcat.\n"
             "\n"
             "  -autoclip = Clip off low-intensity regions in the two datasets,\n"
             "  -automask =  so that the correlation is only computed between\n"
             "               high-intensity (presumably brain) voxels.  The\n"
             "               intensity level is determined the same way that\n"
             "               3dClipLevel works.\n"
             "\n"
             "  -prefix p = Save output into dataset with prefix 'p'\n"
             "               [default prefix is 'Tcorr'].\n"
             "\n"
             "Notes:\n"
             " * The output dataset is functional bucket type, with one\n"
             "    sub-brick, stored in floating point format.\n"
             " * Because both time series are detrended prior to correlation,\n"
             "    the results will not be identical to using FIM or FIM+ to\n"
             "    calculate correlations (whose ideal vector is not detrended).\n"
             " * This is a quick hack for Mike Beauchamp.  Thanks for you-know-what.\n"
             "\n"
             "-- RWCox - Aug 2001\n"
            ) ;
      exit(0) ;
   }

   mainENTRY("3dTCorrelate main"); machdep(); AFNI_logger("3dTcorrelate",argc,argv);
   PRINT_VERSION("3dTcorrelate") ;

   /*-- option processing --*/

   while( nopt < argc && argv[nopt][0] == '-' ){

      if( strcmp(argv[nopt],"-ort") == 0 ){           /* 13 Mar 2003 */
        if( im_ort != NULL ){
          fprintf(stderr,"** Can't have multiple -ort options!\n"); exit(1);
        }
        im_ort = mri_read_1D( argv[++nopt] ) ;
        if( im_ort == NULL ){
          fprintf(stderr,"** Can't read 1D file %s\n",argv[nopt]); exit(1);
        }
        nort = im_ort->ny ;
        fort = (float **) malloc( sizeof(float *)*nort ) ;
        for( ii=0 ; ii < nort ; ii++ )
          fort[ii] = MRI_FLOAT_PTR(im_ort) + (ii*im_ort->nx) ;

        nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-autoclip") == 0 ||
          strcmp(argv[nopt],"-automask") == 0   ){

         do_autoclip = 1 ; nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-pearson") == 0 ){
         method = PEARSON ; nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-spearman") == 0 ){
         method = SPEARMAN ; nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-quadrant") == 0 ){
         method = QUADRANT ; nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-prefix") == 0 ){
         prefix = argv[++nopt] ;
         if( !THD_filename_ok(prefix) ){
            fprintf(stderr,"** Illegal value after -prefix!\n");exit(1);
         }
         nopt++ ; continue ;
      }

      if( strcmp(argv[nopt],"-polort") == 0 ){
         char *cpt ;
         int val = strtod(argv[++nopt],&cpt) ;
         if( *cpt != '\0' || val < -1 || val > 3 ){
            fprintf(stderr,"** Illegal value after -polort!\n");exit(1);
         }
         polort = val ; nopt++ ; continue ;
      }

      fprintf(stderr,"** Illegal option: %s\n",argv[nopt]) ; exit(1) ;
   }

   /*-- open datasets, check for legality --*/

   if( nopt+1 >= argc ){
      fprintf(stderr,"*** Need 2 datasets on command line!?\n"); exit(1);
   }

   xset = THD_open_dataset( argv[nopt] ) ;
   if( xset == NULL ){
      fprintf(stderr,"** Can't open dataset %s\n",argv[nopt]); exit(1);
   }
   if( DSET_NUM_TIMES(xset) < 2 ){
      fprintf(stderr,"** Input dataset %s is not 3D+time\n",argv[nopt]); exit(1);
   }
   yset = THD_open_dataset( argv[++nopt] ) ;
   if( yset == NULL ){
      fprintf(stderr,"** Can't open dataset %s\n",argv[nopt]); exit(1);
   }
   if( DSET_NUM_TIMES(yset) != DSET_NUM_TIMES(xset) ){
      fprintf(stderr,"** Input dataset %s is different length than %s\n",
              argv[nopt],argv[nopt-1]) ;
      exit(1) ;
   }
   if( DSET_NVOX(yset) != DSET_NVOX(xset) ){
      fprintf(stderr,"** Input dataset %s is different size than %s\n",
              argv[nopt],argv[nopt-1]) ;
      exit(1) ;
   }
   if( im_ort != NULL && im_ort->nx < DSET_NUM_TIMES(xset) ){
      fprintf(stderr,"** Input datsets are longer than -ort file!\n"); exit(1);
   }
   DSET_load(xset) ; CHECK_LOAD_ERROR(xset) ;
   DSET_load(yset) ; CHECK_LOAD_ERROR(yset) ;

   /*-- compute mask array, if desired --*/

   nvox = DSET_NVOX(xset) ; nvals = DSET_NVALS(xset) ;

   if( do_autoclip ){
      byte *xmm , *ymm ;
      xmm = THD_automask( xset ) ;
      ymm = THD_automask( yset ) ;
      mmm = (byte *) malloc(sizeof(byte)*nvox) ;
      for( ii=0 ; ii < nvox ; ii++ )
         mmm[ii] = ( xmm[ii] && ymm[ii] ) ;
      free(xmm) ; free(ymm) ;
      ii = THD_countmask( nvox , mmm ) ;
      fprintf(stderr,"++ %d voxels survive -autoclip\n",ii) ;
      if( ii == 0 ) exit(1) ;
   }

   /*-- create output dataset --*/

   cset = EDIT_empty_copy( xset ) ;
   EDIT_dset_items( cset ,
                      ADN_prefix    , prefix         ,
                      ADN_nvals     , 1              ,
                      ADN_ntt       , 0              , /* no time axis */
                      ADN_type      , HEAD_FUNC_TYPE ,
                      ADN_func_type , FUNC_BUCK_TYPE ,
                    ADN_none ) ;

   if( THD_deathcon() && THD_is_file(DSET_HEADNAME(cset)) ){
      fprintf(stderr,"** Output dataset %s already exists!\n",
              DSET_HEADNAME(cset)) ;
      exit(1) ;
   }

   EDIT_BRICK_TO_FICO(cset,0,nvals,1,polort+1+nort) ;  /* stat params */
   EDIT_BRICK_FACTOR(cset,0,0.0) ;                     /* to be safe  */

   switch( method ){                                   /* looks nice  */
      default:
      case PEARSON:  EDIT_BRICK_LABEL(cset,0,"Pear.Corr.") ; break ;
      case SPEARMAN: EDIT_BRICK_LABEL(cset,0,"Spmn.Corr.") ; break ;
      case QUADRANT: EDIT_BRICK_LABEL(cset,0,"Quad.Corr.") ; break ;
   }

   EDIT_substitute_brick( cset , 0 , MRI_float , NULL ) ; /* make array  */
   car = DSET_ARRAY(cset,0) ;                             /* get array   */

   tross_Make_History( "3dTcorrelate" , argc,argv , cset ) ;

   /* loop over voxels, correlate */
   /* fprintf(stderr,"have %d voxels to work with, %d values/time series.\n", nvox, nvals);*/
   for( ii=0 ; ii < nvox ; ii++ ){

      if( mmm != NULL && mmm[ii] == 0 ){  /* the easy case */
         car[ii] = 0.0 ; continue ;
      }

      /* get time series */

      xsim = THD_extract_series(ii,xset,0) ; xsar = MRI_FLOAT_PTR(xsim) ;
      ysim = THD_extract_series(ii,yset,0) ; ysar = MRI_FLOAT_PTR(ysim) ;

      (void)THD_generic_detrend_LSQ( nvals,xsar, polort, nort,fort,NULL ) ;  /* 13 Mar 2003 */
      (void)THD_generic_detrend_LSQ( nvals,ysar, polort, nort,fort,NULL ) ;

      switch( method ){                    /* correlate */
         default:
         case PEARSON:  car[ii] = THD_pearson_corr ( nvals,xsar,ysar ); break;
         case SPEARMAN: car[ii] = THD_spearman_corr( nvals,xsar,ysar ); break;
         case QUADRANT: car[ii] = THD_quadrant_corr( nvals,xsar,ysar ); break;
      }

      mri_free(xsim) ; mri_free(ysim) ;    /* toss time series */

   } /* end of loop over voxels */

   /* toss the other trash */

   DSET_unload(xset); DSET_unload(yset); if( mmm != NULL ) free(mmm);

   /* finito */

   DSET_write(cset) ;
   fprintf(stderr,"++ Wrote dataset: %s\n",DSET_BRIKNAME(cset)) ;
   exit(0) ;
}


syntax highlighted by Code2HTML, v. 0.9.1