Index: /branches/cnb_branches/cnb_branch_20090215/Nebulous/Build.PL
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/Build.PL	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/Build.PL	(revision 23199)
@@ -11,39 +11,36 @@
 my $pkg_dir = "./nebclient";
 
-sub ACTION_code {
-    my $self = shift;
-
-    $self->SUPER::ACTION_code(@_);
-
-    my $old_pwd = getcwd();
-    chdir $pkg_dir;
-
-    unless (-e "configure") {
-        system("./autogen.sh") == 0 or die "install failed: $?";
-    }
-
-    chdir $old_pwd;
-}
-
-sub ACTION_build {
-    my $self = shift;
-
-    $self->SUPER::ACTION_build(@_);
-
-    my $old_pwd = getcwd();
-    chdir $pkg_dir;
-
-    unless (-e "Makefile") {
-        system("sh ./configure") == 0 or die "build failed: $?";
-    }
-
-    system("make") == 0 or die "build failed: $?";
-
-    chdir $old_pwd;
-}
-
-# Do not attempt to install nebclient.  It is bundled in this package for
-# testing only.
-#
+# sub ACTION_code {
+#     my $self = shift;
+# 
+#     $self->SUPER::ACTION_code(@_);
+# 
+#     my $old_pwd = getcwd();
+#     chdir $pkg_dir;
+# 
+#     unless (-e "configure") {
+#         system("./autogen.sh") == 0 or die "install failed: $?";
+#     }
+# 
+#     chdir $old_pwd;
+# }
+# 
+# sub ACTION_build {
+#     my $self = shift;
+# 
+#     $self->SUPER::ACTION_build(@_);
+# 
+#     my $old_pwd = getcwd();
+#     chdir $pkg_dir;
+# 
+#     unless (-e "Makefile") {
+#         system("sh ./configure") == 0 or die "build failed: $?";
+#     }
+# 
+#     system("make") == 0 or die "build failed: $?";
+# 
+#     chdir $old_pwd;
+# }
+# 
 # sub ACTION_install {
 #     my $self = shift;
@@ -58,17 +55,17 @@
 #     chdir $old_pwd;
 # }
-
-sub ACTION_clean {
-    my $self = shift;
-
-    $self->SUPER::ACTION_clean(@_);
-
-    my $old_pwd = getcwd();
-    chdir $pkg_dir;
-
-    system("make clean") == 0 or die "install failed: $?";
-
-    chdir $old_pwd;
-}
+# 
+# sub ACTION_clean {
+#     my $self = shift;
+# 
+#     $self->SUPER::ACTION_clean(@_);
+# 
+#     my $old_pwd = getcwd();
+#     chdir $pkg_dir;
+# 
+#     system("make clean") == 0 or die "install failed: $?";
+# 
+#     chdir $old_pwd;
+# }
 EOF
 
Index: /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/nebulous.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/nebulous.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/nebulous.h	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapC.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapC.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapC.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapClient.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapClient.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapClient.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapClientLib.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapClientLib.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapClientLib.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapH.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapH.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapH.h	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapServer.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapServer.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapServer.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapServerLib.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapServerLib.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapServerLib.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapStub.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapStub.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/nebclient/src/soapStub.h	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/Nebulous/scripts/ptest.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/scripts/ptest.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/scripts/ptest.pl	(revision 23199)
@@ -5,27 +5,35 @@
 
 use lib "./lib";
+package main;
 
-use Nebulous::Client;
+#use Nebulous::Client;
 use IO::Select;
 use IO::Socket;
+use POSIX qw(:DEFAULT :sys_wait_h);
+use Hook::LexWrap;
+use Sys::Hostname;
 
-my $neb = Nebulous::Client->new(
-#    proxy   => 'http://localhost:80/nebulous'
-    proxy   => 'http://alala:80/nebulous'
-);
+my $print_stdout = undef;
+
+$| = 1;
 
 my $key = shift || 'foobar';
 my $kids = shift || 1;
 
-my $s = IO::Select->new();
+$key = "/tmp/" . $key;
+
+#my $s = IO::Select->new();
 
 foreach my $id ( 1..$kids ) {
-    my ($sock_parent, $sock_child) = IO::Socket->socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
-    $s->add($sock_parent);
+#    my ($sock_parent, $sock_child) = IO::Socket->socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
+#    $s->add($sock_parent);
 
     my $pid = fork;
 
     unless ( $pid )  {
+        # child
+        my $sock_child = \*STDOUT;
         child($sock_child, $id);
+        shutdown($sock_child, 2);
         exit 0;
     }
@@ -33,55 +41,70 @@
 }
 
-while ($kids) {
-    foreach my $child ($s->can_read(1)) {
-        my $string = <$child>;
-        my @events = split(/\n/, $string) if $string;
-        print join("\n", @events), "\n" if scalar @events;
+$SIG{CHLD} = \&REAPER;
+
+sub REAPER {
+    while ((my $pid = waitpid(-1,WNOHANG)) > 0) {
+        $kids--;
+#        delete $children{$pid};
     }
+    $SIG{CHLD} = \&REAPER;
 }
 
-#while ( $kids ) {
-#    wait();
-#    $kids --;
-#}
 
-our $my_sock;
+while ($kids) {
+#    foreach my $child ($s->can_read(0)) {
+#        my $string = do { local $/; <$child>};
+#        my @events = split(/\n/, $string) if $string;
+#        print join("\n", @events), "\n" if scalar @events;
+#    }
+}
 
 sub child
 {
-    my ($sock_child, $id) = @_;
+    my ($sock, $id) = @_;
 
-    $my_sock = $sock_child;
+    unless ($print_stdout) {
+        my $filename = hostname() . "." . $$ . ".txt";
+        open my $fh, ">$filename" or die "can't open $filename: $!";
+
+        open STDOUT, ">&", $fh or die "can't reopen STDOUT: $!";
+        autoflush STDOUT 1;
+    }
+
+#    select $sock;
+#    $| = 1;
 
     # child
     my $fname = "${key}_$id";
-    print $sock_child "$$ : i'm a little tea pot using key: $fname\n";
-    my $fh = $neb->open_create( $fname );
-    child_die("can't create file $fname") unless $fh;
 
-    print $fh "fooby\n";
+    my $neb = Nebulous::Client::Bench->new(
+#    proxy   => 'http://localhost:80/nebulous'
+        proxy   => 'http://alala:80/nebulous',
+#        sock    => \*STDOUT,
+    );
 
-    close $fh;
 
-    $fh = $neb->open( $fname, 'read' ) or child_die("can't open file");
-    close $fh;
+    while (1) {
+#    print $sock "$$ : i'm a little tea pot using key: $fname\n";
+        my $fh = $neb->open_create( $fname )
+            or child_die($sock, "can't create file $fname");
+        close $fh;
 
-    $neb->lock( $fname, 'read' );
-    $neb->unlock( $fname, 'read' );
-    $neb->replicate( $fname );
-    $neb->cull( $fname );
+        $fh = $neb->open( $fname, 'read' )
+            or child_die("can't open file");
+        close $fh;
 
-    print $sock_child "$$ : half way\n";
+        $neb->lock( $fname, 'read' );
+        $neb->unlock( $fname, 'read' );
+        $neb->replicate( $fname );
+        $neb->cull( $fname );
+        $neb->find( $fname );
+        $neb->copy( $fname, $fname . "_copy" );
+        $neb->move( $fname, $fname . "_move" );
+        $neb->delete( $fname . "_copy" );
+        $neb->delete( $fname . "_move" );
 
-    $neb->find( $fname );
-    $neb->copy( $fname, $fname . "_copy" );
-    $neb->move( $fname, $fname . "_move" );
-    $neb->delete( $fname . "_copy" );
-    $neb->delete( $fname . "_move" );
-
-    print $sock_child "$$ : all done!\n";
-
-    $sock_child->flush;
-    sleep 10;
+#    print $sock "$$ : all done!\n";
+    }
 
     return 1;
@@ -90,6 +113,65 @@
 sub child_die
 {
-    print $my_sock $@;
-    shutdown($my_sock, 2);
+    my $sock = shift;
+    print $sock @_;
+    shutdown($sock, 2);
     exit 1;
 }
+
+package Nebulous::Client::Bench;
+
+use base qw( Nebulous::Client );
+
+#sub new
+#{
+#    my $class = shift;
+#    my %p = @_;
+#
+#    my $sock = delete $p{sock};
+#    my $self = $class->SUPER::new(%p);
+#    $self->{sock} = $sock;
+#
+#    return $self;
+#}
+
+BEGIN {
+sub make_wrapper
+{
+    my $method = shift;
+
+eval "sub $method {"
+.'    my $self = shift;'
+.'    my $smark = Time::HiRes::time();'
+.'    my $ret = $self->SUPER::' . "$method" .'(@_);'
+.'    my $emark = Time::HiRes::time();'
+.'    printf "%-17s %-17s %s\n", $emark, " ' . "$method" . ' ", ($emark - $smark), "\n";'
+.'    return $ret;'
+.'}';
+
+}
+
+make_wrapper("create");
+make_wrapper("open_create");
+make_wrapper("replicate");
+make_wrapper("cull");
+make_wrapper("lock");
+make_wrapper("unlock");
+make_wrapper("setxattr");
+make_wrapper("getxattr");
+make_wrapper("listxattr");
+make_wrapper("removexattr");
+make_wrapper("find_objects");
+make_wrapper("find_instances");
+#make_wrapper("find");
+#make_wrapper("open");
+#make_wrapper("delete");
+#make_wrapper("copy");
+make_wrapper("move");
+make_wrapper("swap");
+make_wrapper("delete_instance");
+make_wrapper("stat");
+make_wrapper("mounts");
+
+}
+
+1;
Index: /branches/cnb_branches/cnb_branch_20090215/Nebulous/scripts/stats.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Nebulous/scripts/stats.pl	(revision 23199)
+++ /branches/cnb_branches/cnb_branch_20090215/Nebulous/scripts/stats.pl	(revision 23199)
@@ -0,0 +1,50 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+use Statistics::Descriptive;
+
+#my $filename = shift or die "Usage: stats.pl <filename>";
+my $filename = shift || "-";
+
+open(my $fh, "$filename") or die "can't open file $filename: $!";
+
+my $data = do {local $/; <$fh>};
+
+my %methods;
+
+foreach my $line (split(/\n/, $data)) {
+    my ($time, $method, $duration) = split(/\s+/, $line);
+
+    push @{$methods{$method}->{time}}, $time;
+    push @{$methods{$method}->{duration}}, $duration;
+}
+
+close($fh) or die "can't close file $filename: $!";
+
+use Data::Dumper;
+
+my $total_stat = Statistics::Descriptive::Sparse->new();
+#print Dumper \%methods;
+foreach my $method (keys %methods) {
+    {
+        my $duration    = $methods{$method}->{duration};
+        my $stat = Statistics::Descriptive::Sparse->new();
+        $stat->add_data(@$duration);
+        printf("%-40s %f\n", "$method: mean duration: ", $stat->mean());
+    }
+    {
+        my $times       = $methods{$method}->{time};
+        my $stat = Statistics::Descriptive::Sparse->new();
+        $stat->add_data(@$times);
+        $total_stat->add_data(@$times);
+        printf("%-40s %f\n","$method: calls/s: ", $stat->count / ($stat->max - $stat->min));
+    }
+}
+
+print "max : ", $total_stat->max, "\n";
+print "min : ", $total_stat->min, "\n";
+print "total s : ", ($total_stat->max - $total_stat->min), "\n";
+print "count : ", $total_stat->count, "\n";
+print "total : calls/s: ", $total_stat->count / ($total_stat->max - $total_stat->min), "\n";
Index: /branches/cnb_branches/cnb_branch_20090215/Ohana/Makefile.in
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Ohana/Makefile.in	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Ohana/Makefile.in	(revision 23199)
@@ -75,5 +75,5 @@
 	mkdir -p $(DESTLIB)
 	mkdir -p $(DESTBIN)
-	for i in $(LIBS); do make $$i.install || exit; done
+	for i in $(LIBS); do make $$i.install || exit 1; done
 	chmod +x ohana-config
 	cp -f ohana-config $(DESTBIN)/
@@ -83,31 +83,31 @@
 
 all:
-	make libs || exit
-	for i in $(PROGRAM); do make $$i || exit; done
+	make libs || exit 1
+	for i in $(PROGRAM); do make $$i || exit 1; done
 
 extras:
-	for i in $(EXTRAS); do make $$i || exit; done
+	for i in $(EXTRAS); do make $$i || exit 1; done
 
 pantasks:
-	make libs || exit
-	cd src/opihi; make pclient.install && exit
-	cd src/opihi; make pcontrol.install && exit
-	cd src/opihi; make pantasks.install && exit
+	make libs || exit 1
+	cd src/opihi; make pclient.install && exit 1
+	cd src/opihi; make pcontrol.install && exit 1
+	cd src/opihi; make pantasks.install && exit 1
 
 mana:
 	make libs
 	make kapa2.install
-	cd src/opihi; make mana.install && exit
+	cd src/opihi; make mana.install && exit 1
 
 dvoshell:
 	make libs
 	make kapa2.install
-	cd src/opihi; make dvo.install && exit
+	cd src/opihi; make dvo.install && exit 1
 
 clean:
 	@if [ "$(ARCH)" = "" ]; then echo ""; echo " *** please define ARCH ***"; echo; exit 1; fi
-	for i in $(LIBS); do make $$i.clean || exit; done
-	for i in $(PROGRAM); do make $$i.clean || exit; done
-	for i in $(EXTRAS); do make $$i.clean || exit; done
+	for i in $(LIBS); do make $$i.clean || exit 1; done
+	for i in $(PROGRAM); do make $$i.clean || exit 1; done
+	for i in $(EXTRAS); do make $$i.clean || exit 1; done
 	@rm -f `find . -name .mana`
 	@rm -f `find . -name .dvo`
@@ -116,16 +116,16 @@
 dist:
 	@if [ "$(ARCH)" = "" ]; then echo ""; echo " *** please define ARCH ***"; echo; exit 1; fi
-	for i in $(LIBS); do make $$i.dist || exit; done
-	for i in $(PROGRAM); do make $$i.dist || exit; done
+	for i in $(LIBS); do make $$i.dist || exit 1; done
+	for i in $(PROGRAM); do make $$i.dist || exit 1; done
 	@echo -n -e "\0033]0; *** Ohana: done $@ *** \0007" \
 
 install:
 	@if [ "$(ARCH)" = "" ]; then echo ""; echo " *** please define ARCH ***"; echo; exit 1; fi
-	for i in $(LIBS); do make $$i.install || exit; done
-	for i in $(PROGRAM); do make $$i.install || exit; done
+	for i in $(LIBS); do make $$i.install || exit 1; done
+	for i in $(PROGRAM); do make $$i.install || exit 1; done
 	@echo -n -e "\0033]0; *** Ohana: done $@ *** \0007" \
 
 install.extras:
-	for i in $(EXTRAS); do make $$i.install || exit; done
+	for i in $(EXTRAS); do make $$i.install || exit 1; done
 	@echo -n -e "\0033]0; *** Ohana: done $@ *** \0007" \
 
Index: /branches/cnb_branches/cnb_branch_20090215/Ohana/src/addstar/include/skycells.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Ohana/src/addstar/include/skycells.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Ohana/src/addstar/include/skycells.h	(revision 23199)
@@ -12,5 +12,5 @@
 # include <glob.h>
 
-enum {SQUARES, TRIANGLES, LOCAL};
+enum {SQUARES, TRIANGLES, LOCAL, RINGS};
 enum {TETRAHEDRON, CUBE, OCTOHEDRON, DODECAHEDRON, ICOSAHEDRON};
 
@@ -67,4 +67,5 @@
 double SCALE;
 double PADDING;
+double CELLSIZE;
 int    LEVEL;
 
@@ -84,12 +85,19 @@
 int 	     sky_tessellation 	       	    PROTO((FITS_DB *db, int level, int Nmax, int mode, double scale));
 int          sky_tessellation_init          PROTO((double scale));
+
 int 	     sky_tessellation_local         PROTO((FITS_DB *db, int level, int Nmax));
 int 	     sky_tessellation_triangles     PROTO((FITS_DB *db, int level, int Nmax));
 int 	     sky_tessellation_squares       PROTO((FITS_DB *db, int level, int Nmax));
+int          sky_tessellation_rings         PROTO((FITS_DB *db, int level, int Nmax));
+
 int 	     sky_triangle_to_image     	    PROTO((Image *image, SkyTriangle *triangle));
 int 	     sky_triangle_to_rectangle 	    PROTO((SkyRectangle *image, SkyTriangle *triangle));
+
 int          sky_rectangle_local            PROTO((SkyRectangle *rectangle));
 int 	     sky_subdivide_image       	    PROTO((Image *output, SkyRectangle *input, int Nx, int Ny));
 int 	     sky_triangle_coords       	    PROTO((SkyTriangle *triangle));
+
+SkyRectangle *sky_rectangle_ring            PROTO((float dec, float dDEC, int *nring));
+
 SkyTriangle *sky_divide_triangles      	    PROTO((SkyTriangle *in, int *ntriangles));
 SkyTriangle *sky_base_triangles        	    PROTO((int *ntriangles));
Index: /branches/cnb_branches/cnb_branch_20090215/Ohana/src/addstar/src/args_skycells.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Ohana/src/addstar/src/args_skycells.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Ohana/src/addstar/src/args_skycells.c	(revision 23199)
@@ -35,4 +35,7 @@
       MODE = LOCAL;
     }
+    if (!strcasecmp (argv[N], "rings")) {
+      MODE = RINGS;
+    }
     remove_argument (N, &argc, argv);
   }
@@ -140,12 +143,25 @@
 
   LEVEL = 8;
-  if ((MODE != LOCAL) && (N = get_argument (argc, argv, "-level"))) {
-    remove_argument (N, &argc, argv);
-    LEVEL = strtol (argv[N], &ptr, 10);
-    remove_argument (N, &argc, argv);
-    if ((*ptr != 0) || (LEVEL < 0)) {
-      fprintf (stderr, "-level requires an integer (>= 0) argument\n");
+  if ((MODE == SQUARES) || (MODE == TRIANGLES)) {
+    if ((N = get_argument (argc, argv, "-level"))) {
+      remove_argument (N, &argc, argv);
+      LEVEL = strtol (argv[N], &ptr, 10);
+      remove_argument (N, &argc, argv);
+      if ((*ptr != 0) || (LEVEL < 0)) {
+	fprintf (stderr, "-level requires an integer (>= 0) argument\n");
+	help ();
+      }  
+    }
+  }
+
+  CELLSIZE = 4.0;
+  if ((MODE == RINGS) && (N = get_argument (argc, argv, "-cellsize"))) {
+    remove_argument (N, &argc, argv);
+    CELLSIZE = strtod (argv[N], &ptr);
+    if ((*ptr != 0) || (CELLSIZE < 0.0)) {
+      fprintf (stderr, "-level requires a floating-point argument\n");
       help ();
     }  
+    remove_argument (N, &argc, argv);
   }
 
Index: /branches/cnb_branches/cnb_branch_20090215/Ohana/src/addstar/src/sky_tessalation.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/Ohana/src/addstar/src/sky_tessalation.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/Ohana/src/addstar/src/sky_tessalation.c	(revision 23199)
@@ -11,17 +11,19 @@
   sky_tessellation_init (scale);
 
-  if (mode == SQUARES) {
-    sky_tessellation_squares (db, level, Nmax);
-    return TRUE;
-  }
-
-  if (mode == TRIANGLES) {
-    sky_tessellation_triangles (db, level, Nmax);
-    return TRUE;
-  }
-
-  if (mode == LOCAL) {
-    sky_tessellation_local (db, level, Nmax);
-    return TRUE;
+  switch (mode) {
+    case SQUARES:
+      sky_tessellation_squares (db, level, Nmax);
+      return TRUE;
+    case TRIANGLES:
+      sky_tessellation_triangles (db, level, Nmax);
+      return TRUE;
+    case LOCAL:
+      sky_tessellation_local (db, level, Nmax);
+      return TRUE;
+    case RINGS:
+      sky_tessellation_rings (db, level, Nmax);
+      return TRUE;
+    default:
+      break;
   }
 
@@ -222,4 +224,46 @@
 
   free (image);
+  return (TRUE);
+}
+
+// the RINGS tessellation uses the declination zones proposed by Tamas Budavari
+// we generate projects on uniform rings of constant dec height
+int sky_tessellation_rings (FITS_DB *db, int level, int Nmax) {
+
+  int j, nDEC, Nimage, Nring;
+  float dec, dDEC;
+  SkyRectangle *ring;
+  Image *image;
+
+  // The tessellation has one input parameter: the approximate cell size.  Starting with
+  // the cell size, determine the optimal projection cell height (dDEC) that results in an
+  // integer number of dec zones between -90 and +90
+
+  nDEC = 180.0 / CELLSIZE;
+  dDEC = 180.0 / nDEC;
+
+  // generate the a collection of rectangles for each ring
+  for (dec = -90.0 + 0.5*dDEC; dec < +90.0; dec += dDEC) {
+
+    ring = sky_rectangle_ring (dec, dDEC, &Nring);
+
+    // subdivide each image (Nx x Ny subcells)
+    Nimage = NX_SUB*NY_SUB*Nring;
+    ALLOCATE (image, Image, Nimage);
+    for (j = 0; j < Nring; j++) {
+      // convert the SkyRectangles to Images for output
+      sky_subdivide_image (&image[j*NX_SUB*NY_SUB], &ring[j], NX_SUB, NY_SUB);
+    }
+
+    /* add the new images and save */
+    dvo_image_addrows (db, image, Nimage);
+    SetProtect (TRUE);
+    dvo_image_update (db, VERBOSE);
+    SetProtect (FALSE);
+    dvo_image_clear_vtable (db);
+    
+    free (ring);
+    free (image);
+  }    
   return (TRUE);
 }
@@ -480,4 +524,63 @@
 
   return (TRUE);
+}
+
+// define the parameters of a single sky projection center
+SkyRectangle *sky_rectangle_ring (float dec, float dDEC, int *nring) {
+
+  int i, nRA, NX, NY;
+  float dRA, decLower;
+  SkyRectangle *ring;
+
+  // 'dec' is a guess at the center of the cell; in fact, we need to choose decLower and
+  // decUpper to ensure complete overlap of the cells
+
+  // we can determine the 'lower' bound (bound closest to the equator):
+  decLower = (dec > 0.0) ? dec - 0.5*dDEC : dec + 0.5*dDEC;
+
+  // Subdivide the 'lower' bound into an integer number of segments:
+  nRA = cos(dec*RAD_DEG) * 360.0 / CELLSIZE; // CELLSIZE is a projection size
+  dRA = 360.0 / nRA;                         // dRA is a size in RA degrees
+
+  // I think we need to return the value of dec for the next ring, but I am not sure...
+
+  ALLOCATE (ring, SkyRectangle, nRA);
+
+  for (i = 0; i < nRA; i++) {
+    memset (&ring[i], 0, sizeof(SkyRectangle));
+    memset (&ring[i].coords, 0, sizeof(Coords));
+    ring[i].coords.crval1 = i*dRA;
+    ring[i].coords.crval2 = dec;
+
+    ring[i].coords.pc1_1 = +1.0;
+    ring[i].coords.pc1_2 = +0.0;
+    ring[i].coords.pc2_1 = -0.0;
+    ring[i].coords.pc2_2 = +1.0;
+  
+    // range values are in projected degrees
+    NX = cos(dec*RAD_DEG) * dRA  * 3600.0 / SCALE;
+    NY =                    dDEC * 3600.0 / SCALE;
+
+    // crpix1,crpix2 is the projection center
+    ring[i].coords.crpix1 = 0.5*NX;
+    ring[i].coords.crpix2 = 0.5*NY;
+
+    ring[i].coords.cdelt1 = SCALE / 3600.0;
+    ring[i].coords.cdelt2 = SCALE / 3600.0;
+
+    strcpy (ring[i].coords.ctype, "DEC--TAN");
+
+    ring[i].NX = NX;
+    ring[i].NY = NY;
+    ring[i].photcode = 1; // this needs to be set more sensibly
+
+
+    fprintf (stderr, "%f %f  : %f %f\n", 
+	     ring[i].coords.crval1, ring[i].coords.crval2, 
+	     ring[i].coords.crpix1, ring[i].coords.crpix2);
+  }
+
+  *nring = nRA;
+  return (ring);
 }
 
Index: /branches/cnb_branches/cnb_branch_20090215/PS-IPP-Config/lib/PS/IPP/Config.pm
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/PS-IPP-Config/lib/PS/IPP/Config.pm	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/PS-IPP-Config/lib/PS/IPP/Config.pm	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippMonitor/def/detStackedImfile.d
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippMonitor/def/detStackedImfile.d	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippMonitor/def/detStackedImfile.d	(revision 23199)
@@ -1,17 +1,27 @@
-TABLE detStackedImfile
+TABLE detStackedImfile, detRun
 TITLE detStackedImfile
 FILE  detStackedImfile.php
 MENU  ipp.imfiles.dat
 
-#     field         size  format  name                   show  link to     extras
-FIELD det_id,         7,  %s,    det_id
-FIELD iteration,      5,  %s,    iteration
-FIELD class_id,       8,  %s,    class_id
-FIELD fault,          5,  %d,    fault
-FIELD bg,             8,  %f,    backgnd
-FIELD bg_stdev,       8,  %f,    stdev
-FIELD bg_mean_stdev,  8,  %f,    [stdev]
-FIELD uri,           20,  %s,    uri
+WHERE detStackedImfile.det_id = detRun.det_id
+
+# XXX change uri to path_base in db
+ARGS  ARG1 detStackedImfile.det_id=$det_id
+ARGS  ARG1 detStackedImfile.iteration=$iteration
+ARGS  ARG1 camera=$detRun.camera
+ARGS  ARG1 basename=$detStackedImfile.uri
+
+#     field         size  format  name      show  link to     extras
+FIELD detStackedImfile.det_id,         7,  %s,    det_id
+FIELD detStackedImfile.iteration,      5,  %s,    iteration
+FIELD detStackedImfile.class_id,       8,  %s,    class_id,   value, detStackedImfile.php, ARG1
+FIELD detStackedImfile.fault,          5,  %d,    fault
+FIELD detStackedImfile.bg,             8,  %f,    backgnd
+FIELD detStackedImfile.bg_stdev,       8,  %f,    stdev
+FIELD detStackedImfile.bg_mean_stdev,  8,  %f,    [stdev]
+FIELD detStackedImfile.uri,           20,  %s,    uri
 # FIELD recipe, 20,   recipe
 
 TD_CLASS list_off $fault > 0
+
+TAIL PHP insert_log ('LOG.EXP');
Index: /branches/cnb_branches/cnb_branch_20090215/ippMonitor/raw/getimage.php
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippMonitor/raw/getimage.php	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippMonitor/raw/getimage.php	(revision 23199)
@@ -22,5 +22,9 @@
 putenv("PATH=$BINDIR:$PATH");
 
-# echo "args: $args<br>";
+if ($debug) {
+  echo "args: $args<br>";
+  echo "path: $PATH<br>";
+  echo "perl: $PERLLIB<br>";
+}
 
 # $basename may contain filename@filerule
@@ -31,6 +35,9 @@
 
 # $filerule = strtok("@");
-# echo "basename: $basename<br>";
-# echo "filerule: $filerule<br>";
+
+if ($debug) {
+  echo "basename: $basename<br>";
+  echo "filerule: $filerule<br>";
+}
 
 # need to supply the camera as well...
@@ -49,4 +56,14 @@
 $basename = escapeshellarg($basename);
 $basename = str_replace ('..','',$basename);
+
+if ($debug) {
+  exec ("which ipp_filename.pl", $output, $status);
+  echo "output:   $output[0]<br>";
+  echo "status:   $status<br>";
+
+  exec ("whoami", $output, $status);
+  echo "output:   $output[0]<br>";
+  echo "status:   $status<br>";
+}
 
 exec ("ipp_filename.pl --site=$SITE --basename $basename --filerule $filerule --camera $camera --class_id $class_id", $output, $status);
Index: /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/calibrate_dvo.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/calibrate_dvo.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/calibrate_dvo.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/camera_exp.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/camera_exp.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/camera_exp.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/chip_imfile.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/chip_imfile.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/chip_imfile.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_correct_imfile.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_correct_imfile.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_correct_imfile.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_norm_apply.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_norm_apply.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_norm_apply.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_norm_calc.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_norm_calc.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_norm_calc.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_norm_exp.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_norm_exp.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_norm_exp.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_process_exp.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_process_exp.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_process_exp.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_process_imfile.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_process_imfile.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_process_imfile.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_reject_exp.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_reject_exp.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_reject_exp.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_resid_exp.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_resid_exp.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_resid_exp.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_resid_imfile.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_resid_imfile.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_resid_imfile.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_stack.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_stack.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/detrend_stack.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/diff_skycell.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/diff_skycell.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/diff_skycell.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/fake_imfile.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/fake_imfile.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/fake_imfile.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/ipp_cleanup.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/ipp_cleanup.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/ipp_cleanup.pl	(revision 23199)
@@ -18,34 +18,36 @@
 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;
 
-# $mode must be one of "goto_cleaned" or "goto_purged"
-unless (($mode eq "goto_cleaned") || ($mode eq "goto_purged")) {
-    die "invalid cleanup mode $mode\n";    
+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 "goto_purged"
+# goto_cleaned and goto_scrubbed both result in 'cleaned': scrubbed allows chips without config files to
+# be cleaned (they cannot be recovered, but the small data is left behind)
+unless (($mode eq "goto_cleaned") || ($mode eq "goto_scrubbed") || ($mode eq "goto_purged")) {
+    die "invalid cleanup mode $mode\n";
 }
 
@@ -55,11 +57,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
@@ -87,9 +87,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
         if ($mode eq "goto_cleaned") {
             my $config_file = $ipprc->filename("PPIMAGE.CONFIG", $path_base, $class_id);
@@ -124,38 +125,43 @@
                 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 {
                 $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 {
-	    my $command = "$chiptool -updateprocessedimfile -chip_id $stage_id -class_id $class_id -code 1";
-	    $command .= " -dbname $dbname" if defined $dbname;
-
-	    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            # if an error happens for one chip, the chipRun will stay in goto_*, but the chips will stop be run
+            my $command = "$chiptool -updateprocessedimfile -chip_id $stage_id -class_id $class_id -code 1";
+            $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);
-	    }
-	}
-    }
-
-} elsif ($stage eq "camera") {
+            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") {
     die "--stage_id required for stage camera\n" if !$stage_id;
     # this stage uses 'camtool'
@@ -236,5 +242,7 @@
     }
     exit 0;
-} elsif ($stage eq "warp") {
+}
+
+if ($stage eq "warp") {
     die "--stage_id required for stage warp\n" if !$stage_id;
     # this stage uses 'warptool'
@@ -295,6 +303,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";
@@ -302,25 +310,25 @@
                 $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 {
             # XXX: -updateskyfile mode does not exist, need to add it
-	    my $command = "$warptool -updateskyfile -warp_id $stage_id -skycell_id $skycell_id -code 1";
-	    $command .= " -dbname $dbname" if defined $dbname;
+            my $command = "$warptool -updateskyfile -warp_id $stage_id -skycell_id $skycell_id -code 1";
+            $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);
+            }
             exit $PS_EXIT_UNKNOWN_ERROR;
-	}
+        }
     }
     exit 0;
@@ -334,11 +342,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);
     }
@@ -346,5 +354,5 @@
 }
 
-sub addFilename 
+sub addFilename
 {
     my $files      = shift; # reference to a list of files to unlink
Index: /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/ipp_maskscript.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/ipp_maskscript.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/ipp_maskscript.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_definerun.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_definerun.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_definerun.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_destreak.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_destreak.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_destreak.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_mask.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_mask.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_mask.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_process.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_process.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_process.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_tree.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_tree.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/magic_tree.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/register_exp.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/register_exp.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/register_exp.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/register_imfile.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/register_imfile.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/register_imfile.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/stack_skycell.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/stack_skycell.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/stack_skycell.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/warp_overlap.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/warp_overlap.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/warp_overlap.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippScripts/scripts/warp_skycell.pl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/warp_skycell.pl	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippScripts/scripts/warp_skycell.pl	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippTools/share/chiptool_pendingcleanupimfile.sql
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippTools/share/chiptool_pendingcleanupimfile.sql	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippTools/share/chiptool_pendingcleanupimfile.sql	(revision 23199)
@@ -15,3 +15,5 @@
     ((chipRun.state = 'goto_cleaned' AND chipProcessedImfile.data_state = 'full')
 OR 
+    (chipRun.state = 'goto_scrubbed' AND chipProcessedImfile.data_state = 'full')
+OR 
     (chipRun.state = 'goto_purged' AND chipProcessedImfile.data_state != 'purged'))
Index: /branches/cnb_branches/cnb_branch_20090215/ippTools/share/chiptool_pendingcleanuprun.sql
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippTools/share/chiptool_pendingcleanuprun.sql	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippTools/share/chiptool_pendingcleanuprun.sql	(revision 23199)
@@ -7,3 +7,3 @@
 USING (exp_id)
 WHERE
-    (chipRun.state = 'goto_cleaned' OR chipRun.state = 'goto_purged')
+    (chipRun.state = 'goto_cleaned' OR chipRun.state = 'goto_scrubbed' OR chipRun.state = 'goto_purged')
Index: /branches/cnb_branches/cnb_branch_20090215/ippTools/share/dettool_todetrunsummary.sql
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippTools/share/dettool_todetrunsummary.sql	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippTools/share/dettool_todetrunsummary.sql	(revision 23199)
@@ -40,4 +40,5 @@
         AND detRunSummary.det_id IS NULL
         AND detRunSummary.iteration IS NULL
+	AND detResidExp.fault = 0
     GROUP BY
         detRun.det_id,
Index: /branches/cnb_branches/cnb_branch_20090215/ippTools/src/chiptool.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippTools/src/chiptool.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippTools/src/chiptool.c	(revision 23199)
@@ -52,4 +52,5 @@
 static bool runMode(pxConfig *config);
 static bool tocleanedimfileMode(pxConfig *config);
+static bool tocleanedimfile_from_scrubbedMode(pxConfig *config);
 static bool tofullimfileMode(pxConfig *config);
 static bool topurgedimfileMode(pxConfig *config);
@@ -91,4 +92,5 @@
         MODECASE(CHIPTOOL_MODE_RUN,                     runMode);
         MODECASE(CHIPTOOL_MODE_TOCLEANEDIMFILE,         tocleanedimfileMode);
+        MODECASE(CHIPTOOL_MODE_TOCLEANEDIMFILE_FROM_SCRUBBED, tocleanedimfile_from_scrubbedMode);
         MODECASE(CHIPTOOL_MODE_TOFULLIMFILE,            tofullimfileMode);
         MODECASE(CHIPTOOL_MODE_TOPURGEDIMFILE,          topurgedimfileMode);
@@ -1245,4 +1247,8 @@
     return change_imfile_data_state(config, "cleaned", "goto_cleaned");
 }
+static bool tocleanedimfile_from_scrubbedMode(pxConfig *config)
+{
+    return change_imfile_data_state(config, "cleaned", "goto_scrubbed");
+}
 static bool tofullimfileMode(pxConfig *config)
 {
Index: /branches/cnb_branches/cnb_branch_20090215/ippTools/src/chiptool.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippTools/src/chiptool.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippTools/src/chiptool.h	(revision 23199)
@@ -43,4 +43,5 @@
     CHIPTOOL_MODE_RUN,
     CHIPTOOL_MODE_TOCLEANEDIMFILE,
+    CHIPTOOL_MODE_TOCLEANEDIMFILE_FROM_SCRUBBED,
     CHIPTOOL_MODE_TOFULLIMFILE,
     CHIPTOOL_MODE_TOPURGEDIMFILE,
Index: /branches/cnb_branches/cnb_branch_20090215/ippTools/src/chiptoolConfig.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippTools/src/chiptoolConfig.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippTools/src/chiptoolConfig.c	(revision 23199)
@@ -234,4 +234,9 @@
     psMetadataAddStr(tocleanedimfileArgs, PS_LIST_TAIL, "-class_id",  0,        "class ID to update", NULL);
 
+    // -tocleanedimfile_from_scrubbed
+    psMetadata *tocleanedimfile_from_scrubbedArgs = psMetadataAlloc();
+    psMetadataAddS64(tocleanedimfile_from_scrubbedArgs, PS_LIST_TAIL, "-chip_id", 0,          "chip ID to update", 0);
+    psMetadataAddStr(tocleanedimfile_from_scrubbedArgs, PS_LIST_TAIL, "-class_id",  0,        "class ID to update", NULL);
+
     // -tofullimfile
     psMetadata *tofullimfileArgs = psMetadataAlloc();
@@ -275,4 +280,5 @@
     PXOPT_ADD_MODE("-run",                  "show runs",                            CHIPTOOL_MODE_RUN,                  runArgs);
     PXOPT_ADD_MODE("-tocleanedimfile",      "set imfile state to cleaned",          CHIPTOOL_MODE_TOCLEANEDIMFILE,      tocleanedimfileArgs);
+    PXOPT_ADD_MODE("-tocleanedimfile_from_scrubbed", "set imfile state to cleaned (for goto_scrubbed)", CHIPTOOL_MODE_TOCLEANEDIMFILE_FROM_SCRUBBED, tocleanedimfile_from_scrubbedArgs);
     PXOPT_ADD_MODE("-tofullimfile",         "set imfile state to full",              CHIPTOOL_MODE_TOFULLIMFILE,         tofullimfileArgs);
     PXOPT_ADD_MODE("-topurgedimfile",       "set imfile state to purged",            CHIPTOOL_MODE_TOPURGEDIMFILE,       topurgedimfileArgs);
Index: /branches/cnb_branches/cnb_branch_20090215/ippTools/src/dettoolConfig.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippTools/src/dettoolConfig.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippTools/src/dettoolConfig.c	(revision 23199)
@@ -73,6 +73,6 @@
     psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
     psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
-    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
-    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period", NULL);
+    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run period (CURRENTLY NOT USED)", NULL);
+    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period (CURRENTLY NOT USED)", NULL);
     psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-reduction",  0,            "define reduction class for processing", NULL);
     psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-label",  0,            "define detrun label", NULL);
@@ -104,6 +104,6 @@
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
-    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
-    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period (CURRENTLY NOT USED)", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period (CURRENTLY NOT USED)", NULL);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_exp_type",  0,            "search for exp_type", NULL);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_inst",  0,            "search for camera", NULL);
@@ -159,6 +159,6 @@
     psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_time_begin",  0,            "start of period to apply detrend too", NULL);
     psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_time_end",  0,            "end of period to apply detrend too", NULL);
-    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_begin",  0,            "start of detrend run applicable period", NULL);
-    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_end",  0,            "end of detrend run applicable period", NULL);
+    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_begin",  0,            "start of detrend run applicable period (CURRENTLY NOT USED)", NULL);
+    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_end",  0,            "end of detrend run applicable period (CURRENTLY NOT USED)", NULL);
     psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_reduction",  0,            "define reduction class for processing", NULL);
     psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_label",  0,            "define detrun label", NULL);
@@ -833,6 +833,6 @@
     psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
     psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
-    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
-    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period", NULL);
+    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period (CURRENTLY NOT USED)", NULL);
+    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period (CURRENTLY NOT USED)", NULL);
     psMetadataAddS64(register_detrendArgs, PS_LIST_TAIL, "-ref_det_id",  0,            "define reference det_id", 0);
     psMetadataAddS32(register_detrendArgs, PS_LIST_TAIL, "-ref_iter",  0,            "define reference iteration", -1);
Index: /branches/cnb_branches/cnb_branch_20090215/ippTools/src/pxtools.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippTools/src/pxtools.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippTools/src/pxtools.c	(revision 23199)
@@ -30,6 +30,4 @@
     PS_ASSERT_PTR_NON_NULL(state, false);
     
-    // XXX replace strncmp with strcmp
-
     if (!strcmp(state, "new")) return true;
     if (!strcmp(state, "reg")) return true;
@@ -38,9 +36,16 @@
     if (!strcmp(state, "wait")) return true;
     if (!strcmp(state, "goto_cleaned")) return true;
+    if (!strcmp(state, "error_cleaned")) return true;
+    if (!strcmp(state, "goto_scrubbed")) return true;
+    if (!strcmp(state, "error_scrubbed")) return true;
     if (!strcmp(state, "cleaned")) return true;
     if (!strcmp(state, "update")) return true;
     if (!strcmp(state, "purged")) return true;
     if (!strcmp(state, "goto_purged")) return true;
+    if (!strcmp(state, "error_purged")) return true;
 
     return false;
 }
+
+// 'scrubbed' is a virtual state equivalent to cleaned, but allows files to be removed
+// even if the config files is missing
Index: /branches/cnb_branches/cnb_branch_20090215/ippconfig/gpc1/ppImage.config
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippconfig/gpc1/ppImage.config	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippconfig/gpc1/ppImage.config	(revision 23199)
@@ -134,22 +134,50 @@
 # Overscan, bias, dark, shutter
 PPIMAGE_OBDS       METADATA
-  BASE.FITS        BOOL    TRUE            # Save base detrended image?
-  BASE.MASK.FITS   BOOL    TRUE            # Save base detrended image?
+  BASE.FITS          BOOL    TRUE            # Save base detrended image?
+  BASE.MASK.FITS     BOOL    TRUE            # Save base detrended image?
   BASE.VARIANCE.FITS BOOL    TRUE            # Save base detrended image?
-  CHIP.FITS        BOOL    FALSE           # Save chip-mosaic-ed image? 
-  CHIP.MASK.FITS   BOOL    FALSE           # Save chip-mosaic-ed image? 
-  CHIP.VARIANCE.FITS BOOL    FALSE           # Save chip-mosaic-ed image? 
-  OVERSCAN         BOOL    TRUE            # Overscan subtraction
-  BIAS             BOOL    FALSE           # Bias subtraction
-  DARK             BOOL    TRUE            # Dark subtraction
-  SHUTTER          BOOL    FALSE           # Shutter correction
-  FLAT             BOOL    FALSE           # Flat-field normalisation
-  MASK             BOOL    FALSE           # Mask bad pixels
-  FRINGE           BOOL    FALSE           # Fringe subtraction
-  PHOTOM           BOOL    FALSE           # Source identification and photometry
-  ASTROM.CHIP      BOOL    FALSE           # Astrometry per chip?
-  ASTROM.MOSAIC    BOOL    FALSE           # Astrometry for mosaic?
-  BIN1.FITS        BOOL    TRUE            # Save 1st binned chip image?
-  BIN2.FITS        BOOL    TRUE            # Save 2nd binned chip image?
+  CHIP.FITS          BOOL    FALSE           # Save chip-mosaic-ed image? 
+  CHIP.MASK.FITS     BOOL    FALSE           # Save chip-mosaic-ed image? 
+  CHIP.VARIANCE.FITS BOOL    FALSE           # Save chip-mosaic-ed image? 
+  OVERSCAN           BOOL    TRUE            # Overscan subtraction
+  BIAS               BOOL    FALSE           # Bias subtraction
+  DARK               BOOL    TRUE            # Dark subtraction
+  SHUTTER            BOOL    FALSE           # Shutter correction
+  FLAT               BOOL    FALSE           # Flat-field normalisation
+  MASK               BOOL    FALSE           # Mask bad pixels
+  FRINGE             BOOL    FALSE           # Fringe subtraction
+  PHOTOM             BOOL    FALSE           # Source identification and photometry
+  ASTROM.CHIP        BOOL    FALSE           # Astrometry per chip?
+  ASTROM.MOSAIC      BOOL    FALSE           # Astrometry for mosaic?
+  BIN1.FITS          BOOL    TRUE            # Save 1st binned chip image?
+  BIN2.FITS          BOOL    TRUE            # Save 2nd binned chip image?
+END
+
+# Overscan, bias, dark, shutter
+PPIMAGE_FLATPROC_PREMASK       METADATA
+  BASE.FITS          BOOL    TRUE            # Save base detrended image?
+  BASE.MASK.FITS     BOOL    TRUE            # Save base detrended image?
+  BASE.VARIANCE.FITS BOOL    TRUE            # Save base detrended image?
+  CHIP.FITS          BOOL    FALSE           # Save chip-mosaic-ed image? 
+  CHIP.MASK.FITS     BOOL    FALSE           # Save chip-mosaic-ed image? 
+  CHIP.VARIANCE.FITS BOOL    FALSE           # Save chip-mosaic-ed image? 
+  OVERSCAN           BOOL    TRUE            # Overscan subtraction
+  BIAS               BOOL    FALSE           # Bias subtraction
+  DARK               BOOL    TRUE            # Dark subtraction
+  SHUTTER            BOOL    FALSE           # Shutter correction
+  FLAT               BOOL    FALSE           # Flat-field normalisation
+  MASK               BOOL    FALSE           # Mask bad pixels
+  FRINGE             BOOL    FALSE           # Fringe subtraction
+  PHOTOM             BOOL    FALSE           # Source identification and photometry
+  ASTROM.CHIP        BOOL    FALSE           # Astrometry per chip?
+  ASTROM.MOSAIC      BOOL    FALSE           # Astrometry for mosaic?
+  BIN1.FITS          BOOL    TRUE            # Save 1st binned chip image?
+  BIN2.FITS          BOOL    TRUE            # Save 2nd binned chip image?
+
+  DETREND.CONSTRAINTS  METADATA
+    DARK METADATA
+      DETTYPE STR DARK_PREMASK
+    END
+  END   
 END
 
Index: /branches/cnb_branches/cnb_branch_20090215/ippconfig/gpc1/ppMerge.config
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippconfig/gpc1/ppMerge.config	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippconfig/gpc1/ppMerge.config	(revision 23199)
@@ -21,9 +21,9 @@
 DARK.ORDINATES	METADATA
 	CELL.DARKTIME	S32	1
-	CHIP.TEMP	METADATA
-		ORDER	S32	1
-		SCALE	BOOL	TRUE
-		MIN	F32	-95
-		MAX	F32	-50
-	END
+# 	CHIP.TEMP	METADATA
+# 		ORDER	S32	1
+# 		SCALE	BOOL	TRUE
+# 		MIN	F32	-95
+# 		MAX	F32	-50
+# 	END
 END
Index: /branches/cnb_branches/cnb_branch_20090215/ippconfig/ipprc.config.in
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippconfig/ipprc.config.in	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippconfig/ipprc.config.in	(revision 23199)
@@ -3,6 +3,7 @@
 # Default search path for configuration files (add $HOME if desired)
 # Note: do not include $HOME in the distributed copy used by ippMonitor
-# PATH            STR     @pkgdatadir@:$HOME/.ipp:.
-PATH              STR     $HOME/ippconfig/:$PSCONFDIR/$PSCONFIG/share/ippconfig/
+PATH            STR     @pkgdatadir@
+### This is a useful setting for an individual user:
+#PATH           STR     $HOME/ippconfig/:$PSCONFDIR/$PSCONFIG/share/ippconfig/
 
 # load the site-specific information from here
Index: /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/filerules-mef.mdc
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/filerules-mef.mdc	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/filerules-mef.mdc	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippconfig/recipes/filerules-simple.mdc
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/filerules-simple.mdc	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/filerules-simple.mdc	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippconfig/recipes/filerules-split.mdc
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/filerules-split.mdc	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/filerules-split.mdc	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippconfig/recipes/fitstypes.mdc
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/fitstypes.mdc	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/fitstypes.mdc	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ippconfig/recipes/ppImage.config
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/ppImage.config	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/ppImage.config	(revision 23199)
@@ -433,4 +433,32 @@
   BIN1.FITS        BOOL    TRUE            # Save 1st binned chip image?
   BIN2.FITS        BOOL    TRUE            # Save 2nd binned chip image?
+END
+
+# used for the pre-mask version of flat-field processing
+PPIMAGE_FLATPROC_PREMASK       METADATA
+  BASE.FITS          BOOL    TRUE            # Save base detrended image?
+  BASE.MASK.FITS     BOOL    TRUE            # Save base detrended image?
+  BASE.VARIANCE.FITS BOOL    TRUE            # Save base detrended image?
+  CHIP.FITS          BOOL    FALSE           # Save chip-mosaic-ed image? 
+  CHIP.MASK.FITS     BOOL    FALSE           # Save chip-mosaic-ed image? 
+  CHIP.VARIANCE.FITS BOOL    FALSE           # Save chip-mosaic-ed image? 
+  OVERSCAN           BOOL    TRUE            # Overscan subtraction
+  BIAS               BOOL    TRUE            # Bias subtraction
+  DARK               BOOL    TRUE            # Dark subtraction
+  SHUTTER            BOOL    FALSE           # Shutter correction
+  FLAT               BOOL    FALSE           # Flat-field normalisation
+  MASK               BOOL    FALSE           # Mask bad pixels
+  FRINGE             BOOL    FALSE           # Fringe subtraction
+  PHOTOM             BOOL    FALSE           # Source identification and photometry
+  ASTROM.CHIP        BOOL    FALSE           # Astrometry per chip?
+  ASTROM.MOSAIC      BOOL    FALSE           # Astrometry for mosaic?
+  BIN1.FITS          BOOL    TRUE            # Save 1st binned chip image?
+  BIN2.FITS          BOOL    TRUE            # Save 2nd binned chip image?
+
+  DETREND.CONSTRAINTS  METADATA
+    DARK METADATA
+      DETTYPE STR DARK_PREMASK
+    END
+  END   
 END
 
Index: /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/reductionClasses.mdc
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/reductionClasses.mdc	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ippconfig/recipes/reductionClasses.mdc	(revision 23199)
@@ -31,10 +31,10 @@
 
 	# *** premask (unmasked) flat-field types
-	FLAT_PREMASK_PROCESS	STR	PPIMAGE_OBDS
+	FLAT_PREMASK_PROCESS	STR	PPIMAGE_FLATPROC_PREMASK
 	FLAT_PREMASK_RESID	STR	PPIMAGE_F
 	FLAT_PREMASK_VERIFY	STR	PPIMAGE_F
 	FLAT_PREMASK_STACK	STR	PPMERGE_FLAT
 	FLAT_PREMASK_JPEG_IMAGE	STR	FLAT
-	FLAT_PREMASK_JPEG_RESID	STRE	FLAT_RESID
+	FLAT_PREMASK_JPEG_RESID	STR	FLAT_RESID
 
 	DOMEFLAT_PREMASK_PROCESS	STR	PPIMAGE_OBDS
Index: /branches/cnb_branches/cnb_branch_20090215/ppArith/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppArith/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppArith/src/Makefile.am	(revision 23199)
@@ -1,4 +1,14 @@
 bin_PROGRAMS = ppArith
-ppArith_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PPARITH_CFLAGS)
+
+PPARITH_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PPARITH_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`
+PPARITH_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of ppArithVersion.c, since it gets the version information
+ppArithVersion.c: FORCE
+	touch ppArith.c
+FORCE: ;
+
+ppArith_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PPARITH_CFLAGS) -DPPARITH_VERSION=\"$(PPARITH_VERSION)\" -DPPARITH_BRANCH=\"$(PPARITH_BRANCH)\" -DPPARITH_SOURCE=\"$(PPARITH_SOURCE)\"
 ppArith_LDFLAGS  = $(PSLIB_LIBS)   $(PSMODULE_LIBS)   $(PPSTATS_LIBS)   $(PSPHOT_LIBS)   $(PPARITH_LIBS)
 
Index: /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArith.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArith.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArith.c	(revision 23199)
@@ -34,4 +34,6 @@
     }
 
+    ppArithVersionPrint();
+
     if (!ppArithArguments(argc, argv, config)) {
         psErrorStackPrint(stderr, "Error reading arguments.\n");
Index: /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArith.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArith.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArith.h	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppArith/src/ppArithLoop.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArithLoop.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArithLoop.c	(revision 23199)
@@ -113,5 +113,5 @@
                     hdu->header = psMetadataAlloc();
                 }
-                ppArithVersionMetadata(hdu->header);
+                ppArithVersionHeader(hdu->header);
                 lastHDU = hdu;
             }
Index: /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArithVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArithVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppArith/src/ppArithVersion.c	(revision 23199)
@@ -22,26 +22,79 @@
 #include "ppArith.h"
 
-static const char *cvsTag = "$Name: not supported by cvs2svn $";///< CVS tag name
-
 psString ppArithVersion(void)
 {
-    psString version = NULL;            // Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PPARITH_VERSION
+#error "PPARITH_VERSION is not set"
+#endif
+#ifndef PPARITH_BRANCH
+#error "PPARITH_BRANCH is not set"
+#endif
+    return psStringCopy(PPARITH_BRANCH "@" PPARITH_VERSION);
+}
+
+psString ppArithSource(void)
+{
+#ifndef PPARITH_SOURCE
+#error "PPARITH_SOURCE is not set"
+#endif
+    return psStringCopy(PPARITH_SOURCE);
 }
 
 psString ppArithVersionLong(void)
 {
-    psString version = ppArithVersion(); // Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
-    psFree(tag);
+    psString version = ppArithVersion();  // Version, to return
+    psString source = ppArithSource();    // Source
+
+    psStringPrepend(&version, "ppArith ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
     return version;
+};
+
+bool ppArithVersionHeader(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, "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 ppArithVersionMetadata(psMetadata *metadata)
+void ppArithVersionPrint(void)
 {
-    PS_ASSERT_METADATA_NON_NULL(metadata,);
+    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
@@ -50,18 +103,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/cnb_branches/cnb_branch_20090215/ppImage/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppImage/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppImage/src/Makefile.am	(revision 23199)
@@ -4,5 +4,14 @@
 	ppImage.h 
 
-ppImage_CFLAGS = $(PPIMAGE_CFLAGS) $(PPSTATS_CFLAGS) $(PSASTRO_CFLAGS) $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+PPIMAGE_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PPIMAGE_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`
+PPIMAGE_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of ppImageVersion.c, since it gets the version information
+ppImageVersion.c: FORCE
+	touch ppImageVersion.c
+FORCE: ;
+
+ppImage_CFLAGS = $(PPIMAGE_CFLAGS) $(PPSTATS_CFLAGS) $(PSASTRO_CFLAGS) $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) -DPPIMAGE_VERSION=\"$(PPIMAGE_VERSION)\" -DPPIMAGE_BRANCH=\"$(PPIMAGE_BRANCH)\" -DPPIMAGE_SOURCE=\"$(PPIMAGE_SOURCE)\"
 ppImage_LDFLAGS = $(PPIMAGE_LIBS) $(PSASTRO_LIBS) $(PPSTATS_LIBS) $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
 ppImage_SOURCES = \
Index: /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImage.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImage.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImage.c	(revision 23199)
@@ -21,4 +21,6 @@
         exit(PS_EXIT_CONFIG_ERROR);
     }
+
+    ppImageVersionPrint();
 
     // define recipe options
Index: /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImage.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImage.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImage.h	(revision 23199)
@@ -208,10 +208,16 @@
 psString ppImageVersion(void);
 
+/// Return software source
+psString ppImageSource(void);
+
 /// Return long version information
 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/cnb_branches/cnb_branch_20090215/ppImage/src/ppImageLoop.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImageLoop.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImageLoop.c	(revision 23199)
@@ -28,5 +28,5 @@
     if (dump_file) {
         pmConfigCamerasCull(config, NULL);
-        pmConfigRecipesCull(config, "PPIMAGE,PPSTATS,PSPHOT,MASKS,PSASTRO");
+        pmConfigRecipesCull(config, "PPIMAGE,PPSTATS,PSPHOT,MASKS,PSASTRO,JPEG");
 
         pmConfigDump(config, input->fpa, dump_file);
@@ -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;
             }
@@ -96,8 +96,8 @@
                 }
 
-		// free detrend images potentially in use: MASK, BIAS, DARK, SHUTTER, FLAT
-		if (!ppImageDetrendFree (config, view)) {
-		    ESCAPE("Unable to free detrend images");
-		}
+                // free detrend images potentially in use: MASK, BIAS, DARK, SHUTTER, FLAT
+                if (!ppImageDetrendFree (config, view)) {
+                    ESCAPE("Unable to free detrend images");
+                }
             }
 
@@ -105,13 +105,13 @@
                 ppImageDetrendRecord(cell, config, options, view);
             }
-	    // free detrend images potentially in use: MASK, BIAS, DARK, SHUTTER, FLAT
-	    if (!ppImageDetrendFree (config, view)) {
-		ESCAPE("Unable to free detrend images");
-	    }
-        }
-	// free detrend images potentially in use: MASK, BIAS, DARK, SHUTTER, FLAT
-	if (!ppImageDetrendFree (config, view)) {
-	    ESCAPE("Unable to free detrend images");
-	}
+            // free detrend images potentially in use: MASK, BIAS, DARK, SHUTTER, FLAT
+            if (!ppImageDetrendFree (config, view)) {
+                ESCAPE("Unable to free detrend images");
+            }
+        }
+        // free detrend images potentially in use: MASK, BIAS, DARK, SHUTTER, FLAT
+        if (!ppImageDetrendFree (config, view)) {
+            ESCAPE("Unable to free detrend images");
+        }
 
         // Apply the fringe correction
@@ -121,8 +121,8 @@
             }
         }
-	// free detrend images potentially in use: MASK, BIAS, DARK, SHUTTER, FLAT
-	if (!ppImageFringeFree (config, view)) {
-	    ESCAPE("Unable to free fringe images");
-	}
+        // free detrend images potentially in use: MASK, BIAS, DARK, SHUTTER, FLAT
+        if (!ppImageFringeFree (config, view)) {
+            ESCAPE("Unable to free fringe images");
+        }
 
         // measure various pixel-based statistics for this image
@@ -152,15 +152,15 @@
         }
 
-	// these may be used by ppImageSubtractBackground.
-	// if these are defined as internal files, drop them here
-	status = true;
-	status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL");
-	status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV");
-	status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKGND");
-	if (!status) {
-	    psError(PSPHOT_ERR_PROG, false, "trouble dropping internal files");
-	    psFree (view);
-	    return false;
-	}
+        // these may be used by ppImageSubtractBackground.
+        // if these are defined as internal files, drop them here
+        status = true;
+        status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL");
+        status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV");
+        status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKGND");
+        if (!status) {
+            psError(PSPHOT_ERR_PROG, false, "trouble dropping internal files");
+            psFree (view);
+            return false;
+        }
 
         // binning (used for display) must take place after the background is replaced, if desired
Index: /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImageVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImageVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppImage/src/ppImageVersion.c	(revision 23199)
@@ -5,26 +5,82 @@
 #include "ppImage.h"
 
-static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
-
 psString ppImageVersion(void)
 {
-    psString version = NULL;            // Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PPIMAGE_VERSION
+#error "PPIMAGE_VERSION is not set"
+#endif
+#ifndef PPIMAGE_BRANCH
+#error "PPIMAGE_BRANCH is not set"
+#endif
+    return psStringCopy(PPIMAGE_BRANCH "@" PPIMAGE_VERSION);
+}
+
+psString ppImageSource(void)
+{
+#ifndef PPIMAGE_SOURCE
+#error "PPIMAGE_SOURCE is not set"
+#endif
+    return psStringCopy(PPIMAGE_SOURCE);
 }
 
 psString ppImageVersionLong(void)
 {
-    psString version = ppImageVersion(); // Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
-    psFree(tag);
+    psString version = ppImageVersion();  // Version, to return
+    psString source = ppImageSource();    // Source
+
+    psStringPrepend(&version, "ppImage ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
     return version;
+};
+
+bool ppImageVersionHeader(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, "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 ppImageVersionMetadata(psMetadata *metadata)
+void ppImageVersionPrint(void)
 {
-    PS_ASSERT_METADATA_NON_NULL(metadata,);
+    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
@@ -35,20 +91,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/cnb_branches/cnb_branch_20090215/ppMerge/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/Makefile.am	(revision 23199)
@@ -1,5 +1,14 @@
 bin_PROGRAMS = ppMerge
 
-ppMerge_CFLAGS = $(PPMERGE_CFLAGS) $(PPSTATS_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+PPMERGE_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PPMERGE_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`
+PPMERGE_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of ppMergeVersion.c, since it gets the version information
+ppMergeVersion.c: FORCE
+	touch ppMergeVersion.c
+FORCE: ;
+
+ppMerge_CFLAGS = $(PPMERGE_CFLAGS) $(PPSTATS_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) -DPPMERGE_VERSION=\"$(PPMERGE_VERSION)\" -DPPMERGE_BRANCH=\"$(PPMERGE_BRANCH)\" -DPPMERGE_SOURCE=\"$(PPMERGE_SOURCE)\"
 ppMerge_LDFLAGS = $(PPMERGE_LIBS) $(PPSTATS_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
 
@@ -14,5 +23,6 @@
 	ppMergeLoop_Threaded.c  \
 	ppMergeSetThreads.c	\
-	ppMergeMask.c
+	ppMergeMask.c		\
+	ppMergeVersion.c
 
 #	ppMergeLoop.c		
Index: /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMerge.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMerge.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMerge.c	(revision 23199)
@@ -38,4 +38,6 @@
         goto die;
     }
+
+    ppMergeVersionPrint();
 
     ppMergeType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); ///< Type of frame
Index: /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMerge.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMerge.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMerge.h	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeLoop_Threaded.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeLoop_Threaded.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeLoop_Threaded.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeMask.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeMask.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeMask.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeVersion.c	(revision 23199)
@@ -22,46 +22,90 @@
 #include "ppMergeVersion.h"
 
-static const char *cvsTag = "$Name: not supported by cvs2svn $";///< CVS tag name
-
 psString ppMergeVersion(void)
 {
-    psString version = NULL;            ///< Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PPMERGE_VERSION
+#error "PPMERGE_VERSION is not set"
+#endif
+#ifndef PPMERGE_BRANCH
+#error "PPMERGE_BRANCH is not set"
+#endif
+    return psStringCopy(PPMERGE_BRANCH "@" PPMERGE_VERSION);
+}
+
+psString ppMergeSource(void)
+{
+#ifndef PPMERGE_SOURCE
+#error "PPMERGE_SOURCE is not set"
+#endif
+    return psStringCopy(PPMERGE_SOURCE);
 }
 
 psString ppMergeVersionLong(void)
 {
-    psString version = ppMergeVersion(); ///< Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); ///< CVS tag
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
-    psFree(tag);
+    psString version = ppMergeVersion();  // Version, to return
+    psString source = ppMergeSource();    // Source
+
+    psStringPrepend(&version, "ppMerge ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
     return version;
+};
+
+bool ppMergeVersionHeader(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, "ppMerge 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 = 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 ppMergeVersionMetadata(psMetadata *metadata)
+void ppMergeVersionPrint(void)
 {
-    PS_ASSERT_METADATA_NON_NULL(metadata,);
-
-    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
+    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/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeVersion.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeVersion.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppMerge/src/ppMergeVersion.h	(revision 23199)
@@ -20,4 +20,9 @@
 
 /**
+ * Return software source
+ */
+psString ppMergeSource(void);
+
+/**
  * Return long version information
  */
Index: /branches/cnb_branches/cnb_branch_20090215/ppSim/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSim/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSim/src/Makefile.am	(revision 23199)
@@ -1,5 +1,14 @@
 bin_PROGRAMS = ppSim ppSimSequence
 
-ppSim_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSPHOT_CFLAGS) $(PSASTRO_CFLAGS) $(ppSim_CFLAGS)
+PPSIM_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PPSIM_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`
+PPSIM_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of ppSimVersion.c, since it gets the version information
+ppSimVersion.c: FORCE
+	touch ppSimVersion.c
+FORCE: ;
+
+ppSim_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSPHOT_CFLAGS) $(PSASTRO_CFLAGS) $(ppSim_CFLAGS) -DPPSIM_VERSION=\"$(PPSIM_VERSION)\" -DPPSIM_BRANCH=\"$(PPSIM_BRANCH)\" -DPPSIM_SOURCE=\"$(PPSIM_SOURCE)\"
 ppSim_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) $(PSPHOT_LIBS) $(PSASTRO_LIBS)
 ppSim_SOURCES = \
@@ -35,5 +44,6 @@
 	ppSimMosaicChip.c	  \
 	ppSimRandomGaussian.c	  \
-	ppSimBadPixels.c
+	ppSimBadPixels.c          \
+	ppSimVersion.c
 
 ppSimSequence_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSASTRO_CFLAGS) $(ppSim_CFLAGS)
Index: /branches/cnb_branches/cnb_branch_20090215/ppSim/src/ppSim.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSim/src/ppSim.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSim/src/ppSim.h	(revision 23199)
@@ -19,7 +19,7 @@
 
 // Compare a value with minimum and maximum values, replacing where required.
-#define COMPARE(VALUE,MIN,MAX) {		\
-        if (VALUE < MIN) { MIN = VALUE; }	\
-        if (VALUE > MAX) { MAX = VALUE; }	\
+#define COMPARE(VALUE,MIN,MAX) {                \
+        if (VALUE < MIN) { MIN = VALUE; }       \
+        if (VALUE > MAX) { MAX = VALUE; }       \
     }
 
@@ -147,30 +147,30 @@
 float ppSimMagToFlux (float mag, float zp);
 
-float ppSimArgToRecipeF32(bool *status, 
-			  psMetadata *options,    // Target to which to add value
-			  const char *recipeName, // Name for value in the recipe
-			  psMetadata *arguments,  // Command-line arguments
-			  const char *argName	 // Argument name in the command-line arguments
+float ppSimArgToRecipeF32(bool *status,
+                          psMetadata *options,    // Target to which to add value
+                          const char *recipeName, // Name for value in the recipe
+                          psMetadata *arguments,  // Command-line arguments
+                          const char *argName    // Argument name in the command-line arguments
     );
 
 int ppSimArgToRecipeS32(bool *status,
-			psMetadata *options,    // Target to which to add value
-			const char *recipeName, // Name for value in the recipe
-			psMetadata *arguments,  // Command-line arguments
-			const char *argName	 // Argument name in the command-line arguments
+                        psMetadata *options,    // Target to which to add value
+                        const char *recipeName, // Name for value in the recipe
+                        psMetadata *arguments,  // Command-line arguments
+                        const char *argName      // Argument name in the command-line arguments
     );
 
 char *ppSimArgToRecipeStr(bool *status,
-			  psMetadata *options,    // Target to which to add value
-			  const char *recipeName, // Name for value in the recipe
-			  psMetadata *arguments,  // Command-line arguments
-			  const char *argName	 // Argument name in the command-line arguments
+                          psMetadata *options,    // Target to which to add value
+                          const char *recipeName, // Name for value in the recipe
+                          psMetadata *arguments,  // Command-line arguments
+                          const char *argName    // Argument name in the command-line arguments
     );
 
 bool ppSimArgToRecipeBool(bool *status,
-			  psMetadata *options,    // Target to which to add value
-			  const char *recipeName, // Name for value in the recipe
-			  psMetadata *arguments,  // Command-line arguments
-			  const char *argName	    // Argument name in the command-line arguments
+                          psMetadata *options,    // Target to which to add value
+                          const char *recipeName, // Name for value in the recipe
+                          psMetadata *arguments,  // Command-line arguments
+                          const char *argName       // Argument name in the command-line arguments
     );
 
@@ -198,3 +198,12 @@
 bool ppSimDefinePixels (psArray *sources, pmReadout *readout, psMetadata *recipe);
 
+/// Return software version
+psString ppSimVersion(void);
+
+/// Return software source
+psString ppSimSource(void);
+
+/// Return long version information
+psString ppSimVersionLong(void);
+
 #endif
Index: /branches/cnb_branches/cnb_branch_20090215/ppSim/src/ppSimVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSim/src/ppSimVersion.c	(revision 23199)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSim/src/ppSimVersion.c	(revision 23199)
@@ -0,0 +1,39 @@
+#include "ppSim.h"
+
+
+psString ppSimVersion(void)
+{
+#ifndef PPSIM_VERSION
+#error "PPSIM_VERSION is not set"
+#endif
+#ifndef PPSIM_BRANCH
+#error "PPSIM_BRANCH is not set"
+#endif
+    return psStringCopy(PPSIM_BRANCH "@" PPSIM_VERSION);
+}
+
+psString ppSimSource(void)
+{
+#ifndef PPSIM_SOURCE
+#error "PPSIM_SOURCE is not set"
+#endif
+    return psStringCopy(PPSIM_SOURCE);
+}
+
+psString ppSimVersionLong(void)
+{
+    psString version = ppSimVersion();  // Version, to return
+    psString source = ppSimSource();    // Source
+
+    psStringPrepend(&version, "ppSim ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
+    return version;
+};
Index: /branches/cnb_branches/cnb_branch_20090215/ppStack/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/Makefile.am	(revision 23199)
@@ -1,5 +1,14 @@
 bin_PROGRAMS = ppStack
 
-ppStack_CFLAGS 	= $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSPHOT_CFLAGS) $(PPSTATS_CFLAGS) $(PPSTACK_CFLAGS)
+PPSTACK_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PPSTACK_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`
+PPSTACK_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of ppStackVersion.c, since it gets the version information
+ppStackVersion.c: FORCE
+	touch ppStackVersion.c
+FORCE: ;
+
+ppStack_CFLAGS 	= $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSPHOT_CFLAGS) $(PPSTATS_CFLAGS) $(PPSTACK_CFLAGS) -DPPSTACK_VERSION=\"$(PPSTACK_VERSION)\" -DPPSTACK_BRANCH=\"$(PPSTACK_BRANCH)\" -DPPSTACK_SOURCE=\"$(PPSTACK_SOURCE)\"
 ppStack_LDFLAGS = $(PSLIB_LIBS)   $(PSMODULE_LIBS)   $(PSPHOT_LIBS)   $(PPSTATS_LIBS)   $(PPSTACK_LIBS)
 
Index: /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStack.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStack.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStack.c	(revision 23199)
@@ -33,4 +33,6 @@
         goto die;
     }
+
+    ppStackVersionPrint();
 
     if (!pmModelClassInit()) {
Index: /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStack.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStack.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStack.h	(revision 23199)
@@ -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
     );
 
@@ -134,10 +136,16 @@
 psString ppStackVersion(void);
 
+/// Return software source
+psString ppStackSource(void);
+
 // Return long description of software version
 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
@@ -158,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/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackArguments.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackArguments.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackArguments.c	(revision 23199)
@@ -294,5 +294,5 @@
     if (dump_file) {
         pmConfigCamerasCull(config, NULL);
-        pmConfigRecipesCull(config, "PPSTACK,PPSUB,PPSTATS,PSPHOT,MASKS");
+        pmConfigRecipesCull(config, "PPSTACK,PPSUB,PPSTATS,PSPHOT,MASKS,JPEG");
 
         pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PPSTACK.INPUT"); // Input file
Index: /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackLoop.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackLoop.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackLoop.c	(revision 23199)
@@ -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);
@@ -1168,6 +1178,9 @@
         fileActivation(config, photFiles, true);
         pmFPAview *photView = filesIterateDown(config);
+        fileActivation(config, combineFiles, true);
+
         if (!ppStackPhotometry(config, outRO, photView)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry on output.");
+            filesIterateUp(config);
             psFree(outRO);
             psFree(photView);
@@ -1175,6 +1188,4 @@
         }
         psFree(photView);
-
-        fileActivation(config, combineFiles, true);
 
         if (stats) {
@@ -1217,5 +1228,5 @@
         hdu->header = psMetadataAlloc();
     }
-    ppStackVersionMetadata(hdu->header);
+    ppStackVersionHeader(hdu->header);
 
     psFree(outRO);
Index: /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackPSF.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackPSF.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackPSF.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackPhotometry.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackPhotometry.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackPhotometry.c	(revision 23199)
@@ -149,7 +149,6 @@
     if (!psphotReadoutKnownSources(config, view, inSources)) {
         // Clear the error, so that the output files are written.
-        psWarning("Unable to perform photometry on stacked image.");
-        psErrorStackPrint(stderr, "Error stack from photometry:");
-        psErrorClear();
+        psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry on stacked image.");
+        return false;
     }
 
Index: /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackSources.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackSources.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackSources.c	(revision 23199)
@@ -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
@@ -63,5 +107,5 @@
         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
@@ -115,35 +159,25 @@
         return NAN;
     }
+
+#ifdef TESTING
+    dumpMatches("source_match.dat", num, matches, zp, NULL);
+#endif
+
     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
+    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
@@ -172,8 +206,4 @@
 
     psFree(matches);
-    if (!trans) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to measure transparencies");
-        return NAN;
-    }
 
     // M = m + c0 + c1 * airmass - 2.5log(t) + transparency
@@ -183,4 +213,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/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackThread.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackThread.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackThread.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStack/src/ppStackVersion.c	(revision 23199)
@@ -7,51 +7,101 @@
 #include <psmodules.h>
 #include <ppStats.h>
+#include <psphot.h>
 
 #include "ppStack.h"
 
-static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
-
 psString ppStackVersion(void)
 {
-    psString version = NULL;            // Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PPSTACK_VERSION
+#error "PPSTACK_VERSION is not set"
+#endif
+#ifndef PPSTACK_BRANCH
+#error "PPSTACK_BRANCH is not set"
+#endif
+    return psStringCopy(PPSTACK_BRANCH "@" PPSTACK_VERSION);
+}
+
+psString ppStackSource(void)
+{
+#ifndef PPSTACK_SOURCE
+#error "PPSTACK_SOURCE is not set"
+#endif
+    return psStringCopy(PPSTACK_SOURCE);
 }
 
 psString ppStackVersionLong(void)
 {
-    psString version = ppStackVersion(); // Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
-    psFree(tag);
+    psString version = ppStackVersion();  // Version, to return
+    psString source = ppStackSource();    // Source
+
+    psStringPrepend(&version, "ppStack ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
     return version;
-}
+};
 
 
-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/cnb_branches/cnb_branch_20090215/ppStats/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStats/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStats/src/Makefile.am	(revision 23199)
@@ -1,4 +1,14 @@
 lib_LTLIBRARIES = libppStats.la
-libppStats_la_CFLAGS = $(PPSTATS_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+
+PPSTATS_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PPSTATS_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`
+PPSTATS_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of ppStatsVersion.c, since it gets the version information
+ppStatsVersion.c: FORCE
+	touch ppStatsVersion.c
+FORCE: ;
+
+libppStats_la_CFLAGS = $(PPSTATS_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) -DPPSTATS_VERSION=\"$(PPSTATS_VERSION)\" -DPPSTATS_BRANCH=\"$(PPSTATS_BRANCH)\" -DPPSTATS_SOURCE=\"$(PPSTATS_SOURCE)\"
 libppStats_la_LDFLAGS = $(PPSTATS_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
 
Index: /branches/cnb_branches/cnb_branch_20090215/ppStats/src/ppStats.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStats/src/ppStats.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStats/src/ppStats.h	(revision 23199)
@@ -22,7 +22,7 @@
     psList *summary;                    // Summary statistics to calculate
     // Options for input data
-    bool doFirstReadout3D;		// for 3D data, use the first readout?
+    bool doFirstReadout3D;              // for 3D data, use the first readout?
     float sample;                       // Fraction of cell to sample for statistics
-    psImageMaskType maskVal;		// Mask value for images
+    psImageMaskType maskVal;            // Mask value for images
     psList *chips;                      // Chips to look at
     psList *cells;                      // Cells to look at
@@ -108,6 +108,15 @@
 psString ppStatsVersion(void);
 
+/// Return source information
+psString ppStatsSource(void);
+
 /// Return long version information
 psString ppStatsVersionLong(void);
+
+/// Populate header with version information
+bool ppStatsVersionHeader(
+    psMetadata *header                  ///< Header to populate
+    );
+
 
 void p_ppStatsGetMetadata(psMetadata *target, // Target for metadata
Index: /branches/cnb_branches/cnb_branch_20090215/ppStats/src/ppStatsFromMetadataPrint.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStats/src/ppStatsFromMetadataPrint.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStats/src/ppStatsFromMetadataPrint.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppStats/src/ppStatsVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppStats/src/ppStatsVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppStats/src/ppStatsVersion.c	(revision 23199)
@@ -1,19 +1,56 @@
 #include "ppStatsInternal.h"
-
-static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
 
 psString ppStatsVersion(void)
 {
-    psString version = NULL;            // Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PPSTATS_VERSION
+#error "PPSTATS_VERSION is not set"
+#endif
+#ifndef PPSTATS_BRANCH
+#error "PPSTATS_BRANCH is not set"
+#endif
+    return psStringCopy(PPSTATS_BRANCH "@" PPSTATS_VERSION);
+}
+
+psString ppStatsSource(void)
+{
+#ifndef PPSTATS_SOURCE
+#error "PPSTATS_SOURCE is not set"
+#endif
+    return psStringCopy(PPSTATS_SOURCE);
 }
 
 psString ppStatsVersionLong(void)
 {
-    psString version = ppStatsVersion(); // Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
-    psFree(tag);
+    psString version = ppStatsVersion();  // Version, to return
+    psString source = ppStatsSource();    // Source
+
+    psStringPrepend(&version, "ppStats ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
     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/cnb_branches/cnb_branch_20090215/ppSub/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSub/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSub/src/Makefile.am	(revision 23199)
@@ -1,5 +1,14 @@
 bin_PROGRAMS = ppSub ppSubKernel
 
-ppSub_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PPSUB_CFLAGS)
+PPSUB_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PPSUB_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`
+PPSUB_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of ppSubVersion.c, since it gets the version information
+ppSubVersion.c: FORCE
+	touch ppSubVersion.c
+FORCE: ;
+
+ppSub_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PPSUB_CFLAGS) -DPPSUB_VERSION=\"$(PPSUB_VERSION)\" -DPPSUB_BRANCH=\"$(PPSUB_BRANCH)\" -DPPSUB_SOURCE=\"$(PPSUB_SOURCE)\"
 ppSub_LDFLAGS  = $(PSLIB_LIBS)   $(PSMODULE_LIBS)   $(PPSTATS_LIBS)   $(PSPHOT_LIBS)   $(PPSUB_LIBS)
 
Index: /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSub.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSub.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSub.c	(revision 23199)
@@ -34,4 +34,6 @@
         goto die;
     }
+
+    ppSubVersionPrint();
 
     if (!pmModelClassInit()) {
Index: /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSub.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSub.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSub.h	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubArguments.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubArguments.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubArguments.c	(revision 23199)
@@ -377,5 +377,5 @@
     if (dump_file) {
         pmConfigCamerasCull(config, NULL);
-        pmConfigRecipesCull(config, "PPSUB,PPSTATS,PSPHOT,MASKS");
+        pmConfigRecipesCull(config, "PPSUB,PPSTATS,PSPHOT,MASKS,JPEG");
 
         pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PPSUB.INPUT"); // Input file
Index: /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubLoop.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubLoop.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubLoop.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubReadoutUpdate.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubReadoutUpdate.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubReadoutUpdate.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/ppSub/src/ppSubVersion.c	(revision 23199)
@@ -19,51 +19,101 @@
 #include <psmodules.h>
 #include <ppStats.h>
+#include <psphot.h>
 
 #include "ppSub.h"
 
-static const char *cvsTag = "$Name: not supported by cvs2svn $";///< CVS tag name
-
 psString ppSubVersion(void)
 {
-    psString version = NULL;            // Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PPSUB_VERSION
+#error "PPSUB_VERSION is not set"
+#endif
+#ifndef PPSUB_BRANCH
+#error "PPSUB_BRANCH is not set"
+#endif
+    return psStringCopy(PPSUB_BRANCH "@" PPSUB_VERSION);
+}
+
+psString ppSubSource(void)
+{
+#ifndef PPSUB_SOURCE
+#error "PPSUB_SOURCE is not set"
+#endif
+    return psStringCopy(PPSUB_SOURCE);
 }
 
 psString ppSubVersionLong(void)
 {
-    psString version = ppSubVersion(); // Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
-    psFree(tag);
+    psString version = ppSubVersion();  // Version, to return
+    psString source = ppSubSource();    // Source
+
+    psStringPrepend(&version, "ppSub ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
     return version;
-}
+};
 
 
-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/cnb_branches/cnb_branch_20090215/psLib/configure.ac
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/configure.ac	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/configure.ac	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psLib/src/fits/psFitsHeader.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/fits/psFitsHeader.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/fits/psFitsHeader.c	(revision 23199)
@@ -149,5 +149,5 @@
 
 
-bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, psMetadata *header)
+bool psFitsCheckCompressedImagePHU(const psFits *fits, psMetadata *header)
 {
     PS_ASSERT_FITS_NON_NULL(fits, false);
@@ -163,6 +163,6 @@
     }
 
-    if (psFitsGetSize(fits) != 2) {
-        // No second extension, or multiple extensions
+    if (psFitsGetSize(fits) == 1) {
+        // No extension present
         return false;
     }
@@ -416,5 +416,5 @@
     // Explore the potential case that this is an empty PHU, and the first extension contains the sole image,
     // which is compressed.
-    if (psFitsCheckSingleCompressedImagePHU(fits, header)) {
+    if (psFitsCheckCompressedImagePHU(fits, header)) {
         // This is really what we want, not the empty PHU
         psTrace("psLib.fits", 1,
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/fits/psFitsHeader.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/fits/psFitsHeader.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/fits/psFitsHeader.h	(revision 23199)
@@ -20,5 +20,5 @@
 
 
-/// Determine whether the current HDU is an empty PHU with a single compressed image following.
+/// Determine whether the current HDU is an empty PHU with a compressed image following.
 ///
 /// In that case, what should be treated as an image PHU is technically an empty PHU with a binary table
@@ -26,6 +26,6 @@
 /// following compressed image to determine if this is the case.  If so, the FITS file pointer is left
 /// pointing at the compressed image.
-bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, ///< FITS file pointer
-                                         const psMetadata *header ///< Header, or NULL
+bool psFitsCheckCompressedImagePHU(const psFits *fits, ///< FITS file pointer
+                                   const psMetadata *header ///< Header, or NULL
     );
 
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/fits/psFitsImage.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/fits/psFitsImage.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/fits/psFitsImage.c	(revision 23199)
@@ -219,5 +219,5 @@
     PS_ASSERT_FITS_NON_NULL(fits, NULL);
 
-    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+    if (psFitsCheckCompressedImagePHU(fits, NULL)) {
         // This is really what we want, not the empty PHU
         psTrace("psLib.fits", 1,
@@ -432,5 +432,5 @@
     PS_ASSERT_INT_NONNEGATIVE(z, NULL);
 
-    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+    if (psFitsCheckCompressedImagePHU(fits, NULL)) {
         // This is really what we want, not the empty PHU
         psTrace("psLib.fits", 1,
@@ -479,5 +479,5 @@
     }
 
-    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+    if (psFitsCheckCompressedImagePHU(fits, NULL)) {
         // This is really what we want, not the empty PHU
         psTrace("psLib.fits", 1,
@@ -873,5 +873,5 @@
     // code replication, and should be sufficient for our needs.
 
-    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
+    if (psFitsCheckCompressedImagePHU(fits, NULL)) {
         // This is really what we want, not the empty PHU
         psTrace("psLib.fits", 1,
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/imageops/psImageCovariance.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/imageops/psImageCovariance.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/imageops/psImageCovariance.c	(revision 23199)
@@ -43,4 +43,26 @@
     } else {
         covar = psImageCovarianceNone();
+    }
+
+    // Check for non-finite elements
+    for (int y = kernel->yMin; y <= kernel->yMax; y++) {
+        for (int x = kernel->xMin; x <= kernel->xMax; x++) {
+            if (!isfinite(kernel->kernel[y][x])) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        "Non-finite covariance matrix element in kernel at %d,%d", x, y);
+                psFree(covar);
+                return NULL;
+            }
+        }
+    }
+    for (int y = covar->yMin; y <= covar->yMax; y++) {
+        for (int x = covar->xMin; x <= covar->xMax; x++) {
+            if (!isfinite(covar->kernel[y][x])) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        "Non-finite covariance matrix element in covariance matrix at %d,%d", x, y);
+                psFree(covar);
+                return NULL;
+            }
+        }
     }
 
@@ -110,5 +132,5 @@
 float psImageCovarianceFactor(const psKernel *covariance)
 {
-    return covariance ? covariance->kernel[0][0] : NAN;
+    return covariance ? covariance->kernel[0][0] : 1.0;
 }
 
@@ -144,4 +166,11 @@
         for (int y = covar->yMin; y <= covar->yMax; y++) {
             for (int x = covar->xMin; x <= covar->xMax; x++) {
+                if (!isfinite(covar->kernel[y][x])) {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                            "Non-finite covariance matrix element at %d,%d for input %d",
+                            x, y, i);
+                    psFree(sum);
+                    return NULL;
+                }
                 sum->kernel[y][x] += covar->kernel[y][x];
             }
@@ -192,4 +221,9 @@
             int radius = PS_MAX(abs(x), abs(y)); // Squarish radius
             psAssert(radius <= maxRadius, "Radius doesn't fit");
+            if (!isfinite(covar->kernel[y][x])) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Non-finite covariance matrix element at %d,%d",
+                        x, y);
+                return NULL;
+            }
             radiusSum->data.F64[radius] += fabsf(covar->kernel[y][x]);
             sum += fabsf(covar->kernel[y][x]);
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/pslib_strict.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/pslib_strict.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/pslib_strict.h	(revision 23199)
@@ -110,4 +110,5 @@
 #include "psMetadataItemParse.h"
 #include "psMetadataItemCompare.h"
+#include "psMetadataHeader.h"
 #include "psPixels.h"
 #include "psArguments.h"
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/sys/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/sys/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/sys/Makefile.am	(revision 23199)
@@ -3,5 +3,14 @@
 noinst_LTLIBRARIES = libpslibsys.la
 
-libpslibsys_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(CFITSIO_CFLAGS)
+PSLIB_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PSLIB_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`
+PSLIB_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of psConfigure.c, since it gets the version information
+psConfigure.c: FORCE
+	touch psConfigure.c
+FORCE: ;
+
+libpslibsys_la_CPPFLAGS = $(SRCINC) $(PSLIB_CFLAGS) $(CFITSIO_CFLAGS) -DPSLIB_VERSION=\"$(PSLIB_VERSION)\" -DPSLIB_BRANCH=\"$(PSLIB_BRANCH)\" -DPSLIB_SOURCE=\"$(PSLIB_SOURCE)\"
 libpslibsys_la_SOURCES = \
 	psAbort.c \
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/sys/psConfigure.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/sys/psConfigure.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/sys/psConfigure.c	(revision 23199)
@@ -12,9 +12,7 @@
  *  @author Ross Harman, MHPCC
  *  @author Robert DeSonia, MHPCC
+ *  @author Paul Price, IfA
  *
- *  @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-08-08 18:05:08 $
- *
- *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *  Copyright 2004-2009 Institute for Astronomy, University of Hawaii
  */
 
@@ -26,4 +24,12 @@
 #include <stdlib.h>
 #include <string.h>
+
+#include <fitsio.h>
+#include <longnam.h>
+#include <fftw3.h>
+#include <gsl/gsl_version.h>
+#ifdef HAVE_PSDB
+#include <mysql.h>
+#endif
 
 #include "psAbort.h"
@@ -41,26 +47,64 @@
 static FILE *memCheckFile = NULL;       // File to which to write results of mem check
 
-static const char *cvsTag = "$Name: not supported by cvs2svn $"; // CVS tag name
 
 psString psLibVersion(void)
 {
-    psString version = NULL;            // Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PSLIB_VERSION
+#error "PSLIB_VERSION is not set"
+#endif
+#ifndef PSLIB_BRANCH
+#error "PSLIB_BRANCH is not set"
+#endif
+    return psStringCopy(PSLIB_BRANCH "@" PSLIB_VERSION);
+}
+
+psString psLibSource(void)
+{
+#ifndef PSLIB_SOURCE
+#error "PSLIB_SOURCE is not set"
+#endif
+    return psStringCopy(PSLIB_SOURCE);
+}
+
+psString psLibDependencies(void)
+{
+    psString deps = NULL;               // Dependencies, to return
+    float cfitsioVersion;               // CFITSIO version number
+    psStringAppend(&deps, "cfitsio-%.3f gsl-%s %s",
+                   fits_get_version(&cfitsioVersion), gsl_version, fftwf_version);
+
+#ifdef HAVE_PSDB
+    psStringAppend(&deps, " mysql-%s", mysql_get_client_info());
+#endif
+
+    return deps;
 }
 
 psString psLibVersionLong(void)
 {
-    psString version = psLibVersion();    // Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
+    psString version = psLibVersion();  // Version, to return
+    psString source = psLibSource();    // Source
+    psString deps = psLibDependencies();// Dependencies
 
-#ifdef HAVE_PSDB
-    psStringAppend(&version, " (cvs tag %s), %s, %s with psDB", tag, __DATE__, __TIME__);
+    psStringPrepend(&version, "psLib ");
+    psStringAppend(&version, " from %s, built %s, %s with %s",
+                   source, __DATE__, __TIME__, deps);
+    psFree(source);
+    psFree(deps);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
 #else
-    psStringAppend(&version, " (cvs tag %s), %s, %s without psDB", tag, __DATE__, __TIME__);
+    psStringAppend(&version, " unoptimised");
 #endif
-    psFree(tag);
+
+#ifdef PS_NO_TRACE
+    psStringAppend(&version, " without trace");
+#else
+    psStringAppend(&version, " with trace");
+#endif
+
     return version;
-}
+};
 
 // Check the memory; intended for use on exit, but might be used elsewhere
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/sys/psConfigure.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/sys/psConfigure.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/sys/psConfigure.h	(revision 23199)
@@ -20,4 +20,6 @@
 #define PS_CONFIGURE_H
 
+#include <psString.h>
+
 /// @addtogroup SysUtils System Utilities
 /// @{
@@ -29,8 +31,21 @@
  *  @return psString: String with version name.
  */
-psString psLibVersion(
-    void
-);
+psString psLibVersion(void);
 
+/** Get current psLib source
+ *
+ * Returns the current psLib source name as a string.
+ *
+ * @return psString: String with source name.
+ */
+psString psLibSource(void);
+
+/** Get psLib dependencies' versions
+ *
+ * Returns the psLib dependency versions as a string.
+ *
+ * @return psString: String with dependencies.
+ */
+psString psLibDependencies(void);
 
 /** Get current psLib version (full identification)
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/Makefile.am	(revision 23199)
@@ -14,4 +14,5 @@
 	psMetadataItemParse.c \
 	psMetadataItemCompare.c \
+	psMetadataHeader.c \
 	psPixels.c \
 	psArguments.c	\
@@ -30,4 +31,5 @@
 	psMetadataItemParse.h \
 	psMetadataItemCompare.h \
+	psMetadataHeader.h \
 	psPixels.h \
 	psArguments.h	\
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/psMetadata.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/psMetadata.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/psMetadata.h	(revision 23199)
@@ -30,4 +30,5 @@
 #include "psLookupTable.h"
 #include "psMutex.h"
+#include "psError.h"
 
 #define PS_DATA_IS_PRIMITIVE(TYPE) \
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/psMetadataHeader.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/psMetadataHeader.c	(revision 23199)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/psMetadataHeader.c	(revision 23199)
@@ -0,0 +1,29 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include "psMemory.h"
+#include "psConfigure.h"
+#include "psMetadata.h"
+
+#include "psMetadataHeader.h"
+
+bool psLibVersionHeader(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psString version = psLibVersion();  // Software version
+    psString source = psLibSource();    // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSLIB.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSLIB.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
Index: /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/psMetadataHeader.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/psMetadataHeader.h	(revision 23199)
+++ /branches/cnb_branches/cnb_branch_20090215/psLib/src/types/psMetadataHeader.h	(revision 23199)
@@ -0,0 +1,12 @@
+#ifndef PS_METADATA_HEADER_H
+#define PS_METADATA_HEADER_H
+
+#include <psMetadata.h>
+
+/// Populate a header with version information
+bool psLibVersionHeader(
+    psMetadata *header                  ///< Header to populate
+    );
+
+
+#endif
Index: /branches/cnb_branches/cnb_branch_20090215/psModules/src/camera/pmFPAWrite.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/camera/pmFPAWrite.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/camera/pmFPAWrite.c	(revision 23199)
@@ -692,4 +692,19 @@
                      "Centre of covariance matrix in y", -yMinCovar);
 
+    // Turn off compression
+    int bitpix = fits->options ? fits->options->bitpix : 0; // Desired bits per pixel
+    psFitsCompression *compress = psFitsCompressionGet(fits); // Current compression options
+    if (!psFitsSetCompression(fits, PS_FITS_COMPRESS_NONE, NULL, 0, 0, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to set FITS compression to NONE");
+        psFree(extname);
+        psFree(header);
+        psFree(images);
+        psFree(compress);
+        return false;
+    }
+    if (fits->options) {
+        fits->options->bitpix = 0;
+    }
+
     // Write images
     if (!psFitsWriteImageCube(fits, header, images, extname)) {
@@ -699,4 +714,9 @@
         psFree(header);
         psFree(images);
+        if (fits->options) {
+            fits->options->bitpix = bitpix;
+        }
+        psFitsCompressionApply(fits, compress);
+        psFree(compress);
         return 0;
     }
@@ -704,4 +724,15 @@
     psFree(header);
     psFree(images);
+
+    // Restore compression
+    if (fits->options) {
+        fits->options->bitpix = bitpix;
+    }
+    if (!psFitsCompressionApply(fits, compress)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to set FITS compression to NONE");
+        psFree(compress);
+        return false;
+    }
+    psFree(compress);
 
     return true;
Index: /branches/cnb_branches/cnb_branch_20090215/psModules/src/config/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/config/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/config/Makefile.am	(revision 23199)
@@ -1,5 +1,14 @@
 noinst_LTLIBRARIES = libpsmodulesconfig.la
 
-libpsmodulesconfig_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS)
+PSMODULES_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PSMODULES_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`
+PSMODULES_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of pmVersion.c, since it gets the version information
+pmVersion.c: FORCE
+	touch pmVersion.c
+FORCE: ;
+
+libpsmodulesconfig_la_CPPFLAGS = $(SRCINC) $(PSMODULES_CFLAGS) -DPSMODULES_VERSION=\"$(PSMODULES_VERSION)\" -DPSMODULES_BRANCH=\"$(PSMODULES_BRANCH)\" -DPSMODULES_SOURCE=\"$(PSMODULES_SOURCE)\"
 libpsmodulesconfig_la_LDFLAGS  = -release $(PACKAGE_VERSION)
 libpsmodulesconfig_la_SOURCES  = \
Index: /branches/cnb_branches/cnb_branch_20090215/psModules/src/config/pmVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/config/pmVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/config/pmVersion.c	(revision 23199)
@@ -8,21 +8,64 @@
 #include "pmVersion.h"
 
-static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
-
 psString psModulesVersion(void)
 {
-    psString version = NULL;            // Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PSMODULES_VERSION
+#error "PSMODULES_VERSION is not set"
+#endif
+#ifndef PSMODULES_BRANCH
+#error "PSMODULES_BRANCH is not set"
+#endif
+    return psStringCopy(PSMODULES_BRANCH "@" PSMODULES_VERSION);
 }
+
+psString psModulesSource(void)
+{
+#ifndef PSMODULES_SOURCE
+#error "PSMODULES_SOURCE is not set"
+#endif
+    return psStringCopy(PSMODULES_SOURCE);
+}
+
 
 psString psModulesVersionLong(void)
 {
-    psString version = psModulesVersion(); // Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
+    psString version = psModulesVersion();  // Version, to return
+    psString source = psModulesSource();    // Source
 
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
+    psStringPrepend(&version, "psModules ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
 
-    psFree(tag);
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
+#ifdef HAVE_NEBCLIENT
+    psStringAppend(&version, " with nebclient");
+#else
+    psStringAppend(&version, " without nebclient");
+#endif
+
     return version;
+};
+
+
+bool psModulesVersionHeader(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psString version = psModulesVersion(); // Software version
+    psString source = psModulesSource();   // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSMODULES.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSMODULES.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
 }
Index: /branches/cnb_branches/cnb_branch_20090215/psModules/src/config/pmVersion.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/config/pmVersion.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/config/pmVersion.h	(revision 23199)
@@ -1,8 +1,8 @@
 /*  @file pmVersion.h
  *  @brief Version functions
- * 
+ *
  *  @author Paul Price, IfA
  *  @author Eugene Magnier, IfA
- * 
+ *
  *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
  *  @date $Date: 2007-03-30 21:12:56 $
@@ -22,7 +22,13 @@
  *  @return psString: String with version name.
  */
-psString psModulesVersion(
-    void
-);
+psString psModulesVersion(void);
+
+/** Get current psModules source
+ *
+ *  Returns the current psModules source as a string.
+ *
+ *  @return psString: String with source.
+ */
+psString psModulesSource(void);
 
 /** Get current psModules version (full identification)
@@ -34,4 +40,10 @@
 psString psModulesVersionLong(void);
 
+/// Populate a header with version information
+bool psModulesVersionHeader(
+    psMetadata *header                  ///< Header to populate
+    );
+
+
 /// @}
 #endif
Index: /branches/cnb_branches/cnb_branch_20090215/psModules/src/imcombine/pmPSFEnvelope.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/imcombine/pmPSFEnvelope.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/imcombine/pmPSFEnvelope.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/Makefile.am	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmFootprint.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmFootprint.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmFootprint.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmModel.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmModel.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmModel.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmMoments.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmMoments.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmMoments.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmPeaks.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmPeaks.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmPeaks.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSource.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSource.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSource.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSource.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSource.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSource.h	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceContour.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceContour.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceContour.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceFitModel.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceFitModel.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceFitModel.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceFitSet.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceFitSet.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceFitSet.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceMasks.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceMasks.c	(revision 23199)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceMasks.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceMasks.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceMasks.h	(revision 23199)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceMasks.h	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceMatch.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceMatch.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceMatch.c	(revision 23199)
@@ -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;
+                }
+            }
         }
     }
@@ -529,7 +547,10 @@
     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, sysErr); // chi^2 for solution
     psTrace("psModules.objects", 1, "Initial: chi^2 = %f\n", chi2);
     float lastChi2 = INFINITY;          // chi^2 on last iteration
@@ -540,28 +561,5 @@
 
         // 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 +570,39 @@
             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, badImage, 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, badImage, matches, zp, photo, PS_SQR(0.1));
+        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, 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, "Determined %d/%d are photometric", numPhoto, numImages);
 
-        fracRej = sourceMatchRelphotReject(trans, stars, matches, zp, photo, starClip, sysErr);
+        fracRej = sourceMatchRelphotReject(trans, stars, matches, zp, photo, badImage, starClip, sysErr);
         psTrace("psModules.objects", 3, "%f%% of measurements rejected", fracRej * 100);
 
-        chi2 = sourceMatchRelphotIterate(trans, stars, matches, zp, photo, sysErr); // chi^2 for solution
+        chi2 = sourceMatchRelphotIterate(trans, stars, badImage, matches, zp, photo, sysErr);
         psTrace("psModules.objects", 1, "iter = %d: chi^2 = %f rejected = %f\n", i, chi2, fracRej);
     }
 
     psFree(photo);
+    psFree(badImage);
     psFree(stars);
 
Index: /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceSky.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceSky.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceSky.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceUtils.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceUtils.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceUtils.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceVisual.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceVisual.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceVisual.c	(revision 23199)
@@ -7,6 +7,6 @@
 #include "pmSourceVisual.h"
 
-# if (HAVE_KAPA)
-# include <kapa.h>
+#if (HAVE_KAPA)
+#include <kapa.h>
 #include "pmVisual.h"
 
@@ -155,4 +155,5 @@
     // continue, save (provide name), ??
     pmVisualAskUser(&plotPSF);
+
     return true;
 }
@@ -251,4 +252,15 @@
 }
 
-# else
-# endif
+#else
+
+bool pmSourceSetVisual(bool mode)
+{
+    return true;
+}
+
+bool pmSourceVisualPSFModelResid(pmTrend2D *trend, psVector *x, psVector *y, psVector *param, psVector *mask)
+{
+    return true;
+}
+
+#endif
Index: /branches/cnb_branches/cnb_branch_20090215/psModules/src/psmodules.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psModules/src/psmodules.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psModules/src/psmodules.h	(revision 23199)
@@ -114,4 +114,5 @@
 #include <pmPSF.h>
 #include <pmModel.h>
+#include <pmSourceMasks.h>
 #include <pmSource.h>
 #include <pmSourceUtils.h>
Index: /branches/cnb_branches/cnb_branch_20090215/psastro/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psastro/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psastro/src/Makefile.am	(revision 23199)
@@ -1,6 +1,15 @@
+lib_LTLIBRARIES = libpsastro.la
 
-lib_LTLIBRARIES = libpsastro.la
-libpsastro_la_CFLAGS = $(PSASTRO_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
-libpsastro_la_LDFLAGS = $(PSASTRO_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
+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
+psastroVersion.c: FORCE
+	touch psastroVersion.c
+FORCE: ;
+
+libpsastro_la_CFLAGS = $(PSASTRO_CFLAGS) $(PPSTATS_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) -DPSASTRO_VERSION=\"$(PSASTRO_VERSION)\" -DPSASTRO_BRANCH=\"$(PSASTRO_BRANCH)\" -DPSASTRO_SOURCE=\"$(PSASTRO_SOURCE)\"
+libpsastro_la_LDFLAGS = $(PSASTRO_LIBS) $(PPSTATS_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
 
 bin_PROGRAMS = psastro psastroModel psastroModelFit gpcModel
Index: /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastro.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastro.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastro.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psastro/src/psastro.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastro.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastro.h	(revision 23199)
@@ -95,5 +95,9 @@
 // Return version strings.
 psString          psastroVersion(void);
+psString          psastroSource(void);
 psString          psastroVersionLong(void);
+bool              psastroVersionHeader(psMetadata *header);
+bool              psastroVersionHeaderFull(psMetadata *header);
+void              psastroVersionPrint(void);
 
 // demo plots
Index: /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastroDataSave.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastroDataSave.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastroDataSave.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psastro/src/psastroVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastroVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psastro/src/psastroVersion.c	(revision 23199)
@@ -5,7 +5,4 @@
  *  @ingroup libpsastro
  *
- *  @author IfA
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2009-02-07 02:03:34 $
  *  Copyright 2009 Institute for Astronomy, University of Hawaii
  */
@@ -13,20 +10,103 @@
 #include "psastroInternal.h"
 
-static const char *cvsTag = "$Name: not supported by cvs2svn $";///< CVS tag name
-
 psString psastroVersion(void)
 {
-    psString version = NULL;            // Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PSASTRO_VERSION
+#error "PSASTRO_VERSION is not set"
+#endif
+#ifndef PSASTRO_BRANCH
+#error "PSASTRO_BRANCH is not set"
+#endif
+    return psStringCopy(PSASTRO_BRANCH "@" PSASTRO_VERSION);
+}
+
+psString psastroSource(void)
+{
+#ifndef PSASTRO_SOURCE
+#error "PSASTRO_SOURCE is not set"
+#endif
+    return psStringCopy(PSASTRO_SOURCE);
 }
 
 psString psastroVersionLong(void)
 {
-    psString version = psastroVersion(); // Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
-    psFree(tag);
+    psString version = psastroVersion();  // Version, to return
+    psString source = psastroSource();    // Source
+
+    psStringPrepend(&version, "psastro ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
     return version;
+};
+
+bool psastroVersionHeader(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psString version = psastroVersion(); // Software version
+    psString source = psastroSource();   // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSASTRO.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSASTRO.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    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/cnb_branches/cnb_branch_20090215/psconfig/psbuild
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psconfig/psbuild	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psconfig/psbuild	(revision 23199)
@@ -247,12 +247,12 @@
 
         if (-e "Build.PL") {
-            vsystem ("$psperlbuild");
-            if ($?) { &failure($module[$i], "failure in perl Build.PL"); }
-
-            vsystem ("./Build");
-            if ($?) { &failure($module[$i], "failure in Build"); }
-
-            vsystem ("./Build install");
-            if ($?) { &failure($module[$i], "failure in Build install"); }
+            $status = vsystem ("$psperlbuild");
+            if ($status) { &failure($module[$i], "failure in perl Build.PL"); }
+
+            $status = vsystem ("./Build");
+            if ($status) { &failure($module[$i], "failure in Build"); }
+
+            $status = vsystem ("./Build install");
+            if ($status) { &failure($module[$i], "failure in Build install"); }
 
             next;
@@ -272,11 +272,11 @@
         if ($developer && $rebuild_this && ! -e "configure" && -e "autogen.sh") {
             $skip_configure = 1;
-            vsystem ("$psautogen $psopts");
-            if ($?) { &failure($module[$i], "failure in psautogen"); }
+            $status = vsystem ("$psautogen $psopts");
+            if ($status) { &failure($module[$i], "failure in psautogen"); }
         }
 
         if ($rebuild_this && -e "configure" && !$skip_configure) {
-            vsystem ("$psconfigure $psopts");
-            if ($?) { &failure($module[$i], "failure in psconfigure"); }
+            $status = vsystem ("$psconfigure $psopts");
+            if ($status) { &failure($module[$i], "failure in psconfigure"); }
         }
 
@@ -288,13 +288,13 @@
 
         if ($clean) {
-            vsystem ("$make clean");
-            if ($?) { &failure($module[$i], "failure in make clean"); }
-        }
-
-        vsystem ("$make");
-        if ($?) { &failure($module[$i], "failure in make"); }
-
-        vsystem ("$make install");
-        if ($?) { &failure($module[$i], "failure in make install"); }
+            $status = vsystem ("$make clean");
+            if ($status) { &failure($module[$i], "failure in make clean"); }
+        }
+
+        $status = vsystem ("$make");
+        if ($status) { &failure($module[$i], "failure in make"); }
+
+        $status = vsystem ("$make install");
+        if ($status) { &failure($module[$i], "failure in make install"); }
 
         print "*** done with $module[$i] ***\n";
Index: /branches/cnb_branches/cnb_branch_20090215/psconfig/pschecklibs
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psconfig/pschecklibs	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psconfig/pschecklibs	(revision 23199)
@@ -487,5 +487,5 @@
 
 sub usage {
-    print STDERR "USAGE: pscheckperl [-version] [-build]\n";
+    print STDERR "USAGE: pschecklibs [-version] [-build]\n";
     exit 2;
 }
Index: /branches/cnb_branches/cnb_branch_20090215/psconfig/tagsets/ipp-2.8.dist
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psconfig/tagsets/ipp-2.8.dist	(revision 23199)
+++ /branches/cnb_branches/cnb_branch_20090215/psconfig/tagsets/ipp-2.8.dist	(revision 23199)
@@ -0,0 +1,70 @@
+# necessary fields:                    
+# |-- tag?
+# ||-- build?
+# |||-- package? 
+# ||||-- update directory from CVS?
+# |||||-- build for developer?
+# |||||
+# |||||  module                 branch name      tag version   
+# ||||| 
+  YYNNY  Ohana                  ipp-2-8          -0
+  NNYYN  ohana.base             ipp-2-8          -0
+  NNYYN  libohana               ipp-2-8          -0
+  NNYYN  libfits                ipp-2-8          -0
+  NNYYN  libautocode            ipp-2-8          -0
+  NNYYN  libdvo                 ipp-2-8          -0
+  NNYYN  libkapa                ipp-2-8          -0
+  NNYYN  libtap.ohana           ipp-2-8          -0
+  NNYYN  addstar                ipp-2-8          -0
+  NNYYN  delstar                ipp-2-8          -0
+  NNYYN  getstar                ipp-2-8          -0
+  NNYYN  ohana.tools            ipp-2-8          -0
+  NNYYN  kapa2                  ipp-2-8          -0
+  NNYYN  relphot                ipp-2-8          -0
+  NNYYN  relastro               ipp-2-8          -0
+  NNYYN  uniphot                ipp-2-8          -0
+  NNYYN  opihi.base             ipp-2-8          -0
+  NNYYN  mana                   ipp-2-8          -0
+  NNYYN  dvo                    ipp-2-8          -0
+  NNYYN  pantasks               ipp-2-8          -0
+  NNYYN  pcontrol               ipp-2-8          -0
+  NNYYN  pclient                ipp-2-8          -0      
+          
+  YNNYY  Nebulous/nebclient     ipp-2-8          -0
+  YNNYY  Nebulous               ipp-2-8          -0
+  YYYYY  PS-IPP-Metadata-Config ipp-2-8          -0
+  YYYYY  PS-IPP-Config          ipp-2-8          -0     
+          
+  YYYYY  psLib                  ipp-2-8          -0
+  YYYYY  psModules              ipp-2-8          -0
+  YYYYY  ppStats                ipp-2-8          -0
+  YYYYY  psphot                 ipp-2-8          -0
+  YYYYY  psastro                ipp-2-8          -0
+  YYYYY  ppConfigDump           ipp-2-8          -0
+  YYYYY  ppImage                ipp-2-8          -0
+  YYYYY  ppNorm                 ipp-2-8          -0
+  YYYYY  ppMerge                ipp-2-8          -0
+  YNNYN  pedestal               ipp-2-8          -0
+  YYYYY  dvoTools               ipp-2-8          -0
+  YYYYY  pswarp                 ipp-2-8          -0
+  YYYYY  ppArith                ipp-2-8          -0
+  YYYYY  ppStack                ipp-2-8          -0
+  YYYYY  ppSub                  ipp-2-8          -0
+  YYYYY  ppSim                  ipp-2-8          -0
+          
+  YNNYY  glueforge              ipp-2-8          -0
+  YNNYY  dbconfig               ipp-2-8          -0
+  NNNNY  ippdb.src             
+  YYYNN  ippdb                  ipp-2-8          -0
+  YYYYY  PStamp                 ipp-2-8          -0
+  YYYYY  pstamp                 ipp-2-8          -0
+  YYYYY  ippTools               ipp-2-8          -0
+  YYYYY  ippScripts             ipp-2-8          -0
+  YYYYY  ippTasks               ipp-2-8          -0
+          
+  YYYYY  ippconfig              ipp-2-8          -0
+  YNYYN  psconfig               ipp-2-8          -0
+  YNYYN  ippMonitor             ipp-2-8          -0
+  YYYYY  DataStore              ipp-2-8          -0
+
+# there are externally required C libraries and perl modules (see INSTALL)
Index: /branches/cnb_branches/cnb_branch_20090215/psconfig/tagsets/ipp-2.8.libs
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psconfig/tagsets/ipp-2.8.libs	(revision 23199)
+++ /branches/cnb_branches/cnb_branch_20090215/psconfig/tagsets/ipp-2.8.libs	(revision 23199)
@@ -0,0 +1,94 @@
+# this file defines C libraries and C headers needed by the ipp, and information on finding them
+
+# directories to search: /lib, /usr/lib, /usr/X11R6/lib, etc.
+# modifications based on the architecture (eg, PATH/lib64, etc)
+# additional locations based on the env variables
+# dlltype to use
+
+# each entry contains:
+#   type : lib / include
+#   name 
+#   alternate names
+#   alternate paths
+#   tarball name
+#   tar directory
+#   force install by default?
+#   configure options
+#   make options
+#   make install options
+
+lib libm                 NONE           NONE   NONE                     NONE             N NONE NONE NONE
+lib libX11               NONE           NONE   NONE                     NONE             N NONE NONE NONE
+lib libpthread           NONE           NONE   NONE                     NONE             N NONE NONE NONE
+lib libncurses           curses,termcap NONE   ncurses-5.6.tar.gz       ncurses-5.6      N NONE NONE NONE
+lib libreadline          NONE           NONE   readline-5.2-p12.tar.gz  readline-5.2-p12 Y NONE NONE NONE
+lib libz                 NONE           NONE   zlib-1.2.3.tar.gz        zlib-1.2.3       N --shared NONE NONE
+lib libpng               NONE           NONE   libpng-1.2.15.tar.gz     libpng-1.2.15    N NONE NONE NONE
+lib libjpeg              NONE           jpeg   jpegsrc.v6b-p1.tar.gz    jpeg-6b          N --enable-shared NONE install-lib
+lib libcfitsio           NONE           NONE   cfitsio3100-pap.tar.gz   cfitsio3100-pap  N --enable-shared shared NONE
+#lib libmysqlclient      NONE           mysql  mysql-5.0.27.tar.gz      mysql-5.0.27     N NONE NONE NONE
+lib libmysqlclient       NONE           mysql  mysql-5.0.51a.tar.gz     mysql-5.0.51a    N NONE NONE NONE
+lib libgsl               NONE           NONE   gsl-1.11.tar.gz          gsl-1.11         N NONE NONE NONE
+lib libfftw3f            NONE           NONE   fftw-3.0.1.tar.gz        fftw-3.0.1       N --enable-float,--enable-shared,--disable-fortran NONE NONE
+#lib libfftw3            NONE           NONE   fftw-3.0.1.tar.gz        fftw-3.0.1       N --enable-shared,--disable-fortran NONE NONE
+# paul claims we are not currently using double-point FFTs anywhere
+
+bin pkg-config           NONE           NONE   pkg-config-0.22.tar.gz   pkg-config-0.22  N NONE NONE NONE
+
+inc X11/Xatom.h          NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc X11/Xlib.h           NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc X11/Xresource.h      NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc X11/Xutil.h          NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc X11/cursorfont.h     NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc X11/keysym.h         NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc X11/keysymdef.h      NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc arpa/inet.h          NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc assert.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc complex.h            NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc ctype.h              NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc errno.h              NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc fcntl.h              NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc fftw3.h              NONE           NONE   fftw-3.0.1.tar.gz        fftw-3.0.1       N --enable-float,--enable-shared,--disable-fortran NONE NONE
+inc fitsio.h             NONE           NONE   cfitsio3100-pap.tar.gz   cfitsio3100-pap  N --enable-shared shared NONE
+inc glob.h               NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc gsl/gsl_randist.h    NONE           NONE   gsl-1.11.tar.gz          gsl-1.11         N NONE NONE NONE 
+inc gsl/gsl_rng.h        NONE           NONE   gsl-1.11.tar.gz          gsl-1.11         N NONE NONE NONE 
+inc inttypes.h           NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc jpeglib.h            NONE           jpeg   jpegsrc.v6b.tar.gz       jpeg-6b          N --enable-shared NONE install-lib
+inc limits.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc malloc.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc math.h               NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc memory.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc mysql.h              NONE           mysql  mysql-5.0.51a.tar.gz     mysql-5.0.51a    N NONE NONE NONE
+inc netdb.h              NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc netinet/ip.h         NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc png.h                NONE           NONE   libpng-1.2.15.tar.gz     libpng-1.2.15    N NONE NONE NONE
+inc pthread.h            NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc readline/history.h   NONE           NONE   readline-5.2-p12.tar.gz  readline-5.2-p12 N NONE NONE NONE
+inc readline/readline.h  NONE           NONE   readline-5.2-p12.tar.gz  readline-5.2-p12 N NONE NONE NONE
+inc regex.h              NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc signal.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc stdint.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc stdio.h              NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc stdlib.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc string.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/ipc.h            NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/resource.h       NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/sem.h            NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/socket.h         NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/stat.h           NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/time.h           NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/types.h          NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/uio.h            NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/un.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc sys/wait.h           NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc time.h               NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc unistd.h             NONE           NONE   NONE                     NONE             N NONE NONE NONE 
+inc zlib.h               NONE           NONE   zlib-1.2.3.tar.gz        zlib-1.2.3       N --shared NONE NONE
+
+# xml is currently not used by IPP
+# lib xml2       NONE           NONE   NONE                     NONE             Y NONE NONE NONE
+
+# doxygen is having some unknown build issues on alala
+# bin doxygen            NONE NONE doxygen-1.5.1.src.tar.gz doxygen-1.5.1    N NONE NONE NONE
+
Index: /branches/cnb_branches/cnb_branch_20090215/psconfig/tagsets/ipp-2.8.perl
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psconfig/tagsets/ipp-2.8.perl	(revision 23199)
+++ /branches/cnb_branches/cnb_branch_20090215/psconfig/tagsets/ipp-2.8.perl	(revision 23199)
@@ -0,0 +1,83 @@
+# NN    Name                           Tarball                                  Version        Optional Responses
+  00    Getopt::Long                   Getopt-Long-2.36.tar.gz                  2.3            n
+  00    Module::Build                  Module-Build-0.2806.tar.gz               0.2806
+  01    ExtUtils::MakeMaker            ExtUtils-MakeMaker-6.31.tar.gz           0
+  02    Params::Validate               Params-Validate-0.91.tar.gz       0.77
+#  02    Apache::Test                   Apache-Test-1.29.tar.gz                  1.29
+  03    DateTime::TimeZone             DateTime-TimeZone-0.59.tar.gz            0
+  04    DateTime::Locale               DateTime-Locale-0.33.tar.gz              0
+  05    Time::Local                    Time-Local-1.17.tar.gz                   0
+  06    DateTime                       DateTime-0.36.tar.gz                     0
+  07    MIME::Base64                   MIME-Base64-3.07.tar.gz                  0
+  08    IO::Compress::Base             IO-Compress-Base-2.003.tar.gz            0
+  09    Compress::Raw::Zlib            Compress-Raw-Zlib-2.003.tar.gz           0
+  10    Class::Factory::Util           Class-Factory-Util-1.6.tar.gz            0
+  11    DateTime::Format::Strptime     DateTime-Format-Strptime-1.0700.tar.gz   0
+  12    Net::Domain::TLD               Net-Domain-TLD-1.65.tar.gz               0
+  13    Sub::Uplevel                   Sub-Uplevel-0.14.tar.gz                  0
+  14    HTML::Tagset                   HTML-Tagset-3.10.tar.gz                  0
+  15    Digest                         Digest-1.15.tar.gz                       0
+  16    IO::Compress::Zlib::Extra      IO-Compress-Zlib-2.003.tar.gz            0
+  17    version                        version-0.70.tar.gz                      0
+  18    Text::Balanced                 Text-Balanced-v2.0.0.tar.gz              0
+  19    DateTime::Format::Builder      DateTime-Format-Builder-0.7807.tar.gz    0
+  20    ExtUtils::Manifest             ExtUtils-Manifest-1.51.tar.gz            0
+  21    URI                            URI-1.35.tar.gz                          1.30
+  22    Data::Validate::Domain         Data-Validate-Domain-0.05.tar.gz         0
+  23    Test::Exception                Test-Exception-0.24.tar.gz               0
+  24    Tree::DAG_Node                 Tree-DAG_Node-1.05.tar.gz                0
+  25    Array::Compare                 Array-Compare-1.13.tar.gz                0
+  26    HTML::Parser                   HTML-Parser-3.56.tar.gz                  0
+  27    Digest::MD5                    Digest-MD5-2.36.tar.gz                   0
+  28    Net::FTP                       libnet-1.19.tar.gz                       0
+  29    Compress::Zlib                 Compress-Zlib-2.003.tar.gz               0
+  30    Locale::Maketext::Simple       Locale-Maketext-Simple-0.18.tar.gz       0
+  31    Parse::RecDescent              Parse-RecDescent-1.94.tar.gz             1.94
+  32    Class::Accessor                Class-Accessor-0.30.tar.gz               0.19
+  33    DateTime::Format::ISO8601      DateTime-Format-ISO8601-0.06.tar.gz      0.06
+  34    CGI                            CGI.pm-3.25.tar.gz                       3
+  35    Test::Cmd                      Test-Cmd-1.05.tar.gz                     1.05
+  36    Net::HTTPServer                Net-HTTPServer-1.1.1.tar.gz              1.1.1
+  37    LWP                            libwww-perl-5.805.tar.gz                 0
+  38    Digest::MD5::File              Digest-MD5-File-0.05.tar.gz              0.03
+  39    File::Temp                     File-Temp-0.18.tar.gz                    0.16
+  40    Data::Validate::URI            Data-Validate-URI-0.01.tar.gz            0.01
+  41    Test::Warn                     Test-Warn-0.08.tar.gz                    0
+  42    YAML                           YAML-0.62.tar.gz                         0.58           y
+  43    Module::Load                   Module-Load-0.10.tar.gz                  0
+  44    Params::Check                  Params-Check-0.25.tar.gz                 0
+  45    Template                       Template-Toolkit-2.16.tar.gz             0              n,n
+  46    Statistics::Descriptive        Statistics-Descriptive-2.6.tar.gz        2.6
+  47    Storable                       Storable-2.15.tar.gz                     0
+  48    IO::String                     IO-String-1.08.tar.gz                    0
+  49    Date::Parse                    TimeDate-1.16.tar.gz                     0
+  50    Digest::SHA1                   Digest-SHA1-2.11.tar.gz                  0
+  51    DB_File                        DB_File-1.814.tar.gz                     0
+  52    File::NFSLock                  File-NFSLock-1.20.tar.gz                 0
+  53    Heap                           Heap-0.71.tar.gz                         0
+  54    Module::Load::Conditional      Module-Load-Conditional-0.16.tar.gz      0
+  55    IPC::Run                       IPC-Run-0.80.tar.gz                      0
+  56    Cache                          Cache-2.04.tar.gz                        0
+  57    IPC::Cmd                       IPC-Cmd-0.36.tar.gz                      0.36
+  58    SOAP::Lite                     SOAP-Lite-0.69.tar.gz                    0              yes,yes,no
+  59    Log::Log4perl                  Log-Log4perl-1.10.tar.gz                 0
+# 60    File::ExtAttr                  File-ExtAttr-1.04.tar.gz                 0
+  61    Text::Glob                     Text-Glob-0.08.tar.gz                    0.08
+  62    Number::Compare                Number-Compare-0.01.tar.gz               0.01
+  63    File::Find::Rule               File-Find-Rule-0.30.tar.gz               0.30
+  64    Astro::FITS::CFITSIO           Astro-FITS-CFITSIO-1.05.tar.gz           0
+  65    Test::More                     Test-Simple-0.74.tar.gz                  0.49
+#  66    Apache::DBI                   Apache-DBI-1.06.tar.gz                   0
+#  67    Apache2::SOAP                 Apache2-SOAP-0.72.tar.gz                 0
+  68    Test::URI                      Test-URI-1.08.tar.gz                     0
+#  69    Sys::Statistics::Linux::DiskUsage Sys-Statistics-Linux-0.26.tar.gz      0
+#  70    Config::YAML                  Config-YAML-1.42.tar.gz                  0
+#  72    File::ExtAttr                 File-ExtAttr-1.07.tar.gz                 0
+  73    DBI                            DBI-1.601.tar.gz                         0
+  71    DBD::mysql                     DBD-mysql-4.006.tar.gz                   0
+#  74    Net::Server::Daemonize                Net-Server-0.97.tar.gz                   0.05
+  75    File::Path                      File-Path-2.04.tar.gz
+  76    File::Mountpoint                File-Mountpoint-0.01.tar.gz             0.01
+  77    Filesys::Df                     Filesys-Df-0.92.tar.gz                  0.92
+  78    SQL::Interp                     SQL-Interp-1.06.tar.gz
+
Index: /branches/cnb_branches/cnb_branch_20090215/psphot/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psphot/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psphot/src/Makefile.am	(revision 23199)
@@ -1,4 +1,14 @@
 lib_LTLIBRARIES = libpsphot.la
-libpsphot_la_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+
+PSPHOT_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PSPHOT_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`
+PSPHOT_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of psphotVersion.c, since it gets the version information
+psphotVersion.c: FORCE
+	touch psphotVersion.c
+FORCE: ;
+
+libpsphot_la_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) -DPSPHOT_VERSION=\"$(PSPHOT_VERSION)\" -DPSPHOT_BRANCH=\"$(PSPHOT_BRANCH)\" -DPSPHOT_SOURCE=\"$(PSPHOT_SOURCE)\"
 libpsphot_la_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
 
Index: /branches/cnb_branches/cnb_branch_20090215/psphot/src/psphot.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psphot/src/psphot.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psphot/src/psphot.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psphot/src/psphot.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psphot/src/psphot.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psphot/src/psphot.h	(revision 23199)
@@ -16,5 +16,9 @@
 const char     *psphotCVSName(void);
 psString        psphotVersion(void);
+psString        psphotSource(void);
 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/cnb_branches/cnb_branch_20090215/psphot/src/psphotImageLoop.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psphot/src/psphotImageLoop.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psphot/src/psphotImageLoop.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/psphot/src/psphotVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/psphot/src/psphotVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/psphot/src/psphotVersion.c	(revision 23199)
@@ -1,40 +1,121 @@
-# include "psphotInternal.h"
+#include "psphotInternal.h"
 
-# if (HAVE_KAPA)
-# include <kapa.h>
-# endif
-
-static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
+#ifdef HAVE_KAPA
+#include <kapa.h>
+#endif
 
 psString psphotVersion(void)
 {
-    psString version = NULL;            // Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PSPHOT_VERSION
+#error "PSPHOT_VERSION is not set"
+#endif
+#ifndef PSPHOT_BRANCH
+#error "PSPHOT_BRANCH is not set"
+#endif
+    return psStringCopy(PSPHOT_BRANCH "@" PSPHOT_VERSION);
+}
+
+psString psphotSource(void)
+{
+#ifndef PSPHOT_SOURCE
+#error "PSPHOT_SOURCE is not set"
+#endif
+    return psStringCopy(PSPHOT_SOURCE);
 }
 
 psString psphotVersionLong(void)
 {
-    psString version = psphotVersion(); // Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
+    psString version = psLibVersion();  // Version, to return
+    psString source = psLibSource();    // Source
 
-# if (HAVE_KAPA)
-    psString ohanaVersion = psStringStripCVS (ohana_version(), "Name");
-    psString libdvoVersion = psStringStripCVS (libdvo_version(), "Name");
+    psStringPrepend(&version, "psphot ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
 
-    psStringAppend (&version, " with libkapa (ohana %s, libdvo: %s)", ohanaVersion, libdvoVersion);
-    psFree (ohanaVersion);
-    psFree (libdvoVersion);
-# else
-    psStringAppend (&version, " WITHOUT libkapa");
-# endif
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
 
-    psFree(tag);
+#ifdef HAVE_KAPA
+#if 0
+    // XXX Need to get ohana and libdvo versions
+    psString ohanaVersion = psStringStripCVS(ohana_version(), "Name");
+    psString libdvoVersion = psStringStripCVS(libdvo_version(), "Name");
+    psStringAppend(&version, " with libkapa (ohana %s, libdvo: %s)", ohanaVersion, libdvoVersion);
+    psFree(ohanaVersion);
+    psFree(libdvoVersion);
+#else
+    psStringAppend(&version, " with libkapa");
+#endif
+
+#else
+    psStringAppend (&version, " without libkapa");
+#endif
+
     return version;
 }
 
-// Defined by RHL; leaving for backwards compatibility.
-const char *psphotCVSName(void) {
-   return cvsTag;
+bool psphotVersionHeader(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psString version = psphotVersion(); // Software version
+    psString source = psphotSource();   // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSPHOT.VERSION", PS_META_REPLACE,
+                     "Software version", version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "IPP.PSPHOT.SOURCE", PS_META_REPLACE,
+                     "S/W source", source);
+
+    psFree(version);
+    psFree(source);
+
+    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/cnb_branches/cnb_branch_20090215/pswarp/src/Makefile.am
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/pswarp/src/Makefile.am	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/pswarp/src/Makefile.am	(revision 23199)
@@ -1,4 +1,14 @@
 bin_PROGRAMS = pswarp
-pswarp_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PSWARP_CFLAGS)
+
+PSWARP_VERSION=`if [ -e ../../VERSION ]; then cat ../../VERSION; else svnversion; fi`
+PSWARP_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`
+PSWARP_SOURCE=`if [ -e ../../SOURCE ]; then cat ../../SOURCE; else svn info | sed -n -e 's/Repository UUID: // p'; fi`
+
+# Force recompilation of pswarpVersion.c, since it gets the version information
+pswarpVersion.c: FORCE
+	touch pswarpVersion.c
+FORCE: ;
+
+pswarp_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PSWARP_CFLAGS) -DPSWARP_VERSION=\"$(PSWARP_VERSION)\" -DPSWARP_BRANCH=\"$(PSWARP_BRANCH)\" -DPSWARP_SOURCE=\"$(PSWARP_SOURCE)\"
 pswarp_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) $(PPSTATS_LIBS) $(PSPHOT_LIBS) $(PSWARP_LIBS)
 
@@ -18,5 +28,5 @@
 	pswarpSetThreads.c	        \
 	pswarpTransformReadout.c	\
-	pswarpTransformSources.c \
+	pswarpTransformSources.c 	\
 	pswarpTransformTile.c		\
 	pswarpVersion.c            
Index: /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarp.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarp.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarp.c	(revision 23199)
@@ -39,4 +39,6 @@
     if (!config) usage();
 
+    pswarpVersionPrint();
+
     // load identify the data sources
     if (!pswarpParseCamera(config)) {
Index: /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarp.h
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarp.h	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarp.h	(revision 23199)
@@ -112,2 +112,19 @@
  */
 bool pswarpSetThreads ();
+
+/// Return software version
+psString pswarpVersion(void);
+
+/// Return software souce
+psString pswarpSource(void);
+
+/// 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/cnb_branches/cnb_branch_20090215/pswarp/src/pswarpArguments.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarpArguments.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarpArguments.c	(revision 23199)
@@ -210,5 +210,5 @@
                                                     "SKYCELL.CAMERA");  ///< Name of camera for skycell
         pmConfigCamerasCull(config, skyCamera);
-        pmConfigRecipesCull(config, "PSWARP,PPSTATS,PSPHOT,MASKS");
+        pmConfigRecipesCull(config, "PSWARP,PPSTATS,PSPHOT,MASKS,JPEG");
 
         pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.INPUT"); // Input file
Index: /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarpLoop.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarpLoop.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarpLoop.c	(revision 23199)
@@ -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/cnb_branches/cnb_branch_20090215/pswarp/src/pswarpVersion.c
===================================================================
--- /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarpVersion.c	(revision 23198)
+++ /branches/cnb_branches/cnb_branch_20090215/pswarp/src/pswarpVersion.c	(revision 23199)
@@ -18,22 +18,105 @@
 #include <pslib.h>
 #include <psmodules.h>
+#include <psphot.h>
+#include <ppStats.h>
 #include "pswarp.h"
 
-static const char *cvsTag = "$Name: not supported by cvs2svn $";///< CVS tag name
 
 psString pswarpVersion(void)
 {
-    psString version = NULL;            ///< Version, to return
-    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
-    return version;
+#ifndef PSWARP_VERSION
+#error "PSWARP_VERSION is not set"
+#endif
+#ifndef PSWARP_BRANCH
+#error "PSWARP_BRANCH is not set"
+#endif
+    return psStringCopy(PSWARP_BRANCH "@" PSWARP_VERSION);
+}
+
+psString pswarpSource(void)
+{
+#ifndef PSWARP_SOURCE
+#error "PSWARP_SOURCE is not set"
+#endif
+    return psStringCopy(PSWARP_SOURCE);
 }
 
 psString pswarpVersionLong(void)
 {
-    psString version = pswarpVersion(); ///< Version, to return
-    psString tag = psStringStripCVS(cvsTag, "Name"); ///< CVS tag
-    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
-    psFree(tag);
+    psString version = pswarpVersion();  // Version, to return
+    psString source = pswarpSource();    // Source
+
+    psStringPrepend(&version, "pswarp ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
     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;
+}
