#! /bin/tcsh -f

#
# lpcregister
#
# Original Author: Doug Greve
# CVS Revision Info:
#    $Author: greve $
#    $Date: 2009/05/14 23:00:37 $
#    $Revision: 1.4 $
#
# 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: lpcregister,v 1.4 2009/05/14 23:00:37 greve Exp $';
set inputargs = ($argv);

set subject = ();
set fsvol  = brainmask;
set refvol = ();
set movvol = ();
set debug = 0;
set tmpdir = ();
set cleanup = 1;
set PrintHelp = 0;
set frame = ();
set midframe = 0;
set nolog = 0;
set OutVol = ();
set DOF = 6;
set regfile = ();

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

goto parse_args;
parse_args_return:
goto check_params;
check_params_return:

if($#frame == 0) set frame = 0;

set movvoldir = `dirname $movvol`;
if($#tmpdir == 0) set tmpdir = $movvoldir/tmp.lpcreg.$$
mkdir -p $tmpdir

set regdir = `dirname $regfile`
mkdir -p $regdir

if(! $nolog) then
  pushd $regdir > /dev/null
  set LF = `pwd`/`basename $regfile`.log
  popd  > /dev/null
  if(-e $LF) mv $LF $LF.old
else
  set LF = /dev/null
endif

echo "Log file is $LF"

echo "Logfile for lpcregister" >> $LF
date |& tee -a $LF
echo $inputargs |& tee -a $LF
echo $VERSION |& tee -a $LF
which mri_convert |& tee -a $LF
which 3dcopy |& tee -a $LF
which align_epi_anat.py |& tee -a $LF
python -V |& tee -a $LF
csh --version |& tee -a $LF
uname -a |& tee -a $LF

set StartTime = `date`;

set DateString = "`date '+%y%m%d%H%M'`"
if(-e $regfile) mv $regfile $regfile.$DateString

# Use the rawavg as input (for testing only)
if($fsvol == rawavg.cor) then
  set refvol = $SUBJECTS_DIR/$subject/mri/$fsvol.mgz
  if(! -e $refvol) then
    # Does not exist, create
    set orig = $SUBJECTS_DIR/$subject/mri/orig.mgz
    set rawavg = $SUBJECTS_DIR/$subject/mri/rawavg.mgz
    set cmd = (mri_vol2vol --mov $rawavg --targ $orig --o $refvol \
     --no-save-reg --regheader)
    echo $cmd |& tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
    # Now mask it
    set brain = $SUBJECTS_DIR/$subject/mri/brainmask.mgz
    set cmd = (mri_mask $refvol $brain $refvol)
    echo $cmd |& tee -a $LF
    $cmd |& tee -a $LF
    if($status) exit 1;
  endif
endif

# First, Convert reference to NIFTI
set refvol = $SUBJECTS_DIR/$subject/mri/$fsvol.mgz
set refvolnii = $tmpdir/refvol.lpcreg.nii
set cmd = (mri_convert $refvol $refvolnii)
echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF
if($status) exit 1;

# Now, Convert reference from NIFTI to BRIK
set refvolbase = $tmpdir/refvol.lpcreg
set cmd = (3dcopy $refvolnii $refvolbase)
echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF
if($status) exit 1;

# Convert moveable to NIFTI
set movvolnii = $tmpdir/movvol.lpcreg.nii
set cmd = (mri_convert $movvol $movvolnii)
if($#frame) set cmd = ($cmd --frame $frame);
if($midframe) set cmd = ($cmd --mid-frame);
echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF
if($status) exit 1;

# Convert moveable to BRIK
set movvolbase = $tmpdir/movvol.lpcreg
set cmd = (3dcopy $movvolnii $movvolbase)
echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF
if($status) exit 1;

# Run lpc
pushd $tmpdir 
set AOpts = (-weight_frac 1.0 -maxrot 45 -maxshf 40 -VERB)
set cmd = (align_epi_anat.py -epi2anat)
#set cmd = ($cmd -epi_strip None)
#set cmd = ($cmd -partial_coverage)
if($fsvol == brainmask) set cmd = ($cmd -anat_has_skull no)
if($DOF == 3) then
  set cmd = ($cmd -Allineate_opts $AOpts -warp shift_only)
endif
if($DOF == 6) then
  set cmd = ($cmd -Allineate_opts $AOpts -warp shift_rotate)
endif
if($DOF == 9) then
  set cmd = ($cmd -Allineate_opts $AOpts -warp shift_rotate_scale)
endif
# Default is 12
set cmd = ($cmd -big_move -cmass cmass -AddEdge -epi2anat \
    -anat refvol.lpcreg+orig \
    -epi  movvol.lpcreg+orig -epi_base 0 )

echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF | tee cmd.align_epi_anat.py
if($status) exit 1;
popd

# This is the AFNI registration matrix
set mat = $movvolbase"_al_mat.aff12.1D"
if(! -e $mat) then
  echo "ERROR: cannot find $mat" |& tee -a $LF
  exit 1;
endif

# Reshape AFNI registration matrix to 4x4
set tmp = `cat $mat`;
set afnireg = $tmpdir/afnireg.mtx
rm -f $afnireg
echo $tmp[1-4]  >> $afnireg
echo $tmp[5-8]  >> $afnireg
echo $tmp[9-12] >> $afnireg
echo "0 0 0 1"  >> $afnireg

# Reshape AFNI ref vox2ras matrix to 4x4
set tmp = `grep -A 4 IJK_TO_DICOM $refvolbase+orig.HEAD | head -n 5 | tail -n 3`
set Aref = $tmpdir/Aref.mtx
rm -f $Aref
echo $tmp[1-4]  >> $Aref
echo $tmp[5-8]  >> $Aref
echo $tmp[9-12] >> $Aref
echo "0 0 0 1"  >> $Aref

# Reshape AFNI mov vox2ras matrix to 4x4
set tmp = `grep -A 4 IJK_TO_DICOM $movvolbase+orig.HEAD | head -n 5 | tail -n 3`
set Amov = $tmpdir/Amov.mtx
rm -f $Amov
echo $tmp[1-4]  >> $Amov
echo $tmp[5-8]  >> $Amov
echo $tmp[9-12] >> $Amov
echo "0 0 0 1"  >> $Amov

# Compute the vox2vox matrix
# Not really FSL matrix, just simple 4x4
set v2vmtx = $tmpdir/v2v.mtx
set cmd = (mri_matrix_multiply -fsl \
  -iim $Amov -im $afnireg -im $Aref \
  -om $v2vmtx)
echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF
if($status) exit 1;

# Get the tkreg vox2ras matrix for ref
set Tref = $tmpdir/Tref.mtx
set cmd = (mri_info --o $Tref --vox2ras-tkr $refvol )
echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF
if($status) exit 1;

# Get the tkreg vox2ras matrix for mov
set Tmov = $tmpdir/Tmov.mtx
set cmd = (mri_info --o $Tmov --vox2ras-tkr $movvol )
echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF
if($status) exit 1;

# Compute the tkreg matrix
# Not really FSL matrix, just simple 4x4
set tkrmtx = $tmpdir/tkr.mtx
set cmd = (mri_matrix_multiply -fsl \
  -im $Tmov -im $v2vmtx -iim $Tref \
  -om $tkrmtx)
echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF
if($status) exit 1;

# Create a tkreg matfile with the right format
set tmpreg = $tmpdir/reg.header.dat
set cmd = (tkregister2_cmdl --s $subject --mov $movvol \
           --regheader --noedit --reg $tmpreg \
           --targ $refvol);
echo "--------------------------------------" |& tee -a $LF
pwd        |& tee -a $LF
echo $cmd  |& tee -a $LF
$cmd       |& tee -a $LF
if($status) exit 1;

# Finally, create the register.dat
head -n 4 $tmpreg > $regfile
cat $tkrmtx >> $regfile

# Cleanup
if($cleanup) then
  echo "Cleaning up" |& tee -a $LF
  rm -r $tmpdir
endif

echo " " |& tee -a $LF
echo "Started at $StartTime " |& tee -a $LF
echo "Ended   at `date`" |& tee -a $LF
echo " " |& tee -a $LF
echo "lpcregister Done" |& tee -a $LF
echo " "

set tmp = ""
if(-e $SUBJECTS_DIR/$subject/surf/lh.orig) then
  set tmp = "--surf orig"
endif

echo "To check results, run:"
echo "tkregister2 --mov $movvol --reg $regfile $tmp"
echo " "


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

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

  set flag = $argv[1]; shift;

  switch($flag)

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

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

    case "--3":
      set DOF = 3;
      breaksw

    case "--6":
      # Default
      set DOF = 6;
      breaksw

    case "--9":
      set DOF = 9;
      breaksw

    case "--12":
      set DOF = 12;
      breaksw

    case "--rawavg":
      set fsvol = rawavg.cor;
      breaksw

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

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

    case "--mid-frame":
      set midframe = 1;
      breaksw

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

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

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

    case "--s-from-reg":
      if( $#argv < 1) goto arg1err;
      set tmp = $argv[1]; shift;
      set subject = `head -n 1 $tmp`
      breaksw

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

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

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

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

end

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

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

  if($#subject == 0) then
    echo "ERROR: must spec a subject id"
    exit 1;
  endif
  if(! -e $SUBJECTS_DIR/$subject) then
    echo "ERROR: cannot find $subject in $SUBJECTS_DIR"
    exit 1;
  endif

  if($#movvol == 0) then
    echo "ERROR: must spec an mov vol"
    exit 1;
  endif

  if($#regfile == 0) then
    echo "ERROR: must spec an output reg file"
    exit 1;
  endif

  if($#frame && $midframe) then
    echo "ERROR: cannot --frame AND --mid-frame"
    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: lpcregister"
  echo ""
  echo "Required Arguments:";
  echo "   --s subject"
  echo "   --mov volid  : input/movable volume"
  echo "   --reg register.dat"
  echo ""
  echo "Optional Arguments"
  echo "   --9  :  9 dof (default is 6)"
  echo "   --12 : 12 dof (default is 6)"
  echo "   --frame frameno : reg to frameno (default 0=1st)"
  echo "   --mid-frame : reg to middle frame (not with --frame)"
  echo "   --fsvol volid : use FreeSurfer volid (default $fsvol)"
  echo "   --o outvol : resample mov and save as outvol"
  echo ""
  echo "   --tmp tmpdir  : temporary dir (implies --nocleanup)"
  echo "   --nocleanup  : do not delete temporary files"
  echo "   --version : print version and exit"
  echo "   --help    : print help and exit"
  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

Not tested yet!

Registers a volume to its FreeSurfer anatomical using Local Pearson
Correlation (LPC) (the AFNI lpc_align.py program).  creates a
FreeSurfer register.dat file. Does not resample unless --o.

--s subject

Id of the subject as found in SUBJECTS_DIR. The reference volume is
the mri/brain volume (this can be changed with --fsvol). This is
converted to analyze using mri_convert.

--mov volid

Volume identifier of the movable volume. This must be specified in
a way suitable for mri_convert. Uses first frame unless --frame
is specified. For this to work correctly, the movable volume must
have correct geometry information (eg, a valid SPM-style .mat file)
otherwise the results may be unpredictable.

--reg regfile

Output registration file. This will map RAS in the reference to
RAS in the movable. This file/matrix is in a format understood
by freesurfer (see tkregister2 --help for docs). It will contain
the subjectname.

--frame frameno

Use something other than the first frame. Eg, FSL uses the the middle
frame (see --mid-frame). For SPM analyze, you should specify the file
that corresonds to the frame you want because each file only has one
frame.

--mid-frame

Use the middle frame of the mov volume as the template.

SEE ALSO: tkregister2, mri_vol2surf, mri_convert, mri_rigid_register,
fsl_rigid_register, spm_coreg.m.


