#include "mrilib.h"

int main( int argc , char * argv[] )
{
   THD_3dim_dataset *dset1,*dset2=NULL, *oset ;
   MRI_IMAGE *dbr1,*dbr2,*dbr3 ;
   char *prefix = "DFT" ;
   float   *mag, *real;
   complex *comp_array;
   int iarg=1 , doabs=0, ii, jj, kk, ll, nvox, nvals=1, isfloat=0;
   int nx, ny, nz, nfft=0 , detrend=0 ;

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf("Usage: 3dDFT [-prefix ppp] [-abs] [-nfft N] [-detrend] dataset\n"
            "   where dataset is complex or float valued.\n"
            "\n"
            " -abs     == output float dataset = abs(DFT)\n"
            " -nfft N  == use 'N' for DFT length (must be >= #time points)\n"
            " -detrend == least-squares remove linear drift before DFT\n"
           ) ;
     exit(0) ;
   }

   mainENTRY("3dDFT main"); machdep(); AFNI_logger("3dDFT",argc,argv);
   AUTHOR("Kevin Murphy & Zhark the Glorious") ;
#ifdef USING_MCW_MALLOC
   enable_mcw_malloc() ;
#endif

   /*-- options --*/

#define GOOD_TYPE(tt) ((tt)==MRI_complex || (tt)==MRI_float )

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

      if( strcmp(argv[iarg],"-prefix") == 0 ){
         prefix = argv[++iarg] ;
         if( !THD_filename_ok(prefix) )
           ERROR_exit("-prefix %s is illegal!",prefix) ;
         iarg++ ; continue ;
      }

      if( strcmp(argv[iarg],"-abs") == 0 ){
        doabs = 1 ; iarg++ ; continue ;
      }

      if( strcmp(argv[iarg],"-detrend") == 0 ){
        detrend = 1 ; iarg++ ; continue ;
      }

      if( strcmp(argv[iarg],"-nfft") == 0 ){
        nfft = (int)strtod(argv[++iarg],NULL) ;
        if( nfft <= 2 ){
          WARNING_message("Illegal -nfft value on command line") ;
          nfft = 0 ;
        } else {
          ii = csfft_nextup(nfft) ;
          if( ii > nfft ){
            WARNING_message("Replacing -nfft=%d with next largest legal value=%d",
                            nfft,ii) ;
            nfft = ii ;
          }
        }
        iarg++ ; continue ;
      }

      ERROR_exit("ILLEGAL option: %s\n",argv[iarg]) ;
   }

   if( iarg >= argc )
     ERROR_exit("No datasets on command line!?") ;

   /*-- read data --*/

#define OPENIT(ds,aa)                             \
 do{ ds = THD_open_dataset(aa) ;                  \
     if( !ISVALID_DSET(ds) )                      \
       ERROR_exit("Can't open dataset %s",aa);    \
     DSET_load(ds) ;                              \
     if( !DSET_LOADED(ds) )                       \
       ERROR_exit("Can't load dataset %s",aa);    \
 } while(0)

   OPENIT(dset1,argv[iarg])   ;
   if( !GOOD_TYPE( DSET_BRICK_TYPE(dset1,0) ) )
     ERROR_exit("ILLEGAL dataset type in %s - must be complex or float\n",argv[iarg]) ;

   if(DSET_BRICK_TYPE(dset1,0) == MRI_float) { isfloat = 1; }

   dbr1 = DSET_BRICK(dset1,0) ;

   nx = dbr1->nx;
   ny = dbr1->ny;
   nz = dbr1->nz;

   nvox = dbr1->nvox ;
   nvals = DSET_NVALS(dset1);

   /* Calculate size for FFT */
#if 0
   nfft = csfft_nextup_one35(nvals);
#endif

   ii = csfft_nextup(nvals);
   if( nfft <= 2 )
     INFO_message("Data length = %d ; FFT length = %d",nvals,ii) ;
   else if( ii > nfft )
     WARNING_message("Data length = %d ; replacing -nfft=%d with %d",
                     nvals,nfft,ii);
   nfft = ii ;

   /* make output dataset */

   oset = EDIT_empty_copy( dset1 ) ;
   EDIT_dset_items( oset ,
                      ADN_prefix , prefix ,
                      ADN_datum_all, (isfloat) ? MRI_float : MRI_complex  ,
                      ADN_nvals  , nfft ,
                      ADN_ntt    , nfft ,
                    ADN_none ) ;

   DSET_UNMSEC(dset1) ;
   if( DSET_TIMEUNITS(dset1) == UNITS_SEC_TYPE ){   /* 'time' becomes Hz */
     float dt = DSET_TR(dset1) ;
     if( dt <= 0.0f ) dt = 1.0f ;
     EDIT_dset_items( oset ,
                        ADN_tunits , UNITS_HZ_TYPE ,
                        ADN_ttdel  , 1.0f/(nfft*dt) ,
                        ADN_nsl    , 0 ,
                      ADN_none ) ;
   }

#if 0
   if( THD_is_file( DSET_HEADNAME(oset) ) )
     ERROR_exit("Output file %s exists -- will not overwrite!",
                 DSET_HEADNAME(oset) ) ;
#else
   if( THD_deconflict_prefix(oset) > 0 )
     WARNING_message("Filename conflict: changing '%s' to '%s'",
                     prefix , DSET_PREFIX(oset) ) ;
#endif

   /* create empty bricks for output dataset */

   for( ii=0 ; ii < nfft ; ii++ )
     EDIT_substitute_brick( oset , ii ,
                            (doabs) ? MRI_float : MRI_complex ,
                            NULL ) ;

   /* Loop through timeseries and do DFT */

   comp_array = (complex *) calloc( sizeof(complex) , nfft);
   mag        = (float *)   calloc( sizeof(float)   , nfft);
   if (isfloat) { real = (float *)   calloc( sizeof(float)   , nfft); }

   for( ii=0 ; ii < nvox ; ii++ ){  /* loop over voxels */

     if(!isfloat){
       (void)THD_extract_array( ii , dset1 , 1 , comp_array ) ;
       if( detrend ) THD_linear_detrend_complex( nvals , comp_array ) ;
     } else {
       (void)THD_extract_array( ii , dset1 , 1 , real );
       if( detrend ) THD_linear_detrend( nvals , real , NULL,NULL ) ;
       for( jj=0 ; jj < nvals ; jj++ ) {
         comp_array[jj].r = real[jj]; comp_array[jj].i = 0.0f ;
       }
     }

     for( jj=nvals ; jj < nfft ; jj++ )
       comp_array[jj].r = comp_array[jj].i = 0.0f ;  /* zero pad */

    /* Perform the DFT at last! */

     csfft_cox( -1 , nfft, comp_array ) ;

     if( doabs ){
       for( jj=0 ; jj < nfft ; jj++ ) mag[jj] = CABS(comp_array[jj]) ;
       THD_insert_series( ii , oset , nfft , MRI_float   , mag        , 1 );
     } else {
       THD_insert_series( ii , oset , nfft , MRI_complex , comp_array , 1 );
     }
   }

   DSET_unload(dset1) ;

   /* make history */

   tross_Copy_History( oset , dset1 ) ;
   tross_Make_History( "3dDFT", argc,argv, oset ) ;

   INFO_message("output dataset: %s\n",DSET_BRIKNAME(oset)) ;
   DSET_write( oset ) ;
   exit(0) ;
}


syntax highlighted by Code2HTML, v. 0.9.1