Index: /branches/eam_branches/ipp-20110213/Ohana/src/opihi/dvo/dbExtractImages.c
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/opihi/dvo/dbExtractImages.c	(revision 31102)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/opihi/dvo/dbExtractImages.c	(revision 31103)
@@ -59,4 +59,5 @@
   time_t t;
   dbValue value;
+  off_t Nmosaic;
 
   value.Flt = NAN;
@@ -236,4 +237,21 @@
       value.Flt = image[N].fwhm_y / 25.0;
       break;
+
+    case IMAGE_FWHM_MEDIAN:
+      if (!(Nmosaic = FindMosaicForImage (image, Nimage, N))) return value;
+      Nmosaic --; // XXX kind of a hack: FindMosaicForImage returns 0 or the mosaic seq number + 1
+      value.Flt = (image[Nmosaic].fwhm_x + image[Nmosaic].fwhm_y) / 50.0;
+      break;
+    case IMAGE_FWHM_MAJ_MEDIAN:
+      if (!(Nmosaic = FindMosaicForImage (image, Nimage, N))) return value;
+      Nmosaic --; // XXX kind of a hack: FindMosaicForImage returns 0 or the mosaic seq number + 1
+      value.Flt = image[Nmosaic].fwhm_x / 25.0;
+      break;
+    case IMAGE_FWHM_MIN_MEDIAN:
+      if (!(Nmosaic = FindMosaicForImage (image, Nimage, N))) return value;
+      Nmosaic --; // XXX kind of a hack: FindMosaicForImage returns 0 or the mosaic seq number + 1
+      value.Flt = image[Nmosaic].fwhm_y / 25.0;
+      break;
+
     case IMAGE_TRATE:
       value.Flt = image[N].trate / 10000.0;
Index: /branches/eam_branches/ipp-20110213/Ohana/src/opihi/dvo/dbFields.c
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/opihi/dvo/dbFields.c	(revision 31102)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/opihi/dvo/dbFields.c	(revision 31103)
@@ -395,7 +395,16 @@
   if (!strcasecmp (fieldName, "cerror"   )) ESCAPE (IMAGE_CERROR,    MAG_NONE, OPIHI_FLT);
 
-  if (!strcasecmp (fieldName, "FWHM"     )) ESCAPE (IMAGE_FWHM,      MAG_NONE, OPIHI_FLT);
-  if (!strcasecmp (fieldName, "FWHM_MAJ" )) ESCAPE (IMAGE_FWHM_MAJ,  MAG_NONE, OPIHI_FLT);
-  if (!strcasecmp (fieldName, "FWHM_MIN" )) ESCAPE (IMAGE_FWHM_MIN,  MAG_NONE, OPIHI_FLT);
+  if (!strcasecmp (fieldName, "FWHM"       )) ESCAPE (IMAGE_FWHM,      MAG_NONE, OPIHI_FLT);
+  if (!strcasecmp (fieldName, "FWHM_MAJ"   )) ESCAPE (IMAGE_FWHM_MAJ,  MAG_NONE, OPIHI_FLT);
+  if (!strcasecmp (fieldName, "FWHM_MIN"   )) ESCAPE (IMAGE_FWHM_MIN,  MAG_NONE, OPIHI_FLT);
+  if (!strcasecmp (fieldName, "FWHM_MAJOR" )) ESCAPE (IMAGE_FWHM_MAJ,  MAG_NONE, OPIHI_FLT);
+  if (!strcasecmp (fieldName, "FWHM_MINOR" )) ESCAPE (IMAGE_FWHM_MIN,  MAG_NONE, OPIHI_FLT);
+
+  if (!strcasecmp (fieldName, "FWHM_MEDIAN"    ))   ESCAPE (IMAGE_FWHM_MEDIAN,      MAG_NONE, OPIHI_FLT);
+  if (!strcasecmp (fieldName, "FWHM_MAJ_MEDIAN"))   ESCAPE (IMAGE_FWHM_MAJ_MEDIAN,  MAG_NONE, OPIHI_FLT);
+  if (!strcasecmp (fieldName, "FWHM_MIN_MEDIAN"))   ESCAPE (IMAGE_FWHM_MIN_MEDIAN,  MAG_NONE, OPIHI_FLT);
+  if (!strcasecmp (fieldName, "FWHM_MAJOR_MEDIAN")) ESCAPE (IMAGE_FWHM_MAJ_MEDIAN,  MAG_NONE, OPIHI_FLT);
+  if (!strcasecmp (fieldName, "FWHM_MINOR_MEDIAN")) ESCAPE (IMAGE_FWHM_MIN_MEDIAN,  MAG_NONE, OPIHI_FLT);
+
   if (!strcasecmp (fieldName, "trate"    )) ESCAPE (IMAGE_TRATE,     MAG_NONE, OPIHI_FLT);
 
Index: /branches/eam_branches/ipp-20110213/Ohana/src/opihi/dvo/imextract.c
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/opihi/dvo/imextract.c	(revision 31102)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/opihi/dvo/imextract.c	(revision 31103)
@@ -197,7 +197,17 @@
     gprint (GP_ERR, "  cerror : astrometric scatter\n");
 
-    gprint (GP_ERR, "  FWHM : mean fwhm of exposure\n");
-    gprint (GP_ERR, "  FWHM_MAJ : fwhm of major axis\n");
-    gprint (GP_ERR, "  FWHM_MIN : fwhm of minor axis\n");
+    gprint (GP_ERR, "  -- Note: the follow FWHM are from the PSF model --\n");
+    gprint (GP_ERR, "  FWHM : mean fwhm of chip\n");
+    gprint (GP_ERR, "  FWHM_MAJ : fwhm of chip (major axis)\n");
+    gprint (GP_ERR, "  FWHM_MIN : fwhm of chip (minor axis)\n");
+    gprint (GP_ERR, "  FWHM_MAJOR : fwhm of chip (major axis)\n");
+    gprint (GP_ERR, "  FWHM_MININ : fwhm of chip (minor axis)\n");
+
+    gprint (GP_ERR, "  FWHM_MEDIAN : median fwhm of exposure\n");
+    gprint (GP_ERR, "  FWHM_MAJ_MEDIAN : median fwhm of major axis\n");
+    gprint (GP_ERR, "  FWHM_MIN_MEDIAN : median fwhm of minor axis\n");
+    gprint (GP_ERR, "  FWHM_MAJOR_MEDIAN : median fwhm of major axis\n");
+    gprint (GP_ERR, "  FWHM_MININ_MEDIAN : median fwhm of minor axis\n");
+
     gprint (GP_ERR, "  trate : tracking rate for TDI images\n");
 
Index: /branches/eam_branches/ipp-20110213/Ohana/src/opihi/include/dvoshell.h
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/opihi/include/dvoshell.h	(revision 31102)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/opihi/include/dvoshell.h	(revision 31103)
@@ -179,4 +179,5 @@
       IMAGE_TIME, 
       IMAGE_FWHM, 
+      IMAGE_FWHM_MEDIAN, 
       IMAGE_EXPTIME, 
       IMAGE_NSTAR, 
@@ -200,4 +201,6 @@
       IMAGE_FWHM_MAJ,
       IMAGE_FWHM_MIN,
+      IMAGE_FWHM_MAJ_MEDIAN,
+      IMAGE_FWHM_MIN_MEDIAN,
       IMAGE_TRATE,
       IMAGE_IMAGE_ID,
Index: /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/Makefile
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/Makefile	(revision 31102)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/Makefile	(revision 31103)
@@ -1,5 +1,5 @@
-default: uniphot setphot
+default: uniphot setphot setfwhm
 help:
-@echo "make options: uniphot setphot default help install default (uniphot setphot)"
+@echo "make options: uniphot setphot setfwhm default help install default (uniphot setphot setfwhm)"
 
 include ../../Makefile.System
@@ -19,5 +19,6 @@
 uniphot: $(BIN)/uniphot.$(ARCH)
 setphot: $(BIN)/setphot.$(ARCH)
-install: $(DESTBIN)/uniphot $(DESTBIN)/setphot 
+setfwhm: $(BIN)/setfwhm.$(ARCH)
+install: $(DESTBIN)/uniphot $(DESTBIN)/setphot $(DESTBIN)/setfwhm
 
 UNIPHOT = \
@@ -57,2 +58,17 @@
 $(SETPHOT): $(INC)/uniphot.h
 $(BIN)/setphot.$(ARCH): $(SETPHOT)
+
+SETFWHM =                           \
+$(SRC)/setfwhm.$(ARCH).o	    \
+$(SRC)/initialize.$(ARCH).o	    \
+$(SRC)/ConfigInit.$(ARCH).o	    \
+$(SRC)/args.$(ARCH).o               \
+$(SRC)/liststats.$(ARCH).o	    \
+$(SRC)/load_fwhm_table.$(ARCH).o    \
+$(SRC)/load_images.$(ARCH).o	    \
+$(SRC)/match_fwhm_to_images.$(ARCH).o	    \
+$(SRC)/SetSignals.$(ARCH).o	    \
+$(SRC)/Shutdown.$(ARCH).o	    
+
+$(SETFWHM): $(INC)/uniphot.h
+$(BIN)/setfwhm.$(ARCH): $(SETFWHM)
Index: /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/include/uniphot.h
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/include/uniphot.h	(revision 31102)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/include/uniphot.h	(revision 31103)
@@ -47,4 +47,12 @@
     int found;
 } ZptTable;
+
+typedef struct {
+    float fwhm_major;
+    float fwhm_minor;
+    e_time time;
+    int found;
+    unsigned short photcode;
+} FWHMTable;
 
 /* global variables set in parameter file */
@@ -147,2 +155,8 @@
 time_t        GetTimeReference      PROTO((char *reference));
 int           GetTimeUnits          PROTO((char *name));
+
+void          initialize_setfwhm    PROTO((int argc, char **argv));
+int           args_setfwhm          PROTO((int argc, char **argv));
+FWHMTable    *load_fwhm_table       PROTO((char *filename, int *nfwhm));
+int           match_fwhm_to_images  PROTO((Image *image, off_t Nimage, FWHMTable *fwhm, int Nfwhm));
+
Index: /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/args.c
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/args.c	(revision 31102)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/args.c	(revision 31103)
@@ -96,2 +96,26 @@
 }
 
+int args_setfwhm (int argc, char **argv) {
+
+  int N;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  UPDATE = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE = TRUE;
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "ERROR: USAGE: setfwhm (fwhmfile) [options]\n");
+    exit (2);
+  } 
+
+  return (TRUE);
+}
+
Index: /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/initialize.c
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/initialize.c	(revision 31102)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/initialize.c	(revision 31103)
@@ -28,2 +28,9 @@
 }
 
+void initialize_setfwhm (int argc, char **argv) {
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args_setfwhm (argc, argv);
+}
+
Index: /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/load_fwhm_table.c
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/load_fwhm_table.c	(revision 31103)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/load_fwhm_table.c	(revision 31103)
@@ -0,0 +1,49 @@
+# include "uniphot.h"
+
+FWHMTable *load_fwhm_table (char *filename, int *nfwhm) {
+
+  char name[1024], photcode[256];
+  int Nfwhm, NFWHM;
+  FWHMTable *fwhm;
+  double fwhm_major, fwhm_minor, mjd;
+
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open fwhm table file %s\n", filename);
+    exit (1);
+  }
+
+  Nfwhm = 0;
+  NFWHM = 100;
+  ALLOCATE (fwhm, FWHMTable, NFWHM);
+
+  // format is fixed: (time in mjd) (fwhm_major) (fwhm_minor)
+  int status;
+  while ((status = fscanf (f, "%s %lf %s %lf %lf", name, &mjd, photcode, &fwhm_major, &fwhm_minor)) == 5) {
+    fwhm[Nfwhm].fwhm_major = fwhm_major;
+    fwhm[Nfwhm].fwhm_minor = fwhm_minor;
+    fwhm[Nfwhm].time       = ohana_mjd_to_sec (mjd);
+    fwhm[Nfwhm].photcode   = GetPhotcodeCodebyName (photcode);
+    fwhm[Nfwhm].found      = FALSE;
+
+    if (fwhm[Nfwhm].photcode == 0) {
+      fprintf (stderr, "error in photcode %s\n", photcode);
+      abort();
+    }
+
+    Nfwhm ++;
+    CHECK_REALLOCATE (fwhm, FWHMTable, NFWHM, Nfwhm, 100);
+  }
+
+  if (status != EOF) {
+    fprintf (stderr, "unexpected formatting on line %d (status = %d)\n", Nfwhm, status);
+    exit (2);
+  }
+
+  fprintf (stderr, "loaded %d fwhm values\n", Nfwhm);
+
+  *nfwhm = Nfwhm;
+  return fwhm;
+}
Index: /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/match_fwhm_to_images.c
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/match_fwhm_to_images.c	(revision 31103)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/match_fwhm_to_images.c	(revision 31103)
@@ -0,0 +1,175 @@
+# include "uniphot.h"
+
+/* sort a coordinate pair (X,Y) and the associated index (S) */
+static void sort_fwhm_by_time (FWHMTable *fwhm, int Nfwhm) {
+  
+# define SWAPFUNC(A,B){ FWHMTable tmp;		\
+    tmp = fwhm[A]; fwhm[A] = fwhm[B]; fwhm[B] = tmp;	\
+  }
+# define COMPARE(A,B)(fwhm[A].time < fwhm[B].time)
+
+  OHANA_SORT (Nfwhm, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+}
+
+# define SCALE 25.0
+
+int match_fwhm_to_images (Image *image, off_t Nimage, FWHMTable *fwhm, int Nfwhm) {
+
+  // I have two lists.  I need to match images->tzero to fwhm->time.  multiple images may match a single fwhm
+  
+  // sort both lists by time (or at least get sorted indices)
+  // sweep through both lists, advancing the one that is lagging
+  // apply the matches
+
+  int dT, NImatch, Nmatch;
+  off_t i, Ni, Nf, *index;
+  float *fwhmMajorSet, *fwhmMinorSet;
+
+  // create index and sort
+  ALLOCATE (index, off_t, Nimage);
+  for (i = 0; i < Nimage; i++) {
+    index[i] = i;
+  }
+  sort_image_subset(image, index, Nimage);  // slightly misnamed sort function from libdvo
+
+  // XXX GPC1 hack: accumulate the values within a single exposure (time) to provide the 
+  // mosaic exposure with a mean or median
+  int Ncode = 0;
+  int NCODE = 100;
+  ALLOCATE (fwhmMajorSet, float, NCODE);
+  ALLOCATE (fwhmMinorSet, float, NCODE);
+
+  // sort the fwhm
+  sort_fwhm_by_time (fwhm, Nfwhm);
+
+  NImatch = 0; // matched images
+  for (i = Nf = 0; (i < Nimage) && (Nf < Nfwhm); ) {
+
+    if (i % 1000 == 0) fprintf (stderr, ".");
+    if (Nf % 100 == 0) fprintf (stderr, "!");
+
+    Ni = index[i];
+    dT = image[Ni].tzero - fwhm[Nf].time;
+
+    // negative dT, i is too small (allow a 1sec overlap window)
+    if (dT < -1) {
+      i++;
+      continue;
+    }
+
+    // XXX careful about definition of image->tzero and fwhm->time
+    // negative dT, i is too small (allow a 1sec overlap window)
+    if (dT > +1) {
+      Nf++;
+      continue;
+    }
+
+    {
+	// loop over the exposure in this time block to get a median fwhm
+	float fwhmMajorMedian = 0;
+	float fwhmMinorMedian = 0;
+
+	int NfS;
+	int dTf = 0;
+	Ncode = 0;
+	for (NfS = Nf; (dTf < +1) && (NfS < Nfwhm); NfS++) {
+	    dTf = image[Ni].tzero - fwhm[NfS].time;
+	    if (dTf < -1 ) {
+		break; // too far in fwhm sequence
+	    }
+	    
+	    fwhmMajorSet[Ncode] = fwhm[NfS].fwhm_major;
+	    fwhmMinorSet[Ncode] = fwhm[NfS].fwhm_minor;
+	    Ncode ++;
+	    if (Ncode == NCODE) {
+		NCODE += 100;
+		REALLOCATE(fwhmMajorSet, float, NCODE);
+		REALLOCATE(fwhmMinorSet, float, NCODE);
+	    }
+	}
+
+	// find the medians
+	fsort (fwhmMajorSet, Ncode);
+	fsort (fwhmMinorSet, Ncode);
+	if (Ncode) {
+	    if (Ncode % 2) {
+		fwhmMajorMedian = fwhmMajorSet[(int)(Ncode/2)];
+		fwhmMinorMedian = fwhmMinorSet[(int)(Ncode/2)];
+	    } else {
+		fwhmMajorMedian = 0.5*(fwhmMajorSet[(int)(Ncode/2)-1] + fwhmMajorSet[(int)(Ncode/2)]);
+		fwhmMinorMedian = 0.5*(fwhmMinorSet[(int)(Ncode/2)-1] + fwhmMinorSet[(int)(Ncode/2)]);
+	    }
+	}
+
+	// now find the mosaic image and set the median values
+	int iS;
+	int dTi = 0;
+	for (iS = i; (dTi < +1) && (iS < Nimage); iS++) {
+	    int NiS = index[iS];
+	    dTi = image[NiS].tzero - fwhm[Nf].time;
+	    if (dTi > 1) {
+		break; // too far in image sequence
+	    }
+	    // XXX possible hack: if the mosaics ever get a photcode, this will break
+	    if (image[NiS].photcode) continue;
+	    image[NiS].fwhm_x = fwhmMajorMedian * SCALE;
+	    image[NiS].fwhm_y = fwhmMinorMedian * SCALE;
+	    break;
+	}
+    }
+
+    // we have two sets: images[Ni,Ni+N] and fwhm[Nf,Nf+M], now we need to match them by photcode
+    int iNext = i + 1;
+    int NfNext = Nf + 1;
+    int dTi = 0;
+    int iS;
+    for (iS = i; (dTi < +1) && (iS < Nimage); iS++) {
+	int NiS = index[iS];
+	dTi = image[NiS].tzero - fwhm[Nf].time;
+	if (dTi > 1) {
+	    iNext = iS;
+	    break; // too far in image sequence
+	}
+
+	int dTf = 0;
+	int NfS;
+	for (NfS = Nf; (dTf < +1) && (NfS < Nfwhm); NfS++) {
+	    dTf = image[Ni].tzero - fwhm[NfS].time;
+	    if (dTf < -1 ) {
+		NfNext = NfS;
+		break; // too far in fwhm sequence
+	    }
+
+	    if (image[NiS].photcode == fwhm[NfS].photcode) {
+		// we have a match: set zpt and record the match
+		image[NiS].fwhm_x = fwhm[NfS].fwhm_major * SCALE;
+		image[NiS].fwhm_y = fwhm[NfS].fwhm_minor * SCALE;
+		fwhm[NfS].found = TRUE;
+		NImatch ++;
+	    }
+	}
+    }
+
+    // advance the image counter only -- a single zpt may match more than one image
+    Nf = NfNext;
+    i = iNext;
+  }
+
+  // how many fwhm have we matched?
+  Nmatch = 0;
+  for (Nf = 0; Nf < Nfwhm; Nf++) {
+      if (fwhm[Nf].found) {
+	  Nmatch ++;
+      } else {
+	  // fprintf (stderr, "%d %d\n", fwhm[Nf].time, fwhm[Nf].photcode);
+      }
+  }
+
+  fprintf (stderr, "found %d zpt matches, %d image matches\n", Nmatch, NImatch);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/setfwhm.c
===================================================================
--- /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/setfwhm.c	(revision 31103)
+++ /branches/eam_branches/ipp-20110213/Ohana/src/uniphot/src/setfwhm.c	(revision 31103)
@@ -0,0 +1,48 @@
+# include "uniphot.h"
+
+int main (int argc, char **argv) {
+
+  off_t Nimage;
+  int status, Nfwhm;
+  FITS_DB db;
+  FWHMTable *fwhm;
+  Image *image;
+
+  /* get configuration info, args, lockfile */
+  initialize_setfwhm (argc, argv);
+
+  set_db (&db);
+  status = dvo_image_lock (&db, ImageCat, 60.0, (UPDATE ? LCK_XCLD : LCK_SOFT));
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+  if (db.dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
+
+  fwhm = load_fwhm_table (argv[1], &Nfwhm);
+
+  // load images
+  image  = load_images_setphot (&db, &Nimage);
+  if (!UPDATE) dvo_image_unlock (&db); 
+  
+  // apply the newly loaded fwhm values to the corresponding images
+  match_fwhm_to_images (image, Nimage, fwhm, Nfwhm);
+
+  // write image table
+  if (UPDATE) {
+    dvo_image_save (&db, VERBOSE);
+  }
+
+  exit (0);
+}
+  
+
+/* setphot : set the zero points for images in the db (perhaps based on external information)
+   setphot (zpt_table)
+
+ * load text table of zpts, time (photcode?)
+ * load images
+ * match images to zpts
+ * set zpts
+ * load catalogs
+ * update detection (& averages?)
+
+ */
+
