#! /bin/csh -f

#
# mc-sess - motion correction
#
# Original Author: Doug Greve
# CVS Revision Info:
#    $Author: greve $
#    $Date: 2010/04/15 18:49:34 $
#    $Revision: 1.25 $
#
# 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: mc-sess,v 1.25 2010/04/15 18:49:34 greve Exp $'
set cmdargs = ($argv);

set fsd = "bold";
set mcmethod   = "afni"
set targoff    = 0;
set targoffmid = 0;
set PerRun = 0;
set PerSess = 0;
set funcstem   = f;  # stem of functional volume
set funcmcstem = (); # stem of functional motion-corrected volume
set PWDCMD = `getpwdcmd`;
set targnthrun = 1;  # use nth run as target
set targrun = ();    # use explicit run as target
set RunListFile = ();
set targstem = ();
set targstem0 = ();
set UpdateOnly = 0;
set mask = brain;

set nolog = 0;
set PrintHelp = 0;

set outfmt = nii;
if($?FSF_OUTPUT_FORMAT) then
  set outfmt = $FSF_OUTPUT_FORMAT;
endif

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

set n = `echo $argv | grep citation | wc -l` 
if($n != 0) then
  exit 0;
endif

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

goto parse_args;
parse_args_return:

goto check_params;
check_params_return:

set ProjectDir = `pwd`;

## Check each session ##
foreach sess ($SessList)
  set sessid = `basename $sess`;
  if(! -d $sess) then
    echo "ERROR: $sess does not exist"  
    exit 1;
  endif
  if(! -d $sess/$fsd) then
    echo "ERROR: $sess/$fsd does not exist"  
    exit 1;
  endif
end

## Now analyze each session ##
foreach sess ($SessList)
  set sessid = `basename $sess`;

  # Create a log file #
  set LF = /dev/null
  if(! $nolog ) then
    mkdir -p $ProjectDir/log
    set LF = $ProjectDir/log/mc-$sessid-$fsd.log
    rm -f $LF
    touch $LF
  endif
  echo Logfile is $LF

  echo "mc-sess" >> $LF
  echo $sessid      >> $LF
  echo $VERSION  >> $LF
  echo $LF       >> $LF
  uname -a       >> $LF
  date           >> $LF
  echo $cmdargs  >> $LF
  pwd            >> $LF
  echo "ProjectDir $ProjectDir" >> $LF

  echo "-------------------------------------------" |& tee -a $LF
  echo "$sess " |& tee -a $LF

  if(! -d $sess) then
    echo "ERROR: $sess does not exist"   |& tee -a $LF
    exit 1;
  endif

  pushd $sess/$fsd > /dev/null

  set RunList = `getrunlist . $RunListFile`;
  if($status) then
    echo "$RunList"  |& tee -a $LF
    exit 1;
  endif
  echo "RunList: $RunList" |& tee -a $LF

  if($PerSess) then
    set template = `stem2fname template`
    if($status) then
      echo "ERROR: cannot find $template for $sess/$fsd"  |& tee -a $LF
      echo "       run mktemplate-sess"  |& tee -a $LF
      exit 1;
    endif
  endif    

  foreach run ($RunList)  
    set invol = `stem2fname $run/$funcstem`;
    if($status) then
      echo "$invol" 
      exit 1;
    endif
    set outstem = $run/$funcmcstem
    set outvol = $outstem.$outfmt
    set mcdat = $outstem.mcdat

    if($PerRun) then
      set template = `stem2fname $run/template`
      if($status) then
        echo "ERROR: cannot find $template for $sess/$fsd/$run"  |& tee -a $LF
        echo "       run mktemplate-sess"  |& tee -a $LF
        exit 1;
      endif
    endif    

    set UpdateNeeded = 0;
    if(-e $outvol && -e $mcdat && $UpdateOnly) then
      test $invol -nt $outvol
      if(! $status) set UpdateNeeded = 1;
      test $template -nt $outvol
      if(! $status) set UpdateNeeded = 1;
    else
      set UpdateNeeded = 1
    endif

    if(! $UpdateNeeded) then
      echo "$sessid $run Update not needed"
      continue;
    endif

    set cmd = (mc-afni2 --i $invol --t $template --o $outvol  --mcdat $mcdat)
    echo "  ------- ************************** -----------" |& tee -a $LF
    echo "  ------- Motion Correcting Run $run -----------" |& tee -a $LF
    echo "  ------- ************************** -----------" |& tee -a $LF
    echo "sess = $sessid" |& tee -a $LF
    date |& tee -a $LF
    echo $cmd |& tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;

    # Create the external regresssor file -- this requires matlab
    echo "INFO: Making external regressor from mc params" |& tee -a $LF
    #set cmd = (mcparams2extreg -mcfile $outstem.mcdat -northog 6)
    #set cmd = ($cmd -extreg $run/mcextreg)
    
    if($PerSess) set mcextreg = $run/mcextreg
    if($PerRun)  set mcextreg = $run/mcprextreg
    set cmd = (mcdat2mcextreg --i $outstem.mcdat --o $mcextreg)
    echo $cmd |& tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;

  end # Loop over sessions 

  echo "" |& tee -a $LF
  echo "" |& tee -a $LF

  popd > /dev/null
end

date | tee -a $LF
echo "mc-sess completed SUCCESSFULLY" | tee -a $LF

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


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

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

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

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

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

    case "-outfmt":
    case "-fmt":
      if ( $#argv == 0) goto arg1err;
      set outfmt = $fmt;
      breaksw

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

    case "-method":
      if ( $#argv == 0) goto arg1err;
      set mcmethod = $argv[1]; shift;
      if($mcmethod != "afni") then
        echo "ERROR: only afni supported"
        exit 1;
      endif
      breaksw

    case "-per-run":
    case "-perrun":
      set PerRun = 1;
      set PerSess = 0;
      breaksw

    case "-per-session":
      set PerSess = 1;
      set PerRun = 0;
      breaksw

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

    case "-inorm":
      echo "ERROR: cannot perform inorm here anymore"
      exit 1;
      breaksw

    case "-update":
      set UpdateOnly = 1;
      breaksw

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

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

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

    case "-cwd":
      # ignore getsesspath arguments 
      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($PerRun == 0 && $PerSess == 0) then
  echo "ERROR: You must specify -per-run or -per-session"
  exit 1;
endif

if($#funcmcstem == 0) then
  if($PerRun) then
    set funcmcstem = fmcpr
  else
    set funcmcstem = fmc
  endif
endif

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

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

############--------------##################
usage_exit:
  echo ""
  echo "USAGE: mc-sess"
  echo ""
  echo "Session Arguments (Required)"
  echo "   -sf sessidfile  "
  echo "   -df srchdirfile "
  echo "   -s  sessid      "
  echo "   -d  srchdir     "
  echo ""
  echo "You must specify one of these"
  echo "   -per-run           : MC each run to run-level template"
  echo "   -per-session       : MC each run to session-level template"
  echo ""
  echo "Optional Arguments:";
  echo "   -fsd dir        (optional - default = bold)"
  echo "   -fstem fstem       : stem of input volume <f>"
  echo "   -fmcstem fmcstem   : stem of output motion-corrected volume (fmc or fmcpr)"
  echo ""
  echo "   -outfmt format     : nii, nii.gz, mgh, or mgz (default is $outfmt)"
  echo "   -update            : only mc if input is newer than output"
  echo "   -version           : print version and exit"
  echo "   -debug"
  echo ""
  if(! $PrintHelp ) exit 1;
  echo " "
  echo "$VERSION "
  echo " "
  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

Motion correction using AFNI. By default, you only need to pass
the session parameters and it will look for f.nii as an input
in each bold run and will create fmc.nii as an output (along
with fmc.mcdat and mcextreg.bhdr).

You must have run mktemplate-sess first.

When running with -perrun and no explicit output, the oustem is
set to fmcpr

Those using the AFNI motion correction should cite:

RW Cox and A Jesmanowicz.  Real-time 3D image registration for
functional MRI.  Magnetic Resonance in Medicine, 42: 1014-1018, 1999.

