Index: /branches/eam_branches/ipp-20150112/Ohana/src/uniphot/include/setastrom.h
===================================================================
--- /branches/eam_branches/ipp-20150112/Ohana/src/uniphot/include/setastrom.h	(revision 37907)
+++ /branches/eam_branches/ipp-20150112/Ohana/src/uniphot/include/setastrom.h	(revision 37908)
@@ -10,4 +10,14 @@
   double *y2;
 } Spline;
+
+// we have one correction (an image) for each filter and chip
+typedef struct {
+  int Nvalues;
+  int Nfilters; // number of filters
+  int Nx; // number of chips in x
+  int Ny; // number of chips in y
+  Matrix **matrix; // allocate an array of pointers
+  // index = ix + iy*Nx + filter*Nx*Ny + dir*Nx*Ny*Nfilter
+} CamCorrection;
 
 /* global variables set in parameter file */
Index: /branches/eam_branches/ipp-20150112/Ohana/src/uniphot/src/cam_correction.c
===================================================================
--- /branches/eam_branches/ipp-20150112/Ohana/src/uniphot/src/cam_correction.c	(revision 37908)
+++ /branches/eam_branches/ipp-20150112/Ohana/src/uniphot/src/cam_correction.c	(revision 37908)
@@ -0,0 +1,88 @@
+# include "setastrom.h"
+
+// camera systematic (astroflat) correction functions:
+// load the correction set from a file
+
+// note that we are allocating pointers for XY00 - XY77, but only the octal elements are set (and not the 00,07,70,77 ones)
+
+CamCorrection *load_cam_correction (char *filename) {
+
+  int Ncol;
+  off_t Nrow;
+
+  char type[16];
+  char extname[80];
+
+  Header header;
+  Header theader;
+  FTable ftable;
+
+  /* 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;
+  }
+
+  CamCorrection *cam = NULL;
+  ALLOCATE (cam, CamCorrection, 1);
+
+  // read the PHU header
+  if (!gfits_load_header (f, &header)) return (FALSE);
+  
+  int Nbytes = gfits_data_size (&header);
+  fseeko (f, Nbytes, SEEK_CUR);
+
+  ftable.header = &theader;
+
+  if (!gfits_scan (&theader, "NDIR",    "%d", 1, &Ndir))    return (NULL);
+  if (!gfits_scan (&theader, "NFILTER", "%d", 1, &Nfilter)) return (NULL);
+  if (!gfits_scan (&theader, "NX_CHIP", "%d", 1, &Nx)) 	    return (NULL);
+  if (!gfits_scan (&theader, "NY_CHIP", "%d", 1, &Ny)) 	    return (NULL);
+
+  ALLOCATE (cam->matrix, Matrix *, Ndir*Nfilter*Nx*Ny);
+
+  while (TRUE) {
+    // load data for this header : if not found, assume we hit the end of the file
+    if (!gfits_load_header (f, &theader)) break;
+    
+    if (!gfits_scan (&theader, "FILTER",  "%d", 1, &filter))  return (FALSE);
+    if (!gfits_scan (&theader, "DIR",     "%d", 1, &dir))     return (FALSE);
+    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_header (f, matrix, &theader)) break;
+
+    int index = ix + iy*Nx + filter*Nx*Ny + dir*Nx*Ny*Nfilter;
+    myAssert (index >= 0, "index too small");
+    myAssert (index < Ndir*Nfilter*Nx*Ny, "index too big");
+
+    // assert that cam->matrix[index] is NULL?
+    cam->matrix[index] = matrix;
+  }
+  return (TRUE);
+}
+
+int get_kh_correction (int sub, int chip, double *dX, double *dY, float Minst) {
+
+  Spline *spline = NULL;
+
+  *dX = 0.0;
+  *dY = 0.0;
+
+  // XXX need to include some limits on Minst?
+
+  spline = splineset[sub][0][chip];
+  if (spline) {
+    *dX = spline_apply_dbl (spline->xk, spline->yk, spline->y2, spline->Nknots, Minst);
+  }
+
+  spline = splineset[sub][1][chip];
+  if (spline) {
+    *dY = spline_apply_dbl (spline->xk, spline->yk, spline->y2, spline->Nknots, Minst);
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branches/ipp-20150112/Ohana/src/uniphot/src/update_catalog_setastrom.c
===================================================================
--- /branches/eam_branches/ipp-20150112/Ohana/src/uniphot/src/update_catalog_setastrom.c	(revision 37907)
+++ /branches/eam_branches/ipp-20150112/Ohana/src/uniphot/src/update_catalog_setastrom.c	(revision 37908)
@@ -117,4 +117,19 @@
     }
 
+    /**** CAM section ****/
+
+    double dX_CAM = 0.0;
+    double dY_CAM = 0.0;
+    if (CAM_FILE && doCAM) {
+
+      // camera systematic correction ("astroflat") depends on only the X,Y coordinate,
+      // the filter, and the chip
+      
+      int filtCode = (int)(measure->photcode / 100); // eg, 101 = r
+
+      // correction is in arcseconds
+      get_cam_correction (0, chipID, filtCode, measure->Xccd, measure->Yccd, &dX_CAM, &dY_CAM);
+    }
+
     /**** DCR section ****/
 
