Index: /trunk/dvoTools/Makefile.am
===================================================================
--- /trunk/dvoTools/Makefile.am	(revision 11804)
+++ /trunk/dvoTools/Makefile.am	(revision 11804)
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES = *~ core core.*
Index: /trunk/dvoTools/autogen.sh
===================================================================
--- /trunk/dvoTools/autogen.sh	(revision 11804)
+++ /trunk/dvoTools/autogen.sh	(revision 11804)
@@ -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=ppImage
+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/dvoTools/configure.ac
===================================================================
--- /trunk/dvoTools/configure.ac	(revision 11804)
+++ /trunk/dvoTools/configure.ac	(revision 11804)
@@ -0,0 +1,29 @@
+AC_PREREQ(2.59)
+
+AC_INIT([dvoTools], [1.0.0], [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
+AC_PROG_INSTALL
+dnl AC_PROG_LIBTOOL
+AC_SYS_LARGEFILE
+
+PKG_CHECK_MODULES([PSLIB], [pslib >= 1.0.0])
+PKG_CHECK_MODULES([PSMODULE], [psmodules >= 1.0.0])
+
+IPP_STDOPTS
+CFLAGS="${CFLAGS=} -Wall -Werror -std=c99"
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+])
+AC_OUTPUT
Index: /trunk/dvoTools/src/Makefile.am
===================================================================
--- /trunk/dvoTools/src/Makefile.am	(revision 11804)
+++ /trunk/dvoTools/src/Makefile.am	(revision 11804)
@@ -0,0 +1,37 @@
+bin_PROGRAMS = dvoMakeCorr dvoApplyCorr
+
+noinst_HEADERS = \
+	dvoMakeCorr.h \
+	dvoApplyCorr.h
+
+dvoMakeCorr_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(dvoCorr_CFLAGS)
+dvoMakeCorr_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS)
+dvoMakeCorr_SOURCES = \
+	dvoMakeCorr.c \
+	dvoMakeCorrArguments.c \
+	dvoMakeCorrParseCamera.c \
+	dvoMakeCorrLoop.c \
+	dvoMakeCorrUnbin.c \
+	dvoMakeCorrCleanup.c \
+	dvoMakeCorrOptions.c \
+	dvoMakeCorrVersion.c
+
+dvoApplyCorr_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(dvoCorr_CFLAGS)
+dvoApplyCorr_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS)
+dvoApplyCorr_SOURCES = \
+	dvoApplyCorr.c \
+	dvoApplyCorrArguments.c \
+	dvoApplyCorrParseCamera.c \
+	dvoApplyCorrLoop.c \
+	dvoApplyCorrCleanup.c \
+	dvoApplyCorrOptions.c \
+	dvoApplyCorrVersion.c
+
+CLEANFILES = *~
+
+clean-local:
+	-rm -f TAGS
+
+# Tags for emacs
+tags:
+	etags `find . -name \*.[ch] -print`
Index: /trunk/dvoTools/src/dvoApplyCorr.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorr.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoApplyCorr.c	(revision 11804)
@@ -0,0 +1,43 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoApplyCorr.h"
+
+int main(int argc, char **argv) {
+
+    psLibInit(NULL);
+
+    psTimerStart(TIMERNAME);
+
+    // USAGE: dvoApplyCorr -file INPUT OUTPUT
+
+    // Parse the configuration and arguments
+    pmConfig *config = dvoApplyCorrArguments (argc, argv);
+    if (config == NULL) {
+        psErrorStackPrint(stderr, "Unable to parse command-line arguments.");
+        exit(PS_EXIT_CONFIG_ERROR);
+    }
+
+    // define recipe options
+    // define the active I/O files
+    dvoApplyCorrOptions *options = dvoApplyCorrParseCamera(config);
+    if (options == NULL) {
+        psErrorStackPrint(stderr, "Unable to parse camera.");
+        exit(PS_EXIT_CONFIG_ERROR);
+    }
+
+    // Image Loop
+    if (!dvoApplyCorrLoop(config, options)) {
+        psErrorStackPrint(stderr, "Unable to loop over input");
+        exit(PS_EXIT_SYS_ERROR);
+    }
+
+    psLogMsg ("ppImage", 3, "Complete ppImage run: %f sec\n", psTimerMark(TIMERNAME));
+
+    // Cleaning up
+    dvoApplyCorrCleanup(config, options);
+
+    return PS_EXIT_SUCCESS;
+}
+
Index: /trunk/dvoTools/src/dvoApplyCorr.h
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorr.h	(revision 11804)
+++ /trunk/dvoTools/src/dvoApplyCorr.h	(revision 11804)
@@ -0,0 +1,46 @@
+#ifndef DVO_MAKE_CORR_H
+#define DVO_MAKE_CORR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include "pslib.h"
+#include "psmodules.h"
+
+#define RECIPE_NAME "DVOCORR"		// Name of the recipe to use
+#define TIMERNAME "dvoApplyCorr"		// Name of timer
+
+// Options for dvoApplyCorr
+typedef struct {
+    int test;
+} dvoApplyCorrOptions;
+
+dvoApplyCorrOptions *dvoApplyCorrOptionsAlloc(void);
+
+dvoApplyCorrOptions *dvoApplyCorrOptionsParse(pmConfig *config);
+
+// Get the configuration
+pmConfig *dvoApplyCorrArguments(int argc, char **argv);
+
+// Determine what type of camera, and initialise
+dvoApplyCorrOptions *dvoApplyCorrParseCamera(pmConfig *config);
+
+// Loop over the input
+bool dvoApplyCorrLoop(pmConfig *config, dvoApplyCorrOptions *options);
+
+// free memory, check for leaks
+void dvoApplyCorrCleanup (pmConfig *config, dvoApplyCorrOptions *options);
+
+/// Return short version information
+psString dvoApplyCorrVersion(void);
+
+/// Return long version information
+psString dvoApplyCorrVersionLong(void);
+
+/// Update the metadata with version information for all dependencies
+void dvoApplyCorrVersionMetadata(psMetadata *metadata ///< Metadata to update with version information
+    );
+
+#endif
Index: /trunk/dvoTools/src/dvoApplyCorrArguments.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrArguments.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoApplyCorrArguments.c	(revision 11804)
@@ -0,0 +1,64 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoApplyCorr.h"
+
+static void usage (void) {
+    fprintf(stderr, "USAGE: dvoApplyCorr MOSAIC.fits OUTPUT\n\n");
+    exit (2);
+}
+
+pmConfig *dvoApplyCorrArguments(int argc, char **argv)
+{
+    int argnum;
+
+    if (argc == 1) {
+        usage();
+    }
+
+    if (psArgumentGet (argc, argv, "-version")) {
+	psString version;
+	version = dvoApplyCorrVersionLong(); fprintf (stdout, "%s\n", version); psFree (version);
+	version = psModulesVersionLong();   fprintf (stdout, "%s\n", version); psFree (version);
+	version = psLibVersionLong();       fprintf (stdout, "%s\n", version); psFree (version);
+	exit (0);
+    }
+
+    // load the site-wide configuration information
+    pmConfig *config = pmConfigRead(&argc, argv, RECIPE_NAME);
+    if (config == NULL) {
+        psErrorStackPrint(stderr, "Can't find site configuration!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // save the following additional recipe values based on command-line options
+    // these options override the DVOCORR recipe values loaded from recipe files
+    psMetadata *options = pmConfigRecipeOptions (config, RECIPE_NAME);
+
+    // XXX add options from command-line here
+
+    // drop the local view on the options (saved on config->arguments)
+    psFree (options);
+
+    // chip selection is used to limit chips to be processed
+    if ((argnum = psArgumentGet (argc, argv, "-chip"))) {
+        psArgumentRemove (argnum, &argc, argv);
+        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_DATA_STRING, "",
+                          argv[argnum]);
+        psArgumentRemove (argnum, &argc, argv);
+    }
+
+    if (argc != 2) usage ();
+
+    // the input file is a required argument; if not found, we will exit
+    bool status = pmConfigFileSetsMD (config->arguments, config, "INPUT", "-file", "-list");
+    if (!status) {
+        usage ();
+    }
+
+    // Add the output image (which remain on the command-line) to the arguments list
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Name of the output image", argv[1]);
+
+    return config;
+}
Index: /trunk/dvoTools/src/dvoApplyCorrCleanup.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrCleanup.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoApplyCorrCleanup.c	(revision 11804)
@@ -0,0 +1,22 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+# include "dvoApplyCorr.h"
+
+void dvoApplyCorrCleanup (pmConfig *config, dvoApplyCorrOptions *options)
+{
+    // Free memory used by dvoApplyCorrCleanup
+    psFree(options);
+    psFree(config);
+
+    // Free memory used by psModules
+    pmConceptsDone();
+    pmConfigDone();
+
+    // Free memory used by psLib
+    psLibFinalize();
+    fprintf (stderr, "Found %d leaks at %s\n", psMemCheckLeaks (0, NULL, stderr, false), "dvoApplyCorrCleanup");
+
+    return;
+}
Index: /trunk/dvoTools/src/dvoApplyCorrLoop.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrLoop.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoApplyCorrLoop.c	(revision 11804)
@@ -0,0 +1,86 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoApplyCorr.h"
+
+bool dvoApplyCorrLoop (pmConfig *config, dvoApplyCorrOptions *options) {
+
+    bool status;
+    pmChip *chip;
+    pmCell *cell;
+    pmReadout *readout;
+
+    // psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, RECIPE_NAME);
+
+    pmFPAfile *input = psMetadataLookupPtr(&status, config->files, "DVOCORR.INPUT");
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find input data!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    pmFPAview *view = pmFPAviewAlloc(0);// View for level of interest
+
+    // load data at FPA leve
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+	psError(PS_ERR_UNKNOWN, false, "failed IO for fpa in psphot\n");
+	psFree(view);
+        return false;
+    }
+
+    // process each chip in the FPA
+    while ((chip = pmFPAviewNextChip(view, input->fpa, 1)) != NULL) {
+        psLogMsg ("dvoApplyCorrLoop", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) continue;
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
+            psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d in psphot\n", view->chip);
+	    psFree (view);
+	    return false;
+	}
+
+	// process each cell in the Chip
+        while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
+            psLogMsg ("dvoApplyCorrLoop", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) continue;
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE))
+		psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d in psphot\n", view->chip, view->cell);
+	    psFree (view);
+	    return false;
+	}
+
+	// process each of the readouts
+	while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
+	    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+		psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d, readout %d in psphot\n", view->chip, view->cell, view->readout);
+		psFree (view);
+		return false;
+	    }
+	    if (!readout->data_exists) continue;
+
+	    // XXX put the function here which unbins the input image
+
+	    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+		psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d, readout %d in psphot\n", view->chip, view->cell, view->readout);
+		psFree (view);
+		return false;
+	    }
+	}
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+	    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d in psphot\n", view->chip, view->cell);
+	    psFree (view);
+	    return false;
+	}
+    }
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+	psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d in psphot\n", view->chip);
+	psFree (view);
+	return false;
+    }
+
+    psFree (view);
+
+    // fail if we failed to handle an error
+    if (psErrorCodeLast() != PS_ERR_NONE) return false;
+
+    return true;
+}
Index: /trunk/dvoTools/src/dvoApplyCorrOptions.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrOptions.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoApplyCorrOptions.c	(revision 11804)
@@ -0,0 +1,28 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoApplyCorr.h"
+
+static void dvoApplyCorrOptionsFree(dvoApplyCorrOptions *options)
+{
+    if (options == NULL) return;
+
+    return;
+}
+
+dvoApplyCorrOptions *dvoApplyCorrOptionsAlloc(void)
+{
+    dvoApplyCorrOptions *options = psAlloc(sizeof(dvoApplyCorrOptions));
+    psMemSetDeallocator(options, (psFreeFunc)dvoApplyCorrOptionsFree);
+
+    // Initialise options
+    options->test = 0;
+    return options;
+}
+
+dvoApplyCorrOptions *dvoApplyCorrOptionsParse(pmConfig *config)
+{
+    dvoApplyCorrOptions *options = dvoApplyCorrOptionsAlloc ();
+    return options;
+}
Index: /trunk/dvoTools/src/dvoApplyCorrParseCamera.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrParseCamera.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoApplyCorrParseCamera.c	(revision 11804)
@@ -0,0 +1,49 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+# include "dvoApplyCorr.h"
+
+dvoApplyCorrOptions *dvoApplyCorrParseCamera (pmConfig *config) {
+
+    bool status = false;
+
+    // the input image defines the camera, and all recipes and options the follow
+    // XXX we need to change this: mosaic.fits is not in pmFPA format??
+    // - determine the camera from the header keywords
+    pmFPAfile *input = pmFPAfileDefineFromArgs (&status, config, "DVOCORR.INPUT", "INPUT");
+    if (!status || !input) {
+        psError(PS_ERR_IO, false, "Failed to build FPA from DVOCORR.INPUT");
+        return NULL;
+    }
+
+    // add recipe options supplied on command line
+    // psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, RECIPE_NAME);
+
+    // parse the options from the metadata format to the dvoApplyCorrOptions structure
+    dvoApplyCorrOptions *options = dvoApplyCorrOptionsParse (config);
+
+    // the following files are output targets
+    pmFPAfile *output = pmFPAfileDefineOutput(config, input->fpa, "DVOCORR.OUTPUT");
+    if (!output) {
+        psError(PS_ERR_IO, false, _("Unable to generate output file from DVOCORR.OUTPUT"));
+        psFree(options);
+        return NULL;
+    }
+
+    // Chip selection: turn on only the chips specified (pass status to suppress missing-key log msg)
+    char *chipLine = psMetadataLookupStr(&status, config->arguments, "CHIP_SELECTIONS");
+    psArray *chips = psStringSplitArray (chipLine, ",", false);
+    if (chips->n > 0) {
+        pmFPASelectChip (output->fpa, -1, true); // deselect all chips
+        for (int i = 0; i < chips->n; i++) {
+            int chipNum = atoi(chips->data[i]);
+            if (! pmFPASelectChip(output->fpa, chipNum, false)) {
+                psError(PS_ERR_IO, false, "Chip number %d doesn't exist in camera.\n", chipNum);
+                return false;
+            }
+        }
+    }
+    psFree (chips);
+    return (options);
+}
Index: /trunk/dvoTools/src/dvoApplyCorrVersion.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrVersion.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoApplyCorrVersion.c	(revision 11804)
@@ -0,0 +1,52 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoApplyCorr.h"
+
+static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
+
+psString dvoApplyCorrVersion(void)
+{
+    psString version = NULL;            // Version, to return
+    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
+    return version;
+}
+
+psString dvoApplyCorrVersionLong(void)
+{
+    psString version = dvoApplyCorrVersion(); // Version, to return
+    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
+    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
+    psFree(tag);
+    return version;
+}
+
+
+void dvoApplyCorrVersionMetadata(psMetadata *metadata)
+{
+    PS_ASSERT_METADATA_NON_NULL(metadata,);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString dvoApplyCorr = dvoApplyCorrVersionLong(); // dvoApplyCorr version
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString head = NULL;               // Head string
+    psStringAppend(&head, "dvoApplyCorr processing at %s. Component information:", timeString);
+    psFree(timeString);
+
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, head, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, pslib, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, psmodules, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, dvoApplyCorr, "");
+
+    psFree(head);
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(dvoApplyCorr);
+
+    return;
+}
Index: /trunk/dvoTools/src/dvoMakeCorr.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorr.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoMakeCorr.c	(revision 11804)
@@ -0,0 +1,43 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoMakeCorr.h"
+
+int main(int argc, char **argv) {
+
+    psLibInit(NULL);
+
+    psTimerStart(TIMERNAME);
+
+    // USAGE: dvoMakeCorr (mosaic.fits) (output)
+
+    // Parse the configuration and arguments
+    pmConfig *config = dvoMakeCorrArguments (argc, argv);
+    if (config == NULL) {
+        psErrorStackPrint(stderr, "Unable to parse command-line arguments.\n");
+        exit(PS_EXIT_CONFIG_ERROR);
+    }
+
+    // define recipe options
+    // define the active I/O files
+    dvoMakeCorrOptions *options = dvoMakeCorrParseCamera(config);
+    if (options == NULL) {
+        psErrorStackPrint(stderr, "Unable to parse camera.\n");
+        exit(PS_EXIT_CONFIG_ERROR);
+    }
+
+    // Image Loop
+    if (!dvoMakeCorrLoop(config, options)) {
+        psErrorStackPrint(stderr, "Unable to loop over input\n");
+        exit(PS_EXIT_SYS_ERROR);
+    }
+
+    psLogMsg ("ppImage", 3, "Complete dvoMakeCorr run: %f sec\n", psTimerMark(TIMERNAME));
+
+    // Cleaning up
+    dvoMakeCorrCleanup(config, options);
+
+    return PS_EXIT_SUCCESS;
+}
+
Index: /trunk/dvoTools/src/dvoMakeCorr.h
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorr.h	(revision 11804)
+++ /trunk/dvoTools/src/dvoMakeCorr.h	(revision 11804)
@@ -0,0 +1,49 @@
+#ifndef DVO_MAKE_CORR_H
+#define DVO_MAKE_CORR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include "pslib.h"
+#include "psmodules.h"
+
+#define RECIPE_NAME "DVOCORR"		// Name of the recipe to use
+#define TIMERNAME "dvoMakeCorr"		// Name of timer
+
+// Options for dvoMakeCorr
+typedef struct {
+    int test;
+} dvoMakeCorrOptions;
+
+dvoMakeCorrOptions *dvoMakeCorrOptionsAlloc(void);
+
+dvoMakeCorrOptions *dvoMakeCorrOptionsParse(pmConfig *config);
+
+// Get the configuration
+pmConfig *dvoMakeCorrArguments(int argc, char **argv);
+
+// Determine what type of camera, and initialise
+dvoMakeCorrOptions *dvoMakeCorrParseCamera(pmConfig *config);
+
+// Loop over the input
+bool dvoMakeCorrLoop(pmConfig *config, dvoMakeCorrOptions *options);
+
+// convert low-res image to hi-res image
+bool dvoMakeCorrUnbin (pmConfig *config, pmFPAview *view, char *outName, char *inName, char *refName);
+
+// free memory, check for leaks
+void dvoMakeCorrCleanup (pmConfig *config, dvoMakeCorrOptions *options);
+
+/// Return short version information
+psString dvoMakeCorrVersion(void);
+
+/// Return long version information
+psString dvoMakeCorrVersionLong(void);
+
+/// Update the metadata with version information for all dependencies
+void dvoMakeCorrVersionMetadata(psMetadata *metadata ///< Metadata to update with version information
+    );
+
+#endif
Index: /trunk/dvoTools/src/dvoMakeCorrArguments.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrArguments.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoMakeCorrArguments.c	(revision 11804)
@@ -0,0 +1,68 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoMakeCorr.h"
+
+static void usage (void) {
+    fprintf(stderr, "USAGE: dvoMakeCorr -file MOSAIC.fits -ref REF.fits OUTPUT\n\n");
+    exit (2);
+}
+
+pmConfig *dvoMakeCorrArguments(int argc, char **argv)
+{
+    int argnum;
+
+    if (argc == 1) {
+        usage();
+    }
+
+    if (psArgumentGet (argc, argv, "-version")) {
+	psString version;
+	version = dvoMakeCorrVersionLong(); fprintf (stdout, "%s\n", version); psFree (version);
+	version = psModulesVersionLong();   fprintf (stdout, "%s\n", version); psFree (version);
+	version = psLibVersionLong();       fprintf (stdout, "%s\n", version); psFree (version);
+	exit (0);
+    }
+
+    // load the site-wide configuration information
+    pmConfig *config = pmConfigRead(&argc, argv, RECIPE_NAME);
+    if (config == NULL) {
+        psErrorStackPrint(stderr, "Can't find site configuration!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // save the following additional recipe values based on command-line options
+    // these options override the DVOCORR recipe values loaded from recipe files
+    psMetadata *options = pmConfigRecipeOptions (config, RECIPE_NAME);
+
+    // XXX add options from command-line here
+
+    // drop the local view on the options (saved on config->arguments)
+    psFree (options);
+
+    // the input file is a required argument; if not found, we will exit
+    if (!pmConfigFileSetsMD (config->arguments, config, "INPUT", "-file", "-list")) {
+        usage ();
+    }
+
+    // the input file is a required argument; if not found, we will exit
+    if (!pmConfigFileSetsMD (config->arguments, config, "REFHEAD", "-ref", "-reflist")) {
+        usage ();
+    }
+
+    // chip selection is used to limit chips to be processed
+    if ((argnum = psArgumentGet (argc, argv, "-chip"))) {
+        psArgumentRemove (argnum, &argc, argv);
+        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_DATA_STRING, "",
+                          argv[argnum]);
+        psArgumentRemove (argnum, &argc, argv);
+    }
+
+    if (argc != 2) usage ();
+
+    // Add the output image (which remain on the command-line) to the arguments list
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Name of the output image", argv[1]);
+
+    return config;
+}
Index: /trunk/dvoTools/src/dvoMakeCorrCleanup.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrCleanup.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoMakeCorrCleanup.c	(revision 11804)
@@ -0,0 +1,22 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+# include "dvoMakeCorr.h"
+
+void dvoMakeCorrCleanup (pmConfig *config, dvoMakeCorrOptions *options)
+{
+    // Free memory used by dvoMakeCorrCleanup
+    psFree(options);
+    psFree(config);
+
+    // Free memory used by psModules
+    pmConceptsDone();
+    pmConfigDone();
+
+    // Free memory used by psLib
+    psLibFinalize();
+    fprintf (stderr, "Found %d leaks at %s\n", psMemCheckLeaks (0, NULL, stderr, false), "dvoMakeCorrCleanup");
+
+    return;
+}
Index: /trunk/dvoTools/src/dvoMakeCorrLoop.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrLoop.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoMakeCorrLoop.c	(revision 11804)
@@ -0,0 +1,93 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoMakeCorr.h"
+
+bool dvoMakeCorrLoop (pmConfig *config, dvoMakeCorrOptions *options) {
+
+    bool status;
+    pmChip *chip;
+    pmCell *cell;
+    pmReadout *readout;
+
+    // psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, RECIPE_NAME);
+
+    pmFPAfile *input = psMetadataLookupPtr(&status, config->files, "DVOCORR.INPUT");
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find input data!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    pmFPAview *view = pmFPAviewAlloc(0);// View for level of interest
+
+    // load data at FPA leve
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+	psError(PS_ERR_UNKNOWN, false, "failed IO for fpa in psphot\n");
+	psFree(view);
+        return false;
+    }
+
+    // process each chip in the FPA
+    while ((chip = pmFPAviewNextChip(view, input->fpa, 1)) != NULL) {
+        psLogMsg ("dvoMakeCorrLoop", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) continue;
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
+            psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d in dvoMakeCorr\n", view->chip);
+	    psFree (view);
+	    return false;
+	}
+
+	// process each cell in the Chip
+        while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
+            psLogMsg ("dvoMakeCorrLoop", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) continue;
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+		psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d in dvoMakeCorr\n", view->chip, view->cell);
+		psFree (view);
+		return false;
+	    }
+
+	    // process each of the readouts
+	    while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
+		if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+		    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d, readout %d in dvoMakeCorr\n", view->chip, view->cell, view->readout);
+		    psFree (view);
+		    return false;
+		}
+		if (!readout->data_exists) continue;
+
+		// XXX put the function here which unbins the input image
+		dvoMakeCorrUnbin (config, view, "DVOCORR.OUTPUT", "DVOCORR.INPUT", "DVOCORR.REFHEAD");
+
+		if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+		    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d, readout %d in dvoMakeCorr\n", view->chip, view->cell, view->readout);
+		    psFree (view);
+		    return false;
+		}
+	    }
+	    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+		psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d in dvoMakeCorr\n", view->chip, view->cell);
+		psFree (view);
+		return false;
+	    }
+	}
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+	    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d in dvoMakeCorr\n", view->chip);
+	    psFree (view);
+	    return false;
+	}
+    }
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
+	psError(PS_ERR_UNKNOWN, false, "failed IO for fpa in dvoMakeCorr\n");
+	psFree (view);
+	return false;
+    }
+
+    psFree (view);
+
+    // fail if we failed to handle an error
+    if (psErrorCodeLast() != PS_ERR_NONE) return false;
+
+    return true;
+}
Index: /trunk/dvoTools/src/dvoMakeCorrOptions.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrOptions.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoMakeCorrOptions.c	(revision 11804)
@@ -0,0 +1,28 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoMakeCorr.h"
+
+static void dvoMakeCorrOptionsFree(dvoMakeCorrOptions *options)
+{
+    if (options == NULL) return;
+
+    return;
+}
+
+dvoMakeCorrOptions *dvoMakeCorrOptionsAlloc(void)
+{
+    dvoMakeCorrOptions *options = psAlloc(sizeof(dvoMakeCorrOptions));
+    psMemSetDeallocator(options, (psFreeFunc)dvoMakeCorrOptionsFree);
+
+    // Initialise options
+    options->test = 0;
+    return options;
+}
+
+dvoMakeCorrOptions *dvoMakeCorrOptionsParse(pmConfig *config)
+{
+    dvoMakeCorrOptions *options = dvoMakeCorrOptionsAlloc ();
+    return options;
+}
Index: /trunk/dvoTools/src/dvoMakeCorrParseCamera.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrParseCamera.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoMakeCorrParseCamera.c	(revision 11804)
@@ -0,0 +1,54 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+# include "dvoMakeCorr.h"
+
+dvoMakeCorrOptions *dvoMakeCorrParseCamera (pmConfig *config) {
+
+    // the input image defines the camera, and all recipes and options the follow
+    pmFPAfile *input = pmFPAfileDefineFromArgs (NULL, config, "DVOCORR.INPUT", "INPUT");
+    if (!input) {
+        psError(PS_ERR_IO, false, "Failed to build FPA from DVOCORR.INPUT");
+        return NULL;
+    }
+
+    // the input image defines the camera, and all recipes and options the follow
+    pmFPAfile *refhead = pmFPAfileDefineFromArgs (NULL, config, "DVOCORR.REFHEAD", "REFHEAD");
+    if (!refhead) {
+        psError(PS_ERR_IO, false, "Failed to build FPA from DVOCORR.REFHEAD");
+        return NULL;
+    }
+
+    // add recipe options supplied on command line
+    // psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, RECIPE_NAME);
+
+    // parse the options from the metadata format to the dvoMakeCorrOptions structure
+    dvoMakeCorrOptions *options = dvoMakeCorrOptionsParse (config);
+
+    // the following files are output targets
+    // XXX get the binning from where?
+    pmFPAfile *output = pmFPAfileDefineFromFPA(config, input->fpa, 1, 1, "DVOCORR.OUTPUT");
+    if (!output) {
+        psError(PS_ERR_IO, false, _("Unable to generate output file from DVOCORR.OUTPUT"));
+        psFree(options);
+        return NULL;
+    }
+
+    // Chip selection: turn on only the chips specified (pass status to suppress missing-key log msg)
+    bool status = false;
+    char *chipLine = psMetadataLookupStr(&status, config->arguments, "CHIP_SELECTIONS");
+    psArray *chips = psStringSplitArray (chipLine, ",", false);
+    if (chips->n > 0) {
+        pmFPASelectChip (input->fpa, -1, true); // deselect all chips
+        for (int i = 0; i < chips->n; i++) {
+            int chipNum = atoi(chips->data[i]);
+            if (! pmFPASelectChip(input->fpa, chipNum, false)) {
+                psError(PS_ERR_IO, false, "Chip number %d doesn't exist in camera.\n", chipNum);
+                return false;
+            }
+        }
+    }
+    psFree (chips);
+    return (options);
+}
Index: /trunk/dvoTools/src/dvoMakeCorrUnbin.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrUnbin.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoMakeCorrUnbin.c	(revision 11804)
@@ -0,0 +1,77 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoMakeCorr.h"
+
+bool dvoMakeCorrUnbin (pmConfig *config, pmFPAview *view, char *outName, char *inName, char *refName) {
+    
+    bool status;
+
+    pmFPAfile *inFile = psMetadataLookupPtr (&status, config->files, inName);
+    pmFPAfile *refFile = psMetadataLookupPtr (&status, config->files, refName);
+    pmFPAfile *outFile = psMetadataLookupPtr (&status, config->files, outName);
+    assert (inFile);
+    assert (refFile);
+    assert (outFile);
+
+    pmCell *refCell = pmFPAviewThisCell (view, refFile->fpa);
+    assert (refCell);
+
+    pmReadout *inData = pmFPAviewThisReadout (view, inFile->fpa);
+    assert (inData);
+
+    // determine the output array size based on the reference TRIMSEC values
+    psRegion *trimsec = psMetadataLookupPtr(NULL, refCell->concepts, "CELL.TRIMSEC");
+    assert (trimsec);
+
+    // dimensions of input image:
+    int nx = inData->image->numCols;
+    int ny = inData->image->numRows;
+
+    // dimensions of output image:
+    int Nx = trimsec->x1 - trimsec->x0;
+    int Ny = trimsec->y1 - trimsec->y0;
+
+    // choose the binning factor which would yield nx,ny pixels from Nx,Ny
+    int DX = Nx / nx;			// 36 / 3 = 12, 35 / 3 = 11, 34 / 3 = 11
+    if (Nx % nx) DX ++;			// 36, 35, 34 -> DX = 12
+    int xOffset = (Nx % nx) / 2;	// for nx = 3, xOffset = 0 or 1
+    
+    int DY = Ny / ny;
+    if (Ny % ny) DY ++;
+    int yOffset = (Ny % ny) / 2;
+
+    pmReadout *outData = pmFPAviewThisReadout (view, outFile->fpa);
+    if (outData == NULL) {
+	pmChip *inChip = pmFPAviewThisChip (view, inFile->fpa);
+	pmChip *outChip = pmFPAviewThisChip (view, outFile->fpa);
+
+	pmChipCopyStructure (outChip, inChip, DX, DY);
+	outData = pmFPAviewThisReadout (view, outFile->fpa);
+	assert (outData != NULL);
+    }
+
+    psImageRecycle (outData->image, Nx, Ny, PS_TYPE_F32);
+
+    // linear interpolation to full-scale
+    if (!psImageUnbin (outData->image, inData->image, DX, DY, xOffset, yOffset)) {
+	psError (PS_ERR_UNKNOWN, true, "failed to unbin image");
+	return false;
+    }
+
+    // the input image is in magnitudes.  convert here to a multiplicative factor...
+    for (int j = 0; j < outData->image->numRows; j++) {
+	for (int i = 0; i < outData->image->numCols; i++) {
+	    value = outData->image[j][i]; 
+	    outData->image[j][i] = pow(10.0, -0.4*value);
+	}
+    }
+
+    // psFits *fits = psFitsOpen ("tmp.fits", "w");
+    // psFitsWriteImage (fits, NULL, outData->image, 0, NULL);
+    // psFitsClose (fits);
+    // exit (0);
+
+    return true;
+}
Index: /trunk/dvoTools/src/dvoMakeCorrVersion.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrVersion.c	(revision 11804)
+++ /trunk/dvoTools/src/dvoMakeCorrVersion.c	(revision 11804)
@@ -0,0 +1,52 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dvoMakeCorr.h"
+
+static const char *cvsTag = "$Name: not supported by cvs2svn $";// CVS tag name
+
+psString dvoMakeCorrVersion(void)
+{
+    psString version = NULL;            // Version, to return
+    psStringAppend(&version, "%s-%s",PACKAGE_NAME,PACKAGE_VERSION);
+    return version;
+}
+
+psString dvoMakeCorrVersionLong(void)
+{
+    psString version = dvoMakeCorrVersion(); // Version, to return
+    psString tag = psStringStripCVS(cvsTag, "Name"); // CVS tag
+    psStringAppend(&version, " (cvs tag %s) %s, %s", tag, __DATE__, __TIME__);
+    psFree(tag);
+    return version;
+}
+
+
+void dvoMakeCorrVersionMetadata(psMetadata *metadata)
+{
+    PS_ASSERT_METADATA_NON_NULL(metadata,);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString dvoMakeCorr = dvoMakeCorrVersionLong(); // dvoMakeCorr version
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString head = NULL;               // Head string
+    psStringAppend(&head, "dvoMakeCorr processing at %s. Component information:", timeString);
+    psFree(timeString);
+
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, head, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, pslib, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, psmodules, "");
+    psMetadataAddStr(metadata, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, dvoMakeCorr, "");
+
+    psFree(head);
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(dvoMakeCorr);
+
+    return;
+}
