Index: trunk/ippScripts/scripts/magic_definerun.pl
===================================================================
--- trunk/ippScripts/scripts/magic_definerun.pl	(revision 20676)
+++ trunk/ippScripts/scripts/magic_definerun.pl	(revision 20676)
@@ -0,0 +1,231 @@
+#!/usr/bin/env perl
+
+# program to define a magic run
+# The magictool mode will not queue a run until all diffs from an exposure are
+# successfully completed. There may also be issues with multiple warp runs
+# for a single exposure.
+# This program selects the diffs based on the value for warp_id if provided
+
+use Carp;
+use warnings;
+use strict;
+
+## report the program and machine
+use Sys::Hostname;
+my $host = hostname();
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use IPC::Cmd 0.36 qw( can_run run );
+use File::Temp qw( tempfile );
+use PS::IPP::Metadata::Config;
+use PS::IPP::Metadata::List qw( parse_md_list );
+
+use PS::IPP::Config 1.01 qw( :standard );
+
+my $ipprc = PS::IPP::Config->new(); # IPP configuration
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+# Parse the command-line arguments
+my ($exp_id, $warp_id, $workdir, $dbname, $save_temps, $verbose);
+# temporary option to restrict inputs to central skycells of exp_id 37308
+my $only_central_chips;
+
+GetOptions(
+           'exp_id=s'        => \$exp_id,     # exposure identifier
+           'warp_id=s'       => \$warp_id,    # warp identifier
+           'dbname=s'        => \$dbname,     # Database name
+           'workdir=s'       => \$workdir,    # workdir
+           'save-temps'      => \$save_temps, # Save temporary files?
+           'verbose'         => \$verbose,    # Print stuff?
+           'only-central-chips' => \$only_central_chips,   # only include the central 4 chips
+           ) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --exp_id --workdir",
+           -exitval => 3) unless
+    defined $exp_id and
+    defined $workdir;
+
+# $ipprc->define_camera($camera);
+
+# Look for programs we need
+my $missing_tools;
+my $magictool = can_run('magictool') or (warn "Can't find magictool" and $missing_tools = 1);
+my $difftool  = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1);
+if ($missing_tools) {
+    warn("Can't find required tools.");
+    exit($PS_EXIT_CONFIG_ERROR);
+}
+
+my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
+
+### Get a list of inputs
+my $inputs;                     # List of inputs
+{
+    my $command = "$difftool -diffskyfile -exp_id $exp_id";
+    $command .= " -dbname $dbname" if defined $dbname;
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+        run(command => $command, verbose => $verbose);
+    unless ($success) {
+        $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+        &my_die("Unable to perform difftool -diffskyfile error_code: $error_code", $error_code);
+    }
+
+    my $difftool_output = join "", @$stdout_buf;
+
+    $inputs = parse_md_fast($mdcParser, $difftool_output);
+    &my_die("Unable to parse metadata list", $PS_EXIT_UNKNOWN_ERROR) unless $inputs;
+}
+
+my $num_skyfiles = @$inputs;
+if (! $num_skyfiles) {
+    carp("failed to find any diffskyfiles for exposure $exp_id");
+    exit(1);
+}
+
+print "$num_skyfiles skyfiles found for $exp_id\n" if $verbose;
+
+# this list is for a particular exposure 37308
+my %skycell_filter = (
+    'skycell.02877.14' => 1,
+    'skycell.02877.15' => 1,
+    'skycell.02877.21' => 1,
+    'skycell.02877.22' => 1,
+    'skycell.02877.23' => 1,
+    'skycell.02877.29' => 1,
+    'skycell.02877.30' => 1,
+    'skycell.02877.31' => 1,
+    'skycell.02877.37' => 1,
+    'skycell.02877.38' => 1,
+    'skycell.02877.46' => 1,
+    'skycell.02879.08' => 1,
+    'skycell.02879.16' => 1,
+    'skycell.02879.25' => 1,
+    'skycell.02879.32' => 1,
+    'skycell.02879.33' => 1,
+    'skycell.02879.40' => 1,
+    'skycell.02879.41' => 1
+);
+
+if ($warp_id or $only_central_chips) {
+    # filter the inputs
+    my $i = 0;
+    while ($i < scalar @$inputs) {
+        my $keep = 1;
+        my $sf = $inputs->[$i];
+        my $skycell_id = $sf->{skycell_id};
+        my $this_warp_id = $sf->{warp_id_temp_0};
+
+        if ($only_central_chips and ! $skycell_filter{$skycell_id} ) {
+            $keep = 0;
+        }
+        if ($warp_id and ($warp_id ne $this_warp_id)) {
+            $keep = 0;
+        }
+        if ( $keep) {
+            $i++;
+        } else {
+            # remove it
+            splice @$inputs, $i, 1;
+        }
+    }
+    $num_skyfiles = $i;
+    print "$num_skyfiles skyfiles accepted for $exp_id\n" if $verbose;
+}
+
+if (!$num_skyfiles) {
+    # should I return an error here?
+    &my_die("no skyfiles matching criteria found for exp_id $exp_id", 0);
+}
+
+my $magic_id;
+{
+    my $command = "$magictool -definerun -exp_id $exp_id -workdir $workdir -simple";
+    $command .= " -dbname $dbname" if defined $dbname;
+
+    print "$command\n";
+
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+        run(command => $command, verbose => $verbose);
+    unless ($success) {
+        $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+        &my_die("Unable to perform difftool -diffskyfile: $error_code", $error_code);
+    }
+
+    my $buffer = join "", @$stdout_buf;
+    ($magic_id, undef) = split " ", $buffer;
+}
+
+&my_die("failed to retrieve new magic run information", $PS_EXIT_CONFIG_ERROR) if !$magic_id;
+
+foreach my $diff_skyfile (@$inputs) {
+    my $skycell_id = $diff_skyfile->{skycell_id};
+    if ($diff_skyfile->{fault} > 0) {
+        print "skipping faulted diffSkyfile: $skycell_id\n" if $verbose;
+        next;
+    }
+    my $diff_id = $diff_skyfile->{diff_id};
+    my $command = "$magictool -addinputskyfile -magic_id $magic_id -diff_id $diff_id";
+    $command .= "  -node $skycell_id";
+    $command .= " -dbname $dbname" if $dbname;
+
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+        run(command => $command, verbose => $verbose);
+    unless ($success) {
+        $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+        &my_die("Unable to perform magictool -addinputskyfile for magicRun: $magic_id skycell_id: $skycell_id: $error_code", $error_code);
+    }
+}
+
+# set the new magicRun to state 'run'
+{
+    my $command = "$magictool -updaterun -magic_id $magic_id -state run";
+    $command .= " -dbname $dbname" if $dbname;
+
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+        run(command => $command, verbose => $verbose);
+    unless ($success) {
+        $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+        &my_die("Unable to perform magictool -updaterun for magicRun: $magic_id: $error_code", $error_code);
+    }
+}
+
+sub my_die
+{
+    my $msg = shift;            # Warning message on die
+    my $exit_code = shift;      # Exit code to add
+
+    carp($msg);
+    exit $exit_code;
+}
+
+sub parse_md_fast {
+    my $mdcParser = shift;
+    my $input = shift;
+    my $output = ();
+
+    my @whole = split /\n/, $input;
+    my @single = ();
+
+    my $n;
+    while ( ($n = @whole) > 0) {
+        my $value = shift @whole;
+        push @single, $value;
+        if ($value =~ /^\s*END\s*$/) {
+            push @single, "\n";
+
+            my $list = parse_md_list( $mdcParser->parse( join("\n", @single ) ) ) or
+                print STDERR "Unable to parse metdata config doc" and return undef;
+            push @$output, $list->[0];
+
+            @single = ();
+        }
+    }
+    return $output;
+}
+
+__END__
