Index: /branches/czw_branch/20100519/Ohana/src/photdbc/src/copy_images.c
===================================================================
--- /branches/czw_branch/20100519/Ohana/src/photdbc/src/copy_images.c	(revision 28333)
+++ /branches/czw_branch/20100519/Ohana/src/photdbc/src/copy_images.c	(revision 28334)
@@ -3,5 +3,6 @@
 int copy_images (char *outdir) {
 
-  int status, Nimage;
+  int status;
+  off_t Nimage;
   char *ImageOut;
   FITS_DB in;
Index: /branches/czw_branch/20100519/Ohana/src/photdbc/src/join_stars.c
===================================================================
--- /branches/czw_branch/20100519/Ohana/src/photdbc/src/join_stars.c	(revision 28333)
+++ /branches/czw_branch/20100519/Ohana/src/photdbc/src/join_stars.c	(revision 28334)
@@ -7,5 +7,5 @@
   off_t Naverage, Nmeasure, *index;
   double *X, *Y, dX, dY, dR, RADIUS2;
-  double Sr, Sd, Rmid, Dmid;
+  double Rmid, Dmid;
   int basecode, baseNsec, Nsecfilt, *found;
 
@@ -202,5 +202,5 @@
 
   if (Nmeas != Nmeasure) {
-    fprintf (stderr, "failure to match %d measures (%d of %d matched)\n", Nmeasure - Nmeas, Nmeas, Nmeasure);
+    fprintf (stderr, "failure to match "OFF_T_FMT" measures ("OFF_T_FMT" of "OFF_T_FMT" matched)\n", Nmeasure - Nmeas, Nmeas, Nmeasure);
   }
   
Index: /branches/czw_branch/20100519/Ohana/src/photdbc/src/make_subcatalog.c
===================================================================
--- /branches/czw_branch/20100519/Ohana/src/photdbc/src/make_subcatalog.c	(revision 28333)
+++ /branches/czw_branch/20100519/Ohana/src/photdbc/src/make_subcatalog.c	(revision 28334)
@@ -5,6 +5,6 @@
 int make_subcatalog (Catalog *subcatalog, Catalog *catalog) {
   
-  int i, j, offset;
-  int NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm, Nsecfilt;
+  off_t i, j, offset;
+  off_t NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm, Nsecfilt;
   double mag, minMag;
 
@@ -105,5 +105,5 @@
 
   if (VERBOSE) {
-    fprintf (stderr, "%d: using %d stars (%d measures) for catalog\n", i, 
+    fprintf (stderr, OFF_T_FMT": using "OFF_T_FMT" stars ("OFF_T_FMT" measures) for catalog\n", i, 
 	     subcatalog[0].Naverage, subcatalog[0].Nmeasure);
   }
Index: /branches/czw_branch/20100519/Ohana/src/photdbc/src/photdbc.c
===================================================================
--- /branches/czw_branch/20100519/Ohana/src/photdbc/src/photdbc.c	(revision 28333)
+++ /branches/czw_branch/20100519/Ohana/src/photdbc/src/photdbc.c	(revision 28334)
@@ -60,5 +60,5 @@
 	
     // XXX add other filters here:
-    join_stars (&outcatalog);
+    // join_stars (&outcatalog);
     // unique_measures (catalog);
     // flag_measures (&db, catalog);
Index: /branches/czw_branch/20100519/dbconfig/changes.txt
===================================================================
--- /branches/czw_branch/20100519/dbconfig/changes.txt	(revision 28333)
+++ /branches/czw_branch/20100519/dbconfig/changes.txt	(revision 28334)
@@ -1756,5 +1756,8 @@
 ) ENGINE=innodb DEFAULT CHARSET=latin1;
 
--- Version 1.1.69
+ALTER TABLE pstampRequest ADD COLUMN timestamp TIMESTAMP AFTER outdir;
+
+-- Version 1.1.69 warp/stack/diff summary and stack associations.
+
 CREATE TABLE warpSummary (
     warp_id     BIGINT,
@@ -1804,2 +1807,6 @@
 ) ENGINE=innodb DEFAULT CHARSET=latin1;
 
+
+
+
+
Index: /branches/czw_branch/20100519/dbconfig/pstamp.md
===================================================================
--- /branches/czw_branch/20100519/dbconfig/pstamp.md	(revision 28333)
+++ /branches/czw_branch/20100519/dbconfig/pstamp.md	(revision 28334)
@@ -31,4 +31,5 @@
     uri         STR         255
     outdir      STR         255
+    timestamp   UTC         0001-01-01T00:00:00Z
     fault       S32         0
 END
Index: /branches/czw_branch/20100519/ippScripts/scripts/addstar_run.pl
===================================================================
--- /branches/czw_branch/20100519/ippScripts/scripts/addstar_run.pl	(revision 28333)
+++ /branches/czw_branch/20100519/ippScripts/scripts/addstar_run.pl	(revision 28334)
@@ -36,5 +36,5 @@
     exit($PS_EXIT_CONFIG_ERROR);
 }
-
+my $minidvodb_path;
 my ( $exp_tag, $add_id, $camera, $outroot, $camroot, $dbname, $reduction, $dvodb, $minidvodb, $minidvodb_name, $minidvodb_group, $image_only, $verbose, $no_update,
      $no_op, $redirect, $save_temps);
@@ -132,13 +132,17 @@
 		    &my_die("Unable to parse metadata list", $add_id, $PS_EXIT_PROG_ERROR);
 		my $comp = $$components[0];
+		$minidvodb_path = $comp->{minidvodb_path};
 		$minidvodb_name = $comp->{minidvodb_name};
 	
+		if (!defined($minidvodb_path)) {
+		    &my_die("Unable to parse minidvodb_path", $add_id, $PS_EXIT_PROG_ERROR);
+		} 
 		if (!defined($minidvodb_name)) {
 		    &my_die("Unable to parse minidvodb_name", $add_id, $PS_EXIT_PROG_ERROR);
-		} 
-		
+		}
 	    }
 	    # tack on the minidvodb part to the db.
-	    $dvodbReal = $dvodbReal . '/' . $minidvodb_name . '/';
+#	    $dvodbReal = $dvodbReal . '/' . $minidvodb_name . '/';
+#we don't need this now that I fixed the paths	   
 	    
 	}
@@ -160,5 +164,5 @@
         my $command  = "$addstar -update"; # XXX optionally set -update?
         $command .= " -D CAMERA $camdir";
-        $command .= " -D CATDIR $dvodbReal";
+        $command .= " -D CATDIR $minidvodb_path";
         $command .= " $realFile";
         $command .= " -use-name $fpaObjects"; # DVO wants the neb-name as a file reference
@@ -182,5 +186,5 @@
 $fpaCommand .= " -path_base $outroot";
 $fpaCommand .= " -dtime_addstar $dtime_addstar";
-$fpaCommand .= " -dvodb_path $dvodbReal" if defined $dvodbReal;
+$fpaCommand .= " -dvodb_path $minidvodb_path" if defined $minidvodb_path;
 $fpaCommand .= " -minidvodb_name $minidvodb_name" if defined $minidvodb_name;
 $fpaCommand .= " -dbname $dbname" if defined $dbname;
@@ -213,5 +217,5 @@
         $command .= " -addprocessedexp";
         $command .= " -fault $exit_code";
-	$command .= " -dvodb_path $dvodbReal" if defined $dvodbReal;
+	$command .= " -dvodb_path $minidvodb_path" if defined $minidvodb_path;
         $command .= " -path_base $outroot" if defined $outroot;
         $command .= (" -dtime_addstar " . ((DateTime->now->mjd - $mjd_start) * 86400));
Index: /branches/czw_branch/20100519/ippScripts/scripts/minidvodb_createdb.pl
===================================================================
--- /branches/czw_branch/20100519/ippScripts/scripts/minidvodb_createdb.pl	(revision 28333)
+++ /branches/czw_branch/20100519/ippScripts/scripts/minidvodb_createdb.pl	(revision 28334)
@@ -39,5 +39,5 @@
 }
 
-my (  $outroot, $dbname, $dvodb,$minidvodb_interval, $minidvodb_group, $camera,  $verbose, $no_update,
+my (  $outroot, $dbname, $dvodb, $minidvodb,$minidvodb_interval, $minidvodb_group, $camera,  $verbose, $no_update,
      $no_op, $redirect, $save_temps);
 GetOptions(    
@@ -47,4 +47,5 @@
     'outroot|w=s'       => \$outroot, # output file base name
     'dvodb|w=s'         => \$dvodb,  # output DVO database
+    'minidvodb|w=s'     => \$minidvodb, # output miniDVODB
     'interval|w=s'      => \$minidvodb_interval, #interval between creation of minidvodbs (default = 1day)
     'verbose'           => \$verbose,   # Print to stdout
@@ -97,4 +98,13 @@
     exit(4);
 }
+my $minidvodbReal;
+if (defined $minidvodb) {
+    $minidvodbReal = $ipprc->dvo_catdir( $minidvodb ); # catdir for DVO
+    $minidvodbReal = $ipprc->convert_filename_absolute( $minidvodbReal );
+} else {
+    warn("minidvodb undefined:\n");
+    exit(4);
+}
+
 
 if (!defined $minidvodb_interval) {
@@ -215,4 +225,5 @@
     my $fpaCommand = "$addtool -addminidvodbrun";
     $fpaCommand .= " -set_minidvodb_group $minidvodb_group";
+    $fpaCommand .= " -set_minidvodb_path  $minidvodbReal" if defined $minidvodbReal;
     $fpaCommand .= " -set_mergedvodb_path $dvodbReal";
     $fpaCommand .= " -dbname $dbname" if defined $dbname;
Index: /branches/czw_branch/20100519/ippScripts/scripts/skycell_jpeg.pl
===================================================================
--- /branches/czw_branch/20100519/ippScripts/scripts/skycell_jpeg.pl	(revision 28333)
+++ /branches/czw_branch/20100519/ippScripts/scripts/skycell_jpeg.pl	(revision 28334)
@@ -273,8 +273,8 @@
 	my $path_base  = $imfile->{path_base};
 	my $quality    = $imfile->{quality};
-	my $state      = $imfile->{data_state};
+	my $state      = $imfile->{state};
 	my $fault      = $imfile->{fault};
 	my $projection_cell = $skycell_id;
-	if ($quality == 8007 or $state ne 'full' or $fault != 0) {
+	if ($quality == 8007 or $state ne 'full') {
 	    next;
 	}
@@ -333,13 +333,13 @@
     if (scalar (keys %tangents) == 0) {
 	my $projection_cell = 'NULL';
-	$command = "$stacktool -addsummary -stack_id $stage_id -projection_cell $projection_cell -path_base $outroot";
-	if (defined($dbname)) {
-	    $command .= " -dbname $dbname";
-	}
-	
-	( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = run(command => $command, verbose => $verbose);
-	unless ($success) {
-	    $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
-	    &my_die("unable to update diff summary: $error_code", $stage_id, $error_code);
+	$command = "$stacktool -addsummary -sass_id $stage_id -projection_cell $projection_cell -path_base $outroot";
+	if (defined($dbname)) {
+	    $command .= " -dbname $dbname";
+	}
+#	print "$command\n";
+	( $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 update stack summary: $error_code", $stage_id, $error_code);
 	}
     }	
Index: /branches/czw_branch/20100519/ippTasks/diff.pro
===================================================================
--- /branches/czw_branch/20100519/ippTasks/diff.pro	(revision 28333)
+++ /branches/czw_branch/20100519/ippTasks/diff.pro	(revision 28334)
@@ -574,5 +574,5 @@
     book getword diffPendingSummary $pageName workdir -var WORKDIR_TEMPLATE
     book getword diffPendingSummary $pageName dbname -var DBNAME
-    book getword warpPendingSummary $pageName tess_id -var TESS_DIR
+    book getword diffPendingSummary $pageName tess_id -var TESS_DIR
     book getword diffPendingSummary $pageName diff_mode -var DIFF_MODE
     book getword diffPendingSummary $pageName state -var RUN_STATE
@@ -601,5 +601,5 @@
 
     ## generate outroot specific to this exposure
-    sprintf outroot "%s/%s/%s/%s.%s.%sdif.%s.summary" $WORKDIR $TESS_ID $SKYCELL_ID $TESS_ID $SKYCELL_ID $DIFF_TAG $DIFF_ID
+    sprintf outroot "%s/%s/%s.%sdif.%s.summary" $WORKDIR $TESS_ID $TESS_ID $DIFF_TAG $DIFF_ID
 
 
Index: /branches/czw_branch/20100519/ippTasks/minidvodb.pro
===================================================================
--- /branches/czw_branch/20100519/ippTasks/minidvodb.pro	(revision 28333)
+++ /branches/czw_branch/20100519/ippTasks/minidvodb.pro	(revision 28334)
@@ -131,6 +131,6 @@
 ## you get no choice - you add all of them in at the same time. you can always turn off the tasks you don't want to run.
 macro add.minidvodb
-  if ($0 != 5)
-    echo "USAGE: add.minidvodb (minidvodb_group) (dvodb) (interval days) (camera)"
+  if ($0 != 6)
+    echo "USAGE: add.minidvodb (minidvodb_group) (minidvodb) (dvodb) (interval days) (camera)"
     break
   end
@@ -139,15 +139,15 @@
   book newpage MINIDVODB $1
   book setword MINIDVODB $1 MINIDVODB_GROUP $1
-  book setword MINIDVODB $1 DVODB $2
+  book setword MINIDVODB $1 DVODB $3
   book setword MINIDVODB $1 STATE PENDING
   #merge  
   book newpage MINIDVODB_MERGE $1
   book setword MINIDVODB_MERGE $1 MINIDVODB_GROUP $1
-  book setword MINIDVODB_MERGE $1 DVODB $2
+  book setword MINIDVODB_MERGE $1 DVODB $3
   book setword MINIDVODB_MERGE $1 STATE PENDING
   #active  
   book newpage MINIDVODB_ACTIVE $1
   book setword MINIDVODB_ACTIVE $1 MINIDVODB_GROUP $1
-  book setword MINIDVODB_ACTIVE $1 DVODB $2
+  book setword MINIDVODB_ACTIVE $1 DVODB $3
   book setword MINIDVODB_ACTIVE $1 STATE PENDING
 
@@ -155,7 +155,8 @@
   book newpage MINIDVODB_CREATE $1
   book setword MINIDVODB_CREATE $1 MINIDVODB_GROUP $1
-  book setword MINIDVODB_CREATE $1 DVODB $2
-  book setword MINIDVODB_CREATE $1 DVODB_DAYS $3
-  book setword MINIDVODB_CREATE $1 CAMERA $4  
+  book setword MINIDVODB_CREATE $1 MINIDVODB $2
+  book setword MINIDVODB_CREATE $1 DVODB $3
+  book setword MINIDVODB_CREATE $1 DVODB_DAYS $4
+  book setword MINIDVODB_CREATE $1 CAMERA $5  
   book setword MINIDVODB_CREATE $1 STATE PENDING  
 end
@@ -542,8 +543,9 @@
      
     book setword MINIDVODB_CREATE $minidvodb_group STATE DONE
+    book getword MINIDVODB_CREATE $minidvodb_group MINIDVODB -var minidvodb 
     book getword MINIDVODB_CREATE $minidvodb_group DVODB -var dvodb 
     book getword MINIDVODB_CREATE $minidvodb_group DVODB_DAYS -var dvodb_days
     book getword MINIDVODB_CREATE $minidvodb_group CAMERA -var camera
-    $run = minidvodb_createdb.pl --camera $camera --outroot $dvodb --dvodb $dvodb --minidvodb_group $minidvodb_group --interval $dvodb_days
+    $run = minidvodb_createdb.pl --camera $camera --outroot $dvodb --dvodb $dvodb --minidvodb $minidvodb --minidvodb_group $minidvodb_group --interval $dvodb_days
  
     if ($DB:n == 0)
Index: /branches/czw_branch/20100519/ippTasks/stack.pro
===================================================================
--- /branches/czw_branch/20100519/ippTasks/stack.pro	(revision 28333)
+++ /branches/czw_branch/20100519/ippTasks/stack.pro	(revision 28334)
@@ -10,4 +10,5 @@
 ### Initialise the books containing the tasks to do
 book init stackSumSkyfile
+book init stackPendingSummary
 #book init stackCleanup
 
@@ -16,4 +17,5 @@
 $stack_revert_DB = 0
 #$stackCleanup_DB = 0
+$stackSummary_DB = 0
 
 ### Check status of stacking tasks
@@ -26,4 +28,5 @@
 macro stack.reset
   book init stackSumSkyfile
+  book init stackPendingSummary
 #  book init stackCleanup
 end
@@ -40,4 +43,10 @@
     active false
   end
+  task stack.summary.load
+    active true
+  end
+  task stack.summary.run
+    active true
+  end
 end
 
@@ -51,4 +60,10 @@
   end
   task stack.revert
+    active false
+  end
+  task stack.summary.load
+    active false
+  end
+  task stack.summary.run
     active false
   end
@@ -403,2 +418,131 @@
 end
 
+### Load tasks for doing the stack summary
+### Tasks are loaded into stackPendingSummary
+task           stack.summary.load
+  host         local
+
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 1200
+  npending     1
+
+  stdout       NULL
+  stderr       $LOGDIR/stack.summary.load
+
+  task.exec
+    if ($LABEL:n == 0) break
+    $run = stacktool -tosummary
+    if ($DB:n == 0) 
+      option DEFAULT
+    else
+      # save the DB name for the exit tasks
+      option $DB:$stackSummary_DB
+      $run = $run -dbname $DB:$stackSummary_DB
+      $stackSummary_DB ++
+      if ($stackSummary_DB >= $DB:n) set stackSummary_DB = 0
+    end
+    add_poll_args run
+    add_poll_labels run
+    command $run
+  end
+
+  # success
+  task.exit     0
+    # convert 'stdout' to book format
+    ipptool2book stdout stackPendingSummary -key sass_id -uniq -setword dbname $options:0 -setword pantaskState INIT
+    if ($VERBOSE > 2)
+      book listbook stackPendingSummary
+    end
+
+    # delete existing entries in the appropriate pantaskStates
+    process_cleanup stackPendingSummary
+  end
+
+  # locked list
+  task.exit     default
+    showcommand failure
+  end
+
+  task.exit     crash
+    showcommand crash
+  end
+
+  # operation times out?
+  task.exit     timeout
+    showcommand timeout
+  end
+end
+
+### Run tasks for doing the stack summary
+task           stack.summary.run
+  periods      -poll $RUNPOLL
+  periods      -exec $RUNEXEC
+  periods      -timeout 60
+
+  task.exec
+    # if we are unable to run the 'exec', use a long retry time
+    periods -exec $RUNEXEC
+
+    book npages stackPendingSummary -var N
+    if ($N == 0) break
+    if ($NETWORK == 0) break
+
+    # look for new images in stackPendingSummary (pantaskState == INIT)
+    book getpage stackPendingSummary 0 -var pageName -key pantaskState INIT
+    if ("$pageName" == "NULL") break
+
+    book setword stackPendingSummary $pageName pantaskState RUN
+    book getword stackPendingSummary $pageName sass_id -var SASS_ID
+    book getword stackPendingSummary $pageName camera -var CAMERA
+    book getword stackPendingSummary $pageName workdir -var WORKDIR_TEMPLATE
+    book getword stackPendingSummary $pageName dbname -var DBNAME
+    book getword stackPendingSummary $pageName tess_id -var TESS_DIR
+    book getword stackPendingSummary $pageName state -var RUN_STATE
+    book getword stackPendingSummary $pageName projection_cell -var projection_cell
+
+    # set the host and workdir
+    host anyhost
+    strsub $WORKDIR_TEMPLATE @HOST@.0 $default_host -var WORKDIR
+
+    basename $TESS_DIR -var TESS_ID
+
+    ## generate outroot specific to this association
+    sprintf outroot "%s/%s/%s.stk.%s.summary" $WORKDIR $TESS_ID $TESS_ID $SASS_ID
+
+    stdout $LOGDIR/stack.summary.log
+    stderr $LOGDIR/stack.summary.log
+
+    $run = skycell_jpeg.pl --stage stack --stage_id $SASS_ID --camera $CAMERA --outroot $outroot
+    add_standard_args run
+
+    # save the pageName for future reference below
+    options $pageName
+
+    # create the command line
+    if ($VERBOSE > 1)
+	echo command $run
+    end
+    periods -exec 0.05
+    command $run
+  end
+
+  # default exit status
+  task.exit       default
+    process_exit stackPendingSummary $options:0 $JOB_STATUS
+  end
+
+  # locked list
+  task.exit       crash
+    showcommand crash
+    echo "hostname: $JOB_HOSTNAME"
+    book setword stackPendingSummary $options:0 pantaskState CRASH
+  end
+
+  # operation timed out?
+  task.exit       timeout
+    showcommand timeout
+    book setword stackPendingSummary $options:0 pantaskState TIMEOUT
+  end
+end
+
Index: /branches/czw_branch/20100519/ippToPsps/src/ippToPspsBatchDetection.c
===================================================================
--- /branches/czw_branch/20100519/ippToPsps/src/ippToPspsBatchDetection.c	(revision 28333)
+++ /branches/czw_branch/20100519/ippToPsps/src/ippToPspsBatchDetection.c	(revision 28334)
@@ -54,9 +54,15 @@
     float zptObs, zeroPoint, exposureTime;
     char filterType[20];
+    double obsTime;
+    double expStart;
+    double expTime;
     status=0; fits_read_key(fitsIn, TFLOAT, "ZPT_OBS", &zptObs, NULL, &status);
     status=0; fits_read_key(fitsIn, TFLOAT, "ZPT_REF", &zeroPoint, NULL, &status);
     status=0; fits_read_key(fitsIn, TFLOAT, "EXPREQ", &exposureTime, NULL, &status);
     status=0; fits_read_key(fitsIn, TSTRING, "FILTERID", filterType, NULL, &status);
-    
+    status=0; fits_read_key(fitsIn, TDOUBLE, "MJD-OBS", &expStart, NULL, &status);
+    status=0; fits_read_key(fitsIn, TDOUBLE, "EXPTIME", &expTime, NULL, &status);
+    obsTime = expStart + (expTime/172800); // exp start plus half exp time (converted from secs to days)
+   
     ippToPspsConfig_writeTable(this->config, fitsIn, this->fitsOut, 1, "FrameMeta", true);
 
@@ -83,5 +89,4 @@
 
     // stuff to keep from psf.hdr header
-    double obsTime = 0.0;
     int sourceId = -1;
     int imageId = -1;
@@ -132,5 +137,5 @@
     long ippDetectID[MAXDETECT];
     long imageID[MAXDETECT];
-    float obsTimes[MAXDETECT];
+    double obsTimes[MAXDETECT];
     float instFlux[MAXDETECT];
     float instFluxErr[MAXDETECT];
@@ -195,5 +200,4 @@
             status=0; fits_read_key(fitsIn, TFLOAT, "IQ_FW2", &momentMin, NULL, &status);
             status=0; fits_read_key(fitsIn, TLONG, "IMAGEID", &imageId, NULL, &status);
-            status=0; fits_read_key(fitsIn, TDOUBLE, "MJD-OBS", &obsTime, NULL, &status);
             status=0; fits_read_key(fitsIn, TLONG, "SOURCEID", &sourceId, NULL, &status);
 
@@ -333,5 +337,5 @@
             fits_write_col(this->fitsOut, TBYTE, DETECTION_SURVEYID, 1, 1, nDet, surveyIDs, &status);
             fits_write_col(this->fitsOut, TLONGLONG, DETECTION_IMAGEID, 1, 1, nDet, imageID, &status);
-            fits_write_col(this->fitsOut, TFLOAT, DETECTION_OBSTIME, 1, 1, nDet, obsTimes, &status);
+            fits_write_col(this->fitsOut, TDOUBLE, DETECTION_OBSTIME, 1, 1, nDet, obsTimes, &status);
             fits_write_col(this->fitsOut, TFLOAT, DETECTION_INSTFLUX, 1, 1, nDet, instFlux, &status);
             fits_write_col(this->fitsOut, TFLOAT, DETECTION_INSTFLUXERR, 1, 1, nDet, instFluxErr, &status);
Index: /branches/czw_branch/20100519/ippTools/share/difftool_addsummary.sql
===================================================================
--- /branches/czw_branch/20100519/ippTools/share/difftool_addsummary.sql	(revision 28334)
+++ /branches/czw_branch/20100519/ippTools/share/difftool_addsummary.sql	(revision 28334)
@@ -0,0 +1,5 @@
+INSERT INTO diffSummary (diff_id,projection_cell,path_base) VALUES (
+       %lld,   -- warp_id
+       '%s',   -- projection_cell
+       '%s'    -- path_base
+      )
Index: /branches/czw_branch/20100519/ippTools/share/difftool_tosummary.sql
===================================================================
--- /branches/czw_branch/20100519/ippTools/share/difftool_tosummary.sql	(revision 28334)
+++ /branches/czw_branch/20100519/ippTools/share/difftool_tosummary.sql	(revision 28334)
@@ -0,0 +1,5 @@
+SELECT DISTINCT diff_id,"GPC1" as camera,diffRun.workdir,diffRun.tess_id,diffRun.diff_mode,diffRun.state
+       FROM diffRun 
+       LEFT JOIN diffSummary USING(diff_id)
+WHERE diffRun.state = 'full' AND 
+      diffSummary.projection_cell IS NULL 
Index: /branches/czw_branch/20100519/ippTools/share/pxadmin_create_tables.sql
===================================================================
--- /branches/czw_branch/20100519/ippTools/share/pxadmin_create_tables.sql	(revision 28333)
+++ /branches/czw_branch/20100519/ippTools/share/pxadmin_create_tables.sql	(revision 28334)
@@ -1411,4 +1411,5 @@
         uri VARCHAR(255),
         outdir     VARCHAR(255),
+        timestamp TIMESTAMP,
         fault SMALLINT,
         PRIMARY KEY(req_id),
Index: /branches/czw_branch/20100519/ippTools/share/stacktool_addsummary.sql
===================================================================
--- /branches/czw_branch/20100519/ippTools/share/stacktool_addsummary.sql	(revision 28334)
+++ /branches/czw_branch/20100519/ippTools/share/stacktool_addsummary.sql	(revision 28334)
@@ -0,0 +1,5 @@
+INSERT INTO stackSummary (sass_id,projection_cell,path_base) VALUES (
+       %lld,   -- warp_id
+       '%s',   -- projection_cell
+       '%s'    -- path_base
+)
Index: /branches/czw_branch/20100519/ippTools/share/stacktool_associationdefine_select.sql
===================================================================
--- /branches/czw_branch/20100519/ippTools/share/stacktool_associationdefine_select.sql	(revision 28334)
+++ /branches/czw_branch/20100519/ippTools/share/stacktool_associationdefine_select.sql	(revision 28334)
@@ -0,0 +1,12 @@
+SELECT 
+       sass_id,
+       data_group,
+       tess_id,
+       filter,
+       CASE WHEN LOCATE('.',skycell_id,9) > 0 THEN
+       	    SUBSTRING_INDEX(skycell_id,'.',2) ELSE
+	    SUBSTRING_INDEX(skycell_id,'.',1) END
+       AS projection_cell
+       FROM stackRun 
+       LEFT JOIN stackAssociationMap USING (stack_id)
+       WHERE stackRun.stack_id = @STACK_ID@
Index: /branches/czw_branch/20100519/ippTools/share/stacktool_sassskyfile.sql
===================================================================
--- /branches/czw_branch/20100519/ippTools/share/stacktool_sassskyfile.sql	(revision 28334)
+++ /branches/czw_branch/20100519/ippTools/share/stacktool_sassskyfile.sql	(revision 28334)
@@ -0,0 +1,23 @@
+SELECT
+    stackAssociation.sass_id,
+    stackAssociation.projection_cell,
+    stackSumSkyfile.*,
+    stackRun.state,
+    stackRun.tess_id,
+    stackRun.skycell_id,
+    stackRun.filter,
+    stackRun.workdir,
+    stackRun.label,
+    (SELECT rawExp.camera FROM 
+        stackInputSkyfile 
+        JOIN warpRun USING(warp_id)
+        JOIN fakeRun ON warpRun.fake_id = fakeRun.fake_id
+        JOIN camRun ON camRun.cam_id = fakeRun.cam_id
+        JOIN chipRun ON camRun.chip_id  = chipRun.chip_id
+        JOIN rawExp ON chipRun.exp_id  = rawExp.exp_id
+        where stack_id = stackRun.stack_id limit 1
+    ) as camera
+FROM stackRun
+JOIN stackSumSkyfile USING(stack_id)
+JOIN stackAssociationMap USING(stack_id)
+JOIN stackAssociation USING(sass_id)
Index: /branches/czw_branch/20100519/ippTools/share/stacktool_tosummary.sql
===================================================================
--- /branches/czw_branch/20100519/ippTools/share/stacktool_tosummary.sql	(revision 28334)
+++ /branches/czw_branch/20100519/ippTools/share/stacktool_tosummary.sql	(revision 28334)
@@ -0,0 +1,13 @@
+SELECT DISTINCT sass_id,rawExp.camera,stackRun.workdir,stackRun.tess_id,stackRun.state
+       FROM stackRun
+       JOIN stackInputSkyfile ON stackRun.stack_id = stackInputSkyfile.stack_id
+       JOIN stackAssociationMap ON stackRun.stack_id = stackAssociationMap.stack_id
+       JOIN stackAssociation USING(sass_id)
+       JOIN warpRun USING(warp_id)
+       JOIN fakeRun USING(fake_id)
+       JOIN camRun USING(cam_id)
+       JOIN chipRun USING(chip_id)
+       JOIN rawExp USING(exp_id)
+       LEFT JOIN stackSummary USING(sass_id)
+WHERE stackRun.state = 'full' AND
+      stackSummary.projection_cell IS NULL
Index: /branches/czw_branch/20100519/ippTools/share/warptool_addsummary.sql
===================================================================
--- /branches/czw_branch/20100519/ippTools/share/warptool_addsummary.sql	(revision 28334)
+++ /branches/czw_branch/20100519/ippTools/share/warptool_addsummary.sql	(revision 28334)
@@ -0,0 +1,5 @@
+INSERT INTO warpSummary (warp_id,projection_cell,path_base) VALUES(
+       %lld,   -- warp_id
+       '%s',   -- projection_cell
+       '%s'    -- path_base
+)
Index: /branches/czw_branch/20100519/ippTools/share/warptool_tosummary.sql
===================================================================
--- /branches/czw_branch/20100519/ippTools/share/warptool_tosummary.sql	(revision 28334)
+++ /branches/czw_branch/20100519/ippTools/share/warptool_tosummary.sql	(revision 28334)
@@ -0,0 +1,7 @@
+SELECT DISTINCT warp_id,rawExp.camera,warpRun.workdir,warpRun.tess_id,rawExp.exp_tag,warpRun.state
+       FROM warpRun 
+       JOIN fakeRun USING(fake_id) JOIN camRun USING(cam_id)
+       JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)
+       LEFT JOIN warpSummary USING(warp_id)
+WHERE warpRun.state = 'full' AND 
+      warpSummary.projection_cell IS NULL 
Index: /branches/czw_branch/20100519/ippTools/src/addtool.c
===================================================================
--- /branches/czw_branch/20100519/ippTools/src/addtool.c	(revision 28333)
+++ /branches/czw_branch/20100519/ippTools/src/addtool.c	(revision 28334)
@@ -817,4 +817,9 @@
   }
 
+  if (minidvodb_path) {
+    psStringAppend(&minidvodb_path,"/%s",minidvodb_name);
+  }
+
+
   psString query = NULL;
 
Index: /branches/czw_branch/20100519/ippTools/src/pstamptool.c
===================================================================
--- /branches/czw_branch/20100519/ippTools/src/pstamptool.c	(revision 28333)
+++ /branches/czw_branch/20100519/ippTools/src/pstamptool.c	(revision 28334)
@@ -271,4 +271,5 @@
         uri,
         NULL,   // outdir
+        NULL,   // timestamp
         0       // fault
         )) {
@@ -547,4 +548,9 @@
     PXOPT_LOOKUP_BOOL(clearfault,config->args, "-clearfault",    false);
 
+    if (!state && !label && !outProduct && !fault && !uri && !outdir && !name && !reqType && !clearfault) {
+        psError(PS_ERR_UNKNOWN, true, "at least one set option is required");
+        return false;
+    }
+
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-req_id",     "req_id", "==");
@@ -552,4 +558,6 @@
     PXOPT_COPY_S32(config->args, where, "-fault",      "fault", "==");
     PXOPT_COPY_STR(config->args, where, "-state",      "state", "==");
+    PXOPT_COPY_TIME(config->args, where, "-timestamp_begin", "timestamp", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-timestamp_end", "timestamp", "<=");
     pxAddLabelSearchArgs(config, where, "-label",      "pstampRequest.label", "LIKE");
     if (!psListLength(where->list)) {
@@ -559,11 +567,9 @@
     }
 
-    psString query = psStringCopy("UPDATE pstampRequest SET");
+    psString query = psStringCopy("UPDATE pstampRequest SET timestamp = UTC_TIMESTAMP()");
 
     psString stateCheck = NULL;
-    char c = ' ';
     if (state) {
-        psStringAppend(&query, "%c state = '%s'", c, state);
-        c = ',';
+        psStringAppend(&query, ", state = '%s'", state);
         if (!strcmp(state, "goto_cleaned")) {
             psStringAppend(&stateCheck, " AND state != 'cleaned'");
@@ -571,14 +577,11 @@
     }
     if (label) {
-        psStringAppend(&query, "%c label = '%s'", c, label);
-        c = ',';
+        psStringAppend(&query, ", label = '%s'", label);
     }
     if (outProduct) {
-        psStringAppend(&query, "%c outProduct = '%s'", c, outProduct);
-        c = ',';
+        psStringAppend(&query, ", outProduct = '%s'", outProduct);
     }
     if (outdir) {
-        psStringAppend(&query, "%c outdir = '%s'", c, outdir);
-        c = ',';
+        psStringAppend(&query, ", outdir = '%s'", outdir);
     }
     if (clearfault) {
@@ -587,25 +590,16 @@
             return false;
         }
-        psStringAppend(&query, "%c fault = 0", c);
-        c = ',';
+        psStringAppend(&query, ", fault = 0");
     } else if (fault) {
-        psStringAppend(&query, "%c fault = %d", c, fault);
-        c = ',';
+        psStringAppend(&query, ", fault = %d", fault);
     }
     if (uri) {
-        psStringAppend(&query, "%c uri = '%s'", c, uri);
-        c = ',';
+        psStringAppend(&query, ", uri = '%s'", uri);
     }
     if (name) {
-        psStringAppend(&query, "%c name = '%s'", c, name);
-        c = ',';
+        psStringAppend(&query, ", name = '%s'", name);
     }
     if (reqType) {
-        psStringAppend(&query, "%c reqType = '%s'", c, reqType);
-        c = ',';
-    }
-    if (c != ',') {
-        psError(PS_ERR_UNKNOWN, true, "at least one set option is required");
-        return false;
+        psStringAppend(&query, ", reqType = '%s'", reqType);
     }
 
Index: /branches/czw_branch/20100519/ippTools/src/pstamptoolConfig.c
===================================================================
--- /branches/czw_branch/20100519/ippTools/src/pstamptoolConfig.c	(revision 28333)
+++ /branches/czw_branch/20100519/ippTools/src/pstamptoolConfig.c	(revision 28334)
@@ -103,4 +103,6 @@
     psMetadataAddStr(updatereqArgs, PS_LIST_TAIL, "-state", 0,        "search by state", NULL);
     psMetadataAddStr(updatereqArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by pstampJob label (LIKE comparision)", NULL);
+    psMetadataAddTime(updatereqArgs, PS_LIST_TAIL, "-timestamp_begin", 0, "search by timestamp (>=)", NULL);
+    psMetadataAddTime(updatereqArgs, PS_LIST_TAIL, "-timestamp_end", 0, "search by timestamp (<=)", NULL);
     psMetadataAddStr(updatereqArgs, PS_LIST_TAIL, "-set_state", 0,        "new state", NULL);
     psMetadataAddStr(updatereqArgs, PS_LIST_TAIL, "-set_label", 0,        "new label", NULL);
Index: /branches/czw_branch/20100519/ippTools/src/stacktool.c
===================================================================
--- /branches/czw_branch/20100519/ippTools/src/stacktool.c	(revision 28333)
+++ /branches/czw_branch/20100519/ippTools/src/stacktool.c	(revision 28334)
@@ -1372,5 +1372,5 @@
   if (psListLength(where->list)) {
     psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-    psStringAppend(&query, " WHERE %s", whereClause);
+    psStringAppend(&query, " AND %s", whereClause);
     psFree(whereClause);
   } else if (!all) {
@@ -1387,5 +1387,5 @@
     psFree(limitString);
   }
-  
+
   if (!p_psDBRunQuery(config->dbh, query)) {
     psError(PS_ERR_UNKNOWN, false, "database error");
Index: /branches/czw_branch/20100519/ippconfig/recipes/filerules-mef.mdc
===================================================================
--- /branches/czw_branch/20100519/ippconfig/recipes/filerules-mef.mdc	(revision 28333)
+++ /branches/czw_branch/20100519/ippconfig/recipes/filerules-mef.mdc	(revision 28334)
@@ -153,4 +153,9 @@
 PPBGRESTORE.INPUT       INPUT    @FILES        CHIP       IMAGE
 PPBGRESTORE.BACKMDL     INPUT    @FILES        CHIP       IMAGE
+
+PPBACKGROUND.IMAGE	  INPUT    @FILES        CHIP       IMAGE
+PPBACKGROUND.MASK	  INPUT    @FILES        CHIP       MASK
+PPBACKGROUND.PATTERN	  INPUT    @FILES        CHIP       PATTERN
+PPBACKGROUND.BACKGROUND	  INPUT    @FILES        CHIP       IMAGE
 
 ### output file definitions
@@ -330,2 +335,5 @@
 
 PPBGRESTORE.OUTPUT      OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE     COMP_IMG   CHIP       TRUE      NONE
+
+PPBACKGROUND.OUTPUT	     OUTPUT {OUTPUT}.{CHIP.NAME}.fits    IMAGE     COMP_IMG   CHIP       TRUE      NONE
+PPBACKGROUND.OUTPUT.MASK     OUTPUT {OUTPUT}.{CHIP.NAME}.mk.fits MASK      COMP_MASK  CHIP       TRUE      NONE
Index: /branches/czw_branch/20100519/ippconfig/recipes/filerules-simple.mdc
===================================================================
--- /branches/czw_branch/20100519/ippconfig/recipes/filerules-simple.mdc	(revision 28333)
+++ /branches/czw_branch/20100519/ippconfig/recipes/filerules-simple.mdc	(revision 28334)
@@ -128,4 +128,9 @@
 
 PPVIZPATTERN.INPUT        INPUT    @FILES        CHIP       PATTERN
+
+PPBACKGROUND.IMAGE	  INPUT    @FILES        CHIP       IMAGE
+PPBACKGROUND.MASK	  INPUT    @FILES        CHIP       MASK
+PPBACKGROUND.PATTERN	  INPUT    @FILES        CHIP       PATTERN
+PPBACKGROUND.BACKGROUND	  INPUT    @FILES        CHIP       IMAGE
 
 ### output file definitions
@@ -295,2 +300,5 @@
 
 PPBGRESTORE.OUTPUT           OUTPUT {OUTPUT}.fits                 IMAGE           NONE       FPA        TRUE      NONE
+
+PPBACKGROUND.OUTPUT	     OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE           NONE       FPA        TRUE      NONE
+PPBACKGROUND.OUTPUT.MASK     OUTPUT {OUTPUT}.{CHIP.NAME}.mk.fits      MASK            NONE       FPA        TRUE      NONE
Index: /branches/czw_branch/20100519/ippconfig/recipes/filerules-split.mdc
===================================================================
--- /branches/czw_branch/20100519/ippconfig/recipes/filerules-split.mdc	(revision 28333)
+++ /branches/czw_branch/20100519/ippconfig/recipes/filerules-split.mdc	(revision 28334)
@@ -139,4 +139,9 @@
                           
 PPVIZPATTERN.INPUT        INPUT    @FILES        CHIP       PATTERN
+
+PPBACKGROUND.IMAGE	  INPUT    @FILES        CHIP       IMAGE
+PPBACKGROUND.MASK	  INPUT    @FILES        CHIP       MASK
+PPBACKGROUND.PATTERN	  INPUT    @FILES        CHIP       PATTERN
+PPBACKGROUND.BACKGROUND	  INPUT    @FILES        CHIP       IMAGE
 
 ### output file definitions
@@ -321,4 +326,6 @@
 PPVIZPATTERN.CHIP            OUTPUT {OUTPUT}.{CHIP.NAME}.ch.fits      IMAGE           NONE       CHIP       TRUE      NONE
 
+PPBACKGROUND.OUTPUT	     OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE           COMP_IMG   CHIP       TRUE      NONE
+PPBACKGROUND.OUTPUT.MASK     OUTPUT {OUTPUT}.{CHIP.NAME}.mk.fits      MASK            COMP_MASK  CHIP       TRUE      NONE
 
 # FILERULE naming operators:
Index: /branches/czw_branch/20100519/ppBackground/configure.ac
===================================================================
--- /branches/czw_branch/20100519/ppBackground/configure.ac	(revision 28333)
+++ /branches/czw_branch/20100519/ppBackground/configure.ac	(revision 28334)
@@ -20,5 +20,11 @@
 PKG_CHECK_MODULES([PSLIB], [pslib >= 1.0.0])
 PKG_CHECK_MODULES([PSMODULE], [psmodules >= 1.0.0])
-PKG_CHECK_MODULES([PSPHOT], [psphot >= 1.0.0])
+PKG_CHECK_MODULES([PPSTATS], [ppStats >= 1.0.0]) 
+PKG_CHECK_MODULES([PSPHOT], [psphot])
+
+AC_PATH_PROG([ERRORCODES], [psParseErrorCodes], [missing])
+if test "$ERRORCODES" = "missing" ; then
+  AC_MSG_ERROR([psParseErrorCodes is required])
+fi
 
 dnl Set CFLAGS for build
Index: /branches/czw_branch/20100519/ppBackground/src/Makefile.am
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/Makefile.am	(revision 28333)
+++ /branches/czw_branch/20100519/ppBackground/src/Makefile.am	(revision 28334)
@@ -2,15 +2,15 @@
 
 if HAVE_SVNVERSION
-PPVIZPATTERN_VERSION=`$(SVNVERSION) ..`
+PPBACKGROUND_VERSION=`$(SVNVERSION) ..`
 else
-PPVIZPATTERN_VERSION="UNKNOWN"
+PPBACKGROUND_VERSION="UNKNOWN"
 endif
 
 if HAVE_SVN
-PPVIZPATTERN_BRANCH=`$(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 }'`
-PPVIZPATTERN_SOURCE=`$(SVN) info | $(SED) -n -e 's/Repository UUID: // p'`
+PPBACKGROUND_BRANCH=`$(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 }'`
+PPBACKGROUND_SOURCE=`$(SVN) info | $(SED) -n -e 's/Repository UUID: // p'`
 else
-PPVIZPATTERN_BRANCH="UNKNOWN"
-PPVIZPATTERN_SOURCE="UNKNOWN"
+PPBACKGROUND_BRANCH="UNKNOWN"
+PPBACKGROUND_SOURCE="UNKNOWN"
 endif
 
@@ -19,5 +19,5 @@
 ppBackgroundVersionDefinitions.h: ppBackgroundVersionDefinitions.h.in FORCE
 	-$(RM) ppBackgroundVersionDefinitions.h
-	$(SED) -e "s|@PPVIZPATTERN_VERSION@|\"$(PPVIZPATTERN_VERSION)\"|" -e "s|@PPVIZPATTERN_BRANCH@|\"$(PPVIZPATTERN_BRANCH)\"|" -e "s|@PPVIZPATTERN_SOURCE@|\"$(PPVIZPATTERN_SOURCE)\"|" ppBackgroundVersionDefinitions.h.in > ppBackgroundVersionDefinitions.h
+	$(SED) -e "s|@PPBACKGROUND_VERSION@|\"$(PPBACKGROUND_VERSION)\"|" -e "s|@PPBACKGROUND_BRANCH@|\"$(PPBACKGROUND_BRANCH)\"|" -e "s|@PPBACKGROUND_SOURCE@|\"$(PPBACKGROUND_SOURCE)\"|" ppBackgroundVersionDefinitions.h.in > ppBackgroundVersionDefinitions.h
 FORCE: ;
 
@@ -25,6 +25,6 @@
 
 
-ppBackground_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSPHOT_CFLAGS) $(PPBACKGROUND_CFLAGS)
-ppBackground_LDFLAGS  = $(PSLIB_LIBS)   $(PSMODULE_LIBS)   $(PSPHOT_LIBS)   $(PPBACKGROUND_LIBS)
+ppBackground_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PPBACKGROUND_CFLAGS)
+ppBackground_LDFLAGS  = $(PSLIB_LIBS)   $(PSMODULE_LIBS)   $(PPSTATS_LIBS)   $(PSPHOT_LIBS)   $(PPBACKGROUND_LIBS)
 
 ppBackground_SOURCES =		\
@@ -35,6 +35,7 @@
 	ppBackgroundLoop.c	\
 	ppBackgroundVersion.c   \
-	ppBackgroundModel.c	\
-	ppBackgroundErrorCodes.c
+	ppBackgroundRestore.c	\
+	ppBackgroundErrorCodes.c	\
+	ppBackgroundExit.c
 
 noinst_HEADERS = \
Index: /branches/czw_branch/20100519/ppBackground/src/ppBackground.c
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/ppBackground.c	(revision 28333)
+++ /branches/czw_branch/20100519/ppBackground/src/ppBackground.c	(revision 28334)
@@ -6,4 +6,5 @@
 #include <pslib.h>
 #include <psmodules.h>
+#include <psphot.h>
 
 #include "ppBackground.h"
@@ -12,4 +13,8 @@
 {
     ppBackgroundVersionPrint();
+
+    pmErrorRegister();
+    psphotErrorRegister();
+    ppBackgroundErrorRegister();
 
     ppBackgroundData *data = ppBackgroundDataInit(&argc, argv);
@@ -46,5 +51,4 @@
         }
         data->statsFile = NULL;
-        pmConfigRunFilenameAddWrite(data->config, "STATS", data->statsName);
         exitValue = ppBackgroundExitCode(exitValue);
     }
Index: /branches/czw_branch/20100519/ppBackground/src/ppBackground.h
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/ppBackground.h	(revision 28333)
+++ /branches/czw_branch/20100519/ppBackground/src/ppBackground.h	(revision 28334)
@@ -5,5 +5,5 @@
 #include <psmodules.h>
 
-#include <ppBackgroundErrorCodes.h>
+#include "ppBackgroundErrorCodes.h"
 
 #define PPBACKGROUND_RECIPE "PPBACKGROUND"      // Recipe name
@@ -37,4 +37,13 @@
     );
 
+/// Restore the background to an image
+bool ppBackgroundRestore(
+    pmChip *chip,                       // Chip to correct
+    const pmChip *background,           // Chip with background model
+    const pmChip *pattern,              // Chip with pattern
+    const pmFPAview *view,              // View to data
+    pmConfig *config                    // Configuration
+    );
+
 /// Determine exit code
 psExit ppBackgroundExitCode(
Index: /branches/czw_branch/20100519/ppBackground/src/ppBackgroundArguments.c
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/ppBackgroundArguments.c	(revision 28333)
+++ /branches/czw_branch/20100519/ppBackground/src/ppBackgroundArguments.c	(revision 28334)
@@ -45,9 +45,11 @@
     assert(data->config);
 
-    psMetadata *arguments = psMetadataAlloc(); // Command-line arguments
+    psMetadata *arguments = data->config->arguments;
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-pattern", 0, "Filename of pattern correction", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-background", 0, "Filename of background model", NULL);
-    psMetadataAddStr(arguments, PS_LIST_TAIL, "-image", 0, "Filename of image", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-image", 0, "Filename of image (required)", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-mask", 0, "Filename of mask", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-stats", 0, "Output statistics file", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dumpconfig", 0, "Output configuration file", NULL);
     if (argc == 1 || !psArgumentParse(arguments, &argc, argv) || argc != 2) {
         usage(argv[0], arguments, data);
@@ -59,8 +61,7 @@
     data->maskName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-mask"));
     data->outRoot = psStringCopy(argv[1]);
-    psMetadataAddStr(data->config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Output root name", data->outRoot);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "OUTPUT", 0, "Output root name", data->outRoot);
 
     psTrace("ppBackground", 1, "Done reading command-line arguments\n");
-    psFree(arguments);
 
     if (!data->patternName && !data->backgroundName) {
@@ -68,6 +69,21 @@
         return false;
     }
+    if (!data->imageName) {
+        psError(PPBACKGROUND_ERR_CONFIG, true, "Must specify -image");
+        return false;
+    }
 
     PS_ASSERT_STRING_NON_EMPTY(data->outRoot, false);
+
+    const char *statsName = psMetadataLookupStr(NULL, arguments, "-stats");
+    if (statsName) {
+        data->statsFile = fopen(statsName, "w");
+        if (!data->statsFile) {
+            psError(PPBACKGROUND_ERR_IO, true, "Unable to open statistics file %s", statsName);
+            return false;
+        }
+        data->stats = psMetadataAlloc();
+        pmConfigRunFilenameAddWrite(data->config, "STATS", statsName);
+    }
 
     return true;
Index: /branches/czw_branch/20100519/ppBackground/src/ppBackgroundCamera.c
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/ppBackgroundCamera.c	(revision 28333)
+++ /branches/czw_branch/20100519/ppBackground/src/ppBackgroundCamera.c	(revision 28334)
@@ -32,31 +32,32 @@
     bool status;                        // Status of file definition
 
-    fileArguments("PATTERN", data->patternName, "Input pattern", data->config);
-    pmFPAfile *pattern = pmFPAfileDefineFromArgs(&status, data->config, "PPBACKGROUND.PATTERN",
-                                                 "PATTERN"); // File
-    if (!status) {
-        psError(psErrorCodeLast(), false, "Failed to build file from PPBACKGROUND.PATTERN");
-        return false;
+    if (data->patternName) {
+        fileArguments("PATTERN", data->patternName, "Input pattern", data->config);
+        pmFPAfileDefineFromArgs(&status, data->config, "PPBACKGROUND.PATTERN", "PATTERN"); // File
+        if (!status) {
+            psError(psErrorCodeLast(), false, "Failed to build file from PPBACKGROUND.PATTERN");
+            return false;
+        }
     }
 
-    fileArguments("BACKGROUND", data->backgroundName, "Input background model", data->config);
-    pmFPAfile *background = pmFPAfileBindFromArgs(&status, data->config, "PPBACKGROUND.BACKGROUND",
-                                                  "BACKGROUND"); // File
-    if (!status) {
-        psError(psErrorCodeLast(), false, "Failed to build file from PPBACKGROUND.BACKGROUND");
-        return false;
+    if (data->backgroundName) {
+        fileArguments("BACKGROUND", data->backgroundName, "Input background model", data->config);
+        pmFPAfileDefineFromArgs(&status, data->config, "PPBACKGROUND.BACKGROUND", "BACKGROUND"); // File
+        if (!status) {
+            psError(psErrorCodeLast(), false, "Failed to build file from PPBACKGROUND.BACKGROUND");
+            return false;
+        }
     }
 
-    fileArguments("IMAGE", data->backgroundName, "Input uncorrected image", data->config);
-    pmFPAfile *image = pmFPAfileBindFromArgs(&status, background, data->config, "PPBACKGROUND.IMAGE",
-                                             "IMAGE"); // File
-    if (!status) {
+    fileArguments("IMAGE", data->imageName, "Input uncorrected image", data->config);
+    pmFPAfile *image = pmFPAfileDefineFromArgs(&status, data->config, "PPBACKGROUND.IMAGE",
+                                               "IMAGE"); // File
+    if (!status || !image) {
         psError(psErrorCodeLast(), false, "Failed to build file from PPBACKGROUND.IMAGE");
         return false;
     }
 
-    fileArguments("MASK", data->backgroundName, "Input uncorrected mask", data->config);
-    pmFPAfile *mask = pmFPAfileBindFromArgs(&status, image, data->config, "PPBACKGROUND.MASK",
-                                              "MASK"); // File
+    fileArguments("MASK", data->maskName, "Input uncorrected mask", data->config);
+    pmFPAfileBindFromArgs(&status, image, data->config, "PPBACKGROUND.MASK", "MASK"); // File
     if (!status) {
         psError(psErrorCodeLast(), false, "Failed to build file from PPBACKGROUND.MASK");
@@ -64,5 +65,5 @@
     }
 
-    pmFPAfile *output = pmFPAfileDefineOutput(data->config, file->fpa, "PPBACKGROUND.OUTPUT");
+    pmFPAfile *output = pmFPAfileDefineOutput(data->config, image->fpa, "PPBACKGROUND.OUTPUT");
     if (!output) {
         psError(psErrorCodeLast(), false, "Unable to define output.");
@@ -70,4 +71,11 @@
     }
     output->save = true;
+
+    pmFPAfile *outMask = pmFPAfileDefineOutput(data->config, output->fpa, "PPBACKGROUND.OUTPUT.MASK");
+    if (!outMask) {
+        psError(psErrorCodeLast(), false, "Unable to define output.");
+        return false;
+    }
+    outMask->save = true;
 
 #if 0
Index: /branches/czw_branch/20100519/ppBackground/src/ppBackgroundExit.c
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/ppBackgroundExit.c	(revision 28333)
+++ /branches/czw_branch/20100519/ppBackground/src/ppBackgroundExit.c	(revision 28334)
@@ -13,5 +13,5 @@
     if (errorCode != PS_ERR_NONE) {
         pmFPAfileFreeSetStrict(false);
-        psErrorStackPrint(stderr, "Error in subtraction:");
+        psErrorStackPrint(stderr, "Error in background restoration:");
         switch (errorCode) {
           case PS_ERR_UNKNOWN:
Index: /branches/czw_branch/20100519/ppBackground/src/ppBackgroundLoop.c
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/ppBackgroundLoop.c	(revision 28333)
+++ /branches/czw_branch/20100519/ppBackground/src/ppBackgroundLoop.c	(revision 28334)
@@ -6,4 +6,5 @@
 #include <pslib.h>
 #include <psmodules.h>
+#include <ppStats.h>
 
 #include "ppBackground.h"
@@ -13,9 +14,10 @@
 {
     pmConfig *config = data->config;                                        // Configuration data
-    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPBACKGROUND.BACKGROUND", 0);
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPBACKGROUND.IMAGE", 0);
     pmFPAfile *patternFile = pmFPAfileSelectSingle(config->files, "PPBACKGROUND.PATTERN", 0); // File with data
+    pmFPAfile *bgFile = pmFPAfileSelectSingle(config->files, "PPBACKGROUND.BACKGROUND", 0);   // File with bg
     pmFPA *patternMosaic = pmFPAConstruct(file->camera, file->cameraName); // Mosaicked FPA for pattern
 
-    psImageMaskType maskBad = pmConfigMaskGet("BLANK", config); // Mask value to set
+    psImageMaskType maskBad = pmConfigMaskGet("DETECTOR", config); // Mask value to set
 
     pmFPAview *view = pmFPAviewAlloc(0); // Pointer into FPA hierarchy
@@ -34,5 +36,5 @@
         }
 
-        if (chip->cell->n > 1) {
+        if (chip->cells->n > 1) {
             psError(PPBACKGROUND_ERR_CONFIG, true,
                     "Input image and background model should be chip-mosaicked");
@@ -44,7 +46,7 @@
             pmFPAfileActivate(config->files, true, "PPBACKGROUND.PATTERN");
 
-            pmCell *cell;               // Cell with pattern data
+            pmCell *patternCell;               // Cell with pattern data
             while ((patternCell = pmFPAviewNextCell(view, patternFile->fpa, 1))) {
-                if (!cell->process || !cell->file_exists) {
+                if (!patternCell->process || !patternCell->file_exists) {
                     continue;
                 }
@@ -68,10 +70,10 @@
                     // Get size of image from concepts
                     if (numCols == 0 || numRows == 0) {
-                        numCols = psMetadataLookupS32(NULL, cell->concepts, "CELL.XSIZE");
-                        numRows = psMetadataLookupS32(NULL, cell->concepts, "CELL.YSIZE");
+                        numCols = psMetadataLookupS32(NULL, patternCell->concepts, "CELL.XSIZE");
+                        numRows = psMetadataLookupS32(NULL, patternCell->concepts, "CELL.YSIZE");
                     }
                     // Get size of image from TRIMSEC
                     if (numCols == 0 || numRows == 0) {
-                        psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC");
+                        psRegion *trimsec = psMetadataLookupPtr(NULL, patternCell->concepts, "CELL.TRIMSEC");
                         numCols = trimsec->x1 - trimsec->x0;
                         numRows = trimsec->y1 - trimsec->y0;
@@ -84,4 +86,6 @@
                     readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
                     psImageInit(readout->image, 0.0);
+                    readout->mask = psImageAlloc(numCols, numRows, PS_TYPE_IMAGE_MASK);
+                    psImageInit(readout->mask, 0);
 
                     if (!pmPatternRowApply(readout, maskBad) || !pmPatternCellApply(readout, maskBad)) {
@@ -91,5 +95,5 @@
 
                     // Remove bias sections to avoid warnings
-                    psMetadataItem *biassec = psMetadataLookup(patternRO->parent->concepts, "CELL.BIASSEC");
+                    psMetadataItem *biassec = psMetadataLookup(patternCell->concepts, "CELL.BIASSEC");
                     if (psListLength(biassec->data.V)) {
                         psFree(biassec->data.V);
@@ -114,35 +118,36 @@
             }
 
-            pmChip *mosaic = pmFPAviewThisChip(view, patternMosaic); // Chip for mosaicked pattern
-            if (!pmChipMosaic(mosaic, chip, true, maskBad)) {
-                psError(psErrorCodeLast(), false, "Unable to mosaic pattern correction");
-                return false;
+            if (data->patternName) {
+                pmChip *patternChip = pmFPAviewThisChip(view, patternFile->fpa); // Chip for pattern
+                pmChip *mosaic = pmFPAviewThisChip(view, patternMosaic); // Chip for mosaicked pattern
+                if (!mosaic->hdu && !mosaic->parent->hdu) {
+                    pmFPAAddSourceFromView(patternMosaic, view, file->format);
+                }
+                if (!pmChipMosaic(mosaic, patternChip, true, maskBad)) {
+                    psError(psErrorCodeLast(), false, "Unable to mosaic pattern correction");
+                    return false;
+                }
+                pmFPAfileActivate(config->files, true, NULL);
+            //            pmFPAfileActivate(config->files, false, "PPBACKGROUND.PATTERN");
             }
-            pmFPAfileActivate(config->files, true, NULL);
-            pmFPAfileActivate(config->files, false, "PPBACKGROUND.PATTERN");
         }
 
+        pmChip *patternChip = patternFile ? pmFPAviewThisChip(view, patternMosaic) : NULL; // Chip with pattern
+        pmChip *bgChip = bgFile ? pmFPAviewThisChip(view, bgFile->fpa) : NULL; // Chip with background model
+        if (!ppBackgroundRestore(chip, bgChip, patternChip, view, config)) {
+            psError(psErrorCodeLast(), false, "Unable to replace background");
+            return false;
+        }
+        pmChipFreeData(patternChip);
 
-
-
-
-
-
-                pmHDU *hdu = pmHDUGetLowest(file->fpa, chip, cell); // HDU for readout
-                if (!hdu) {
-                    psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find HDU for data.");
-                    return false;
-                }
-                if (!hdu->header) {
-                    hdu->header = psMetadataAlloc();
-                }
-                ppBackgroundVersionHeader(hdu->header);
-
-
-
-
-
-
-
+        pmHDU *hdu = pmHDUGetLowest(file->fpa, chip, NULL); // HDU for chip
+        if (!hdu) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find HDU for data.");
+            return false;
+        }
+        if (!hdu->header) {
+            hdu->header = psMetadataAlloc();
+        }
+        ppBackgroundVersionHeader(hdu->header);
 
         // Chip
@@ -158,4 +163,17 @@
     }
 
+    psFree(patternMosaic);
+
+    if (data->stats) {
+        psImageMaskType maskVal = 0;    // Bits to mask
+        if (!pmConfigMaskSetBits(&maskVal, NULL, config)) {
+            psError(psErrorCodeLast(), false, "Unable to find bits to mask");
+            return false;
+        }
+        ppStatsFPA(data->stats, file->fpa, view, maskVal, config);
+    }
+
+    psFree(view);
+
     return true;
 }
Index: anches/czw_branch/20100519/ppBackground/src/ppBackgroundModel.c
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/ppBackgroundModel.c	(revision 28333)
+++ 	(revision )
@@ -1,92 +1,0 @@
-#include <stdio.h>
-#include <pslib.h>
-#include <psmodules.h>
-#include <psphot.h>
-
-
-bool ppBackgroundModel(
-        pmReadout *ro = cell->readouts->data[0]; // Readout of interest
-        if (!ro || !ro->data_exists) {
-            psError(PS_ERR_UNKNOWN, true, "readout has no data");
-            return false;
-        }
-        psImage *image = ro->image;
-//        psImage *mask = NULL;
-//        psImageMaskType maskVal = 0;
-
-        pmFPAview roView = *view;
-        roView.cell = 0;
-        roView.readout = 0;
-        pmReadout *modelRO = pmFPAviewThisReadout(&roView, backmdl->fpa);
-        if (!modelRO || !modelRO->data_exists) {
-            psError(PS_ERR_UNKNOWN, true, "model readout has no data");
-            return false;
-        }
-        output->save = true;
-        background->save = save_background;
-
-        psImageBinning *binning = psphotBackgroundBinning(image, config);
-        if (!binning) {
-            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find background binning");
-            return false;
-        }
-        pmReadout *backgroundRO;
-#define USE_CELL
-#ifdef USE_CELL
-        pmCell *backgroundCell = pmFPAviewThisCell(&roView, background->fpa);
-        backgroundRO = pmReadoutAlloc(backgroundCell);
-#else
-        backgroundRO = pmFPAviewThisReadout(&roView, background->fpa);
-//        backgroundRO = pmFPAfileDefineInternal (config->files, "PSPHOT.BACKGND", image->numCols, image->numRows, PS_TYPE_F32);
-#endif
-        backgroundRO->image = psImageAlloc(image->numCols, image->numRows, PS_TYPE_F32);
-        backgroundRO->data_exists = true;
-        backgroundRO->parent->data_exists = true;
-        backgroundRO->parent->parent->data_exists = true;
-
-        // linear interpolation to full-scale
-        if (!psImageUnbin (backgroundRO->image, modelRO->image, binning)) {
-            psError (PSPHOT_ERR_PROG, true, "inconsistent sizes for unbinning");
-            psFree(binning);
-            return false;
-        }
-        psFree(binning);
-        psF32 **backData = backgroundRO->image->data.F32;
-
-        // Undo the background subtraction
-        int numCols = image->numCols, numRows = image->numRows; // Size of image
-        long nancount = 0;
-        long naninputs = 0;
-        long finitecount = 0;
-        for (int y = 0; y < numRows; y++) {
-            for (int x = 0; x < numCols; x++) {
-                float imageval =  image->data.F32[y][x] ;
-                float bgvalue = backData[y][x];
-                if (!isfinite(bgvalue)) {
-                    // if background is NAN leave the image unchanged
-                    // According to ppImageSubtractBackground pixels where the background is not finite should be NAN
-                    // experimentally
-                    // for breakpoint
-                    nancount++;
-                    if (isfinite(imageval)) {
-                         finitecount++;
-                         //   psWarning("unexpected finite image value %f found at %d %d background is infinite", imageval, x, y);
-                    }
-                    //      Doing this is causes a lot of new NAN pixels to appear.
-                    //      NANS are appearing in the model for some reason.
-                    //      image->data.F32[y][x] = NAN;
-                } else if (isfinite(imageval)) {
-                    // XXX: TODO:following ppImage we should not modify pixels that are masked.
-                    image->data.F32[y][x] = imageval + bgvalue;
-                } else {
-                    naninputs++;
-                }
-            }
-        }
-        if (naninputs) {
-            printf("%ld infinite pixels found in input image\n", naninputs);
-        }
-        if (nancount) {
-            psWarning("%ld infinite pixels found in background %ld pixels were finite\n", nancount, finitecount);
-        }
-//        pmFPAfileDropInternal(config->files, "PSPHOT.BACKGND");
Index: /branches/czw_branch/20100519/ppBackground/src/ppBackgroundRestore.c
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/ppBackgroundRestore.c	(revision 28334)
+++ /branches/czw_branch/20100519/ppBackground/src/ppBackgroundRestore.c	(revision 28334)
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include <psphot.h>
+
+#include "ppBackground.h"
+
+bool ppBackgroundRestore(pmChip *chip, const pmChip *background, const pmChip *pattern,
+                         const pmFPAview *oldView, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(oldView, false);
+
+    pmFPAview *view = pmFPAviewAlloc(0); // View to readout
+    *view = *oldView;
+    view->cell = 0;
+    view->readout = 0;
+
+    pmReadout *ro = pmFPAviewThisReadout(view, chip->parent);
+    if (!ro || !ro->data_exists) {
+        psError(PPBACKGROUND_ERR_CONFIG, true, "Readout has no data");
+        return false;
+    }
+    const psImage *image = ro->image, *mask = ro->mask;   // Input image
+    int numCols = image->numCols, numRows = image->numRows; // Size of image
+
+    if (background) {
+        pmReadout *bgRO = pmFPAviewThisReadout(view, background->parent); // Readout with background
+        psImageBinning *binning = psphotBackgroundBinning(image, config);
+        if (!binning) {
+            psError(psErrorCodeLast(), false, "Unable to find background binning");
+            return false;
+        }
+        if (binning->nXfine != numCols || binning->nYfine != numRows) {
+            psError(PPBACKGROUND_ERR_CONFIG, true,
+                    "Unbinned background model and input don't match (%dx%d vs %dx%d)",
+                    binning->nXfine, binning->nYfine, numCols, numRows);
+            return false;
+        }
+
+        psImage *bgImage = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Background
+        if (!psImageUnbin(bgImage, bgRO->image, binning)) {
+            psError(psErrorCodeLast(), false, "Unable to unbin background model");
+            psFree(binning);
+            return false;
+        }
+        psFree(binning);
+
+        for (int y = 0; y < numRows; y++) {
+            for (int x = 0; x < numCols; x++) {
+                image->data.F32[y][x] += bgImage->data.F32[y][x];
+            }
+        }
+        psFree(bgImage);
+    }
+
+    if (pattern) {
+        pmReadout *patternRO = pmFPAviewThisReadout(view, pattern->parent); // Readout with pattern
+        psImage *patternImage = patternRO->image; // Image with pattern
+        psImage *patternMask = patternRO->mask;   // Mask for pattern
+        for (int y = 0; y < numRows; y++) {
+            for (int x = 0; x < numCols; x++) {
+                image->data.F32[y][x] -= patternImage->data.F32[y][x];
+                mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= patternMask->data.PS_TYPE_IMAGE_MASK_DATA[y][x];
+            }
+        }
+    }
+
+    ro->data_exists = true;
+    ro->parent->data_exists = true;
+    ro->parent->parent->data_exists = true;
+
+    return true;
+}
+
+
+
Index: /branches/czw_branch/20100519/ppBackground/src/ppBackgroundVersionDefinitions.h.in
===================================================================
--- /branches/czw_branch/20100519/ppBackground/src/ppBackgroundVersionDefinitions.h.in	(revision 28333)
+++ /branches/czw_branch/20100519/ppBackground/src/ppBackgroundVersionDefinitions.h.in	(revision 28334)
@@ -1,8 +1,8 @@
-#ifndef PPVIZPATTERN_VERSION_DEFINITIONS_H
-#define PPVIZPATTERN_VERSION_DEFINITIONS_H
+#ifndef PPBACKGROUND_VERSION_DEFINITIONS_H
+#define PPBACKGROUND_VERSION_DEFINITIONS_H
 
-#define PPVIZPATTERN_VERSION @PPVIZPATTERN_VERSION@ // SVN version
-#define PPVIZPATTERN_BRANCH  @PPVIZPATTERN_BRANCH@  // SVN branch
-#define PPVIZPATTERN_SOURCE  @PPVIZPATTERN_SOURCE@  // SVN source
+#define PPBACKGROUND_VERSION @PPBACKGROUND_VERSION@ // SVN version
+#define PPBACKGROUND_BRANCH  @PPBACKGROUND_BRANCH@  // SVN branch
+#define PPBACKGROUND_SOURCE  @PPBACKGROUND_SOURCE@  // SVN source
 
 #endif
Index: /branches/czw_branch/20100519/ppImage/src/ppImageLoop.c
===================================================================
--- /branches/czw_branch/20100519/ppImage/src/ppImageLoop.c	(revision 28333)
+++ /branches/czw_branch/20100519/ppImage/src/ppImageLoop.c	(revision 28334)
@@ -51,5 +51,5 @@
             ESCAPE("load failure for Chip");
         }
-	printf("PPI: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
         // crosstalk measurement needs to be done on the entire chip at once, and before
         // signal levels are modified by the detrending.  If crosstalk measurement is
@@ -65,5 +65,5 @@
           ESCAPE("Unable to perform crosstalk correction");
         }
-	printf("PPI: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
         psTimerStart(TIMER_DETREND);
         pmCell *cell;                   // Cell from chip
@@ -152,5 +152,5 @@
             ESCAPE("Unable to free detrend images");
         }
-	printf("PPI: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
         // Apply the fringe correction
         if (options->doFringe) {
@@ -163,5 +163,5 @@
             ESCAPE("Unable to free fringe images");
         }
-	printf("PPI: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
         // Apply the pattern correction
         if (options->doPatternRow || options->doPatternCell) {
@@ -170,10 +170,10 @@
           }
         }
-	printf("PPI: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
         // measure various pixel-based statistics for this image
         if (!ppImagePixelStats(config, stats, options, view)) {
             ESCAPE("Unable to measures pixel stats for image");
         }
-	printf("PPI: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
         if (!ppImageMosaicChip(config, options, view, "PPIMAGE.CHIP", "PPIMAGE.OUTPUT")) {
             ESCAPE("Unable to mosaic chip");
@@ -182,5 +182,5 @@
 
         // we perform photometry on the readouts of this chip in the output
-	printf("PPI: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
         psTimerStart(TIMER_PHOT);
         if (options->doPhotom) {
Index: /branches/czw_branch/20100519/ppImage/src/ppImageMosaic.c
===================================================================
--- /branches/czw_branch/20100519/ppImage/src/ppImageMosaic.c	(revision 28333)
+++ /branches/czw_branch/20100519/ppImage/src/ppImageMosaic.c	(revision 28334)
@@ -9,5 +9,5 @@
 {
     bool status;                        // Status of MD lookup
-	printf("PPIM: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
     pmFPAfile *in = psMetadataLookupPtr(&status, config->files, inFile); // Input file
     if (!status) {
@@ -15,5 +15,5 @@
         exit(EXIT_FAILURE);
     }
-	printf("PPIM: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
     pmFPAfile *out = psMetadataLookupPtr(&status, config->files, outFile); // Output file
     if (!status) {
@@ -21,5 +21,5 @@
         exit(EXIT_FAILURE);
     }
-	printf("PPIM: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
     pmChip *outChip = pmFPAviewThisChip(view, out->fpa);
     pmChip *inChip = pmFPAviewThisChip(view, in->fpa);
@@ -27,10 +27,8 @@
         pmFPAAddSourceFromView(out->fpa, view, out->format);
     }
-	printf("PPIM: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
     // If the input is a dark (normalising and mosaicking) then it looks like a video cell and will be ignored
     // by pmChipMosaic.  We therefore hack the structure so it doesn't look like a video cell.
     psVector *darkNumbers = NULL;       // Number of dark readouts for each cell
-    //    psVectorInit(darkNumbers, 0);
-    printf("PPIM: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
     if (psMetadataLookupBool(&status, config->arguments, "INPUT_IS_DARK")) {
         darkNumbers = psVectorAlloc(inChip->cells->n, PS_TYPE_S32);
@@ -45,5 +43,5 @@
         }
     }
-	printf("PPMI: %x %s\n",psErrorCodeLast(),psErrorCodeString(psErrorCodeLast()));
+
     psTrace("pmChipMosaic", 5, "mosaic chip %s to %s (xbin,ybin: %d,%d to %d,%d)\n",
             in->name, out->name, in->xBin, in->yBin, out->xBin, out->yBin);
Index: /branches/czw_branch/20100519/ppStack/src/ppStackTarget.c
===================================================================
--- /branches/czw_branch/20100519/ppStack/src/ppStackTarget.c	(revision 28333)
+++ /branches/czw_branch/20100519/ppStack/src/ppStackTarget.c	(revision 28334)
@@ -164,8 +164,31 @@
 
         psStats *bg = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for background
+        float mean = NAN;                                  // Measured mean variance
         if (!psImageBackground(bg, NULL, variance, mask, maskVal, rng)) {
-            psError(PPSTACK_ERR_DATA, false, "Can't measure background for image.");
-            psFree(rng);
-            return NULL;
+            psErrorClear();
+            // Retry using all the available pixels
+            bg->nSubsample = variance->numCols * variance->numRows + 1;
+            if (!psImageStats(bg, variance, mask, maskVal)) {
+                psLogMsg("ppStack", PS_LOG_DETAIL,
+                         "Couldn't measure mean variance for image %d; retrying.", i);
+                psErrorClear();
+                // Retry with desperate statistic
+                bg->options = PS_STAT_SAMPLE_MEAN;
+                if (!psImageStats(bg, variance, mask, maskVal)) {
+                    psWarning("Unable to measure mean variance for image %d --- rejecting.", i);
+                    psErrorStackPrint(stderr, "Unable to measure mean variance for image %d", i);
+                    options->inputMask->data.PS_TYPE_VECTOR_MASK_DATA[i] |= PPSTACK_MASK_PSF;
+                    goto DONE;
+                } else {
+                    // Desperate retry
+                    mean = bg->sampleMean;
+                }
+            } else {
+                // Retry with all available pixels
+                mean = bg->robustMedian;
+            }
+        } else {
+            // First attempt
+            mean = bg->robustMedian;
         }
 
@@ -177,4 +200,6 @@
         }
 
+    DONE:
+        psFree(bg);
         if (!ppStackFilesIterateUp(config)) {
             psFree(rng);
Index: /branches/czw_branch/20100519/psLib/src/sys/psAbort.c
===================================================================
--- /branches/czw_branch/20100519/psLib/src/sys/psAbort.c	(revision 28333)
+++ /branches/czw_branch/20100519/psLib/src/sys/psAbort.c	(revision 28334)
@@ -23,9 +23,48 @@
 #include <stdarg.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
+#if defined(HAVE_BACKTRACE)
+#include <execinfo.h>
+#define BACKTRACE_BUFFER_SIZE 256       // Maximum size of backtrace
+#endif
+
 #include "psAbort.h"
+#include "psString.h"
+#include "psMemory.h"
 #include "psError.h"
 #include "psLogMsg.h"
+
+// Write backtrace to log
+static inline void psBacktrace(void)
+{
+#ifdef HAVE_BACKTRACE
+    void **bt = psAlloc(BACKTRACE_BUFFER_SIZE * sizeof(void *)); // Backtrace information
+    if (!bt) {
+        psLogMsg("psLib.sys", PS_LOG_ABORT, "Unable to allocate memory for backtrace");
+        return;
+    }
+    int size = backtrace(bt, BACKTRACE_BUFFER_SIZE);             // Size of backtrace
+    char **strings = backtrace_symbols((void *const *)bt, size);
+    psLogMsg("psLib.sys", PS_LOG_ABORT, "Backtrace depth: %d", size);
+    for (int i = 0; i < size; i++) {
+        // if the caller was an anon function then strchr won't
+        // find a '(' in the string and will return NULL
+        char *caller = strchr(strings[i], '(');
+        if (caller) {
+            // skip over the '('
+            caller++;
+            // find the end of the symbol name
+            size_t callerLength = abs(strchr(caller, '+') - caller);
+            psString name = psStringNCopy(caller, callerLength);
+            psLogMsg("psLib.sys", PS_LOG_ABORT, "Backtrace %d: %s", i, name);
+            psFree(name);
+        } else {
+            psLogMsg("psLib.sys", PS_LOG_ABORT, "Backtrace %d: (unknown)", i);
+        }
+    }
+#endif // ifdef HAVE_BACKTRACE
+}
 
 void p_psAbort(const char *file,
@@ -46,4 +85,6 @@
     // Clean up stack after variable arguement has been used
     va_end(argPtr);
+
+    psBacktrace();
 
     // Call system abort function to terminate program execution
@@ -72,4 +113,6 @@
     va_end(argPtr);
 
+    psBacktrace();
+
     // Call system abort function to terminate program execution
     fsync(psLogGetDestination());
Index: /branches/czw_branch/20100519/psLib/src/sys/psThread.c
===================================================================
--- /branches/czw_branch/20100519/psLib/src/sys/psThread.c	(revision 28333)
+++ /branches/czw_branch/20100519/psLib/src/sys/psThread.c	(revision 28334)
@@ -210,5 +210,7 @@
         psThreadTask *task = psHashLookup(tasks, job->type); // Task to execute job
         psAssert(task, "Couldn't find thread task %s", job->type);
-        psAssert(job->args->n == task->nArgs, "invalid number of arguments to %s (%ld supplied, expected %d)", task->type, job->args->n, task->nArgs);
+        psAssert(job->args->n == task->nArgs,
+                 "invalid number of arguments to %s (%ld supplied, expected %d)",
+                 task->type, job->args->n, task->nArgs);
         bool status = task->function(job); // Status of executing task
 
Index: /branches/czw_branch/20100519/psModules/src/config/pmConfig.c
===================================================================
--- /branches/czw_branch/20100519/psModules/src/config/pmConfig.c	(revision 28333)
+++ /branches/czw_branch/20100519/psModules/src/config/pmConfig.c	(revision 28334)
@@ -306,5 +306,5 @@
     *config = psMetadataConfigRead(NULL, &numBadLines, realName, true);
     if (numBadLines > 0) {
-        psError(PM_ERR_CONFIG, false, "%d bad lines in %s configuration file (%s)",
+        psError(PM_ERR_CONFIG, true, "%d bad lines in %s configuration file (%s)",
                 numBadLines, description, realName);
         psFree (realName);
@@ -1751,5 +1751,5 @@
     psMetadataItem *item = psMetadataLookup(camera, "FILERULES"); // Item with the file rule of interest
     if (!item) {
-        psError(PM_ERR_CONFIG, false, "Unable to find FILERULES in the camera configuration.");
+        psError(PM_ERR_CONFIG, true, "Unable to find FILERULES in the camera configuration.");
         return NULL;
     }
@@ -1771,5 +1771,5 @@
     }
 
-    return psMetadataLookupMetadata(&mdok, filerules, realname);
+    return psMetadataLookupMetadata(NULL, filerules, realname);
 }
 
Index: /branches/czw_branch/20100519/pstamp/src/pstamp.h
===================================================================
--- /branches/czw_branch/20100519/pstamp/src/pstamp.h	(revision 28333)
+++ /branches/czw_branch/20100519/pstamp/src/pstamp.h	(revision 28334)
@@ -33,6 +33,8 @@
 #define PSTAMP_SELECT_BACKMDL   32
 #define PSTAMP_SELECT_INVERSE 1024
+#define PSTAMP_SELECT_UNCONV  2048
+#define PSTAMP_USE_IMFILE_ID 16384
 
-#define PSTAMP_WAIT_FOR_UPDATE 2048
+#define PSTAMP_NO_WAIT_FOR_UPDATE 32768
 
 #define PSTAMP_CENTER_IN_PIXELS 1
Index: /branches/czw_branch/20100519/tools/chip_outputs.pl
===================================================================
--- /branches/czw_branch/20100519/tools/chip_outputs.pl	(revision 28333)
+++ /branches/czw_branch/20100519/tools/chip_outputs.pl	(revision 28334)
@@ -23,4 +23,6 @@
                              'PSF' => '.psf',     # Point-spread function
                              'LOG' => '.log',     # Processing log
+                             'PATTERN' => '.ptn', # Pattern subtraction
+                             'MODEL' => '.mdl.fits', # Background model
                          };
 
