Index: /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/include/uniphot.h
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/include/uniphot.h	(revision 33132)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/include/uniphot.h	(revision 33133)
@@ -67,4 +67,5 @@
 int          VERBOSE;
 int          UBERCAL; // load the supplied ubercal zero point fits table (with flat-field corrections)
+int          NO_METADATA; // the supplied ubercal data has no descriptive metadata
 int          NLOOP;
 int          TimeSelect;
@@ -77,17 +78,4 @@
 time_t 	     TSTOP;
 PhotCode    *photcode;
-
-// hard-wired values which describe the ubercal analysis
-# define NFILTER 5
-# define NSEASON 4
-# define NCHIP_X 8
-# define NCHIP_Y 8
-# define NCELL_X 2
-# define NCELL_Y 2
-
-// these are initialized by initialize_setphot (in initialize.c)
-e_time tstart    [NSEASON];
-e_time tstop     [NSEASON];
-char   filter    [NFILTER];
 
 enum {black, white, red, orange, yellow, green, blue, indigo, violet};
@@ -150,4 +138,5 @@
 
 ZptTable *load_zpt_ubercal (char *filename, int *nzpts, FlatCorrectionTable *flatcorrTable);
+ZptTable *load_zpt_ubercal_nometadata (char *filename, int *nzpts, FlatCorrectionTable *flatcorrTable);
 int match_flatcorr_to_images (Image *image, off_t Nimage, FlatCorrectionTable *flatcorrTable);
 
Index: /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/args.c
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/args.c	(revision 33132)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/args.c	(revision 33133)
@@ -88,4 +88,10 @@
   }
 
+  NO_METADATA = FALSE;
+  if ((N = get_argument (argc, argv, "-no-metadata"))) {
+    remove_argument (N, &argc, argv);
+    NO_METADATA = TRUE;
+  }
+
   UPDATE = FALSE;
   if ((N = get_argument (argc, argv, "-update"))) {
Index: /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/initialize.c
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/initialize.c	(revision 33132)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/initialize.c	(revision 33133)
@@ -42,20 +42,4 @@
     exit (1);
   }
-
-  // we have hard-coded the MJD season ranges from Eddie in uniphot.h
-
-  double tstart_mjd[] = {55000.0, 55296.0, 55327.0, 55662.0};
-  double tstop_mjd[]  = {55296.0, 55327.0, 55662.0, 60000.0};
-  filter[0] = 'g';
-  filter[1] = 'r';
-  filter[2] = 'i';
-  filter[3] = 'z';
-  filter[4] = 'y';
-
-  int i;
-  for (i = 0; i < NSEASON; i++) {
-    tstart[i] = ohana_mjd_to_sec(tstart_mjd[i]);
-    tstop[i]  = ohana_mjd_to_sec(tstop_mjd[i]);
-  }
 }
 
Index: /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/load_zpt_table.c
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/load_zpt_table.c	(revision 33132)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/load_zpt_table.c	(revision 33133)
@@ -42,9 +42,18 @@
 }
 
-ZptTable *load_zpt_ubercal (char *filename, int *nzpts, FlatCorrectionTable *flatcorrTable) {
+/* Slightly more generic loader than the ubercal version.  Still assumes Nfilters x Nseasons
+   the input file must contain the following:
+   PHU Header : NFILTER, NSEASON, NCHIP_X, NCHIP_Y, NCELL_X, NCELL_Y, TS0_nnnn (season nnnn start mjd), TS1_nnnn (season nnnn end mjd)
+   
+   NSEASON * 2 extensions with
+   TABLE : mjd, zpt; Header: FILTER
+   IMAGE : 1D array of flat offsets
+*/
+
+ZptTable *load_zpt_ubercal(char *filename, int *nzpts, FlatCorrectionTable *flatcorrTable) {
 
   int i, nfilter, nseason, ix, iy, ixc, iyc, Ncol, seq;
   off_t Nrow;
-  char type[16];
+  char type[16], filter[80];
   int Nzpts, NZPTS;
   ZptTable *zpts;
@@ -54,4 +63,14 @@
   FTable ftable;
 
+  // parameters describing the flat-field correction
+  int NSEASON;
+  int NFILTER;
+  int NCHIP_X;
+  int NCHIP_Y;
+  int NCELL_X;
+  int NCELL_Y;
+  int CHIP_DX;
+  int CHIP_DY;
+
   FILE *f;
 
@@ -78,4 +97,72 @@
   NZPTS = 0;
   ALLOCATE (zpts, ZptTable, NZPTS);
+
+  // this function would be better if we read the list of filters, seasons, and the dimensions from the header
+  // for current testing, make fake smfs that correspond to specific chips, filter, and mjd ranges?
+
+  if (!gfits_scan (&header, "NSEASON", "%d", 1, &NSEASON)) { 
+    fprintf (stderr, "cannot find NSEASON in header of %s\n", filename);
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_scan (&header, "NFILTER", "%d", 1, &NFILTER)) { 
+    fprintf (stderr, "cannot find NFILTER in header of %s\n", filename);
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_scan (&header, "NCHIP_X", "%d", 1, &NCHIP_X)) { 
+    fprintf (stderr, "cannot find NCHIP_X in header of %s\n", filename);
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_scan (&header, "NCHIP_Y", "%d", 1, &NCHIP_Y)) { 
+    fprintf (stderr, "cannot find NCHIP_Y in header of %s\n", filename);
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_scan (&header, "NCELL_X", "%d", 1, &NCELL_X)) { 
+    fprintf (stderr, "cannot find NCELL_X in header of %s\n", filename);
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_scan (&header, "NCELL_Y", "%d", 1, &NCELL_Y)) { 
+    fprintf (stderr, "cannot find NCELL_Y in header of %s\n", filename);
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_scan (&header, "CHIP_DX", "%d", 1, &CHIP_DX)) { 
+    fprintf (stderr, "cannot find CHIP_DX in header of %s\n", filename);
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_scan (&header, "CHIP_DY", "%d", 1, &CHIP_DY)) { 
+    fprintf (stderr, "cannot find CHIP_DY in header of %s\n", filename);
+    fclose (f);
+    return NULL;
+  }
+
+  flatcorrTable->Nseason = NSEASON;
+  ALLOCATE (flatcorrTable->tstart, e_time, NSEASON);
+  ALLOCATE (flatcorrTable->tstop,  e_time, NSEASON);
+
+  for (i = 0; i < NSEASON; i++) {
+    double mjdvalue;
+    char name[9];
+    snprintf (name, 9, "TS0_%04d", i);
+    if (!gfits_scan (&header, name, "%lf", 1, &mjdvalue)) { 
+      fprintf (stderr, "cannot find %s in header of %s\n", name, filename);
+      fclose (f);
+      return NULL;
+    }
+    flatcorrTable->tstart[i] = ohana_mjd_to_sec(mjdvalue);
+
+    snprintf (name, 9, "TS1_%04d", i);
+    if (!gfits_scan (&header, name, "%lf", 1, &mjdvalue)) { 
+      fprintf (stderr, "cannot find %s in header of %s\n", name, filename);
+      fclose (f);
+      return NULL;
+    }
+    flatcorrTable->tstop[i]  = ohana_mjd_to_sec(mjdvalue);
+  }
 
   // we have 5 filters, and 4 flat-field correction sets for each
@@ -115,15 +202,184 @@
       zpts[i+Nzpts].time = ohana_mjd_to_sec(mjd[i]);
       zpts[i+Nzpts].zpt = zp[i];
-      zpts[i+Nzpts].zpt_err = zperr[i];
+      // zpts[i+Nzpts].zpt_err = zperr[i];
     }
     Nzpts += Nrow;
 
-    // the image contains the flat-field corrections
+    // the image contains the flat-field corrections for a specific filter
 
     // load data for this header 
     if (!gfits_load_header (f, &header)) return (NULL);
 
+    if (!gfits_scan (&theader, "FILTER", "%s", 1, filter)) { 
+      fprintf (stderr, "cannot find FILTER in header of %s\n", filename);
+      fclose (f);
+      return NULL;
+    }
+
     // read the fits table bytes
     if (!gfits_fread_matrix (f, &matrix, &header)) return (NULL);
+    assert (header.bitpix == -64); // hardwired as a double
+    double *offset = (double *) matrix.buffer;
+
+    for (nseason = 0; nseason < NSEASON; nseason++) { // seasons
+      for (iy = 0; iy < NCHIP_Y; iy++) { // y-chip
+	for (ix = 0; ix < NCHIP_X; ix++) { // x-chip
+
+	  // photcode name
+	  char photname[64];
+	  snprintf (photname, 64, "GPC1.%s.XY%d%d", filter, ix, iy);
+	  // note that the XY00, XY07, etc, chips will have photcode values of 0
+
+	  flatcorrTable->image[Nimage].photcode = GetPhotcodeCodebyName(photname);
+	  flatcorrTable->image[Nimage].Nx = NCELL_X;
+	  flatcorrTable->image[Nimage].Ny = NCELL_Y;
+	  flatcorrTable->image[Nimage].ID = corrID;
+	  flatcorrTable->image[Nimage].DX = CHIP_DX;
+	  flatcorrTable->image[Nimage].DY = CHIP_DY;
+	  flatcorrTable->image[Nimage].tstart = flatcorrTable->tstart[nseason];
+	  flatcorrTable->image[Nimage].tstop  = flatcorrTable->tstop[nseason];
+	  
+	  // This enforces a 180 chip rotation for XY3n - XY7n & is only known to be valid for GPC1 (the XYnn names as well)
+	  for (iyc = 0; iyc < NCELL_Y; iyc++) {
+	    for (ixc = 0; ixc < NCELL_X; ixc++) {
+	      if (ix > 3) {
+		seq = nfilter*NSEASON*NCHIP_X*NCHIP_Y*NCELL_X*NCELL_Y + nseason*NCHIP_X*NCHIP_Y*NCELL_X*NCELL_Y + (iy*NCELL_Y + NCELL_Y - 1 - iyc)*NCHIP_X*NCELL_X + (ix*NCELL_X + NCELL_X - 1 - ixc);
+	      } else {
+		seq = nfilter*NSEASON*NCHIP_X*NCHIP_Y*NCELL_X*NCELL_Y + nseason*NCHIP_X*NCHIP_Y*NCELL_X*NCELL_Y + (iy*NCELL_Y + iyc)*NCHIP_X*NCELL_X + (ix*NCELL_X + ixc);
+	      }
+	      assert (!flatcorrTable->corr[seq].ID);
+	      flatcorrTable->corr[seq].x = ixc;
+	      flatcorrTable->corr[seq].y = iyc;
+	      flatcorrTable->corr[seq].offset = offset[seq];
+	      flatcorrTable->corr[seq].ID = corrID;
+	    }
+	  }
+	  corrID ++;
+	  Nimage ++;
+	}
+      }
+    }	      
+  }
+
+  /*** convert from corr,image format to offsets ***/
+  FlatCorrectionInternal (flatcorrTable);
+
+  fprintf (stderr, "loaded %d zero points\n", Nzpts);
+
+  *nzpts = Nzpts;
+  return zpts;
+}
+
+ZptTable *load_zpt_ubercal_nometadata (char *filename, int *nzpts, FlatCorrectionTable *flatcorrTable) {
+
+  int i, nfilter, nseason, ix, iy, ixc, iyc, Ncol, seq;
+  off_t Nrow;
+  char type[16];
+  int Nzpts, NZPTS;
+  ZptTable *zpts;
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  // hard-wired values which describe the ubercal analysis
+  int NFILTER = 5;
+  int NSEASON = 4;
+  int NCHIP_X = 8;
+  int NCHIP_Y = 8;
+  int NCELL_X = 2;
+  int NCELL_Y = 2;
+  int CHIP_DX = 4880;
+  int CHIP_DY = 4864;
+
+  flatcorrTable->Nseason = NSEASON;
+  ALLOCATE (flatcorrTable->tstart, e_time, NSEASON);
+  ALLOCATE (flatcorrTable->tstop,  e_time, NSEASON);
+
+  char filter[] = {'g', 'r', 'i', 'z', 'y'};
+
+  double tstart_mjd[] = {55000.0, 55296.0, 55327.0, 55662.0};
+  double tstop_mjd[]  = {55296.0, 55327.0, 55662.0, 60000.0};
+
+  for (i = 0; i < NSEASON; i++) {
+    flatcorrTable->tstart[i] = ohana_mjd_to_sec(tstart_mjd[i]);
+    flatcorrTable->tstop[i]  = ohana_mjd_to_sec(tstop_mjd[i]);
+  }
+
+  FILE *f = fopen (filename, "r");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open zpt table file %s\n", filename);
+    exit (1);
+  }
+
+  /* load in PHU segment (ignore) */
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read Flat Correction header\n");
+    fclose (f);
+    return (NULL);
+  }
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read Flat Correction matrix\n");
+    gfits_free_header (&header);
+    fclose (f);
+    return (NULL);
+  }
+
+  Nzpts = 0;
+  NZPTS = 0;
+  ALLOCATE (zpts, ZptTable, NZPTS);
+
+  // this function would be better if we read the list of filters, seasons, and the dimensions from the header
+  // for current testing, make fake smfs that correspond to specific chips, filter, and mjd ranges?
+
+  // we have 5 filters, and 4 flat-field correction sets for each
+  flatcorrTable->Ncorr = NFILTER*NSEASON*NCHIP_X*NCHIP_Y*NCELL_X*NCELL_Y;
+  flatcorrTable->Nimage = NFILTER*NSEASON*NCHIP_X*NCHIP_Y;
+
+  ALLOCATE (flatcorrTable->corr, FlatCorrection, flatcorrTable->Ncorr);
+  ALLOCATE (flatcorrTable->image, FlatCorrectionImage, flatcorrTable->Nimage);
+  memset (flatcorrTable->corr, 0, flatcorrTable->Ncorr*sizeof(FlatCorrection));
+
+  int corrID = 1;
+  int Nimage = 0;
+  ftable.header = &theader;
+  for (nfilter = 0; nfilter < NFILTER; nfilter++) {
+    // load data for this header 
+    if (!gfits_load_header (f, &theader)) return (NULL);
+
+    // read the fits table bytes
+    if (!gfits_fread_ftable_data (f, &ftable, FALSE)) return (NULL);
+  
+    // skip over remaining bytes in data segment
+    fseeko (f, ftable.datasize - ftable.validsize, SEEK_CUR);
+
+    // need to create and assign to flat-field correction
+    double *mjd = gfits_get_bintable_column_data (&theader, &ftable, "mjd_obs", type, &Nrow, &Ncol);
+    assert (!strcmp(type, "double"));
+
+    double *zp = gfits_get_bintable_column_data (&theader, &ftable, "zp", type, &Nrow, &Ncol);
+    assert (!strcmp(type, "double"));
+      
+    // float *zperr = gfits_get_bintable_column_data (&theader, &ftable, "resid", type, &Nrow, &Ncol);
+    // assert (!strcmp(type, "float"));
+      
+    NZPTS += Nrow;
+    REALLOCATE (zpts, ZptTable, NZPTS);
+    for (i = 0; i < Nrow; i++) {
+      zpts[i+Nzpts].time = ohana_mjd_to_sec(mjd[i]);
+      zpts[i+Nzpts].zpt = zp[i];
+      // zpts[i+Nzpts].zpt_err = zperr[i];
+    }
+    Nzpts += Nrow;
+
+    // the image contains the flat-field corrections
+
+    // load data for this header 
+    if (!gfits_load_header (f, &header)) return (NULL);
+
+    // read the fits table bytes
+    if (!gfits_fread_matrix (f, &matrix, &header)) return (NULL);
+    assert (header.bitpix == -64); // hardwired as a double
+    double *offset = (double *) matrix.buffer;
 
     for (nseason = 0; nseason < NSEASON; nseason++) { // seasons
@@ -140,8 +396,8 @@
 	  flatcorrTable->image[Nimage].Ny = NCELL_Y;
 	  flatcorrTable->image[Nimage].ID = corrID;
-	  flatcorrTable->image[Nimage].DX = 4880;
-	  flatcorrTable->image[Nimage].DY = 4864;
-	  flatcorrTable->image[Nimage].tstart = tstart[nseason];
-	  flatcorrTable->image[Nimage].tstop  = tstop[nseason];
+	  flatcorrTable->image[Nimage].DX = CHIP_DX;
+	  flatcorrTable->image[Nimage].DY = CHIP_DY;
+	  flatcorrTable->image[Nimage].tstart = flatcorrTable->tstart[nseason];
+	  flatcorrTable->image[Nimage].tstop  = flatcorrTable->tstop[nseason];
 	  
 	  for (iyc = 0; iyc < NCELL_Y; iyc++) {
@@ -155,5 +411,5 @@
 	      flatcorrTable->corr[seq].x = ixc;
 	      flatcorrTable->corr[seq].y = iyc;
-	      flatcorrTable->corr[seq].offset = matrix.buffer[seq];
+	      flatcorrTable->corr[seq].offset = offset[seq];
 	      flatcorrTable->corr[seq].ID = corrID;
 	    }
Index: /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/match_flatcorr_to_images.c
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/match_flatcorr_to_images.c	(revision 33132)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/match_flatcorr_to_images.c	(revision 33133)
@@ -18,15 +18,10 @@
   maxCode ++; // we want the outer bound, not the last value
 
-  ALLOCATE (index, short *, NSEASON);
-  for (i = 0; i < NSEASON; i++) {
+  ALLOCATE (index, short *, flatcorrTable->Nseason);
+  for (i = 0; i < flatcorrTable->Nseason; i++) {
       ALLOCATE (index[i], short, maxCode);
       for (j = 0; j < maxCode; j++) {
 	index[i][j] = -1;
       }
-  }
-
-  for (j = 0; j < NSEASON; j++) {
-    assert (tstart[j]);
-    assert (tstop[j]);
   }
 
@@ -37,6 +32,6 @@
 
     // which season?
-    for (j = 0; j < NSEASON; j++) {
-      if (flatcorrTable->image[i].tstart == tstart[j]) {
+    for (j = 0; j < flatcorrTable->Nseason; j++) {
+      if (flatcorrTable->image[i].tstart == flatcorrTable->tstart[j]) {
 	assert (index[j][flatcorrTable->image[i].photcode] == -1);
 	index[j][flatcorrTable->image[i].photcode] = i;
@@ -45,12 +40,12 @@
     }
   }
-
+  
   for (i = 0; i < Nimage; i++) {
     if (!image[i].photcode) continue; // skip PHU images
 
     int found = FALSE;
-    for (j = 0; !found && (j < NSEASON); j++) {
-      if (image[i].tzero < tstart[j]) continue;
-      if (image[i].tzero > tstop[j]) continue;
+    for (j = 0; !found && (j < flatcorrTable->Nseason); j++) {
+      if (image[i].tzero < flatcorrTable->tstart[j]) continue;
+      if (image[i].tzero > flatcorrTable->tstop[j]) continue;
 
       int seq = index[j][image[i].photcode];
Index: /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/match_zpts_to_images.c
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/match_zpts_to_images.c	(revision 33132)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/match_zpts_to_images.c	(revision 33133)
@@ -72,4 +72,8 @@
     image[Ni].dMcal = zpts[Nz].zpt_err;
     image[Ni].flags &= ~ID_IMAGE_PHOTOM_NOCAL; // clear the NOCAL flag
+    // image[Ni].flags |=  ID_IMAGE_PHOTOM_EXTERN; XXX do we want some flag like this?
+    if (UBERCAL) {
+      image[Ni].flags |=  ID_IMAGE_PHOTOM_UBERCAL;
+    }
     zpts[Nz].found = TRUE;
     NImatch ++;
Index: /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/setphot.c
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/setphot.c	(revision 33132)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/setphot.c	(revision 33133)
@@ -19,5 +19,12 @@
 
   if (UBERCAL) {
-    zpts = load_zpt_ubercal (argv[1], &Nzpts, &flatcorrTable);
+    if (NO_METADATA) {
+      // the simple files from Eddie have no internal metadata describing the corrections,
+      // so they must be manually encoded
+      zpts = load_zpt_ubercal_nometadata (argv[1], &Nzpts, &flatcorrTable);
+    } else {
+      zpts = load_zpt_ubercal (argv[1], &Nzpts, &flatcorrTable);
+    }
+
     char flatcorrfile[64];
     snprintf (flatcorrfile, 64, "%s/flatcorr.fits", CATDIR);
Index: /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/update_catalog_setphot.c
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/update_catalog_setphot.c	(revision 33132)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/uniphot/src/update_catalog_setphot.c	(revision 33133)
@@ -96,4 +96,9 @@
       catalog[0].measure[m].Mcal = Mcal + Mcal_offset;
       catalog[0].measure[m].dMcal = dMcal;
+
+      if (UBERCAL) {
+	catalog[0].measure[m].dbFlags |=  ID_MEAS_PHOTOM_UBERCAL;
+      }
+
       found ++;
     }
