Index: /trunk/ippScripts/scripts/phase6_sum.pl
===================================================================
--- /trunk/ippScripts/scripts/phase6_sum.pl	(revision 11849)
+++ /trunk/ippScripts/scripts/phase6_sum.pl	(revision 11849)
@@ -0,0 +1,205 @@
+#!/usr/bin/env perl
+
+use warnings;
+use strict;
+
+## report the program and machine
+use Sys::Hostname;
+my $host = hostname();
+print "\n\n";
+print "Starting script $0 on $host\n\n";
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use IPC::Cmd qw( can_run run );
+use PS::IPP::Metadata::Config;
+use PS::IPP::Metadata::Stats;
+use Data::Dumper;
+
+use PS::IPP::Config qw(
+    $PS_EXIT_SUCCESS
+    $PS_EXIT_UNKNOWN_ERROR
+    $PS_EXIT_SYS_ERROR
+    $PS_EXIT_CONFIG_ERROR
+    $PS_EXIT_PROG_ERROR
+    $PS_EXIT_DATA_ERROR
+    $PS_EXIT_TIMEOUT_ERROR
+    );
+my $ipprc = PS::IPP::Config->new(); # IPP configuration
+use File::Spec;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+my ($p6_id, $camera, $dbname, $workdir, $no_update, $no_op);
+GetOptions(
+    'p6_id|d=s'         => \$p6_id, # Phase 6 identifier
+    'camera|c=s'        => \$camera, # Camera name
+    'dbname|d=s'        => \$dbname, # Database name
+    'workdir|w=s'       => \$workdir,	# Working directory, for output files
+    'no-update'         => \$no_update,	# Don't update the database?
+    'no-op'             => \$no_op, # Don't do any operations?
+) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage(
+    -msg => "Required options: --p6_id --camera",
+    -exitval => 3,
+) unless defined $p6_id
+    and defined $camera;
+
+$ipprc->define_camera($camera);
+
+# Look for programs we need
+my $missing_tools;
+my $p6tool = can_run('p6tool') or (warn "Can't find p6tool" and $missing_tools = 1);
+my $ppStac = can_run('ppStac') or (warn "Can't find ppStac" and $missing_tools = 1);
+if ($missing_tools) { 
+    warn("Can't find required tools.");
+    exit($PS_EXIT_CONFIG_ERROR); 
+}
+
+# Get list of components for subtraction
+my $mdcParser = PS::IPP::Metadata::Config->new;	# Parser for metadata config files
+my $files;
+{
+    my $command = "$p6tool -inputscfile -p6_id $p6_id";
+    $command .= " -dbname $dbname" if defined $dbname;
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+	run(command => $command, verbose => 1);
+    unless ($success) {
+	$error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+	&my_die("Unable to perform p6tool -inputscfile: $error_code", $p6_id, $error_code);
+    }
+
+    my $metadata = $mdcParser->parse(join "", @$stdout_buf) or
+	&my_die("Unable to parse metadata config doc", $p6_id, $PS_EXIT_PROG_ERROR);
+    $files = parse_md_list($metadata) or 
+	&my_die("Unable to parse metadata list", $p6_id, $PS_EXIT_PROG_ERROR);
+}
+
+&my_die("Subtraction list contains more than two elements", $p6_id, $PS_EXIT_SYS_ERROR) unless
+    scalar @$files >= 2;
+
+# Identify the input and the template
+my $inputList;			# List of input files
+my $skycell_id;			# Skycell identifier
+foreach my $file (@$files) {
+    my $uri = $ipprc->convert_filename_absolute( $file->{uri} ); # URI for file
+    $inputList .= "$uri ";
+    if (defined $skycell_id) {
+	&my_die("Skycell identifiers don't match", $p6_id, $PS_EXIT_SYS_ERROR) unless
+	    $file->{skycell_id} eq $skycell_id;
+    } else {
+	$skycell_id = $file->{skycell_id};
+    }
+}
+
+### Working directory
+if (defined $workdir) {
+    $workdir = $ipprc->convert_filename_absolute( $workdir );
+} else {
+    my ($vol, $dir, $file) = File::Spec->splitpath( $ipprc->convert_filename_absolute( $$files[0]->{uri} ) );
+    $workdir = $dir;
+}
+
+# Get the output filenames
+my $outputFile = "$skycell_id.sub.$p6_id"; # Root name
+my $outputRoot = File::Spec->catfile( $workdir, $outputFile );
+
+my $outputName = $outputRoot . ".fits";
+my $bin1Name =  $ipprc->filename("PPIMAGE.BIN1", $outputRoot);
+my $bin2Name =  $ipprc->filename("PPIMAGE.BIN2", $outputRoot);
+my $outputStats = $outputRoot . '.stats';
+
+# Perform subtraction
+my $stats = PS::IPP::Metadata::Stats->new(); # Stats parser
+unless ($no_op) {
+    my $command = "$ppStac $outputName $inputList"; # Command to run pois
+
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+	run(command => $command, verbose => 1);
+    unless ($success) {
+	$error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+	&my_die("Unable to perform ppImage: $error_code", $p6_id, $error_code);
+    }
+    &my_die("Couldn't find expected output file: $outputName", $p6_id, $PS_EXIT_SYS_ERROR) unless -f $outputName;
+#    &my_die("Couldn't find expected output file: $bin1Name",    $p6_id, $PS_EXIT_SYS_ERROR) unless -f $bin1Name;
+#    &my_die("Couldn't find expected output file: $bin2Name",    $p6_id, $PS_EXIT_SYS_ERROR) unless -f $bin2Name;
+#    &my_die("Couldn't find expected output file: $outputStats", $p6_id, $PS_EXIT_SYS_ERROR) unless -f $outputStats;
+
+    # Get the statistics on the residual image
+    if (0) { ### Disabled because ppStac doesn't output stats yet
+	my $statsFile;		# File handle
+	open $statsFile, $outputStats or &my_die("Can't open statistics file $outputStats: $!", $p6_id, $PS_EXIT_SYS_ERROR);
+	my @contents = <$statsFile>; # Contents of file
+	close $statsFile;
+	my $metadata = $mdcParser->parse(join "", @contents) or
+	    &my_die("Unable to parse metadata config doc", $p6_id, $PS_EXIT_PROG_ERROR);
+	$stats->parse($metadata) or &my_die("Unable to find all values in statistics output.", $p6_id, $PS_EXIT_PROG_ERROR);
+    }
+}
+
+# Add the processed file to the database
+$outputName = $ipprc->convert_filename_relative( $outputName );
+
+my $bg = ($stats->bg_mean() or 'NAN');
+my $bg_stdev = ($stats->bg_stdev() or 'NAN');
+
+unless ($no_update) {
+
+    # Add the subtraction result
+    {
+	my $command = "$p6tool -addsumscfile -p6_id $p6_id -uri $outputName -b1_uri $outputRoot";
+	$command .= " -bg $bg -bg_stdev $bg_stdev";
+	$command .= " -dbname $dbname" if defined $dbname;
+	
+	my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+	    run(command => $command, verbose => 1);
+	unless ($success) {
+	    $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+	    &my_die("Unable to perform p6tool -adddiffscfile: $error_code", $p6_id, $error_code);
+	}
+	
+#	unlink $outputStats;    
+    }
+
+    # Register the run as completed
+    {
+	my $command = "$p6tool -updaterun -p6_id $p6_id -state stop"; # Command to run p6tool
+	$command .= " -dbname $dbname" if defined $dbname;
+
+	my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+	    run(command => $command, verbose => 1);
+	unless ($success) {
+	    $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+	    warn("Unable to perform p6tool -updaterun: $error_code\n");
+	    exit($error_code);
+	}
+    }
+}
+
+
+sub my_die
+{
+    my $msg = shift;		# Warning message on die
+    my $p6_id = shift;		# Phase 5 identifier
+    my $exit_code = shift;	# Exit code to add
+
+    warn($msg);
+    if ($p6_id and not $no_update) {
+	my $command = "$p6tool -updaterun -p6_id $p6_id -state stop -code $exit_code";
+	$command .= " -dbname $dbname" if defined $dbname;
+        system ($command);
+    }
+    exit $exit_code;
+}
+
+END {
+    my $exit = $?;
+    system("sync") == 0 or die "failed to execute sync: $!";
+    $? = $exit;
+}
+
+__END__
