Index: /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/nebulous.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/nebulous.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/nebulous.h	(revision 23225)
@@ -1,5 +1,5 @@
 /* src/nebulous.h
-   Generated by wsdl2h 1.2.11 from nebulous.wsdl and typemap.dat
-   2008-10-16 23:26:37 GMT
+   Generated by wsdl2h 1.2.12 from nebulous.wsdl and typemap.dat
+   2009-03-05 21:11:05 GMT
    Copyright (C) 2001-2008 Robert van Engelen, Genivia Inc. All Rights Reserved.
    This part of the software is released under one of the following licenses:
Index: /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapC.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapC.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapC.c	(revision 23225)
@@ -1,4 +1,4 @@
 /* soapC.c
-   Generated by gSOAP 2.7.11 from src/nebulous.h
+   Generated by gSOAP 2.7.12 from src/nebulous.h
    Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved.
    This part of the software is released under one of the following licenses:
@@ -12,5 +12,5 @@
 #endif
 
-SOAP_SOURCE_STAMP("@(#) soapC.c ver 2.7.11 2008-10-16 23:26:39 GMT")
+SOAP_SOURCE_STAMP("@(#) soapC.c ver 2.7.12 2009-03-05 21:11:05 GMT")
 
 
@@ -676,6 +676,7 @@
 
 SOAP_FMAC3 char * SOAP_FMAC4 soap_in_byte(struct soap *soap, const char *tag, char *a, const char *type)
-{
-	return soap_inbyte(soap, tag, a, type, SOAP_TYPE_byte);
+{	char *p;
+	p = soap_inbyte(soap, tag, a, type, SOAP_TYPE_byte);
+	return p;
 }
 
@@ -711,6 +712,7 @@
 
 SOAP_FMAC3 int * SOAP_FMAC4 soap_in_int(struct soap *soap, const char *tag, int *a, const char *type)
-{
-	return soap_inint(soap, tag, a, type, SOAP_TYPE_int);
+{	int *p;
+	p = soap_inint(soap, tag, a, type, SOAP_TYPE_int);
+	return p;
 }
 
@@ -3384,5 +3386,5 @@
 {
 	int i, n = a->__size;
-	char *t = soap_putsize(soap, "xsd:string", a->__size);
+	char *t = a->__ptr ? soap_putsize(soap, "xsd:string", a->__size) : NULL;
 	id = soap_element_id(soap, tag, id, a, (struct soap_array*)&a->__ptr, 1, type, SOAP_TYPE_ArrayOfString);
 	if (id < 0)
@@ -4026,6 +4028,7 @@
 
 SOAP_FMAC3 char * * SOAP_FMAC4 soap_in__QName(struct soap *soap, const char *tag, char **a, const char *type)
-{
-	return soap_instring(soap, tag, a, type, SOAP_TYPE__QName, 2, -1, -1);
+{	char **p;
+	p = soap_instring(soap, tag, a, type, SOAP_TYPE__QName, 2, -1, -1);
+	return p;
 }
 
@@ -4066,6 +4069,7 @@
 
 SOAP_FMAC3 char * * SOAP_FMAC4 soap_in_string(struct soap *soap, const char *tag, char **a, const char *type)
-{
-	return soap_instring(soap, tag, a, type, SOAP_TYPE_string, 1, -1, -1);
+{	char **p;
+	p = soap_instring(soap, tag, a, type, SOAP_TYPE_string, 1, -1, -1);
+	return p;
 }
 
Index: /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapClient.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapClient.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapClient.c	(revision 23225)
@@ -1,4 +1,4 @@
 /* soapClient.c
-   Generated by gSOAP 2.7.11 from src/nebulous.h
+   Generated by gSOAP 2.7.12 from src/nebulous.h
    Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved.
    This part of the software is released under one of the following licenses:
@@ -10,5 +10,5 @@
 #endif
 
-SOAP_SOURCE_STAMP("@(#) soapClient.c ver 2.7.11 2008-10-16 23:26:38 GMT")
+SOAP_SOURCE_STAMP("@(#) soapClient.c ver 2.7.12 2009-03-05 21:11:05 GMT")
 
 
Index: /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapClientLib.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapClientLib.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapClientLib.c	(revision 23225)
@@ -1,4 +1,4 @@
 /* soapClientLib.c
-   Generated by gSOAP 2.7.11 from src/nebulous.h
+   Generated by gSOAP 2.7.12 from src/nebulous.h
    Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved.
    This part of the software is released under one of the following licenses:
Index: /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapH.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapH.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapH.h	(revision 23225)
@@ -1,4 +1,4 @@
 /* soapH.h
-   Generated by gSOAP 2.7.11 from src/nebulous.h
+   Generated by gSOAP 2.7.12 from src/nebulous.h
    Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved.
    This part of the software is released under one of the following licenses:
Index: /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapServer.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapServer.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapServer.c	(revision 23225)
@@ -1,4 +1,4 @@
 /* soapServer.c
-   Generated by gSOAP 2.7.11 from src/nebulous.h
+   Generated by gSOAP 2.7.12 from src/nebulous.h
    Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved.
    This part of the software is released under one of the following licenses:
@@ -10,5 +10,5 @@
 #endif
 
-SOAP_SOURCE_STAMP("@(#) soapServer.c ver 2.7.11 2008-10-16 23:26:38 GMT")
+SOAP_SOURCE_STAMP("@(#) soapServer.c ver 2.7.12 2009-03-05 21:11:05 GMT")
 
 
Index: /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapServerLib.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapServerLib.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapServerLib.c	(revision 23225)
@@ -1,4 +1,4 @@
 /* soapServerLib.c
-   Generated by gSOAP 2.7.11 from src/nebulous.h
+   Generated by gSOAP 2.7.12 from src/nebulous.h
    Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved.
    This part of the software is released under one of the following licenses:
Index: /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapStub.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapStub.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/Nebulous/nebclient/src/soapStub.h	(revision 23225)
@@ -1,4 +1,4 @@
 /* soapStub.h
-   Generated by gSOAP 2.7.11 from src/nebulous.h
+   Generated by gSOAP 2.7.12 from src/nebulous.h
    Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved.
    This part of the software is released under one of the following licenses:
Index: /branches/eam_branches/eam_branch_20090303/PS-IPP-Config/lib/PS/IPP/Config.pm
===================================================================
--- /branches/eam_branches/eam_branch_20090303/PS-IPP-Config/lib/PS/IPP/Config.pm	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/PS-IPP-Config/lib/PS/IPP/Config.pm	(revision 23225)
@@ -71,5 +71,5 @@
     unless (defined $class) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -85,5 +85,5 @@
     unless (open $file, $name) {
         carp "Unable to open ipprc file $name: $!";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
     my @contents = <$file>;        # Contents of the ipprc file
@@ -95,5 +95,5 @@
     unless (defined $path) {
         carp "PATH is not set in $name\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -112,8 +112,8 @@
     bless $self, $class;
 
-    $self->load_site();
-    $self->load_system();
-
-    $self->define_camera($camera) if defined $camera;
+    $self->load_site() or return undef;
+    $self->load_system() or return undef;
+
+    ( $self->define_camera($camera) or return undef ) if defined $camera;
 
     return $self;
@@ -148,5 +148,5 @@
                 unless ($found) {
                     carp "Unable to find camera configuration file $filename\n";
-                    exit($PS_EXIT_CONFIG_ERROR);
+                    return undef;
                 }
             }
@@ -158,5 +158,5 @@
 
     carp "Unable to find configuration file: $filename";
-    exit($PS_EXIT_CONFIG_ERROR);
+    return undef;
 }
 
@@ -170,5 +170,5 @@
     unless (defined $self) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -176,8 +176,9 @@
     unless (defined $filename) {
         carp "Unable to find site configuration file\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
     my $realfile = $self->_find_config($filename); # Resolved filename, after hunting the PATH
+    ( carp "Unable to find site configuration" and return undef ) unless defined $realfile;
 
     # Read the file
@@ -185,5 +186,5 @@
     unless (open $file, $realfile) {
         carp "Unable to open site configuration file $realfile: $!";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -194,5 +195,5 @@
     unless (defined $self->{_siteConfig}) {
         carp "Failure to parse the site configuration file $realfile";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -207,5 +208,5 @@
     unless (defined $self) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -213,8 +214,9 @@
     unless (defined $filename) {
         carp "Unable to find system configuration file\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
     my $realfile = $self->_find_config($filename); # Resolved filename, after hunting the PATH
+    ( carp "Unable to find system configuration" and return undef ) unless defined $realfile;
 
     # Read the file
@@ -222,5 +224,5 @@
     unless (open $file, $realfile) {
         carp "Unable to open system configuration file $realfile: $!";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
     my @contents = <$file>;
@@ -230,5 +232,5 @@
     unless (defined $self->{_systemConfig}) {
         carp "Failure to define system configuration";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -244,5 +246,5 @@
     unless (defined $self and defined $name) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -251,8 +253,9 @@
     unless (defined $filename) {
         carp "Unable to find configuration file for camera $name\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
     my $realfile = $self->_find_config($filename); # Resolved filename, after hunting the PATH
+    ( carp "Unable to find camera configuration" and return undef ) unless defined $realfile;
 
     # Read the file
@@ -260,5 +263,5 @@
     unless (open $file, $realfile) {
         carp "Unable to open camera configuration file $realfile: $!";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
     my @contents = <$file>;
@@ -269,5 +272,5 @@
     unless (defined $self->{camera}) {
         carp "Failure to define camera";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -326,5 +329,5 @@
     unless (defined $self and defined $name) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -333,5 +336,5 @@
     unless (defined $pathname) {
         carp "Unable to find datapath $name\n" ;
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -340,5 +343,5 @@
 
 # convert the database name and the table ID to a image source id
-sub source_id 
+sub source_id
 {
     my $self = shift;
@@ -351,8 +354,8 @@
     my $admindb = "ippadmin";
 
-    die "dbserver not defined in configuration" unless defined($dbserver);
-    die "dbuser not defined in configuration" unless defined($dbuser);
-    die "dbpassword not defined in configuration" unless defined($dbpassword);
-    die "dbname not defined in configuration" unless defined($dbname);
+    ( carp "dbserver not defined in configuration"  and return undef ) unless defined($dbserver);
+    ( carp "dbuser not defined in configuration"  and return undef ) unless defined($dbuser);
+    ( carp "dbpassword not defined in configuration"  and return undef ) unless defined($dbpassword);
+    ( carp "dbname not defined in configuration"  and return undef ) unless defined($dbname);
 
     my $dsn = "DBI:mysql:host=$dbserver;database=$admindb";
@@ -363,5 +366,5 @@
     $stmt->execute();
     my $ref = $stmt->fetchrow_hashref();
-    die "ippdb $dbname not found" unless ($ref);
+    ( carp "ippdb $dbname not found" and return undef ) unless ($ref);
 
     my $proj_id = $ref->{proj_id};
@@ -382,5 +385,5 @@
     if ($@) {
         carp "Can't find Nebulous::Client.";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -390,11 +393,11 @@
     unless (defined $server) {
         carp "Unable to find NEB_SERVER in camera configuration file.";
-        exit($PS_EXIT_CONFIG_ERROR);
-    }
-
-    my $neb = Nebulous::Client->new( proxy => $server );
-    unless (defined $neb) {
+        return undef;
+    }
+
+    my $neb = eval { Nebulous::Client->new( proxy => $server ); };
+    if ($@ or not defined $neb) {
         carp "Unable to find NEB_SERVER in camera configuration file.";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -415,28 +418,30 @@
     if ($scheme) {
         $scheme = lc($scheme);
-	# print "scheme: $scheme\n";
+        # print "scheme: $scheme\n";
 
         if ($scheme eq 'neb') {
-            $self->_neb_start();
+            $self->_neb_start() or ( carp "Can't start Nebulous" and return undef );
             my $neb = $self->{nebulous}; # Nebulous handle
             if ($create_if_doesnt_exist) {
-                unless ($neb->stat( $name )) {
-		    # print "entry $name not found, creating...\n";
-                    my $uri = $neb->create( $name );
-                    unless(defined $uri) {
+                my $status = eval { $neb->stat( $name ); };
+                ( carp "Unable to stat Nebulous handle $name" and return undef ) if $@;
+                unless ($status) {
+                    # print "entry $name not found, creating...\n";
+                    my $uri = eval { $neb->create( $name ); };
+                    if ($@ or not defined $uri) {
                         carp "unable to instantiate $name.";
-                        exit($PS_EXIT_DATA_ERROR);
+                        return undef;
                     }
                     my $path = URI->new( $uri )->path;
-		    # print "created path: $path\n";
+                    # print "created path: $path\n";
                     return $path;
                 }
             }
-	    my $path = $neb->find( $name );
-	    if (not defined $path) { 
-		carp "neb entry $name not found, not created\n"; 
-		exit($PS_EXIT_DATA_ERROR);
-	    } 
-	    # print "found path: $path\n";
+            my $path = eval { $neb->find( $name ); };
+            if ($@ or not defined $path) {
+                carp "neb entry $name not found, not created\n";
+                return undef;
+            }
+            # print "found path: $path\n";
             return $path;
         }
@@ -444,6 +449,6 @@
         if ($scheme eq 'path' or $scheme eq 'file') {
             # guaranteed to have a scheme (path:// or file://)
-            $name = $self->convert_filename_absolute( $name );
-	    # print "resolved path to $name\n";
+            $name = $self->convert_filename_absolute( $name ) or return undef;
+            # print "resolved path to $name\n";
         }
     }
@@ -454,12 +459,13 @@
         if (! -e $dir) {
             my $rc = system "mkdir -p $dir";
-            die "failed to create directory for $name" unless (!$rc);
+            ( carp "failed to create directory for $name" and return undef ) unless (!$rc);
         } elsif (! -d $dir ) {
-            die "parent for $name exists and is not a directory";
-        }
-
-        open F, ">$name" or die "failed to create $name";
+            carp "parent for $name exists and is not a directory";
+            return undef;
+        }
+
+        open F, ">$name" or ( carp "failed to create $name" and return undef );
         close F;
-	# print "created target $name\n";
+        # print "created target $name\n";
     }
 
@@ -473,5 +479,5 @@
     my $name = shift;                # File name to check
 
-    $self->file_prepare( $name );
+    $self->file_prepare( $name ) or return undef;
 
     my $scheme = file_scheme($name); # The scheme, e.g., file://, path://
@@ -479,10 +485,15 @@
         $scheme = lc($scheme);
         if ($scheme eq 'neb') {
-            $self->_neb_start();
-            return $self->{nebulous}->open_create( $name );
+            $self->_neb_start() or ( carp "Unable to start Nebulous" and return undef );
+            my $fh = eval { $self->{nebulous}->open_create( $name ); };
+            if ($@ or not defined $fh) {
+                carp "Unable to open/create Nebulous handle $name";
+                return undef;
+            }
+            return $fh;
         }
         if ($scheme eq 'path' or $scheme eq 'file') {
             # guaranteed to have a scheme (path:// or file://)
-            $name = $self->convert_filename_absolute( $name );
+            $name = $self->convert_filename_absolute( $name ) or return undef;
         }
     }
@@ -490,5 +501,5 @@
     if (-f $name) {
         carp "Unable to create file $name --- file exists.";
-        exit($PS_EXIT_SYS_ERROR);
+        return undef;
     }
 
@@ -496,5 +507,5 @@
     unless (open $fh, '>', $name) {
         carp "Unable to create file $name --- $!";
-        exit($PS_EXIT_SYS_ERROR);
+        return undef;
     }
     return $fh;
@@ -507,5 +518,5 @@
     my $name = shift;                # File name to check
 
-    $self->file_prepare( $name );
+    $self->file_prepare( $name ) or return undef;
 
     my $scheme = file_scheme($name); # The scheme, e.g., file://, path://
@@ -513,10 +524,15 @@
         $scheme = lc($scheme);
         if ($scheme eq 'neb') {
-            $self->_neb_start();
-            return $self->{nebulous}->open_create( $name );
+            $self->_neb_start() or ( carp "Unable to start Nebulous" and return undef );
+            my $fh = eval { $self->{nebulous}->open_create( $name ) };
+            if ($@ or not defined $fh) {
+                carp "Unable to open/create Nebulous handle $name";
+                return undef;
+            }
+            return $fh;
         }
         if ($scheme eq 'path' or $scheme eq 'file') {
             # guaranteed to have a scheme (path:// or file://)
-            $name = $self->convert_filename_absolute( $name );
+            $name = $self->convert_filename_absolute( $name ) or return undef;
         }
     }
@@ -525,5 +541,5 @@
     unless (open $fh, '>>', $name) {
         carp "Unable to create file $name --- $!";
-        exit($PS_EXIT_SYS_ERROR);
+        return undef;
     }
     return $fh;
@@ -536,10 +552,14 @@
     my $name = shift;                # File name to check
 
-    $self->file_prepare( $name );
+    $self->file_prepare( $name ) or return undef;
 
     my $scheme = file_scheme($name); # The scheme, e.g., file://, path://
     if (defined $scheme and lc($scheme) eq 'neb') {
-        $self->_neb_start();
-        $name = $self->{nebulous}->create( $name );
+        $self->_neb_start() or ( carp "Unable to start Nebulous" and return undef );
+        $name = eval { $self->{nebulous}->create( $name ) };
+        if ($@ or not defined $name) {
+            carp "Unable to create Nebulous handle $name";
+            return undef;
+        }
     }
 
@@ -555,6 +575,8 @@
     my $scheme = file_scheme($name); # The scheme, e.g., file://, path://
     if (defined $scheme and lc($scheme) eq 'neb') {
-        $self->_neb_start();
-        return (defined $self->{nebulous}->find_instances( $name ) ? 1 : 0);
+        $self->_neb_start() or ( carp "Unable to start Nebulous" and return undef );
+        my $found = eval { $self->{nebulous}->find_instances( $name ); };
+        ( carp "Unable to find instances of Nebulous handle $name" and return undef ) if $@;
+        return (defined $found ? 1 : 0);
     }
 
@@ -569,16 +591,19 @@
     my $target = shift;                # Name of target file
 
-    $self->file_prepare( $target );
+    $self->file_prepare( $target ) or return undef;
 
     my $scheme = file_scheme($target); # The scheme, e.g., file://, path://
     if (defined $scheme and lc($scheme) eq 'neb') {
-        $self->_neb_start();
-        $target = $self->{nebulous}->create( $target );
+        $self->_neb_start() or ( carp "Unable to start Nebulous" and return undef );
+        $target = eval { $self->{nebulous}->create( $target ); };
+        if ($@ or not defined $target) {
+            carp "Unable to create Nebulous handle";
+            return undef;
+        }
     }
     $target = $self->file_resolve( $target );
     $source = $self->file_resolve( $source );
 
-    system("cp $source $target") == 0 or (carp "Can't copy file $source to $target." and
-                                          exit($PS_EXIT_DATA_ERROR));
+    system("cp $source $target") == 0 or ( carp "Can't copy file $source to $target." and return undef );
     return 1;
 }
@@ -593,5 +618,5 @@
     my $preserve = shift;
 
-    die "pathname must be defined" unless ($pathname);
+    ( carp "pathname must be defined" and return undef ) unless ($pathname);
 
     my $fileRef;
@@ -602,7 +627,7 @@
 
     if ($preserve) {
-        # we want to keep the file just create it in the current directory 
+        # we want to keep the file just create it in the current directory
         $fileName = "./$base";
-        open $fileRef, ">$fileName" or die "can't open $fileName for output";
+        open $fileRef, ">$fileName" or ( carp "can't open $fileName for output" and return undef );
     } else {
         #  we really want a tempfile, so put it in /tmp
@@ -621,9 +646,10 @@
     my $scheme = file_scheme($name); # The scheme, e.g., file://, path://
     if (defined $scheme and lc($scheme) eq 'neb') {
-        $self->_neb_start();
-        $status = $self->{nebulous}->delete( $name );
+        $self->_neb_start() or ( carp "Unable to start Nebulous" and return undef );
+        $status = eval { $self->{nebulous}->delete( $name ); };
+        ( carp "Unable to delete Nebulous handle $name" and return undef ) if $@;
     } else {
-        my $resolved = $self->file_resolve($name);
-        if ($resolved && -e $resolved) {
+        my $resolved = $self->file_resolve($name) or return undef;
+        if (defined $resolved and -e $resolved) {
             $status = unlink($resolved);
         }
@@ -638,9 +664,9 @@
     my $name = shift;
 
-    die "need name" unless $name;
+    ( carp "need redirection target" and return undef ) unless $name;
 
     my $filename = $self->file_resolve($name, 1);
 
-    die "cannot resolve $name" unless $filename;
+    ( carp "cannot resolve $name" and return undef ) unless $filename;
 
     if (! open(STDOUT, ">>$filename") ) {
@@ -651,5 +677,6 @@
         while (! open STDOUT, ">>$filename" ) {
             if ($try == $max_tries) {
-                die "failed to redirect stdout to $filename after trying $max_tries times";
+                carp "failed to redirect stdout to $filename after trying $max_tries times";
+                return undef;
             }
             sleep 5;
@@ -658,5 +685,7 @@
         print STDERR "   redirect stdout to $filename succeded on try $try\n";
     }
-    open STDERR, ">>$filename" or die "failed to redirect stderr to $filename";
+    open STDERR, ">>$filename" or ( carp "failed to redirect stderr to $filename" and return undef );
+
+    return 1;
 }
 
@@ -676,5 +705,5 @@
     my $name = shift;                # File name for which to prepare
     my $workdir = shift;        # Working directory
-    my $template = shift;        # Template filename from which to get working directory if 
+    my $template = shift;        # Template filename from which to get working directory if
 
     if (defined $workdir) {
@@ -692,8 +721,8 @@
     # not guaranteed to have a scheme (path:// or file://) - might be /PATH/foobar
     # a relative path (PATH/foobar) is invalid here
-    my $resolved = $self->convert_filename_absolute( $name );
+    my $resolved = $self->convert_filename_absolute( $name ) or return undef;
     my ( $vol, $dirs, $file ) = File::Spec->splitpath( $resolved );
     unless (-d $dirs) {
-        system("mkdir -p $dirs") == 0 or (carp "Can't create directory $dirs" and exit($PS_EXIT_DATA_ERROR));
+        system("mkdir -p $dirs") == 0 or ( carp "Can't create directory $dirs" and return undef );
     }
 
@@ -716,8 +745,8 @@
     # not guaranteed to have a scheme (path:// or file://) - might be /PATH/foobar
     # a relative path (PATH/foobar) is invalid here
-    my $resolved = $self->convert_filename_absolute( $outroot );
+    my $resolved = $self->convert_filename_absolute( $outroot ) or return undef;
     my ( $vol, $dirs, $file ) = File::Spec->splitpath( $resolved );
     unless (-d $dirs) {
-        system("mkdir -p $dirs") == 0 or (carp "Can't create directory $dirs" and exit($PS_EXIT_DATA_ERROR));
+        system("mkdir -p $dirs") == 0 or ( carp "Can't create directory $dirs" and return undef );
     }
 
@@ -734,5 +763,5 @@
     unless (defined $self and defined $name) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -741,9 +770,9 @@
 
     ## if this is already an absolute path (/PATH/file), just return the path
-    unless (defined $scheme) { 
+    unless (defined $scheme) {
         if ($name =~ m|^/|) { return $name; }
         # without a leading slash, this is an error
         carp "Relative file name provided: relative paths are not permitted.";
-        exit($PS_EXIT_SYS_ERROR);
+        return undef;
     }
 
@@ -751,5 +780,5 @@
 
     if (lc($scheme) eq 'file') {
-        # the above strips of the leading slash; replace it for file:// 
+        # the above strips of the leading slash; replace it for file://
         $name = '/' . $name;
         return $name;
@@ -764,10 +793,6 @@
     }
 
-    # looks like we cannot reach here without an invalid scheme.  
-    # programming error?
-    # return $name;
-
-    carp "Programming error";
-    exit($PS_EXIT_PROG_ERROR);
+    # It's already absolute
+    return $name;
 }
 
@@ -777,10 +802,10 @@
     my $self = shift;                # Configuration object
     my $name = shift;                # raw name
-    
+
     unless (defined $self and defined $name) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
-    }
-    
+        return undef;
+    }
+
     # First, check to see if it's already in a relative form
     my $scheme = file_scheme($name); # The scheme, e.g., file, path
@@ -790,5 +815,5 @@
             # We may as well search for a 'better' path
             # guaranteed to have a scheme (path:// or file://)
-            $name = $self->convert_filename_absolute( $name );
+            $name = $self->convert_filename_absolute( $name ) or return undef;
         } elsif ($scheme eq 'neb') {
             # No chance of changing anything --- move along
@@ -796,8 +821,8 @@
         }
     }
-    
+
     $name = File::Spec->canonpath( $name); # Clean up
     my @dirs = File::Spec->splitdir( $name );
-    
+
     my $path_list = metadataLookupMD($self->{_siteConfig}, 'DATAPATH'); # List of paths
     my $best_path;
@@ -809,5 +834,5 @@
       $path =~ s|/*$||;
       my @path_dirs = File::Spec->splitdir( $path );
-      
+
       # Check if the path is suitable
       next if scalar @path_dirs > scalar @dirs;
@@ -823,5 +848,5 @@
       }
   }
-    
+
     $name =~ s|^/||;
     $name =~ s|/$||;
@@ -845,5 +870,5 @@
     unless (defined $self and defined $name and defined $type) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -854,13 +879,13 @@
             return undef;
         }
-        
+
         # rejections are saved as a recipe: REJECTIONS
         my @rejContents = `ppConfigDump -dump-recipe REJECTIONS -camera $camera -`;
-        
+
         # load from resulting psMetadataConfig
         $self->{rejection} = $parser->parse( join '', @rejContents); # The rejection metadata
         unless (defined $self->{rejection}) {
             carp "Unable to parse REJECTION recipe for $camera.";
-            exit($PS_EXIT_CONFIG_ERROR);
+            return undef;
         }
     }
@@ -873,5 +898,5 @@
           unless ($item->{class} eq "metadata") {
               carp "$name within REJECTIONS is not of type METADATA";
-              exit($PS_EXIT_PROG_ERROR);
+              return undef;
           }
           my $limits = $item->{value}; # List of rejection limits
@@ -880,7 +905,5 @@
           foreach my $limit (@$limits) {
               if ($limit->{name} eq 'FILTER') {
-                  if ($limit->{value} eq '*' or
-                      (defined $filter and
-                       $limit->{value} eq $filter)) {
+                  if ($limit->{value} eq '*' or (defined $filter and $limit->{value} eq $filter)) {
                       last;
                   }
@@ -888,5 +911,5 @@
               }
           }
-          
+
           foreach my $limit (@$limits) {
               return $limit->{value} if $limit->{name} eq $name;
@@ -915,5 +938,5 @@
     unless (defined $self and defined $name and defined $output) {
         carp "Programming error: required inputs left undefined";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -929,5 +952,5 @@
             return undef;
         }
-        
+
         $filerules = metadataLookup($camera, 'FILERULES');        # File rules
         unless (defined $filerules) {
@@ -935,13 +958,15 @@
             return undef;
         }
-        
+
         if ($filerules->{class} eq "scalar" and $filerules->{type} eq "STR") {
             # Allow indirection to a file
             my $filename = $self->_find_config($filerules->{value}); # Resolved filename
+            ( carp "Unable to find file rules file" and return undef ) unless defined $filename;
+
             # Read the file
             my $file;                # File handle
             unless (open $file, $filename) {
                 carp "Unable to open filerules file $filename: $!";
-                exit($PS_EXIT_CONFIG_ERROR);
+                return undef;
             }
             my @contents = <$file>;
@@ -973,5 +998,5 @@
         unless (defined $component) {
             carp "Programming error";
-            exit($PS_EXIT_PROG_ERROR);
+            return undef;
         }
         $filename =~ s/\{CHIP\.NAME\}/$component/;
@@ -980,5 +1005,5 @@
 
     return $filename;
-}   
+}
 
 # Return an EXTNAME From the EXTNAME.RULE table in the camera configuration
@@ -991,5 +1016,5 @@
     unless (defined $self and defined $name) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -1015,5 +1040,5 @@
         unless (defined $component) {
             carp "Programming error";
-            exit($PS_EXIT_PROG_ERROR);
+            return undef;
         }
         $extname =~ s/\{CHIP\.NAME\}/$component/;
@@ -1021,5 +1046,5 @@
 
     return $extname;
-}   
+}
 
 # Return catdir for tessellation, from TESSELLATIONS within the site configuration
@@ -1031,5 +1056,5 @@
     unless (defined $self and defined $self->{_siteConfig} and defined $tess_id) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -1037,5 +1062,5 @@
     unless (defined $tessellations) {
         carp "Can't find TESSELLATIONS in site configuration.\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -1050,5 +1075,5 @@
     if (defined $scheme and lc($scheme) eq 'neb') {
         carp "Tessellation $tess_id refers to a Nebulous path: $catdir\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -1065,5 +1090,5 @@
     unless (defined $self and defined $self->{_siteConfig} and defined $dvodb) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -1071,5 +1096,5 @@
     unless (defined $catdirs) {
         carp "Can't find DVO.CATDIRS in site configuration.\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -1084,5 +1109,5 @@
     if (defined $scheme and lc($scheme) eq 'neb') {
         carp "DVO catdir $dvodb refers to a Nebulous path: $catdir\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -1098,5 +1123,5 @@
     unless (defined $self and defined $self->{_siteConfig} and defined $dvodb) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -1104,5 +1129,5 @@
     unless (defined $catdirs) {
         carp "Can't find PSASTRO.CATDIRS in site configuration.\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -1117,5 +1142,5 @@
     if (defined $scheme and lc($scheme) eq 'neb') {
         carp "PSASTRO catdir $dvodb refers to a Nebulous path: $catdir\n";
-        exit($PS_EXIT_CONFIG_ERROR);
+        return undef;
     }
 
@@ -1130,5 +1155,5 @@
     unless (defined $self) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -1158,5 +1183,5 @@
     unless (defined $self and defined $reduction and defined $name) {
         carp "Programming error --- inputs undefined";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -1180,13 +1205,14 @@
             return undef;
         }
-        
+
         if ($reductionClasses->{class} eq "scalar" and $reductionClasses->{type} eq "STR") {
             # Allow indirection to a file
             my $filename = $self->_find_config($reductionClasses->{value}); # Resolved filename
+            ( carp "Unable to find reduction classes file" and return undef ) unless defined $filename;
             # Read the file
             my $file;                # File handle
             unless (open $file, $filename) {
                 carp "Unable to open reductionClasses file $filename: $!";
-                exit($PS_EXIT_CONFIG_ERROR);
+                return undef;
             }
             my @contents = <$file>;
@@ -1203,10 +1229,8 @@
 
     my $class = metadataLookupMD($reductionClasses, $reduction) or # Class of interest
-        (carp "Can't find $reduction in REDUCTION in camera configuration.\n" and
-         exit($PS_EXIT_CONFIG_ERROR));
+        ( carp "Can't find $reduction in REDUCTION in camera configuration.\n" and return undef );
 
     my $actual = metadataLookupStr($class, $name) or # The actual recipe name of interest
-        (carp "Can't find $name in $class in REDUCTION in camera configuration.\n" and
-         exit($PS_EXIT_CONFIG_ERROR));
+        (carp "Can't find $name in $class in REDUCTION in camera configuration.\n" and return undef );
 
     return $actual;
@@ -1226,19 +1250,19 @@
     }
 
-    my $dvoImageExtract = can_run('dvoImageExtract') or die "Can't find dvoImageExtract";
-    
+    my $dvoImageExtract = can_run('dvoImageExtract') or ( carp "Can't find dvoImageExtract" and return undef );
+
     my $tess_dir = $self->tessellation_catdir( $tess_id ); # Tessellation catdir for DVO
     unless (defined $tess_dir) {
         carp "Can't get list of tessellations.";
-        return 0;
-    }
-    $tess_dir = $self->convert_filename_absolute( $tess_dir );
+        return undef;
+    }
+    $tess_dir = $self->convert_filename_absolute( $tess_dir ) or return undef;
 
     unless ($self->file_exists( $outname )) {
-        my $outnameResolved = $self->file_create( $outname ); # Resolved filename, for Nebulous
+        my $outnameResolved = $self->file_create( $outname ) or return undef; # Resolved filename, for Nebulous
         my $command = "$dvoImageExtract -D CATDIR $tess_dir $skycell_id -o $outnameResolved";
         my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
             run(command => $command, verbose => $verbose);
-        die "Unable to perform dvoImageExtract for $tess_id $skycell_id\n" unless ($success and $self->file_exists( $outname ));
+        ( carp "Unable to perform dvoImageExtract for $tess_id $skycell_id\n" and return undef ) unless ($success and $self->file_exists( $outname ));
     }
 
@@ -1258,5 +1282,5 @@
         unless (defined $value) {
             carp "Unable to find environment variable $name";
-            exit($PS_EXIT_SYS_ERROR);
+            return undef;
         }
         $dir =~ s/\$\{?$name\}?/$value\//;
@@ -1272,5 +1296,5 @@
     unless (defined $mdc and defined $name) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
@@ -1285,5 +1309,5 @@
     return undef;
 }
-   
+
 
 # Lookup the metadata, checking the type is STR
@@ -1325,5 +1349,5 @@
     unless (defined $mdc and defined $name) {
         carp "Programming error";
-        exit($PS_EXIT_PROG_ERROR);
+        return undef;
     }
 
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/calibrate_dvo.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/calibrate_dvo.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/calibrate_dvo.pl	(revision 23225)
@@ -52,7 +52,7 @@
 my $caltool  = can_run('caltool')  or (warn "Can't find caltool"  and $missing_tools = 1);
 
-if ($missing_tools) { 
+if ($missing_tools) {
     warn ("Can't find required tools");
-    exit($PS_EXIT_CONFIG_ERROR); 
+    exit($PS_EXIT_CONFIG_ERROR);
 }
 
@@ -74,5 +74,5 @@
         cache_run(command => $command, verbose => 1);
 
-    unless ($success) { 
+    unless ($success) {
         $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
         &my_die ("Unable to perform addstar -resort on region $region: $error_code", $cal_id, $region, "RESORT", $status, $dbname);
@@ -83,15 +83,15 @@
 {
     foreach my $filter (@filters) {
-	my $command = "$relphot $filter";
-	$command .= "-D CATDIR $dvodb";
-	$command .= "-region $RAs $RAe $DECs $DECe";
+        my $command = "$relphot $filter";
+        $command .= "-D CATDIR $dvodb";
+        $command .= "-region $RAs $RAe $DECs $DECe";
 
-	my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
-	    cache_run(command => $command, verbose => 1);
+        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            cache_run(command => $command, verbose => 1);
 
-	unless ($success) { 
-	    $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
-	    &my_die ("Unable to perform addstar -resort on region $region: $error_code", $cal_id, $region, "RELPHOT", $status, $dbname);
-	}
+        unless ($success) {
+            $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+            &my_die ("Unable to perform addstar -resort on region $region: $error_code", $cal_id, $region, "RELPHOT", $status, $dbname);
+        }
     }
 }
@@ -101,15 +101,15 @@
 if (0) {
     foreach my $filter (@filters) {
-	my $command = "$uniphot $filter";
-	$command .= "-D CATDIR $dvodb";
-	$command .= "-region $RAs $RAe $DECs $DECe";
+        my $command = "$uniphot $filter";
+        $command .= "-D CATDIR $dvodb";
+        $command .= "-region $RAs $RAe $DECs $DECe";
 
-	my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
-	    cache_run(command => $command, verbose => 1);
+        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            cache_run(command => $command, verbose => 1);
 
-	unless ($success) { 
-	    $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
-	    &my_die ("Unable to perform addstar -resort on region $region: $error_code", $cal_id, $region, "UNIPHOT", $status, $dbname);
-	}
+        unless ($success) {
+            $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+            &my_die ("Unable to perform addstar -resort on region $region: $error_code", $cal_id, $region, "UNIPHOT", $status, $dbname);
+        }
     }
 }
@@ -121,9 +121,9 @@
 
     my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
-	cache_run(command => $command, verbose => 1);
+        cache_run(command => $command, verbose => 1);
 
-    unless ($success) { 
-	$error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
-	&my_die ("Unable to perform addstar -resort on region $region: $error_code", $cal_id, $region, "RELASTRO.OBJECTS", $status, $dbname);
+    unless ($success) {
+        $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+        &my_die ("Unable to perform addstar -resort on region $region: $error_code", $cal_id, $region, "RELASTRO.OBJECTS", $status, $dbname);
     }
 }
@@ -135,9 +135,9 @@
 
     my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
-	cache_run(command => $command, verbose => 1);
+        cache_run(command => $command, verbose => 1);
 
-    unless ($success) { 
-	$error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
-	&my_die ("Unable to perform addstar -resort on region $region: $error_code", $cal_id, $region, "RELASTRO.IMAGES", $status, $dbname);
+    unless ($success) {
+        $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+        &my_die ("Unable to perform addstar -resort on region $region: $error_code", $cal_id, $region, "RELASTRO.IMAGES", $status, $dbname);
     }
 }
@@ -169,14 +169,14 @@
     my $region    = shift;
     my $last_step = shift;
-    my $status 	  = shift;
-    my $dbname 	  = shift;
+    my $status    = shift;
+    my $dbname    = shift;
 
     carp($msg);
     if (defined $cal_id && defined $region && defined $last_step && defined $status and not $no_update) {
         my $command = "$caltool -addcalrun";
-	$command .= " -cal_id $cal_id";
+        $command .= " -cal_id $cal_id";
         $command .= " -region $region";
-	$command .= " -last_step $last_step";
-	$command .= " -state $status";
+        $command .= " -last_step $last_step";
+        $command .= " -state $status";
         $command .= " -dbname $dbname" if defined $dbname;
         system ($command);
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/camera_exp.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/camera_exp.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/camera_exp.pl	(revision 23225)
@@ -22,6 +22,4 @@
 use PS::IPP::Config 1.01 qw( :standard );
 use File::Temp qw( tempfile );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -70,9 +68,5 @@
     defined $camera;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $cam_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $cam_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 
 my $logDest = $ipprc->filename("LOG.EXP", $outroot) or &my_die("Missing entry from camera config", $cam_id, $PS_EXIT_CONFIG_ERROR);
@@ -84,5 +78,5 @@
 
 if ($redirect) {
-    $ipprc->redirect_output($logDest);
+    $ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $cam_id, $PS_EXIT_SYS_ERROR );
     print "\n\n";
     print "Starting script $0 on $host\n\n";
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/chip_imfile.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/chip_imfile.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/chip_imfile.pl	(revision 23225)
@@ -20,6 +20,4 @@
 use PS::IPP::Metadata::Config;
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -70,9 +68,5 @@
     defined $run_state;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $exp_id, $chip_id, $class_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $exp_id, $chip_id, $class_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 
 my $logDest = $ipprc->filename("LOG.IMFILE", $outroot, $class_id) or &my_die("Missing entry from camera config", $exp_id, $chip_id, $class_id, $PS_EXIT_CONFIG_ERROR);
@@ -80,5 +74,5 @@
 
 if ($redirect) {
-    $ipprc->redirect_output($logDest);
+    $ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $exp_id, $chip_id, $class_id, $PS_EXIT_SYS_ERROR );
     print STDOUT "\n\n";
     print STDOUT "Starting script $0 on $host\n\n";
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_correct_imfile.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_correct_imfile.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_correct_imfile.pl	(revision 23225)
@@ -18,6 +18,4 @@
 use PS::IPP::Metadata::Config;
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -60,15 +58,9 @@
     and defined $camera;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $class_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-# XXX this exits with status = 0 on failure
-$ipprc->define_camera($camera);
-
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $det_id, $class_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 if ($redirect) {
     my $logDest = $ipprc->filename("LOG.IMFILE", $outroot, $class_id)
        or &my_die("Missing entry from camera config", $det_id, $class_id, $PS_EXIT_CONFIG_ERROR);
-    $ipprc->redirect_output($logDest);
+    $ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $det_id, $class_id, $PS_EXIT_SYS_ERROR );
 }
 
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_norm_apply.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_norm_apply.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_norm_apply.pl	(revision 23225)
@@ -17,6 +17,4 @@
 use PS::IPP::Metadata::Config;
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -64,13 +62,9 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $iter, $class_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $det_id, $iter, $class_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 
 my $logDest = $ipprc->filename("LOG.IMFILE", $outroot, $class_id)
         or &my_die("Missing entry from camera config", $det_id, $iter, $class_id, $PS_EXIT_CONFIG_ERROR);
-$ipprc->redirect_output($logDest) if $redirect;
+$ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $det_id, $iter, $class_id, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 my $RECIPE_PPIMAGE = 'PPIMAGE_N'; # Recipe to use with ppImage
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_norm_calc.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_norm_calc.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_norm_calc.pl	(revision 23225)
@@ -19,6 +19,4 @@
 use PS::IPP::Metadata::List qw( parse_md_list );
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -57,11 +55,8 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $iter, $PS_EXIT_UNKNOWN_ERROR ); };
+my $ipprc = PS::IPP::Config->new() or my_die( "Unable to set up", $det_id, $iter, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 
 my $logfile = $outroot . ".log";
-
-$ipprc->redirect_output($logfile) if $redirect;
+$ipprc->redirect_output($logfile) or my_die( "Unable to redirect output", $det_id, $iter, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 use constant STATISTIC => 'bg'; # Background statistic to use from the database
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_norm_exp.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_norm_exp.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_norm_exp.pl	(revision 23225)
@@ -19,6 +19,4 @@
 use PS::IPP::Metadata::List qw( parse_md_list );
 use File::Temp qw( tempfile );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -60,13 +58,7 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $iter, $PS_EXIT_UNKNOWN_ERROR ); };
-
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $det_id, $iter, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 my $logfile = $outroot . ".log";
-
-$ipprc->redirect_output($logfile) if $redirect;
-
-$ipprc->define_camera($camera);
+$ipprc->redirect_output($logfile) or my_die( "Unable to redirect output", $det_id, $iter, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 # Recipes to use based on reduction class
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_process_exp.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_process_exp.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_process_exp.pl	(revision 23225)
@@ -19,6 +19,4 @@
 use PS::IPP::Metadata::List qw( parse_md_list );
 use File::Temp qw( tempfile );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -63,14 +61,9 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $exp_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
-
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $det_id, $exp_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 if ($redirect) {
     my $logDest = $ipprc->filename("LOG.EXP", $outroot, "NONE")
         or &my_die("Missing entry in file rules", $det_id, $exp_id, $PS_EXIT_CONFIG_ERROR);
-    $ipprc->redirect_output($logDest);
+    $ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $det_id, $exp_id, $PS_EXIT_SYS_ERROR );
 }
 
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_process_imfile.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_process_imfile.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_process_imfile.pl	(revision 23225)
@@ -17,6 +17,4 @@
 use PS::IPP::Metadata::Config;
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -65,14 +63,7 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $exp_id, $class_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-# XXX this exits with status = 0 on failure
-$ipprc->define_camera($camera);
-
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $det_id, $exp_id, $class_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 my $logDest = $ipprc->filename("LOG.IMFILE", $outroot, $class_id) or &my_die("Missing entry from camera config", $det_id, $exp_id, $class_id, $PS_EXIT_CONFIG_ERROR);
-
-$ipprc->redirect_output($logDest) if $redirect;
+$ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $det_id, $exp_id, $class_id, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 # Recipes to use as a function of detrend type
@@ -81,4 +72,24 @@
 my $jpeg_recipe = $ipprc->reduction($reduction, uc($det_type) . '_JPEG_IMAGE'); # Recipe name for JPEG
 
+# The output file rule name depends on the detrend type
+my $FILERULES = { 'FLATMASK'         => undef,
+                  'DARKMASK'         => undef,
+                  'MASK'             => undef,
+                  'BIAS'             => undef,
+                  'DARK'             => undef,
+                  'DARK_PREMASK'     => undef,
+                  'SHUTTER'          => 'PPIMAGE.OUTPUT.DETREND',
+                  'FLAT_PREMASK'     => 'PPIMAGE.OUTPUT.DETREND',
+                  'DOMEFLAT_PREMASK' => 'PPIMAGE.OUTPUT.DETREND',
+                  'SKYFLAT_PREMASK'  => 'PPIMAGE.OUTPUT.DETREND',
+                  'FLAT_RAW'         => 'PPIMAGE.OUTPUT.DETREND',
+                  'DOMEFLAT_RAW'     => 'PPIMAGE.OUTPUT.DETREND',
+                  'SKYFLAT_RAW'      => 'PPIMAGE.OUTPUT.DETREND',
+                  'FLAT'             => 'PPIMAGE.OUTPUT.DETREND',
+                  'DOMEFLAT'         => 'PPIMAGE.OUTPUT.DETREND',
+                  'SKYFLAT'          => 'PPIMAGE.OUTPUT.DETREND',
+                  'FRINGE'           => undef,
+              };
+
 &my_die("Couldn't find input file: $input_uri\n", $det_id, $exp_id, $class_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists($input_uri);
 
@@ -93,9 +104,14 @@
 my $cmdflags;
 
-my $outputImage = $ipprc->filename("PPIMAGE.OUTPUT", $outroot, $class_id) or &my_die("Missing entry from camera config", $det_id, $exp_id, $class_id, $PS_EXIT_PROG_ERROR);
+my $filerule = $FILERULES->{$det_type}; # File rule to use for output
+$filerule =  "PPIMAGE.OUTPUT" unless defined $filerule;
+
+my $outputImage = $ipprc->filename($filerule,        $outroot, $class_id) or &my_die("Missing entry from camera config", $det_id, $exp_id, $class_id, $PS_EXIT_PROG_ERROR);
 my $outputBin1  = $ipprc->filename("PPIMAGE.BIN1",   $outroot, $class_id) or &my_die("Missing entry from camera config", $det_id, $exp_id, $class_id, $PS_EXIT_PROG_ERROR);
 my $outputBin2  = $ipprc->filename("PPIMAGE.BIN2",   $outroot, $class_id) or &my_die("Missing entry from camera config", $det_id, $exp_id, $class_id, $PS_EXIT_PROG_ERROR);
 my $outputStats = $ipprc->filename("PPIMAGE.STATS",  $outroot, $class_id) or &my_die("Missing entry from camera config", $det_id, $exp_id, $class_id, $PS_EXIT_PROG_ERROR);
 my $traceDest   = $ipprc->filename("TRACE.IMFILE",   $outroot, $class_id) or &my_die("Missing entry from camera config", $exp_id, $exp_id, $class_id, $PS_EXIT_CONFIG_ERROR);
+
+
 # Run ppImage
 unless ($no_op) {
@@ -105,4 +121,5 @@
     $command .= " -recipe PPSTATS DETSTATS";
     $command .= " -stats $outputStats";
+    $command .= " -F PPIMAGE.OUTPUT $filerule" if $filerule ne "PPIMAGE.OUTPUT";
     $command .= " -tracedest $traceDest -log $logDest";
     $command .= " -threads $threads" if defined $threads;
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_reject_exp.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_reject_exp.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_reject_exp.pl	(revision 23225)
@@ -20,6 +20,4 @@
 use PS::IPP::Metadata::List qw( parse_md_list );
 use Statistics::Descriptive;
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 my $ITER_LIMIT = 20;
@@ -60,14 +58,8 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $iter, $PS_EXIT_UNKNOWN_ERROR ); };
-
-# check for existing directory, generate if needed
-$ipprc->outroot_prepare($outroot);
-
+my $ipprc = PS::IPP::Config->new() or my_die( "Unable to set up", $det_id, $iter, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+$ipprc->outroot_prepare($outroot) or my_die( "Unable to prepare output root", $det_id, $iter, $PS_EXIT_SYS_ERROR );
 my $logName = "$outroot.log"; # Name for log
-
-$ipprc->redirect_output($logName) if $redirect;
+$ipprc->redirect_output($logName) or my_die( "Unable to redirect", $det_id, $iter, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 # values to extract from output metadata and the stats to calculate
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_resid_exp.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_resid_exp.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_resid_exp.pl	(revision 23225)
@@ -30,6 +30,4 @@
 use File::Temp qw( tempfile );                   # tools to construct temp files
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt ); # option parsing
@@ -79,14 +77,8 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $iter, $exp_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
 # load IPP config information for the specified camera
-$ipprc->define_camera($camera);
-
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $det_id, $iter, $exp_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 my $logDest = $ipprc->filename("LOG.EXP", $outroot) or &my_die("Missing entry from camera config", $det_id, $iter, $exp_id, $PS_EXIT_CONFIG_ERROR);
-
-$ipprc->redirect_output($logDest) if $redirect;
+$ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $det_id, $iter, $exp_id, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 # Recipes to use based on reduction class
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_resid_imfile.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_resid_imfile.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_resid_imfile.pl	(revision 23225)
@@ -17,6 +17,4 @@
 use PS::IPP::Metadata::Config;
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -76,13 +74,7 @@
     defined $detrend;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $iter, $exp_id, $class_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
-my $logDest     = $ipprc->filename("LOG.IMFILE", $outroot, $class_id);
-if ($redirect) {
-    $ipprc->redirect_output($logDest);
-}
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $det_id, $iter, $exp_id, $class_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+my $logDest = $ipprc->filename("LOG.IMFILE", $outroot, $class_id) or my_die( "Unable to find LOG.IMFILE", $det_id, $iter, $exp_id, $class_id, $PS_EXIT_CONFIG_ERROR );
+$ipprc->redirect_output($logDest) or my_die( "Unable to find LOG.IMFILE", $det_id, $iter, $exp_id, $class_id, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 # Recipes to use as a function of detrend type and mode
@@ -124,4 +116,24 @@
 };
 
+# The output file rule name depends on the detrend type
+my $FILERULES = { 'FLATMASK'         => 'PPIMAGE.OUTPUT.RESID',
+                  'DARKMASK'         => 'PPIMAGE.OUTPUT.RESID',
+                  'MASK'             => 'PPIMAGE.OUTPUT.RESID',
+                  'BIAS'             => 'PPIMAGE.OUTPUT.RESID',
+                  'DARK'             => 'PPIMAGE.OUTPUT.RESID',
+                  'DARK_PREMASK'     => 'PPIMAGE.OUTPUT.RESID',
+                  'SHUTTER'          => 'PPIMAGE.OUTPUT.DETREND',
+                  'FLAT_PREMASK'     => 'PPIMAGE.OUTPUT.DETREND',
+                  'DOMEFLAT_PREMASK' => 'PPIMAGE.OUTPUT.DETREND',
+                  'SKYFLAT_PREMASK'  => 'PPIMAGE.OUTPUT.DETREND',
+                  'FLAT_RAW'         => 'PPIMAGE.OUTPUT.DETREND',
+                  'DOMEFLAT_RAW'     => 'PPIMAGE.OUTPUT.DETREND',
+                  'SKYFLAT_RAW'      => 'PPIMAGE.OUTPUT.DETREND',
+                  'FLAT'             => 'PPIMAGE.OUTPUT.DETREND',
+                  'DOMEFLAT'         => 'PPIMAGE.OUTPUT.DETREND',
+                  'SKYFLAT'          => 'PPIMAGE.OUTPUT.DETREND',
+                  'FRINGE'           => 'PPIMAGE.OUTPUT.RESID',
+              };
+
 # outroot examples (HOST components must be set)
 # file://data/ipp004.0/gpc1/20080130
@@ -135,5 +147,7 @@
 # my $outputName  = $ipprc->filename("PPIMAGE.OUTPUT", $outroot, $class_id);
 
-my $outputName  = $ipprc->filename("PPIMAGE.OUTPUT.RESID", $outroot, $class_id);
+my $filerule = $FILERULES->{$det_type}; # File rule to use
+
+my $outputName  = $ipprc->filename($filerule,        $outroot, $class_id);
 my $bin1Name    = $ipprc->filename("PPIMAGE.BIN1",   $outroot, $class_id);
 my $bin2Name    = $ipprc->filename("PPIMAGE.BIN2",   $outroot, $class_id);
@@ -149,5 +163,5 @@
     $command .= " -recipe JPEG $jpeg_recipe";
     $command .= " -recipe PPSTATS RESIDUAL";
-    $command .= " -F PPIMAGE.OUTPUT PPIMAGE.OUTPUT.RESID";
+    $command .= " -F PPIMAGE.OUTPUT $filerule";
     $command .= " -stats $outputStats";
     $command .= " -tracedest $traceDest -log $logDest";
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_stack.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_stack.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/detrend_stack.pl	(revision 23225)
@@ -18,6 +18,4 @@
 use PS::IPP::Metadata::List qw( parse_md_list );
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -63,16 +61,10 @@
     defined $outroot;
 
-$ipprc->define_camera($camera);
 $det_type = uc($det_type);
 
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $det_id, $iter, $class_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 my $logDest = $ipprc->filename("LOG.IMFILE", $outroot, $class_id)
     or &my_die("Missing entry in file rules", $det_id, $iter, $class_id, $PS_EXIT_CONFIG_ERROR);
-
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $det_id, $iter, $class_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-# optionally redirect the outputs from this script to LOG.IMFILE
-$ipprc->redirect_output($logDest) if $redirect;
+$ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $det_id, $iter, $class_id, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 # Recipes to use as a function of detrend type
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/diff_skycell.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/diff_skycell.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/diff_skycell.pl	(revision 23225)
@@ -21,6 +21,4 @@
 use Data::Dumper;
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -62,12 +60,10 @@
     and defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $diff_id, $skycell_id, $PS_EXIT_UNKNOWN_ERROR ); };
+my $ipprc = PS::IPP::Config->new() or my_die( "Unable to set up", $diff_id, $skycell_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 
 # XXX camera is not known here; cannot use filerules...
 # my $logDest = $ipprc->filename("LOG.EXP", $outroot);
 my $logDest = "$outroot.log";
-$ipprc->redirect_output($logDest) if $redirect;
+$ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $diff_id, $skycell_id, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 my $source_id = $ipprc->source_id($dbname, $PS_TABLE_ID_DIFF);
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/fake_imfile.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/fake_imfile.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/fake_imfile.pl	(revision 23225)
@@ -36,6 +36,4 @@
 use PS::IPP::Metadata::Config;
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -82,13 +80,7 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $exp_id, $fake_id, $class_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
-
-my $logDest = $ipprc->filename("LOG.IMFILE", $outroot, $class_id)  or &my_die("Missing entry from camera config", $exp_id, $fake_id, $class_id, $PS_EXIT_CONFIG_ERROR);
-
-$ipprc->redirect_output($logDest) if $redirect;
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $exp_id, $fake_id, $class_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+my $logDest = $ipprc->filename("LOG.IMFILE", $outroot, $class_id) or &my_die("Missing entry from camera config", $exp_id, $fake_id, $class_id, $PS_EXIT_CONFIG_ERROR);
+$ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $exp_id, $fake_id, $class_id, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 # Recipes to use based on reduction class
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/ipp_cleanup.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/ipp_cleanup.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/ipp_cleanup.pl	(revision 23225)
@@ -18,30 +18,30 @@
 use Pod::Usage qw( pod2usage );
 
-my $ipprc = PS::IPP::Config->new(); # this is used for PATH, NEB filename conversions
-
 # Parse the command-line arguments
 my ($stage, $camera, $stage_id, $mode, $path_base, $dbname, $verbose, $no_op, $helplist);
 GetOptions('stage=s'        => \$stage,     # which analysis stage to clean?
-	   'camera|i=s'     => \$camera,    # user-supplied camera name
-	   'stage_id=s'     => \$stage_id,  # id for this stage (only needed for certain stages)
-	   'mode|m=s'       => \$mode,      # cleanup mode (clean / purge)
-	   'path_base=s'    => \$path_base, # basename for files
-	   'dbname|d=s'     => \$dbname,    # Database name
+           'camera|i=s'     => \$camera,    # user-supplied camera name
+           'stage_id=s'     => \$stage_id,  # id for this stage (only needed for certain stages)
+           'mode|m=s'       => \$mode,      # cleanup mode (clean / purge)
+           'path_base=s'    => \$path_base, # basename for files
+           'dbname|d=s'     => \$dbname,    # Database name
            'verbose'        => \$verbose,   # Print to stdout
-	   'no-op'          => \$no_op,     # pretend but don't actually inject
-	   'helplist'       => \$helplist   # give help listing
-	   ) or pod2usage( 2 );
-
-pod2usage( -msg => "remove temporary / all data files for an IPP analysis stage", 
-	   -exitval => 2) if defined $helplist;
-
-pod2usage( -msg => "Usage: $0 --camera (name) --stage (stage) --stage_id (stage_id) --mode (mode) [--path_base (path)] [--dbname dbname] [--no-op] [--help]", 
-	   -exitval => 2 ) if scalar @ARGV;
+           'no-op'          => \$no_op,     # pretend but don't actually inject
+           'helplist'       => \$helplist   # give help listing
+           ) or pod2usage( 2 );
+
+pod2usage( -msg => "remove temporary / all data files for an IPP analysis stage",
+           -exitval => 2) if defined $helplist;
+
+pod2usage( -msg => "Usage: $0 --camera (name) --stage (stage) --stage_id (stage_id) --mode (mode) [--path_base (path)] [--dbname dbname] [--no-op] [--help]",
+           -exitval => 2 ) if scalar @ARGV;
 
 pod2usage( -msg => "Required options:--camera (name) --stage (stage) --mode (mode)",
-	   -exitval => 3) unless 
+           -exitval => 3) unless
     defined $camera and
     defined $stage and
     defined $mode;
+
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die("Unable to set up", $stage_id, $PS_EXIT_CONFIG_ERROR); # this is used for PATH, NEB filename conversions
 
 # $mode must be one of "goto_cleaned", "goto_scrubbed", or
@@ -50,7 +50,6 @@
 # to be cleaned; they cannot be recovered, but the small data is left
 # behind). XXX make 'scrubbed' a data_state?
-
 unless (($mode eq "goto_cleaned") || ($mode eq "goto_scrubbed") || ($mode eq "goto_purged")) {
-    die "invalid cleanup mode $mode\n";    
+    die "invalid cleanup mode $mode\n";
 }
 
@@ -66,11 +65,9 @@
 }
 
-$ipprc->define_camera($camera);
-
 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
 
 # choice of files to delete depends on the stage
 if ($stage eq "chip") {
-    
+
     die "--stage_id required for stage chip\n" if !$stage_id;
     ### select the imfiles for this entry
@@ -98,10 +95,10 @@
     # loop over all of the imfiles, determine the path_base and class_id for each
     foreach my $imfile (@$imfiles) {
-	my $class_id = $imfile->{class_id};
-	my $path_base = $imfile->{path_base};
+        my $class_id = $imfile->{class_id};
+        my $path_base = $imfile->{path_base};
         my $status = 1;
 
         # don't clean up unless the data needed to update is available
-	# modes goto_purged and goto_scrubbed will remove files even if the config is non-existent
+        # modes goto_purged and goto_scrubbed will remove files even if the config is non-existent
         if ($mode eq "goto_cleaned") {
             my $config_file = $ipprc->filename("PPIMAGE.CONFIG", $path_base, $class_id);
@@ -136,41 +133,42 @@
                 addFilename (\@files, "PPIMAGE.CONFIG", $path_base, $class_id);
             }
-	
+
             # actual command to delete the files
             $status = &delete_files (\@files);
         }
 
-	if ($status)  {
-	    my $command = "$chiptool -chip_id $stage_id -class_id $class_id";
+        if ($status)  {
+            my $command = "$chiptool -chip_id $stage_id -class_id $class_id";
             if ($mode eq "goto_purged") {
                 $command .= " -topurgedimfile";
             } elsif ($mode eq "goto_scrubbed") {
                 $command .= " -tocleanedimfile_from_scrubbed";
-	    } else {
+            } else {
                 $command .= " -tocleanedimfile";
             }
-	    $command .= " -dbname $dbname" if defined $dbname;
-
-	    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            $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: $error_code", "chip", $stage_id, $error_code);
-	    }
+            unless ($success) {
+                $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+                &my_die("Unable to perform chiptool: $error_code", "chip", $stage_id, $error_code);
+            }
         } else {
-	    # if an error happens for a chip, the chipRun will stay in goto_*, but the chips will go to error_* (matching the goto_*)
+
+	    # if an error happens for one chip, the chipRun will stay in goto_*, but the chips will go to error_* (matching the goto_*)
 	    my $command = "$chiptool -updateprocessedimfile -chip_id $stage_id -class_id $class_id -set_state $error_state";
 	    $command .= " -dbname $dbname" if defined $dbname;
 
-	    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            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: $error_code", "chip", $stage_id, $error_code);
-	    }
-	}
+            unless ($success) {
+                $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+                &my_die("Unable to perform chiptool: $error_code", "chip", $stage_id, $error_code);
+            }
+        }
     }
     exit 0;
-} 
+}
 
 if ($stage eq "camera") {
@@ -258,5 +256,5 @@
     }
     exit 0;
-} 
+}
 
 if ($stage eq "warp") {
@@ -319,6 +317,6 @@
         }
 
-	if ($status)  {
-	    my $command = "$warptool -warp_id $stage_id -skycell_id $skycell_id";
+        if ($status)  {
+            my $command = "$warptool -warp_id $stage_id -skycell_id $skycell_id";
             if ($mode eq "goto_purged") {
                 $command .= " -topurgedskyfile";
@@ -326,12 +324,12 @@
                 $command .= " -tocleanedskyfile";
             }
-	    $command .= " -dbname $dbname" if defined $dbname;
-
-	    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            $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 warptool: $error_code", "warp", $stage_id, $error_code);
-	    }
+            unless ($success) {
+                $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+                &my_die("Unable to perform warptool: $error_code", "warp", $stage_id, $error_code);
+            }
          } else {
 	    my $command = "$warptool -updateskyfile -warp_id $stage_id -skycell_id $skycell_id -set_state $error_state";
@@ -340,10 +338,10 @@
             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 warptool: $error_code", "warp", $stage_id, $error_code);
-	    }
+            unless ($success) {
+                $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+                &my_die("Unable to perform warptool: $error_code", "warp", $stage_id, $error_code);
+            }
             exit $PS_EXIT_UNKNOWN_ERROR;
-	}
+        }
     }
     exit 0;
@@ -357,11 +355,11 @@
 die "ipp_cleanup.pl -stage $stage not yet implemented\n";
 
-sub delete_files 
+sub delete_files
 {
     my $files = shift; # reference to a list of files to unlink
-    
-    # this script is, of course, very dangerous.  
+
+    # this script is, of course, very dangerous.
     foreach my $file (@$files) {
-	print STDERR "unlinking $file\n";
+        print STDERR "unlinking $file\n";
         $ipprc->file_delete($file);
     }
@@ -369,5 +367,5 @@
 }
 
-sub addFilename 
+sub addFilename
 {
     my $files      = shift; # reference to a list of files to unlink
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/ipp_maskscript.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/ipp_maskscript.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/ipp_maskscript.pl	(revision 23225)
@@ -12,22 +12,19 @@
 use PS::IPP::Config 1.01 qw( :standard );
 
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
-
 my ($dbname, $det_id, $camera);
-
 GetOptions('dbname=s'    => \$dbname,
-	   'det_id=s'    => \$det_id,
-	   'camera|c=s'  => \$camera,
-	   ) or pod2usage( 2 );
+           'det_id=s'    => \$det_id,
+           'camera|c=s'  => \$camera,
+           ) or pod2usage( 2 );
 
 pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
 
 pod2usage(
-	  -msg => "USAGE: ipp_maskscript.pl --dbname (name) --det_id (id) --iter (iteration) --camera (name)",
-	  -exitval => 3,
-	  ) unless defined $dbname and defined $det_id and defined $camera;
+          -msg => "USAGE: ipp_maskscript.pl --dbname (name) --det_id (id) --iter (iteration) --camera (name)",
+          -exitval => 3,
+          ) unless defined $dbname and defined $det_id and defined $camera;
 
 # I could determine the camera from a query for the detrun
-$ipprc->define_camera($camera);
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die("Unable to setup", $PS_EXIT_CONFIG_ERROR); # IPP configuration
 
 ###  Get list of dark imfile results
@@ -47,5 +44,5 @@
 
 # parse the output into a list
-my $mdcParser = PS::IPP::Metadata::Config->new;	# Parser for metadata config files
+my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
 my $metadata = $mdcParser->parse(join "", @$stdout_buf) or
     &my_die("Unable to parse metadata config doc", $PS_EXIT_PROG_ERROR);
@@ -81,5 +78,5 @@
     # print STDERR "contents: @contents\n";
 
-    my $parser = PS::IPP::Metadata::Config->new;	# Parser for metadata config files
+    my $parser = PS::IPP::Metadata::Config->new;        # Parser for metadata config files
     my $statsList = $parser->parse(join "", @contents) or &my_die("Unable to parse metadata for imfile stats", $PS_EXIT_SYS_ERROR);
 
@@ -110,5 +107,5 @@
     open (DATA, ">$component.dat");
     for (my $i = 0; $i < @{$nameX}; $i++) {
-	print DATA "${$nameX}[$i] ${$nameY}[$i]\n";
+        print DATA "${$nameX}[$i] ${$nameY}[$i]\n";
     }
     close (DATA);
@@ -147,10 +144,10 @@
     my ($exp_time, $tag, $md) = @_;
 
-    # descend through the fpa        
+    # descend through the fpa
     foreach my $entry (@$md) {
-	# print STDERR "name: $entry->{name}, class: $entry->{class}\n";
+        # print STDERR "name: $entry->{name}, class: $entry->{class}\n";
         # recurse on nested metadata
         if ($entry->{class} eq 'metadata') {
-	    my $newtag = $tag . "_" . $entry->{name};
+            my $newtag = $tag . "_" . $entry->{name};
             &parse_stats_table ($exp_time, $newtag, $entry->{value});
         }
@@ -161,15 +158,15 @@
                 push @bg_stdev_data, $entry->{value};
             } else {
-		push @bg_name,    $tag;
+                push @bg_name,    $tag;
                 push @bg_data,    $entry->{value};
-		push @bg_exptime, $exp_time;
-		# print STDERR "$tag $exp_time $entry->{value}\n";
+                push @bg_exptime, $exp_time;
+                # print STDERR "$tag $exp_time $entry->{value}\n";
             }
-	    if (!$componentsHash{$tag}) {
-		push @components, $tag;
-		$componentsHash{$tag} = 1;
-	    }
-	    next;
-	} 
+            if (!$componentsHash{$tag}) {
+                push @components, $tag;
+                $componentsHash{$tag} = 1;
+            }
+            next;
+        }
     }
     return 1;
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_definerun.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_definerun.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_definerun.pl	(revision 23225)
@@ -25,12 +25,19 @@
 use PS::IPP::Config 1.01 qw( :standard );
 
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
-
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
 use Pod::Usage qw( pod2usage );
 
+# Look for programs we need
+my $missing_tools;
+my $magictool = can_run('magictool') or (warn "Can't find magictool" and $missing_tools = 1);
+my $difftool  = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1);
+my $warptool  = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1);
+if ($missing_tools) {
+    warn("Can't find required tools.");
+    exit($PS_EXIT_CONFIG_ERROR);
+}
+
 # Parse the command-line arguments
 my ($exp_id, $warp_id, $min_diff_id, $label, $workdir, $dbname, $save_temps, $verbose);
-
 GetOptions(
            'exp_id=s'        => \$exp_id,     # exposure identifier
@@ -50,15 +57,5 @@
     defined $warp_id;
 
-# $ipprc->define_camera($camera);
-
-# Look for programs we need
-my $missing_tools;
-my $magictool = can_run('magictool') or (warn "Can't find magictool" and $missing_tools = 1);
-my $difftool  = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1);
-my $warptool  = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1);
-if ($missing_tools) {
-    warn("Can't find required tools.");
-    exit($PS_EXIT_CONFIG_ERROR);
-}
+my $ipprc = PS::IPP::Config->new() or my_die("Unable to set up", $PS_EXIT_CONFIG_ERROR); # IPP configuration
 
 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_destreak.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_destreak.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_destreak.pl	(revision 23225)
@@ -21,6 +21,4 @@
 
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -76,8 +74,6 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $magic_ds_id, $component, $PS_EXIT_UNKNOWN_ERROR ); };
-
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $magic_ds_id, $component, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+$ipprc->redirect_output($logfile) or my_die( "Unable to redirect output", $magic_ds_id, $component, $PS_EXIT_SYS_ERROR ) if $logfile;
 
 my ($skycell_args, $class_id, $skycell_id);
@@ -94,9 +90,4 @@
     &my_die("Invalid value for stage: $stage", $magic_ds_id, $component, $PS_EXIT_CONFIG_ERROR);
 }
-
-$ipprc->redirect_output($logfile) if $logfile;
-
-$ipprc->define_camera($camera);
-
 
 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_mask.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_mask.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_mask.pl	(revision 23225)
@@ -22,6 +22,4 @@
 
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -58,11 +56,6 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $magic_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
-
-$ipprc->redirect_output($logfile) if $logfile;
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $magic_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+$ipprc->redirect_output($logfile) or my_die( "Unable to redirect output", $magic_id, $PS_EXIT_SYS_ERROR ) if $logfile;
 
 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_process.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_process.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_process.pl	(revision 23225)
@@ -23,6 +23,4 @@
 
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -62,9 +60,6 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $magic_id, $node, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $magic_id, $node, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+$ipprc->redirect_output($logfile) or my_die( "Unable to redirect output", $magic_id, $node, $PS_EXIT_SYS_ERROR ) if $logfile;
 
 # RemoveStreaks doesn't know about nebulous. It expects to be able to append strings to outroot
@@ -73,12 +68,9 @@
 # of the file names as arguments
 if ($outroot =~ 'neb:/') {
-    &my_die("RemoveStreaks does not support nebulous paths in outroot", $magic_id, $node,
-        $PS_EXIT_CONFIG_ERROR);
+    &my_die("RemoveStreaks does not support nebulous paths in outroot", $magic_id, $node, $PS_EXIT_CONFIG_ERROR);
 }
 
 # resolve any path:// or file:// in outroot
 $outroot = $ipprc->file_resolve($outroot);
-
-$ipprc->redirect_output($logfile) if $logfile;
 
 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_tree.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_tree.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/magic_tree.pl	(revision 23225)
@@ -24,6 +24,4 @@
 use File::Temp qw( tempfile );
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -70,11 +68,6 @@
     defined $outroot;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $magic_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
-
-$ipprc->redirect_output($logfile) if $logfile;
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $magic_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+$ipprc->redirect_output($logfile) or my_die( "Unable to redirect output", $magic_id, $PS_EXIT_SYS_ERROR ) if $logfile;
 
 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/register_exp.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/register_exp.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/register_exp.pl	(revision 23225)
@@ -24,6 +24,4 @@
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
 use Pod::Usage qw( pod2usage );
-
-my $ipprc = PS::IPP::Config->new();
 
 # Look for commands we need
@@ -53,9 +51,6 @@
 ) or pod2usage( 2 );
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $exp_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->redirect_output($logfile) if $logfile;
+my $ipprc = PS::IPP::Config->new() or my_die( "Unable to set up", $exp_id, $PS_EXIT_CONFIG_ERROR );
+$ipprc->redirect_output($logfile) or my_die( "Unable to redirect output", $exp_id, $PS_EXIT_SYS_ERROR ) if $logfile;
 
 pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/register_imfile.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/register_imfile.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/register_imfile.pl	(revision 23225)
@@ -23,5 +23,4 @@
 use Math::Trig;
 
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 use File::Spec;
 
@@ -49,9 +48,6 @@
 ) or pod2usage( 2 );
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $exp_id, $tmp_exp_name, $tmp_class_id, $uri, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->redirect_output($logfile) if $logfile;
+my $ipprc = PS::IPP::Config->new() or my_die( "Unable to set up", $exp_id, $tmp_exp_name, $tmp_class_id, $uri, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+$ipprc->redirect_output($logfile) or my_die( "Unable to redirect output", $exp_id, $tmp_exp_name, $tmp_class_id, $uri, $PS_EXIT_SYS_ERROR ) if $logfile;
 
 pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/stack_skycell.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/stack_skycell.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/stack_skycell.pl	(revision 23225)
@@ -24,6 +24,4 @@
 use File::Basename;
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
@@ -66,7 +64,5 @@
     and defined $run_state;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $stack_id, $PS_EXIT_UNKNOWN_ERROR ); };
+my $ipprc = PS::IPP::Config->new() or my_die( "Unable to set up", $stack_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
 
 # XXX camera is not known here; cannot use filerules...
@@ -81,5 +77,5 @@
 }
 
-$ipprc->redirect_output($logDest) if $redirect;
+$ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $stack_id, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 my $temp_images_exist = 0;
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/warp_overlap.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/warp_overlap.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/warp_overlap.pl	(revision 23225)
@@ -23,6 +23,4 @@
 use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
 use Pod::Usage qw( pod2usage );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 # Look for programs we need
@@ -49,6 +47,4 @@
 ) or pod2usage( 2 );
 
-$ipprc->redirect_output($logfile) if $logfile;
-
 pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
 pod2usage(
@@ -59,9 +55,6 @@
     and defined $tess_dir;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $warp_id, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $warp_id, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+$ipprc->redirect_output($logfile) or my_die( "Unable to redirect output", $warp_id, $PS_EXIT_SYS_ERROR ) if $logfile;
 
 &my_die("Tessellation identifier not provided: $tess_dir", $warp_id, $PS_EXIT_SYS_ERROR) unless $tess_dir ne "NULL";
Index: /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/warp_skycell.pl
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/warp_skycell.pl	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippScripts/scripts/warp_skycell.pl	(revision 23225)
@@ -24,6 +24,4 @@
 use PS::IPP::Metadata::List qw( parse_md_list );
 use PS::IPP::Config 1.01 qw( :standard );
-
-my $ipprc = PS::IPP::Config->new(); # IPP configuration
 
 # Look for programs we need
@@ -68,14 +66,10 @@
     and defined $run_state;
 
-# Unhandled exceptions should be passed on to my_die so they get pushed into the database
-$SIG{__DIE__} = sub { die @_ if $^S;
-                      my_die( $_[0], $warp_id, $skycell_id, $tess_dir, $PS_EXIT_UNKNOWN_ERROR ); };
-
-$ipprc->define_camera($camera);
-
-my $logDest = $ipprc->filename("LOG.EXP", $outroot, $skycell_id);
+my $ipprc = PS::IPP::Config->new( $camera ) or my_die( "Unable to set up", $warp_id, $skycell_id, $tess_dir, $PS_EXIT_CONFIG_ERROR ); # IPP configuration
+
+my $logDest = $ipprc->filename("LOG.EXP", $outroot, $skycell_id) or my_die( "Unable to get log filename", $warp_id, $skycell_id, $tess_dir, $PS_EXIT_SYS_ERROR );
 $logDest .= ".update" if ($run_state eq 'update');
 
-$ipprc->redirect_output($logDest) if $redirect;
+$ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $warp_id, $skycell_id, $tess_dir, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 my $source_id = $ipprc->source_id($dbname, $PS_TABLE_ID_WARP);
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20080925.config
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20080925.config	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20080925.config	(revision 23225)
@@ -189,5 +189,5 @@
         FPA.RA          STR     RA
         FPA.DEC         STR     DEC
-        FPA.RADECSYS    STR     RADECSYS
+        FPA.RADECSYS    STR     EQUINOX
         FPA.OBSTYPE     STR     OBSTYPE
         FPA.OBJECT      STR     OBJECT
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20080929.config
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20080929.config	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20080929.config	(revision 23225)
@@ -184,5 +184,5 @@
         FPA.RA          STR     RA
         FPA.DEC         STR     DEC
-        FPA.RADECSYS    STR     RADECSYS
+        FPA.RADECSYS    STR     EQUINOX
         FPA.OBSTYPE     STR     OBSTYPE
         FPA.OBJECT      STR     OBJECT
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20081011.config
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20081011.config	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20081011.config	(revision 23225)
@@ -174,5 +174,5 @@
         FPA.RA          STR     RA
         FPA.DEC         STR     DEC
-        FPA.RADECSYS    STR     RADECSYS
+        FPA.RADECSYS    STR     EQUINOX
         FPA.OBSTYPE     STR     OBSTYPE
         FPA.OBJECT      STR     OBJECT
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20090120.config
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20090120.config	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20090120.config	(revision 23225)
@@ -173,5 +173,5 @@
         FPA.RA          STR     RA
         FPA.DEC         STR     DEC
-        FPA.RADECSYS    STR     RADECSYS
+        FPA.RADECSYS    STR     EQUINOX
         FPA.OBSTYPE     STR     OBSTYPE
         FPA.OBJECT      STR     OBJECT
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20090220.config
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20090220.config	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_20090220.config	(revision 23225)
@@ -173,5 +173,5 @@
         FPA.RA          STR     RA
         FPA.DEC         STR     DEC
-        FPA.RADECSYS    STR     RADECSYS
+        FPA.RADECSYS    STR     EQUINOX
         FPA.OBSTYPE     STR     OBSTYPE
         FPA.OBJECT      STR     OBJECT
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_mef.config
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_mef.config	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_mef.config	(revision 23225)
@@ -168,5 +168,5 @@
         FPA.RA          STR     RA
         FPA.DEC         STR     DEC
-        FPA.RADECSYS    STR     RADECSYS
+        FPA.RADECSYS    STR     EQUINOX
 	FPA.OBSTYPE     STR     OBSTYPE
 	FPA.OBJECT	STR	OBJECT
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_orig.config
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_orig.config	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_orig.config	(revision 23225)
@@ -182,5 +182,5 @@
         # FPA.RA          STR     COMRA
         # FPA.DEC         STR     COMDEC
-        FPA.RADECSYS    STR     RADECSYS
+        FPA.RADECSYS    STR     EQUINOX
         FPA.OBSTYPE     STR     OBSTYPE
         FPA.OBJECT      STR     OBJECT
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_relphot.config
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_relphot.config	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/gpc1/format_relphot.config	(revision 23225)
@@ -105,5 +105,5 @@
         FPA.RA          STR     RA
         FPA.DEC         STR     DEC
-        FPA.RADECSYS    STR     RADECSYS
+        FPA.RADECSYS    STR     EQUINOX
 	FPA.OBSTYPE     STR     OBSTYPE
 	FPA.OBJECT	STR	OBJECT
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/filerules-mef.mdc
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/filerules-mef.mdc	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/filerules-mef.mdc	(revision 23225)
@@ -128,4 +128,5 @@
 PPIMAGE.OUT.WT.SPL      OUTPUT {OUTPUT}.{CHIP.NAME}.wt.fits      VARIANCE  NONE       CHIP       TRUE      SPLIT
 PPIMAGE.OUTPUT.DETMASK  OUTPUT {OUTPUT}.fits                     IMAGE     MASK       CHIP       TRUE      MEF
+PPIMAGE.OUTPUT.DETREND  OUTPUT {OUTPUT}.fits                     IMAGE     COMP_DET   CHIP       TRUE      MEF
 PPIMAGE.OUTPUT.RESID    OUTPUT {OUTPUT}.b0.fits                  IMAGE     COMP_SUB   CHIP       TRUE      MEF
 PPIMAGE.CONFIG          OUTPUT {OUTPUT}.{CHIP.NAME}.ppImage.mdc  TEXT      NONE       CHIP       TRUE      NONE
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/filerules-simple.mdc
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/filerules-simple.mdc	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/filerules-simple.mdc	(revision 23225)
@@ -91,4 +91,5 @@
 PPIMAGE.OUTPUT.VARIANCE OUTPUT {OUTPUT}.wt.fits      VARIANCE  NONE       FPA        TRUE      SIMPLE
 PPIMAGE.OUTPUT.DETMASK  OUTPUT {OUTPUT}.fits         IMAGE     NONE       FPA        TRUE      SIMPLE
+PPIMAGE.OUTPUT.DETREND  OUTPUT {OUTPUT}.fits         IMAGE     NONE       FPA        TRUE      SIMPLE
 PPIMAGE.OUTPUT.RESID    OUTPUT {OUTPUT}.fits         IMAGE     NONE       FPA        TRUE      SIMPLE
 PPIMAGE.CONFIG          OUTPUT {OUTPUT}.ppImage.mdc  TEXT      NONE       FPA        TRUE      NONE
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/filerules-split.mdc
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/filerules-split.mdc	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/filerules-split.mdc	(revision 23225)
@@ -100,11 +100,7 @@
 PPIMAGE.OUTPUT.VARIANCE OUTPUT {OUTPUT}.{CHIP.NAME}.wt.fits      VARIANCE  COMP_WT    CHIP       TRUE      NONE
 PPIMAGE.OUTPUT.DETMASK  OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE     DET_MASK   CHIP       TRUE      NONE
+PPIMAGE.OUTPUT.DETREND  OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE     COMP_DET   CHIP       TRUE      NONE
 PPIMAGE.OUTPUT.RESID    OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE     COMP_SUB   CHIP       TRUE      NONE
 PPIMAGE.CONFIG          OUTPUT {OUTPUT}.{CHIP.NAME}.ppImage.mdc  TEXT      NONE       CHIP       TRUE      NONE
-
-#PPIMAGE.OUTPUT          OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE     NONE  CHIP       TRUE      NONE
-#PPIMAGE.OUTPUT.MASK     OUTPUT {OUTPUT}.{CHIP.NAME}.mk.fits      MASK      NONE  CHIP       TRUE      NONE
-#PPIMAGE.OUTPUT.VARIANCE OUTPUT {OUTPUT}.{CHIP.NAME}.wt.fits      VARIANCE  NONE  CHIP       TRUE      NONE
-#PPIMAGE.OUTPUT.DETMASK  OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE     NONE  CHIP       TRUE      NONE
 	        									        
 PPIMAGE.CHIP            OUTPUT {OUTPUT}.{CHIP.NAME}.ch.fits      IMAGE     COMP_IMG   CHIP       TRUE      NONE
@@ -124,7 +120,7 @@
 		        									        
 PPIMAGE.STATS           OUTPUT {OUTPUT}.{CHIP.NAME}.stats        STATS     NONE       CHIP       TRUE      NONE
-		        									        
+
 ## note: these use the  same output naming convention since they are used for different ppMerge runs
-PPMERGE.OUTPUT.MASK     OUTPUT {OUTPUT}.{CHIP.NAME}.fits         MASK      NONE       CHIP       TRUE      NONE
+PPMERGE.OUTPUT.MASK     OUTPUT {OUTPUT}.{CHIP.NAME}.fits         MASK      DET_MASK   CHIP       TRUE      NONE
 PPMERGE.OUTPUT.BIAS     OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE     NONE       CHIP       TRUE      NONE
 PPMERGE.OUTPUT.DARK     OUTPUT {OUTPUT}.{CHIP.NAME}.fits         DARK      NONE       CHIP       TRUE      NONE
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/fitstypes.mdc
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/fitstypes.mdc	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/fitstypes.mdc	(revision 23225)
@@ -19,4 +19,17 @@
 # STDEV.NUM(F32) is the number of standard deviations to the edge (when SCALING = STDEV_NEGATIVE|STDEV_POSITIVE)
 # FLOAT(STR) is the name of a custom floating-point type
+
+# Compressed detrend
+COMP_FLAT	METADATA
+	BITPIX		S32	16
+	SCALING		STR	MANUAL
+	BSCALE		F32	1.0
+	BZERO		F32	32768.0
+	COMPRESSION	STR	RICE
+	TILE.X		S32	0
+	TILE.Y		S32	1
+	TILE.Z		S32	1
+	NOISE		S32	8
+END
 
 DET_IMAGE	METADATA
Index: /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/ppStack.config
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/ppStack.config	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ippconfig/recipes/ppStack.config	(revision 23225)
@@ -32,12 +32,16 @@
 
 ZP.RADIUS	F32	1.0		# Radius (pixels) for matching sources
-ZP.ITER		S32	1000		# Maximum iterations for zero point
+ZP.ITER.1	S32	5		# Iterations for zero point; pass 1
+ZP.ITER.2	S32	1000		# Iterations for zero point; pass 2
 ZP.TOL		F32	1.0e-6		# Tolerance for zero point iterations
 ZP.TRANS.ITER	S32	2		# Iterations for transparency determination
 ZP.TRANS.REJ	F32	3.0		# Rejection threshold for transparency determination
 ZP.TRANS.THRESH	F32	1.0		# Threshold for transparency determination
-ZP.STAR.REJ	F32	3.0		# Rejection threshold for stars
+ZP.STAR.REJ.1	F32	20.0		# Rejection threshold for stars; pass 1
+ZP.STAR.REJ.2	F32	3.0		# Rejection threshold for stars; pass 2
 ZP.STAR.LIMIT	F32	1.0e-2		# Limit on star rejection fraction for successful iteration
-ZP.STAR.SYS	F32	0.05		# Estimated systematic error
+ZP.STAR.SYS.1	F32	0.10		# Estimated systematic error; pass 1
+ZP.STAR.SYS.2	F32	0.05		# Estimated systematic error; pass 2
+ZP.MATCH	F32	0.3		# Fraction of images to match for good star
 ZP.AIRMASS	METADATA		# Airmass terms by filter
 	g	F32	0.0
Index: /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArith.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArith.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArith.c	(revision 23225)
@@ -34,4 +34,6 @@
     }
 
+    ppArithVersionPrint();
+
     if (!ppArithArguments(argc, argv, config)) {
         psErrorStackPrint(stderr, "Error reading arguments.\n");
Index: /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArith.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArith.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArith.h	(revision 23225)
@@ -22,6 +22,6 @@
  * Parse the arguments
  */
-bool ppArithArguments(int argc, char *argv[], ///< Command-line arguments 
-                      pmConfig *config    ///< Configuration 
+bool ppArithArguments(int argc, char *argv[], ///< Command-line arguments
+                      pmConfig *config    ///< Configuration
     );
 
@@ -29,5 +29,5 @@
  * Parse the camera input
  */
-bool ppArithCamera(pmConfig *config       ///< Configuration 
+bool ppArithCamera(pmConfig *config       ///< Configuration
     );
 
@@ -35,5 +35,5 @@
  * Loop over the FPA hierarchy
  */
-bool ppArithLoop(pmConfig *config         ///< Configuration 
+bool ppArithLoop(pmConfig *config         ///< Configuration
     );
 
@@ -41,16 +41,19 @@
  * Perform arithmetic on the readout
  */
-bool ppArithReadout(pmReadout *output,  ///< Output readout 
-                    const pmReadout *input1, ///< Input readout 
-                    const pmReadout *input2, ///< Input readout 
-                    const pmConfig *config, ///< Configuration 
-                    const pmFPAview *view ///< View of readout on which to operate 
+bool ppArithReadout(pmReadout *output,  ///< Output readout
+                    const pmReadout *input1, ///< Input readout
+                    const pmReadout *input2, ///< Input readout
+                    const pmConfig *config, ///< Configuration
+                    const pmFPAview *view ///< View of readout on which to operate
     );
 
 /**
- * Put the program version information into a metadata
+ * Put the program version information into header
  */
-void ppArithVersionMetadata(psMetadata *metadata ///< Metadata to populate
+bool ppArithVersionHeader(psMetadata *header ///< Header to populate
     );
+
+/// Print version information
+void ppArithVersionPrint(void);
 
 ///@}
Index: /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArithLoop.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArithLoop.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArithLoop.c	(revision 23225)
@@ -113,5 +113,5 @@
                     hdu->header = psMetadataAlloc();
                 }
-                ppArithVersionMetadata(hdu->header);
+                ppArithVersionHeader(hdu->header);
                 lastHDU = hdu;
             }
Index: /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArithVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArithVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppArith/src/ppArithVersion.c	(revision 23225)
@@ -65,7 +65,42 @@
 };
 
-void ppArithVersionMetadata(psMetadata *metadata)
+bool ppArithVersionHeader(psMetadata *header)
 {
-    PS_ASSERT_METADATA_NON_NULL(metadata,);
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "ppArith at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    ppStatsVersionHeader(header);
+
+    psString version = ppArithVersion(); // Software version
+    psString source  = ppArithSource();  // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPARITH.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPARITH.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
+
+void ppArithVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("ppArith", PS_LOG_INFO, "ppArith at %s", timeString);
+    psFree(timeString);
 
     psString pslib = psLibVersionLong();// psLib version
@@ -74,18 +109,9 @@
     psString ppArith = ppArithVersionLong(); // ppArith version
 
-    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
-    psString timeString = psTimeToISO(time); // The time in an ISO string
-    psFree(time);
-    psString head = NULL;               // Head string
-    psStringAppend(&head, "ppArith processing at %s. Component information:", timeString);
-    psFree(timeString);
+    psLogMsg("ppArith", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("ppArith", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("ppArith", PS_LOG_INFO, "%s", ppStats);
+    psLogMsg("ppArith", PS_LOG_INFO, "%s", ppArith);
 
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, head, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, pslib, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, psmodules, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppStats, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppArith, "");
-
-    psFree(head);
     psFree(pslib);
     psFree(psmodules);
Index: /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImage.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImage.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImage.c	(revision 23225)
@@ -21,4 +21,6 @@
         exit(PS_EXIT_CONFIG_ERROR);
     }
+
+    ppImageVersionPrint();
 
     // define recipe options
Index: /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImage.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImage.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImage.h	(revision 23225)
@@ -216,7 +216,10 @@
 psString ppImageVersionLong(void);
 
-/// Update the metadata with version information for all dependencies
-void ppImageVersionMetadata(psMetadata *metadata ///< Metadata to update with version information
-    );
+/// Populate the header with version information for all dependencies
+bool ppImageVersionHeader(psMetadata *metadata ///< Header to populate
+    );
+
+/// Print version information
+void ppImageVersionPrint(void);
 
 
Index: /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImageLoop.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImageLoop.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImageLoop.c	(revision 23225)
@@ -63,7 +63,7 @@
 
             // Put version information into the header
-            pmHDU *hdu = pmHDUFromCell(cell);
+            pmHDU *hdu = pmHDUGetHighest(input->fpa, chip, cell);
             if (hdu && hdu != lastHDU) {
-                ppImageVersionMetadata(hdu->header);
+                ppImageVersionHeader(hdu->header);
                 lastHDU = hdu;
             }
Index: /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImageVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImageVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppImage/src/ppImageVersion.c	(revision 23225)
@@ -48,7 +48,45 @@
 };
 
-void ppImageVersionMetadata(psMetadata *metadata)
+bool ppImageVersionHeader(psMetadata *header)
 {
-    PS_ASSERT_METADATA_NON_NULL(metadata,);
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "ppImage at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    psphotVersionHeader(header);
+    psastroVersionHeader(header);
+    ppStatsVersionHeader(header);
+
+    psString version = ppImageVersion(); // ppImage software version
+    psString source  = ppImageSource();  // ppImage software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPIMAGE.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPIMAGE.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
+
+
+void ppImageVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("ppImage", PS_LOG_INFO, "ppImage at %s", timeString);
+    psFree(timeString);
 
     psString pslib = psLibVersionLong();// psLib version
@@ -59,20 +97,11 @@
     psString ppImage = ppImageVersionLong(); // ppImage version
 
-    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
-    psString timeString = psTimeToISO(time); // The time in an ISO string
-    psFree(time);
-    psString head = NULL;               // Head string
-    psStringAppend(&head, "ppImage processing at %s. Component information:", timeString);
-    psFree(timeString);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", psphot);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", psastro);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", ppStats);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", ppImage);
 
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, head, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, pslib, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, psmodules, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, psphot, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, psastro, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppStats, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppImage, "");
-
-    psFree(head);
     psFree(pslib);
     psFree(psmodules);
Index: /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMerge.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMerge.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMerge.c	(revision 23225)
@@ -38,4 +38,6 @@
         goto die;
     }
+
+    ppMergeVersionPrint();
 
     ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); ///< Type of frame
Index: /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMerge.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMerge.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMerge.h	(revision 23225)
@@ -28,7 +28,7 @@
 /// @{
 
-#define TIMERNAME "ppMerge"             ///< Name for timer 
-#define PPMERGE_RECIPE "PPMERGE"        ///< Recipe name 
-#define THREADED 1                      ///< Compile with threads? 
+#define TIMERNAME "ppMerge"             ///< Name for timer
+#define PPMERGE_RECIPE "PPMERGE"        ///< Recipe name
+#define THREADED 1                      ///< Compile with threads?
 
 /**
@@ -36,11 +36,11 @@
  */
 typedef enum {
-    PPMERGE_TYPE_UNKNOWN,               ///< Unknown type 
-    PPMERGE_TYPE_BIAS,                  ///< Bias frame 
-    PPMERGE_TYPE_DARK,                  ///< (Multi-)Dark frame 
-    PPMERGE_TYPE_MASK,                  ///< Mask frame 
-    PPMERGE_TYPE_SHUTTER,               ///< Shutter frame 
+    PPMERGE_TYPE_UNKNOWN,               ///< Unknown type
+    PPMERGE_TYPE_BIAS,                  ///< Bias frame
+    PPMERGE_TYPE_DARK,                  ///< (Multi-)Dark frame
+    PPMERGE_TYPE_MASK,                  ///< Mask frame
+    PPMERGE_TYPE_SHUTTER,               ///< Shutter frame
     PPMERGE_TYPE_FLAT,                  ///< Flat-field frame (dome or sky)
-    PPMERGE_TYPE_FRINGE,                ///< Fringe frame 
+    PPMERGE_TYPE_FRINGE,                ///< Fringe frame
 } ppMergeType;
 
@@ -49,7 +49,7 @@
  */
 typedef enum {
-    PPMERGE_FILES_ALL,                  ///< All files 
-    PPMERGE_FILES_INPUT,                ///< Input files 
-    PPMERGE_FILES_OUTPUT                ///< Output files 
+    PPMERGE_FILES_ALL,                  ///< All files
+    PPMERGE_FILES_INPUT,                ///< Input files
+    PPMERGE_FILES_OUTPUT                ///< Output files
 } ppMergeFiles;
 
@@ -60,9 +60,9 @@
  */
 typedef struct {
-    psArray *readouts;                  ///< Input readouts 
-    bool read;                          ///< Has the scan been read? 
-    bool busy;                          ///< Is the scan being processed? 
-    int firstScan;                      ///< First row of the chunk to be read for this group 
-    int lastScan;                       ///< Last row of the chunk to be read for this group 
+    psArray *readouts;                  ///< Input readouts
+    bool read;                          ///< Has the scan been read?
+    bool busy;                          ///< Is the scan being processed?
+    int firstScan;                      ///< First row of the chunk to be read for this group
+    int lastScan;                       ///< Last row of the chunk to be read for this group
 } ppMergeFileGroup;
 
@@ -71,5 +71,5 @@
  */
 bool ppMergeArguments(int argc, char *argv[], ///< Command-line arguments
-                      pmConfig *config  ///< Configuration 
+                      pmConfig *config  ///< Configuration
     );
 
@@ -77,5 +77,5 @@
  * Set up camera files
  */
-bool ppMergeCamera(pmConfig *config     ///< Configuration 
+bool ppMergeCamera(pmConfig *config     ///< Configuration
     );
 
@@ -83,5 +83,5 @@
  * Measure scale and zero-points
  */
-bool ppMergeScaleZero(pmConfig *config  ///< Configuration 
+bool ppMergeScaleZero(pmConfig *config  ///< Configuration
     );
 
@@ -89,5 +89,5 @@
  * Main loop to do the merging
  */
-bool ppMergeLoop(pmConfig *config       ///< Configuration 
+bool ppMergeLoop(pmConfig *config       ///< Configuration
     );
 
@@ -95,5 +95,5 @@
  * Main loop for masks
  */
-bool ppMergeMask(pmConfig *config       ///< Configuration 
+bool ppMergeMask(pmConfig *config       ///< Configuration
     );
 
@@ -101,8 +101,8 @@
  * Read nominated input file
  */
-bool ppMergeFileReadInput(pmConfig *config, ///< Configuration 
-                          pmReadout *readout, ///< Readout into which to read 
-                          int num,      ///< Number of file in sequence 
-                          int rows      ///< Number of rows to read at once 
+bool ppMergeFileReadInput(pmConfig *config, ///< Configuration
+                          pmReadout *readout, ///< Readout into which to read
+                          int num,      ///< Number of file in sequence
+                          int rows      ///< Number of rows to read at once
     );
 
@@ -110,7 +110,7 @@
  * Open nominated input file
  */
-bool ppMergeFileOpenInput(pmConfig *config, ///< Configuration 
-                          const pmFPAview *view, ///< View to open 
-                          int num       ///< Number of file in sequence 
+bool ppMergeFileOpenInput(pmConfig *config, ///< Configuration
+                          const pmFPAview *view, ///< View to open
+                          int num       ///< Number of file in sequence
     );
 
@@ -166,4 +166,23 @@
 bool ppMergeSetThreads(void);
 
+
+/// Return software version
+psString ppMergeVersion(void);
+
+/// Return software source
+psString ppMergeSource(void);
+
+/// Return detailed software version information
+psString ppMergeVersionLong(void);
+
+/// Populate a FITS header with version information
+bool ppMergeVersionHeader(
+    psMetadata *header                  ///< Header to populate
+    );
+
+/// Print version information
+void ppMergeVersionPrint(void);
+
+
 ///@}
 #endif
Index: /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMergeLoop_Threaded.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMergeLoop_Threaded.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMergeLoop_Threaded.c	(revision 23225)
@@ -137,4 +137,5 @@
     assert(output && output->fpa);
     pmFPA *outFPA = output->fpa;        ///< Output FPA
+    pmHDU *lastHDU = NULL;              // Last HDU that was updated
     int cellNum = 0;                    ///< Index of cell
     if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
@@ -156,4 +157,13 @@
                 // No data here
                 continue;
+            }
+
+            // Update the header
+            {
+                pmHDU *hdu = pmHDUGetHighest(outFPA, outChip, outCell); // HDU for file
+                if (hdu && hdu != lastHDU) {
+                    ppMergeVersionHeader(hdu->header);
+                    lastHDU = hdu;
+                }
             }
 
Index: /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMergeMask.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMergeMask.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMergeMask.c	(revision 23225)
@@ -16,4 +16,5 @@
                       const pmFPAview *view, ///< View to chip
                       bool writeOut,     ///< Write output?
+                      pmHDU **lastHDU,   ///< HDU last updated
                       psRandom *rng,    ///< Random number generator
                       psMetadata *stats ///< Statistics output
@@ -96,4 +97,13 @@
                     i, inView->chip, inView->cell);
 
+            // Update the header
+            {
+                pmHDU *hdu = pmHDUGetHighest(outCell->parent->parent, outCell->parent, outCell); // File HDU
+                if (hdu && hdu != *lastHDU) {
+                    ppMergeVersionHeader(hdu->header);
+                    *lastHDU = hdu;
+                }
+            }
+
             if (!pmFPAfileIOChecks(config, inView, PM_FPA_BEFORE)) {
                 psFree(inView);
@@ -395,4 +405,5 @@
     assert(output && output->fpa);
     pmFPA *outFPA = output->fpa;        ///< Output FPA
+    pmHDU *lastHDU = NULL;              // Last HDU updated
 
     if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
@@ -409,5 +420,5 @@
 
         for (int i = 0; i < iter; i++) {
-            if (!mergeMask(config, view, (i == iter - 1), rng, stats)) {
+            if (!mergeMask(config, view, (i == iter - 1), &lastHDU, rng, stats)) {
                 psError(PS_ERR_UNKNOWN, false, "Unable to merge chip %d", view->chip);
                 goto PPMERGE_MASK_ERROR;
Index: /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMergeVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMergeVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppMerge/src/ppMergeVersion.c	(revision 23225)
@@ -65,27 +65,53 @@
 };
 
-void ppMergeVersionMetadata(psMetadata *metadata)
+bool ppMergeVersionHeader(psMetadata *header)
 {
-    PS_ASSERT_METADATA_NON_NULL(metadata,);
+    PS_ASSERT_METADATA_NON_NULL(header, false);
 
-    psString pslib = psLibVersionLong();///< psLib version
-    psString psmodules = psModulesVersionLong(); ///< psModules version
-    psString ppStats = ppStatsVersionLong(); ///< ppStats version
-    psString ppMerge = ppMergeVersionLong(); ///< ppMerge version
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "ppMerge at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
 
-    psTime *time = psTimeGetNow(PS_TIME_TAI); ///< The time now
-    psString timeString = psTimeToISO(time); ///< The time in an ISO string
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    ppStatsVersionHeader(header);
+
+    psString version = ppMergeVersion(); // Software version
+    psString source  = ppMergeSource();  // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPMERGE.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPMERGE.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
+
+void ppMergeVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
     psFree(time);
-    psString head = NULL;               ///< Head string
-    psStringAppend(&head, "ppMerge processing at %s. Component information:", timeString);
+    psLogMsg("ppMerge", PS_LOG_INFO, "ppMerge at %s", timeString);
     psFree(timeString);
 
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, head, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, pslib, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, psmodules, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppStats, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppMerge, "");
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString ppStats = ppStatsVersionLong(); // ppStats version
+    psString ppMerge = ppMergeVersionLong(); // ppMerge version
 
-    psFree(head);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", ppStats);
+    psLogMsg("ppImage", PS_LOG_INFO, "%s", ppMerge);
+
     psFree(pslib);
     psFree(psmodules);
Index: /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStack.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStack.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStack.c	(revision 23225)
@@ -33,4 +33,6 @@
         goto die;
     }
+
+    ppStackVersionPrint();
 
     if (!pmModelClassInit()) {
Index: /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStack.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStack.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStack.h	(revision 23225)
@@ -10,8 +10,9 @@
 // Mask values for inputs
 typedef enum {
-    PPSTACK_MASK_MATCH  = 0x01,         // PSF-matching failed
-    PPSTACK_MASK_CHI2   = 0x02,         // Chi^2 too deviant
-    PPSTACK_MASK_REJECT = 0x04,         // Rejection failed
-    PPSTACK_MASK_BAD    = 0x08,         // Bad image (too many pixels rejected)
+    PPSTACK_MASK_CAL    = 0x01,         // Photometric calibration failed
+    PPSTACK_MASK_MATCH  = 0x02,         // PSF-matching failed
+    PPSTACK_MASK_CHI2   = 0x04,         // Chi^2 too deviant
+    PPSTACK_MASK_REJECT = 0x08,         // Rejection failed
+    PPSTACK_MASK_BAD    = 0x10,         // Bad image (too many pixels rejected)
     PPSTACK_MASK_ALL    = 0xff          // All errors
 } ppStackMask;
@@ -81,5 +82,6 @@
 pmPSF *ppStackPSF(const pmConfig *config, // Configuration
                   int numCols, int numRows, // Size of image
-                  const psArray *psfs   // List of input PSFs
+                  const psArray *psfs,  // List of input PSFs
+                  const psVector *inputMask // Mask for inputs
     );
 
@@ -140,7 +142,10 @@
 psString ppStackVersionLong(void);
 
-// Supplement metadata with software version
-void ppStackVersionMetadata(psMetadata *metadata // Metadata to supplement
+// Supplement header with software version
+bool ppStackVersionHeader(psMetadata *header // Header to supplement
     );
+
+/// Print version information
+void ppStackVersionPrint(void);
 
 /// Convolve image to match specified seeing
@@ -161,4 +166,5 @@
 /// Corrects the source PSF photometry to a common system.  Return the sum of the exposure times.
 float ppStackSourcesTransparency(const psArray *sourceLists, // Sources for each input
+                                 psVector *inputMask, // Indicates bad input
                                  const pmFPAview *view, // View to readout
                                  const pmConfig *config // Configuration
Index: /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackArguments.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackArguments.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackArguments.c	(revision 23225)
@@ -168,12 +168,15 @@
                       "Play safe with small numbers of pixels to combine?", false);
     psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-radius", 0, "Radius (pixels) for matching sources", NAN);
-    psMetadataAddS32(arguments, PS_LIST_TAIL, "-zp-iter", 0, "Maximum iterations for zero point", 0);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-zp-iter-1", 0, "Maximum iterations for zero point; pass 1", 0);
+    psMetadataAddS32(arguments, PS_LIST_TAIL, "-zp-iter-2", 0, "Maximum iterations for zero point; pass 2", 0);
     psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-tol", 0, "Tolerance for zero point iterations", NAN);
     psMetadataAddS32(arguments, PS_LIST_TAIL, "-zp-trans-iter", 0, "Iterations for transparency determination", 0);
     psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-trans-rej", 0, "Rejection threshold for transparency determination", NAN);
     psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-trans-thresh", 0, "Threshold for transparency determination", NAN);
-    psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-star-rej", 0, "Rejection threshold for stars", NAN);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-star-rej-1", 0, "Rejection threshold for stars; pass 1", NAN);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-star-rej-2", 0, "Rejection threshold for stars; pass 2", NAN);
     psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-star-limit", 0, "Limit on star rejection fraction for successful iteration", NAN);
-    psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-star-sys", 0, "Estimated systematic error", NAN);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-star-sys-1", 0, "Estimated systematic error; pass 1", NAN);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp-star-sys-2", 0, "Estimated systematic error; pass 2", NAN);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-temp-image", 0, "Suffix for temporary images", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-temp-mask", 0, "Suffix for temporary masks", NULL);
@@ -242,12 +245,15 @@
 
     VALUE_ARG_RECIPE_FLOAT("-zp-radius",       "ZP.RADIUS",       F32);
-    VALUE_ARG_RECIPE_INT("-zp-iter",           "ZP.ITER",         S32, 0);
+    VALUE_ARG_RECIPE_INT("-zp-iter-1",         "ZP.ITER.1",       S32, 0);
+    VALUE_ARG_RECIPE_INT("-zp-iter-2",         "ZP.ITER.2",       S32, 0);
     VALUE_ARG_RECIPE_FLOAT("-zp-tol",          "ZP.TOL",          F32);
     VALUE_ARG_RECIPE_INT("-zp-trans-iter",     "ZP.TRANS.ITER",   S32, 0);
     VALUE_ARG_RECIPE_FLOAT("-zp-trans-rej",    "ZP.TRANS.REJ",    F32);
     VALUE_ARG_RECIPE_FLOAT("-zp-trans-thresh", "ZP.TRANS.THRESH", F32);
-    VALUE_ARG_RECIPE_FLOAT("-zp-star-rej",     "ZP.STAR.REJ",     F32);
+    VALUE_ARG_RECIPE_FLOAT("-zp-star-rej-1",   "ZP.STAR.REJ.1",   F32);
+    VALUE_ARG_RECIPE_FLOAT("-zp-star-rej-2",   "ZP.STAR.REJ.2",   F32);
     VALUE_ARG_RECIPE_FLOAT("-zp-star-limit",   "ZP.STAR.LIMIT",   F32);
-    VALUE_ARG_RECIPE_FLOAT("-zp-star-sys",     "ZP.STAR.SYS",     F32);
+    VALUE_ARG_RECIPE_FLOAT("-zp-star-sys-1",   "ZP.STAR.SYS.1",   F32);
+    VALUE_ARG_RECIPE_FLOAT("-zp-star-sys-2",   "ZP.STAR.SYS.2",   F32);
 
     VALUE_ARG_RECIPE_INT("-psf-instances", "PSF.INSTANCES", S32, 0);
Index: /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackLoop.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackLoop.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackLoop.c	(revision 23225)
@@ -257,4 +257,6 @@
     pmPSF *targetPSF = NULL;            // Target PSF
     float sumExposure = NAN;            // Sum of exposure times
+    psVector *inputMask = psVectorAlloc(num, PS_TYPE_VECTOR_MASK); // Mask for inputs
+    psVectorInit(inputMask, 0);
     if (psMetadataLookupBool(NULL, config->arguments, "HAVE.PSF")) {
         pmFPAfileActivate(config->files, false, NULL);
@@ -283,4 +285,5 @@
                 psFree(fileIter);
                 psFree(psfs);
+                psFree(inputMask);
                 return false;
             }
@@ -299,4 +302,5 @@
                 psFree(fileIter);
                 psFree(psfs);
+                psFree(inputMask);
                 return false;
             }
@@ -324,5 +328,6 @@
                     psFree(sourceLists);
                     psFree(targetPSF);
-                    return false;
+                    psFree(inputMask);
+                   return false;
                 }
 
@@ -333,4 +338,5 @@
                     psFree(sourceLists);
                     psFree(targetPSF);
+                    psFree(inputMask);
                     return false;
                 }
@@ -340,4 +346,5 @@
                     psFree(sourceLists);
                     psFree(targetPSF);
+                    psFree(inputMask);
                     return false;
                 }
@@ -351,14 +358,15 @@
 
         // Zero point calibration
-        sumExposure = ppStackSourcesTransparency(sourceLists, view, config);
+        sumExposure = ppStackSourcesTransparency(sourceLists, inputMask, view, config);
         if (!isfinite(sumExposure) || sumExposure <= 0) {
             psError(PS_ERR_UNKNOWN, false, "Unable to calculate transparency differences");
             psFree(sourceLists);
             psFree(targetPSF);
+            psFree(inputMask);
             return false;
         }
 
         // Generate target PSF
-        targetPSF = ppStackPSF(config, numCols, numRows, psfs);
+        targetPSF = ppStackPSF(config, numCols, numRows, psfs, inputMask);
         psFree(psfs);
         if (!targetPSF) {
@@ -366,4 +374,5 @@
             psFree(sourceLists);
             psFree(view);
+            psFree(inputMask);
             return false;
         }
@@ -409,6 +418,4 @@
     int numGood = 0;                    // Number of good frames
     int numCols = 0, numRows = 0;       // Size of image
-    psVector *inputMask = psVectorAlloc(num, PS_TYPE_VECTOR_MASK); // Mask for inputs
-    psVectorInit(inputMask, 0);
     psVector *matchChi2 = psVectorAlloc(num, PS_TYPE_F32); // chi^2 for stamps when matching
     psVectorInit(matchChi2, NAN);
@@ -419,4 +426,7 @@
     psArray *covariances = psArrayAlloc(num); // Covariance matrices
     for (int i = 0; i < num; i++) {
+        if (inputMask->data.U8[i]) {
+            continue;
+        }
         psTrace("ppStack", 2, "Convolving input %d of %d to target PSF....\n", i, num);
         pmFPAfileActivate(config->files, false, NULL);
@@ -1213,5 +1223,5 @@
         hdu->header = psMetadataAlloc();
     }
-    ppStackVersionMetadata(hdu->header);
+    ppStackVersionHeader(hdu->header);
 
     psFree(outRO);
Index: /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackPSF.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackPSF.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackPSF.c	(revision 23225)
@@ -9,5 +9,6 @@
 #include "ppStack.h"
 
-pmPSF *ppStackPSF(const pmConfig *config, int numCols, int numRows, const psArray *psfs)
+pmPSF *ppStackPSF(const pmConfig *config, int numCols, int numRows,
+                  const psArray *psfs, const psVector *inputMask)
 {
     // Get the recipe values
@@ -19,4 +20,11 @@
     const char *psfModel = psMetadataLookupStr(NULL, recipe, "PSF.MODEL"); // Model for PSF
     int psfOrder = psMetadataLookupS32(NULL, recipe, "PSF.ORDER"); // Spatial order for PSF
+
+    for (int i = 0; i < psfs->n; i++) {
+        if (inputMask->data.U8[i]) {
+            psFree(psfs->data[i]);
+            psfs->data[i] = NULL;
+        }
+    }
 
     // Solve for the target PSF
Index: /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackSources.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackSources.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackSources.c	(revision 23225)
@@ -13,11 +13,55 @@
 #define FAKE_ROWS 4913
 
-float ppStackSourcesTransparency(const psArray *sourceLists, const pmFPAview *view, const pmConfig *config)
+#ifdef TESTING
+// Dump matches to a file
+static void dumpMatches(const char *filename, // File to which to dump
+                        int num,        // Number of inputs
+                        psArray *matches, // Star matches
+                        psVector *zp,   // Zero points
+                        psVector *trans // Transparencies
+                        )
+{
+    FILE *outMatches = fopen(filename, "w"); // Output matches
+    psVector *mag = psVectorAlloc(num, PS_TYPE_F32); // Magnitudes for each star
+    psVector *magErr = psVectorAlloc(num, PS_TYPE_F32); // Errors for each star
+    for (int i = 0; i < matches->n; i++) {
+        pmSourceMatch *match = matches->data[i]; // Match of interest
+        psVectorInit(mag, NAN);
+        psVectorInit(magErr, NAN);
+        for (int j = 0; j < match->num; j++) {
+            if (match->mask->data.PS_TYPE_VECTOR_MASK_DATA[j]) {
+                continue;
+            }
+            int index = match->image->data.U32[j]; // Image index
+            mag->data.F32[index] = match->mag->data.F32[j] - zp->data.F32[index];
+            if (trans) {
+                mag->data.F32[index] -= trans->data.F32[index];
+            }
+            magErr->data.F32[index] = match->magErr->data.F32[j];
+        }
+        for (int j = 0; j < num; j++) {
+            fprintf(outMatches, "%f (%f) ", mag->data.F32[j], magErr->data.F32[j]);
+        }
+        fprintf(outMatches, "\n");
+    }
+    psFree(mag);
+    psFree(magErr);
+    fclose(outMatches);
+    return;
+}
+#endif
+
+
+float ppStackSourcesTransparency(const psArray *sourceLists, psVector *inputMask,
+                                 const pmFPAview *view, const pmConfig *config)
 {
     PS_ASSERT_ARRAY_NON_NULL(sourceLists, NAN);
+    PS_ASSERT_VECTOR_NON_NULL(inputMask, NAN);
+    PS_ASSERT_VECTOR_TYPE(inputMask, PS_TYPE_U8, NAN);
+    PS_ASSERT_VECTOR_SIZE(inputMask, sourceLists->n, NAN);
     PS_ASSERT_PTR_NON_NULL(view, NAN);
     PS_ASSERT_PTR_NON_NULL(config, NAN);
 
-#ifdef TESTING
+#if defined(TESTING) && 0
     {
         // Deliberately induce a major transparency difference
@@ -37,12 +81,19 @@
 
     float radius = psMetadataLookupF32(NULL, recipe, "ZP.RADIUS"); // Radius (pixels) for matching sources
-    int iter = psMetadataLookupS32(NULL, recipe, "ZP.ITER"); // Maximum iterations
+    int iter1 = psMetadataLookupS32(NULL, recipe, "ZP.ITER.1"); // Maximum iterations for pass 1
+    int iter2 = psMetadataLookupS32(NULL, recipe, "ZP.ITER.2"); // Maximum iterations for pass 2
     float tol = psMetadataLookupF32(NULL, recipe, "ZP.TOL"); // Tolerance for zero point iterations
     int transIter = psMetadataLookupS32(NULL, recipe, "ZP.TRANS.ITER"); // Iterations for transparency
     float transRej = psMetadataLookupF32(NULL, recipe, "ZP.TRANS.REJ");// Rejection threshold for transparency
     float transThresh = psMetadataLookupF32(NULL, recipe, "ZP.TRANS.THRESH"); // Threshold for transparency
-    float starRej = psMetadataLookupF32(NULL, recipe, "ZP.STAR.REJ"); // Rejection threshold for stars
+
+    float starRej1 = psMetadataLookupF32(NULL, recipe, "ZP.STAR.REJ.1"); // Rejection threshold for stars
+    float starSys1 = psMetadataLookupF32(NULL, recipe, "ZP.STAR.SYS.1"); // Estimated systematic error
+    float starRej2 = psMetadataLookupF32(NULL, recipe, "ZP.STAR.REJ.2"); // Rejection threshold for stars
+    float starSys2 = psMetadataLookupF32(NULL, recipe, "ZP.STAR.SYS.2"); // Estimated systematic error
+
     float starLimit = psMetadataLookupF32(NULL, recipe, "ZP.STAR.LIMIT"); // Limit on star rejection fraction
-    float starSys = psMetadataLookupF32(NULL, recipe, "ZP.STAR.SYS"); // Estimated systematic error
+
+    float fracMatch = psMetadataLookupF32(NULL, recipe, "ZP.MATCH"); // Fraction of images to match for star
 
     psMetadata *airmassZP = psMetadataLookupMetadata(NULL, recipe, "ZP.AIRMASS"); // Airmass terms
@@ -63,8 +114,9 @@
         pmCell *cell = pmFPAviewThisCell(view, file->fpa); // Cell of interest
 
-#ifdef TESTING
+#if defined(TESTING) && 0
         pmReadout *fake = pmReadoutAlloc(NULL); // Fake readout
         pmPSF *psf = psMetadataLookupPtr(NULL, config->arguments, "PSF.TARGET"); // PSF for fake image
-        pmReadoutFakeFromSources(fake, FAKE_COLS, FAKE_ROWS, sourceLists->data[i], NULL, NULL, psf, 5, 0, false, true);
+        pmReadoutFakeFromSources(fake, FAKE_COLS, FAKE_ROWS, sourceLists->data[i],
+                                 NULL, NULL, psf, 5, 0, false, true);
         psString name = NULL;
         psStringAppend(&name, "start_%03d.fits", i);
@@ -114,65 +166,54 @@
         return NAN;
     }
-    psVector *trans = pmSourceMatchRelphot(matches, zp, iter, tol, starLimit, transIter, transRej,
-                                           transThresh, starRej, starSys); // Transparencies for each image
-
-#ifdef TESTING
-    {
-        // Dump the corrected magnitudes
-        FILE *outMatches = fopen("source_match.dat", "w"); // Output matches
-        psVector *mag = psVectorAlloc(num, PS_TYPE_F32); // Magnitudes for each star
-        psVector *magErr = psVectorAlloc(num, PS_TYPE_F32); // Errors for each star
-        for (int i = 0; i < matches->n; i++) {
-            pmSourceMatch *match = matches->data[i]; // Match of interest
-            psVectorInit(mag, NAN);
-            psVectorInit(magErr, NAN);
-            for (int j = 0; j < match->num; j++) {
-                if (match->mask->data.PS_TYPE_VECTOR_MASK_DATA[j]) {
-                    continue;
-                }
-                int index = match->image->data.U32[j]; // Image index
-                mag->data.F32[index] = match->mag->data.F32[j] - zp->data.F32[index] - trans->data.F32[index];
-                magErr->data.F32[index] = match->magErr->data.F32[j];
-            }
-            for (int j = 0; j < num; j++) {
-                fprintf(outMatches, "%f (%f) ", mag->data.F32[j], magErr->data.F32[j]);
-            }
-            fprintf(outMatches, "\n");
-        }
-        psFree(mag);
-        psFree(magErr);
-        fclose(outMatches);
-    }
-#endif
+
+#ifdef TESTING
+    dumpMatches("source_match.dat", num, matches, zp, NULL);
+#endif
+
+    psVector *trans = pmSourceMatchRelphot(matches, zp, tol, iter1, starRej1, starSys1,
+                                           iter2, starRej2, starSys2, starLimit,
+                                           transIter, transRej, transThresh); // Transparencies for each image
+    if (!trans) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to measure transparencies");
+        return NAN;
+    }
+
+#ifdef TESTING
+    dumpMatches("source_mags.dat", num, matches, zp, trans);
+#endif
+
+    for (int i = 0; i < trans->n; i++) {
+        if (!isfinite(trans->data.F32[i])) {
+            inputMask->data.U8[i] = PPSTACK_MASK_CAL;
+        }
+    }
 
     // Save best matches SOMEWHERE for future photometry
     // XXX this is a really poor output location; clean up the pmFPAfiles used in ppStack
     pmCell *sourcesCell = pmFPAfileThisCell(config->files, view, "PPSTACK.OUTPUT");
-    psArray *sourcesBest = psArrayAllocEmpty (100);
-
-    // XXX something of a hack: require at 2 detections or 1/2 of the max possible
-    int minMatches = PS_MAX (2, 0.5*num);
+    psArray *sourcesBest = psArrayAllocEmpty(matches->n);
+
+    // XXX something of a hack: require at least 2 detections or the nominated fraction of the max possible
+    int minMatches = PS_MAX(2, fracMatch * num);// Minimum number of matches required
     for (int i = 0; i < matches->n; i++) {
-	pmSourceMatch *match = matches->data[i]; // Match of interest
-	if (match->num < minMatches) continue;
-
-	// We need to grab a single instance of this source: just take the first available
-	int nImage = match->image->data.S32[0];
-	int nIndex = match->index->data.S32[0];
-	psArray *sources = sourceLists->data[nImage];
-	pmSource *source = sources->data[nIndex];
-	
-	// stick this sample source on sourcesBest
-	psArrayAdd (sourcesBest, 100, source);
-    }
-    psMetadataAdd (sourcesCell->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY | PS_META_REPLACE, "psphot sources", sourcesBest);
-    psLogMsg("ppStack", PS_LOG_INFO, "Selected %ld sources for photometry analysis\n", sourcesBest->n);
-    psFree (sourcesBest);
+        pmSourceMatch *match = matches->data[i]; // Match of interest
+        if (match->num < minMatches) {
+            continue;
+        }
+
+        // We need to grab a single instance of this source: just take the first available
+        int image = match->image->data.S32[0]; // Index of image
+        int index = match->index->data.S32[0]; // Index of source within image
+        psArray *sources = sourceLists->data[image]; // Sources for image
+        pmSource *source = sources->data[index]; // Source of interest
+
+        psArrayAdd(sourcesBest, sourcesBest->n, source);
+    }
+    psMetadataAdd(sourcesCell->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY | PS_META_REPLACE,
+                  "psphot sources", sourcesBest);
+    psLogMsg("ppStack", PS_LOG_INFO, "Selected %ld sources for photometry analysis", sourcesBest->n);
+    psFree(sourcesBest);
 
     psFree(matches);
-    if (!trans) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to measure transparencies");
-        return NAN;
-    }
 
     // M = m + c0 + c1 * airmass - 2.5log(t) + transparency
@@ -182,4 +223,7 @@
     // We don't need to know the magnitude zero point for the filter, since it cancels out
     for (int i = 0; i < num; i++) {
+        if (!isfinite(trans->data.F32[i])) {
+            continue;
+        }
         psArray *sources = sourceLists->data[i]; // Sources of interest
         float magCorr = airmassTerm - 2.5*log10(sumExpTime) - zp->data.F32[i] - trans->data.F32[i];
Index: /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackThread.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackThread.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackThread.c	(revision 23225)
@@ -36,7 +36,13 @@
     psFree(stack->threads);
     for (int i = 0; i < stack->imageFits->n; i++) {
-        psFitsClose(stack->imageFits->data[i]);
-        psFitsClose(stack->maskFits->data[i]);
-        psFitsClose(stack->varianceFits->data[i]);
+        if (stack->imageFits->data[i]) {
+            psFitsClose(stack->imageFits->data[i]);
+        }
+        if (stack->maskFits->data[i]) {
+            psFitsClose(stack->maskFits->data[i]);
+        }
+        if (stack->varianceFits->data[i]) {
+            psFitsClose(stack->varianceFits->data[i]);
+        }
         stack->imageFits->data[i] = stack->maskFits->data[i] = stack->varianceFits->data[i] = NULL;
     }
Index: /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStack/src/ppStackVersion.c	(revision 23225)
@@ -7,4 +7,5 @@
 #include <psmodules.h>
 #include <ppStats.h>
+#include <psphot.h>
 
 #include "ppStack.h"
@@ -54,29 +55,59 @@
 
 
-void ppStackVersionMetadata(psMetadata *metadata)
+bool ppStackVersionHeader(psMetadata *header)
 {
-    PS_ASSERT_METADATA_NON_NULL(metadata,);
-
-    psString pslib = psLibVersionLong();// psLib version
-    psString psmodules = psModulesVersionLong(); // psModules version
-    psString ppStats = ppStatsVersionLong(); // ppStats version
-    psString ppStack = ppStackVersionLong(); // ppStack version
+    PS_ASSERT_METADATA_NON_NULL(header, false);
 
     psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
     psString timeString = psTimeToISO(time); // The time in an ISO string
     psFree(time);
-    psString head = NULL;               // Head string
-    psStringAppend(&head, "ppStack processing at %s. Component information:", timeString);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "ppStack at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    psphotVersionHeader(header);
+    ppStatsVersionHeader(header);
+
+    psString version = ppStackVersion(); // Software version
+    psString source  = ppStackSource();  // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPSTACK.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPSTACK.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
+
+void ppStackVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("ppStack", PS_LOG_INFO, "ppStack at %s", timeString);
     psFree(timeString);
 
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, "", head);
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, "", pslib);
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, "", psmodules);
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, "", ppStats);
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, "", ppStack);
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString psphot = psphotVersionLong(); // psphot version
+    psString ppStats = ppStatsVersionLong(); // psastro version
+    psString ppStack = ppStackVersionLong(); // ppStack version
 
-    psFree(head);
+    psLogMsg("ppStack", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("ppStack", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("ppStack", PS_LOG_INFO, "%s", psphot);
+    psLogMsg("ppStack", PS_LOG_INFO, "%s", ppStats);
+    psLogMsg("ppStack", PS_LOG_INFO, "%s", ppStack);
+
     psFree(pslib);
     psFree(psmodules);
+    psFree(psphot);
     psFree(ppStats);
     psFree(ppStack);
Index: /branches/eam_branches/eam_branch_20090303/ppStats/src/ppStats.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStats/src/ppStats.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStats/src/ppStats.h	(revision 23225)
@@ -114,4 +114,10 @@
 psString ppStatsVersionLong(void);
 
+/// Populate header with version information
+bool ppStatsVersionHeader(
+    psMetadata *header                  ///< Header to populate
+    );
+
+
 void p_ppStatsGetMetadata(psMetadata *target, // Target for metadata
                           psMetadata *source, // Source for metadata
Index: /branches/eam_branches/eam_branch_20090303/ppStats/src/ppStatsFromMetadataPrint.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStats/src/ppStatsFromMetadataPrint.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStats/src/ppStatsFromMetadataPrint.c	(revision 23225)
@@ -41,5 +41,7 @@
             VALUE_NUMERICAL_CASE(F64, "lf",   F64);
           case PS_DATA_STRING:
-            fprintf(f, "%s '%s' ", entry->flag, entry->value->data.str);
+            if (entry->value->data.str) {
+                fprintf(f, "%s '%s' ", entry->flag, entry->value->data.str);
+            }
             break;
           case PS_DATA_BOOL:
@@ -50,7 +52,9 @@
           case PS_DATA_TIME: {
               psTime *t = (psTime*)entry->value->data.V;
-              psString str = psTimeToISO(t);
-              fprintf(f, "%s %.19sZ ", entry->flag, str);
-              psFree(str);
+              if (t) {
+                  psString str = psTimeToISO(t);
+                  fprintf(f, "%s %.19sZ ", entry->flag, str);
+                  psFree(str);
+              }
               break;
           }
Index: /branches/eam_branches/eam_branch_20090303/ppStats/src/ppStatsVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppStats/src/ppStatsVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppStats/src/ppStatsVersion.c	(revision 23225)
@@ -43,2 +43,20 @@
     return version;
 };
+
+bool ppStatsVersionHeader(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psString version = ppStatsVersion(); // Software version
+    psString source = ppStatsSource();   // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPSTATS.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPSTATS.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSub.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSub.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSub.c	(revision 23225)
@@ -34,4 +34,6 @@
         goto die;
     }
+
+    ppSubVersionPrint();
 
     if (!pmModelClassInit()) {
Index: /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSub.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSub.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSub.h	(revision 23225)
@@ -89,7 +89,10 @@
     );
 
-/// Put the program version information into a metadata
-void ppSubVersionMetadata(psMetadata *metadata ///< Metadata to populate
+/// Put the program version information into a header
+bool ppSubVersionHeader(psMetadata *header ///< Header to populate
     );
+
+/// Print version information
+void ppSubVersionPrint(void);
 
 
Index: /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubLoop.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubLoop.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubLoop.c	(revision 23225)
@@ -59,5 +59,4 @@
 
     pmFPAview *view = pmFPAviewAlloc(0); // Pointer into FPA hierarchy
-    pmHDU *lastHDU = NULL;              // Last HDU that was updated
 
     // Iterate over the FPA hierarchy
@@ -99,14 +98,4 @@
             if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
                 return false;
-            }
-
-            // Put version information into the header
-            pmHDU *hdu = pmHDUFromCell(inCell);
-            if (hdu && hdu != lastHDU) {
-                if (!hdu->header) {
-                    hdu->header = psMetadataAlloc();
-                }
-                ppSubVersionMetadata(hdu->header);
-                lastHDU = hdu;
             }
 
Index: /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubMatchPSFs.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubMatchPSFs.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubMatchPSFs.c	(revision 23225)
@@ -129,9 +129,10 @@
 
     // XXX drop the pixels associated with inRO and refRO (now that we have inConv and refConf)
-
+#ifdef TESTING
     psphotSaveImage (NULL, inRO->image, "inRO.fits");
     psphotSaveImage (NULL, refRO->image, "refRO.fits");
     psphotSaveImage (NULL, inConv->image, "inConv.fits");
     psphotSaveImage (NULL, refConv->image, "refConv.fits");
+#endif
 
     return true;
Index: /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubReadoutUpdate.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubReadoutUpdate.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubReadoutUpdate.c	(revision 23225)
@@ -44,4 +44,5 @@
     psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.INPUT", 0,
                      "Subtraction input", inFile->filename);
+    ppSubVersionHeader(outHDU->header);
 
     // Statistics on the matching
Index: /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/ppSub/src/ppSubVersion.c	(revision 23225)
@@ -19,4 +19,5 @@
 #include <psmodules.h>
 #include <ppStats.h>
+#include <psphot.h>
 
 #include "ppSub.h"
@@ -66,29 +67,59 @@
 
 
-void ppSubVersionMetadata(psMetadata *metadata)
+bool ppSubVersionHeader(psMetadata *header)
 {
-    PS_ASSERT_METADATA_NON_NULL(metadata,);
-
-    psString pslib = psLibVersionLong();// psLib version
-    psString psmodules = psModulesVersionLong(); // psModules version
-    psString ppStats = ppStatsVersionLong(); // ppStats version
-    psString ppSub = ppSubVersionLong(); // ppSub version
+    PS_ASSERT_METADATA_NON_NULL(header, false);
 
     psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
     psString timeString = psTimeToISO(time); // The time in an ISO string
     psFree(time);
-    psString head = NULL;               // Head string
-    psStringAppend(&head, "ppSub processing at %s. Component information:", timeString);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "ppSub at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    psphotVersionHeader(header);
+    ppStatsVersionHeader(header);
+
+    psString version = ppSubVersion(); // Software version
+    psString source  = ppSubSource();  // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPSUB.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PPSUB.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
+
+void ppSubVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("ppSub", PS_LOG_INFO, "ppSub at %s", timeString);
     psFree(timeString);
 
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, head, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, pslib, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, psmodules, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppStats, "");
-    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, ppSub, "");
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString psphot = psphotVersionLong(); // psphot version
+    psString ppStats = ppStatsVersionLong(); // ppStats version
+    psString ppSub = ppSubVersionLong(); // ppSub version
 
-    psFree(head);
+    psLogMsg("ppSub", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("ppSub", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("ppSub", PS_LOG_INFO, "%s", psphot);
+    psLogMsg("ppSub", PS_LOG_INFO, "%s", ppStats);
+    psLogMsg("ppSub", PS_LOG_INFO, "%s", ppSub);
+
     psFree(pslib);
     psFree(psmodules);
+    psFree(psphot);
     psFree(ppStats);
     psFree(ppSub);
Index: /branches/eam_branches/eam_branch_20090303/psLib/configure.ac
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psLib/configure.ac	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psLib/configure.ac	(revision 23225)
@@ -122,40 +122,23 @@
 TMP_CPPFLAGS=${CPPFLAGS}
 
-AC_ARG_WITH(cfitsio,
-[AS_HELP_STRING(--with-cfitsio=DIR,Specify location of CFITSIO.)],
-[CFITSIO_CFLAGS="-I$withval/include"
- CFITSIO_LDFLAGS="-L$withval/lib"])
-AC_ARG_WITH(cfitsio-include,
-[AS_HELP_STRING(--with-cfitsio-include=DIR,Specify CFITSIO include directory.)],
-[CFITSIO_CFLAGS="-I$withval"])
-AC_ARG_WITH(cfitsio-lib,
-[AS_HELP_STRING(--with-cfitsio-lib=DIR,Specify CFITSIO library directory.)],
-[CFITSIO_LDFLAGS="-L$withval"])
+PKG_CHECK_MODULES([CFITSIO], [cfitsio], [], AC_MSG_ERROR([CFITSIO package not found.  Obtain CFITSIO at  http://heasarc.gsfc.nasa.gov/docs/software/fitsio]))
+
 PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${CFITSIO_CFLAGS}"
-PSLIB_LIBS="${PSLIB_LIBS=} $CFITSIO_LDFLAGS -lcfitsio -lm"
+PSLIB_LIBS="${PSLIB_LIBS=} ${CFITSIO_LIBS}"
 
 CFLAGS="${CFLAGS=} ${CFITSIO_CFLAGS}"
-LDFLAGS="${LDFLAGS=} ${CFITSIO_LDFLAGS}"
-
-dnl Solaris needs to suck in these symbols from unusual locations
-AC_SEARCH_LIBS([gethostbyname], [nsl])
-AC_SEARCH_LIBS([socket], [socket])
-
-AC_CHECK_HEADERS([fitsio.h],[],
-   [AC_MSG_ERROR([CFITSIO headers not found.  Obtain CFITSIO at  http://heasarc.gsfc.nasa.gov/docs/software/fitsio or use --with-cfitsio to specify location.])]
-)
-TMP_LIBS=${LIBS}
-AC_CHECK_LIB(cfitsio,ffopen,[],
-  [AC_MSG_ERROR([CFITSIO library not found.  Obtain it at  http://heasarc.gsfc.nasa.gov/docs/software/fitsio or use --with-cfitsio to specify location.])],[-lm]
-)
+LDFLAGS="${LDFLAGS=} ${CFITSIO_LIBS}"
+
 dnl Now check if CFITSIO supports fits_open_diskfile, i.e., is at least version 2.501
-AC_CHECK_LIB(cfitsio,ffdkopn,
+AC_CHECK_FUNC(ffdkopn,
   [CFITSIO_DISKFILE=1],
   [AC_MSG_WARN([The CFITSIO library version is rather old.  Suggested version is 2.501 or greater.])
-   CFITSIO_DISKFILE=0],[-lm]
+   CFITSIO_DISKFILE=0]
 )
 
 AC_DEFINE_UNQUOTED([CFITSIO_DISKFILE],${CFITSIO_DISKFILE},[Define to 1 if you have fits_open_diskfile in CFITSIO])
+
 AC_SUBST([CFITSIO_CFLAGS])
+AC_SUBST([CFITSIO_LIBS])
 
 dnl restore the LIBS/CFLAGS/LDFLAGS
@@ -173,44 +156,20 @@
 TMP_CPPFLAGS=${CPPFLAGS}
 
-AC_ARG_WITH(fftw3,
-[AS_HELP_STRING(--with-fftw3=DIR,Specify location of FFTW version 3.)],
-[FFTW3_CFLAGS="-I$withval/include"
- FFTW3_LDFLAGS="-L$withval/lib"])
-AC_ARG_WITH(fftw3-include,
-[AS_HELP_STRING(--with-fftw3-include=DIR,Specify FFTW version 3 include directory.)],
-[FFTW3_CFLAGS="-I$withval"])
-AC_ARG_WITH(fftw3-lib,
-[AS_HELP_STRING(--with-fftw3-lib=DIR,Specify FFTW version 3 library directory.)],
-[FFTW3_LDFLAGS="-L$withval"])
+PKG_CHECK_MODULES([FFTW3], [fftw3f], [], AC_MSG_ERROR([FFTW version 3 (--enable-float) library not found.  Obtain it at http://www.fftw.org/]))
+
 PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${FFTW3_CFLAGS}"
-PSLIB_LIBS="${PSLIB_LIBS=} $FFTW3_LDFLAGS -lfftw3f"
+PSLIB_LIBS="${PSLIB_LIBS=} ${FFTW3_LIBS}"
 
 CFLAGS="${CFLAGS} ${FFTW3_CFLAGS}"
 CPPFLAGS=${CFLAGS}
-LDFLAGS="${LDFLAGS} ${FFTW3_LDFLAGS}"
-
-AC_CHECK_LIB(fftw3f,fftwf_plan_dft_2d,[],
-  [AC_MSG_ERROR([FFTW version 3 (--enable-float) library not found.  Obtain it at http://www.fftw.org/ or use --with-fftw3 to specify location.])])
-
-FFTW_THREADS=0
-AC_CHECK_LIB(fftw3f,fftwf_init_threads,[FFTW_THREADS=1],
-  [AC_CHECK_LIB(fftw3f_threads,fftwf_init_threads, [
-    FFTW_THREADS=1
-    PSLIB_LIBS="${PSLIB_LIBS=} -lfftw3f_threads"],
-   AC_MSG_WARN([FFTW version 3 not compiled with thread support (--enable-threads)]),[-lm]
-   )],[-lm]
-)
-
-dnl AC_CHECK_LIB(fftw3f,fftwf_plan_dft_2d,[],
-dnl   [AC_MSG_ERROR([FFTW version 3 (--enable-float) library not found.  Obtain it at http://www.fftw.org/ or use --with-fftw3 to specify location.])],[-lm]
-dnl )
-
-AC_CHECK_HEADERS([fftw3.h],[],
-  [AC_MSG_ERROR([FFTW version 3 (--enable-float) headers not found.  Obtain it at http://www.fftw.org/ or use --with-fftw3 to specify location.])]
-)
-
+LDFLAGS="${LDFLAGS} ${FFTW3_LIBS}"
+
+AC_CHECK_FUNC(fftwf_plan_dft_2d,[],
+  [AC_MSG_ERROR([FFTW version 3 (--enable-float) library not found.  Obtain it at http://www.fftw.org/])])
+AC_CHECK_FUNC(fftwf_init_threads,[FFTW_THREADS=1],[FFTW_THREADS=0])
 AC_DEFINE_UNQUOTED([HAVE_FFTW_THREADS],${FFTW_THREADS},[Define to 1 if you have FFTW compiled with thread support])
 
 AC_SUBST([FFTW3_CFLAGS])
+AC_SUBST([FFTW3_LIBS])
 
 dnl restore the CFLAGS/LDFLAGS
@@ -228,23 +187,11 @@
 TMP_CPPFLAGS=${CPPFLAGS}
 
-AC_ARG_WITH(gsl-config,
-[AS_HELP_STRING(--with-gsl-config=FILE,Specify location of gsl-config.)],
-[GSL_CONFIG=$withval],
-[GSL_CONFIG=`which gsl-config`])
-AC_CHECK_FILE($GSL_CONFIG,[],
-    [AC_MSG_ERROR([GSL is required.  Obtain it at http://www.gnu.org/software/gsl or use --with-gsl-config to specify location.])])
-
-AC_MSG_CHECKING([GSL cflags])
-GSL_CFLAGS="`${GSL_CONFIG} --cflags`"
-AC_MSG_RESULT([${GSL_CFLAGS}])
-
-AC_MSG_CHECKING([GSL ldflags])
-GSL_LDFLAGS="`${GSL_CONFIG} --libs`"
-AC_MSG_RESULT([${GSL_LDFLAGS}])
+PKG_CHECK_MODULES([GSL], [gsl], [], AC_MSG_ERROR([GSL is required.  Obtain it at http://www.gnu.org/software/gsl]))
 
 PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${GSL_CFLAGS}"
-PSLIB_LIBS="${PSLIB_LIBS=} ${GSL_LDFLAGS}"
+PSLIB_LIBS="${PSLIB_LIBS=} ${GSL_LIBS}"
 
 AC_SUBST([GSL_CFLAGS])
+AC_SUBST([GSL_LIBS])
 
 dnl restore the CFLAGS/LDFLAGS
@@ -277,10 +224,10 @@
 LDFLAGS="${LDFLAGS} ${JPEG_LDFLAGS}"
 
-AC_CHECK_HEADERS([jpeglib.h],[PSLIB_CFLAGS="$PSLIB_CFLAGS $JPEG_CFLAGS"
+AC_CHECK_HEADERS([jpeglib.h],[PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${JPEG_CFLAGS}"
 			      AC_SUBST(JPEG_CFLAGS)],
   [AC_MSG_ERROR([libjpeg headers not found.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
 )
 
-AC_CHECK_LIB(jpeg,jpeg_CreateCompress,[PSLIB_LIBS="$PSLIB_LIBS $JPEG_LDFLAGS -ljpeg"],
+AC_CHECK_LIB(jpeg,jpeg_CreateCompress,[PSLIB_LIBS="${PSLIB_LIBS=} ${JPEG_LDFLAGS} -ljpeg"],
   [AC_MSG_ERROR([libjpeg library not found.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
 )
@@ -291,37 +238,4 @@
 LDFLAGS=${TMP_LDFLAGS}
 CPPFLAGS=${TMP_CPPFLAGS}
-
-dnl ------------------- XML2 options ---------------------
-dnl AC_ARG_WITH(xml2-config,
-dnl [AS_HELP_STRING(--with-xml2-config=FILE,Specify location of xml2-config.)],
-dnl [XML_CONFIG=$withval],
-dnl [XML_CONFIG=`which xml2-config`])
-dnl AC_CHECK_FILE($XML_CONFIG,[],
-dnl     [AC_MSG_ERROR([GNOME XML C parser is required.  Obtain it at http://www.xmlsoft.org or use --with-xml2-config to specify location.])])
-dnl
-dnl AC_MSG_CHECKING([xml2 version])
-dnl XML_VERSION=`xml2-config --version`
-dnl XML_VERSION_major=`echo $XML_VERSION | ${PERL} -pe 's|^(\d+).*|\1|'`
-dnl XML_VERSION_minor=`echo $XML_VERSION | ${PERL} -pe 's|^(\d+)\.(\d+).*|\2|'`
-dnl dnl First test the minimum version of 2.6
-dnl if test $XML_VERSION_major -lt 2 || ( test $XML_VERSION_major -eq 2 && test $XML_VERSION_minor -lt 6 )
-dnl then
-dnl 	AC_MSG_ERROR([requires libxml2 2.6.0 or greater, found $XML_VERSION.  Install newer version or use --with-xml2-config to specify another location.])
-dnl else
-dnl     AC_MSG_RESULT([$XML_VERSION... yes])
-dnl fi
-dnl
-dnl AC_MSG_CHECKING([xml2 cflags])
-dnl XML_CFLAGS="`${XML_CONFIG} --cflags`"
-dnl AC_MSG_RESULT([${XML_CFLAGS}])
-dnl
-dnl AC_MSG_CHECKING([xml2 ldflags])
-dnl XML_LDFLAGS="`${XML_CONFIG} --libs`"
-dnl AC_MSG_RESULT([${XML_LDFLAGS}])
-dnl
-dnl PSLIB_CFLAGS="${PSLIB_CFLAGS=} ${XML_CFLAGS}"
-dnl PSLIB_LIBS="${PSLIB_LIBS=} ${XML_LDFLAGS}"
-dnl
-dnl AC_SUBST([XML_CFLAGS])
 
 dnl ------------------- SWIG options ---------------------
@@ -477,7 +391,4 @@
   utils/Makefile
 ])
-dnl src/xml/Makefile
-dnl test/xml/Makefile
-
 
 #if test "$SWIG_REQ" == "yes"
Index: /branches/eam_branches/eam_branch_20090303/psLib/src/sys/psLogMsg.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psLib/src/sys/psLogMsg.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psLib/src/sys/psLogMsg.c	(revision 23225)
@@ -195,5 +195,5 @@
     }
 
-    int fileD = creat(dest, 0666);
+    int fileD = open(dest, O_WRONLY | O_CREAT, 0666);
     if (fileD == 0) {
         psError(PS_ERR_IO, true, _("Could not open file '%s' for output."), dest);
@@ -316,5 +316,5 @@
 
     if (write(logFD, head, strlen(head))) {;} // ignore return value
-    
+
     if (logMsg) {
         psString msg = NULL;            // Message to print
Index: /branches/eam_branches/eam_branch_20090303/psLib/src/types/psMetadataHeader.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psLib/src/types/psMetadataHeader.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psLib/src/types/psMetadataHeader.c	(revision 23225)
@@ -19,7 +19,7 @@
 
     psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSLIB.VERSION", PS_META_REPLACE,
-                     "psLib software version", version);
+                     "Software version", version);
     psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSLIB.SOURCE", PS_META_REPLACE,
-                     "psLib software source", source);
+                     "S/W source", source);
 
     psFree(version);
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/config/pmConfig.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/config/pmConfig.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/config/pmConfig.c	(revision 23225)
@@ -1110,6 +1110,6 @@
 // camera.  If we are discovering the camera (config->camera == NULL), then we also load the
 // recipe files for the camera.
-psMetadata *pmConfigCameraFormatFromHeader(psMetadata **camera, psString *cameraName, psString *formatName, 
-					   pmConfig *config, const psMetadata *header, bool readRecipes)
+psMetadata *pmConfigCameraFormatFromHeader(psMetadata **camera, psString *cameraName, psString *formatName,
+                                           pmConfig *config, const psMetadata *header, bool readRecipes)
 {
     PS_ASSERT_PTR_NON_NULL(config, NULL);
@@ -1672,5 +1672,5 @@
                 // if the object does not exist and create isn't set, then we
                 // should puke
-                psError(PM_ERR_SYS, true, "Unable to access file %s", filename);
+                psError(PM_ERR_SYS, true, "Unable to access file %s: %s", filename, nebErr(server));
                 nebServerFree(server);
                 return NULL;
@@ -1685,5 +1685,6 @@
         if (trunc) {
             if(truncate(path, 0) != 0) {
-                psError(PS_ERR_IO, true, "Failed to truncate Nebulous file %s (real name %s)\n", filename, path);
+                psError(PS_ERR_IO, true, "Failed to truncate Nebulous file %s (real name %s)\n",
+                        filename, path);
                 return NULL;
             }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/config/pmVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/config/pmVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/config/pmVersion.c	(revision 23225)
@@ -49,4 +49,10 @@
 #endif
 
+#ifdef HAVE_NEBCLIENT
+    psStringAppend(&version, " with nebclient");
+#else
+    psStringAppend(&version, " without nebclient");
+#endif
+
     return version;
 };
@@ -61,7 +67,7 @@
 
     psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSMODULES.VERSION", PS_META_REPLACE,
-                     "psModules software version", version);
+                     "Software version", version);
     psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSMODULES.SOURCE", PS_META_REPLACE,
-                     "psModules software source", source);
+                     "S/W source", source);
 
     psFree(version);
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/imcombine/pmPSFEnvelope.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/imcombine/pmPSFEnvelope.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/imcombine/pmPSFEnvelope.c	(revision 23225)
@@ -115,4 +115,7 @@
     for (int i = 0; i < inputs->n; i++) {
         pmPSF *psf = inputs->data[i];   // PSF of interest
+        if (!psf) {
+            continue;
+        }
         pmResiduals *resid = psf->residuals;// PSF residuals
         psf->residuals = NULL;
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/Makefile.am	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/Makefile.am	(revision 23225)
@@ -19,4 +19,5 @@
 	pmModelUtils.c \
 	pmSource.c \
+	pmSourceMasks.c \
 	pmSourceMoments.c \
 	pmSourceExtendedPars.c \
@@ -69,4 +70,5 @@
 	pmModelUtils.h \
 	pmSource.h \
+	pmSourceMasks.h \
 	pmSourceExtendedPars.h \
 	pmSourceUtils.h \
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmFootprint.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmFootprint.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmFootprint.c	(revision 23225)
@@ -28,10 +28,10 @@
    }
 
-   psTrace("psModules.objects", 5, "---- begin ----\n");
+   psTrace("psModules.objects", 10, "---- begin ----\n");
 
    psFree(tmp->spans);
    psFree(tmp->peaks);
 
-   psTrace("psModules.objects", 5, "---- end ----\n");
+   psTrace("psModules.objects", 10, "---- end ----\n");
 }
 
@@ -42,5 +42,5 @@
 			      const psImage *image) // region footprint lives in
 {
-    psTrace("psModules.objects", 5, "---- begin ----\n");
+    psTrace("psModules.objects", 10, "---- begin ----\n");
 
     static int id = 1;
@@ -69,5 +69,5 @@
     }
 
-    psTrace("psModules.objects", 5, "---- end ----\n");
+    psTrace("psModules.objects", 10, "---- end ----\n");
     return(footprint);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmModel.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmModel.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmModel.c	(revision 23225)
@@ -32,8 +32,8 @@
 static void modelFree(pmModel *tmp)
 {
-    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     psFree(tmp->params);
     psFree(tmp->dparams);
-    psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
 }
 
@@ -44,5 +44,5 @@
 pmModel *pmModelAlloc(pmModelType type)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
 
     pmModelClass *class = pmModelClassSelect (type);
@@ -87,5 +87,5 @@
     tmp->modelFitStatus     = class->modelFitStatus;
 
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(tmp);
 }
@@ -130,5 +130,5 @@
 psF32 pmModelEval(pmModel *model, psImage *image, psS32 col, psS32 row)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(image, NAN);
     PS_ASSERT_PTR_NON_NULL(model, NAN);
@@ -144,5 +144,5 @@
     tmpF = model->modelFunc (NULL, model->params, x);
     psFree(x);
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(tmpF);
 }
@@ -150,5 +150,5 @@
 psF32 pmModelEvalWithOffset(pmModel *model, psImage *image, psS32 col, psS32 row, int dx, int dy)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(image, false);
     PS_ASSERT_PTR_NON_NULL(model, false);
@@ -164,5 +164,5 @@
     tmpF = model->modelFunc (NULL, model->params, x);
     psFree(x);
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(tmpF);
 }
@@ -180,5 +180,5 @@
     )
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
 
     PS_ASSERT_PTR_NON_NULL(model, false);
@@ -344,5 +344,5 @@
 
     psFree(x);
-    psTrace("psModules.objects", 3, "---- %s(true) end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s(true) end ----\n", __func__);
     return(true);
 }
@@ -356,7 +356,7 @@
                 psImageMaskType maskVal)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     psBool rc = AddOrSubModel(image, mask, model, mode, true, maskVal, 0.0, 0.0);
-    psTrace("psModules.objects", 3, "---- %s(%d) end ----\n", __func__, rc);
+    psTrace("psModules.objects", 10, "---- %s(%d) end ----\n", __func__, rc);
     return(rc);
 }
@@ -370,7 +370,7 @@
                 psImageMaskType maskVal)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     psBool rc = AddOrSubModel(image, mask, model, mode, false, maskVal, 0.0, 0.0);
-    psTrace("psModules.objects", 3, "---- %s(%d) end ----\n", __func__, rc);
+    psTrace("psModules.objects", 10, "---- %s(%d) end ----\n", __func__, rc);
     return(rc);
 }
@@ -386,7 +386,7 @@
                           int dy)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     psBool rc = AddOrSubModel(image, mask, model, mode, true, maskVal, dx, dy);
-    psTrace("psModules.objects", 3, "---- %s(%d) end ----\n", __func__, rc);
+    psTrace("psModules.objects", 10, "---- %s(%d) end ----\n", __func__, rc);
     return(rc);
 }
@@ -402,7 +402,7 @@
                           int dy)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     psBool rc = AddOrSubModel(image, mask, model, mode, false, maskVal, dx, dy);
-    psTrace("psModules.objects", 3, "---- %s(%d) end ----\n", __func__, rc);
+    psTrace("psModules.objects", 10, "---- %s(%d) end ----\n", __func__, rc);
     return(rc);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmMoments.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmMoments.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmMoments.c	(revision 23225)
@@ -27,5 +27,5 @@
 pmMoments *pmMomentsAlloc()
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     pmMoments *tmp = (pmMoments *) psAlloc(sizeof(pmMoments));
     tmp->Mx = 0.0;
@@ -52,5 +52,5 @@
     tmp->nPixels = 0;
 
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(tmp);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmPeaks.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmPeaks.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmPeaks.c	(revision 23225)
@@ -37,5 +37,5 @@
                         pmPeakType type)
 {
-    psTrace("psModules.objects", 5, "---- begin ----\n");
+    psTrace("psModules.objects", 10, "---- begin ----\n");
 
     if (peaks == NULL) {
@@ -82,5 +82,5 @@
     psFree (peak);
 
-    psTrace("psModules.objects", 5, "---- end ----\n");
+    psTrace("psModules.objects", 10, "---- end ----\n");
     return(peaks);
 }
@@ -96,5 +96,5 @@
                                        psU32 row)
 {
-    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_IMAGE_NON_NULL(image, NULL);
     PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, NULL);
@@ -104,5 +104,5 @@
         tmpVector->data.F32[col] = image->data.F32[row][col];
     }
-    psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(tmpVector);
 }
@@ -117,13 +117,13 @@
                              psS32 y)
 {
-    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     if ((x >= valid.x0) &&
             (x <= valid.x1) &&
             (y >= valid.y0) &&
             (y <= valid.y1)) {
-        psTrace("psModules.objects", 4, "---- %s(true) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(true) end ----\n", __func__);
         return(true);
     }
-    psTrace("psModules.objects", 4, "---- %s(false) end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s(false) end ----\n", __func__);
     return(false);
 }
@@ -140,5 +140,5 @@
                     pmPeakType type)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     static int id = 1;
     pmPeak *tmp = (pmPeak *) psAlloc(sizeof(pmPeak));
@@ -157,5 +157,5 @@
     psMemSetDeallocator(tmp, (psFreeFunc) peakFree);
 
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(tmp);
 }
@@ -172,5 +172,5 @@
 int pmPeaksCompareAscend (const void **a, const void **b)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     pmPeak *A = *(pmPeak **)a;
     pmPeak *B = *(pmPeak **)b;
@@ -180,11 +180,11 @@
     diff = A->value - B->value;
     if (diff < FLT_EPSILON) {
-        psTrace("psModules.objects", 3, "---- %s(-1) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(-1) end ----\n", __func__);
         return (-1);
     } else if (diff > FLT_EPSILON) {
-        psTrace("psModules.objects", 3, "---- %s(+1) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(+1) end ----\n", __func__);
         return (+1);
     }
-    psTrace("psModules.objects", 3, "---- %s(0) end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s(0) end ----\n", __func__);
     return (0);
 }
@@ -194,5 +194,5 @@
 int pmPeaksCompareDescend (const void **a, const void **b)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     pmPeak *A = *(pmPeak **)a;
     pmPeak *B = *(pmPeak **)b;
@@ -202,11 +202,11 @@
     diff = A->value - B->value;
     if (diff < FLT_EPSILON) {
-        psTrace("psModules.objects", 3, "---- %s(+1) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(+1) end ----\n", __func__);
         return (+1);
     } else if (diff > FLT_EPSILON) {
-        psTrace("psModules.objects", 3, "---- %s(-1) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(-1) end ----\n", __func__);
         return (-1);
     }
-    psTrace("psModules.objects", 3, "---- %s(0) end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s(0) end ----\n", __func__);
     return (0);
 }
@@ -258,5 +258,5 @@
 			 psF32 threshold)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_VECTOR_NON_NULL(vector, NULL);
     PS_ASSERT_VECTOR_NON_EMPTY(vector, NULL);
@@ -276,5 +276,5 @@
             tmpVector = psVectorAlloc(0, PS_TYPE_U32);
         }
-        psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
         return(tmpVector);
     }
@@ -341,5 +341,5 @@
     }
 
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(tmpVector);
 }
@@ -363,10 +363,10 @@
 psArray *pmPeaksInImage(const psImage *image, psF32 threshold)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_IMAGE_NON_NULL(image, NULL);
     PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, NULL);
     if ((image->numRows == 1) || (image->numCols == 1)) {
         psError(PS_ERR_UNKNOWN, true, "Currently, input image must have at least 2 rows and 2 columns.");
-        psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(NULL) end ----\n", __func__);
         return(NULL);
     }
@@ -425,5 +425,5 @@
     //
     if (image->numRows == 1) {
-        psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
         return(list);
     }
@@ -549,5 +549,5 @@
     psFree (tmpRow);
     psFree (row1);
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(list);
 }
@@ -560,5 +560,5 @@
     const psRegion valid)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(peaks, NULL);
 
@@ -575,5 +575,5 @@
         psArrayAdd (output, 200, tmpPeak);
     }
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(output);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSource.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSource.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSource.c	(revision 23225)
@@ -41,5 +41,5 @@
         return;
 
-    psTrace("psModules.objects", 5, "---- begin ----\n");
+    psTrace("psModules.objects", 10, "---- begin ----\n");
     psFree(tmp->peak);
     psFree(tmp->pixels);
@@ -55,5 +55,5 @@
     psFree(tmp->extpars);
     psFree(tmp->blends);
-    psTrace("psModules.objects", 5, "---- end ----\n");
+    psTrace("psModules.objects", 10, "---- end ----\n");
 }
 
@@ -94,5 +94,5 @@
 pmSource *pmSourceAlloc()
 {
-    psTrace("psModules.objects", 5, "---- begin ----\n");
+    psTrace("psModules.objects", 10, "---- begin ----\n");
     static int id = 1;
     pmSource *source = (pmSource *) psAlloc(sizeof(pmSource));
@@ -131,5 +131,5 @@
     source->extNsigma = NAN;
 
-    psTrace("psModules.objects", 5, "---- end ----\n");
+    psTrace("psModules.objects", 10, "---- end ----\n");
     return(source);
 }
@@ -280,5 +280,5 @@
 pmPSFClump pmSourcePSFClump(psRegion *region, psArray *sources, psMetadata *recipe)
 {
-    psTrace("psModules.objects", 5, "---- begin ----\n");
+    psTrace("psModules.objects", 10, "---- begin ----\n");
 
     psArray *peaks  = NULL;
@@ -496,5 +496,5 @@
     }
 
-    psTrace("psModules.objects", 5, "---- end ----\n");
+    psTrace("psModules.objects", 10, "---- end ----\n");
     return (psfClump);
 }
@@ -508,5 +508,5 @@
 bool pmSourceRoughClass(psRegion *region, psArray *sources, psMetadata *recipe, pmPSFClump clump, psImageMaskType maskSat)
 {
-    psTrace("psModules.objects", 5, "---- begin ----");
+    psTrace("psModules.objects", 10, "---- begin ----");
 
     PS_ASSERT_PTR_NON_NULL(sources, false);
@@ -664,5 +664,5 @@
     psTrace ("psModules.objects", 2, "Ncr:      %3d\n", Ncr);
 
-    psTrace("psModules.objects", 5, "---- end ----\n");
+    psTrace("psModules.objects", 10, "---- end ----\n");
     return true;
 }
@@ -692,5 +692,5 @@
                      psF32 radius)
 {
-    psTrace("psModules.objects", 5, "---- begin ----\n");
+    psTrace("psModules.objects", 10, "---- begin ----\n");
     PS_ASSERT_PTR_NON_NULL(source, false);
     PS_ASSERT_PTR_NON_NULL(source->peak, false);
@@ -807,5 +807,5 @@
         psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n",
                  numPixels, (int)(0.75*R2), Sum);
-        psTrace("psModules.objects", 5, "---- end (false) ----\n");
+        psTrace("psModules.objects", 10, "---- end (false) ----\n");
         return (false);
     }
@@ -824,5 +824,5 @@
         psTrace ("psModules.objects", 3, "large centroid swing; invalid peak %d, %d\n",
                  source->peak->x, source->peak->y);
-        psTrace("psModules.objects", 5, "---- end(false)  ----\n");
+        psTrace("psModules.objects", 10, "---- end(false)  ----\n");
         return (false);
     }
@@ -850,5 +850,5 @@
              source->moments->Mxx, source->moments->Myy, source->moments->Mxy);
 
-    psTrace("psModules.objects", 5, "---- end ----\n");
+    psTrace("psModules.objects", 10, "---- end ----\n");
     return(true);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSource.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSource.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSource.h	(revision 23225)
@@ -19,4 +19,6 @@
 /// @addtogroup Objects Object Detection / Analysis Functions
 /// @{
+
+#include <pmSourceMasks.h>
 
 /** pmSourceType enumeration
@@ -34,37 +36,4 @@
     PM_SOURCE_TYPE_EXTENDED,            ///< an extended object (eg, galaxy) (subtracted model is EXT)
 } pmSourceType;
-
-// bit flags to distinguish analysis results
-typedef enum {
-    PM_SOURCE_MODE_DEFAULT    	    = 0x00000000, ///< Initial value: resets all bits
-    PM_SOURCE_MODE_PSFMODEL   	    = 0x00000001, ///< Source fitted with a psf model (linear or non-linear)
-    PM_SOURCE_MODE_EXTMODEL   	    = 0x00000002, ///< Source fitted with an extended-source model
-    PM_SOURCE_MODE_FITTED     	    = 0x00000004, ///< Source fitted with non-linear model (PSF or EXT; good or bad)
-    PM_SOURCE_MODE_FAIL       	    = 0x00000008, ///< Fit (non-linear) failed (non-converge, off-edge, run to zero)
-    PM_SOURCE_MODE_POOR       	    = 0x00000010, ///< Fit succeeds, but low-SN, high-Chisq, or large (for PSF -- drop?)
-    PM_SOURCE_MODE_PAIR       	    = 0x00000020, ///< Source fitted with a double psf
-    PM_SOURCE_MODE_PSFSTAR    	    = 0x00000040, ///< Source used to define PSF model
-    PM_SOURCE_MODE_SATSTAR    	    = 0x00000080, ///< Source model peak is above saturation
-    PM_SOURCE_MODE_BLEND      	    = 0x00000100, ///< Source is a blend with other sourcers
-    PM_SOURCE_MODE_EXTERNAL   	    = 0x00000200, ///< Source based on supplied input position
-    PM_SOURCE_MODE_BADPSF     	    = 0x00000400, ///< Failed to get good estimate of object's PSF
-    PM_SOURCE_MODE_DEFECT     	    = 0x00000800, ///< Source is thought to be a defect
-    PM_SOURCE_MODE_SATURATED  	    = 0x00001000, ///< Source is thought to be saturated pixels (bleed trail)
-    PM_SOURCE_MODE_CR_LIMIT   	    = 0x00002000, ///< Source has crNsigma above limit
-    PM_SOURCE_MODE_EXT_LIMIT  	    = 0x00004000, ///< Source has extNsigma above limit
-    PM_SOURCE_MODE_MOMENTS_FAILURE  = 0x00008000, ///< could not measure the moments
-    PM_SOURCE_MODE_SKY_FAILURE      = 0x00010000, ///< could not measure the local sky
-    PM_SOURCE_MODE_SKYVAR_FAILURE   = 0x00020000, ///< could not measure the local sky variance
-    PM_SOURCE_MODE_BELOW_MOMENTS_SN = 0x00040000, ///< moments not measured due to low S/N
-    PM_SOURCE_MODE_BIG_RADIUS       = 0x00100000, ///< poor moments for small radius, try large radius
-    PM_SOURCE_MODE_AP_MAGS          = 0x00200000, ///< source has an aperture magnitude
-    PM_SOURCE_MODE_BLEND_FIT        = 0x00400000, ///< source was fitted as a blend
-    PM_SOURCE_MODE_EXTENDED_FIT     = 0x00800000, ///< full extended fit was used
-    PM_SOURCE_MODE_EXTENDED_STATS   = 0x01000000, ///< extended aperture stats calculated
-    PM_SOURCE_MODE_LINEAR_FIT       = 0x02000000, ///< source fitted with the linear fit
-    PM_SOURCE_MODE_NONLINEAR_FIT    = 0x04000000, ///< source fitted with the non-linear fit
-    PM_SOURCE_MODE_RADIAL_FLUX      = 0x08000000, ///< radial flux measurements calculated
-    PM_SOURCE_MODE_SIZE_SKIPPED     = 0x10000000, ///< size could not be determined
-} pmSourceMode;
 
 typedef enum {
@@ -101,5 +70,5 @@
     pmSourceType type;                  ///< Best identification of object.
     pmSourceMode mode;                  ///< analysis flags set for object.
-    pmSourceTmpF tmpFlags;		///< internal-only flags
+    pmSourceTmpF tmpFlags;              ///< internal-only flags
     psArray *blends;                    ///< collection of sources thought to be confused with object
     float psfMag;                       ///< calculated from flux in modelPSF
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceContour.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceContour.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceContour.c	(revision 23225)
@@ -59,5 +59,5 @@
 {
 
-    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
 
     // We define variables incr and lastColumn so that we can use the same loop
@@ -80,10 +80,10 @@
         float value = image->data.F32[y][subCol];
         if (value <= threshold) {
-            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
             return (subCol);
         }
         subCol += incr;
     }
-    psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return (lastColumn);
 }
@@ -99,5 +99,5 @@
 {
 
-    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
 
     // We define variables incr and lastColumn so that we can use the same loop
@@ -119,5 +119,5 @@
         float value = image->data.F32[y][subCol];
         if (value >= threshold) {
-            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
             if (subCol == x) {
                 return (subCol);
@@ -127,5 +127,5 @@
         subCol += incr;
     }
-    psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return (lastColumn);
 }
@@ -149,5 +149,5 @@
                        psU32 dir)
 {
-    psTrace("psModules.objects", 4, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     //
     // Convert coords to subImage space.
@@ -159,9 +159,9 @@
     if (!((0 <= subCol) && (subCol < source->pixels->numCols))) {
         psError(PS_ERR_UNKNOWN, true, "Starting column outside subImage range");
-        psTrace("psModules.objects", 4, "---- %s(NAN) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(NAN) end ----\n", __func__);
         return(NAN);
     }
     if (!((0 <= subRow) && (subRow < source->pixels->numRows))) {
-        psTrace("psModules.objects", 4, "---- %s(NAN) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(NAN) end ----\n", __func__);
         psError(PS_ERR_UNKNOWN, true, "Starting row outside subImage range");
         return(NAN);
@@ -172,5 +172,5 @@
     psF32 oldValue = pmModelEval(source->modelEXT, source->pixels, subCol, subRow);
     if (oldValue == level) {
-        psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
         return(((psF32) (subCol + source->pixels->col0)));
     }
@@ -194,5 +194,5 @@
         psF32 newValue = pmModelEval(source->modelEXT, source->pixels, subCol, subRow);
         if (oldValue == level) {
-            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
             return((psF32) (subCol + source->pixels->col0));
         }
@@ -200,5 +200,5 @@
         if ((newValue <= level) && (level <= oldValue)) {
             // This is simple linear interpolation.
-            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
             return( ((psF32) (subCol + source->pixels->col0)) + ((psF32) incr) * ((level - newValue) / (oldValue - newValue)) );
         }
@@ -206,5 +206,5 @@
         if ((oldValue <= level) && (level <= newValue)) {
             // This is simple linear interpolation.
-            psTrace("psModules.objects", 4, "---- %s() end ----\n", __func__);
+            psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
             return( ((psF32) (subCol + source->pixels->col0)) + ((psF32) incr) * ((level - oldValue) / (newValue - oldValue)) );
         }
@@ -213,5 +213,5 @@
     }
 
-    psTrace("psModules.objects", 4, "---- %s(NAN) end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s(NAN) end ----\n", __func__);
     return(NAN);
 }
@@ -222,5 +222,5 @@
 psArray *pmSourceContour (psImage *image, int xc, int yc, float threshold)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(image, NULL);
 
@@ -339,5 +339,5 @@
     tmpArray->data[0] = (psPtr *) xVec;
     tmpArray->data[1] = (psPtr *) yVec;
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(tmpArray);
 }
@@ -360,5 +360,5 @@
                                psF32 level)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(source, false);
     PS_ASSERT_PTR_NON_NULL(image, false);
@@ -390,5 +390,5 @@
             psFree(xVec);
             psFree(yVec);
-            psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+            psTrace("psModules.objects", 10, "---- %s(NULL) end ----\n", __func__);
             return(NULL);
             //psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not find contour edge (NAN)\n");
@@ -403,5 +403,5 @@
             psFree(xVec);
             psFree(yVec);
-            psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+            psTrace("psModules.objects", 10, "---- %s(NULL) end ----\n", __func__);
             return(NULL);
             //psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not find contour edge (NAN)\n");
@@ -428,5 +428,5 @@
             psFree(xVec);
             psFree(yVec);
-            psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+            psTrace("psModules.objects", 10, "---- %s(NULL) end ----\n", __func__);
             return(NULL);
             //psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not find contour edge (NAN)\n");
@@ -440,5 +440,5 @@
             psFree(xVec);
             psFree(yVec);
-            psTrace("psModules.objects", 3, "---- %s(NULL) end ----\n", __func__);
+            psTrace("psModules.objects", 10, "---- %s(NULL) end ----\n", __func__);
             return(NULL);
             //psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not find contour edge (NAN)\n");
@@ -457,5 +457,5 @@
     tmpArray->data[0] = (psPtr *) yVec;
     tmpArray->data[1] = (psPtr *) xVec;
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(tmpArray);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceFitModel.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceFitModel.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceFitModel.c	(revision 23225)
@@ -58,5 +58,5 @@
                        psImageMaskType maskVal)
 {
-    psTrace("psModules.objects", 5, "---- %s begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(source, false);
     PS_ASSERT_PTR_NON_NULL(source->pixels, false);
@@ -231,5 +231,5 @@
 
     rc = (onPic && fitStatus);
-    psTrace("psModules.objects", 5, "---- %s(%d) end ----\n", __func__, rc);
+    psTrace("psModules.objects", 10, "---- %s(%d) end ----\n", __func__, rc);
     return(rc);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceFitSet.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceFitSet.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceFitSet.c	(revision 23225)
@@ -446,5 +446,5 @@
                      psImageMaskType maskVal)
 {
-    psTrace("psModules.objects", 3, "---- %s begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(source, false);
     PS_ASSERT_PTR_NON_NULL(source->pixels, false);
@@ -533,5 +533,5 @@
     if (nPix <  thisSet->nParamSet + 1) {
         psTrace (__func__, 4, "insufficient valid pixels\n");
-        psTrace("psModules.objects", 3, "---- %s() end : fail pixels ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s() end : fail pixels ----\n", __func__);
         for (int i = 0; i < modelSet->n; i++) {
             pmModel *model = modelSet->data[i];
@@ -602,5 +602,5 @@
 
     bool rc = (onPic && fitStatus);
-    psTrace("psModules.objects", 5, "---- %s end (%d) ----\n", __func__, rc);
+    psTrace("psModules.objects", 10, "---- %s end (%d) ----\n", __func__, rc);
     return(rc);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c	(revision 23225)
@@ -209,17 +209,23 @@
     }
 
+    psMetadata *header = psMetadataCopy(NULL, tableHeader);
+    pmSourceMasksHeader(header);
+
     if (table->n == 0) {
-        psFitsWriteBlank (fits, tableHeader, extname);
-        psFree (table);
+        psFitsWriteBlank(fits, header, extname);
+        psFree(table);
+        psFree(header);
         return true;
     }
 
     psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
-    if (!psFitsWriteTable (fits, tableHeader, table, extname)) {
+    if (!psFitsWriteTable(fits, header, table, extname)) {
         psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
         psFree(table);
+        psFree(header);
         return false;
     }
-    psFree (table);
+    psFree(table);
+    psFree(header);
 
     return true;
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMasks.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMasks.c	(revision 23225)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMasks.c	(revision 23225)
@@ -0,0 +1,48 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmSourceMasks.h"
+
+#define ADD_MASK(HEADER, NAME, COMMENT) \
+    psMetadataAddU32(HEADER, PS_LIST_TAIL, "SOURCE.MASK." #NAME, \
+                     PS_META_REPLACE, COMMENT, (psU32)PM_SOURCE_MODE_##NAME);
+
+bool pmSourceMasksHeader(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    ADD_MASK(header, PSFMODEL        , "Fit with PSF model");
+    ADD_MASK(header, EXTMODEL        , "Fit with extended model");
+    ADD_MASK(header, FITTED          , "Fit with non-linear model");
+    ADD_MASK(header, FAIL            , "Non-linear fit failed");
+    ADD_MASK(header, POOR            , "Non-linear fit poor");
+    ADD_MASK(header, PAIR            , "Fit with double PSF");
+    ADD_MASK(header, PSFSTAR         , "Used to define PSF model");
+    ADD_MASK(header, SATSTAR         , "Model peak is above saturation");
+    ADD_MASK(header, BLEND           , "Blended with other sources");
+    ADD_MASK(header, EXTERNAL        , "Based on supplied input position");
+    ADD_MASK(header, BADPSF          , "Unable to estimate object PSF");
+    ADD_MASK(header, DEFECT          , "Suspected defect");
+    ADD_MASK(header, SATURATED       , "Suspected saturated (bleed trail)");
+    ADD_MASK(header, CR_LIMIT        , "Suspected cosmic ray");
+    ADD_MASK(header, EXT_LIMIT       , "Suspected extended");
+    ADD_MASK(header, MOMENTS_FAILURE , "Failed to measure moments");
+    ADD_MASK(header, SKY_FAILURE     , "Failed to measure local sky");
+    ADD_MASK(header, SKYVAR_FAILURE  , "Failed to measure sky variance");
+    ADD_MASK(header, BELOW_MOMENTS_SN, "Moments not measured due to low S/N");
+    ADD_MASK(header, BIG_RADIUS      , "Small radius has poor moments");
+    ADD_MASK(header, AP_MAGS         , "Measured aperture magnitude");
+    ADD_MASK(header, BLEND_FIT       , "Fit as a blend");
+    ADD_MASK(header, EXTENDED_FIT    , "Fit with full extended fit");
+    ADD_MASK(header, EXTENDED_STATS  , "Calculated extended aperture stats");
+    ADD_MASK(header, LINEAR_FIT      , "Fit with linear fit");
+    ADD_MASK(header, NONLINEAR_FIT   , "Fit with non-linear fit");
+    ADD_MASK(header, RADIAL_FLUX     , "Calculated radial flux measurements");
+    ADD_MASK(header, SIZE_SKIPPED    , "Could not be determine size");
+
+    return true;
+}
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMasks.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMasks.h	(revision 23225)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMasks.h	(revision 23225)
@@ -0,0 +1,46 @@
+#ifndef PM_SOURCE_MASKS_H
+#define PM_SOURCE_MASKS_H
+
+// Bit flags to distinguish analysis results
+// When adding to or subtracting from this list, please also modify pmSourceMaskHeader
+typedef enum {
+    PM_SOURCE_MODE_DEFAULT          = 0x00000000, ///< Initial value: resets all bits
+    PM_SOURCE_MODE_PSFMODEL         = 0x00000001, ///< Source fitted with a psf model (linear or non-linear)
+    PM_SOURCE_MODE_EXTMODEL         = 0x00000002, ///< Source fitted with an extended-source model
+    PM_SOURCE_MODE_FITTED           = 0x00000004, ///< Source fitted with non-linear model (PSF or EXT; good or bad)
+    PM_SOURCE_MODE_FAIL             = 0x00000008, ///< Fit (non-linear) failed (non-converge, off-edge, run to zero)
+    PM_SOURCE_MODE_POOR             = 0x00000010, ///< Fit succeeds, but low-SN, high-Chisq, or large (for PSF -- drop?)
+    PM_SOURCE_MODE_PAIR             = 0x00000020, ///< Source fitted with a double psf
+    PM_SOURCE_MODE_PSFSTAR          = 0x00000040, ///< Source used to define PSF model
+    PM_SOURCE_MODE_SATSTAR          = 0x00000080, ///< Source model peak is above saturation
+    PM_SOURCE_MODE_BLEND            = 0x00000100, ///< Source is a blend with other sourcers
+    PM_SOURCE_MODE_EXTERNAL         = 0x00000200, ///< Source based on supplied input position
+    PM_SOURCE_MODE_BADPSF           = 0x00000400, ///< Failed to get good estimate of object's PSF
+    PM_SOURCE_MODE_DEFECT           = 0x00000800, ///< Source is thought to be a defect
+    PM_SOURCE_MODE_SATURATED        = 0x00001000, ///< Source is thought to be saturated pixels (bleed trail)
+    PM_SOURCE_MODE_CR_LIMIT         = 0x00002000, ///< Source has crNsigma above limit
+    PM_SOURCE_MODE_EXT_LIMIT        = 0x00004000, ///< Source has extNsigma above limit
+    PM_SOURCE_MODE_MOMENTS_FAILURE  = 0x00008000, ///< could not measure the moments
+    PM_SOURCE_MODE_SKY_FAILURE      = 0x00010000, ///< could not measure the local sky
+    PM_SOURCE_MODE_SKYVAR_FAILURE   = 0x00020000, ///< could not measure the local sky variance
+    PM_SOURCE_MODE_BELOW_MOMENTS_SN = 0x00040000, ///< moments not measured due to low S/N
+    PM_SOURCE_MODE_BIG_RADIUS       = 0x00100000, ///< poor moments for small radius, try large radius
+    PM_SOURCE_MODE_AP_MAGS          = 0x00200000, ///< source has an aperture magnitude
+    PM_SOURCE_MODE_BLEND_FIT        = 0x00400000, ///< source was fitted as a blend
+    PM_SOURCE_MODE_EXTENDED_FIT     = 0x00800000, ///< full extended fit was used
+    PM_SOURCE_MODE_EXTENDED_STATS   = 0x01000000, ///< extended aperture stats calculated
+    PM_SOURCE_MODE_LINEAR_FIT       = 0x02000000, ///< source fitted with the linear fit
+    PM_SOURCE_MODE_NONLINEAR_FIT    = 0x04000000, ///< source fitted with the non-linear fit
+    PM_SOURCE_MODE_RADIAL_FLUX      = 0x08000000, ///< radial flux measurements calculated
+    PM_SOURCE_MODE_SIZE_SKIPPED     = 0x10000000, ///< size could not be determined
+} pmSourceMode;
+
+
+/// Populate header with mask values
+bool pmSourceMasksHeader(
+    psMetadata *header                  ///< Header to populate
+    );
+
+
+
+#endif
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMatch.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMatch.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMatch.c	(revision 23225)
@@ -63,8 +63,8 @@
         pmSource *source = sources->data[i]; // Source of interest
         if (!source) continue;
-	if (source->mode & SOURCE_MASK) continue;
-	if (!isfinite(source->psfMag)) continue;
-	if (!isfinite(source->errMag)) continue;
-	if (source->psfMag > SOURCE_FAINTEST) continue;
+        if (source->mode & SOURCE_MASK) continue;
+        if (!isfinite(source->psfMag)) continue;
+        if (!isfinite(source->errMag)) continue;
+        if (source->psfMag > SOURCE_FAINTEST) continue;
 
         float xSrc, ySrc;               // Coordinates of source
@@ -290,4 +290,5 @@
 static float sourceMatchRelphotIterate(psVector *trans, // Transparencies
                                        psVector *stars, // Star magnitudes
+                                       psVector *badImage, // Bad image mask
                                        const psArray *matches, // Array of matches
                                        const psVector *zp, // Zero points for each image (incl. airmass term)
@@ -363,5 +364,7 @@
     for (int i = 0; i < numImages; i++) {
         trans->data.F32[i] = accum->data.F64[i] / accumErr->data.F64[i];
-
+        if (!isfinite(trans->data.F32[i])) {
+            badImage->data.U8[i] = 0xFF;
+        }
         psTrace("psModules.objects", 3, "Transparency for image %d: %f\n", i, trans->data.F32[i]);
     }
@@ -379,4 +382,7 @@
             }
             int index = match->image->data.U32[j]; // Image index
+            if (badImage->data.U8[index]) {
+                continue;
+            }
             float mag = match->mag->data.F32[j]; // Measured magnitude
             float magErr2 = PS_SQR(match->magErr->data.F32[j]) + sysErr2; // Error in measured magnitude
@@ -402,4 +408,5 @@
 static int sourceMatchRelphotPhotometric(psVector *photo, // Photometric determination
                                          const psVector *trans, // Estimated transparencies
+                                         const psVector *badImage, // Bad image?
                                          int transIter, // Iterations for transparency
                                          float transClip, // Clipping level for transparency
@@ -409,8 +416,10 @@
     psAssert(photo && photo->type.type == PS_TYPE_U8, "Need photometric determination");
     psAssert(trans && trans->type.type == PS_TYPE_F32, "Need transparencies");
+    psAssert(badImage && badImage->type.type == PS_TYPE_U8, "Need bad image determination");
 
     int numImages = photo->n;              // Number of images
 
     psAssert(trans->n == numImages, "Not enough transparencies: %ld", trans->n);
+    psAssert(badImage->n == numImages, "Not enough bad image determinations: %ld", badImage->n);
     psAssert(transIter >= 0, "Iterations for transparency must be non-negative: %d", transIter);
     psAssert(transClip > 0, "Clipping level for transparency must be positive: %f", transClip);
@@ -421,5 +430,5 @@
     stats->clipSigma = transClip;
 
-    if (!psVectorStats(stats, trans, NULL, NULL, 0)) {
+    if (!psVectorStats(stats, trans, NULL, badImage, 0xFF)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to perform statistics on transparencies.");
         psFree(stats);
@@ -432,4 +441,7 @@
     int numPhoto = 0;                   // Number of photometric images
     for (int i = 0; i < numImages; i++) {
+        if (badImage->data.U8[i]) {
+            continue;
+        }
         if (trans->data.F32[i] < thresh) {
             photo->data.U8[i] = 0xFF;
@@ -451,4 +463,5 @@
                                       const psVector *zp, // Zero points for each image
                                       const psVector *photo, // Photometric image?
+                                      const psVector *badImage, // Bad image?
                                       float starClip, // Clipping for stars
                                       float sysErr2 // Systematic error squared
@@ -468,4 +481,6 @@
     psAssert(!photo || photo->type.type == PS_TYPE_U8, "Photometric determination is wrong type");
     psAssert(!photo || photo->n == numImages, "Not enough photometric determinations: %ld", photo->n);
+    psAssert(!badImage || badImage->type.type == PS_TYPE_U8, "Photometric determination is wrong type");
+    psAssert(!badImage || badImage->n == numImages, "Not enough bad determinations: %ld", badImage->n);
 
     starClip = PS_SQR(starClip);
@@ -481,4 +496,7 @@
             numMeasurements++;
             int index = match->image->data.U32[j]; // Image index
+            if (badImage->data.U8[index]) {
+                continue;
+            }
             float mag = match->mag->data.F32[j]; // Measured magnitude
             float magErr = match->magErr->data.F32[j]; // Error in measured magnitude
@@ -489,12 +507,12 @@
             float dev = mag + cal - stars->data.F32[i]; // Deviation
 
-	    // only reject detections from photometric images (non-photometric images can
-	    // have large errors.  XXX Or: allow a much higher rejection threshold
-	    if (photo->data.U8[index]) {
-	      if (PS_SQR(dev) > starClip * (PS_SQR(magErr) + sysErr2)) {
-                numRejected++;
-                match->mask->data.PS_TYPE_VECTOR_MASK_DATA[j] = 0xFF;
-	      }
-	    }
+            // only reject detections from photometric images (non-photometric images can
+            // have large errors.  XXX Or: allow a much higher rejection threshold
+            if (photo->data.U8[index]) {
+                if (PS_SQR(dev) > starClip * (PS_SQR(magErr) + sysErr2)) {
+                    numRejected++;
+                    match->mask->data.PS_TYPE_VECTOR_MASK_DATA[j] = 0xFF;
+                }
+            }
         }
     }
@@ -506,12 +524,15 @@
 psVector *pmSourceMatchRelphot(const psArray *matches, // Array of matches
                                const psVector *zp, // Zero points for each image (including airmass term)
-                               int maxIter, // Maximum number of iterations
                                float tol, // Relative tolerance for convergence
+                               int iter1, // Number of iterations for pass 1
+                               float rej1, // Limit on rejection between iterations for pass 1
+                               float sys1, // Systematic error in measurements for pass 1
+                               int iter2, // Number of iterations for pass 2
+                               float rej2, // Limit on rejection between iterations for pass 2
+                               float sys2, // Systematic error in measurements for pass 2
                                float rejLimit, // Limit on rejection between iterations
                                int transIter, // Clipping iterations for transparency
                                float transClip, // Clipping level for transparency
-                               float photoLevel, // Level at which we declare image is photometric
-                               float starClip, // Clipping for stars
-                               float sysErr // Systematic error in measurements
+                               float photoLevel // Level at which we declare image is photometric
                                )
 {
@@ -521,5 +542,6 @@
     PS_ASSERT_FLOAT_LARGER_THAN(transClip, 0.0, NULL);
 
-    sysErr *= sysErr;
+    sys1 *= sys1;
+    sys2 *= sys2;
 
     int numImages = zp->n;              // Number of images
@@ -529,39 +551,20 @@
     psVector *photo = psVectorAlloc(numImages, PS_TYPE_U8); // Photometric determination for each image
     psVectorInit(photo, 0);
+    psVector *badImage = psVectorAlloc(numImages, PS_TYPE_U8); // Bad image?
+    psVectorInit(badImage, 0);
     psVector *stars = psVectorAlloc(numStars, PS_TYPE_F32); // Magnitudes for each star
 
-    float chi2 = sourceMatchRelphotIterate(trans, stars, matches, zp, photo, sysErr); // chi^2 for solution
+    float chi2 = sourceMatchRelphotIterate(trans, stars, badImage, matches, zp,
+                                           photo, sys1); // chi^2 for solution
     psTrace("psModules.objects", 1, "Initial: chi^2 = %f\n", chi2);
     float lastChi2 = INFINITY;          // chi^2 on last iteration
     float fracRej = INFINITY;        // Fraction of measurements rejected
 
-    // in the first passes, the transparencies are not well deteremined: use high systematic error and the rejection thresholds
-    for (int i = 0; i < 5; i++) {
+    // In the first passes, the transparencies are not well deteremined: use high systematic error and
+    // rejection thresholds
+    for (int i = 0; i < iter1; i++) {
 
         // Identify photometric nights
-        int numPhoto = sourceMatchRelphotPhotometric(photo, trans, transIter, transClip, photoLevel); // Number of photometric images
-        if (numPhoto < 0) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to perform photometric determination");
-            psFree(trans);
-            psFree(photo);
-            psFree(stars);
-            return NULL;
-        }
-        psTrace("psModules.objects", 3, "Pass 1: Determined %d/%d are photometric", numPhoto, numImages);
-
-	// XXX use 20 sigma rejection and 0.1 mag systematic error (move these to the recipe)
-        fracRej = sourceMatchRelphotReject(trans, stars, matches, zp, photo, 20.0, PS_SQR(0.1));
-        psTrace("psModules.objects", 3, "Pass 1: %f%% of measurements rejected", fracRej * 100);
-
-	// XXX use 0.05 mag systematic error (move these to the recipe)
-        chi2 = sourceMatchRelphotIterate(trans, stars, matches, zp, photo, PS_SQR(0.1)); // chi^2 for solution
-        psTrace("psModules.objects", 1, "Pass 1: iter = %d: chi^2 = %f rejected = %f\n", i, chi2, fracRej);
-    }
-
-    for (int i = 0; i < maxIter && (fabsf(lastChi2 - chi2) > tol * chi2 || fracRej > rejLimit); i++) {
-        lastChi2 = chi2;
-
-        // Identify photometric nights
-        int numPhoto = sourceMatchRelphotPhotometric(photo, trans, transIter, transClip,
+        int numPhoto = sourceMatchRelphotPhotometric(photo, trans, badImage, transIter, transClip,
                                                      photoLevel); // Number of photometric images
         if (numPhoto < 0) {
@@ -572,14 +575,37 @@
             return NULL;
         }
-        psTrace("psModules.objects", 3, "Determined %d/%d are photometric", numPhoto, numImages);
-
-        fracRej = sourceMatchRelphotReject(trans, stars, matches, zp, photo, starClip, sysErr);
-        psTrace("psModules.objects", 3, "%f%% of measurements rejected", fracRej * 100);
-
-        chi2 = sourceMatchRelphotIterate(trans, stars, matches, zp, photo, sysErr); // chi^2 for solution
-        psTrace("psModules.objects", 1, "iter = %d: chi^2 = %f rejected = %f\n", i, chi2, fracRej);
+        psTrace("psModules.objects", 3, "Pass 1: Determined %d/%d are photometric", numPhoto, numImages);
+
+        fracRej = sourceMatchRelphotReject(trans, stars, matches, zp, photo, badImage, rej1, sys1);
+        psTrace("psModules.objects", 3, "Pass 1: %f%% of measurements rejected", fracRej * 100);
+
+        chi2 = sourceMatchRelphotIterate(trans, stars, badImage, matches, zp, photo, sys1);
+        psTrace("psModules.objects", 1, "Pass 1: iter = %d: chi^2 = %f rejected = %f\n", i, chi2, fracRej);
+    }
+
+    for (int i = 0; i < iter2 && (fabsf(lastChi2 - chi2) > tol * chi2 || fracRej > rejLimit); i++) {
+        lastChi2 = chi2;
+
+        // Identify photometric nights
+        int numPhoto = sourceMatchRelphotPhotometric(photo, trans, badImage, transIter, transClip,
+                                                     photoLevel); // Number of photometric images
+        if (numPhoto < 0) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to perform photometric determination");
+            psFree(trans);
+            psFree(photo);
+            psFree(stars);
+            return NULL;
+        }
+        psTrace("psModules.objects", 3, "Pass 2: Determined %d/%d are photometric", numPhoto, numImages);
+
+        fracRej = sourceMatchRelphotReject(trans, stars, matches, zp, photo, badImage, rej2, sys2);
+        psTrace("psModules.objects", 3, "Pass 2: %f%% of measurements rejected", fracRej * 100);
+
+        chi2 = sourceMatchRelphotIterate(trans, stars, badImage, matches, zp, photo, sys2);
+        psTrace("psModules.objects", 1, "Pass 2: iter = %d: chi^2 = %f rejected = %f\n", i, chi2, fracRej);
     }
 
     psFree(photo);
+    psFree(badImage);
     psFree(stars);
 
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMatch.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMatch.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceMatch.h	(revision 23225)
@@ -55,12 +55,15 @@
 psVector *pmSourceMatchRelphot(const psArray *matches, // Array of matches
                                const psVector *zp, // Zero points for each image (including airmass term)
-                               int maxIter, // Maximum number of iterations
                                float tol, // Relative tolerance for convergence
+                               int iter1, // Number of iterations for pass 1
+                               float rej1, // Limit on rejection between iterations for pass 1
+                               float sys1, // Systematic error in measurements for pass 1
+                               int iter2, // Number of iterations for pass 2
+                               float rej2, // Limit on rejection between iterations for pass 2
+                               float sys2, // Systematic error in measurements for pass 2
                                float rejLimit, // Limit on rejection between iterations
                                int transIter, // Clipping iterations for transparency
                                float transClip, // Clipping level for transparency
-                               float photoLevel, // Level at which we declare image is photometric
-                               float starClip, // Clipping for stars
-                               float sysErr // Systematic error in measurements
+                               float photoLevel // Level at which we declare image is photometric
     );
 
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceSky.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceSky.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceSky.c	(revision 23225)
@@ -55,5 +55,5 @@
     psImageMaskType markVal)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(source, false);
     PS_ASSERT_IMAGE_NON_NULL(source->pixels, false);
@@ -91,5 +91,5 @@
 
     if (isnan(value)) {
-        psTrace("psModules.objects", 3, "---- %s(false) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(false) end ----\n", __func__);
         return(false);
     }
@@ -98,5 +98,5 @@
     }
     source->moments->Sky = value;
-    psTrace("psModules.objects", 3, "---- %s(true) end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s(true) end ----\n", __func__);
     return (true);
 }
@@ -111,5 +111,5 @@
 )
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(source, false);
     PS_ASSERT_IMAGE_NON_NULL(source->variance, false);
@@ -147,5 +147,5 @@
 
     if (isnan(value)) {
-        psTrace("psModules.objects", 3, "---- %s(false) end ----\n", __func__);
+        psTrace("psModules.objects", 10, "---- %s(false) end ----\n", __func__);
         return(false);
     }
@@ -154,5 +154,5 @@
     }
     source->moments->dSky = value;
-    psTrace("psModules.objects", 3, "---- %s(true) end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s(true) end ----\n", __func__);
     return (true);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceUtils.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceUtils.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/objects/pmSourceUtils.c	(revision 23225)
@@ -49,5 +49,5 @@
                             pmModelType modelType)
 {
-    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(source, NULL);
     PS_ASSERT_PTR_NON_NULL(source->moments, NULL);
@@ -61,5 +61,5 @@
     }
 
-    psTrace("psModules.objects", 3, "---- %s() end ----\n", __func__);
+    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
     return(model);
 }
Index: /branches/eam_branches/eam_branch_20090303/psModules/src/psmodules.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psModules/src/psmodules.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psModules/src/psmodules.h	(revision 23225)
@@ -113,4 +113,5 @@
 #include <pmPSF.h>
 #include <pmModel.h>
+#include <pmSourceMasks.h>
 #include <pmSource.h>
 #include <pmSourceUtils.h>
Index: /branches/eam_branches/eam_branch_20090303/psastro/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psastro/src/Makefile.am	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psastro/src/Makefile.am	(revision 23225)
@@ -1,15 +1,12 @@
 lib_LTLIBRARIES = libpsastro.la
 
-# PSASTRO_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
-# PSASTRO_BRANCH=`if [ -e ../../BRANCH ]; then cat ../../BRANCH; else svn info | sed -n -e '/URL:/ h' -e '/Repository Root:/ { x; H; x; s|Repository Root: \(.*\)\nURL: \1\(.*\)|\2| ; s|^/|| ; s|/[a-zA-Z]*/src.*|| ; p }'; fi`
-# PSASTRO_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
-# 
-# # Force recompilation of psastroVersion.c, since it gets the version information
+libpsastro_la_CFLAGS = $(PSASTRO_CFLAGS) $(PPSTATS_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) -DPSASTRO_VERSION=$(SVN_VERSION) -DPSASTRO_BRANCH=$(SVN_BRANCH) -DPSASTRO_SOURCE=$(SVN_SOURCE)
+libpsastro_la_LDFLAGS = $(PSASTRO_LIBS) $(PPSTATS_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
+
+# Force recompilation of psastroVersion.c, since it gets the version information
+# can we do this with dependency info?
 # psastroVersion.c: FORCE
-# 	touch psastroVersion.c
+# touch psastroVersion.c
 # FORCE: ;
-
-libpsastro_la_CFLAGS = $(PSASTRO_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) -DPSASTRO_VERSION=$(SVN_VERSION) -DPSASTRO_BRANCH=$(SVN_BRANCH) -DPSASTRO_SOURCE=$(SVN_SOURCE)
-libpsastro_la_LDFLAGS = $(PSASTRO_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
 
 bin_PROGRAMS = psastro psastroModel psastroModelFit gpcModel
Index: /branches/eam_branches/eam_branch_20090303/psastro/src/psastro.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psastro/src/psastro.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psastro/src/psastro.c	(revision 23225)
@@ -34,8 +34,10 @@
     if (!config) usage ();
 
+    psastroVersionPrint();
+
     // load identify the data sources
     if (!psastroParseCamera (config)) {
-	psErrorStackPrint(stderr, "error setting up the camera\n");
-	exit (1);
+        psErrorStackPrint(stderr, "error setting up the camera\n");
+        exit (1);
     }
 
@@ -43,18 +45,18 @@
     // select subset of stars for astrometry
     if (!psastroDataLoad (config)) {
-	psErrorStackPrint(stderr, "error loading input data\n");
-	exit (1);
+        psErrorStackPrint(stderr, "error loading input data\n");
+        exit (1);
     }
 
     // run the full astrometry analysis (chip and/or mosaic)
     if (!psastroAnalysis (config)) {
-	psErrorStackPrint(stderr, "failure in psastro analysis\n");
-	exit (1);
+        psErrorStackPrint(stderr, "failure in psastro analysis\n");
+        exit (1);
     }
-    
+
     // write out the results
     if (!psastroDataSave (config)) {
-	psErrorStackPrint(stderr, "failed to write out data\n");
-	exit (1);
+        psErrorStackPrint(stderr, "failed to write out data\n");
+        exit (1);
     }
 
Index: /branches/eam_branches/eam_branch_20090303/psastro/src/psastro.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psastro/src/psastro.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psastro/src/psastro.h	(revision 23225)
@@ -98,4 +98,6 @@
 psString          psastroVersionLong(void);
 bool              psastroVersionHeader(psMetadata *header);
+bool              psastroVersionHeaderFull(psMetadata *header);
+void              psastroVersionPrint(void);
 
 // demo plots
Index: /branches/eam_branches/eam_branch_20090303/psastro/src/psastroDataSave.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psastro/src/psastroDataSave.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psastro/src/psastroDataSave.c	(revision 23225)
@@ -18,5 +18,5 @@
   return false; \
 }
-  
+
 /**
  * this loop saves the photometry/astrometry data files
@@ -31,6 +31,6 @@
     psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, PSASTRO_RECIPE);
     if (!recipe) {
-	psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe!\n");
-	return false;
+        psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe!\n");
+        return false;
     }
 
@@ -38,6 +38,6 @@
     pmFPAfile *output = psMetadataLookupPtr (NULL, config->files, "PSASTRO.OUTPUT");
     if (!output) {
-	psError(PSASTRO_ERR_CONFIG, true, "Can't find or interpret output file rule PSASTRO.OUTPUT!\n");
-	return false;
+        psError(PSASTRO_ERR_CONFIG, true, "Can't find or interpret output file rule PSASTRO.OUTPUT!\n");
+        return false;
     }
 
@@ -48,4 +48,5 @@
 
     pmFPAview *view = pmFPAviewAlloc (0);
+    pmHDU *lastHDU = NULL;              // Last HDU updated
 
     // open/load files as needed
@@ -55,21 +56,28 @@
         psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
         if (!chip->process || !chip->file_exists) { continue; }
-	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
 
-	while ((cell = pmFPAviewNextCell (view, output->fpa, 1)) != NULL) {
+        while ((cell = pmFPAviewNextCell (view, output->fpa, 1)) != NULL) {
             psTrace ("psastro", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
             if (!cell->process || !cell->file_exists) { continue; }
-	    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+            if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
 
-	    // process each of the readouts
-	    while ((readout = pmFPAviewNextReadout (view, output->fpa, 1)) != NULL) {
-		if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
-		if (!readout->data_exists) { continue; }
+            // process each of the readouts
+            while ((readout = pmFPAviewNextReadout (view, output->fpa, 1)) != NULL) {
+                if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+                if (!readout->data_exists) { continue; }
 
-		if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
-	    }
-	    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
-	}
-	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+                // Put version information into the header
+                pmHDU *hdu = pmHDUGetHighest(output->fpa, chip, cell);
+                if (hdu && hdu != lastHDU) {
+                    psastroVersionHeaderFull(hdu->header);
+                    lastHDU = hdu;
+                }
+
+                if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+            }
+            if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+        }
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
     }
     if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
Index: /branches/eam_branches/eam_branch_20090303/psastro/src/psastroVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psastro/src/psastroVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psastro/src/psastroVersion.c	(revision 23225)
@@ -61,7 +61,7 @@
 
     psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSASTRO.VERSION", PS_META_REPLACE,
-                     "psastro software version", version);
+                     "Software version", version);
     psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSASTRO.SOURCE", PS_META_REPLACE,
-                     "psastro software source", source);
+                     "S/W source", source);
 
     psFree(version);
@@ -70,2 +70,49 @@
     return true;
 }
+
+bool psastroVersionHeaderFull(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "psastro at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    ppStatsVersionHeader(header);
+    psastroVersionHeader(header);
+
+    return true;
+}
+
+void psastroVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("psastro", PS_LOG_INFO, "psastro at %s", timeString);
+    psFree(timeString);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString ppStats = ppStatsVersionLong(); // ppStats version
+    psString psastro = psastroVersionLong(); // psastro version
+
+    psLogMsg("psastro", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("psastro", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("psastro", PS_LOG_INFO, "%s", ppStats);
+    psLogMsg("psastro", PS_LOG_INFO, "%s", psastro);
+
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(ppStats);
+    psFree(psastro);
+
+    return;
+}
Index: /branches/eam_branches/eam_branch_20090303/psphot/src/psphot.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psphot/src/psphot.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psphot/src/psphot.c	(revision 23225)
@@ -9,5 +9,5 @@
 
     psTimerStart ("complete");
-    pmErrorRegister();			// register psModule's error codes/messages
+    pmErrorRegister();                  // register psModule's error codes/messages
     psphotInit();
 
@@ -15,7 +15,9 @@
     pmConfig *config = psphotArguments (argc, argv);
     if (!config) {
-	psErrorStackPrint(stderr, "Error reading arguments\n");
-	usage ();
+        psErrorStackPrint(stderr, "Error reading arguments\n");
+        usage ();
     }
+
+    psphotVersionPrint();
 
     // load input data (config and images (signal, noise, mask)
Index: /branches/eam_branches/eam_branch_20090303/psphot/src/psphot.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psphot/src/psphot.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psphot/src/psphot.h	(revision 23225)
@@ -19,4 +19,6 @@
 psString        psphotVersionLong(void);
 bool            psphotVersionHeader(psMetadata *header);
+bool            psphotVersionHeaderFull(psMetadata *header);
+void            psphotVersionPrint(void);
 
 bool            psphotModelTest (pmConfig *config, const pmFPAview *view, psMetadata *recipe);
Index: /branches/eam_branches/eam_branch_20090303/psphot/src/psphotImageLoop.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psphot/src/psphotImageLoop.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psphot/src/psphotImageLoop.c	(revision 23225)
@@ -26,4 +26,5 @@
 
     pmFPAview *view = pmFPAviewAlloc (0);
+    pmHDU *lastHDU = NULL;              // Last HDU updated
 
     // files associated with the science image
@@ -64,4 +65,13 @@
                 psLogMsg ("psphot", 6, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
                 if (! readout->data_exists) { continue; }
+
+                // Update the header
+                {
+                    pmHDU *hdu = pmHDUGetHighest(input->fpa, chip, cell);
+                    if (hdu && hdu != lastHDU) {
+                        psphotVersionHeaderFull(hdu->header);
+                        lastHDU = hdu;
+                    }
+                }
 
                 // run the actual photometry analysis on this chip/cell/readout
Index: /branches/eam_branches/eam_branch_20090303/psphot/src/psphotSetThreads.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psphot/src/psphotSetThreads.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psphot/src/psphotSetThreads.c	(revision 23225)
@@ -25,5 +25,5 @@
     psFree(task);
 
-    task = psThreadTaskAlloc("PSPHOT_SOURCE_STATS", 4);
+    task = psThreadTaskAlloc("PSPHOT_SOURCE_STATS", 5);
     task->function = &psphotSourceStats_Threaded;
     psThreadTaskAdd(task);
Index: /branches/eam_branches/eam_branch_20090303/psphot/src/psphotSourceStats.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psphot/src/psphotSourceStats.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psphot/src/psphotSourceStats.c	(revision 23225)
@@ -15,5 +15,5 @@
     int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     if (!status) {
-	nThreads = 0;
+        nThreads = 0;
     }
 
@@ -41,8 +41,8 @@
         pmSource *source = pmSourceAlloc();
 
-	// add the peak
+        // add the peak
         source->peak = psMemIncrRefCounter(peak);
 
-	// allocate space for moments
+        // allocate space for moments
         source->moments = pmMomentsAlloc();
 
@@ -50,14 +50,14 @@
         pmSourceDefinePixels (source, readout, source->peak->x, source->peak->y, OUTER);
 
-	peak->assigned = true;
-	psArrayAdd (sources, 100, source);
-	psFree (source);
+        peak->assigned = true;
+        psArrayAdd (sources, 100, source);
+        psFree (source);
     }
 
     if (!strcasecmp (breakPt, "PEAKS")) {
-	psLogMsg ("psphot", PS_LOG_INFO, "%ld sources : %f sec\n", sources->n, psTimerMark ("psphot.stats"));
-	psLogMsg ("psphot", PS_LOG_INFO, "break point PEAKS, skipping MOMENTS\n");
-	psphotVisualShowMoments (sources);
-	return sources;
+        psLogMsg ("psphot", PS_LOG_INFO, "%ld sources : %f sec\n", sources->n, psTimerMark ("psphot.stats"));
+        psLogMsg ("psphot", PS_LOG_INFO, "break point PEAKS, skipping MOMENTS\n");
+        psphotVisualShowMoments (sources);
+        return sources;
     }
 
@@ -65,4 +65,5 @@
     int Nfail = 0;
     int Nmoments = 0;
+    int Nfaint = 0;
 
     // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
@@ -74,60 +75,63 @@
     for (int i = 0; i < cellGroups->n; i++) {
 
-	psArray *cells = cellGroups->data[i];
-
-	for (int j = 0; j < cells->n; j++) {
-
-	    // allocate a job -- if threads are not defined, this just runs the job
-	    psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS");
-
-	    psArrayAdd(job->args, 1, cells->data[j]); // sources
-	    psArrayAdd(job->args, 1, recipe);
-	    PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nmoments
-	    PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfail
-
-	    if (!psThreadJobAddPending(job)) {
-		psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
-		psFree (job);
-		return NULL;
-	    }
-	    psFree(job);
+        psArray *cells = cellGroups->data[i];
+
+        for (int j = 0; j < cells->n; j++) {
+
+            // allocate a job -- if threads are not defined, this just runs the job
+            psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS");
+
+            psArrayAdd(job->args, 1, cells->data[j]); // sources
+            psArrayAdd(job->args, 1, recipe);
+            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nmoments
+            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfail
+            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfaint
+
+            if (!psThreadJobAddPending(job)) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
+                psFree (job);
+                return NULL;
+            }
+            psFree(job);
 
 # if (0)
-		int nfail = 0;
-		int nmoments = 0;
-		if (!psphotSourceStats_Unthreaded (&nfail, &nmoments, cells->data[j], recipe)) {
-		    psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
-		    return NULL;
-		}
-		Nfail += nfail;
-		Nmoments += nmoments;
+                int nfail = 0;
+                int nmoments = 0;
+                if (!psphotSourceStats_Unthreaded (&nfail, &nmoments, cells->data[j], recipe)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
+                    return NULL;
+                }
+                Nfail += nfail;
+                Nmoments += nmoments;
 # endif
-	}
-
-	// wait for the threads to finish and manage results
-	if (!psThreadPoolWait (false)) {
-	    psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
-	    return NULL;
-	}
-
-	// we have only supplied one type of job, so we can assume the types here
-	psThreadJob *job = NULL;
-	while ((job = psThreadJobGetDone()) != NULL) {
-	    if (job->args->n < 1) {
-		fprintf (stderr, "error with job\n");
-	    } else {
-		psScalar *scalar = NULL;
-		scalar = job->args->data[2];
-		Nmoments += scalar->data.S32;
-		scalar = job->args->data[3];
-		Nfail += scalar->data.S32;
-	    }
-	    psFree(job);
-	}
+        }
+
+        // wait for the threads to finish and manage results
+        if (!psThreadPoolWait (false)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
+            return NULL;
+        }
+
+        // we have only supplied one type of job, so we can assume the types here
+        psThreadJob *job = NULL;
+        while ((job = psThreadJobGetDone()) != NULL) {
+            if (job->args->n < 1) {
+                fprintf (stderr, "error with job\n");
+            } else {
+                psScalar *scalar = NULL;
+                scalar = job->args->data[2];
+                Nmoments += scalar->data.S32;
+                scalar = job->args->data[3];
+                Nfail += scalar->data.S32;
+                scalar = job->args->data[4];
+                Nfaint += scalar->data.S32;
+            }
+            psFree(job);
+        }
     }
 
     psFree (cellGroups);
 
-    psLogMsg ("psphot", PS_LOG_INFO, "%ld sources, %d moments, %d failed: %f sec\n", sources->n, Nmoments, Nfail, psTimerMark ("psphot.stats"));
+    psLogMsg ("psphot", PS_LOG_INFO, "%ld sources, %d moments, %d faint, %d failed: %f sec\n", sources->n, Nmoments, Nfaint, Nfail, psTimerMark ("psphot.stats"));
 
     psphotVisualShowMoments (sources);
@@ -166,4 +170,5 @@
     int Nfail = 0;
     int Nmoments = 0;
+    int Nfaint = 0;
     for (int i = 0; i < sources->n; i++) {
         pmSource *source = sources->data[i];
@@ -171,5 +176,6 @@
         // skip faint sources for moments measurement
         if (source->peak->SN < MIN_SN) {
-	    source->mode |= PM_SOURCE_MODE_BELOW_MOMENTS_SN;
+            source->mode |= PM_SOURCE_MODE_BELOW_MOMENTS_SN;
+            Nfaint++;
             continue;
         }
@@ -179,8 +185,8 @@
         status = pmSourceLocalSky (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
         if (!status) {
-	    source->mode |= PM_SOURCE_MODE_SKY_FAILURE;
-	    psErrorClear(); // XXX re-consider the errors raised here
-	    Nfail ++;
-	    continue;
+            source->mode |= PM_SOURCE_MODE_SKY_FAILURE;
+            psErrorClear(); // XXX re-consider the errors raised here
+            Nfail ++;
+            continue;
         }
 
@@ -189,8 +195,8 @@
         status = pmSourceLocalSkyVariance (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
         if (!status) {
-	    source->mode |= PM_SOURCE_MODE_SKYVAR_FAILURE;
-	    Nfail ++;
-	    psErrorClear();
-	    continue;
+            source->mode |= PM_SOURCE_MODE_SKYVAR_FAILURE;
+            Nfail ++;
+            psErrorClear();
+            continue;
         }
 
@@ -208,10 +214,10 @@
         status = pmSourceMoments (source, BIG_RADIUS);
         if (status) {
-	    source->mode |= PM_SOURCE_MODE_BIG_RADIUS;
+            source->mode |= PM_SOURCE_MODE_BIG_RADIUS;
             Nmoments ++;
             continue;
         }
 
-	source->mode |= PM_SOURCE_MODE_MOMENTS_FAILURE;
+        source->mode |= PM_SOURCE_MODE_MOMENTS_FAILURE;
         Nfail ++;
         psErrorClear();
@@ -225,5 +231,8 @@
     scalar = job->args->data[3];
     scalar->data.S32 = Nfail;
-    
+
+    scalar = job->args->data[4];
+    scalar->data.S32 = Nfaint;
+
     return true;
 }
@@ -268,7 +277,7 @@
         status = pmSourceLocalSky (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
         if (!status) {
-	    psErrorClear(); // XXX re-consider the errors raised here
-	    Nfail ++;
-	    continue;
+            psErrorClear(); // XXX re-consider the errors raised here
+            Nfail ++;
+            continue;
         }
 
@@ -277,7 +286,7 @@
         status = pmSourceLocalSkyVariance (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
         if (!status) {
-	    Nfail ++;
-	    psErrorClear();
-	    continue;
+            Nfail ++;
+            psErrorClear();
+            continue;
         }
 
@@ -307,6 +316,6 @@
     *nmoments = Nmoments;
     *nfail = Nfail;
-    
+
     return true;
 }
-# endif 
+# endif
Index: /branches/eam_branches/eam_branch_20090303/psphot/src/psphotVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/psphot/src/psphotVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/psphot/src/psphotVersion.c	(revision 23225)
@@ -72,7 +72,7 @@
 
     psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSPHOT.VERSION", PS_META_REPLACE,
-                     "psphot software version", version);
+                     "Software version", version);
     psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSPHOT.SOURCE", PS_META_REPLACE,
-                     "psphot software source", source);
+                     "S/W source", source);
 
     psFree(version);
@@ -81,2 +81,47 @@
     return true;
 }
+
+
+bool psphotVersionHeaderFull(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "psphot at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    psphotVersionHeader(header);
+
+    return true;
+}
+
+
+void psphotVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("psphot", PS_LOG_INFO, "psphot at %s", timeString);
+    psFree(timeString);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString psphot = psphotVersionLong(); // psphot version
+
+    psLogMsg("psphot", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("psphot", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("psphot", PS_LOG_INFO, "%s", psphot);
+
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(psphot);
+
+    return;
+}
Index: /branches/eam_branches/eam_branch_20090303/pswarp/src/Makefile.am
===================================================================
--- /branches/eam_branches/eam_branch_20090303/pswarp/src/Makefile.am	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/pswarp/src/Makefile.am	(revision 23225)
@@ -28,5 +28,5 @@
 	pswarpSetThreads.c	        \
 	pswarpTransformReadout.c	\
-	pswarpTransformSources.c \
+	pswarpTransformSources.c 	\
 	pswarpTransformTile.c		\
 	pswarpVersion.c            
Index: /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarp.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarp.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarp.c	(revision 23225)
@@ -39,4 +39,6 @@
     if (!config) usage();
 
+    pswarpVersionPrint();
+
     // load identify the data sources
     if (!pswarpParseCamera(config)) {
Index: /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarp.h
===================================================================
--- /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarp.h	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarp.h	(revision 23225)
@@ -121,2 +121,10 @@
 /// Return long software version information
 psString pswarpVersionLong(void);
+
+/// Populate header with version information
+bool pswarpVersionHeader(
+    psMetadata *header                  ///< Header to populate
+    );
+
+/// Print version information
+void pswarpVersionPrint(void);
Index: /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarpLoop.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarpLoop.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarpLoop.c	(revision 23225)
@@ -339,4 +339,6 @@
     }
 
+    pswarpVersionHeader(hdu->header);
+
     if (!pmAstromWriteWCS(hdu->header, outFPA, outChip, WCS_NONLIN_TOL)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to generate WCS header.");
Index: /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarpVersion.c
===================================================================
--- /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarpVersion.c	(revision 23224)
+++ /branches/eam_branches/eam_branch_20090303/pswarp/src/pswarpVersion.c	(revision 23225)
@@ -18,4 +18,6 @@
 #include <pslib.h>
 #include <psmodules.h>
+#include <psphot.h>
+#include <ppStats.h>
 #include "pswarp.h"
 
@@ -57,2 +59,64 @@
     return version;
 };
+
+
+bool pswarpVersionHeader(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "pswarp at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    psphotVersionHeader(header);
+    ppStatsVersionHeader(header);
+
+    psString version = pswarpVersion(); // Software version
+    psString source  = pswarpSource();  // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSWARP.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSWARP.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
+
+void pswarpVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("pswarp", PS_LOG_INFO, "pswarp at %s", timeString);
+    psFree(timeString);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString psphot = psphotVersionLong(); // psphot version
+    psString ppStats = ppStatsVersionLong(); // ppStats version
+    psString pswarp = pswarpVersionLong(); // pswarp version
+
+    psLogMsg("pswarp", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("pswarp", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("pswarp", PS_LOG_INFO, "%s", psphot);
+    psLogMsg("pswarp", PS_LOG_INFO, "%s", ppStats);
+    psLogMsg("pswarp", PS_LOG_INFO, "%s", pswarp);
+
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(psphot);
+    psFree(ppStats);
+    psFree(pswarp);
+
+    return;
+}
