Index: /trunk/Ohana/src/uniphot/Makefile
===================================================================
--- /trunk/Ohana/src/uniphot/Makefile	(revision 39271)
+++ /trunk/Ohana/src/uniphot/Makefile	(revision 39272)
@@ -37,5 +37,5 @@
 
 # install: $(DESTBIN)/uniphot $(DESTBIN)/setfwhm $(DESTBIN)/setphot $(DESTBIN)/setphot_client $(DESTBIN)/setposangle $(DESTBIN)/setposangle_client $(DESTBIN)/setastrom $(DESTBIN)/setastrom_client $(DESTBIN)/setgalmodel $(DESTBIN)/setgalmodel_client $(DESTBIN)/fiximids $(DESTBIN)/fiximids_client $(DESTBIN)/fixstkids $(DESTBIN)/fixstkids_client $(DESTBIN)/ckids $(DESTBIN)/ckids_client
-install: $(DESTBIN)/uniphot $(DESTBIN)/setfwhm $(DESTBIN)/setposangle $(DESTBIN)/setposangle_client $(DESTBIN)/setastrom $(DESTBIN)/setastrom_client $(DESTBIN)/setgalmodel $(DESTBIN)/setgalmodel_client $(DESTBIN)/fiximids $(DESTBIN)/fiximids_client $(DESTBIN)/fixstkids $(DESTBIN)/fixstkids_client $(DESTBIN)/ckids $(DESTBIN)/ckids_client
+install: $(DESTBIN)/uniphot $(DESTBIN)/setfwhm $(DESTBIN)/setphot $(DESTBIN)/setposangle $(DESTBIN)/setposangle_client $(DESTBIN)/setastrom $(DESTBIN)/setastrom_client $(DESTBIN)/setgalmodel $(DESTBIN)/setgalmodel_client $(DESTBIN)/fiximids $(DESTBIN)/fiximids_client $(DESTBIN)/fixstkids $(DESTBIN)/fixstkids_client $(DESTBIN)/ckids $(DESTBIN)/ckids_client
 
 UNIPHOT = \
@@ -68,4 +68,6 @@
 $(SRC)/match_zpts_to_images.$(ARCH).o	    \
 $(SRC)/match_flatcorr_to_images.$(ARCH).o	    \
+$(SRC)/match_camcorr_to_images.$(ARCH).o	    \
+$(SRC)/cam_zpt_correction.$(ARCH).o	    \
 $(SRC)/update_dvo_setphot.$(ARCH).o \
 $(SRC)/update_catalog_setphot.$(ARCH).o \
Index: /trunk/Ohana/src/uniphot/include/setphot.h
===================================================================
--- /trunk/Ohana/src/uniphot/include/setphot.h	(revision 39271)
+++ /trunk/Ohana/src/uniphot/include/setphot.h	(revision 39272)
@@ -35,5 +35,11 @@
   int NyCCD;	// number of pixels
 
+  e_time *tstart;
+  e_time *tstop;
+
+  Header *phu;
   Matrix **matrix; // allocate an array of pointers
+  Header **header; // allocate an array of pointers
+  
   // index = ix + iy*Nx + filter*Nchips + dir*Ngroup
 } CamCorrection;
@@ -47,4 +53,5 @@
 char        *IMAGES;
 char        *SINGLE_CPT;
+char        *CAM_FILE;
 int          VERBOSE;
 int          RESET;
@@ -89,6 +96,6 @@
 Image        *load_images_setphot    PROTO((FITS_DB *db, off_t *Nimage));
 int           match_zpts_to_images   PROTO((Image *image, off_t Nimage, ZptTable *zpts, int Nzpts));
-int           update_dvo_setphot     PROTO((Image *image, off_t Nimage, FlatCorrectionTable *flatcorr));
-void          update_catalog_setphot PROTO((Catalog *catalog, Image *image, off_t *index, off_t Nimage, FlatCorrectionTable *flatcorr));
+int           update_dvo_setphot     PROTO((Image *image, off_t Nimage, CamCorrection *camcorr));
+void          update_catalog_setphot PROTO((Catalog *catalog, Image *image, off_t *index, off_t Nimage, CamCorrection *camcorr));
 void          update_catalog_setphot_client PROTO((Catalog *catalog, ImageSubset *image, off_t *index, off_t Nimage, FlatCorrectionTable *flatcorr));
 
@@ -100,3 +107,13 @@
 float         apply_zpt_offset            PROTO((short code));
 
-int repair_catalog_by_objID (Catalog *catalog);
+int           repair_catalog_by_objID     PROTO((Catalog *catalog));
+
+void           free_cam_correction          PROTO((CamCorrection *cam));
+CamCorrection *alloc_cam_correction         PROTO((int Nx, int Ny, int Nfilter, int Nseason));
+CamCorrection *load_cam_correction          PROTO((char *filename));
+int            save_cam_correction          PROTO((CamCorrection *cam, char *filename));
+// int            get_cam_correction        PROTO((int chipID, int filter, float Xccd, float Yccd, double *dX, double *dY));
+float          get_cam_correction           PROTO((CamCorrection *cam, int flat_id, float Xccd, float Yccd));
+CamCorrection *merge_flatcorr_and_camcorr   PROTO((FlatCorrectionTable *flatcorr, CamCorrection *camcorr));
+
+int            match_camcorr_to_images      PROTO((Image *image, off_t Nimage, CamCorrection *camcorr));
Index: /trunk/Ohana/src/uniphot/src/cam_zpt_correction.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/cam_zpt_correction.c	(revision 39271)
+++ /trunk/Ohana/src/uniphot/src/cam_zpt_correction.c	(revision 39272)
@@ -1,3 +1,6 @@
 # include "setphot.h"
+
+// hard-coded values
+char filters[5][3] = {"g", "r", "i", "z", "y"};
 
 // camera systematic (photoflat) correction functions:
@@ -6,19 +9,20 @@
 // note that we are allocating pointers for XY00 - XY77, but only the octal elements are set (and not the 00,07,70,77 ones)
 
-static CamCorrection *cam = NULL;
-
-CamCorrection *get_cam_correction_ptr () {
-  return cam;
-}
-
 void free_cam_correction (CamCorrection *cam) {
 
   if (!cam) return;
 
+  int i;
   for (i = 0; i < cam->Nvalues; i++) {
     FREE (cam->matrix[i]);
-  }
+    FREE (cam->header[i]);
+  }
+  FREE (cam->phu);
+
+  free (cam->tstart);
+  free (cam->tstop);
 
   free (cam->matrix);
+  free (cam->header);
   free (cam);
 }
@@ -30,5 +34,9 @@
   ALLOCATE (cam, CamCorrection, 1);
 
+  cam->phu = NULL;
+  ALLOCATE (cam->header, Header *, Nseason*Nfilter*Nx*Ny);
   ALLOCATE (cam->matrix, Matrix *, Nseason*Nfilter*Nx*Ny);
+  ALLOCATE (cam->tstart, e_time,   Nseason);
+  ALLOCATE (cam->tstop,  e_time,   Nseason);
 
   cam->Nx      = Nx;  	   // for gpc1, should be 8
@@ -42,4 +50,6 @@
 
   ALLOCATE (cam->matrix, Matrix *, cam->Nvalues);
+
+  int i;
   for (i = 0; i < cam->Nvalues; i++) {
     cam->matrix[i] = NULL;
@@ -49,8 +59,9 @@
 }
 
-int load_cam_correction (char *filename) {
-
-  int i, ix, iy, dir, filter;
-  Header header;
+CamCorrection *load_cam_correction (char *filename) {
+
+  int i, ix, iy, season, filter;
+
+  Header *phu = gfits_alloc_header();
 
   /* open file for input */
@@ -62,21 +73,21 @@
 
   // read the PHU header
-  if (!gfits_load_header (f, &header)) return FALSE;
+  if (!gfits_load_header (f, phu)) return FALSE;
   
-  int Nbytes = gfits_data_size (&header);
+  int Nbytes = gfits_data_size (phu);
   fseeko (f, Nbytes, SEEK_CUR);
 
-  int Ndir, Nfilter, Nx, Ny, dX, dY, NxCCD, NyCCD;
-  if (!gfits_scan (&header, "NSEASON",  "%d", 1, &Nseason)) return FALSE;
-  if (!gfits_scan (&header, "NFILTER",  "%d", 1, &Nfilter)) return FALSE;
-  if (!gfits_scan (&header, "NX", 	"%d", 1, &Nx)) 	    return FALSE;
-  if (!gfits_scan (&header, "NY", 	"%d", 1, &Ny)) 	    return FALSE;
-  if (!gfits_scan (&header, "DX", 	"%d", 1, &dX)) 	    return FALSE;
-  if (!gfits_scan (&header, "DY", 	"%d", 1, &dY)) 	    return FALSE;
-
-  if (!gfits_scan (&header, "NX_CHIP", "%d", 1, &NxCCD))   return FALSE;
-  if (!gfits_scan (&header, "NY_CHIP", "%d", 1, &NyCCD))   return FALSE;
+  int Nseason, Nfilter, Nx, Ny, dX, dY, NxCCD, NyCCD;
+  if (!gfits_scan (phu, "NSEASON", "%d", 1, &Nseason)) return FALSE;
+  if (!gfits_scan (phu, "NFILTER", "%d", 1, &Nfilter)) return FALSE;
+  if (!gfits_scan (phu, "NX", 	   "%d", 1, &Nx))      return FALSE;
+  if (!gfits_scan (phu, "NY", 	   "%d", 1, &Ny))      return FALSE;
+  if (!gfits_scan (phu, "DX", 	   "%d", 1, &dX))      return FALSE;
+  if (!gfits_scan (phu, "DY", 	   "%d", 1, &dY))      return FALSE;
+  if (!gfits_scan (phu, "NX_CHIP", "%d", 1, &NxCCD))   return FALSE;
+  if (!gfits_scan (phu, "NY_CHIP", "%d", 1, &NyCCD))   return FALSE;
 
   CamCorrection *cam = alloc_cam_correction (Nx, Ny, Nfilter, Nseason);
+  cam->phu = phu;
 
   cam->dX      = dX;  	   // superpixel sampling, x-dir
@@ -86,23 +97,34 @@
   cam->NyCCD   = NyCCD;    // pixels per chip
 
+  for (i = 0; i < Nseason; i++) {
+    char field[256];
+    double value;
+
+    snprintf (field, 256, "TS_%03d", i);
+    if (!gfits_scan (phu, field, "%lf", 1, &value)) return FALSE;
+    cam->tstart[i] = ohana_mjd_to_sec(value);
+
+    snprintf (field, 256, "TE_%03d", i);
+    if (!gfits_scan (phu, field, "%lf", 1, &value)) return FALSE;
+    cam->tstop[i] = ohana_mjd_to_sec(value);
+  }
+
   while (TRUE) {
-    Header *header = NULL;
-    ALLOCATE (header, H
-
     // load data for this header : if not found, assume we hit the end of the file
-    if (!gfits_load_header (f, &theader)) break;
+    Header *header = gfits_alloc_header();
+    if (!gfits_load_header (f, header)) { 
+      free (header);
+      break;
+    }
     
-    if (!gfits_scan (&theader, "FILTER", "%d", 1, &filter)) return FALSE;
-    if (!gfits_scan (&theader, "SEASON", "%d", 1, &season)) return FALSE;
-
+    if (!gfits_scan (header, "FILTER", "%d", 1, &filter)) myAbort ("failed to find FILTER");
+    if (!gfits_scan (header, "SEASON", "%d", 1, &season)) myAbort ("failed to find SEASON");
+    if (!gfits_scan (header, "X_CHIP", "%d", 1, &ix))     myAbort ("failed to find X_CHIP");
+    if (!gfits_scan (header, "Y_CHIP", "%d", 1, &iy))     myAbort ("failed to find Y_CHIP");
     // XXX NOTE: astroflat.20150209.fits had ix and iy backwards in header
     // double-check that the new flats are OK
-    
-    if (!gfits_scan (&theader, "X_CHIP",  "%d", 1, &ix))      return FALSE;
-    if (!gfits_scan (&theader, "Y_CHIP",  "%d", 1, &iy))      return FALSE;
-
-    Matrix *matrix = NULL;
-    ALLOCATE (matrix, Matrix, 1);
-    if (!gfits_load_matrix (f, matrix, &theader)) break;
+
+    Matrix *matrix = gfits_alloc_matrix();
+    if (!gfits_load_matrix (f, matrix, header)) myAbort ("failed to read matrix");
 
     int index = ix + iy*cam->Nx + filter*cam->Nchips + season*cam->Nflats;
@@ -112,63 +134,45 @@
     myAssert (!cam->matrix[index], "entry already assigned?");
 
-    // assert that cam->matrix[index] is NULL?
     cam->matrix[index] = matrix;
     cam->header[index] = header;
   }
+  return cam;
+}
+
+int save_cam_correction (CamCorrection *cam, char *filename) {
+
+  int i;
+
+  /* open file for input */
+  FILE *f = fopen (filename, "w");
+  if (!f) {
+    gprint (GP_ERR, "can't open file for write : %s\n", filename);
+    return FALSE;
+  }
+
+  Matrix matrix;
+
+  gfits_modify_alt (cam->phu, "EXTEND", "%t",  1, TRUE);
+  gfits_fwrite_header  (f, cam->phu);
+  gfits_create_matrix (cam->phu, &matrix);
+  gfits_fwrite_matrix  (f, &matrix);
+  // write an empty matrix?
+
+  for (i = 0; i < cam->Nvalues; i++) {
+    if (!cam->matrix[i]) continue;
+    gfits_primary_to_extended (cam->header[i], "IMAGE", "Image Extension");
+    gfits_fwrite_header  (f, cam->header[i]);
+    gfits_fwrite_matrix  (f, cam->matrix[i]);
+    fflush (f);
+  }
+
   return TRUE;
 }
 
-int save_cam_correction (char *filename) {
-
-  int i, ix, iy, dir, filter;
-  Header header;
-
-  /* open file for input */
-  FILE *f = fopen (filename, "r");
-  if (f == (FILE *) NULL) {
-    gprint (GP_ERR, "can't open file for read : %s\n", filename);
-    return FALSE;
-  }
-
-  gfits_init_header (&header);
-  header.extend = TRUE;
-  gfits_create_header (&header);
-  gfits_create_matrix (&header, &matrix);
-
-  gfits_modify (&header, "NSEASON",  "%d", 1, camcoor->Nseason);
-  gfits_modify (&header, "NFILTER",  "%d", 1, camcoor->Nfilter);
-  gfits_modify (&header, "NX", 	     "%d", 1, camcoor->Nx);
-  gfits_modify (&header, "NY", 	     "%d", 1, camcoor->Ny);
-  gfits_modify (&header, "DX", 	     "%d", 1, camcoor->dX);
-  gfits_modify (&header, "DY", 	     "%d", 1, camcoor->dY);
-  gfits_modify (&header, "NX_CHIP",  "%d", 1, camcoor->NxCCD);
-  gfits_modify (&header, "NY_CHIP",  "%d", 1, camcoor->NyCCD);
-
-  gfits_fwrite_header  (f, &header);
-  gfits_fwrite_matrix  (f, &matrix);
-  gfits_free_header (&header);
-  gfits_free_matrix (&matrix);
-
-  for (i = 0; i < camcorr->Nvalues; i++) {
-
-    // I don't need to do this, do I?
-    // if (!gfits_scan (&theader, "FILTER", "%d", 1, &filter)); 
-    // if (!gfits_scan (&theader, "SEASON", "%d", 1, &season)); 
-    // if (!gfits_scan (&theader, "X_CHIP",  "%d", 1, &ix));    
-    // if (!gfits_scan (&theader, "Y_CHIP",  "%d", 1, &iy));    
-
-    if (!cam->matrix[i]) continue;
-
-    gfits_fwrite_header  (f, whatHeader);
-    gfits_fwrite_matrix  (f, cam->matrix[i]);
-  }
-
-  return TRUE;
-}
-
+# if (0)
 // input is:
 // chipID == octal chip ID (eg 40 for XY40)
 // filter == (01234 = grizy)
-int get_cam_correction (int chipID, int filter, float Xccd, float Yccd, double *dX, double *dY) {
+int get_cam_correction (CamCorrection *cam, int chipID, int filter, float Xccd, float Yccd, double *dX, double *dY) {
 
   *dX = 0.0;
@@ -215,28 +219,37 @@
   return TRUE;
 }
-
-float get_cam_correction_by_flatid (int flat_id, float Xccd, float Yccd) {
-
-  float dM = 0.0;
+# endif
+
+float get_cam_correction (CamCorrection *cam, int flat_id, float Xccd, float Yccd) {
+
+  if (!flat_id) return 0.0;
+
+  myAssert (flat_id > 0, "flat_id out of range");
+  myAssert (flat_id <= cam->Nvalues, "flat_id out of range");
 
   // validate the flat_id (not out of range?)
-  int seq = camcorr->IDtoSeq[flat_id];
+  // NOTE: we are setting the ID to be the sequence + 1 (match_camcorr_to_images.c:39)
+  int seq = flat_id - 1;
 
   Matrix *matrix = cam->matrix[seq];
-  NxModel = cam->matrix[index]->Naxis[0];
-
-  buffer = (float *) matrix->buffer;
-
-  jx = MAX(MIN(cam->NxCCD, Xccd / cam->dX), 0);
-  jy = MAX(MIN(cam->NyCCD, Yccd / cam->dY), 0);
-
-  value = buffer[jx + jy*NxModel];
-
-  dM = isnan(value) ? 0.0 : value;
+  myAssert (matrix, "oops");
+
+  int NxModel = matrix->Naxis[0];
+
+  float *buffer = (float *) matrix->buffer;
+
+  int jx = MAX(MIN(cam->NxCCD, Xccd / cam->dX), 0);
+  int jy = MAX(MIN(cam->NyCCD, Yccd / cam->dY), 0);
+
+  float value = buffer[jx + jy*NxModel];
+
+  float dM = isnan(value) ? 0.0 : value;
 
   return dM;
 }
 
-int merge_flatcorr_and_camcorr (FlatCorrectionTable *flatcorr, CamCorrection *camcorr) {
+CamCorrection *merge_flatcorr_and_camcorr (FlatCorrectionTable *flatcorr, CamCorrection *camcorr) {
+
+  int i, j, ix, iy, Nf, Ns;
 
   // this function is specifically tuned for merging the ubercal flats with the high-res flats
@@ -245,9 +258,11 @@
   // we have a highres flat with Nfilter, Nx, Ny images
 
-  myAssert (flatcorr->Nfilter <= camcorr->Nfilter, "unclear how to use more flatcorr filters");
   myAssert (camcorr->Nseason == 1, "no code to merge seasons flats to seasonal flats");
 
   // we need to create a new CamCorrection with Nx,Ny,Nfilter from camcorr and Nseason from flatcorr:
   CamCorrection *newcorr = alloc_cam_correction (camcorr->Nx, camcorr->Ny, camcorr->Nfilter, flatcorr->Nseason);
+  newcorr->phu = gfits_alloc_header();
+  gfits_create_header(newcorr->phu);
+
   newcorr->dX      = camcorr->dX;    // superpixel sampling, x-dir
   newcorr->dY      = camcorr->dY;    // superpixel sampling, y-dir
@@ -258,4 +273,26 @@
     newcorr->tstart[Ns] = flatcorr->tstart[Ns];
     newcorr->tstop[Ns]  = flatcorr->tstop[Ns];
+  }
+
+  gfits_modify (newcorr->phu, "NSEASON",  "%d", 1, newcorr->Nseason);
+  gfits_modify (newcorr->phu, "NFILTER",  "%d", 1, newcorr->Nfilter);
+  gfits_modify (newcorr->phu, "NX",       "%d", 1, newcorr->Nx);
+  gfits_modify (newcorr->phu, "NY",       "%d", 1, newcorr->Ny);
+  gfits_modify (newcorr->phu, "DX",       "%d", 1, newcorr->dX);
+  gfits_modify (newcorr->phu, "DY",       "%d", 1, newcorr->dY);
+  gfits_modify (newcorr->phu, "NX_CHIP",  "%d", 1, newcorr->NxCCD);
+  gfits_modify (newcorr->phu, "NY_CHIP",  "%d", 1, newcorr->NyCCD);
+
+  // XXX UNITS for tstart, tstop
+  for (Ns = 0; Ns < newcorr->Nseason; Ns++) {
+    char field[256];
+    double value;
+    snprintf (field, 256, "TS_%03d", Ns);
+    value = ohana_sec_to_mjd (newcorr->tstart[Ns]);
+    if (!gfits_modify (newcorr->phu, field, "%lf", 1, value)) return FALSE;
+
+    snprintf (field, 256, "TE_%03d", Ns);
+    value = ohana_sec_to_mjd (newcorr->tstop[Ns]);
+    if (!gfits_modify (newcorr->phu, field, "%lf", 1, value))  return FALSE;
   }
 
@@ -265,12 +302,29 @@
       for (ix = 0; ix < newcorr->Nx; ix++) {
 	for (iy = 0; iy < newcorr->Ny; iy++) {
-	  int index = ix + iy*newcorr->Nx + Nf*newcorr->Nchips + Ns*newcorr->Nflats;
-	  ALLOCATE (newcorr->matrix[index], Matrix, 1);
-	  
 	  // camcorr only had one season
+	  int idxNew = ix + iy*newcorr->Nx + Nf*newcorr->Nchips + Ns*newcorr->Nflats;
 	  int idxOld = ix + iy*camcorr->Nx + Nf*camcorr->Nchips;
 
-	  // allocates the buffer 
-	  gfits_copy_matrix (camcorr->matrix[idxOld], newcorr->matrix[index]);
+	  if (!camcorr->matrix[idxOld]) continue;
+	  myAssert (camcorr->header[idxOld], "oops");
+
+	  // these allocate the structures but not the data
+	  newcorr->matrix[idxNew] = gfits_alloc_matrix();
+	  newcorr->header[idxNew] = gfits_alloc_header();
+
+	  // these allocate the buffers
+	  gfits_copy_header (camcorr->header[idxOld], newcorr->header[idxNew]);
+	  gfits_copy_matrix (camcorr->matrix[idxOld], newcorr->matrix[idxNew]);
+
+	  // using hard-wired filter names:
+	  if (!gfits_modify (newcorr->header[idxNew], "FILTNAME", "%s", 1, filters[Nf])) myAbort ("failed to set FILTNAME");
+	  if (!gfits_modify (newcorr->header[idxNew], "FILTER", "%d", 1, Nf)) myAbort ("failed to set FILTER");
+	  if (!gfits_modify (newcorr->header[idxNew], "SEASON", "%d", 1, Ns)) myAbort ("failed to set SEASON");
+	  if (!gfits_modify (newcorr->header[idxNew], "X_CHIP", "%d", 1, ix)) myAbort ("failed to set X_CHIP");
+	  if (!gfits_modify (newcorr->header[idxNew], "Y_CHIP", "%d", 1, iy)) myAbort ("failed to set Y_CHIP");
+
+	  char extname[80];
+	  snprintf (extname, 80, "td_dM_%d_%s_%d_%d", Ns, filters[Ns], ix, iy);
+	  if (!gfits_modify (newcorr->header[idxNew], "EXTNAME", "%s", 1, extname)) myAbort ("failed to set EXTNAME");
 	}
       }
@@ -283,9 +337,8 @@
 
   // loop over the flatcorr images and match from image[seq] to newcorr:
-
   for (i = 0; i < flatcorr->Nimage; i++) {
 
     int ID = flatcorr->image[i].ID;
-    myAssert (flatcorrTable->IDtoSeq[ID] == i, "oops");
+    myAssert (flatcorr->IDtoSeq[ID] == i, "oops");
 
     // find the season (these are inherited from flatcorr, so they must match
@@ -300,19 +353,29 @@
 
     // find the chip and filter from photcode:
-    iy = flatcorr->image[i].photcode % 10;
-    ix = (int)(flatcorr->image[i].photcode / 10) % 10;
-    filter = (int)(flatcorr->image[i].photcode / 100) % 10;
+    int iy = photcode % 10;
+    int ix = (int)(photcode / 10) % 10;
+    int filter = (int)(photcode / 100) % 10;
 	      
+    myAssert (ix     < newcorr->Nx, "oops");
+    myAssert (iy     < newcorr->Ny, "oops");
+    myAssert (filter < newcorr->Nfilter, "oops");
+
     // seq is the flatcorr entry of interest
-    int seq = ix + iy * newcorr->Nx + filter * newcorr->Nchips + season * camcorr->Nflat;
+    int seq = ix + iy * newcorr->Nx + filter * newcorr->Nchips + season * newcorr->Nflats;
 
     // we now have newcorr->matrix[seq]
+    // flatcorr contains entries for unpopulated corner chips, but camcorr does not
     Matrix *newDelta = newcorr->matrix[seq];
+    if (!newDelta) continue;
+
+    float *values = (float *) newDelta->buffer;
 
     int jx, jy;
+    int NxModel = newDelta->Naxis[0];
+    int NyModel = newDelta->Naxis[1];
 
     // now loop over the newcorr pixels to get the flatcorr value:
-    for (jx = 0; jx < newcorr->NxCCD; jx++) {
-      for (jy = 0; jy < newcorr->NyCCD; jy++) {
+    for (jx = 0; jx < NxModel; jx++) {
+      for (jy = 0; jy < NyModel; jy++) {
 	
 	int chipX = jx * newcorr->dX;
@@ -320,13 +383,13 @@
 
 	// get the flatcorr offset from this chip coordinate
-	float delta = FlatCorrectionOffset (flatcorr, flatcorr->image[i].ID, chipX, chipY);
-
-	newDelta->buffer[jx + jy*NxCCD] += flatcorr->offset[i][Jx][Jy];
+	float delta = FlatCorrectionOffset (flatcorr, ID, chipX, chipY);
+
+	values[jx + jy*NxModel] += delta;
       }
     }
   }    
 
-  return TRUE;
-}
-
-
+  return newcorr;
+}
+
+
Index: /trunk/Ohana/src/uniphot/src/initialize_setphot.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/initialize_setphot.c	(revision 39271)
+++ /trunk/Ohana/src/uniphot/src/initialize_setphot.c	(revision 39272)
@@ -35,14 +35,9 @@
 
   CAM_FILE = NULL;
-  if ((N = get_argument (argc, argv, "-CAM"))) {
+  if ((N = get_argument (argc, argv, "-cam-flat"))) {
     remove_argument (N, &argc, argv);
     char *tmpfile = strcreate (argv[N]);
     CAM_FILE = abspath (tmpfile, DVO_MAX_PATH);
     remove_argument (N, &argc, argv);
-  }
-  CAM_RESET = FALSE;
-  if ((N = get_argument (argc, argv, "-CAM-reset"))) {
-    remove_argument (N, &argc, argv);
-    CAM_RESET = TRUE;
   }
 
@@ -131,4 +126,8 @@
     remove_argument (N, &argc, argv);
     UBERCAL = TRUE;
+    if (!CAM_FILE) {
+      fprintf (stderr, "ubercal now requires a high-res static flat-file: -cam-flat filename\n");
+      exit (2);
+    }
   }
 
Index: /trunk/Ohana/src/uniphot/src/load_zpt_table.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/load_zpt_table.c	(revision 39271)
+++ /trunk/Ohana/src/uniphot/src/load_zpt_table.c	(revision 39272)
@@ -253,5 +253,5 @@
     } else {
       if (!gfits_scan (&header, "FILTER", "%s", 1, filter)) { 
-	fprintf (stderr, "cannot find FILTER in header of %s, using %s\n", filename, filters_uc[nfilter]);
+	fprintf (stderr, "warning: cannot find FILTER in header of %s, using %s\n", filename, filters_uc[nfilter]);
 	strcpy (filter, filters_uc[nfilter]);
 	// fclose (f);
Index: /trunk/Ohana/src/uniphot/src/match_camcorr_to_images.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/match_camcorr_to_images.c	(revision 39271)
+++ /trunk/Ohana/src/uniphot/src/match_camcorr_to_images.c	(revision 39272)
@@ -4,9 +4,7 @@
 // the photcode is used to find the actual flat correction
 
-int match_camcorr_to_images (Image *image, off_t Nimage) {
+int match_camcorr_to_images (Image *image, off_t Nimage, CamCorrection *camcorr) {
 
   int i, j;
-
-  CamCorrection *camcorr = get_cam_correction_ptr ();  
 
   // we have an array of CamCorrection->matrix values, where each matrix is a flat-field image
@@ -19,4 +17,6 @@
   int maxCode = 10576;
 
+  int Nmissed = 0;
+  
   for (i = 0; i < Nimage; i++) {
     if (!image[i].photcode) continue; // skip PHU images
@@ -30,11 +30,12 @@
       if (image[i].tzero > camcorr->tstop[j]) continue;
 
-      int iy = image[i].photcode % 10;
-      int ix = (int)(image[i].photcode / 10) % 10;
-      int filter = (int)(image[i].photcode / 100) % 10;
+      int photcode = image[i].photcode;
+      int iy =  photcode % 10;
+      int ix = (int)(photcode / 10) % 10;
+      int filter = (int)(photcode / 100) % 10;
 
-      int seq = ix + iy * camcorr->Nx + filter * camcorr->Nchips + j * camcorr->Ngroup;
-
-      image[i].photom_map_id = camcorr->imageID[seq].ID;
+      // we add one so photom_map_id = 0 can mean no map
+      int seq = ix + iy * camcorr->Nx + filter * camcorr->Nchips + j * camcorr->Nflats;
+      image[i].photom_map_id = seq + 1;
       found = TRUE;
     }
Index: /trunk/Ohana/src/uniphot/src/setphot.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/setphot.c	(revision 39271)
+++ /trunk/Ohana/src/uniphot/src/setphot.c	(revision 39272)
@@ -7,7 +7,7 @@
   FITS_DB db;
   ZptTable *zpts;
-  Image *image;
 
-  // FlatCorrectionTable flatcorrTable;
+  CamCorrection *camcorr = NULL;
+  FlatCorrectionTable flatcorrTable;
 
   /* get configuration info, args, lockfile */
@@ -31,14 +31,15 @@
     // XXX should this program save any old copy of this file?
 
-    if (!load_cam_correction (CAM_FILE)) {
+    CamCorrection *rawcorr = load_cam_correction (CAM_FILE);
+    if (!rawcorr) {
       fprintf (stderr, "failed to load camera-static flat-field correction\n");
       exit (2);
     }
-    merge_flatcorr_with_cam (flatcorrTable);
+    camcorr = merge_flatcorr_and_camcorr (&flatcorrTable, rawcorr);
 
     char newflatfile[DVO_MAX_PATH];
-    int size = snprintf (newflatfile, DVO_MAX_PATH, "%s/flatfield.fits", CATDIR);
+    size = snprintf (newflatfile, DVO_MAX_PATH, "%s/flatfield.fits", CATDIR);
     assert (size < DVO_MAX_PATH);
-    save_cam_correction (newflatfile);
+    save_cam_correction (camcorr, newflatfile);
   } else {
     zpts = load_zpt_table (argv[1], &Nzpts);
@@ -48,5 +49,5 @@
 
   // load images 
-  image  = load_images_setphot (&db, &Nimage);
+  Image *image  = load_images_setphot (&db, &Nimage);
   if (!UPDATE) dvo_image_unlock (&db); 
   
@@ -56,9 +57,9 @@
     // we are going to deprecate the flatcorr imaage lookup
     // match_flatcorr_to_images (image, Nimage, &flatcorrTable);
-    match_camcorr_to_images (image, Nimage);
+    match_camcorr_to_images (image, Nimage, camcorr);
   } 
 
   if (!IMAGES_ONLY) {
-    status = update_dvo_setphot (image, Nimage);
+    status = update_dvo_setphot (image, Nimage, camcorr);
   }
 
Index: /trunk/Ohana/src/uniphot/src/update_catalog_setphot.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/update_catalog_setphot.c	(revision 39271)
+++ /trunk/Ohana/src/uniphot/src/update_catalog_setphot.c	(revision 39272)
@@ -1,5 +1,5 @@
 # include "setphot.h"
 
-void update_catalog_setphot (Catalog *catalog, Image *image, off_t *index, off_t Nimage) {
+void update_catalog_setphot (Catalog *catalog, Image *image, off_t *index, off_t Nimage, CamCorrection *camcorr) {
 
   off_t i, j, found;
@@ -7,6 +7,4 @@
   // if we are resetting, reset all flags
   DVOMeasureFlags photomFlags = ID_MEAS_POOR_PHOTOM | ID_MEAS_SKIP_PHOTOM | ID_MEAS_PHOTOM_UBERCAL;
-
-  CamCorrection *camcorr = get_cam_correction_ptr ();  
 
   found = 0;    
@@ -28,5 +26,5 @@
       int flat_id = image[id].photom_map_id;
       if (flat_id > 0) {
-	Mflat = CamCorrectionOffset (camcorr, flat_id, catalog[0].measure[m].Xccd, catalog[0].measure[m].Yccd);
+	Mflat = get_cam_correction (camcorr, flat_id, catalog[0].measure[m].Xccd, catalog[0].measure[m].Yccd);
       }
 
Index: /trunk/Ohana/src/uniphot/src/update_dvo_setphot.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/update_dvo_setphot.c	(revision 39271)
+++ /trunk/Ohana/src/uniphot/src/update_dvo_setphot.c	(revision 39272)
@@ -3,5 +3,5 @@
 
 // XXX convert this to use the ImageSubset to save space
-int update_dvo_setphot (Image *image, off_t Nimage, FlatCorrectionTable *flatcorr) {
+int update_dvo_setphot (Image *image, off_t Nimage, CamCorrection *camcorr) {
 
   SkyTable *sky = NULL;
@@ -73,5 +73,5 @@
     }
 
-    update_catalog_setphot (&catalog, image, index, Nimage, flatcorr);
+    update_catalog_setphot (&catalog, image, index, Nimage, camcorr);
 
     if (!UPDATE) {
