Index: /branches/eam_branches/ipp-20110404/Nebulous-Server/lib/Nebulous/Server.pm
===================================================================
--- /branches/eam_branches/ipp-20110404/Nebulous-Server/lib/Nebulous/Server.pm	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/Nebulous-Server/lib/Nebulous/Server.pm	(revision 31439)
@@ -2546,9 +2546,9 @@
     }
 
-    if ($xattr) {
-        my $path = $uri->file;
-        $log->logdie("can not set xattr on $path: $!")
-            unless (setfattr($path, 'user.nebulous_key', $key->path));
-    }
+#     if ($xattr) {
+#         my $path = $uri->file;
+#         $log->logdie("can not set xattr on $path: $!")
+#             unless (setfattr($path, 'user.nebulous_key', $key->path));
+#     }
 
     return $uri;
Index: /branches/eam_branches/ipp-20110404/Nebulous-Server/lib/Nebulous/Server/SQL.pm
===================================================================
--- /branches/eam_branches/ipp-20110404/Nebulous-Server/lib/Nebulous/Server/SQL.pm	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/Nebulous-Server/lib/Nebulous/Server/SQL.pm	(revision 31439)
@@ -336,4 +336,5 @@
              AND m.available = ?
              AND m.allocate = ?
+             AND m.xattr = 0
              AND ( (v.cab_id IS NULL) ||
                    (v.cab_id != ?) )
@@ -344,4 +345,5 @@
     },
     # volume handler
+    # This has a hack to get around the lack of location awareness by using xattr.
     get_storage_volume          => qq{
         SELECT * from (
@@ -357,4 +359,5 @@
             AND available = ?
             AND allocate = ?
+            AND xattr = 0
         ORDER BY free DESC
         LIMIT ?) as topfew
Index: /branches/eam_branches/ipp-20110404/Nebulous/bin/neb-df
===================================================================
--- /branches/eam_branches/ipp-20110404/Nebulous/bin/neb-df	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/Nebulous/bin/neb-df	(revision 31439)
@@ -16,5 +16,5 @@
 use Pod::Usage qw( pod2usage );
 
-my ($server);
+my ($server,$names);
 
 $server = $ENV{'NEB_SERVER'} unless $server;
@@ -22,4 +22,5 @@
 GetOptions(
     'server|s=s'    => \$server,
+    'names'         => \$names,
 ) || pod2usage( 2 );
 
@@ -51,4 +52,8 @@
         = @$row;
     my $path        = $vol{host};
+    if ($names) {
+	$path = $vol{name};
+    }
+
     my $total       = $vol{total};
     $total_total    += $total;
Index: /branches/eam_branches/ipp-20110404/dbconfig/add.md
===================================================================
--- /branches/eam_branches/ipp-20110404/dbconfig/add.md	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/dbconfig/add.md	(revision 31439)
@@ -2,5 +2,6 @@
 addRun METADATA
     add_id          S64     0       # Primary Key AUTO_INCREMENT
-    cam_id          S64     0       # Key INDEX(add_id,cam_id) fkey(cam_id) ref camRun(cam_id)
+    stage 	    STR	    64      # what the stage is (warp, cam, diff,
+    stage_id          S64     0       # Key INDEX(add_id,cam_id) fkey(cam_id) ref camRun(cam_id)
     state           STR     64      # Key
     workdir         STR     255
Index: /branches/eam_branches/ipp-20110404/dbconfig/changes.txt
===================================================================
--- /branches/eam_branches/ipp-20110404/dbconfig/changes.txt	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/dbconfig/changes.txt	(revision 31439)
@@ -2057,5 +2057,77 @@
 
 UPDATE dbversion set schema_version = '1.1.69', updated= CURRENT_TIMESTAMP();
-
-
-
+ALTER TABLE addRun ADD COLUMN stage VARCHAR(64) AFTER add_id;
+ALTER TABLE addRun ADD COLUMN stage_id bigint(20) after stage;
+UPDATE addRun set stage_id = cam_id;
+
+-- these next steps I don't know if it's generic or not. This is how to drop
+   the cam_id table in addRun for gpc1
+
+show create table addRun;
+alter table `addRun` drop foreign key `addRun_ibfk_1`, drop column cam_id;
+
+-- this sets the addRun stage for all the old addRuns to 'cam' 
+
+
+--do this update only once, so I'm commenting it out (it's been done)
+-- update addRun set stage = 'cam';
+
+
+-- Version 1.1.70
+
+CREATE TABLE lapSequence (
+    seq_id BIGINT AUTO_INCREMENT, -- Identifier for the processing sequence
+    name VARCHAR(64) NOT NULL,    -- short name of the sequence
+    description VARCHAR(255) NOT NULL, -- longer description of the sequence
+    PRIMARY KEY(seq_id),
+    KEY(name)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE lapRun (
+    lap_id BIGINT AUTO_INCREMENT, -- Identifier for the processing run
+    seq_id BIGINT NOT NULL,       -- Identifier to match to the sequence
+    tess_id VARCHAR(64) NOT NULL, -- tessellation id to use
+    projection_cell VARCHAR(64) NOT NULL, -- projection cell from the tessellation to consider
+    filter VARCHAR(64) NOT NULL,  -- filter
+    state VARCHAR(64) NOT NULL,   -- state of run
+    label VARCHAR(64) NOT NULL,   -- processing label
+    dist_group VARCHAR(64) NOT NULL, -- distribution group for products of this run
+    registered TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- time run was registered
+    fault SMALLINT NOT NULL,      -- fault code
+    quick_sass_id BIGINT,         -- stackAssociation id for quick stack
+    final_sass_id BIGINT,         -- stackAssociation id for final stack
+    PRIMARY KEY(lap_id),
+    KEY(seq_id),
+    KEY(projection_cell),
+    KEY(filter),
+    KEY(state),
+    KEY(label),
+    KEY(fault),
+    FOREIGN KEY(seq_id) REFERENCES lapSequence(seq_id),
+    FOREIGN KEY(quick_sass_id) REFERENCES stackAssociation(sass_id),
+    FOREIGN KEY(final_sass_id) REFERENCES stackAssociation(sass_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE lapExp (
+    lap_id BIGINT NOT NULL, -- Link back to processing run
+    exp_id BIGINT NOT NULL, -- exposure definition
+    chip_id BIGINT,         -- processing id from chipRun
+    pair_id BIGINT,         -- companion chip_id
+    private TINYINT DEFAULT 0, -- denotes this exposure is private
+    pairwise TINYINT DEFAULT 0, -- denotes if this exposure should be pairwise diffed
+    active TINYINT DEFAULT 0, -- denotes if this exposure is currently in use
+    data_state VARCHAR(64) NOT NULL, -- state of exposure
+    PRIMARY KEY (lap_id,exp_id),
+    KEY (lap_id),
+    KEY (exp_id),
+    KEY (chip_id),
+    KEY (pair_id),
+    KEY (data_state),
+    FOREIGN KEY (lap_id) REFERENCES lapRun(lap_id),
+    FOREIGN KEY (exp_id) REFERENCES rawExp(exp_id),
+    FOREIGN KEY (chip_id,exp_id) REFERENCES chipRun(chip_id,exp_id),
+    FOREIGN KEY (pair_id) REFERENCES chipRun(chip_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+UPDATE dbversion set schema_version = '1.1.70', updated= CURRENT_TIMESTAMP();
+
Index: /branches/eam_branches/ipp-20110404/dbconfig/ipp.m4
===================================================================
--- /branches/eam_branches/ipp-20110404/dbconfig/ipp.m4	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/dbconfig/ipp.m4	(revision 31439)
@@ -35,2 +35,3 @@
 include(background.md)
 include(diffphot.md)
+include(lap.md)
Index: /branches/eam_branches/ipp-20110404/dbconfig/lap.md
===================================================================
--- /branches/eam_branches/ipp-20110404/dbconfig/lap.md	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/dbconfig/lap.md	(revision 31439)
@@ -0,0 +1,31 @@
+lapSequence METADATA
+    seq_id         S64         0    # Primary Key AUTO_INCREMENT
+    name           STR         64   # Key
+    description    STR         255
+END
+
+lapRun METADATA
+    lap_id         S64         0    # Primary Key AUTO_INCREMENT
+    seq_id         S64         0    # Key fkey (seq_id) ref lapSequence(seq_id)
+    tess_id        STR         64
+    projection_cell STR        64   # Key
+    filter         STR         64   # Key
+    state          STR         64   # Key
+    label          STR         64   # Key
+    dist_group     STR         64 
+    registered     TAI	       NULL 
+    fault          S16	       0    # Key
+    quick_sass_id  S64         0    # fkey(quick_sass_id) ref stackAssociation(sass_id)
+    final_sass_id  S64         0    # fkey(final_sass_id) ref stackAssociation(sass_id)
+END
+
+lapExp METADATA
+    lap_id         S64         0    # Primary Key fkey (lap_id) ref lapRun(lap_id)
+    exp_id         S64         0    # Primary Key fkey (exp_id) ref rawExp(exp_id)
+    chip_id        S64         0    # Key fkey (exp_id, chip_id) ref chipRun(exp_id, chip_id)
+    pair_id        S64         0    # Key fkey (pair_id) ref chipRun(chip_id)
+    private        BOOL        f    
+    pairwise       BOOL        f    
+    active         BOOL        f
+    data_state     STR         64   # Key
+END
Index: /branches/eam_branches/ipp-20110404/ippMonitor/def/addRunProcessed.d
===================================================================
--- /branches/eam_branches/ipp-20110404/ippMonitor/def/addRunProcessed.d	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippMonitor/def/addRunProcessed.d	(revision 31439)
@@ -11,5 +11,6 @@
 FIELD distinct(addRun.add_id),        5, %d,     add ID
 
-FIELD addRun.cam_id,          5, %d,     cam ID
+FIELD addRun.stage,        5, %s,     stage
+FIELD addRun.stage_id,          5, %d,     cam ID
 FIELD addRun.state,        5, %s,     state
 FIELD addProcessedExp.fault,        5, %d,     fault
Index: /branches/eam_branches/ipp-20110404/ippMonitor/def/addRunRun.d
===================================================================
--- /branches/eam_branches/ipp-20110404/ippMonitor/def/addRunRun.d	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippMonitor/def/addRunRun.d	(revision 31439)
@@ -10,6 +10,6 @@
 #     field                   size  format  name         show    link to                  extras
 FIELD distinct(addRun.add_id),        5, %d,     add ID
-
-FIELD addRun.cam_id,          5, %d,     cam ID
+FIELD addRun.stage,        5, %s,     stage
+FIELD addRun.stage_id,          5, %d,     stage ID
 FIELD addRun.add_id,        5, %d,     add ID
 FIELD addRun.state,        5, %s,     state
Index: /branches/eam_branches/ipp-20110404/ippScripts/Build.PL
===================================================================
--- /branches/eam_branches/ipp-20110404/ippScripts/Build.PL	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippScripts/Build.PL	(revision 31439)
@@ -117,4 +117,5 @@
         scripts/skycell_jpeg.pl
         scripts/diffphot.pl
+        scripts/lap_science.pl
     )],
     dist_abstract => 'Scripts for running the Pan-STARRS IPP',
Index: /branches/eam_branches/ipp-20110404/ippScripts/MANIFEST
===================================================================
--- /branches/eam_branches/ipp-20110404/ippScripts/MANIFEST	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippScripts/MANIFEST	(revision 31439)
@@ -45,3 +45,4 @@
 scripts/ipp_cluster_load_monitor.pl
 scripts/skycell_jpeg.pl
+scripts/lap_science.pl
 t/00_distribution.t
Index: /branches/eam_branches/ipp-20110404/ippScripts/scripts/addstar_run.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/ippScripts/scripts/addstar_run.pl	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippScripts/scripts/addstar_run.pl	(revision 31439)
@@ -37,13 +37,14 @@
 }
 my $minidvodb_path;
-my ( $exp_tag, $add_id, $camera, $outroot, $camroot, $dbname, $reduction, $dvodb, $minidvodb, $minidvodb_name, $minidvodb_group, $image_only, $verbose, $no_update,
+my ( $add_id, $camera, $stage, $outroot, $stageroot, $dbname, $reduction, $dvodb, $minidvodb, $minidvodb_name, $minidvodb_group, $image_only, $verbose, $no_update,
      $no_op, $redirect, $save_temps);
 GetOptions(
-    'exp_tag=s'          => \$exp_tag, # Exposure identifier
     'add_id=s'          => \$add_id, # Camtool identifier
     'camera|c=s'        => \$camera, # Camera
+    'stage|s=s'        => \$stage, # Camera
+    
     'dbname|d=s'        => \$dbname, # Database name
     'outroot|w=s'       => \$outroot, # output file base name
-    'camroot|w=s'       => \$camroot, # camera stage root name.
+    'stageroot|w=s'       => \$stageroot, # stage root name.
     'reduction=s'       => \$reduction, # Reduction class
     'dvodb|w=s'         => \$dvodb,  # output DVO database
@@ -61,11 +62,11 @@
 pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
 pod2usage(
-          -msg => "Required options: --exp_tag --add_id --camera --outroot --dvodb --camroot",
+          -msg => "Required options: --add_id --camera --outroot --dvodb --stageroot --stage",
           -exitval => 3,
           ) unless
-    defined $exp_tag and
+    defined $stage and
     defined $add_id and
     defined $outroot and
-    defined $camroot and
+    defined $stageroot and
     defined $dvodb and
     defined $camera;
@@ -86,7 +87,15 @@
 # Recipes to use based on reduction class
 $reduction = 'DEFAULT' unless defined $reduction;
-
+my $recipe_addstar = $ipprc->reduction($reduction, 'ADDSTAR');
 # XXX This is now not used: do we still need it?
-my $recipe_addstar = $ipprc->reduction($reduction, 'ADDSTAR'); # Recipe to use
+if ($stage =~/cam/) {
+  $recipe_addstar = $ipprc->reduction($reduction, 'ADDSTAR'); # Recipe to use
+}
+if ($stage =~/stack/) {
+  $recipe_addstar = $ipprc->reduction($reduction, 'ADDSTAR_STACK'); # Recipe to use
+}
+#if ($stage =~/staticsky/) {
+#  $recipe_addstar = $ipprc->reduction($reduction, 'ADDSTAR_STATICSKY'); # Recipe to use
+#}
 &my_die("Unrecognised ADDSTAR recipe", $add_id, $PS_EXIT_CONFIG_ERROR) unless defined $recipe_addstar;
 
@@ -97,5 +106,12 @@
 
 # the camera configurations should define the psastro output to be a single file (MEF), regardless of the inputs
-my $fpaObjects = $ipprc->filename("PSASTRO.OUTPUT",     $camroot) or &my_die("Missing entry from camera config", $add_id, $PS_EXIT_CONFIG_ERROR);
+
+# it was PSASTRO.OUTPUT
+my $fpaObjects = $ipprc->filename("PSASTRO.OUTPUT",     $stageroot) or &my_die("Missing entry from camera config", $add_id, $PS_EXIT_CONFIG_ERROR);
+
+if (($stage =~/staticsky/) || ($stage =~/stack/)) {
+    $fpaObjects =~ s/smf$/cmf/;
+    
+}
 my $traceDest  = $ipprc->filename("TRACE.EXP",          $outroot) or &my_die("Missing entry from camera config", $add_id, $PS_EXIT_CONFIG_ERROR);
 
@@ -173,6 +189,8 @@
         $command .= " $realFile";
         $command .= " -use-name $fpaObjects"; # DVO wants the neb-name as a file reference
-        $command .= " -image" if $image_only;
-
+	    $command .= " -image" if $image_only;
+	    if ($stage = ~/staticsky/) {
+		$command .= " -accept-astrom ";
+	    }
         my $mjd_addstar_start = DateTime->now->mjd;   # MJD of starting script
 
Index: /branches/eam_branches/ipp-20110404/ippScripts/scripts/diff_skycell.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/ippScripts/scripts/diff_skycell.pl	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippScripts/scripts/diff_skycell.pl	(revision 31439)
@@ -31,4 +31,5 @@
 my $ppSub = can_run('ppSub') or (warn "Can't find ppSub" and $missing_tools = 1);
 my $ppStatsFromMetadata = can_run('ppStatsFromMetadata') or (warn "Can't find ppStatsFromMetadata" and $missing_tools = 1);
+my $nebInsert = can_run('neb-insert') or (warn "Can't find neb-insert" and $missing_tools = 1);
 if ($missing_tools) {
     warn("Can't find required tools.");
@@ -265,4 +266,7 @@
 my $do_photom = 1;
 my $dump_config = 1; 
+if ($reduction eq 'NOCONVDIFF') {
+    $do_photom = 0;
+}
 if ($run_state eq 'new') {
     $configuration = prepare_output("PPSUB.CONFIG", $outroot, 1);
@@ -380,4 +384,17 @@
                 }
             }
+	    if ($reduction eq 'NOCONVDIFF') {
+		my $refConv = prepare_output("PPSUB.REF.CONV", $outroot, 0);
+		my $templateFile = $ipprc->file_resolve($template,0);
+		$command = "$nebInsert $refConv $templateFile";
+		( $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 neb-insert: $error_code", $diff_id, $skycell_id, $error_code);
+		}
+	    }
+
+
         } elsif ($run_state eq 'update') {
             &my_die("Update resulted in poor quality image: $quality", $diff_id, $skycell_id, $PS_EXIT_SYS_ERROR);
Index: /branches/eam_branches/ipp-20110404/ippScripts/scripts/lap_science.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/ippScripts/scripts/lap_science.pl	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippScripts/scripts/lap_science.pl	(revision 31439)
@@ -0,0 +1,907 @@
+#!/usr/bin/env perl
+
+
+use warnings;
+use strict;
+use Carp;
+use IPC::Cmd 0.36 qw( can_run run);
+use PS::IPP::Metadata::List qw( parse_md_list );
+use PS::IPP::Config 1.01 qw( :standard );
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+use DateTime;
+
+#
+# Set up
+################################################################################
+
+my $missing_tools = 0;
+my $regtool  = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1);
+my $chiptool = can_run('chiptool') or (warn "Can't find chiptool" and $missing_tools = 1);
+my $warptool = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1);
+my $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1);
+my $stacktool = can_run('stacktool') or (warn "Can't find stacktool" and $missing_tools = 1);
+my $magicdstool = can_run('magicdstool') or (warn "Can't find magicdstool" and $missing_tools = 1);
+my $laptool  = can_run('laptool') or (warn "Can't find laptool" and $missing_tools = 1);
+
+my ( $help, $verbose, $debug, $do_nothing);
+my ( $camera, $dbname);
+my ( $lap_id );
+my ( $chip_mode, $monitor_mode, $cleanup_mode);
+
+GetOptions(
+    'help|h'       => \$help,
+    'verbose'      => \$verbose,
+    'debug'        => \$debug,
+    'do_nothing'   => \$do_nothing,
+
+    'camera=s'     => \$camera,
+    'dbname=s'     => \$dbname,
+    
+    'lap_id=s'     => \$lap_id,
+
+    'chip_mode'    => \$chip_mode,
+    'monitor_mode' => \$monitor_mode,
+    'cleanup_mode' => \$cleanup_mode,
+    ) or pod2usage ( 2 );
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage(
+    -msg => "Choose a mode: --chip_mode --monitor_mode --cleanup_mode",
+    -exitval => 3,
+    ) unless
+    defined $chip_mode or defined $monitor_mode or defined $cleanup_mode;
+pod2usage(
+    -msg => "--lap_id is required",
+    -exitval => 3,
+    ) unless
+    defined $lap_id;
+
+unless (defined $dbname) {
+    $dbname = 'gpc1';
+}
+
+my $mdcParser = PS::IPP::Metadata::Config->new;
+
+# Fetch all the information about this run
+my %lapRunInfo = get_lapRun_info($lap_id);
+
+# Run the appropriate mode
+
+if (defined($chip_mode)) {
+    unless ($lapRunInfo{state} eq 'new') {
+	&my_die("Cannot run chip_mode if lapRun.state != new!",$lap_id);
+    }
+    my $status = chip_mode($lap_id);
+    exit $status;
+}
+if (defined($monitor_mode)) {
+    unless ($lapRunInfo{state} eq 'run') {
+	&my_die("Cannot run monitor_mode if lapRun != run!", $lap_id);
+    }
+    my $status = monitor_mode($lap_id);
+    exit $status;
+}
+if (defined($cleanup_mode)) {
+    unless (($lapRunInfo{state} eq 'full')||
+	    ($lapRunInfo{state} eq 'drop')) {
+	&my_die("Cannot run cleanup_mode if lapRun != done!", $lap_id);
+    }
+    my $status = cleanup_mode($lap_id);
+    exit $status;
+}
+
+#
+# Chip
+################################################################################
+
+sub chip_mode {
+    my $lap_id = shift;
+    my $status = queue_chips($lap_id);
+
+    if ($status) {
+	my $command = "$laptool -updaterun -lap_id $lap_id";
+	$command .= " -dbname $dbname " if defined $dbname;
+	$command .= " -set_state run ";
+	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 laptool -updaterun: $error_code", $lap_id);
+	}
+    }
+    return($status);
+}
+
+# retrieve the chip_id for the exposure inserted
+sub get_chip_id_from_metadata {
+    my $exp_id = shift;
+    my $label = shift;
+    my $data_group = shift;
+    # This is a puzzler... chiptool doesn't actually return a useful metadata.  We'll just scrape it from the database for now.
+
+    my $command = "$chiptool -listrun -exp_id $exp_id -label $label -data_group $data_group";
+    $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 chiptool -listrun: $error_code", $exp_id, $data_group);
+    }
+    my $chips = $mdcParser->parse_list(join "", @$stdout_buf) or
+	&my_die("Unable to parse metadata from chiptool -listrun", $exp_id, $data_group);
+    # There should be only one.
+    my $chip = ${ $chips }[0];
+    my $chip_id = 0;
+    if ($chip) {
+	$chip_id = $chip->{chip_id};
+    }
+    
+    return($chip_id);
+}
+
+sub get_lapRun_info {
+    my $lap_id = shift;
+    my $command = "$laptool -pendingrun -lap_id $lap_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 laptool -pendingrun: $error_code", $lap_id);
+    }
+    my $Runs = $mdcParser->parse_list(join "", @$stdout_buf) or
+	&my_die("Unable to parse metadata from laptool -pendingrun", $lap_id);
+    # There should be only one.
+    my $Run = ${ $Runs }[0];
+    my %info = %{ $Run };
+    return(%info);
+}
+
+
+# Queue a chipRun for this exposure with the appropriate parameters.
+sub remake_this_exposure {
+    my $exposure = shift;
+
+    my @utctime = gmtime();
+    $utctime[5] += 1900;
+    $utctime[4] += 1;
+
+    my $label = $exposure->{label};
+
+    my $date = sprintf("%4d%02d%02d",$utctime[5],$utctime[4],$utctime[3]);
+    my $workdir_date = sprintf("%4d/%02d/%02d",$utctime[5],$utctime[4],$utctime[3]);
+    my $workdir = "neb://\@HOST\@.0/${dbname}/${label}/${workdir_date}";
+    my $data_group = "${label}.${date}";
+
+
+    my $chip_cmd = "$chiptool";
+    $chip_cmd .= " -pretend " if defined $debug;
+    $chip_cmd .= " -dbname $dbname " if defined $dbname;
+    $chip_cmd .= " -definebyquery -exp_id $exposure->{exp_id} -set_end_stage warp -set_tess_id $exposure->{tess_id} ";
+    $chip_cmd .= " -set_label $exposure->{label} -set_data_group $data_group ";
+    $chip_cmd .= " -set_workdir $workdir -set_dist_group $exposure->{dist_group} ";
+
+    my ($success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+	run(command => $chip_cmd, verbose => $verbose);
+    unless ($success) {
+	$error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+	&my_die("Unable to perform chiptool -definebyquery: $error_code", $exposure->{lap_id}, $exposure->{proj_cell});
+    }
+    
+    $exposure->{chip_id} = get_chip_id_from_metadata($exposure->{exp_id},$exposure->{label},$data_group); 
+    $exposure->{data_state} = 'new';
+    update_this_exposure($exposure);
+    return($exposure);
+}
+
+# This is the "user level" subroutine.
+sub queue_chips {
+    my $lap_id = shift;
+    
+    my $command = "$laptool -pendingexp -lap_id $lap_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 laptool -pendingexp: $error_code", $lap_id);
+    }
+    
+    if (@$stdout_buf == 0) {
+	# Nothing to do.
+	return(0);
+    }
+    
+    my $exposures = $mdcParser->parse_list(join "", @$stdout_buf) or
+	&my_die("Unable to parse metadata from laptool -pendingexp", $lap_id);
+
+    my $counter = 0;
+    my %matching = ();
+    my %indexing = ();
+    # Determine which exposures need a chipRun queued.
+    foreach my $exposure (@$exposures) {  
+	# $lap_id = $exposure->{lap_id};  # This should be already known.
+	my $tess_id = $exposure->{tess_id};
+	my $exp_id = $exposure->{exp_id};
+	my $chip_id = $exposure->{chip_id};
+	my $pair_id = $exposure->{pair_id};
+	my $private = $exposure->{private};
+	my $pairwise = $exposure->{pairwise};
+	my $active = $exposure->{active};
+	my $data_state = $exposure->{data_state};
+	my $dateobs = $exposure->{dateobs};
+	my $object = $exposure->{object};
+	my $comment = $exposure->{comment};
+
+	if (S64_IS_NOT_NULL($chip_id)) { # We already have a defined chip_id
+	    if (($pairwise) && !($pair_id)) {
+		# This is an error.
+		&my_die("Exposure $exp_id for $lap_id is declared pairwise without a defined pair", $lap_id);
+	    }
+	    $matching{$object}{$comment} = $exp_id;
+	    $indexing{$exp_id} = $counter;
+	    $counter++; 
+	    next;
+	}
+	else { # We do not already have a chip_id.  
+	    # Make a chipRun, and update the exposure.
+	    $exposure = remake_this_exposure($exposure); 
+	    
+	    # Save our information for diff pairing.
+	    $matching{$object}{$comment} = $exp_id;
+	    $indexing{$exp_id} = $counter;
+	    $counter++;
+	}
+    }
+
+    # Determine which exposures have a pair for diffing.
+    foreach my $object (keys %matching) { 
+	my @exp_ids_to_diff = ();
+	foreach my $comment (keys %{ $matching{$object} }) {
+	    push @exp_ids_to_diff, $matching{$object}{$comment};
+	}
+	@exp_ids_to_diff = sort { $indexing{$a} <=> $indexing{$b} } @exp_ids_to_diff;
+	
+	if (( $#exp_ids_to_diff + 1) % 2 != 0) { # We have an odd number of exposures, even after comment filtering
+	    pop(@exp_ids_to_diff); # dump the last entry.
+	}
+
+	while ($#exp_ids_to_diff > -1) {  # Save the pair information to the opposite exposure.
+	    my $exp_id_A = shift(@exp_ids_to_diff);
+	    my $exp_id_B = shift(@exp_ids_to_diff);
+
+	    my $exp_A = ${ $exposures }[$indexing{$exp_id_A}];
+	    my $exp_B = ${ $exposures }[$indexing{$exp_id_B}];
+
+	    $exp_A->{pairwise} = 1;
+	    $exp_A->{private} = 0;
+	    $exp_A->{pair_id} = $exp_B->{chip_id};
+	    
+	    $exp_B->{pairwise} = 1;
+	    $exp_B->{private} = 0;
+	    $exp_B->{pair_id} = $exp_A->{chip_id};
+	    
+	    if ($verbose) {
+		print "LAP_DIFFS: $object: $exp_A->{exp_id} and $exp_B->{exp_id} are a pair\n";
+	    }
+	}
+    }
+
+    # Scan all exposures, and ensure that pairwise and private are set correctly
+    foreach my $exposure (@$exposures) { 
+	if ($exposure->{pairwise} && !($exposure->{pair_id})) {
+	    $exposure->{pairwise} = 0; # We marked it for pairwise diffs, but didn't match it. Probably an error.
+	}
+	if (!($exposure->{pairwise})) {
+	    $exposure->{private} = 1; # If this isn't being pairwise diffed, it needs to be private
+	}
+
+	$exposure = update_this_exposure($exposure);
+    }
+    return(1);
+}
+
+
+#
+# Decide Things
+################################################################################
+sub monitor_mode {
+    my $lap_id = shift;
+    return(check_status($lap_id));
+}
+    
+
+sub check_stack_status {  # look at lapRun associated stacks, and confirm their states.
+    my $lap_id = shift;
+
+    my ($defined_qstack,$have_qstack,$defined_fstack,$have_fstack);
+    
+    my $command = "$laptool -stacks -lap_id $lap_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 laptool -stacks: $error_code", $lap_id, "");
+    }
+
+    ($defined_qstack,$have_qstack,$defined_fstack,$have_fstack) = (0,0,0,0);
+    if (@$stdout_buf == 0) {
+	# Nothing to do.  Possibly an error, but for now, just accept it
+	return($defined_qstack,$have_qstack,$defined_fstack,$have_fstack);
+    }
+
+    my $stacks = $mdcParser->parse_list(join "", @$stdout_buf) or
+	&my_die("Unable to parse metadata from laptool -stacks", $lap_id, "");
+
+    my $total_qstacks = 0;
+    my $complete_qstacks = 0;
+    my $total_fstacks = 0;
+    my $complete_fstacks = 0;
+    foreach my $stack (@$stacks) {
+	if (($stack->{quick_stack_id})&&
+	    (S64_IS_NOT_NULL($stack->{quick_stack_id}))) {
+	    $defined_qstack = 1;
+	    $total_qstacks++;
+	}
+	if (($stack->{final_stack_id})&&
+	    (S64_IS_NOT_NULL($stack->{final_stack_id}))) {
+	    $defined_fstack = 1;
+	    $total_fstacks++;
+	}
+	
+	if (($stack->{quick_state})&&
+	    ($stack->{quick_state} eq 'full')) {
+	    $complete_qstacks++;
+	}
+	elsif (($stack->{quick_state})&&($stack->{quick_state} eq 'new')&&
+	       ($stack->{quick_fault} >= 4)&&($stack->{quick_fault} != 32767)) {
+	    printf STDERR "Faulted quick stack: $stack->{quick_stack_id} $stack->{quick_fault}\n";
+	    $complete_qstacks++;# This is not the best solution, but if they continually fail, there's not much we can do.
+	}
+	if (($stack->{final_state})&&
+	    ($stack->{final_state} eq 'full')) {
+	    $complete_fstacks++;
+	}
+	elsif (($stack->{final_state})&&($stack->{final_state} eq 'new')&&
+	       ($stack->{final_fault} >= 4)&&($stack->{final_fault} != 32767)) {
+	    printf STDERR "Faulted final stack: $stack->{final_stack_id} $stack->{final_fault}\n";
+	    $complete_fstacks++; # This is not the best solution, but if they continually fail, there's not much we can do.
+	}
+
+    }
+    if (($complete_qstacks > 0)&&
+	($complete_qstacks == $total_qstacks)) {
+	$have_qstack = 1;
+    }
+    if (($complete_fstacks > 0)&&
+	($complete_fstacks == $total_fstacks)) {
+	$have_fstack = 1;
+    }
+    
+	
+    return($defined_qstack,$have_qstack,$defined_fstack,$have_fstack);
+}
+sub check_status {
+    my $lap_id = shift;
+    
+    my ($defined_qstack,$have_qstack,$defined_fstack,$have_fstack) = check_stack_status($lap_id);
+
+    my $command = "$laptool -exposures -lap_id $lap_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 laptool -exposures: $error_code", $lap_id);
+    }
+    
+    if (@$stdout_buf == 0) {
+	# Nothing to do. However, this is likely an error.
+	return(0);
+    }
+    
+    my $exposures = $mdcParser->parse_list(join "", @$stdout_buf) or
+	&my_die("Unable to parse metadata from laptool -exposures", $lap_id);
+
+    # Need to prescan to see who matches whom.
+    my %match_hash = ();
+    my $index = 0;
+    foreach my $exposure (@$exposures) {
+	if ($exposure->{pair_id}) {
+	    $match_hash{$exposure->{pair_id}} = $index; # Tell the companion who we are, so they can find us next time.
+	}
+	$index++;
+    }
+
+    # Things I want to know before I'm through
+    my $needs_qstack = 0;
+    my $needs_something_remade = 0;
+    my $needs_something_private = 0;
+    my $can_qstack = 0;
+    my $have_diff = 0;
+    my $can_diff = 0;
+    my $can_fstack = 0;
+    my $total_exposures = 0;
+    foreach my $exposure (@$exposures) {
+	$total_exposures++;
+	my $companion;
+
+	if ($exposure->{pair_id}) { # Load companion exposure information
+	    if (exists($match_hash{$exposure->{chip_id}})) {
+		$companion = ${ $exposures }[$match_hash{$exposure->{chip_id}}]; # Match!
+	    }
+	}
+	
+	if ($exposure->{private}) { # I've declared this exposure private to this lapRun.
+	    $needs_qstack = 1;
+	}
+	
+	if ($exposure->{needs_remade}) { # This does the check that private = false for other lapRun
+	    $needs_something_remade = 1;
+	    $exposure = remake_this_exposure($exposure);
+	}
+	if ($exposure->{cam_quality}) {
+	    $needs_qstack = 1;
+	    $needs_something_private = 1;
+	    if ($companion) {
+		$companion->{private} = 1;
+		$companion->{pairwise} = 0;
+		&update_this_exposure($companion);
+	    }
+	    $exposure->{private} = 1;
+	    $exposure->{pairwise} = 0;
+	    $exposure->{data_state} = 'drop';
+	    &update_this_exposure($exposure);
+
+	}
+# 	if ($companion) { # Validate that there are no problems with the companion exposure
+# 	    if ($companion->{cam_quality}) { # Maybe other things here?
+# 		$exposure->{private} = 1;
+# 		$exposure->{data_state} = 'drop';
+# 		&update_this_exposure($exposure);
+# 		$needs_qstack = 1;
+# 	    }
+# 	}
+	if  ($exposure->{data_state} eq 'drop') { # This exposure is impossible, so fudge the counts so we get through.
+	    $can_qstack ++;
+	    $can_diff ++;
+	    $have_diff ++;
+	    $can_fstack ++;	    
+	    next;
+	}
+
+	if (($exposure->{warpRun_state})&&  # This exposure has a warp
+	    ($exposure->{warpRun_state} eq 'full')) { # This exposure's warp is done.
+	    $can_qstack ++;
+	    $can_diff ++;
+	}
+	if (($exposure->{magicked}&&
+	     &S64_IS_NOT_NULL($exposure->{magicked}))) {  # This exposure has been magicked, so it is through with diff.
+	    $can_fstack ++;
+	}
+	if (($exposure->{diff_id})&&(&S64_IS_NOT_NULL($exposure->{diff_id}))) {
+	    $have_diff ++;
+	}
+    }
+
+
+    print "STATUS: DEFINED_QSTACK:  $defined_qstack\n";
+    print "STATUS: HAVE_QSTACK:     $have_qstack\n";
+    print "STATUS: DEFINED_FSTACK:  $defined_fstack\n";
+    print "STATUS: HAVE_FSTACK:     $have_fstack\n";
+
+    print "STATUS: NEEDS_QSTACK:    $needs_qstack\n";
+    print "STATUS: NEEDS_REMADE:    $needs_something_remade\n";
+    print "STATUS: NEEDS PRIVATIZE: $needs_something_private\n";
+    print "STATUS: CAN_QSTACK:      $can_qstack\n";
+    print "STATUS: CAN_DIFF:        $can_diff\n";
+    print "STATUS: HAVE_DIFF:       $have_diff\n";
+    print "STATUS: CAN_FSTACK:      $can_fstack\n";
+
+    print "STATUS: TOTAL_EXPOSURES: $total_exposures\n";
+    if ($do_nothing) {
+	exit(0);
+    }
+    if (($needs_qstack == 1)&&              # Do we need the quick stack?
+	($defined_qstack == 0)&&            # Have we not made it already?
+	($can_qstack == $total_exposures)&& # Are all warps done?
+	($needs_something_remade == 0)      # Do we need to wait for a stolen exposure?
+	) {
+	print "STATUS: Will now queue quickstacks\n";
+	&queue_quickstack($exposures);
+    }
+
+    if (($can_diff == $total_exposures)&&   # Are all warps done?
+	($needs_something_remade == 0)&&    # Do we need to wait for a stolen exposure?
+	($have_diff < $can_diff)&&          # We haven't already done them all.
+	(($needs_qstack == 0)||             # Are we just doing pairwise diffs?
+	 ($needs_qstack == 1)&&($have_qstack == 1)) ) { # If we need a quickstack, do we have it?
+	print "STATUS: Will now queue diffs\n";
+	&queue_diffs($exposures);
+    }
+
+    if (($can_fstack == $total_exposures)&& # Are all warps done?
+	($needs_something_remade == 0)&&    # Do we need to wait for a stolen exposure?
+	($defined_fstack == 0)) {           # Have we not made it already?
+	print "STATUS: Will now queue final stacks\n";
+	&queue_finalstack($exposures);
+    }
+
+    if (($have_fstack == 1)) {              # Are we all done making the final product?
+	print "STATUS: Will now deactivate exposures for this complete lapRun.\n";
+	&deactivate_exposures($exposures);
+	$command = "$laptool -updaterun -lap_id $lap_id";
+	$command .= " -dbname $dbname " if defined $dbname;
+	$command .= " -set_state full ";
+	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 laptool -updaterun: $error_code", $lap_id);
+	}
+    }
+    
+}
+
+sub queue_quickstack {
+    my $exposures = shift; # reference to exposure array;
+    my $exposure = ${ $exposures }[0]; # reference to the first exposure to get run level information
+    
+    my $lap_id    = $exposure->{lap_id};
+    my $label     = $exposure->{label};
+    my $filter    = $exposure->{filter};
+    my $proj_cell = $exposure->{projection_cell};
+
+    unless (defined($label) && defined($filter) && defined($proj_cell)) {
+	&my_die("Unable to perform stacktool. Insufficient information.", $lap_id);
+    }
+
+    my @utctime = gmtime();
+    $utctime[5] += 1900;
+    $utctime[4] += 1;
+    my $date = sprintf("%4d%02d%02d",$utctime[5],$utctime[4],$utctime[3]);
+    my $workdir_date = sprintf("%4d/%02d/%02d",$utctime[5],$utctime[4],$utctime[3]);
+    my $workdir = "neb://\@HOST\@.0/${dbname}/${label}/${workdir_date}";
+    my $data_group = "${label}.${date}";
+
+    my $command = "$stacktool ";
+    $command .= " -pretend " if defined $debug;
+    $command .= " -dbname $dbname " if defined $dbname;
+    $command .= " -definebyquery -select_label $label -select_skycell_id ${proj_cell}.% -select_filter $filter ";
+    $command .= " -set_label ${label} -set_data_group ${proj_cell}.quick.${date} ";
+    $command .= "  -set_workdir $workdir  -set_dist_group NODIST ";
+    $command .= " -min_num 2 -set_reduction QUICKSTACK ";
+
+    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 stacktool -definebyquery: $error_code", $lap_id);
+    }
+
+    $command = "$stacktool ";
+    $command .= " -dbname $dbname " if defined $dbname;
+    $command .= " -sassskyfile -data_group ${proj_cell}.quick.${date} ";
+    $command .= " -filter $filter -projection_cell ${proj_cell} ";
+
+    ($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 stacktool -sassskyfile: $error_code", $lap_id);
+    }
+    
+    my $stacks = $mdcParser->parse_list(join "", @$stdout_buf) or
+	&my_die("Unable to parse metadata from stacktool -sassskyfile", $lap_id, "");
+    
+    my $stack = ${ $stacks }[0];
+    my $sass_id = $stack->{sass_id};
+    unless (defined($sass_id)) {
+	&my_die("Unable to parse metadata from stacktool for sass_id", $lap_id, "");
+    }
+
+    print "QUICK_SASS_ID: $sass_id\n";
+    $command = "$laptool -updaterun -lap_id $lap_id -set_quick_sass_id $sass_id";
+    $command .= " -dbname $dbname " if defined $dbname;
+
+    ($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 laptool -updaterun: $error_code", $lap_id);
+    }
+    
+
+}
+sub queue_finalstack {
+    my $exposures = shift; # reference to exposure array;
+    my $exposure = ${ $exposures }[0]; # reference to the first exposure to get run level information
+    
+    my $lap_id    = $exposure->{lap_id};
+    my $label     = $exposure->{label};
+    my $filter    = $exposure->{filter};
+    my $proj_cell = $exposure->{projection_cell};
+
+    unless (defined($label) && defined($filter) && defined($proj_cell)) {
+	&my_die("Unable to perform stacktool. Insufficient information.", $lap_id);
+    }
+
+    my @utctime = gmtime();
+    $utctime[5] += 1900;
+    $utctime[4] += 1;
+    my $date = sprintf("%4d%02d%02d",$utctime[5],$utctime[4],$utctime[3]);
+    my $workdir_date = sprintf("%4d/%02d/%02d",$utctime[5],$utctime[4],$utctime[3]);
+    my $workdir = "neb://\@HOST\@.0/${dbname}/${label}/${workdir_date}";
+    my $data_group = "${label}.${date}";
+
+    my $command = "$stacktool ";
+    $command .= " -pretend " if defined $debug;
+    $command .= " -dbname $dbname " if defined $dbname;
+    $command .= " -definebyquery -select_label $label -select_skycell_id ${proj_cell}.% -select_filter $filter ";
+    $command .= " -set_label ${label} -set_workdir $workdir -set_data_group ${proj_cell}.final.${date} ";
+    $command .= " -min_num 2 -set_reduction THREEPI_STACK ";
+
+    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 stacktool -definebyquery: $error_code", $lap_id);
+    }
+    
+    
+    $command = "$stacktool ";
+    $command .= " -dbname $dbname " if defined $dbname;
+    $command .= " -sassskyfile -data_group ${proj_cell}.final.${date} ";
+    $command .= " -filter $filter -projection_cell ${proj_cell} ";
+
+    ($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 stacktool -sassskyfile: $error_code", $lap_id);
+    }
+
+    my $stacks = $mdcParser->parse_list(join "", @$stdout_buf) or
+	&my_die("Unable to parse metadata from stacktool -sassskyfile", $lap_id, "");
+
+    my $stack = ${ $stacks }[0];
+    my $sass_id = $stack->{sass_id};
+    unless (defined($sass_id)) {
+	&my_die("Unable to parse metadata from stacktool for sass_id", $lap_id, "");
+    }
+    print "FINAL_SASS_ID: $sass_id\n";
+    $command = "$laptool -updaterun -lap_id $lap_id -set_final_sass_id $sass_id";
+    $command .= " -dbname $dbname " if defined $dbname;
+
+    ($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 laptool -updaterun: $error_code", $lap_id);
+    }
+
+}
+sub queue_diffs {
+    my $exposures = shift;
+    
+    # Need to prescan to see who matches whom.
+    my %match_hash = ();
+    my $index = 0;
+    foreach my $exposure (@$exposures) {
+	if ($exposure->{pair_id}) {
+	    $match_hash{$exposure->{pair_id}} = $index; # Tell the companion who we are, so they can find us next time.
+	}
+	$index++;
+    }
+
+    my %already_queued = ();
+    foreach my $exposure (@$exposures) {
+	if ($exposure->{data_state} eq 'drop') { # Kick out unusable exposures
+	    next;
+	}
+	if ($exposure->{diff_id}&&S64_IS_NOT_NULL($exposure->{diff_id})) { # Not sure how this would happen, but still. ## This happens when we inherit a complete exposure.
+	    next;
+	}
+	if ($already_queued{$exposure->{warp_id}}) {
+	    print "STATUS: Have already queued a diff containing $exposure->{exp_id} $exposure->{chip_id} $exposure->{warp_id}\n";
+	    next;
+	}
+
+	my @utctime = gmtime();
+	$utctime[5] += 1900;
+	$utctime[4] += 1;
+
+	my $label = $exposure->{label};
+	my $dist_group = $exposure->{dist_group};
+	my $date = sprintf("%4d%02d%02d",$utctime[5],$utctime[4],$utctime[3]);
+	my $workdir_date = sprintf("%4d/%02d/%02d",$utctime[5],$utctime[4],$utctime[3]);
+	my $workdir = "neb://\@HOST\@.0/${dbname}/${label}/${workdir_date}";
+	my $data_group = "${label}.${date}";
+
+
+	my $command = "$difftool ";
+	$command .= " -pretend " if defined $debug;
+	$command .= " -dbname $dbname " if defined $dbname;
+	$command .= " -set_label $label -set_workdir $workdir -set_data_group $data_group ";
+	if ($exposure->{dist_group}) {
+	    $command .= " -set_dist_group $exposure->{dist_group} ";
+	}
+	
+	if ($exposure->{pairwise}) { # warpwarp
+	    my $companion = ${ $exposures }[$match_hash{$exposure->{chip_id}}];
+	    $command .= " -definewarpwarp ";
+	    $command .= "-input_label $label -template_label $label -backwards ";
+	    $command .= "-warp_id $exposure->{warp_id} -template_warp_id $companion->{warp_id} ";
+	    $already_queued{$exposure->{warp_id}} = 1;
+	    $already_queued{$companion->{warp_id}} = 1;
+	    
+	}
+	else { # warp-qstack
+	    $command .= " -definewarpstack -set_reduction NOCONVDIFF -available -good_frac 0.2 ";
+	    $command .= " -warp_id $exposure->{warp_id} -stack_label ${label}.quick ";
+	    $already_queued{$exposure->{warp_id}} = 1;
+	}
+	
+	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 -definewarp(warp|stack): $error_code", $exposure->{lap_id}, $exposure->{proj_cell});
+	}
+	
+	my $diffs = $mdcParser->parse_list(join "", @$stdout_buf) or
+	    &my_die("Unable to parse metadata from difftool -definewarp(warp|stack)", $lap_id, "");
+	
+	my $diff = ${ $diffs }[0];
+	my $diff_id = $diff->{diff_id};
+	unless (defined($diff_id)) {
+	    $exposure->{data_state} = 'drop';
+	    &update_this_exposure($exposure);
+	}
+	
+    }
+}
+
+# Deactivate all exposures in this run.
+sub deactivate_exposures {
+    my $exposures = shift;
+    foreach my $exposure (@$exposures) {
+	$exposure->{active} = 0;
+	update_this_exposure($exposure);
+    }
+}
+
+
+#
+# Cleanup
+################################################################################
+
+sub cleanup_mode {
+    my $lap_id = shift;
+    my $command = "$laptool -inactiveexp -lap_id $lap_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 laptool -inactiveexp: $error_code", "none", "none");
+    }
+    if (@$stdout_buf == 0) {
+	# Nothing to do.
+	return(0);
+    }
+    
+    my $exposures = $mdcParser->parse_list(join "", @$stdout_buf) or
+	&my_die("Unable to parse metadata from laptool -inactiveexp", $lap_id);
+
+    my @clean_modes = (
+	'chiptool -dbname @DBNAME@ -updaterun -set_state goto_cleaned -state full -set_label goto_cleaned -label @LABEL@ -chip_id @CHIP_ID@',
+	'warptool -dbname @DBNAME@ -updaterun -set_state goto_cleaned -state full -set_label goto_cleaned -label @LABEL@ -warp_id @WARP_ID@',
+	'difftool -dbname @DBNAME@ -updaterun -set_state goto_cleaned -state full -set_label goto_cleaned -label @LABEL@ -diff_id @DIFF_ID@',
+	'magicdstool -dbname @DBNAME@ -updaterun -set_state goto_cleaned -state full -set_label goto_cleaned -stage chip -stage_id @CHIP_ID@',
+	'magicdstool -dbname @DBNAME@ -updaterun -set_state goto_cleaned -state full -set_label goto_cleaned -stage warp -stage_id @WARP_ID@',
+	'magicdstool -dbname @DBNAME@ -updaterun -set_state goto_cleaned -state full -set_label goto_cleaned -stage diff -stage_id @DIFF_ID@');
+    foreach my $exposure (@$exposures) {
+	if ($exposure->{is_in_use}) {
+	    next;
+	}
+ 	foreach my $clean_mode (@clean_modes) {
+ 	    my $command = $clean_mode;
+	    $command =~ s/\@DBNAME\@/$dbname/g;
+	    $command =~ s/\@CHIP_ID\@/$exposure->{chip_id}/;
+	    $command =~ s/\@WARP_ID\@/$exposure->{warp_id}/;
+	    $command =~ s/\@DIFF_ID\@/$exposure->{diff_id}/;
+	    $command =~ s/\@LABEL\@/$exposure->{label}/;
+	    
+	    ($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 cleantool: $command : $error_code", "none", "none");
+	    }
+ 	}
+ 	$exposure->{data_state} = 'cleaned';
+ 	update_this_exposure($exposure);
+    }
+}
+    
+	    
+
+
+#
+# Utilities
+################################################################################
+
+sub my_die {
+    my $msg = shift; # Warning message on die
+    my $lap_id = shift; # identifier
+    my $optional = shift;
+    my $exit_code = shift;
+    unless (defined $exit_code) {
+	$exit_code = $PS_EXIT_PROG_ERROR;
+    }
+    carp($msg);
+    exit $exit_code;
+}
+
+# Check to see if a 64bit integer is NULL or not.  This is probably fragile, but I don't know how to get a S64 NULL out.
+sub S64_IS_NOT_NULL {
+    if ($_[0] == 9223372036854775807) {
+	return(0);
+    }
+    else {
+	return(1);
+    }
+}
+
+# Take the current exposure structure, and save it to the database.
+sub update_this_exposure {
+    my $exposure = shift;
+    
+    # These are required
+    my $lap_id = $exposure->{lap_id};
+    my $exp_id = $exposure->{exp_id};
+    
+    my $command = "$laptool -updateexp -lap_id $lap_id -exp_id $exp_id ";
+    if (($exposure->{chip_id})&&(S64_IS_NOT_NULL($exposure->{chip_id}))) {
+	$command .= " -set_chip_id  $exposure->{chip_id} ";
+    }
+    if (($exposure->{pair_id})&&(S64_IS_NOT_NULL($exposure->{pair_id}))) {
+	$command .= " -set_pair_id  $exposure->{pair_id} ";
+    }
+
+    if ($exposure->{private}) {
+	$command .= " -private ";
+    }
+    else {
+	$command .= " -public ";
+    }
+    if ($exposure->{pairwise}) {
+	$command .= " -pairwise ";
+    }
+    else {
+	$command .= " -nopairwise ";
+    }
+    if ($exposure->{active}) {
+	$command .= " -active ";
+    }
+    else {
+	$command .= " -inactive ";
+    }
+    if ($exposure->{data_state}) {
+	$command .= " -set_data_state $exposure->{data_state} ";
+    }
+
+    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 laptool -updateexp: $error_code", $exposure->{lap_id}, $exposure->{proj_cell});
+    }
+}    
+
Index: /branches/eam_branches/ipp-20110404/ippScripts/scripts/magic_destreak.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/ippScripts/scripts/magic_destreak.pl	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippScripts/scripts/magic_destreak.pl	(revision 31439)
@@ -360,5 +360,10 @@
         $command .= " -chip_mask $ch_mask" if defined $ch_mask;
         $command .= " -weight $weight" if defined $weight;
-        $command .= " -sources $sources" if defined $sources;
+	if ((defined($sources))&&($ipprc->file_exists($sources))) {
+	    $command .= " -sources $sources" if defined $sources;
+	}
+	else {
+	    print "Did not add sources because they do not appear to exist. This may be an error.\n";
+	}
         $command .= " -skycelllist $skycell_list" if defined $skycell_list;
         $command .= " -replace" if $replace;
Index: /branches/eam_branches/ipp-20110404/ippScripts/scripts/nightly_science.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/ippScripts/scripts/nightly_science.pl	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippScripts/scripts/nightly_science.pl	(revision 31439)
@@ -996,4 +996,5 @@
     $cmd .= " -min_num 4";
     $cmd .= " -select_good_frac_min 0.05";
+    $cmd .= " -set_reduction NIGHTLY_STACK ";
     $cmd .= " $select ";
     if ($debug == 1) {
Index: /branches/eam_branches/ipp-20110404/ippScripts/scripts/stack_skycell.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/ippScripts/scripts/stack_skycell.pl	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippScripts/scripts/stack_skycell.pl	(revision 31439)
@@ -73,5 +73,4 @@
 PPSTACK.OUTPUT.EXPNUM       
 PPSTACK.OUTPUT.EXPWT
-PPSTACK.TARGET.PSF          
 PPSTACK.OUTPUT.JPEG1        
 PPSTACK.OUTPUT.JPEG2        
@@ -84,4 +83,5 @@
 # extra outputs when convolving
 my @outputListUnconv = qw(
+PPSTACK.TARGET.PSF          
 PPSTACK.UNCONV
 PPSTACK.UNCONV.MASK
@@ -181,6 +181,7 @@
 my $recipe_psphot  = $ipprc->reduction($reduction, 'STACK_PSPHOT'); # Recipe to use for psphot
 my $recipe_ppstats = 'STACKSTATS';
-if ($run_state eq 'update') {
-    $recipe_ppstats = 'WARPSTATS';
+if ($
+run_state eq 'update') {
+     $recipe_ppstats = 'WARPSTATS';
 }
 unless ($recipe_ppStack and $recipe_ppSub and $recipe_psphot) {
@@ -208,4 +209,6 @@
     &my_die("Unable to not compress and logflux compress simultaneously. Check config.",$stack_id, $PS_EXIT_CONFIG_ERROR);
 }
+my $stack_type = metadataLookupStr($recipe, 'STACK.TYPE');
+&my_die("STACK.TYPE not found in recipe. Check config.",$stack_id, $PS_EXIT_CONFIG_ERROR) unless $stack_type;
 
 # Generate MDC file with the inputs
@@ -281,4 +284,5 @@
     $command .= " -recipe PSPHOT $recipe_psphot";
     $command .= " -recipe PPSTATS $recipe_ppstats" if $do_stats;;
+    $command .= " -stack-type $stack_type";
     $command .= " -F PSPHOT.PSF.SAVE PSPHOT.PSF.SKY.SAVE";
     $command .= " -F PSPHOT.OUTPUT PSPHOT.OUT.CMF.MEF";
Index: /branches/eam_branches/ipp-20110404/ippScripts/scripts/staticsky.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/ippScripts/scripts/staticsky.pl	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippScripts/scripts/staticsky.pl	(revision 31439)
@@ -32,5 +32,7 @@
 my $staticskytool = can_run('staticskytool') or (warn "Can't find staticskytool" and $missing_tools = 1);
 my $psphotStack = can_run('psphotStack') or (warn "Can't find psphotStack" and $missing_tools = 1);
+my $psphot = can_run('psphot') or (warn "Can't find psphot" and $missing_tools = 1);
 my $ppStatsFromMetadata = can_run('ppStatsFromMetadata') or (warn "Can't find ppStatsFromMetadata" and $missing_tools = 1);
+my $ppConfigDump = can_run('ppConfigDump') or (warn "Can't find ppConfigDump" and $missing_tools = 1);
 if ($missing_tools) {
     warn("Can't find required tools.");
@@ -96,143 +98,229 @@
 }
 
+# Recipes to use based on reduction class
+$reduction = 'DEFAULT' unless defined $reduction;
+
+
 # generate the input 
 print $listFile "INPUT   MULTI\n";
 my $nInputs = @$files;
 
-my $configuration = $ipprc->filename("PSPHOT.STACK.CONFIG", $outroot);
-
-foreach my $file (@$files) {
-    print $listFile "INPUT   METADATA\n";
-
-    # XXX if we take the input from 'warp', we will need to make different selections here
-    my $path_base = $file->{path_base};
-    print "input: $path_base\n";
-
-    my $imageCnv  = $ipprc->filename("PPSTACK.OUTPUT",          $path_base ); # Image name
-    my $maskCnv   = $ipprc->filename("PPSTACK.OUTPUT.MASK",     $path_base ); # Mask name
-    my $weightCnv = $ipprc->filename("PPSTACK.OUTPUT.VARIANCE", $path_base ); # Weight name
-
-    my $imageRaw  = $ipprc->filename("PPSTACK.UNCONV",          $path_base ); # Image name
-    my $maskRaw   = $ipprc->filename("PPSTACK.UNCONV.MASK",     $path_base ); # Mask name
-    my $weightRaw = $ipprc->filename("PPSTACK.UNCONV.VARIANCE", $path_base ); # Weight name
-
-    my $sources   = $ipprc->filename("PSPHOT.OUT.CMF.MEF",      $path_base ); # Sources name
-
-    # XXX is this the correct PSF file?
-    my $psfCnv    = $ipprc->filename("PPSTACK.TARGET.PSF",      $path_base ); # PSF name
-
-    # XXX we could make some different choices if some inputs do not exist...
-    &my_die("Couldn't find input: $imageRaw",  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$imageRaw");
-    &my_die("Couldn't find input: $maskRaw",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$maskRaw");
-    &my_die("Couldn't find input: $weightRaw", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$weightRaw");
-    &my_die("Couldn't find input: $imageCnv",  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$imageCnv");
-    &my_die("Couldn't find input: $maskCnv",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$maskCnv");
-    &my_die("Couldn't find input: $weightCnv", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$weightCnv");
-    &my_die("Couldn't find input: $psfCnv",    $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$psfCnv");
-    &my_die("Couldn't find input: $sources",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$sources");
-
-    print $listFile "  RAW:IMAGE     STR  " . $imageRaw  . "\n";
-    print $listFile "  RAW:MASK      STR  " . $maskRaw   . "\n";
-    print $listFile "  RAW:VARIANCE  STR  " . $weightRaw . "\n";
-
-    print $listFile "  CNV:IMAGE     STR  " . $imageCnv  . "\n";
-    print $listFile "  CNV:MASK      STR  " . $maskCnv   . "\n";
-    print $listFile "  CNV:VARIANCE  STR  " . $weightCnv . "\n";
-    print $listFile "  CNV:PSF       STR  " . $psfCnv    . "\n";
-
-    print $listFile "  SOURCES       STR  " . $sources   . "\n";
-
-    print $listFile "END\n\n";
-}
-
-# Recipes to use based on reduction class
-$reduction = 'DEFAULT' unless defined $reduction;
-my $recipe_psphot  = $ipprc->reduction($reduction, 'STACKPHOT_PSPHOT'); # Recipe to use for psphot
-my $recipe_ppsub   = $ipprc->reduction($reduction, 'STACKPHOT_PPSUB'); # Recipe to use for ppsub
-my $recipe_ppstack = $ipprc->reduction($reduction, 'STACKPHOT_PPSTACK'); # Recipe to use for ppstack
-unless ($recipe_psphot) {
-    &my_die("Couldn't find selected reduction for STACKPHOT: $reduction\n", $sky_id, $PS_EXIT_CONFIG_ERROR);
-}
-
-print "reduction:      $reduction\n";
-print "recipe_psphot:  $recipe_psphot\n";
-print "recipe_ppsub:   $recipe_ppsub\n";
-print "recipe_ppstack: $recipe_ppstack\n";
-
-# my $cmdflags;
-
-# Perform stack photometry analysis
-{
-    my $command = "$psphotStack $outroot";
-    $command .= " -input $listName";
-    $command .= " -threads $threads" if defined $threads;
-    $command .= " -recipe PSPHOT  $recipe_psphot";
-    $command .= " -recipe PPSUB   $recipe_ppsub";
-    $command .= " -recipe PPSTACK $recipe_ppstack";
-    $command .= " -dumpconfig $configuration";
-    $command .= " -tracedest $traceDest -log $logDest";
-    # $command .= " -dbname $dbname" if defined $dbname;
-    # $command .= " -image_id $diff_skyfile_id" if defined $diff_skyfile_id;
-    # $command .= " -source_id $source_id" if defined $source_id;
-
-    unless ($no_op) {
-	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 psphotStack: $error_code", $sky_id, $error_code);
-	}
-
-        # my $outputStatsReal = $ipprc->file_resolve($outputStats);
-        # &my_die("Couldn't find expected output file: $outputStats", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputStatsReal);
-
-        # measure chip stats
-        # $command = "$ppStatsFromMetadata $outputStatsReal - DIFF_SKYCELL";
-        # ( $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 ppStatsFromMetadata: $error_code", $sky_id, $error_code);
-        # }
-        # foreach my $line (@$stdout_buf) {
-        #     $cmdflags .= " $line";
-        # }
-        # chomp $cmdflags;
-
-        # my ($quality) = $cmdflags =~ /-quality (\d+)/; # Quality flag
-
-	my $quality = 0;
-        if (!$quality) {
-
-	    # Get the output filenames
-	    # we have one set of output files per input file set
-	    for (my $i = 0; $i < @$files; $i++) {
-		my $outputName     = $ipprc->filename("PSPHOT.STACK.OUTPUT.IMAGE", $outroot, $i);
-		my $outputMask     = $ipprc->filename("PSPHOT.STACK.OUTPUT.MASK", $outroot, $i);
-		my $outputVariance = $ipprc->filename("PSPHOT.STACK.OUTPUT.VARIANCE", $outroot, $i);
-		my $outputSources  = $ipprc->filename("PSPHOT.STACK.OUTPUT", $outroot, $i);
-
-		# XXX these are optional and not generated by default
-		# &my_die("Couldn't find expected output file: $outputName", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputName);
-		# &my_die("Couldn't find expected output file: $outputMask", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputMask);
-		# &my_die("Couldn't find expected output file: $outputVariance", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputVariance);
-		&my_die("Couldn't find expected output file: $outputSources", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputSources);
-	    }
-
-	    #my $configuration  = $ipprc->filename("PPSUB.CONFIG", $outroot);
-	    #my $outputStats    = $ipprc->filename("SKYCELL.STATS", $outroot);
-	    #my $traceDest      = $ipprc->filename("TRACE.EXP", $outroot);
-
-	    my $chisqName     = $ipprc->filename("PSPHOT.CHISQ.IMAGE", $outroot);
-	    my $chisqMask     = $ipprc->filename("PSPHOT.CHISQ.MASK", $outroot);
-	    my $chisqVariance = $ipprc->filename("PSPHOT.CHISQ.VARIANCE", $outroot);
-
-	    # XXX check the recipe -- should we expect these to exist?
-            # &my_die("Couldn't find expected output file: $chisqName", 	  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($chisqName);
-            # &my_die("Couldn't find expected output file: $chisqMask", 	  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($chisqMask);
-            # &my_die("Couldn't find expected output file: $chisqVariance", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($chisqVariance);
-        }
-    } else {
-        print "Not executing: $command\n";
-    }
+if ($nInputs > 1) {
+        my $recipe_psphot  = $ipprc->reduction($reduction, 'STACKPHOT_PSPHOT'); # Recipe to use for psphot
+        my $recipe_ppsub   = $ipprc->reduction($reduction, 'STACKPHOT_PPSUB'); # Recipe to use for ppsub
+        my $recipe_ppstack = $ipprc->reduction($reduction, 'STACKPHOT_PPSTACK'); # Recipe to use for ppstack
+        unless ($recipe_psphot) {
+            &my_die("Couldn't find selected reduction for STACKPHOT: $reduction\n", $sky_id, $PS_EXIT_CONFIG_ERROR);
+        }
+
+        print "reduction:      $reduction\n";
+        print "recipe_psphot:  $recipe_psphot\n";
+        print "recipe_ppsub:   $recipe_ppsub\n";
+        print "recipe_ppstack: $recipe_ppstack\n";
+        my $configuration = $ipprc->filename("PSPHOT.STACK.CONFIG", $outroot);
+
+        foreach my $file (@$files) {
+            print $listFile "INPUT   METADATA\n";
+
+            # XXX if we take the input from 'warp', we will need to make different selections here
+            my $path_base = $file->{path_base};
+            print "input: $path_base\n";
+
+            my $imageCnv  = $ipprc->filename("PPSTACK.OUTPUT",          $path_base ); # Image name
+            my $maskCnv   = $ipprc->filename("PPSTACK.OUTPUT.MASK",     $path_base ); # Mask name
+            my $weightCnv = $ipprc->filename("PPSTACK.OUTPUT.VARIANCE", $path_base ); # Weight name
+
+            my $imageRaw  = $ipprc->filename("PPSTACK.UNCONV",          $path_base ); # Image name
+            my $maskRaw   = $ipprc->filename("PPSTACK.UNCONV.MASK",     $path_base ); # Mask name
+            my $weightRaw = $ipprc->filename("PPSTACK.UNCONV.VARIANCE", $path_base ); # Weight name
+
+            my $sources   = $ipprc->filename("PSPHOT.OUT.CMF.MEF",      $path_base ); # Sources name
+
+            # XXX is this the correct PSF file?
+            my $psfCnv    = $ipprc->filename("PPSTACK.TARGET.PSF",      $path_base ); # PSF name
+
+            # XXX we could make some different choices if some inputs do not exist...
+            &my_die("Couldn't find input: $imageRaw",  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$imageRaw");
+            &my_die("Couldn't find input: $maskRaw",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$maskRaw");
+            &my_die("Couldn't find input: $weightRaw", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$weightRaw");
+            &my_die("Couldn't find input: $imageCnv",  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$imageCnv");
+            &my_die("Couldn't find input: $maskCnv",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$maskCnv");
+            &my_die("Couldn't find input: $weightCnv", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$weightCnv");
+            &my_die("Couldn't find input: $psfCnv",    $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$psfCnv");
+            &my_die("Couldn't find input: $sources",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$sources");
+
+            print $listFile "  RAW:IMAGE     STR  " . $imageRaw  . "\n";
+            print $listFile "  RAW:MASK      STR  " . $maskRaw   . "\n";
+            print $listFile "  RAW:VARIANCE  STR  " . $weightRaw . "\n";
+
+            print $listFile "  CNV:IMAGE     STR  " . $imageCnv  . "\n";
+            print $listFile "  CNV:MASK      STR  " . $maskCnv   . "\n";
+            print $listFile "  CNV:VARIANCE  STR  " . $weightCnv . "\n";
+            print $listFile "  CNV:PSF       STR  " . $psfCnv    . "\n";
+
+            print $listFile "  SOURCES       STR  " . $sources   . "\n";
+
+            print $listFile "END\n\n";
+        }
+
+        # my $cmdflags;
+
+        # Perform stack photometry analysis
+        {
+            my $command = "$psphotStack $outroot";
+            $command .= " -input $listName";
+            $command .= " -threads $threads" if defined $threads;
+            $command .= " -recipe PSPHOT  $recipe_psphot";
+            $command .= " -recipe PPSUB   $recipe_ppsub";
+            $command .= " -recipe PPSTACK $recipe_ppstack";
+            $command .= " -dumpconfig $configuration";
+            $command .= " -tracedest $traceDest -log $logDest";
+            # $command .= " -dbname $dbname" if defined $dbname;
+
+            unless ($no_op) {
+                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 psphotStack: $error_code", $sky_id, $error_code);
+                }
+
+                # my $outputStatsReal = $ipprc->file_resolve($outputStats);
+                # &my_die("Couldn't find expected output file: $outputStats", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputStatsReal);
+
+                # measure chip stats
+                # $command = "$ppStatsFromMetadata $outputStatsReal - DIFF_SKYCELL";
+                # ( $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 ppStatsFromMetadata: $error_code", $sky_id, $error_code);
+                # }
+                # foreach my $line (@$stdout_buf) {
+                #     $cmdflags .= " $line";
+                # }
+                # chomp $cmdflags;
+
+                # my ($quality) = $cmdflags =~ /-quality (\d+)/; # Quality flag
+
+                my $quality = 0;
+                if (!$quality) {
+
+                    # Get the output filenames
+                    # we have one set of output files per input file set
+                    for (my $i = 0; $i < @$files; $i++) {
+                        my $outputName     = $ipprc->filename("PSPHOT.STACK.OUTPUT.IMAGE", $outroot, $i);
+                        my $outputMask     = $ipprc->filename("PSPHOT.STACK.OUTPUT.MASK", $outroot, $i);
+                        my $outputVariance = $ipprc->filename("PSPHOT.STACK.OUTPUT.VARIANCE", $outroot, $i);
+                        my $outputSources  = $ipprc->filename("PSPHOT.STACK.OUTPUT", $outroot, $i);
+
+                        # XXX these are optional and not generated by default
+                        # &my_die("Couldn't find expected output file: $outputName", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputName);
+                        # &my_die("Couldn't find expected output file: $outputMask", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputMask);
+                        # &my_die("Couldn't find expected output file: $outputVariance", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputVariance);
+                        &my_die("Couldn't find expected output file: $outputSources", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputSources);
+                    }
+
+                    #my $configuration  = $ipprc->filename("PPSUB.CONFIG", $outroot);
+                    #my $outputStats    = $ipprc->filename("SKYCELL.STATS", $outroot);
+                    #my $traceDest      = $ipprc->filename("TRACE.EXP", $outroot);
+
+                    my $chisqName     = $ipprc->filename("PSPHOT.CHISQ.IMAGE", $outroot);
+                    my $chisqMask     = $ipprc->filename("PSPHOT.CHISQ.MASK", $outroot);
+                    my $chisqVariance = $ipprc->filename("PSPHOT.CHISQ.VARIANCE", $outroot);
+
+                    # XXX check the recipe -- should we expect these to exist?
+                    # &my_die("Couldn't find expected output file: $chisqName", 	  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($chisqName);
+                    # &my_die("Couldn't find expected output file: $chisqMask", 	  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($chisqMask);
+                    # &my_die("Couldn't find expected output file: $chisqVariance", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($chisqVariance);
+                }
+            } else {
+                print "Not executing: $command\n";
+            }
+        }
+} else {
+        # single input. Run psphot
+        # find the recipe
+        my $recipe_psphot  = $ipprc->reduction($reduction, 'STACKPHOT_SINGLE_PSPHOT'); # Recipe to use for psphot
+        unless ($recipe_psphot) {
+            &my_die("Couldn't find selected reduction for STACKPHOT: $reduction\n", $sky_id, $PS_EXIT_CONFIG_ERROR);
+        }
+
+        print "reduction:      $reduction\n";
+        print "recipe_psphot:  $recipe_psphot\n";
+
+        my $configuration = $ipprc->filename("PSPHOT.SKY.CONFIG", $outroot);
+
+        my $file = $files->[0];
+
+        # XXX if we take the input from 'warp', we will need to make different selections here
+        my $path_base = $file->{path_base};
+        print "input: $path_base\n";
+
+        # examine the recipe to determine whether to analyze the "raw" or convolved images
+        my $command = "$ppConfigDump -camera $camera -dump-recipe PSPHOT -recipe PSPHOT $recipe_psphot -";
+        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+        run(command => $command, verbose => 0);
+        unless ($success) {
+            $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+            &my_die("Unable to perform ppConfigDump: $error_code", $sky_id, $PS_EXIT_SYS_ERROR);
+        }
+        my $recipeData = $mdcParser->parse(join "", @$stdout_buf) or
+            &my_die("Unable to parse metadata config doc", $sky_id, $PS_EXIT_SYS_ERROR);
+
+        my $use_raw = metadataLookupBool($recipeData, 'PSPHOT.STACK.USE.RAW');
+
+        my ($image, $mask, $variance);
+        if ($use_raw) {
+            $image  = $ipprc->filename("PPSTACK.UNCONV",          $path_base ); # Image name
+            $mask   = $ipprc->filename("PPSTACK.UNCONV.MASK",     $path_base ); # Mask name
+            $variance = $ipprc->filename("PPSTACK.UNCONV.VARIANCE", $path_base ); # Weight name
+        } else {
+            $image  = $ipprc->filename("PPSTACK.OUTPUT",          $path_base ); # Image name
+            $mask   = $ipprc->filename("PPSTACK.OUTPUT.MASK",     $path_base ); # Mask name
+            $variance = $ipprc->filename("PPSTACK.OUTPUT.VARIANCE", $path_base ); # Weight name
+        }
+
+        my $output_sources_filerule = "PSPHOT.OUT.CMF.MEF";
+        my $output_psf_filerule = "PSPHOT.PSF.SKY.SAVE";
+
+        # XXX we could make some different choices if some inputs do not exist...
+        &my_die("Couldn't find input: $image",  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$image");
+        &my_die("Couldn't find input: $mask",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$mask");
+        &my_die("Couldn't find input: $variance", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$variance");
+
+        # Perform stack photometry analysis
+        {
+            my $command = "$psphot $outroot";
+            $command .= " -file $image";
+            $command .= " -mask $mask";
+            $command .= " -variance $variance";
+            $command .= " -threads $threads" if defined $threads;
+            $command .= " -recipe PSPHOT  $recipe_psphot";
+            $command .= " -dumpconfig $configuration" if $configuration;
+            $command .= " -tracedest $traceDest -log $logDest";
+            $command .= " -F PSPHOT.OUTPUT $output_sources_filerule";
+            $command .= " -F PSPHOT.PSF.SAVE $output_psf_filerule";
+
+            unless ($no_op) {
+                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 psphot: $error_code", $sky_id, $error_code);
+                }
+
+                my $quality = 0;
+                if (!$quality) {
+                    my $outputSources  = $ipprc->filename($output_sources_filerule, $outroot);
+                    &my_die("Couldn't find expected output file: $outputSources", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputSources);
+                    my $outputPSF  = $ipprc->filename($output_psf_filerule, $outroot);
+                    &my_die("Couldn't find expected output file: $outputPSF", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($outputPSF);
+                }
+
+                &my_die("Couldn't find expected output file: $configuration", $sky_id, $PS_EXIT_SYS_ERROR) 
+                    unless $ipprc->file_exists($configuration);
+            } else {
+                print "Not executing: $command\n";
+            }
+        }
 }
 
Index: /branches/eam_branches/ipp-20110404/ippTasks/addstar.pro
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTasks/addstar.pro	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTasks/addstar.pro	(revision 31439)
@@ -17,5 +17,11 @@
 
 macro addstar.on
-  task addstar.exp.load
+  task addstar.exp.load.stack
+    active true
+  end
+  task addstar.exp.load.cam
+    active true
+  end
+  task addstar.exp.load.staticsky
     active true
   end
@@ -26,5 +32,11 @@
 
 macro addstar.off
-  task addstar.exp.load
+  task addstar.exp.load.stack
+    active false
+  end
+  task addstar.exp.load.cam
+    active false
+  end
+  task addstar.exp.load.staticsky
     active false
   end
@@ -54,5 +66,5 @@
 # new entries are added to addPendingExp
 # skip already-present entries
-task	       addstar.exp.load
+task	       addstar.exp.load.stack
   host         local
 
@@ -67,5 +79,5 @@
   task.exec
    # if ($LABEL:n == 0) break
-    $run = addtool -pendingexp
+    $run = addtool -pendingexp -stage stack
     if ($DB:n == 0)
       option DEFAULT
@@ -109,4 +121,112 @@
 end
 
+task	       addstar.exp.load.cam
+  host         local
+
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 30
+  npending     1
+
+  stdout NULL
+  stderr $LOGDIR/addstar.exp.log
+
+  task.exec
+   # if ($LABEL:n == 0) break
+    $run = addtool -pendingexp -stage cam
+    if ($DB:n == 0)
+      option DEFAULT
+    else
+      # save the DB name for the exit tasks
+      option $DB:$addstar_DB
+      $run = $run -dbname $DB:$addstar_DB
+      $addstar_DB ++
+      if ($addstar_DB >= $DB:n) set addstar_DB = 0
+    end
+    add_poll_args run
+    add_poll_labels run
+    command $run
+  end
+
+  # success
+  task.exit    0
+    # convert 'stdout' to book format
+    ipptool2book stdout addPendingExp -key add_id -uniq -setword dbname $options:0 -setword pantaskState INIT
+    if ($VERBOSE > 2)
+      book listbook addPendingExp
+    end
+
+    # delete existing entries in the appropriate pantaskStates
+    process_cleanup addPendingExp
+  end
+
+  # default exit status
+  task.exit    default
+    showcommand failure
+  end
+
+  task.exit    crash
+    showcommand crash
+  end
+
+  # operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
+task	       addstar.exp.load.staticsky
+  host         local
+
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 30
+  npending     1
+
+  stdout NULL
+  stderr $LOGDIR/addstar.exp.log
+
+  task.exec
+   # if ($LABEL:n == 0) break
+    $run = addtool -pendingexp -stage staticsky
+    if ($DB:n == 0)
+      option DEFAULT
+    else
+      # save the DB name for the exit tasks
+      option $DB:$addstar_DB
+      $run = $run -dbname $DB:$addstar_DB
+      $addstar_DB ++
+      if ($addstar_DB >= $DB:n) set addstar_DB = 0
+    end
+    add_poll_args run
+    add_poll_labels run
+    command $run
+  end
+
+  # success
+  task.exit    0
+    # convert 'stdout' to book format
+    ipptool2book stdout addPendingExp -key add_id -uniq -setword dbname $options:0 -setword pantaskState INIT
+    if ($VERBOSE > 2)
+      book listbook addPendingExp
+    end
+
+    # delete existing entries in the appropriate pantaskStates
+    process_cleanup addPendingExp
+  end
+
+  # default exit status
+  task.exit    default
+    showcommand failure
+  end
+
+  task.exit    crash
+    showcommand crash
+  end
+
+  # operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
 # run the addstar script on pending exposures
 task	       addstar.exp.run
@@ -132,5 +252,6 @@
     book getword addPendingExp $pageName exp_tag -var EXP_TAG
     book getword addPendingExp $pageName add_id -var ADD_ID
-    book getword addPendingExp $pageName camroot -var CAMROOT
+    book getword addPendingExp $pageName stageroot -var STAGEROOT
+    book getword addPendingExp $pageName stage -var STAGE  
     book getword addPendingExp $pageName workdir -var WORKDIR_TEMPLATE
     book getword addPendingExp $pageName reduction -var REDUCTION
@@ -157,10 +278,20 @@
 
     ## generate outroot specific to this exposure (& chip)
-    sprintf outroot "%s/%s/%s.add.%s" $WORKDIR $EXP_TAG $EXP_TAG $ADD_ID
+
+    if ("$STAGE" == "cam")
+	sprintf outroot "%s/%s/%s.add.%s" $WORKDIR $EXP_TAG $EXP_TAG $ADD_ID
+    end
+    if ("$STAGE" == "staticsky")
+	sprintf outroot "%s.add.%s" $STAGEROOT $ADD_ID
+    end
+    if ("$STAGE" == "stack")
+	sprintf outroot "%s.add.%s" $STAGEROOT $ADD_ID
+    end
+  
 
     stdout $LOGDIR/addstar.exp.log
     stderr $LOGDIR/addstar.exp.log
 
-    $run = addstar_run.pl --exp_tag $EXP_TAG --add_id $ADD_ID --camera $CAMERA --dvodb $DVODB --camroot $CAMROOT --outroot $outroot --redirect-output
+    $run = addstar_run.pl --add_id $ADD_ID --camera $CAMERA --dvodb $DVODB --stage $STAGE --stageroot $STAGEROOT --outroot $outroot --redirect-output
     if ("$REDUCTION" != "NULL")
       $run = $run --reduction $REDUCTION
Index: /branches/eam_branches/ipp-20110404/ippTasks/lap.pro
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTasks/lap.pro	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTasks/lap.pro	(revision 31439)
@@ -0,0 +1,370 @@
+## lap.pro : -*- sh -*-
+
+check.globals
+
+$lapSeq:n = 0
+
+book init lapRuns
+
+macro lap.add.sequence
+  if ($0 != 2) 
+    echo "USAGE: lap.add.sequence (seq_id)"
+    break
+  end
+  if ($?lapSeq:n == 0) 
+    list lapSeq -add $1
+    return
+  end
+
+  local found
+  $found = 0
+  for i 0 $lapSeq:n
+    if ($lapSeq:$i == $1)
+      $found = 1
+      echo "$lapSeq:$i set"
+      last
+    end
+  end
+
+  if ($found == 0)
+    list lapSeq -add $1
+  end
+end
+
+macro lap.del.sequence
+  if ($0 != 2)
+    echo "USAGE: lap.del.sequence (seq_id)"
+    break
+  end
+  if ($?lapSeq:n == 0)
+    return
+  end
+
+  list lapSeq -del $1
+end
+ 
+
+task           lap.initial.load
+  host         local
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 30
+  npending     1
+
+  task.exec
+    stdout NULL
+    stderr $LOGDIR/lap.load.log
+
+    $run = laptool -pendingrun -state new
+
+    if ($lapSeq:n == 0)
+      break
+    else 
+      option $lapSeq:$lap_N
+      $run = $run -seq_id $lapSeq:$lap_N
+      $lap_N ++
+      if ($lap_N >= $lapSeq:n) set lap_N = 0
+    end
+
+    if ($DB:n == 0)
+      option DEFAULT
+    else
+      option $DB:$lap_DB
+      $run = $run -dbname $DB:$lap_DB
+      $lap_DB ++
+      if ($lap_DB >= $DB:n) set lap_DB = 0
+    end
+
+    command $run
+  end
+  # success
+  task.exit  0
+    book delpage lapNewRuns $options:0
+    ipptool2book stdout lapNewRuns -uniq -key proj
+
+    if ($VERBOSE > 2)
+      book listbook lapNewRuns
+    end
+  end
+  # locked list
+  task.exit    default
+    showcommand failure
+  end
+  task.exit    crash
+    showcommand crash
+  end
+  #operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
+
+task           lap.initial.run
+  host         local
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 600
+# This can probably be increased and spread over hosts in the future.
+  npending     1            
+
+  task.exec
+    stdout NULL
+    stderr $LOGDIR/lap.initial.log
+
+    book npages lapNewRuns -var N
+    if ($N == 0) break
+    if ($NETWORK == 0) break
+
+
+    book getpage lapNewRuns 0 -var pageName -key pantaskState INIT
+    if ("$pageName" == "NULL") break
+
+    book setword lapNewRuns $pageName pantaskState RUN
+    book getword lapNewRuns $pageName lap_id -var LAP_ID
+    book getword lapNewRuns $pageName dbname -var DBNAME
+
+    $run = lap_science.pl --chip_mode --dbname $DBNAME --lap_id $LAP_ID
+
+    command $run
+
+  end
+
+  # success
+  task.exit  0
+    book delpage lapNewRuns $options:0
+    ipptool2book stdout lapNewRuns -uniq -key proj
+
+    if ($VERBOSE > 2)
+      book listbook lapNewRuns
+    end
+  end
+  # locked list
+  task.exit    default
+    showcommand failure
+  end
+  task.exit    crash
+    showcommand crash
+  end
+  #operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
+
+
+
+task           lap.monitor.load
+  host         local
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 30
+  npending     1
+
+  task.exec
+    stdout NULL
+    stderr $LOGDIR/lap.load.log
+
+    $run = laptool -pendingrun -state run
+
+    if ($lapSeq:n != 0)
+      option $lapSeq:$lap_N
+      $run = $run -seq_id $lapSeq:$lap_N
+      $lap_N ++
+      if ($lap_N >= $lapSeq:n) set lap_N = 0
+    end
+
+    if ($DB:n == 0)
+      option DEFAULT
+    else
+      option $DB:$lap_DB
+      $run = $run -dbname $DB:$lap_DB
+      $lap_DB ++
+      if ($lap_DB >= $DB:n) set lap_DB = 0
+    end
+
+    add_poll_labels run
+
+    command $run
+  end
+  # success
+  task.exit  0
+    book delpage lapRuRuns $options:0
+    ipptool2book stdout lapRunRuns -uniq -key lap_id
+
+    if ($VERBOSE > 2)
+      book listbook lapRunRuns
+    end
+  end
+  # locked list
+  task.exit    default
+    showcommand failure
+  end
+  task.exit    crash
+    showcommand crash
+  end
+  #operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
+
+task           lap.monitor.run
+  host         local
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 600
+# This can probably be increased and spread over hosts in the future.
+  npending     1            
+
+  task.exec
+    stdout NULL
+    stderr $LOGDIR/lap.initial.log
+
+    book npages lapRunRuns -var N
+    if ($N == 0) break
+    if ($NETWORK == 0) break
+
+
+    book getpage lapNewRuns 0 -var pageName -key pantaskState INIT
+    if ("$pageName" == "NULL") break
+
+    book setword lapNewRuns $pageName pantaskState RUN
+    book getword lapNewRuns $pageName lap_id -var LAP_ID
+    book getword lapNewRuns $pageName dbname -var DBNAME
+
+    $run = lap_science.pl --monitor_mode --dbname $DBNAME --lap_id $LAP_ID
+
+    command $run
+
+  end
+
+  # success
+  task.exit  0
+    book delpage lapRunRuns $options:0
+    ipptool2book stdout lapRunRuns -uniq -key proj
+
+    if ($VERBOSE > 2)
+      book listbook lapRunRuns
+    end
+  end
+  # locked list
+  task.exit    default
+    showcommand failure
+  end
+  task.exit    crash
+    showcommand crash
+  end
+  #operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
+
+
+
+task           lap.cleanup.load
+  host         local
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 30
+  npending     1
+
+  task.exec
+    stdout NULL
+    stderr $LOGDIR/lap.load.log
+
+    $run = laptool -pendingrun -state done
+
+    if ($lapSeq:n != 0)
+      option $lapSeq:$lap_N
+      $run = $run -seq_id $lapSeq:$lap_N
+      $lap_N ++
+      if ($lap_N >= $lapSeq:n) set lap_N = 0
+    end
+
+    if ($DB:n == 0)
+      option DEFAULT
+    else
+      option $DB:$lap_DB
+      $run = $run -dbname $DB:$lap_DB
+      $lap_DB ++
+      if ($lap_DB >= $DB:n) set lap_DB = 0
+    end
+
+    add_poll_labels run
+
+    command $run
+  end
+  # success
+  task.exit  0
+    book delpage lapDoneRuns $options:0
+    ipptool2book stdout lapDoneRuns -uniq -key lap_id
+
+    if ($VERBOSE > 2)
+      book listbook lapRuns
+    end
+  end
+  # locked list
+  task.exit    default
+    showcommand failure
+  end
+  task.exit    crash
+    showcommand crash
+  end
+  #operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
+
+task           lap.cleanup.run
+  host         local
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 600
+# This can probably be increased and spread over hosts in the future.
+  npending     1            
+
+  task.exec
+    stdout NULL
+    stderr $LOGDIR/lap.cleanup.log
+
+    book npages lapNewRuns -var N
+    if ($N == 0) break
+    if ($NETWORK == 0) break
+
+
+    book getpage lapNewRuns 0 -var pageName -key pantaskState INIT
+    if ("$pageName" == "NULL") break
+
+    book setword lapDoneRuns $pageName pantaskState RUN
+    book getword lapDoneRuns $pageName lap_id -var LAP_ID
+    book getword lapDoneRuns $pageName dbname -var DBNAME
+
+    $run = lap_science.pl --cleanup_mode --dbname $DBNAME --lap_id $LAP_ID
+
+    command $run
+
+  end
+
+  # success
+  task.exit  0
+    book delpage lapDoneRuns $options:0
+    ipptool2book stdout lapDoneRuns -uniq -key proj
+
+    if ($VERBOSE > 2)
+      book listbook lapDoneRuns
+    end
+  end
+  # locked list
+  task.exit    default
+    showcommand failure
+  end
+  task.exit    crash
+    showcommand crash
+  end
+  #operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
Index: /branches/eam_branches/ipp-20110404/ippTasks/survey.pro
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTasks/survey.pro	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTasks/survey.pro	(revision 31439)
@@ -231,6 +231,6 @@
 
 macro survey.add.addstar
-  if ($0 != 4)
-    echo "USAGE: survey.add.addstar (label) (dvodb) (minidvodb_group)"
+  if ($0 != 5)
+    echo "USAGE: survey.add.addstar (label) (dvodb) (minidvodb_group) (stage)"
     break
   end
@@ -238,4 +238,5 @@
   book setword SURVEY_ADDSTAR $1 DVODB $2
   book setword SURVEY_ADDSTAR $1 MINIDVODB_GROUP $3
+  book setword SURVEY_ADDSTAR $1 STAGE $4  
   book setword SURVEY_ADDSTAR $1 STATE PENDING
 end
@@ -753,4 +754,6 @@
     book getword SURVEY_ADDSTAR $label DVODB -var dvodb
     book getword SURVEY_ADDSTAR $label MINIDVODB_GROUP -var minidvodb_group
+    book getword SURVEY_ADDSTAR $label STAGE -var stage
+    
   
  #   $run = addtool -definebyquery -destreaked -label $label -set_dvodb $dbodb
@@ -763,6 +766,12 @@
     end
     
-    $run = $run -definebyquery -destreaked -label $label -set_dvodb $dvodb -set_minidvodb_group $minidvodb_group -set_minidvodb -set_label $minidvodb_group
+    $run = $run -definebyquery -label $label -set_dvodb $dvodb -set_minidvodb_group $minidvodb_group -set_minidvodb -set_label $minidvodb_group -stage $stage
     # echo $run
+    if ($stage == 'cam') 
+        #only queue destreaked cams. stacks and staticsky don't need this
+        $run = $run -destreaked
+    end
+   
+
     command $run
   end
Index: /branches/eam_branches/ipp-20110404/ippToPsps/config/detection/map.xml
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/config/detection/map.xml	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/config/detection/map.xml	(revision 31439)
@@ -146,4 +146,10 @@
           <map pspsName="momentXY" ippType="TFLOAT" ippName="MOMENTS_XY" comment=" moment XY (unit = arcsec)"/> -->
           <map pspsName="momentYY" ippType="TFLOAT" ippName="MOMENTS_YY" comment=" momeny YY (unit = arcsec)"/> -->
+          <map pspsName="apMag" ippType="TFLOAT" ippName="AP_MAG" comment=" Aperture magnitude (unit = magnitude)"/> 
+    <!--  **MISSING** <map pspsName="apMagErr" ippType="TFLOAT" ippName="" comment=" Aperture magnitude error (unit = magnitude)"/> -->
+    <!--  **MISSING** <map pspsName="kronFlux" ippType="TFLOAT" ippName="" comment=" Kron flux (unit = magnitude)"/> -->
+    <!--  **MISSING** <map pspsName="kronFluxErr" ippType="TFLOAT" ippName="" comment=" Kron flux error (unit = magnitude)"/> -->
+    <!--  **MISSING** <map pspsName="kronRad" ippType="TFLOAT" ippName="" comment=" Kron radius (unit = arcsecs)"/> -->
+    <!--  **MISSING** <map pspsName="kronRadErr" ippType="TFLOAT" ippName="" comment=" Kron radius error (unit = arcsecs)"/> -->
     <!--  **MISSING** <map pspsName="crLikelihood" ippType="TFLOAT" ippName="" comment="Likelihood the source is a cosmic ray"/> -->
     <!--  **MISSING** <map pspsName="extendedLikelihood" ippType="TFLOAT" ippName="" comment="Likelihood the source is extended"/> -->
Index: /branches/eam_branches/ipp-20110404/ippToPsps/config/detection/tables.xml
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/config/detection/tables.xml	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/config/detection/tables.xml	(revision 31439)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<tableDescriptions type="det">
+<tableDescriptions type="detection">
   <table name="FrameMeta">
     <column name="frameID" type="TLONG" default="0" comment="unique exposure/frame identifier."></column>
@@ -146,4 +146,10 @@
     <column name="momentXY" type="TFLOAT" default="-999" comment=" moment XY (unit = arcsec)"></column>
     <column name="momentYY" type="TFLOAT" default="-999" comment=" momeny YY (unit = arcsec)"></column>
+    <column name="apMag" type="TFLOAT" default="-999" comment=" Aperture magnitude (unit = magnitude)"></column>
+    <column name="apMagErr" type="TFLOAT" default="-999" comment=" Aperture magnitude error (unit = magnitude)"></column>
+    <column name="kronFlux" type="TFLOAT" default="-999" comment=" Kron flux (unit = magnitude)"></column>
+    <column name="kronFluxErr" type="TFLOAT" default="-999" comment=" Kron flux error (unit = magnitude)"></column>
+    <column name="kronRad" type="TFLOAT" default="-999" comment=" Kron radius (unit = arcsecs)"></column>
+    <column name="kronRadErr" type="TFLOAT" default="-999" comment=" Kron radius error (unit = arcsecs)"></column>
     <column name="crLikelihood" type="TFLOAT" default="-999" comment="Likelihood the source is a cosmic ray"></column>
     <column name="extendedLikelihood" type="TFLOAT" default="-999" comment="Likelihood the source is extended"></column>
Index: /branches/eam_branches/ipp-20110404/ippToPsps/config/init/data.xml
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/config/init/data.xml	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/config/init/data.xml	(revision 31439)
@@ -4,6 +4,6 @@
 
  <table name="StackType">
-  <row stackTypeID="0" stackType="NIGHTLY_STACK" />
-  <row stackTypeID="1" stackType="DEEP_STACK" />
+  <row stackTypeID="0" name="NIGHTLY_STACK" description="Nightly stacks"/>
+  <row stackTypeID="1" name="DEEP_STACK" description="Deep stacks"/>
  </table>
 
Index: /branches/eam_branches/ipp-20110404/ippToPsps/config/init/tables.vot
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/config/init/tables.vot	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/config/init/tables.vot	(revision 31439)
@@ -0,0 +1,430 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<VOTABLE version="1.1">
+  <RESOURCE>
+    <TABLE name="Filter">
+      <DESCRIPTION>VOTable description of PSPS table Filter</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="filterID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>filter ID: g=1, r=2, i=3, z=4, y=5, w=6, ...</DESCRIPTION>
+      </FIELD>
+      <FIELD name="filterType" arraysize="100" datatype="char">
+        <DESCRIPTION>filter name: g,r,i,z,y, etc.</DESCRIPTION>
+      </FIELD>
+      <FIELD name="filterSpec" arraysize="100" datatype="char">
+        <DESCRIPTION>No comment</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA>
+        <TR><TD>1</TD><TD>g</TD></TR>
+        <TR><TD>2</TD><TD>r</TD></TR>
+        <TR><TD>3</TD><TD>i</TD></TR>
+        <TR><TD>4</TD><TD>z</TD></TR>
+        <TR><TD>5</TD><TD>y</TD></TR>
+        <TR><TD>6</TD><TD>z</TD></TR>
+        </TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="FitModel">
+      <DESCRIPTION>VOTable description of PSPS table FitModel</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="fitModelID" arraysize="1" datatype="short">
+        <DESCRIPTION>indentifier of alternate model fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="name" arraysize="100" datatype="char">
+        <DESCRIPTION>model name</DESCRIPTION>
+      </FIELD>
+      <FIELD name="description" arraysize="100" datatype="char">
+        <DESCRIPTION>string describing the model</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param1" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param2" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param3" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param4" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param5" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param6" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param7" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param8" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param9" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param10" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param11" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 11</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param12" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 12</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param13" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 13</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param14" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 14</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param15" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 15</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param16" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 16</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param17" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 17</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param18" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 18</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param19" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 19</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param20" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 20</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param21" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 21</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param22" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 22</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param23" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 23</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param24" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 24</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param25" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 25</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param26" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 26</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param27" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 27</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param28" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 28</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param29" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 29</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param30" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 30</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param31" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 31</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param32" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 32</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param33" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 33</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param34" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 34</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param35" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 35</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param36" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 36</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param37" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 37</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param38" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 38</DESCRIPTION>
+      </FIELD>
+      <FIELD name="param39" arraysize="100" datatype="char">
+        <DESCRIPTION>description of model parameter 39</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA>
+          <TR><TD>0</TD><TD>PS_MODEL_PSF_AVG</TD><TD>Psf avg fit</TD></TR>
+          <TR><TD>1</TD><TD>PS_MODEL_PSF</TD><TD>Psf fit</TD></TR>
+          <TR><TD>2</TD><TD>PS_MODEL_DEV</TD><TD>deVaucouleur Fit</TD></TR>
+          <TR><TD>3</TD><TD>PS_MODEL_EXP</TD><TD>Exponential Fit</TD></TR>
+          <TR><TD>4</TD><TD>PS_MODEL_SERSIC</TD><TD>Sersic Fit</TD></TR>
+        </TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="PhotozRecipe">
+      <DESCRIPTION>VOTable description of PSPS table PhotozRecipe</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="recipeID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>recipe index</DESCRIPTION>
+      </FIELD>
+      <FIELD name="description" arraysize="100" datatype="char">
+        <DESCRIPTION>string describing the recipe</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="Survey">
+      <DESCRIPTION>VOTable description of PSPS table Survey</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>index of survey type</DESCRIPTION>
+      </FIELD>
+      <FIELD name="name" arraysize="100" datatype="char">
+        <DESCRIPTION>survey name</DESCRIPTION>
+      </FIELD>
+      <FIELD name="description" arraysize="100" datatype="char">
+        <DESCRIPTION>survey description</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA>
+          <TR><TD>0</TD><TD>3PI</TD><TD>PS1 3PI Survey</TD></TR>
+          <TR><TD>1</TD><TD>MD01</TD><TD>PS1 MD01 XMM-LSS-DXS 022224-043000</TD></TR>
+          <TR><TD>2</TD><TD>MD02</TD><TD>PS1 MD02 CDFS/GOODS/GEMS 033224-274800</TD></TR>
+          <TR><TD>3</TD><TD>MD03</TD><TD>PS1 MD03 IFA/Lynx 084300+444000</TD></TR>
+          <TR><TD>4</TD><TD>MD04</TD><TD>PS1 MD04 COSMOS 100000+021200</TD></TR>
+          <TR><TD>5</TD><TD>MD05</TD><TD>PS1 MD05 Lockman-DXS 110000+570000</TD></TR>
+          <TR><TD>6</TD><TD>MD06</TD><TD>PS1 MD06 NGC 4258 121857+471814</TD></TR>
+          <TR><TD>7</TD><TD>MD07</TD><TD>PS1 MD07 VISTA-Video1 140000+050000</TD></TR>
+          <TR><TD>8</TD><TD>MD08</TD><TD>PS1 MD08 EliasN1-DXS 160000+570000</TD></TR>
+          <TR><TD>9</TD><TD>MD09</TD><TD>PS1 MD09 Vimos4-DXS-SSA 220000+003000</TD></TR>
+          <TR><TD>10</TD><TD>MD10</TD><TD>PS1 MD10 Deep2 233000+000000</TD></TR>
+          <TR><TD>11</TD><TD>M31</TD><TD>PS1 M31 Andromeda 004242+411600</TD></TR>
+          <TR><TD>12</TD><TD>STS1</TD><TD>PS1 STS1 Outskirts of Bulge 195048+170339</TD></TR>
+          <TR><TD>26</TD><TD>STS2</TD><TD>PS1 STS2 Hyades 004000+150000</TD></TR>
+          <TR><TD>27</TD><TD>STS3</TD><TD>PS1 STS3 Praesepe 083000+200000</TD></TR>
+          <TR><TD>13</TD><TD>CAL01</TD><TD>PS1 Cal North Pole 000000+900000</TD></TR>
+          <TR><TD>14</TD><TD>CAL02</TD><TD>PS1 Cal SA92 Dense Landolt Std Field 005808+004232</TD></TR>
+          <TR><TD>15</TD><TD>CAL03</TD><TD>PS1 Cal Perseus Cluster / Abell 426 031900+413300</TD></TR>
+          <TR><TD>16</TD><TD>CAL04</TD><TD>PS1 Cal SA95 Dense Landolt Std Field 065207+001710</TD></TR>
+          <TR><TD>17</TD><TD>CAL05</TD><TD>PS1 Cal Taurus dark cloud (diverse extinction) 043000+250000</TD></TR>
+          <TR><TD>18</TD><TD>CAL06</TD><TD>PS1 Cal SA98 Densle Landolt Std Field 065207+001710</TD></TR>
+          <TR><TD>19</TD><TD>CAL07</TD><TD>PS1 Cal M81-M82-HolmIX (Local Group) 095640+692200</TD></TR>
+          <TR><TD>20</TD><TD>CAL08</TD><TD>PS1 Cal Virgo Cluster (Center) 123000+130000</TD></TR>
+          <TR><TD>21</TD><TD>CAL09</TD><TD>PS1 Cal Hercules Cluster (Center) 160508+1745+28</TD></TR>
+          <TR><TD>22</TD><TD>CAL10</TD><TD>PS1 Cal M17-M24 Region 181400+000544</TD></TR>
+          <TR><TD>23</TD><TD>CAL11</TD><TD>PS1 Cal SA110 Dense Landolt Std Field 184207+000544</TD></TR>
+          <TR><TD>24</TD><TD>CAL12</TD><TD>PS1 Cal Kepler Mission Astrometric field 192240+443000</TD></TR>
+          <TR><TD>25</TD><TD>CAL13</TD><TD>PS1 Cal 3C454.1 (Northern field) 225033+712919</TD></TR>
+          <TR><TD>28</TD><TD>SSS</TD><TD>PS1 Solar System Sweet Spot Survey</TD></TR>
+        </TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="CameraConfig">
+      <DESCRIPTION>VOTable description of PSPS table CameraConfig</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="cameraID" arraysize="1" datatype="short">
+        <DESCRIPTION>camera identification number</DESCRIPTION>
+      </FIELD>
+      <FIELD name="cameraConfigID" arraysize="1" datatype="short">
+        <DESCRIPTION>configuration identification number</DESCRIPTION>
+      </FIELD>
+      <FIELD name="endDate" arraysize="1" datatype="float">
+        <DESCRIPTION> ending date of this configuration in MJD (unit = day)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="configDetails" arraysize="100" datatype="char">
+        <DESCRIPTION>text/table giving the details of the camera configuration</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="PhotoCal">
+      <DESCRIPTION>VOTable description of PSPS table PhotoCal</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="photoCalID" arraysize="1" datatype="int">
+        <DESCRIPTION>numerical code for this reduction</DESCRIPTION>
+      </FIELD>
+      <FIELD name="filterID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>filter id</DESCRIPTION>
+      </FIELD>
+      <FIELD name="photoCodeDesc" arraysize="100" datatype="char">
+        <DESCRIPTION>Photometry reduction code name</DESCRIPTION>
+      </FIELD>
+      <FIELD name="AB" arraysize="1" datatype="float">
+        <DESCRIPTION>AB magnitude</DESCRIPTION>
+      </FIELD>
+      <FIELD name="zeropoint" arraysize="1" datatype="float">
+        <DESCRIPTION>photometric zero point (excluding long term variation)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="extinction" arraysize="1" datatype="float">
+        <DESCRIPTION>photometric extinction term (excluding long term variation)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="colorterm" arraysize="1" datatype="float">
+        <DESCRIPTION>photometric color term (excluding long term variation)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="colorExtn" arraysize="1" datatype="float">
+        <DESCRIPTION>photometric color dependent extinction (excluding long term variation)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="orphanCalColor" arraysize="1" datatype="float">
+        <DESCRIPTION>color adopted for magnitude calculation</DESCRIPTION>
+      </FIELD>
+      <FIELD name="orphanCalColorErr" arraysize="1" datatype="float">
+        <DESCRIPTION>error in calibrating color</DESCRIPTION>
+      </FIELD>
+      <FIELD name="startDate" arraysize="1" datatype="float">
+        <DESCRIPTION> starting date of this configuration in MJD (unit = day)</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="SkyCell">
+      <DESCRIPTION>VOTable description of PSPS table SkyCell</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="skyCellID" arraysize="1" datatype="int">
+        <DESCRIPTION>indentifier of the sky cell</DESCRIPTION>
+      </FIELD>
+      <FIELD name="projectionCellID" arraysize="1" datatype="int">
+        <DESCRIPTION>indentifier of the projection cell</DESCRIPTION>
+      </FIELD>
+      <FIELD name="partitionKey" arraysize="1" datatype="long">
+        <DESCRIPTION>fgetPANobjID(skyCell_center_ra,  skyCell_center_dec, zHeight)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="regionID" arraysize="1" datatype="long">
+        <DESCRIPTION>region identifier in the Region table</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="ProjectionCell">
+      <DESCRIPTION>VOTable description of PSPS table ProjectionCell</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="projectionCellID" arraysize="1" datatype="int">
+        <DESCRIPTION>projection cell unique identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="partitionKey" arraysize="1" datatype="long">
+        <DESCRIPTION>fGetPanObjID(crval1,crval2)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="primaryCellRegionID" arraysize="1" datatype="long">
+        <DESCRIPTION>reference to the primary cell region definition in the Region table</DESCRIPTION>
+      </FIELD>
+      <FIELD name="projectionCellRegionID" arraysize="1" datatype="long">
+        <DESCRIPTION>reference to the projectio cell region definition in the Region table)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ctype1" arraysize="100" datatype="char">
+        <DESCRIPTION>name of astrometric projection in RA</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ctype2" arraysize="100" datatype="char">
+        <DESCRIPTION>name of astrometric projection in DEC</DESCRIPTION>
+      </FIELD>
+      <FIELD name="crval1" arraysize="1" datatype="double">
+        <DESCRIPTION> RA corresponding to reference pixel (unit = deg)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="crval2" arraysize="1" datatype="double">
+        <DESCRIPTION> DEC corresponding to reference pixel (unit = deg)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="crpix1" arraysize="1" datatype="double">
+        <DESCRIPTION>reference pixel value for RA</DESCRIPTION>
+      </FIELD>
+      <FIELD name="crpix2" arraysize="1" datatype="double">
+        <DESCRIPTION>reference pixel value for DEC</DESCRIPTION>
+      </FIELD>
+      <FIELD name="pc001001" arraysize="1" datatype="double">
+        <DESCRIPTION>elements of rotation/Dcale matrix</DESCRIPTION>
+      </FIELD>
+      <FIELD name="pc001002" arraysize="1" datatype="double">
+        <DESCRIPTION>elements of rotation/Dcale matrix</DESCRIPTION>
+      </FIELD>
+      <FIELD name="pc002001" arraysize="1" datatype="double">
+        <DESCRIPTION>elements of rotation/Dcale matrix</DESCRIPTION>
+      </FIELD>
+      <FIELD name="pc002002" arraysize="1" datatype="double">
+        <DESCRIPTION>elements of rotation/Dcale matrix</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="Region">
+      <DESCRIPTION>VOTable description of PSPS table Region</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="regionID" arraysize="1" datatype="long">
+        <DESCRIPTION>Unique Region identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="id" arraysize="1" datatype="long">
+        <DESCRIPTION>Custom Identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="type" arraysize="100" datatype="char">
+        <DESCRIPTION>Region type</DESCRIPTION>
+      </FIELD>
+      <FIELD name="comment" arraysize="100" datatype="char">
+        <DESCRIPTION>Comment</DESCRIPTION>
+      </FIELD>
+      <FIELD name="area" arraysize="1" datatype="double">
+        <DESCRIPTION>Area covered by the region</DESCRIPTION>
+      </FIELD>
+      <FIELD name="regionBinary" arraysize="100" datatype="char">
+        <DESCRIPTION>Binary object managed by the spatial library</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="StackType">
+      <DESCRIPTION>VOTable description of PSPS table StackType</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="stackTypeID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>stack type identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="name" arraysize="100" datatype="char">
+        <DESCRIPTION>stack type name</DESCRIPTION>
+      </FIELD>
+      <FIELD name="description" arraysize="100" datatype="char">
+        <DESCRIPTION>stack type description</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA>
+          <TR><TD>0</TD><TD>NIGHTLY_STACK</TD><TD>Nightly stack</TD></TR>
+          <TR><TD>1</TD><TD>DEEP_STACK</TD><TD>Deep stack</TD></TR>
+        </TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="ImageFlags">
+      <DESCRIPTION>VOTable description of PSPS table ImageFlags</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="name" arraysize="100" datatype="char">
+        <DESCRIPTION>Name of flag</DESCRIPTION>
+      </FIELD>
+      <FIELD name="value" arraysize="1" datatype="long">
+        <DESCRIPTION>Flag value</DESCRIPTION>
+      </FIELD>
+      <FIELD name="description" arraysize="100" datatype="char">
+        <DESCRIPTION>Description of the flag</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="DetectionFlags">
+      <DESCRIPTION>VOTable description of PSPS table DetectionFlags</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="name" arraysize="100" datatype="char">
+        <DESCRIPTION>Name of flag</DESCRIPTION>
+      </FIELD>
+      <FIELD name="value" arraysize="1" datatype="long">
+        <DESCRIPTION>Flag value</DESCRIPTION>
+      </FIELD>
+      <FIELD name="description" arraysize="100" datatype="char">
+        <DESCRIPTION>Description of the flag</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+  </RESOURCE>
+</VOTABLE>
Index: /branches/eam_branches/ipp-20110404/ippToPsps/config/init/tables.xml
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/config/init/tables.xml	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/config/init/tables.xml	(revision 31439)
@@ -9,4 +9,5 @@
   <table name="FitModel">
     <column name="fitModelID" type="TSHORT" default="0" comment="indentifier of alternate model fit"></column>
+    <column name="name" type="TSTRING" default=" " comment="model name"></column>
     <column name="description" type="TSTRING" default=" " comment="string describing the model"></column>
     <column name="param1" type="TSTRING" default=" " comment="description of model parameter 1"></column>
@@ -56,6 +57,6 @@
   <table name="Survey">
     <column name="surveyID" type="TBYTE" default="0" comment="index of survey type"></column>
+    <column name="name" type="TSTRING" default=" " comment="survey name"></column>
     <column name="description" type="TSTRING" default=" " comment="survey description"></column>
-    <column name="name" type="TSTRING" default=" " comment="survey name"></column>
   </table>
   <table name="CameraConfig">
@@ -110,5 +111,6 @@
   <table name="StackType">
     <column name="stackTypeID" type="TBYTE" default="0" comment="stack type identifier"></column>
-    <column name="description" type="TSTRING" default=" " comment="survey description"></column>
+    <column name="name" type="TSTRING" default=" " comment="stack type name"></column>
+    <column name="description" type="TSTRING" default=" " comment="stack type description"></column>
   </table>
   <table name="ImageFlags">
Index: /branches/eam_branches/ipp-20110404/ippToPsps/config/stack/map.xml
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/config/stack/map.xml	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/config/stack/map.xml	(revision 31439)
@@ -9,5 +9,5 @@
     <!--  DONE IN CODE <map pspsName="filterID" ippType="TBYTE" ippName="" comment="filter identifier"/> -->
     <!--  DONE IN CODE <map pspsName="stackTypeID" ippType="TBYTE" ippName="" comment="stack type identifier"/> -->
-    <!--  **MISSING** <map pspsName="stackGroupID" ippType="TLONG" ippName="" comment="stack group identifier"/> -->
+    <!--  WILL BE REMOVED <map pspsName="stackGroupID" ippType="TLONG" ippName="" comment="stack group identifier"/> -->
           <map pspsName="magSat" ippType="TFLOAT" ippName="FSATUR" comment="saturation magnitude level"/>
     <!--  **MISSING** <map pspsName="analVer" ippType="TSHORT" ippName="" comment="analysis version index"/> -->
@@ -20,5 +20,5 @@
     <!--  **MISSING** <map pspsName="mean" ippType="TDOUBLE" ippName="" comment="mean PSF FWHM in the stack"/> -->
     <!--  **MISSING** <map pspsName="max" ippType="TDOUBLE" ippName="" comment="maximum PSF FWHM in the stack"/> -->
-    <!--  **MISSING** <map pspsName="photoZero" ippType="TFLOAT" ippName="" comment="local derived photometric zero point"/> -->
+          <map pspsName="photoZero" ippType="TFLOAT" ippName="FPA.ZP" comment="local derived photometric zero point"/>
     <!--  **MISSING** <map pspsName="photoColor" ippType="TFLOAT" ippName="" comment="local derived photometric color term"/> -->
           <map pspsName="ctype1" ippType="TSTRING" ippName="CTYPE1" comment="name of astrometric projection in RA"/>
@@ -44,12 +44,12 @@
     <!--  DONE IN CODE <map pspsName="filterID" ippType="TBYTE" ippName="" comment="filter identifier"/> -->
     <!--  DONE IN CODE <map pspsName="stackTypeID" ippType="TBYTE" ippName="" comment="stack type identifier"/> -->
-    <!--  **MISSING** <map pspsName="stackGroupID" ippType="TLONG" ippName="" comment="stack group id"/> -->
+    <!--  WILL BE REMOVED <map pspsName="stackGroupID" ippType="TLONG" ippName="" comment="stack group id"/> -->
     <!--  DONE IN CODE <map pspsName="surveyID" ippType="TBYTE" ippName="" comment="survey flag identifier"/> -->
     <!--  **MISSING** <map pspsName="primaryF" ippType="TBYTE" ippName="" comment="identifies best stack detection for Stacks overlapping the same region of the sky."/> -->
-    <!--  **MISSING** <map pspsName="stackMetaID" ippType="TLONGLONG" ippName="" comment="stack identifier"/> -->
+    <!--  DONE IN CODE <map pspsName="stackMetaID" ippType="TLONGLONG" ippName="" comment="stack identifier"/> -->
     <!--  DONE IN CODE <map pspsName="skyCellID" ippType="TLONG" ippName="" comment=skycell identifier"/> -->
     <!--  **MISSING** <map pspsName="projectionCellID" ippType="TLONG" ippName="" comment="projection cell identifier"/> -->
     <!--  **MISSING** <map pspsName="stackVer" ippType="TSHORT" ippName="" comment="version number of this stack"/> -->
-    <!--  **MISSING** <map pspsName="obsTime" ippType="TDOUBLE" ippName="" comment=" Time of mid observation (unit = day)"/> -->
+    <!--  DONE IN CODE <map pspsName="obsTime" ippType="TDOUBLE" ippName="" comment=" Time of mid observation (unit = day)"/> -->
           <map pspsName="xPos" ippType="TFLOAT" ippName="X_PSF" comment="measured x on CCD from PSF fit"/>
           <map pspsName="yPos" ippType="TFLOAT" ippName="Y_PSF" comment="measured y on CCD from PSF fit"/>
@@ -74,5 +74,5 @@
     <!--  **MISSING** <map pspsName="dataRelease" ippType="TBYTE" ippName="" comment="Data release when this detection was originally taken."/> -->
   </table>
-  <table name="StackApFlx" ippfitsextension="SkyChip.xrad">
+  <table name="StackApFlx" ippfitsextension="SkyChip.xsrc">
     <!--  **MISSING** <map pspsName="objID" ippType="TLONGLONG" ippName="" comment="ODM object identifier"/> -->
     <!--  **MISSING** <map pspsName="stackDetectID" ippType="TLONGLONG" ippName="" comment="ODM detection identifier"/> -->
@@ -81,8 +81,8 @@
     <!--  DONE IN CODE <map pspsName="filterID" ippType="TBYTE" ippName="" comment="filter identifier"/> -->
     <!--  DONE IN CODE <map pspsName="stackTypeID" ippType="TBYTE" ippName="" comment="stack type identifier"/> -->
-    <!--  **MISSING** <map pspsName="stackGroupID" ippType="TLONG" ippName="" comment="stack group id"/> -->
+    <!--  WILL BE REMOVED <map pspsName="stackGroupID" ippType="TLONG" ippName="" comment="stack group id"/> -->
     <!--  DONE IN CODE <map pspsName="surveyID" ippType="TBYTE" ippName="" comment="survey flag identifier"/> -->
     <!--  **MISSING** <map pspsName="primaryF" ippType="TBYTE" ippName="" comment="identifies best stack detection for Stacks overlapping the same region of the sky."/> -->
-    <!--  **MISSING** <map pspsName="stackMetaID" ippType="TLONGLONG" ippName="" comment="stack identifier"/> -->
+    <!--  DONE IN CODE <map pspsName="stackMetaID" ippType="TLONGLONG" ippName="" comment="stack identifier"/> -->
     <!--  **MISSING** <map pspsName="isophotMag" ippType="TFLOAT" ippName="" comment="isophotal magnitude"/> -->
     <!--  **MISSING** <map pspsName="isophotMagErr" ippType="TFLOAT" ippName="" comment="estimated error in isophotal magnitude"/> -->
@@ -237,15 +237,15 @@
     <!--  DONE IN CODE <map pspsName="filterID" ippType="TBYTE" ippName="" comment="filter identifier"/> -->
     <!--  DONE IN CODE <map pspsName="stackTypeID" ippType="TBYTE" ippName="" comment="stack type identifier"/> -->
-    <!--  **MISSING** <map pspsName="stackGroupID" ippType="TLONG" ippName="" comment="stack group id"/> -->
+    <!--  WILL BE REMOVED <map pspsName="stackGroupID" ippType="TLONG" ippName="" comment="stack group id"/> -->
     <!--  DONE IN CODE <map pspsName="surveyID" ippType="TBYTE" ippName="" comment="survey flag identifier"/> -->
     <!--  **MISSING** <map pspsName="primaryF" ippType="TBYTE" ippName="" comment="identifies best stack detection for Stacks overlapping the same region of the sky."/> -->
-    <!--  **MISSING** <map pspsName="stackMetaID" ippType="TLONGLONG" ippName="" comment="stack identifier"/> -->
-    <!--  **MISSING** <map pspsName="deVRadius" ippType="TFLOAT" ippName="" comment="deVaucouleurs radius"/> -->
+    <!--  DONE IN CODE <map pspsName="stackMetaID" ippType="TLONGLONG" ippName="" comment="stack identifier"/> -->
+    <!--  DONE IN CODE <map pspsName="deVRadius" ippType="TFLOAT" ippName="" comment="deVaucouleurs radius"/> -->
     <!--  **MISSING** <map pspsName="deVRadiusErr" ippType="TFLOAT" ippName="" comment="estimated error in deVaucouleurs radius"/> -->
-    <!--  **MISSING** <map pspsName="deVMag" ippType="TFLOAT" ippName="" comment="deVaucouleurs magntiude"/> -->
-    <!--  **MISSING** <map pspsName="deVMagErr" ippType="TFLOAT" ippName="" comment="estimated error in deV_mag"/> -->
-    <!--  **MISSING** <map pspsName="deVAb" ippType="TFLOAT" ippName="" comment="deVaucoulerus axis ratio"/> -->
+    <!--  DONE IN CODE <map pspsName="deVMag" ippType="TFLOAT" ippName="" comment="deVaucouleurs magntiude"/> -->
+    <!--  DONE IN CODE <map pspsName="deVMagErr" ippType="TFLOAT" ippName="" comment="estimated error in deV_mag"/> -->
+    <!--  DONE IN CODE <map pspsName="deVAb" ippType="TFLOAT" ippName="" comment="deVaucoulerus axis ratio"/> -->
     <!--  **MISSING** <map pspsName="deVAbErr" ippType="TFLOAT" ippName="" comment="estimated error in deVaucoulerus axis ratio"/> -->
-    <!--  **MISSING** <map pspsName="deVPhi" ippType="TFLOAT" ippName="" comment="estmated phi of deVaucouleurs axis"/> -->
+    <!--  DONE IN CODE <map pspsName="deVPhi" ippType="TFLOAT" ippName="" comment="estmated phi of deVaucouleurs axis"/> -->
     <!--  **MISSING** <map pspsName="deVPhiErr" ippType="TFLOAT" ippName="" comment="estmated error of phi of deVaucouleurs axis"/> -->
     <!--  **MISSING** <map pspsName="raDeVOff" ippType="TFLOAT" ippName="" comment="Offset in RA of deVaucouleurs fit from PSF RA"/> -->
@@ -255,32 +255,32 @@
     <!--  **MISSING** <map pspsName="deVCf" ippType="TFLOAT" ippName="" comment="deVaucouleurs fit coverage factor"/> -->
     <!--  **MISSING** <map pspsName="deVLikelihood" ippType="TFLOAT" ippName="" comment="deVaucouleurs fit likelihood factor"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar11" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar12" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar13" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar14" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar15" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar16" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar17" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar22" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar23" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar24" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar25" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar26" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar27" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar33" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar34" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar35" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar36" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar37" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar44" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar45" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar46" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar47" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar55" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar56" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar57" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar66" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar67" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
-    <!--  **MISSING** <map pspsName="deVCovar77" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar11" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar12" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar13" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar14" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar15" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar16" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar17" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar22" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar23" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar24" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar25" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar26" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar27" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar33" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar34" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar35" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar36" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar37" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar44" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar45" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar46" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar47" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar55" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar56" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar57" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar66" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar67" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
+    <!--  DONE IN CODE <map pspsName="deVCovar77" ippType="TFLOAT" ippName="" comment="covariance for deVaucouleurs fit"/> -->
     <!--  **MISSING** <map pspsName="expRadius" ippType="TFLOAT" ippName="" comment="Exponential fit radius"/> -->
     <!--  **MISSING** <map pspsName="expRadiusErr" ippType="TFLOAT" ippName="" comment="estimated error in Exponential fit radius"/> -->
@@ -297,32 +297,32 @@
     <!--  **MISSING** <map pspsName="expCf" ippType="TFLOAT" ippName="" comment="Exponential fit coverage factor"/> -->
     <!--  **MISSING** <map pspsName="expLikelihood" ippType="TFLOAT" ippName="" comment="Exponential fit likelihood factor"/> -->
-    <!--  **MISSING** <map pspsName="expCovar11" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar12" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar13" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar14" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar15" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar16" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar17" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar22" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar23" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar24" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar25" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar26" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar27" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar33" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar34" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar35" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar36" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar37" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar44" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar45" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar46" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar47" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar55" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar56" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar57" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar66" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar67" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
-    <!--  **MISSING** <map pspsName="expCovar77" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar11" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar12" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar13" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar14" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar15" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar16" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar17" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar22" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar23" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar24" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar25" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar26" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar27" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar33" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar34" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar35" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar36" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar37" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar44" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar45" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar46" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar47" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar55" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar56" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar57" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar66" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar67" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
+    <!--  DONE IN CODE <map pspsName="expCovar77" ippType="TFLOAT" ippName="" comment="covariance for Exponential fit"/> -->
     <!--  **MISSING** <map pspsName="serRadius" ippType="TFLOAT" ippName="" comment="Sersic radius"/> -->
     <!--  **MISSING** <map pspsName="serRadiusErr" ippType="TFLOAT" ippName="" comment="estimated error in Sersic radius"/> -->
@@ -341,45 +341,45 @@
     <!--  **MISSING** <map pspsName="serCf" ippType="TFLOAT" ippName="" comment="Sersic fit coverage factor"/> -->
     <!--  **MISSING** <map pspsName="serLikelihood" ippType="TFLOAT" ippName="" comment="Sersic fit likelihood factor"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar11" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar12" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar13" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar14" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar15" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar16" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar17" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar18" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar22" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar23" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar24" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar25" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar26" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar27" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar28" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar33" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar34" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar35" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar36" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar37" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar38" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar44" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar45" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar46" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar47" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar48" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar55" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar56" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar57" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar58" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar66" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar67" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar68" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar77" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar78" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
-    <!--  **MISSING** <map pspsName="sersicCovar88" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar11" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar12" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar13" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar14" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar15" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar16" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar17" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar18" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar22" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar23" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar24" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar25" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar26" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar27" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar28" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar33" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar34" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar35" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar36" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar37" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar38" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar44" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar45" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar46" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar47" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar48" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar55" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar56" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar57" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar58" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar66" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar67" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar68" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar77" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar78" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
+    <!--  DONE IN CODE <map pspsName="sersicCovar88" ippType="TFLOAT" ippName="" comment="covariance for Sersic fit"/> -->
     <!--  **MISSING** <map pspsName="activeFlag" ippType="TBYTE" ippName="" comment="indicates whether this detection/orphan is still a detection/orphan"/> -->
     <!--  **MISSING** <map pspsName="dataRelease" ippType="TBYTE" ippName="" comment="Data release when this detection was taken"/> -->
   </table>
   <table name="StackToImage" ippfitsextension="">
-    <!--  **MISSING** <map pspsName="stackMetaID" ippType="TLONGLONG" ippName="" comment="stack identifier"/> -->
+    <!--  DONE IN CODE <map pspsName="stackMetaID" ippType="TLONGLONG" ippName="" comment="stack identifier"/> -->
     <!--  **MISSING** <map pspsName="imageID" ippType="TLONGLONG" ippName="" comment="hashed exposure-ccdID identifier"/> -->
   </table>
Index: /branches/eam_branches/ipp-20110404/ippToPsps/config/stack/tables.vot
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/config/stack/tables.vot	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/config/stack/tables.vot	(revision 31439)
@@ -6,37 +6,106 @@
       <DESCRIPTION>VOTable description of PSPS table StackMeta</DESCRIPTION>
       <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
-      <FIELD name="stackMetaID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="skycellID" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="photoCalID" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="filterID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackTypeID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackGroupID" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="magSat" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="analVer" arraysize="1" datatype="short"></FIELD>
-      <FIELD name="nP2Images" arraysize="1" datatype="short"></FIELD>
-      <FIELD name="completMag" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="astroScat" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="photoScat" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="nAstroRef" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="nPhoRef" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="mean" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="max" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="photoZero" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="photoColor" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="ctype1" arraysize="24" datatype="char"></FIELD>
-      <FIELD name="ctype2" arraysize="24" datatype="char"></FIELD>
-      <FIELD name="crval1" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="crval2" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="crpix1" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="crpix2" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="cdelt1" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="cdelt2" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="pc001001" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="pc001002" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="pc002001" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="pc002002" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="calibModNum" arraysize="1" datatype="short"></FIELD>
-      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte"></FIELD>
+      <FIELD name="stackMetaID" arraysize="1" datatype="long">
+        <DESCRIPTION>stack identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="skycellID" arraysize="1" datatype="int">
+        <DESCRIPTION>skycell region identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>survey flag identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="photoCalID" arraysize="1" datatype="int">
+        <DESCRIPTION>photometry code numerical id</DESCRIPTION>
+      </FIELD>
+      <FIELD name="filterID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>filter identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackTypeID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>stack type identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="magSat" arraysize="1" datatype="float">
+        <DESCRIPTION>saturation magnitude level</DESCRIPTION>
+      </FIELD>
+      <FIELD name="analVer" arraysize="1" datatype="short">
+        <DESCRIPTION>analysis version index</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expTime" arraysize="1" datatype="float">
+        <DESCRIPTION> exposure time (unit = s)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="nP2Images" arraysize="1" datatype="short">
+        <DESCRIPTION>number of P2 images contributing to this cell</DESCRIPTION>
+      </FIELD>
+      <FIELD name="completMag" arraysize="1" datatype="float">
+        <DESCRIPTION>95% completion level in mag</DESCRIPTION>
+      </FIELD>
+      <FIELD name="astroScat" arraysize="1" datatype="float">
+        <DESCRIPTION>astrometric scatter for chip</DESCRIPTION>
+      </FIELD>
+      <FIELD name="photoScat" arraysize="1" datatype="float">
+        <DESCRIPTION>photometric scatter for chip</DESCRIPTION>
+      </FIELD>
+      <FIELD name="nAstroRef" arraysize="1" datatype="int">
+        <DESCRIPTION>number of astrometric reference sources</DESCRIPTION>
+      </FIELD>
+      <FIELD name="nPhoRef" arraysize="1" datatype="int">
+        <DESCRIPTION>number of photometric reference sources</DESCRIPTION>
+      </FIELD>
+      <FIELD name="psfModelID" arraysize="100" datatype="char">
+        <DESCRIPTION>PSF model identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="psfFwhm_mean" arraysize="1" datatype="double">
+        <DESCRIPTION>mean PSF FWHM in the stack</DESCRIPTION>
+      </FIELD>
+      <FIELD name="psfFwhm_max" arraysize="1" datatype="double">
+        <DESCRIPTION>maximum PSF FWHM in the stack</DESCRIPTION>
+      </FIELD>
+      <FIELD name="photoZero" arraysize="1" datatype="float">
+        <DESCRIPTION>local derived photometric zero point</DESCRIPTION>
+      </FIELD>
+      <FIELD name="photoColor" arraysize="1" datatype="float">
+        <DESCRIPTION>local derived photometric color term</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ctype1" arraysize="100" datatype="char">
+        <DESCRIPTION>name of astrometric projection in RA</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ctype2" arraysize="100" datatype="char">
+        <DESCRIPTION>name of astrometric projection in DEC</DESCRIPTION>
+      </FIELD>
+      <FIELD name="crval1" arraysize="1" datatype="double">
+        <DESCRIPTION>RA corresponding to reference pixel</DESCRIPTION>
+      </FIELD>
+      <FIELD name="crval2" arraysize="1" datatype="double">
+        <DESCRIPTION>DEC corresponding to reference pixel</DESCRIPTION>
+      </FIELD>
+      <FIELD name="crpix1" arraysize="1" datatype="double">
+        <DESCRIPTION>reference pixel value for RA</DESCRIPTION>
+      </FIELD>
+      <FIELD name="crpix2" arraysize="1" datatype="double">
+        <DESCRIPTION>reference pixel value for DEC</DESCRIPTION>
+      </FIELD>
+      <FIELD name="cdelt1" arraysize="1" datatype="double">
+        <DESCRIPTION>scale factor for RA</DESCRIPTION>
+      </FIELD>
+      <FIELD name="cdelt2" arraysize="1" datatype="double">
+        <DESCRIPTION>scale factor for DEC</DESCRIPTION>
+      </FIELD>
+      <FIELD name="pc001001" arraysize="1" datatype="double">
+        <DESCRIPTION>elements of rotation/Dcale matrix</DESCRIPTION>
+      </FIELD>
+      <FIELD name="pc001002" arraysize="1" datatype="double">
+        <DESCRIPTION>elements of rotation/Dcale matrix</DESCRIPTION>
+      </FIELD>
+      <FIELD name="pc002001" arraysize="1" datatype="double">
+        <DESCRIPTION>elements of rotation/Dcale matrix</DESCRIPTION>
+      </FIELD>
+      <FIELD name="pc002002" arraysize="1" datatype="double">
+        <DESCRIPTION>elements of rotation/Dcale matrix</DESCRIPTION>
+      </FIELD>
+      <FIELD name="calibModNum" arraysize="1" datatype="short">
+        <DESCRIPTION>calibration modification number</DESCRIPTION>
+      </FIELD>
+      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>Data release</DESCRIPTION>
+      </FIELD>
       <DATA>
         <TABLEDATA></TABLEDATA>
@@ -46,39 +115,148 @@
       <DESCRIPTION>VOTable description of PSPS table StackDetection</DESCRIPTION>
       <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
-      <FIELD name="objID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="stackDetectID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="ippObjID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="ippDetectID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="filterID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackTypeID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackGroupID" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="primaryF" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackMetaID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="skyCellID" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="projectionCellID" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="stackVer" arraysize="1" datatype="short"></FIELD>
-      <FIELD name="obsTime" arraysize="1" datatype="double"></FIELD>
-      <FIELD name="xPos" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="yPos" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="xPosErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="yPosErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="instFlux" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="instFluxErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="peakFlux" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sky" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="skyErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sgSep" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="psfWidMajor" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="psfWidMinor" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="psfTheta" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="psfLikelihood" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="psfCf" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="infoFlag" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="nFrames" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="activeFlag" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="assocDate" arraysize="24" datatype="char"></FIELD>
-      <FIELD name="historyModNum" arraysize="1" datatype="short"></FIELD>
-      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte"></FIELD>
+      <FIELD name="objID" arraysize="1" datatype="long">
+        <DESCRIPTION>ODM object identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackDetectID" arraysize="1" datatype="long">
+        <DESCRIPTION>ODM detection identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ippObjID" arraysize="1" datatype="long">
+        <DESCRIPTION>IPP object identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ippDetectID" arraysize="1" datatype="long">
+        <DESCRIPTION>detection ID generated by IPP</DESCRIPTION>
+      </FIELD>
+      <FIELD name="filterID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>filter identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackTypeID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>stack type identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>survey flag identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="primaryF" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>identifies best stack detection for Stacks overlapping the same region of the sky.</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackMetaID" arraysize="1" datatype="long">
+        <DESCRIPTION>stack identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="skyCellID" arraysize="1" datatype="int">
+        <DESCRIPTION>skycell identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="projectionCellID" arraysize="1" datatype="int">
+        <DESCRIPTION>projection cell identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="obsTime" arraysize="1" datatype="double">
+        <DESCRIPTION> Time of mid observation (unit = day)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="xPos" arraysize="1" datatype="float">
+        <DESCRIPTION>measured x on CCD from PSF fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="yPos" arraysize="1" datatype="float">
+        <DESCRIPTION>measured y on CCD from PSF fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="xPosErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in x</DESCRIPTION>
+      </FIELD>
+      <FIELD name="yPosErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in y</DESCRIPTION>
+      </FIELD>
+      <FIELD name="instFlux" arraysize="1" datatype="float">
+        <DESCRIPTION>PSF instrumental flux</DESCRIPTION>
+      </FIELD>
+      <FIELD name="instFluxErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in instrumental flux</DESCRIPTION>
+      </FIELD>
+      <FIELD name="peakFlux" arraysize="1" datatype="float">
+        <DESCRIPTION>ratio of peak flux to total flux</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sky" arraysize="1" datatype="float">
+        <DESCRIPTION>PSF sky level at source (adu)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="skyErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in sky</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sgSep" arraysize="1" datatype="float">
+        <DESCRIPTION>star/galaxy separator</DESCRIPTION>
+      </FIELD>
+      <FIELD name="psfWidMajor" arraysize="1" datatype="float">
+        <DESCRIPTION>PSF width in major axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="psfWidMinor" arraysize="1" datatype="float">
+        <DESCRIPTION>PSF width in minor axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="psfTheta" arraysize="1" datatype="float">
+        <DESCRIPTION>PSF orientation angle</DESCRIPTION>
+      </FIELD>
+      <FIELD name="psfLikelihood" arraysize="1" datatype="float">
+        <DESCRIPTION>PSF likelihood</DESCRIPTION>
+      </FIELD>
+      <FIELD name="psfCf" arraysize="1" datatype="float">
+        <DESCRIPTION>PSF coverage factor</DESCRIPTION>
+      </FIELD>
+      <FIELD name="momentXX" arraysize="1" datatype="float">
+        <DESCRIPTION> moment XX (unit = arcsec)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="momentXY" arraysize="1" datatype="float">
+        <DESCRIPTION> moment XY (unit = arcsec)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="momentYY" arraysize="1" datatype="float">
+        <DESCRIPTION> moment YY (unit = arcsec)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="momentM3C" arraysize="1" datatype="float">
+        <DESCRIPTION> moment M3C (unit = arcsec)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="momentM3S" arraysize="1" datatype="float">
+        <DESCRIPTION> moment M3S (unit = arcsec)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="momentM4C" arraysize="1" datatype="float">
+        <DESCRIPTION> moment M4C (unit = arcsec)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="momentM4S" arraysize="1" datatype="float">
+        <DESCRIPTION> moment M4S (unit = arcsec)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="momentR1" arraysize="1" datatype="float">
+        <DESCRIPTION> moment R1 (unit = arcsec)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="momentRH" arraysize="1" datatype="float">
+        <DESCRIPTION> moment RH (unit = arcsec)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="apMag" arraysize="1" datatype="float">
+        <DESCRIPTION> Aperture magnitude (unit = magnitude)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="apMagErr" arraysize="1" datatype="float">
+        <DESCRIPTION> Aperture magnitude error (unit = magnitude)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="kronFlux" arraysize="1" datatype="float">
+        <DESCRIPTION> Kron flux (unit = magnitude)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="kronFluxErr" arraysize="1" datatype="float">
+        <DESCRIPTION> Kron flux error (unit = magnitude)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="kronRad" arraysize="1" datatype="float">
+        <DESCRIPTION> Kron radius (unit = arcsecs)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="kronRadErr" arraysize="1" datatype="float">
+        <DESCRIPTION> Kron radius error (unit = arcsecs)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="infoFlag" arraysize="1" datatype="long">
+        <DESCRIPTION>indicator of strange propeties</DESCRIPTION>
+      </FIELD>
+      <FIELD name="nFrames" arraysize="1" datatype="int">
+        <DESCRIPTION>number of frames contributing to source</DESCRIPTION>
+      </FIELD>
+      <FIELD name="activeFlag" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>indicates whether this detection/orphan is still a detection/orphan</DESCRIPTION>
+      </FIELD>
+      <FIELD name="assocDate" arraysize="100" datatype="char">
+        <DESCRIPTION>date object association assigned</DESCRIPTION>
+      </FIELD>
+      <FIELD name="historyModNum" arraysize="1" datatype="short">
+        <DESCRIPTION>modification number in the O-D association history</DESCRIPTION>
+      </FIELD>
+      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>Data release when this detection was originally taken.</DESCRIPTION>
+      </FIELD>
       <DATA>
         <TABLEDATA></TABLEDATA>
@@ -88,158 +266,463 @@
       <DESCRIPTION>VOTable description of PSPS table StackApFlx</DESCRIPTION>
       <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
-      <FIELD name="objID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="stackDetectID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="ippObjID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="ippDetectID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="filterID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackTypeID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackGroupID" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="primaryF" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackMetaID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="isophotMag" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotMagErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotMajAxis" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotMajAxisErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotMinAxis" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotMinAxisErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotMajAxisGrad" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotMinAxisGrad" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotPA" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotPAErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="isophotPAGrad" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="petRadius" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="petRadiusErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="petMag" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="petMagErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="petR50" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="petR50Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="petR90" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="petR90Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="petCf" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR1" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR1Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR1Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR1Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR2" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR2Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR2Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR2Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR3" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR3Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR3Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR3Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR4" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR4Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR4Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR4Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR5" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR5Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR5Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR5Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR6" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR6Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR6Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR6Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR7" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR7Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR7Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR7Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR8" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR8Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR8Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR8Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR9" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR9Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR9Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR9Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR10" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR10Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR10Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="flxR10Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR1" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR1Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR1Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR1Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR2" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR2Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR2Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR2Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR3" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR3Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR3Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR3Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR4" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR4Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR4Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR4Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR5" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR5Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR5Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR5Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR6" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR6Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR6Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR6Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR7" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR7Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR7Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR7Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR8" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR8Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR8Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR8Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR9" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR9Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR9Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR9Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR10" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR10Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR10Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c1flxR10Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR1" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR1Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR1Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR1Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR2" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR2Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR2Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR2Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR3" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR3Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR3Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR3Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR4" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR4Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR4Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR4Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR5" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR5Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR5Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR5Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR6" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR6Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR6Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR6Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR7" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR7Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR7Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR7Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR8" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR8Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR8Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR8Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR9" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR9Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR9Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR9Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR10" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR10Err" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR10Std" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="c2flxR10Fill" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="logC" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="logA" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="activeFlag" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte"></FIELD>
+      <FIELD name="objID" arraysize="1" datatype="long">
+        <DESCRIPTION>ODM object identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackDetectID" arraysize="1" datatype="long">
+        <DESCRIPTION>ODM detection identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ippObjID" arraysize="1" datatype="long">
+        <DESCRIPTION>IPP object identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ippDetectID" arraysize="1" datatype="long">
+        <DESCRIPTION>detection ID generated by IPP</DESCRIPTION>
+      </FIELD>
+      <FIELD name="filterID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>filter identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackTypeID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>stack type identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>survey flag identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="primaryF" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>identifies best stack detection for Stacks overlapping the same region of the sky.</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackMetaID" arraysize="1" datatype="long">
+        <DESCRIPTION>stack identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotMag" arraysize="1" datatype="float">
+        <DESCRIPTION>isophotal magnitude</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotMagErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in isophotal magnitude</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotMajAxis" arraysize="1" datatype="float">
+        <DESCRIPTION>isophotal Major Axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotMajAxisErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in isophotal Major Axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotMinAxis" arraysize="1" datatype="float">
+        <DESCRIPTION>isophotal Minor Axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotMinAxisErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in isophotal Minor Axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotMajAxisGrad" arraysize="1" datatype="float">
+        <DESCRIPTION>isophotal major axis gradient</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotMinAxisGrad" arraysize="1" datatype="float">
+        <DESCRIPTION>isophotal minor axis gradient</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotPA" arraysize="1" datatype="float">
+        <DESCRIPTION>isophotal position angle</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotPAErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in isophotal position angle</DESCRIPTION>
+      </FIELD>
+      <FIELD name="isophotPAGrad" arraysize="1" datatype="float">
+        <DESCRIPTION>isophotal position angle gradient</DESCRIPTION>
+      </FIELD>
+      <FIELD name="petRadius" arraysize="1" datatype="float">
+        <DESCRIPTION>Petrosian radius</DESCRIPTION>
+      </FIELD>
+      <FIELD name="petRadiusErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error inPetrosian radius</DESCRIPTION>
+      </FIELD>
+      <FIELD name="petMag" arraysize="1" datatype="float">
+        <DESCRIPTION>Petrosian magntiude</DESCRIPTION>
+      </FIELD>
+      <FIELD name="petMagErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in petMag</DESCRIPTION>
+      </FIELD>
+      <FIELD name="petR50" arraysize="1" datatype="float">
+        <DESCRIPTION>Petrosian radius at 50% light</DESCRIPTION>
+      </FIELD>
+      <FIELD name="petR50Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error inPetrosian radius at 50% light</DESCRIPTION>
+      </FIELD>
+      <FIELD name="petR90" arraysize="1" datatype="float">
+        <DESCRIPTION>Petrosian radius at 90% light</DESCRIPTION>
+      </FIELD>
+      <FIELD name="petR90Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in Petrosian radius at 90% light</DESCRIPTION>
+      </FIELD>
+      <FIELD name="petCf" arraysize="1" datatype="float">
+        <DESCRIPTION>Petrosian fit coverage factor</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR1" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR1Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR1Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR1Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR2" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR2Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR2Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR2Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR3" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR3Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR3Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR3Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR4" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR4Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR4Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR4Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR5" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR5Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR5Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR5Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR6" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR6Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR6Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR6Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR7" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR7Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR7Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR7Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR8" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR8Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR8Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR8Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR9" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR9Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR9Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR9Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR10" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR10Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is flxR10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR10Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in flxR10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="flxR10Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR1" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR1Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR1Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR1Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR2" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR2Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR2Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR2Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR3" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR3Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR3Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR3Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR4" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR4Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR4Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR4Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR5" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR5Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR5Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR5Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR6" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR6Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR6Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR6Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR7" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR7Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR7Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR7Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR8" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR8Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR8Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR8Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR9" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR9Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR9Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR9Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR10" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR10Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c1flxR10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR10Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c1flxR10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c1flxR10Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR1" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR1Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR1Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR1Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR2" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR2Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR2Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR2</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR2Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R1</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR3" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR3Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR3Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR3Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R3</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR4" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR4Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR4Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR4Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R4</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR5" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR5Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR5Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR5Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R5</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR6" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR6Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR6Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR6Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R6</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR7" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR7Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR7Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR7Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R7</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR8" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR8Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR8Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR8Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R8</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR9" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR9Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR9Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR9Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R9</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR10" arraysize="1" datatype="float">
+        <DESCRIPTION>Flux inside r = 10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR10Err" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error is c2flxR10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR10Std" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated standard deviation in c2flxR10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="c2flxR10Fill" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated filling factor at R10</DESCRIPTION>
+      </FIELD>
+      <FIELD name="logC" arraysize="1" datatype="float">
+        <DESCRIPTION>Abraham concentration index</DESCRIPTION>
+      </FIELD>
+      <FIELD name="logA" arraysize="1" datatype="float">
+        <DESCRIPTION>Abraham asymmetry index</DESCRIPTION>
+      </FIELD>
+      <FIELD name="activeFlag" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>indicates whether this detection/orphan is still a detection/orphan</DESCRIPTION>
+      </FIELD>
+      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>Data release when this detection was taken</DESCRIPTION>
+      </FIELD>
       <DATA>
         <TABLEDATA></TABLEDATA>
@@ -249,152 +732,445 @@
       <DESCRIPTION>VOTable description of PSPS table StackModelFit</DESCRIPTION>
       <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
-      <FIELD name="objID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="stackDetectID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="ippObjID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="ippDetectID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="filterID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackTypeID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackGroupID" arraysize="1" datatype="int"></FIELD>
-      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="primaryF" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="stackMetaID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="deVRadius" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVRadiusErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVMag" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVMagErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVAb" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVAbErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVPhi" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVPhiErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="raDeVOff" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="decDeVOff" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="raDeVOffErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="decDeVOffErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCf" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVLikelihood" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar11" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar12" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar13" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar14" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar15" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar16" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar17" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar22" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar23" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar24" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar25" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar26" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar27" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar33" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar34" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar35" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar36" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar37" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar44" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar45" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar46" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar47" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar55" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar56" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar57" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar66" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar67" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="deVCovar77" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expRadius" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expRadiusErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expMag" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expMagErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expAb" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expAbErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expPhi" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expPhiErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="raExpOff" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="decExpOff" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="raExpOffErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="decExpOffErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCf" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expLikelihood" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar11" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar12" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar13" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar14" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar15" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar16" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar17" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar22" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar23" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar24" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar25" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar26" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar27" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar33" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar34" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar35" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar36" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar37" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar44" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar45" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar46" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar47" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar55" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar56" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar57" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar66" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar67" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="expCovar77" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serRadius" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serRadiusErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serMag" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serMagErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serAb" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serAbErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serNu" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serNuErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serPhi" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serPhiErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="raSerOff" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="decSerOff" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="raSerOffErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="decSerOffErr" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serCf" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="serLikelihood" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar11" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar12" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar13" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar14" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar15" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar16" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar17" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar18" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar22" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar23" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar24" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar25" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar26" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar27" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar28" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar33" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar34" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar35" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar36" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar37" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar38" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar44" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar45" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar46" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar47" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar48" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar55" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar56" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar57" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar58" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar66" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar67" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar68" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar77" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar78" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="sersicCovar88" arraysize="1" datatype="float"></FIELD>
-      <FIELD name="activeFlag" arraysize="1" datatype="unsignedByte"></FIELD>
-      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte"></FIELD>
+      <FIELD name="objID" arraysize="1" datatype="long">
+        <DESCRIPTION>ODM object identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackDetectID" arraysize="1" datatype="long">
+        <DESCRIPTION>ODM detection identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ippObjID" arraysize="1" datatype="long">
+        <DESCRIPTION>IPP object identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ippDetectID" arraysize="1" datatype="long">
+        <DESCRIPTION>detection ID generated by IPP</DESCRIPTION>
+      </FIELD>
+      <FIELD name="filterID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>filter identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackTypeID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>stack type identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>survey flag identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="primaryF" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>identifies best stack detection for Stacks overlapping the same region of the sky.</DESCRIPTION>
+      </FIELD>
+      <FIELD name="stackMetaID" arraysize="1" datatype="long">
+        <DESCRIPTION>stack identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVRadius" arraysize="1" datatype="float">
+        <DESCRIPTION>deVaucouleurs radius</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVRadiusErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in deVaucouleurs radius</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVMag" arraysize="1" datatype="float">
+        <DESCRIPTION>deVaucouleurs magntiude</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVMagErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in deV_mag</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVAb" arraysize="1" datatype="float">
+        <DESCRIPTION>deVaucoulerus axis ratio</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVAbErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in deVaucoulerus axis ratio</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVPhi" arraysize="1" datatype="float">
+        <DESCRIPTION>estmated phi of deVaucouleurs axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVPhiErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estmated error of phi of deVaucouleurs axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="raDeVOff" arraysize="1" datatype="float">
+        <DESCRIPTION>Offset in RA of deVaucouleurs fit from PSF RA</DESCRIPTION>
+      </FIELD>
+      <FIELD name="decDeVOff" arraysize="1" datatype="float">
+        <DESCRIPTION>Offset in DEC of deVaucouleurs fit from PSF DEC</DESCRIPTION>
+      </FIELD>
+      <FIELD name="raDeVOffErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in ra offset</DESCRIPTION>
+      </FIELD>
+      <FIELD name="decDeVOffErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in dec offset</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCf" arraysize="1" datatype="float">
+        <DESCRIPTION>deVaucouleurs fit coverage factor</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVLikelihood" arraysize="1" datatype="float">
+        <DESCRIPTION>deVaucouleurs fit likelihood factor</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar11" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar12" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar13" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar14" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar15" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar16" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar17" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar22" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar23" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar24" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar25" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar26" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar27" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar33" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar34" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar35" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar36" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar37" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar44" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar45" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar46" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar47" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar55" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar56" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar57" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar66" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar67" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="deVCovar77" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for deVaucouleurs fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expRadius" arraysize="1" datatype="float">
+        <DESCRIPTION>Exponential fit radius</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expRadiusErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in Exponential fit radius</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expMag" arraysize="1" datatype="float">
+        <DESCRIPTION>Exponential fit magntiude</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expMagErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in expMag</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expAb" arraysize="1" datatype="float">
+        <DESCRIPTION>Exponential fit axis ratio</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expAbErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in Exponential fit axis ratio</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expPhi" arraysize="1" datatype="float">
+        <DESCRIPTION>estmated phi of Exponential axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expPhiErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estmated error of phi of Exponential axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="raExpOff" arraysize="1" datatype="float">
+        <DESCRIPTION>Offset in RA of Exponential fit from PSF RA</DESCRIPTION>
+      </FIELD>
+      <FIELD name="decExpOff" arraysize="1" datatype="float">
+        <DESCRIPTION>Offset in DEC of Exponential fit from PSF DEC</DESCRIPTION>
+      </FIELD>
+      <FIELD name="raExpOffErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in raExpOff</DESCRIPTION>
+      </FIELD>
+      <FIELD name="decExpOffErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in decExpOff</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCf" arraysize="1" datatype="float">
+        <DESCRIPTION>Exponential fit coverage factor</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expLikelihood" arraysize="1" datatype="float">
+        <DESCRIPTION>Exponential fit likelihood factor</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar11" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar12" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar13" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar14" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar15" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar16" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar17" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar22" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar23" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar24" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar25" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar26" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar27" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar33" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar34" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar35" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar36" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar37" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar44" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar45" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar46" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar47" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar55" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar56" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar57" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar66" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar67" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="expCovar77" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Exponential fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serRadius" arraysize="1" datatype="float">
+        <DESCRIPTION>Sersic radius</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serRadiusErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in Sersic radius</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serMag" arraysize="1" datatype="float">
+        <DESCRIPTION>Sersic magntiude</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serMagErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in serMag</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serAb" arraysize="1" datatype="float">
+        <DESCRIPTION>Sersic axis ratio</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serAbErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in Sersic axis ratio</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serNu" arraysize="1" datatype="float">
+        <DESCRIPTION>Sersic index</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serNuErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in Sersic index</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serPhi" arraysize="1" datatype="float">
+        <DESCRIPTION>estmated phi of Sersic axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serPhiErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estmated error of phi of Sersic axis</DESCRIPTION>
+      </FIELD>
+      <FIELD name="raSerOff" arraysize="1" datatype="float">
+        <DESCRIPTION>Offset in RA of Sersic fit from PSF RA</DESCRIPTION>
+      </FIELD>
+      <FIELD name="decSerOff" arraysize="1" datatype="float">
+        <DESCRIPTION>Offset in DEC of Sersic fit from PSF DEC</DESCRIPTION>
+      </FIELD>
+      <FIELD name="raSerOffErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in raSerOff</DESCRIPTION>
+      </FIELD>
+      <FIELD name="decSerOffErr" arraysize="1" datatype="float">
+        <DESCRIPTION>estimated error in decSerOff</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serCf" arraysize="1" datatype="float">
+        <DESCRIPTION>Sersic fit coverage factor</DESCRIPTION>
+      </FIELD>
+      <FIELD name="serLikelihood" arraysize="1" datatype="float">
+        <DESCRIPTION>Sersic fit likelihood factor</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar11" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar12" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar13" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar14" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar15" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar16" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar17" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar18" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar22" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar23" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar24" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar25" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar26" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar27" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar28" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar33" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar34" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar35" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar36" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar37" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar38" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar44" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar45" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar46" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar47" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar48" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar55" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar56" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar57" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar58" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar66" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar67" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar68" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar77" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar78" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="sersicCovar88" arraysize="1" datatype="float">
+        <DESCRIPTION>covariance for Sersic fit</DESCRIPTION>
+      </FIELD>
+      <FIELD name="activeFlag" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>indicates whether this detection/orphan is still a detection/orphan</DESCRIPTION>
+      </FIELD>
+      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>Data release when this detection was taken</DESCRIPTION>
+      </FIELD>
       <DATA>
         <TABLEDATA></TABLEDATA>
@@ -404,6 +1180,60 @@
       <DESCRIPTION>VOTable description of PSPS table StackToImage</DESCRIPTION>
       <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
-      <FIELD name="stackMetaID" arraysize="1" datatype="long"></FIELD>
-      <FIELD name="imageID" arraysize="1" datatype="long"></FIELD>
+      <FIELD name="stackMetaID" arraysize="1" datatype="long">
+        <DESCRIPTION>stack identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="imageID" arraysize="1" datatype="long">
+        <DESCRIPTION>hashed exposure-ccdID identifier</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="SkinnyObject">
+      <DESCRIPTION>VOTable description of PSPS table SkinnyObject</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="objID" arraysize="1" datatype="long">
+        <DESCRIPTION>ODM object identifier index</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ippObjID" arraysize="1" datatype="long">
+        <DESCRIPTION>IPP object number</DESCRIPTION>
+      </FIELD>
+      <FIELD name="projectionCellID" arraysize="1" datatype="int">
+        <DESCRIPTION>projection cell identifier at discovery time</DESCRIPTION>
+      </FIELD>
+      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>Data release to propagate to the object</DESCRIPTION>
+      </FIELD>
+      <FIELD name="surveyID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>surveyID &lt;/coluumn&gt;</DESCRIPTION>
+      </FIELD>
+      <DATA>
+        <TABLEDATA></TABLEDATA>
+      </DATA>
+    </TABLE>
+    <TABLE name="ObjectCalColor">
+      <DESCRIPTION>VOTable description of PSPS table ObjectCalColor</DESCRIPTION>
+      <PARAM arraysize="1" datatype="char" ucd="meta.bib.author" name="Author" value="PSPS"></PARAM>
+      <FIELD name="objID" arraysize="1" datatype="long">
+        <DESCRIPTION>ODM object identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="ippObjID" arraysize="1" datatype="long">
+        <DESCRIPTION>ipp object identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="filterID" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>filter identifier</DESCRIPTION>
+      </FIELD>
+      <FIELD name="calColor" arraysize="1" datatype="float">
+        <DESCRIPTION> color adopted for magnitude calculation (unit = mag)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="calColorErr" arraysize="1" datatype="float">
+        <DESCRIPTION> error in calibrating color (unit = mag)</DESCRIPTION>
+      </FIELD>
+      <FIELD name="calibModNum" arraysize="1" datatype="short">
+        <DESCRIPTION>calibration modification number</DESCRIPTION>
+      </FIELD>
+      <FIELD name="dataRelease" arraysize="1" datatype="unsignedByte">
+        <DESCRIPTION>Data release when this color calibration was established</DESCRIPTION>
+      </FIELD>
       <DATA>
         <TABLEDATA></TABLEDATA>
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/batch.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/batch.py	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/batch.py	(revision 31439)
@@ -4,43 +4,84 @@
 import datetime
 import re
+import sys
+import os
+import md5
+import shutil
+import logging
+from subprocess import call, PIPE, Popen
+
+from datastore import Datastore
+from scratchdb import ScratchDb
+from gpc1db import Gpc1Db
+from ipptopspsdb import IppToPspsDb
 
 from java.lang import *
 from java.sql import *
-
-
+from xml.etree.ElementTree import ElementTree, Element, tostring
+
+'''
+Base class of all batch types.
+'''
 class Batch(object):
 
-    driverName="com.mysql.jdbc.Driver"
-
     '''
     Constructor
-    '''
-    def __init__(self, batchType, inputFitsPath, outputFitsPath, dbHost, dbName, dbUser, dbPass, survey=""):
+
+    >>> batch = Batch(1,2,3,4,5,6,7)
+    >>> print batch.pspsVoTableFilePath
+    "../config/2/tables.vot"
+    '''
+    def __init__(self, logger, batchType, inputFitsPath="", survey="", useFullTables=False):
+
+        # set up logging
+        self.logger = logger
+        self.logger.info("-------------------------------------------------------------------------------")
+        self.logger.debug("Batch class constructor")
 
         # set up class variables
+        self.batchType = batchType;
         self.pspsVoTableFilePath = "../config/" + batchType + "/tables.vot"
         self.inputFitsPath = inputFitsPath
-        self.outputFitsPath = outputFitsPath
-        self.dbHost = dbHost
-        self.dbName = dbName
-        self.dbUser = dbUser
-        self.dbPass = dbPass
         self.survey = survey
-
-        # set up JDBC connection
-        self.url = "jdbc:mysql://"+self.dbHost+"/"+self.dbName+"?user="+self.dbUser+"&password="+self.dbPass
-        self.con = DriverManager.getConnection(self.url)
-        self.stmt = self.con.createStatement()
-
-        # get survey ID from init table
-        sql = "SELECT surveyID from Survey WHERE name = '" + survey + "'"
-        try:
-            rs = self.stmt.executeQuery(sql)  
-            rs.first()
-            self.surveyID = rs.getInt(1)
-        except:
-            self.log("No survey ID found for this survey: '" + survey + "'")
+        self.useFullTables = useFullTables
+
+        # TODO
+        self.tablesToExport = []
+
+        # open config
+        doc = ElementTree(file="config.xml")
+
+        # create Gpc1Db object
+        self.gpc1Db = Gpc1Db(self.logger)
+        self.ippToPspsDb = IppToPspsDb(logger)
+        self.scratchDb = ScratchDb(logger, self.useFullTables)
+
+        if self.survey != "":
+            self.surveyID = self.scratchDb.getSurveyID(self.survey)
+   
+            # get dvo info from config
+            dvoName = doc.find("dvo_" + self.survey + "/name").text
+            self.dvoLocation = doc.find("dvo_" + self.survey + "/location").text
+        else:
+            dvoName = ""
+            self.dvoLocation = ""
             self.surveyID = -1;
-    
+         
+        # get datastore info from config
+        self.datastore = Datastore(self.logger)
+
+        # create a new batch
+        self.batchID = self.ippToPspsDb.createNewBatch( 
+                self.getPspsBatchType(), 
+                survey,
+                dvoName, 
+                self.datastore.product)
+
+        # get local storage location from config
+        self.batchName = "B%08d" % self.batchID
+        self.subDir = doc.find("localOutPath").text + "/" + self.getPspsBatchType() + "/" + dvoName
+        self.localOutPath = self.subDir + "/" + self.batchName 
+        if not os.path.exists(self.localOutPath): os.makedirs(self.localOutPath)
+
         # store today's date
         now = datetime.datetime.now();
@@ -48,5 +89,11 @@
 
         if self.inputFitsPath != "": 
-            self.parseFitsHeader()
+            file = open(self.inputFitsPath)
+            self.header = self.parseFitsHeader(file)
+            self.logger.info("Read primary and found " + str(len(self.header)) + " header cards") 
+            # TODO close file?
+
+        # create DVO tables if accessing DVO directly
+        if not self.useFullTables: self.scratchDb.createDvoTables()
 
     '''
@@ -55,70 +102,207 @@
     def __del__(self):
 
-        self.log("Batch destructor")
-        self.stmt.close()
-        self.con.close()
-
-    '''
-    Prints a log message with the current time
-    '''
-    def log(self, msg):
-
-        print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " | " + msg
-
-    '''
-    Updates a table with surveyID
-    '''
-    def updateSurveyID(self, table):
-
-        sql = "UPDATE " + table + "  SET surveyID=%d" % self.surveyID
-        self.stmt.execute(sql)
-
-    '''
-    Updates a table with filterID grabbed from Filter init table
-    '''
-    def updateFilterID(self, table):
-
-        sql = "UPDATE "+table+" AS a, Filter AS b SET a.filterID=b.filterID WHERE b.filterType = '" + self.filter + "'"
-        self.stmt.execute(sql)
+        self.logger.debug("Batch destructor")
+
+
+    '''
+    Returns the value from this dictinary or else NULL
+    '''
+    def safeDictionaryAccess(self, header, key):
+
+         if key in header: return header[key]
+         else: return "NULL"
+
+    '''
+    Finds and reads a header extension
+    '''
+    def findAndReadFITSHeader(self, name, file):
+
+        found = False
+        
+        while True:
+           
+            index = file.tell()
+
+            record = file.read(80)
+            if not record: break;
+
+            # quit when we reach 'END'
+            if record.startswith("XTENSION= 'IMAGE"):
+
+                header = self.parseFitsHeader(file)
+                if header['EXTNAME'] == name:
+                    found = True
+                    file.seek(index + 2880, 0)
+                    break
+
+            file.seek(index + 2880, 0)
+            
+        if found != True: self.logger.error("...could not find extension '" + name + "'")
+        else: self.logger.info("...read header at '" + name + "' and found " + str(len(header)) + " header cards") 
+
+        return header
+
+
+    '''
+    Writes the batch manifest file
+    '''
+    def writeBatchManifest(self):
+
+        outPath = self.localOutPath + "/BatchManifest.xml"
+        tmpPath = "./tmp.xml"
+        self.logger.info("Creating batch manifest file here: " + outPath)
+        root = Element('manifest')
+
+        # batch information
+        root.attrib['name'] = self.batchName
+        root.attrib['type'] = self.getPspsBatchType()
+        root.attrib['timestamp'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 
+        if self.survey != "":
+            root.attrib['survey'] = self.getBatchFriendlySurveyType()
+        try: self.minObjID
+        except: pass
+        else: root.attrib['minObjId'] = str(self.minObjID)
+        try: self.maxObjID
+        except: pass
+        else: root.attrib['maxObjId'] = str(self.maxObjID)
+
+        # get md5sum
+        p = Popen("md5sum " + self.outputFitsPath, shell=True, stdout=PIPE)
+        p.wait()
+        out = p.stdout.read()
+        md5sum = out[0:out.rfind(" ")]
+
+        # get file size
+        fileSize = os.path.getsize(self.outputFitsPath)
+
+        # file information
+        child = Element('file')
+        root.append(child)
+        child.attrib['name'] = self.outputFitsFile
+        child.attrib['bytes'] = str(fileSize)
+        child.attrib['md5'] = md5sum
+
+        # now create doc and write to file
+        file = open(tmpPath, 'w')
+        ElementTree(root).write(file)
+        file.close()
+
+        # clunky way to prettify XML
+        p = Popen("xmllint --format " + tmpPath + " > " + outPath, shell=True, stdout=PIPE)
+        p.wait()
+        os.remove(tmpPath)
+
+
+    '''
+    tar and zips batch directory
+    '''
+    def createTarball(self):
+      
+        # set up filenams and paths
+        tarFile = self.batchName + ".tar"
+        tarPath = self.subDir + "/" + tarFile
+
+        self.tarballFile = tarFile + ".gz"
+        tarballPath = self.subDir + "/" + self.tarballFile
+
+        # tar directory
+        p = Popen("tar -cvf " + tarPath + "\
+                -C " + self.subDir + " \
+                " + self.batchName, shell=True, stdout=PIPE)
+        p.wait()
+
+        # zip tar archive
+        p = Popen("gzip -c " + tarPath + " > " + tarballPath, shell=True, stdout=PIPE)
+        p.wait()
+
+        # delete tar file and original directory
+        os.remove(tarPath)
+        shutil.rmtree(self.localOutPath)
+
+    '''
+    Publishes this batch to the datastore
+    '''
+    def publishToDatastore(self):
+
+        if self.datastore.publish(self.batchName, self.subDir, self.tarballFile, "tgz"):
+            self.ippToPspsDb.updateLoadedToDatastore(self.batchID, 1)
+
+    '''
+    Gets PSPS-friendly survey type
+    '''
+    def getBatchFriendlySurveyType(self):
+
+        return "SCR" # TODO
+
+        try:
+            self.survey
+        except:
+            return "NA" 
+
+        if self.survey == "3PI": return "3PI"
+        elif self.survey == "MD04": return "MD4"
+        else:
+            self.logger.error("Don't know this survey: '" + self.survey + "'")
+            return "NA"
+
+    '''
+    Gets PSPS friendly batch type
+    '''
+    def getPspsBatchType(self):
+
+        if self.batchType == "init": return "IN"
+        elif self.batchType == "detection": return "P2"
+        elif self.batchType == "stack": return "ST"
+        else: self.logger.error("Don't know this batch type: " + self.survey)
+
+    '''
+    Sets min and max obj ID using the provided table, or list of tables
+    '''
+    def setMinMaxObjID(self, tables):
+
+        first = True
+        for table in tables:
+
+            sql = "SELECT MIN(objID), MAX(objID) FROM " + table
+            rs = self.scratchDb.stmt.executeQuery(sql)
+            rs.first()
+
+            if first:
+                self.minObjID = rs.getLong(1)
+                self.maxObjID = rs.getLong(2)
+            else:
+                if rs.getLong(1) < self.minObjID: self.minObjID = rs.getLong(1)
+                if rs.getLong(2) > self.maxObjID: self.maxObjID = rs.getLong(2)
+
+            first = False
+
+        self.ippToPspsDb.updateMinMaxObjID(self.batchID, self.minObjID, self.maxObjID)
 
     '''
     Reads FITS header and stores all fields in a dictionary object
     '''
-    def parseFitsHeader(self):
-
-        fitsFile = open(self.inputFitsPath)
-
-        self.header = {}
+    def parseFitsHeader(self, fitsFile):
+
+        header = {}
 
         while (True):
+
            record = fitsFile.read(80)
 
            # quit when we reach 'END'
-           if record.startswith("END"): break
-
-           # ignore comments
-           if record.startswith("COMMENT"): continue
-           match = re.match('(.*)=(.*)', record)
+           if re.match('END\s+', record): break
+
+           # this regex will get param/value pairs for all header cards, ignoring comments and parsing out 'HIERACH' prefixes
+           match = re.match('^(HIERARCH )*([a-zA-Z0-9-_\.]+)\s*=\s+\'*([a-zA-Z0-9-_\.:\s@#]+)\'*\\/*', record)
            if match:
 
-               # remove HIERARCH prefix
-               param = match.group(1).replace("HIERARCH", "")
-               param = param.strip()
-
-               value = match.group(2)
-               # remove trailing comment after / char, if there is one
-               index = value.find("/")
-               if index != -1: value = value[0:index]
-
-               # remove ' chars around content
-               value = value.replace("'", "")
-
-               # remove leading and trailing whitespace
-               value = value.strip()
-
-               # store in out dictionary object
-               self.header[param] = value
+               param = match.group(2)
+               value = match.group(3).strip()
+               if value == "NaN": value = "NULL"
+               header[param] = value
 
                #print param + "|" + value + "|"
+
+        return header
 
     '''
@@ -129,8 +313,9 @@
          self.pspsTables = stilts.treads(self.pspsVoTableFilePath)
          for table in self.pspsTables:
-             self.log("Creating PSPS table: " + table.name)
-             table.write(self.url + '#' + table.name)
-
-         self.indexPspsTables()
+             self.logger.info("Creating PSPS table: " + table.name)
+             table.write(self.scratchDb.url + '#' + table.name)
+             self.tablesToExport.append(table.name)
+
+         self.alterPspsTables();
 
     '''
@@ -138,34 +323,21 @@
     '''   
     def indexIppTables(self):
-        self.log("indexIppTables not implemented")
-
-
-    '''
-    Adds an index to the supplied table and column
-    '''
-    def createIndex(self, table, column):
-
-        self.log("Creating index on column '"+column+"' for table '"+table+"'")
-
-        sql = "CREATE INDEX "+table+"_index ON "+table+" ("+column+")"
-        try:
-            self.stmt.execute(sql)
-        except:
-            self.log("Index already in place on '" + column + "' for table '" + table + "'")
-
-
-    '''
-    Subclass should implement this to index PSPS tables
+        self.logger.warn("indexIppTables not implemented")
+
+
+    '''
+    Alter PSPS tables
     '''   
-    def indexPspsTables(self):
-        self.log("indexPspsTables not implemented")
+    def alterPspsTables(self):
+        self.logger.warn("alterPspsTables not implemented")
 
     '''
     Imports IPP tables from FITS file
 
-    Accepts a regular expression filter so not all tabls need to be imported
+    Accepts a regular expression filter so not all tables need to be imported
     '''
     def importIppTables(self, filter):
 
+      self.logger.info("Attempting to import tables from input FITS file")
       tables = stilts.treads(self.inputFitsPath)
 
@@ -175,34 +347,74 @@
           match = re.match(filter, table.name)
           if not match: continue
-          self.log("Creating IPP table " + table.name)
+          self.logger.info("   Reading IPP table " + table.name + " from FITS file")
           table = stilts.tpipe(table, cmd='explodeall')
+
+          # drop any previous tables before import
+          self.scratchDb.dropTable(table.name)
+
+          # IPP FITS files are littered with infinities, so remove these
+          self.logger.info("   Removing Infinity values from all columns")
+          table = stilts.tpipe(table, cmd='replaceval -Infinity null *')
+          table = stilts.tpipe(table, cmd='replaceval Infinity null *')
+
           try:
-              table.write(self.url + '#' + table.name)
+              table.write(self.scratchDb.url + '#' + table.name)
           except:
-              self.log("ERROR problem writing table '" + table.name + "' to the database")
-
+              self.logger.exception("   Problem writing table '" + table.name + "' to the database")
           count = count + 1
 
-      self.log("Imported %d tables from '%s' " % (count, self.inputFitsPath))
+      self.logger.info("Done. Imported %d tables" % count)
 
       self.indexIppTables()
 
     '''
-    Exports PSPS tables from the database to FITS format
+    Exports PSPS tables from the database to FITS format. Optional regex if you want to alter table names prior to export
     '''    
-    def exportPspsTablesToFits(self):
-
-        self.log("Exporting all PSPS tables to FITS")
+    def exportPspsTablesToFits(self, regex="(.*)"):
+
+        self.logger.info("Replacing NULLs with -999 then exporting all PSPS tables to FITS")
         _tables = []
 
-        self.log("    Selecting database tables")
+        self.logger.info("    Selecting database tables")
+        for table in self.tablesToExport:
+
+           # check for an empty table
+           if self.scratchDb.getRowCount(table) < 1: continue
+
+           # get everything from table
+           _table = stilts.tread(self.scratchDb.url + '#SELECT * FROM ' + table)
+
+           # replace nulls and empty fields with weird PSPS -999 pseudo-null
+           _table = stilts.tpipe(_table, cmd='replaceval "" -999 *')
+
+           match = re.match(regex, table)
+           newTableName = match.group(1)
+
+           # change table names
+           _table = stilts.tpipe(_table, cmd='tablename ' + newTableName)
+           _tables.append(_table)
+
+        self.logger.info("    Writing to FITS file '" + self.outputFitsPath + "'...")
+        stilts.twrites(_tables, self.outputFitsPath, fmt='fits')
+        self.logger.info("    ...done")
+        self.ippToPspsDb.updateProcessed(self.batchID, 1)
+
+    '''
+    Searches all PSPS tables and reports the columns that are either partially or completely populated with NULLs
+    '''
+    def reportNullsInAllPspsTables(self, showPartials):
+
         for table in self.pspsTables:
-           _table = stilts.tread(self.url + '#SELECT * FROM ' + table.name)
-           _table = stilts.tpipe(_table, cmd='tablename ' + table.name)
-           _tables.append(_table)
-
-        self.log("    Writing to FITS file " + self.outputFitsPath)
-        stilts.twrites(_tables, self.outputFitsPath, fmt='fits')
-
+            self.scratchDb.reportNulls(table.name, showPartials)
+
+    '''
+    Searches all PSPS tables and replaces all NULLs with the provided substitute
+    '''
+    def replaceAllPspsNulls(self, sub):
+
+        self.logger.info("Replacing all NULL values in PSPS tables with '" + sub + "'...")
+        for table in self.pspsTables:
+            self.scratchDb.replaceNulls(table.name, sub)
+        self.logger.info("...done")
 
     '''
@@ -210,4 +422,31 @@
     '''
     def populatePspsTables(self):
-        self.log("Not implemented yet")
-
+        self.logger.warn("Not implemented yet")
+
+    '''
+    Calls DVO program to 'query' DVO database and populate results to local MySQL Db table
+    '''
+    def getIDsFromDVO(self):
+
+        # TODO path to DVO prog hardcoded temporarily
+        cmd = "../src/dvograbber " + self.dvoLocation
+        self.logger.info("Running: '" + cmd + "'...")
+        p = Popen(cmd, shell=True, stdout=PIPE)
+        p.wait()
+        #        out = p.stdout.read()
+        self.logger.info("...done")
+
+        if self.scratchDb.getRowCount("dvoDetection") < 1:
+            self.logger.error("No DVO IDs found")
+            return False
+            
+        return True
+
+    '''
+    Checks whether this batch has already been processed and published. To be implemented by all subclasses
+    '''
+    def alreadyProcessed(self):
+           self.logger.info("Not implemented")
+
+
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/config.xml
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/config.xml	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/config.xml	(revision 31439)
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Global config for ippToPsps -->
+
+<ippToPsps>
+
+  <!-- local scratch Db section -->
+  <localdatabase>
+    <name>ipptopsps_scratch</name>
+    <host>localhost</host>
+    <user>ipp</user>
+    <password>ipp</password>
+  </localdatabase>
+
+  <!-- GPC1 Db section -->
+  <gpc1database>
+    <name>gpc1</name>
+    <!--<name>haf_addtest</name>-->
+    <host>ippdb01</host>
+    <user>ipp</user>
+    <password>ipp</password>
+  </gpc1database>
+
+  <!-- ippToPsps Db section -->
+  <ipptopspsdatabase>
+    <name>ipptopsps</name>
+    <host>ippdb01</host>
+    <user>ipp</user>
+    <password>ipp</password>
+  </ipptopspsdatabase>
+
+  <!-- datastore section -->
+  <datastore>
+    <!--<product>PSPS_JHU</product>-->
+    <product>PSPS_test</product>
+    <type>IPP_PSPS</type>
+  </datastore>
+
+  <!-- DVO section -->
+  <dvo_3PI>
+    <name>ThreePi.V1</name>
+    <location>/data/ipp004.0/gpc1/catdirs/ThreePi.V1</location>
+  </dvo_3PI>
+
+  <dvo_MD04>
+    <name>MD04.merge</name>
+    <!--<location>/export/ippc00.1/rhenders/MD04.merge</location>-->
+    <location>/data/ipp005.0/gpc1/catdirs/MD04.merges/MD04.merge</location>
+    <!--<name>HAFTest.Staticsky</name>-->
+    <!--<location>/data/ipp004.0/gpc1/catdirs/HAFTest.StaticSky/HAFTest.Staticsky.540</location>-->
+    <!--<name>MD04.V1</name>-->
+    <!--<location>/data/ipp004.0/gpc1/catdirs/MD04.V1</location>-->
+  </dvo_MD04>
+
+  <!-- local storage locations -->
+  <localOutPath>/data/ipp005.0/rhenders</localOutPath>
+  <!--<localOutPath>./</localOutPath>-->
+
+</ippToPsps>
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/datastore.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/datastore.py	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/datastore.py	(revision 31439)
@@ -0,0 +1,85 @@
+#!/usr/bin/env jython
+
+from subprocess import call, PIPE, Popen
+import tempfile
+import logging
+import sys
+from xml.etree.ElementTree import ElementTree, Element, tostring
+
+
+'''
+Class encapsulating the IPP datastore
+'''
+class Datastore(object):
+
+    '''
+        Constructor
+
+    '''
+    def __init__(self, logger):
+    
+        # setup logger
+        self.logger = logger
+        self.logger.debug("Datastore constructor")
+
+        # open config
+        doc = ElementTree(file="config.xml")
+        self.product = doc.find("datastore/product").text
+        self.type = doc.find("datastore/type").text
+
+        self.logger.debug("Using product: '" + self.product + "' and type: '" + self.type + "'")
+
+    '''
+    Publishes an item to the datastore
+    '''
+    def publish(self, name, path, file, fileType):
+
+        self.logger.info("Attempting to publish '" + path +"/" + file + "' to datastore product: '" + self.product + "', type: '" + self.type + "'")
+        tempFile = tempfile.NamedTemporaryFile(mode='w+b')
+        tempFile.write(file + "|||" + fileType)
+        tempFile.seek(0)
+
+        # build dsreg command command
+        command  = "dsreg --add " + name + "\
+                    --copy --datapath " + path + "\
+                    --type " + self.type + "\
+                    --product " + self.product + "\
+                    --list " + tempFile.name
+
+        p = Popen(command, shell=True, stdout=PIPE)
+        p.wait()
+
+        if p.returncode != 0:
+            self.logger.error("Datastore publish failed")
+            ret = False
+        else:
+            self.logger.info("Datastore publish successful")
+            ret = True
+            
+
+        tempFile.close()
+        return ret
+
+
+    '''
+    Removes an item to the datastore
+    '''
+    def remove(self, name):
+
+        command = "dsreg \
+                   --del " + name + " \
+                   --rm \
+                   --product " + self.product
+
+        p = Popen(command, shell=True, stdout=PIPE)
+        p.wait()
+
+        if p.returncode != 0:
+            self.logger.error("Datastore removal of " + name + " failed")
+            ret = False
+        else:
+            ret = True
+            self.logger.info("Datastore removal of " + name + " successful")
+            
+        return ret
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/detectionbatch.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/detectionbatch.py	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/detectionbatch.py	(revision 31439)
@@ -1,9 +1,17 @@
 #!/usr/bin/env jython
 
+import os.path
+import sys
 import stilts
 from java.lang import *
 from java.sql import *
 from batch import Batch
-
+from gpc1db import Gpc1Db
+
+import logging.config
+
+'''
+DetectionBatch class
+'''
 class DetectionBatch(Batch):
 
@@ -11,61 +19,124 @@
     Constructor
     '''
-    def __init__(self):
+    def __init__(self, logger, camID, inputFile, test=False, useFullTables=False):
        super(DetectionBatch, self).__init__(
+               logger,
                "detection", 
-               "detdemo.fits", 
-               "detection.fits",
-               "localhost",
-               "ipptopsps_scratch",
-               "ipp",
-               "ipp",
-               "3PI") # TODO
-
-
-
-    '''
-    Updates a table with stackMetaID
-    '''
-    def updateStackMetaID(self, table):
-
-        sql = "UPDATE " + table + "  SET stackMetaID=" + self.header['STK_ID']
-        self.stmt.execute(sql)
-
-    '''
-    Updates a table with stackTypeID grabbed from FitModel init table
-    '''
-    def updateStackTypeID(self, table):
-
-        sql = "UPDATE "+table+" AS a, StackType AS b SET a.stackTypeID=b.stackTypeID WHERE b.name = '"+self.header['STK_TYPE']+"'"
-        self.stmt.execute(sql)
+               inputFile, 
+               "MD04",
+               useFullTables) # TODO
+               #"3PI") # TODO
+
+       self.logger.info("DetectionBatch constructor. Creating batch from: '" + inputFile + "'")
+
+       meta = self.gpc1Db.getCameraStageMeta(camID)
+      
+       self.expID = meta[0];
+       self.expName = meta[1];
+       self.distGroup = meta[2];
+
+       self.logger.info("Processing exposure with ID: %d, name: %s and distribution group: %s" % (self.expID, self.expName, self.distGroup))
+
+       # create an output filename, which is {expID}.FITS
+       self.outputFitsFile = "%08d.FITS" % self.expID
+       self.outputFitsPath = "%s/%s" % (self.localOutPath, self.outputFitsFile)
+
+       # if test mode
+       if test:
+           self.startX = 3
+           self.endX = 4
+           self.startY = 3
+           self.endY = 4
+       else:
+           self.startX = 0
+           self.endX = 8
+           self.startY = 0
+           self.endY = 8
+
+       #self.startX = 1
+       #self.endX = 2
+       #self.startY = 7
+       #self.endY = 8
+
+       self.obsTime = float(self.header['MJD-OBS']) + (float(self.header['EXPTIME']) / 172800.0)
+      
+       # set up some defauts
+       self.calibModNum = 0
+       self.dataRelease = 0
+
+       self.totalNumPhotoRef = 0
+
+       # get filterID using init table
+       self.filter = self.header['FILTERID'][0:1]
+
+       # insert what we know about this stack batch into the stack table
+       self.ippToPspsDb.insertDetectionMeta(self.batchID, self.expID, self.filter)
+
 
     '''
     Populates the FrameMeta table, mainly from dictionary values found in IPP FITS header
     '''
-    def populateImageMeta(self):
-        self.log("Procesing ImageMeta table")
-        '''
-        sql = "INSERT INTO ImageMeta (\
-        stackMetaID \
-        ,skycellID \
-        ,photoZero \
-        ,nP2Images \
-        ,ctype1 \
-        ,ctype2 \
-        ,crval1 \
-        ,crval2 \
-        ,crpix1 \
-        ,crpix2 \
-        ,cdelt1 \
-        ,cdelt2 \
-        ,pc001001 \
-        ,pc001002 \
-        ,pc002001 \
-        ,pc002002 \
+    def populateFrameMeta(self):
+        self.logger.info("Procesing FrameMeta table")
+
+        sql = "INSERT INTO FrameMeta (\
+          frameID \
+         ,frameName \
+         ,cameraID \
+         ,cameraConfigID \
+         ,telescopeID \
+         ,analysisVer \
+         ,p1Recip \
+         ,p2Recip \
+         ,p3Recip \
+         ,photoScat \
+         ,expStart \
+         ,expTime \
+         ,airmass \
+         ,raBore \
+         ,decBore \
+         ,ctype1 \
+         ,ctype2 \
+         ,crval1 \
+         ,crval2 \
+         ,crpix1 \
+         ,crpix2 \
+         ,cdelt1 \
+         ,cdelt2 \
+         ,pc001001 \
+         ,pc001002 \
+         ,pc002001 \
+         ,pc002002 \
+         ,polyOrder \
+         ,pca1x3y0 \
+         ,pca1x2y1 \
+         ,pca1x1y2 \
+         ,pca1x0y3 \
+         ,pca1x2y0 \
+         ,pca1x1y1 \
+         ,pca1x0y2 \
+         ,pca2x3y0 \
+         ,pca2x2y1 \
+         ,pca2x1y2 \
+         ,pca2x0y3 \
+         ,pca2x2y0 \
+         ,pca2x1y1 \
+         ,pca2x0y2 \
          ) VALUES ( \
-        " + self.header['STK_ID'] + " \
-        ," + self.skycell + " \
-        ," + self.header['FPA.ZP'] + " \
-        ," + self.header['NINPUTS'] + " \
+        " + str(self.expID) + " \
+        ,'" + self.expName + "' \
+        ,1  \
+        ,1  \
+        ,1  \
+        ,' ' \
+        ,' ' \
+        ,' ' \
+        ,' ' \
+        ," + self.header['ZPT_ERR'] + " \
+        ," + self.header['MJD-OBS'] + " \
+        ," + self.header['EXPREQ'] + " \
+        ," + self.header['AIRMASS'] + " \
+        ," + self.header['RA'] + " \
+        ," + self.header['DEC'] + " \
         ,'" + self.header['CTYPE1'] + "' \
         ,'" + self.header['CTYPE2'] + "' \
@@ -80,75 +151,519 @@
         ," + self.header['PC002001'] + " \
         ," + self.header['PC002002'] + " \
+        ," + self.header['NPLYTERM'] + " \
+        ," + self.header['PCA1X3Y0'] + " \
+        ," + self.header['PCA1X2Y1'] + " \
+        ," + self.header['PCA1X1Y2'] + " \
+        ," + self.header['PCA1X0Y3'] + " \
+        ," + self.header['PCA1X2Y0'] + " \
+        ," + self.header['PCA1X1Y1'] + " \
+        ," + self.header['PCA1X0Y2'] + " \
+        ," + self.header['PCA2X3Y0'] + " \
+        ," + self.header['PCA2X2Y1'] + " \
+        ," + self.header['PCA2X1Y2'] + " \
+        ," + self.header['PCA2X0Y3'] + " \
+        ," + self.header['PCA2X2Y0'] + " \
+        ," + self.header['PCA2X1Y1'] + " \
+        ," + self.header['PCA2X0Y2'] + " \
         )"
-        self.stmt.execute(sql)
-
-        self.updateSurveyID("ImageMeta")
-        self.updateFilterID("ImageMeta")
-        self.updateStackTypeID("ImageMeta")
-        '''
-
-    '''
-    Populates the Detection tables
-    '''
-    def populateDetectionTables(self):
-
-        self.log("Procesing Detection tables")
-        for x in range(3,4):
-           for y in range(3,4):
-
-               self.log("Populating detections for OTA %d%d" % (x, y))
+        self.scratchDb.stmt.execute(sql)
+
+        self.scratchDb.updateAllRows("FrameMeta", "surveyID", str(self.surveyID))
+        self.scratchDb.updateFilterID("FrameMeta", self.filter)
+        self.scratchDb.updateAllRows("FrameMeta", "calibModNum", str(self.calibModNum))
+        self.scratchDb.updateAllRows("FrameMeta", "dataRelease", str(self.dataRelease))
+
+    '''
+    Populates the ImageMeta table for this OTA
+    '''
+    def populateImageMetaTable(self, ota, header):
+
+        tableName = "ImageMeta_" + ota
+        
+        # drop then re-create table
+        self.scratchDb.dropTable(tableName)
+        sql = "CREATE TABLE " + tableName + " LIKE ImageMeta"
+        try: self.scratchDb.stmt.execute(sql)
+        except: pass
+
+        # insert all detections into table
+        sql = "INSERT INTO " + tableName + " ( \
+               frameID \
+               ,ccdID \
+               ,sky \
+               ,skyScat \
+               ,magSat \
+               ,completMag \
+               ,astroScat \
+               ,photoScat \
+               ,numAstroRef \
+               ,numPhotoRef \
+               ,nx \
+               ,ny \
+               ,psfFwhm \
+               ,psfWidMajor \
+               ,psfWidMinor \
+               ,psfTheta \
+               ,momentFwhm \
+               ,momentWidMajor \
+               ,momentWidMinor \
+               ,apResid \
+               ,dapResid \
+               ,detectorID \
+               ,qaFlags \
+               ,detrend1 \
+               ,detrend2 \
+               ,detrend3 \
+               ,detrend4 \
+               ,detrend5 \
+               ,detrend6 \
+               ,detrend7 \
+               ,detrend8 \
+               ,photoZero \
+               ,ctype1 \
+               ,ctype2 \
+               ,crval1 \
+               ,crval2 \
+               ,crpix1 \
+               ,crpix2 \
+               ,cdelt1 \
+               ,cdelt2 \
+               ,pc001001 \
+               ,pc001002 \
+               ,pc002001 \
+               ,pc002002 \
+               ,polyOrder \
+               ,pca1x3y0 \
+               ,pca1x2y1 \
+               ,pca1x1y2 \
+               ,pca1x0y3 \
+               ,pca1x2y0 \
+               ,pca1x1y1 \
+               ,pca1x0y2 \
+               ,pca2x3y0 \
+               ,pca2x2y1 \
+               ,pca2x1y2 \
+               ,pca2x0y3 \
+               ,pca2x2y0 \
+               ,pca2x1y1 \
+               ,pca2x0y2 \
+               ) VALUES ( \
+               " + str(self.expID) + " \
+               ," + ota[2:4] + " \
+               ," + self.safeDictionaryAccess(header, 'MSKY_MN') + " \
+               ," + self.safeDictionaryAccess(header, 'MSKY_SIG') + " \
+               ," + self.safeDictionaryAccess(header, 'FSATUR') + " \
+               ," + self.safeDictionaryAccess(header, 'FLIMIT') + " \
+               ," + self.safeDictionaryAccess(header, 'CERROR') + " \
+               ," + self.safeDictionaryAccess(self.header, 'ZPT_OBS') + " \
+               ," + self.safeDictionaryAccess(header, 'NASTRO') + " \
+               ," + self.safeDictionaryAccess(header, 'NASTRO') + " \
+               ," + self.safeDictionaryAccess(header, 'CNAXIS1') + " \
+               ," + self.safeDictionaryAccess(header, 'CNAXIS2') + " \
+               ," + str((float(self.safeDictionaryAccess(header, 'FWHM_MAJ')) + float(self.safeDictionaryAccess(header, 'FWHM_MIN')))/2.0) + " \
+               ," + self.safeDictionaryAccess(header, 'FWHM_MAJ') + " \
+               ," + self.safeDictionaryAccess(header, 'FWHM_MIN') + " \
+               ," + self.safeDictionaryAccess(header, 'ANGLE') + " \
+               ," + str((float(self.safeDictionaryAccess(header, 'IQ_FW1')) + float(self.safeDictionaryAccess(header, 'IQ_FW2')))/2.0) + " \
+               ," + self.safeDictionaryAccess(header, 'IQ_FW1') + " \
+               ," + self.safeDictionaryAccess(header, 'IQ_FW2') + " \
+               ," + self.safeDictionaryAccess(header, 'APMIFIT') + " \
+               ," + self.safeDictionaryAccess(header, 'DAPMIFIT') + " \
+               ,'" + self.safeDictionaryAccess(header, 'DETECTOR') + "' \
+               ," + str(self.scratchDb.getDvoImageFlags(header['SOURCEID'], header['IMAGEID'])) + " \
+               ,'" + self.safeDictionaryAccess(header, 'DETREND.MASK') + "' \
+               ,'" + self.safeDictionaryAccess(header, 'DETREND.DARK') + "' \
+               ,'" + self.safeDictionaryAccess(header, 'DETREND.FLAT') + "' \
+               ,' ' \
+               ,' ' \
+               ,' ' \
+               ,' ' \
+               ,' ' \
+               ," + self.safeDictionaryAccess(self.header, 'ZPT_OBS') + " \
+               ,'" + self.safeDictionaryAccess(header, 'CTYPE1') + "' \
+               ,'" + self.safeDictionaryAccess(header, 'CTYPE2') + "' \
+               ," + self.safeDictionaryAccess(header, 'CRVAL1') + " \
+               ," + self.safeDictionaryAccess(header, 'CRVAL2') + " \
+               ," + self.safeDictionaryAccess(header, 'CRPIX1') + " \
+               ," + self.safeDictionaryAccess(header, 'CRPIX2') + " \
+               ," + self.safeDictionaryAccess(header, 'CDELT1') + " \
+               ," + self.safeDictionaryAccess(header, 'CDELT2') + " \
+               ," + self.safeDictionaryAccess(header, 'PC001001') + " \
+               ," + self.safeDictionaryAccess(header, 'PC001002') + " \
+               ," + self.safeDictionaryAccess(header, 'PC002001') + " \
+               ," + self.safeDictionaryAccess(header, 'PC002002') + " \
+               ," + self.safeDictionaryAccess(header, 'NPLYTERM') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA1X3Y0') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA1X2Y1') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA1X1Y2') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA1X0Y3') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA1X2Y0') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA1X1Y1') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA1X0Y2') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA2X3Y0') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA2X2Y1') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA2X1Y2') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA2X0Y3') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA2X2Y0') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA2X1Y1') + " \
+               ," + self.safeDictionaryAccess(header, 'PCA2X0Y2') + " \
+               )"
+
+        self.scratchDb.stmt.execute(sql)
+        self.scratchDb.updateFilterID(tableName, self.filter)
+        self.scratchDb.updateAllRows(tableName, "calibModNum", str(self.calibModNum))
+        self.scratchDb.updateAllRows(tableName, "dataRelease", str(self.dataRelease))
+        self.totalNumPhotoRef = self.totalNumPhotoRef + int(header['NASTRO'])
+        self.scratchDb.replaceNullsInThisColumn(tableName, "polyOrder", "0")
+
+    '''
+    Populates the Detection table for this OTA
+    '''
+    def populateDetectionTable(self, ota):
+
+        tableName = "Detection_" + ota
+        
+        # drop then re-create table
+        self.scratchDb.dropTable(tableName)
+        sql = "CREATE TABLE " + tableName + " LIKE Detection"
+        try: self.scratchDb.stmt.execute(sql)
+        except: pass
+
+        # insert all detections into table
+        sql = "INSERT INTO " + tableName + " ( \
+               ippDetectID \
+               ,xPos \
+               ,yPos \
+               ,xPosErr \
+               ,yPosErr \
+               ,instFlux \
+               ,instFluxErr \
+               ,peakADU \
+               ,psfWidMajor \
+               ,psfWidMinor \
+               ,psfTheta \
+               ,psfCf \
+               ,momentXX \
+               ,momentXY \
+               ,momentYY \
+               ,apMag \
+               ,infoFlag \
+               ,sky \
+               ,skyErr \
+               ,sgSep \
+               ) \
+               SELECT \
+               IPP_IDET \
+               ,X_PSF \
+               ,Y_PSF \
+               ,X_PSF_SIG \
+               ,Y_PSF_SIG \
+               ,POW(10.0, (-0.4*PSF_INST_MAG)) / "+self.header['EXPTIME']+" \
+               ,ABS((PSF_INST_MAG_SIG*(POW(10.0, (-0.4*PSF_INST_MAG)) / "+self.header['EXPTIME']+")) / 1.085736) \
+               ,POW(10.0, (-0.4*PEAK_FLUX_AS_MAG)) / "+self.header['EXPTIME']+" \
+               ,PSF_MAJOR \
+               ,PSF_MINOR \
+               ,PSF_THETA \
+               ,PSF_QF \
+               ,MOMENTS_XX \
+               ,MOMENTS_XY \
+               ,MOMENTS_YY \
+               ,AP_MAG \
+               ,FLAGS\
+               ,SKY \
+               ,SKY_SIGMA \
+               ,EXT_NSIGMA \
+               FROM " + ota + "_psf"
+
+        self.scratchDb.stmt.execute(sql)
+
+        # set obsTime
+        sql = "UPDATE " + tableName + " SET obsTime = %f, assocDate = '%s', activeFlag = 0" % (self.obsTime, self.dateStr)
+        self.scratchDb.stmt.execute(sql)
+        self.scratchDb.updateAllRows(tableName, "dataRelease", str(self.dataRelease))
+        self.scratchDb.updateAllRows(tableName, "historyModNum", "0")
+
+        self.scratchDb.updateAllRows(tableName, "surveyID", str(self.surveyID))
+        self.scratchDb.updateFilterID(tableName, self.filter)
+
+        # now delete bad flux
+        self.scratchDb.reportAndDeleteRowsWithNULLS(tableName, "instFlux")
+        self.scratchDb.reportAndDeleteRowsWithNULLS(tableName, "peakADU")
+
+    '''
+    Populates the SkinnyObject table for this OTA
+    '''
+    def populateSkinnyObjectTable(self, ota):
+
+        tableName = "SkinnyObject_" + ota
+        
+        # drop then re-create table
+        self.scratchDb.dropTable(tableName)
+        sql = "CREATE TABLE " + tableName + " LIKE SkinnyObject"
+        try: self.scratchDb.stmt.execute(sql)
+        except: pass
+
+        # insert all detections into table
+        sql = "INSERT INTO " + tableName + " ( \
+               objID \
+               ,ippObjID \
+               ,surveyID \
+               ) \
+               SELECT \
+               objID \
+               ,ippObjID \
+               ,surveyID \
+               FROM Detection_" + ota
+        self.scratchDb.stmt.execute(sql)
+
+        self.scratchDb.updateAllRows(tableName, "dataRelease", str(self.dataRelease))
+
+    '''
+    Populates the Detection table for this OTA
+    '''
+    def populateObjectCalColorTable(self, ota):
+
+        tableName = "ObjectCalColor_" + ota
+        
+        # drop then re-create table
+        self.scratchDb.dropTable(tableName)
+        sql = "CREATE TABLE " + tableName + " LIKE ObjectCalColor"
+        try: self.scratchDb.stmt.execute(sql)
+        except: pass
+
+        # insert all detections into table
+        sql = "INSERT INTO " + tableName + " ( \
+               objID \
+               ,ippObjID \
+               ,filterID \
+               ) \
+               SELECT \
+               objID \
+               ,ippObjID \
+               ,filterID \
+               FROM Detection_" + ota
+        self.scratchDb.stmt.execute(sql)
+
+        self.scratchDb.updateAllRows(tableName, "calibModNum", str(self.calibModNum))
+        self.scratchDb.updateAllRows(tableName, "dataRelease", str(self.dataRelease))
+
+
+    '''
+    Applies indexes and other constraints to the PSPS tables
+    '''
+    def alterPspsTables(self):
+
+        self.logger.info("Altering PSPS tables")
+        self.logger.info("Creating indexes on PSPS tables")
+        self.scratchDb.makeColumnUnique("Detection", "objID")
+        self.scratchDb.createIndex("Detection", "ippDetectID")
+
+    '''
+    Applies indexes to the IPP tables
+    '''
+    def indexIppTables(self):
+
+        self.logger.info("Creating indexes on IPP tables")
+
+        for x in range(self.startX, self.endX):
+            for y in range(self.startY, self.endY):
+
+                # dodge the corners
+                if x==0 and y==0: continue
+                if x==0 and y==7: continue
+                if x==7 and y==0: continue
+                if x==7 and y==7: continue
+
+                extension = "XY%d%d_psf" % (x, y)
+                self.scratchDb.createIndex(extension, "IPP_IDET")
+
+    '''
+    Updates provided table with DVO IDs from DVO table
+    '''
+    def updateDvoIDs(self, table, sourceID, externID):
+
+        imageID = self.scratchDb.getImageIDFromExternID(sourceID, externID)
+        self.logger.info("Updating table '" + table + "' with DVO IDs using imageID = %d" % imageID)
+        sql = "UPDATE IGNORE " + table + " AS a, " + self.scratchDb.dvoDetection + " AS b SET \
+               a.ippObjID = b.ippObjID, \
+               a.detectID = b.detectID, \
+               a.objID = b.objID, \
+               a.infoFlag = b.flags << 32 | a.infoFlag \
+               WHERE a.ippDetectID = b.ippDetectID \
+               AND b.sourceID = " + str(sourceID) + " \
+               AND b.imageID = " + str(imageID)
+
+        self.scratchDb.stmt.execute(sql)
+
+
+    '''
+    Does the processing, i.e. pulling stuff from IPP tables into PSPS tables
+    '''
+    def populatePspsTables(self):
+
+        self.populateFrameMeta()
+     
+        # dictionary objects to hold sourceIDs and imageIDs for later
+        sourceIDs = {}
+        imageIDs = {}
+
+        file = open(self.inputFitsPath, 'r')
+
+        # loop through all OTAs and populate ImageMeta extensions
+        for x in range(self.startX, self.endX):
+            for y in range(self.startY, self.endY):
                
-               sql = "INSERT INTO Detection ( \
-                      ippDetectID \
-                      ) \
-                      SELECT \
-                      IPP_IDET \
-                      FROM XY%d%d_psf" % (x, y)
-
-               self.stmt.execute(sql)
-
-
-    '''
-    Applies indexes to the PSPS tables
-    '''
-    def indexPspsTables(self):
-
-        self.log("Creating indexes on PSPS tables")
-#        self.createIndex("StackDetection", "ippDetectID")
- #       self.createIndex("StackApFlx", "ippDetectID")
-  #      self.createIndex("StackModelFit", "ippDetectID")
-
-    '''
-    Applies indexes to the IPP tables
-    '''
-    def indexIppTables(self):
-
-        self.log("Creating indexes on IPP tables")
-
-        for x in range(0,7):
-           for y in range(0,7):
-
-               extension = "XY%d%d_psf" % (x, y)
-               self.createIndex(extension, "IPP_IDET")
-
-    '''
-    Does the processing, i.e. pulling stuff from IPP tables into PSPS tables
-    '''
-    def populatePspsTables(self):
-
-        # get filterID using init table
-        self.filter = self.header['FILTERID']
-        self.filter = self.filter[0:1]
-        print "filter = ", self.filter
-
-        #self.populateStackMeta()
-        self.populateDetectionTables()
-        #self.populateStackModelFit()
-        #self.populateStackApFlx()
-
+                # dodge the corners
+                if x==0 and y==0: continue
+                if x==0 and y==7: continue
+                if x==7 and y==0: continue
+                if x==7 and y==7: continue
+
+                ota = "XY%d%d" % (x, y)
+                
+                # load corresponding header into memory
+                header = self.findAndReadFITSHeader(ota + ".hdr", file)
+
+                # store sourceID/imageID combo in Db so DVO can look up later
+                if not self.useFullTables:
+                    self.scratchDb.insertNewDvoImage(header['SOURCEID'], header['IMAGEID'])
+
+                # check we have valid sourceID/imageID pair from the header
+                if 'SOURCEID' not in header or 'IMAGEID' not in header: 
+                    self.logger.error("Can't read SOURCEID/IMAGEID pair from " + ota + " header")
+                    continue
+
+                # store these for later
+                sourceIDs[ota] = header['SOURCEID']
+                imageIDs[ota] = header['IMAGEID']
+
+                # populate ImageMeta
+                self.populateImageMetaTable(ota, header)
+                self.updateImageID("ImageMeta_" + ota, x, y) 
+             
+        # now run DVO code to get all IDs
+        if not self.useFullTables: self.getIDsFromDVO()
+
+        # loop through all OTAs again to update with DVO IDs
+        self.tablesToExport = []    
+        self.tablesToExport.append("FrameMeta")
+        tables = []    
+        otaCount = 0
+        for x in range(self.startX, self.endX):
+            for y in range(self.startY, self.endY):
+               
+                # dodge the corners
+                if x==0 and y==0: continue
+                if x==0 and y==7: continue
+                if x==7 and y==0: continue
+                if x==7 and y==7: continue
+
+                ota = "XY%d%d" % (x, y)
+                if ota not in sourceIDs: continue
+
+                self.logger.info("******************* Dealing with OTA " + ota + " *******************")
+
+                # populate remainder of tables
+                self.populateDetectionTable(ota)
+
+                # now add DVO IDs
+                self.updateDvoIDs("Detection_" + ota, sourceIDs[ota], imageIDs[ota])
+                self.scratchDb.reportAndDeleteRowsWithNULLS("Detection_" + ota, "objID")
+                self.updateImageID("Detection_" + ota, x, y) 
+                
+                # check we have something in this Detection table
+                if self.scratchDb.getRowCount("Detection_" + ota) < 1:
+                    self.logger.info("Empty tables for ota " + ota + ". Skipping.")
+                    continue;
+
+                # update ImageMeta with count of detections for this OTA and photoCodeID
+                sql = "UPDATE ImageMeta_" + ota + " SET nDetect = %d, photoCalID = %d" % (self.scratchDb.getRowCount("Detection_" + ota), self.scratchDb.getPhotoCalID(sourceIDs[ota], imageIDs[ota]))
+                self.scratchDb.stmt.execute(sql)
+
+                self.populateSkinnyObjectTable(ota)
+                self.populateObjectCalColorTable(ota)
+
+                # add these to list of tables to export later
+                self.tablesToExport.append("ImageMeta_" + ota)
+                self.tablesToExport.append("Detection_" + ota)
+                self.tablesToExport.append("SkinnyObject_" + ota)
+                self.tablesToExport.append("ObjectCalColor_" + ota)
+                tables.append("Detection_" + ota)
+           
+                otaCount = otaCount + 1
+
+        # if we only have one table export, i.e. FrameMeta, then get out of here
+        if len(self.tablesToExport) == 1:
+            
+            self.logger.error("No tables to export")
+            return False
+
+        self.setMinMaxObjID(tables)
+
+        # update FrameMeta with count OTAs in this file and total number of photometric reference sources
+        sql = "UPDATE FrameMeta SET nOTA = %d, numPhotoRef = %d" % (otaCount, self.totalNumPhotoRef)
+        self.scratchDb.stmt.execute(sql)
+        
+        return True
+
+    '''
+    Updates imageID {EXP_ID}{OTA} in the provided table
+    '''
+    def updateImageID(self, tableName, x, y):
+
+        sql = "UPDATE " + tableName + " SET imageID = %d%d%d" % (self.expID, x, y) 
+        self.scratchDb.stmt.execute(sql)
+
+    '''
+    Checks whether this batch has already been processed and published
+    '''
+    def alreadyProcessed(self):
+
+        return self.ippToPspsDb.alreadyProcessed("detection", "exp_id", self.expID)
+
+
+    '''
+    Overriding this method
+    '''
+    def reportNullsInAllPspsTables(self, showPartials):
+
+        # loops round all imported tables, but we want to check one OTA's worth
+        for table in self.pspsTables:
+            if table.name == "FrameMeta": self.scratchDb.reportNulls(table.name, showPartials)
+            else: self.scratchDb.reportNulls(table.name + "_XY33", showPartials)
+
+
+logging.config.fileConfig("logging.conf")
+logger = logging.getLogger("detectionbatch")
+logger.info("Starting")
+
+gpc1Db = Gpc1Db(logger)
+camIDs = gpc1Db.getIDsInThisDVODbForThisStage("MD04.V2", "cam")
+logger.info("Found %d exposures" % len(camIDs))
+
+i = 0
+for camID in camIDs:
+
+    logger.info("-------------------------------------------------- cam ID: %d" % camID)
+
+    file = gpc1Db.getCameraStageSmf(camID)
+    if not os.path.isfile(file):
+        logger.error("Cannot read file at '" + file)
+        continue
+
+    detectionBatch = DetectionBatch(logger, camID, file, False, True)
+
+    if not detectionBatch.alreadyProcessed():
+
+        detectionBatch.createEmptyPspsTables()
+        detectionBatch.importIppTables(".*.psf")
+        if detectionBatch.populatePspsTables():
+            detectionBatch.exportPspsTablesToFits("([a-zA-Z]+)")
+            detectionBatch.writeBatchManifest()
+            #detectionBatch.reportNullsInAllPspsTables(False)
+            #detectionBatch.createTarball()
+            #detectionBatch.publishToDatastore()
     
-detectionBatch = DetectionBatch()
-detectionBatch.createEmptyPspsTables()
-detectionBatch.importIppTables("XY33\.psf")
-detectionBatch.populatePspsTables()
-detectionBatch.exportPspsTablesToFits()
+            i = i+1
+           # if i > 0: sys.exit()
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/dvoToMySQL.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/dvoToMySQL.py	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/dvoToMySQL.py	(revision 31439)
@@ -0,0 +1,209 @@
+#!/usr/bin/env jython
+
+import stilts
+import datetime
+import re
+import sys
+import os
+import logging
+import glob
+from subprocess import call, PIPE, Popen
+
+from gpc1db import Gpc1Db
+from scratchdb import ScratchDb
+
+from java.lang import *
+from java.sql import *
+from xml.etree.ElementTree import ElementTree, Element, tostring
+
+
+'''
+Class for pulling IDs from a DVO database and shoving in a MySQL database 
+'''
+class DvoToMySql(object):
+
+    '''
+    Constructor
+
+    '''
+    def __init__(self, logger, pathToDvo):
+
+        # set up logging
+        self.logger = logger
+        self.pathToDvo = pathToDvo
+        self.logger.debug("DvoToMySql class constructor")
+
+        self.logger.debug("Important DVO database at " + self.pathToDvo)
+
+        # open config
+        doc = ElementTree(file="config.xml")
+
+        # create database objects
+        self.scratchDb = ScratchDb(logger)
+        self.gpc1Db = Gpc1Db(self.logger)
+
+        # create DVO tables
+        #self.scratchDb.createDvoTables()
+
+        # import Images.dat table
+        sql = "DELETE FROM dvoMetaFull"
+        self.scratchDb.stmt.execute(sql)
+
+        imagesTableName = self.importFits(self.pathToDvo, 
+                "", 
+                "Images.dat", 
+                "IMAGE_ID SOURCE_ID CCDNUM EXTERN_ID FLAGS PHOTCODE NSTAR")
+        self.scratchDb.createIndex(imagesTableName, "IMAGE_ID")
+
+        # insert into dvoMetaFull
+        self.logger.info("Inserting all image meta data into database")
+        sql = "INSERT INTO dvoMetaNew ( \
+               sourceID, \
+               imageID, \
+               externID, \
+               flags, \
+               photcode \
+               ) SELECT \
+               SOURCE_ID, \
+               IMAGE_ID, \
+               EXTERN_ID, \
+               FLAGS, \
+               PHOTCODE \
+               FROM " + imagesTableName
+        self.scratchDb.stmt.execute(sql)
+
+        subdirs = ['n0000']
+
+        for subdir in subdirs:
+
+            files = glob.glob(pathToDvo + "/" + subdir + "/*.cpm")
+
+            #files = ['0247.06', '0244.06', '0244.10']
+
+            for file in files:
+
+                # get just filename, without extension
+                file = os.path.basename(os.path.splitext(file)[0])
+                self.logger.info("---------------------------------------------: " + file)
+
+                if self.scratchDb.alreadyImportedThisDvoTable(file): continue
+
+                # import cpm table and index
+                cpmTableName = self.importFits(self.pathToDvo, 
+                        subdir, 
+                        file + ".cpm", 
+                        "IMAGE_ID DET_ID OBJ_ID CAT_ID EXT_ID DB_FLAGS")
+                self.scratchDb.createIndex(cpmTableName, "CAT_ID")
+                self.scratchDb.createIndex(cpmTableName, "OBJ_ID")
+
+                # import cpt table and index
+                cptTableName = self.importFits(self.pathToDvo, 
+                        subdir, 
+                        file + ".cpt", 
+                        "OBJ_ID CAT_ID EXT_ID")
+                self.scratchDb.createIndex(cptTableName, "CAT_ID")
+                self.scratchDb.createIndex(cptTableName, "OBJ_ID")
+      
+                # shove SOURCE_IDs into measurement table
+                self.logger.info("Adding SOURCE_IDs into measurements table")
+                sql = "ALTER TABLE "+cpmTableName+" ADD COLUMN (SOURCE_ID SMALLINT)"
+                self.scratchDb.stmt.execute(sql)
+                sql = "UPDATE "+cpmTableName+" AS a, "+imagesTableName+" AS b \
+                       SET a.SOURCE_ID = b.SOURCE_ID \
+                       WHERE a.IMAGE_ID = b.IMAGE_ID"
+                self.scratchDb.stmt.execute(sql)
+
+                # shove PSPS objID in measurement table
+                self.logger.info("Adding PSPS objID into measurements table")
+                sql = "ALTER TABLE "+cpmTableName+" ADD COLUMN (PSPS_OBJ_ID BIGINT)"
+                self.scratchDb.stmt.execute(sql)
+                sql = "UPDATE "+cpmTableName+" AS a, "+cptTableName+" AS b \
+                       SET a.PSPS_OBJ_ID = b.EXT_ID \
+                       WHERE a.CAT_ID = b.CAT_ID \
+                       AND a.OBJ_ID = b.OBJ_ID" 
+                self.scratchDb.stmt.execute(sql)
+
+                self.logger.info("Putting everything into dvoDetectionFull table")
+                sql = "INSERT IGNORE INTO dvoDetectionFull (\
+                       sourceID \
+                       ,imageID \
+                       ,ippDetectID \
+                       ,detectID \
+                       ,ippObjID \
+                       ,objID \
+                       ,flags \
+                       ) SELECT \
+                       SOURCE_ID \
+                       ,IMAGE_ID \
+                       ,DET_ID \
+                       ,EXT_ID \
+                       ,CAT_ID * 1000000000 + OBJ_ID \
+                       ,PSPS_OBJ_ID \
+                       ,DB_FLAGS \
+                       FROM " + cpmTableName
+                self.scratchDb.stmt.execute(sql)
+
+                # now drop what we don't need
+                self.logger.info("Dropping tables")
+                self.scratchDb.dropTable(cpmTableName)
+                self.scratchDb.dropTable(cptTableName)
+       
+                self.scratchDb.setImportedThisDvoTable(file)
+
+        self.scratchDb.dropTable(imagesTableName)
+
+
+    '''
+    Destructor
+    '''
+    def __del__(self):
+
+        self.logger.debug("DvoToMySql destructor")
+
+    '''
+    Imports a FITS file. A regex filter lets you choose which tables to pull from the file
+    '''
+    def importFits(self, path, subdir, file, columns):
+
+      fullPath = path + "/" + subdir + "/" + file
+
+      if len(subdir) < 1: tableName = file
+      else: tableName = subdir + "_" + file
+
+      tableName = tableName.replace('.', '_')
+
+      self.logger.info("Attempting to import tables from '" + fullPath + "' to '" + tableName + "'")
+
+      tables = stilts.treads(fullPath)
+
+      count = 0
+      for table in tables:
+
+          self.logger.info("Reading IPP table " + table.name + " from FITS file")
+          table = stilts.tpipe(table, cmd='explodeall')
+     
+          # IPP FITS files are littered with infinities, so remove these
+          self.logger.info("Removing Infinity values from all columns")
+          table = stilts.tpipe(table, cmd='replaceval -Infinity null *')
+          table = stilts.tpipe(table, cmd='replaceval Infinity null *')
+
+          #try:
+          self.logger.info("Writing FITS table to database")
+          table.cmd_keepcols(columns).write(self.scratchDb.url + '#' + tableName)
+          #except:
+          #    self.logger.exception("   Problem writing table '" + table.name + "' to the database")
+          count = count + 1
+
+      self.logger.info("Done. Imported %d tables" % count)
+
+      return tableName
+
+logging.config.fileConfig("logging.conf")
+logger = logging.getLogger("dvotomysql")
+logger.info("Starting")
+
+dvoToMySql = DvoToMySql(logger, "/data/ipp005.0/gpc1/catdirs/MD04.merges/MD04.merge")
+#dvoToMySql = DvoToMySql(logger, "/export/ippc00.1/rhenders/MD04.merge")
+
+logger.info("Program complete")
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/gpc1db.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/gpc1db.py	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/gpc1db.py	(revision 31439)
@@ -0,0 +1,212 @@
+#!/usr/bin/env jython
+
+import re
+import sys
+import glob
+import os
+import logging
+
+from mysql import MySql
+from java.sql import *
+
+
+'''
+Class for GPC1 database connectivity
+'''
+class Gpc1Db(MySql):
+
+    '''
+    Constructor
+    '''
+    def __init__(self, logger):
+        super(Gpc1Db, self).__init__(logger,"gpc1database")
+
+    '''
+    Destructor
+    '''
+    def __del__(self):
+
+        self.logger.debug("Gpc1Db destructor")
+
+    '''
+    Gets a list of ids in this DVO database for this stage, could be cam or staticsky (so far)
+    '''
+    def getIDsInThisDVODbForThisStage(self, dvoDb, stage):
+
+        sql = "SELECT DISTINCT stage_id \
+               FROM addRun \
+               WHERE stage = '" + stage + "' \
+               AND dvodb = '" + dvoDb + "'"
+
+        try:
+            rs = self.stmt.executeQuery(sql)
+        except:
+            self.logger.exception("Can't query for ids in DVO")
+
+        ids = []
+        while (rs.next()):
+            ids.append(rs.getInt(1))
+
+        rs.close()
+
+        self.logger.debug("Found %d items in DVO database '%s' for stage='%s'" % (len(ids), dvoDb, stage))
+
+        return ids
+
+    '''
+    Gets a list of PSPS image IDs for this stack ID
+    '''
+    def getImageIDsForThisStackID(self, stackID):
+
+        self.logger.debug("Querying GPC1 for image IDs for stack ID: " + str(stackID))
+
+        sql = "SELECT DISTINCT CONCAT(exp_id, SUBSTR(class_id, 3, 4)) FROM ( \
+               SELECT DISTINCT exp_id,class_id \
+               FROM warpSkyCellMap \
+               JOIN warpRun USING(warp_id) \
+               JOIN stackInputSkyfile USING(warp_id) \
+               JOIN stackRun USING(stack_id,skycell_id) \
+               JOIN fakeRun USING(fake_id) \
+               JOIN camRun USING(cam_id)  \
+               JOIN chipRun USING(chip_id) \
+               WHERE stackRun.stack_id = " + str(stackID) + ") AS a"
+
+        try:
+            rs = self.stmt.executeQuery(sql)
+        except:
+            self.logger.exception("Can't query for imageIDs")
+
+        imageIDs = []
+        while (rs.next()):
+            imageIDs.append(rs.getString(1))
+        rs.close()
+
+        return imageIDs
+
+    '''
+    Gets some stack-stage meta data for this sky_id # TODO this SQL could surely be improved
+    '''
+    def getStackStageMeta(self, skyID, filter):
+
+        self.logger.debug("Querying GPC1 for stack meta data")
+
+        meta = []
+        sql = "SELECT \
+               stackRun.stack_id,\
+               stackRun.skycell_id \
+               FROM \
+               staticskyInput, staticskyRun, stackRun, staticskyResult \
+               WHERE staticskyRun.sky_id = staticskyInput.sky_id \
+               AND staticskyInput.stack_id = stackRun.stack_id \
+               AND staticskyInput.sky_id = staticskyResult.sky_id \
+               and staticskyInput.sky_id = %d \
+               and filter = '%s'" % (skyID, filter)
+
+
+        try:
+            rs = self.stmt.executeQuery(sql)
+            rs.first()
+            meta.append(rs.getInt(1))
+            meta.append(rs.getString(2))
+        except:
+            self.logger.exception("Can't query for stack meta")
+
+        return meta
+    '''
+    Gets some camera-stage meta data for this cam_id
+    '''
+    def getCameraStageMeta(self, camID):
+
+        self.logger.debug("Querying GPC1 for camera meta data")
+
+        meta = []
+        sql = "SELECT exp_id, exp_name, camRun.dist_group \
+               FROM camRun \
+               JOIN chipRun USING(chip_id) \
+               JOIN rawExp USING(exp_id) WHERE camRun.cam_id = %d" % camID
+
+        try:
+            rs = self.stmt.executeQuery(sql)
+            rs.first()
+            meta.append(rs.getInt(1))
+            meta.append(rs.getString(2))
+            meta.append(rs.getString(3))
+        except:
+            self.logger.exception("Can't query for camera meta")
+
+        return meta
+
+    '''
+    Gets a camera-stage smf for this cam_id
+    '''
+    def getCameraStageSmf(self, camID):
+
+        self.logger.debug("Querying GPC1 for camera smf files with cam_id = " + str(camID))
+
+        sql = "SELECT path_base \
+               FROM camProcessedExp \
+               JOIN camRun USING(cam_id) \
+               WHERE camRun.cam_id = %d" % camID
+
+        try:
+            rs = self.stmt.executeQuery(sql)
+            rs.first()
+        except:
+            self.logger.exception("Can't query for camera smfs")
+
+        # get path to base dir of cmf files
+        path = rs.getString(1)
+        path = path[0:path.rfind("/")]
+       
+        # list all cmf files if a neb path
+        files = []
+        if path.startswith("neb"):
+
+            f=os.popen("neb-ls -p "+path+"/%smf")
+            for i in f.readlines():
+                files.append(i.rstrip())
+
+        # or not a neb path
+        else:
+            files = glob.glob(path + "/*.cmf")
+
+        return files[0] # TODO just returning first file - check
+
+
+    '''
+    Gets all cmf files for this sky_id. handles both absolute paths and neb paths
+    '''
+    def getStackStageCmfs(self, skyID):
+
+        self.logger.debug("Querying GPC1 for stack cmf files")
+
+        sql = "SELECT path_base, num_inputs \
+               FROM staticskyResult \
+               WHERE sky_id = %d" % skyID
+
+        try:
+            rs = self.stmt.executeQuery(sql)
+            rs.first()
+        except:
+            self.logger.exception("Can't query for stack cmfs")
+
+        # get path to base dir of cmf files
+        path = rs.getString(1)
+        #path = path[0:path.rfind("/")]
+       
+        # list all cmf files if a neb path
+        files = []
+        if path.startswith("neb"):
+
+            f=os.popen("neb-ls -p "+path+"%cmf")
+            print "neb-ls -p "+path+"%cmf"
+            for i in f.readlines():
+                files.append(i.rstrip())
+                print i.rstrip()
+
+        # or not a neb path
+        else:
+            files = glob.glob(path + "*.cmf")
+
+        return files
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/initbatch.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/initbatch.py	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/initbatch.py	(revision 31439)
@@ -2,4 +2,6 @@
 
 import stilts
+import logging
+import logging.config
 from java.lang import *
 from java.sql import *
@@ -14,15 +16,14 @@
     Constructor
     '''
-    def __init__(self):
-       super(InitBatch, self).__init__(
-               "init", 
-               "", 
-               "init.fits",
-               "localhost",
-               "ipptopsps_scratch",
-               "ipp",
-               "ipp")
+    def __init__(self, logger):
+       super(InitBatch, self).__init__(logger, "init")
 
-initBatch = InitBatch()
+       self.outputFitsFile = "00000000.FITS";
+       self.outputFitsPath = self.localOutPath + "/" + self.outputFitsFile
+
+logging.config.fileConfig("logging.conf")
+logger = logging.getLogger("initbatch")
+initBatch = InitBatch(logger)
 initBatch.createEmptyPspsTables()
 initBatch.exportPspsTablesToFits()
+initBatch.writeBatchManifest()
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/ipptopspsdb.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/ipptopspsdb.py	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/ipptopspsdb.py	(revision 31439)
@@ -0,0 +1,164 @@
+#!/usr/bin/env jython
+
+import re
+import sys
+import os
+import logging
+
+from mysql import MySql
+from java.sql import *
+
+'''
+Class for ippToPsps database connectivity
+'''
+class IppToPspsDb(MySql):
+
+    '''
+    Constructor
+    '''
+    def __init__(self, logger):
+        super(IppToPspsDb, self).__init__(logger,"ipptopspsdatabase")
+
+    '''
+    Creates a new batch
+    '''
+    def createNewBatch(self, batchType, survey, dvoDb, datastoreProduct):
+
+        sql = "INSERT INTO batch ( \
+               batch_type, \
+               survey, \
+               dvo_db, \
+               datastore_product \
+               ) VALUES ( \
+               '" + batchType + "', \
+               '" + survey + "', \
+               '" + dvoDb + "', \
+               '" + datastoreProduct + "' \
+               )"
+
+        self.stmt.execute(sql)
+
+        sql = "SELECT MAX(batch_id) FROM batch"
+
+        batchID = -1;
+
+        try:
+            rs = self.stmt.executeQuery(sql)
+            rs.first()
+            batchID = rs.getInt(1)
+        except:
+            self.logger.exception("Unable to get batch ID")
+
+        self.logger.info("Created new batch in ippToPsps database with batchID = %d" % batchID)
+
+        return batchID;
+
+    '''
+    Updates min/max object ID on this table and batch 
+    '''
+    def updateMinMaxObjID(self, batchID, minObjID, maxObjID):
+
+        sql = "UPDATE batch SET \
+               min_obj_id = " + str(minObjID) + ", \
+               max_obj_id = " + str(maxObjID) + " \
+               WHERE batch_id = " + str(batchID)
+
+        self.stmt.execute(sql)
+
+    '''
+    Updates batch processed field 
+    '''
+    def updateProcessed(self, batchID, processed):
+
+        sql = "UPDATE batch \
+               SET processed = " + str(processed) + " \
+               WHERE batch_id = " + str(batchID)
+
+        self.stmt.execute(sql)
+
+    '''
+    Updates batch loaded_to_datastore field 
+    '''
+    def updateLoadedToDatastore(self, batchID, loadedToDatastore):
+
+        sql = "UPDATE batch \
+               SET loaded_to_datastore = " + str(loadedToDatastore) + " \
+               WHERE batch_id = " + str(batchID)
+
+        self.stmt.execute(sql)
+
+    '''
+    Have we already processed and published this batch?
+    '''
+    def alreadyProcessed(self, table, col, value):
+
+        sql = "SELECT COUNT(*) FROM \
+               " + table + " \
+               JOIN batch USING(batch_id) \
+               WHERE " + col + " = " + str(value) + " \
+               AND processed \
+               AND loaded_to_datastore"
+
+        try:
+            rs = self.stmt.executeQuery(sql)
+            rs.first()
+            if rs.getInt(1) > 0: 
+                self.logger.error("Batch with "+col+" = "+str(value)+" has already been processed and published to datastore")
+                return True
+            else: 
+                return False
+        except:
+            self.logger.exception("Unable to check whether this batch has already been processed")
+
+     
+
+    '''
+    Inserts some detection metadata for this batch ID
+    '''
+    def insertDetectionMeta(self, batchID, expID, filter):
+
+        sql = "INSERT INTO detection ( \
+               batch_id \
+               ,exp_id \
+               ,filter \
+               ) VALUES ( \
+               " + str(batchID) + " \
+               ," + str(expID) + " \
+               ,'" + filter + "' \
+               )"
+
+        self.stmt.execute(sql)
+
+    '''
+    Inserts some stack metadata for this batch ID
+    '''
+    def insertStackMeta(self, batchID, skyID, stackID, filter, stackType):
+
+        sql = "INSERT INTO stack ( \
+               batch_id \
+               ,sky_id \
+               ,stack_id \
+               ,filter \
+               ,stack_type \
+               ) VALUES ( \
+               " + str(batchID) + " \
+               ," + str(skyID) + " \
+               ," + str(stackID) + " \
+               ,'" + filter + "' \
+               ,'" + stackType + "' \
+               )"
+
+        self.stmt.execute(sql)
+
+
+    '''
+    Destructor
+    '''
+    def __del__(self):
+
+        self.logger.debug("IppToPspsDb Desstructor")
+        self.stmt.close()
+        self.con.close()
+
+
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/logging.conf
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/logging.conf	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/logging.conf	(revision 31439)
@@ -0,0 +1,28 @@
+[loggers]
+keys=root,simpleExample
+
+[handlers]
+keys=consoleHandler
+
+[formatters]
+keys=simpleFormatter
+
+[logger_root]
+level=DEBUG
+handlers=consoleHandler
+
+[logger_simpleExample]
+level=DEBUG
+handlers=consoleHandler
+qualname=simpleExample
+propagate=0
+
+[handler_consoleHandler]
+class=StreamHandler
+level=DEBUG
+formatter=simpleFormatter
+args=(sys.stdout,)
+
+[formatter_simpleFormatter]
+format=%(asctime)s | %(levelname)7s | %(message)s
+datefmt=%Y-%m-%d %H:%M:%S
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/mysql.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/mysql.py	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/mysql.py	(revision 31439)
@@ -0,0 +1,200 @@
+#!/usr/bin/env jython
+
+import re
+import sys
+import os
+import logging
+
+from java.lang import *
+from java.sql import *
+from xml.etree.ElementTree import ElementTree
+
+'''
+Base class of all MySql database classes.
+'''
+class MySql(object):
+
+    driverName="com.mysql.jdbc.Driver"
+
+    '''
+    Constructor
+
+    '''
+    def __init__(self, logger, dbType):
+
+        # set up logging
+        self.logger = logger
+        self.logger.debug("MySql class constructor")
+
+        # open config and grab database parameters
+        doc = ElementTree(file="config.xml")
+        self.dbName = doc.find(dbType +"/name").text
+        self.dbHost = doc.find(dbType +"/host").text
+        self.dbUser = doc.find(dbType +"/user").text
+        self.dbPass = doc.find(dbType +"/password").text
+
+        # set up JDBC connection
+        self.url = "jdbc:mysql://"+self.dbHost+"/"+self.dbName+"?user="+self.dbUser+"&password="+self.dbPass
+        self.con = DriverManager.getConnection(self.url)
+        self.stmt = self.con.createStatement()
+
+    '''
+    Destructor
+    '''
+    def __del__(self):
+
+        self.logger.debug("MySql destructor")
+        self.stmt.close()
+        self.con.close()
+
+    '''
+    Updates all rows of this column of this table with this value
+    '''
+    def updateAllRows(self, table, column, value):
+
+        sql = "UPDATE " + table + " SET " + column + " = " + value
+        self.stmt.execute(sql)
+
+    '''
+    Drops a table
+    '''
+    def dropTable(self, table):
+
+        sql = "DROP TABLE " + table
+        try: self.stmt.execute(sql)
+        except: return
+
+    '''
+    Alters a column to be unique
+    '''
+    def makeColumnUnique(self, table, column):
+
+        self.logger.debug("Making '"+column+"' unique on table '"+table+"'")
+
+        sql = "ALTER TABLE " + table + " ADD UNIQUE (" + column + ")"
+        try:
+            self.stmt.execute(sql)
+        except: pass
+            #self.logger.warn("Index already in place on '" + column + "' for table '" + table + "'")
+    '''
+    Adds an index to the supplied table and column
+    '''
+    def createIndex(self, table, column):
+
+        self.logger.debug("Creating index on column '"+column+"' for table '"+table+"'")
+
+        sql = "CREATE INDEX "+table+"_"+column+"_index ON "+table+" ("+column+")"
+        try:
+            self.stmt.execute(sql)
+        except: pass
+            #self.logger.warn("Index already in place on '" + column + "' for table '" + table + "'")
+
+    '''
+    Returns a list of column names for this table
+    '''
+    def getColumnNames(self, tableName):
+
+       sql = "SHOW COLUMNS FROM " + tableName
+       rs = self.stmt.executeQuery(sql)
+       columns = []
+       while (rs.next()): columns.append(rs.getString(1))
+       rs.close()
+       
+       return columns
+
+    '''
+    Replaces all NULL values in the provided table and column ith the provided substitute 
+    '''
+    def replaceNullsInThisColumn(self, tableName, column, sub):
+
+      sql = "UPDATE " + tableName + " SET " + column + " = " + sub + " WHERE " + column + " IS NULL"
+      self.stmt.execute(sql)
+
+    '''
+    Replaces all NULL values in the provided table with the provided substitute 
+    '''
+    def replaceNulls(self, tableName, sub):
+
+       # get list of columns
+       columns = self.getColumnNames(tableName)
+
+       # now loop through all columns and replace all NULLs with sub
+       for column in columns:
+          
+          sql = "UPDATE " + tableName + " SET " + column + " = " + sub + " WHERE " + column + " IS NULL"
+          self.stmt.execute(sql)
+
+    '''
+    Reports the number of rows with this columns set as this numeric value and then deletes them 
+    '''
+    def reportAndDeleteRowsWithThisValue(self, tableName, columnName, value):
+
+        sql = "SELECT COUNT(*) FROM " + tableName + " WHERE " + columnName + " = " + value
+        rs = self.stmt.executeQuery(sql)
+        rs.first()
+        nBadFlux = rs.getInt(1)
+        self.logger.info("%d NULL %s values in table %s. Deleting." % (nBadFlux, columnName, tableName))
+
+        sql="DELETE from " + tableName + " WHERE " + columnName + " = " + value
+        self.stmt.execute(sql)
+
+    '''
+    Reports the number of rows with this column NULL and then deletes them 
+    '''
+    def reportAndDeleteRowsWithNULLS(self, tableName, columnName):
+
+        sql = "SELECT COUNT(*) FROM " + tableName + " WHERE " + columnName + " IS NULL"
+        rs = self.stmt.executeQuery(sql)
+        rs.first()
+        nBadFlux = rs.getInt(1)
+        self.logger.info("%d NULL %s values in table %s. Deleting." % (nBadFlux, columnName, tableName))
+
+        sql="DELETE from " + tableName + " WHERE " + columnName + " IS NULL"
+        self.stmt.execute(sql)
+
+    '''
+    Searches a table and reports the columns that are either partially or completely populated with NULLs
+    '''
+    def reportNulls(self, tableName, showPartials):
+
+       # first, count rows
+       sql = "SELECT COUNT(*) FROM " + tableName
+       rs = self.stmt.executeQuery(sql)
+       rs.first()
+       numRows = rs.getInt(1)
+
+       # get list of columns
+       columns = self.getColumnNames(tableName)
+
+       print "+----------------------+---------------+"
+       print "|  %25s           |" % tableName
+       print "+----------------------+---------------+"
+
+       # now see which columns are full of NULLS, with are partially NULL
+       for column in columns:
+          
+          sql = "SELECT COUNT(*) FROM " + tableName + " WHERE " + column + " IS NULL"
+          rs = self.stmt.executeQuery(sql)
+          rs.first()
+          if rs.getInt(1) == numRows:
+              print "| %20s | all NULL      |" % column
+          elif showPartials and rs.getInt(1) > 0:
+              print "| %20s | partial NULL  |" % column
+       rs.close()
+       print "+----------------------+---------------+"
+
+    '''
+    Returns a row count for this table
+    '''
+    def getRowCount(self, table):
+
+        sql = "SELECT COUNT(*) FROM " + table
+        try:
+            rs = self.stmt.executeQuery(sql)  
+            rs.first()
+            return rs.getInt(1)
+        except:
+            self.logger.exception("Could not count rows for table: '" + table + "'")
+            return -1
+
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/removeFromDatastore.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/removeFromDatastore.py	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/removeFromDatastore.py	(revision 31439)
@@ -0,0 +1,17 @@
+#!/usr/bin/env jython
+
+from datastore import Datastore
+import logging
+import sys
+import getopt
+
+
+logging.config.fileConfig("logging.conf")
+logger = logging.getLogger("datastore")
+
+
+
+
+datastore = Datastore(logger)
+datastore.remove(str(sys.argv[1]))
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/run.sh
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/run.sh	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/run.sh	(revision 31439)
@@ -1,1 +1,1 @@
-~/jre1.6.0_24/bin/java -Xbootclasspath/a:../jars/stilts.jar:../jars/mysql-connector-java-5.1.14-bin.jar -jar ~/jython2.5.2/jython.jar $1
+~/jre1.6.0_24/bin/java -Xbootclasspath/a:../jars/stilts.jar:../jars/mysql-connector-java-5.1.14-bin.jar -jar ~/jython2.5.2/jython.jar $1 $2 $3 $4 $5 $6 $7 $8 $9
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/scratchdb.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/scratchdb.py	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/scratchdb.py	(revision 31439)
@@ -0,0 +1,197 @@
+#!/usr/bin/env jython
+
+import re
+import sys
+import os
+import logging
+
+from java.lang import *
+from java.sql import *
+
+from mysql import MySql
+
+'''
+Class for local scratch database connectivity
+'''
+class ScratchDb(MySql):
+
+    '''
+    Constructor
+    '''
+    def __init__(self, logger, useFull=False):
+        super(ScratchDb, self).__init__(logger,"localdatabase")
+
+        if useFull:
+            self.dvoMeta = "dvoMetaNew"
+            self.dvoDetection = "dvoDetectionFull"
+        else:
+            self.dvoMeta = "dvoMeta"
+            self.dvoDetection = "dvoDetection"
+
+        self.logger.debug("ScratchDb constructor, using DVO tables: " + self.dvoMeta + " and " + self.dvoDetection)
+
+    '''
+    Destructor
+    '''
+    def __del__(self):
+
+        self.logger.debug("ScratchDb destructor")
+
+    '''
+    Gets survey ID for this survey name
+    '''
+    def getSurveyID(self, name):
+     
+        sql = "SELECT surveyID FROM Survey WHERE name = '" + name + "'"
+        try:
+            rs = self.stmt.executeQuery(sql)
+            rs.first()
+            return rs.getInt(1)
+        except:
+            self.logger.exception("No survey ID found for this survey: '" + self.survey + "'")
+            return -1
+
+    '''
+    Gets DVO image flags
+    '''
+    def getDvoImageFlags(self, sourceID, externID):
+
+        flags = 0
+
+        sql = "SELECT flags FROM " + self.dvoMeta + " WHERE sourceID = %s AND externID = %s" % (sourceID, externID)
+        try:
+            rs = self.stmt.executeQuery(sql)  
+            rs.first()
+            flags = rs.getInt(1)
+        except:
+            self.logger.exception("Unable to get flags from dvo table")
+
+        return flags
+
+    '''
+    Gets imageID from extern ID
+    '''
+    def getImageIDFromExternID(self, sourceID, externID):
+
+        imageID = -1
+
+        sql = "SELECT imageID FROM " + self.dvoMeta + " WHERE sourceID = %s AND externID = %s" % (sourceID, externID)
+        try:
+            rs = self.stmt.executeQuery(sql)  
+            rs.first()
+            imageID = rs.getInt(1)
+        except:
+            self.logger.exception("Unable to get imageID from dvo meta table")
+
+        return imageID
+
+    '''
+    Gets photcode (aka photoCalID from dvo table)
+    '''
+    def getPhotoCalID(self, sourceID, externID):
+
+        photcode = -1
+
+        sql = "SELECT photcode FROM " + self.dvoMeta + " WHERE sourceID = %s AND externID = %s" % (sourceID, externID)
+        try:
+            rs = self.stmt.executeQuery(sql)  
+            rs.first()
+            photcode = rs.getInt(1)
+        except:
+            self.logger.exception("Unable to get photcode from dvo table with: " + sql)
+
+        return photcode
+
+    '''
+    Updates a table with filterID grabbed from Filter init table
+    '''
+    def updateFilterID(self, table, filter):
+
+        sql = "UPDATE "+table+" AS a, Filter AS b SET a.filterID=b.filterID WHERE b.filterType = '" + filter + "'"
+        self.stmt.execute(sql)
+
+    '''
+    Inserts a new sourceID/imageID combo into dvoMeta
+    '''
+    def insertNewDvoImage(self, sourceID, imageID):
+
+        sql = "INSERT INTO dvoMeta ( \
+               sourceID, \
+               imageID \
+               ) VALUES (\
+               " + str(sourceID) + ", \
+               " + str(imageID) + "    \
+               )"
+        self.stmt.execute(sql)
+
+    '''
+    Updates dvoDone table with this DVO table
+    '''
+    def setImportedThisDvoTable(self, name):
+
+        sql = "INSERT INTO dvoDone (name) VALUES ('" + name + "')"
+        self.stmt.execute(sql)
+        
+    '''
+    Have we already imported this DVO table?
+    '''
+    def alreadyImportedThisDvoTable(self, name):
+
+        sql = "SELECT COUNT(*) FROM dvoDone WHERE name = '" + name + "'"
+
+        try:
+            rs = self.stmt.executeQuery(sql)
+            rs.first()
+            if rs.getInt(1) > 0:
+                self.logger.error("DVO tables " + name + " have already been imported")
+                return True
+            else:
+                return False
+        except:
+            self.logger.exception("Unable to check whether this DVO table has been imported")
+
+
+    '''
+    Creates a table for for ID matching
+    '''
+    def createDvoTables(self):
+
+        self.logger.info("Creating DVO meta and detection tables")
+
+        sql = "DROP TABLE dvoMeta"
+        try: self.stmt.execute(sql)
+        except: pass
+        
+        sql = "DROP TABLE dvoDetection"
+        try: self.stmt.execute(sql)
+        except: pass
+
+        sql = "CREATE TABLE dvoMeta ( \
+               sourceID INT, \
+               imageID INT, \
+               flags INT, \
+               photcode INT, \
+               PRIMARY KEY (sourceID, imageID) \
+               )"
+
+        try: self.stmt.execute(sql)
+        except: 
+            self.logger.error("Unable to create DVO meta-data database table")
+
+        sql = "CREATE TABLE dvoDetection ( \
+               sourceID INT, \
+               imageID INT, \
+               ippDetectID BIGINT, \
+               detectID BIGINT, \
+               ippObjID BIGINT, \
+               objID BIGINT, \
+               flags INT, \
+               PRIMARY KEY (sourceID, imageID, ippDetectID) \
+               )"
+               #INDEX (sourceID), \
+               #INDEX (imageID), \
+               #INDEX (ippDetectID) \
+
+        try: self.stmt.execute(sql)
+        except: 
+            self.logger.error("Unable to create DVO detection database table")
Index: /branches/eam_branches/ipp-20110404/ippToPsps/jython/stackbatch.py
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/jython/stackbatch.py	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/jython/stackbatch.py	(revision 31439)
@@ -1,9 +1,18 @@
 #!/usr/bin/env jython
+
+import os.path
+import sys
 
 import stilts
 from java.lang import *
 from java.sql import *
+
+from gpc1db import Gpc1Db
 from batch import Batch
-
+import logging.config
+
+'''
+StackBatch class
+'''
 class StackBatch(Batch):
 
@@ -11,17 +20,66 @@
     Constructor
     '''
-    def __init__(self):
+    def __init__(self, logger, skyID, inputFile, stackType, useFullTables=False):
        super(StackBatch, self).__init__(
+               logger,
                "stack", 
-               #"/data/ipp053.0/eugene/md04.20110320/staticsky/MD04.V2/skycell.087/MD04.V2.skycell.087.stk.280.000.cmf", 
-               "demo.fits", 
-               "stack.fits",
-               "localhost",
-               "ipptopsps_scratch",
-               "ipp",
-               "ipp",
-               "MD04") # TODO
-
-
+               inputFile, 
+               "MD04",
+               useFullTables) # TODO
+
+       self.logger.info("StackBatch constructor. Creating batch from: '" + inputFile + "'")
+
+       self.skyID = skyID
+
+       # get filterID using init table
+       self.filter = self.header['FPA.FILTER']
+       self.filter = self.filter[0:1]
+
+       self.stackType = stackType
+       meta = self.gpc1Db.getStackStageMeta(self.skyID, self.header['FPA.FILTER'])
+       if len(meta) < 1: return
+       self.stackID = meta[0];
+       self.skycell = meta[1];
+
+       # determine skycell from header value
+       #self.skycell = "skycell.34" #= self.header['SKYCELL']
+       self.skycell = self.skycell[8:]
+
+       self.logger.info("Processing stack with ID: %d, type: %s and skycell: %s filter: %s" % (self.stackID, self.stackType, self.skycell, self.filter))
+
+
+       # delete PSPS tables
+       self.scratchDb.dropTable("StackMeta")
+       self.scratchDb.dropTable("StackDetection")
+       self.scratchDb.dropTable("StackModelFit")
+       self.scratchDb.dropTable("StackApFlx")
+       self.scratchDb.dropTable("StackToImage")
+       self.scratchDb.dropTable("SkinnyObject")
+       self.scratchDb.dropTable("ObjectCalColor")
+
+       # delete IPP tables
+       #self.scratchDb.dropTable("SkyChip_psf")
+       #self.scratchDb.dropTable("SkyChip_xsrc")
+       #self.scratchDb.dropTable("SkyChip_xfit")
+       #self.scratchDb.dropTable("SkyChip_xrad")
+
+       self.logger.info("Stack type: " + self.safeDictionaryAccess(self.header, self.stackType))
+       # obs time makes no sense except for nightly stacks
+       #if self.header['STK_TYPE'] != "NIGHTLY_STACK": self.header['MJD-OBS'] = "-999"
+
+       # create an output filename, which is {filterID}{skycellID}.FITS
+       self.outputFitsFile = "%s%07d.FITS" % (self.filter, int(self.skycell))
+       self.outputFitsPath = "%s/%s" % (self.localOutPath, self.outputFitsFile)
+
+       # set some constants
+       self.dataRelease = "1"
+       self.historyModNum = "0"
+
+       # insert what we know about this stack batch into the stack table
+       self.ippToPspsDb.insertStackMeta(self.batchID, self.skyID, self.stackID, self.filter, self.stackType)
+
+       # insert sourceID/imageID combo so DVO can look it up
+       if not self.useFullTables:
+           self.scratchDb.insertNewDvoImage(self.header['SOURCEID'], self.header['IMAGEID'])
 
     '''
@@ -30,6 +88,6 @@
     def updateStackMetaID(self, table):
 
-        sql = "UPDATE " + table + "  SET stackMetaID=" + self.header['STK_ID']
-        self.stmt.execute(sql)
+        sql = "UPDATE " + table + "  SET stackMetaID=" + str(self.stackID)
+        self.scratchDb.stmt.execute(sql)
 
     '''
@@ -38,6 +96,6 @@
     def updateStackTypeID(self, table):
 
-        sql = "UPDATE "+table+" AS a, StackType AS b SET a.stackTypeID=b.stackTypeID WHERE b.name = '"+self.header['STK_TYPE']+"'"
-        self.stmt.execute(sql)
+        sql = "UPDATE "+table+" AS a, StackType AS b SET a.stackTypeID=b.stackTypeID WHERE b.name = '" + self.stackType + "'"
+        self.scratchDb.stmt.execute(sql)
 
 
@@ -90,5 +148,5 @@
         WHERE a.ippDetectID=b.IPP_IDET AND b.PSF_FWHM "+psfCondition
 
-        self.stmt.execute(sql)
+        self.scratchDb.stmt.execute(sql)
 
     '''
@@ -138,5 +196,5 @@
         WHERE a.ippDetectID=b.IPP_IDET AND b.MODEL_TYPE = '"+ippModelType+"'"
 
-        self.stmt.execute(sql)
+        self.scratchDb.stmt.execute(sql)
 
         # sersic fit has an extra parameter
@@ -150,8 +208,10 @@
             "+modelLong+"Covar68=b.EXT_COVAR_05_07,  \
             "+modelLong+"Covar78=b.EXT_COVAR_06_07,  \
-            "+modelLong+"Covar88=b.EXT_COVAR_07_07   \
+            "+modelLong+"Covar88=b.EXT_COVAR_07_07,   \
+            "+"serNu=b.EXT_PAR_07,   \
+            "+"serNuErr=SQRT(EXT_COVAR_07_07)  \
             WHERE a.ippDetectID=b.IPP_IDET AND b.MODEL_TYPE = '"+ippModelType+"'"
 
-            self.stmt.execute(sql)
+            self.scratchDb.stmt.execute(sql)
 
 
@@ -160,11 +220,13 @@
     '''
     def populateStackMeta(self):
-        self.log("Procesing StackMeta table")
+        self.logger.info("Procesing StackMeta table")
 
         sql = "INSERT INTO StackMeta (\
         stackMetaID \
         ,skycellID \
+        ,photoCalID \
         ,photoZero \
-        ,nP2Images \
+        ,expTime \
+        ,psfModelID \
         ,ctype1 \
         ,ctype2 \
@@ -180,8 +242,10 @@
         ,pc002002 \
          ) VALUES ( \
-        " + self.header['STK_ID'] + " \
+        " + str(self.stackID) + " \
         ," + self.skycell + " \
+        ," + str(self.scratchDb.getPhotoCalID(self.header['SOURCEID'], self.header['IMAGEID'])) + " \
         ," + self.header['FPA.ZP'] + " \
-        ," + self.header['NINPUTS'] + " \
+        ," + self.header['EXPTIME'] + " \
+        ,'" + self.safeDictionaryAccess(self.header, 'PSFMODEL') + "' \
         ,'" + self.header['CTYPE1'] + "' \
         ,'" + self.header['CTYPE2'] + "' \
@@ -197,8 +261,9 @@
         ," + self.header['PC002002'] + " \
         )"
-        self.stmt.execute(sql)
-
-        self.updateSurveyID("StackMeta")
-        self.updateFilterID("StackMeta")
+        self.scratchDb.stmt.execute(sql)
+
+        self.scratchDb.updateAllRows("StackMeta", "surveyID", str(self.surveyID))
+        self.scratchDb.updateFilterID("StackMeta", self.filter)
+        self.scratchDb.updateAllRows("StackMeta", "dataRelease", str(self.dataRelease))
         self.updateStackTypeID("StackMeta")
 
@@ -207,9 +272,11 @@
     '''
     def populateStackDetection(self):
-        self.log("Procesing StackDetection table")
+        self.logger.info("Procesing StackDetection table")
 
         # insert all the detections
         sql = "INSERT INTO StackDetection (\
                ippDetectID \
+               ,skyCellID \
+               ,obsTime \
                ,xPos \
                ,yPos \
@@ -225,15 +292,35 @@
                ,psfWidMinor \
                ,psfTheta \
+               ,infoFlag \
                ,psfCf \
+               ,momentXX \
+               ,momentXY \
+               ,momentYY \
+               ,momentM3C \
+               ,momentM3S \
+               ,momentM4C \
+               ,momentM4S \
+               ,momentR1 \
+               ,momentRH \
+               ,apMag \
+               ,apMagErr \
+               ,kronFlux \
+               ,kronFluxErr \
+               ,kronRad \
+               ,kronRadErr \
                ,nFrames \
+               ,assocDate \
+               ,historyModNum \
                ) \
                SELECT \
                IPP_IDET \
+               ," + self.skycell + " \
+               ," + self.header['MJD-OBS'] + " \
                ,X_PSF \
                ,Y_PSF \
                ,X_PSF_SIG \
                ,Y_PSF_SIG \
-               ,PSF_INST_FLUX \
-               ,PSF_INST_FLUX_SIG \
+               ,POW(10.0, (-0.4*PSF_INST_MAG)) / "+self.header['EXPTIME']+" \
+               ,ABS((PSF_INST_MAG_SIG*(POW(10.0, (-0.4*PSF_INST_MAG)) / "+self.header['EXPTIME']+")) / 1.085736) \
                ,POW(10.0, (-0.4*PEAK_FLUX_AS_MAG)) / "+self.header['EXPTIME']+" \
                ,SKY \
@@ -243,21 +330,41 @@
                ,PSF_MINOR \
                ,PSF_THETA \
+               ,FLAGS << 32 | FLAGS2 \
                ,PSF_QF \
+               ,MOMENTS_XX \
+               ,MOMENTS_XY \
+               ,MOMENTS_YY \
+               ,MOMENTS_M3C \
+               ,MOMENTS_M3S \
+               ,MOMENTS_M4C \
+               ,MOMENTS_M4S \
+               ,MOMENTS_R1 \
+               ,MOMENTS_RH \
+               ,AP_MAG \
+               , NULL \
+               ,KRON_FLUX \
+               ,KRON_FLUX_ERR \
+               , NULL \
+               , NULL \
                ,N_FRAMES \
+               , '" + self.dateStr + "' \
+               ," + self.historyModNum + " \
                FROM SkyChip_psf"
 
-        self.stmt.execute(sql)
-
-        if self.header['STK_TYPE'] != "NIGHTLY_STACK": 
-            sql = "UPDATE StackDetection SET obsTime = " + self.header['MJD-OBS']
-            self.stmt.execute(sql)
-
-
-        sql = "UPDATE StackDetection SET skycellID = " + self.skycell + ", assocDate = '"+self.dateStr+"'"
-        self.stmt.execute(sql)
-        self.updateSurveyID("StackDetection")
-        self.updateFilterID("StackDetection")
+        self.scratchDb.stmt.execute(sql)
+
+        self.scratchDb.updateAllRows("StackDetection", "surveyID", str(self.surveyID))
+        self.scratchDb.updateFilterID("StackDetection", self.filter)
+        self.scratchDb.updateAllRows("StackDetection", "dataRelease", str(self.dataRelease))
+        self.scratchDb.updateAllRows("StackDetection", "primaryF", "0")
+        self.scratchDb.updateAllRows("StackDetection", "activeFlag", "0")
         self.updateStackMetaID("StackDetection")
         self.updateStackTypeID("StackDetection")
+        self.updateDvoIDs("StackDetection")
+
+        # now delete bad flux
+        self.scratchDb.reportAndDeleteRowsWithNULLS("StackDetection", "instFlux")
+        self.scratchDb.reportAndDeleteRowsWithNULLS("StackDetection", "objID")
+
 
     '''
@@ -265,5 +372,5 @@
     '''
     def populateStackApFlx(self):
-        self.log("Procesing StackApFlx table")
+        self.logger.info("Procesing StackApFlx table")
  
         sql = "INSERT INTO StackApFlx \
@@ -272,12 +379,18 @@
                DISTINCT IPP_IDET \
                FROM SkyChip_xrad"
-        self.stmt.execute(sql)
-
-        self.log("    Adding 1st convolved fluxes")
+
+        try:
+            self.scratchDb.stmt.execute(sql)
+        except: return
+
+        # TODO temporarily loading 1st convolved fluxes into unconvolved fields
+        self.logger.info("    Adding un-convolved fluxes")
+        self.updateApFlxs("", "< 7.0")
+        self.logger.info("    Adding 1st convolved fluxes")
         self.updateApFlxs("c1", "< 7.0")
-        self.log("    Adding 2nd convolved fluxes")
+        self.logger.info("    Adding 2nd convolved fluxes")
         self.updateApFlxs("c2", "> 7.0")
 
-        self.log("    Adding petrosian stuff for extended sources")
+        self.logger.info("    Adding petrosians for extended sources")
         sql = "UPDATE StackApFlx AS a, SkyChip_xsrc AS b SET \
         petRadius=b.PETRO_RADIUS \
@@ -290,19 +403,14 @@
         ,petR90Err=b.PETRO_RADIUS_90_ERR \
         WHERE a.ippDetectID=b.IPP_IDET"
-        self.stmt.execute(sql)
-
-        self.updateSurveyID("StackApFlx")
-        self.updateFilterID("StackApFlx")
+        self.scratchDb.stmt.execute(sql)
+
+        self.scratchDb.updateAllRows("StackApFlx", "surveyID", str(self.surveyID))
+        self.scratchDb.updateFilterID("StackApFlx", self.filter)
+        self.scratchDb.updateAllRows("StackApFlx", "dataRelease", str(self.dataRelease))
+        self.scratchDb.updateAllRows("StackApFlx", "primaryF", "0")
+        self.scratchDb.updateAllRows("StackApFlx", "activeFlag", "0")
         self.updateStackMetaID("StackApFlx")
         self.updateStackTypeID("StackApFlx")
-
-        #rs = stmt.executeQuery(sql)
-        # list = []
-
-        #while (rs.next()):
-
-        #       print rs.getString(1)
-
-        #rs.close()
+        self.updateDvoIDs("StackApFlx")
 
     '''
@@ -310,22 +418,86 @@
     '''
     def populateStackModelFit(self):
-        self.log("Procesing StackModelFit table")
+        self.logger.info("Procesing StackModelFit table")
 
         # insert all the detections
         sql = "INSERT INTO StackModelFit (ippDetectID) SELECT DISTINCT IPP_IDET from SkyChip_xfit"
-        self.stmt.execute(sql)
+        try:
+            self.scratchDb.stmt.execute(sql)
+        except:
+            return
+
 
         # populate model parameters
-        self.log("    Adding deVaucouleurs fit")
+        self.logger.info("    Adding deVaucouleurs fit")
         self.updateModelFit("deV", "PS_MODEL_DEV")
-        self.log("    Adding exponential fit")
+        self.logger.info("    Adding exponential fit")
         self.updateModelFit("exp", "PS_MODEL_EXP")
-        self.log("    Adding sersic fit")
+        self.logger.info("    Adding sersic fit")
         self.updateModelFit("ser", "PS_MODEL_SERSIC")
 
-        self.updateSurveyID("StackModelFit")
-        self.updateFilterID("StackModelFit")
+        self.scratchDb.updateAllRows("StackModelFit", "surveyID", str(self.surveyID))
+        self.scratchDb.updateFilterID("StackModelFit", self.filter)
+        self.scratchDb.updateAllRows("StackModelFit", "dataRelease", str(self.dataRelease))
+        self.scratchDb.updateAllRows("StackModelFit", "primaryF", "0")
+        self.scratchDb.updateAllRows("StackModelFit", "activeFlag", "0")
         self.updateStackMetaID("StackModelFit")
         self.updateStackTypeID("StackModelFit")
+        self.updateDvoIDs("StackModelFit")
+
+    '''
+    Populates the StackToImage table
+    '''
+    def populateStackToImage(self):
+        self.logger.info("Procesing StackToImage table")
+
+        imageIDs = self.gpc1Db.getImageIDsForThisStackID(self.stackID)
+
+        for imageID in imageIDs:
+            sql = "INSERT INTO StackToImage (stackMetaID, imageID) \
+                   VALUES (\
+                   " + str(self.stackID) + ", " + imageID + ")"
+            self.scratchDb.stmt.execute(sql)
+
+        # now update StackMeta with correct number of inputs
+        sql = "UPDATE StackMeta SET nP2Images = (SELECT COUNT(*) FROM StackToImage)"
+        self.scratchDb.stmt.execute(sql)
+
+    '''
+    Populates the SkinnyObject table
+    '''
+    def populateSkinnyObject(self):
+        self.logger.info("Procesing SkinnyObject table")
+
+        sql = "INSERT INTO SkinnyObject (\
+               objID \
+               ,ippObjID \
+               ) \
+               SELECT \
+               objID \
+               ,ippObjID \
+               FROM StackDetection"
+        self.scratchDb.stmt.execute(sql)
+
+        self.scratchDb.updateAllRows("SkinnyObject", "surveyID", str(self.surveyID))
+        self.scratchDb.updateAllRows("SkinnyObject", "dataRelease", str(self.dataRelease))
+
+    '''
+    Populates the ObjectCalColor table
+    '''
+    def populateObjectCalColor(self):
+        self.logger.info("Procesing ObjectCalColor table")
+
+        sql = "INSERT INTO ObjectCalColor (\
+               objID \
+               ,ippObjID \
+               ) \
+               SELECT \
+               objID \
+               ,ippObjID \
+               FROM StackDetection"
+        self.scratchDb.stmt.execute(sql)
+
+        self.scratchDb.updateFilterID("ObjectCalColor", self.filter)
+        self.scratchDb.updateAllRows("ObjectCalColor", "dataRelease", str(self.dataRelease))
 
 
@@ -333,10 +505,11 @@
     Applies indexes to the PSPS tables
     '''
-    def indexPspsTables(self):
-
-        self.log("Creating indexes on PSPS tables")
-        self.createIndex("StackDetection", "ippDetectID")
-        self.createIndex("StackApFlx", "ippDetectID")
-        self.createIndex("StackModelFit", "ippDetectID")
+    def alterPspsTables(self):
+
+        self.logger.info("Altering PSPS tables")
+        self.scratchDb.makeColumnUnique("StackDetection", "objID")
+        self.scratchDb.createIndex("StackDetection", "ippDetectID")
+        self.scratchDb.createIndex("StackApFlx", "ippDetectID")
+        self.scratchDb.createIndex("StackModelFit", "ippDetectID")
 
     '''
@@ -345,9 +518,27 @@
     def indexIppTables(self):
 
-        self.log("Creating indexes on IPP tables")
-        self.createIndex("SkyChip_psf", "IPP_IDET")
-        self.createIndex("SkyChip_xfit", "IPP_IDET")
-        self.createIndex("SkyChip_xrad", "IPP_IDET")
-        self.createIndex("SkyChip_xsrc", "IPP_IDET")
+        self.logger.info("Creating indexes on IPP tables")
+        self.scratchDb.createIndex("SkyChip_psf", "IPP_IDET")
+        self.scratchDb.createIndex("SkyChip_xfit", "IPP_IDET")
+        self.scratchDb.createIndex("SkyChip_xrad", "IPP_IDET")
+        self.scratchDb.createIndex("SkyChip_xsrc", "IPP_IDET")
+
+    '''
+    Updates provided table with DVO IDs from DVO table
+    '''
+    def updateDvoIDs(self, table):
+
+        imageID = self.scratchDb.getImageIDFromExternID(self.header['SOURCEID'], self.header['IMAGEID'])
+
+        self.logger.info("Updating table '" + table + "' with DVO IDs...")
+        sql = "UPDATE IGNORE " + table + " AS a, dvoDetectionFull AS b SET \
+               a.ippObjID = b.ippObjID, \
+               a.stackDetectID = b.detectID, \
+               a.objID = b.objID \
+               WHERE a.ippDetectID = b.ippDetectID \
+               AND b.sourceID = " + self.header['SOURCEID'] + "\
+               AND b.imageID = " + str(imageID)
+        self.scratchDb.stmt.execute(sql)
+
 
     '''
@@ -356,11 +547,7 @@
     def populatePspsTables(self):
 
-        # determine skycell from header value
-        self.skycell = self.header['SKYCELL']
-        self.skycell = self.skycell[8:]
-
-        # get filterID using init table
-        self.filter = self.header['FPA.FILTER']
-        self.filter = self.filter[0:1]
+        if not self.useFullTables:
+            if not self.getIDsFromDVO():
+                return False
 
         self.populateStackMeta()
@@ -368,9 +555,60 @@
         self.populateStackModelFit()
         self.populateStackApFlx()
-
-    
-stackBatch = StackBatch()
-stackBatch.createEmptyPspsTables()
-stackBatch.importIppTables(".*psf")
-stackBatch.populatePspsTables()
-stackBatch.exportPspsTablesToFits()
+        self.populateStackToImage()
+        self.populateSkinnyObject()
+        self.populateObjectCalColor()
+
+        self.setMinMaxObjID(["StackDetection"])
+        
+        return True
+
+    '''
+    Checks whether this batch has already been processed and published
+    '''
+    def alreadyProcessed(self):
+
+        return self.ippToPspsDb.alreadyProcessed("stack", "stack_id", self.stackID)
+
+logging.config.fileConfig("logging.conf")
+logger = logging.getLogger("stackbatch")
+logger.info("Starting")
+gpc1Db = Gpc1Db(logger)
+stackType = "NIGHTLY_STACK"
+skyIDs = gpc1Db.getIDsInThisDVODbForThisStage("MD04.Staticsky", "staticsky")
+#skyIDs = gpc1Db.getIDsInThisDVODbForThisStage("MD04.GENE.PSPSDEEP", "staticsky")
+#stackType = "DEEP_STACK"
+#skyIDs = [689]
+#skyIDs = [299]
+#skyIDs = [302]
+#skyIDs = [8508]
+i = 0
+for skyID in skyIDs:
+
+    logger.info("-------------------------------------------------- sky ID: %d" % skyID)
+
+    cmfFiles = gpc1Db.getStackStageCmfs(skyID)
+
+    for file in cmfFiles:
+
+        if not os.path.isfile(file):
+            logger.error("Cannot read file at '" + file)
+            continue
+
+        stackBatch = StackBatch(logger, skyID, file, stackType, True)
+
+        if not stackBatch.alreadyProcessed():
+
+            stackBatch.createEmptyPspsTables()
+            stackBatch.importIppTables("")
+            if stackBatch.populatePspsTables():
+ 
+                #stackBatch.reportNullsInAllPspsTables(False)
+                stackBatch.exportPspsTablesToFits()
+                stackBatch.writeBatchManifest()
+                #stackBatch.createTarball()
+                #stackBatch.publishToDatastore()
+
+                i = i + 1
+                #if i > 0: sys.exit()
+
+logger.info("Finished")
Index: /branches/eam_branches/ipp-20110404/ippToPsps/perl/pspsSchema2xml.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/perl/pspsSchema2xml.pl	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/perl/pspsSchema2xml.pl	(revision 31439)
@@ -307,5 +307,5 @@
 
     # parse line
-    if ($line =~ m/\s*([a-zA-Z0-9()-\[\]]+)\s+(.*)\s*--\/(.*)/) {
+    if ($line =~ m/\s*([a-zA-Z0-9()-_\[\]]+)\s+(.*)\s*--\/(.*)/) {
 
         $name = $1;
@@ -320,5 +320,5 @@
     }
     # no comment case
-    elsif ($line =~ m/\s*([a-zA-Z0-9()-\[\]]+)\s+(.*)/) {
+    elsif ($line =~ m/\s*([a-zA-Z0-9()-_\[\]]+)\s+(.*)/) {
 
         $name = $1;
@@ -394,4 +394,5 @@
             "arraysize" => $arraySize,
             "datatype" => $votType);
+    $votWriter->dataElement('DESCRIPTION', $comment);
     $votWriter->endTag();
 
Index: /branches/eam_branches/ipp-20110404/ippToPsps/src/Dvo.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/src/Dvo.c	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/src/Dvo.c	(revision 31439)
@@ -0,0 +1,220 @@
+/** @file Dvo.c
+ *
+ *  @ingroup ippToPsps
+ *
+ *  @author IfA
+ *  Copyright 2011 Institute for Astronomy, University of Hawaii
+ */
+
+#include "Dvo.h"
+
+/**
+  Destructor.
+  */
+static void destroy(Dvo* this) {
+
+    if (this == NULL) return;
+
+    this->logger->print(this->logger, MSG_DEBUG, "Dvo", "Destructor\n");
+
+    if (this->dvoConfig) dvoConfigFree(this->dvoConfig);
+    if (this->mysql) mysql_close(this->mysql);
+
+    free(this);
+}
+
+/**
+  Gets detections for this imageid
+  */
+static bool getDetections(Dvo* this, int32_t sourceId, int32_t imageId) {
+
+    SkyList* skyList = NULL;
+    Image* image = NULL;
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Getting skylist from DVO database...\n"); 
+    skyList = dvoSkyListByExternID(this->dvoConfig, sourceId, imageId, &image);
+    if (!skyList) {
+
+        this->logger->print(this->logger, MSG_ERROR, 
+                "Dvo", "Could not find skylist for sourceId=%d and image ID = %d\n", 
+                sourceId, imageId);
+
+        return false;
+    }
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "...done\n"); 
+
+    // now get detections
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Getting detections...\n"); 
+    dvoDetection* dvoDetections = NULL;
+    int32_t maxDetectionId = -1;
+    int32_t numDetections = 
+        dvoGetDetections(skyList, image->imageID, &dvoDetections, &maxDetectionId);
+
+    this->logger->print(this->logger, MSG_INFO, "Dvo", 
+            "Found %d detections with a max detection ID of %d\n", 
+            numDetections, maxDetectionId); 
+
+    if (dvoDetections) dvoFree(dvoDetections);
+    SkyListFree(skyList);
+
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Deleting everything from dvo table\n"); 
+    mysql_query(this->mysql, "DELETE FROM dvo");
+
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Inserting IDs into dvo table...\n"); 
+    
+    char sql[500];
+    for (int i=0; i<numDetections; i++) {
+
+        sprintf(sql, 
+                "INSERT INTO dvo (ippDetectID, ippObjID, objID) VALUES (%u, %lu, %lu)",
+                dvoDetections[i].meas.detID,
+                (uint64_t)dvoDetections[i].ave.catID*1000000000 + (uint64_t)dvoDetections[i].ave.objID,
+                dvoDetections[i].ave.extID);
+
+        mysql_query(this->mysql, sql); 
+    }
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "...done\n"); 
+
+#if 0
+    mysql_query(this->mysql, "SELECT * FROM Filter");
+    MYSQL_RES* result = mysql_store_result(this->mysql);
+
+    int num_fields = mysql_num_fields(result);
+
+    MYSQL_ROW row;
+
+    while ((row = mysql_fetch_row(result))) {
+
+        for(int i = 0; i < num_fields; i++) {
+
+            printf("%s ", row[i] ? row[i] : "NULL");
+        }
+        printf("\n");
+    }
+
+    mysql_free_result(result);
+#endif
+    return true;
+}
+
+/**
+  Constructor.
+  */
+Dvo* new_Dvo(Logger* logger, const char* dvoDatabase) {
+
+    Dvo* this = (Dvo*)calloc(1, sizeof(Dvo));
+    this->logger = logger;
+    this->logger->print(this->logger, MSG_DEBUG, "Dvo", "Constructor\n");
+
+    const char *configFile = "jython/config.xml";
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Using config file here '%s'\n", configFile);
+    xmlDoc* doc = xmlReadFile(configFile, NULL, 0);
+
+    // database parameters to be retrieved from config file
+    char host[20];
+    char user[20];
+    char passwd[20];
+    char dbname[20];
+
+
+    if (doc == NULL) {
+
+        this->logger->print(this->logger, MSG_ERROR, "Dvo", "Could not load config file\n");
+    }
+    else {
+
+        xmlNode* root_element = xmlDocGetRootElement(doc);
+
+
+        /* We don't care what the top level element name is */
+        xmlNodePtr cur = root_element->xmlChildrenNode;
+        char name[50];
+        unsigned char* value;
+        while (cur != NULL) {
+
+            // get database stuff
+            if (strcmp((char*)cur->name, "localdatabase") == 0) {
+
+                xmlNodePtr dbParams = cur->xmlChildrenNode;
+
+                while (dbParams != NULL) {
+
+                    sprintf(name, "%s", dbParams->name);
+                    value = xmlNodeListGetString(doc, dbParams->xmlChildrenNode, 1);
+                    if (strcmp(name, "name") == 0) sprintf(dbname, "%s", value);
+                    else if (strcmp(name, "user") == 0) sprintf(user, "%s", value);
+                    else if (strcmp(name, "host") == 0) sprintf(host, "%s", value);
+                    else if (strcmp(name, "password") == 0) sprintf(passwd, "%s", value);
+
+                    dbParams = dbParams->next;
+                }
+            }
+
+            cur = cur->next;
+        }
+
+        xmlFreeDoc(doc);
+    }
+
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Using DVO database = '%s'\n", dvoDatabase);
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Using db name      = '%s'\n", dbname);
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Using db host      = '%s'\n", host);
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Using db user      = '%s'\n", user);
+    this->logger->print(this->logger, MSG_INFO, "Dvo", "Using db password  = '%s'\n", passwd);
+
+    int argc = 4;
+    char** argv;
+    argv = (char**)calloc(argc, sizeof(char *));
+    for (int i=0; i<argc; i++)
+        argv[i] = (char*)calloc(200, sizeof(char));
+
+    sprintf(argv[0], "nothing");
+    sprintf(argv[1], "-D");
+    sprintf(argv[2], "CATDIR");
+    sprintf(argv[3], dvoDatabase);
+
+    this->dvoConfig = dvoConfigRead(&argc, argv);
+
+    for (int i=0; i<argc; i++) free(argv[i]);
+    free(argv);
+
+    // method pointers
+    this->destroy = destroy;
+    this->getDetections = getDetections;
+
+    // set up MySQL connection
+    this->mysql = mysql_init(NULL);
+
+    if (!this->mysql)
+        this->logger->print(this->logger, MSG_ERROR, "Dvo", "mysql_init(), out of memory\n");
+    else {
+
+        if (!mysql_real_connect(this->mysql, host, user, passwd, dbname, 0, NULL, 0)) 
+            this->logger->print(this->logger, MSG_ERROR, "Dvo", "Failed to connect to database: %s\n", 
+                    mysql_error(this->mysql));
+
+        else
+            this->logger->print(this->logger, MSG_INFO, "Dvo", "Connected to %s@%s as user '%s'\n",
+                    dbname, host, user);
+
+    }
+
+    return this;
+}
+
+
+/**
+  Main
+  */
+int main(int argc, char **argv) {
+
+    Logger* logger = new_Logger(NULL, true);
+
+    Dvo * dvo = new_Dvo(logger, "/data/ipp004.0/gpc1/catdirs/ThreePi.V1");
+    dvo->getDetections(dvo, 33, 8345290);
+    dvo->destroy(dvo);
+
+    logger->destroy(logger);
+
+    return 0;
+}
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/src/Dvo.h
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/src/Dvo.h	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/src/Dvo.h	(revision 31439)
@@ -0,0 +1,47 @@
+/** @file Dvo.h
+ *
+ *  @ingroup ippToPsps
+ *
+ *  @author IfA
+ *  Copyright 2011 Institute for Astronomy, University of Hawaii
+ */
+
+#ifndef IPPTOPSPS_DVO_H
+#define IPPTOPSPS_DVO_H
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include <mysql/mysql.h>
+#include <mysql/mysql_com.h>
+
+#include "dvo_util.h"
+#include <psmodules.h>
+
+#include "Logger.h"
+
+/**
+
+  Class encapsulating the DVO database
+
+*/
+typedef struct Dvo {
+
+    // fields
+    Logger* logger;
+    dvoConfig* dvoConfig;
+    MYSQL* mysql;
+
+    // methods
+    bool (*getDetections)();
+
+    // destructor
+    void (*destroy)();
+
+} Dvo; 
+
+// constructor
+Dvo* new_Dvo(Logger* logger, const char* dvoDatabase);
+
+#endif // IPPTOPSPS_DVO_H
+
Index: /branches/eam_branches/ipp-20110404/ippToPsps/src/Makefile.am
===================================================================
--- /branches/eam_branches/ipp-20110404/ippToPsps/src/Makefile.am	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippToPsps/src/Makefile.am	(revision 31439)
@@ -21,6 +21,13 @@
 
 # all the programs we create
-bin_PROGRAMS = initbatch detectionbatch stackbatch
+bin_PROGRAMS = dvo initbatch detectionbatch stackbatch
 
+
+# DVO
+dvo_CFLAGS = $(IPPTOPSPS_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) -I/usr/include/libxml2
+dvo_LDFLAGS = $(IPPTOPSPS_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) -lxml2
+dvo_SOURCES = \
+	Dvo.c \
+	Logger.c 
 
 # initbatch
Index: /branches/eam_branches/ipp-20110404/ippTools/share/Makefile.am
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/Makefile.am	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/Makefile.am	(revision 31439)
@@ -8,7 +8,16 @@
 	addtool_find_cam_id_dvo.sql \
 	addtool_find_cam_id.sql \
+	addtool_find_sky_id_dvo.sql \
+	addtool_find_sky_id.sql \
+	addtool_find_stack_id_dvo.sql \
+	addtool_find_stack_id.sql \
 	addtool_find_pendingexp.sql \
+	addtool_find_pendingexp_cam.sql \
+	addtool_find_pendingexp_stack.sql \
+	addtool_find_pendingexp_staticsky.sql \
 	addtool_find_pendingmergeprocess.sql \
-	addtool_find_processedexp.sql \
+	addtool_find_processedexp_cam.sql \
+	addtool_find_processedexp_stack.sql \
+	addtool_find_processedexp_staticsky.sql \
 	addtool_find_minidvodbprocessed.sql \
 	addtool_find_minidvodbrun.sql \
@@ -16,7 +25,11 @@
 	addtool_pendingcleanuprun.sql \
 	addtool_queue_cam_id.sql \
+	addtool_queue_stack_id.sql \
+	addtool_queue_sky_id.sql \
 	addtool_queue_minidvodbrun.sql \
 	addtool_revertminidvodbprocessed.sql \
-	addtool_revertprocessedexp.sql \
+	addtool_revertprocessedexp_cam.sql \
+	addtool_revertprocessedexp_stack.sql \
+	addtool_revertprocessedexp_staticsky.sql \
 	bgtool_advancechip.sql \
 	bgtool_advancewarp.sql \
@@ -164,4 +177,5 @@
 	disttool_definebyquery_fake.sql \
 	disttool_definebyquery_raw.sql \
+	disttool_definebyquery_raw_no_magic.sql \
 	disttool_definebyquery_sky.sql \
 	disttool_definebyquery_stack.sql \
@@ -400,3 +414,12 @@
 	diffphottool_advance.sql \
 	diffphottool_revert.sql \
-	diffphottool_data.sql
+	diffphottool_data.sql \
+	laptool_definerun.sql \
+	laptool_exposures.sql \
+	laptool_inactiveexp.sql \ 
+	laptool_listsequence.sql \
+	laptool_pendingchipexp.sql \
+	laptool_pendingexp.sql \
+	laptool_pendingrun.sql \
+	laptool_stacks.sql
+
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_cam_id.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_cam_id.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_cam_id.sql	(revision 31439)
@@ -11,8 +11,9 @@
                   addRun.dvodb AS previous_dvodb
            FROM addRun
-           JOIN camRun USING(cam_id)
+           JOIN camRun on cam_id=stage_id
 	   JOIN chipRun USING(chip_id)
           ) as foo
      ON exp_id = added_exp_id
+     AND stage = 'cam'
      -- hook for qualifying the join on the previous_dvodb
      AND %s
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_cam_id_dvo.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_cam_id_dvo.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_cam_id_dvo.sql	(revision 31439)
@@ -6,6 +6,6 @@
     AND exp_id NOT IN (SELECT exp_id
        FROM addRun
-       JOIN camRun USING(cam_id)
+       JOIN camRun on cam_id=stage_id
        JOIN chipRun USING(chip_id)
-       WHERE %s
+       WHERE stage = 'cam' AND %s
       )
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp.sql	(revision 31439)
@@ -1,20 +1,5 @@
 SELECT
-    addRun.*,
-    camProcessedExp.path_base as camroot,
-    rawExp.exp_tag,
-    rawExp.exp_id,
-    rawExp.exp_name,
-    rawExp.camera,
-    rawExp.telescope,
-    rawExp.filelevel
+    addRun.*
 FROM addRun
-JOIN camRun
-    USING(cam_id)
-JOIN camProcessedExp
-    USING(cam_id)
-JOIN chipRun
-    USING(chip_id)
-JOIN rawExp
-    USING(exp_id)
 LEFT JOIN addProcessedExp
     USING(add_id)
@@ -22,6 +7,5 @@
     ON addRun.label = addMask.label
 WHERE
-    camRun.state = 'full'
-    AND ((addRun.state = 'new' AND addProcessedExp.add_id IS NULL) OR addRun.state = 'update')
+((addRun.state = 'new' AND addProcessedExp.add_id IS NULL) OR addRun.state = 'update')
     AND addRun.dvodb IS NOT NULL
     AND addRun.workdir IS NOT NULL
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp_cam.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp_cam.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp_cam.sql	(revision 31439)
@@ -0,0 +1,30 @@
+SELECT
+    addRun.*,
+    camProcessedExp.path_base as stageroot,
+    rawExp.exp_tag,
+    rawExp.exp_id,
+    rawExp.exp_name,
+    rawExp.camera,
+    rawExp.telescope,
+    rawExp.filelevel
+FROM addRun
+JOIN camRun
+    on cam_id = stage_id
+JOIN camProcessedExp
+    USING(cam_id)
+JOIN chipRun
+    USING(chip_id)
+JOIN rawExp
+    USING(exp_id)
+LEFT JOIN addProcessedExp
+    USING(add_id)
+LEFT JOIN addMask
+    ON addRun.label = addMask.label
+WHERE
+    camRun.state = 'full' 
+    AND addRun.stage = 'cam' 
+    AND ((addRun.state = 'new' AND addProcessedExp.add_id IS NULL) OR addRun.state = 'update')
+    AND addRun.dvodb IS NOT NULL
+    AND addRun.workdir IS NOT NULL
+    AND addMask.label IS NULL
+
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp_stack.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp_stack.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp_stack.sql	(revision 31439)
@@ -0,0 +1,28 @@
+SELECT
+    addRun.*,
+    stackSumSkyfile.path_base as stageroot,
+    rawExp.camera,
+    rawExp.telescope
+FROM addRun
+JOIN stackRun
+    ON stack_id = stage_id
+JOIN stackSumSkyfile
+    USING(stack_id)
+JOIN stackInputSkyfile 
+     USING(stack_id)
+JOIN warpRun using(warp_id)
+JOIN fakeRun using(fake_id)
+JOIN camRun using(cam_id)
+JOIN chipRun using(chip_id)
+JOIN rawExp using (exp_id)
+LEFT JOIN addProcessedExp using (add_id)
+LEFT JOIN addMask
+    ON addRun.label = addMask.label
+WHERE
+    stackRun.state = 'full'
+    AND stage = 'stack'
+    AND ((addRun.state = 'new' AND addProcessedExp.add_id IS NULL) OR addRun.state = 'update')
+    AND addRun.dvodb IS NOT NULL
+    AND addRun.workdir IS NOT NULL
+    AND addMask.label IS NULL
+
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp_staticsky.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp_staticsky.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_pendingexp_staticsky.sql	(revision 31439)
@@ -0,0 +1,32 @@
+SELECT
+    addRun.*,
+    staticskyResult.path_base as stageroot,
+    rawExp.camera,
+    rawExp.telescope
+FROM addRun
+JOIN staticskyRun 
+    ON sky_id = stage_id
+JOIN staticskyResult
+     USING (sky_id)
+JOIN staticskyInput
+     USING (sky_id)
+JOIN stackRun
+    USING (stack_id)
+JOIN stackInputSkyfile 
+     USING(stack_id)
+JOIN warpRun using(warp_id)
+JOIN fakeRun using(fake_id)
+JOIN camRun using(cam_id)
+JOIN chipRun using(chip_id)
+JOIN rawExp using (exp_id)
+LEFT JOIN addProcessedExp using (add_id)
+LEFT JOIN addMask
+    ON addRun.label = addMask.label
+WHERE
+    staticskyRun.state = 'full'
+    AND stage = 'staticsky'
+    AND ((addRun.state = 'new' AND addProcessedExp.add_id IS NULL) OR addRun.state = 'update')
+    AND addRun.dvodb IS NOT NULL
+    AND addRun.workdir IS NOT NULL
+    AND addMask.label IS NULL
+
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_processedexp_cam.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_processedexp_cam.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_processedexp_cam.sql	(revision 31439)
@@ -0,0 +1,12 @@
+SELECT
+    addProcessedExp.*,
+    addRun.workdir
+FROM addProcessedExp
+JOIN addRun
+    USING(add_id)
+JOIN camRun
+    on cam_id = stage_id
+JOIN chipRun
+    USING(chip_id)
+JOIN rawExp
+    ON chipRun.exp_id = rawExp.exp_id
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_processedexp_stack.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_processedexp_stack.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_processedexp_stack.sql	(revision 31439)
@@ -0,0 +1,6 @@
+SELECT
+    addProcessedExp.*,
+    addRun.workdir
+FROM addProcessedExp
+JOIN addRun
+    USING(add_id)
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_processedexp_staticsky.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_processedexp_staticsky.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_processedexp_staticsky.sql	(revision 31439)
@@ -0,0 +1,6 @@
+SELECT
+    addProcessedExp.*,
+    addRun.workdir
+FROM addProcessedExp
+JOIN addRun
+    USING(add_id)
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_sky_id.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_sky_id.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_sky_id.sql	(revision 31439)
@@ -0,0 +1,22 @@
+SELECT
+    staticskyRun.*
+FROM 
+     staticskyResult
+join staticSkyRun using (sky_id)
+join staticSkyInput using (stack_id)
+JOIN stackRun USING(stack_id)
+
+LEFT JOIN (SELECT sky_id       AS added_sky_id,
+                  addRun.dvodb AS previous_dvodb
+           FROM addRun
+JOIN staticskyRun on sky_id = stage_id
+          ) as foo
+     ON sky_id = added_sky_id 
+     AND stage = 'sky'
+     -- hook for qualifying the join on the previous_dvodb
+     AND %s
+WHERE
+    staticskyRun.state = 'full'
+    AND staticskyResult.quality = 0
+    AND added_exp_id IS NULL
+    -- addtool adds checks on exposure being added to the dvodb previously
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_sky_id_dvo.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_sky_id_dvo.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_sky_id_dvo.sql	(revision 31439)
@@ -0,0 +1,9 @@
+SELECT staticskyRun.* FROM staticskyResult
+JOIN staticskyRun USING(sky_id)
+WHERE staticskyRun.state = 'full' and staticskyResult.quality = 0
+    AND sky_id NOT IN (SELECT sky_id
+       FROM addRun
+       JOIN staticskyResult on staticskyResult.sky_id = addRun.stage_id
+       JOIN staticskyRun USING(sky_id)
+       WHERE addRun.stage = 'staticsky' AND %s
+      )
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_stack_id.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_stack_id.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_stack_id.sql	(revision 31439)
@@ -0,0 +1,19 @@
+SELECT
+    stackRun.*
+FROM stackSumSkyfile
+JOIN stackRun USING(stack_id)
+
+LEFT JOIN (SELECT stack_id       AS added_stack_id,
+                  addRun.dvodb AS previous_dvodb
+           FROM addRun
+JOIN stackRun on stack_id = stage_id
+          ) as foo
+     ON stack_id = added_stack_id 
+     AND stage = 'stack'
+     -- hook for qualifying the join on the previous_dvodb
+     AND %s
+WHERE
+    stackRun.state = 'full'
+    AND stackSumSkyfile.quality = 0
+    AND added_exp_id IS NULL
+    -- addtool adds checks on exposure being added to the dvodb previously
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_stack_id_dvo.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_stack_id_dvo.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_find_stack_id_dvo.sql	(revision 31439)
@@ -0,0 +1,9 @@
+SELECT stackRun.* FROM stackSumSkyfile
+JOIN stackRun USING(stack_id)
+WHERE stackRun.state = 'full' and stackSumSkyfile.quality = 0
+    AND stack_id NOT IN (SELECT stack_id
+       FROM addRun
+       JOIN stackInputSkyfile on stackInputSkyfile.stack_id = addRun.stage_id
+       JOIN stackRun USING(stack_id)
+       WHERE addRun.stage = 'stack' AND %s
+      )
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_queue_cam_id.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_queue_cam_id.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_queue_cam_id.sql	(revision 31439)
@@ -2,5 +2,6 @@
     SELECT
         0,              -- add_id
-        cam_id,         -- cam_id
+	'cam',		-- stage
+        cam_id,         -- stage_id
         '%s',           -- state
         '%s',           -- workdir
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_queue_sky_id.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_queue_sky_id.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_queue_sky_id.sql	(revision 31439)
@@ -0,0 +1,21 @@
+INSERT INTO addRun
+    SELECT
+        0,              -- add_id
+        'staticsky',		-- stage
+        sky_id,         -- stage_id
+        '%s',           -- state
+        '%s',           -- workdir
+	'%s',           -- workdir_state
+        '%s',           -- reduction
+        '%s',           -- label
+        '%s',           -- data_group
+        '%s',           -- dvodb 
+        '%s',           -- note
+	%d,		-- image_only
+	%d,		-- minidvodb
+	'%s',           -- minidvodb_group 
+ 	'%s'	        -- minidvodb_name
+    FROM staticskyRun
+    WHERE
+        staticskyRun.state = 'full'
+        AND staticskyRun.sky_id = %lld
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_queue_stack_id.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_queue_stack_id.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_queue_stack_id.sql	(revision 31439)
@@ -0,0 +1,21 @@
+INSERT INTO addRun
+    SELECT
+        0,              -- add_id
+        'stack',		-- stage
+        stack_id,         -- stage_id
+        '%s',           -- state
+        '%s',           -- workdir
+	'%s',           -- workdir_state
+        '%s',           -- reduction
+        '%s',           -- label
+        '%s',           -- data_group
+        '%s',           -- dvodb 
+        '%s',           -- note
+	%d,		-- image_only
+	%d,		-- minidvodb
+	'%s',           -- minidvodb_group 
+ 	'%s'	        -- minidvodb_name
+    FROM stackRun
+    WHERE
+        stackRun.state = 'full'
+        AND stackRun.stack_id = %lld
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_revertprocessedexp_cam.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_revertprocessedexp_cam.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_revertprocessedexp_cam.sql	(revision 31439)
@@ -0,0 +1,10 @@
+DELETE FROM addProcessedExp
+USING addProcessedExp, addRun, camRun, chipRun, rawExp
+WHERE
+    addRun.add_id = addProcessedExp.add_id
+    AND addRun.stage_id = camRun.cam_id
+    AND camRun.chip_id = chipRun.chip_id
+    AND chipRun.exp_id = rawExp.exp_id
+    AND addProcessedExp.fault != 0
+    AND addRun.state = 'new'
+    AND addRun.stage = 'cam'
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_revertprocessedexp_stack.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_revertprocessedexp_stack.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_revertprocessedexp_stack.sql	(revision 31439)
@@ -0,0 +1,7 @@
+DELETE FROM addProcessedExp
+USING addProcessedExp, addRun
+WHERE
+    addRun.add_id = addProcessedExp.add_id
+    AND addProcessedExp.fault != 0
+    AND addRun.state = 'new'
+    AND addRun.stage = 'stack'
Index: /branches/eam_branches/ipp-20110404/ippTools/share/addtool_revertprocessedexp_staticsky.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/addtool_revertprocessedexp_staticsky.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/addtool_revertprocessedexp_staticsky.sql	(revision 31439)
@@ -0,0 +1,7 @@
+DELETE FROM addProcessedExp
+USING addProcessedExp, addRun
+WHERE
+    addRun.add_id = addProcessedExp.add_id
+    AND addProcessedExp.fault != 0
+    AND addRun.state = 'new'
+    AND addRun.stage = 'staticsky'
Index: /branches/eam_branches/ipp-20110404/ippTools/share/difftool_listrun.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/difftool_listrun.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/difftool_listrun.sql	(revision 31439)
@@ -20,4 +20,5 @@
     camProcessedInput.zpt_lq,
     camProcessedInput.zpt_uq,
+    camProcessedInput.fwhm_major,
     rawInput.comment,
     rawInput.exp_time,
@@ -25,4 +26,5 @@
     rawInput.exp_name AS exp_name_1,
     rawInput.exp_id AS exp_id_1,
+    rawInput.filter AS filter_1,
     rawInput.comment AS comment_1,
     rawInput.dateobs AS dateobs_1,
@@ -34,4 +36,5 @@
     rawTemplate.exp_name AS exp_name_2,
     rawTemplate.exp_id AS exp_id_2,
+    rawInput.filter AS filter_2,
     rawTemplate.comment AS comment_2,
     rawTemplate.dateobs AS dateobs_2,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/difftool_skyfile.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/difftool_skyfile.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/difftool_skyfile.sql	(revision 31439)
@@ -24,4 +24,5 @@
     rawInput.exp_name AS exp_name_1,
     rawInput.exp_id AS exp_id_1,
+    rawInput.filter AS filter_1,
     chipInput.chip_id AS chip_id_1,
     camInput.cam_id AS cam_id_1,
@@ -31,4 +32,5 @@
     rawTemplate.exp_name AS exp_name_2,
     rawTemplate.exp_id AS exp_id_2,
+    rawTemplate.filter AS filter_2,
     chipTemplate.chip_id AS chip_id_2,
     camTemplate.cam_id AS cam_id_2,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_definebyquery_raw_no_magic.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_definebyquery_raw_no_magic.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_definebyquery_raw_no_magic.sql	(revision 31439)
@@ -0,0 +1,18 @@
+SELECT 
+    'raw' AS stage,
+    rawExp.exp_id AS stage_id,
+    rawExp.exp_name AS run_tag,
+    rawExp.magicked,
+    CAST(NULL AS CHAR(255)) AS label,
+    CAST(NULL AS CHAR(255)) AS data_group,
+    distTarget.dist_group,
+    distTarget.target_id,
+    distTarget.clean
+FROM rawExp
+JOIN distTarget ON distTarget.stage = 'raw'
+    AND rawExp.filter = distTarget.filter
+JOIN rcInterest USING(target_id)
+LEFT JOIN distRun ON distRun.stage_id = exp_id AND distRun.target_id = distTarget.target_id
+WHERE distRun.dist_id IS NULL           -- no existing distRun for this exposure
+    AND distTarget.state = 'enabled'    -- target and intrest are enabled
+    AND rcInterest.state = 'enabled'
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_SSdiff.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_SSdiff.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_SSdiff.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     diffSkyfile.skycell_id AS component,
+    exp_type,
     clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_camera.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_camera.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_camera.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     'exposure' AS component,
+    exp_type,
     clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_chip.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_chip.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_chip.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     chipProcessedImfile.class_id AS component,
+    exp_type,
     distRun.clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_chip_bg.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_chip_bg.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_chip_bg.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     chipBackgroundImfile.class_id AS component,
+    exp_type,
     distRun.clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_diff.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_diff.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_diff.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     diffSkyfile.skycell_id AS component,
+    exp_type,
     clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_fake.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_fake.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_fake.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     fakeProcessedImfile.class_id AS component,
+    exp_type,
     clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_raw.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_raw.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_raw.sql	(revision 31439)
@@ -1,2 +1,4 @@
+SELECT * FROM (
+-- rawExp magicked with re_place
 SELECT
     distRun.dist_id,
@@ -6,4 +8,5 @@
     rawExp.exp_id AS stage_id,
     rawImfile.class_id AS component,
+    rawExp.exp_type,
     clean,
     rawExp.camera,
@@ -38,8 +41,49 @@
     AND distRun.stage = 'raw'
     AND distComponent.dist_id IS NULL
-    AND (rawExp.magicked OR distRun.no_magic)
+    -- AND (rawExp.magicked OR distRun.no_magic)
+    AND rawExp.magicked
     -- need to have magicked the chip image which makes the camera mask
     AND chipProcessedImfile.magicked != 0
     AND camRun.magicked > 0 
+    AND (Label.active OR Label.active IS NULL)
+UNION
+SELECT
+    -- raw images no_magic required
+    distRun.dist_id,
+    distRun.label,
+    distTarget.dist_group,
+    'raw' AS stage,
+    rawExp.exp_id AS stage_id,
+    rawImfile.class_id AS component,
+    rawExp.exp_type,
+    clean,
+    rawExp.camera,
+    CONCAT_WS('.', distRun.outroot, CONVERT(distRun.dist_id, CHAR)) as outdir,
+    -- XXX: replace this with rawImfile.path_base once it exists
+    TRIM(TRAILING '.fits' FROM rawImfile.uri) AS path_base,
+    CAST(NULL AS CHAR(255)) AS alt_path_base,
+    -- pass camera stage path base since we want the camera mask file. The script knows what to do
+    CAST(NULL AS CHAR(255)) AS chip_path_base,
+    CAST(NULL AS CHAR(255)) AS state,
+    CAST(NULL AS CHAR(255)) AS data_state,
+    0 as quality,
+    distRun.no_magic,
+    rawImfile.magicked,
+    IFNULL(Label.priority, 10000) AS priority
+FROM distRun
+JOIN distTarget USING(target_id, stage, clean)
+JOIN rawExp ON rawExp.exp_id = stage_id 
+            AND distTarget.stage = 'raw' AND distRun.alternate = 0
+JOIN rawImfile USING(exp_id)
+LEFT JOIN distComponent 
+    ON distRun.dist_id = distComponent.dist_id 
+    AND rawImfile.class_id = distComponent.component
+LEFT JOIN Label ON distRun.label = Label.label
+WHERE
+    distRun.state = 'new'
+    AND distRun.clean = 0
+    AND distRun.stage = 'raw'
+    AND distComponent.dist_id IS NULL
+    AND (distRun.no_magic)
     AND (Label.active OR Label.active IS NULL)
 UNION
@@ -52,4 +96,5 @@
     rawExp.exp_id AS stage_id,
     rawImfile.class_id AS component,
+    rawExp.exp_type,
     clean,
     rawExp.camera,
@@ -96,4 +141,5 @@
     rawExp.exp_id AS stage_id,
     'exposure' AS component,
+    rawExp.exp_type,
     clean,
     rawExp.camera,
@@ -120,2 +166,4 @@
     AND distComponent.dist_id IS NULL
     AND (Label.active OR Label.active IS NULL)
+) AS distRun
+WHERE 1
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_sky.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_sky.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_sky.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     stackRun.skycell_id AS component,
+    exp_type,
     clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_stack.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_stack.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_stack.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     stackRun.skycell_id AS component,
+    exp_type,
     clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_warp.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_warp.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_warp.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     warpSkyfile.skycell_id AS component,
+    exp_type,
     clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_warp_bg.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_warp_bg.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/disttool_pending_warp_bg.sql	(revision 31439)
@@ -6,4 +6,5 @@
     stage_id,
     warpBackgroundSkyfile.skycell_id AS component,
+    exp_type,
     clean,
     rawExp.camera,
Index: /branches/eam_branches/ipp-20110404/ippTools/share/laptool_definerun.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/laptool_definerun.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/laptool_definerun.sql	(revision 31439)
@@ -0,0 +1,16 @@
+SELECT want.exp_id, have.chip_id, false as private, true as active, false as pairwise
+  FROM
+  (SELECT exp_id FROM rawExp 
+     WHERE rawExp.exp_type= 'OBJECT' AND
+     rawExp.dateobs >= '2009-04-01T00:00:00.000000' AND
+-- Position restriction goes here.
+     @WHERE@
+  ) AS want
+  LEFT JOIN 
+  (SELECT *
+     FROM lapExp 
+     where private IS FALSE 
+     AND chip_id IS NOT NULL
+     AND active = TRUE ) AS have USING(exp_id)
+     
+
Index: /branches/eam_branches/ipp-20110404/ippTools/share/laptool_exposures.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/laptool_exposures.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/laptool_exposures.sql	(revision 31439)
@@ -0,0 +1,43 @@
+SELECT DISTINCT 
+    D.*,diffRun.state,
+    coalesce(CONVERT(sum(others.private),SIGNED),0) AS needs_remade 
+--      0 AS needs_remade
+    FROM (
+  SELECT DISTINCT 
+      W.*,CONVERT(IFNULL(diff1.diff_id,diff2.diff_id),SIGNED) AS diff_id FROM (
+    SELECT DISTINCT
+        lap_id,lapRun.tess_id,projection_cell,filter,lapRun.state as lapRun_state, lapRun.registered, lapRun.fault, lapRun.label, lapRun.dist_group,
+        lapExp.exp_id,lapExp.chip_id,lapExp.pair_id,private,pairwise,active,lapExp.data_state,
+        chipRun.state as chipRun_state, 
+	coalesce(CONVERT(sum(chipProcessedImfile.fault),SIGNED),0) as chip_faults, 
+	coalesce(CONVERT(sum(chipProcessedImfile.quality),SIGNED),0) as chip_quality,
+        camRun.cam_id, camRun.state as camRun_state,   
+	coalesce(CONVERT(sum(camProcessedExp.fault),SIGNED),0) AS cam_faults, 
+	coalesce(CONVERT(sum(camProcessedExp.quality),SIGNED),0) AS cam_quality,
+	fakeRun.fake_id, fakeRun.state as fakeRun_state, 
+	coalesce(CONVERT(sum(fakeProcessedImfile.fault),SIGNED),0) as fake_faults,
+  	warpRun.warp_id, warpRun.state as warpRun_state, 
+	coalesce(CONVERT(sum(warpSkyfile.fault),SIGNED),0) as warp_faults, 
+	coalesce(CONVERT(sum(warpSkyfile.quality),SIGNED),0) as warp_quality,
+        warpRun.magicked
+    FROM lapRun JOIN lapExp USING(lap_id)
+    LEFT JOIN chipRun USING(chip_id)
+    LEFT JOIN chipProcessedImfile USING(chip_id)
+    LEFT JOIN camRun USING(chip_id) LEFT JOIN camProcessedExp USING(cam_id)
+    LEFT JOIN fakeRun USING(cam_id) LEFT JOIN fakeProcessedImfile USING(fake_id)
+    LEFT JOIN warpRun USING(fake_id) LEFT JOIN warpSkyfile USING(warp_id)
+    WHERE    @WHERE@
+    AND (warpSkyfile.quality IS NULL OR
+         (warpSkyfile.quality != 8007      -- known cases where quality != 0, but everything's fine.
+          AND warpSkyfile.quality != 3006  -- known cases where quality != 0, but everything's fine.
+	  ))
+    GROUP BY lap_id,exp_id
+    ) AS W
+-- This was unreasonably slow in testing, so that's why I'm using a subquery here.
+  LEFT JOIN diffInputSkyfile AS diff1 ON (W.warp_id = diff1.warp1)
+  LEFT JOIN diffInputSkyfile AS diff2 ON (W.warp_id = diff2.warp2)
+) AS D
+LEFT JOIN diffRun USING(diff_id)
+LEFT JOIN lapExp AS others ON (D.chip_id = others.chip_id AND D.lap_id != others.lap_id)
+GROUP BY lap_id,exp_id
+
Index: /branches/eam_branches/ipp-20110404/ippTools/share/laptool_inactiveexp.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/laptool_inactiveexp.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/laptool_inactiveexp.sql	(revision 31439)
@@ -0,0 +1,41 @@
+SELECT DISTINCT 
+    D.*,diffRun.state AS diff_state,coalesce(CONVERT(sum(others.active),SIGNED),0) AS is_in_use FROM (
+  SELECT DISTINCT 
+      W.*,IFNULL(diff1.diff_id,diff2.diff_id) AS diff_id FROM (
+    SELECT DISTINCT
+        lapRun.lap_id, lapRun.seq_id, lapRun.tess_id, lapRun.projection_cell, lapRun.filter, lapRun.state, lapRun.label,
+        lapRun.dist_group, lapRun.registered, lapRun.fault, lapRun.quick_sass_id, lapRun.final_sass_id,
+        lapExp.exp_id,lapExp.chip_id,lapExp.pair_id,private,pairwise,active,lapExp.data_state,
+        chipRun.state as chipRun_state, 
+	CONVERT(sum(chipProcessedImfile.fault),SIGNED) as chip_faults, 
+	CONVERT(sum(chipProcessedImfile.quality),SIGNED) as chip_quality,
+        camRun.cam_id, camRun.state as camRun_state,   
+	CONVERT(sum(camProcessedExp.fault),SIGNED) AS cam_faults, 
+	CONVERT(sum(camProcessedExp.quality),SIGNED) AS cam_quality,
+	fakeRun.fake_id, fakeRun.state as fakeRun_state, 
+	CONVERT(sum(fakeProcessedImfile.fault),SIGNED) as fake_faults,
+  	warpRun.warp_id, warpRun.state as warpRun_state, 
+	CONVERT(sum(warpSkyfile.fault),SIGNED) as warp_faults, 
+	CONVERT(sum(warpSkyfile.quality),SIGNED) as warp_quality,
+        warpRun.magicked
+    FROM lapRun JOIN lapExp USING(lap_id)
+    LEFT JOIN chipRun USING(chip_id)
+    LEFT JOIN chipProcessedImfile USING(chip_id)
+    LEFT JOIN camRun USING(chip_id) LEFT JOIN camProcessedExp USING(cam_id)
+    LEFT JOIN fakeRun USING(cam_id) LEFT JOIN fakeProcessedImfile USING(fake_id)
+    LEFT JOIN warpRun USING(fake_id) LEFT JOIN warpSkyfile USING(warp_id)
+    WHERE lapExp.active = FALSE
+    AND @WHERE@
+    AND (warpSkyfile.quality IS NULL OR
+         (warpSkyfile.quality != 8007      -- known cases where quality != 0, but everything's fine.
+          AND warpSkyfile.quality != 3006  -- known cases where quality != 0, but everything's fine.
+          ))
+    GROUP BY lap_id,exp_id
+    ) AS W
+-- This was unreasonably slow in testing, so that's why I'm using a subquery here.
+  LEFT JOIN diffInputSkyfile AS diff1 ON (W.warp_id = diff1.warp1)
+  LEFT JOIN diffInputSkyfile AS diff2 ON (W.warp_id = diff2.warp2)
+) AS D
+LEFT JOIN diffRun USING(diff_id)
+LEFT JOIN lapExp AS others ON (D.chip_id = others.chip_id AND D.lap_id != others.lap_id)
+GROUP BY lap_id,exp_id
Index: /branches/eam_branches/ipp-20110404/ippTools/share/laptool_listsequence.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/laptool_listsequence.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/laptool_listsequence.sql	(revision 31439)
@@ -0,0 +1,1 @@
+select * from lapSequence
Index: /branches/eam_branches/ipp-20110404/ippTools/share/laptool_pendingchipexp.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/laptool_pendingchipexp.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/laptool_pendingchipexp.sql	(revision 31439)
@@ -0,0 +1,11 @@
+SELECT re_id,projection_cell,registered,reprocRun.state as reproc_state, tess_id,
+  exp_id,private,active,
+  chip_id,chipRun.state AS chip_state,
+  cam_id,camRun.state AS cam_state,
+  fake_id,fakeRun.state AS fake_state,
+  warp_id,warpRun.state AS warp_state
+  FROM reprocRun JOIN reprocExp USING(re_id)
+  LEFT JOIN chipRun USING(chip_id,tess_id)
+  LEFT JOIN camRun  USING(chip_id,tess_id)
+  LEFT JOIN fakeRun USING(fake_id,tess_id)
+  LEFT JOIN warpRun USING(fake_id,tess_id)
Index: /branches/eam_branches/ipp-20110404/ippTools/share/laptool_pendingexp.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/laptool_pendingexp.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/laptool_pendingexp.sql	(revision 31439)
@@ -0,0 +1,10 @@
+select lapRun.lap_id, lapRun.seq_id, lapRun.tess_id, lapRun.projection_cell, lapRun.filter, 
+       lapRun.state, lapRun.label,
+       lapRun.dist_group, lapRun.registered, lapRun.fault, lapRun.quick_sass_id, lapRun.final_sass_id,
+       exp_id, chip_id, pair_id, private, pairwise, active, lapExp.data_state,
+       dateobs, object, comment
+  FROM lapRun JOIN lapExp USING(lap_id)
+  JOIN rawExp USING(exp_id,filter)
+WHERE active IS TRUE AND lapRun.fault = 0
+-- lap_id restriction here.
+-- This probably needs to be sorted by dateobs.
Index: /branches/eam_branches/ipp-20110404/ippTools/share/laptool_pendingrun.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/laptool_pendingrun.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/laptool_pendingrun.sql	(revision 31439)
@@ -0,0 +1,1 @@
+SELECT * from lapRun
Index: /branches/eam_branches/ipp-20110404/ippTools/share/laptool_stacks.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/laptool_stacks.sql	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/laptool_stacks.sql	(revision 31439)
@@ -0,0 +1,103 @@
+SELECT 
+       lapRun.lap_id,lapRun.seq_id,lapRun.tess_id,lapRun.projection_cell,lapRun.filter,
+       lapRun.state,lapRun.label,lapRun.dist_group,lapRun.registered,lapRun.fault,
+       skycell_id,
+       lapRun.quick_sass_id,quick_data_group,quick_stack_id,quick_state,quick_fault,quick_quality,
+       lapRun.final_sass_id,final_data_group,final_stack_id,final_state,final_fault,final_quality
+       FROM
+       lapRun LEFT JOIN 
+       (
+SELECT DISTINCT 
+       lap_id,tess_id,projection_cell,filter,skycell_id,
+       quick_sass_id,quick_data_group,quick_stack_id,quick_state,quick_fault,quick_quality,
+       final_sass_id,final_data_group,final_stack_id,final_state,final_fault,final_quality
+       FROM
+       (select lapRun.lap_id,
+       	       stackAssociation.sass_id AS quick_sass_id,
+	       stackAssociation.data_group AS quick_data_group,
+	       stackAssociation.projection_cell,
+	       stackAssociation.tess_id,
+	       stackAssociation.filter,
+	       stackRun.stack_id AS quick_stack_id,
+	       stackRun.skycell_id,
+	       stackRun.state AS quick_state,
+	       stackSumSkyfile.fault AS quick_fault,
+	       stackSumSkyfile.quality AS quick_quality FROM
+	   lapRun 
+	   LEFT JOIN stackAssociation ON (lapRun.quick_sass_id = stackAssociation.sass_id)
+	   LEFT JOIN stackAssociationMap USING (sass_id)
+	   LEFT JOIN stackRun USING(stack_id)
+	   LEFT JOIN stackSumSkyfile USING(stack_id)
+	   WHERE 1 @WHERE@
+	   AND sass_id = lapRun.quick_sass_id
+       ) AS quick LEFT JOIN
+       (select lapRun.lap_id,
+       	       stackAssociation.sass_id AS final_sass_id,
+	       stackAssociation.data_group AS final_data_group,
+	       stackAssociation.projection_cell,
+	       stackAssociation.tess_id,
+	       stackAssociation.filter,
+	       stackRun.stack_id AS final_stack_id,
+	       stackRun.skycell_id,
+	       stackRun.state AS final_state,
+	       stackSumSkyfile.fault AS final_fault,
+	       stackSumSkyfile.quality AS final_quality FROM
+	   lapRun 
+	   LEFT JOIN stackAssociation ON (lapRun.final_sass_id = stackAssociation.sass_id)
+	   LEFT JOIN stackAssociationMap USING (sass_id)
+	   LEFT JOIN stackRun USING(stack_id)
+	   LEFT JOIN stackSumSkyfile USING(stack_id)
+	   WHERE 1 @WHERE@
+	   AND sass_id = lapRun.final_sass_id
+       ) AS final USING(lap_id,projection_cell,tess_id,filter,skycell_id)
+       UNION
+SELECT DISTINCT 
+       lap_id,tess_id,projection_cell,filter,skycell_id,
+       quick_sass_id,quick_data_group,quick_stack_id,quick_state,quick_fault,quick_quality,
+       final_sass_id,final_data_group,final_stack_id,final_state,final_fault,final_quality
+       FROM
+       (select lapRun.lap_id,
+       	       stackAssociation.sass_id AS quick_sass_id,
+	       stackAssociation.data_group AS quick_data_group,
+	       stackAssociation.projection_cell,
+	       stackAssociation.tess_id,
+	       stackAssociation.filter,
+	       stackRun.stack_id AS quick_stack_id,
+	       stackRun.skycell_id,
+	       stackRun.state AS quick_state,
+	       stackSumSkyfile.fault AS quick_fault,
+	       stackSumSkyfile.quality AS quick_quality FROM
+	   lapRun 
+	   LEFT JOIN stackAssociation ON (lapRun.quick_sass_id = stackAssociation.sass_id)
+	   LEFT JOIN stackAssociationMap USING (sass_id)
+	   LEFT JOIN stackRun USING(stack_id)
+	   LEFT JOIN stackSumSkyfile USING(stack_id)
+	   WHERE 1 @WHERE@
+	   AND sass_id = lapRun.quick_sass_id
+       ) AS quick RIGHT JOIN
+       (select lapRun.lap_id,
+       	       stackAssociation.sass_id AS final_sass_id,
+	       stackAssociation.data_group AS final_data_group,
+	       stackAssociation.projection_cell,
+	       stackAssociation.tess_id,
+	       stackAssociation.filter,
+	       stackRun.stack_id AS final_stack_id,
+	       stackRun.skycell_id,
+	       stackRun.state AS final_state,
+	       stackSumSkyfile.fault AS final_fault,
+	       stackSumSkyfile.quality AS final_quality FROM
+	   lapRun 
+	   LEFT JOIN stackAssociation ON (lapRun.final_sass_id = stackAssociation.sass_id)
+	   LEFT JOIN stackAssociationMap USING (sass_id)
+	   LEFT JOIN stackRun USING(stack_id)
+	   LEFT JOIN stackSumSkyfile USING(stack_id)
+	   WHERE 1 @WHERE@
+	   AND sass_id = lapRun.final_sass_id
+       ) AS final USING(lap_id,projection_cell,tess_id,filter,skycell_id)
+ ) stacks ON (stacks.lap_id = lapRun.lap_id AND
+             stacks.projection_cell = lapRun.projection_cell AND
+             stacks.tess_id = lapRun.tess_id AND
+             stacks.filter = lapRun.filter AND
+             (lapRun.quick_sass_id IS NULL OR lapRun.quick_sass_id = stacks.quick_sass_id) AND
+             (lapRun.final_sass_id IS NULL OR lapRun.final_sass_id = stacks.final_sass_id))
+WHERE 1 @WHERE@
Index: /branches/eam_branches/ipp-20110404/ippTools/share/pxadmin_create_tables.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/pxadmin_create_tables.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/pxadmin_create_tables.sql	(revision 31439)
@@ -1891,4 +1891,59 @@
 ) ENGINE=innodb DEFAULT CHARSET=latin1;
 
+-- Tables for large area processing
+
+CREATE TABLE lapSequence (
+    seq_id BIGINT AUTO_INCREMENT, -- Identifier for the processing sequence
+    name VARCHAR(64) NOT NULL,    -- short name of the sequence
+    description VARCHAR(255) NOT NULL, -- longer description of the sequence
+    PRIMARY KEY(seq_id),
+    KEY(name)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE lapRun (
+    lap_id BIGINT AUTO_INCREMENT, -- Identifier for the processing run
+    seq_id BIGINT NOT NULL,       -- Identifier to match to the sequence
+    tess_id VARCHAR(64) NOT NULL, -- tessellation id to use
+    projection_cell VARCHAR(64) NOT NULL, -- projection cell from the tessellation to consider
+    filter VARCHAR(64) NOT NULL,  -- filter
+    state VARCHAR(64) NOT NULL,   -- state of run
+    label VARCHAR(64) NOT NULL,   -- processing label
+    dist_group VARCHAR(64) NOT NULL, -- distribution group for products of this run
+    registered TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- time run was registered
+    fault SMALLINT NOT NULL,      -- fault code
+    quick_sass_id BIGINT,         -- stackAssociation id for quick stack
+    final_sass_id BIGINT,         -- stackAssociation id for final stack
+    PRIMARY KEY(lap_id),
+    KEY(seq_id),
+    KEY(projection_cell),
+    KEY(filter),
+    KEY(state),
+    KEY(label),
+    KEY(fault),
+    FOREIGN KEY(seq_id) REFERENCES lapSequence(seq_id),
+    FOREIGN KEY(quick_sass_id) REFERENCES stackAssociation(sass_id),
+    FOREIGN KEY(final_sass_id) REFERENCES stackAssociation(sass_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE lapExp (
+    lap_id BIGINT NOT NULL, -- Link back to processing run
+    exp_id BIGINT NOT NULL, -- exposure definition
+    chip_id BIGINT,         -- processing id from chipRun
+    pair_id BIGINT,         -- companion chip_id
+    private TINYINT DEFAULT 0, -- denotes this exposure is private
+    pairwise TINYINT DEFAULT 0, -- denotes if this exposure should be pairwise diffed
+    active TINYINT DEFAULT 0, -- denotes if this exposure is currently in use
+    data_state VARCHAR(64) NOT NULL, -- state of exposure
+    PRIMARY KEY (lap_id),
+    KEY (exp_id),
+    KEY (chip_id),
+    KEY (pair_id),
+    KEY (data_state),
+    FOREIGN KEY (lap_id) REFERENCES lapRun(lap_id),
+    FOREIGN KEY (exp_id) REFERENCES rawExp(exp_id),
+    FOREIGN KEY (chip_id,exp_id) REFERENCES chipRun(chip_id,exp_id),
+    FOREIGN KEY (pair_id) REFERENCES chipRun(chip_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;    
+
 -- This comment line is here to avoid empty query error.
 -- Another way to avoid that problem is to omit the semicolon above but I think that is untidy.
Index: /branches/eam_branches/ipp-20110404/ippTools/share/stacktool_sassskyfile.sql
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/share/stacktool_sassskyfile.sql	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/share/stacktool_sassskyfile.sql	(revision 31439)
@@ -18,6 +18,6 @@
         where stack_id = stackRun.stack_id limit 1
     ) as camera
-FROM stackRun
-JOIN stackSumSkyfile USING(stack_id)
-JOIN stackAssociationMap USING(stack_id)
-JOIN stackAssociation USING(sass_id)
+FROM stackAssociation
+JOIN stackAssociationMap USING(sass_id)
+JOIN stackRun USING(stack_id)
+LEFT JOIN stackSumSkyfile USING(stack_id)
Index: /branches/eam_branches/ipp-20110404/ippTools/src/Makefile.am
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/Makefile.am	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/Makefile.am	(revision 31439)
@@ -28,5 +28,6 @@
 	pubtool \
 	diffphottool \
-	minidvodbtool
+	minidvodbtool \
+	laptool
 
 pkginclude_HEADERS = \
@@ -76,5 +77,6 @@
 	pubtool.h \
 	diffphottool.h \
-	minidvodbtool.h
+	minidvodbtool.h \
+	laptool.h
 
 lib_LTLIBRARIES = libpxtools.la
@@ -290,4 +292,10 @@
     minidvodbtoolConfig.c
 
+laptool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+laptool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+laptool_SOURCES = \
+    laptool.c \
+    laptoolConfig.c
+
 clean-local:
 	-rm -f TAGS
Index: /branches/eam_branches/ipp-20110404/ippTools/src/addtool.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/addtool.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/addtool.c	(revision 31439)
@@ -119,9 +119,26 @@
     pxcamGetSearchArgs (config, where);
     PXOPT_COPY_S64(config->args, where,  "-cam_id",    "camRun.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where,  "-stack_id",    "stackRun.stack_id", "==");
+ PXOPT_COPY_S64(config->args, where,  "-sky_id",    "staticskyRun.sky_id", "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
+    if (strcmp(stage, "cam")== 0) {
+
     pxAddLabelSearchArgs (config, where, "-label",     "camRun.label", "=="); // define using camRun label
     pxAddLabelSearchArgs (config, where, "-data_group","camRun.data_group", "=="); // define using camRun label
     PXOPT_COPY_STR(config->args, where,  "-reduction", "camRun.reduction", "==");
-
-
+    }
+    if (strcmp(stage, "stack")== 0) {
+
+    pxAddLabelSearchArgs (config, where, "-label",     "stackRun.label", "=="); // define using camRun label
+    pxAddLabelSearchArgs (config, where, "-data_group","stackRun.data_group", "=="); // define using camRun label
+    PXOPT_COPY_STR(config->args, where,  "-reduction", "stackRun.reduction", "==");
+    }
+    if (strcmp(stage, "staticsky")== 0) {
+
+    pxAddLabelSearchArgs (config, where, "-label",     "staticskyRun.label", "=="); // define using camRun label
+    pxAddLabelSearchArgs (config, where, "-data_group","staticskyRun.data_group", "=="); // define using camRun label
+    PXOPT_COPY_STR(config->args, where,  "-reduction", "staticskyyRun.reduction", "==");
+    }
+    
     if (!psListLength(where->list)) {
         psFree(where);
@@ -129,5 +146,5 @@
         return false;
     }
-
+    // PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     PXOPT_LOOKUP_STR(workdir,     config->args, "-set_workdir", false, false);
     PXOPT_LOOKUP_STR(dvodb,       config->args, "-set_dvodb", false, false);
@@ -148,6 +165,8 @@
     psString dvodb_string = NULL;
     psString bare_query = NULL;
+
+    if (strcmp(stage,"cam") == 0 ) {
     if (dvodb) {
-      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_cam_id_dvo.sql\n", dvodb);
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_cam_id_dvo.sql\n%s\n", dvodb,stage);
         // find the cam_id of all the exposures that we want to queue up.
         bare_query = pxDataGet("addtool_find_cam_id_dvo.sql");
@@ -155,5 +174,5 @@
 	psStringAppend(&dvodb_string, "addRun.dvodb = '%s'", dvodb);
     } else {
-        psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_find_cam_id.sql\n");
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_find_cam_id.sql\n%s\n",stage);
         // find the cam_id of all the exposures that we want to queue up.
         bare_query = pxDataGet("addtool_find_cam_id.sql");
@@ -161,4 +180,38 @@
         psStringAppend(&dvodb_string, "(camRun.dvodb IS NOT NULL AND previous_dvodb = camRun.dvodb)");
     }
+    }
+    if (strcmp(stage,"stack") == 0) {
+    if (dvodb ) {
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_stack_id_dvo.sql\n%s\n", dvodb,stage);
+        // find the cam_id of all the exposures that we want to queue up.
+        bare_query = pxDataGet("addtool_find_stack_id_dvo.sql");
+	// user supplied dvodb
+	psStringAppend(&dvodb_string, "addRun.dvodb = '%s'", dvodb);
+    } else {
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_find_stack_id.sql\n%s\n",stage);
+        // find the cam_id of all the exposures that we want to queue up.
+        bare_query = pxDataGet("addtool_find_stack_id.sql");
+        // inherit dvodb from camRun, avoid matching NULL
+        psStringAppend(&dvodb_string, "(stackRun.dvodb IS NOT NULL AND previous_dvodb = stackRun.dvodb)");
+    }
+    }
+    if (strcmp(stage,"staticsky") == 0) {
+    if (dvodb ) {
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_sky_id_dvo.sql\n%s\n", dvodb,stage);
+        // find the cam_id of all the exposures that we want to queue up.
+        bare_query = pxDataGet("addtool_find_sky_id_dvo.sql");
+	// user supplied dvodb
+	psStringAppend(&dvodb_string, "addRun.dvodb = '%s'", dvodb);
+    } else {
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_find_sky_id.sql\n%s\n",stage);
+        // find the cam_id of all the exposures that we want to queue up.
+        bare_query = pxDataGet("addtool_find_sky_id.sql");
+        // inherit dvodb from camRun, avoid matching NULL
+        psStringAppend(&dvodb_string, "(staticskyRun.dvodb IS NOT NULL AND previous_dvodb = staticskyRun.dvodb)");
+    }
+    }
+
+
+
     if (!bare_query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
@@ -184,9 +237,17 @@
 
     if (destreaked) {
+      if (strcmp(stage,"cam") == 0) {
         psStringAppend(&query, " AND (camRun.magicked > 0)");
-    }
+      }
+      if (strcmp(stage,"stack") == 0) {
+	psStringAppend(&query, " AND (stackRun.magicked > 0)");
+      }
+      // staticSky has no magicked column.
+    }
+
+    psTrace("addtool.c", PS_LOG_INFO,"query: \n\n%s\n\n",query);
 
     if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
+      psError(PS_ERR_UNKNOWN, false, "database error, \n%s\n", query);
         psFree(query);
         return false;
@@ -217,8 +278,10 @@
 
     // loop over our list of camRun rows to check the supplied and selected dvodb and workdir values:
+    if (strcmp(stage,"cam") == 0) {
     for (long i = 0; i < psArrayLength(output); i++) {
         psMetadata *md = output->data[i];
 
-        camRunRow *row = camRunObjectFromMetadata(md);
+	camRunRow *row = camRunObjectFromMetadata(md);
+	
         if (!row) {
             psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
@@ -240,4 +303,57 @@
         psFree(row);
     }
+    }
+    if (strcmp(stage,"stack") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+	stackRunRow *row = stackRunObjectFromMetadata(md);
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
+            psFree(output);
+            return false;
+        }
+
+        if (!dvodb && !row->dvodb) {
+            psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined dvodb: label: %s, stack_id %" PRId64, row->label, row->stack_id);
+            psFree(output);
+            return false;
+        }
+        if (!workdir && !row->workdir) {
+            psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined workdir: label: %s, stack_id %" PRId64, row->label, row->stack_id);
+            psFree(output);
+            return false;
+        }
+
+        psFree(row);
+    }
+    }
+    if (strcmp(stage,"staticsky") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+	staticskyRunRow *row = staticskyRunObjectFromMetadata(md);
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
+            psFree(output);
+            return false;
+        }
+
+        if (!dvodb) {  //there's no staticsky.dvodb
+            psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined dvodb: label: %s, sky_id %" PRId64, row->label, row->sky_id);
+            psFree(output);
+            return false;
+        }
+        if (!workdir && !row->workdir) {
+            psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined workdir: label: %s, sky_id %" PRId64, row->label, row->sky_id);
+            psFree(output);
+            return false;
+        }
+
+        psFree(row);
+    }
+    }
 
     // start a transaction so we don't end up with an exp without any associted
@@ -255,8 +371,12 @@
 
     // loop over our list of camRun rows
+    if (strcmp(stage,"cam") == 0) {
     for (long i = 0; i < psArrayLength(output); i++) {
         psMetadata *md = output->data[i];
-
-        camRunRow *row = camRunObjectFromMetadata(md);
+	psS64 stage_id =0; 
+	
+		  camRunRow *row = camRunObjectFromMetadata(md);
+	  stage_id = row->cam_id;
+	
         if (!row) {
             psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
@@ -267,5 +387,6 @@
         // queue the exp
         if (!pxaddQueueByCamID(config,
-                               row->cam_id,
+			       stage,
+                               stage_id,
                                workdir     ? workdir   : row->workdir,
                                reduction   ? reduction : row->reduction,
@@ -283,5 +404,5 @@
             }
             psError(PS_ERR_UNKNOWN, false,
-                    "failed to trying to queue chip_id: %" PRId64, row->cam_id);
+                    "failed to trying to queue stage %s %" PRId64,stage, stage_id);
             psFree(row);
             psFree(output);
@@ -290,4 +411,88 @@
         psFree(row);
     }
+      }
+    if (strcmp(stage,"stack") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+	psS64 stage_id =0; 
+	
+		  stackRunRow *row = stackRunObjectFromMetadata(md);
+	  stage_id = row->stack_id;
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        if (!pxaddQueueByCamID(config,
+			       stage,
+                               stage_id,
+                               workdir     ? workdir   : row->workdir,
+                               reduction   ? reduction : row->reduction,
+                               label       ? label     : row->label,
+                               data_group  ? data_group : (row->data_group ? row->data_group :  (label ? label : row->label)),
+                               dvodb       ? dvodb     : row->dvodb,
+                               note        ? note      : NULL,
+                               image_only,
+                               minidvodb,
+                               minidvodb_group,
+                               minidvodb_name
+        )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error sfg");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue stage %s %" PRId64,stage, stage_id);
+            psFree(row);
+            psFree(output);
+            return false;
+        }
+        psFree(row);
+    }
+      }
+    if (strcmp(stage,"staticsky") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+	psS64 stage_id =0; 
+	
+	staticskyRunRow *row = staticskyRunObjectFromMetadata(md);
+	stage_id = row->sky_id;
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        if (!pxaddQueueByCamID(config,
+			       stage,
+                               stage_id,
+                               workdir     ? workdir   : row->workdir,
+                               reduction   ? reduction : row->reduction,
+                               label       ? label     : row->label,
+                               data_group  ? data_group : (row->data_group ? row->data_group :  (label ? label : row->label)),
+                               dvodb       ? dvodb     : NULL,
+                               note        ? note      : NULL,
+                               image_only,
+                               minidvodb,
+                               minidvodb_group,
+                               minidvodb_name
+        )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error sfg");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue stage %s %" PRId64,stage, stage_id);
+            psFree(row);
+            psFree(output);
+            return false;
+        }
+        psFree(row);
+    }
+      }
+
     psFree(output);
 
@@ -308,4 +513,8 @@
     PXOPT_COPY_S64(config->args, where, "-add_id",    "addRun.add_id", "==");
     PXOPT_COPY_S64(config->args, where, "-cam_id",    "camRun.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-stack_id",    "stackRun.stack_id", "==");
+   PXOPT_COPY_S64(config->args, where, "-sky_id",    "staticskyRun.sky_id", "==");
+    
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where); // most search arguments based on camera
     PXOPT_COPY_STR(config->args, where, "-label",     "addRun.label", "==");
@@ -319,6 +528,14 @@
         return false;
     }
-
-    psString query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)");
+    psString query = NULL;
+    if (strcmp(stage, "cam")==0) {
+    query = psStringCopy("UPDATE addRun JOIN camRun on cam_id = stage_id JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)");
+    }
+    if (strcmp(stage, "stack")==0) {
+    query = psStringCopy("UPDATE addRun JOIN stackRun on stack_id = stage_id");
+    }
+    if (strcmp(stage, "staticsky")==0) {
+    query = psStringCopy("UPDATE addRun JOIN staticskyRun on sky_id = stage_id");
+    }
 
     // pxUpdateRun gets parameters from config->args and runs the update query
@@ -340,4 +557,7 @@
     PXOPT_COPY_S64(config->args, where, "-add_id",    "addRun.add_id", "==");
     PXOPT_COPY_S64(config->args, where, "-cam_id",    "camRun.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-stack_id",    "stackRun.stack_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-sky_id",    "staticskyRun.sky_id", "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where);
     pxAddLabelSearchArgs (config, where, "-label", "addRun.label", "==");
@@ -345,6 +565,18 @@
     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
-
-    psString query = pxDataGet("addtool_find_pendingexp.sql");
+    
+    psString query = NULL;
+    
+    if (strcmp(stage, "cam")==0) { 
+    query = pxDataGet("addtool_find_pendingexp_cam.sql");
+    }
+    if (strcmp(stage, "stack")==0) { 
+    query = pxDataGet("addtool_find_pendingexp_stack.sql");
+    }
+    if (strcmp(stage, "staticsky")==0) { 
+    query = pxDataGet("addtool_find_pendingexp_staticsky.sql");
+    }
+
+
     if (!query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -359,4 +591,12 @@
     }
     psFree(where);
+    if (strcmp(stage, "stack") == 0) {
+      //this group by is needed to join against all the warps (to get camera)
+      psStringAppend(&query, " GROUP BY %s", "stack_id");
+    }
+    if (strcmp(stage, "staticsky") == 0) {
+      //this group by is needed to join against all the warps (to get camera)
+      psStringAppend(&query, " GROUP BY %s", "sky_id");
+    }
 
     // treat limit == 0 as "no limit"
@@ -522,5 +762,6 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-add_id",    "addRun.add_id",    "==");
-    PXOPT_COPY_S64(config->args, where, "-cam_id",    "camRun.cam_id",    "==");
+    PXOPT_COPY_S64(config->args, where, "-stage_id",    "addRun.stage_id",    "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where);
     pxAddLabelSearchArgs (config, where, "-label",    "addRun.label",     "==");
@@ -537,6 +778,16 @@
         return false;
     }
-
-    psString query = pxDataGet("addtool_find_processedexp.sql");
+    psString query = NULL;
+
+    if (strcmp (stage,"cam") == 0) {
+    query = pxDataGet("addtool_find_processedexp_cam.sql");
+    }
+    if (strcmp (stage,"stack") == 0) {
+    query = pxDataGet("addtool_find_processedexp_stack.sql");
+    }
+    if (strcmp (stage,"staticsky") == 0) {
+    query = pxDataGet("addtool_find_processedexp_staticsky.sql");
+    }
+   
     if (!query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -567,4 +818,6 @@
         psStringAppend(&query, " %s", " WHERE addProcessedExp.fault = 0");
     }
+    psStringAppend(&query, " AND stage = '%s'", stage);
+
     psFree(where);
 
@@ -616,5 +869,6 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-add_id",    "addRun.add_id",         "==");
-    PXOPT_COPY_S64(config->args, where, "-cam_id",    "camRun.cam_id",         "==");
+    PXOPT_COPY_S64(config->args, where, "-stage_id",    "addRun.stage_id",         "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where);
     pxAddLabelSearchArgs (config, where, "-label",    "addRun.label",     "==");
@@ -634,8 +888,18 @@
 
     {
-        psString query = pxDataGet("addtool_revertprocessedexp.sql");
-        if (!query) {
+      psString query = NULL;
+      if (strcmp(stage, "cam") == 0) {
+         query = pxDataGet("addtool_revertprocessedexp_cam.sql");
+	}
+	
+    if (strcmp(stage, "stack") == 0) {
+	 query = pxDataGet("addtool_revertprocessedexp_stack.sql");
+      }
+     if (strcmp(stage, "staticsky") == 0) {
+	 query = pxDataGet("addtool_revertprocessedexp_staticsky.sql");
+      }
+      if (!query) {
             // rollback
-            if (!psDBRollback(config->dbh)) {
+	if (!psDBRollback(config->dbh)) {
                 psError(PS_ERR_UNKNOWN, false, "database error");
             }
@@ -681,5 +945,6 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-add_id",   "add_id",   "==");
-    PXOPT_COPY_S64(config->args, where, "-cam_id",  "cam_id",  "==");
+    PXOPT_COPY_S64(config->args, where, "-stage_id",  "stage_id",  "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     PXOPT_LOOKUP_S16(fault, config->args, "-fault", true, false);
 
Index: /branches/eam_branches/ipp-20110404/ippTools/src/addtoolConfig.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/addtoolConfig.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/addtoolConfig.c	(revision 31439)
@@ -49,5 +49,8 @@
     // -definebyquery
     psMetadata *definebyqueryArgs = psMetadataAlloc();
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-stage",             0, "set the stage (required)", NULL);
     psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-cam_id",             0, "search by cam_id", 0);
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-stack_id",             0, "search by stack_id", 0);
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-sky_id",             0, "search by sky_id", 0);
     pxcamSetSearchArgs(definebyqueryArgs);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by camRun label", NULL);
@@ -72,6 +75,9 @@
     // -updaterun
     psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-stage",             0, "set the stage (required)", NULL);
     psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-add_id",                 0, "search by add_id", 0);
     psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-cam_id",                 0, "search by cam_id", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-stack_id",                 0, "search by stack_id", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-sky_id",                 0, "search by sky_id", 0);
     pxcamSetSearchArgs(updaterunArgs);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label",                  0, "search by addRun label", NULL);
@@ -89,6 +95,9 @@
     // -pendingexp
     psMetadata *pendingexpArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingexpArgs, PS_LIST_TAIL, "-stage",             0, "set the stage (required)", NULL);
     psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-add_id",            0, "search by add_id", 0);
     psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-cam_id",            0, "search by cam_id", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-stack_id",                 0, "search by stack_id", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-sky_id",                 0, "search by sky_id", 0);
     pxcamSetSearchArgs(pendingexpArgs);
     psMetadataAddStr(pendingexpArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by addRun label", NULL);
@@ -109,5 +118,6 @@
     psMetadata *processedexpArgs = psMetadataAlloc();
     psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-add_id",   0,            "search by add_id", 0);
-    psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-cam_id",   0,            "search by cam_id", 0);
+    psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-stage_id",   0,            "search by stage_id", 0);
+    psMetadataAddStr(processedexpArgs, PS_LIST_TAIL, "-stage",             0, "set the stage", NULL);
     pxcamSetSearchArgs(processedexpArgs);
     psMetadataAddStr(processedexpArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by addRun label", NULL);
@@ -122,5 +132,6 @@
     psMetadata *revertprocessedexpArgs = psMetadataAlloc();
     psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-add_id",   0,            "search by add_id", 0);
-    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-cam_id",   0,            "search by cam_id", 0);
+    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-stage_id",   0,            "search by stage_id", 0);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-stage",             0, "set the stage", NULL);
     pxcamSetSearchArgs(revertprocessedexpArgs);
     psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-label",    PS_META_DUPLICATE_OK, "search by addRun label", NULL);
@@ -132,5 +143,6 @@
     psMetadata *updateprocessedexpArgs = psMetadataAlloc();
     psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-add_id", 0,            "search by addtool ID", 0);
-    psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-cam_id",  0,            "search by camtool ID", 0);
+    psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-stage_id",  0,            "search by stage_id", 0);
+    psMetadataAddStr(updateprocessedexpArgs, PS_LIST_TAIL, "-stage",             0, "set the stage", NULL);
     psMetadataAddS16(updateprocessedexpArgs, PS_LIST_TAIL, "-fault",  0,            "set fault code", 0);
 
Index: /branches/eam_branches/ipp-20110404/ippTools/src/dettool.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/dettool.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/dettool.c	(revision 31439)
@@ -1351,4 +1351,10 @@
     }
 
+    PXOPT_LOOKUP_STR(det_type, config->args, "-set_det_type", false, false);
+    if (det_type) {
+      updating = true;
+      PXOPT_COPY_STR(config->args,     values,       "-set_det_type", "det_type", "==");
+    }
+
 
     // either -rerun or -state must be specified
Index: /branches/eam_branches/ipp-20110404/ippTools/src/dettoolConfig.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/dettoolConfig.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/dettoolConfig.c	(revision 31439)
@@ -103,5 +103,6 @@
     psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-sun_angle_max",  0,            "define max solar angle", NAN);
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
-    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period (required)", NULL);
+    // i'm requiring time_begin because otherwise if not specified detselect will pick the wrong detrend for old date ranges (it will pick the most recent one with NULL)
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
@@ -848,4 +849,5 @@
     psMetadataAddBool(updatedetrunArgs, PS_LIST_TAIL, "-again",  0,            "start a new iteration of this detrend run", false);
     psMetadataAddStr(updatedetrunArgs, PS_LIST_TAIL, "-state",  0,            "set the state of this detrend run", false);
+    psMetadataAddStr(updatedetrunArgs, PS_LIST_TAIL, "-set_det_type", 0,          "set the det_type", NULL);
     psMetadataAddTime(updatedetrunArgs, PS_LIST_TAIL, "-set_time_begin",  0,            "start of period to apply detrend too", NULL);
     psMetadataAddTime(updatedetrunArgs, PS_LIST_TAIL, "-set_time_end",  0,            "end of period to apply detrend too", NULL);
Index: /branches/eam_branches/ipp-20110404/ippTools/src/difftool.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/difftool.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/difftool.c	(revision 31439)
@@ -1625,4 +1625,5 @@
     PXOPT_COPY_S64(config->args, selectWhere, "-exp_id", "inputRawExp.exp_id", "==");
     PXOPT_COPY_S64(config->args, selectWhere, "-template_exp_id", "templateRawExp.exp_id", "==");
+    PXOPT_COPY_S64(config->args, selectWhere, "-template_warp_id", "templateWarpRun.warp_id", "==");
     PXOPT_COPY_STR(config->args, selectWhere, "-filter", "inputRawExp.filter", "==");
     PXOPT_COPY_STR(config->args, selectWhere, "-obs_mode", "inputRawExp.obs_mode", "==");
@@ -2967,4 +2968,6 @@
     pxAddLabelSearchArgs (config, where, "-data_group", "diffRun.data_group", "LIKE");
     pxAddLabelSearchArgs (config, where, "-dist_group", "diffRun.dist_group", "LIKE");
+
+    PXOPT_COPY_S64(config->args, where, "-template_exp_id", "rawTemplate.exp_id", "==");
     
     PXOPT_LOOKUP_BOOL(template, config->args, "-template", false);
Index: /branches/eam_branches/ipp-20110404/ippTools/src/difftoolConfig.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/difftoolConfig.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/difftoolConfig.c	(revision 31439)
@@ -182,4 +182,5 @@
     psMetadataAddTime(listrunArgs, PS_LIST_TAIL, "-dateobs_end", 0,      "search for exposures by time (<=)", NULL);
     psMetadataAddStr(listrunArgs, PS_LIST_TAIL,  "-filter", 0,           "search for filter", NULL);
+    psMetadataAddS64(listrunArgs, PS_LIST_TAIL,  "-template_exp_id",  0, "search by exposure ID of template", 0);
     psMetadataAddStr(listrunArgs,  PS_LIST_TAIL, "-label",  PS_META_DUPLICATE_OK, "search by diffRun label (LIKE comparison)", NULL);
     psMetadataAddStr(listrunArgs,  PS_LIST_TAIL, "-data_group",  PS_META_DUPLICATE_OK, "search by diffRun data_group (LIKE comparison)", NULL);
@@ -277,4 +278,5 @@
     psMetadataAddBool(definewarpwarpArgs, PS_LIST_TAIL, "-not-bothways",  0, "only do the single-direction subtraction?", false);
     psMetadataAddS64(definewarpwarpArgs, PS_LIST_TAIL,  "-template_exp_id",  0,  "search by template exposure ID", 0);
+    psMetadataAddS64(definewarpwarpArgs, PS_LIST_TAIL,  "-template_warp_id",  0,  "search by template warp ID", 0);
     psMetadataAddStr(definewarpwarpArgs, PS_LIST_TAIL, "-filter", 0, "search by filter", NULL);
     psMetadataAddF32(definewarpwarpArgs, PS_LIST_TAIL, "-distance", 0, "limit distance between input and template (deg)", NAN);
Index: /branches/eam_branches/ipp-20110404/ippTools/src/flatcorr.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/flatcorr.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/flatcorr.c	(revision 31439)
@@ -664,4 +664,5 @@
         if (!pxaddQueueByCamID(
                 config,
+		"cam",
                 row->cam_id,
                 row->workdir,
Index: /branches/eam_branches/ipp-20110404/ippTools/src/laptool.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/laptool.c	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/laptool.c	(revision 31439)
@@ -0,0 +1,816 @@
+/*
+ * laptool.c
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#include "pxtools.h"
+#include "pxdata.h"
+#include "laptool.h"
+
+
+// Sequence level
+static bool definesequenceMode(pxConfig *config);
+static bool listsequenceMode(pxConfig *config);
+
+// Run level
+static bool definerunMode(pxConfig *config);
+static bool pendingrunMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+// Exposure level
+static bool pendingexpMode(pxConfig *config);
+static bool exposuresMode(pxConfig *config);
+static bool stacksMode(pxConfig *config);
+static bool updateexpMode(pxConfig *config);
+
+static bool inactiveexpMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+  case caseName: \
+  if (!func(config)) { \
+  goto FAIL; \
+  } \
+  break;
+
+int main(int argc, char **argv)
+{
+  psLibInit(NULL);
+
+  pxConfig *config = laptoolConfig(NULL, argc, argv);
+  if (!config) {
+    psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+    goto FAIL;
+  }
+
+  switch (config->mode) {
+    MODECASE(LAPTOOL_MODE_DEFINESEQUENCE, definesequenceMode);
+    MODECASE(LAPTOOL_MODE_LISTSEQUENCE,   listsequenceMode);
+    
+    MODECASE(LAPTOOL_MODE_DEFINERUN,     definerunMode);
+    MODECASE(LAPTOOL_MODE_PENDINGRUN,    pendingrunMode);
+    MODECASE(LAPTOOL_MODE_UPDATERUN,     updaterunMode);
+
+    MODECASE(LAPTOOL_MODE_PENDINGEXP,    pendingexpMode);
+    MODECASE(LAPTOOL_MODE_EXPOSURES,     exposuresMode);
+    MODECASE(LAPTOOL_MODE_STACKS,        stacksMode);
+    MODECASE(LAPTOOL_MODE_UPDATEEXP,     updateexpMode);
+
+    MODECASE(LAPTOOL_MODE_INACTIVEEXP,   inactiveexpMode);
+  default:
+    psAbort("invalid option (this should not happen)");
+  }
+  psTrace("laptool", 9, "Attempting to free config\n");
+  psFree(config);
+  pmConfigDone();
+  psLibFinalize();
+  exit(EXIT_SUCCESS);
+
+ FAIL:
+  psErrorStackPrint(stderr, "\n");
+  int exit_status = pxerrorGetExitStatus();
+
+  psFree(config);
+  pmConfigDone();
+  psLibFinalize();
+
+  exit(exit_status);
+}
+
+// Sequence level
+
+static bool definesequenceMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_STR(name,        config->args, "-name",        true, false);
+  PXOPT_LOOKUP_STR(description, config->args, "-description", true, false);
+  PXOPT_LOOKUP_BOOL(simple,     config->args, "-simple",     false);
+
+  lapSequenceRow *run = lapSequenceRowAlloc(0, // seq_id
+					    name,
+					    description);
+  if (!run) {
+    psError(PS_ERR_UNKNOWN, false, "failed to alloc lapSequence object");
+    return(true);
+  }
+
+  if (!psDBTransaction(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  if (!lapSequenceInsertObject(config->dbh, run)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(run);
+    return(true);
+  }
+
+  // point of no return
+  if (!psDBCommit(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  if (!lapSequencePrintObject(stdout, run, !simple)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to print object");
+    psFree(run);
+    return false;
+  }
+
+  psFree(run);
+
+  return true;  
+}
+
+static bool listsequenceMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",  false, false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-seq_id", "seq_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-seq_name",   "name",   "LIKE");
+
+  psString query = pxDataGet("laptool_listsequence.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return false;
+  }
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " WHERE %s", whereClause);
+    psFree(whereClause);
+  }
+
+  if (limit) {
+    psString limitString = psDBGenerateLimitSQL(limit);
+    psStringAppend(&query, " %s", limitString);
+    psFree(limitString);
+  }
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return false;
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+    }
+
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  if (psArrayLength(output)) {
+    if (!ippdbPrintMetadatas(stdout, output, "lapSequence", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+
+  psFree(output);
+
+  return true;
+}
+  
+
+// Run level
+static bool definerunMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_S64(seq_id,          config->args, "-seq_id",          true, false);
+  PXOPT_LOOKUP_STR(projection_cell, config->args, "-projection_cell", true, false);
+  PXOPT_LOOKUP_STR(tess_id,         config->args, "-tess_id",         true, false);
+  PXOPT_LOOKUP_F64(ra,              config->args, "-ra",              true, false);
+  PXOPT_LOOKUP_F64(decl,            config->args, "-decl",            true, false);
+  PXOPT_LOOKUP_F32(radius,          config->args, "-radius",          true, false);
+  PXOPT_LOOKUP_STR(filter,          config->args, "-filter",          true, false);
+  PXOPT_LOOKUP_STR(label,           config->args, "-label",           false, false);
+  PXOPT_LOOKUP_STR(dist_group,      config->args, "-dist_group",      false, false);
+  PXOPT_LOOKUP_BOOL(all_obsmode,    config->args, "-all_obsmode",     false);
+  PXOPT_LOOKUP_BOOL(simple,         config->args, "-simple",          false);
+
+  lapRunRow *run = lapRunRowAlloc(0, // lap_id
+				  seq_id,
+				  tess_id,
+				  projection_cell,
+				  filter,
+				  "new", // state
+				  label,
+				  dist_group,
+				  NULL, // registered
+				  0,    // fault
+				  INT64_MAX,    // quick_sass_id
+				  INT64_MAX     // final_sass_id
+				  );
+  if (!run) {
+    psError(PS_ERR_UNKNOWN, false, "failed to alloc lapRun object");
+    return(true);
+  }
+
+  if (!psDBTransaction(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  if (!lapRunInsertObject(config->dbh, run)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(run);
+    return(true);
+  }
+
+
+  if (!lapRunPrintObject(stdout, run, !simple)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "failed to print object");
+    psFree(run);
+    return false;
+  }
+
+  psS64 lap_id = psDBLastInsertID(config->dbh);
+
+  // Find the input exposures
+  psString query = pxDataGet("laptool_definerun.sql");
+  if (!query) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return(false);
+  }
+
+  // Add constraints to the exposure search:
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_STR(config->args, where, "-filter", "rawExp.filter", "==");
+
+  // This seems unnecessarily clunky.
+  if (!all_obsmode) {
+    //    fprintf(stderr, "Not doing all obsmodes!\n");
+    if (!psMetadataLookupStr(NULL,config->args,"-obsmode")) {
+      //      fprintf(stderr, "Not doing all obsmodes and none specified!\n");
+      psMetadataAddStr(where,PS_LIST_TAIL,"rawExp.obs_mode",0,"==","3PI");
+    }
+    pxAddLabelSearchArgs (config, where, "-obsmode", "rawExp.obsmode", "==");
+  }
+  
+  psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+  if (!pxspaceAddWhere(config, &whereClause, "rawExp")) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psError(psErrorCodeLast(), false, "pxSpaceAddWhere failed");
+    return(false);
+  }
+
+  if (whereClause) {
+    psStringSubstitute(&query,whereClause,"@WHERE@");
+  }
+  psFree(where);
+
+  // Fetch exposures
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return(false);
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return(false);
+  }
+  if (!psArrayLength(output)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return(true);
+  }
+
+  // Insert the exposure data
+  for (long i = 0; i < output->n; i++) {
+    psMetadata *row = output->data[i]; // Row from select
+    // Add default values from this run:
+    psMetadataAddS64(row, PS_LIST_TAIL, "lap_id", 0, "", lap_id);
+    psMetadataAddS64(row, PS_LIST_TAIL, "pair_id", 0, "", INT64_MAX);
+    psMetadataAddStr(row, PS_LIST_TAIL, "data_state", 0, "", "new");
+    lapExpRow *lapExp = lapExpObjectFromMetadata(row);
+    lapExp->lap_id = lap_id;
+
+    if (!lapExpInsertObject(config->dbh,lapExp)) {
+      if (!lapExpPrintObject(stdout, lapExp, !simple)) {
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+	psError(PS_ERR_UNKNOWN, false, "failed to print object");
+	psFree(run);
+	return false;
+      }
+      
+      if (!psDBRollback(config->dbh)) {
+	psError(PS_ERR_UNKNOWN, false, "database error");
+      }
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(output);
+      psFree(lapExp);
+      return(false);
+    }
+  }
+
+  // point of no return
+  if (!psDBCommit(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  
+  psFree(output);
+  return(true);  
+}
+
+static bool pendingrunMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-seq_id", "seq_id", "==");
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-projection_cell", "projection_cell", "==");
+  PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+  PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+  PXOPT_COPY_STR(config->args, where, "-state", "state", "==");
+  PXOPT_COPY_STR(config->args, where, "-fault", "fault", "==");
+
+  psString query = pxDataGet("laptool_pendingrun.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return false;
+  }
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " WHERE %s", whereClause);
+    psFree(whereClause);
+  }
+  
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return false;
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+    }
+
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  if (psArrayLength(output)) {
+    if (!ippdbPrintMetadatas(stdout, output, "lapRun", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+
+  psFree(output);
+
+  return true;
+}
+
+static bool updaterunMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_LOOKUP_S64(lap_id, config->args, "-lap_id", true, false);
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+
+  psMetadata *values = psMetadataAlloc();
+  PXOPT_LOOKUP_STR(state, config->args, "-set_state", false, false);
+  PXOPT_COPY_STR(config->args, values, "-set_state", "state", "==");
+  PXOPT_COPY_S16(config->args, values, "-fault",     "fault", "==");
+  PXOPT_COPY_STR(config->args, values, "-set_label", "label", "==");
+  PXOPT_COPY_S64(config->args, values, "-set_quick_sass_id", "quick_sass_id", "==");
+  PXOPT_COPY_S64(config->args, values, "-set_final_sass_id", "final_sass_id", "==");
+
+  long rows = psDBUpdateRows(config->dbh, "lapRun", where, values);
+  psFree(values);
+  
+  if (rows) {
+    // We're done with these exposures now, so mark them as inactive.
+    if (state) {
+      if ((strcmp(state,"drop") == 0)||
+	  (strcmp(state,"full") == 0)) {
+	values = psMetadataAlloc();
+	psMetadataAddBool(values, PS_LIST_TAIL, "active", 0, "", false);
+	long exps = psDBUpdateRows(config->dbh, "lapExp", where, values);
+	
+	if (exps) {
+	  return(true);
+	}
+	else {
+	  return(true); // We shouldn't really fail if we didn't change anything. Maybe there's nothing to change.
+	}
+      }
+    }
+  }
+
+  return(true);
+}
+
+// Exposure level
+
+static bool pendingexpMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",  false, false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+
+  psString query = pxDataGet("laptool_pendingexp.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return false;
+  }
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, "\n AND %s", whereClause);
+    psFree(whereClause);
+  }
+  psStringAppend(&query, " ORDER BY rawExp.dateobs ");
+  
+  if (limit) {
+    psString limitString = psDBGenerateLimitSQL(limit);
+    psStringAppend(&query, "\n %s", limitString);
+    psFree(limitString);
+  }
+
+  
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return false;
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+    }
+
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  if (psArrayLength(output)) {
+    if (!ippdbPrintMetadatas(stdout, output, "lapExp", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+
+  psFree(output);
+
+  return true;
+}
+
+
+static bool exposuresMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+  PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+  
+  psString query = pxDataGet("laptool_exposures.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return(false);
+  }
+  psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+  if (whereClause) {
+    psStringSubstitute(&query,whereClause,"@WHERE@");
+  }
+  
+  psString limitString = NULL;
+  if (limit) {
+    limitString = psDBGenerateLimitSQL(limit);
+    psStringPrepend(&limitString, "\n");
+  }
+
+  if (!p_psDBRunQueryF(config->dbh, query, whereClause, limitString ? limitString : "")) {
+    psError(PXTOOLS_ERR_PROG, false, "database error");
+    psFree(limitString);
+    psFree(query);
+    psFree(whereClause);
+    return(false);
+  }
+  psFree(limitString);
+  psFree(query);
+  psFree(whereClause);
+  
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return(false);
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return(true);
+  }
+  
+  if (!ippdbPrintMetadatas(stdout, output, "lapExp", !simple)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to print array");
+    psFree(output);
+    return(false);
+  }
+
+  psFree(output);
+  return(true);
+}
+
+static bool stacksMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+  PXOPT_LOOKUP_S64(lap_id, config->args, "-lap_id", true, false);
+
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lapRun.lap_id", "==");
+  
+  psString query = pxDataGet("laptool_stacks.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return(false);
+  }
+  
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringPrepend(&whereClause, "\n AND ");
+    psStringSubstitute(&query,whereClause,"@WHERE@");
+    psFree(whereClause);
+  }
+
+  if (limit) {
+    psString limitString = psDBGenerateLimitSQL(limit);
+    psStringAppend(&query, " %s", limitString);
+    psFree(limitString);
+  }
+
+
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return false;
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error %d",err);
+    }
+
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  if (psArrayLength(output)) {
+    if (!ippdbPrintMetadatas(stdout, output, "lapRunStacks", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+
+  psFree(output);
+  return(true);
+}
+
+static bool updateexpMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_LOOKUP_S64(lap_id,  config->args, "-lap_id",  true, false);
+  PXOPT_LOOKUP_S64(exp_id,  config->args, "-exp_id",  true, false);
+  PXOPT_LOOKUP_S64(chip_id, config->args, "-chip_id", false, false);
+
+  PXOPT_LOOKUP_S64(set_chip_id, config->args, "-set_chip_id", false, false);
+  PXOPT_LOOKUP_S64(set_pair_id, config->args, "-set_pair_id", false, false);
+  PXOPT_LOOKUP_STR(set_data_state, config->args, "-set_data_state", false, false);
+  PXOPT_LOOKUP_BOOL(private,    config->args, "-private",     false);
+  PXOPT_LOOKUP_BOOL(public,     config->args, "-public",      false);
+  PXOPT_LOOKUP_BOOL(pairwise,   config->args, "-pairwise",    false);
+  PXOPT_LOOKUP_BOOL(nopairwise, config->args, "-nopairwise",  false);
+  PXOPT_LOOKUP_BOOL(active,     config->args, "-active",      false);
+  PXOPT_LOOKUP_BOOL(inactive,   config->args, "-inactive",    false);
+
+
+  if (private && public) {
+    psError(PS_ERR_UNKNOWN, false, "only one of -private and -public may be selected");
+  }
+  if (active && inactive) {
+    psError(PS_ERR_UNKNOWN, false, "only one of -active and -inactive may be selected");
+  }
+  if (pairwise && nopairwise) {
+    psError(PS_ERR_UNKNOWN, false, "only one of -pairwise and -nopairwise may be selected");
+  }
+
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+  PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+  PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+
+
+  psMetadata *values = psMetadataAlloc();
+  if (set_chip_id) {
+    PXOPT_COPY_S64(config->args, values, "-set_chip_id", "chip_id", "==");
+  }
+  if (set_pair_id) {
+    PXOPT_COPY_S64(config->args, values, "-set_pair_id", "pair_id", "==");
+  }
+  if (private) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "private", 0, "==", true);
+  }
+  else if (public) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "private", 0, "==", false);
+  }
+  if (active) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "active", 0, "==", true);
+  }
+  else if (inactive) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "active", 0, "==", false);
+  }
+  if (pairwise) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "pairwise", 0, "==", true);
+  }
+  else if (nopairwise) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "pairwise", 0, "==", false);
+  }
+  if (set_data_state) {
+    PXOPT_COPY_STR(config->args, values, "-set_data_state", "data_state", "==");
+  }
+  long rows = psDBUpdateRows(config->dbh,"lapExp",where,values);
+  if (rows) {
+    return(true);
+  }
+/*   else { */
+/*     return(false); */
+/*   }   */
+  return(true);
+}
+
+
+    
+
+static bool inactiveexpMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+  PXOPT_LOOKUP_S64(lap_id,          config->args, "-lap_id",          true, false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+  
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+  
+  psString query = pxDataGet("laptool_inactiveexp.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return(false);
+  }
+  psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+  if (whereClause) {
+    psStringSubstitute(&query,whereClause,"@WHERE@");
+  }
+  
+  psString limitString = NULL;
+  if (limit) {
+    limitString = psDBGenerateLimitSQL(limit);
+    psStringPrepend(&limitString, "\n");
+  }
+
+  if (!p_psDBRunQueryF(config->dbh, query, whereClause, limitString ? limitString : "")) {
+    psError(PXTOOLS_ERR_PROG, false, "database error");
+    psFree(limitString);
+    psFree(query);
+    psFree(whereClause);
+    return(false);
+  }
+  psFree(limitString);
+  psFree(query);
+  psFree(whereClause);
+  
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return(false);
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return(true);
+  }
+  
+  if (!ippdbPrintMetadatas(stdout, output, "lapExp", !simple)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to print array");
+    psFree(output);
+    return(false);
+  }
+
+  psFree(output);
+  return(true);
+}
+
Index: /branches/eam_branches/ipp-20110404/ippTools/src/laptool.h
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/laptool.h	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/laptool.h	(revision 31439)
@@ -0,0 +1,28 @@
+/*
+ * laptool.h
+ */
+
+#ifndef LAPTOOL_H
+#define LAPTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+  LAPTOOL_MODE_NONE           = 0x0,
+  LAPTOOL_MODE_DEFINESEQUENCE,
+  LAPTOOL_MODE_LISTSEQUENCE,
+  LAPTOOL_MODE_DEFINERUN,
+  LAPTOOL_MODE_PENDINGRUN,
+  LAPTOOL_MODE_UPDATERUN,
+  LAPTOOL_MODE_PENDINGEXP,
+  LAPTOOL_MODE_EXPOSURES,
+  LAPTOOL_MODE_STACKS,
+  LAPTOOL_MODE_UPDATEEXP,
+  LAPTOOL_MODE_INACTIVEEXP
+} laptoolMode;
+
+pxConfig *laptoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // LAPTOOL_H
+
+
Index: /branches/eam_branches/ipp-20110404/ippTools/src/laptoolConfig.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/laptoolConfig.c	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/laptoolConfig.c	(revision 31439)
@@ -0,0 +1,165 @@
+/*
+ * laptoolConfig.c
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <stdint.h>
+
+#include <psmodules.h>
+#include "pxtools.h"
+#include "laptool.h"
+
+#define ADD_OPT(TYPE,TARG,NAME,COMMENT,DEFAULT) psMetadataAdd##TYPE(TARG, PS_LIST_TAIL, NAME, 0, COMMENT, DEFAULT)
+
+pxConfig *laptoolConfig(pxConfig *config, int argc, char **argv)
+{
+  if (!config) {
+    config = pxConfigAlloc();
+  }
+
+  pmConfigReadParamsSet(false);
+
+  // setup site config
+  config->modules = pmConfigRead(&argc, argv, NULL);
+  if (!config->modules) {
+    psError(psErrorCodeLast(), false, "Can't find site configuration");
+    psFree(config);
+    return NULL;
+  }
+
+  // -definesequence
+  psMetadata *definesequenceArgs = psMetadataAlloc();
+  ADD_OPT(Str, definesequenceArgs, "-name",                   "short name for this LAP sequence (required)", NULL);
+  ADD_OPT(Str, definesequenceArgs, "-description",            "define the description for this LAP sequence (required)", NULL);
+  ADD_OPT(Bool,definesequenceArgs, "-simple",                 "use the simple output format", false);
+  
+  // -listsequence
+  psMetadata *listsequenceArgs = psMetadataAlloc();
+  ADD_OPT(S64, listsequenceArgs, "-seq_id",                   "search by LAP sequence ID", 0);
+  ADD_OPT(Str, listsequenceArgs, "-seq_name",                 "search by LAP sequence name", 0);
+  ADD_OPT(Bool,listsequenceArgs, "-simple",                   "use the simple output format", false);
+  ADD_OPT(U64, listsequenceArgs, "-limit",                    "limit result set to N items", 0);
+
+  
+  // -definerun
+  psMetadata *definerunArgs = psMetadataAlloc();
+  ADD_OPT(S64, definerunArgs, "-seq_id",                      "define the LAP sequence for this run (required)", 0);
+  ADD_OPT(Str, definerunArgs, "-projection_cell",             "define the projection cell for this run (required)", NULL);
+  ADD_OPT(Str, definerunArgs, "-tess_id",                     "define the tessellation used (required)", NULL);
+  ADD_OPT(F64, definerunArgs, "-ra",                          "define RA center (required)", NAN);
+  ADD_OPT(F64, definerunArgs, "-decl",                        "define DEC center (required)", NAN);
+  ADD_OPT(F32, definerunArgs, "-radius",                      "define radius from center to consider (required)", NAN);
+  ADD_OPT(Str, definerunArgs, "-filter",                      "define the filter used (required)", NULL);
+  ADD_OPT(Str, definerunArgs, "-label",                       "define the label used", NULL);
+  ADD_OPT(Str, definerunArgs, "-dist_group",                  "define the distribution group for this data", NULL);
+
+  psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-obsmode", PS_META_DUPLICATE_OK, "search by obsmode", NULL);
+  ADD_OPT(Bool,definerunArgs, "-all_obsmode",                 "use all science obsmodes", false);
+  
+  ADD_OPT(Bool,definerunArgs, "-simple",                      "use the simple output format", false);
+  
+  // -pendingrun
+  psMetadata *pendingrunArgs = psMetadataAlloc();
+  ADD_OPT(S64, pendingrunArgs, "-seq_id",                     "search by LAP sequence ID", 0);
+  ADD_OPT(S64, pendingrunArgs, "-lap_id",                     "search by LAP run ID", 0);
+  ADD_OPT(Str, pendingrunArgs, "-projection_cell",            "search by projection cell", NULL);
+  ADD_OPT(Str, pendingrunArgs, "-filter",                     "search by filter", NULL);
+  ADD_OPT(Str, pendingrunArgs, "-label",                      "search by LAP run label", NULL);
+  ADD_OPT(Str, pendingrunArgs, "-state",                      "search by LAP run state", NULL);
+  ADD_OPT(Str, pendingrunArgs, "-fault",                      "search by LAP run fault", NULL);
+  ADD_OPT(Bool,pendingrunArgs, "-simple",                     "use the simple output format", false);
+
+  // -updaterun
+  psMetadata *updaterunArgs = psMetadataAlloc();
+  ADD_OPT(S64, updaterunArgs, "-lap_id",                      "search by lap run ID", 0);
+  ADD_OPT(Str, updaterunArgs, "-set_state",                   "set state", NULL);
+  ADD_OPT(S16, updaterunArgs, "-fault",                       "set fault code", INT16_MAX);
+  ADD_OPT(Str, updaterunArgs, "-set_label",                   "set label", NULL);
+  ADD_OPT(S64, updaterunArgs, "-set_quick_sass_id",           "set quick stack sass_id", 0);
+  ADD_OPT(S64, updaterunArgs, "-set_final_sass_id",           "set final stack sass_id", 0);
+  
+  
+  // -pendingexp
+  psMetadata *pendingexpArgs = psMetadataAlloc();
+  ADD_OPT(S64, pendingexpArgs, "-lap_id",                     "lap run ID", 0);
+  ADD_OPT(Str, pendingexpArgs, "-projection_cell",            "projection cell to consider", NULL);
+  ADD_OPT(U64, pendingexpArgs, "-limit",                      "limit result set to N items", 0);
+  ADD_OPT(Bool,pendingexpArgs, "-simple",                     "use the simple output format", false);
+
+  // -exposures
+  psMetadata *exposuresArgs = psMetadataAlloc();
+  ADD_OPT(S64, exposuresArgs, "-lap_id",                      "search by lap run ID", 0);
+  ADD_OPT(S64, exposuresArgs, "-exp_id",                      "search by exp_id", 0);
+  ADD_OPT(Bool,exposuresArgs, "-simple",                      "use the simple output format", false);
+  ADD_OPT(U64, exposuresArgs, "-limit",                       "limit result set to N items", 0);
+
+  // -stacks
+  psMetadata *stacksArgs = psMetadataAlloc();
+  ADD_OPT(S64, stacksArgs, "-lap_id",                         "search by lap run ID", 0);
+  ADD_OPT(Bool,stacksArgs, "-simple",                         "use the simple output format", false);
+  ADD_OPT(U64, stacksArgs, "-limit",                          "limit result set to N items", 0);
+  
+  // -updateexp
+  psMetadata *updateexpArgs = psMetadataAlloc();
+  ADD_OPT(S64, updateexpArgs, "-lap_id",                      "search by lap run ID", 0);
+  ADD_OPT(S64, updateexpArgs, "-exp_id",                      "search by exposure ID", 0);
+  ADD_OPT(S64, updateexpArgs, "-chip_id",                     "search by chip ID", 0);
+  ADD_OPT(S64, updateexpArgs, "-set_chip_id",                 "set the chip ID", 0);
+  ADD_OPT(S64, updateexpArgs, "-set_pair_id",                 "set the pair ID", 0);
+  ADD_OPT(Str, updateexpArgs, "-set_data_state",              "set the lapExp data_state", NULL);
+  ADD_OPT(Bool,updateexpArgs, "-private",                     "set this exposure as private", 0);
+  ADD_OPT(Bool,updateexpArgs, "-public",                      "set this exposure as public", 0);
+  ADD_OPT(Bool,updateexpArgs, "-pairwise",                    "set this exposure to be pairwise", 0);
+  ADD_OPT(Bool,updateexpArgs, "-nopairwise",                  "set this exposure to not be pairwise", 0);
+  ADD_OPT(Bool,updateexpArgs, "-active",                      "set this exposure to active", 0);
+  ADD_OPT(Bool,updateexpArgs, "-inactive",                    "set this exposure to active", 0);
+
+  // -inactiveexp
+  psMetadata *inactiveexpArgs = psMetadataAlloc();
+  ADD_OPT(S64, inactiveexpArgs, "-lap_id",                    "search by lap run ID", 0);
+  ADD_OPT(Bool,inactiveexpArgs, "-simple",                    "use the simple output format", false);
+  ADD_OPT(U64, inactiveexpArgs, "-limit",                     "limit result set to N items", 0);
+  
+  
+  psMetadata *argSets = psMetadataAlloc();
+  psMetadata *modes = psMetadataAlloc();
+
+  PXOPT_ADD_MODE("-definesequence",          "", LAPTOOL_MODE_DEFINESEQUENCE,   definesequenceArgs);
+  PXOPT_ADD_MODE("-listsequence",            "", LAPTOOL_MODE_LISTSEQUENCE,     listsequenceArgs);
+  PXOPT_ADD_MODE("-definerun",               "", LAPTOOL_MODE_DEFINERUN,        definerunArgs);
+  PXOPT_ADD_MODE("-pendingrun",              "", LAPTOOL_MODE_PENDINGRUN,       pendingrunArgs);
+  PXOPT_ADD_MODE("-updaterun",               "", LAPTOOL_MODE_UPDATERUN,        updaterunArgs);
+  PXOPT_ADD_MODE("-pendingexp",              "", LAPTOOL_MODE_PENDINGEXP,       pendingexpArgs);
+  PXOPT_ADD_MODE("-exposures",               "", LAPTOOL_MODE_EXPOSURES,        exposuresArgs);
+  PXOPT_ADD_MODE("-stacks",                  "", LAPTOOL_MODE_STACKS,           stacksArgs);
+  PXOPT_ADD_MODE("-updateexp",               "", LAPTOOL_MODE_UPDATEEXP,        updateexpArgs);
+  PXOPT_ADD_MODE("-inactiveexp",             "", LAPTOOL_MODE_INACTIVEEXP,      inactiveexpArgs);
+  
+  if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+    psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+    psFree(argSets);
+    psFree(modes);
+    psFree(config);
+    return NULL;
+  }
+
+  psFree(argSets);
+  psFree(modes);
+
+  // define Database handle, if used
+  config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+  if (!config->dbh) {
+    psError(PXTOOLS_ERR_SYS, false, "Can't configure database");
+    psFree(config);
+    return NULL;
+  }
+
+  return config;
+}
+
+
+  
Index: /branches/eam_branches/ipp-20110404/ippTools/src/pxadd.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/pxadd.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/pxadd.c	(revision 31439)
@@ -37,5 +37,5 @@
     if (!pxIsValidState(state)) {
         psError(PS_ERR_UNKNOWN, false,
-                "invalid camRun state: %s", state);
+                "invalid stageRun state: %s", state);
         return false;
     }
@@ -51,5 +51,5 @@
 
 
-bool pxaddRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state)
+bool pxaddRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *stage, const char *state)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -59,10 +59,16 @@
     if (!pxIsValidState(state)) {
         psError(PS_ERR_UNKNOWN, false,
-                "invalid chipRun state: %s", state);
+                "invalid stageRun state: %s", state);
         return false;
     }
-
-    psString query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET addRun.state = '%s'");
-
+    psString query = NULL;
+    if (strcmp(stage, "cam") == 0) {
+      query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET addRun.state = '%s'");
+    } 
+    if (strcmp(stage, "stack") == 0) {
+      ///xxx this needs to be fixed
+     
+      /// psString query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET addRun.state = '%s'");
+    } 
     if (where) {
         psString whereClause = psDBGenerateWhereSQL(where, NULL);
@@ -98,9 +104,9 @@
 }
 
-bool pxaddRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label)
+bool pxaddRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *stage, const char *label)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
     // note label == NULL should be explicitly allowed
-
+    //xxx fix for stack
     psString query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET addRun.label = '%s'");
 
@@ -123,5 +129,6 @@
 
 bool pxaddQueueByCamID(pxConfig *config,
-                       psS64 cam_id,
+		       char *stage,
+                       psS64 stage_id,
                        char *workdir,
                        char *reduction,
@@ -140,6 +147,16 @@
     static psString query = NULL;
     if (!query) {
+      if (strcmp( stage , "cam") == 0) {
         query = pxDataGet("addtool_queue_cam_id.sql");
         psMemSetPersistent(query, true);
+      }
+      if (strcmp(stage,"stack") == 0) {
+	query = pxDataGet("addtool_queue_stack_id.sql");
+        psMemSetPersistent(query, true);
+      }
+      if (strcmp(stage,"staticsky") == 0) {
+	query = pxDataGet("addtool_queue_sky_id.sql");
+        psMemSetPersistent(query, true);
+      }
         if (!query) {
             psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -148,11 +165,12 @@
     }
 
+    psTrace("addtool.c", PS_LOG_INFO, "pxadd query \n%s\n",query);
     // queue the exp
     // Note: cam_id is being cast here work around psS64 have a different type different
     // on 32/64
     if (!p_psDBRunQueryF(config->dbh, query,
-                         "new", // state
+			 "new", // state
                          workdir  ? workdir   : "NULL",
-                         "dirty", //workdir_state
+			  "dirty", //workdir_state
                          reduction? reduction : "NULL",
                          label    ? label     : "NULL",
@@ -164,5 +182,5 @@
 			 minidvodb_group,
 			 minidvodb_name,
-                         (long long) cam_id
+                         (long long) stage_id
     )) {
       psError(PS_ERR_UNKNOWN, false, "database error %s", query);
Index: /branches/eam_branches/ipp-20110404/ippTools/src/pxadd.h
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/pxadd.h	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/pxadd.h	(revision 31439)
@@ -26,10 +26,11 @@
 
 bool pxaddRunSetState(pxConfig *config, psS64 add_id, const char *state);
-bool pxaddRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state);
+bool pxaddRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *stage, const char *state);
 bool pxaddRunSetLabel(pxConfig *config, psS64 add_id, const char *label);
-bool pxaddRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label);
+bool pxaddRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *stage, const char *label);
 
 bool pxaddQueueByCamID(pxConfig *config,
-		       psS64 cam_id,
+		       char *stage,
+		       psS64 stage_id,
 		       char *workdir,
 		       char *reduction,
Index: /branches/eam_branches/ipp-20110404/ippTools/src/regtool.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/regtool.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/regtool.c	(revision 31439)
@@ -326,4 +326,5 @@
   query = rep;
 
+  // This matches against summitExp.dateobs
   psStringSubstitute(&query,dateobs_begin,"@DATEOBS_BEGIN@");
   psStringSubstitute(&query,dateobs_end,"@DATEOBS_END@");
Index: /branches/eam_branches/ipp-20110404/ippTools/src/stacktool.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/stacktool.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/stacktool.c	(revision 31439)
@@ -243,5 +243,5 @@
     PXOPT_COPY_STR(config->args,  where, "-select_exp_type",           "rawExp.exp_type", "==");
     PXOPT_COPY_F32(config->args,  where, "-select_good_frac_min",      "warpSkyfile.good_frac", ">=");
-    PXOPT_COPY_STR(config->args,  where, "-select_skycell_id",         "warpSkyfile.skycell_id", "==");
+    PXOPT_COPY_STR(config->args,  where, "-select_skycell_id",         "warpSkyfile.skycell_id", "LIKE");
     PXOPT_COPY_STR(config->args,  where, "-select_data_group",         "warpRun.data_group", "==");
     pxAddLabelSearchArgs (config, where, "-select_label",              "warpRun.label", "LIKE"); // define using warp label
Index: /branches/eam_branches/ipp-20110404/ippTools/src/staticskytool.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/staticskytool.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/staticskytool.c	(revision 31439)
@@ -115,4 +115,5 @@
     PXOPT_COPY_F32(config->args, whereMD, "-select_good_frac_min", "stackSumSkyfile.good_frac", ">=");
     pxAddLabelSearchArgs(config, whereMD, "-select_label",         "stackRun.label",            "LIKE");
+    pxAddLabelSearchArgs(config, whereMD, "-select_data_group",    "stackRun.data_group",       "LIKE");
     pxAddLabelSearchArgs(config, whereMD, "-select_filter",        "stackRun.filter",           "LIKE");
 
@@ -123,9 +124,4 @@
     psAssert (filters->data.list->n, "-select_filter should at least have a place-holder");
     int num_filter = filters->data.list->n;
-    if (num_filter < 2) {
-        psError(PXTOOLS_ERR_CONFIG, false, "invalid request: only 1 filter selected");
-        psFree(whereMD);
-        return false;
-    }
 
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
@@ -284,5 +280,5 @@
 	}
 
-	// create a chipRun
+	// create a staticskyRun
 	if (!staticskyRunInsert(config->dbh,
 				0x0,	     // sky_id
Index: /branches/eam_branches/ipp-20110404/ippTools/src/staticskytoolConfig.c
===================================================================
--- /branches/eam_branches/ipp-20110404/ippTools/src/staticskytoolConfig.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippTools/src/staticskytoolConfig.c	(revision 31439)
@@ -52,5 +52,6 @@
     psMetadataAddF32(definebyqueryArgs,  PS_LIST_TAIL, "-select_good_frac_min", 0, "define min good_frac", 0.0);
     psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_label", PS_META_DUPLICATE_OK, "search by stackRun label (LIKE comparison, multiple OK)", NULL);
-    psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_filter", PS_META_DUPLICATE_OK, "search by filter (LIKE comparison, multiple required)", NULL);
+    psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_data_group", PS_META_DUPLICATE_OK, "search by stackRun data_group (LIKE comparison, multiple OK)", NULL);
+    psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_filter", PS_META_DUPLICATE_OK, "search by filter (LIKE comparison, multiplei OK)", NULL);
     psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-set_workdir", 0, "define workdir (required)", NULL);
     psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-set_label", 0, "define label", NULL);
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20080925.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20080925.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20080925.config	(revision 31439)
@@ -670,3 +670,65 @@
         XY76    STR     1111111111111111111111111111111111111111111111111111111111111111
 END
-
+PATTERN.CELL.SUBSET      METADATA        # List of chips and whether to do cell pattern correction  
+        XY01    BOOL 	FALSE
+        XY02    BOOL 	FALSE
+        XY03    BOOL 	FALSE
+        XY04    BOOL 	FALSE
+        XY05    BOOL 	FALSE
+        XY06    BOOL 	FALSE
+        XY10    BOOL 	FALSE
+        XY11    BOOL 	FALSE
+ 	XY12    BOOL 	FALSE
+        XY13    BOOL 	FALSE
+        XY14    BOOL 	FALSE
+        XY15    BOOL 	FALSE
+        XY16    BOOL 	FALSE
+        XY17    BOOL 	FALSE
+        XY20    BOOL 	FALSE
+        XY21    BOOL 	FALSE
+        XY22    BOOL 	FALSE
+        XY23    BOOL 	FALSE
+        XY24    BOOL 	FALSE
+        XY25    BOOL 	FALSE
+        XY26    BOOL 	FALSE
+        XY27    BOOL 	FALSE
+        XY30    BOOL 	FALSE
+        XY31    BOOL 	FALSE
+        XY32    BOOL 	FALSE
+        XY33    BOOL 	FALSE
+        XY34    BOOL 	FALSE
+        XY35    BOOL 	FALSE
+        XY36    BOOL 	FALSE
+        XY37    BOOL 	FALSE
+        XY40    BOOL 	FALSE
+        XY41    BOOL 	FALSE
+        XY42    BOOL 	FALSE
+        XY43    BOOL 	FALSE
+        XY44    BOOL 	FALSE
+        XY45    BOOL 	FALSE
+        XY46    BOOL 	FALSE
+        XY47    BOOL 	FALSE
+        XY50    BOOL 	FALSE
+        XY51    BOOL 	FALSE
+        XY52    BOOL 	FALSE
+        XY53    BOOL 	FALSE
+        XY54    BOOL 	FALSE
+        XY55    BOOL 	FALSE
+        XY56    BOOL 	FALSE
+        XY57    BOOL 	FALSE
+        XY60    BOOL 	FALSE
+        XY61    BOOL 	FALSE
+        XY62    BOOL 	FALSE
+        XY63    BOOL 	FALSE
+        XY64    BOOL 	FALSE
+        XY65    BOOL 	FALSE
+        XY66    BOOL 	FALSE
+        XY67    BOOL 	FALSE
+        XY71    BOOL 	FALSE
+        XY72    BOOL 	FALSE
+        XY73    BOOL 	FALSE
+        XY74    BOOL 	FALSE
+        XY75    BOOL 	FALSE
+        XY76    BOOL 	FALSE
+END
+
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20080929.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20080929.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20080929.config	(revision 31439)
@@ -666,3 +666,65 @@
         XY76    STR     1111111111111111111111111111111111111111111111111111111111111111
 END
-
+PATTERN.CELL.SUBSET      METADATA        # List of chips and whether to do cell pattern correction  
+        XY01    BOOL 	FALSE
+        XY02    BOOL 	FALSE
+        XY03    BOOL 	FALSE
+        XY04    BOOL 	FALSE
+        XY05    BOOL 	FALSE
+        XY06    BOOL 	FALSE
+        XY10    BOOL 	FALSE
+        XY11    BOOL 	FALSE
+ 	XY12    BOOL 	FALSE
+        XY13    BOOL 	FALSE
+        XY14    BOOL 	FALSE
+        XY15    BOOL 	FALSE
+        XY16    BOOL 	FALSE
+        XY17    BOOL 	FALSE
+        XY20    BOOL 	FALSE
+        XY21    BOOL 	FALSE
+        XY22    BOOL 	FALSE
+        XY23    BOOL 	FALSE
+        XY24    BOOL 	FALSE
+        XY25    BOOL 	FALSE
+        XY26    BOOL 	FALSE
+        XY27    BOOL 	FALSE
+        XY30    BOOL 	FALSE
+        XY31    BOOL 	FALSE
+        XY32    BOOL 	FALSE
+        XY33    BOOL 	FALSE
+        XY34    BOOL 	FALSE
+        XY35    BOOL 	FALSE
+        XY36    BOOL 	FALSE
+        XY37    BOOL 	FALSE
+        XY40    BOOL 	FALSE
+        XY41    BOOL 	FALSE
+        XY42    BOOL 	FALSE
+        XY43    BOOL 	FALSE
+        XY44    BOOL 	FALSE
+        XY45    BOOL 	FALSE
+        XY46    BOOL 	FALSE
+        XY47    BOOL 	FALSE
+        XY50    BOOL 	FALSE
+        XY51    BOOL 	FALSE
+        XY52    BOOL 	FALSE
+        XY53    BOOL 	FALSE
+        XY54    BOOL 	FALSE
+        XY55    BOOL 	FALSE
+        XY56    BOOL 	FALSE
+        XY57    BOOL 	FALSE
+        XY60    BOOL 	FALSE
+        XY61    BOOL 	FALSE
+        XY62    BOOL 	FALSE
+        XY63    BOOL 	FALSE
+        XY64    BOOL 	FALSE
+        XY65    BOOL 	FALSE
+        XY66    BOOL 	FALSE
+        XY67    BOOL 	FALSE
+        XY71    BOOL 	FALSE
+        XY72    BOOL 	FALSE
+        XY73    BOOL 	FALSE
+        XY74    BOOL 	FALSE
+        XY75    BOOL 	FALSE
+        XY76    BOOL 	FALSE
+END
+
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20081011.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20081011.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20081011.config	(revision 31439)
@@ -656,2 +656,64 @@
         XY76    STR     1111111111111111111111111111111111111111111111111111111111111111
 END
+PATTERN.CELL.SUBSET      METADATA        # List of chips and whether to do cell pattern correction  
+        XY01    BOOL 	FALSE
+        XY02    BOOL 	FALSE
+        XY03    BOOL 	FALSE
+        XY04    BOOL 	FALSE
+        XY05    BOOL 	FALSE
+        XY06    BOOL 	FALSE
+        XY10    BOOL 	FALSE
+        XY11    BOOL 	FALSE
+ 	XY12    BOOL 	FALSE
+        XY13    BOOL 	FALSE
+        XY14    BOOL 	FALSE
+        XY15    BOOL 	FALSE
+        XY16    BOOL 	FALSE
+        XY17    BOOL 	FALSE
+        XY20    BOOL 	FALSE
+        XY21    BOOL 	FALSE
+        XY22    BOOL 	FALSE
+        XY23    BOOL 	FALSE
+        XY24    BOOL 	FALSE
+        XY25    BOOL 	FALSE
+        XY26    BOOL 	FALSE
+        XY27    BOOL 	FALSE
+        XY30    BOOL 	FALSE
+        XY31    BOOL 	FALSE
+        XY32    BOOL 	FALSE
+        XY33    BOOL 	FALSE
+        XY34    BOOL 	FALSE
+        XY35    BOOL 	FALSE
+        XY36    BOOL 	FALSE
+        XY37    BOOL 	FALSE
+        XY40    BOOL 	FALSE
+        XY41    BOOL 	FALSE
+        XY42    BOOL 	FALSE
+        XY43    BOOL 	FALSE
+        XY44    BOOL 	FALSE
+        XY45    BOOL 	FALSE
+        XY46    BOOL 	FALSE
+        XY47    BOOL 	FALSE
+        XY50    BOOL 	FALSE
+        XY51    BOOL 	FALSE
+        XY52    BOOL 	FALSE
+        XY53    BOOL 	FALSE
+        XY54    BOOL 	FALSE
+        XY55    BOOL 	FALSE
+        XY56    BOOL 	FALSE
+        XY57    BOOL 	FALSE
+        XY60    BOOL 	FALSE
+        XY61    BOOL 	FALSE
+        XY62    BOOL 	FALSE
+        XY63    BOOL 	FALSE
+        XY64    BOOL 	FALSE
+        XY65    BOOL 	FALSE
+        XY66    BOOL 	FALSE
+        XY67    BOOL 	FALSE
+        XY71    BOOL 	FALSE
+        XY72    BOOL 	FALSE
+        XY73    BOOL 	FALSE
+        XY74    BOOL 	FALSE
+        XY75    BOOL 	FALSE
+        XY76    BOOL 	FALSE
+END
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20090120.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20090120.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20090120.config	(revision 31439)
@@ -588,2 +588,64 @@
         XY76    STR     1111111111111111111111111111111111111111111111111111111111111111
 END
+PATTERN.CELL.SUBSET      METADATA        # List of chips and whether to do cell pattern correction  
+        XY01    BOOL 	FALSE
+        XY02    BOOL 	FALSE
+        XY03    BOOL 	FALSE
+        XY04    BOOL 	FALSE
+        XY05    BOOL 	FALSE
+        XY06    BOOL 	FALSE
+        XY10    BOOL 	FALSE
+        XY11    BOOL 	FALSE
+ 	XY12    BOOL 	FALSE
+        XY13    BOOL 	FALSE
+        XY14    BOOL 	FALSE
+        XY15    BOOL 	FALSE
+        XY16    BOOL 	FALSE
+        XY17    BOOL 	FALSE
+        XY20    BOOL 	FALSE
+        XY21    BOOL 	FALSE
+        XY22    BOOL 	FALSE
+        XY23    BOOL 	FALSE
+        XY24    BOOL 	FALSE
+        XY25    BOOL 	FALSE
+        XY26    BOOL 	FALSE
+        XY27    BOOL 	FALSE
+        XY30    BOOL 	FALSE
+        XY31    BOOL 	FALSE
+        XY32    BOOL 	FALSE
+        XY33    BOOL 	FALSE
+        XY34    BOOL 	FALSE
+        XY35    BOOL 	FALSE
+        XY36    BOOL 	FALSE
+        XY37    BOOL 	FALSE
+        XY40    BOOL 	FALSE
+        XY41    BOOL 	FALSE
+        XY42    BOOL 	FALSE
+        XY43    BOOL 	FALSE
+        XY44    BOOL 	FALSE
+        XY45    BOOL 	FALSE
+        XY46    BOOL 	FALSE
+        XY47    BOOL 	FALSE
+        XY50    BOOL 	FALSE
+        XY51    BOOL 	FALSE
+        XY52    BOOL 	FALSE
+        XY53    BOOL 	FALSE
+        XY54    BOOL 	FALSE
+        XY55    BOOL 	FALSE
+        XY56    BOOL 	FALSE
+        XY57    BOOL 	FALSE
+        XY60    BOOL 	FALSE
+        XY61    BOOL 	FALSE
+        XY62    BOOL 	FALSE
+        XY63    BOOL 	FALSE
+        XY64    BOOL 	FALSE
+        XY65    BOOL 	FALSE
+        XY66    BOOL 	FALSE
+        XY67    BOOL 	FALSE
+        XY71    BOOL 	FALSE
+        XY72    BOOL 	FALSE
+        XY73    BOOL 	FALSE
+        XY74    BOOL 	FALSE
+        XY75    BOOL 	FALSE
+        XY76    BOOL 	FALSE
+END
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20090220.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20090220.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20090220.config	(revision 31439)
@@ -590,3 +590,65 @@
         XY76    STR     1111111111111111111111111111111111111111111111111111111111111111
 END
-
+PATTERN.CELL.SUBSET      METADATA        # List of chips and whether to do cell pattern correction  
+        XY01    BOOL 	FALSE
+        XY02    BOOL 	FALSE
+        XY03    BOOL 	FALSE
+        XY04    BOOL 	FALSE
+        XY05    BOOL 	FALSE
+        XY06    BOOL 	FALSE
+        XY10    BOOL 	FALSE
+        XY11    BOOL 	FALSE
+ 	XY12    BOOL 	FALSE
+        XY13    BOOL 	FALSE
+        XY14    BOOL 	FALSE
+        XY15    BOOL 	FALSE
+        XY16    BOOL 	FALSE
+        XY17    BOOL 	FALSE
+        XY20    BOOL 	FALSE
+        XY21    BOOL 	FALSE
+        XY22    BOOL 	FALSE
+        XY23    BOOL 	FALSE
+        XY24    BOOL 	FALSE
+        XY25    BOOL 	FALSE
+        XY26    BOOL 	FALSE
+        XY27    BOOL 	FALSE
+        XY30    BOOL 	FALSE
+        XY31    BOOL 	FALSE
+        XY32    BOOL 	FALSE
+        XY33    BOOL 	FALSE
+        XY34    BOOL 	FALSE
+        XY35    BOOL 	FALSE
+        XY36    BOOL 	FALSE
+        XY37    BOOL 	FALSE
+        XY40    BOOL 	FALSE
+        XY41    BOOL 	FALSE
+        XY42    BOOL 	FALSE
+        XY43    BOOL 	FALSE
+        XY44    BOOL 	FALSE
+        XY45    BOOL 	FALSE
+        XY46    BOOL 	FALSE
+        XY47    BOOL 	FALSE
+        XY50    BOOL 	FALSE
+        XY51    BOOL 	FALSE
+        XY52    BOOL 	FALSE
+        XY53    BOOL 	FALSE
+        XY54    BOOL 	FALSE
+        XY55    BOOL 	FALSE
+        XY56    BOOL 	FALSE
+        XY57    BOOL 	FALSE
+        XY60    BOOL 	FALSE
+        XY61    BOOL 	FALSE
+        XY62    BOOL 	FALSE
+        XY63    BOOL 	FALSE
+        XY64    BOOL 	FALSE
+        XY65    BOOL 	FALSE
+        XY66    BOOL 	FALSE
+        XY67    BOOL 	FALSE
+        XY71    BOOL 	FALSE
+        XY72    BOOL 	FALSE
+        XY73    BOOL 	FALSE
+        XY74    BOOL 	FALSE
+        XY75    BOOL 	FALSE
+        XY76    BOOL 	FALSE
+END
+
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20091209.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20091209.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20091209.config	(revision 31439)
@@ -527,5 +527,5 @@
 PATTERN.ROW.SUBSET	METADATA	# List of chips and whether to do row pattern correction
 	XY01	BOOL	FALSE
-	XY02	BOOL	FALSE
+        XY02	STR     0000000000000000000000000000000000000000000000000000000000000001 # xy77
 	XY03	BOOL	FALSE
 	XY04	BOOL	FALSE
@@ -533,8 +533,8 @@
 	XY06	BOOL	FALSE
 	XY10	BOOL	FALSE
-	XY11	BOOL	FALSE
+	XY11	STR	0011100100000000000000000000000000000000000000000000000000000000
 	XY12	BOOL	FALSE
 	XY13	BOOL	FALSE
-	XY14	BOOL	FALSE
+        XY14	STR     0000000000000000000100000000000000000000000000000000000000000000 # xy23
 	XY15	STR     1111111100000000000000000000000000000000000000000000000000000000 # cols: 0
 	XY16	BOOL	FALSE
@@ -549,5 +549,5 @@
 	XY27	STR     1111111111111111111111111111111100000000000000000000000011111111 # cols: 0,1,2,3,7
 	XY30	BOOL	FALSE
-	XY31	BOOL	FALSE
+	XY31	STR     0000000000000000000000000000000000000000000000000000000011111111 # cols: 7
 	XY32	STR     0000000000000000000000001111111100000000000000000000000011111111 # cols: 3,7
 	XY33	BOOL	FALSE
@@ -578,5 +578,5 @@
 	XY64	BOOL	FALSE
 	XY65	BOOL	FALSE
-	XY66	BOOL	FALSE
+	XY66	STR	0000000000000000000000000000000000000000000000000000000000000100 # cell xy75
 	XY67	BOOL	FALSE
 	XY71	BOOL	FALSE
@@ -595,10 +595,10 @@
 	XY04	BOOL	FALSE
 	XY05	BOOL	FALSE
-	XY06    STR     11010000000100000001101001000000000000000000000000000000000000000
+	XY06    STR     1101000000010000000110100100000000000000000000000000000000000000
 	XY10	BOOL	FALSE
 	XY11	BOOL	FALSE
 	XY12	BOOL	FALSE
 	XY13	BOOL	FALSE
-	XY14	STR     0000000000000000000000000000000000000000000000010000000000101101
+	XY14	STR     0000000000000000111111110000000000000000000000010000000000101101
 	XY15	STR     0011111100011000000001000000010000001001000111110001010000011111
 	XY16	STR     0000000100000000000000000000000000000001000000000000000000000000
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20100122.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20100122.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20100122.config	(revision 31439)
@@ -525,8 +525,10 @@
  
 
+# Pattern correction information:
+
 # PATTERN.ROW		BOOL 	TRUE	# Do any row pattern correction at all?
 PATTERN.ROW.SUBSET	METADATA	# List of chips and whether to do row pattern correction
 	XY01	BOOL	FALSE
-	XY02	BOOL	FALSE
+	XY02	STR     0000000000000000000000000000000000000000000000000000000000000001 # xy77
 	XY03	BOOL	FALSE
 	XY04	BOOL	FALSE
@@ -534,8 +536,8 @@
 	XY06	BOOL	FALSE
 	XY10	BOOL	FALSE
-	XY11	BOOL	FALSE
+	XY11	STR	0011100100000000000000000000000000000000000000000000000000000000
 	XY12	BOOL	FALSE
 	XY13	BOOL	FALSE
-	XY14	BOOL	FALSE
+	XY14	STR     0000000000000000000100000000000000000000000000000000000000000000 # xy23
 	XY15	STR     1111111100000000000000000000000000000000000000000000000000000000 # cols: 0
 	XY16	BOOL	FALSE
@@ -550,5 +552,5 @@
 	XY27	STR     1111111111111111111111111111111100000000000000000000000011111111 # cols: 0,1,2,3,7
 	XY30	BOOL	FALSE
-	XY31	BOOL	FALSE
+	XY31	STR     0000000000000000000000000000000000000000000000000000000011111111 # cols: 7
 	XY32	STR     0000000000000000000000001111111100000000000000000000000011111111 # cols: 3,7
 	XY33	BOOL	FALSE
@@ -579,5 +581,5 @@
 	XY64	BOOL	FALSE
 	XY65	BOOL	FALSE
-	XY66	BOOL	FALSE
+	XY66	STR	0000000000000000000000000000000000000000000000000000000000000100 # cell xy75
 	XY67	BOOL	FALSE
 	XY71	BOOL	FALSE
@@ -596,10 +598,10 @@
 	XY04	BOOL	FALSE
 	XY05	BOOL	FALSE
-	XY06    STR     11010000000100000001101001000000000000000000000000000000000000000
+	XY06    STR     1101000000010000000110100100000000000000000000000000000000000000
 	XY10	BOOL	FALSE
 	XY11	BOOL	FALSE
 	XY12	BOOL	FALSE
 	XY13	BOOL	FALSE
-	XY14	STR     0000000000000000000000000000000000000000000000010000000000101101
+	XY14	STR     0000000000000000111111110000000000000000000000010000000000101101
 	XY15	STR     0011111100011000000001000000010000001001000111110001010000011111
 	XY16	STR     0000000100000000000000000000000000000001000000000000000000000000
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20100228.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20100228.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20100228.config	(revision 31439)
@@ -529,5 +529,5 @@
 PATTERN.ROW.SUBSET	METADATA	# List of chips and whether to do row pattern correction
 	XY01	BOOL	FALSE
-	XY02	BOOL	FALSE
+	XY02	STR     0000000000000000000000000000000000000000000000000000000000000001 # xy77
 	XY03	BOOL	FALSE
 	XY04	BOOL	FALSE
@@ -535,8 +535,8 @@
 	XY06	BOOL	FALSE
 	XY10	BOOL	FALSE
-	XY11    STR	0011100100000000000000000000000000000000000000000000000000000000
+	XY11	STR	0011100100000000000000000000000000000000000000000000000000000000
 	XY12	BOOL	FALSE
 	XY13	BOOL	FALSE
-	XY14	BOOL	FALSE
+	XY14	STR     0000000000000000000100000000000000000000000000000000000000000000 # xy23
 	XY15	STR     1111111100000000000000000000000000000000000000000000000000000000 # cols: 0
 	XY16	BOOL	FALSE
@@ -551,5 +551,5 @@
 	XY27	STR     1111111111111111111111111111111100000000000000000000000011111111 # cols: 0,1,2,3,7
 	XY30	BOOL	FALSE
-	XY31	BOOL	FALSE
+	XY31	STR     0000000000000000000000000000000000000000000000000000000011111111 # cols: 7
 	XY32	STR     0000000000000000000000001111111100000000000000000000000011111111 # cols: 3,7
 	XY33	BOOL	FALSE
@@ -580,5 +580,5 @@
 	XY64	BOOL	FALSE
 	XY65	BOOL	FALSE
-	XY66	BOOL	FALSE
+	XY66	STR	0000000000000000000000000000000000000000000000000000000000000100 # cell xy75
 	XY67	BOOL	FALSE
 	XY71	BOOL	FALSE
@@ -602,5 +602,5 @@
 	XY12	BOOL	FALSE
 	XY13	BOOL	FALSE
-	XY14	STR     0000000000000000000000000000000000000000000000010000000000101101
+	XY14	STR     0000000000000000111111110000000000000000000000010000000000101101
 	XY15	STR     0011111100011000000001000000010000001001000111110001010000011111
 	XY16	STR     0000000100000000000000000000000000000001000000000000000000000000
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20100723.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20100723.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/format_20100723.config	(revision 31439)
@@ -529,5 +529,5 @@
 PATTERN.ROW.SUBSET	METADATA	# List of chips and whether to do row pattern correction
 	XY01	BOOL	FALSE
-	XY02	BOOL	FALSE
+	XY02	STR     0000000000000000000000000000000000000000000000000000000000000001 # xy77
 	XY03	BOOL	FALSE
 	XY04	BOOL	FALSE
@@ -538,5 +538,5 @@
 	XY12	BOOL	FALSE
 	XY13	BOOL	FALSE
-	XY14	BOOL	FALSE
+	XY14	STR     0000000000000000000100000000000000000000000000000000000000000000 # xy23
 	XY15	STR     1111111100000000000000000000000000000000000000000000000000000000 # cols: 0
 	XY16	BOOL	FALSE
@@ -551,5 +551,5 @@
 	XY27	STR     1111111111111111111111111111111100000000000000000000000011111111 # cols: 0,1,2,3,7
 	XY30	BOOL	FALSE
-	XY31	BOOL	FALSE
+	XY31	STR     0000000000000000000000000000000000000000000000000000000011111111 # cols: 7
 	XY32	STR     0000000000000000000000001111111100000000000000000000000011111111 # cols: 3,7
 	XY33	BOOL	FALSE
@@ -580,5 +580,5 @@
 	XY64	BOOL	FALSE
 	XY65	BOOL	FALSE
-	XY66	BOOL	FALSE
+	XY66	STR	0000000000000000000000000000000000000000000000000000000000000100 # cell xy75
 	XY67	BOOL	FALSE
 	XY71	BOOL	FALSE
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/ppImage.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/ppImage.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/ppImage.config	(revision 31439)
@@ -222,4 +222,5 @@
        FILTER   STR FPA.FILTERID
      END
+  END
 END
  
Index: /branches/eam_branches/ipp-20110404/ippconfig/gpc1/psastro.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/gpc1/psastro.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/gpc1/psastro.config	(revision 31439)
@@ -16,6 +16,6 @@
 PSASTRO.GRID.SCALE     F32      50
 PSASTRO.GRID.NSTAR.MAX S32     800 # deprecated 
-PSASTRO.GRID.NREF.MAX  S32     800 # max stars accepted for fitting from ref catalog
-PSASTRO.GRID.NRAW.MAX  S32    1200 # max stars accepted for fitting from raw image
+PSASTRO.GRID.NREF.MAX  S32     800 # max stars accepted for grid search from ref catalog
+PSASTRO.GRID.NRAW.MAX  S32    1200 # max stars accepted for grid search from raw image
 
 PSASTRO.MAX.NRAW      S32      1000   # max stars accepted for fitting (0 for all)
@@ -28,4 +28,6 @@
 PSASTRO.MIN.INST.MAG.RAW       F32     -15.0   # min instrumental magnitude for stars accepted for fitting
 PSASTRO.MAX.INST.MAG.RAW       F32      -8.0   # max instrumental magnitude for stars accepted for fitting
+PSASTRO.GRID.MIN.INST.MAG.RAW  F32     -15.0   # min instrumental magnitude for stars accepted for grid search
+PSASTRO.GRID.MAX.INST.MAG.RAW  F32      -8.0   # max instrumental magnitude for stars accepted for grid search
 
 PSASTRO.GRID.MIN.ANGLE F32 -1.0 # start angle (degrees)
@@ -314,7 +316,16 @@
   # allow more stars per chip and boost the density to which we query
   # from the reference database.
-  PSASTRO.MAX.NRAW      S32      2000   # 
-  PSASTRO.MAX.NREF      S32      8000   # max stars accepted for fitting (0 for all)
-  DVO.GETSTAR.MAX.RHO   F32      60000.0
+  PSASTRO.MAX.NRAW               S32      2000   # 
+  PSASTRO.MAX.NREF               S32      8000   # max stars accepted for fitting (0 for all)
+  # use wider range of magnitudes for grid search
+  PSASTRO.GRID.MIN.INST.MAG.RAW  F32     -15.0   # min instrumental magnitude for stars accepted for fitting
+  PSASTRO.GRID.MAX.INST.MAG.RAW  F32     -11.0   # max instrumental magnitude for stars accepted for fitting
+
+  # reduce the magnitude range to avoid the bright stars have bad astrometry problem
+  PSASTRO.MIN.INST.MAG.RAW       F32     -12.0   # min instrumental magnitude for stars accepted for fitting
+  PSASTRO.MAX.INST.MAG.RAW       F32     -11.0   # min instrumental magnitude for stars accepted for fitting
+
+  DVO.GETSTAR.MIN.MAG.INST   F32     -15.0
+  DVO.GETSTAR.MAX.RHO        F32      60000.0
   
   # the crowding is high, so unless we restrict somewhat tightly early
@@ -324,5 +335,5 @@
 
   # single-chip radius match in pixels
-  PSASTRO.MATCH.RADIUS.N0 F32    10
+  PSASTRO.MATCH.RADIUS.N0 F32   10
   PSASTRO.MATCH.RADIUS.N1 F32    5
   PSASTRO.MATCH.RADIUS.N2 F32    5
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/dqStatsTool.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/dqStatsTool.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/dqStatsTool.config	(revision 31439)
@@ -15,167 +15,166 @@
 # echo "select zpt_obs,fwhm_major,deteff from camProcessedExp JOIN camRun USING (cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) WHERE camRun.label LIKE '%.nightlyscience' AND quality = 0 AND filter = 'FILTER';" | sed 's/FILTER/g.00000/' | mysql -h ippdb01 -u ipp -pipp gpc1 | awk '{print($3)}' | grep -v deteff | grep -v NULL | mk_cdf.pl | awk '{print($2,$1)}' | spline - `echo 0.0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 0.99 1.0`
 # CZW: 2011-03-10 We've been off the sky too much to get much new science data. I've added the ThreePi.136 reprocessing to this to help gri
-    RULE METADATA
-    	COLNAME STR DETEFF
-	RULETYPE STR CDF
-	FILTER  STR g.00000
-        CDF00   F32 20.199000
-        CDF05   F32 21.471400
-        CDF10   F32 21.725000
-        CDF15   F32 21.857800
-        CDF20   F32 21.918700
-        CDF25   F32 21.976500
-        CDF30   F32 22.020800
-        CDF35   F32 22.062900
-        CDF40   F32 22.104200
-        CDF45   F32 22.136400
-        CDF50   F32 22.173500
-        CDF55   F32 22.210900
-        CDF60   F32 22.243500
-        CDF65   F32 22.280600
-        CDF70   F32 22.317500
-        CDF75   F32 22.360300
-        CDF80   F32 22.405100
-        CDF85   F32 22.453400
-        CDF90   F32 22.508500
-        CDF95   F32 22.575100
-        CDF99   F32 22.715100
+# CZW: 2011-05-04 Updated values. 
+    RULE METADATA
+        COLNAME STR DETEFF
+        RULETYPE STR CDF
+        FILTER  STR g.00000
+        CDF00   F32 19.245000
+        CDF05   F32 21.519900
+        CDF10   F32 21.705100
+        CDF15   F32 21.831400
+        CDF20   F32 21.901700
+        CDF25   F32 21.961500
+        CDF30   F32 22.009200
+        CDF35   F32 22.049700
+        CDF40   F32 22.085100
+        CDF45   F32 22.126400
+        CDF50   F32 22.161100
+        CDF55   F32 22.196100
+        CDF60   F32 22.230600
+        CDF65   F32 22.261400
+        CDF70   F32 22.294200
+        CDF75   F32 22.332200
+        CDF80   F32 22.372500
+        CDF85   F32 22.421000
+        CDF90   F32 22.471900
+        CDF95   F32 22.540200
+        CDF99   F32 22.657600
         CDF100  F32 22.992000
     END
     RULE METADATA
-    	COLNAME STR DETEFF
-	RULETYPE STR CDF
-	FILTER  STR r.00000
+        COLNAME STR DETEFF
+        RULETYPE STR CDF
+        FILTER  STR r.00000
         CDF00   F32 16.424200
-        CDF05   F32 20.942300
-        CDF10   F32 21.219600
-        CDF15   F32 21.432500
-        CDF20   F32 21.605300
-        CDF25   F32 21.731400
-        CDF30   F32 21.803200
-        CDF35   F32 21.890000
-        CDF40   F32 21.954700
-        CDF45   F32 22.006200
-        CDF50   F32 22.052200
-        CDF55   F32 22.098400
-        CDF60   F32 22.132500
-        CDF65   F32 22.163900
-        CDF70   F32 22.198400
-        CDF75   F32 22.229200
-        CDF80   F32 22.267200
-        CDF85   F32 22.307500
-        CDF90   F32 22.356100
-        CDF95   F32 22.419900
-        CDF99   F32 22.555900
+        CDF05   F32 21.111400
+        CDF10   F32 21.317500
+        CDF15   F32 21.472400
+        CDF20   F32 21.615500
+        CDF25   F32 21.711900
+        CDF30   F32 21.789700
+        CDF35   F32 21.846100
+        CDF40   F32 21.898400
+        CDF45   F32 21.945800
+        CDF50   F32 21.989500
+        CDF55   F32 22.034000
+        CDF60   F32 22.075800
+        CDF65   F32 22.116800
+        CDF70   F32 22.152700
+        CDF75   F32 22.189200
+        CDF80   F32 22.230300
+        CDF85   F32 22.271900
+        CDF90   F32 22.329200
+        CDF95   F32 22.394500
+        CDF99   F32 22.532000
         CDF100  F32 22.870400
     END
     RULE METADATA
-    	COLNAME STR DETEFF
-	RULETYPE STR CDF
-	FILTER  STR i.00000
+        COLNAME STR DETEFF
+        RULETYPE STR CDF
+        FILTER  STR i.00000
         CDF00   F32 15.811400
-        CDF05   F32 20.082600
-        CDF10   F32 20.829900
-        CDF15   F32 21.044500
-        CDF20   F32 21.163700
-        CDF25   F32 21.256500
-        CDF30   F32 21.343700
-        CDF35   F32 21.412300
-        CDF40   F32 21.474900
-        CDF45   F32 21.533000
-        CDF50   F32 21.593000
-        CDF55   F32 21.658700
-        CDF60   F32 21.734000
-        CDF65   F32 21.790500
-        CDF70   F32 21.861200
-        CDF75   F32 21.927400
-        CDF80   F32 22.004800
-        CDF85   F32 22.103500
-        CDF90   F32 22.238100
-        CDF95   F32 22.378100
-        CDF99   F32 22.489700
+        CDF05   F32 20.490100
+        CDF10   F32 21.001400
+        CDF15   F32 21.176500
+        CDF20   F32 21.286300
+        CDF25   F32 21.368800
+        CDF30   F32 21.437400
+        CDF35   F32 21.509900
+        CDF40   F32 21.572000
+        CDF45   F32 21.629900
+        CDF50   F32 21.697600
+        CDF55   F32 21.756500
+        CDF60   F32 21.809000
+        CDF65   F32 21.857300
+        CDF70   F32 21.907200
+        CDF75   F32 21.951700
+        CDF80   F32 22.006600
+        CDF85   F32 22.070800
+        CDF90   F32 22.162300
+        CDF95   F32 22.323700
+        CDF99   F32 22.476700
         CDF100  F32 22.892300
     END
-# Updated with somewhat questionable values due to low numbers of zy data.
-    RULE METADATA
-    	COLNAME STR DETEFF
-	RULETYPE STR CDF
-	FILTER  STR z.00000
+    RULE METADATA
+        COLNAME STR DETEFF
+        RULETYPE STR CDF
+        FILTER  STR z.00000
         CDF00   F32 14.759100
-        CDF05   F32 17.486900
-        CDF10   F32 18.923700
-        CDF15   F32 19.383900
-        CDF20   F32 19.760100
-        CDF25   F32 19.950600
-        CDF30   F32 20.097300
-        CDF35   F32 20.203800
-        CDF40   F32 20.286700
-        CDF45   F32 20.377800
-        CDF50   F32 20.455000
-        CDF55   F32 20.527300
-        CDF60   F32 20.621800
-        CDF65   F32 20.713000
-        CDF70   F32 20.787700
-        CDF75   F32 20.884300
-        CDF80   F32 21.027100
-        CDF85   F32 21.183500
-        CDF90   F32 21.275500
-        CDF95   F32 21.383300
-        CDF99   F32 21.577900
-        CDF100  F32 21.670700
-    END
-    RULE METADATA
-    	COLNAME STR DETEFF
-	RULETYPE STR CDF
-	FILTER  STR y.00000
+        CDF05   F32 18.965400
+        CDF10   F32 19.733200
+        CDF15   F32 20.050200
+        CDF20   F32 20.224400
+        CDF25   F32 20.317200
+        CDF30   F32 20.403300
+        CDF35   F32 20.491200
+        CDF40   F32 20.581900
+        CDF45   F32 20.656000
+        CDF50   F32 20.720000
+        CDF55   F32 20.778800
+        CDF60   F32 20.843400
+        CDF65   F32 20.916000
+        CDF70   F32 20.998600
+        CDF75   F32 21.093300
+        CDF80   F32 21.182900
+        CDF85   F32 21.242400
+        CDF90   F32 21.297500
+        CDF95   F32 21.383500
+        CDF99   F32 21.553000
+        CDF100  F32 21.701800
+    END
+    RULE METADATA
+        COLNAME STR DETEFF
+        RULETYPE STR CDF
+        FILTER  STR y.00000
         CDF00   F32 14.606500
-        CDF05   F32 17.436900
-        CDF10   F32 18.090700
-        CDF15   F32 18.350700
-        CDF20   F32 18.549300
-        CDF25   F32 18.727300
-        CDF30   F32 18.934300
-        CDF35   F32 19.140200
-        CDF40   F32 19.294800
-        CDF45   F32 19.400400
-        CDF50   F32 19.493000
-        CDF55   F32 19.564800
-        CDF60   F32 19.665600
-        CDF65   F32 19.744900
-        CDF70   F32 19.821300
-        CDF75   F32 19.900400
-        CDF80   F32 20.005400
-        CDF85   F32 20.087600
-        CDF90   F32 20.148200
-        CDF95   F32 20.220300
-        CDF99   F32 20.365800
+        CDF05   F32 17.858300
+        CDF10   F32 18.328600
+        CDF15   F32 18.584100
+        CDF20   F32 18.870500
+        CDF25   F32 19.100900
+        CDF30   F32 19.237800
+        CDF35   F32 19.339200
+        CDF40   F32 19.407300
+        CDF45   F32 19.473800
+        CDF50   F32 19.541000
+        CDF55   F32 19.608900
+        CDF60   F32 19.682500
+        CDF65   F32 19.743900
+        CDF70   F32 19.811100
+        CDF75   F32 19.899000
+        CDF80   F32 20.011200
+        CDF85   F32 20.089600
+        CDF90   F32 20.148100
+        CDF95   F32 20.221100
+        CDF99   F32 20.340000
         CDF100  F32 20.594900
     END
-# Not updated on 2011-03-28 due to insufficient w data.
-    RULE METADATA
-    	COLNAME STR DETEFF
-	RULETYPE STR CDF
-	FILTER  STR w.00000
-	CDF00   F32 17.4082
-	CDF05   F32 19.4333
-	CDF10   F32 19.9698
-	CDF15   F32 20.2711
-	CDF20   F32 20.3919
-	CDF25   F32 20.5038
-	CDF30   F32 20.6192
-	CDF35   F32 20.7273
-	CDF40   F32 20.8184
-	CDF45   F32 20.9186
-	CDF50   F32 21.0151
-	CDF55   F32 21.1326
-	CDF60   F32 21.2442
-	CDF65   F32 21.3412
-	CDF70   F32 21.4394
-	CDF75   F32 21.5105
-	CDF80   F32 21.5567
-	CDF85   F32 21.6281
-	CDF90   F32 21.6908
-	CDF95   F32 21.7566
-	CDF99   F32 21.8907
-	CDF100  F32 23.6312
+    RULE METADATA
+        COLNAME STR DETEFF
+        RULETYPE STR CDF
+        FILTER  STR w.00000
+        CDF00   F32 21.986000
+        CDF05   F32 21.990000
+        CDF10   F32 22.056500
+        CDF15   F32 22.097000
+        CDF20   F32 22.145000
+        CDF25   F32 22.186500
+        CDF30   F32 22.209500
+        CDF35   F32 22.286500
+        CDF40   F32 22.339800
+        CDF45   F32 22.385200
+        CDF50   F32 22.413200
+        CDF55   F32 22.506700
+        CDF60   F32 22.554200
+        CDF65   F32 22.587100
+        CDF70   F32 22.594200
+        CDF75   F32 22.616800
+        CDF80   F32 22.688200
+        CDF85   F32 22.723000
+        CDF90   F32 22.765800
+        CDF95   F32 22.891600
+        CDF99   F32 22.964500
+        CDF100  F32 22.977000
     END
     RULE METADATA
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/filerules-mef.mdc
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/filerules-mef.mdc	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/filerules-mef.mdc	(revision 31439)
@@ -225,4 +225,8 @@
 PSPHOT.PSF.RAW.SAVE     OUTPUT {OUTPUT}.psf                      PSF       NONE       CHIP       TRUE      MEF
 PSPHOT.PSF.SKY.SAVE     OUTPUT {OUTPUT}.psf                      PSF       NONE       CHIP       TRUE      MEF
+
+# used by staticsky with single input
+PSPHOT.SKY.CONFIG       OUTPUT {OUTPUT}.psphot.mdc               TEXT      NONE       FPA        TRUE      NONE
+
                                                                                      
 # outputs for psphotStack:
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/filerules-simple.mdc
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/filerules-simple.mdc	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/filerules-simple.mdc	(revision 31439)
@@ -193,4 +193,7 @@
 PSPHOT.PSF.RAW.SAVE          OUTPUT {OUTPUT}.psf                  PSF             NONE       FPA        TRUE      NONE
 PSPHOT.PSF.SKY.SAVE          OUTPUT {OUTPUT}.psf                  PSF             NONE       FPA        TRUE      NONE
+
+# used by staticsky with single input
+PSPHOT.SKY.CONFIG       OUTPUT {OUTPUT}.psphot.mdc               TEXT      NONE       FPA        TRUE      NONE
 
 # outputs for psphotStack:
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/filerules-split.mdc
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/filerules-split.mdc	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/filerules-split.mdc	(revision 31439)
@@ -211,4 +211,7 @@
 PSPHOT.PSF.RAW.SAVE          OUTPUT {OUTPUT}.{CHIP.NAME}.psf          PSF             NONE       CHIP       TRUE      MEF
 PSPHOT.PSF.SKY.SAVE          OUTPUT {OUTPUT}.psf                      PSF             NONE       FPA        TRUE      MEF
+
+# used by staticsky with single input
+PSPHOT.SKY.CONFIG       OUTPUT {OUTPUT}.psphot.mdc               TEXT      NONE       FPA        TRUE      NONE
                                                                                                               
 # outputs for psphotStack:
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/nightly_science.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/nightly_science.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/nightly_science.config	(revision 31439)
@@ -22,5 +22,5 @@
 CLEAN_MODES METADATA
   MODE           STR MAGICDS
-  COMMAND        STR magicdstool -dbname @DBNAME@ -updaterun -set_state goto_cleaned -state full -set_label goto_cleaned -label @LABEL@
+  COMMAND        STR magicdstool -dbname @DBNAME@ -updaterun -set_state goto_cleaned -state full -set_label goto_cleaned -label @LABEL@ -data_group @DATA_GROUP@
   RETENTION_TIME S16 2
 END
@@ -203,9 +203,13 @@
   NAME      STR STS
   DISTRIBUTION STR STS
-  TESS      STR STS
+  # XXX: STS observations are temporarily being taken outside the STS tessellation
+  # switch tess_id from STS.V3 to RINGS
+  TESS      STR RINGS.V3
+  # TESS      STR STS.V3
   OBSMODE   STR STS%
   OBJECT    STR STS%
   STACKABLE BOOL FALSE
   DIFFABLE  BOOL FALSE
+  REDUCTION STR STS_DATASET
 END
 TARGETS METADATA
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/ppStack.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/ppStack.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/ppStack.config	(revision 31439)
@@ -97,4 +97,6 @@
 OUTPUT.REPLICATE BOOL   TRUE
 
+STACK.TYPE      STR     DEEP_STACK
+
 # Recipe overrides for STACK
 STACK	METADATA
@@ -123,4 +125,10 @@
 END
 
+QUICKSTACK    METADATA
+        CONVOLVE        BOOL   FALSE
+	COMBINE.REJ     F32    3.0
+        COMBINE.DISCARD F32    0.3
+        MASK.VAL	STR    MASK.VALUE,CONV.BAD,GHOST,BURNTOOL # Mask value of input bad pixels
+END
 
 # 
@@ -130,4 +138,5 @@
 
 STACK_NIGHTLY  METADATA
+    STACK.TYPE      STR     NIGHTLY_STACK
 END
 
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/ppSub.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/ppSub.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/ppSub.config	(revision 31439)
@@ -76,4 +76,6 @@
 INVERSE		BOOL	FALSE		# Generate inverse subtraction?
 PHOTOMETRY	BOOL	FALSE		# Perform photometry?
+NOCONVOLVE      BOOL    FALSE           # Skip convolution?
+
 
 FORCED.PHOTOMETRY.BOTH BOOL FALSE       # forced photometry on input sources?
@@ -141,4 +143,42 @@
  FORCED.PHOTOMETRY.BOTH BOOL    TRUE    # forced photometry on input sources
 END
+
+# Difference of warp - quickstack
+WARPQSTACK	METADATA
+	DUAL		BOOL	TRUE	# Dual convolution?
+	INVERSE		BOOL	FALSE	# Generate inverse subtraction?
+	PHOTOMETRY	BOOL	TRUE	# Perform photometry?
+
+	# penalty of 1.0
+	# DUAL convolution is more sensitive to the number of kernels
+	# do not provide as many orders as for SINGLE
+        # @ISIS.WIDTHS	F32	2.4  5.0  10.0  # Gaussian kernel FWHM values
+	@ISIS.WIDTHS	F32	1.5  3.0  6.0   # Gaussian kernel FWHM values
+	# @ISIS.WIDTHS	F32	2.0  3.0  5.0   # Gaussian kernel FWHM values
+        # @ISIS.WIDTHS	F32	2.1  4.2  8.4   # Gaussian kernel FWHM values
+	@ISIS.ORDERS	S32	2    2    2     # Polynomial orders for ISIS kernels
+
+	SCALE.REF	F32     5.0		# FWHM reference for kernel parameter scaling
+	KERNEL.SIZE     S32	15		# Kernel half-size (pixels)
+	STAMP.FOOTPRINT S32	15		# Size of stamps (pixels)
+END
+
+# Do no convolution
+UNCONVOLVED	METADATA
+	DUAL		BOOL	FALSE	# Dual convolution?
+	INVERSE		BOOL	FALSE   # Generate inverse subtraction?
+	PHOTOMETRY	BOOL	FALSE	# Perform photometry?
+	NOCONVOLVE      BOOL    TRUE
+	CONVOLVE.TARGET STR     SINGLE2	# convolution direction
+END
+
+# Difference of warp - junkstack
+WARPJSTACK      METADATA
+	DUAL		BOOL	FALSE	# Dual convolution?
+	INVERSE		BOOL	FALSE   # Generate inverse subtraction?
+	PHOTOMETRY	BOOL	TRUE	# Perform photometry?
+	CONVOLVE.TARGET STR     SINGLE1	# convolution direction
+END
+
 
 #PR image class
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/psastro.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/psastro.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/psastro.config	(revision 31439)
@@ -83,4 +83,6 @@
 PSASTRO.MIN.INST.MAG.RAW       F32      0.0   # min instrumental magnitude for stars accepted for fitting
 PSASTRO.MAX.INST.MAG.RAW       F32      0.0   # max instrumental magnitude for stars accepted for fitting
+PSASTRO.GRID.MIN.INST.MAG.RAW       F32      0.0   # min instrumental magnitude for stars accepted for grid search
+PSASTRO.GRID.MAX.INST.MAG.RAW       F32      0.0   # max instrumental magnitude for stars accepted for grid search
 
 PSASTRO.MATCH.LUMFUNC  BOOL     FALSE
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/psphot.config
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/psphot.config	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/psphot.config	(revision 31439)
@@ -203,18 +203,18 @@
 
 # define the annuli (in pixels) for surface brightness measurements
-# @RADIAL.ANNULAR.BINS.LOWER           F32     0.0   5.0  10.0  20.0  40.0  80.0
-# @RADIAL.ANNULAR.BINS.UPPER           F32     5.0  10.0  20.0  40.0  80.0 160.0
+# @RADIAL.ANNULAR.BINS.LOWER           F32     0.0   5.0  10.0  20.0  40.0  80.0 # comment due to ticket #1476
+# @RADIAL.ANNULAR.BINS.UPPER           F32     5.0  10.0  20.0  40.0  80.0 160.0 #
 
 # SDSS values (in SDSS pixels)
-#@RADIAL.ANNULAR.BINS.LOWER           F32     0.00 0.56 1.69 2.59 4.41  7.51 11.58 18.58 28.55 45.50  70.51 110.53 172.49 269.52 420.51
-#@RADIAL.ANNULAR.BINS.UPPER           F32     0.56 1.69 2.59 4.41 7.51 11.58 18.58 28.55 45.50 70.51 110.53 172.49 269.52 420.51 652.50
+#@RADIAL.ANNULAR.BINS.LOWER           F32     0.00 0.56 1.69 2.59 4.41  7.51 11.58 18.58 28.55 45.50  70.51 110.53 172.49 269.52 420.51 #
+#@RADIAL.ANNULAR.BINS.UPPER           F32     0.56 1.69 2.59 4.41 7.51 11.58 18.58 28.55 45.50 70.51 110.53 172.49 269.52 420.51 652.50 #
 
 # PS1 values? (all SDSS @ PS1 0.2 arcsec pixel scales)
-# @RADIAL.ANNULAR.BINS.LOWER           F32      0.0 1.2 3.4 5.2  8.8 15.0 23.2 37.2 57.1  91.0 141.0 221.1 345.0 539.1  841.0
-# @RADIAL.ANNULAR.BINS.UPPER           F32      1.2 3.4 5.2 8.8 15.0 23.2 37.2 57.1 91.0 141.0 221.1 345.0 539.1 841.0 1305.0
+# @RADIAL.ANNULAR.BINS.LOWER           F32      0.0 1.2 3.4 5.2  8.8 15.0 23.2 37.2 57.1  91.0 141.0 221.1 345.0 539.1  841.0 #
+# @RADIAL.ANNULAR.BINS.UPPER           F32      1.2 3.4 5.2 8.8 15.0 23.2 37.2 57.1 91.0 141.0 221.1 345.0 539.1 841.0 1305.0 #
 
 # PS1 values?
-@RADIAL.ANNULAR.BINS.LOWER           F32      0.0 1.2 3.4 5.2  8.8 15.0 23.2 37.2 57.1  91.0 141.0 
-@RADIAL.ANNULAR.BINS.UPPER           F32      1.2 3.4 5.2 8.8 15.0 23.2 37.2 57.1 91.0 141.0 221.1 
+@RADIAL.ANNULAR.BINS.LOWER           F32      0.0 1.2 3.4 5.2  8.8 15.0 23.2 37.2 57.1  91.0 141.0  # perl parser fails without a comment ticket #1476
+@RADIAL.ANNULAR.BINS.UPPER           F32      1.2 3.4 5.2 8.8 15.0 23.2 37.2 57.1 91.0 141.0 221.1  # perl parser fails without a comment ticket #1476
 
 # Extended source fit parameters
@@ -431,4 +431,9 @@
 END
 
+STACKPHOT_SINGLE    METADATA
+  PSPHOT.STACK.USE.RAW                BOOL  F   # since false perform photometry & morphology analysis on the convolved images
+  SAVE.BACKMDL                        BOOL  F
+END
+
 # Recipe overrides for CHIP
 CHIP	METADATA
Index: /branches/eam_branches/ipp-20110404/ippconfig/recipes/reductionClasses.mdc
===================================================================
--- /branches/eam_branches/ipp-20110404/ippconfig/recipes/reductionClasses.mdc	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/ippconfig/recipes/reductionClasses.mdc	(revision 31439)
@@ -160,4 +160,5 @@
 	STACKPHOT_PPSUB   STR     STACKPHOT
 	STACKPHOT_PPSTACK STR     STACKPHOT
+	STACKPHOT_SINGLE_PSPHOT  STR     STACKPHOT_SINGLE
 	BACKGROUND_PPBACKGROUND	STR	BACKGROUND
 	BACKGROUND_PSWARP	STR	BACKGROUND
@@ -178,5 +179,7 @@
 	ADDSTAR		STR	ADDSTAR
 	PSASTRO		STR     DEFAULT_RECIPE
-	STACKPHOT       STR     STACKPHOT
+	STACKPHOT_PSPHOT  STR     STACKPHOT
+	STACKPHOT_PPSUB   STR     STACKPHOT
+	STACKPHOT_PPSTACK STR     STACKPHOT
  	BACKGROUND_PPBACKGROUND	STR	BACKGROUND
  	BACKGROUND_PSWARP	STR	BACKGROUND
@@ -210,4 +213,18 @@
 STACKSTACK	METADATA
 	DIFF_PPSUB	STR	STACKSTACK
+	DIFF_PSPHOT	STR	DIFF
+	JPEG_BIN1	STR	PPIMAGE_J1
+	JPEG_BIN2	STR	PPIMAGE_J2
+END
+
+WARPQSTACK	METADATA
+	DIFF_PPSUB	STR	WARPQSTACK
+	DIFF_PSPHOT	STR	DIFF
+	JPEG_BIN1	STR	PPIMAGE_J1
+	JPEG_BIN2	STR	PPIMAGE_J2
+END
+
+NOCONVDIFF	METADATA
+	DIFF_PPSUB	STR	UNCONVOLVED
 	DIFF_PSPHOT	STR	DIFF
 	JPEG_BIN1	STR	PPIMAGE_J1
@@ -237,4 +254,11 @@
 END
 
+# quick stacks
+QUICKSTACK            METADATA
+      STACK_PPSTACK   STR      QUICKSTACK
+      STACK_PPSUB     STR      STACK
+      STACK_PSPHOT    STR      STACK
+END
+
 # basic science analysis
 PHOTFEST.SINGLE1	METADATA
@@ -339,4 +363,5 @@
 	STACKPHOT_PPSUB   STR     STACKPHOT
 	STACKPHOT_PPSTACK STR     STACKPHOT
+	STACKPHOT_SINGLE_PSPHOT  STR     STACKPHOT_SINGLE
 END
 
@@ -630,2 +655,19 @@
 END
 
+STS_DATASET METADATA
+   CHIP_PPIMAGE STR CHIP
+   CHIP_PSPHOT STR CHIP
+   WARP_PSWARP STR WARP
+   STACK_PPSTACK   STR STACK
+   STACK_PPSUB STR STACK
+   STACK_PSPHOT    STR STACK
+   DIFF_PPSUB  STR DIFF
+   DIFF_PSPHOT STR DIFF
+   JPEG_BIN1   STR PPIMAGE_J1
+   JPEG_BIN2   STR PPIMAGE_J2
+   FAKEPHOT    STR FAKEPHOT
+   ADDSTAR     STR ADDSTAR
+   PSASTRO    STR STS_DATASET
+   STACKPHOT       STR     STACKPHOT
+END
+
Index: /branches/eam_branches/ipp-20110404/psLib/src/db/psDB.c
===================================================================
--- /branches/eam_branches/ipp-20110404/psLib/src/db/psDB.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/psLib/src/db/psDB.c	(revision 31439)
@@ -1043,5 +1043,5 @@
         pType = psDBMySQLToPType(field[i].type, field[i].flags);
         if (!pType) {
-          psError(PS_ERR_UNKNOWN, false, "Failed to lookup type.");
+          psError(PS_ERR_UNKNOWN, false, "Failed to lookup type. %d %d %d",i,field[i].type, field[i].flags);
           psFree(md);
           mysql_free_result(result);
Index: /branches/eam_branches/ipp-20110404/psastro/src/psastroAstromGuess.c
===================================================================
--- /branches/eam_branches/ipp-20110404/psastro/src/psastroAstromGuess.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/psastro/src/psastroAstromGuess.c	(revision 31439)
@@ -161,4 +161,27 @@
                     psastroPlotRawstars (rawstars, fpa, chip, recipe);
                 }
+
+                // Next if we are using a different set of stars for grid search fill out their pmAstromObjs
+                psArray *grid_rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.GRID.RAWSTARS");
+                if (grid_rawstars == NULL || grid_rawstars == rawstars) { continue; }
+
+                for (int i = 0; i < grid_rawstars->n; i++) {
+                    pmAstromObj *raw = grid_rawstars->data[i];
+
+                    psPlaneTransformApply (raw->FP, chip->toFPA, raw->chip);
+                    psPlaneTransformApply (raw->TP, fpa->toTPA, raw->FP);
+                    psDeproject (raw->sky, raw->TP, fpa->toSky);
+
+                    // rationalize ra to sky range centered on boresite
+                    while (raw->sky->r < RAminSky) raw->sky->r += 2.0*M_PI;
+                    while (raw->sky->r > RAmaxSky) raw->sky->r -= 2.0*M_PI;
+
+                    RAmin = PS_MIN (raw->sky->r, RAmin);
+                    RAmax = PS_MAX (raw->sky->r, RAmax);
+
+                    DECmin = PS_MIN (raw->sky->d, DECmin);
+                    DECmax = PS_MAX (raw->sky->d, DECmax);
+                }
+                // XXX: should we plot grid_rawstars?
             }
         }
Index: /branches/eam_branches/ipp-20110404/psastro/src/psastroChipAstrom.c
===================================================================
--- /branches/eam_branches/ipp-20110404/psastro/src/psastroChipAstrom.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/psastro/src/psastroChipAstrom.c	(revision 31439)
@@ -60,4 +60,16 @@
 
                 // select the raw objects for this readout
+                psArray *gridrawstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.GRID.RAWSTARS.SUBSET");
+                if (gridrawstars == NULL) {
+                    gridrawstars = rawstars;
+                } else {
+                    // the absolute minimum number of stars is 4 (for order = 1)
+                    if (gridrawstars->n < 4) {
+                        readout->data_exists = false;
+                        psLogMsg ("psastro", 3, "insufficient gird rawstars (%ld)", gridrawstars->n);
+                        continue;
+                    }
+                }
+
                 psArray *refstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.REFSTARS.SUBSET");
                 if (refstars == NULL) { continue; }
@@ -80,5 +92,5 @@
 
                 // XXX update the header with info to reflect the failure
-                if (!psastroOneChipGrid (fpa, chip, refstars, rawstars, recipe, updates)) {
+                if (!psastroOneChipGrid (fpa, chip, refstars, gridrawstars, recipe, updates)) {
                     readout->data_exists = false;
                     psLogMsg ("psastro", 3, "failed to find a solution\n");
Index: /branches/eam_branches/ipp-20110404/psastro/src/psastroConvert.c
===================================================================
--- /branches/eam_branches/ipp-20110404/psastro/src/psastroConvert.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/psastro/src/psastroConvert.c	(revision 31439)
@@ -14,4 +14,6 @@
 // leak free 2006.04.27
 
+static psArray * chooseStars(psArray *inStars, char *listName, psArray *sources, psVector *index, int nMax, float iMagMin, float iMagMax, pmSourceMode skip);
+
 bool psastroConvertFPA (pmFPA *fpa, psMetadata *recipe) {
 
@@ -87,7 +89,36 @@
     }
 
+    psArray *rawStars = chooseStars(inStars, "", sources, index, PS_MIN(nMax, inStars->n), iMagMin, iMagMax, skip);
+    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.RAWSTARS", PS_DATA_ARRAY, "astrometry objects", rawStars);
+
+    bool gridSearch = psMetadataLookupBool (&status, recipe, "PSASTRO.GRID.SEARCH");
+    if (gridSearch) {
+        // See if different magnitude limits have been specified for grid search. If so, create a separate list of stars to use.
+        float iGridMagMax = psMetadataLookupF32 (&status, recipe, "PSASTRO.GRID.MAX.INST.MAG.RAW");
+        float iGridMagMin = psMetadataLookupF32 (&status, recipe, "PSASTRO.GRID.MIN.INST.MAG.RAW");
+        int   nMaxGrid = psMetadataLookupS32 (&status, recipe, "PSASTRO.GRID.NRAW.MAX");
+    
+        // XXX Should we check PSASTRO.GRID.NRAW.MAX != PSASTRO.MAX.NRAW as well? It usually is smaller so that would cause
+        // us to always create a separate list. So I won't check.
+
+        if ((iGridMagMax != iMagMax) || (iGridMagMin != iMagMin)) {
+            psArray *gridStars = chooseStars(inStars, "grid search ", sources, index, PS_MIN(nMaxGrid, inStars->n), iGridMagMin, iGridMagMax, skip);
+            psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.GRID.RAWSTARS", PS_DATA_ARRAY, "astrometry objects for grid search", gridStars);
+            psFree(gridStars);
+        }
+    }
+
+    psFree (index);
+    psFree (inStars);
+    psFree (rawStars);
+
+    return true;
+}
+
+
+psArray * chooseStars(psArray *inStars, char *listName, psArray *sources, psVector *index, int nMax, float iMagMin, float iMagMax, pmSourceMode skip) {
     // choose the first nMax sources
     int j = 0;
-    psArray *rawStars = psArrayAlloc (PS_MIN (nMax, inStars->n));
+    psArray *rawStars = psArrayAlloc(nMax);
 
     float mMin = +100.0;
@@ -128,14 +159,8 @@
     rawStars->n = j;
 
-    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.RAWSTARS", PS_DATA_ARRAY, "astrometry objects", rawStars);
-
-    psLogMsg ("psastro", 4, "loaded %ld sources, using %ld of %ld good sources (inst mag: %f to %f)\n", sources->n, rawStars->n, inStars->n, mMin, mMax);
+    psLogMsg ("psastro", 4, "loaded %ld %ssources, using %ld of %ld good sources (inst mag: %f to %f)\n", sources->n, listName, rawStars->n, inStars->n, mMin, mMax);
     psLogMsg ("psastro", 4, "skip reasons: mode: %d, faint: %d, bright: %d, inf: %d\n", nModeSkip, nFaintSkip, nBrightSkip, nInfSkip);
 
-    psFree (index);
-    psFree (inStars);
-    psFree (rawStars);
-
-    return true;
+    return rawStars;
 }
 
Index: /branches/eam_branches/ipp-20110404/psastro/src/psastroRemoveClumps.c
===================================================================
--- /branches/eam_branches/ipp-20110404/psastro/src/psastroRemoveClumps.c	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/psastro/src/psastroRemoveClumps.c	(revision 31439)
@@ -61,4 +61,11 @@
 		psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.RAWSTARS.SUBSET", PS_DATA_ARRAY, "astrometry objects", subset);
 		psFree (subset);
+
+                psArray *gridstars = psMetadataLookupPtr(&status, readout->analysis, "PSASTRO.GRID.RAWSTARS");
+                if ((gridstars == rawstars) || (gridstars == NULL)) { continue; }
+
+		psArray *gridstars_subset = psastroRemoveClumpsIterate(gridstars, 150, 3);
+		psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.GRID.RAWSTARS.SUBSET", PS_DATA_ARRAY, "astrometry objects", gridstars_subset);
+		psFree (gridstars_subset);
 	    }
 	}
Index: /branches/eam_branches/ipp-20110404/tools/czartool/MetricsIndex.pm
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/czartool/MetricsIndex.pm	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/tools/czartool/MetricsIndex.pm	(revision 31439)
@@ -53,4 +53,6 @@
     $self->createHtml("IPP Metrics");
     my $htmlFile = $self->{htmlFile};
+
+    print $htmlFile "<img src=\"masterMask.png\" alt=\"master magic mask fraction plot\" />\n";
 
     opendir(DIR, $self->{path}) or die $!;
Index: /branches/eam_branches/ipp-20110404/tools/czartool/Nebulous.pm
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/czartool/Nebulous.pm	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/tools/czartool/Nebulous.pm	(revision 31439)
@@ -110,5 +110,6 @@
             next;
         }
-        elsif ($line =~ m/(ipp[0-9]+)\s.+[0-9]+\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)%.*/i) {
+        elsif (($line =~ m/(ipp[0-9]+)\s.+[0-9]+\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)%.*/i)||
+	       ($line =~ m/(ippb[0-9]+)\s.+[0-9]+\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)%.*/i)) {
         
             $self->{_totalHosts}++;
Index: /branches/eam_branches/ipp-20110404/tools/mysql-dump/README
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/mysql-dump/README	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/tools/mysql-dump/README	(revision 31439)
@@ -0,0 +1,16 @@
+See ~ipp/mysql-dump on the production and the Manoa cluster
+
+Various utilities for mySQL dumps.
+
+Documentation at:
+http://svn.pan-starrs.ifa.hawaii.edu/trac/ipp/wiki/DatabaseBackups
+
+and in each script:
+ * functions.sh: various utilities
+ * gpc1Import.py: "import" the last gpc1 dump into gpc1_0/gpc1_1
+ * gpc1_dump.sh: dumps and copies gpc1 from a server hosting gpc1
+ * gpc1_install.sh: checks, installs, distributes the gpc1 dumps
+ * neb_copy.sh: copies and checks the last nebulous dump
+ * neb_dump.sh: dumps nebulous
+ * ops_dump.csh: dumps (and distributes when necessary) the ippadmin, 
+   isp, and ipprequestServer databases.
Index: /branches/eam_branches/ipp-20110404/tools/mysql-dump/functions.sh
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/mysql-dump/functions.sh	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/tools/mysql-dump/functions.sh	(revision 31439)
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# Some useful functions that can be reused in sh scripts
+
+# log: A limited logging function
+#
+# Usage: log ARG1 ARG2
+# where ARG1: a log level (put what is sensible for you)
+#       ARG2: a message (preferrably enclosed in quotes)
+# The date is prepended to the log level and message
+# e.g.:
+#       log USELESS "A useless message" 
+#    will show something like:
+# 2011-04-01T08:00:00: USELESS: A useless message
+function log() {
+    LOGLEVEL=`printf ":%8s:" $1`
+    shift
+    MESSAGE=$@
+    DATE=`date +"%FT%T"`
+    echo "$DATE$LOGLEVEL $MESSAGE"
+}
+
+# email: Send an e-mail
+#
+# Usage: email SUBJECT RECIPIENT MESSAGE
+# where SUBJECT: the e-mail subject
+#       RECIPIENT: a valid e-mail address
+#       MESSAGE: a message
+# e.g.:
+#       email "Monday?" mailing-list@dictators.org "Let's conquer the world"
+function email() {
+    SUBJECT=$1
+    shift
+    RECIPIENT=$1
+    shift
+    MESSAGE=$@
+    echo "$MESSAGE" | /bin/mail -s "$SUBJECT" $RECIPIENT
+}
+
Index: /branches/eam_branches/ipp-20110404/tools/mysql-dump/gpc1Import.py
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/mysql-dump/gpc1Import.py	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/tools/mysql-dump/gpc1Import.py	(revision 31439)
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+
+import commands
+filename='/netdisks/panstarrs/ipp/mysql-dump/.curr_gpc1_name'
+f=open(filename, 'r+')
+currname=f.read()
+f.close()
+
+if(currname=='gpc1_0'):
+	newname='gpc1_1'
+else:
+	newname='gpc1_0'
+
+print newname
+gpc1dumps=commands.getoutput('ls -t -1 /export/ipp001.0/ipp/mysql-dumps/mysql-gpc1*')
+dumparray=gpc1dumps.split()[1]
+cmd='bunzip2 < '+dumparray+' | mysql -hipp001 -u ipp -pipp -f ' + newname
+results = commands.getstatusoutput(cmd)
+
+f=open(filename, 'w')
+f.write(newname)
+f.close()
+
+print results
Index: /branches/eam_branches/ipp-20110404/tools/mysql-dump/gpc1_dump.sh
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/mysql-dump/gpc1_dump.sh	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/tools/mysql-dump/gpc1_dump.sh	(revision 31439)
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# This script is based on ops_dump.csh. It was originally run on ipp001. I changed it a bit
+#
+# Now it is supposed to be run on $HOST where a MySQL server hosts the gpc1 database (it can
+# the master or one of its slaves). It performs the following tasks:
+# 1) It tidies up the local directory used for MySQL dumps, namely:
+#       - it deletes the old MySQL dumps
+#       - it deletes the old MD5 checksum file
+# 2) It calls mysqldump to dump gpc1 to some bzipped file
+# 3) It computes the checksum
+# 4) It copies the dump and the checksum files onto the TARGET_HOST
+
+# Load utilities functions
+. /home/panstarrs/ipp/mysql-dump/functions.sh
+. /home/panstarrs/ipp/mysql-dump/password.sh
+
+EMAILTO=ps-ipp-ops@ifa.hawaii.edu
+
+HOST=ippc02
+TARGET_HOST=ipp0012
+TARGET_DIR=/export/ipp001.0/ipp/mysql-dumps/
+
+log INFO "Starting gpc1 backup"
+
+DUMP_PATH=/export/$HOST.0/mysql-dumps                  #path
+
+#1) Cleaning
+log INFO "Deleting old dumps"
+for file in `find $DUMP_PATH -name mysql-gpc1-$HOST-\*.dump.bz`; do
+	log INFO "Deleting $file"
+	/bin/rm -f $file
+done
+log INFO "Deleting old md5 sum file"
+/bin/rm -f $MD5FILENAME
+
+#2) Dumping
+DATEVAR=`date +%FT%T`                                   #date        
+FILENAME=$DUMP_PATH/mysql-gpc1-$HOST-$DATEVAR.dump.bz    #dump file name
+DB_USERNAME=gpc1_dump
+MD5FILENAME=$DUMP_PATH/gpc1_checksum.md5
+log INFO "Dumping to $FILENAME"
+/usr/bin/mysqldump -h localhost -u $DB_USERNAME -p$DB_PASSWORD --flush-logs --single-transaction gpc1 | ~ipp/local/bin/pbzip2 > $FILENAME
+dump_status=${PIPESTATUS[0]}
+if [ "$dump_status" -ne "0" ]; then
+	log ERROR "Sending warning e-mail"
+	email "Gpc1 dump failed" $EMAILTO "Check log file: /export/$HOST.0/mysql-dumps/gpc1_dump.log"
+	log INFO "End of gpc1 dump (Error)"
+	exit 1
+fi
+
+#3) Checksum
+log INFO "Generating MD5 checksum"
+/usr/bin/md5sum $FILENAME > $MD5FILENAME
+log INFO "End of gpc1 dump (Success)"
+
+#4) Copy onto TARGET_HOST
+log INFO "Copying $FILENAME on $TARGET_HOST"
+sudo -u ipp /usr/bin/scp -q $FILENAME ipp@$TARGET_HOST:$TARGET_DIR
+log INFO "Copying MD5 checksum file to $TARGET_HOST"
+sudo -u ipp /usr/bin/scp -q $MD5FILENAME ipp@$TARGET_HOST:$TARGET_DIR
+
+log INFO "End of gpc1 backup (Success)"
+
Index: /branches/eam_branches/ipp-20110404/tools/mysql-dump/gpc1_install.sh
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/mysql-dump/gpc1_install.sh	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/tools/mysql-dump/gpc1_install.sh	(revision 31439)
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+# This script is supposed to be executed on ipp001 (HOST)
+#
+# It checks, 'installs', and 'distributes' the last gpc1 MySQL dump.
+# The main steps are the following:
+# 1) Check if a checksum file is available
+#    - if it is not, the script sleeps $SLEEPING_TIME seconds, and
+#      iterates up to $MAX_ITERATIONS times.
+# 2) Check the gpc1 dump file against its checksum.
+# 3) Distribute the validated files, that is:
+#    - Hard-links the bzipped MySQL dump in the distribution directory
+#    - Moves the MD5 checksum to the distribution directory
+# 4) Import gpc1 into gpc1_0 or gpc1_1 (ensured by gpc1Import.py utility)
+. /home/panstarrs/ipp/mysql-dump/functions.sh
+
+EMAILTO=ps-ipp-ops@ifa.hawaii.edu
+
+HOST=ipp001
+TARGET=/export/$HOST.0/ipp/mysql-dumps
+MD5FILE=gpc1_checksum.md5
+
+DISTRIBUTION_TARGET=$TARGET/distribution/ippdb01-gpc1.dump.bz
+DISTRIBUTION_MD5=$TARGET/distribution/ippdb01-gpc1.md5
+
+MAX_ITERATIONS=200
+SLEEPING_TIME=60
+
+log INFO "Starting installation of gpc1"
+
+ITERATION=1
+MD5_STATUS=1
+while [ "$MD5_STATUS" -ne "0" ]; do
+	if [ ! -s $TARGET/$MD5FILE ]; then
+		log WARNING "MD5 file not found [$TARGET/$MD5FILE]. Waiting $SLEEPING_TIME seconds (Attempt: $ITERATION out of $MAX_ITERATIONS)"
+		sleep $SLEEPING_TIME
+		let ITERATION=ITERATION+1
+		if [ "$ITERATION" -ge "$MAX_ITERATIONS" ]; then
+			log ERROR "Copy of $TARGET/$MD5FILE failed after $ITERATION iterations. Giving up"
+			email "Too many failures when attempting to copy $TARGET/$MD5FILE" $EMAILTO "Check log"
+			log INFO "End of gpc1_install.sh (Failure)"
+			exit 1
+		fi
+	else
+		MD5_STATUS=0
+	fi
+done
+
+log INFO "Checking gpc1 backup file checksum"
+EXPECTED_MD5SUM=`cat $TARGET/$MD5FILE | sed 's/ .*$//'`
+BACKUP_FILE=`cat $TARGET/$MD5FILE | sed 's/^.* \//\//'`
+BACKUP_FILE=`basename $BACKUP_FILE`
+log INFO "Backup file is [$TARGET/$BACKUP_FILE]"
+ACTUAL_MD5SUM=`/usr/bin/md5sum $TARGET/$BACKUP_FILE | sed 's/ .*$//'`
+if [ "$ACTUAL_MD5SUM" != "$EXPECTED_MD5SUM" ]; then
+        log ERROR "Checksums are different: actual=[$ACTUAL_MD5SUM], expected=[$EXPECTED_MD5SUM]"
+	email "Invalid checksum for gpc1 backup" $EMAILTO "Checksums are different: actual=[$ACTUAL_MD5SUM], expected=[$EXPECTED_MD5SUM]"
+	log INFO "End of gpc1_install.sh (Failure)"
+        exit 2
+fi
+
+log INFO "Symlinking backup file [$TARGET/$BACKUP_FILE] to distribution [$DISTRIBUTION_TARGET]"
+/usr/bin/ln -f $TARGET/$BACKUP_FILE $DISTRIBUTION_TARGET
+/usr/bin/mv -f $TARGET/$MD5FILE $DISTRIBUTION_MD5
+
+# if it is between 0 and 4, ingest into gpc1_0 or gpc1_1
+HOUR=`date +"%H"`
+if [ "$HOUR" -lt "4" ]; then
+	log INFO "Importing gpc1 backup file to gpc1_0 or gpc1_1"
+	/usr/bin/python /home/panstarrs/ipp/mysql-dump/gpc1Import.py
+else
+	log DEBUG "No gpc1 backup importation"
+fi
+
+log INFO "End of gpc1_install.sh (Success)"
+
Index: /branches/eam_branches/ipp-20110404/tools/mysql-dump/neb_copy.sh
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/mysql-dump/neb_copy.sh	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/tools/mysql-dump/neb_copy.sh	(revision 31439)
@@ -0,0 +1,79 @@
+#!/bin/bash
+
+# This script is supposed to be executed on ipp001
+#
+# Its main steps:
+# 1) Copies the MD5 checksum from the ithe host where the nebulous db was dumped 
+#    using neb_dump.sh
+# 2) Copies the nebulous dump
+# 3) Checks the copy agaisnt the checksum
+# In case of failure, an e-mail is sent to $EMAILTO
+
+. /home/panstarrs/ipp/mysql-dump/functions.sh
+
+EMAILTO=ps-ipp-ops@ifa.hawaii.edu
+
+SOURCE_HOST=ippdb02
+HOST=ipp001
+
+SOURCE=ipp@$SOURCE_HOST:/export/$SOURCE_HOST.0/mysql-dumps
+TARGET=/export/$HOST.0/ipp/mysql-dumps
+
+MD5FILE=neb_checksum.md5
+
+MAX_ITERATIONS=200
+SLEEPING_TIME=60
+
+MD5_COPY_STATUS=1
+ITERATION=1
+while [ "$MD5_COPY_STATUS" -ne "0" ]; do
+	/usr/bin/scp -q $SOURCE/$MD5FILE $TARGET 2> /dev/null
+	MD5_COPY_STATUS=$?
+	if [ "$MD5_COPY_STATUS" -ne "0" ]; then
+		log WARNING "MD5 file not found on $SOURCE_HOST. Waiting $SLEEPING_TIME seconds (Attempt: $ITERATION out of $MAX_ITERATIONS)"
+		sleep $SLEEPING_TIME
+	else 
+		log DEBUG "Checking size of $TARGET/$MD5FILE"
+		if [ ! -s $TARGET/$MD5FILE ]; then
+			log WARNING "MD5 file has zero-size. Waiting $SLEEPING_TIME seconds (Attempt: $ITERATION out of $MAX_ITERATIONS)"
+			MD5_COPY_STATUS=1
+			sleep $SLEEPING_TIME
+		fi
+	fi
+	let ITERATION=ITERATION+1
+	if [ "$ITERATION" -ge "$MAX_ITERATIONS" ]; then
+                log ERROR "Copy of $SOURCE/$MD5FILE failed after $ITERATION iterations. Giving up"
+		email "Nebulous MD5 copy failed" $EMAILTO "Copy of $SOURCE/$MD5FILE failed after $ITERATION iterations. Giving up"
+		exit 1
+	fi
+done
+
+log INFO "MD5 file successfully copied ($TARGET/$MD5FILE)"
+
+EXPECTED_MD5SUM=`cat $TARGET/$MD5FILE | sed 's/ .*$//'`
+FILE_TO_COPY=`cat $TARGET/$MD5FILE | sed 's/^.* \//\//'`
+FILE_TO_COPY=`basename $FILE_TO_COPY`
+
+log INFO "Copying [$FILE_TO_COPY] now (expected MD5 sum: [$EXPECTED_MD5SUM])"
+/usr/bin/scp -q $SOURCE/$FILE_TO_COPY $TARGET > /dev/null
+if [ "$?" -ne "0" ]; then
+	log ERROR "Can't copy nebulous backup file [$FILE_TO_COPY]"
+	email "Nebulous backup file [$FILE_TO_COPY] copy failed" $EMAILTO "Can't copy nebulous backup file [$FILE_TO_COPY]"
+	exit 2
+else
+	log INFO "Nebulous backup file [$FILE_TO_COPY] successfully copied"
+fi
+
+log INFO "Checking nebulous backup file now"
+ACTUAL_MD5SUM=`/usr/bin/md5sum $TARGET/$FILE_TO_COPY | sed 's/ .*$//'`
+
+if [ "$ACTUAL_MD5SUM" != "$EXPECTED_MD5SUM" ]; then
+	log ERROR "Checksums are different: actual=[$ACTUAL_MD5SUM], expected=[$EXPECTED_MD5SUM]"
+	email "Bad Nebulous checksum" $EMAILTO "Checksums are different: actual=[$ACTUAL_MD5SUM], expected=[$EXPECTED_MD5SUM]"
+	exit 3
+fi
+
+log INFO "Successfully done with [$TARGET/$FILE_TO_COPY]"
+
+exit 0
+
Index: /branches/eam_branches/ipp-20110404/tools/mysql-dump/neb_dump.sh
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/mysql-dump/neb_dump.sh	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/tools/mysql-dump/neb_dump.sh	(revision 31439)
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# This script is inspired by ops_dump.csh. It was originally run on ipp001.
+#
+# This is the script that performs nebulous databases dumps. It can be run on any
+# server hosting the nebulous database. Its main steps are:
+# 1) Clean the old dump and the old MD5 checksum files
+# 2) Dump the nebulous database
+# 3) Computes the MD5 checksum
+
+. /home/panstarrs/ipp/mysql-dump/functions.sh
+. /home/panstarrs/ipp/mysql-dump/password.sh
+
+EMAILTO=ps-ipp-ops@ifa.hawaii.edu
+
+HOST=ippdb02
+
+log INFO "Starting nebulous dump"
+
+DUMP_PATH=/export/$HOST.0/mysql-dumps                  #path
+
+log INFO "Deleting old dumps"
+for file in `find $DUMP_PATH -name mysql-neb-$HOST-\*.dump.bz`; do
+	log INFO "Deleting $file"
+	/bin/rm -f $file
+done
+DATEVAR=`date +%FT%T`                                   #date        
+FILENAME=$DUMP_PATH/mysql-neb-$HOST-$DATEVAR.dump.bz    #dump file name
+DB_USERNAME=neb_dump
+MD5FILENAME=$DUMP_PATH/neb_checksum.md5
+
+log INFO "Deleting old md5 sum file"
+/bin/rm -f $MD5FILENAME
+
+log INFO "Dumping to [$FILENAME]"
+/usr/bin/mysqldump -h localhost -u $DB_USERNAME -p$DB_PASSWORD --flush-logs --single-transaction nebulous | ~ipp/local/bin/pbzip2 > $FILENAME
+dump_status=${PIPESTATUS[0]}
+if [ "$dump_status" -ne "0" ]; then
+	log ERROR "Sending warning e-mail"
+	email "Nebulous dump failed" $EMAILTO "Check log file: /export/ippdb02.0/mysql-dumps/neb-dump.log"
+	log INFO "End of nebulous dump (Error)"
+	exit 1
+fi
+
+/usr/bin/md5sum $FILENAME > $MD5FILENAME
+log INFO "End of nebulous dump (Success)"
+
Index: /branches/eam_branches/ipp-20110404/tools/mysql-dump/ops_dump.csh
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/mysql-dump/ops_dump.csh	(revision 31439)
+++ /branches/eam_branches/ipp-20110404/tools/mysql-dump/ops_dump.csh	(revision 31439)
@@ -0,0 +1,42 @@
+#!/bin/csh
+
+echo "## `/bin/date +%FT%T`"
+
+set EMAILTO = ps-ipp-ops@ifa.hawaii.edu
+
+# dump ippRequestServer from ippc19
+set DUMP_PATH = /data/ipp001.0/ipp/mysql-dumps       #path(SAB)
+mysqldump --compress -hippc19 -uipp -pipp --flush-logs --single-transaction --log-error=RS-err ippRequestServer | bzip2 > $DUMP_PATH/mysql-RS-ippc19-`date +%FT%T`.dump.bz
+if ($status != 0) then
+   /bin/mail -s "Warning ippRequestServer/RS dump failed" $EMAILTO < msg
+endif
+
+# dump ippadmin from ippdb01
+set DUMP_PATH = /data/ipp001.0/ipp/mysql-dumps               #path(SAB)
+set DATEVAR=`date +%FT%T`                                    #date
+set FILENAME = $DUMP_PATH/mysql-ippadmin-ippdb01-$DATEVAR.dump.bz
+mysqldump --compress -hippdb01 -uipp -pipp --flush-logs --single-transaction ippadmin | bzip2 > $FILENAME
+if ($status != 0) then
+   /bin/mail -s "Warning ippadmin dump failed" $EMAILTO < msg  
+endif
+
+# simlink to ippadmin ippdb01 dump
+set DUMP_PATH = /data/ipp001.0/ipp/mysql-dumps       #path(SAB)
+cd $DUMP_PATH/distribution/                          #link dir
+ln -f  ../mysql-ippadmin-ippdb01-$DATEVAR.dump.bz ippdb01-ippadmin.dump.bz
+
+
+# dump isp from ippdb01
+set DUMP_PATH = /data/ipp001.0/ipp/mysql-dumps               #path(SAB)
+set DATEVAR=`date +%FT%T`                                    #date
+set FILENAME = $DUMP_PATH/mysql-isp-ippdb01-$DATEVAR.dump.bz
+mysqldump --compress -hippdb01 -uipp -pipp --flush-logs --single-transaction isp | bzip2 > $FILENAME
+if ($status != 0) then
+   /bin/mail -s "Warning isp dump failed" $EMAILTO < msg  
+endif
+
+# simlink to isp ippdb01 dump
+set DUMP_PATH = /data/ipp001.0/ipp/mysql-dumps       #path(SAB)
+cd $DUMP_PATH/distribution/                          #link dir
+ln -f  ../mysql-isp-ippdb01-$DATEVAR.dump.bz ippdb01-isp.dump.bz
+
Index: /branches/eam_branches/ipp-20110404/tools/regpeek.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/regpeek.pl	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/tools/regpeek.pl	(revision 31439)
@@ -17,4 +17,5 @@
 }
 print "Date: $date\n";
+print "CMD: regtool -checkstatus -date $date -class_id ota33 -dbname gpc1 -simple\n";
 chomp(my $bad_exp = `regtool -checkstatus -date $date -class_id ota33 -dbname gpc1 -simple | grep 'stop run' | head -1`);
 my @row = split /\s+/, $bad_exp;
Index: /branches/eam_branches/ipp-20110404/tools/runcameraexp.pl
===================================================================
--- /branches/eam_branches/ipp-20110404/tools/runcameraexp.pl	(revision 31438)
+++ /branches/eam_branches/ipp-20110404/tools/runcameraexp.pl	(revision 31439)
@@ -16,4 +16,5 @@
 my $dbname = "gpc1";
 my ($cam_id, $update, $redirect, $save_temps, $pretend, $no_verbose);
+my ($outdir);
 
 GetOptions(
@@ -22,4 +23,5 @@
     'redirect-output'   => \$redirect,
     'save-temps'        => \$save_temps,
+    'outdir=s'          => \$outdir,
     'update'            => \$update,
     'dbname=s'          => \$dbname,
@@ -55,4 +57,11 @@
 
 die "Cannot update when run is not faulted\n" if $update and ! $fault;
+
+if ($outdir) {
+    my $base = basename($path_base);
+    $path_base = "$outdir/$base";
+    print STDERR "changing path_base to $path_base";
+    $update = 0;
+}
 
 my  $run_state;
