#! /bin/csh -f

#
# kmacf-sess
#
# Original Author: Doug Greve
# CVS Revision Info:
#    $Author: nicks $
#    $Date: 2007/01/09 22:41:18 $
#    $Revision: 1.5 $
#
# Copyright (C) 2002-2007,
# The General Hospital Corporation (Boston, MA). 
# All rights reserved.
#
# Distribution, usage and copying of this software is covered under the
# terms found in the License Agreement file named 'COPYING' found in the
# FreeSurfer source code root directory, and duplicated here:
# https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferOpenSourceLicense
#
# General inquiries: freesurfer@nmr.mgh.harvard.edu
# Bug reports: analysis-bugs@nmr.mgh.harvard.edu
#


set VERSION = '$Id: kmacf-sess,v 1.5 2007/01/09 22:41:18 nicks Exp $';

set inputargs = ($argv);
set DateStr = "`date '+%y%m%d%H%M'`"

set TopDir = `pwd`;

set analysis = ();
set nclusters = ();
set nmaxlag = ();
set acfdirname = acf;
set mask = brain;
set outbase = ();
set monly = 0;
set MLF = ();
set QuitOnError = 0;
set FitPolyZ = 0;
set PolyZOrder = 0;
set UseKJW = 0;
set InitMethod = '';
set kmacfid = ();
set PrintHelp = 0;

if($#argv == 0) goto usage_exit;
set n = `echo $argv | grep version | wc -l` 
if($n != 0) then
  echo $VERSION
  exit 0;
endif
set n = `echo $argv | grep help | wc -l` 
if($n != 0) then
  set PrintHelp = 1;
  goto usage_exit;
endif

set SessList = `getsesspath $argv`;
if($status || $#SessList == 0) then
  getsesspath $argv 
  exit 1;
endif

goto parse_args;
parse_args_return:

goto check_params;
check_params_return:

# get full path for cfg and info files #
pushd $analysis > /dev/null;
set analysisdir = `pwd`;
popd > /dev/null;
set cfgfile  = $analysisdir/analysis.cfg
set infofile = $analysisdir/analysis.info
if(! -e $infofile) then
  echo "ERROR: cannot find $infofile"
  exit 1;
endif

## Get parameters from the info file ##
set fsd         = `cat $infofile | awk '{if($1 == "fsd") print $2}'`;
set runlistfile = `cat $infofile | awk '{if($1 == "runlistfile") print $2}'`;

set designtype  = `cat $infofile | awk '{if($1 == "designtype") print $2}'`;
if($#designtype == 0) then
  set designtype = `cat $infofile | awk '{if($1 == "avgtype") print $2}'`;
endif
if($designtype != "event-related" && $designtype != "blocked") then
  echo "ERROR: the design type of this analysis is $designtype"
  echo "  evspatfil-jk-sess can only be used to analyse event-related and blocked"
  exit 1;
endif

##### Create a log file ######
set logdir = `pwd`/log;
mkdir -p $logdir
if(! -e $logdir) then
  echo "WARNING: could not create $logdir"
  set LF = /dev/null
else
  set LF = $logdir/kmacf-$DateStr.log
  if(-e $LF) mv $LF $LF.old
endif
echo "--------------------------------------------------------------"
echo "kmacf-sess logfile is $LF"
echo "--------------------------------------------------------------"

echo "kmacf-sess log file" >> $LF
echo $VERSION >> $LF
id            >> $LF
pwd           >> $LF
echo $0         >> $LF
echo $inputargs >> $LF
uname -a        >> $LF
date            >> $LF

### Go through each session ###
set StartTime = `date`;
foreach sess ($SessList)

  set sessbase = `basename $sess`;
  echo "-------------------------------------------" |& tee -a $LF
  echo "$sess " |& tee -a $LF
  date |& tee -a $LF

  set fsdpath = $sess/$fsd
  cd $fsdpath

  if($#runlistfile == 0) then
      set RunList = `getrunlist .`;
      if($status || $#RunList == 0) then
        echo "ERROR: $sess/$fsd has no runs"  |& tee -a $LF
        exit 1;
      endif
    else
      if(! -e $runlistfile) then
        echo "ERROR: ($sessbase) could not find runlistfile $runlistfile"
        exit 1;
      endif
      set RunList = (`cat $runlistfile`);
    endif
    echo "INFO ($sessbase): RunList = $RunList" 
  endif

  if(! $monly) set MLF = /tmp/kmacf-$$.m
  rm -f $MLF
  echo "MLF is $MLF" |& tee -a $LF
  if($#mask != 0) then
    set maskstem = masks/$mask
  else
    set maskstem = ();
  endif

  @ nthRun = 1;
  foreach Run ($RunList)
    echo "  Run $Run -----------------------------" |& tee -a $LF
    date |& tee -a $LF

    set ana = $analysis-$Run;
    if(! -e $ana) then
      echo "ERROR: $ana does not exist" |& tee -a $LF
      exit 1;
    endif

    set acfdir = $ana/$acfdirname;
    if(! -e $acfdir) then
      echo "ERROR: $acfdir does not exist" |& tee -a $LF
      exit 1;
    endif

    #set nthRunId = `printf %03d $nthRun`;
    #set acfstem = $acfdir/acf$nthRunId
    set acfstem = $acfdir/acf001
    if(! -e $acfstem"_000.bfloat") then
      echo "ERROR: $acfstem" |& tee -a $LF
      exit 1;
    endif

    set outbasestem = $acfdir/acf001

    set xmatfile = $analysis-$Run/X.mat;

    set MLFTMP = $acfdir/kmacf-tmp.m
    rm -f $MLFTMP
#-----------------------------------------------------------------#
tee $MLFTMP <<EOF

clear all;
fsdpath = '$fsdpath';
cd(fsdpath);

kmacfid   = '$kmacfid';
acfstem   = '$acfstem';
maskstem   = '$maskstem';
nmaxlag   = $nmaxlag;
nitersmax = $nitersmax;
nclusters = $nclusters;
outbasestem = '$outbasestem';
xmatfile    = '$xmatfile';
fitpolyz    = $FitPolyZ;
polyzorder  = $PolyZOrder;
usekjw      = $UseKJW;
initmethod  = '$InitMethod';

fast_kmacf;

EOF
#-----------------------------------------------------------------#
    cat $MLFTMP >> $MLF

    @ nthRun = $nthRun + 1;
  end # Runs

  rm $MLFTMP
  if(! $monly ) then
    cat $MLF | matlab -display iconic |& tee -a $LF
  endif

end # Sessions

echo " "
echo "Started at $StartTime "
echo "Ended   at `date`"
echo " "
echo "kmacf-sess Done"
echo " "

exit 0;
###############################################

############--------------##################
parse_args:
set cmdline = ($argv);
while( $#argv != 0 )

  set flag = $argv[1]; shift;
  
  switch($flag)

    case "-a":
    case "-analysis":
      if ( $#argv < 1) goto arg1err;
      set analysis = $argv[1]; shift;
      set analysis = `basename $analysis`; # remove trailing /
      breaksw

    case "-kmacfid":
      if ( $#argv == 0) goto arg1err;
      set kmacfid = $argv[1]; shift;
      breaksw

    case "-k":
      if ( $#argv == 0) goto arg1err;
      set nclusters = $argv[1]; shift;
      breaksw

    case "-polyz":
      if ( $#argv == 0) goto arg1err;
      set PolyZOrder = $argv[1]; shift;
      set FitPolyZ = 1;
      breaksw

    case "-nmaxlag":
      if ( $#argv == 0) goto arg1err;
      set nmaxlag = $argv[1]; shift;
      breaksw

    case "-nitersmax":
      if ( $#argv == 0) goto arg1err;
      set nitersmax = $argv[1]; shift;
      breaksw

    case "-acfdir":
      if ( $#argv == 0) goto arg1err;
      set acfdirname = $argv[1]; shift;
      breaksw

    case "-mask":
      if ( $#argv == 0) goto arg1err;
      set mask = $argv[1]; shift;
      breaksw

    case "-o":
      if ( $#argv == 0) goto arg1err;
      set outbase = $argv[1]; shift;
      breaksw

    case "-monly":
      if ( $#argv == 0) goto arg1err;
      set MLF = $argv[1]; shift;
      set monly = 1;
      breaksw

    case "-nomask":
      set mask = ();
      breaksw

    case "-init":
      if ( $#argv < 1) goto arg1err;
      set InitMethod = $argv[1]; shift;
      breaksw

    case "-debias":
    case "-kjw":
      set UseKJW = 1;
      breaksw

    case "-verbose":
      set verbose = 1;
      breaksw

    case "-echo":
      set echo = 1;
      breaksw

    case "-debug":
      set verbose = 1;
      set echo = 1;
      breaksw

    case "-g":
    case "-s":
    case "-sf":
    case "-d":
    case "-df":
      shift;
      # ignore getsesspath arguments 
      breaksw

    case "-cwd":
      # ignore getsesspath arguments 
      breaksw

    case "-umask":
      if ( $#argv == 0) goto arg1err;
      umask $1; shift;
      breaksw

    default:
      echo ERROR: Flag $flag unrecognized. 
      echo $cmdline
      exit 1
      breaksw
  endsw

end

goto parse_args_return;
############--------------##################

############--------------##################
check_params:

  if($#SessList == 0) then
     echo "ERROR: no sessions specified"
     exit 1
  endif

  if($#analysis == 0) then
     echo "ERROR: no analysis name specified"
     exit 1
  endif

  if(! -d $analysis ) then
    echo "ERROR: analysis $analysis does not exist, see mkanalysis-sess"
    exit 1;
  endif

  if($#nclusters == 0) then
    echo "ERROR: number of clusters not specified"
    exit 1;
  endif

  if($#kmacfid == 0) then
    echo "ERROR: no kmacf id specified"
    exit 1;
  endif

  if($#nmaxlag == 0) then
    echo "ERROR: nmaxlag not specified"
    exit 1;
  endif

  if($#nitersmax == 0) then
    echo "ERROR: nitersmax not specified"
    exit 1;
  endif

goto check_params_return;
############--------------##################

############--------------##################
arg1err:
  echo "ERROR: flag $flag requires one argument"
  exit 1
############--------------##################

############--------------##################
arg2err:
  echo "ERROR: flag $flag requires two arguments"
  exit 1
############--------------##################

############--------------##################
usage_exit:
  echo ""
  echo "USAGE: kmacf-sess"
  echo ""
  echo "Required Arguments:";
  echo "   -analysis  analysisname : name of functional analysis"
  echo "   -kmacfid   id : id used for naming"
  echo "   -k         nclusters    : number of clusters"
  echo "   -nmaxlag   nmaxlag      : max lag when fitting"
  echo "   -nitersmax nitersmax    : maximum number of iterations"
  echo ""
  echo "Optional Arguments:";
  #echo "   -acfdir  acfdirname : default is acf"
  echo "   -mask    stem : use mask in FSD/masks/stem (default brain)"
  echo "   -nomask  : do not use a mask"
  echo "   -init method : firstlag or svd"
#  echo "   -o       outbase : acfRRR"
  echo ""
  echo "Session Arguments (Required)"
  echo "   -sf sessidfile  ..."
  echo "   -df srchdirfile ..."
  echo "   -s  sessid      ..."
  echo "   -d  srchdir     ..."
  echo ""
  echo "Session Arguments (Optional)"
  echo "   -umask umask   : set unix file permission mask"
  echo "   -version       : print version and exit"
  echo ""
  echo ""

  if($PrintHelp) \
  cat $0 | awk 'BEGIN{prt=0}{if(prt) print $0; if($1 == "BEGINHELP") prt = 1 }'

exit 1;

#---- Everything below here is printed out as part of help -----#
BEGINHELP

Performs k-means clustering of the autocorrelation functions (ACFs) of
the residuals of the given analysis as saved by a run of
selxavg-sess-perrun -svacf. The cluster map is saved in
ana/acf/acf001-kmacfid-kmap, and the cluster vectors are saved in
ana/acf/acf001-kmacfid-racf, where kmacfid is the argument to the
-kmacfid flag. These will be used by kmacfcond-sess and
kmacfwht-sess. By default, only the voxels found in the brain mask are
used; this can be changed with -nomask or -mask newmask.

-kmacfid id

Unique id that will be used to name files.

-k nclusters

Run k-means with nclusters. Suggest 10.

-nmaxlag nmaxlag

Train k-means with nmaxlag components of the ACF. This is only used
when determining the cluster vectors. The output ACFs will have a
length equal to that of the input acf.

-nitersmax nitersmax 

Run k-means with a maximum nitersmax iterations. Suggest 25.

-mask maskname

Use maskname (as found in fsd/masks) instead of brain.

-nomask

Do not use a mask at all.

-init method

Initialize the k-means with either firstlag or svd. With firstlag,
k-means is run on the first lag of the ACF (this takes about 10-15
sec), then a new set of nmaxlag length k-means are computed from this
map and used as input to the full k-means. With svd, the top ncluster
eigenvectors of the input data set are used. If no init method is
specified, then the first nclusters from the input set are used.
Suggest: firstlag.

-polyz order

Remove components from the input data set that are not spanned by the
space of a polynomial of the given order. This polynomial basis
is set up to have a zero at nmaxlag. See fast_polyzacf_fit.m. Suggest
not using this.

-debias

Remove bias from the input ACF. The bias comes from the fact that the
ACFs are from the residual and not the actual noise process.  Uses
method proposed by KJW. See fast_kjw_mtx.m. Suggest not using this
here; use with kmacfcond-sess.

See also fast_kmacf.m, kmacfcond-sess, kmacfwht-sess
