#!/usr/bin/perl -w
#3dPARtoANALYZE  somefile.par

# This file is a modified version of this file
# http://www.cdfi.uab.edu/cdfi/Documents/6740FF06-1993-4EAE-8CF7-18CBCA3D78B6.html

use strict;
use Getopt::Std;
use Cwd;

my %Options = ();
my $ok = getopts("hsnvg24o:a", \%Options);

sub usage(){

  print "3dPAR2ANFI\n";
  print "Command line Options:\n";
  print "-h     This help message.\n";
  print "-v     Be verbose in operation.\n";
  print "-s     Skip the outliers test when converting 4D files\n";
  print "       The default is to perform the outliers test.\n";
  print "-n     Output NIfTI files instead of HEAD/BRIK.\n";
  print "       The default is create HEAD/BRIK files.\n";
  print "-a     Output ANALYZE files instead of HEAD/BRIK.\n";
  print "-o     The name of the directory where the created files should be\n";
  print "       placed.  If this directory does not exist the program exits\n";
  print "       without performing any conversion.\n";
  print "       The default is to place created files in the same directory\n";
  print "       as the PAR files.\n";
  print "-g     Gzip the files created.\n";
  print "       The default is not to gzip the files.\n";
  print "-2     2-Byte-swap the files created.\n";
  print "       The default is not to 2 byte-swap.\n";
  print "-4     4-Byte-swap the files created.\n";
  print "       The default is not to 4 byte-swap.\n\n";

  print "Sample invocations:\n";
  print "3dPAR2AFNI subject1.PAR\n";
  print "       Converts the subject1.PAR file to subject1+orig.{HEAD,BRIK}\n";
  print "3dPAR2AFNI -s subject1.PAR\n";
  print "       Same as above but skip the outlier test\n";
  print "3dPAR2AFNI -n subject1.PAR\n";
  print "       Converts the file subject1.PAR file to subject1.nii\n";
  print "3dPAR2AFNI -n -s subject1.PAR\n";
  print "       Same as above but skip the outlier test\n";
  print "3dPAR2AFNI -n -s -o ~/tmp subject1.PAR\n";
  print "       Same as above but skip the outlier test and place the\n";
  print "       created NIfTI files in ~/tmp\n";
  print "3dPAR2AFNI -n -s -o ~/tmp *.PAR\n";
  print "       Converts all the PAR/REC files in the current directory to\n";
  print "       NIfTI files, skip the outlier test and place the created\n";
  print "       NIfTI files in ~/tmp\n";

  exit;
}

sub convertPar($) {
  $,=" ";
  $\="\n";
  my $verbose = $Options{"v"};
  my $skipOutliers = $Options{"s"};
  my $nifti = $Options{"n"};
  my $analyze = $Options{"a"};
  my $gzip =  $Options{"g"};
  my $twoSwap =  $Options{"2"};
  my $fourSwap =  $Options{"4"};
  my $outputDirectory =  $Options{"o"};
  my $outliers="";
  my $parFile = shift;
  my ($rootname, $extension, %fov, %angulation, %origin, $slices, $tr, $volumes, $bitdepth, %reconres, $prefixargs);
  my ($timeargs, $totalslices, $anterior, $posterior, $foot, $head, $right, $left, $FOVargs, $filespec, $session);

  if ($outputDirectory){
    if ( ! -d $outputDirectory ) {
      print "$outputDirectory does not exist. Exiting!\n";
      exit;
    }
    $outputDirectory = Cwd::abs_path($outputDirectory);
  }

  if ($verbose) {
    print "Skipping outliers test\nOutput file will be NIfTI format\n";
  }

  if ($parFile =~ /([A-Za-z_0-9]+)\.([Pp][Aa][Rr])$/) {
    $rootname=$1;
    $extension=$2;
  }

  # parse PAR file.
  my $lineCount=0;

  open(PFH, $parFile) || die "Unable to open $parFile for reading: $!.\n";
  my @buffer = ();

  while (<PFH>) {
    chomp;                      # strip record separator

    push (@buffer, $_);
    if ($#buffer > 2){
      shift @buffer;
    }

    if ($lineCount <= 91 ) {
      # file version
      if (/# CLINICAL TRYOUT             Research image export tool     V([0-9])/) {
        my $fileVersion = $1;
        if ($fileVersion != 4 ) {
          print "This program can only handle Version 4 PAR/REC files. Exiting.";
          exit;
        }
      }

      # field of view
      if (/FOV \((..),(..),(..)\) \[.*\].*:\ *([0-9]+\.[0-9]+)\ *([0-9]+\.[0-9]+)\ *([0-9]+\.[0-9]+)/) {
        $fov{$1}=$4;
        $fov{$2}=$5;
        $fov{$3}=$6;
      }
      # matrix size

      # angulation
      if (/Angulation midslice\((..),(..),(..)\)\[.*\].*:\ *(-?[0-9]+\.[0-9]+)\ *(-?[0-9]+\.[0-9]+)\ *(-?[0-9]+\.[0-9]+)/) {
        $angulation{$1}=$4;
        $angulation{$2}=$5;
        $angulation{$3}=$6;
      }
      # distance from origin of FOV center
      if (/Off Centre midslice\((..),(..),(..)\) \[.*\].*:\ *(-?[0-9]+\.[0-9]+)\ *(-?[0-9]+\.[0-9]+)\ *(-?[0-9]+\.[0-9]+)/) {
        $origin{$1}=$4;
        $origin{$2}=$5;
        $origin{$3}=$6;
      }

      # number of slices
      if (/number of slices.*:\ *([0-9]+)/) {
        $slices=$1;
      }

      # TR
      if (/Repetition time.*:\ *([0-9]+\.[0-9]+)/) {
        $tr=$1;
      }
      # number of volumes
      if (/number of dynamics.*:\ *([0-9]+)/) {
        $volumes=$1;
      }

      if (/\s*[0-9]*\s*[0-9]*\s*[0-9]*\s*[0-9]*\s*[0-9]*\s*[0-9]*\s*[0-9]*\s*([0-9]*)\s*[0-9]*\s*([0-9]*)\s*([0-9]*).*/) {
        $bitdepth=$1;
        $reconres{"x"}=$2;
        $reconres{"y"}=$3;
      }
    }
    $lineCount++;
  } # end of while (<PFH>)

  if (shift(@buffer) =~ /\s*[0-9]*\s*[0-9]*\s*[0-9]*\s*[0-9]*\s*[0-9]*\s*[0-9]*\s*([0-9]*).*/){
    my $numberOfImages = $1 + 1;
    if ($verbose) {
      print "*** Number of images is $numberOfImages";
    }

    if ($numberOfImages / $slices != $volumes) {
      print "*** WARNING: The number of volumes from the PAR header does not match the number of slices times the number of images!";
      $volumes = $numberOfImages / $slices;
      print "*** WARNING: Resetting the number of volumes to be the number of slices times the number of images ($volumes).";
    }
  }

  close(PFH);

  if ($verbose) {
    print "$rootname.$extension";
    print "** Field of View ***";
    print "ap=$fov{ap}";
    print "fh=$fov{fh}";
    print "rl=$fov{rl}";
    print "*** Reconstruction Matrix ***";
    print "x=$reconres{x}";
    print "y=$reconres{y}";
    print "*** Angulation ***";
    print "ap=$angulation{ap}";
    print "fh=$angulation{fh}";
    print "rl=$angulation{rl}";
    print "*** Origin ***";
    print "ap=$origin{ap}";
    print "fh=$origin{fh}";
    print "rl=$origin{rl}";
    print "*** Slices = $slices ***";
    print "*** Bit Depth = $bitdepth ***";
    print "*** TR = $tr ***";
  }

  # -----------calculate values and args for AFNI to3d to convert REC file
  #
  if ($outputDirectory) {
    $session = "-session $outputDirectory/";
  }
  else {
    $session = "";
  }

  if ($nifti) {
    $prefixargs = "-prefix $rootname.nii";
  }
  else {
    $prefixargs = "-prefix $rootname";
  }

  my $swap = "";
  if ($twoSwap) {
    $swap = "-2swap";
  }
  elsif ($fourSwap) {
    $swap = "-4swap";
  }

  # generate time args for func or anat
  $timeargs = "";
  $totalslices = $slices;

  if ($volumes > 1) {
    if ($verbose) {
      print "$volumes timepoints";
    }
    $timeargs = "-time:tz $volumes $slices ${tr}ms zero";
    #    $timeargs = "-time:zt $slices $volumes ${tr}ms zero";
    $totalslices=$volumes*$slices;
    if ($skipOutliers) {
      $outliers="-skip_outliers";
    }
  }

  #calculate FOV args
  $anterior = abs($origin{ap}-$fov{ap}/2);
  $posterior= abs($origin{ap}+$fov{ap}/2);
  $foot     = abs($origin{fh}-$fov{fh}/2);
  $head     = abs($origin{fh}+$fov{fh}/2);
  $right    = abs($origin{rl}-$fov{rl}/2);
  $left     = abs($origin{rl}+$fov{rl}/2);

  $FOVargs = "-xFOV ${right}R-${left}L -yFOV ${anterior}A-${posterior}P -zFOV ${foot}I-${head}S";

  #file specification
  my $recextension="rec";
  if ($extension =~ /PAR/) {
    $recextension="REC";
  }
  $filespec = "3D:-1:0:$reconres{x}:$reconres{y}:$totalslices:$rootname.$recextension";
  my $fileSize = -s "$rootname.$recextension";

  if ( $fileSize > 0 ) {
    # to3d command
    print my $command="to3d $session $swap $outliers $prefixargs $timeargs $FOVargs $filespec";
    system $command;
    if ($analyze) {
        print my $command="3dAFNItoANALYZE $rootname $rootname+orig.HEAD";
        system $command;
        print $command="rm -f  $rootname+orig.{HEAD,BRIK}";
        system $command;
    }
    if ($gzip) {
      if ($nifti) {
        $command="gzip -9v $rootname.nii";
      }
      elsif ($analyze) {
        $command="gzip -9v $rootname.img";
      }
      else {
        $command="gzip -9v $rootname+orig.BRIK";
      }
      print $command;
      system $command;
    }
  }
  else {
    print "Skipping $parFile: The corresponding REC file is 0 bytes in length\n";

  }
}

sub main() {
  my $argCount = $#ARGV + 1;
  usage() if $Options{"h"} or $argCount < 1;

  foreach my $parFile (@ARGV) {
    convertPar($parFile);
  }
}

main();


syntax highlighted by Code2HTML, v. 0.9.1