Index: /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/Makefile
===================================================================
--- /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/Makefile	(revision 35247)
+++ /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/Makefile	(revision 35248)
@@ -98,4 +98,6 @@
 $(SRC)/LoadImages.$(ARCH).o		\
 $(SRC)/ImageSelection.$(ARCH).o		\
+$(SRC)/ImageMetadataSelection.$(ARCH).o \
+$(SRC)/ImageMetadata.$(ARCH).o \
 $(SRC)/ImageOps.$(ARCH).o		\
 $(SRC)/match_image.$(ARCH).o		\
Index: /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/doc/image-searches.txt
===================================================================
--- /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/doc/image-searches.txt	(revision 35248)
+++ /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/doc/image-searches.txt	(revision 35248)
@@ -0,0 +1,19 @@
+
+I am making some fixes to the code to select an image from the full
+table (specifically for mextract).
+
+here is how things work currently: 
+
+* mextract detects that a query needs data from an image field
+* mextract calls SetImageSelection()
+  * SetImageSelection calls:
+    * LoadImagesDVO(), which reads the image table into its static cache
+    * BuildChipMatch to generate the index for chip->mosaic 
+    * image_subset which generates a local (to ImageSelection.c) static subset
+    * sort_image_subset sorts the subset selection to be ordered by time
+* mextract calls MatchImageDVO to find a specific image
+  * match_image_subset is ok because subset is sorted by time
+
+* for the image metadata, I need to do the following:
+
+* load the image subset table
Index: /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/include/dvodb.h
===================================================================
--- /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/include/dvodb.h	(revision 35247)
+++ /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/include/dvodb.h	(revision 35248)
@@ -298,4 +298,16 @@
 } dbValue;
 
+typedef struct {
+  double crval1;
+  double crval2;
+  unsigned int imageID;
+  unsigned int externID;
+  unsigned int expname;
+  float Mcal;
+  float secz;
+  float Xcenter;
+  float Ycenter;
+} ImageMetadata;
+
 Image        *LoadImagesDVO         PROTO((off_t *Nimage));
 void          FreeImagesDVO         PROTO((Image *images));
@@ -346,5 +358,5 @@
 int dbExtractMeasuresInitAve (void);
 int dbExtractMeasuresInitMeas (void);
-int dbExtractMeasuresInit (void);
+int dbExtractMeasuresInit (int isRemoteClient);
 
 int dbExtractAveragesInitTransform (CoordTransformSystem target);
@@ -363,3 +375,13 @@
 #include "get_graphdata.h"
 
+ImageMetadata *ImageMetadataLoad(char *filename, off_t *nimage);
+int ImageMetadataSave(char *filename, Image *image, off_t Nimage);
+
+int SetImageMetadataSelection (char *filename);
+void FreeImageMetadataSelection ();
+ImageMetadata *MatchImageMetadataDVO (unsigned int imageID);
+Coords *MatchMosaicMetadata (unsigned int imageID);
+off_t match_image_by_ID (ImageMetadata *image, off_t Nimage, unsigned int ID);
+void sort_image_metadata (ImageMetadata *image, off_t Nimage);
+
 # endif
Index: /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageMetadata.c
===================================================================
--- /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageMetadata.c	(revision 35247)
+++ /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageMetadata.c	(revision 35248)
@@ -1,3 +1,4 @@
-# include "dvoshell.h"
+# include "dvo.h"
+# define VERBOSE 1
 
 # define GET_COLUMN(OUT,NAME,TYPE) \
@@ -6,5 +7,5 @@
 
 // this is nearly identical to the one in 'uniphot' and 'relphot'
-ImageSubset *ImageSubsetLoad(char *filename, off_t *nimage) {
+ImageMetadata *ImageMetadataLoad(char *filename, off_t *nimage) {
 
   int i, Ncol;
@@ -16,5 +17,5 @@
 
   *nimage = 0;
-  ImageSubset *image = NULL;
+  ImageMetadata *image = NULL;
 
   FILE *f = fopen (filename, "r");
@@ -57,36 +58,37 @@
   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);
+  GET_COLUMN (imageID,  "IMAGE_ID",       int);
+  GET_COLUMN (externID, "EXTERN_ID",      int);
+  GET_COLUMN (expname,  "EXPNAME_AS_INT", int);
+  GET_COLUMN (crval1,   "CRVAL1",         double);
+  GET_COLUMN (crval2,   "CRVAL2",         double);
+  GET_COLUMN (Mcal,     "MCAL",           float);
+  GET_COLUMN (secz,     "SECZ",           float);
+  GET_COLUMN (Xcenter,  "X_CENTER",       float);
+  GET_COLUMN (Ycenter,  "Y_CENTER",       float);
+
+  ALLOCATE (image, ImageMetadata, 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];
+    image[i].imageID  = imageID[i] ;
+    image[i].externID = externID[i];
+    image[i].expname  = expname[i] ;
+    image[i].crval1   = crval1[i]  ;
+    image[i].crval2   = crval2[i]  ;
+    image[i].Mcal     = Mcal[i]    ;
+    image[i].secz     = secz[i]    ;
+    image[i].Xcenter  = Xcenter[i] ;
+    image[i].Ycenter  = Ycenter[i] ;
   }
   fprintf (stderr, "loaded data for %lld images\n", (long long) Nrow);
 
+  free (imageID);
+  free (externID);
+  free (expname);
+  free (crval1);
+  free (crval2);
   free (Mcal);
-  free (dMcal);
-  free (imageID);
-  free (map);
-  free (flags);
-  free (tzero);
-  free (trate);
-  free (ucdist);
+  free (secz);
+  free (Xcenter);
+  free (Ycenter);
 
   *nimage = Nrow;
@@ -132,5 +134,5 @@
   unsigned int *imageID, *externID, *expname;
   double *crval1, *crval2;
-  float *Mcal, *dMcal, *Xcenter, *Ycenter;
+  float *Mcal, *Xcenter, *Ycenter, *secz;
 
   // create intermediate storage arrays
@@ -149,6 +151,6 @@
     imageID[i]  = image[i].imageID;
     externID[i] = image[i].externID;
-    crval1[i]   = image[i].crval1;
-    crval2[i]   = image[i].crval2;
+    crval1[i]   = image[i].coords.crval1;
+    crval2[i]   = image[i].coords.crval2;
     Mcal[i]     = image[i].Mcal;
     secz[i]     = image[i].secz;
@@ -158,6 +160,6 @@
     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]);
+      int mjd  = atoi(&image[i].name[1]);
+      int Nexp = atoi(&image[i].name[6]);
       expname[i] = mjd * 10000 + Nexp;
     }
Index: /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageMetadataSelection.c
===================================================================
--- /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageMetadataSelection.c	(revision 35248)
+++ /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageMetadataSelection.c	(revision 35248)
@@ -0,0 +1,87 @@
+# include "dvo.h"
+
+/* db image table */
+static ImageMetadata *image = NULL;
+static off_t Nimage = 0;
+static Coords mosaic;
+
+/* load images based on parameters and region, etc */
+int SetImageMetadataSelection (char *filename) {
+
+  image = NULL;
+  
+  /* mosaic defines a frame with 0,0 at the mosaic center, and 1 arcsec / pixel */
+  mosaic.crpix1 = mosaic.crpix2 = 0.0;
+  mosaic.cdelt1 = mosaic.cdelt2 = 1.0 / 3600;
+  mosaic.pc1_1  = mosaic.pc2_2  = 1.0;
+  mosaic.pc1_2  = mosaic.pc2_1  = 0.0;
+  mosaic.Npolyterms = 0;
+  strcpy (mosaic.ctype, "RA---SIN");
+
+  if ((image = ImageMetadataLoad (filename, &Nimage)) == NULL) return (FALSE);
+
+  // sort the images by their imageID for fast searches
+  // XXX is this too slow?  do I need to sort an array of pointers?
+  sort_image_metadata (image, Nimage);
+  return (TRUE);
+}
+
+/* free loaded images */
+void FreeImageMetadataSelection () {
+  if (image != NULL) free(image);
+  image = NULL;
+  return;
+}
+
+ImageMetadata *MatchImageMetadataDVO (unsigned int imageID) { 
+
+  off_t m = match_image_by_ID (image, Nimage, imageID);
+  if (m == -1) return (NULL);
+
+  return (&image[m]);
+}
+
+Coords *MatchMosaicMetadata (unsigned int imageID) { 
+
+  int m;
+
+  m = match_image_by_ID (image, Nimage, imageID);
+  if (m == -1) return (NULL);
+  mosaic.crval1 = image[m].crval1;
+  mosaic.crval2 = image[m].crval2;
+  return (&mosaic);
+}
+
+off_t match_image_by_ID (ImageMetadata *image, off_t Nimage, unsigned int ID) {
+
+  off_t N, Nlo, Nhi, N1, N2;
+
+  /* bracket first value of interest */
+  Nlo = 0; Nhi = Nimage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[N].imageID < ID) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  N1 = Nlo;
+
+  /* bracket last value of interest */
+  Nlo = 0; Nhi = Nimage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[N].imageID > ID) {
+      Nhi = N;
+    } else {
+      Nlo = N - 1;
+    }
+  }
+  N2 = Nhi;
+
+  for (N = N1; N < N2; N++) {
+    if (image[N].imageID == ID) return (N);
+  }
+  return (-1);
+}
Index: /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageSelection.c
===================================================================
--- /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageSelection.c	(revision 35247)
+++ /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/ImageSelection.c	(revision 35248)
@@ -66,4 +66,25 @@
 }
 
+Image *MatchImageDVO_old (unsigned int time, short int source, unsigned int imageID) { 
+
+  int m = -1;
+
+  if ((imageID != 0) && (imageID < Nimage)) {
+    // imageID is in range for the array of images. If the table is still in order and
+    // no images have been deleted the index of the image we are looking for will be imageID - 1
+    // If this is the case, we have it. Otherwise we'll have to go search for it below
+    int guess = (int) imageID - 1;
+    if (image[guess].imageID == imageID) {
+        m = guess;
+    }
+  } 
+  if (m == -1) {
+    m = match_image_subset (image, subset, Nsubset, time, source);
+  }
+  if (m == -1) return (NULL);
+  if (!FindMosaicForImage (image, Nimage, m)) return (NULL);
+  return (&image[m]);
+}
+
 Coords *MatchMosaic (unsigned int time, short int source) { 
 
Index: /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/dbExtractMeasures.c
===================================================================
--- /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/dbExtractMeasures.c	(revision 35247)
+++ /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/dbExtractMeasures.c	(revision 35248)
@@ -14,4 +14,6 @@
 static CoordTransform *celestial_to_ecliptic = NULL;
 
+static int REMOTE_CLIENT = FALSE;
+
 static int haveGalacticAve = FALSE;
 static double GLON_AVE = 0.0;
@@ -30,5 +32,6 @@
 static double ELAT_MEAS = 0.0;
 
-int dbExtractMeasuresInit () {
+int dbExtractMeasuresInit (int isRemoteClient) {
+  REMOTE_CLIENT = isRemoteClient;
   GetTimeFormat (&TimeReference, &TimeFormat);
   return (TRUE);
@@ -335,16 +338,14 @@
       break;
     case MEAS_MEAN_AIRMASS: /* OK */
-      {
-	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;
-      }
+      if (REMOTE_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;
     case MEAS_AZ: /* OK */
       value.Flt = measure[0].az;
@@ -467,5 +468,5 @@
       ra  = average[0].R - measure[0].dR / 3600.0;
       dec = average[0].D - measure[0].dD / 3600.0;
-      mosaic = MatchMosaic (measure[0].t, measure[0].photcode);
+      mosaic = MatchMosaicMetadata (measure[0].imageID);
       if (mosaic == NULL) break;
       RD_to_XY (&x, &y, ra, dec, mosaic);
@@ -521,16 +522,22 @@
       break;
     case MEAS_EXTERN_ID: /* OK */
-      {
-	Image *image;
-	image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
+      if (REMOTE_CLIENT) {
+	ImageMetadata *image = MatchImageMetadataDVO (measure[0].imageID);
 	if (image == NULL) break;
 	value.Int = image->externID;
+      } else {
+	Image *image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
+	if (image == NULL) break;
+	value.Int = image[0].externID;
       }
       break;
 
     case MEAS_EXPNAME_AS_INT:
-      {
-	Image *image;
-	image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
+      if (REMOTE_CLIENT) {
+	ImageMetadata *image = MatchImageMetadataDVO (measure[0].imageID);
+	if (image == NULL) break;
+	value.Int = image->expname;
+      } else {
+	Image *image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
 	if (image == NULL) break;
 	// XXX very crude: if this matches oNNNNgNNNNo, then convert to an int
@@ -550,20 +557,27 @@
     case MEAS_FLAT: /* OK */
       // flat = measure.Mcal - image.Mcal
-      { 
-	Image *image;
-	image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
+      if (REMOTE_CLIENT) {
+	ImageMetadata *image = MatchImageMetadataDVO (measure[0].imageID);
 	if (image == NULL) break;
 	value.Flt = measure[0].Mcal - image[0].Mcal;
-      }
-      break;
-
+      } else {
+	Image *image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
+	if (image == NULL) break;
+	value.Flt = measure[0].Mcal - image[0].Mcal;
+      }
+      break;
+
+      // we have measure[0].Xccd,Yccd and image[0].NX,NY.  Find the distance to the center
     case MEAS_CENTER_OFFSET: /* OK */
-      { 
-	Image *image;
-	image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
-	if (image == NULL) break;
-	
-	// we have measure[0].Xccd,Yccd and image[0].NX,NY.  Find the distance to the center
-
+      if (REMOTE_CLIENT) {
+	ImageMetadata *image = MatchImageMetadataDVO (measure[0].imageID);
+	if (image == NULL) break;
+	float Xcenter = image[0].Xcenter;
+	float Ycenter = image[0].Ycenter;
+	float distance = hypot (measure[0].Xccd - Xcenter, measure[0].Yccd - Ycenter);
+	value.Flt = distance;
+      } else {
+	Image *image = MatchImageDVO (measure[0].t, measure[0].photcode, measure[0].imageID);
+	if (image == NULL) break;
 	// XXX we may hypotetically have images with -NX to +NX here (eg, projection center), but 
 	// we do not get a detection from that type of image
Index: /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/dvosorts.c
===================================================================
--- /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/dvosorts.c	(revision 35247)
+++ /branches/eam_branches/ipp-20130306/Ohana/src/libdvo/src/dvosorts.c	(revision 35248)
@@ -23,4 +23,17 @@
 
   OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+/* sort ImageMetadata array by image[i].imageID */
+void sort_image_metadata (ImageMetadata *image, off_t Nimage) {
+
+# define SWAPFUNC(A,B){ ImageMetadata tmp; tmp = image[A]; image[A] = image[B]; image[B] = tmp; }
+# define COMPARE(A,B)(image[A].imageID < image[B].imageID)
+
+  OHANA_SORT (Nimage, COMPARE, SWAPFUNC);
 
 # undef SWAPFUNC
