Index: branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageMetadata.c
===================================================================
--- branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageMetadata.c	(revision 35245)
+++ branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageMetadata.c	(revision 35245)
@@ -0,0 +1,223 @@
+# include "dvoshell.h"
+
+# define GET_COLUMN(OUT,NAME,TYPE) \
+  TYPE *OUT = gfits_get_bintable_column_data (&theader, &ftable, NAME, type, &Nrow, &Ncol); \
+  myAssert (!strcmp(type, #TYPE), "wrong column type");
+
+// this is nearly identical to the one in 'uniphot' and 'relphot'
+ImageSubset *ImageSubsetLoad(char *filename, off_t *nimage) {
+
+  int i, Ncol;
+  off_t Nrow;
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  *nimage = 0;
+  ImageSubset *image = NULL;
+
+  FILE *f = fopen (filename, "r");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open image subset file %s\n", filename);
+    return NULL;
+  }
+
+  /* load in PHU segment (ignore) */
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset header\n");
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset matrix\n");
+    gfits_free_header (&header);
+    fclose (f);
+    return NULL;
+  }
+
+  ftable.header = &theader;
+
+  // load data for this header 
+  if (!gfits_load_header (f, &theader)) {
+    fclose (f);
+    return NULL;
+  }
+
+  // read the fits table bytes
+  if (!gfits_fread_ftable_data (f, &ftable, FALSE)) {
+    fclose (f);
+    return (NULL);
+  }
+  fclose (f);
+
+  // a bit annoying : we read the entire block of data, then extract the columns, then set the image structure values.
+  // this means I need 3 copies in memory at some point.  ugh.
+
+  char type[16];
+
+  GET_COLUMN (Mcal,    "MCAL",       float);
+  GET_COLUMN (dMcal,   "MCAL_ERR",   float);
+  GET_COLUMN (imageID, "IMAGE_ID",   int);
+  GET_COLUMN (map,     "PHOTOM_MAP", int);
+  GET_COLUMN (flags,   "FLAGS",      int);
+  GET_COLUMN (tzero,   "TZERO",      int);
+  GET_COLUMN (trate,   "TRATE",      short);
+  GET_COLUMN (ucdist,  "UBERCAL_DIST", short);
+
+  // XXX free the fits table data here 
+
+  ALLOCATE (image, ImageSubset, Nrow);
+  for (i = 0; i < Nrow; i++) {
+    image[i].Mcal          = Mcal[i];
+    image[i].dMcal         = dMcal[i];
+    image[i].imageID       = imageID[i];
+    image[i].photom_map_id = map[i];
+    image[i].flags         = flags[i];
+    image[i].tzero         = tzero[i];
+    image[i].trate         = trate[i];
+    image[i].ubercalDist   = ucdist[i];
+  }
+  fprintf (stderr, "loaded data for %lld images\n", (long long) Nrow);
+
+  free (Mcal);
+  free (dMcal);
+  free (imageID);
+  free (map);
+  free (flags);
+  free (tzero);
+  free (trate);
+  free (ucdist);
+
+  *nimage = Nrow;
+  return image;
+}
+
+// STATUS is value expected for success
+# define CHECK_STATUS(STATUS,MSG,...)					\
+  if (!(STATUS)) {							\
+    fprintf (stderr, MSG, __VA_ARGS__);					\
+    return FALSE;							\
+  }
+
+// save a minimal set of metadata needed to mextract joins
+int ImageMetadataSave(char *filename, Image *image, off_t Nimage) {
+
+  int i;
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  gfits_init_header (&header);
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+
+  gfits_create_table_header (&theader, "BINTABLE", "IMAGE_SUBSET");
+
+  gfits_define_bintable_column (&theader, "J", "IMAGE_ID", "image ID", NULL, 1.0, 1.0*0x8000);
+  gfits_define_bintable_column (&theader, "J", "EXTERN_ID", "extern ID", NULL, 1.0, 1.0*0x8000);
+  gfits_define_bintable_column (&theader, "J", "EXPNAME_AS_INT", "expname as integer", NULL, 1.0, 1.0*0x8000);
+  gfits_define_bintable_column (&theader, "D", "CRVAL1", "ra at center", "degrees", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "D", "CRVAL2", "dec at center", "degrees", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "MCAL", "zero point offset", "magnitudes", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "SECZ", "airmass", "none", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "X_CENTER", "chip center", "none", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "Y_CENTER", "chip center", "none", 1.0, 0.0);
+
+  // generate the output array that carries the data
+  gfits_create_table (&theader, &ftable);
+
+  unsigned int *imageID, *externID, *expname;
+  double *crval1, *crval2;
+  float *Mcal, *dMcal, *Xcenter, *Ycenter;
+
+  // create intermediate storage arrays
+  ALLOCATE (imageID,  unsigned int,   Nimage);
+  ALLOCATE (externID, unsigned int,   Nimage);
+  ALLOCATE (expname,  unsigned int,   Nimage);
+  ALLOCATE (crval1,   double,  	      Nimage);
+  ALLOCATE (crval2,   double, 	      Nimage);
+  ALLOCATE (Mcal,     float, 	      Nimage);
+  ALLOCATE (secz,     float, 	      Nimage);
+  ALLOCATE (Xcenter,  float, 	      Nimage);
+  ALLOCATE (Ycenter,  float, 	      Nimage);
+
+  // assign the storage arrays
+  for (i = 0; i < Nimage; i++) {
+    imageID[i]  = image[i].imageID;
+    externID[i] = image[i].externID;
+    crval1[i]   = image[i].crval1;
+    crval2[i]   = image[i].crval2;
+    Mcal[i]     = image[i].Mcal;
+    secz[i]     = image[i].secz;
+    Xcenter[i]  = 0.5*image[i].NX;
+    Ycenter[i]  = 0.5*image[i].NY;
+
+    expname[i]  = 0;
+    if ((image[i].name[0] == 'o') && (image[i].name[5] == 'g') && (image[i].name[10] == 'o')) {
+      int mjd  = atoi(image[i].name[1]);
+      int Nexp = atoi(image[i].name[6]);
+      expname[i] = mjd * 10000 + Nexp;
+    }
+  }
+
+  // add the columns to the output array
+  gfits_set_bintable_column (&theader, &ftable, "IMAGE_ID",       imageID,  Nimage);
+  gfits_set_bintable_column (&theader, &ftable, "EXTERN_ID",      externID, Nimage);
+  gfits_set_bintable_column (&theader, &ftable, "EXPNAME_AS_INT", expname,  Nimage);
+  gfits_set_bintable_column (&theader, &ftable, "CRVAL1",         crval1,  Nimage);
+  gfits_set_bintable_column (&theader, &ftable, "CRVAL2",         crval2,  Nimage);
+  gfits_set_bintable_column (&theader, &ftable, "MCAL",           Mcal,    Nimage);
+  gfits_set_bintable_column (&theader, &ftable, "SECZ",           secz,    Nimage);
+  gfits_set_bintable_column (&theader, &ftable, "X_CENTER",       Xcenter, Nimage);
+  gfits_set_bintable_column (&theader, &ftable, "Y_CENTER",       Ycenter, Nimage);
+
+  free (imageID);
+  free (externID);
+  free (expname);
+  free (crval1);
+  free (crval2);
+  free (Mcal);
+  free (secz);
+  free (Xcenter);
+  free (Ycenter);
+
+  FILE *f = fopen (filename, "w");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open image subset file for output %s\n", filename);
+    return FALSE;
+  }
+
+  int status;
+  status = gfits_fwrite_header  (f, &header);
+  CHECK_STATUS (status, "ERROR: cannot write header for image subset %s\n", filename);
+
+  status = gfits_fwrite_matrix  (f, &matrix);
+  CHECK_STATUS (status, "ERROR: cannot write matrix for image subset %s\n", filename);
+
+  status = gfits_fwrite_Theader (f, &theader);
+  CHECK_STATUS (status, "ERROR: cannot write table header for image subset %s\n", filename);
+
+  status = gfits_fwrite_table  (f, &ftable);
+  CHECK_STATUS (status, "ERROR: cannot write table data for image subset %s\n", filename);
+
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  gfits_free_header (&theader);
+  gfits_free_table (&ftable);
+
+  int fd = fileno (f);
+
+  status = fflush (f);
+  CHECK_STATUS (!status, "ERROR: cannot flush file image subset %s\n", filename);
+
+  status = fsync (fd);
+  CHECK_STATUS (!status, "ERROR: cannot flush file image subset %s\n", filename);
+
+  status = fclose (f);
+  CHECK_STATUS (!status, "ERROR: problem closing image subset file %s\n", filename);
+
+  return TRUE;
+}
Index: branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/dbExtractMeasures.c
===================================================================
--- branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/dbExtractMeasures.c	(revision 35244)
+++ branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/dbExtractMeasures.c	(revision 35245)
@@ -336,7 +336,13 @@
     case MEAS_MEAN_AIRMASS: /* OK */
       {
-	Image *image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
-	if (image == NULL) break;
-	value.Flt = image[0].secz;
+	if (CLIENT) {
+	  ImageMetadata *image = MatchImageMetadataDVO (measure[0].imageID);
+	  if (image == NULL) break;
+	  value.Flt = image[0].secz;
+	} else {
+	  Image *image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
+	  if (image == NULL) break;
+	  value.Flt = image[0].secz;
+	}
 	break;
       }
