#! /bin/csh -f

#
# mc-afni2
#
# Original Author: Doug Greve
# CVS Revision Info:
#    $Author: greve $
#    $Date: 2009/12/09 18:09:08 $
#    $Revision: 1.6 $
#
# 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-afni2,v 1.6 2009/12/09 18:09:08 greve Exp $';

set invol = ();
set outvol = ();
set tempvol = ();
set frame = 0;
set mcdat = ();

set nolog = 0;
set tmpdir = ();
set cleanup = 1;
set PrintHelp = 0;

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

goto parse_args;
parse_args_return:

goto check_params;
check_params_return:

# Check that the AFNI 3dvolreg exists
which 3dvolreg > /dev/null
if($status) then
  echo "ERROR: cannot find AFNI command 3dvolreg"
  exit 1;
endif

# Set up template volume
if($#tempvol == 0) set tempvol = $invol;
set infotxt = /tmp/mriinfo.$$
set cmd = (mri_info --nframes --o $infotxt $tempvol);
pwd
echo $cmd
$cmd
if($status) exit 1;
set nframes = `cat $infotxt`;
if($frame >= $nframes) then
  echo "ERROR: template volume $tempvol has only $nframes"
  echo "       but you have specified to use $frame"
  exit 1;
endif

# Set up output mcdat
if($#mcdat == 0) set mcdat = $outvol.mcdat 
if(-e $mcdat) then
  if(! -w $mcdat) then
    echo ""
    echo "ERROR: $mcdat exists and you don't have perms to overwrite it"
    ls -l `pwd`/$mcdat
    echo ""
    exit 1;
  endif
endif
set matdat = `fname2stem $outvol`.mat


# Output directory
set outdir = `dirname $outvol`;
mkdir -p $outdir
if($status) then
  echo "ERROR: creating $outdir"
  exit 1;
endif

# Setup the log file
if(! $nolog) then
  set LF = $outvol.mclog
  rm -f $LF
else
  set LF = /dev/null
endif
echo "log file is $LF"
pwd >> $LF
which mc-afni2 >> $LF
echo $cmdargs >> $LF
date     >> $LF
id       >> $LF
hostname >> $LF
uname -a >> $LF
which 3dvolreg >> $LF

echo "mcdat file is $mcdat" |& tee -a $LF

# Tmp Dir
if($#tmpdir == 0) set tmpdir = $outdir/tmp.mc-afni2.$$
mkdir -p $tmpdir
echo "tmp dir is $tmpdir" |& tee -a $LF

# Extract Template from template volume
set newtempvol = $tmpdir/tempvol.nii.gz
@ nskip = $frame
@ ndrop = ($nframes - $frame) - 1;
set cmd = (mri_convert $tempvol $newtempvol \
  --nskip $nskip --ndrop $ndrop -odt float)
echo "#@# --------------------------------" |& tee -a $LF
pwd |& tee -a $LF
echo $cmd |& tee -a $LF
$cmd |& tee -a $LF
if($status) exit 1;

# Convert the input to nifti (always to assure float)
set newinvol = $tmpdir/invol.nii.gz
set cmd = (mri_convert $invol $newinvol -odt float)
echo "#@# --------------------------------" |& tee -a $LF
pwd |& tee -a $LF
echo $cmd |& tee -a $LF
$cmd |& tee -a $LF
if($status) exit 1;

# Setup the output volume
set newoutvol = $tmpdir/outvol.nii.gz

# Now, finally, do the motion correction
set cmd = (3dvolreg -verbose -dfile $mcdat -1Dmatrix_save $matdat \
           -base $newtempvol -prefix $newoutvol $newinvol )
echo "#@# --------------------------------" |& tee -a $LF
pwd       |& tee -a $LF
echo $cmd |& tee -a $LF
$cmd      |& tee -a $LF
if($status) then
  echo "ERROR: 3dvolreg" |& tee -a $LF
  if($cleanup) then
    echo "... cleaning up ...."; |& tee -a $LF
    rm -r $tmpdir
  endif
  exit 1;
endif

# Always convert the output. AFNI mucks with the goemetry,
# so we have to run mri_convert with --like to keep it.
# 3dvolreg will remove off-diagonal components (but keeps
# the basic geometry correct).
echo "#@# --------------------------------" |& tee -a $LF
set cmd = (mri_convert $newoutvol $outvol --in_like $tempvol)
pwd |& tee -a $LF
echo $cmd |& tee -a $LF
$cmd |& tee -a $LF
if($status) then
  echo "ERROR: converting output " |& tee -a $LF
  if($cleanup) then
    echo "... cleaning up ...."; |& tee -a $LF
    rm -r $tmpdir
  endif
  exit 1;
endif

# add total distplacment to last col of mcdat file
set tmpmc = /tmp/tmp_$$.mcdat
addmcparams $mcdat > $tmpmc 
mv $tmpmc $mcdat

## Clean up the anfi files ##
if($cleanup) then
   echo "... cleaning up ...." |& tee -a $LF
   rm -r $tmpdir
endif

date |& tee -a $LF
echo "mc-afni2 done" |& tee -a $LF

exit 0;

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

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

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

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

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

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

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

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

    case "--nocleanup":
      set cleanup = 0;
      breaksw

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

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

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

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

end

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

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

if($#invol == 0) then
  echo "ERROR: must specify an input volume"
  exit 1;
endif
if(! -e $invol) then
  echo "ERROR: cannot find $invol"
  exit 1;
endif
if($#outvol == 0) then
  echo "ERROR: must specify an output volume"
  exit 1;
endif
if($#tempvol != 0) then
  if(! -e $tempvol) then 
    echo "ERROR: cannot find template volume $tempvol"
    exit 1;
  endif
endif

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

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

############--------------##################
usage_exit:
  echo "USAGE: mc-afni2"
  echo ""
  echo " Required:";
  echo "   --i invol  : input  volume "
  echo "   --o outvol : output volume "
  echo ""
  echo " Options:";
  echo "   --t templatevol   : default is to use input volume"
  echo "   --frame frame     : 0-based frame of template "
  echo "   --mcdat mcdatfile : text file with mc parameters"
  echo ""
  echo "   --tmp tmpdir   : specify template directory (implies --nocleanup)"
  echo "   --nocleanup    : do not delete temporary files"
  echo "   --cleanup      : force cleanup"
  echo ""
  echo "   --help"
  echo "   --version : print version and exit"
  echo ""

  if(! $PrintHelp) exit 1;

  echo $VERSION

  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

Front-end for motion correction with AFNI 3dvolreg. See 3dvolreg -help
for more info.

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.

Differs from mc-afni in that: (1) it can take any format for input and
output, (2) uses nifit gz as input/output from 3dvolreg, and (3) gives
and gets floats to/from 3dvolreg instead of shorts. The motion
correction parameters in the mcdat file may have a different order.

--i invol

Input volume to be registered. Can/should have multiple frames.

--o outvol 

Output after all frames have been aligned with the template. Will
have the same geometry as the template. Note: this is NOT the default
for AFNI/3dvolreg.

--t templatevol

Volume to register to. If not specified, defaults to the first frame
of the input. The output volume will have the same geometry as the
template volume.

--frame nth

Use nth frame from the template volume as the template. nth is 0-based,
ie, nth=0 means first frame, etc. Default is 0.

--mcdat mcdatfile

Save motion correction parameters into mcdatfile. Default is outvol.mcdat.

  The AFNI 3dvolreg output mcdat file will have the following 10 columns:
  1. n      : time point
  2. roll   : rotation about the column (?) axis (degrees CCW)
  3. pitch  : rotation about the row (?) axis (degrees CCW)
  4. yaw    : rotation about the slice (?) axis (degrees CCW)
  5. dcol   : displacement in the column direction (mm)
  6. drow   : displacement in the row direction (mm)
  7. dslice : displacement in the slice direction (mm)
  8. rmsold : RMS difference between input frame and reference frame
  9. rmsnew : RMS difference between output frame and reference frame
  10. trans : translation (mm) = sqrt(dslice^2 + dcol^2 + drow^2)

  Where "displacement in the column direction" means orthogonal to the
  row-slice plane. A negative dcol indicates that the input volume was
  originally shifted up from the template and had to be shifted down. A
  negative drow indicates that the input was was originally to the right
  of the template and had to be shifted to the left. A negative dslice
  means that the input started closer to slice 0 than the template and
  had to be shifted away from slice 0.

--tmp tmpdir

Use tmpdir as a staging area. Default is to create a randomly named
subdirectory in the output directory. --tmp implies --nocleanup

--nocleanup

Do NOT delete tmpdir

--cleanup

DO delete tmpdir

