Index: /trunk/ppImage/src/Makefile.am
===================================================================
--- /trunk/ppImage/src/Makefile.am	(revision 6565)
+++ /trunk/ppImage/src/Makefile.am	(revision 6566)
@@ -1,12 +1,14 @@
-bin_PROGRAMS = ppImage
+bin_PROGRAMS = ppImage ppTest
+
+noinst_HEADERS = \
+	ppImage.h \
+	ppImageData.h \
+	ppImageDetrend.h \
+	ppImageOptions.h
 
 ppImage_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(ppImage_CFLAGS)
-ppImage_LDADD = $(PSLIB_LIBS) $(PSMODULE_LIBS)
+ppImage_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS)
 ppImage_SOURCES = \
-	ppConfig.c \
-	ppFile.c \
-	ppMem.c \
 	ppImage.c \
-	ppImageConfig.c \
 	ppImageData.c \
 	ppImageDetrendBias.c \
@@ -26,13 +28,9 @@
 #	ppImagePhot.c
 
+ppTest_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(ppImage_CFLAGS)
+ppTest_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS)
+ppTest_SOURCES = ppTest.c
 
-noinst_HEADERS = \
-	ppConfig.h \
-	ppFile.h \
-	ppMem.h \
-	ppImage.h \
-	ppImageData.h \
-	ppImageDetrend.h \
-	ppImageOptions.h
+
 
 clean-local:
Index: /trunk/ppImage/src/ppTest.c
===================================================================
--- /trunk/ppImage/src/ppTest.c	(revision 6566)
+++ /trunk/ppImage/src/ppTest.c	(revision 6566)
@@ -0,0 +1,99 @@
+#include <stdio.h>
+
+#include "pslib.h"
+#include "psmodules.h"
+
+#define RECIPE "PHASE2"
+
+int main(int argc, char *argv[])
+{
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// ppImageConfig.c
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    pmConfig *config = pmConfigRead(&argc, argv, RECIPE);
+    if (! config) {
+        psErrorStackPrint(stderr, "Can't find site configuration!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // Parse other command-line arguments
+    config->arguments = psMetadataAlloc(); // The arguments, with default values
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-key", 0, "exposure ID", "");
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-bias", 0, "Name of the bias image", "");
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-dark", 0, "Name of the dark image", "");
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-flat", 0, "Name of the flat-field image", "");
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-mask", 0, "Name of the mask image", "");
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-fringe", 0, "Name of the fringe image", "");
+    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "-chip", 0, "Chip number to process (if positive)", -1);
+
+    if (! psArgumentParse(config->arguments, &argc, argv) || argc != 3) {
+        printf("\nPan-STARRS Phase 2 processing\n\n");
+        printf("Usage: %s INPUT.fits OUTPUT.fits\n\n", argv[0]);
+        psArgumentHelp(config->arguments);
+        psFree(config->arguments);
+        exit(EXIT_FAILURE);
+    }
+
+    // Add the input and output images (which remain on the command-line) to the arguments list
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-input",  0, "Name of the input image",  argv[1]);
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "-output", 0, "Name of the output image", argv[2]);
+
+    // Define database handle, if used
+#if 0
+    config->database = pmConfigDB(config->site);
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// ppImageParseCamera.c extract with some alterations
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    const char *filename = psMetadataLookupStr(NULL, config->arguments, "-input");
+    psLogMsg("ppImage", PS_LOG_INFO, "Opening input image: %s\n", filename);
+    psFits *fits = psFitsOpen(filename, "r"); // File handle for FITS file
+    if (! fits) {
+        // There's no point in continuing if we can't open the input
+        psErrorStackPrint(stderr, "Can't open input image: %s\n", filename);
+        exit(EXIT_FAILURE);
+    }
+    psMetadata *phu = psFitsReadHeader(NULL, fits); // FITS primary header
+
+    psMetadata *cameraFormat = pmConfigCameraFormatFromHeader(config, phu);
+    if (! config->camera) {
+        cameraFormat = pmConfigCameraFormatFromHeader(config, phu);
+        if (! config->camera) {
+             // There's no point in continuing if we can't recognise what we've got
+            psErrorStackPrint(stderr, "Can't find camera configuration!\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+    // Determine the correct recipe to use
+    if (! config->recipe && !pmConfigRecipeFromCamera(config, RECIPE)) {
+        // There's no point in continuing if we can't work out what recipe to use
+        psErrorStackPrint(stderr, "Can't find recipe configuration!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // Construct camera in preparation for reading
+    pmFPA *fpa = pmFPAConstruct(config->camera);
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// NEW
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    // Add in a source file
+    pmFPAAddSource(fpa, NULL, NULL, phu, cameraFormat);
+
+    // Read the FPA
+//    pmFPARead(fpa, fits, NULL);
+
+    // How'd we do?
+    pmFPAPrint(fpa, false);
+
+    psFitsClose(fits);
+    psFree(phu);
+    psFree(cameraFormat);
+    psFree(fpa);
+
+    // Pau.
+}
