Index: trunk/ppViz/src/ppCoord/ppCoord.h
===================================================================
--- trunk/ppViz/src/ppCoord/ppCoord.h	(revision 27417)
+++ trunk/ppViz/src/ppCoord/ppCoord.h	(revision 27441)
@@ -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: trunk/ppViz/src/ppCoord/ppCoordArguments.c
===================================================================
--- trunk/ppViz/src/ppCoord/ppCoordArguments.c	(revision 27417)
+++ trunk/ppViz/src/ppCoord/ppCoordArguments.c	(revision 27441)
@@ -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: trunk/ppViz/src/ppCoord/ppCoordCamera.c
===================================================================
--- trunk/ppViz/src/ppCoord/ppCoordCamera.c	(revision 27417)
+++ trunk/ppViz/src/ppCoord/ppCoordCamera.c	(revision 27441)
@@ -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: trunk/ppViz/src/ppCoord/ppCoordData.c
===================================================================
--- trunk/ppViz/src/ppCoord/ppCoordData.c	(revision 27417)
+++ trunk/ppViz/src/ppCoord/ppCoordData.c	(revision 27441)
@@ -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: trunk/ppViz/src/ppCoord/ppCoordLoop.c
===================================================================
--- trunk/ppViz/src/ppCoord/ppCoordLoop.c	(revision 27417)
+++ trunk/ppViz/src/ppCoord/ppCoordLoop.c	(revision 27441)
@@ -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" : ""));
         }
     }
