#! /bin/tcsh -f

#
# mri_motion_correct2
#
# Performs motion correction of anatomicals. This should produce
# the same output as mri_motion_correct
#
# Original Author: Doug Greve
# CVS Revision Info:
#    $Author: nicks $
#    $Date: 2008/02/29 20:14:51 $
#    $Revision: 1.15 $
#
# Copyright (C) 2002-2008,
# 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: mri_motion_correct2,v 1.15 2008/02/29 20:14:51 nicks Exp $';

set tmpdir      = ();
set inputlist   = ();
set outspec     = ();
set PrintHelp   = 0;
set LF          = ();
set CleanUp     = 1;
set CleanUpList = ();
set SaveXFM     = 1;
set PWD = pwd;
if ( -e /bin/pwd ) set PWD = /bin/pwd
set HiRes = '';
set outfmt = ();
set AllowWild = 0;

# If no args, print usage and exit #
if($#argv == 0) then
  goto usage_exit;
  exit 1;
endif

# Look for version #
set n = `echo $argv | grep version | wc -l`
if($n != 0) then
  echo $VERSION
  ##### gather version info used in this script
  mri_convert --version
  set prog = `which rawtominc`
  strings $prog | grep rawtominc.c
  set prog = `which minctracc`
  strings $prog | grep minctracc.c
  set prog = `which mincresample`
  strings $prog | grep mincresample.c
  set prog = `which mincaverage`
  strings $prog | grep mincaverage.c
  exit 0;
endif

goto parse_args;
parse_args_return:

goto check_params;
check_params_return:

##### Create a log file ######
if($#LF == 0) then
  if("$outfmt" == "COR") then
    set LF = $outdir/mri_motion_correct2.log
  else
    set LF = $outspec.mri_motion_correct2.log
  endif
  if(-e $LF) mv $LF $LF.old
endif

echo "--------------------------------------------------------------"
echo "mri_motion_correct2 logfile is $LF"
echo "--------------------------------------------------------------"

echo "mri_motion_correct2 log file" >> $LF
echo $VERSION      >> $LF
echo $0            >> $LF
echo $argv         >> $LF
pwd               >> $LF
uname -a           >> $LF
date               >> $LF
which mri_convert  >> $LF
echo SaveXFM $SaveXFM

set StartTime = `date`;

# Get TR, TI, TE, and FlipAngle, check consist
foreach input ($inputlist)
  set TR = `mri_info $input --tr`;
  if($status) then
    echo "ERROR: $status"
    exit 1;
  endif
  set TE = `mri_info $input --te`;
  if($status) then
    echo "ERROR: $status"
    exit 1;
  endif
  set TI = `mri_info $input --ti`;
  if($status) then
    echo "ERROR: $status"
    exit 1;
  endif
  set FlipAngle = `mri_info $input --flip_angle`;
  if($status) then
    echo "ERROR: $status"
    exit 1;
  endif

  if($input == $inputlist[1]) then
    set TR0 = $TR;
    set TE0 = $TE;
    set TI0 = $TI;
    set FlipAngle0 = $FlipAngle
  endif

  if($TR != $TR0) then
    echo "WARNING: TRs are inconsistent $TR0 $TR"
  endif
  if($TE != $TE0) then
    echo "WARNING: TEs are inconsistent $TE0 $TE"
  endif
  if($TI != $TI0) then
    echo "WARNING: TIs are inconsistent $TI0 $TI"
  endif
  if($FlipAngle != $FlipAngle0) then
    echo "WARNING: FlipAngles are inconsistent $FlipAngle0 $FlipAngle"
  endif

end


#------------- Convert each input to MINC ------------#
set CleanUpList = ($CleanUpList );
set mncinputlist = ();
@ run = 0;
foreach input ($inputlist)
  @ run = $run + 1;

  echo "-----------------------------------------" |& tee -a $LF
  echo "Converting $input " |& tee -a $LF
  date |& tee -a $LF

  set mncinput = $tmpdir/cor-$run.mnc
  set mncinputlist = ($mncinputlist $mncinput);
  rm -f $mncinput

  set cmd = (mri_convert $input $mncinput)
  #set cmd = (mri_convert $input $mncinput -odt float) # should do this instead?
  pwd >> $LF
  echo $cmd >> $LF
  $cmd |& tee -a $LF
  if($status) then
    echo "ERROR: mri_convert failed" |& tee -a $LF
    exit 1;
  endif

  set CleanUpList = ($CleanUpList $mncinput);

end

#----------- Motion Correct ---------------#
set mncresampled = $tmpdir/resampled.mnc
set mnctarget = $mncinputlist[1];
@ run = 0;
foreach mncinput ($mncinputlist)
  @ run = $run + 1;

  if($mncinput == $mnctarget) continue;

  if($SaveXFM) then
    set xfm = $outstem-mc$run.xfm
  else
    set xfm = $tmpdir/run$run.xfm
    set CleanUpList = ($CleanUpList $xfm);
  endif
  rm -f $xfm

  echo "-----------------------------------------" |& tee -a $LF
  echo "Motion Correcting $mncinput" |& tee -a $LF
  date |& tee -a $LF
  echo "xfm is $xfm" |& tee -a $LF
  # minctracc is MNI software without version option, but cvs'ed.
  set cmd = (minctracc -lsq6 $mncinput $mnctarget $xfm)
  pwd | tee -a $LF
  echo $cmd | tee -a $LF
  $cmd |& tee -a $LF
  if($status) then
    echo "ERROR: mritoself failed" |& tee -a $LF
    exit 1;
  endif

  echo "-----------------------------------------" |& tee -a $LF
  echo "Resampling $mncinput" |& tee -a $LF
  date |& tee -a $LF

  rm -f $mncresampled
  # mincresample is MNI software without version option, but cvs'ed
  set cmd = (mincresample -like $mnctarget -transform $xfm)
  set cmd = ($cmd $mncinput $mncresampled)
  pwd >> $LF
  echo $cmd >> $LF
  $cmd |& tee -a $LF
  if($status) then
    echo "ERROR: mincresample failed" |& tee -a $LF
    exit 1;
  endif

  mv $mncresampled $mncinput |& tee -a $LF

end

#----------- Average Volumes Together ---------------#
echo "-----------------------------------------" |& tee -a $LF
echo "Averaging " |& tee -a $LF
date |& tee -a $LF
set avgvol = $tmpdir/avgvol.mnc
set CleanUpList = ($CleanUpList $avgvol);
rm -f $avgvol
set cmd = (mincaverage $mncinputlist $avgvol);
pwd >> $LF
echo $cmd >> $LF
$cmd |& tee -a $LF
if($status) then
  echo "ERROR: mincaverage failed" |& tee -a $LF
  exit 1;
endif

#----------- Convert Average to output ---------------#
echo "-----------------------------------------" |& tee -a $LF
echo "Converting Average to output " |& tee -a $LF
date |& tee -a $LF
set cmd = (mri_convert ${HiRes} $avgvol $outspec);
set cmd = ($cmd -tr $TR -te $TE -TI $TI -flip_angle $FlipAngle)
pwd >> $LF
echo $cmd >> $LF
$cmd |& tee -a $LF
if($status) then
  echo "ERROR: mri_convert failed" |& tee -a $LF
  exit 1;
endif

goto cleanup;
cleanup_return:

#---------------- end processing--------------------#
echo "Started at: $StartTime"    |& tee -a $LF
echo "Ended at:   `date`"        |& tee -a $LF
echo "mri_motion_correct2: done" |& tee -a $LF

exit 0;

################# subroutines #######################
#################             #######################

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

  set flag = $argv[1]; shift;

  switch($flag)

    case "-help"
    case "--help"
      set PrintHelp = 1;
      goto usage_exit;
      breaksw

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

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

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

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

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

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

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

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

    case "-wild":
      set AllowWild = 1;
      breaksw

    case "-cm":
      set HiRes = ('-cm')
      breaksw

    default:
      if($AllowWild) then
        set inputlist = ($inputlist $flag);
      else
        echo ERROR: Flag $flag unrecognized.
        echo $cmdline
        exit 1
      endif
      breaksw
  endsw

end

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

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

  if($#inputlist == 0) then
    echo "ERROR: no inputs specified"
    exit 1;
  endif

  if($#inputlist == 1) then
    echo "ERROR: only one input specified"
    exit 1;
  endif

  if($#outspec == 0) then
    echo "ERROR: no output specified"
    exit 1;
  endif

  set outfmt = `mri_info $outspec --format`
  if("$outfmt" == "unknown") set outfmt = "COR";

  if("$outfmt" == "COR") then
    set outdir = $outspec
    set outstem = $outspec/COR
  else
    set outdir = `dirname $outspec`;
    set outstem = `fname2stem $outspec`
    if($status) then
      echo "$outstem"
      exit 1;
    endif
  endif
  mkdir -p $outdir
  if($status) then
    echo "ERROR: cannot create $outdir"
    exit 1;
  endif

  # Go through each input, make sure it exists
  foreach i ($inputlist)
    mri_info $i > /dev/null
    if($status) then
      echo "ERROR: with $i"
      exit 1;
    endif
  end

  # Create the tmp directory and get full path
  if($#tmpdir == 0) then
    set tmpdir = $outdir/tmp-mri_motion_correct2-$$
  endif
  echo tmpdir is $tmpdir
  if($tmpdir != /tmp) then
    mkdir -p $tmpdir
    if($status) then
      echo "ERROR: cannot create $tmpdir"
      exit 1;
    endif
    pushd $tmpdir > /dev/null
    set tmpdir = `pwd`;
    popd > /dev/null
  endif

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

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


############--------------##################
cleanup:

  if($#CleanUp > 0) then
    foreach f ($CleanUpList)
      rm -f $f
    end
  endif

  rm -r $tmpdir

goto cleanup_return;
############--------------##################




############--------------##################
usage_exit:
  echo "USAGE: mri_motion_correct2"
  echo ""
  echo "Required Arguments:"
  echo ""
  echo "  -o  output spec : output file or directory (for COR)"
  echo "  -i  input1 <-i input2 <-i input3>>"
  echo ""
  echo "Optional Arguments:";
  echo ""
  echo "  -wild          : assume unmatched args are input files"
  echo "  -tmpdir tmpdir : directory for temporary files"
  echo "  -nocleanup     : do not delete temporary files"
  echo "  -umask umask   : set unix file permission mask"
  echo "  -cm            : COR volumes conform to min voxel size"
  echo "  -version       : print version and exit"
  echo "  -debug         : print lots of stuff to screen"
  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

Aligns and averages two or more volumes. Uses minctracc with -lsq6 to
perform the alignment. Then uses mincresample and mincaverage.

The inputs and output can be any format accepted by mri_convert.

Example 1:

mri_motion_correct2 -i 002.mgz  -i 003 -o mc4.img

  002.mgz is a volume in compressed MGH format.
  003 is in COR format.
  mc4.img (the output) is in analyze format.

Example 2:

Say you have many input volumes, eg, 001.mgh ... 010.mgh, and
you do not want to list all of them on the command-line with
a -i. Then you can:

mri_motion_correct2 -o mc.mgh  -wild *.mgh

Note that -wild must appear BEFORE the wildcard.
