Index: trunk/ppBackground/Makefile.am
===================================================================
--- trunk/ppBackground/Makefile.am	(revision 28276)
+++ trunk/ppBackground/Makefile.am	(revision 28276)
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES = *.pyc *~ core core.*
Index: trunk/ppBackground/autogen.sh
===================================================================
--- trunk/ppBackground/autogen.sh	(revision 28276)
+++ trunk/ppBackground/autogen.sh	(revision 28276)
@@ -0,0 +1,103 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=ppBackground
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+AUTOHEADER=autoheader
+AUTOMAKE=automake
+AUTOCONF=autoconf
+
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $LIBTOOLIZE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/libtool/"
+        DIE=1
+}
+
+($ACLOCAL --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $ACLOCAL installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOHEADER --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOHEADER installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOMAKE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOCONF installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+if test "$DIE" -eq 1; then
+        exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+        echo "You must run this script in the top-level $PROJECT directory"
+        exit 1
+}
+
+if test -z "$*"; then
+        echo "I am going to run ./configure with no arguments - if you wish "
+        echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+$LIBTOOLIZE --copy --force || echo "$LIBTOOLIZE failed"
+$ACLOCAL || echo "$ACLOCAL failed"
+$AUTOHEADER || echo "$AUTOHEADER failed"
+$AUTOMAKE --add-missing --force-missing --copy || echo "$AUTOMAKE  failed"
+$AUTOCONF || echo "$AUTOCONF failed"
+
+cd $ORIGDIR
+
+run_configure=true
+for arg in $*; do
+    case $arg in
+        --no-configure)
+            run_configure=false
+            ;;
+        *)
+            ;;
+    esac
+done
+
+if $run_configure; then
+    $srcdir/configure --enable-maintainer-mode "$@"
+    echo
+    echo "Now type 'make' to compile $PROJECT."
+else
+    echo
+    echo "Now run 'configure' and 'make' to compile $PROJECT."
+fi
Index: trunk/ppBackground/configure.ac
===================================================================
--- trunk/ppBackground/configure.ac	(revision 28276)
+++ trunk/ppBackground/configure.ac	(revision 28276)
@@ -0,0 +1,38 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.61)
+
+AC_INIT([ppBackground], [0.1.1], [ipp-support@ifa.hawaii.edu])
+AC_CONFIG_SRCDIR([src])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([src/config.h])
+AM_MAINTAINER_MODE
+
+IPP_STDCFLAGS
+
+AC_LANG(C)
+AC_GNU_SOURCE
+AC_PROG_CC_C99
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+AC_SYS_LARGEFILE
+
+PKG_CHECK_MODULES([PSLIB], [pslib >= 1.0.0])
+PKG_CHECK_MODULES([PSMODULE], [psmodules >= 1.0.0])
+PKG_CHECK_MODULES([PSPHOT], [psphot >= 1.0.0])
+
+dnl Set CFLAGS for build
+IPP_STDOPTS
+CFLAGS="${CFLAGS} -Wall -Werror"
+
+IPP_VERSION
+
+AC_SUBST([PPBACKGROUND_CFLAGS])
+AC_SUBST([PPBACKGROUND_LIBS])
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+])
+
+AC_OUTPUT
Index: trunk/ppBackground/src/Makefile.am
===================================================================
--- trunk/ppBackground/src/Makefile.am	(revision 28276)
+++ trunk/ppBackground/src/Makefile.am	(revision 28276)
@@ -0,0 +1,61 @@
+bin_PROGRAMS = ppBackground
+
+if HAVE_SVNVERSION
+PPVIZPATTERN_VERSION=`$(SVNVERSION) ..`
+else
+PPVIZPATTERN_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'`
+else
+PPVIZPATTERN_BRANCH="UNKNOWN"
+PPVIZPATTERN_SOURCE="UNKNOWN"
+endif
+
+# Force recompilation of ppBackgroundVersion.c, since it gets the version information
+ppBackgroundVersion.c: ppBackgroundVersionDefinitions.h
+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
+FORCE: ;
+
+BUILT_SOURCES = ppBackgroundVersionDefinitions.h
+
+
+ppBackground_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSPHOT_CFLAGS) $(PPBACKGROUND_CFLAGS)
+ppBackground_LDFLAGS  = $(PSLIB_LIBS)   $(PSMODULE_LIBS)   $(PSPHOT_LIBS)   $(PPBACKGROUND_LIBS)
+
+ppBackground_SOURCES =		\
+	ppBackground.c		\
+	ppBackgroundArguments.c	\
+	ppBackgroundCamera.c	\
+	ppBackgroundData.c	\
+	ppBackgroundLoop.c	\
+	ppBackgroundVersion.c   \
+	ppBackgroundModel.c	\
+	ppBackgroundErrorCodes.c
+
+noinst_HEADERS = \
+	ppBackground.h		\
+	ppBackgroundErrorCodes.h
+
+### Error codes.
+BUILT_SOURCES = ppBackgroundErrorCodes.h ppBackgroundErrorCodes.c
+CLEANFILES = ppBackgroundErrorCodes.h ppBackgroundErrorCodes.c
+
+ppBackgroundErrorCodes.h : ppBackgroundErrorCodes.dat ppBackgroundErrorCodes.h.in
+	$(ERRORCODES) --data=ppBackgroundErrorCodes.dat --outdir=. ppBackgroundErrorCodes.h
+
+ppBackgroundErrorCodes.c : ppBackgroundErrorCodes.dat ppBackgroundErrorCodes.c.in ppBackgroundErrorCodes.h
+	$(ERRORCODES) --data=ppBackgroundErrorCodes.dat --outdir=. ppBackgroundErrorCodes.c
+
+
+clean-local:
+	-rm -f TAGS
+
+# Tags for emacs
+tags:
+	etags `find . -name \*.[ch] -print`
+
Index: trunk/ppBackground/src/ppBackground.c
===================================================================
--- trunk/ppBackground/src/ppBackground.c	(revision 28276)
+++ trunk/ppBackground/src/ppBackground.c	(revision 28276)
@@ -0,0 +1,68 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppBackground.h"
+
+int main(int argc, char *argv[])
+{
+    ppBackgroundVersionPrint();
+
+    ppBackgroundData *data = ppBackgroundDataInit(&argc, argv);
+    if (!data) {
+        goto DIE;
+    }
+
+    if (!ppBackgroundArguments(data, argc, argv)) {
+        goto DIE;
+    }
+
+    if (!ppBackgroundCamera(data)) {
+        goto DIE;
+    }
+
+    if (!ppBackgroundLoop(data)) {
+        goto DIE;
+    }
+
+ DIE:
+    ; // Empty statement to satisy compiler
+    psExit exitValue = ppBackgroundExitCode(PS_EXIT_SUCCESS); // Exit code
+
+    if (data && data->stats && data->statsFile) {
+        psString stats = psMetadataConfigFormat(data->stats); // Statistics to output
+        if (!stats || strlen(stats) == 0) {
+            psError(PPBACKGROUND_ERR_IO, false, "Unable to format statistics file");
+        } else if (fprintf(data->statsFile, "%s", stats) != strlen(stats)) {
+            psError(PPBACKGROUND_ERR_IO, true, "Unable to write statistics file");
+        }
+        psFree(stats);
+        if (fclose(data->statsFile) == EOF) {
+            psError(PPBACKGROUND_ERR_IO, true, "Unable to close statistics file");
+        }
+        data->statsFile = NULL;
+        pmConfigRunFilenameAddWrite(data->config, "STATS", data->statsName);
+        exitValue = ppBackgroundExitCode(exitValue);
+    }
+
+    if (data) {
+        psString dump_file = psMetadataLookupStr(NULL, data->config->arguments, "-dumpconfig");
+        if (dump_file) {
+            if (!pmConfigDump(data->config, dump_file)) {
+                psError(psErrorCodeLast(), false, "Unable to dump configuration.");
+                exitValue = ppBackgroundExitCode(exitValue);
+            }
+        }
+        psFree(data);
+    }
+
+    pmConfigDone();
+    psLibFinalize();
+
+    return ppBackgroundExitCode(exitValue);
+}
+
Index: trunk/ppBackground/src/ppBackground.h
===================================================================
--- trunk/ppBackground/src/ppBackground.h	(revision 28276)
+++ trunk/ppBackground/src/ppBackground.h	(revision 28276)
@@ -0,0 +1,52 @@
+#ifndef PP_VIZPSF_H
+#define PP_VIZPSF_H
+
+#include <pslib.h>
+#include <psmodules.h>
+
+#include <ppBackgroundErrorCodes.h>
+
+#define PPBACKGROUND_RECIPE "PPBACKGROUND"      // Recipe name
+
+// Data for processing
+typedef struct {
+    psString patternName;               // Filename of pattern
+    psString backgroundName;            // Filename of background
+    psString imageName, maskName;       // Filenames of input image/mask
+    psString outRoot;                   // Output root name
+    psMetadata *stats;                  // Statistics for output
+    FILE *statsFile;                    // Output statistics file
+    pmConfig *config;                   // Configuration
+} ppBackgroundData;
+
+/// Initialise data for processing
+ppBackgroundData *ppBackgroundDataInit(int *argc, char *argv[] // Command-line arguments
+    );
+
+/// Parse command-line arguments
+bool ppBackgroundArguments(ppBackgroundData *data, // Data for processing
+                        int argc, char *argv[] // Command-line arguments
+    );
+
+/// Parse camera configurations
+bool ppBackgroundCamera(ppBackgroundData *data // Data for processing
+    );
+
+/// Loop over input data, processing
+bool ppBackgroundLoop(ppBackgroundData *data // Data for processing
+    );
+
+/// Determine exit code
+psExit ppBackgroundExitCode(
+    psExit exitValue                    // Current exit code
+    );
+
+/// Add version information to header
+bool ppBackgroundVersionHeader(
+    psMetadata *header                  // Header to supplement
+    );
+
+/// Print version information to stdout
+void ppBackgroundVersionPrint(void);
+
+#endif
Index: trunk/ppBackground/src/ppBackgroundArguments.c
===================================================================
--- trunk/ppBackground/src/ppBackgroundArguments.c	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundArguments.c	(revision 28276)
@@ -0,0 +1,76 @@
+/** @file ppBackgroundArguments.c
+ *
+ *  @brief
+ *
+ *  @ingroup ppBackground
+ *
+ *  @author Paul Price
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppBackground.h"
+
+/// Print usage information and die
+static void usage(const char *program,  // Name of the program
+                  psMetadata *arguments, // Command-line arguments
+                  ppBackgroundData *data   // Run-time data
+    )
+{
+    fprintf(stderr, "\nPan-STARRS background replacement\n\n");
+    fprintf(stderr, "Usage: %s OUTPUT_ROOT\n\n", program);
+    fprintf(stderr, "\n");
+    psArgumentHelp(arguments);
+    psFree(arguments);
+    psFree(data);
+
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(PS_EXIT_CONFIG_ERROR);
+}
+
+
+bool ppBackgroundArguments(ppBackgroundData *data, int argc, char *argv[])
+{
+    assert(data);
+    assert(data->config);
+
+    psMetadata *arguments = psMetadataAlloc(); // Command-line 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, "-mask", 0, "Filename of mask", NULL);
+    if (argc == 1 || !psArgumentParse(arguments, &argc, argv) || argc != 2) {
+        usage(argv[0], arguments, data);
+    }
+
+    data->patternName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-pattern"));
+    data->backgroundName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-background"));
+    data->imageName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-image"));
+    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);
+
+    psTrace("ppBackground", 1, "Done reading command-line arguments\n");
+    psFree(arguments);
+
+    if (!data->patternName && !data->backgroundName) {
+        psError(PPBACKGROUND_ERR_CONFIG, true, "Must specify at least one of -pattern and -background");
+        return false;
+    }
+
+    PS_ASSERT_STRING_NON_EMPTY(data->outRoot, false);
+
+    return true;
+}
+
+
Index: trunk/ppBackground/src/ppBackgroundCamera.c
===================================================================
--- trunk/ppBackground/src/ppBackgroundCamera.c	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundCamera.c	(revision 28276)
@@ -0,0 +1,83 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppBackground.h"
+
+/// Add a single filename to the arguments as an array, so that it can be used with pmFPAfileBindFromArgs, etc
+static void fileArguments(const char *file, // The symbolic name for the file
+                          const char *name, // The name of the file
+                          const char *comment, // Description of the file
+                          pmConfig *config // Configuration
+    )
+{
+    psArray *files = psArrayAlloc(1); // Array with file names
+    files->data[0] = psStringCopy(name);
+    if (psMetadataLookup(config->arguments, file)) {
+        psMetadataRemoveKey(config->arguments, file);
+    }
+    psMetadataAddArray(config->arguments, PS_LIST_TAIL, file, 0, comment, files);
+    psFree(files);
+    return;
+}
+
+
+bool ppBackgroundCamera(ppBackgroundData *data // Run-time data
+    )
+{
+    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;
+    }
+
+    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;
+    }
+
+    fileArguments("IMAGE", data->backgroundName, "Input uncorrected image", data->config);
+    pmFPAfile *image = pmFPAfileBindFromArgs(&status, background, data->config, "PPBACKGROUND.IMAGE",
+                                             "IMAGE"); // File
+    if (!status) {
+        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
+    if (!status) {
+        psError(psErrorCodeLast(), false, "Failed to build file from PPBACKGROUND.MASK");
+        return false;
+    }
+
+    pmFPAfile *output = pmFPAfileDefineOutput(data->config, file->fpa, "PPBACKGROUND.OUTPUT");
+    if (!output) {
+        psError(psErrorCodeLast(), false, "Unable to define output.");
+        return false;
+    }
+    output->save = true;
+
+#if 0
+    // Now the camera has been determined, we can read the recipe
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, data->config->recipes, PPBACKGROUND_RECIPE); // Recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPBACKGROUND_RECIPE);
+        return false;
+    }
+#endif
+
+    return true;
+}
Index: trunk/ppBackground/src/ppBackgroundData.c
===================================================================
--- trunk/ppBackground/src/ppBackgroundData.c	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundData.c	(revision 28276)
@@ -0,0 +1,56 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppBackground.h"
+
+// Destructor
+static void backgroundDataFree(ppBackgroundData *data // Data to free
+    )
+{
+    psFree(data->patternName);
+    psFree(data->backgroundName);
+    psFree(data->imageName);
+    psFree(data->maskName);
+    psFree(data->outRoot);
+    psFree(data->stats);
+    psFree(data->config);
+    return;
+}
+
+
+ppBackgroundData *ppBackgroundDataAlloc(void)
+{
+    ppBackgroundData *data = psAlloc(sizeof(ppBackgroundData)); // Processing data, to return
+    psMemSetDeallocator(data, (psFreeFunc)backgroundDataFree);
+
+    data->patternName = NULL;
+    data->backgroundName = NULL;
+    data->imageName = NULL;
+    data->maskName = NULL;
+    data->outRoot = NULL;
+    data->stats = NULL;
+    data->statsFile = NULL;
+    data->config = NULL;
+
+    return data;
+}
+
+
+ppBackgroundData *ppBackgroundDataInit(int *argc, char **argv)
+{
+    PS_ASSERT_PTR_NON_NULL(argc, NULL);
+    PS_ASSERT_PTR_NON_NULL(argv, NULL);
+
+    ppBackgroundData *data = ppBackgroundDataAlloc(); // Processing data, to return
+    data->config = pmConfigRead(argc, argv, PPBACKGROUND_RECIPE);
+    if (!data->config) {
+        psError(psErrorCodeLast(), false, "Unable to read configuration.");
+        return NULL;
+    }
+    return data;
+}
Index: trunk/ppBackground/src/ppBackgroundErrorCodes.c.in
===================================================================
--- trunk/ppBackground/src/ppBackgroundErrorCodes.c.in	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundErrorCodes.c.in	(revision 28276)
@@ -0,0 +1,25 @@
+#include "pslib.h"
+#include "ppBackgroundErrorCodes.h"
+
+/*
+ * The line
+    { PPBACKGROUND_ERR_$X{ErrorCode}, "$X{ErrorDescription}"},
+ * (without the Xs)
+ * will be replaced by values from errorCodes.dat
+ */
+void ppBackgroundErrorRegister(void)
+{
+    static psErrorDescription errors[] = {
+       { PPBACKGROUND_ERR_BASE, "First value we use" },
+       { PPBACKGROUND_ERR_${ErrorCode}, "${ErrorDescription}"},
+    };
+    static int nerror = PPBACKGROUND_ERR_NERROR - PPBACKGROUND_ERR_BASE; ///< number of values in enum
+
+    for (int i = 0; i < nerror; i++) {
+       psErrorDescription *tmp = psAlloc(sizeof(psErrorDescription));
+       *tmp = errors[i];
+       psErrorRegister(tmp, 1);
+       psFree(tmp);                     /* it's on the internal list */
+    }
+    nerror = 0;                                 // don't register more than once
+}
Index: trunk/ppBackground/src/ppBackgroundErrorCodes.dat
===================================================================
--- trunk/ppBackground/src/ppBackgroundErrorCodes.dat	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundErrorCodes.dat	(revision 28276)
@@ -0,0 +1,11 @@
+#
+# This file is used to generate ppBackgroundErrorClasses.h
+#
+BASE = 17000		First value we use
+UNKNOWN			Unknown ppBackground error code
+NOT_IMPLEMENTED		Desired feature is not yet implemented
+ARGUMENTS		Incorrect arguments
+CONFIG			Problem in configure files
+IO			Problem in FITS I/O
+DATA                    Problem in data values
+PROG			Programming error
Index: trunk/ppBackground/src/ppBackgroundErrorCodes.h.in
===================================================================
--- trunk/ppBackground/src/ppBackgroundErrorCodes.h.in	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundErrorCodes.h.in	(revision 28276)
@@ -0,0 +1,18 @@
+#if !defined(PPBACKGROUND_ERROR_CODES_H)
+#define PPBACKGROUND_ERROR_CODES_H
+/*
+ * The line
+ *  PPBACKGROUND_ERR_$X{ErrorCode},
+ * (without the X)
+ *
+ * will be replaced by values from errorCodes.dat
+ */
+typedef enum {
+    PPBACKGROUND_ERR_BASE = 17000,
+    PPBACKGROUND_ERR_${ErrorCode},
+    PPBACKGROUND_ERR_NERROR
+} ppBackgroundErrorCode;
+
+void ppBackgroundErrorRegister(void);
+
+#endif
Index: trunk/ppBackground/src/ppBackgroundExit.c
===================================================================
--- trunk/ppBackground/src/ppBackgroundExit.c	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundExit.c	(revision 28276)
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <pslib.h>
+
+#include "ppBackground.h"
+
+psExit ppBackgroundExitCode(psExit exitValue)
+{
+    if (exitValue != PS_EXIT_SUCCESS) {
+        return exitValue;
+    }
+
+    psErrorCode errorCode = psErrorCodeLast(); // Error code
+    if (errorCode != PS_ERR_NONE) {
+        pmFPAfileFreeSetStrict(false);
+        psErrorStackPrint(stderr, "Error in subtraction:");
+        switch (errorCode) {
+          case PS_ERR_UNKNOWN:
+            psLogMsg("ppBackground", PS_LOG_WARN, "Unknown error code: %x", errorCode);
+            exitValue = PS_EXIT_UNKNOWN_ERROR;
+            break;
+          case PS_ERR_IO:
+          case PS_ERR_DB_CLIENT:
+          case PS_ERR_DB_SERVER:
+          case PS_ERR_BAD_FITS:
+          case PS_ERR_OS_CALL_FAILED:
+          case PM_ERR_SYS:
+            psLogMsg("ppBackground", PS_LOG_WARN, "I/O error code: %x", errorCode);
+            exitValue = PS_EXIT_SYS_ERROR;
+            break;
+          case PS_ERR_BAD_PARAMETER_VALUE:
+          case PS_ERR_BAD_PARAMETER_TYPE:
+          case PS_ERR_BAD_PARAMETER_NULL:
+          case PS_ERR_BAD_PARAMETER_SIZE:
+          case PPBACKGROUND_ERR_ARGUMENTS:
+          case PPBACKGROUND_ERR_CONFIG:
+            psLogMsg("ppBackground", PS_LOG_WARN, "Configuration error code: %x", errorCode);
+            exitValue = PS_EXIT_CONFIG_ERROR;
+            break;
+          case PPBACKGROUND_ERR_DATA:
+            psLogMsg("ppBackground", PS_LOG_WARN, "Data error code: %x", errorCode);
+            exitValue = PS_EXIT_DATA_ERROR;
+            break;
+          case PS_ERR_UNEXPECTED_NULL:
+          case PS_ERR_PROGRAMMING:
+          case PPBACKGROUND_ERR_PROG:
+            psLogMsg("ppBackground", PS_LOG_WARN, "Programming error code: %x", errorCode);
+            exitValue = PS_EXIT_PROG_ERROR;
+            break;
+          default:
+            // It's a programming error if we're not dealing with the error correctly
+            psLogMsg("ppBackground", PS_LOG_WARN, "Unrecognised error code: %x", errorCode);
+            exitValue = PS_EXIT_PROG_ERROR;
+            break;
+        }
+    }
+
+    return exitValue;
+}
Index: trunk/ppBackground/src/ppBackgroundLoop.c
===================================================================
--- trunk/ppBackground/src/ppBackgroundLoop.c	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundLoop.c	(revision 28276)
@@ -0,0 +1,161 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppBackground.h"
+
+bool ppBackgroundLoop(ppBackgroundData *data // Run-time data
+    )
+{
+    pmConfig *config = data->config;                                        // Configuration data
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPBACKGROUND.BACKGROUND", 0);
+    pmFPAfile *patternFile = pmFPAfileSelectSingle(config->files, "PPBACKGROUND.PATTERN", 0); // File with data
+    pmFPA *patternMosaic = pmFPAConstruct(file->camera, file->cameraName); // Mosaicked FPA for pattern
+
+    psImageMaskType maskBad = pmConfigMaskGet("BLANK", config); // Mask value to set
+
+    pmFPAview *view = pmFPAviewAlloc(0); // Pointer into FPA hierarchy
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+        return NULL;
+    }
+    pmConceptsCopyFPA(patternMosaic, file->fpa, false, false);
+    pmChip *chip;                       // Chip from FPA
+    while ((chip = pmFPAviewNextChip(view, file->fpa, 1))) {
+        if (!chip->process || !chip->file_exists) {
+            continue;
+        }
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+            psError(psErrorCodeLast(), false, "Error loading data from files.");
+            return false;
+        }
+
+        if (chip->cell->n > 1) {
+            psError(PPBACKGROUND_ERR_CONFIG, true,
+                    "Input image and background model should be chip-mosaicked");
+            return false;
+        }
+
+        if (data->patternName) {
+            pmFPAfileActivate(config->files, false, NULL);
+            pmFPAfileActivate(config->files, true, "PPBACKGROUND.PATTERN");
+
+            pmCell *cell;               // Cell with pattern data
+            while ((patternCell = pmFPAviewNextCell(view, patternFile->fpa, 1))) {
+                if (!cell->process || !cell->file_exists) {
+                    continue;
+                }
+                if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                    psError(psErrorCodeLast(), false, "Error loading data from files.");
+                    return false;
+                }
+
+                pmReadout *readout;         // Readout with pattern data
+                while ((readout = pmFPAviewNextReadout(view, patternFile->fpa, 1))) {
+                    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                        psError(psErrorCodeLast(), false, "Error loading data from files.");
+                        return false;
+                    }
+                    if (!readout->data_exists) {
+                        continue;
+                    }
+
+                    int numCols = 0, numRows = 0; // Size of image
+
+                    // 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");
+                    }
+                    // Get size of image from TRIMSEC
+                    if (numCols == 0 || numRows == 0) {
+                        psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC");
+                        numCols = trimsec->x1 - trimsec->x0;
+                        numRows = trimsec->y1 - trimsec->y0;
+                    }
+                    if (numCols <= 0 || numRows <= 0) {
+                        psError(PS_ERR_UNKNOWN, true, "Image size isn't set: %dx%d.", numCols, numRows);
+                        return false;
+                    }
+
+                    readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+                    psImageInit(readout->image, 0.0);
+
+                    if (!pmPatternRowApply(readout, maskBad) || !pmPatternCellApply(readout, maskBad)) {
+                        psError(psErrorCodeLast(), false, "Unable to apply pattern correction.");
+                        return false;
+                    }
+
+                    // Remove bias sections to avoid warnings
+                    psMetadataItem *biassec = psMetadataLookup(patternRO->parent->concepts, "CELL.BIASSEC");
+                    if (psListLength(biassec->data.V)) {
+                        psFree(biassec->data.V);
+                        biassec->data.V = psListAlloc(NULL);
+                    }
+
+                    readout->data_exists = true;
+                    readout->parent->data_exists = true;
+                    readout->parent->parent->data_exists = true;
+
+                    // Readout
+                    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                        psError(psErrorCodeLast(), false, "Error saving data to files.");
+                        return false;
+                    }
+                }
+                // Cell
+                if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                    psError(psErrorCodeLast(), false, "Error saving data to files.");
+                    return false;
+                }
+            }
+
+            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;
+            }
+            pmFPAfileActivate(config->files, true, NULL);
+            pmFPAfileActivate(config->files, false, "PPBACKGROUND.PATTERN");
+        }
+
+
+
+
+
+
+
+                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);
+
+
+
+
+
+
+
+
+        // Chip
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+            psError(psErrorCodeLast(), false, "Error saving data to files.");
+            return false;
+        }
+    }
+    // FPA
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+        psError(psErrorCodeLast(), false, "Error saving data to files.");
+        return false;
+    }
+
+    return true;
+}
Index: trunk/ppBackground/src/ppBackgroundModel.c
===================================================================
--- trunk/ppBackground/src/ppBackgroundModel.c	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundModel.c	(revision 28276)
@@ -0,0 +1,92 @@
+#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: trunk/ppBackground/src/ppBackgroundVersion.c
===================================================================
--- trunk/ppBackground/src/ppBackgroundVersion.c	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundVersion.c	(revision 28276)
@@ -0,0 +1,118 @@
+/** @file ppBackgroundVersion.c
+ *
+ *  @brief
+ *
+ *  @ingroup ppBackground
+ *
+ *  @author IfA
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-06 19:45:30 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppBackground.h"
+#include "ppBackgroundVersionDefinitions.h"
+
+#ifndef PPBACKGROUND_VERSION
+#error "PPBACKGROUND_VERSION is not set"
+#endif
+#ifndef PPBACKGROUND_BRANCH
+#error "PPBACKGROUND_BRANCH is not set"
+#endif
+#ifndef PPBACKGROUND_SOURCE
+#error "PPBACKGROUND_SOURCE is not set"
+#endif
+
+psString ppBackgroundVersion(void)
+{
+    char *value = NULL;
+    psStringAppend(&value, "%s@%s", PPBACKGROUND_BRANCH, PPBACKGROUND_VERSION);
+    return value;
+}
+
+psString ppBackgroundSource(void)
+{
+    return psStringCopy(PPBACKGROUND_SOURCE);
+}
+
+psString ppBackgroundVersionLong(void)
+{
+    psString version = ppBackgroundVersion();  // Version, to return
+    psString source = ppBackgroundSource();    // Source
+
+    psStringPrepend(&version, "ppBackground ");
+    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 ppBackgroundVersionHeader(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, "ppBackground at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+
+    psString version = ppBackgroundVersion(); // Software version
+    psString source  = ppBackgroundSource();  // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "VIZPAT_V", PS_META_REPLACE, NULL, PPBACKGROUND_VERSION);
+    
+    psStringPrepend(&version, "ppBackground version: ");
+    psStringPrepend(&version, "ppBackground source: ");
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
+
+void ppBackgroundVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("ppBackground", PS_LOG_INFO, "ppBackground at %s", timeString);
+    psFree(timeString);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString ppBackground = ppBackgroundVersionLong(); // ppBackground version
+
+    psLogMsg("ppBackground", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("ppBackground", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("ppBackground", PS_LOG_INFO, "%s", ppBackground);
+
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(ppBackground);
+
+    return;
+}
Index: trunk/ppBackground/src/ppBackgroundVersionDefinitions.h.in
===================================================================
--- trunk/ppBackground/src/ppBackgroundVersionDefinitions.h.in	(revision 28276)
+++ trunk/ppBackground/src/ppBackgroundVersionDefinitions.h.in	(revision 28276)
@@ -0,0 +1,8 @@
+#ifndef PPVIZPATTERN_VERSION_DEFINITIONS_H
+#define PPVIZPATTERN_VERSION_DEFINITIONS_H
+
+#define PPVIZPATTERN_VERSION @PPVIZPATTERN_VERSION@ // SVN version
+#define PPVIZPATTERN_BRANCH  @PPVIZPATTERN_BRANCH@  // SVN branch
+#define PPVIZPATTERN_SOURCE  @PPVIZPATTERN_SOURCE@  // SVN source
+
+#endif
