#!/usr/local/bin/perl 
##-------------------------------------------------------------------------
## 
## con2con -- Convert contour file
## 
## Author          : Pierre Jaccard
## Created On      : 1999/08/03 21:46:27
## Last Modified By: Pierre Jaccard
## Last Modified On: 1999/08/10 18:50:02
## Update Count    : 109
## Directory       : /home/pego/pcd1/codas3c/gfi/bin/perl/
## Version         : 0.0
## Status          : Unknown
## --------------------------------------------------------------------- ++
## DESCRIPTION: 
## 
##    See separate manual page.
## 
## --------------------------------------------------------------------- ++
## 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:i:o:x:C:X:', \%OPTS);

#--- Defaults Options:
$OPTS{'o'} = '-'         unless($OPTS{'o'});
if($OPTS{'f'}){
  $OPTS{'c'} = '2,3'     unless($OPTS{'c'});
  $OPTS{'i'} = 2         unless($OPTS{'i'});
  $OPTS{'x'} = '1'       unless($OPTS{'x'});
  $OPTS{'C'} = '1,2,3'   unless($OPTS{'C'});
  $OPTS{'X'} = '1'       unless($OPTS{'X'});
}else{
  $OPTS{'c'} = '';
  $OPTS{'i'} = 0 ;
  $OPTS{'x'} = '';
  $OPTS{'C'} = '1,4,5'   unless($OPTS{'C'});
  $OPTS{'X'} = '';
}

#--- Process column specifications:
$OPTS{'C'} = $OPTS{'X'} . ',' . $OPTS{'C'};
$OPTS{'C'} = [ gfimisc_lst2arr($OPTS{'C'}) ];
$OPTS{'c'} = $OPTS{'x'} . ',' . $OPTS{'c'};
$OPTS{'c'} = [ gfimisc_lst2arr($OPTS{'c'}) ];
$OPTS{'i'} -= 1;
$OPTS{'x'} = [ gfimisc_lst2arr($OPTS{'x'}) ];
$OPTS{'X'} = [ gfimisc_lst2arr($OPTS{'X'}) ];

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

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

my($fh_out);

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

#--- Here I separate completely the two possible actions, as they involve
#    quite different operations.

if($OPTS{'f'}){

  do_con_2_gcon();

}else{

  do_gcon_to_con();

};

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

exit(0);

#------------------------------------------------------------------

sub do_con_2_gcon {

  my(@pos, @x, $con);

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

    @pos = ();

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

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

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

    #--- Loop through input file:
    while($data = <$fh>){
      chomp;
      
      my($n, @data, @d, $str, $i, $j);

      #--- NOTE: the first column in the list of columns must point to the
      #          X-data.  
      $n = @data = gfimisc_get_data($data, $OPTS{'C'});
      next unless($n);
      next unless($data[0] < $ADJ_BAD); 
      
      #--- Get inpterpolated data
      @d = @{$pos{$data[0]}};
      shift(@data);

      #--- Prepare output string:
      $str = '';
      for($i=0; ($i<$OPTS{'i'}) && ($i< (@data)); $i++){
        if($data[$i] < $ADJ_BAD){
          $str = $str . sprintf $FMT, $data[$i];
        }else{
          $str = $str . $BADPRF . $BADSTR;
        }
        $str = $str . $SEP;
      }
      #--- Insert interpolated data:
      for($j=0; $j<(@d); $j++){
        if($d[$j] < $ADJ_BAD){
          $str = $str . sprintf $FMT, $d[$j];
        }else{
          $str = $str . $BADPRF . $BADSTR;
        }
        $str = $str . $SEP;
      }
      #--- Put the rest:
      while($i < (@data)){
        if($data[$i] < $ADJ_BAD){
          $str = $str . sprintf $FMT, $data[$i];
        }else{
          $str = $str . $BADPRF . $BADSTR;
        }
        $str = $str . $SEP;
        $i++;
      }
      
      #--- Print the new line:
      print $fh_out "$str\n";

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

  return(1);
};

#------------------------------------------------------------------

sub do_gcon_to_con {

  my($con);

  #--- Loop through input files:
  foreach $con (@ARGV){

    my($fh, $data, $n, @data, $str, $i);

    $fh = new FileHandle "< $con";
    confess("\nOpening input file $con\n") unless(defined $fh);
    
    #--- Loop through input file:
    while($data = <$fh>){
      chomp($data);

      #--- Get next input data:
      $n = @data = gfimisc_get_data($data, $OPTS{'C'});
      next unless($n);

      #--- Prepare output string:
      $str = '';
      for($i=0; () || ($i< (@data)); $i++){
        if($data[$i] < $ADJ_BAD){
          $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");
  }
 
  return(1);
} 

#------------------------------------------------------------------
# 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--; 

    #--- 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);
};

#------------------------------------------------------------------

sub get_X_data {

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

  my($fh, $cols) = @_ ;
  
  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;
