#!/bin/tcsh -fe

set retval = 0   # return a status (do we need to goto END?)

PARSE:
   set Narg = $#
   set cnt = 1
   set v1_list = ""
   set v2i = ""
   set v1i = ""
   set usecp = 1
   set xmat_only = 0
   set xmat_only_meanit = 0  # really don't make new dsets
 
   set mode = 'grid'
   set cm_amask = '-automask' # -automask or ''     6 Nov 2015 [rickr]
   set overw = 0
   set overf = ''
   if ("$1" == '') goto HELP
   while ($cnt <= $Narg)
      set donext = 1

      if ($donext && "$argv[$cnt]" == "-echo") then
         set echo
         set donext = 0 
      endif
      
      if ($donext && "$argv[$cnt]" == "-help" || "$argv[$cnt]" == "-h") then
         goto HELP
      endif

      if ($donext && "$argv[$cnt]" == "-base") then
         set pLoc = $cnt      
         if ($pLoc == $Narg) then
            echo "Need string after -base"
            set retval = 1
            goto END
         else
            @ cnt ++
            set v2i = "$argv[$cnt]"
            set donext = 0   
         endif   
      endif

      if ($donext && "$argv[$cnt]" == "-overwrite") then
         set overw = 1
         set overf = ' -overwrite '
         set donext = 0   
      endif
      
      if ($donext && "$argv[$cnt]" == "-cm") then
         set mode = 'cm'
         set donext = 0   
      endif
      if ($donext && "$argv[$cnt]" == "-cm_no_amask") then
         set mode = 'cm'
         set cm_amask = ''
         set donext = 0   
      endif
      if ($donext && "$argv[$cnt]" == "-grid") then
         set mode = 'grid'
         set donext = 0   
      endif
      if ($donext && "$argv[$cnt]" == "-no_cp") then
         set usecp = 0
         set donext = 0   
      endif
      
      if ($donext && "$argv[$cnt]" == "-1Dmat_only") then
         set xmat_only = 1
         set donext = 0   
      endif

      if ($donext && "$argv[$cnt]" == "-1Dmat_only_nodset") then
         set xmat_only = 1
         set xmat_only_meanit = 1
         set donext = 0   
      endif
      
      if ($donext && "$argv[$cnt]" == "-dset") then
         set pLoc = $cnt      
         if ($pLoc >= $Narg) then
            echo "Need dset after -dset"
            set retval = 1
            goto END
         else
            @ cnt ++
            set v1i = ($argv[$cnt])
            set donext = 0   
         endif   
      endif
      if ($donext && "$argv[$cnt]" == "-child") then
         set pLoc = $cnt      
         if ($pLoc == $Narg) then
            echo "Need dsets after -child"
            set retval = 1
            goto END
         else
            @ cnt ++
            set v1_list = ($argv[$cnt-])
            set nv1 = $#v1_list
            set cnt = `expr $cnt + $nv1 - 1`
            set donext = 0   
         endif   
      endif
      if ($donext == 1) then
         echo "Error: Option or parameter '$argv[$cnt]' not understood"
            set retval = 1
         goto END
      endif
      @ cnt ++
   end

if ("$v1i" == "" || "$v2i" == "") then
   echo "Error: Missing input"
            set retval = 1
   goto END
endif   

SET_PARAMS: 
set v2_vw = `@GetAfniView $v2i`
set pth2 = $v2i:h
if ("$pth2" == "$v2i") then 

   set pth2 = .

   # allow for template datasets in path, etc.  24 Apr 2011 [rickr]
   # We execute with -e, and @FADP may exit with 1 if the dataset is
   # not found.  So to fail here instead, put it in the background.

   set test_path = `@FindAfniDsetPath $v2i &`
   if ( $#test_path == 1 && "$test_path" != "./" ) then
      set pth2 = $test_path
   endif
endif

set v2_pref = `@GetAfniPrefix $v2i`
set v2 = $pth2/$v2_pref$v2_vw
 
CHECKS:
#make sure input exists
if ( `@CheckForAfniDset $v2` < 2) then
   echo "Error: base brick $v2 not found."
   set retval = 1
   goto END
endif

SETCENTER:
   set v1_vw = `@GetAfniView $v1i`
   set v1_pth = $v1i:h
   if ("$v1_pth" == "$v1i") then 
      set v1_pth = .
   endif

   set v1_pref = `@GetAfniPrefix $v1i`
   set v1 = $v1_pth/$v1_pref$v1_vw
   set oname = `ParseName -app _shft  -out PrefixView $v1`

if ($mode == 'grid') then
   #orientation of v1
   set v1_orient = `@GetAfniOrient $v1`
   #center of v1, in native orientation
   set v1_center = `@VolCenter -dset $v1`
   #center of v2, in v1's orientation
   set v2_center_v1or = `@VolCenter -dset $v2 -or $v1_orient`
   #calculate deltas
   set del = ( 0 0 0 )
   foreach i (1 2 3)
      set del[$i] = `ccalc -eval "$v2_center_v1or[$i] - $v1_center[$i]"`
   end
   
   #get delta in RAI 
   #echo "del: $del"
   set del_RAI = `@ToRAI -xyz $del -or $v1_orient`
   #echo "del_RAI: $del_RAI"
   
   
   #multiply deltas by axis signs
   set mp = `@AfniOrientSign $v1_orient`
   set del_refit = ($del)
   foreach i ( 1 2 3)
         # changed to form double  RR/DG  24 Mar 2008
         set del_refit[$i] = `ccalc -form d -expr "$mp[$i] * $del[$i]"`
   end
   #apply delta
   if ($usecp == 1) then
      
      if ($xmat_only_meanit != 1) then
         if ( $overw == 0 && `@CheckForAfniDset $v1_pth/$oname` != 0 ) then
            echo ""
            echo "Error `basename $0`"
            echo "Dset $v1_pth/$oname found, cleanup first!"
            echo ""
            set retval = 1
            goto END
         endif

         3dcopy $overf $v1  $v1_pth/$oname
         3drefit  -dxorigin $del_refit[1] \
                  -dyorigin $del_refit[2] \
                  -dzorigin $del_refit[3] $v1_pth/$oname
      endif
   else
      if ($xmat_only_meanit != 1) then
          3drefit  -dxorigin $del_refit[1] \
               -dyorigin $del_refit[2] -dzorigin $del_refit[3] $v1
      endif
   endif
else
   
   #get the center of mass of the base and apply delta
   set v2_center_RAI = `3dCM $cm_amask $v2i`
   if ($usecp == 1) then
      if ( $overw == 0 && `@CheckForAfniDset $v1_pth/$oname` != 0 ) then
         echo ""
         echo "Error `basename $0`"
         echo "Dset $v1_pth/$oname found, cleanup first!"
         echo ""
         set retval = 1
         goto END
      endif

      if ($xmat_only_meanit != 1) then
         3dcopy $overf $v1  $v1_pth/$oname
         set v1_center_RAI = `3dCM $cm_amask -set $v2_center_RAI \
                              $v1_pth/$oname`
      endif
   else
      if ($xmat_only_meanit != 1) then
         set v1_center_RAI = `3dCM $cm_amask -set $v2_center_RAI $v1`
      endif
   endif
   
   set del_RAI = ( 0 0 0 )
   foreach i (1 2 3)
      set del_RAI[$i] = `ccalc -eval "$v2_center_RAI[$i] - $v1_center_RAI[$i]"`
   end
   echo base: $v2_center_RAI
   echo dset: $v1_center_RAI
   echo delta: $del_RAI
endif   

DELTA_TO_XMAT:
   #Output xform matrix for allineating
   set del_xform = ()
   foreach delx ($del_RAI)
      set del_xform = ($del_xform `ccalc -eval "$delx * -1"`)
   end
   set oname = `ParseName -app _shft  -out Prefix $v1`
   #get rid of .nii which remains in prefix
   set o1d = `ParseName -out FNameNoAfniExt $oname`
   echo "1 0 0 $del_xform[1] 0 1 0 $del_xform[2] 0 0 1 $del_xform[3]" \
         > ${o1d}.1D
   if ($xmat_only == 1) then
      goto END
   else
      #echo "Proceeding..."
   endif

   
SETCHILDREN:
foreach v1foli ( $v1_list )
   set v1fol_vw = `@GetAfniView $v1foli`
   set v1fol_pth = $v1foli:h
   if ("$v1fol_pth" == "$v1foli") then 
      set v1fol_pth = .
   endif

   set v1fol_pref = `@GetAfniPrefix $v1foli`
   set v1fol = $v1fol_pth/$v1fol_pref$v1fol_vw

   if ("`@GetAfniID $v1fol`" != "`@GetAfniID $v1i`" && \
       "`@GetAfniID $v1fol`" != "`@GetAfniID $v2i`") then
      #orientation of v1fol
      set v1fol_orient = `@GetAfniOrient $v1fol`
      #change del_RAI to v1fol_orient
      set del = `@FromRAI -xyz $del_RAI -or $v1fol_orient`
      echo $del

      #multiply deltas by axis signs         (changed from v1_orient  DG/RR)
      set mp = `@AfniOrientSign $v1fol_orient` 
      set del_refit = ($del)
      foreach i ( 1 2 3)
            # changed to form double
            set del_refit[$i] = `ccalc -form d -expr "$mp[$i] * $del[$i]"`
      end

      #apply the  delta
      set oname = `ParseName -app _shft  -out PrefixView ${v1fol_pref}${v1fol_vw}`
      if ($usecp == 1) then
         if ( `@CheckForAfniDset $v1fol_pth/${oname}` != 0 ) then
            echo ""
            echo "Error `basename $0`"
            echo "Child Dset $v1fol_pth/${oname} found, cleanup first!"
            echo ""
            set retval = 1
            goto END
         endif
         3dcopy $overf $v1fol  $v1fol_pth/${oname}
         3drefit  -dxorigin $del_refit[1] \
                  -dyorigin $del_refit[2] \
                  -dzorigin $del_refit[3] $v1fol_pth/${oname}
      else   
         3drefit  -dxorigin $del_refit[1] \
                  -dyorigin $del_refit[2] \
                  -dzorigin $del_refit[3] $v1fol
      endif
   else
      echo "Child dset $v1fol is same as $v1i or $v2i, skipping it."
   endif
end   

goto END  


HELP:
   echo ""
   echo "Usage: `basename $0` <-base BASE> <-dset DSET> [-no_cp] "
   echo "                     [-child CHILD_2 ... CHILD_N] [-echo]"
   echo ""
   echo "   Moves the center of DSET to the center of BASE."
   echo "   By default, center refers to the center of the volume's voxel grid."
   echo "   Use -cm to use the brain's center of mass instead."
   echo ""
   echo "   AND/OR creates the transform matrix XFORM.1D needed for this shift."
   echo "   The transform can be used with 3dAllineate's -1Dmatrix_apply "
   echo "      3dAllineate   -1Dmatrix_apply XFORM.1D    \"
   echo "                    -prefix PREFIX -master BASE \"
   echo "                    -input DSET"
   echo ""
   echo "   -echo: Echo all commands to terminal for debugging"
   echo "   -overwrite: You know what"
   echo "   -1Dmat_only: Only output the transfrom needed to align"
   echo "                the centers. Do not shift any child volumes."
   echo "                The transform is named DSET_shft.1D"
   echo "   -1Dmat_only_nodset: Like above, but no dsets at all"
   echo "                are created or changed."
   echo "   -base BASE: Base volume, typically a template."
   echo "   -dset DSET: Typically an anatomical dset to be"
   echo "               aligned to BASE."
   echo "   -child CHILD_'*': A bunch of datasets, originally"
   echo "                     in register with DSET, that"
   echo "                     should be shifted in the same"
   echo "                     way."
   echo "   -no_cp: Do not create new data, shift existing ones"
   echo "           This is a good option if you know what you "
   echo "           are doing. It will save you a lot of space."
   echo "           See NOTE below before using it."
   echo ""
   echo "    DSET and CHILD_'*' are typically all the datasets "
   echo "    from a particular scanning session that"
   echo "    you want to eventually align to BASE."
   echo "    Such an operation is needed when DSET and CHILD_'*'"
   echo "    overlap very little, if at all with BASE"
   echo ""
   echo " Note that you can specify *.HEAD for the children even "
   echo " if the wildcard substitution would contain DSET "
   echo " and possibly even BASE. The script will not process"
   echo " a dataset twice in one execution."
   echo ""
   echo " Center options:"
   echo "   -grid: (default) Center is that of the volume's grid"
   echo "   -cm : Center is the center of mass of the volume."
   echo "   -cm_no_amask : Implies -cm, but with no -automask."
   echo "" 
   echo ""
   echo "   See also @Center_Distance"
   echo ""
   echo " NOTE: Running the script multiple times on the same data"
   echo "       will cause a lot of trouble. That is why the default"
   echo "       is to create new datasets as opposed to shifting the"
   echo "       existing ones. Do not use -no_cp unless you know what"
   echo "       you are doing."
   echo "       To undo errors caused by repeated executions"
   echo "       look at the history of each dset and undo"
   echo "       the excess 3drefit operations."
   echo ""
   echo "Requires 3drefit newer than Oct. 02/02."
   echo ""
   echo "Ziad Saad (saadz@mail.nih.gov)"
   echo "SSCC/NIMH/ National Institutes of Health, Bethesda Maryland"
   echo ""
   goto END


goto END

 
END:

exit $retval
