#!/usr/local/bin/perl
##-------------------------------------------------------------------------
## 
## rel2abs -- Merge ADCP relative currents with ship velocity
## 
## Author          : Pierre Jaccard
## Created On      : 1999/08/06 12:13:58
## Last Modified By: Pierre Jaccard
## Last Modified On: 1999/08/10 18:48:50
## Update Count    : 24
## Directory       : /home/pego/pcd1/codas3c/gfi/bin/perl/
## Version         : 0.0
## Status          : Unknown
## --------------------------------------------------------------------- ++
## DESCRIPTION: 
## 
##    See separate documentation.
## 
## --------------------------------------------------------------------- ++
## REVISIONS: 
## --------------------------------------------------------------------- ++
## CHANGES: 
##-------------------------------------------------------------------------

BEGIN{
  use vars qw($GFILIBDIR);
  $GFILIBDIR = "$ENV{'CODASHOME'}/gfi/lib/perl";
};

#------------------------------------------------------------------
# Modules:
#------------------------------------------------------------------

use strict;
use Carp;
use Getopt::Std;
use FileHandle;

select(STDOUT); $| = 1;

#------------------------------------------------------------------
# Global variables
#------------------------------------------------------------------

use vars qw($BAD $ADJ_BAD);

$ADJ_BAD = 1.0e37;
$BAD     = 1.0E38;

#------------------------------------------------------------------
# File Variables:
#------------------------------------------------------------------

my(%OPTS);

my($FMT, $SEP, $BADPRF, $BADSTR) = ('%15.6f', ' ', 0, "1.0E38");

$BADPRF = ' ' x (length( sprintf $FMT, 1.0 ) - length($BADSTR));

#------------------------------------------------------------------
# GFI Modules:
#------------------------------------------------------------------

use lib "$GFILIBDIR";
use gfimisc;
use gfimath;

#------------------------------------------------------------------
# Options:
#------------------------------------------------------------------

getopts('c:f:o:C:', \%OPTS);

#--- Defaults Options:
confess("\nMissing input file with ship velocities (option -f).\n\n")
  unless($OPTS{'f'});

$OPTS{'o'} = '-' unless($OPTS{'o'});
$OPTS{'c'} = '1,2,3'     unless($OPTS{'c'});
$OPTS{'C'} = '1,2,3'   unless($OPTS{'C'});

#--- Process column specifications:
$OPTS{'C'} = [ gfimisc_lst2arr($OPTS{'C'}) ];
$OPTS{'c'} = [ gfimisc_lst2arr($OPTS{'c'}) ];

#--- Check arguments:
@ARGV = ( '-' ) unless(@ARGV);

#------------------------------------------------------------------
# MAIN:
#------------------------------------------------------------------

my($fh_out, @x, @ship, $con);

$fh_out = new FileHandle "> $OPTS{'o'}";
confess("\nOpening output file $OPTS{'o'}\n") unless(defined $fh_out);

#--- Get all ship data:
{
  my($fh, $x, $ship);

  @ship = ();

  $fh = new FileHandle "< $OPTS{'f'}";
  confess("\nOpening input file $OPTS{'f'}\n") unless(defined $fh);
  ($x, $ship) = get_all_data($fh, $OPTS{'c'});
  @x = @{$x};
  @ship = @{$ship};
  $fh->close() || confess("\nClosing input file $OPTS{'f'}\n");
}

#--- Loop through input files:
foreach $con (@ARGV){
    
  my($fh, @X, %ship, $data);
    
  $fh = new FileHandle "< $con";
  confess("\nOpening input file $con\n") unless(defined $fh);
    
  #--- Get all X-data:
  @X  = get_X_data($fh, $OPTS{'C'});
  seek($fh, 0, 0) || confess("\nReseting input file $con\n"); 

  #--- Interpolate positions to X-data:
  %ship = gfimath_interpolate(\@X, \@x, \@ship);

  #--- Loop through input file:
  while($data = <$fh>){
    chomp;
      
    my($n, @data, $iX, $iU, $iV, $X, $U, $V, $u, $v, $str, $i);

    #--- NOTE: the first column in the list of columns must point to the
    #          X-data.  
    $n = @data = gfimisc_get_data($data);
    next unless($n);
    ($iX, $iU, $iV) = @{$OPTS{'C'}};
    ($X, $U, $V) = @data[@{$OPTS{'C'}}];
    next unless($X < $ADJ_BAD);
      
    #--- Get inpterpolated data
    ($u, $v) = @{$ship{$X}};
    $U = $BAD unless($u < $ADJ_BAD);
    $V = $BAD unless($v < $ADJ_BAD);
    @data[($iU, $iV)] = ($U, $V);

    #--- Prepare output string:
    $str = '';
    for($i=0; $i<$n; $i++){
      if($data[$i] < $ADJ_BAD){
        $data[$i] += $u if($i == $iU);
        $data[$i] += $v if($i == $iV);
        $str = $str . sprintf $FMT, $data[$i];
      }else{
        $str = $str . $BADPRF . $BADSTR;
      }
      $str = $str . $SEP;
    }
      
    #--- Print the new line:
    print $fh_out "$str\n";

  }
  
  $fh->close() || confess("\nClosing input file $con\n");
}

$fh_out->close() || confess("\nClosing output file $OPTS{'o'}\n");

exit(0);

#------------------------------------------------------------------
# NOTE: the first column in the list of columns must point to the
#       x-data.
#------------------------------------------------------------------

sub get_all_data {

  my(%data, $data, @data, %n, $n, $i, $k, $j, @x);

  my($fh, $cols) = @_ ;
  
  #--- Initializations:
  %data = %n = ();

  #--- Loop through file:
  while($data = <$fh>){
    chomp;

    #--- Get next input line:
    $n = @data = gfimisc_get_data($data, $cols);
    next unless($n);

    #--- Key to x-data:
    $k = $data[0];
    next unless($k < $ADJ_BAD);

    #--- Update data array:
    shift(@data);
    $n--; 
    next unless(($data[0] < $ADJ_BAD) && ($data[1] < $ADJ_BAD));

    #--- Initialize statistics:
    unless(exists $data{$k}){
      for($i=0; $i<$n; $i++){
        $data{$k}->[$i] = $n{$k}->[$i] = 0.0;
      }
    }
    
    #--- Update statistics:
    for($i=0; $i<$n; $i++){
      if($data[$i] < $ADJ_BAD){
        $data{$k}->[$i] += $data[$i];
        $n{$k}->[$i] += 1;
      }
    }
  }
  
  #--- Calculate statistics:
  foreach $k (keys %data){
    $n = @{$data{$k}};
    for($i=0; $i<$n; $i++){
      $data{$k}->[$i] = $BAD unless($n{$k}->[$i] > 0);
      $data{$k}->[$i] /= $n{$k}->[$i] if($data{$k}->[$i] < $ADJ_BAD);
    }
  }
    
  #--- Rebuild a sorted output array:
  @data = ();
  @x = sort { $a <=> $b } keys %data;
  for($j=0; $j<(@x); $j++){
    $k = $x[$j];
    $n = @{$data{$k}};
    $data[$j] = ();
    for($i=0; $i<$n; $i++){
      $data[$j]->[$i] = $data{$k}->[$i];
    }
  }
  
  return(\@x, \@data);
};

#------------------------------------------------------------------
# NOTE: the first element must point to the X-data
#------------------------------------------------------------------

sub get_X_data {

  my($data, @data, $n, %data, @cols);

  my($fh, $cols) = @_ ;
  
  @cols = ($cols->[0]);

  while($data = <$fh>){
    chomp;

    #--- Get next input line:
    $n = @data = gfimisc_get_data($data, \@cols);
    next unless($n);
    next unless($data[0] < $ADJ_BAD);
    
    $data{$data[0]}++;
  }
  
  @data = sort { $a <=> $b } (keys %data);

  return(@data);
};



1;
