Index: branches/eam_branches/20100225/ppViz/configure.ac
===================================================================
--- branches/eam_branches/20100225/ppViz/configure.ac	(revision 27087)
+++ branches/eam_branches/20100225/ppViz/configure.ac	(revision 27517)
@@ -35,4 +35,5 @@
   src/ppVizPSF/Makefile
   src/ppCoord/Makefile
+  src/ppVizPattern/Makefile
 ])
 
Index: branches/eam_branches/20100225/ppViz/src/Makefile.am
===================================================================
--- branches/eam_branches/20100225/ppViz/src/Makefile.am	(revision 27087)
+++ branches/eam_branches/20100225/ppViz/src/Makefile.am	(revision 27517)
@@ -1,3 +1,3 @@
-SUBDIRS = ppVizPSF ppCoord
+SUBDIRS = ppVizPSF ppCoord ppVizPattern
 
 CLEANFILES = *.pyc *~ core core.*
Index: branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoord.h
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoord.h	(revision 27087)
+++ branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoord.h	(revision 27517)
@@ -10,8 +10,11 @@
 typedef struct {
     psString astromName;                // Filename with astrometry
+    psString rawName;                   // Filename with raw image (or NULL)
     psString pixelsName;                // Filename with pixel coordinates
     psString chipName;                  // Name of chip of interest
     psString radecName;                 // Filename with sky coordinates
     pmConfig *config;                   // Configuration
+    bool radians;                       // RA,Dec are in radians?
+    bool all;                           // Only all coordinates?
 } ppCoordData;
 
Index: branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordArguments.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordArguments.c	(revision 27087)
+++ branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordArguments.c	(revision 27517)
@@ -47,16 +47,21 @@
     psMetadata *arguments = psMetadataAlloc(); // Command-line arguments
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-astrom", 0, "Filename with astrometry", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-raw", 0, "Filename with raw data", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-pixels", 0, "Filename with pixel coordinates", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-chip", 0, "Chip for pixel coordinates", NULL);
-    psMetadataAddStr(arguments, PS_LIST_TAIL, "-radec", 0, "Filename with RA, Dec", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-radec", 0, "Filename with RA,Dec (default decimal degrees)", NULL);
+    psMetadataAddBool(arguments, PS_LIST_TAIL, "-radians", 0, "RA,Dec in radians?", NULL);
+    psMetadataAddBool(arguments, PS_LIST_TAIL, "-all", 0, "Output all coordinates?", NULL);
     if (!psArgumentParse(arguments, &argc, argv) || argc != 1) {
         usage(argv[0], arguments, data);
     }
 
-    bool mdok;                          // Status of MD lookup
     data->astromName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-astrom"));
+    data->rawName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-raw"));
     data->pixelsName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-pixels"));
     data->chipName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-chip"));
-    data->radecName = psMemIncrRefCounter(psMetadataLookupStr(&mdok, arguments, "-radec"));
+    data->radecName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-radec"));
+    data->radians = psMetadataLookupBool(NULL, arguments, "-radians");
+    data->all = psMetadataLookupBool(NULL, arguments, "-all");
 //    psMetadataAddStr(data->config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Output root name", data->outRoot);
 
Index: branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordCamera.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordCamera.c	(revision 27087)
+++ branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordCamera.c	(revision 27517)
@@ -39,4 +39,13 @@
     }
 
+    if (data->rawName) {
+        fileArguments("RAW", data->rawName, "Input raw image", data->config);
+        pmFPAfile *raw = pmFPAfileDefineFromArgs(&status, data->config, "PPIMAGE.INPUT", "RAW"); // File
+        if (!status || !raw) {
+            psError(PS_ERR_IO, false, "Failed to build file from PPIMAGE.INPUT");
+            return false;
+        }
+    }
+
 #if 0
     // Now the camera has been determined, we can read the recipe
Index: branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordData.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordData.c	(revision 27087)
+++ branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordData.c	(revision 27517)
@@ -14,4 +14,5 @@
 {
     psFree(data->astromName);
+    psFree(data->rawName);
     psFree(data->pixelsName);
     psFree(data->chipName);
@@ -28,4 +29,5 @@
 
     data->astromName = NULL;
+    data->rawName = NULL;
     data->pixelsName = NULL;
     data->chipName = NULL;
Index: branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordLoop.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordLoop.c	(revision 27087)
+++ branches/eam_branches/20100225/ppViz/src/ppCoord/ppCoordLoop.c	(revision 27517)
@@ -20,4 +20,7 @@
     }
 
+    pmFPAfile *rawFile = data->rawName ? pmFPAfileSelectSingle(config->files, "PPIMAGE.INPUT", 0) :
+        NULL; // File with raw image
+
     psArray *pixels = NULL, *radec = NULL; // Array of vectors with coordinates
     psArray *radecOut = NULL;              // Output for sky coordinates
@@ -25,5 +28,5 @@
         pixels = psVectorsReadFromFile(data->pixelsName, "%f %f");
         if (!pixels || pixels->n != 2) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to read pixel coordinates");
+            psError(psErrorCodeLast(), false, "Unable to read pixel coordinates");
             return false;
         }
@@ -32,13 +35,14 @@
         radec = psVectorsReadFromFile(data->radecName, "%lf %lf");
         if (!radec || radec->n != 2) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to read sky coordinates");
+            psError(psErrorCodeLast(), false, "Unable to read sky coordinates");
             return false;
         }
         psVector *ra = radec->data[0];  // RA coordinates
         long num = ra->n;               // Number of coordinates
-        radecOut = psArrayAlloc(3);
+        radecOut = psArrayAlloc(4);
         radecOut->data[0] = psArrayAlloc(num);
         radecOut->data[1] = psVectorAlloc(num, PS_TYPE_F32);
         radecOut->data[2] = psVectorAlloc(num, PS_TYPE_F32);
+        radecOut->data[3] = psArrayAlloc(num);
         psVectorInit(radecOut->data[1], NAN);
         psVectorInit(radecOut->data[2], NAN);
@@ -61,5 +65,5 @@
     if (bilevelAstrometry) {
         if (!pmAstromReadBilevelMosaic(astromFile->fpa, phu->header)) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel mosaic astrometry for input FPA.");
+            psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for input FPA.");
             psFree(view);
             return false;
@@ -72,10 +76,16 @@
             continue;
         }
+        if (rawFile) {
+            pmChip *rawChip = pmFPAviewThisChip(view, rawFile->fpa);                   // Chip with raw data
+            if (!rawChip || !rawChip->file_exists) {
+                continue;
+            }
+        }
         const char *chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME"); // Name of chip
         if (data->chipName && strcmp(chipName, data->chipName) != 0) {
-                continue;
+            continue;
         }
         if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
-            psError(PS_ERR_UNKNOWN, false, "Error loading data from files.");
+            psError(psErrorCodeLast(), false, "Error loading data from files.");
             return false;
         }
@@ -89,5 +99,5 @@
         if (bilevelAstrometry) {
             if (!pmAstromReadBilevelChip (chip, hdu->header)) {
-                psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel chip astrometry for input FPA.");
+                psError(psErrorCodeLast(), false, "Unable to read bilevel chip astrometry for input FPA.");
                 psFree(view);
                 return false;
@@ -97,5 +107,5 @@
             psWarning("Reading WCS astrometry for chip %s.", chipName);
             if (!pmAstromReadWCS(astromFile->fpa, chip, hdu->header, 1.0)) {
-                psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry for input FPA.");
+                psError(psErrorCodeLast(), false, "Unable to read WCS astrometry for input FPA.");
                 psFree(view);
                 return false;
@@ -120,4 +130,9 @@
                 psDeproject(sky, tp, astromFile->fpa->toSky);
 
+                if (!data->radians) {
+                    sky->r *= M_PI / 180.0;
+                    sky->d *= M_PI / 180.0;
+                }
+
                 fprintf(stdout, "%s %.3f %.3f --> %.10lf %.10lf\n", chipName, pix->x, pix->y, sky->r, sky->d);
             }
@@ -129,4 +144,65 @@
 
         if (radec) {
+            pmChip *rawChip = rawFile ? pmFPAviewThisChip(view, rawFile->fpa) : NULL; // Chip with raw
+            psArray *cellBounds = NULL;                                               // Bounds of each cell
+            psArray *cellNames = NULL;                                                // Names of each cell
+            psVector *cellParityX = NULL, *cellParityY = NULL;                        // Parity for each cell
+            psVector *cellX0 = NULL, *cellY0 = NULL;                                  // Offset for each cell
+            psVector *cellBinX = NULL, *cellBinY = NULL;                              // Binning for each cell
+            if (rawChip) {
+                if (!rawChip->data_exists) {
+                    // Not interested in this chip
+                    continue;
+                }
+                int numCells = rawChip->cells->n; // Number of cells
+
+                cellBounds = psArrayAlloc(numCells);
+                cellNames = psArrayAlloc(numCells);
+                cellParityX = psVectorAlloc(numCells, PS_TYPE_S32);
+                cellParityY = psVectorAlloc(numCells, PS_TYPE_S32);
+                cellX0 = psVectorAlloc(numCells, PS_TYPE_S32);
+                cellY0 = psVectorAlloc(numCells, PS_TYPE_S32);
+                cellBinX = psVectorAlloc(numCells, PS_TYPE_S32);
+                cellBinY = psVectorAlloc(numCells, PS_TYPE_S32);
+
+                pmCell *rawCell;        // Cell with raw data
+                while ((rawCell = pmFPAviewNextCell(view, rawFile->fpa, 1))) {
+                    if (!rawCell->data_exists) {
+                        continue;
+                    }
+                    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                        psError(psErrorCodeLast(), false, "Error loading data from files.");
+                        return false;
+                    }
+                    psRegion *region = pmCellExtent(rawCell); // Bounds of cell
+                    if (!region) {
+                        psError(psErrorCodeLast(), false, "Unable to determine extent of cell.");
+                        return false;
+                    }
+                    cellBounds->data[view->cell] = region;
+                    cellNames->data[view->cell] = psMemIncrRefCounter(psMetadataLookupStr(NULL,
+                                                      rawCell->concepts, "CELL.NAME"));
+                    cellParityX->data.S32[view->cell] = psMetadataLookupS32(NULL, rawCell->concepts, "CELL.XPARITY");
+                    cellParityY->data.S32[view->cell] = psMetadataLookupS32(NULL, rawCell->concepts, "CELL.YPARITY");
+                    cellX0->data.S32[view->cell] = psMetadataLookupS32(NULL, rawCell->concepts, "CELL.X0");
+                    cellY0->data.S32[view->cell] = psMetadataLookupS32(NULL, rawCell->concepts, "CELL.Y0");
+                    cellBinX->data.S32[view->cell] = psMetadataLookupS32(NULL, rawCell->concepts, "CELL.XBIN");
+                    cellBinY->data.S32[view->cell] = psMetadataLookupS32(NULL, rawCell->concepts, "CELL.YBIN");
+                    if (cellParityX->data.S32[view->cell] == 0 || cellParityY->data.S32[view->cell] == 0 ||
+                        cellBinX->data.S32[view->cell] == 0 || cellBinY->data.S32[view->cell] == 0) {
+                        psError(PM_ERR_CONCEPTS, true, "Concepts aren't set: %d %d %d %d %d %d\n",
+                                cellParityX->data.S32[view->cell], cellParityY->data.S32[view->cell],
+                                cellX0->data.S32[view->cell], cellY0->data.S32[view->cell],
+                                cellBinX->data.S32[view->cell], cellBinY->data.S32[view->cell]);
+                        return false;
+                    }
+
+                    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                        psError(psErrorCodeLast(), false, "Error freeing data from files.");
+                        return false;
+                    }
+                }
+            }
+
             psVector *ra = radec->data[0], *dec = radec->data[1]; // Pixel coordinates
             long num = ra->n;                                     // Number of coordinates
@@ -135,5 +211,5 @@
             int numRows = psMetadataLookupS32(NULL, hdu->header, "IMNAXIS2"); // Number of rows
             if (numCols <= 0 || numRows <= 0) {
-                psError(PS_ERR_UNKNOWN, false, "Unable to read size of chip.");
+                psError(psErrorCodeLast(), false, "Unable to read size of chip.");
                 return false;
             }
@@ -147,8 +223,14 @@
             psVector *xPix = radecOut->data[1];   // x coordinate for pixels
             psVector *yPix = radecOut->data[2];   // y coordinate for pixels
+            psArray *cellPix = radecOut->data[3]; // Cell for pixels
 
             for (long i = 0; i < num; i++) {
                 sky->r = ra->data.F64[i];
                 sky->d = dec->data.F64[i];
+
+                if (!data->radians) {
+                    sky->r *= M_PI / 180.0;
+                    sky->d *= M_PI / 180.0;
+                }
 
                 psProject(tp, sky, astromFile->fpa->toSky);
@@ -162,4 +244,21 @@
                 }
 
+                if (rawChip) {
+                    psString cellName = NULL;         // Name of cell
+                    int numCells = rawChip->cells->n; // Number of cells
+                    for (int i = 0; i < numCells && !cellName; i++) {
+                        psRegion *region = cellBounds->data[i]; // Bounds of cell
+                        if (x >= region->x0 && x < region->x1 && y >= region->y0 && y < region->y1) {
+                            cellName = psStringCopy(cellNames->data[i]);
+                            // Transform chip coordinates to cell coordinates
+                            x = (x - cellX0->data.S32[i]) /
+                                (float)(cellParityX->data.S32[i] * cellBinX->data.S32[i]);
+                            y = (y - cellY0->data.S32[i]) /
+                                (float)(cellParityY->data.S32[i] * cellBinY->data.S32[i]);
+                        }
+                    }
+                    cellPix->data[i] = cellName;
+                }
+
                 chipPix->data[i] = psStringCopy(chipName);
                 xPix->data.F32[i] = x;
@@ -170,9 +269,17 @@
             psFree(tp);
             psFree(sky);
+            psFree(cellNames);
+            psFree(cellBounds);
+            psFree(cellParityX);
+            psFree(cellParityY);
+            psFree(cellBinX);
+            psFree(cellBinY);
+            psFree(cellX0);
+            psFree(cellY0);
         }
 
         // Chip
         if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
-            psError(PS_ERR_UNKNOWN, false, "Error saving data to files.");
+            psError(psErrorCodeLast(), false, "Error saving data to files.");
             return false;
         }
@@ -180,5 +287,5 @@
     // FPA
     if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
-        psError(PS_ERR_UNKNOWN, false, "Error saving data to files.");
+        psError(psErrorCodeLast(), false, "Error saving data to files.");
         return false;
     }
@@ -188,4 +295,5 @@
         psVector *xPix = radecOut->data[1];   // x coordinate for pixels
         psVector *yPix = radecOut->data[2];   // y coordinate for pixels
+        psArray *cellPix = radecOut->data[3]; // Cell for pixels
         psVector *ra = radec->data[0];        // RA coordinate
         psVector *dec = radec->data[1];       // Dec coordinate
@@ -193,7 +301,14 @@
         for (long i = 0; i < chipPix->n; i++) {
             const char *chipName = chipPix->data[i]; // Name of chip
-            fprintf(stdout, "%.10lf %.10lf --> %.3f %.3f %s\n",
+            const char *cellName = cellPix->data[i]; // Name of cell, or NULL
+            if (!data->all && (!isfinite(xPix->data.F32[i]) || !isfinite(yPix->data.F32[i]) ||
+                               !chipName || (rawFile && !cellName))) {
+                continue;
+            }
+            fprintf(stdout, "%.10lf %.10lf --> %.3f %.3f %s%s%s\n",
                     ra->data.F64[i], dec->data.F64[i], xPix->data.F32[i], yPix->data.F32[i],
-                    chipName ? chipName : "UNKNOWN");
+                    chipName ? chipName : "UNKNOWN",
+                    rawFile ? " " : "",
+                    rawFile && cellName ? cellName : (rawFile ? "UNKNOWN" : ""));
         }
     }
Index: branches/eam_branches/20100225/ppViz/src/ppVizPattern/Makefile.am
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppVizPattern/Makefile.am	(revision 27517)
+++ branches/eam_branches/20100225/ppViz/src/ppVizPattern/Makefile.am	(revision 27517)
@@ -0,0 +1,47 @@
+bin_PROGRAMS = ppVizPattern
+
+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 ppVizPatternVersion.c, since it gets the version information
+ppVizPatternVersion.c: ppVizPatternVersionDefinitions.h
+ppVizPatternVersionDefinitions.h: ppVizPatternVersionDefinitions.h.in FORCE
+	-$(RM) ppVizPatternVersionDefinitions.h
+	$(SED) -e "s|@PPVIZPATTERN_VERSION@|\"$(PPVIZPATTERN_VERSION)\"|" -e "s|@PPVIZPATTERN_BRANCH@|\"$(PPVIZPATTERN_BRANCH)\"|" -e "s|@PPVIZPATTERN_SOURCE@|\"$(PPVIZPATTERN_SOURCE)\"|" ppVizPatternVersionDefinitions.h.in > ppVizPatternVersionDefinitions.h
+FORCE: ;
+
+BUILT_SOURCES = ppVizPatternVersionDefinitions.h
+
+
+ppVizPattern_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPVIZPATTERN_CFLAGS)
+ppVizPattern_LDFLAGS  = $(PSLIB_LIBS)   $(PSMODULE_LIBS)   $(PPVIZPATTERN_LIBS)
+
+ppVizPattern_SOURCES =		\
+	ppVizPattern.c		\
+	ppVizPatternArguments.c	\
+	ppVizPatternCamera.c	\
+	ppVizPatternData.c		\
+	ppVizPatternLoop.c		\
+	ppVizPatternVersion.c            
+
+noinst_HEADERS = \
+	ppVizPattern.h
+
+clean-local:
+	-rm -f TAGS
+
+# Tags for emacs
+tags:
+	etags `find . -name \*.[ch] -print`
+
Index: branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPattern.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPattern.c	(revision 27517)
+++ branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPattern.c	(revision 27517)
@@ -0,0 +1,43 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppVizPattern.h"
+
+int main(int argc, char *argv[])
+{
+    ppVizPatternVersionPrint();
+
+    ppVizPatternData *data = ppVizPatternDataInit(&argc, argv);
+    if (!data) {
+        psErrorStackPrint(stderr, "Unable to initialise.");
+        return PS_EXIT_CONFIG_ERROR;
+    }
+
+    if (!ppVizPatternArguments(data, argc, argv)) {
+        psErrorStackPrint(stderr, "Unable to parse arguments.");
+        psFree(data);
+        return PS_EXIT_CONFIG_ERROR;
+    }
+
+    if (!ppVizPatternCamera(data)) {
+        psErrorStackPrint(stderr, "Unable to parse camera configuration.");
+        psFree(data);
+        return PS_EXIT_CONFIG_ERROR;
+    }
+
+    if (!ppVizPatternLoop(data)) {
+        psErrorStackPrint(stderr, "Unable to process data.");
+        psFree(data);
+        return PS_EXIT_DATA_ERROR;
+    }
+
+    psFree(data);
+
+    return PS_EXIT_SUCCESS;
+}
+
Index: branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPattern.h
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPattern.h	(revision 27517)
+++ branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPattern.h	(revision 27517)
@@ -0,0 +1,41 @@
+#ifndef PP_VIZPSF_H
+#define PP_VIZPSF_H
+
+#include <pslib.h>
+#include <psmodules.h>
+
+#define PPVIZPATTERN_RECIPE "PPVIZPATTERN"      // Recipe name
+
+// Data for processing
+typedef struct {
+    psString patternName;               // Filename with pattern
+    psString outRoot;                   // Output root name
+    pmConfig *config;                   // Configuration
+} ppVizPatternData;
+
+/// Initialise data for processing
+ppVizPatternData *ppVizPatternDataInit(int *argc, char *argv[] // Command-line arguments
+    );
+
+/// Parse command-line arguments
+bool ppVizPatternArguments(ppVizPatternData *data, // Data for processing
+                        int argc, char *argv[] // Command-line arguments
+    );
+
+/// Parse camera configurations
+bool ppVizPatternCamera(ppVizPatternData *data // Data for processing
+    );
+
+/// Loop over input data, processing
+bool ppVizPatternLoop(ppVizPatternData *data // Data for processing
+    );
+
+/// Add version information to header
+bool ppVizPatternVersionHeader(
+    psMetadata *header                  // Header to supplement
+    );
+
+/// Print version information to stdout
+void ppVizPatternVersionPrint(void);
+
+#endif
Index: branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternArguments.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternArguments.c	(revision 27517)
+++ branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternArguments.c	(revision 27517)
@@ -0,0 +1,68 @@
+/** @file ppVizPatternArguments.c
+ *
+ *  @brief
+ *
+ *  @ingroup ppVizPattern
+ *
+ *  @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 "ppVizPattern.h"
+
+/// Print usage information and die
+static void usage(const char *program,  // Name of the program
+                  psMetadata *arguments, // Command-line arguments
+                  ppVizPatternData *data   // Run-time data
+    )
+{
+    fprintf(stderr, "\nPan-STARRS pattern visualisation\n\n");
+    fprintf(stderr,
+            "Usage: %s -pattern PATTERN.ptn OUTPUT_ROOT\n\n",
+            program);
+    fprintf(stderr, "\n");
+    psArgumentHelp(arguments);
+    psFree(arguments);
+    psFree(data);
+
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(PS_EXIT_CONFIG_ERROR);
+}
+
+
+bool ppVizPatternArguments(ppVizPatternData *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);
+    if (argc == 1 || !psArgumentParse(arguments, &argc, argv) || argc != 2) {
+        usage(argv[0], arguments, data);
+    }
+
+    data->patternName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-pattern"));
+    data->outRoot = psStringCopy(argv[1]);
+    psMetadataAddStr(data->config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Output root name", data->outRoot);
+
+    psTrace("ppVizPattern", 1, "Done reading command-line arguments\n");
+    psFree(arguments);
+
+    PS_ASSERT_STRING_NON_EMPTY(data->patternName, false);
+    PS_ASSERT_STRING_NON_EMPTY(data->outRoot, false);
+
+    return true;
+}
+
+
Index: branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternCamera.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternCamera.c	(revision 27517)
+++ branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternCamera.c	(revision 27517)
@@ -0,0 +1,59 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppVizPattern.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 ppVizPatternCamera(ppVizPatternData *data // Run-time data
+    )
+{
+    bool status;                        // Status of file definition
+
+    fileArguments("PATTERN", data->patternName, "Input pattern", data->config);
+    pmFPAfile *input = pmFPAfileDefineFromArgs(&status, data->config, "PPVIZPATTERN.INPUT",
+                                               "PATTERN"); // File
+    if (!status || !input) {
+        psError(PS_ERR_IO, false, "Failed to build file from PPVIZPATTERN.INPUT");
+        return false;
+    }
+
+    pmFPAfile *output = pmFPAfileDefineOutput(data->config, input->fpa, "PPVIZPATTERN.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, PPVIZPATTERN_RECIPE); // Recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPVIZPATTERN_RECIPE);
+        return false;
+    }
+#endif
+
+    return true;
+}
Index: branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternData.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternData.c	(revision 27517)
+++ branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternData.c	(revision 27517)
@@ -0,0 +1,47 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppVizPattern.h"
+
+// Destructor
+static void vizPatternDataFree(ppVizPatternData *data // Data to free
+    )
+{
+    psFree(data->patternName);
+    psFree(data->outRoot);
+    psFree(data->config);
+    return;
+}
+
+
+ppVizPatternData *ppVizPatternDataAlloc(void)
+{
+    ppVizPatternData *data = psAlloc(sizeof(ppVizPatternData)); // Processing data, to return
+    psMemSetDeallocator(data, (psFreeFunc)vizPatternDataFree);
+
+    data->patternName = NULL;
+    data->outRoot = NULL;
+    data->config = NULL;
+
+    return data;
+}
+
+
+ppVizPatternData *ppVizPatternDataInit(int *argc, char **argv)
+{
+    PS_ASSERT_PTR_NON_NULL(argc, NULL);
+    PS_ASSERT_PTR_NON_NULL(argv, NULL);
+
+    ppVizPatternData *data = ppVizPatternDataAlloc(); // Processing data, to return
+    data->config = pmConfigRead(argc, argv, PPVIZPATTERN_RECIPE);
+    if (!data->config) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read configuration.");
+        return NULL;
+    }
+    return data;
+}
Index: branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternLoop.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternLoop.c	(revision 27517)
+++ branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternLoop.c	(revision 27517)
@@ -0,0 +1,122 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+
+#include "ppVizPattern.h"
+
+#define MASK_BAD 0xFFFF                 // Mask for bad pixels
+
+bool ppVizPatternLoop(ppVizPatternData *data // Run-time data
+    )
+{
+    pmConfig *config = data->config;                                        // Configuration data
+    pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PPVIZPATTERN.INPUT", 0); // File with PSF
+
+    pmFPAview *view = pmFPAviewAlloc(0); // Pointer into FPA hierarchy
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+        return NULL;
+    }
+
+    pmChip *chip;                       // Chip from FPA
+    while ((chip = pmFPAviewNextChip(view, input->fpa, 1))) {
+        if (!chip->process || !chip->file_exists) {
+            continue;
+        }
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+            psError(PS_ERR_UNKNOWN, false, "Error loading data from files.");
+            return false;
+        }
+
+        pmCell *cell;                   // Cell from chip
+        while ((cell = pmFPAviewNextCell(view, input->fpa, 1))) {
+            if (!cell->process || !cell->file_exists) {
+                continue;
+            }
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                psError(PS_ERR_UNKNOWN, false, "Error loading data from files.");
+                return false;
+            }
+
+            pmReadout *readout;         // Readout from cell
+            while ((readout = pmFPAviewNextReadout(view, input->fpa, 1))) {
+                if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+                    psError(PS_ERR_UNKNOWN, 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, MASK_BAD) || !pmPatternCellApply(readout, MASK_BAD)) {
+                    psError(PS_ERR_UNKNOWN, false, "Unable to apply pattern correction.");
+                    return false;
+                }
+
+                readout->data_exists = true;
+                readout->parent->data_exists = true;
+                readout->parent->parent->data_exists = true;
+
+                pmHDU *hdu = pmHDUGetLowest(input->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();
+                }
+                ppVizPatternVersionHeader(hdu->header);
+
+
+                // Readout
+                if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                    psError(PS_ERR_UNKNOWN, false, "Error saving data to files.");
+                    return false;
+                }
+            }
+            // Cell
+            if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+                psError(PS_ERR_UNKNOWN, false, "Error saving data to files.");
+                return false;
+            }
+        }
+        // Chip
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+            psError(PS_ERR_UNKNOWN, false, "Error saving data to files.");
+            return false;
+        }
+    }
+    // FPA
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+        psError(PS_ERR_UNKNOWN, false, "Error saving data to files.");
+        return false;
+    }
+
+    return true;
+}
Index: branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternVersion.c
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternVersion.c	(revision 27517)
+++ branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternVersion.c	(revision 27517)
@@ -0,0 +1,116 @@
+/** @file ppVizPatternVersion.c
+ *
+ *  @brief
+ *
+ *  @ingroup ppVizPattern
+ *
+ *  @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 "ppVizPattern.h"
+#include "ppVizPatternVersionDefinitions.h"
+
+#ifndef PPVIZPATTERN_VERSION
+#error "PPVIZPATTERN_VERSION is not set"
+#endif
+#ifndef PPVIZPATTERN_BRANCH
+#error "PPVIZPATTERN_BRANCH is not set"
+#endif
+#ifndef PPVIZPATTERN_SOURCE
+#error "PPVIZPATTERN_SOURCE is not set"
+#endif
+
+psString ppVizPatternVersion(void)
+{
+    char *value = NULL;
+    psStringAppend(&value, "%s@%s", PPVIZPATTERN_BRANCH, PPVIZPATTERN_VERSION);
+    return value;
+}
+
+psString ppVizPatternSource(void)
+{
+    return psStringCopy(PPVIZPATTERN_SOURCE);
+}
+
+psString ppVizPatternVersionLong(void)
+{
+    psString version = ppVizPatternVersion();  // Version, to return
+    psString source = ppVizPatternSource();    // Source
+
+    psStringPrepend(&version, "ppVizPattern ");
+    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 ppVizPatternVersionHeader(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, "ppVizPattern 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 = ppVizPatternVersion(); // Software version
+    psString source  = ppVizPatternSource();  // Software source
+
+    psStringPrepend(&version, "ppVizPattern version: ");
+    psStringPrepend(&version, "ppVizPattern 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 ppVizPatternVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("ppVizPattern", PS_LOG_INFO, "ppVizPattern at %s", timeString);
+    psFree(timeString);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString ppVizPattern = ppVizPatternVersionLong(); // ppVizPattern version
+
+    psLogMsg("ppVizPattern", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("ppVizPattern", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("ppVizPattern", PS_LOG_INFO, "%s", ppVizPattern);
+
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(ppVizPattern);
+
+    return;
+}
Index: branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternVersionDefinitions.h.in
===================================================================
--- branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternVersionDefinitions.h.in	(revision 27517)
+++ branches/eam_branches/20100225/ppViz/src/ppVizPattern/ppVizPatternVersionDefinitions.h.in	(revision 27517)
@@ -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
