#!/usr/bin/perl
#
# Does things
#
# $Name:  $
#
# $Log: doRaw.pl,v $
# Revision 1.4  2001/12/12 03:31:33  robc
# Add support for keeping track if ID column output from
# DAOPHOT so PSF phomotery may be matched with apeture
# photometry in future scritps.
#
#
# Revision 1.2  2001/11/14 03:48:38  robc
# Run perltidy
# Add a little more checking to reduce re-computed data on re-runs
#
# Revision 1.1  2001/10/06 09:53:43  robc
# First version
#

use warnings;
use strict;
use lib( $ENV{ TASSIV_FITS_PM } );

use FITS;
use Astro::Time;
use DB_File;
use IO;
use AppConfig qw( :argcount :expand );
use Math::Trig qw( atan );

sub setup_args( $$ );

STDOUT->autoflush;

my $ID = q$Id: doRaw.pl,v 1.4 2001/12/12 03:31:33 robc Exp $;
my $version = join ( ' ', ( split ( ' ', $ID ) )[ 1 .. 3 ] );
$version =~ s/,v\b//;
$version =~ s/(\S+)$/($1)/;

my $CONFIG_FILE = '/tass/src/tassiv_reduce/tassiv_reduce.cfg';

my $cfg = AppConfig->new(
	{ 
      CREATE => 1,
      GLOBAL => {
                  EXPAND   => EXPAND_VAR,
                  ARGCOUNT => ARGCOUNT_ONE
      }
   }
   );
$cfg = setup_args( $cfg, $CONFIG_FILE );

my $MAX_DIFF = $cfg->max_time_diff / 3600 / 24;

my @dirs = sort { $b <=> $a } @ARGV;

for my $dir ( @dirs )
   {
   print "Finding matching files for $dir\n";
   my $matched_ref;

   $matched_ref = FITS_find_matched( $dir, $MAX_DIFF );

   for ( sort keys %$matched_ref )
      {
      system( "date" );
      if ( !-e $_ . ".raw" || !-e $matched_ref->{ $_ } . ".raw"
           || -s $_ . '.raw' == 0 || -s $matched_ref->{ $_ } . '.raw' == 0
           || -e $_ . ".apm" || -e $matched_ref->{ $_ } . ".apm" )
         {
         next;
         }
      my @files;
      push @files, $_;
      push @files, $matched_ref->{ $_ };
      foreach my $file ( @files )
         {
         if ( !-e $file . ".mat" )
            {
            system( "matchStars.pl", $file );
            }
         }
      if ( -e $files[ 0 ] . ".mat" && -e $files[ 1 ] . ".mat" )
         {
         print "Matched $files[0] and $files[1] independently\n";
         apply_match(
                      $files[ 0 ], $files[ 0 ] . ".mat",
                      ".raw",      ".dup",
                      ".apm"
                      );
         apply_match(
                      $files[ 1 ], $files[ 1 ] . ".mat",
                      ".raw",      ".dup",
                      ".apm"
                      );
         }
      elsif ( !-e $files[ 0 ] . ".mat" && -e $files[ 1 ] . ".mat" )
         {
         if ( !match_star_to_star( $files[ 0 ], $files[ 1 ], ".tmp" ) )
            {
            print "Couldn't match $files[0] to $files[1]\n";
            next;
            }
         print "Matched $files[0] to $files[1]\n";
         apply_match(
                      $files[ 0 ], $files[ 1 ] . ".mat",
                      ".tmp",      ".dup",
                      ".apm"
                      );
         apply_match(
                      $files[ 1 ], $files[ 1 ] . ".mat",
                      ".raw",      ".dup",
                      ".apm"
                      );
         }
      elsif ( -e $files[ 0 ] . ".mat" && !-e $files[ 1 ] . ".mat" )
         {
         if ( !match_star_to_star( $files[ 1 ], $files[ 0 ], ".tmp" ) )
            {
            print "Couldn't match $files[1] to $files[0]\n";
            next;
            }
         print "Matched $files[1] to $files[0]\n";
         apply_match(
                      $files[ 0 ], $files[ 0 ] . ".mat",
                      ".raw",      ".dup",
                      ".apm"
                      );
         apply_match(
                      $files[ 1 ], $files[ 0 ] . ".mat",
                      ".tmp",      ".dup",
                      ".apm"
                      );
         }
      }
   print "Removing residual files...\n";
   unlink glob "$dir/*.dup";
   unlink glob "$dir/*.tmp";

   #   unlink glob "$dir/*.apm";
   }

sub apply_match( $$$$$ )
   {
   my ( $file, $mat, @ext ) = @_;

   my $raw = $file . $ext[ 0 ];
   my $dup = $file . $ext[ 1 ];
   my $apm = $file . $ext[ 2 ];
   my $cmd;

	print "Applying match to $file\n";

   tie my %thash, "DB_File", $mat or die "Error: cannot tie to $mat";

   if ( $ext[ 0 ] eq ".raw" )
      {
      my $temp = $cfg->keep_cols;
      $cmd = "dupColumns.pl -file $raw";
      $cmd .= ' -dup ' . $cfg->x_col . ' -dup ' . $cfg->y_col;
      $cmd .= ' -keep ';
      $cmd .= join ' -keep ', sort { $a <=> $b } map { split /,?\s+/ } @$temp;

      open IN, "$cmd |";
      }
   else
      {
      open IN, "< $raw";
      }

   open OUT, "> $apm";

	#
	# Derivation of alpha and delta taken straight from Michael Richmond's
	# apply_match, part of match, found at:
	# http://acd188a-005.rit.edu/match/
	# Basically, apply_match couldn't deal with the number of columns (33)
	# which might be used here.  So rather than re-write apply_match, do it
	# in perl with the [-2,-1] indicie trick.
	#
   my $cos_dec = cos( deg2rad( $thash{ dec } ) );
   my $sin_dec = sin( deg2rad( $thash{ dec } ) );

   while ( <IN> )
      {
      if ( /^#/ )
         {
         print OUT $_;
         next;
         }
      else
         {
         my @data = split;
         my ( $x, $y ) = @data[ -2, -1 ];

         my $delta_ra  = $thash{ a } + $thash{ b } * $x + $thash{ c } * $y;
         my $delta_dec = $thash{ d } + $thash{ e } * $x + $thash{ f } * $y;
         my $z         = $cos_dec - $delta_dec * $sin_dec;
         my $alpha     = $thash{ ra } + rad2deg( atan( $delta_ra / $z ) );

         my $delta =
            cos( deg2rad( $alpha - $thash{ ra } ) ) *
            ( $sin_dec + $delta_dec * $cos_dec ) / $z;
         $delta = rad2deg( atan( $delta ) );

         if ( $alpha < 0 )
            {
            $alpha += 360.0;
            }
         elsif ( $alpha >= 360.0 )
            {
            $alpha -= 360.0;
            }
         $data[ -2 ] = $alpha;
         $data[ -1 ] = $delta;

         print OUT join ( ' ', @data ) . "\n";
         }
      }

   untie %thash;
   }

sub match_star_to_star( $$$ )
   {
   my ( $bad, $good, $ext ) = @_;

   print "Matching $bad.raw to $good.raw\n";

   my $cmd = "match $bad.raw";
   $cmd .= ' ' . $cfg->x_col . ' ' . $cfg->y_col . ' ' . $cfg->mag_col;
   $cmd .= " $good.raw";
   $cmd .= ' ' . $cfg->x_col . ' ' . $cfg->y_col . ' ' . $cfg->mag_col;
   $cmd .= " nobj=40 scale=1.0 recalc";

   my $output = `$cmd`;
	
   `wc -l matched.mtA` =~ /(\d+)/;
   my $match_count = $1;

   $output =~ /a\=([-.\d]+)\s+
               b\=([-.\d]+)\s+
               c\=([-.\d]+)\s+
               d\=([-.\d]+)\s+
               e\=([-.\d]+)\s+
               f\=([-.\d]+)\s+
              /x;

   return 0
      unless defined $1 and defined $2 and defined $3 and defined $4
      and defined $4 and defined $6;

   my $aa = $1;
   my $bb = $2;
   my $c  = $3;
   my $d  = $4;
   my $e  = $5;
   my $f  = $6;

   my $sum1 = abs( $bb ) + abs( $f );
   my $sub1 = abs( abs( $bb ) - abs( $f ) );
   my $sum2 = abs( $c ) + abs( $e );
   my $sub2 = abs( abs( $c ) - abs( $e ) );
   my $per1 = 100 * $sub1 / $sum1;
   my $per2 = 100 * $sub2 / $sum2;

   tie my %good_thash, "DB_File", $good . ".mat"
      or die "Error: cannot tie to $good.mat";

   tie my %bad_thash, "DB_File", $bad . ".mat"
      or die "Error: cannot tie to $bad.mat";

   $bad_thash{ a } = $aa;
   $bad_thash{ b } = $bb;
   $bad_thash{ c } = $c;
   $bad_thash{ d } = $d;
   $bad_thash{ e } = $e;
   $bad_thash{ f } = $f;
   $bad_thash{ count } = $match_count;
	$bad_thash{ to_cat } = 0;

   $bad_thash{ g_a } = $good_thash{ a };
   $bad_thash{ g_b } = $good_thash{ b };
   $bad_thash{ g_c } = $good_thash{ c };
   $bad_thash{ g_d } = $good_thash{ d };
   $bad_thash{ g_e } = $good_thash{ e };
   $bad_thash{ g_f } = $good_thash{ f };
   $bad_thash{ g_count } = $good_thash{ count };

   untie %good_thash;
   untie %bad_thash;

   printf "Matched %5.1f%% %5.1f%%\n", $per1, $per2;
   return 0 if ( $per1 > .2 ) || ( $per2 > 10 );

   my $temp = $cfg->keep_cols;
   $cmd = "dupColumns.pl -file $bad.raw";
   $cmd .= ' -dup ' . $cfg->x_col . ' -dup ' . $cfg->y_col . ' -keep ';
   $cmd .= join ' -keep ', sort { $a <=> $b } map { split /,?\s+/ } @$temp;

   open( IN,  "$cmd |" )     or die "Error: cannot open $bad for reading";
   open( OUT, "> $bad$ext" ) or die "Error: cannot open $bad.$ext for writing";

   while ( <IN> )
      {
      if ( /^#/ )
         {
         print OUT $_;
         next;
         }
      else
         {
         my @data = split;
         my ( $x, $y ) = @data[ -2, -1 ];

         $data[ -2 ] = $aa + $bb * $x + $c * $y;
         $data[ -1 ] = $d + $e * $x + $f * $y;
         print OUT join ( ' ', @data ) . "\n";
         }
      }
   close IN;
   close OUT;

   return 1;
   }

sub setup_args( $$ )
   {
   my ( $c, $file ) = @_;
   $c->define(
               Do_Raw_max_time_diff => {
                                         DEFAULT => 3,
                                         ALIAS   => 'max_time_diff'
               },
               Do_Raw_x_col => {
                                 DEFAULT => 0,
                                 ALIAS   => 'x_col'
               },
               Do_Raw_y_col => {
                                 DEFAULT => 1,
                                 ALIAS   => 'y_col'
               },
               Do_Raw_mag_col => {
                                   DEFAULT => 1,
                                   ALIAS   => 'mag_col'
               }
               );
   $c->define( 'Do_Raw_keep_cols|keep_cols=i@' );
   $c->file( $file );

   $c->define( 'help|h!' );
   $c->define( 'version|v!' );

   $c->args( \@ARGV );

   return $c;
   }
