Index: /branches/eam_branches/ipp-20111122/Ohana/src/libautocode/def/FlatCorrection.d
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/libautocode/def/FlatCorrection.d	(revision 33100)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/libautocode/def/FlatCorrection.d	(revision 33100)
@@ -0,0 +1,10 @@
+STRUCT  FlatCorrection
+EXTNAME FLAT_CORRECTION
+TYPE    BINTABLE
+SIZE    16
+
+FIELD   x,	   X,	           int
+FIELD   y,	   Y,	           int
+FIELD   offst,     OFFSET,	   float
+FIELD   photcode,  PHOTCODE,	   short
+FIELD   padding,   PADDING,	   short
Index: /branches/eam_branches/ipp-20111122/Ohana/src/libautocode/def/FlatCorrectionImage.d
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/libautocode/def/FlatCorrectionImage.d	(revision 33100)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/libautocode/def/FlatCorrectionImage.d	(revision 33100)
@@ -0,0 +1,14 @@
+STRUCT  FlatCorrectionImage
+EXTNAME FLAT_CORRECTION_IMAGE
+TYPE    BINTABLE
+SIZE    32
+
+FIELD   tstart,	   TSTART,	   e_time, 
+FIELD   tstop,	   TSTOP,	   e_time, 
+FIELD   ID,	   ID,	           int
+FIELD   Nx,	   NX,	           int
+FIELD   Ny,	   NY,	           int
+FIELD   DX,	   DX,             int
+FIELD   DY,        DY,             int
+FIELD   photcode,  PHOTCODE,	   short
+FIELD   padding,   PADDING,	   short
Index: /branches/eam_branches/ipp-20111122/Ohana/src/libdvo/src/flatcorr_io.c
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/libdvo/src/flatcorr_io.c	(revision 33100)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/libdvo/src/flatcorr_io.c	(revision 33100)
@@ -0,0 +1,208 @@
+# include "dvo.h"
+
+// FlatCorrection -- description of a single flat-field correction image
+// a flat-field correction is defined for a specific camera (defined how?) or photcode (this makes some sense)
+// it has a period of validity
+
+/* The flat-field correction is defined by two FITS tables / structures.  The first
+ * (FlatCorrectionImage) describes the layout of the chips and which filters are being
+ * corrected.  The second lists the actual corrections for each of the cells
+ */
+
+typedef struct {
+    int Nimage;
+    FlatCorrectionImage *flatcorrImage;
+
+    int Nflatcorr;
+    FlatCorrection *flatcorr;
+} FlatCorrectionTable;
+
+FlatCorrectionTable *FlatCorrectionLoad (char *filename, int VERBOSE) {
+
+  FILE *f;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  int i, Nflatcorr;
+  FlatCorrection *flatcorr;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    if (VERBOSE) fprintf (stderr, "can't find Flat Correction file %s\n", filename);
+    return (NULL);
+  }
+
+  /* load in table data */
+  ftable.header = &theader;
+  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);
+  }
+  if (!gfits_fread_ftable (f, &ftable, "FLAT_CORRECTION")) {
+    if (VERBOSE) fprintf (stderr, "can't read Flat Correction table\n");
+    gfits_free_header (&header);
+    gfits_free_matrix (&matrix);
+    fclose (f);
+    return (NULL);
+  }
+
+  ALLOCATE (flatcorrTable, FlatCorrectionTable, 1);
+
+  flatcorrTable.images = gfits_table_get_FlatCorrectionImage (&ftable, &flatcorrTable.Nimage, NULL);
+  if (!skytable[0].regions) {
+    fprintf (stderr, "ERROR: failed to read sky regions\n");
+    exit (2);
+  }
+
+  if (!gfits_fread_ftable (f, &ftable, "FLAT_CORRECTION")) {
+    if (VERBOSE) fprintf (stderr, "can't read Flat Correction table\n");
+    gfits_free_header (&header);
+    gfits_free_matrix (&matrix);
+    fclose (f);
+    return (NULL);
+  }
+
+  flatcorrTable.images = gfits_table_get_FlatCorrectionImage (&ftable, &flatcorrTable.Nimage, NULL);
+  if (!skytable[0].regions) {
+    fprintf (stderr, "ERROR: failed to read sky regions\n");
+    exit (2);
+  }
+
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  gfits_free_header (&theader);
+
+  return (flatcorr);
+}
+
+int SkyTableSave (SkyTable *skytable, char *filename) {
+
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  FILE *f;
+
+  /* make phu header (no matrix needed) */
+  ftable.header = &theader;
+  gfits_init_header (&header);
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+
+  gfits_table_set_SkyRegion (&ftable, skytable[0].regions, skytable[0].Nregions);
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) { 
+    fprintf (stderr, "cannot open %s for output\n", filename);
+    return (FALSE);
+  }
+  
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table  (f, &ftable);
+  fclose (f);
+
+  return (TRUE);
+}
+
+SkyTable *SkyTableLoadOptimal (char *catdir, char *skyfile, char *gscfile, int readwrite, int depth, int verbose) {
+
+  char filename[256];
+  struct stat filestat;
+  SkyTable *sky;
+
+  /* first option: CATDIR/SkyTable.fits */
+  sprintf (filename, "%s/SkyTable.fits", catdir);
+  if (stat (filename, &filestat)) goto SKYFILE;
+  if (!check_file_access (filename, FALSE, readwrite, verbose)) goto SKYFILE;
+  sky = SkyTableLoad (filename, verbose);
+  if (sky == NULL) {
+    fprintf (stderr, "error loading sky table\n");
+    exit (1);
+  }
+  return (sky);
+
+SKYFILE:
+  /* second option: SKYFILE */
+  if (skyfile == NULL) goto GSCFILE;
+  if (skyfile[0] != 0) goto GSCFILE;
+  if (stat (skyfile, &filestat)) goto GSCFILE;
+  if (!check_file_access (skyfile, FALSE, readwrite, verbose)) goto GSCFILE;
+  sky = SkyTableLoad (skyfile, verbose);
+  if (sky == NULL) {
+    fprintf (stderr, "error loading sky table\n");
+    return (NULL);
+  }
+  /* set the depths to the default depth */
+  SkyTableSetDepth (sky, depth);
+
+  /* create CATDIR copy */
+  sprintf (filename, "%s/SkyTable.fits", catdir);
+  check_file_access (filename, FALSE, readwrite, verbose);
+  if (!SkyTableSave (sky, filename)) return NULL;
+
+  gfits_convert_SkyRegion (sky[0].regions, sizeof (SkyTable), sky[0].Nregions);
+  return (sky);
+
+GSCFILE:
+
+  /* third option: GSCFILE */
+
+  if (gscfile == NULL) {
+    fprintf (stderr, "error loading sky table from existing db (%s)\n", catdir);
+    return (NULL);
+  }
+
+  sky = SkyTableFromGSC (gscfile, depth, verbose);
+  if (sky == NULL) {
+    fprintf (stderr, "error loading sky table\n");
+    return (NULL);
+  }
+
+  /* create CATDIR copy */
+  sprintf (filename, "%s/SkyTable.fits", catdir);
+  check_file_access (filename, FALSE, readwrite, verbose);
+  if (!SkyTableSave (sky, filename)) return NULL;
+
+  gfits_convert_SkyRegion (sky[0].regions, sizeof (SkyRegion), sky[0].Nregions);
+  return (sky);
+}
+
+int SkyListSetFilenames (SkyList *list, char *path, char *ext) {
+
+  int i;
+  char line[256];
+
+  // this generates the names, be sure to free when not needed
+  for (i = 0; i < list[0].Nregions; i++) {
+    sprintf (line, "%s/%s.%s", path, list[0].regions[i][0].name, ext);
+    list[0].filename[i] = strcreate (line);
+  }
+
+  return (TRUE);
+}
+
+int SkyTableSetFilenames (SkyTable *sky, char *path, char *ext) {
+
+  int i;
+  char line[256];
+
+  // this generates the names, be sure to free when not needed
+  for (i = 0; i < sky[0].Nregions; i++) {
+    sprintf (line, "%s/%s.%s", path, sky[0].regions[i].name, ext);
+    sky[0].filename[i] = strcreate (line);
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branches/ipp-20111122/Ohana/src/relphot/doc/flatcorr.txt
===================================================================
--- /branches/eam_branches/ipp-20111122/Ohana/src/relphot/doc/flatcorr.txt	(revision 33100)
+++ /branches/eam_branches/ipp-20111122/Ohana/src/relphot/doc/flatcorr.txt	(revision 33100)
@@ -0,0 +1,73 @@
+
+2012.01.13
+
+Thinking it over, I've decided that the easiest way to move forward on
+the implementation is to define a second grid-like correction to
+represent the flat-field, and defer unifying the two (conceptually
+similar) things to the future.
+
+So, we start with infrastructure:
+
+* APIs to read and write the flat-field corrections
+
+  * how to represent the flat-field correction?
+    * each pixel as a row in a table?
+      * easy to do the file I/O (one table for all corrections)
+      * need to unwrap the values into correction[photcode][x][y]
+      * 
+    * each photcode as a FITS image extention?
+      * 
+    * each camera as a full image (like Grid)?
+    
+
+2012.01.12
+
+The Ubercal analysis gives me zero points along with flat-field
+corrections defined for certain time ranges as a function of
+fractional cell location.  I need to include equivalent information
+into the DVO tables, both to apply the ubercal values and to do
+equivalent fits.  This needs to be done in both relphot and setphot.
+(Other programs refer to the value of Mcal for each detection; only
+relphot and setphot modify or apply the image Mcal to the detection
+value).
+
+In setphot, the needed modification is in update_catalog_setphot,
+where the value of Mcal is set from the image.  This function needs to
+also look up the corresponding flat-correction and include it in that
+calculation.  It is also necessary to load the externally-defined
+description of the flat-correction and to determine which images go
+which which corrections.
+
+In relphot, we would like to be able to fit for the value of interest,
+as well as to apply the values loaded from the database.  
+
+In relphot:
+
+The survey-wide flat-field correction information is similar to the
+Grid that is currently used to calculate the flat-field correction
+terms, though there are some subtleties.  
+
+Currently, the grid analysis is a bit complicated by the way we relate
+the chip coordinates to the camera coordinates.  The main problem is
+that we do not do a good job of tracking which chip a detection comes
+from.
+
+GridOps loads a configuration table which describes the layout of the
+camera.  This means the relative orientations of each of the chips.
+Each chip is define by its ccdnum value and by its ccdname.  
+
+The code assigns the Grid bin by using the camera layout information
+to relate the chip X,Y position to the camera X,Y coordinate.  The
+grid cells are then defined as a function of camera coordinate. 
+
+This is not a terrible solution, but it conflates two things: the chip
+and position in the chip with the layout of the focal plane.  To solve
+or apply a flat-field term, we don't actually need to know anything
+about the location of the chip in the camera.  
+
+In other words, Grid[Xbin][Ybin] is currently a single array assuming
+a monotonic relationship between Xbin and Xchip, etc.  We could have
+Grid[chip][Xbin][Ybin], where Xbin and Ybin come directl from
+Xchip,Ychip and have a different function which converts the resulting
+image to a camera-coordinate system image.
+
