Index: /trunk/Ohana/src/relphot/src/GridOps.c
===================================================================
--- /trunk/Ohana/src/relphot/src/GridOps.c	(revision 20185)
+++ /trunk/Ohana/src/relphot/src/GridOps.c	(revision 20186)
@@ -23,6 +23,10 @@
   int *Fx, *Fy;  /* chip flip */
   int *Ox, *Oy;  /* chip offset */
+  int *valid;
   char **ccdname;
 } camera;    
+
+static int *ccdnum;
+static char *config;
 
 # ifdef GRID_V1
@@ -49,6 +53,9 @@
 void initGrid (int dX, int dY) {
 
-  int i;
-  char field[64], *config, line[256];
+  int i, N, ccdnum_max;
+  char *p, field[64], line[256];
+  int *Fx, *Fy;  /* chip flip */
+  int *Ox, *Oy;  /* chip offset */
+  char **ccdname;
 
   /* load camera config file */
@@ -66,18 +73,64 @@
   ScanConfig (config, "NAXIS2", "%d", 1, &camera.Ny);
 
-  ALLOCATE (camera.Fx, int, camera.Nchip);
-  ALLOCATE (camera.Fy, int, camera.Nchip);
-  ALLOCATE (camera.Ox, int, camera.Nchip);
-  ALLOCATE (camera.Oy, int, camera.Nchip);
-  ALLOCATE (camera.ccdname, char *, camera.Nchip);
+  // temporary storage
+  ALLOCATE (Fx,      int,    camera.Nchip);
+  ALLOCATE (Fy,      int,    camera.Nchip);
+  ALLOCATE (Ox,      int,    camera.Nchip);
+  ALLOCATE (Oy,      int,    camera.Nchip);
+  ALLOCATE (ccdname, char *, camera.Nchip);
+  ALLOCATE (ccdnum,  int,    camera.Nchip);
 
   /* load per-chip parameters */
   for (i = 0; i < camera.Nchip; i++) {
-    ALLOCATE (camera.ccdname[i], char, 256);
+    ALLOCATE (ccdname[i], char, 256);
     sprintf (field, "CCD.%d", i);
     ScanConfig (config, field, "%s", 1, line);
-    sscanf (line, "%s %d %d %d %d", camera.ccdname[i], &camera.Ox[i], &camera.Oy[i], &camera.Fx[i], &camera.Fy[i]);
-  }
-  free (config);
+    // XXX get error status!
+
+    sscanf (line, "%s %d %d %d %d", ccdname[i], &Ox[i], &Oy[i], &Fx[i], &Fy[i]);
+    
+    p = ccdname[i];
+    while (!isdigit(*p) && *p) p++;
+    if (*p == 0) continue;
+    ccdnum[i] = atoi (p);
+  }
+
+  /* we now have the parameters loaded into a minimal length list; reshuffle to the a list of length 0 - MAX(ccdnum) */
+  ccdnum_max = 0;
+  for (i = 0; i < camera.Nchip; i++) {
+    ccdnum_max = MAX(ccdnum_max, ccdnum[i]);
+  }
+  ccdnum_max ++;
+
+  if (ccdnum_max < camera.Nchip) {
+    fprintf (stderr, "problem with camera config: duplicate ccd IDs\n");
+    exit (1);
+  }
+  
+  if (ccdnum_max > 0x1000) {
+    fprintf (stderr, "problem with camera config: absurd max ccd ID number %d\n", ccdnum_max);
+    exit (1);
+  }
+
+  ALLOCATE (camera.Fx, 	    int,    ccdnum_max);
+  ALLOCATE (camera.Fy, 	    int,    ccdnum_max);
+  ALLOCATE (camera.Ox, 	    int,    ccdnum_max);
+  ALLOCATE (camera.Oy, 	    int,    ccdnum_max);
+  ALLOCATE (camera.valid,   int,    ccdnum_max);
+  ALLOCATE (camera.ccdname, char *, ccdnum_max);
+
+  for (i = 0; i < ccdnum_max; i++) {
+    camera.valid[i] = FALSE;
+  }
+
+  for (i = 0; i < camera.Nchip; i++) {
+    N = ccdnum[i];
+    camera.Fx[N] = Fx[i];
+    camera.Fy[N] = Fy[i];
+    camera.Ox[N] = Ox[i];
+    camera.Oy[N] = Oy[i];
+    camera.ccdname[N] = ccdname[i];
+    camera.valid[N] = TRUE;
+  }
 
   /* define mosaic 2d correction grid: 
@@ -215,5 +268,5 @@
   bin[cat][meas] = i;
   Xmeas[cat][meas] = x + camera.Ox[ccdnum]*camera.Nx;
-  Ymeas[cat][meas] = Y + camera.Oy[ccdnum]*camera.Ny;
+  Ymeas[cat][meas] = y + camera.Oy[ccdnum]*camera.Ny;
   clist[i][Nlist[i]] = cat;
   mlist[i][Nlist[i]] = meas;
@@ -248,5 +301,5 @@
 void setMgrid (Catalog *catalog) {
 
-  int i, j, m, c, n, N, Nmax;
+  int i, j, m, c, n, N, Nmax, Nbad, Nmos, Ncal, Nrel, Nsys;
   double *list, *dlist;
   float Msys, Mrel, Mcal, Mmos;
@@ -261,4 +314,6 @@
   ALLOCATE (list, double, Nmax);
   ALLOCATE (dlist, double, Nmax);
+
+  Nbad = Ncal = Nmos = Nrel = Nsys = 0;
 
   for (i = 0; i < Ngrid; i++) {
@@ -270,14 +325,30 @@
       c = clist[i][j];
       
-      if (catalog[c].measure[m].dbFlags & MEAS_BAD) continue;
+      if (catalog[c].measure[m].dbFlags & MEAS_BAD) {
+	Nbad ++;
+	continue;
+      }
       Mcal = getMcal  (m, c);
-      if (isnan(Mcal)) continue;
+      if (isnan(Mcal)) {
+	Ncal ++;
+	continue;
+      }
       Mmos = getMmos  (m, c);
-      if (isnan(Mmos)) continue;
+      if (isnan(Mmos)) {
+	Nmos ++;
+	continue;
+      }
       Mrel  = getMrel  (catalog, m, c);
-      if (isnan(Mrel)) continue;
+      if (isnan(Mrel)) {
+	Nrel ++;
+	continue;
+      }
       
       n = catalog[c].measure[m].averef;
       Msys = PhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+      if (isnan(Msys)) {
+	Nsys++;
+	continue;
+      }
       list[N] = Msys - Mrel - Mcal - Mmos;
       dlist[N] = MAX (catalog[c].measure[m].dM, MIN_ERROR);
@@ -290,4 +361,7 @@
     gridN[i] = N;
   }
+
+  fprintf (stderr, "grid cells having too few measurements (Nbad: %d, Nmos: %d, Ncal: %d, Nrel: %d, Nsys: %d)\n", Nbad, Nmos, Ncal, Nrel, Nsys);
+
   free (list);
   free (dlist);
@@ -347,10 +421,10 @@
   graphdata.ymin = PlotdMmin;
   graphdata.ymax = PlotdMmax;
-  plot_list (&graphdata, xlist, Mlist, N, "X vs dM raw", "XdM.png");
-  plot_list (&graphdata, xlist, dlist, N, "X vs dM corrected", "XdMf.png");
-  plot_list (&graphdata, ylist, dlist, N, "Y vs dM corrected", "YdMf.png");
+  plot_list (&graphdata, xlist, Mlist, N, "X vs dM raw", "%s.XdM.png", OUTROOT);
+  plot_list (&graphdata, xlist, dlist, N, "X vs dM corrected", "%s.XdMf.png", OUTROOT);
+  plot_list (&graphdata, ylist, dlist, N, "Y vs dM corrected", "%s.YdMf.png", OUTROOT);
 
   plot_defaults (&graphdata);
-  plot_list (&graphdata, xlist, ylist, N, "X vs Y", "XY.png");
+  plot_list (&graphdata, xlist, ylist, N, "X vs Y", "%s.XY.png", OUTROOT);
 
   free (ylist);
@@ -363,5 +437,5 @@
 void dump_grid () { 
 
-  int i, j, Nimage;
+    int i, j, Nimage, Nbytes, Nformat;
   int *imlist;
   FILE *f;
@@ -369,12 +443,19 @@
   Matrix matrix;
   Mosaic *refmosaic;
+  char *filename;
+  char formatline[32], key[32], value[64];
     
+  Nbytes = strlen (OUTROOT) + 6;
+  ALLOCATE (filename, char, Nbytes);
+  snprintf (filename, Nbytes, "%s.fits", OUTROOT);
+
   /* select reference mosaic image */
   imlist = SelectRefMosaic (&refmosaic, &Nimage);
 
   /* we are writing to this file */
-  f = fopen ("mosaic.fits", "w");
+  f = fopen (filename, "w");
   if (f == (FILE *) NULL) { 
-    fprintf (stderr, "cannot open %s for output\n", "mosaic.fits");
+    fprintf (stderr, "cannot open %s for output\n", filename);
+    free (filename);
     return;
   }
@@ -388,4 +469,14 @@
   gfits_modify (&header, "FILTER", "%s", 1, photcode[0].name);
   gfits_modify (&header, "COMMENT", "%S", 1, "Mosaic Photometry Grid Analysis");
+
+  // we need to add lines to the PHU to identify the camera and format; these are used by the ipp config system
+  // Note that config must have been loaded (and not freed) above.
+  ScanConfig (config, "NFORMAT", "%d", 1, &Nformat);
+  for (i = 1; i <= Nformat; i++) {
+      ScanConfig (config, "FORMAT", "%s", i, formatline);
+      sscanf (formatline, "%s %s", key, value);
+      gfits_modify (&header, key, "%s", 1, value);
+  }
+
   gfits_fwrite_header (f, &header);
   gfits_fwrite_matrix (f, &matrix);
@@ -483,7 +574,9 @@
   /* grid pixels are tied to detector pixels, but are flipped to match focal plane */
   for (i = 0; i < camera.Nchip; i++) {
-    int ix, iy, x, y, X, Y, bin;
-
-    gfits_modify (&theader, "EXTNAME", "%s", 1, camera.ccdname[i]);
+    int N, ix, iy, x, y, X, Y, bin;
+
+    N = ccdnum[i];
+
+    gfits_modify (&theader, "EXTNAME", "%s", 1, camera.ccdname[N]);
     gfits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
     gfits_modify (&theader, "NX", "%d", 1, camera.Nx);
@@ -501,11 +594,11 @@
 	/* normalize X & Y */
 	x = X;
-	if (camera.Fx[i]) x = RELPHOT_GRID_X - X - 1;
+	if (camera.Fx[N]) x = RELPHOT_GRID_X - X - 1;
 	y = Y;
-	if (camera.Fy[i]) y = RELPHOT_GRID_Y - Y - 1;
+	if (camera.Fy[N]) y = RELPHOT_GRID_Y - Y - 1;
 	      
 	/* coordinates in the grid */
-	ix = x + camera.Ox[i]*RELPHOT_GRID_X;
-	iy = y + camera.Oy[i]*RELPHOT_GRID_Y;
+	ix = x + camera.Ox[N]*RELPHOT_GRID_X;
+	iy = y + camera.Oy[N]*RELPHOT_GRID_Y;
 	      
 	bin = ix + iy*gridX;
@@ -519,4 +612,5 @@
 # endif
 
+  free (filename);
 }
 
