Index: /trunk/Ohana/src/addstar/include/WISE.h
===================================================================
--- /trunk/Ohana/src/addstar/include/WISE.h	(revision 38061)
+++ /trunk/Ohana/src/addstar/include/WISE.h	(revision 38062)
@@ -35,6 +35,7 @@
 int getWISE_sortStars (WISE_Stars *tstars, int Ntstars);
 
+int loadwise_star_prelim (Stars **star, char *line, int Nmax);
 int loadwise_star_allsky (Stars **star, char *line, int Nmax);
-int loadwise_star_prelim (Stars **star, char *line, int Nmax);
+int loadwise_star_allwise (Stars **star, char *line, int Nmax);
 
 
Index: /trunk/Ohana/src/addstar/src/args_loadwise.c
===================================================================
--- /trunk/Ohana/src/addstar/src/args_loadwise.c	(revision 38061)
+++ /trunk/Ohana/src/addstar/src/args_loadwise.c	(revision 38062)
@@ -53,7 +53,4 @@
   }
 
-enum {MODE_NONE, MODE_ALLWISE, MODE_ALLSKY, MODE_PRELIM};
-int MODE;
-
   /* load the prelim data dump */
   MODE = MODE_ALLWISE;
Index: /trunk/Ohana/src/addstar/src/loadwise_rawdata.c
===================================================================
--- /trunk/Ohana/src/addstar/src/loadwise_rawdata.c	(revision 38061)
+++ /trunk/Ohana/src/addstar/src/loadwise_rawdata.c	(revision 38062)
@@ -7,5 +7,5 @@
 
 /* read in chunks of ~64MB */
-# define NBYTE 0x4000000
+# define NBYTE 0x40000000
 # define DEBUG 0
 
@@ -167,6 +167,7 @@
 	    break;
 	  case MODE_ALLWISE:
+	    loadwise_star_allwise (&stars[Nstars], &buffer[offset], Nbyte - offset);
+	    break;
 	  default:
-	    // loadwise_star_allwise (&stars[Nstars], &buffer[offset], Nbyte - offset);
 	    break;
 	}
Index: /trunk/Ohana/src/addstar/src/loadwise_star_full.c
===================================================================
--- /trunk/Ohana/src/addstar/src/loadwise_star_full.c	(revision 38061)
+++ /trunk/Ohana/src/addstar/src/loadwise_star_full.c	(revision 38062)
@@ -14,4 +14,147 @@
 // RA and DEC have already been set
 int loadwise_star_allwise (Stars **star, char *line, int Nmax) {
+
+  int i;
+  char *ptr;
+
+  if (line == NULL) Shutdown ("format error in WISE");
+
+  ptr = line;
+
+  // I can assign dRA and dDEC to dX and dY if I can consistently set posangle and pltscale
+  star[0][0].measure.posangle = 0.0;
+  star[0][0].measure.pltscale = 1.0;
+
+  ptr = skipNbounds (ptr, '|', 3, Nmax); // skip: desig, ra, dec,
+  star[0][0].measure.dXccd = ToShortPixels((strtod (ptr, NULL) + 0.005)); // sig_ra -- add 5/1000 to avoid truncation
+  ptr = nextWISEfield (ptr);
+  star[0][0].measure.dYccd = ToShortPixels((strtod (ptr, NULL) + 0.005)); // sig_dec
+  ptr = nextWISEfield (ptr);
+
+  // we only know a single set of values for all 4 bands 
+  for (i = 1; i < 4; i++) {
+      star[i][0].measure.dXccd    = star[0][0].measure.dXccd;
+      star[i][0].measure.dYccd    = star[0][0].measure.dYccd;
+      star[i][0].measure.posangle = star[0][0].measure.posangle;
+      star[i][0].measure.pltscale = star[0][0].measure.pltscale;
+  }
+  ptr = skipNbounds (ptr, '|', 5, Nmax); // skip: sig_radec, glon, glat, elon, elat
+
+  star[0][0].measure.Xccd = strtod (ptr, NULL); // wx
+  ptr = nextWISEfield (ptr); // skip wx
+  star[0][0].measure.Yccd = strtod (ptr, NULL); // wy
+  ptr = nextWISEfield (ptr); // skip wy
+
+  for (i = 1; i < 4; i++) {
+      star[i][0].measure.Xccd    = star[0][0].measure.Xccd;
+      star[i][0].measure.Yccd    = star[0][0].measure.Yccd;
+  }
+  ptr = skipNbounds (ptr, '|', 4, Nmax); // skip: cntr, source_id, coadd_id, src
+
+  // W1
+  for (i = 0; i < 4; i++) {
+    char *endpoint;
+      star[i][0].measure.M  = strtod (ptr, &endpoint); // w?mpro
+      if (endpoint == ptr) {
+	star[i][0].measure.M  = NAN;
+      }
+      ptr = nextWISEfield (ptr);
+      star[i][0].measure.dM = strtod (ptr, &endpoint); // w?sigmpro
+      if (endpoint == ptr) {
+	star[i][0].measure.dM  = NAN;
+      }
+      ptr = skipNbounds (ptr, '|', 2, Nmax); // skip: w?sigmpro, w?snr
+      star[i][0].measure.psfChisq = strtod (ptr, NULL); // w?rchi2
+      star[i][0].measure.psfQF = strtod (ptr, NULL); // w?rchi2
+      ptr = nextWISEfield (ptr); // skip : w1rchi2
+
+      // init the photFlags field
+      star[i][0].measure.photFlags = 0;
+  }
+
+  ptr = nextWISEfield (ptr); // skip: rchi2
+
+  // set blend flags for all 4 measures
+  setWISE_blend_flag (star, ptr); // nb & na both used here
+  ptr = skipNbounds (ptr, '|', 2, Nmax); // skip: nb, na
+
+  for (i = 0; i < 4; i++) {
+      setWISE_sat_flag (star[i], ptr); // w1sat
+      ptr = nextWISEfield (ptr); 
+  }
+  ptr = nextWISEfield (ptr); // skip satnum
+
+  ptr = skipNbounds (ptr, '|', 15, Nmax); // skip pm info
+
+  for (i = 0; i < 4; i++) {
+      setWISE_cc_flag (star[i], ptr[i]); // cc_flags
+  }
+  ptr = nextWISEfield (ptr); // skip cc_flags
+  ptr = nextWISEfield (ptr); // skip rel
+
+  // set ext flags for all 4 measures
+  setWISE_ext_flag_allsky (star, ptr[0]); // ext_flg
+  ptr = nextWISEfield (ptr); // skip ext_flags
+
+  for (i = 0; i < 4; i++) {
+      setWISE_var_flag_allsky (star[i], ptr[i]); // var_flg
+  }
+  ptr = nextWISEfield (ptr); // skip var_flags
+
+  for (i = 0; i < 4; i++) {
+      setWISE_ph_qual (star[i], ptr[i]); // ph_qual
+  }
+
+  ptr = skipNbounds (ptr, '|', 157, Nmax); // skip: det_bit, moon_lev, w?nm, w?m, w?cov, etc, etc.
+  // w?frtr dropped, (-4), use_src, best_use_cntr, ngrp added (+3), w?dmag dropped, w?k added, 
+
+  for (i = 0; i < 4; i++) {
+    ptr = skipNbounds (ptr, '|', 8, Nmax); // skip: w?magp, w?sigp1,2, w?dmag, w?ndf, w?m1q, w?mjdmin, w?mjdmax
+    // w?magp is at 217, ph_qual is at 60
+    // double mjdmin = strtod (ptr, NULL); // mjd min
+    // ptr = nextWISEfield (ptr); // skip
+    // double mjdmax = strtod (ptr, NULL); // mjd max
+    // ptr = nextWISEfield (ptr); // skip mjd max
+    double mjdmean = strtod (ptr, NULL); // mjd mean
+    ptr = nextWISEfield (ptr); // skip mjd mean
+
+    // fprintf (stderr, "w%d mjd: %f\n", i, mjdmean);
+
+    // the release is based on data taken in the period 14 January 2010 to 29 April 2010
+    if (mjdmean == 0.0) {
+      star[i][0].measure.t = 0;
+    } else {
+      star[i][0].measure.t = ohana_mjd_to_sec (mjdmean);
+    }
+  }
+
+  star[0][0].measure.photcode  = WISE_W1;
+  star[0][0].measure.detID   = 0;
+  star[0][0].measure.imageID = 0;
+
+  star[1][0].measure.photcode  = WISE_W2;
+  star[1][0].measure.detID   = 0;
+  star[1][0].measure.imageID = 0;
+
+  star[2][0].measure.photcode  = WISE_W3;
+  star[2][0].measure.detID   = 0;
+  star[2][0].measure.imageID = 0;
+
+  star[3][0].measure.photcode  = WISE_W4;
+  star[3][0].measure.detID   = 0;
+  star[3][0].measure.imageID = 0;
+
+  return TRUE;
+}
+
+// there are slight format differences between the prelim data dump and the allsky data dump:
+// * after ph_qual & det_bit : new field moon_lev
+// * for each filter, after w?sigp2 : new fields w?dmag, w?ndf, w?mlq, w?mjdmin, w?mjdmax, w?mjdmean
+// * after w4mdjmean : new fields rho12, rho23, rho34, q12, q23, q34
+// * after k_msig_2mass : new fields best_use_cntr, ngrp
+
+// fill in the data for a WISE quad star.  takes a pointer to the start of the line the
+// RA and DEC have already been set
+int loadwise_star_allsky (Stars **star, char *line, int Nmax) {
 
   int i;
@@ -84,11 +227,8 @@
   ptr = nextWISEfield (ptr); // skip satnum
 
-  ptr = skipNbounds (ptr, '|', 15, Nmax); // skip pm info
-
-  for (i = 0; i < 4; i++) {
-      setWISE_cc_flag (star[i], ptr[i]); // cc_flags
+  for (i = 0; i < 4; i++) {
+      setWISE_cc_flag (star[i], ptr[i]); // cc_flg
   }
   ptr = nextWISEfield (ptr); // skip cc_flags
-  ptr = nextWISEfield (ptr); // skip rel
 
   // set ext flags for all 4 measures
@@ -105,9 +245,8 @@
   }
 
-  ptr = skipNbounds (ptr, '|', 158, Nmax); // skip: det_bit, moon_lev, w?nm, w?m, w?cov, etc, etc.
-  // w?frtr dropped, (-4), use_src, best_use_cntr, ngrp added (+3), w?dmag dropped, w?k added, 
-
-  for (i = 0; i < 4; i++) {
-    ptr = skipNbounds (ptr, '|', 8, Nmax); // skip: w?magp, w?sigp1,2, w?dmag, w?ndf, w?m1q, w?mjdmin, w?mjdmax
+  ptr = skipNbounds (ptr, '|', 159, Nmax); // skip: det_bit, moon_lev, w?nm, w?m, w?cov, etc, etc.
+
+  for (i = 0; i < 4; i++) {
+    ptr = skipNbounds (ptr, '|', 8, Nmax); // skip: det_bit, moon_lev, w?nm, w?m, w?cov, etc, etc.
 
     // double mjdmin = strtod (ptr, NULL); // mjd min
@@ -147,13 +286,7 @@
 }
 
-// there are slight format differences between the prelim data dump and the allsky data dump:
-// * after ph_qual & det_bit : new field moon_lev
-// * for each filter, after w?sigp2 : new fields w?dmag, w?ndf, w?mlq, w?mjdmin, w?mjdmax, w?mjdmean
-// * after w4mdjmean : new fields rho12, rho23, rho34, q12, q23, q34
-// * after k_msig_2mass : new fields best_use_cntr, ngrp
-
 // fill in the data for a WISE quad star.  takes a pointer to the start of the line the
 // RA and DEC have already been set
-int loadwise_star_allsky (Stars **star, char *line, int Nmax) {
+int loadwise_star_prelim (Stars **star, char *line, int Nmax) {
 
   int i;
@@ -196,136 +329,4 @@
   // W1
   for (i = 0; i < 4; i++) {
-    char *endpoint;
-      star[i][0].measure.M  = strtod (ptr, &endpoint); // w?mpro
-      if (endpoint == ptr) {
-	star[i][0].measure.M  = NAN;
-      }
-      ptr = nextWISEfield (ptr);
-      star[i][0].measure.dM = strtod (ptr, &endpoint); // w?sigmpro
-      if (endpoint == ptr) {
-	star[i][0].measure.dM  = NAN;
-      }
-      ptr = skipNbounds (ptr, '|', 2, Nmax); // skip: w?sigmpro, w?snr
-      star[i][0].measure.psfChisq = strtod (ptr, NULL); // w?rchi2
-      ptr = nextWISEfield (ptr); // skip : w1rchi2
-
-      // init the photFlags field
-      star[i][0].measure.photFlags = 0;
-  }
-
-  ptr = nextWISEfield (ptr); // skip: rchi2
-
-  // set blend flags for all 4 measures
-  setWISE_blend_flag (star, ptr); // nb & na both used here
-  ptr = skipNbounds (ptr, '|', 2, Nmax); // skip: nb, na
-
-  for (i = 0; i < 4; i++) {
-      setWISE_sat_flag (star[i], ptr); // w1sat
-      ptr = nextWISEfield (ptr); 
-  }
-  ptr = nextWISEfield (ptr); // skip satnum
-
-  for (i = 0; i < 4; i++) {
-      setWISE_cc_flag (star[i], ptr[i]); // cc_flg
-  }
-  ptr = nextWISEfield (ptr); // skip cc_flags
-
-  // set ext flags for all 4 measures
-  setWISE_ext_flag_allsky (star, ptr[0]); // ext_flg
-  ptr = nextWISEfield (ptr); // skip ext_flags
-
-  for (i = 0; i < 4; i++) {
-      setWISE_var_flag_allsky (star[i], ptr[i]); // var_flg
-  }
-  ptr = nextWISEfield (ptr); // skip var_flags
-
-  for (i = 0; i < 4; i++) {
-      setWISE_ph_qual (star[i], ptr[i]); // ph_qual
-  }
-
-  ptr = skipNbounds (ptr, '|', 159, Nmax); // skip: det_bit, moon_lev, w?nm, w?m, w?cov, etc, etc.
-
-  for (i = 0; i < 4; i++) {
-    ptr = skipNbounds (ptr, '|', 8, Nmax); // skip: det_bit, moon_lev, w?nm, w?m, w?cov, etc, etc.
-
-    // double mjdmin = strtod (ptr, NULL); // mjd min
-    // ptr = nextWISEfield (ptr); // skip
-    // double mjdmax = strtod (ptr, NULL); // mjd max
-    // ptr = nextWISEfield (ptr); // skip mjd max
-    double mjdmean = strtod (ptr, NULL); // mjd mean
-    ptr = nextWISEfield (ptr); // skip mjd mean
-
-    // fprintf (stderr, "w%d mjd: %f\n", i, mjdmean);
-
-    // the release is based on data taken in the period 14 January 2010 to 29 April 2010
-    if (mjdmean == 0.0) {
-      star[i][0].measure.t = 0;
-    } else {
-      star[i][0].measure.t = ohana_mjd_to_sec (mjdmean);
-    }
-  }
-
-  star[0][0].measure.photcode  = WISE_W1;
-  star[0][0].measure.detID   = 0;
-  star[0][0].measure.imageID = 0;
-
-  star[1][0].measure.photcode  = WISE_W2;
-  star[1][0].measure.detID   = 0;
-  star[1][0].measure.imageID = 0;
-
-  star[2][0].measure.photcode  = WISE_W3;
-  star[2][0].measure.detID   = 0;
-  star[2][0].measure.imageID = 0;
-
-  star[3][0].measure.photcode  = WISE_W4;
-  star[3][0].measure.detID   = 0;
-  star[3][0].measure.imageID = 0;
-
-  return TRUE;
-}
-
-// fill in the data for a WISE quad star.  takes a pointer to the start of the line the
-// RA and DEC have already been set
-int loadwise_star_prelim (Stars **star, char *line, int Nmax) {
-
-  int i;
-  char *ptr;
-
-  if (line == NULL) Shutdown ("format error in WISE");
-
-  ptr = line;
-
-  // I can assign dRA and dDEC to dX and dY if I can consistently set posangle and pltscale
-  star[0][0].measure.posangle = 0.0;
-  star[0][0].measure.pltscale = 1.0;
-
-  ptr = skipNbounds (ptr, '|', 3, Nmax); // skip: desig, ra, dec,
-  star[0][0].measure.dXccd = ToShortPixels(strtod (ptr, NULL)); // sig_ra
-  ptr = nextWISEfield (ptr);
-  star[0][0].measure.dYccd = ToShortPixels(strtod (ptr, NULL)); // sig_dec
-  ptr = nextWISEfield (ptr);
-
-  // we only know a single set of values for all 4 bands 
-  for (i = 1; i < 4; i++) {
-      star[i][0].measure.dXccd    = star[0][0].measure.dXccd;
-      star[i][0].measure.dYccd    = star[0][0].measure.dYccd;
-      star[i][0].measure.posangle = star[0][0].measure.posangle;
-      star[i][0].measure.pltscale = star[0][0].measure.pltscale;
-  }
-  ptr = skipNbounds (ptr, '|', 5, Nmax); // skip: sig_radec, glon, glat, elon, elat
-
-  star[0][0].measure.Xccd = strtod (ptr, NULL); // wx
-  ptr = nextWISEfield (ptr); // skip wx
-  star[0][0].measure.Yccd = strtod (ptr, NULL); // wy
-  ptr = nextWISEfield (ptr); // skip wy
-
-  for (i = 1; i < 4; i++) {
-      star[i][0].measure.Xccd    = star[0][0].measure.Xccd;
-      star[i][0].measure.Yccd    = star[0][0].measure.Yccd;
-  }
-  ptr = skipNbounds (ptr, '|', 4, Nmax); // skip: cntr, source_id, coadd_id, src
-
-  // W1
-  for (i = 0; i < 4; i++) {
       star[i][0].measure.M  = strtod (ptr, NULL); // w?mpro
       ptr = nextWISEfield (ptr);
@@ -413,4 +414,5 @@
 # define FLAG_PH_U 	      0x00000008 // quality flag 'U'
 # define FLAG_PH_X 	      0x00000010 // quality flag 'X'
+# define FLAG_PH_Z 	      0x00000020 // quality flag 'Z'
 
 # define FLAG_SATURATED_PIX   0x00000100 // sat > 0.0
@@ -429,6 +431,7 @@
 # define FLAG_EXT_BY_XSC      0x04000000 // ext == 1
 
-# define FLAG_VARIABLE_LEVEL1 0x10000000 // var_flg == 1 to 4
-# define FLAG_VARIABLE_LEVEL2 0x20000000 // var_flg == 5 to 7
+// note prelim version had 1 -> 1-4, 2 -> 5-6
+# define FLAG_VARIABLE_LEVEL1 0x10000000 // var_flg == 0 to 5
+# define FLAG_VARIABLE_LEVEL2 0x20000000 // var_flg == 6 or 7
 # define FLAG_VARIABLE_LEVEL3 0x40000000 // var_flg == 8 or 9
 
@@ -606,4 +609,5 @@
     case 'U': star[0].measure.photFlags |= FLAG_PH_U; break;
     case 'X': star[0].measure.photFlags |= FLAG_PH_X; break;
+    case 'Z': star[0].measure.photFlags |= FLAG_PH_Z; break;
     default: 
       fprintf (stderr, "error in ph_flag: %c\n", qual);
Index: /trunk/Ohana/src/dvomerge/src/args.c
===================================================================
--- /trunk/Ohana/src/dvomerge/src/args.c	(revision 38061)
+++ /trunk/Ohana/src/dvomerge/src/args.c	(revision 38062)
@@ -206,4 +206,11 @@
   }
 
+  UPDATE_CATFORMAT = NULL;
+  if ((N = get_argument (*argc, argv, "-update-catformat"))) {
+    remove_argument (N, argc, argv);
+    UPDATE_CATFORMAT = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
   /* replace measurement, don't duplicate */
   REPLACE_BY_PHOTCODE = FALSE;
Index: /trunk/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c
===================================================================
--- /trunk/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c	(revision 38061)
+++ /trunk/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c	(revision 38062)
@@ -270,11 +270,12 @@
 
     char tmpline[DVO_MAX_PATH];
-    if (VERBOSE)             { snprintf (tmpline, DVO_MAX_PATH, "%s -v",               command); strcpy (command, tmpline); }
-    if (VERIFY)              { snprintf (tmpline, DVO_MAX_PATH, "%s -verify",          command); strcpy (command, tmpline); }
-    if (VERIFY_CATALOG_ONLY) { snprintf (tmpline, DVO_MAX_PATH, "%s -verify-catalogs", command); strcpy (command, tmpline); }
-    if (REPLACE_BY_PHOTCODE) { snprintf (tmpline, DVO_MAX_PATH, "%s -replace",         command); strcpy (command, tmpline); }
-    if (PARALLEL_INPUT)      { snprintf (tmpline, DVO_MAX_PATH, "%s -parallel-input",  command); strcpy (command, tmpline); }
-    if (FORCE_MERGE)         { snprintf (tmpline, DVO_MAX_PATH, "%s -force-merge",     command); strcpy (command, tmpline); }
-    if (MATCHED_TABLES)      { snprintf (tmpline, DVO_MAX_PATH, "%s -matched-tables",  command); strcpy (command, tmpline); }
+    if (VERBOSE)             { snprintf (tmpline, DVO_MAX_PATH, "%s -v",                command); strcpy (command, tmpline); }
+    if (VERIFY)              { snprintf (tmpline, DVO_MAX_PATH, "%s -verify",           command); strcpy (command, tmpline); }
+    if (VERIFY_CATALOG_ONLY) { snprintf (tmpline, DVO_MAX_PATH, "%s -verify-catalogs",  command); strcpy (command, tmpline); }
+    if (REPLACE_BY_PHOTCODE) { snprintf (tmpline, DVO_MAX_PATH, "%s -replace",          command); strcpy (command, tmpline); }
+    if (PARALLEL_INPUT)      { snprintf (tmpline, DVO_MAX_PATH, "%s -parallel-input",   command); strcpy (command, tmpline); }
+    if (FORCE_MERGE)         { snprintf (tmpline, DVO_MAX_PATH, "%s -force-merge",      command); strcpy (command, tmpline); }
+    if (MATCHED_TABLES)      { snprintf (tmpline, DVO_MAX_PATH, "%s -matched-tables",   command); strcpy (command, tmpline); }
+    if (UPDATE_CATFORMAT)    { snprintf (tmpline, DVO_MAX_PATH, "%s -update-catformat %s", command, UPDATE_CATFORMAT); strcpy (command, tmpline); }
 
     // add some config variables:
Index: /trunk/Ohana/src/kapa2/src/DrawObjects.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawObjects.c	(revision 38061)
+++ /trunk/Ohana/src/kapa2/src/DrawObjects.c	(revision 38062)
@@ -630,4 +630,64 @@
     }
   }
+  if (object[0].ptype == 14) {	/* upside-down filled triangle */
+    XPoint points[4];
+    for (i = 0; i < object[0].Npts; i++) {
+      if (!(finite(x[i]) && finite(y[i]))) continue;
+      sx = x[i]*mxi + y[i]*mxj + bx + XCENTER;
+      sy = x[i]*myi + y[i]*myj + by + YCENTER;
+      if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	  (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy)) {
+	if (scaleColor) {
+	  if (!finite(z[i])) continue;
+	  int pixel = MIN (graphic->Npixels - 2, MAX (0, z[i]*(graphic->Npixels - 1)));
+	  XSetForeground (graphic->display, graphic->gc, graphic->cmap[pixel].pixel);
+	}
+	D = scaleSize ? dz*z[i] : ds;
+	points[0].x = sx - D;  points[0].y = sy - 0.58*D;  
+	points[1].x = sx + D;  points[1].y = sy - 0.58*D;  
+	points[2].x = sx;      points[2].y = sy + 1.15*D;  
+	points[3].x = sx - D;  points[3].y = sy - 0.58*D;  
+	XFillPolygon (graphic->display, graphic->window, graphic->gc, points, 4, Convex, CoordModeOrigin);
+      }
+    }
+  }
+  if (object[0].ptype == 15) {	/* upside-down open triangle */
+    for (i = 0; i < object[0].Npts; i++) {
+      if (!(finite(x[i]) && finite(y[i]))) continue;
+      sx = x[i]*mxi + y[i]*mxj + bx + XCENTER;
+      sy = x[i]*myi + y[i]*myj + by + YCENTER;
+      if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	  (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy)) {
+	if (scaleColor) {
+	  if (!finite(z[i])) continue;
+	  int pixel = MIN (graphic->Npixels - 2, MAX (0, z[i]*(graphic->Npixels - 1)));
+	  XSetForeground (graphic->display, graphic->gc, graphic->cmap[pixel].pixel);
+	}
+	D = scaleSize ? dz*z[i] : ds;
+	DrawLine (sx - D, sy - 0.58*D, sx + D, sy - 0.58*D);
+	DrawLine (sx + D, sy - 0.58*D, sx,     sy + 1.15*D);
+	DrawLine (sx,     sy + 1.15*D, sx - D, sy - 0.58*D);
+      }
+    }
+  }
+  if (object[0].ptype == 16) {	/* upside-down Y */
+    for (i = 0; i < object[0].Npts; i++) {
+      if (!(finite(x[i]) && finite(y[i]))) continue;
+      sx = x[i]*mxi + y[i]*mxj + bx + XCENTER;
+      sy = x[i]*myi + y[i]*myj + by + YCENTER;
+      if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	  (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy)) {
+	if (scaleColor) {
+	  if (!finite(z[i])) continue;
+	  int pixel = MIN (graphic->Npixels - 2, MAX (0, z[i]*(graphic->Npixels - 1)));
+	  XSetForeground (graphic->display, graphic->gc, graphic->cmap[pixel].pixel);
+	}
+	D = scaleSize ? dz*z[i] : ds;
+	DrawLine (sx, sy, sx - D, sy + 0.58*D);
+	DrawLine (sx, sy, sx + D, sy + 0.58*D);
+	DrawLine (sx, sy, sx,     sy - 1.15*D);
+      }
+    }
+  }
   if (object[0].ptype == 100) {	/* connect a pair of points */
 
@@ -652,8 +712,10 @@
 void DrawXErrors (KapaGraphWidget *graph, Gobjects *object) {
   
-  int i, bar;
-  float *x, *y, *dxm, *dxp;
+  int i, bar, dz, ds, D;
+  float *x, *y, *z, *dxm, *dxp;
   double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
   double sx0, sy0, sx1, sy1, sz, sx10, sx11, X0, X1, Y0, Y1;
+
+  int scaleSize = (object[0].size < 0);
 
   mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
@@ -670,5 +732,8 @@
   by = byi + byj;
   
-  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  ds = 0.5 * (graphic->dx + graphic->dy) * 0.003 * object[0].size;
+  dz = 0.5 * (graphic->dx + graphic->dy) * 0.010;
+
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; z = object[0].z;
   bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
   
@@ -678,10 +743,19 @@
   Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
 
+  /// XXX NOTE : D should be modified by (mxi,myi) for tilted axes dx = D*(mxi/mx), dy = D*(myi/mx)
+
   for (i = 0; i < object[0].Npts; i++) {
-    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
-    sx0 = x[i]*mxi + y[i]*mxj + bx + XCENTER;
+    // for open circles, only go to the outer radius
+    D = 0;
+    if (object[0].ptype ==  7) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  1) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  5) { D = scaleSize ? 0.66*dz*z[i] : 0.66*ds; }
+    if (object[0].ptype == 15) { D = scaleSize ? 0.66*dz*z[i] : 0.66*ds; }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) goto skip_dxp;
+    if (D > fabs(dxp[i]*mxi)) goto skip_dxp;
+    sx0 = x[i]*mxi + y[i]*mxj + bx + XCENTER + D;
     sy0 = x[i]*myi + y[i]*myj + by + YCENTER;
-    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx + XCENTER;
-    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by + YCENTER;
+    sx1 = sx0 + dxp[i]*mxi - D;
+    sy1 = sy0 + dxp[i]*myi;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -696,9 +770,11 @@
       }
     }
+  skip_dxp:
     if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
-    sx0 = x[i]*mxi + y[i]*mxj + bx + XCENTER;
+    if (D > fabs(dxm[i]*mxi)) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx + XCENTER - D;
     sy0 = x[i]*myi + y[i]*myj + by + YCENTER;
-    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx + XCENTER;
-    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by + YCENTER;
+    sx1 = sx0 - dxm[i]*mxi + D;
+    sy1 = sy0 - dxm[i]*myi;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -719,8 +795,10 @@
 void DrawYErrors (KapaGraphWidget *graph, Gobjects *object) {
 
-  int i, bar;
-  float *x, *y, *dym, *dyp;
+  int i, bar, dz, ds, D;
+  float *x, *y, *z, *dym, *dyp;
   double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
   double sx0, sy0, sx1, sy1, sz, sx10, sx11, X0, X1, Y0, Y1;
+
+  int scaleSize = (object[0].size < 0);
 
   mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
@@ -737,5 +815,8 @@
   by = byi + byj;
   
-  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  ds = 0.5 * (graphic->dx + graphic->dy) * 0.003 * object[0].size;
+  dz = 0.5 * (graphic->dx + graphic->dy) * 0.010;
+
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; z = object[0].z;
   bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
   
@@ -745,10 +826,19 @@
   Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
 
+  /// XXX NOTE : D should be modified by (mxi,myi) for tilted axes dx = D*(mxi/mx), dy = D*(myi/mx)
+
   for (i = 0; i < object[0].Npts; i++) {
-    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    // for open circles, only go to the outer radius
+    D = 0;
+    if (object[0].ptype ==  7) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  1) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  5) { D = scaleSize ? 1.15*dz*z[i] : 1.15*ds; }
+    if (object[0].ptype == 15) { D = scaleSize ? 0.58*dz*z[i] : 0.58*ds; }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) goto skip_dyp;
+    if (D > fabs(dyp[i]*myj)) goto skip_dyp;
     sx0 = x[i]*mxi + y[i]*mxj + bx + XCENTER;
-    sy0 = x[i]*myi + y[i]*myj + by + YCENTER;
+    sy0 = x[i]*myi + y[i]*myj + by + YCENTER - D;
     sx1 = sx0 + dyp[i]*mxj;
-    sy1 = sy0 + dyp[i]*myj;
+    sy1 = sy0 + dyp[i]*myj + D;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -763,9 +853,13 @@
       }
     }
+  skip_dyp:
     if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    if (object[0].ptype ==  5) { D = scaleSize ? 0.58*dz*z[i] : 0.58*ds; }
+    if (object[0].ptype == 15) { D = scaleSize ? 1.15*dz*z[i] : 1.15*ds; }
+    if (D > fabs(dym[i]*myj)) continue;
     sx0 = x[i]*mxi + y[i]*mxj + bx + XCENTER;
-    sy0 = x[i]*myi + y[i]*myj + by + YCENTER;
-    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx + XCENTER;
-    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by + YCENTER;
+    sy0 = x[i]*myi + y[i]*myj + by + YCENTER + D;
+    sx1 = sx0 - dym[i]*mxj;
+    sy1 = sy0 - dym[i]*myj - D;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
Index: /trunk/Ohana/src/kapa2/src/InterpretKeys.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/InterpretKeys.c	(revision 38061)
+++ /trunk/Ohana/src/kapa2/src/InterpretKeys.c	(revision 38062)
@@ -98,7 +98,6 @@
       Screen_to_Image (&X, &Y, (double)(event[0].x + 0.5), (double)(event[0].y + 0.5), &image[0].picture); \
       UpdateStatusBox (graphic, image, X, Y, 0.0, 1); \
+      Remap (graphic, image); \
       break;
-
-//    Remap (graphic, image); 
 
     // the number of entries here must match the value of NCHANNELS in contants.h
Index: /trunk/Ohana/src/kapa2/src/PSObjects.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PSObjects.c	(revision 38061)
+++ /trunk/Ohana/src/kapa2/src/PSObjects.c	(revision 38062)
@@ -403,9 +403,22 @@
 	D = scaleSize ? dz*z[i] : ds;
 	FillTriangle (sx - D, sy - 0.58*D, sx + D, sy - 0.58*D, sx, sy + 1.15*D);
-	/*
-	  DrawLine (sx - D, sy + 0.58*D, sx + D, sy + 0.58*D);
-	  DrawLine (sx + D, sy + 0.58*D, sx,          sy - 1.15*D);
-	  DrawLine (sx,          sy - 1.15*D, sx - D, sy + 0.58*D);
-	*/
+      }
+    }
+  }
+  if (object[0].ptype == 14) {	/* filled triangle */
+    for (i = 0; i < object[0].Npts; i++) {
+      if (!(finite(x[i]) && finite(y[i]))) continue;
+      sx = x[i]*mxi + y[i]*mxj + bx;
+      sy = x[i]*myi + y[i]*myj + by;
+      if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	  (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+      {
+	if (scaleColor) {
+	  if (!finite(z[i])) continue;
+	  int pixel = MIN (graphic->Npixels - 2, MAX (0, z[i]*(graphic->Npixels - 1)));
+	  fprintf (f, "%4.2f %4.2f %4.2f setrgbcolor\n", pixel1[pixel], pixel2[pixel], pixel3[pixel]);
+	}
+	D = scaleSize ? dz*z[i] : ds;
+	FillTriangle (sx - D, sy + 0.58*D, sx + D, sy + 0.58*D, sx, sy - 1.15*D);
       }
     }
@@ -426,6 +439,26 @@
 	D = scaleSize ? dz*z[i] : ds;
 	DrawLine (sx - D, sy - 0.58*D, sx + D, sy - 0.58*D);
-	DrawLine (sx + D, sy - 0.58*D, sx,          sy + 1.15*D);
-	DrawLine (sx,          sy + 1.15*D, sx - D, sy - 0.58*D);
+	DrawLine (sx + D, sy - 0.58*D, sx,     sy + 1.15*D);
+	DrawLine (sx,     sy + 1.15*D, sx - D, sy - 0.58*D);
+      }
+    }
+  }
+  if (object[0].ptype == 15) {	/* upside-down open triangle */
+    for (i = 0; i < object[0].Npts; i++) {
+      if (!(finite(x[i]) && finite(y[i]))) continue;
+      sx = x[i]*mxi + y[i]*mxj + bx;
+      sy = x[i]*myi + y[i]*myj + by;
+      if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	  (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+      {
+	if (scaleColor) {
+	  if (!finite(z[i])) continue;
+	  int pixel = MIN (graphic->Npixels - 2, MAX (0, z[i]*(graphic->Npixels - 1)));
+	  fprintf (f, "%4.2f %4.2f %4.2f setrgbcolor\n", pixel1[pixel], pixel2[pixel], pixel3[pixel]);
+	}
+	D = scaleSize ? dz*z[i] : ds;
+	DrawLine (sx - D, sy + 0.58*D, sx + D, sy + 0.58*D);
+	DrawLine (sx + D, sy + 0.58*D, sx,     sy - 1.15*D);
+	DrawLine (sx,     sy - 1.15*D, sx - D, sy + 0.58*D);
       }
     }
@@ -448,4 +481,24 @@
 	DrawLine (sx, sy, sx + D, sy + 0.58*D);
 	DrawLine (sx, sy, sx,          sy - 1.15*D);
+      }
+    }
+  }
+  if (object[0].ptype == 16) {	/* Y */
+    for (i = 0; i < object[0].Npts; i++) {
+      if (!(finite(x[i]) && finite(y[i]))) continue;
+      sx = x[i]*mxi + y[i]*mxj + bx;
+      sy = x[i]*myi + y[i]*myj + by;
+      if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	  (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+      {
+	if (scaleColor) {
+	  if (!finite(z[i])) continue;
+	  int pixel = MIN (graphic->Npixels - 2, MAX (0, z[i]*(graphic->Npixels - 1)));
+	  fprintf (f, "%4.2f %4.2f %4.2f setrgbcolor\n", pixel1[pixel], pixel2[pixel], pixel3[pixel]);
+	}
+	D = scaleSize ? dz*z[i] : ds;
+	DrawLine (sx, sy, sx - D, sy - 0.58*D);
+	DrawLine (sx, sy, sx + D, sy - 0.58*D);
+	DrawLine (sx, sy, sx,     sy + 1.15*D);
       }
     }
@@ -557,8 +610,10 @@
 void PSXErrors (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
   
-  int i, bar;
-  float *x, *y, *dxm, *dxp;
+  int i, bar, dz, ds, D;
+  float *x, *y, *z, *dxm, *dxp;
   double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
   double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  int scaleSize = (object[0].size < 0);
 
   mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
@@ -575,5 +630,8 @@
   by = byi + byj;
   
-  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  ds = 0.5 * (graphic->dx + graphic->dy) * 0.003 * object[0].size;
+  dz = 0.5 * (graphic->dx + graphic->dy) * 0.010;
+
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; z = object[0].z;
   bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
    
@@ -583,10 +641,19 @@
   double Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
 
+  /// XXX NOTE : D should be modified by (mxi,myi) for tilted axes dx = D*(mxi/mx), dy = D*(myi/mx)
+
   for (i = 0; i < object[0].Npts; i++) {
-    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
-    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    // for open circles, only go to the outer radius
+    D = 0;
+    if (object[0].ptype ==  7) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  1) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  5) { D = scaleSize ? 0.66*dz*z[i] : 0.66*ds; }
+    if (object[0].ptype == 15) { D = scaleSize ? 0.66*dz*z[i] : 0.66*ds; }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) goto skip_dxp;
+    if (D > fabs(dxp[i]*mxi)) goto skip_dxp;
+    sx0 = x[i]*mxi + y[i]*mxj + bx + D;
     sy0 = x[i]*myi + y[i]*myj + by;
-    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
-    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    sx1 = sx0 + dxp[i]*mxi - D;
+    sy1 = sy0 + dxp[i]*myi;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -595,17 +662,17 @@
       {
 	ClipLinePS (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1, f);
-	// DrawLine (sx0, sy0, sx1, sy1);
 	if (bar) {
 	  sx10 = sy1 - sz;
 	  sx11 = sy1 + sz;
 	  ClipLinePS (sx1, sx10, sx1, sx11, X0, Y0, X1, Y1, f);
-	  // DrawLine (sx1, sx10, sx1, sx11);
-	}
-      }
+	}
+      }
+  skip_dxp:
     if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
-    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    if (D > fabs(dxm[i]*mxi)) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx - D;
     sy0 = x[i]*myi + y[i]*myj + by;
-    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
-    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    sx1 = sx0 - dxm[i]*mxi + D;
+    sy1 = sy0 - dxm[i]*myi;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -614,10 +681,8 @@
       {
 	ClipLinePS (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1, f);
-	// DrawLine (sx0, sy0, sx1, sy1);
 	if (bar) {
 	  sx10 = sy1 - sz;
 	  sx11 = sy1 + sz;
 	  ClipLinePS (sx1, sx10, sx1, sx11, X0, Y0, X1, Y1, f);
-	  // DrawLine (sx1, sx10, sx1, sx11);
 	}
       }
@@ -629,9 +694,11 @@
 void PSYErrors (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
   
-  int i, bar;
-  float *x, *y, *dym, *dyp;
+  int i, bar, dz, ds, D;
+  float *x, *y, *z, *dym, *dyp;
   double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
   double sx0, sy0, sx1, sy1, sz, sx10, sx11;
   
+  int scaleSize = (object[0].size < 0);
+
   mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
   mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
@@ -647,5 +714,8 @@
   by = byi + byj;
   
-  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  ds = 0.5 * (graphic->dx + graphic->dy) * 0.003 * object[0].size;
+  dz = 0.5 * (graphic->dx + graphic->dy) * 0.010;
+
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; z = object[0].z;
   bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
   
@@ -655,10 +725,19 @@
   double Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
 
+  /// XXX NOTE : D should be modified by (mxi,myi) for tilted axes dx = D*(mxi/mx), dy = D*(myi/mx)
+
   for (i = 0; i < object[0].Npts; i++) {
-    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    // for open circles, only go to the outer radius
+    D = 0;
+    if (object[0].ptype ==  7) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  1) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  5) { D = scaleSize ? 1.15*dz*z[i] : 1.15*ds; }
+    if (object[0].ptype == 15) { D = scaleSize ? 0.58*dz*z[i] : 0.58*ds; }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) goto skip_dyp;
+    if (D > fabs(dyp[i]*myj)) goto skip_dyp;
     sx0 = x[i]*mxi + y[i]*mxj + bx;
-    sy0 = x[i]*myi + y[i]*myj + by;
-    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
-    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
+    sy0 = x[i]*myi + y[i]*myj + by - D;
+    sx1 = sx0 + dyp[i]*mxj;
+    sy1 = sy0 + dyp[i]*myj + D;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -667,17 +746,19 @@
       {
 	ClipLinePS (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1, f);
-	// DrawLine (sx0, sy0, sx1, sy1);
 	if (bar) {
 	  sx10 = sx1 - sz;
 	  sx11 = sx1 + sz;
 	  ClipLinePS (sx10, sy1, sx11, sy1, X0, Y0, X1, Y1, f);
-	  // DrawLine (sx10, sy1, sx11, sy1);
-	}
-      }
+	}
+      }
+  skip_dyp:
     if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    if (object[0].ptype ==  5) { D = scaleSize ? 0.58*dz*z[i] : 0.58*ds; }
+    if (object[0].ptype == 15) { D = scaleSize ? 1.15*dz*z[i] : 1.15*ds; }
+    if (D > fabs(dym[i]*myj)) continue;
     sx0 = x[i]*mxi + y[i]*mxj + bx;
-    sy0 = x[i]*myi + y[i]*myj + by;
-    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
-    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    sy0 = x[i]*myi + y[i]*myj + by + D;
+    sx1 = sx0 - dym[i]*mxj;
+    sy1 = sy0 - dym[i]*myj - D;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -686,10 +767,8 @@
       {
 	ClipLinePS (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1, f);
-	// DrawLine (sx0, sy0, sx1, sy1);
 	if (bar) {
 	  sx10 = sx1 - sz;
 	  sx11 = sx1 + sz;
 	  ClipLinePS (sx10, sy1, sx11, sy1, X0, Y0, X1, Y1, f);
-	  // DrawLine (sx10, sy1, sx11, sy1);
 	}
       }
Index: /trunk/Ohana/src/kapa2/src/bDrawObjects.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/bDrawObjects.c	(revision 38061)
+++ /trunk/Ohana/src/kapa2/src/bDrawObjects.c	(revision 38062)
@@ -406,4 +406,26 @@
     }
   }
+  if (object[0].ptype == 14) {	/* filled triangle */
+    for (i = 0; i < object[0].Npts; i++) {
+      if (!(finite(x[i]) && finite(y[i]))) continue;
+      sx = x[i]*mxi + y[i]*mxj + bx;
+      sy = x[i]*myi + y[i]*myj + by;
+      if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	  (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+      {
+	if (scaleColor) {
+	  if (!finite(z[i])) continue;
+	  int pixel = MIN (graphic->Npixels - 2, MAX (0, z[i]*(graphic->Npixels - 1)));
+	  buffer->bColor_R = pixel1[pixel];
+	  buffer->bColor_G = pixel2[pixel];
+	  buffer->bColor_B = pixel3[pixel];
+	}
+	D = scaleSize ? dz*z[i] : ds;
+	// FillTriangle (buffer, sx - D, sy - 0.58*D, sx + D, sy - 0.58*D, sx, sy + 1.15*D);
+	FillTriangle (buffer, sx, sy - 0.58*D, D, +1.73*D);
+	// out-of-range points skipped by bDrawPoint
+      }
+    }
+  }
   if (object[0].ptype == 5) {	/* open triangle */
     for (i = 0; i < object[0].Npts; i++) {
@@ -423,4 +445,25 @@
 	D = scaleSize ? dz*z[i] : ds;
 	OpenTriangle (buffer, sx - D, sy + 0.58*D, sx + D, sy + 0.58*D, sx, sy - 1.15*D);
+	// out-of-range points skipped by bDrawPoint
+      }
+    }
+  }
+  if (object[0].ptype == 15) {	/* open triangle */
+    for (i = 0; i < object[0].Npts; i++) {
+      if (!(finite(x[i]) && finite(y[i]))) continue;
+      sx = x[i]*mxi + y[i]*mxj + bx;
+      sy = x[i]*myi + y[i]*myj + by;
+      if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	  (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+      {
+	if (scaleColor) {
+	  if (!finite(z[i])) continue;
+	  int pixel = MIN (graphic->Npixels - 2, MAX (0, z[i]*(graphic->Npixels - 1)));
+	  buffer->bColor_R = pixel1[pixel];
+	  buffer->bColor_G = pixel2[pixel];
+	  buffer->bColor_B = pixel3[pixel];
+	}
+	D = scaleSize ? dz*z[i] : ds;
+	OpenTriangle (buffer, sx - D, sy - 0.58*D, sx + D, sy - 0.58*D, sx, sy + 1.15*D);
 	// out-of-range points skipped by bDrawPoint
       }
@@ -446,4 +489,27 @@
 	DrawLine (buffer, sx, sy, sx + D, sy - 0.58*D);
 	DrawLine (buffer, sx, sy, sx,     sy + 1.15*D);
+	// out-of-range points skipped by bDrawPoint
+      }
+    }
+  }
+  if (object[0].ptype == 16) {	/* Y */
+    for (i = 0; i < object[0].Npts; i++) {
+      if (!(finite(x[i]) && finite(y[i]))) continue;
+      sx = x[i]*mxi + y[i]*mxj + bx;
+      sy = x[i]*myi + y[i]*myj + by;
+      if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	  (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+      {
+	if (scaleColor) {
+	  if (!finite(z[i])) continue;
+	  int pixel = MIN (graphic->Npixels - 2, MAX (0, z[i]*(graphic->Npixels - 1)));
+	  buffer->bColor_R = pixel1[pixel];
+	  buffer->bColor_G = pixel2[pixel];
+	  buffer->bColor_B = pixel3[pixel];
+	}
+	D = scaleSize ? dz*z[i] : ds;
+	DrawLine (buffer, sx, sy, sx - D, sy + 0.58*D);
+	DrawLine (buffer, sx, sy, sx + D, sy + 0.58*D);
+	DrawLine (buffer, sx, sy, sx,     sy - 1.15*D);
 	// out-of-range points skipped by bDrawPoint
       }
@@ -590,8 +656,10 @@
 void bDrawXErrors (bDrawBuffer *buffer, KapaGraphWidget *graph, Gobjects *object) {
   
-  int i, bar;
-  float *x, *y, *dxm, *dxp;
+  int i, bar, dz, ds, D;
+  float *x, *y, *z, *dxm, *dxp;
   double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
   double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  int scaleSize = (object[0].size < 0);
 
   mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
@@ -608,5 +676,8 @@
   by = byi + byj;
   
-  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  ds = 0.5 * (graphic->dx + graphic->dy) * 0.003 * object[0].size;
+  dz = 0.5 * (graphic->dx + graphic->dy) * 0.010;
+
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; z = object[0].z;
   bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
    
@@ -616,10 +687,19 @@
   double Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
 
+  /// XXX NOTE : D should be modified by (mxi,myi) for tilted axes dx = D*(mxi/mx), dy = D*(myi/mx)
+
   for (i = 0; i < object[0].Npts; i++) {
-    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
-    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    // for open circles, only go to the outer radius
+    D = 0;
+    if (object[0].ptype ==  7) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  1) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  5) { D = scaleSize ? 0.66*dz*z[i] : 0.66*ds; }
+    if (object[0].ptype == 15) { D = scaleSize ? 0.66*dz*z[i] : 0.66*ds; }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) goto skip_dxp;
+    if (D > fabs(dxp[i]*mxi)) goto skip_dxp;
+    sx0 = x[i]*mxi + y[i]*mxj + bx + D;
     sy0 = x[i]*myi + y[i]*myj + by;
-    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
-    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    sx1 = sx0 + dxp[i]*mxi - D;
+    sy1 = sy0 + dxp[i]*myi;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -628,17 +708,17 @@
     {
       bDrawClipLine (buffer, sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
-      //   DrawLine (buffer, sx0, sy0, sx1, sy1);
       if (bar) {
 	sx10 = sy1 - sz;
 	sx11 = sy1 + sz;
 	bDrawClipLine (buffer, sx1, sx10, sx1, sx11, X0, Y0, X1, Y1);
-	//   DrawLine (buffer, sx1, sx10, sx1, sx11);
-      }
-    }
+      }
+    }
+  skip_dxp:
     if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
-    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    if (D > fabs(dxm[i]*mxi)) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx - D;
     sy0 = x[i]*myi + y[i]*myj + by;
-    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
-    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    sx1 = sx0 - dxm[i]*mxi + D;
+    sy1 = sy0 - dxm[i]*myi;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -647,10 +727,8 @@
     {
       bDrawClipLine (buffer, sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
-      //   DrawLine (buffer, sx0, sy0, sx1, sy1);
       if (bar) {
 	sx10 = sy1 - sz;
 	sx11 = sy1 + sz;
 	bDrawClipLine (buffer, sx1, sx10, sx1, sx11, X0, Y0, X1, Y1);
-	//   DrawLine (buffer, sx1, sx10, sx1, sx11);
       }
     }
@@ -661,9 +739,11 @@
 void bDrawYErrors (bDrawBuffer *buffer, KapaGraphWidget *graph, Gobjects *object) {
   
-  int i, bar;
-  float *x, *y, *dym, *dyp;
+  int i, bar, dz, ds, D;
+  float *x, *y, *z, *dym, *dyp;
   double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
   double sx0, sy0, sx1, sy1, sz, sx10, sx11;
   
+  int scaleSize = (object[0].size < 0);
+
   mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
   mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
@@ -679,5 +759,8 @@
   by = byi + byj;
   
-  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  ds = 0.5 * (graphic->dx + graphic->dy) * 0.003 * object[0].size;
+  dz = 0.5 * (graphic->dx + graphic->dy) * 0.010;
+
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; z = object[0].z;
   bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
   
@@ -687,10 +770,19 @@
   double Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
 
+  /// XXX NOTE : D should be modified by (mxi,myi) for tilted axes dx = D*(mxi/mx), dy = D*(myi/mx)
+
   for (i = 0; i < object[0].Npts; i++) {
-    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    // for open circles, only go to the outer radius
+    D = 0;
+    if (object[0].ptype ==  7) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  1) { D = scaleSize ? dz*z[i] : ds; }
+    if (object[0].ptype ==  5) { D = scaleSize ? 1.15*dz*z[i] : 1.15*ds; }
+    if (object[0].ptype == 15) { D = scaleSize ? 0.58*dz*z[i] : 0.58*ds; }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) goto skip_dyp;
+    if (D > fabs(dyp[i]*myj)) goto skip_dyp;
     sx0 = x[i]*mxi + y[i]*mxj + bx;
-    sy0 = x[i]*myi + y[i]*myj + by;
-    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
-    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
+    sy0 = x[i]*myi + y[i]*myj + by - D;
+    sx1 = sx0 + dyp[i]*mxj;
+    sy1 = sy0 + dyp[i]*myj + D;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -699,17 +791,19 @@
     {
       bDrawClipLine (buffer, sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
-      //   DrawLine (buffer, sx0, sy0, sx1, sy1);
       if (bar) {
 	sx10 = sx1 - sz;
 	sx11 = sx1 + sz;
 	bDrawClipLine (buffer, sx10, sy1, sx11, sy1, X0, Y0, X1, Y1);
-	//   DrawLine (buffer, sx10, sy1, sx11, sy1);
-      }
-    }
+      }
+    }
+  skip_dyp:
     if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    if (object[0].ptype ==  5) { D = scaleSize ? 0.58*dz*z[i] : 0.58*ds; }
+    if (object[0].ptype == 15) { D = scaleSize ? 1.15*dz*z[i] : 1.15*ds; }
+    if (D > fabs(dym[i]*myj)) continue;
     sx0 = x[i]*mxi + y[i]*mxj + bx;
-    sy0 = x[i]*myi + y[i]*myj + by;
-    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
-    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    sy0 = x[i]*myi + y[i]*myj + by + D;
+    sx1 = sx0 - dym[i]*mxj;
+    sy1 = sy0 - dym[i]*myj - D;
     if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
 	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
@@ -718,10 +812,8 @@
     {
       bDrawClipLine (buffer, sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
-      //   DrawLine (buffer, sx0, sy0, sx1, sy1);
       if (bar) {
 	sx10 = sx1 - sz;
 	sx11 = sx1 + sz;
 	bDrawClipLine (buffer, sx10, sy1, sx11, sy1, X0, Y0, X1, Y1);
-	//   DrawLine (buffer, sx10, sy1, sx11, sy1);
       }
     }
Index: /trunk/Ohana/src/libautocode/def/measure-ps1-v5.d
===================================================================
--- /trunk/Ohana/src/libautocode/def/measure-ps1-v5.d	(revision 38061)
+++ /trunk/Ohana/src/libautocode/def/measure-ps1-v5.d	(revision 38062)
@@ -2,5 +2,5 @@
 EXTNAME      DVO_MEASURE_PS1_V5
 TYPE         BINTABLE
-SIZE         232
+SIZE         240
 DESCRIPTION  DVO Detection Measurement Table 
 
@@ -40,4 +40,6 @@
 FIELD XoffDCR,        X_OFF_DCR,     float,          X offset from correction,     pixels
 FIELD YoffDCR,        Y_OFF_DCR,     float,          Y offset from correction,     pixels
+FIELD XoffCAM,        X_OFF_CAM,     float,          X offset from correction,     pixels
+FIELD YoffCAM,        Y_OFF_CAM,     float,          Y offset from correction,     pixels
 FIELD RoffGAL,        R_OFF_GAL,     float,          RA offset from correction,    arcsec
 FIELD DoffGAL,        D_OFF_GAL,     float,          DEC offset from correction,   arcsec
Index: /trunk/Ohana/src/libautocode/def/measure.d
===================================================================
--- /trunk/Ohana/src/libautocode/def/measure.d	(revision 38061)
+++ /trunk/Ohana/src/libautocode/def/measure.d	(revision 38062)
@@ -2,5 +2,5 @@
 EXTNAME      DVO_MEASURE
 TYPE         BINTABLE
-SIZE         228
+SIZE         236
 DESCRIPTION  DVO Detection Measurement Table 
 
@@ -40,4 +40,6 @@
 FIELD XoffDCR,        X_OFF_DCR,     float,          X offset from correction,     pixels
 FIELD YoffDCR,        Y_OFF_DCR,     float,          Y offset from correction,     pixels
+FIELD XoffCAM,        X_OFF_CAM,     float,          X offset from correction,     pixels
+FIELD YoffCAM,        Y_OFF_CAM,     float,          Y offset from correction,     pixels
 FIELD RoffGAL,        R_OFF_GAL,     float,          RA offset from correction,    arcsec
 FIELD DoffGAL,        D_OFF_GAL,     float,          DEC offset from correction,   arcsec
Index: /trunk/Ohana/src/libdvo/include/dvo.h
===================================================================
--- /trunk/Ohana/src/libdvo/include/dvo.h	(revision 38061)
+++ /trunk/Ohana/src/libdvo/include/dvo.h	(revision 38062)
@@ -555,4 +555,72 @@
 Measure *Measure_PS1_V4alt_ToInternal (Average *ave, Measure_PS1_V4alt *in, off_t Nvalues);
 
+typedef struct {
+  double           R;                    // RA at epoch (degrees)
+  double           D;                    // DEC at epoch (degrees)
+  float            M;                    // catalog mag (mag)
+  float            dM;                   // mag error (mag)
+  float            Map;                  // aperture mag (mag)
+  float            dMap;                 // aperture mag (mag)
+  float            Mkron;                // kron magnitude (mag)
+  float            dMkron;               // kron magnitude error (mag)
+  float            Mcal;                 // image cal mag (mag)
+  float            dMcal;                // systematic calibration error (mag)
+  float            dt;                   // exposure time (2.5*log(exptime))
+  float            FluxPSF;              // flux from psf fit (counts/sec)
+  float            dFluxPSF;             // error on psf flux (counts/sec)
+  float            FluxKron;             // flux from kron ap (counts/sec)
+  float            dFluxKron;            // error on kron flux (counts/sec)
+  float            FluxAp;               // flux from ap ap (counts/sec)
+  float            dFluxAp;              // error on ap flux (counts/sec)
+  float            airmass;              // (airmass - 1) (airmass)
+  float            az;                   // telescope azimuth
+  float            Xccd;                 // X coord on chip (raw value) (pixels)
+  float            Yccd;                 // Y coord on chip (raw value) (pixels)
+  float            Xfix;                 // X coord after correction (pixels)
+  float            Yfix;                 // Y coord after correction (pixels)
+  float            XoffKH;               // X offset from correction (pixels)
+  float            YoffKH;               // Y offset from correction (pixels)
+  float            XoffDCR;              // X offset from correction (pixels)
+  float            YoffDCR;              // Y offset from correction (pixels)
+  float            RoffGAL;              // RA offset from correction (arcsec)
+  float            DoffGAL;              // DEC offset from correction (arcsec)
+  float            Sky;                  // local estimate of sky flux (counts/sec)
+  float            dSky;                 // local estimate of sky flux (counts/sec)
+  int              t;                    // time in seconds (UNIX)
+  unsigned int     averef;               // reference to average entry      
+  unsigned int     detID;                // detection ID
+  unsigned int     objID;                // unique ID for object in table
+  unsigned int     catID;                // unique ID for table in which object was first realized
+  uint64_t         extID;                // external ID (eg PSPS detID)
+  unsigned int     imageID;              // reference to DVO image ID
+  float            psfQF;                // psf coverage/quality factor
+  float            psfQFperf;            // psf coverage / quality factor (all mask bits)
+  float            psfChisq;             // psf fit chisq
+  int              psfNdof;              // psf degrees of freedom
+  int              psfNpix;              // psf number of pixels
+  int              photFlags2;           // flags supplied by photometry program
+  float            extNsigma;            // Nsigma deviation towards EXT
+  short            FWx;                  // object fwhm major axis (1/100 of pixels)
+  short            FWy;                  // object fwhm minor axis (1/100 of pixels )
+  short            theta;                // angle wrt ccd X dir ((0xffff/360) deg)
+  short            Mxx;                  // second moments in pixel coords (1/100 of pixels)
+  short            Mxy;                  // second moments in pixel coords (1/100 of pixels)
+  short            Myy;                  // second moments in pixel coords (1/100 of pixels)
+  unsigned short   t_msec;               // time fraction of second (milliseconds)
+  unsigned short   photcode;             // photcode
+  short            dXccd;                // X coord error on chip (1/100 of pixels)
+  short            dYccd;                // Y coord error on chip (1/100 of pixels)
+  short            dRsys;                // systematic error from astrom (1/100 of pixels)
+  short            posangle;             // position angle sky to chip ((0xffff/360) deg)
+  float            pltscale;             // plate scale (arcsec/pixel)
+  unsigned int     dbFlags;              // flags supplied by analysis in database
+  unsigned int     photFlags;            // flags supplied by photometry program
+  int              padding;              // padding to ensure 8byte blocks
+} Measure_PS1_V5alt;
+
+Measure *Measure_PS1_V5alt_ToInternal (Average *ave, Measure_PS1_V5alt *in, off_t Nvalues);
+int gfits_convert_Measure_PS1_V5alt (Measure_PS1_V5alt *data, off_t size, off_t nitems);
+Measure_PS1_V5alt *gfits_table_get_Measure_PS1_V5alt (FTable *ftable, off_t *Ndata, char *swapped);
+
 // alternate version of PS1_V5 (old dev version)
 typedef struct {
Index: /trunk/Ohana/src/libdvo/include/dvodb.h
===================================================================
--- /trunk/Ohana/src/libdvo/include/dvodb.h	(revision 38061)
+++ /trunk/Ohana/src/libdvo/include/dvodb.h	(revision 38062)
@@ -178,4 +178,6 @@
       MEAS_XOFF_DCR, 
       MEAS_YOFF_DCR, 
+      MEAS_XOFF_CAM, 
+      MEAS_YOFF_CAM, 
       MEAS_ROFF_GAL, 
       MEAS_DOFF_GAL, 
@@ -237,5 +239,5 @@
       MEAS_RA_GALMODEL,      // model pm prediction
       MEAS_DEC_GALMODEL,     // model pm prediction
-};
+} dvoMeasureType;
 
 /* average fields */
@@ -289,5 +291,5 @@
       AVE_RA_GALMODEL,      // model pm prediction
       AVE_DEC_GALMODEL,     // model pm prediction
-};
+} dvoAverageType;
 
 //       AVE_NPHOT, 
@@ -365,5 +367,5 @@
       IMAGE_REF_COLOR_BLUE,
       IMAGE_REF_COLOR_RED
-};
+} dvoImageType;
 
 enum {DVO_TABLE_AVERAGE, DVO_TABLE_MEASURE, DVO_TABLE_IMAGE};
@@ -383,5 +385,5 @@
   int extract;
   int table;
-  int ID;
+  int ID; // may be either dvoMeasureType or dvoAverageType
 
   dvoMagSourceType magSource; // chip, (forced) warp, stack [only relevant for averages]
Index: /trunk/Ohana/src/libdvo/src/dbExtractAverages.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dbExtractAverages.c	(revision 38061)
+++ /trunk/Ohana/src/libdvo/src/dbExtractAverages.c	(revision 38062)
@@ -53,4 +53,5 @@
 
   // off_t i;
+  int n;
   dbValue value;
 
@@ -186,30 +187,7 @@
     case AVE_PHOT:
       // if we request mag:ave, use equiv for photcode (ie a given measure, say GPC1.g.XY01, will return g for mag:ave)
-      if  (field->photcode->type == PHOT_MAG) {
-	// this is an error
-	break;
-      }
-
-      // if we ask for 2MASS_K, etc (REF values), return NAN unless measure->code matches
-      if (field->photcode->type == PHOT_REF) {
-	// need to ensure measure exists.
-	break;
-      }
-
-      // if we ask for GPC1.g.XY03:rel, etc (DEP values), return NAN unless measure->code matches
-      if (field->photcode->type == PHOT_DEP) {
-	// again.
-	break;
-      }
-
-      /* in some cases below we need a measurement which matches the requested photcode.
-	 here is some sample code to find this.
-
-	  for (i = 0; i < average[0].Nmeasure; i++) {
-	    if (field->photcode->code != measure[i].photcode) continue;
-	    value.Flt = measure[i].M;
-	    break;
-	  }
-      */
+
+      // this is an error (no exposed photcodes should be of type PHOT_MAG)
+      if  (field->photcode->type == PHOT_MAG) break;
 
       switch (field->magOption) {
@@ -220,11 +198,37 @@
 	      break;
 	    case MAG_LEVEL_REF:
-	      // which measure is needed here?
-	      // PhotRef  (field->photcode, average, secfilt, measure, field->magClass, field->magSource); 
 	      break;
 	    case MAG_LEVEL_INST:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotInst (&measure[n], field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_CAT:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotCat (&measure[n], field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_SYS:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotSys  (&measure[n], average, secfilt, field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_REL:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotRel (&measure[n], average, secfilt, field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_CAL:
 	    case MAG_LEVEL_NONE:
@@ -243,4 +247,11 @@
 	    case MAG_LEVEL_SYS:
 	    case MAG_LEVEL_REL:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotErr (&measure[n], field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_CAL:
 	    case MAG_LEVEL_NONE:
@@ -259,7 +270,35 @@
 	      break;
 	    case MAG_LEVEL_INST:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotFluxInst (&measure[n], field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_CAT:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotFluxCat (&measure[n], field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_SYS:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotFluxSys (&measure[n], average, secfilt, field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_REL:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotFluxRel (&measure[n], average, secfilt, field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_CAL:
 	    case MAG_LEVEL_NONE:
@@ -278,4 +317,11 @@
 	    case MAG_LEVEL_SYS:
 	    case MAG_LEVEL_REL:
+	      // find an appropriate measure (if one exists)
+	      for (n = 0; n < average->Nmeasure; n++) {
+		if (field->photcode->code != measure[n].photcode) continue;
+		value.Flt = PhotFluxInstErr (&measure[n], field->magClass); 
+		break;
+	      }
+	      break;
 	    case MAG_LEVEL_CAL:
 	    case MAG_LEVEL_NONE:
Index: /trunk/Ohana/src/libdvo/src/dbExtractMeasures.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dbExtractMeasures.c	(revision 38061)
+++ /trunk/Ohana/src/libdvo/src/dbExtractMeasures.c	(revision 38062)
@@ -573,4 +573,6 @@
     case MEAS_XOFF_DCR: { value.Flt = measure[0].XoffDCR; break; }
     case MEAS_YOFF_DCR: { value.Flt = measure[0].YoffDCR; break; }
+    case MEAS_XOFF_CAM: { value.Flt = measure[0].XoffCAM; break; }
+    case MEAS_YOFF_CAM: { value.Flt = measure[0].YoffCAM; break; }
     case MEAS_ROFF_GAL: { value.Flt = measure[0].RoffGAL; break; }
     case MEAS_DOFF_GAL: { value.Flt = measure[0].DoffGAL; break; }
Index: /trunk/Ohana/src/libdvo/src/dbFields.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dbFields.c	(revision 38061)
+++ /trunk/Ohana/src/libdvo/src/dbFields.c	(revision 38062)
@@ -480,4 +480,6 @@
   if (!strcasecmp (fieldName, "XOFF_DCR"))     	 ESCAPE (MEAS_XOFF_DCR,       OPIHI_FLT);
   if (!strcasecmp (fieldName, "YOFF_DCR"))     	 ESCAPE (MEAS_YOFF_DCR,       OPIHI_FLT);
+  if (!strcasecmp (fieldName, "XOFF_CAM"))     	 ESCAPE (MEAS_XOFF_CAM,       OPIHI_FLT);
+  if (!strcasecmp (fieldName, "YOFF_CAM"))     	 ESCAPE (MEAS_YOFF_CAM,       OPIHI_FLT);
   if (!strcasecmp (fieldName, "ROFF_GAL"))       ESCAPE (MEAS_ROFF_GAL,       OPIHI_FLT);
   if (!strcasecmp (fieldName, "DOFF_GAL"))       ESCAPE (MEAS_DOFF_GAL,       OPIHI_FLT);
Index: /trunk/Ohana/src/libdvo/src/dvo_catalog.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_catalog.c	(revision 38061)
+++ /trunk/Ohana/src/libdvo/src/dvo_catalog.c	(revision 38062)
@@ -273,4 +273,6 @@
  measure->XoffDCR   = NAN;
  measure->YoffDCR   = NAN;
+ measure->XoffCAM   = NAN;
+ measure->YoffCAM   = NAN;
  measure->RoffGAL   = NAN;
  measure->DoffGAL   = NAN;
Index: /trunk/Ohana/src/libdvo/src/dvo_convert.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_convert.c	(revision 38061)
+++ /trunk/Ohana/src/libdvo/src/dvo_convert.c	(revision 38062)
@@ -204,4 +204,20 @@
     free (tmpMeasure);
     *format = DVO_FORMAT_PS1_V4;
+    return (measure); 
+  }
+
+  // block to convert PV1_V5_0 tables (PS1_V5 made before the XoffCAM,YoffCAM addition)
+  if (!strcmp (extname, "DVO_MEASURE_PS1_V5") && (ftable[0].header[0].Naxis[0] == 232)) {
+    fprintf (stderr, "reading alt PS1_V5 format\n");
+    Measure_PS1_V5alt *tmpMeasure;
+    tmpMeasure = gfits_table_get_Measure_PS1_V5alt (ftable, Nmeasure, NULL);
+    if (!tmpMeasure) {
+      fprintf (stderr, "ERROR: failed to read measures\n");
+      exit (2);
+    }
+    myAssert (average, "conversion to internal needs average table");
+    measure = Measure_PS1_V5alt_ToInternal (average, tmpMeasure, *Nmeasure);
+    free (tmpMeasure);
+    *format = DVO_FORMAT_PS1_V5;
     return (measure); 
   }
Index: /trunk/Ohana/src/libdvo/src/dvo_convert_PS1_V5.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_convert_PS1_V5.c	(revision 38061)
+++ /trunk/Ohana/src/libdvo/src/dvo_convert_PS1_V5.c	(revision 38062)
@@ -4,4 +4,1382 @@
 
 Measure *Measure_PS1_V5_ToInternal (Average *ave, Measure_PS1_V5 *in, off_t Nvalues) {
+
+  off_t i;
+  Measure *out;
+
+  ALLOCATE_ZERO (out, Measure, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_measure_init (&out[i]);
+
+    out[i].R          = in[i].R;
+    out[i].D          = in[i].D;
+    out[i].M          = in[i].M;
+    out[i].dM         = in[i].dM;
+    out[i].Map        = in[i].Map;
+    out[i].dMap       = in[i].dMap;
+    out[i].Mkron      = in[i].Mkron;
+    out[i].dMkron     = in[i].dMkron;
+    out[i].Mcal       = in[i].Mcal;
+    out[i].dMcal      = in[i].dMcal;
+    out[i].dt         = in[i].dt;
+    out[i].FluxPSF    = in[i].FluxPSF;
+    out[i].dFluxPSF   = in[i].dFluxPSF;
+    out[i].FluxKron   = in[i].FluxKron;
+    out[i].dFluxKron  = in[i].dFluxKron;
+    out[i].FluxAp     = in[i].FluxAp;
+    out[i].dFluxAp    = in[i].dFluxAp;
+    out[i].airmass    = in[i].airmass;
+    out[i].az         = in[i].az;
+    out[i].Xccd       = in[i].Xccd;
+    out[i].Yccd       = in[i].Yccd;
+    out[i].Xfix       = in[i].Xfix;
+    out[i].Yfix       = in[i].Yfix;
+    out[i].XoffKH     = in[i].XoffKH;
+    out[i].YoffKH     = in[i].YoffKH;
+    out[i].XoffDCR    = in[i].XoffDCR;
+    out[i].YoffDCR    = in[i].YoffDCR;
+    out[i].XoffCAM    = in[i].XoffCAM;
+    out[i].YoffCAM    = in[i].YoffCAM;
+    out[i].RoffGAL    = in[i].RoffGAL;
+    out[i].DoffGAL    = in[i].DoffGAL;
+    out[i].Sky        = in[i].Sky;
+    out[i].dSky       = in[i].dSky;
+    out[i].t          = in[i].t;
+    out[i].averef     = in[i].averef;
+    out[i].detID      = in[i].detID;
+    out[i].objID      = in[i].objID;
+    out[i].catID      = in[i].catID;
+    out[i].extID      = in[i].extID;
+    out[i].imageID    = in[i].imageID;
+    out[i].psfQF      = in[i].psfQF;
+    out[i].psfQFperf  = in[i].psfQFperf;
+    out[i].psfChisq   = in[i].psfChisq;
+    out[i].psfNdof    = in[i].psfNdof;
+    out[i].psfNpix    = in[i].psfNpix;
+    out[i].extNsigma  = in[i].extNsigma;
+    out[i].FWx 	      = in[i].FWx;
+    out[i].FWy 	      = in[i].FWy;
+    out[i].theta      = in[i].theta;
+    out[i].Mxx 	      = in[i].Mxx;
+    out[i].Mxy 	      = in[i].Mxy;
+    out[i].Myy 	      = in[i].Myy;
+    out[i].t_msec     = in[i].t_msec;
+    out[i].photcode   = in[i].photcode;
+    out[i].dXccd      = in[i].dXccd;
+    out[i].dYccd      = in[i].dYccd;
+    out[i].dRsys      = in[i].dRsys;
+    out[i].posangle   = in[i].posangle;
+    out[i].pltscale   = in[i].pltscale;
+    out[i].dbFlags    = in[i].dbFlags;
+    out[i].photFlags  = in[i].photFlags;
+    out[i].photFlags2 = in[i].photFlags2;
+  }
+  return (out);
+}
+
+Measure_PS1_V5 *MeasureInternalTo_PS1_V5 (Average *ave, Measure *in, off_t Nvalues) {
+
+  off_t i;
+  Measure_PS1_V5 *out;
+
+  ALLOCATE_ZERO (out, Measure_PS1_V5, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R          = in[i].R;
+    out[i].D          = in[i].D;
+    out[i].M          = in[i].M;
+    out[i].dM         = in[i].dM;
+    out[i].Map        = in[i].Map;
+    out[i].dMap       = in[i].dMap;
+    out[i].Mkron      = in[i].Mkron;
+    out[i].dMkron     = in[i].dMkron;
+    out[i].Mcal       = in[i].Mcal;
+    out[i].dMcal      = in[i].dMcal;
+    out[i].dt         = in[i].dt;
+    out[i].FluxPSF    = in[i].FluxPSF;
+    out[i].dFluxPSF   = in[i].dFluxPSF;
+    out[i].FluxKron   = in[i].FluxKron;
+    out[i].dFluxKron  = in[i].dFluxKron;
+    out[i].FluxAp     = in[i].FluxAp;
+    out[i].dFluxAp    = in[i].dFluxAp;
+    out[i].airmass    = in[i].airmass;
+    out[i].az         = in[i].az;
+    out[i].Xccd       = in[i].Xccd;
+    out[i].Yccd       = in[i].Yccd;
+    out[i].Xfix       = in[i].Xfix;
+    out[i].Yfix       = in[i].Yfix;
+    out[i].XoffKH     = in[i].XoffKH;
+    out[i].YoffKH     = in[i].YoffKH;
+    out[i].XoffDCR    = in[i].XoffDCR;
+    out[i].YoffDCR    = in[i].YoffDCR;
+    out[i].XoffCAM    = in[i].XoffCAM;
+    out[i].YoffCAM    = in[i].YoffCAM;
+    out[i].RoffGAL    = in[i].RoffGAL;
+    out[i].DoffGAL    = in[i].DoffGAL;
+    out[i].Sky        = in[i].Sky;
+    out[i].dSky       = in[i].dSky;
+    out[i].t          = in[i].t;
+    out[i].averef     = in[i].averef;
+    out[i].detID      = in[i].detID;
+    out[i].objID      = in[i].objID;
+    out[i].catID      = in[i].catID;
+    out[i].extID      = in[i].extID;
+    out[i].imageID    = in[i].imageID;
+    out[i].psfQF      = in[i].psfQF;
+    out[i].psfQFperf  = in[i].psfQFperf;
+    out[i].psfChisq   = in[i].psfChisq;
+    out[i].psfNdof    = in[i].psfNdof;
+    out[i].psfNpix    = in[i].psfNpix;
+    out[i].extNsigma  = in[i].extNsigma;
+    out[i].FWx 	      = in[i].FWx;
+    out[i].FWy 	      = in[i].FWy;
+    out[i].theta      = in[i].theta;
+    out[i].Mxx 	      = in[i].Mxx;
+    out[i].Mxy 	      = in[i].Mxy;
+    out[i].Myy 	      = in[i].Myy;
+    out[i].t_msec     = in[i].t_msec;
+    out[i].photcode   = in[i].photcode;
+    out[i].dXccd      = in[i].dXccd;
+    out[i].dYccd      = in[i].dYccd;
+    out[i].dRsys      = in[i].dRsys;
+    out[i].posangle   = in[i].posangle;
+    out[i].pltscale   = in[i].pltscale;
+    out[i].dbFlags    = in[i].dbFlags;
+    out[i].photFlags  = in[i].photFlags;
+    out[i].photFlags2 = in[i].photFlags2;
+  }
+  return (out);
+}
+
+// 'primary' is needed to conform with the API for Loneos and Elixir, but is not used
+Average *Average_PS1_V5_ToInternal (Average_PS1_V5 *in, off_t Nvalues, SecFilt **primary) {
+
+  off_t i;
+  Average *out;
+
+  ALLOCATE_ZERO (out, Average, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_average_init (&out[i]);
+
+    out[i].R        	 = in[i].R;      
+    out[i].D        	 = in[i].D;      
+    out[i].dR       	 = in[i].dR;
+    out[i].dD       	 = in[i].dD;
+    out[i].uR       	 = in[i].uR;
+    out[i].uD       	 = in[i].uD;
+    out[i].duR      	 = in[i].duR;
+    out[i].duD      	 = in[i].duD;
+    out[i].P        	 = in[i].P;
+    out[i].dP       	 = in[i].dP;
+
+    out[i].Rstk        	 = in[i].Rstk;      
+    out[i].Dstk        	 = in[i].Dstk;      
+    out[i].dRstk       	 = in[i].dRstk;
+    out[i].dDstk       	 = in[i].dDstk;
+
+    out[i].ChiSqAve    	 = in[i].ChiSqAve;     
+    out[i].ChiSqPM    	 = in[i].ChiSqPM;     
+    out[i].ChiSqPar    	 = in[i].ChiSqPar;     
+    out[i].Tmean    	 = in[i].Tmean;     
+    out[i].Trange   	 = in[i].Trange;     
+
+    out[i].psfQF         = in[i].psfQF;
+    out[i].psfQFperf     = in[i].psfQFperf;
+    out[i].stargal     	 = in[i].stargal;     
+    out[i].Npos       	 = in[i].Npos;     
+
+    out[i].Nmeasure      = in[i].Nmeasure;     
+    out[i].Nmissing      = in[i].Nmissing;     
+    out[i].Nlensing      = in[i].Nlensing;     
+    out[i].Nlensobj      = in[i].Nlensobj;     
+    out[i].Nstarpar      = in[i].Nstarpar;     
+    out[i].Nextend       = in[i].Nextend;     
+
+    out[i].measureOffset = in[i].measureOffset; 
+    out[i].missingOffset = in[i].missingOffset;
+    out[i].lensingOffset = in[i].lensingOffset;
+    out[i].lensobjOffset = in[i].lensobjOffset;
+    out[i].starparOffset = in[i].starparOffset;
+    out[i].extendOffset  = in[i].extendOffset;
+
+    out[i].refColorBlue  = in[i].refColorBlue;
+    out[i].refColorRed   = in[i].refColorRed;
+
+    out[i].tessID        = in[i].tessID;
+    out[i].skycellID     = in[i].skycellID;
+    out[i].projectionID  = in[i].projectionID;
+
+    out[i].flags     	 = in[i].flags;   
+    out[i].photFlagsUpper = in[i].photFlagsUpper;   
+    out[i].photFlagsLower = in[i].photFlagsLower;   
+    out[i].objID 	 = in[i].objID;
+    out[i].catID 	 = in[i].catID;
+    out[i].extID 	 = in[i].extID;
+    out[i].extIDgc 	 = in[i].extIDgc;
+  }
+  return (out);
+}
+
+// 'primary' is needed to conform with the API for Loneos and Elixir, but is not used
+Average_PS1_V5 *AverageInternalTo_PS1_V5 (Average *in, off_t Nvalues, SecFilt *primary) {
+
+  off_t i;
+  Average_PS1_V5 *out;
+
+  ALLOCATE_ZERO (out, Average_PS1_V5, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R        	  = in[i].R;      
+    out[i].D        	  = in[i].D;      
+    out[i].dR       	  = in[i].dR;
+    out[i].dD       	  = in[i].dD;
+    out[i].uR       	  = in[i].uR;
+    out[i].uD       	  = in[i].uD;
+    out[i].duR      	  = in[i].duR;
+    out[i].duD      	  = in[i].duD;
+    out[i].P        	  = in[i].P;
+    out[i].dP       	  = in[i].dP;
+			  
+    out[i].Rstk        	  = in[i].Rstk;      
+    out[i].Dstk        	  = in[i].Dstk;      
+    out[i].dRstk       	  = in[i].dRstk;
+    out[i].dDstk       	  = in[i].dDstk;
+			  
+    out[i].ChiSqAve    	  = in[i].ChiSqAve;     
+    out[i].ChiSqPM     	  = in[i].ChiSqPM;     
+    out[i].ChiSqPar   	  = in[i].ChiSqPar;     
+    out[i].Tmean    	  = in[i].Tmean;     
+    out[i].Trange   	  = in[i].Trange;     
+			  
+    out[i].psfQF          = in[i].psfQF;
+    out[i].psfQFperf      = in[i].psfQFperf;
+    out[i].stargal     	  = in[i].stargal;     
+    out[i].Npos       	  = in[i].Npos;     
+			  
+    out[i].Nmeasure       = in[i].Nmeasure;     
+    out[i].Nmissing       = in[i].Nmissing;     
+    out[i].Nlensing       = in[i].Nlensing;     
+    out[i].Nlensobj       = in[i].Nlensobj;     
+    out[i].Nstarpar       = in[i].Nstarpar;     
+    out[i].Nextend        = in[i].Nextend;     
+			  
+    out[i].measureOffset  = in[i].measureOffset; 
+    out[i].missingOffset  = in[i].missingOffset;
+    out[i].lensingOffset  = in[i].lensingOffset;
+    out[i].lensobjOffset  = in[i].lensobjOffset;
+    out[i].starparOffset  = in[i].starparOffset;
+    out[i].extendOffset   = in[i].extendOffset;
+			  
+    out[i].refColorBlue   = in[i].refColorBlue;
+    out[i].refColorRed    = in[i].refColorRed;
+			  
+    out[i].tessID         = in[i].tessID;
+    out[i].skycellID      = in[i].skycellID;
+    out[i].projectionID   = in[i].projectionID;
+			  
+    out[i].flags     	  = in[i].flags;   
+    out[i].photFlagsUpper = in[i].photFlagsUpper;   
+    out[i].photFlagsLower = in[i].photFlagsLower;   
+    out[i].objID 	  = in[i].objID;
+    out[i].catID 	  = in[i].catID;
+    out[i].extID 	  = in[i].extID;
+    out[i].extIDgc 	  = in[i].extIDgc;
+  }
+  return (out);
+}
+
+SecFilt *SecFilt_PS1_V5_ToInternal (SecFilt_PS1_V5 *in, off_t Nvalues) {
+
+  off_t i;
+  SecFilt *out;
+
+  ALLOCATE_ZERO (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_secfilt_init (&out[i]);
+
+    out[i].M             = in[i].M;      
+    out[i].dM            = in[i].dM;      
+    out[i].Map           = in[i].Map;      
+    out[i].dMap          = in[i].dMap;      
+    out[i].sMap          = in[i].sMap;      
+    out[i].Mkron         = in[i].Mkron;      
+    out[i].dMkron        = in[i].dMkron;      
+    out[i].sMkron        = in[i].sMkron;      
+
+    out[i].psfQfMax      = in[i].psfQfMax;      
+    out[i].psfQfPerfMax  = in[i].psfQfPerfMax;      
+
+    out[i].Mstdev        = in[i].Mstdev;      
+    out[i].Mmin          = in[i].Mmin;      
+    out[i].Mmax          = in[i].Mmax;      
+    out[i].Mchisq        = in[i].Mchisq;     
+
+    out[i].Ncode         = in[i].Ncode;
+    out[i].Nused         = in[i].Nused;
+    out[i].NusedKron     = in[i].NusedKron;
+    out[i].NusedAp       = in[i].NusedAp;
+
+    out[i].flags         = in[i].flags;     
+
+    out[i].MpsfStk       = in[i].MpsfStk;
+    out[i].FpsfStk       = in[i].FpsfStk;
+    out[i].dFpsfStk      = in[i].dFpsfStk;
+
+    out[i].MkronStk      = in[i].MkronStk;
+    out[i].FkronStk      = in[i].FkronStk;
+    out[i].dFkronStk     = in[i].dFkronStk;
+
+    out[i].MapStk        = in[i].MapStk;
+    out[i].FapStk        = in[i].FapStk;
+    out[i].dFapStk       = in[i].dFapStk;
+
+    out[i].Nstack        = in[i].Nstack;      
+    out[i].NstackDet     = in[i].NstackDet;      
+
+    out[i].stackPrmryOff = in[i].stackPrmryOff;      
+    out[i].stackBestOff  = in[i].stackBestOff;      
+
+    out[i].MpsfWrp       = in[i].MpsfWrp;
+    out[i].FpsfWrp       = in[i].FpsfWrp;
+    out[i].dFpsfWrp      = in[i].dFpsfWrp;
+    out[i].sFpsfWrp      = in[i].sFpsfWrp;
+
+    out[i].MkronWrp      = in[i].MkronWrp;
+    out[i].FkronWrp      = in[i].FkronWrp;
+    out[i].dFkronWrp     = in[i].dFkronWrp;
+    out[i].sFkronWrp     = in[i].sFkronWrp;
+
+    out[i].MapWrp        = in[i].MapWrp;
+    out[i].FapWrp        = in[i].FapWrp;
+    out[i].dFapWrp       = in[i].dFapWrp;
+    out[i].sFapWrp       = in[i].sFapWrp;
+
+    out[i].NusedWrp      = in[i].NusedWrp;
+    out[i].NusedKronWrp  = in[i].NusedKronWrp;
+    out[i].NusedApWrp    = in[i].NusedApWrp;
+
+    out[i].Nwarp         = in[i].Nwarp;      
+    out[i].NwarpGood     = in[i].NwarpGood;      
+
+    out[i].ubercalDist   = in[i].ubercalDist;      
+  }
+  return (out);
+}
+
+SecFilt_PS1_V5 *SecFiltInternalTo_PS1_V5 (SecFilt *in, off_t Nvalues) {
+
+  off_t i;
+  SecFilt_PS1_V5 *out;
+
+  ALLOCATE_ZERO (out, SecFilt_PS1_V5, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+
+    out[i].M             = in[i].M;      
+    out[i].dM            = in[i].dM;      
+    out[i].Map           = in[i].Map;      
+    out[i].dMap          = in[i].dMap;      
+    out[i].sMap          = in[i].sMap;      
+    out[i].Mkron         = in[i].Mkron;      
+    out[i].dMkron        = in[i].dMkron;      
+    out[i].sMkron        = in[i].sMkron;      
+
+    out[i].psfQfMax      = in[i].psfQfMax;      
+    out[i].psfQfPerfMax  = in[i].psfQfPerfMax;      
+
+    out[i].Mstdev        = in[i].Mstdev;      
+    out[i].Mmin          = in[i].Mmin;      
+    out[i].Mmax          = in[i].Mmax;      
+    out[i].Mchisq        = in[i].Mchisq;     
+
+    out[i].Ncode         = in[i].Ncode;
+    out[i].Nused         = in[i].Nused;
+    out[i].NusedKron     = in[i].NusedKron;
+    out[i].NusedAp       = in[i].NusedAp;
+
+    out[i].flags         = in[i].flags;     
+
+    out[i].MpsfStk       = in[i].MpsfStk;
+    out[i].FpsfStk       = in[i].FpsfStk;
+    out[i].dFpsfStk      = in[i].dFpsfStk;
+
+    out[i].MkronStk      = in[i].MkronStk;
+    out[i].FkronStk      = in[i].FkronStk;
+    out[i].dFkronStk     = in[i].dFkronStk;
+
+    out[i].MapStk        = in[i].MapStk;
+    out[i].FapStk        = in[i].FapStk;
+    out[i].dFapStk       = in[i].dFapStk;
+
+    out[i].Nstack        = in[i].Nstack;      
+    out[i].NstackDet     = in[i].NstackDet;      
+
+    out[i].stackPrmryOff = in[i].stackPrmryOff;      
+    out[i].stackBestOff  = in[i].stackBestOff;      
+
+    out[i].MpsfWrp       = in[i].MpsfWrp;
+    out[i].FpsfWrp       = in[i].FpsfWrp;
+    out[i].dFpsfWrp      = in[i].dFpsfWrp;
+    out[i].sFpsfWrp      = in[i].sFpsfWrp;
+
+    out[i].MkronWrp      = in[i].MkronWrp;
+    out[i].FkronWrp      = in[i].FkronWrp;
+    out[i].dFkronWrp     = in[i].dFkronWrp;
+    out[i].sFkronWrp     = in[i].sFkronWrp;
+
+    out[i].MapWrp        = in[i].MapWrp;
+    out[i].FapWrp        = in[i].FapWrp;
+    out[i].dFapWrp       = in[i].dFapWrp;
+    out[i].sFapWrp       = in[i].sFapWrp;
+
+    out[i].NusedWrp      = in[i].NusedWrp;
+    out[i].NusedKronWrp  = in[i].NusedKronWrp;
+    out[i].NusedApWrp    = in[i].NusedApWrp;
+
+    out[i].Nwarp         = in[i].Nwarp;      
+    out[i].NwarpGood     = in[i].NwarpGood;      
+
+    out[i].ubercalDist   = in[i].ubercalDist;      
+  }
+  return (out);
+}
+
+Lensing *Lensing_PS1_V5_R2_ToInternal (Lensing_PS1_V5_R2 *in, off_t Nvalues) {
+
+  off_t i;
+  Lensing *out;
+
+  ALLOCATE_ZERO (out, Lensing, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_lensing_init (&out[i]);
+
+    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
+    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
+    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
+    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
+    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
+	             	                 
+    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
+    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
+    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
+    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
+    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
+	             	                 
+    out[i].X11_sm_psf  = in[i].X11_sm_psf;
+    out[i].X12_sm_psf  = in[i].X12_sm_psf;
+    out[i].X22_sm_psf  = in[i].X22_sm_psf;
+    out[i].E1_sm_psf   = in[i].E1_sm_psf;
+    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
+	             	                 
+    out[i].X11_sh_psf  = in[i].X11_sh_psf;
+    out[i].X12_sh_psf  = in[i].X12_sh_psf;
+    out[i].X22_sh_psf  = in[i].X22_sh_psf;
+    out[i].E1_sh_psf   = in[i].E1_sh_psf;
+    out[i].E2_sh_psf   = in[i].E2_sh_psf;
+
+    out[i].E1_psf      = in[i].E1_psf;
+    out[i].E2_psf      = in[i].E2_psf;
+
+    out[i].F_ApR5      = in[i].F_ApR5;
+    out[i].dF_ApR5     = in[i].dF_ApR5;
+    out[i].sF_ApR5     = in[i].sF_ApR5;
+    out[i].fF_ApR5     = in[i].fF_ApR5;
+	               	            
+    out[i].F_ApR6      = in[i].F_ApR6;
+    out[i].dF_ApR6     = in[i].dF_ApR6;
+    out[i].sF_ApR6     = in[i].sF_ApR6;
+    out[i].fF_ApR6     = in[i].fF_ApR6;
+	          	            
+    out[i].detID       = in[i].detID;
+    out[i].objID       = in[i].objID;
+    out[i].catID       = in[i].catID;
+    out[i].averef      = in[i].averef;
+
+    out[i].imageID     = in[i].imageID;
+  }
+  return (out);
+}
+
+Lensing_PS1_V5_R2 *LensingInternalTo_PS1_V5_R2 (Lensing *in, off_t Nvalues) {
+
+  off_t i;
+  Lensing_PS1_V5_R2 *out;
+
+  ALLOCATE_ZERO (out, Lensing_PS1_V5, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+
+    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
+    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
+    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
+    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
+    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
+	             	                 
+    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
+    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
+    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
+    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
+    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
+	             	                 
+    out[i].X11_sm_psf  = in[i].X11_sm_psf;
+    out[i].X12_sm_psf  = in[i].X12_sm_psf;
+    out[i].X22_sm_psf  = in[i].X22_sm_psf;
+    out[i].E1_sm_psf   = in[i].E1_sm_psf;
+    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
+	             	                 
+    out[i].X11_sh_psf  = in[i].X11_sh_psf;
+    out[i].X12_sh_psf  = in[i].X12_sh_psf;
+    out[i].X22_sh_psf  = in[i].X22_sh_psf;
+    out[i].E1_sh_psf   = in[i].E1_sh_psf;
+    out[i].E2_sh_psf   = in[i].E2_sh_psf;
+
+    out[i].E1_psf      = in[i].E1_psf;
+    out[i].E2_psf      = in[i].E2_psf;
+
+    out[i].F_ApR5      = in[i].F_ApR5;
+    out[i].dF_ApR5     = in[i].dF_ApR5;
+    out[i].sF_ApR5     = in[i].sF_ApR5;
+    out[i].fF_ApR5     = in[i].fF_ApR5;
+	               	            
+    out[i].F_ApR6      = in[i].F_ApR6;
+    out[i].dF_ApR6     = in[i].dF_ApR6;
+    out[i].sF_ApR6     = in[i].sF_ApR6;
+    out[i].fF_ApR6     = in[i].fF_ApR6;
+	          	            
+    out[i].detID       = in[i].detID;
+    out[i].objID       = in[i].objID;
+    out[i].catID       = in[i].catID;
+    out[i].averef      = in[i].averef;
+
+    out[i].imageID     = in[i].imageID;
+  }
+  return (out);
+}
+
+Lensobj *Lensobj_PS1_V5_ToInternal (Lensobj_PS1_V5 *in, off_t Nvalues) {
+
+  off_t i;
+  Lensobj *out;
+
+  ALLOCATE_ZERO (out, Lensobj, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_lensobj_init (&out[i], FALSE);
+
+    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
+    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
+    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
+    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
+    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
+	             	                 
+    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
+    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
+    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
+    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
+    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
+	             	                 
+    out[i].X11_sm_psf  = in[i].X11_sm_psf;
+    out[i].X12_sm_psf  = in[i].X12_sm_psf;
+    out[i].X22_sm_psf  = in[i].X22_sm_psf;
+    out[i].E1_sm_psf   = in[i].E1_sm_psf;
+    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
+	             	                 
+    out[i].X11_sh_psf  = in[i].X11_sh_psf;
+    out[i].X12_sh_psf  = in[i].X12_sh_psf;
+    out[i].X22_sh_psf  = in[i].X22_sh_psf;
+    out[i].E1_sh_psf   = in[i].E1_sh_psf;
+    out[i].E2_sh_psf   = in[i].E2_sh_psf;
+
+    out[i].F_ApR5      = in[i].F_ApR5;
+    out[i].dF_ApR5     = in[i].dF_ApR5;
+    out[i].sF_ApR5     = in[i].sF_ApR5;
+    out[i].fF_ApR5     = in[i].fF_ApR5;
+	               	            
+    out[i].F_ApR6      = in[i].F_ApR6;
+    out[i].dF_ApR6     = in[i].dF_ApR6;
+    out[i].sF_ApR6     = in[i].sF_ApR6;
+    out[i].fF_ApR6     = in[i].fF_ApR6;
+	          	            
+    out[i].gamma       = in[i].gamma;
+    out[i].E1          = in[i].E1;
+    out[i].E2          = in[i].E2;
+
+    out[i].objID       = in[i].objID;
+    out[i].catID       = in[i].catID;
+
+    out[i].photcode    = in[i].photcode;
+    out[i].Nmeas       = in[i].Nmeas;
+  }
+  return (out);
+}
+
+Lensobj_PS1_V5 *LensobjInternalTo_PS1_V5 (Lensobj *in, off_t Nvalues) {
+
+  off_t i;
+  Lensobj_PS1_V5 *out;
+
+  ALLOCATE_ZERO (out, Lensobj_PS1_V5, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+
+    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
+    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
+    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
+    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
+    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
+	             	                 
+    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
+    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
+    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
+    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
+    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
+	             	                 
+    out[i].X11_sm_psf  = in[i].X11_sm_psf;
+    out[i].X12_sm_psf  = in[i].X12_sm_psf;
+    out[i].X22_sm_psf  = in[i].X22_sm_psf;
+    out[i].E1_sm_psf   = in[i].E1_sm_psf;
+    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
+	             	                 
+    out[i].X11_sh_psf  = in[i].X11_sh_psf;
+    out[i].X12_sh_psf  = in[i].X12_sh_psf;
+    out[i].X22_sh_psf  = in[i].X22_sh_psf;
+    out[i].E1_sh_psf   = in[i].E1_sh_psf;
+    out[i].E2_sh_psf   = in[i].E2_sh_psf;
+
+    out[i].F_ApR5      = in[i].F_ApR5;
+    out[i].dF_ApR5     = in[i].dF_ApR5;
+    out[i].sF_ApR5     = in[i].sF_ApR5;
+    out[i].fF_ApR5     = in[i].fF_ApR5;
+	               	            
+    out[i].F_ApR6      = in[i].F_ApR6;
+    out[i].dF_ApR6     = in[i].dF_ApR6;
+    out[i].sF_ApR6     = in[i].sF_ApR6;
+    out[i].fF_ApR6     = in[i].fF_ApR6;
+	          	            
+    out[i].gamma       = in[i].gamma;
+    out[i].E1          = in[i].E1;
+    out[i].E2          = in[i].E2;
+
+    out[i].objID       = in[i].objID;
+    out[i].catID       = in[i].catID;
+
+    out[i].photcode    = in[i].photcode;
+    out[i].Nmeas       = in[i].Nmeas;
+  }
+  return (out);
+}
+
+StarPar *StarPar_PS1_V5_ToInternal (StarPar_PS1_V5 *in, off_t Nvalues) {
+
+  off_t i;
+  StarPar *out;
+
+  ALLOCATE_ZERO (out, StarPar, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_starpar_init (&out[i]);
+
+    out[i].R  	     = in[i].R;      
+    out[i].D  	     = in[i].D;      
+    out[i].galLat    = in[i].galLat;      
+    out[i].galLon    = in[i].galLon;      
+
+    out[i].Ebv       = in[i].Ebv     ;      
+    out[i].dEbv      = in[i].dEbv    ;      
+    out[i].DistMag   = in[i].DistMag ;      
+    out[i].dDistMag  = in[i].dDistMag;      
+    out[i].M_r       = in[i].M_r     ;      
+    out[i].dM_r      = in[i].dM_r    ;      
+    out[i].FeH       = in[i].FeH     ;      
+    out[i].dFeH      = in[i].dFeH    ;      
+    out[i].uRA       = in[i].uRA     ;      
+    out[i].uDEC      = in[i].uDEC    ;      
+
+    out[i].averef  = in[i].averef;
+    out[i].objID   = in[i].objID ;
+    out[i].catID   = in[i].catID ;
+  }
+  return (out);
+}
+
+StarPar_PS1_V5 *StarParInternalTo_PS1_V5 (StarPar *in, off_t Nvalues) {
+
+  off_t i;
+  StarPar_PS1_V5 *out;
+
+  ALLOCATE_ZERO (out, StarPar_PS1_V5, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+
+    out[i].R  	     = in[i].R;      
+    out[i].D  	     = in[i].D;      
+    out[i].galLat    = in[i].galLat;      
+    out[i].galLon    = in[i].galLon;      
+
+    out[i].Ebv       = in[i].Ebv     ;      
+    out[i].dEbv      = in[i].dEbv    ;      
+    out[i].DistMag   = in[i].DistMag ;      
+    out[i].dDistMag  = in[i].dDistMag;      
+    out[i].M_r       = in[i].M_r     ;      
+    out[i].dM_r      = in[i].dM_r    ;      
+    out[i].FeH       = in[i].FeH     ;      
+    out[i].dFeH      = in[i].dFeH    ;      
+    out[i].uRA       = in[i].uRA     ;      
+    out[i].uDEC      = in[i].uDEC    ;      
+
+    out[i].averef  = in[i].averef;
+    out[i].objID   = in[i].objID ;
+    out[i].catID   = in[i].catID ;
+  }
+  return (out);
+}
+
+# define RAW_IMAGE_NAME_LEN 117
+
+Image *Image_PS1_V5_ToInternal (Image_PS1_V5 *in, off_t Nvalues, off_t Nalloc) {
+
+  off_t i;
+  Image *out;
+
+  char *buffer;
+  ALLOCATE_ZERO (buffer, char, Nalloc);
+  out = (Image *) buffer;
+  // ALLOCATE_ZERO (out, Image, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    // this is only safe because the initial 120 bytes in Coords match CoordsDisk
+    memcpy (&out[i].coords, &in[i].coords, sizeof(CoordsDisk));
+    out[i].coords.mosaic   = NULL;
+    out[i].coords.offsetMap = NULL;
+
+    // RAW_IMAGE_NAME_LEN == DVO_IMAGE_NAME_LEN
+    strncpy (out[i].name, in[i].name, RAW_IMAGE_NAME_LEN - 1);
+    out[i].name[RAW_IMAGE_NAME_LEN - 1] = 0; // force termination
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].secz	    	    = in[i].secz;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].apmifit  	    = in[i].apmifit;
+    out[i].dapmifit 	    = in[i].dapmifit;
+    out[i].Mcal	    	    = in[i].Mcal;
+    out[i].dMcal    	    = in[i].dMcal;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].sidtime  	    = in[i].sidtime;
+    out[i].latitude  	    = in[i].latitude;
+
+    out[i].RAo  	    = in[i].RAo;
+    out[i].DECo  	    = in[i].DECo;
+    out[i].Radius  	    = in[i].Radius;
+    out[i].refColorBlue	    = in[i].refColorBlue;
+    out[i].refColorRed 	    = in[i].refColorRed;
+
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].flags	    = in[i].flags;
+    out[i].imageID	    = in[i].imageID;
+    out[i].parentID	    = in[i].parentID;
+    out[i].externID	    = in[i].externID;
+    out[i].sourceID	    = in[i].sourceID;
+
+    // as of 2011.02.03, the old Mx,My,..., Mxxxx,Myyyy have been deprecated and replaced
+    // with the following.  (no real databases used those values -- see
+    // libdvo/doc/dvo-images.txt)
+    out[i].nLinkAstrom	    = in[i].nLinkAstrom;
+    out[i].nLinkPhotom	    = in[i].nLinkPhotom;
+    out[i].ubercalDist	    = in[i].ubercalDist;
+    out[i].dXpixSys	    = in[i].dXpixSys;
+    out[i].dYpixSys	    = in[i].dYpixSys;
+    out[i].dMagSys	    = in[i].dMagSys;
+    out[i].nFitAstrom       = in[i].nFitAstrom;
+    out[i].nFitPhotom       = in[i].nFitPhotom;
+    out[i].photom_map_id    = in[i].photom_map_id;
+    out[i].astrom_map_id    = in[i].astrom_map_id;
+  }
+  return (out);
+}
+
+Image_PS1_V5 *ImageInternalTo_PS1_V5 (Image *in, off_t Nvalues) {
+
+  off_t i;
+  Image_PS1_V5 *out;
+
+  ALLOCATE_ZERO (out, Image_PS1_V5, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    // this is only save because the initial 120 bytes in Coords match CoordsDisk
+    memcpy (&out[i].coords, &in[i].coords, sizeof(CoordsDisk));
+
+    // RAW_IMAGE_NAME_LEN == DVO_IMAGE_NAME_LEN
+    strncpy (out[i].name, in[i].name, RAW_IMAGE_NAME_LEN - 1);
+    out[i].name[RAW_IMAGE_NAME_LEN - 1] = 0; // force termination
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].secz	    	    = in[i].secz;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].apmifit  	    = in[i].apmifit;
+    out[i].dapmifit 	    = in[i].dapmifit;
+    out[i].Mcal	    	    = in[i].Mcal;
+    out[i].dMcal    	    = in[i].dMcal;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].sidtime  	    = in[i].sidtime;
+    out[i].latitude  	    = in[i].latitude;
+
+    out[i].RAo  	    = in[i].RAo;
+    out[i].DECo  	    = in[i].DECo;
+    out[i].Radius  	    = in[i].Radius;
+    out[i].refColorBlue	    = in[i].refColorBlue;
+    out[i].refColorRed 	    = in[i].refColorRed;
+
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].flags	    = in[i].flags;
+    out[i].imageID	    = in[i].imageID;
+    out[i].parentID	    = in[i].parentID;
+    out[i].externID	    = in[i].externID;
+    out[i].sourceID	    = in[i].sourceID;
+
+    // as of 2011.02.03, the old Mx,My,..., Mxxxx,Myyyy have been deprecated and replaced
+    // with the following.  (no real databases used those values -- see
+    // libdvo/doc/dvo-images.txt)
+    out[i].nLinkAstrom	    = in[i].nLinkAstrom;
+    out[i].nLinkPhotom	    = in[i].nLinkPhotom;
+    out[i].ubercalDist	    = in[i].ubercalDist;
+    out[i].dXpixSys	    = in[i].dXpixSys;
+    out[i].dYpixSys	    = in[i].dYpixSys;
+    out[i].dMagSys	    = in[i].dMagSys;
+    out[i].nFitAstrom       = in[i].nFitAstrom;
+    out[i].nFitPhotom       = in[i].nFitPhotom;
+    out[i].photom_map_id    = in[i].photom_map_id;
+    out[i].astrom_map_id    = in[i].astrom_map_id;
+  }
+  return (out);
+}
+
+PhotCode *PhotCode_PS1_V5_To_Internal (PhotCode_PS1_V5 *in, off_t Nvalues) {
+
+  off_t i;
+  PhotCode *out;
+
+  ALLOCATE_ZERO (out, PhotCode, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code  = in[i].code;         
+    out[i].type  = in[i].type;         
+    out[i].C     = in[i].C;            
+    out[i].dC 	 = in[i].dC;           
+    out[i].dX 	 = in[i].dX;           
+    out[i].K  	 = in[i].K;            
+    out[i].c1 	 = in[i].c1;           
+    out[i].c2 	 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc    = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+
+    out[i].astromErrSys      = in[i].astromErrSys;
+    out[i].astromErrScale    = in[i].astromErrScale;
+    out[i].astromErrMagScale = in[i].astromErrMagScale;
+    out[i].photomErrSys      = in[i].photomErrSys;
+
+    out[i].photomPoorMask      = in[i].photomPoorMask;
+    out[i].photomBadMask       = in[i].photomBadMask;
+    out[i].astromPoorMask      = in[i].astromPoorMask;
+    out[i].astromBadMask       = in[i].astromBadMask;
+  }
+  return (out);
+}
+
+PhotCode_PS1_V5 *PhotCode_Internal_To_PS1_V5 (PhotCode *in, off_t Nvalues) {
+
+  off_t i;
+  PhotCode_PS1_V5 *out;
+
+  ALLOCATE_ZERO (out, PhotCode_PS1_V5, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code  = in[i].code;         
+    out[i].type  = in[i].type;         
+    out[i].C     = in[i].C;            
+    out[i].dC 	 = in[i].dC;           
+    out[i].dX 	 = in[i].dX;           
+    out[i].K  	 = in[i].K;            
+    out[i].c1 	 = in[i].c1;           
+    out[i].c2 	 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc    = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+
+    out[i].astromErrSys      = in[i].astromErrSys;
+    out[i].astromErrScale    = in[i].astromErrScale;
+    out[i].astromErrMagScale = in[i].astromErrMagScale;
+    out[i].photomErrSys      = in[i].photomErrSys;
+
+    out[i].photomPoorMask      = in[i].photomPoorMask;
+    out[i].photomBadMask       = in[i].photomBadMask;
+    out[i].astromPoorMask      = in[i].astromPoorMask;
+    out[i].astromBadMask       = in[i].astromBadMask;
+  }
+  return (out);
+}
+
+/*********************** old / alternate version **********************/
+
+// 'primary' is needed to conform with the API for Loneos and Elixir, but is not used
+Average *Average_PS1_V5alt_ToInternal (Average_PS1_V5alt *in, off_t Nvalues) {
+
+  off_t i;
+  Average *out;
+
+  ALLOCATE_ZERO (out, Average, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_average_init (&out[i]);
+
+    out[i].R        	  = in[i].R;      
+    out[i].D        	  = in[i].D;      
+    out[i].dR       	  = in[i].dR;
+    out[i].dD       	  = in[i].dD;
+    out[i].uR       	  = in[i].uR;
+    out[i].uD       	  = in[i].uD;
+    out[i].duR      	  = in[i].duR;
+    out[i].duD      	  = in[i].duD;
+    out[i].P        	  = in[i].P;
+    out[i].dP       	  = in[i].dP;
+			  
+    out[i].Rstk        	  = in[i].Rstk;      
+    out[i].Dstk        	  = in[i].Dstk;      
+    out[i].dRstk       	  = in[i].dRstk;
+    out[i].dDstk       	  = in[i].dDstk;
+			  
+    out[i].ChiSqAve    	  = in[i].ChiSqAve;     
+    out[i].ChiSqPM    	  = in[i].ChiSqPM;     
+    out[i].ChiSqPar    	  = in[i].ChiSqPar;     
+    out[i].Tmean    	  = in[i].Tmean;     
+    out[i].Trange   	  = in[i].Trange;     
+			  
+    out[i].psfQF          = in[i].psfQF;
+    out[i].psfQFperf      = in[i].psfQFperf;
+    out[i].stargal     	  = in[i].stargal;     
+    out[i].Npos       	  = in[i].Npos;     
+			  
+    out[i].Nmeasure       = in[i].Nmeasure;     
+    out[i].Nmissing       = in[i].Nmissing;     
+    out[i].Nlensing       = in[i].Nlensing;     
+    out[i].Nlensobj       = in[i].Nlensobj;     
+    out[i].Nextend        = in[i].Nextend;     
+			  
+    out[i].measureOffset  = in[i].measureOffset; 
+    out[i].missingOffset  = in[i].missingOffset;
+    out[i].lensingOffset  = in[i].lensingOffset;
+    out[i].lensobjOffset  = in[i].lensobjOffset;
+    out[i].starparOffset  = in[i].starparOffset;
+    out[i].extendOffset   = in[i].extendOffset;
+			  
+    out[i].refColorBlue   = in[i].refColorBlue;
+    out[i].refColorRed    = in[i].refColorRed;
+			  
+    out[i].flags     	  = in[i].flags;   
+    out[i].photFlagsUpper = in[i].photFlagsUpper;   
+    out[i].photFlagsLower = in[i].photFlagsLower;   
+    out[i].objID 	  = in[i].objID;
+    out[i].catID 	  = in[i].catID;
+    out[i].extID 	  = in[i].extID;
+    out[i].extIDgc 	  = in[i].extIDgc;
+  }
+  return (out);
+}
+
+int gfits_convert_Average_PS1_V5alt (Average_PS1_V5alt *data, off_t size, off_t nitems) {
+
+  off_t i;
+  unsigned char *byte, tmp;
+
+  if (size != 184) { 
+    fprintf (stderr, "WARNING: mismatch in data types Average_PS1_V5alt: "OFF_T_FMT" vs %d\n",  size,  184);
+    return (FALSE);
+  }
+
+  /* provide initial values to avoid compiler warnings for non-BYTE_SWAP arch */
+  i = tmp = 0;
+  byte = NULL;
+
+# ifdef BYTE_SWAP
+  byte = (unsigned char *) data;
+  for (i = 0; i < nitems; i++, byte += 184) {
+    /** BYTE SWAP **/
+    SWAP_DBLE (0); // RA
+    SWAP_DBLE (8); // DEC
+    SWAP_WORD (16); // RA_ERR
+    SWAP_WORD (20); // DEC_ERR
+    SWAP_WORD (24); // U_RA
+    SWAP_WORD (28); // U_DEC
+    SWAP_WORD (32); // V_RA_ERR
+    SWAP_WORD (36); // V_DEC_ERR
+    SWAP_WORD (40); // PAR
+    SWAP_WORD (44); // PAR_ERR
+    SWAP_DBLE (48); // RA_STK
+    SWAP_DBLE (56); // DEC_STK
+    SWAP_WORD (64); // RA_STK_ERR
+    SWAP_WORD (68); // DEC_STK_ERR
+    SWAP_WORD (72); // CHISQ_POS
+    SWAP_WORD (76); // CHISQ_PM
+    SWAP_WORD (80); // CHISQ_PAP
+    SWAP_WORD (84); // MEAN_EPOCH
+    SWAP_WORD (88); // TIME_RANGE
+    SWAP_WORD (92); // PSF_QF
+    SWAP_WORD (96); // PSF_QF_PERF
+    SWAP_WORD (100); // STARGAL_SEP
+    SWAP_BYTE (104); // NUMBER_POS
+    SWAP_BYTE (106); // NMEASURE
+    SWAP_BYTE (108); // NMISSING
+    SWAP_BYTE (110); // NLENSING
+    SWAP_BYTE (112); // NLENSOBJ
+    SWAP_BYTE (114); // NEXTEND
+    SWAP_WORD (116); // OFF_MEASURE
+    SWAP_WORD (120); // OFF_MISSING
+    SWAP_WORD (124); // OFF_LENSING
+    SWAP_WORD (128); // OFF_LENSOBJ
+    SWAP_WORD (132); // OFF_EXTEND
+    SWAP_WORD (136); // OFF_PARAMS
+    SWAP_WORD (140); // REF_COLOR_BLUE
+    SWAP_WORD (144); // REF_COLOR_RED
+    SWAP_WORD (148); // FLAGS
+    SWAP_WORD (152); // PHOTFLAGS_U
+    SWAP_WORD (156); // PHOTFLAGS_L
+    SWAP_WORD (160); // OBJ_ID
+    SWAP_WORD (164); // CAT_ID
+    SWAP_DBLE (168); // EXT_ID
+    SWAP_DBLE (176); // EXT_ID_GC
+  }
+# endif  
+
+  return (TRUE);
+} 
+
+/*** add test of EXTNAME and header-defined columns? ***/
+/* return internal structure representation */
+Average_PS1_V5alt *gfits_table_get_Average_PS1_V5alt (FTable *ftable, off_t *Ndata, char *swapped) {
+
+  int Ncols;
+  Average_PS1_V5alt *data;
+
+  Ncols = ftable[0].header[0].Naxis[0];
+  if (Ncols != 184) {
+    fprintf (stderr, "ERROR: mis-match in table size: width is %d but should be %d bytes\n", Ncols, 184);
+    return NULL;
+  }
+
+  *Ndata = ftable[0].header[0].Naxis[1];
+  data = (Average_PS1_V5alt *) ftable[0].buffer;
+  if ((swapped == NULL) || (*swapped == FALSE)) {
+    if (!gfits_convert_Average_PS1_V5alt (data, sizeof (Average_PS1_V5alt), *Ndata)) {
+      return NULL;
+    }
+    gfits_table_scale_data (ftable);
+    if (swapped != NULL) *swapped = TRUE;
+  }
+  return (data);
+}
+
+/****** alt secfilt **********/
+
+SecFilt *SecFilt_PS1_V5alt_ToInternal (SecFilt_PS1_V5alt *in, off_t Nvalues) {
+
+  off_t i;
+  SecFilt *out;
+
+  ALLOCATE_ZERO (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_secfilt_init (&out[i]);
+
+    out[i].M             = in[i].M;      
+    out[i].dM            = in[i].dM;      
+    out[i].Map           = in[i].Map;      
+    out[i].dMap          = in[i].dMap;      
+    out[i].sMap          = in[i].sMap;      
+    out[i].Mkron         = in[i].Mkron;      
+    out[i].dMkron        = in[i].dMkron;      
+
+    out[i].Mstdev        = in[i].Mstdev;      
+    out[i].Mmin          = in[i].Mmin;      
+    out[i].Mmax          = in[i].Mmax;      
+    out[i].Mchisq        = in[i].Mchisq;     
+
+    out[i].Ncode         = in[i].Ncode;
+    out[i].Nused         = in[i].Nused;
+    out[i].NusedKron     = in[i].NusedKron;
+    out[i].NusedAp       = in[i].NusedAp;
+
+    out[i].flags         = in[i].flags;     
+
+    out[i].MpsfStk       = in[i].MpsfStk;
+    out[i].FpsfStk       = in[i].FpsfStk;
+    out[i].dFpsfStk      = in[i].dFpsfStk;
+
+    out[i].MkronStk      = in[i].MkronStk;
+    out[i].FkronStk      = in[i].FkronStk;
+    out[i].dFkronStk     = in[i].dFkronStk;
+
+    out[i].MapStk        = in[i].MapStk;
+    out[i].FapStk        = in[i].FapStk;
+    out[i].dFapStk       = in[i].dFapStk;
+
+    out[i].stackPrmryOff = in[i].stackPrmryOff;      
+    out[i].stackBestOff  = in[i].stackBestOff;      
+
+    out[i].MpsfWrp       = in[i].MpsfWrp;
+    out[i].FpsfWrp       = in[i].FpsfWrp;
+    out[i].dFpsfWrp      = in[i].dFpsfWrp;
+    out[i].sFpsfWrp      = in[i].sFpsfWrp;
+
+    out[i].MkronWrp      = in[i].MkronWrp;
+    out[i].FkronWrp      = in[i].FkronWrp;
+    out[i].dFkronWrp     = in[i].dFkronWrp;
+    out[i].sFkronWrp     = in[i].sFkronWrp;
+
+    out[i].MapWrp        = in[i].MapWrp;
+    out[i].FapWrp        = in[i].FapWrp;
+    out[i].dFapWrp       = in[i].dFapWrp;
+    out[i].sFapWrp       = in[i].sFapWrp;
+
+    out[i].NusedWrp      = in[i].NusedWrp;
+    out[i].NusedKronWrp  = in[i].NusedKronWrp;
+    out[i].NusedApWrp    = in[i].NusedApWrp;
+
+    out[i].ubercalDist   = in[i].ubercalDist;      
+  }
+  return (out);
+}
+
+int gfits_convert_SecFilt_PS1_V5alt (SecFilt_PS1_V5alt *data, off_t size, off_t nitems) {
+
+  off_t i;
+  unsigned char *byte, tmp;
+
+  if (size != 160) { 
+    fprintf (stderr, "WARNING: mismatch in data types SecFilt_PS1_V5alt: "OFF_T_FMT" vs %d\n",  size,  160);
+    return (FALSE);
+  }
+
+  /* provide initial values to avoid compiler warnings for non-BYTE_SWAP arch */
+  i = tmp = 0;
+  byte = NULL;
+
+# ifdef BYTE_SWAP
+  byte = (unsigned char *) data;
+  for (i = 0; i < nitems; i++, byte += 160) {
+    /** BYTE SWAP **/
+    SWAP_WORD (0); // MAG
+    SWAP_WORD (4); // MAG_ERR
+    SWAP_WORD (8); // MAG_AP
+    SWAP_WORD (12); // MAG_AP_ERR
+    SWAP_WORD (16); // MAG_AP_STDEV
+    SWAP_WORD (20); // MAG_KRON
+    SWAP_WORD (24); // MAG_KRON_ERR
+    SWAP_WORD (28); // MAG_KRON_STDEV
+    SWAP_WORD (32); // MAG_STDEV
+    SWAP_WORD (36); // MAG_MIN
+    SWAP_WORD (40); // MAG_MAX
+    SWAP_WORD (44); // MAG_CHI
+    SWAP_BYTE (48); // NCODE
+    SWAP_BYTE (50); // NUSED
+    SWAP_BYTE (52); // NUSED_KRON
+    SWAP_BYTE (54); // NUSED_AP
+    SWAP_WORD (56); // FLAGS
+    SWAP_WORD (60); // MAG_PSF_STK
+    SWAP_WORD (64); // FLUX_PSF_STK
+    SWAP_WORD (68); // FLUX_PSF_STK_ERR
+    SWAP_WORD (72); // MAG_KRON_STK
+    SWAP_WORD (76); // FLUX_KRON_STK
+    SWAP_WORD (80); // FLUX_KRON_STK_ERR
+    SWAP_WORD (84); // MAG_AP_STK
+    SWAP_WORD (88); // FLUX_AP_STK
+    SWAP_WORD (92); // FLUX_AP_STK_ERR
+    SWAP_WORD (96); // STACK_PRIMARY_OFF
+    SWAP_WORD (100); // STACK_BEST_OFF
+    SWAP_WORD (104); // MAG_PSF_WRP
+    SWAP_WORD (108); // FLUX_PSF_WRP
+    SWAP_WORD (112); // FLUX_PSF_WRP_ERR
+    SWAP_WORD (116); // FLUX_PSF_WRP_STD
+    SWAP_WORD (120); // MAG_KRON_WRP
+    SWAP_WORD (124); // FLUX_KRON_WRP
+    SWAP_WORD (128); // FLUX_KRON_WRP_ERR
+    SWAP_WORD (132); // FLUX_KRON_WRP_STD
+    SWAP_WORD (136); // MAG_AP_WRP
+    SWAP_WORD (140); // FLUX_AP_WRP
+    SWAP_WORD (144); // FLUX_AP_WRP_ERR
+    SWAP_WORD (148); // FLUX_AP_WRP_STD
+    SWAP_BYTE (152); // NUSED_WRP
+    SWAP_BYTE (154); // NUSED_KRON_WRP
+    SWAP_BYTE (156); // NUSED_AP_WRP
+    SWAP_BYTE (158); // UBERCAL_DIST
+  }
+# endif  
+
+  return (TRUE);
+} 
+
+/*** add test of EXTNAME and header-defined columns? ***/
+/* return internal structure representation */
+SecFilt_PS1_V5alt *gfits_table_get_SecFilt_PS1_V5alt (FTable *ftable, off_t *Ndata, char *swapped) {
+
+  int Ncols;
+  SecFilt_PS1_V5alt *data;
+
+  Ncols = ftable[0].header[0].Naxis[0];
+  if (Ncols != 160) {
+    fprintf (stderr, "ERROR: mis-match in table size: width is %d but should be %d bytes\n", Ncols, 160);
+    return NULL;
+  }
+
+  *Ndata = ftable[0].header[0].Naxis[1];
+  data = (SecFilt_PS1_V5alt *) ftable[0].buffer;
+  if ((swapped == NULL) || (*swapped == FALSE)) {
+    if (!gfits_convert_SecFilt_PS1_V5alt (data, sizeof (SecFilt_PS1_V5alt), *Ndata)) {
+      return NULL;
+    }
+    gfits_table_scale_data (ftable);
+    if (swapped != NULL) *swapped = TRUE;
+  }
+  return (data);
+}
+
+Lensing *Lensing_PS1_V5_R0_ToInternal (Lensing_PS1_V5_R0 *in, off_t Nvalues) {
+
+  off_t i;
+  Lensing *out;
+
+  ALLOCATE_ZERO (out, Lensing, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_lensing_init (&out[i]);
+
+    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
+    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
+    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
+    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
+    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
+	             	                 
+    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
+    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
+    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
+    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
+    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
+	             	                 
+    out[i].X11_sm_psf  = in[i].X11_sm_psf;
+    out[i].X12_sm_psf  = in[i].X12_sm_psf;
+    out[i].X22_sm_psf  = in[i].X22_sm_psf;
+    out[i].E1_sm_psf   = in[i].E1_sm_psf;
+    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
+	             	                 
+    out[i].X11_sh_psf  = in[i].X11_sh_psf;
+    out[i].X12_sh_psf  = in[i].X12_sh_psf;
+    out[i].X22_sh_psf  = in[i].X22_sh_psf;
+    out[i].E1_sh_psf   = in[i].E1_sh_psf;
+    out[i].E2_sh_psf   = in[i].E2_sh_psf;
+
+    out[i].F_ApR5      = in[i].F_ApR5;
+    out[i].dF_ApR5     = in[i].dF_ApR5;
+    out[i].sF_ApR5     = in[i].sF_ApR5;
+    out[i].fF_ApR5     = in[i].fF_ApR5;
+	               	            
+    out[i].F_ApR6      = in[i].F_ApR6;
+    out[i].dF_ApR6     = in[i].dF_ApR6;
+    out[i].sF_ApR6     = in[i].sF_ApR6;
+    out[i].fF_ApR6     = in[i].fF_ApR6;
+	          	            
+    out[i].detID       = in[i].detID;
+    out[i].objID       = in[i].objID;
+    out[i].catID       = in[i].catID;
+    out[i].averef      = in[i].averef;
+  }
+  return (out);
+}
+
+Lensing *Lensing_PS1_V5_R1_ToInternal (Lensing_PS1_V5_R1 *in, off_t Nvalues) {
+
+  off_t i;
+  Lensing *out;
+
+  ALLOCATE_ZERO (out, Lensing, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    dvo_lensing_init (&out[i]);
+
+    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
+    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
+    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
+    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
+    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
+	             	                 
+    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
+    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
+    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
+    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
+    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
+	             	                 
+    out[i].X11_sm_psf  = in[i].X11_sm_psf;
+    out[i].X12_sm_psf  = in[i].X12_sm_psf;
+    out[i].X22_sm_psf  = in[i].X22_sm_psf;
+    out[i].E1_sm_psf   = in[i].E1_sm_psf;
+    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
+	             	                 
+    out[i].X11_sh_psf  = in[i].X11_sh_psf;
+    out[i].X12_sh_psf  = in[i].X12_sh_psf;
+    out[i].X22_sh_psf  = in[i].X22_sh_psf;
+    out[i].E1_sh_psf   = in[i].E1_sh_psf;
+    out[i].E2_sh_psf   = in[i].E2_sh_psf;
+
+    out[i].F_ApR5      = in[i].F_ApR5;
+    out[i].dF_ApR5     = in[i].dF_ApR5;
+    out[i].sF_ApR5     = in[i].sF_ApR5;
+    out[i].fF_ApR5     = in[i].fF_ApR5;
+	               	            
+    out[i].F_ApR6      = in[i].F_ApR6;
+    out[i].dF_ApR6     = in[i].dF_ApR6;
+    out[i].sF_ApR6     = in[i].sF_ApR6;
+    out[i].fF_ApR6     = in[i].fF_ApR6;
+	          	            
+    out[i].detID       = in[i].detID;
+    out[i].objID       = in[i].objID;
+    out[i].catID       = in[i].catID;
+    out[i].averef      = in[i].averef;
+
+    out[i].imageID     = in[i].imageID;
+  }
+  return (out);
+}
+
+/********** PS1_V5alt measure ************/
+
+Measure *Measure_PS1_V5alt_ToInternal (Average *ave, Measure_PS1_V5alt *in, off_t Nvalues) {
 
   off_t i;
@@ -77,947 +1455,11 @@
 }
 
-Measure_PS1_V5 *MeasureInternalTo_PS1_V5 (Average *ave, Measure *in, off_t Nvalues) {
-
-  off_t i;
-  Measure_PS1_V5 *out;
-
-  ALLOCATE_ZERO (out, Measure_PS1_V5, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    out[i].R          = in[i].R;
-    out[i].D          = in[i].D;
-    out[i].M          = in[i].M;
-    out[i].dM         = in[i].dM;
-    out[i].Map        = in[i].Map;
-    out[i].dMap       = in[i].dMap;
-    out[i].Mkron      = in[i].Mkron;
-    out[i].dMkron     = in[i].dMkron;
-    out[i].Mcal       = in[i].Mcal;
-    out[i].dMcal      = in[i].dMcal;
-    out[i].dt         = in[i].dt;
-    out[i].FluxPSF    = in[i].FluxPSF;
-    out[i].dFluxPSF   = in[i].dFluxPSF;
-    out[i].FluxKron   = in[i].FluxKron;
-    out[i].dFluxKron  = in[i].dFluxKron;
-    out[i].FluxAp     = in[i].FluxAp;
-    out[i].dFluxAp    = in[i].dFluxAp;
-    out[i].airmass    = in[i].airmass;
-    out[i].az         = in[i].az;
-    out[i].Xccd       = in[i].Xccd;
-    out[i].Yccd       = in[i].Yccd;
-    out[i].Xfix       = in[i].Xfix;
-    out[i].Yfix       = in[i].Yfix;
-    out[i].XoffKH     = in[i].XoffKH;
-    out[i].YoffKH     = in[i].YoffKH;
-    out[i].XoffDCR    = in[i].XoffDCR;
-    out[i].YoffDCR    = in[i].YoffDCR;
-    out[i].RoffGAL    = in[i].RoffGAL;
-    out[i].DoffGAL    = in[i].DoffGAL;
-    out[i].Sky        = in[i].Sky;
-    out[i].dSky       = in[i].dSky;
-    out[i].t          = in[i].t;
-    out[i].averef     = in[i].averef;
-    out[i].detID      = in[i].detID;
-    out[i].objID      = in[i].objID;
-    out[i].catID      = in[i].catID;
-    out[i].extID      = in[i].extID;
-    out[i].imageID    = in[i].imageID;
-    out[i].psfQF      = in[i].psfQF;
-    out[i].psfQFperf  = in[i].psfQFperf;
-    out[i].psfChisq   = in[i].psfChisq;
-    out[i].psfNdof    = in[i].psfNdof;
-    out[i].psfNpix    = in[i].psfNpix;
-    out[i].extNsigma  = in[i].extNsigma;
-    out[i].FWx 	      = in[i].FWx;
-    out[i].FWy 	      = in[i].FWy;
-    out[i].theta      = in[i].theta;
-    out[i].Mxx 	      = in[i].Mxx;
-    out[i].Mxy 	      = in[i].Mxy;
-    out[i].Myy 	      = in[i].Myy;
-    out[i].t_msec     = in[i].t_msec;
-    out[i].photcode   = in[i].photcode;
-    out[i].dXccd      = in[i].dXccd;
-    out[i].dYccd      = in[i].dYccd;
-    out[i].dRsys      = in[i].dRsys;
-    out[i].posangle   = in[i].posangle;
-    out[i].pltscale   = in[i].pltscale;
-    out[i].dbFlags    = in[i].dbFlags;
-    out[i].photFlags  = in[i].photFlags;
-    out[i].photFlags2 = in[i].photFlags2;
-  }
-  return (out);
-}
-
-// 'primary' is needed to conform with the API for Loneos and Elixir, but is not used
-Average *Average_PS1_V5_ToInternal (Average_PS1_V5 *in, off_t Nvalues, SecFilt **primary) {
-
-  off_t i;
-  Average *out;
-
-  ALLOCATE_ZERO (out, Average, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    dvo_average_init (&out[i]);
-
-    out[i].R        	 = in[i].R;      
-    out[i].D        	 = in[i].D;      
-    out[i].dR       	 = in[i].dR;
-    out[i].dD       	 = in[i].dD;
-    out[i].uR       	 = in[i].uR;
-    out[i].uD       	 = in[i].uD;
-    out[i].duR      	 = in[i].duR;
-    out[i].duD      	 = in[i].duD;
-    out[i].P        	 = in[i].P;
-    out[i].dP       	 = in[i].dP;
-
-    out[i].Rstk        	 = in[i].Rstk;      
-    out[i].Dstk        	 = in[i].Dstk;      
-    out[i].dRstk       	 = in[i].dRstk;
-    out[i].dDstk       	 = in[i].dDstk;
-
-    out[i].ChiSqAve    	 = in[i].ChiSqAve;     
-    out[i].ChiSqPM    	 = in[i].ChiSqPM;     
-    out[i].ChiSqPar    	 = in[i].ChiSqPar;     
-    out[i].Tmean    	 = in[i].Tmean;     
-    out[i].Trange   	 = in[i].Trange;     
-
-    out[i].psfQF         = in[i].psfQF;
-    out[i].psfQFperf     = in[i].psfQFperf;
-    out[i].stargal     	 = in[i].stargal;     
-    out[i].Npos       	 = in[i].Npos;     
-
-    out[i].Nmeasure      = in[i].Nmeasure;     
-    out[i].Nmissing      = in[i].Nmissing;     
-    out[i].Nlensing      = in[i].Nlensing;     
-    out[i].Nlensobj      = in[i].Nlensobj;     
-    out[i].Nstarpar      = in[i].Nstarpar;     
-    out[i].Nextend       = in[i].Nextend;     
-
-    out[i].measureOffset = in[i].measureOffset; 
-    out[i].missingOffset = in[i].missingOffset;
-    out[i].lensingOffset = in[i].lensingOffset;
-    out[i].lensobjOffset = in[i].lensobjOffset;
-    out[i].starparOffset = in[i].starparOffset;
-    out[i].extendOffset  = in[i].extendOffset;
-
-    out[i].refColorBlue  = in[i].refColorBlue;
-    out[i].refColorRed   = in[i].refColorRed;
-
-    out[i].tessID        = in[i].tessID;
-    out[i].skycellID     = in[i].skycellID;
-    out[i].projectionID  = in[i].projectionID;
-
-    out[i].flags     	 = in[i].flags;   
-    out[i].photFlagsUpper = in[i].photFlagsUpper;   
-    out[i].photFlagsLower = in[i].photFlagsLower;   
-    out[i].objID 	 = in[i].objID;
-    out[i].catID 	 = in[i].catID;
-    out[i].extID 	 = in[i].extID;
-    out[i].extIDgc 	 = in[i].extIDgc;
-  }
-  return (out);
-}
-
-// 'primary' is needed to conform with the API for Loneos and Elixir, but is not used
-Average_PS1_V5 *AverageInternalTo_PS1_V5 (Average *in, off_t Nvalues, SecFilt *primary) {
-
-  off_t i;
-  Average_PS1_V5 *out;
-
-  ALLOCATE_ZERO (out, Average_PS1_V5, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    out[i].R        	  = in[i].R;      
-    out[i].D        	  = in[i].D;      
-    out[i].dR       	  = in[i].dR;
-    out[i].dD       	  = in[i].dD;
-    out[i].uR       	  = in[i].uR;
-    out[i].uD       	  = in[i].uD;
-    out[i].duR      	  = in[i].duR;
-    out[i].duD      	  = in[i].duD;
-    out[i].P        	  = in[i].P;
-    out[i].dP       	  = in[i].dP;
-			  
-    out[i].Rstk        	  = in[i].Rstk;      
-    out[i].Dstk        	  = in[i].Dstk;      
-    out[i].dRstk       	  = in[i].dRstk;
-    out[i].dDstk       	  = in[i].dDstk;
-			  
-    out[i].ChiSqAve    	  = in[i].ChiSqAve;     
-    out[i].ChiSqPM     	  = in[i].ChiSqPM;     
-    out[i].ChiSqPar   	  = in[i].ChiSqPar;     
-    out[i].Tmean    	  = in[i].Tmean;     
-    out[i].Trange   	  = in[i].Trange;     
-			  
-    out[i].psfQF          = in[i].psfQF;
-    out[i].psfQFperf      = in[i].psfQFperf;
-    out[i].stargal     	  = in[i].stargal;     
-    out[i].Npos       	  = in[i].Npos;     
-			  
-    out[i].Nmeasure       = in[i].Nmeasure;     
-    out[i].Nmissing       = in[i].Nmissing;     
-    out[i].Nlensing       = in[i].Nlensing;     
-    out[i].Nlensobj       = in[i].Nlensobj;     
-    out[i].Nstarpar       = in[i].Nstarpar;     
-    out[i].Nextend        = in[i].Nextend;     
-			  
-    out[i].measureOffset  = in[i].measureOffset; 
-    out[i].missingOffset  = in[i].missingOffset;
-    out[i].lensingOffset  = in[i].lensingOffset;
-    out[i].lensobjOffset  = in[i].lensobjOffset;
-    out[i].starparOffset  = in[i].starparOffset;
-    out[i].extendOffset   = in[i].extendOffset;
-			  
-    out[i].refColorBlue   = in[i].refColorBlue;
-    out[i].refColorRed    = in[i].refColorRed;
-			  
-    out[i].tessID         = in[i].tessID;
-    out[i].skycellID      = in[i].skycellID;
-    out[i].projectionID   = in[i].projectionID;
-			  
-    out[i].flags     	  = in[i].flags;   
-    out[i].photFlagsUpper = in[i].photFlagsUpper;   
-    out[i].photFlagsLower = in[i].photFlagsLower;   
-    out[i].objID 	  = in[i].objID;
-    out[i].catID 	  = in[i].catID;
-    out[i].extID 	  = in[i].extID;
-    out[i].extIDgc 	  = in[i].extIDgc;
-  }
-  return (out);
-}
-
-SecFilt *SecFilt_PS1_V5_ToInternal (SecFilt_PS1_V5 *in, off_t Nvalues) {
-
-  off_t i;
-  SecFilt *out;
-
-  ALLOCATE_ZERO (out, SecFilt, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    dvo_secfilt_init (&out[i]);
-
-    out[i].M             = in[i].M;      
-    out[i].dM            = in[i].dM;      
-    out[i].Map           = in[i].Map;      
-    out[i].dMap          = in[i].dMap;      
-    out[i].sMap          = in[i].sMap;      
-    out[i].Mkron         = in[i].Mkron;      
-    out[i].dMkron        = in[i].dMkron;      
-    out[i].sMkron        = in[i].sMkron;      
-
-    out[i].psfQfMax      = in[i].psfQfMax;      
-    out[i].psfQfPerfMax  = in[i].psfQfPerfMax;      
-
-    out[i].Mstdev        = in[i].Mstdev;      
-    out[i].Mmin          = in[i].Mmin;      
-    out[i].Mmax          = in[i].Mmax;      
-    out[i].Mchisq        = in[i].Mchisq;     
-
-    out[i].Ncode         = in[i].Ncode;
-    out[i].Nused         = in[i].Nused;
-    out[i].NusedKron     = in[i].NusedKron;
-    out[i].NusedAp       = in[i].NusedAp;
-
-    out[i].flags         = in[i].flags;     
-
-    out[i].MpsfStk       = in[i].MpsfStk;
-    out[i].FpsfStk       = in[i].FpsfStk;
-    out[i].dFpsfStk      = in[i].dFpsfStk;
-
-    out[i].MkronStk      = in[i].MkronStk;
-    out[i].FkronStk      = in[i].FkronStk;
-    out[i].dFkronStk     = in[i].dFkronStk;
-
-    out[i].MapStk        = in[i].MapStk;
-    out[i].FapStk        = in[i].FapStk;
-    out[i].dFapStk       = in[i].dFapStk;
-
-    out[i].Nstack        = in[i].Nstack;      
-    out[i].NstackDet     = in[i].NstackDet;      
-
-    out[i].stackPrmryOff = in[i].stackPrmryOff;      
-    out[i].stackBestOff  = in[i].stackBestOff;      
-
-    out[i].MpsfWrp       = in[i].MpsfWrp;
-    out[i].FpsfWrp       = in[i].FpsfWrp;
-    out[i].dFpsfWrp      = in[i].dFpsfWrp;
-    out[i].sFpsfWrp      = in[i].sFpsfWrp;
-
-    out[i].MkronWrp      = in[i].MkronWrp;
-    out[i].FkronWrp      = in[i].FkronWrp;
-    out[i].dFkronWrp     = in[i].dFkronWrp;
-    out[i].sFkronWrp     = in[i].sFkronWrp;
-
-    out[i].MapWrp        = in[i].MapWrp;
-    out[i].FapWrp        = in[i].FapWrp;
-    out[i].dFapWrp       = in[i].dFapWrp;
-    out[i].sFapWrp       = in[i].sFapWrp;
-
-    out[i].NusedWrp      = in[i].NusedWrp;
-    out[i].NusedKronWrp  = in[i].NusedKronWrp;
-    out[i].NusedApWrp    = in[i].NusedApWrp;
-
-    out[i].Nwarp         = in[i].Nwarp;      
-    out[i].NwarpGood     = in[i].NwarpGood;      
-
-    out[i].ubercalDist   = in[i].ubercalDist;      
-  }
-  return (out);
-}
-
-SecFilt_PS1_V5 *SecFiltInternalTo_PS1_V5 (SecFilt *in, off_t Nvalues) {
-
-  off_t i;
-  SecFilt_PS1_V5 *out;
-
-  ALLOCATE_ZERO (out, SecFilt_PS1_V5, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-
-    out[i].M             = in[i].M;      
-    out[i].dM            = in[i].dM;      
-    out[i].Map           = in[i].Map;      
-    out[i].dMap          = in[i].dMap;      
-    out[i].sMap          = in[i].sMap;      
-    out[i].Mkron         = in[i].Mkron;      
-    out[i].dMkron        = in[i].dMkron;      
-    out[i].sMkron        = in[i].sMkron;      
-
-    out[i].psfQfMax      = in[i].psfQfMax;      
-    out[i].psfQfPerfMax  = in[i].psfQfPerfMax;      
-
-    out[i].Mstdev        = in[i].Mstdev;      
-    out[i].Mmin          = in[i].Mmin;      
-    out[i].Mmax          = in[i].Mmax;      
-    out[i].Mchisq        = in[i].Mchisq;     
-
-    out[i].Ncode         = in[i].Ncode;
-    out[i].Nused         = in[i].Nused;
-    out[i].NusedKron     = in[i].NusedKron;
-    out[i].NusedAp       = in[i].NusedAp;
-
-    out[i].flags         = in[i].flags;     
-
-    out[i].MpsfStk       = in[i].MpsfStk;
-    out[i].FpsfStk       = in[i].FpsfStk;
-    out[i].dFpsfStk      = in[i].dFpsfStk;
-
-    out[i].MkronStk      = in[i].MkronStk;
-    out[i].FkronStk      = in[i].FkronStk;
-    out[i].dFkronStk     = in[i].dFkronStk;
-
-    out[i].MapStk        = in[i].MapStk;
-    out[i].FapStk        = in[i].FapStk;
-    out[i].dFapStk       = in[i].dFapStk;
-
-    out[i].Nstack        = in[i].Nstack;      
-    out[i].NstackDet     = in[i].NstackDet;      
-
-    out[i].stackPrmryOff = in[i].stackPrmryOff;      
-    out[i].stackBestOff  = in[i].stackBestOff;      
-
-    out[i].MpsfWrp       = in[i].MpsfWrp;
-    out[i].FpsfWrp       = in[i].FpsfWrp;
-    out[i].dFpsfWrp      = in[i].dFpsfWrp;
-    out[i].sFpsfWrp      = in[i].sFpsfWrp;
-
-    out[i].MkronWrp      = in[i].MkronWrp;
-    out[i].FkronWrp      = in[i].FkronWrp;
-    out[i].dFkronWrp     = in[i].dFkronWrp;
-    out[i].sFkronWrp     = in[i].sFkronWrp;
-
-    out[i].MapWrp        = in[i].MapWrp;
-    out[i].FapWrp        = in[i].FapWrp;
-    out[i].dFapWrp       = in[i].dFapWrp;
-    out[i].sFapWrp       = in[i].sFapWrp;
-
-    out[i].NusedWrp      = in[i].NusedWrp;
-    out[i].NusedKronWrp  = in[i].NusedKronWrp;
-    out[i].NusedApWrp    = in[i].NusedApWrp;
-
-    out[i].Nwarp         = in[i].Nwarp;      
-    out[i].NwarpGood     = in[i].NwarpGood;      
-
-    out[i].ubercalDist   = in[i].ubercalDist;      
-  }
-  return (out);
-}
-
-Lensing *Lensing_PS1_V5_R2_ToInternal (Lensing_PS1_V5_R2 *in, off_t Nvalues) {
-
-  off_t i;
-  Lensing *out;
-
-  ALLOCATE_ZERO (out, Lensing, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    dvo_lensing_init (&out[i]);
-
-    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
-    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
-    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
-    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
-    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
-	             	                 
-    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
-    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
-    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
-    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
-    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
-	             	                 
-    out[i].X11_sm_psf  = in[i].X11_sm_psf;
-    out[i].X12_sm_psf  = in[i].X12_sm_psf;
-    out[i].X22_sm_psf  = in[i].X22_sm_psf;
-    out[i].E1_sm_psf   = in[i].E1_sm_psf;
-    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
-	             	                 
-    out[i].X11_sh_psf  = in[i].X11_sh_psf;
-    out[i].X12_sh_psf  = in[i].X12_sh_psf;
-    out[i].X22_sh_psf  = in[i].X22_sh_psf;
-    out[i].E1_sh_psf   = in[i].E1_sh_psf;
-    out[i].E2_sh_psf   = in[i].E2_sh_psf;
-
-    out[i].E1_psf      = in[i].E1_psf;
-    out[i].E2_psf      = in[i].E2_psf;
-
-    out[i].F_ApR5      = in[i].F_ApR5;
-    out[i].dF_ApR5     = in[i].dF_ApR5;
-    out[i].sF_ApR5     = in[i].sF_ApR5;
-    out[i].fF_ApR5     = in[i].fF_ApR5;
-	               	            
-    out[i].F_ApR6      = in[i].F_ApR6;
-    out[i].dF_ApR6     = in[i].dF_ApR6;
-    out[i].sF_ApR6     = in[i].sF_ApR6;
-    out[i].fF_ApR6     = in[i].fF_ApR6;
-	          	            
-    out[i].detID       = in[i].detID;
-    out[i].objID       = in[i].objID;
-    out[i].catID       = in[i].catID;
-    out[i].averef      = in[i].averef;
-
-    out[i].imageID     = in[i].imageID;
-  }
-  return (out);
-}
-
-Lensing_PS1_V5_R2 *LensingInternalTo_PS1_V5_R2 (Lensing *in, off_t Nvalues) {
-
-  off_t i;
-  Lensing_PS1_V5_R2 *out;
-
-  ALLOCATE_ZERO (out, Lensing_PS1_V5, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-
-    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
-    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
-    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
-    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
-    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
-	             	                 
-    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
-    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
-    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
-    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
-    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
-	             	                 
-    out[i].X11_sm_psf  = in[i].X11_sm_psf;
-    out[i].X12_sm_psf  = in[i].X12_sm_psf;
-    out[i].X22_sm_psf  = in[i].X22_sm_psf;
-    out[i].E1_sm_psf   = in[i].E1_sm_psf;
-    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
-	             	                 
-    out[i].X11_sh_psf  = in[i].X11_sh_psf;
-    out[i].X12_sh_psf  = in[i].X12_sh_psf;
-    out[i].X22_sh_psf  = in[i].X22_sh_psf;
-    out[i].E1_sh_psf   = in[i].E1_sh_psf;
-    out[i].E2_sh_psf   = in[i].E2_sh_psf;
-
-    out[i].E1_psf      = in[i].E1_psf;
-    out[i].E2_psf      = in[i].E2_psf;
-
-    out[i].F_ApR5      = in[i].F_ApR5;
-    out[i].dF_ApR5     = in[i].dF_ApR5;
-    out[i].sF_ApR5     = in[i].sF_ApR5;
-    out[i].fF_ApR5     = in[i].fF_ApR5;
-	               	            
-    out[i].F_ApR6      = in[i].F_ApR6;
-    out[i].dF_ApR6     = in[i].dF_ApR6;
-    out[i].sF_ApR6     = in[i].sF_ApR6;
-    out[i].fF_ApR6     = in[i].fF_ApR6;
-	          	            
-    out[i].detID       = in[i].detID;
-    out[i].objID       = in[i].objID;
-    out[i].catID       = in[i].catID;
-    out[i].averef      = in[i].averef;
-
-    out[i].imageID     = in[i].imageID;
-  }
-  return (out);
-}
-
-Lensobj *Lensobj_PS1_V5_ToInternal (Lensobj_PS1_V5 *in, off_t Nvalues) {
-
-  off_t i;
-  Lensobj *out;
-
-  ALLOCATE_ZERO (out, Lensobj, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    dvo_lensobj_init (&out[i], FALSE);
-
-    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
-    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
-    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
-    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
-    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
-	             	                 
-    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
-    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
-    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
-    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
-    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
-	             	                 
-    out[i].X11_sm_psf  = in[i].X11_sm_psf;
-    out[i].X12_sm_psf  = in[i].X12_sm_psf;
-    out[i].X22_sm_psf  = in[i].X22_sm_psf;
-    out[i].E1_sm_psf   = in[i].E1_sm_psf;
-    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
-	             	                 
-    out[i].X11_sh_psf  = in[i].X11_sh_psf;
-    out[i].X12_sh_psf  = in[i].X12_sh_psf;
-    out[i].X22_sh_psf  = in[i].X22_sh_psf;
-    out[i].E1_sh_psf   = in[i].E1_sh_psf;
-    out[i].E2_sh_psf   = in[i].E2_sh_psf;
-
-    out[i].F_ApR5      = in[i].F_ApR5;
-    out[i].dF_ApR5     = in[i].dF_ApR5;
-    out[i].sF_ApR5     = in[i].sF_ApR5;
-    out[i].fF_ApR5     = in[i].fF_ApR5;
-	               	            
-    out[i].F_ApR6      = in[i].F_ApR6;
-    out[i].dF_ApR6     = in[i].dF_ApR6;
-    out[i].sF_ApR6     = in[i].sF_ApR6;
-    out[i].fF_ApR6     = in[i].fF_ApR6;
-	          	            
-    out[i].gamma       = in[i].gamma;
-    out[i].E1          = in[i].E1;
-    out[i].E2          = in[i].E2;
-
-    out[i].objID       = in[i].objID;
-    out[i].catID       = in[i].catID;
-
-    out[i].photcode    = in[i].photcode;
-    out[i].Nmeas       = in[i].Nmeas;
-  }
-  return (out);
-}
-
-Lensobj_PS1_V5 *LensobjInternalTo_PS1_V5 (Lensobj *in, off_t Nvalues) {
-
-  off_t i;
-  Lensobj_PS1_V5 *out;
-
-  ALLOCATE_ZERO (out, Lensobj_PS1_V5, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-
-    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
-    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
-    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
-    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
-    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
-	             	                 
-    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
-    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
-    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
-    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
-    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
-	             	                 
-    out[i].X11_sm_psf  = in[i].X11_sm_psf;
-    out[i].X12_sm_psf  = in[i].X12_sm_psf;
-    out[i].X22_sm_psf  = in[i].X22_sm_psf;
-    out[i].E1_sm_psf   = in[i].E1_sm_psf;
-    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
-	             	                 
-    out[i].X11_sh_psf  = in[i].X11_sh_psf;
-    out[i].X12_sh_psf  = in[i].X12_sh_psf;
-    out[i].X22_sh_psf  = in[i].X22_sh_psf;
-    out[i].E1_sh_psf   = in[i].E1_sh_psf;
-    out[i].E2_sh_psf   = in[i].E2_sh_psf;
-
-    out[i].F_ApR5      = in[i].F_ApR5;
-    out[i].dF_ApR5     = in[i].dF_ApR5;
-    out[i].sF_ApR5     = in[i].sF_ApR5;
-    out[i].fF_ApR5     = in[i].fF_ApR5;
-	               	            
-    out[i].F_ApR6      = in[i].F_ApR6;
-    out[i].dF_ApR6     = in[i].dF_ApR6;
-    out[i].sF_ApR6     = in[i].sF_ApR6;
-    out[i].fF_ApR6     = in[i].fF_ApR6;
-	          	            
-    out[i].gamma       = in[i].gamma;
-    out[i].E1          = in[i].E1;
-    out[i].E2          = in[i].E2;
-
-    out[i].objID       = in[i].objID;
-    out[i].catID       = in[i].catID;
-
-    out[i].photcode    = in[i].photcode;
-    out[i].Nmeas       = in[i].Nmeas;
-  }
-  return (out);
-}
-
-StarPar *StarPar_PS1_V5_ToInternal (StarPar_PS1_V5 *in, off_t Nvalues) {
-
-  off_t i;
-  StarPar *out;
-
-  ALLOCATE_ZERO (out, StarPar, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    dvo_starpar_init (&out[i]);
-
-    out[i].R  	     = in[i].R;      
-    out[i].D  	     = in[i].D;      
-    out[i].galLat    = in[i].galLat;      
-    out[i].galLon    = in[i].galLon;      
-
-    out[i].Ebv       = in[i].Ebv     ;      
-    out[i].dEbv      = in[i].dEbv    ;      
-    out[i].DistMag   = in[i].DistMag ;      
-    out[i].dDistMag  = in[i].dDistMag;      
-    out[i].M_r       = in[i].M_r     ;      
-    out[i].dM_r      = in[i].dM_r    ;      
-    out[i].FeH       = in[i].FeH     ;      
-    out[i].dFeH      = in[i].dFeH    ;      
-    out[i].uRA       = in[i].uRA     ;      
-    out[i].uDEC      = in[i].uDEC    ;      
-
-    out[i].averef  = in[i].averef;
-    out[i].objID   = in[i].objID ;
-    out[i].catID   = in[i].catID ;
-  }
-  return (out);
-}
-
-StarPar_PS1_V5 *StarParInternalTo_PS1_V5 (StarPar *in, off_t Nvalues) {
-
-  off_t i;
-  StarPar_PS1_V5 *out;
-
-  ALLOCATE_ZERO (out, StarPar_PS1_V5, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-
-    out[i].R  	     = in[i].R;      
-    out[i].D  	     = in[i].D;      
-    out[i].galLat    = in[i].galLat;      
-    out[i].galLon    = in[i].galLon;      
-
-    out[i].Ebv       = in[i].Ebv     ;      
-    out[i].dEbv      = in[i].dEbv    ;      
-    out[i].DistMag   = in[i].DistMag ;      
-    out[i].dDistMag  = in[i].dDistMag;      
-    out[i].M_r       = in[i].M_r     ;      
-    out[i].dM_r      = in[i].dM_r    ;      
-    out[i].FeH       = in[i].FeH     ;      
-    out[i].dFeH      = in[i].dFeH    ;      
-    out[i].uRA       = in[i].uRA     ;      
-    out[i].uDEC      = in[i].uDEC    ;      
-
-    out[i].averef  = in[i].averef;
-    out[i].objID   = in[i].objID ;
-    out[i].catID   = in[i].catID ;
-  }
-  return (out);
-}
-
-# define RAW_IMAGE_NAME_LEN 117
-
-Image *Image_PS1_V5_ToInternal (Image_PS1_V5 *in, off_t Nvalues, off_t Nalloc) {
-
-  off_t i;
-  Image *out;
-
-  char *buffer;
-  ALLOCATE_ZERO (buffer, char, Nalloc);
-  out = (Image *) buffer;
-  // ALLOCATE_ZERO (out, Image, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    // this is only safe because the initial 120 bytes in Coords match CoordsDisk
-    memcpy (&out[i].coords, &in[i].coords, sizeof(CoordsDisk));
-    out[i].coords.mosaic   = NULL;
-    out[i].coords.offsetMap = NULL;
-
-    // RAW_IMAGE_NAME_LEN == DVO_IMAGE_NAME_LEN
-    strncpy (out[i].name, in[i].name, RAW_IMAGE_NAME_LEN - 1);
-    out[i].name[RAW_IMAGE_NAME_LEN - 1] = 0; // force termination
-
-    out[i].tzero    	    = in[i].tzero;
-    out[i].nstar    	    = in[i].nstar;
-    out[i].secz	    	    = in[i].secz;
-    out[i].NX	    	    = in[i].NX;
-    out[i].NY	    	    = in[i].NY;
-    out[i].apmifit  	    = in[i].apmifit;
-    out[i].dapmifit 	    = in[i].dapmifit;
-    out[i].Mcal	    	    = in[i].Mcal;
-    out[i].dMcal    	    = in[i].dMcal;
-    out[i].Xm	    	    = in[i].Xm;
-    out[i].photcode   	    = in[i].photcode;
-    out[i].exptime  	    = in[i].exptime;
-    out[i].sidtime  	    = in[i].sidtime;
-    out[i].latitude  	    = in[i].latitude;
-
-    out[i].RAo  	    = in[i].RAo;
-    out[i].DECo  	    = in[i].DECo;
-    out[i].Radius  	    = in[i].Radius;
-    out[i].refColorBlue	    = in[i].refColorBlue;
-    out[i].refColorRed 	    = in[i].refColorRed;
-
-    out[i].detection_limit  = in[i].detection_limit;
-    out[i].saturation_limit = in[i].saturation_limit;
-    out[i].cerror	    = in[i].cerror;
-    out[i].fwhm_x	    = in[i].fwhm_x;
-    out[i].fwhm_y	    = in[i].fwhm_y;
-    out[i].trate	    = in[i].trate;
-    out[i].ccdnum	    = in[i].ccdnum;
-    out[i].flags	    = in[i].flags;
-    out[i].imageID	    = in[i].imageID;
-    out[i].parentID	    = in[i].parentID;
-    out[i].externID	    = in[i].externID;
-    out[i].sourceID	    = in[i].sourceID;
-
-    // as of 2011.02.03, the old Mx,My,..., Mxxxx,Myyyy have been deprecated and replaced
-    // with the following.  (no real databases used those values -- see
-    // libdvo/doc/dvo-images.txt)
-    out[i].nLinkAstrom	    = in[i].nLinkAstrom;
-    out[i].nLinkPhotom	    = in[i].nLinkPhotom;
-    out[i].ubercalDist	    = in[i].ubercalDist;
-    out[i].dXpixSys	    = in[i].dXpixSys;
-    out[i].dYpixSys	    = in[i].dYpixSys;
-    out[i].dMagSys	    = in[i].dMagSys;
-    out[i].nFitAstrom       = in[i].nFitAstrom;
-    out[i].nFitPhotom       = in[i].nFitPhotom;
-    out[i].photom_map_id    = in[i].photom_map_id;
-    out[i].astrom_map_id    = in[i].astrom_map_id;
-  }
-  return (out);
-}
-
-Image_PS1_V5 *ImageInternalTo_PS1_V5 (Image *in, off_t Nvalues) {
-
-  off_t i;
-  Image_PS1_V5 *out;
-
-  ALLOCATE_ZERO (out, Image_PS1_V5, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    // this is only save because the initial 120 bytes in Coords match CoordsDisk
-    memcpy (&out[i].coords, &in[i].coords, sizeof(CoordsDisk));
-
-    // RAW_IMAGE_NAME_LEN == DVO_IMAGE_NAME_LEN
-    strncpy (out[i].name, in[i].name, RAW_IMAGE_NAME_LEN - 1);
-    out[i].name[RAW_IMAGE_NAME_LEN - 1] = 0; // force termination
-
-    out[i].tzero    	    = in[i].tzero;
-    out[i].nstar    	    = in[i].nstar;
-    out[i].secz	    	    = in[i].secz;
-    out[i].NX	    	    = in[i].NX;
-    out[i].NY	    	    = in[i].NY;
-    out[i].apmifit  	    = in[i].apmifit;
-    out[i].dapmifit 	    = in[i].dapmifit;
-    out[i].Mcal	    	    = in[i].Mcal;
-    out[i].dMcal    	    = in[i].dMcal;
-    out[i].Xm	    	    = in[i].Xm;
-    out[i].photcode   	    = in[i].photcode;
-    out[i].exptime  	    = in[i].exptime;
-    out[i].sidtime  	    = in[i].sidtime;
-    out[i].latitude  	    = in[i].latitude;
-
-    out[i].RAo  	    = in[i].RAo;
-    out[i].DECo  	    = in[i].DECo;
-    out[i].Radius  	    = in[i].Radius;
-    out[i].refColorBlue	    = in[i].refColorBlue;
-    out[i].refColorRed 	    = in[i].refColorRed;
-
-    out[i].detection_limit  = in[i].detection_limit;
-    out[i].saturation_limit = in[i].saturation_limit;
-    out[i].cerror	    = in[i].cerror;
-    out[i].fwhm_x	    = in[i].fwhm_x;
-    out[i].fwhm_y	    = in[i].fwhm_y;
-    out[i].trate	    = in[i].trate;
-    out[i].ccdnum	    = in[i].ccdnum;
-    out[i].flags	    = in[i].flags;
-    out[i].imageID	    = in[i].imageID;
-    out[i].parentID	    = in[i].parentID;
-    out[i].externID	    = in[i].externID;
-    out[i].sourceID	    = in[i].sourceID;
-
-    // as of 2011.02.03, the old Mx,My,..., Mxxxx,Myyyy have been deprecated and replaced
-    // with the following.  (no real databases used those values -- see
-    // libdvo/doc/dvo-images.txt)
-    out[i].nLinkAstrom	    = in[i].nLinkAstrom;
-    out[i].nLinkPhotom	    = in[i].nLinkPhotom;
-    out[i].ubercalDist	    = in[i].ubercalDist;
-    out[i].dXpixSys	    = in[i].dXpixSys;
-    out[i].dYpixSys	    = in[i].dYpixSys;
-    out[i].dMagSys	    = in[i].dMagSys;
-    out[i].nFitAstrom       = in[i].nFitAstrom;
-    out[i].nFitPhotom       = in[i].nFitPhotom;
-    out[i].photom_map_id    = in[i].photom_map_id;
-    out[i].astrom_map_id    = in[i].astrom_map_id;
-  }
-  return (out);
-}
-
-PhotCode *PhotCode_PS1_V5_To_Internal (PhotCode_PS1_V5 *in, off_t Nvalues) {
-
-  off_t i;
-  PhotCode *out;
-
-  ALLOCATE_ZERO (out, PhotCode, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
-    out[i].name[31] = 0; // force termination
-
-    out[i].code  = in[i].code;         
-    out[i].type  = in[i].type;         
-    out[i].C     = in[i].C;            
-    out[i].dC 	 = in[i].dC;           
-    out[i].dX 	 = in[i].dX;           
-    out[i].K  	 = in[i].K;            
-    out[i].c1 	 = in[i].c1;           
-    out[i].c2 	 = in[i].c2;           
-    out[i].equiv = in[i].equiv;        
-    out[i].Nc    = in[i].Nc;           
-    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
-
-    out[i].astromErrSys      = in[i].astromErrSys;
-    out[i].astromErrScale    = in[i].astromErrScale;
-    out[i].astromErrMagScale = in[i].astromErrMagScale;
-    out[i].photomErrSys      = in[i].photomErrSys;
-
-    out[i].photomPoorMask      = in[i].photomPoorMask;
-    out[i].photomBadMask       = in[i].photomBadMask;
-    out[i].astromPoorMask      = in[i].astromPoorMask;
-    out[i].astromBadMask       = in[i].astromBadMask;
-  }
-  return (out);
-}
-
-PhotCode_PS1_V5 *PhotCode_Internal_To_PS1_V5 (PhotCode *in, off_t Nvalues) {
-
-  off_t i;
-  PhotCode_PS1_V5 *out;
-
-  ALLOCATE_ZERO (out, PhotCode_PS1_V5, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
-    out[i].name[31] = 0; // force termination
-
-    out[i].code  = in[i].code;         
-    out[i].type  = in[i].type;         
-    out[i].C     = in[i].C;            
-    out[i].dC 	 = in[i].dC;           
-    out[i].dX 	 = in[i].dX;           
-    out[i].K  	 = in[i].K;            
-    out[i].c1 	 = in[i].c1;           
-    out[i].c2 	 = in[i].c2;           
-    out[i].equiv = in[i].equiv;        
-    out[i].Nc    = in[i].Nc;           
-    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
-
-    out[i].astromErrSys      = in[i].astromErrSys;
-    out[i].astromErrScale    = in[i].astromErrScale;
-    out[i].astromErrMagScale = in[i].astromErrMagScale;
-    out[i].photomErrSys      = in[i].photomErrSys;
-
-    out[i].photomPoorMask      = in[i].photomPoorMask;
-    out[i].photomBadMask       = in[i].photomBadMask;
-    out[i].astromPoorMask      = in[i].astromPoorMask;
-    out[i].astromBadMask       = in[i].astromBadMask;
-  }
-  return (out);
-}
-
-/*********************** old / alternate version **********************/
-
-// 'primary' is needed to conform with the API for Loneos and Elixir, but is not used
-Average *Average_PS1_V5alt_ToInternal (Average_PS1_V5alt *in, off_t Nvalues) {
-
-  off_t i;
-  Average *out;
-
-  ALLOCATE_ZERO (out, Average, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    dvo_average_init (&out[i]);
-
-    out[i].R        	  = in[i].R;      
-    out[i].D        	  = in[i].D;      
-    out[i].dR       	  = in[i].dR;
-    out[i].dD       	  = in[i].dD;
-    out[i].uR       	  = in[i].uR;
-    out[i].uD       	  = in[i].uD;
-    out[i].duR      	  = in[i].duR;
-    out[i].duD      	  = in[i].duD;
-    out[i].P        	  = in[i].P;
-    out[i].dP       	  = in[i].dP;
-			  
-    out[i].Rstk        	  = in[i].Rstk;      
-    out[i].Dstk        	  = in[i].Dstk;      
-    out[i].dRstk       	  = in[i].dRstk;
-    out[i].dDstk       	  = in[i].dDstk;
-			  
-    out[i].ChiSqAve    	  = in[i].ChiSqAve;     
-    out[i].ChiSqPM    	  = in[i].ChiSqPM;     
-    out[i].ChiSqPar    	  = in[i].ChiSqPar;     
-    out[i].Tmean    	  = in[i].Tmean;     
-    out[i].Trange   	  = in[i].Trange;     
-			  
-    out[i].psfQF          = in[i].psfQF;
-    out[i].psfQFperf      = in[i].psfQFperf;
-    out[i].stargal     	  = in[i].stargal;     
-    out[i].Npos       	  = in[i].Npos;     
-			  
-    out[i].Nmeasure       = in[i].Nmeasure;     
-    out[i].Nmissing       = in[i].Nmissing;     
-    out[i].Nlensing       = in[i].Nlensing;     
-    out[i].Nlensobj       = in[i].Nlensobj;     
-    out[i].Nextend        = in[i].Nextend;     
-			  
-    out[i].measureOffset  = in[i].measureOffset; 
-    out[i].missingOffset  = in[i].missingOffset;
-    out[i].lensingOffset  = in[i].lensingOffset;
-    out[i].lensobjOffset  = in[i].lensobjOffset;
-    out[i].starparOffset  = in[i].starparOffset;
-    out[i].extendOffset   = in[i].extendOffset;
-			  
-    out[i].refColorBlue   = in[i].refColorBlue;
-    out[i].refColorRed    = in[i].refColorRed;
-			  
-    out[i].flags     	  = in[i].flags;   
-    out[i].photFlagsUpper = in[i].photFlagsUpper;   
-    out[i].photFlagsLower = in[i].photFlagsLower;   
-    out[i].objID 	  = in[i].objID;
-    out[i].catID 	  = in[i].catID;
-    out[i].extID 	  = in[i].extID;
-    out[i].extIDgc 	  = in[i].extIDgc;
-  }
-  return (out);
-}
-
-int gfits_convert_Average_PS1_V5alt (Average_PS1_V5alt *data, off_t size, off_t nitems) {
+int gfits_convert_Measure_PS1_V5alt (Measure_PS1_V5alt *data, off_t size, off_t nitems) {
 
   off_t i;
   unsigned char *byte, tmp;
 
-  if (size != 184) { 
-    fprintf (stderr, "WARNING: mismatch in data types Average_PS1_V5alt: "OFF_T_FMT" vs %d\n",  size,  184);
+  if (size != 232) { 
+    fprintf (stderr, "WARNING: mismatch in data types Measure_PS1_V5alt: "OFF_T_FMT" vs %d\n",  size,  232);
     return (FALSE);
   }
@@ -1029,49 +1471,67 @@
 # ifdef BYTE_SWAP
   byte = (unsigned char *) data;
-  for (i = 0; i < nitems; i++, byte += 184) {
+  for (i = 0; i < nitems; i++, byte += 232) {
     /** BYTE SWAP **/
     SWAP_DBLE (0); // RA
     SWAP_DBLE (8); // DEC
-    SWAP_WORD (16); // RA_ERR
-    SWAP_WORD (20); // DEC_ERR
-    SWAP_WORD (24); // U_RA
-    SWAP_WORD (28); // U_DEC
-    SWAP_WORD (32); // V_RA_ERR
-    SWAP_WORD (36); // V_DEC_ERR
-    SWAP_WORD (40); // PAR
-    SWAP_WORD (44); // PAR_ERR
-    SWAP_DBLE (48); // RA_STK
-    SWAP_DBLE (56); // DEC_STK
-    SWAP_WORD (64); // RA_STK_ERR
-    SWAP_WORD (68); // DEC_STK_ERR
-    SWAP_WORD (72); // CHISQ_POS
-    SWAP_WORD (76); // CHISQ_PM
-    SWAP_WORD (80); // CHISQ_PAP
-    SWAP_WORD (84); // MEAN_EPOCH
-    SWAP_WORD (88); // TIME_RANGE
-    SWAP_WORD (92); // PSF_QF
-    SWAP_WORD (96); // PSF_QF_PERF
-    SWAP_WORD (100); // STARGAL_SEP
-    SWAP_BYTE (104); // NUMBER_POS
-    SWAP_BYTE (106); // NMEASURE
-    SWAP_BYTE (108); // NMISSING
-    SWAP_BYTE (110); // NLENSING
-    SWAP_BYTE (112); // NLENSOBJ
-    SWAP_BYTE (114); // NEXTEND
-    SWAP_WORD (116); // OFF_MEASURE
-    SWAP_WORD (120); // OFF_MISSING
-    SWAP_WORD (124); // OFF_LENSING
-    SWAP_WORD (128); // OFF_LENSOBJ
-    SWAP_WORD (132); // OFF_EXTEND
-    SWAP_WORD (136); // OFF_PARAMS
-    SWAP_WORD (140); // REF_COLOR_BLUE
-    SWAP_WORD (144); // REF_COLOR_RED
-    SWAP_WORD (148); // FLAGS
-    SWAP_WORD (152); // PHOTFLAGS_U
-    SWAP_WORD (156); // PHOTFLAGS_L
-    SWAP_WORD (160); // OBJ_ID
-    SWAP_WORD (164); // CAT_ID
-    SWAP_DBLE (168); // EXT_ID
-    SWAP_DBLE (176); // EXT_ID_GC
+    SWAP_WORD (16); // MAG
+    SWAP_WORD (20); // MAG_ERR
+    SWAP_WORD (24); // M_APER
+    SWAP_WORD (28); // M_APER_ERR
+    SWAP_WORD (32); // M_KRON
+    SWAP_WORD (36); // M_KRON_ERR
+    SWAP_WORD (40); // M_CAL
+    SWAP_WORD (44); // MAG_CAL_ERR
+    SWAP_WORD (48); // M_TIME
+    SWAP_WORD (52); // FLUX_PSF
+    SWAP_WORD (56); // FLUX_PSF_ERR
+    SWAP_WORD (60); // FLUX_KRON
+    SWAP_WORD (64); // FLUX_KRON_ERR
+    SWAP_WORD (68); // FLUX_AP
+    SWAP_WORD (72); // FLUX_AP_ERR
+    SWAP_WORD (76); // AIRMASS
+    SWAP_WORD (80); // AZ
+    SWAP_WORD (84); // X_CCD
+    SWAP_WORD (88); // Y_CCD
+    SWAP_WORD (92); // X_FIX
+    SWAP_WORD (96); // Y_FIX
+    SWAP_WORD (100); // X_OFF_KH
+    SWAP_WORD (104); // Y_OFF_KH
+    SWAP_WORD (108); // X_OFF_DCR
+    SWAP_WORD (112); // Y_OFF_DCR
+    SWAP_WORD (116); // R_OFF_GAL
+    SWAP_WORD (120); // D_OFF_GAL
+    SWAP_WORD (124); // SKY_FLUX
+    SWAP_WORD (128); // SKY_FLUX_ERR
+    SWAP_WORD (132); // TIME
+    SWAP_WORD (136); // AVE_REF
+    SWAP_WORD (140); // DET_ID
+    SWAP_WORD (144); // OBJ_ID
+    SWAP_WORD (148); // CAT_ID
+    SWAP_DBLE (152); // EXT_ID
+    SWAP_WORD (160); // IMAGE_ID
+    SWAP_WORD (164); // PSF_QF
+    SWAP_WORD (168); // PSF_QF_PEFECT
+    SWAP_WORD (172); // PSF_CHISQ
+    SWAP_WORD (176); // PSF_NDOF
+    SWAP_WORD (180); // PSF_NPIX
+    SWAP_WORD (184); // PHOT_FLAGS
+    SWAP_WORD (188); // EXT_NSIGMA
+    SWAP_BYTE (192); // FWHM_MAJOR
+    SWAP_BYTE (194); // FWHM_MINOR
+    SWAP_BYTE (196); // PSF_THETA
+    SWAP_BYTE (198); // MXX
+    SWAP_BYTE (200); // MXY
+    SWAP_BYTE (202); // MYY
+    SWAP_BYTE (204); // TIME_MSEC
+    SWAP_BYTE (206); // PHOTCODE
+    SWAP_BYTE (208); // X_CCD_ERR
+    SWAP_BYTE (210); // Y_CCD_ERR
+    SWAP_BYTE (212); // POS_SYS_ERR
+    SWAP_BYTE (214); // POSANGLE
+    SWAP_WORD (216); // PLTSCALE
+    SWAP_WORD (220); // DB_FLAGS
+    SWAP_WORD (224); // PHOT_FLAGS
+    SWAP_WORD (228); // PADDING
   }
 # endif  
@@ -1080,21 +1540,20 @@
 } 
 
-/*** add test of EXTNAME and header-defined columns? ***/
 /* return internal structure representation */
-Average_PS1_V5alt *gfits_table_get_Average_PS1_V5alt (FTable *ftable, off_t *Ndata, char *swapped) {
+Measure_PS1_V5alt *gfits_table_get_Measure_PS1_V5alt (FTable *ftable, off_t *Ndata, char *swapped) {
 
   int Ncols;
-  Average_PS1_V5alt *data;
+  Measure_PS1_V5alt *data;
 
   Ncols = ftable[0].header[0].Naxis[0];
-  if (Ncols != 184) {
-    fprintf (stderr, "ERROR: mis-match in table size: width is %d but should be %d bytes\n", Ncols, 184);
+  if (Ncols != 232) {
+    fprintf (stderr, "ERROR: mis-match in table size: width is %d but should be %d bytes\n", Ncols, 232);
     return NULL;
   }
 
   *Ndata = ftable[0].header[0].Naxis[1];
-  data = (Average_PS1_V5alt *) ftable[0].buffer;
+  data = (Measure_PS1_V5alt *) ftable[0].buffer;
   if ((swapped == NULL) || (*swapped == FALSE)) {
-    if (!gfits_convert_Average_PS1_V5alt (data, sizeof (Average_PS1_V5alt), *Ndata)) {
+    if (!gfits_convert_Measure_PS1_V5alt (data, sizeof (Measure_PS1_V5alt), *Ndata)) {
       return NULL;
     }
@@ -1105,272 +1564,3 @@
 }
 
-/****** alt secfilt **********/
-
-SecFilt *SecFilt_PS1_V5alt_ToInternal (SecFilt_PS1_V5alt *in, off_t Nvalues) {
-
-  off_t i;
-  SecFilt *out;
-
-  ALLOCATE_ZERO (out, SecFilt, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    dvo_secfilt_init (&out[i]);
-
-    out[i].M             = in[i].M;      
-    out[i].dM            = in[i].dM;      
-    out[i].Map           = in[i].Map;      
-    out[i].dMap          = in[i].dMap;      
-    out[i].sMap          = in[i].sMap;      
-    out[i].Mkron         = in[i].Mkron;      
-    out[i].dMkron        = in[i].dMkron;      
-
-    out[i].Mstdev        = in[i].Mstdev;      
-    out[i].Mmin          = in[i].Mmin;      
-    out[i].Mmax          = in[i].Mmax;      
-    out[i].Mchisq        = in[i].Mchisq;     
-
-    out[i].Ncode         = in[i].Ncode;
-    out[i].Nused         = in[i].Nused;
-    out[i].NusedKron     = in[i].NusedKron;
-    out[i].NusedAp       = in[i].NusedAp;
-
-    out[i].flags         = in[i].flags;     
-
-    out[i].MpsfStk       = in[i].MpsfStk;
-    out[i].FpsfStk       = in[i].FpsfStk;
-    out[i].dFpsfStk      = in[i].dFpsfStk;
-
-    out[i].MkronStk      = in[i].MkronStk;
-    out[i].FkronStk      = in[i].FkronStk;
-    out[i].dFkronStk     = in[i].dFkronStk;
-
-    out[i].MapStk        = in[i].MapStk;
-    out[i].FapStk        = in[i].FapStk;
-    out[i].dFapStk       = in[i].dFapStk;
-
-    out[i].stackPrmryOff = in[i].stackPrmryOff;      
-    out[i].stackBestOff  = in[i].stackBestOff;      
-
-    out[i].MpsfWrp       = in[i].MpsfWrp;
-    out[i].FpsfWrp       = in[i].FpsfWrp;
-    out[i].dFpsfWrp      = in[i].dFpsfWrp;
-    out[i].sFpsfWrp      = in[i].sFpsfWrp;
-
-    out[i].MkronWrp      = in[i].MkronWrp;
-    out[i].FkronWrp      = in[i].FkronWrp;
-    out[i].dFkronWrp     = in[i].dFkronWrp;
-    out[i].sFkronWrp     = in[i].sFkronWrp;
-
-    out[i].MapWrp        = in[i].MapWrp;
-    out[i].FapWrp        = in[i].FapWrp;
-    out[i].dFapWrp       = in[i].dFapWrp;
-    out[i].sFapWrp       = in[i].sFapWrp;
-
-    out[i].NusedWrp      = in[i].NusedWrp;
-    out[i].NusedKronWrp  = in[i].NusedKronWrp;
-    out[i].NusedApWrp    = in[i].NusedApWrp;
-
-    out[i].ubercalDist   = in[i].ubercalDist;      
-  }
-  return (out);
-}
-
-int gfits_convert_SecFilt_PS1_V5alt (SecFilt_PS1_V5alt *data, off_t size, off_t nitems) {
-
-  off_t i;
-  unsigned char *byte, tmp;
-
-  if (size != 160) { 
-    fprintf (stderr, "WARNING: mismatch in data types SecFilt_PS1_V5alt: "OFF_T_FMT" vs %d\n",  size,  160);
-    return (FALSE);
-  }
-
-  /* provide initial values to avoid compiler warnings for non-BYTE_SWAP arch */
-  i = tmp = 0;
-  byte = NULL;
-
-# ifdef BYTE_SWAP
-  byte = (unsigned char *) data;
-  for (i = 0; i < nitems; i++, byte += 160) {
-    /** BYTE SWAP **/
-    SWAP_WORD (0); // MAG
-    SWAP_WORD (4); // MAG_ERR
-    SWAP_WORD (8); // MAG_AP
-    SWAP_WORD (12); // MAG_AP_ERR
-    SWAP_WORD (16); // MAG_AP_STDEV
-    SWAP_WORD (20); // MAG_KRON
-    SWAP_WORD (24); // MAG_KRON_ERR
-    SWAP_WORD (28); // MAG_KRON_STDEV
-    SWAP_WORD (32); // MAG_STDEV
-    SWAP_WORD (36); // MAG_MIN
-    SWAP_WORD (40); // MAG_MAX
-    SWAP_WORD (44); // MAG_CHI
-    SWAP_BYTE (48); // NCODE
-    SWAP_BYTE (50); // NUSED
-    SWAP_BYTE (52); // NUSED_KRON
-    SWAP_BYTE (54); // NUSED_AP
-    SWAP_WORD (56); // FLAGS
-    SWAP_WORD (60); // MAG_PSF_STK
-    SWAP_WORD (64); // FLUX_PSF_STK
-    SWAP_WORD (68); // FLUX_PSF_STK_ERR
-    SWAP_WORD (72); // MAG_KRON_STK
-    SWAP_WORD (76); // FLUX_KRON_STK
-    SWAP_WORD (80); // FLUX_KRON_STK_ERR
-    SWAP_WORD (84); // MAG_AP_STK
-    SWAP_WORD (88); // FLUX_AP_STK
-    SWAP_WORD (92); // FLUX_AP_STK_ERR
-    SWAP_WORD (96); // STACK_PRIMARY_OFF
-    SWAP_WORD (100); // STACK_BEST_OFF
-    SWAP_WORD (104); // MAG_PSF_WRP
-    SWAP_WORD (108); // FLUX_PSF_WRP
-    SWAP_WORD (112); // FLUX_PSF_WRP_ERR
-    SWAP_WORD (116); // FLUX_PSF_WRP_STD
-    SWAP_WORD (120); // MAG_KRON_WRP
-    SWAP_WORD (124); // FLUX_KRON_WRP
-    SWAP_WORD (128); // FLUX_KRON_WRP_ERR
-    SWAP_WORD (132); // FLUX_KRON_WRP_STD
-    SWAP_WORD (136); // MAG_AP_WRP
-    SWAP_WORD (140); // FLUX_AP_WRP
-    SWAP_WORD (144); // FLUX_AP_WRP_ERR
-    SWAP_WORD (148); // FLUX_AP_WRP_STD
-    SWAP_BYTE (152); // NUSED_WRP
-    SWAP_BYTE (154); // NUSED_KRON_WRP
-    SWAP_BYTE (156); // NUSED_AP_WRP
-    SWAP_BYTE (158); // UBERCAL_DIST
-  }
-# endif  
-
-  return (TRUE);
-} 
-
-/*** add test of EXTNAME and header-defined columns? ***/
-/* return internal structure representation */
-SecFilt_PS1_V5alt *gfits_table_get_SecFilt_PS1_V5alt (FTable *ftable, off_t *Ndata, char *swapped) {
-
-  int Ncols;
-  SecFilt_PS1_V5alt *data;
-
-  Ncols = ftable[0].header[0].Naxis[0];
-  if (Ncols != 160) {
-    fprintf (stderr, "ERROR: mis-match in table size: width is %d but should be %d bytes\n", Ncols, 160);
-    return NULL;
-  }
-
-  *Ndata = ftable[0].header[0].Naxis[1];
-  data = (SecFilt_PS1_V5alt *) ftable[0].buffer;
-  if ((swapped == NULL) || (*swapped == FALSE)) {
-    if (!gfits_convert_SecFilt_PS1_V5alt (data, sizeof (SecFilt_PS1_V5alt), *Ndata)) {
-      return NULL;
-    }
-    gfits_table_scale_data (ftable);
-    if (swapped != NULL) *swapped = TRUE;
-  }
-  return (data);
-}
-
-Lensing *Lensing_PS1_V5_R0_ToInternal (Lensing_PS1_V5_R0 *in, off_t Nvalues) {
-
-  off_t i;
-  Lensing *out;
-
-  ALLOCATE_ZERO (out, Lensing, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    dvo_lensing_init (&out[i]);
-
-    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
-    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
-    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
-    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
-    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
-	             	                 
-    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
-    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
-    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
-    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
-    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
-	             	                 
-    out[i].X11_sm_psf  = in[i].X11_sm_psf;
-    out[i].X12_sm_psf  = in[i].X12_sm_psf;
-    out[i].X22_sm_psf  = in[i].X22_sm_psf;
-    out[i].E1_sm_psf   = in[i].E1_sm_psf;
-    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
-	             	                 
-    out[i].X11_sh_psf  = in[i].X11_sh_psf;
-    out[i].X12_sh_psf  = in[i].X12_sh_psf;
-    out[i].X22_sh_psf  = in[i].X22_sh_psf;
-    out[i].E1_sh_psf   = in[i].E1_sh_psf;
-    out[i].E2_sh_psf   = in[i].E2_sh_psf;
-
-    out[i].F_ApR5      = in[i].F_ApR5;
-    out[i].dF_ApR5     = in[i].dF_ApR5;
-    out[i].sF_ApR5     = in[i].sF_ApR5;
-    out[i].fF_ApR5     = in[i].fF_ApR5;
-	               	            
-    out[i].F_ApR6      = in[i].F_ApR6;
-    out[i].dF_ApR6     = in[i].dF_ApR6;
-    out[i].sF_ApR6     = in[i].sF_ApR6;
-    out[i].fF_ApR6     = in[i].fF_ApR6;
-	          	            
-    out[i].detID       = in[i].detID;
-    out[i].objID       = in[i].objID;
-    out[i].catID       = in[i].catID;
-    out[i].averef      = in[i].averef;
-  }
-  return (out);
-}
-
-Lensing *Lensing_PS1_V5_R1_ToInternal (Lensing_PS1_V5_R1 *in, off_t Nvalues) {
-
-  off_t i;
-  Lensing *out;
-
-  ALLOCATE_ZERO (out, Lensing, Nvalues);
-
-  for (i = 0; i < Nvalues; i++) {
-    dvo_lensing_init (&out[i]);
-
-    out[i].X11_sm_obj  = in[i].X11_sm_obj;      
-    out[i].X12_sm_obj  = in[i].X12_sm_obj;      
-    out[i].X22_sm_obj  = in[i].X22_sm_obj;      
-    out[i].E1_sm_obj   = in[i].E1_sm_obj;      
-    out[i].E2_sm_obj   = in[i].E2_sm_obj;      
-	             	                 
-    out[i].X11_sh_obj  = in[i].X11_sh_obj;      
-    out[i].X12_sh_obj  = in[i].X12_sh_obj;      
-    out[i].X22_sh_obj  = in[i].X22_sh_obj;      
-    out[i].E1_sh_obj   = in[i].E1_sh_obj;      
-    out[i].E2_sh_obj   = in[i].E2_sh_obj;     
-	             	                 
-    out[i].X11_sm_psf  = in[i].X11_sm_psf;
-    out[i].X12_sm_psf  = in[i].X12_sm_psf;
-    out[i].X22_sm_psf  = in[i].X22_sm_psf;
-    out[i].E1_sm_psf   = in[i].E1_sm_psf;
-    out[i].E2_sm_psf   = in[i].E2_sm_psf;     
-	             	                 
-    out[i].X11_sh_psf  = in[i].X11_sh_psf;
-    out[i].X12_sh_psf  = in[i].X12_sh_psf;
-    out[i].X22_sh_psf  = in[i].X22_sh_psf;
-    out[i].E1_sh_psf   = in[i].E1_sh_psf;
-    out[i].E2_sh_psf   = in[i].E2_sh_psf;
-
-    out[i].F_ApR5      = in[i].F_ApR5;
-    out[i].dF_ApR5     = in[i].dF_ApR5;
-    out[i].sF_ApR5     = in[i].sF_ApR5;
-    out[i].fF_ApR5     = in[i].fF_ApR5;
-	               	            
-    out[i].F_ApR6      = in[i].F_ApR6;
-    out[i].dF_ApR6     = in[i].dF_ApR6;
-    out[i].sF_ApR6     = in[i].sF_ApR6;
-    out[i].fF_ApR6     = in[i].fF_ApR6;
-	          	            
-    out[i].detID       = in[i].detID;
-    out[i].objID       = in[i].objID;
-    out[i].catID       = in[i].catID;
-    out[i].averef      = in[i].averef;
-
-    out[i].imageID     = in[i].imageID;
-  }
-  return (out);
-}
-
+
Index: /trunk/Ohana/src/libdvo/src/dvo_tiny_values.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_tiny_values.c	(revision 38061)
+++ /trunk/Ohana/src/libdvo/src/dvo_tiny_values.c	(revision 38062)
@@ -2,4 +2,5 @@
 
 void CopyAverageToTiny (AverageTiny *averageT, Average *average) {
+  memset (averageT, 0, sizeof(AverageTiny));
   averageT[0].R     	    = average[0].R;
   averageT[0].D     	    = average[0].D;
@@ -14,4 +15,5 @@
 
 void CopyMeasureToTiny (MeasureTiny *measureT, Measure *measure) {
+  memset (measureT, 0, sizeof(MeasureTiny));
   measureT[0].R          = measure[0].R;
   measureT[0].D          = measure[0].D;
Index: /trunk/Ohana/src/libfits/include/gfitsio.h
===================================================================
--- /trunk/Ohana/src/libfits/include/gfitsio.h	(revision 38061)
+++ /trunk/Ohana/src/libfits/include/gfitsio.h	(revision 38062)
@@ -147,4 +147,5 @@
 
 int     gfits_init_matrix              PROTO((Matrix *matrix));
+off_t   gfits_npix_matrix              PROTO((Matrix *matrix));
 void   	gfits_add_matrix_value         PROTO((Matrix *matrix, off_t x, off_t y, double value)); 
 int    	gfits_convert_format           PROTO((Header *header, Matrix *matrix, int outBitpix, double outScale, double outZero, int inBlank, int outUnsign));
Index: /trunk/Ohana/src/libfits/matrix/F_convert_format.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_convert_format.c	(revision 38061)
+++ /trunk/Ohana/src/libfits/matrix/F_convert_format.c	(revision 38062)
@@ -90,7 +90,8 @@
 
 /*********************** fits convert format ***********************************/
+/* this function is safe in the number of axes (can even be 0) */
 int gfits_convert_format (Header *header, Matrix *matrix, int outBitpix, double outScale, double outZero, int inBlank, int outUnsign) {
 
-  unsigned long i, nbytes, Npixels;
+  off_t i, nbytes;
   int    inBitpix, inUnsign;
   double inScale, inZero;
@@ -116,6 +117,6 @@
   gfits_modify_alt (header, "UNSIGN", "%t", 1, outUnsign);
 
-  Npixels          = header[0].Naxis[0]*header[0].Naxis[1];
-  nbytes           = Npixels * (abs(outBitpix) / 8);
+  off_t Npixels = gfits_npix_matrix (matrix);
+  nbytes                = Npixels * (abs(outBitpix) / 8);
 
   A = inScale / outScale;
Index: /trunk/Ohana/src/libfits/matrix/F_create_M.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_create_M.c	(revision 38061)
+++ /trunk/Ohana/src/libfits/matrix/F_create_M.c	(revision 38062)
@@ -43,3 +43,15 @@
 }
 
-// XXX free buffer if non-null: need to double check for existing frees
+/*********************** return number of valid pixels *******************************/
+off_t gfits_npix_matrix (Matrix *matrix) {
+
+  if (!matrix->Naxes) return 0;
+
+  int i;
+  int Npix = 1;
+  for (i = 0; i < matrix->Naxes; i++) {
+    if (matrix->Naxis[i] == 0) break;
+    Npix *= matrix->Naxis[i];
+  }
+  return Npix;
+}
Index: /trunk/Ohana/src/libohana/src/config.c
===================================================================
--- /trunk/Ohana/src/libohana/src/config.c	(revision 38061)
+++ /trunk/Ohana/src/libohana/src/config.c	(revision 38062)
@@ -146,4 +146,5 @@
   NBYTES = D_NBYTES;
   ALLOCATE (ibuffer, char, NBYTES + 2);
+  memset (ibuffer, 0, NBYTES + 2);
     
   /* load data from file */
Index: /trunk/Ohana/src/libohana/src/findexec.c
===================================================================
--- /trunk/Ohana/src/libohana/src/findexec.c	(revision 38061)
+++ /trunk/Ohana/src/libohana/src/findexec.c	(revision 38062)
@@ -429,4 +429,6 @@
   ALLOCATE (newpath, char, Nbytes);
   snprintf (newpath, Nbytes, "%s/%s", cwd, oldpath);
+
+  real_free (cwd);
   return newpath;
 }
Index: /trunk/Ohana/src/opihi/cmd.astro/Makefile
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/Makefile	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.astro/Makefile	(revision 38062)
@@ -29,4 +29,5 @@
 $(SRC)/czplot.$(ARCH).o	   \
 $(SRC)/cdensify.$(ARCH).o	   \
+$(SRC)/cdhistogram.$(ARCH).o	   \
 $(SRC)/drizzle.$(ARCH).o	   \
 $(SRC)/flux.$(ARCH).o		   \
Index: /trunk/Ohana/src/opihi/cmd.astro/cdensify.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/cdensify.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.astro/cdensify.c	(revision 38062)
@@ -111,8 +111,4 @@
     switch (PSFTYPE) {
       case IS_DOT:
-	RD_to_XY (&x, &y, rn, *d, &graphmode.coords);
-	Xb = (x - Xmin) / dX;
-	Yb = (y - Ymin) / dY;
-
 	RD_to_XY (&x, &y, rn, *d, &newcoords);
 	Xb = (int) x;
Index: /trunk/Ohana/src/opihi/cmd.astro/cdhistogram.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/cdhistogram.c	(revision 38062)
+++ /trunk/Ohana/src/opihi/cmd.astro/cdhistogram.c	(revision 38062)
@@ -0,0 +1,135 @@
+# include "data.h"
+
+# define CHECKVAL(ARG) if (!isfinite(ARG)) { gprint (GP_ERR, "illegal value for %s: %f\n", #ARG, ARG); return (FALSE); }
+
+int cdhistogram (int argc, char **argv) {
+
+  int i, Nz, N, Xpix, Ypix;
+  double Xmin, Xmax, dX, Ymin, Ymax, dY;
+  float *val;
+  Buffer *bf;
+  Vector *vr, *vd, *vz, *range;
+  opihi_flt *r, *d, *z, x, y;
+  int kapa;
+  Graphdata graphmode;
+
+  range = NULL;
+  if ((N = get_argument (argc, argv, "-range"))) {
+    remove_argument (N, &argc, argv);
+    if ((range = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+  double Rmin = graphmode.coords.crval1 - 182.0;
+  double Rmax = graphmode.coords.crval1 + 182.0;
+
+  float dZ = NAN;
+  if ((N = get_argument (argc, argv, "-delta"))) {
+    remove_argument (N, &argc, argv);
+    dZ = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: cdhistogram buffer R D value (min) (max) [-delta dval]\n");
+    gprint (GP_ERR, " output buffer is 3D\n");
+    return (FALSE);
+  }
+  
+  if ((bf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vr = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vd = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vz = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (vr[0].Nelements != vd[0].Nelements) return (FALSE);
+  if (vr[0].Nelements != vz[0].Nelements) return (FALSE);
+
+  float Zmin = atof(argv[5]);
+  float Zmax = atof(argv[6]);
+  if (!isfinite(dZ)) {
+    Nz = 100;
+    dZ = (Zmax - Zmin) / (Nz - 1);
+  } else {
+    Nz = (Zmax - Zmin) / dZ + 1;
+  }
+  if (dZ < 0) {
+    gprint (GP_ERR, "invalid value for delta: %f\n", dZ);
+    return (FALSE);
+  }
+  if (Nz > 1000) {
+    gprint (GP_ERR, "warning: delta of %f will result in %d histogram bins\n", dZ, Nz);
+    return (FALSE);
+  }
+
+  if (range) {
+    ResetVector (range, OPIHI_FLT, Nz);
+    for (i = 0; i < range[0].Nelements; i++) {
+      range[0].elements.Flt[i] = Zmin + i*dZ;
+    }
+  }
+
+  REQUIRE_VECTOR_FLT (vr, FALSE); 
+  REQUIRE_VECTOR_FLT (vd, FALSE); 
+  REQUIRE_VECTOR_FLT (vz, FALSE); 
+
+  KapaGetImageRange (kapa, &Xmin, &Xmax, &Ymax, &Ymin, &Xpix, &Ypix);
+  Xmax = graphmode.xmax;
+  Xmin = graphmode.xmin;
+  Ymax = graphmode.ymax;
+  Ymin = graphmode.ymin;
+  dX = (Xmax - Xmin) / (Xpix - 1);
+  dY = (Ymax - Ymin) / (Ypix - 1);
+
+  CHECKVAL(Xmin);
+  CHECKVAL(Xmax);
+  CHECKVAL(dX);
+
+  CHECKVAL(Ymin);
+  CHECKVAL(Ymax);
+  CHECKVAL(dY);
+
+  int Nx = (Xmax - Xmin) / dX + 1;
+  int Ny = (Ymax - Ymin) / dY + 1;
+  
+  Coords newcoords = graphmode.coords;
+  newcoords.cdelt1 *= dX;
+  newcoords.cdelt2 *= dY;
+  newcoords.crpix1 = (newcoords.crpix1 - Xmin) / dX;
+  newcoords.crpix2 = (newcoords.crpix2 - Ymin) / dY;
+
+  gfits_free_matrix (&bf[0].matrix);
+  gfits_free_header (&bf[0].header);
+  CreateBuffer3D (bf, Nx, Ny, Nz, -32, 0.0, 1.0);
+  strcpy (bf[0].file, "(empty)");
+  PutCoords (&newcoords, &bf[0].header);
+  
+  // generate the PSF in a local tangent plane
+  Coords coords;
+  InitCoords (&coords, "DEC--TAN");
+
+  r = vr[0].elements.Flt;
+  d = vd[0].elements.Flt;
+  z = vz[0].elements.Flt;
+
+  val = (float *)bf[0].matrix.buffer;
+
+  for (i = 0; i < vr[0].Nelements; i++, r++, d++, z++) {
+    double rn = ohana_normalize_angle (*r);
+    while (rn < Rmin) rn += 360.0;
+    while (rn > Rmax) rn -= 360.0;
+    RD_to_XY (&x, &y, rn, *d, &newcoords);
+    int Xb = x;
+    int Yb = y;
+    int Zb = (*z - Zmin) / dZ;
+
+    if (Xb >= Nx) continue;
+    if (Yb >= Ny) continue;
+    if (Zb >= Nz) continue;
+    if (Xb < 0) continue;
+    if (Yb < 0) continue;
+    if (Zb < 0) continue;
+    val[Xb + Yb*Nx + Zb*Nx*Ny] ++;
+  }
+  return (TRUE);
+}
Index: /trunk/Ohana/src/opihi/cmd.astro/init.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/init.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.astro/init.c	(revision 38062)
@@ -14,4 +14,5 @@
 int czcplot                 PROTO((int, char **));
 int cdensify                PROTO((int, char **));
+int cdhistogram             PROTO((int, char **));
 int drizzle                 PROTO((int, char **));
 int flux                    PROTO((int, char **));
@@ -77,5 +78,6 @@
   {1, "czplot",      czplot,       "plot scaled vectors in sky coordinates"},
   {1, "czcplot",     czcplot,      "plot color-scaled vectors in sky coordinates"},
-  {1, "cdensify",    cdensify,      "vectors to density history on projection"},
+  {1, "cdensify",    cdensify,     "vectors to density history on projection"},
+  {1, "cdhistogram", cdhistogram,  "vectors to 3D histogram on projection"},
   {1, "drizzle",     drizzle,      "transform image to image"},
   {1, "flux",        flux,         "flux in a convex contour"},
Index: /trunk/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 38062)
@@ -61,4 +61,5 @@
 $(SRC)/ungridify.$(ARCH).o     \
 $(SRC)/histogram.$(ARCH).o	\
+$(SRC)/tdhistogram.$(ARCH).o	\
 $(SRC)/hermitian1d.$(ARCH).o	\
 $(SRC)/hermitian2d.$(ARCH).o	\
@@ -89,4 +90,5 @@
 $(SRC)/medacc.$(ARCH).o	\
 $(SRC)/mget.$(ARCH).o		\
+$(SRC)/mget3d.$(ARCH).o		\
 $(SRC)/minterpolate.$(ARCH).o	\
 $(SRC)/medimage.$(ARCH).o	\
@@ -130,4 +132,5 @@
 $(SRC)/imspline_apply.$(ARCH).o	\
 $(SRC)/imspline_construct.$(ARCH).o \
+$(SRC)/squash3d.$(ARCH).o	   \
 $(SRC)/imstats.$(ARCH).o	   \
 $(SRC)/style.$(ARCH).o		   \
Index: /trunk/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/init.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.data/init.c	(revision 38062)
@@ -51,4 +51,5 @@
 int ungridify        PROTO((int, char **));
 int histogram        PROTO((int, char **));
+int tdhistogram      PROTO((int, char **));
 int hermitian1d      PROTO((int, char **));
 int hermitian2d      PROTO((int, char **));
@@ -80,4 +81,5 @@
 int medacc           PROTO((int, char **));
 int mget             PROTO((int, char **));
+int mget3d           PROTO((int, char **));
 int minterp          PROTO((int, char **));
 int medimage_command PROTO((int, char **));
@@ -117,4 +119,5 @@
 int imspline_apply   PROTO((int, char **));
 int imspline_construct PROTO((int, char **));
+int squash3d         PROTO((int, char **));
 int stats            PROTO((int, char **));
 int imstats          PROTO((int, char **));
@@ -217,4 +220,5 @@
   {1, "header",       header,           "print image header"},
   {1, "histogram",    histogram,        "generate histogram from vector"},
+  {1, "tdhistogram",  tdhistogram,      "generate 2D histogram image from vector set"},
   {1, "hermitian1d",  hermitian1d,      "generate 1-D Hermitian Polynomial"},
   {1, "hermitian2d",  hermitian2d,      "generate 2-D Hermitian Polynomial"},
@@ -243,4 +247,5 @@
   {1, "medacc",       medacc,           "accumulate vector values in another vector"},
   {1, "mget",         mget,             "extract a vector from an image"},
+  {1, "mget3d",       mget3d,           "extract a vector from a 3D image"},
   {1, "imget",        mget,             "extract a vector from an image"},
   {1, "minterp",      minterp,          "interpolate image pixels"},
@@ -289,4 +294,5 @@
   {1, "imspline.apply", imspline_apply, "apply spline fit to generate an image"},
   {1, "imspline.const", imspline_construct, "create spline 2nd deriv. terms"},
+  {1, "squash3d",     squash3d,         "squash 3d buffer to 2d"},
   {1, "stats",        imstats,          "statistics on a portion of an image"},
   {1, "style",        style,            "set the style for graph plots"},
Index: /trunk/Ohana/src/opihi/cmd.data/interpolate.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/interpolate.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.data/interpolate.c	(revision 38062)
@@ -1,4 +1,5 @@
 # include "data.h"
 
+// XXX use 'threshold' to interpolate to a value
 int interpolate (int argc, char **argv) {
 
@@ -11,6 +12,7 @@
     gprint (GP_ERR, "USAGE: interpolate Xi Yi Xo Yo\n");
     gprint (GP_ERR, "  Xi Yi - sorted reference vectors\n");
-    gprint (GP_ERR, "  Xo    - output positions\n");
-    gprint (GP_ERR, "  Yo    - output values\n");
+    gprint (GP_ERR, "  Xo    - output positions (vector)\n");
+    gprint (GP_ERR, "  Yo    - output values (vector)\n");
+    gprint (GP_ERR, "  (use 'threshold' to interpolate to a value)\n");
     return (FALSE);
   }
@@ -18,4 +20,6 @@
   if ((xin  = SelectVector (argv[1],  OLDVECTOR, TRUE)) == NULL) return (FALSE);
   if ((yin  = SelectVector (argv[2],  OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  // target positions are a vector
   if ((xout = SelectVector (argv[3],  OLDVECTOR, TRUE)) == NULL) return (FALSE);
   if ((yout = SelectVector (argv[4],  ANYVECTOR, TRUE)) == NULL) return (FALSE);
Index: /trunk/Ohana/src/opihi/cmd.data/mcreate.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/mcreate.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.data/mcreate.c	(revision 38062)
@@ -3,20 +3,32 @@
 int mcreate (int argc, char **argv) {
   
-  int Nx, Ny;
+  int N;
   Buffer *buf;
 
+  int Nz = 0;
+  if ((N = get_argument (argc, argv, "-nz"))) {
+    remove_argument (N, &argc, argv);
+    Nz = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
   if (argc != 4) {
-    gprint (GP_ERR, "USAGE: mcreate <buffer> Nx Ny\n");
+    gprint (GP_ERR, "USAGE: mcreate <buffer> Nx Ny [-nz Nz]\n");
     return (FALSE);
   }
 
   if ((buf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
-  Nx = atof (argv[2]);
-  Ny = atof (argv[3]);
+  int Nx = atof (argv[2]);
+  int Ny = atof (argv[3]);
 
   /* I should encapsulate this in a create_default_buffer */
   gfits_free_matrix (&buf[0].matrix);
   gfits_free_header (&buf[0].header);
-  CreateBuffer (buf, Nx, Ny, -32, 1.0, 0.0);
+
+  if (Nz) {
+    CreateBuffer3D (buf, Nx, Ny, Nz, -32, 1.0, 0.0);
+  } else {
+    CreateBuffer (buf, Nx, Ny, -32, 1.0, 0.0);
+  }
   return (TRUE);
 }
Index: /trunk/Ohana/src/opihi/cmd.data/mget3d.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/mget3d.c	(revision 38062)
+++ /trunk/Ohana/src/opihi/cmd.data/mget3d.c	(revision 38062)
@@ -0,0 +1,46 @@
+# include "data.h"
+
+int mget3d (int argc, char **argv) {
+  
+  int i;
+  Buffer *buf;
+  Vector *vec;
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: mget <buffer> <vector> x y\n");
+    return (FALSE);
+  }
+
+  int x = atoi(argv[3]);
+  int y = atoi(argv[4]);
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if (buf[0].matrix.Naxes < 3) {
+    gprint (GP_ERR, "buffer is not 3D\n");
+    return FALSE;
+  }
+
+  int Nx = buf[0].matrix.Naxis[0];
+  int Ny = buf[0].matrix.Naxis[1];
+  int Nz = buf[0].matrix.Naxis[2];
+
+  int invalid = FALSE;
+  invalid = invalid || (x < 0);
+  invalid = invalid || (x >= Nx);
+  invalid = invalid || (y < 0);
+  invalid = invalid || (y >= Ny);
+  if (invalid) {
+    gprint (GP_ERR, "selection (%d,%d) out of range\n", x, y);
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  ResetVector (vec, OPIHI_FLT, Nz);
+  float *in  = (float *) buf[0].matrix.buffer + x + y*Nx;
+  opihi_flt *out = vec[0].elements.Flt;
+  for (i = 0; i < Nz; i++, in += Nx*Ny, out++) {
+    *out = *in;
+  }
+  return (TRUE);
+}
Index: /trunk/Ohana/src/opihi/cmd.data/rd.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/rd.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.data/rd.c	(revision 38062)
@@ -4,11 +4,10 @@
 int rd (int argc, char **argv) {
   
-  int i, N, status, plane, Nplane, extend, Nextend, Nskip, JustHead, blank;
-  int ccdsel, done, Nword, IsCompressed;
-  char region[512], *ccdid, *filename;
-  FILE *f;
+  int i, N, Nskip, blank;
+  int done, Nword;
+  char region[512];
   Buffer *buf;
 
-  JustHead = FALSE;
+  int JustHead = FALSE;
   if ((N = get_argument (argc, argv, "-head"))) {
     remove_argument (N, &argc, argv);
@@ -16,5 +15,5 @@
   }
 
-  plane = 1;
+  int plane = -1;
   if ((N = get_argument (argc, argv, "-plane"))) {
     remove_argument (N, &argc, argv);
@@ -23,6 +22,6 @@
   }
 
-  extend = FALSE;
-  Nextend = -1;
+  int extend = FALSE;
+  int Nextend = -1;
   if ((N = get_argument (argc, argv, "-x"))) {
     remove_argument (N, &argc, argv);
@@ -32,6 +31,6 @@
   }
 
-  ccdsel = FALSE;
-  ccdid = (char *) NULL;
+  int ccdsel = FALSE;
+  char *ccdid = NULL;
   if ((N = get_argument (argc, argv, "-n"))) {
     remove_argument (N, &argc, argv);
@@ -52,5 +51,5 @@
 
   /* test if file exists */
-  f = fopen (argv[2], "r");
+  FILE *f = fopen (argv[2], "r");
   if (f == (FILE *) NULL) {
     gprint (GP_ERR, "file %s not found\n", argv[2]);
@@ -67,10 +66,10 @@
 
   /* save file name */
-  filename = filebasename (argv[2]);
+  char *filename = filebasename (argv[2]);
   strcpy (buf[0].file, filename);
   free (filename);
 
-  status = FALSE;
-  IsCompressed = FALSE;
+  int status = FALSE;
+  int IsCompressed = FALSE;
 
   /*** advance to the correct FITS extension ***/
@@ -168,15 +167,24 @@
 
   /* check for valid plane */
-  Nplane = buf[0].header.Naxis[2];
-  if (Nplane == 0) Nplane = 1;
-  if (plane > Nplane) {
-    gprint (GP_ERR, "-plane is too large: %d total planes\n", Nplane);
-    DeleteBuffer (buf);
-    fclose (f);
-    return (FALSE);
+  int Nz = buf[0].header.Naxis[2];
+  if (plane >= 0) {
+    // we are requesting a specific plane (-1 : all data)
+    int tooFar = Nz ? (plane >= Nz) : (plane > Nz);
+    if (tooFar) {
+      gprint (GP_ERR, "-plane is too large: %d total planes\n", Nz);
+      DeleteBuffer (buf);
+      fclose (f);
+      return (FALSE);
+    }
   }
 
   /* load matrix data */
   if (IsCompressed) {
+    if (plane > -1) {
+      gprint (GP_ERR, "-plane incompatible with compressed image\n");
+      DeleteBuffer (buf);
+      fclose (f);
+      return (FALSE);
+    }
     FTable ftable;
     Header theader;
@@ -191,6 +199,15 @@
     // XXX this currently does not work for a cube (we get a cube back, not a specific plane)
   } else {
-    sprintf (region, "-1 -1 -1 -1 %d %d", (plane - 1), plane);
-    status = gfits_fread_matrix_segment (f, &buf[0].matrix, &buf[0].header, region);
+    if (plane > -1) {
+      // read a single plane into a 2D image
+      sprintf (region, "-1 -1 -1 -1 %d %d", (plane - 1), plane);
+      status = gfits_fread_matrix_segment (f, &buf[0].matrix, &buf[0].header, region);
+      buf[0].header.Naxis[2] = 0;
+      buf[0].header.Naxes = 2;
+      gfits_modify (&buf[0].header, "NAXIS", "%d", 1, 2);
+      gfits_modify (&buf[0].header, "NAXIS3", "%d", 1, 0);
+    } else {
+      status = gfits_fread_matrix (f, &buf[0].matrix, &buf[0].header);
+    }
   }
   fclose (f);
@@ -200,12 +217,4 @@
     DeleteBuffer (buf);
     return (FALSE);
-  }
-
-  /* adjust buffer to represent 2D data */
-  if (Nplane > 1) {
-    buf[0].header.Naxis[2] = 0;
-    buf[0].header.Naxes = 2;
-    gfits_modify (&buf[0].header, "NAXIS", "%d", 1, 2);
-    gfits_delete (&buf[0].header, "NAXIS3", 1);
   }
 
@@ -215,4 +224,6 @@
     buf[0].header.Naxis[1] = 1;
     buf[0].matrix.Naxis[1] = 1;
+    gfits_modify (&buf[0].header, "NAXIS", "%d", 1, 2);
+    gfits_modify (&buf[0].header, "NAXIS2", "%d", 1, 1);
   }    
 
Index: /trunk/Ohana/src/opihi/cmd.data/read_vectors.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 38062)
@@ -372,4 +372,10 @@
   }
 
+  int VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
   int start = 0;
   int Nrows = -1; // -1 : read entire table
@@ -399,5 +405,6 @@
   // }
 
-  if (argc < 2) ESCAPE ("USAGE: read -fits extension [-extnum] [-keyword key] name name ...\n");
+  if ((argc < 2) && !getSizes) ESCAPE ("USAGE: read -fits extension [-extnum] [-keyword key] name name ...\n");
+  if ((argc != 1) && getSizes) ESCAPE ("USAGE: read -sizes -fits extension [-extnum] (does not read data values)\n");
 
   if (f == NULL) ESCAPE ("file not found\n");
@@ -436,5 +443,9 @@
     if (start >= header.Naxis[1]) ESCAPE ("invalid range: start >= Ny (%d)\n", header.Naxis[1]);
     if (Nrows < 0) ESCAPE ("invalid range: Nrows < 0\n");
-    if (start + Nrows > header.Naxis[1]) ESCAPE ("invalid range: start + Nrows > Ny (%d)\n", header.Naxis[1]);
+
+    // just a warning:
+    if (start + Nrows > header.Naxis[1]) {
+      if (VERBOSE) gprint (GP_ERR, "NOTE: reading last block will return only %d rows\n", header.Naxis[1] - start);
+    }
 
     // Ny = 100, start = 0, Nrows = -1 -> Nrows => 100
@@ -472,4 +483,11 @@
       }
 
+      if (getSizes) {
+	read_table_sizes (&header);
+	if (CCDKeyword != NULL) free (CCDKeyword); 
+	gfits_free_header (&header); 
+	return TRUE;
+      }
+
       if (Nrows == -1) {
 	Nrows = header.Naxis[1] - start;
@@ -478,5 +496,9 @@
       if (start >= header.Naxis[1]) ESCAPE ("invalid range: start >= Ny (%d)\n", header.Naxis[1]);
       if (Nrows < 0) ESCAPE ("invalid range: Nrows < 0\n");
-      if (start + Nrows > header.Naxis[1]) ESCAPE ("invalid range: start + Nrows > Ny (%d)\n", header.Naxis[1]);
+
+      // just a warning:
+      if (start + Nrows > header.Naxis[1]) {
+	if (VERBOSE) gprint (GP_ERR, "NOTE: reading last block will return only %d rows\n", header.Naxis[1] - start);
+      }
 
       if (!gfits_fread_ftable_range (f, padIfShort, &table, start, Nrows)) ESCAPE ("error reading table for extension %d\n", Nextend);
@@ -603,5 +625,5 @@
 
   set_int_variable ("table:Nx", header->Naxis[0]);
-  set_int_variable ("table:Nx", header->Naxis[0]);
+  set_int_variable ("table:Ny", header->Naxis[1]);
   set_int_variable ("table:Nfields", Nfields);
 
Index: /trunk/Ohana/src/opihi/cmd.data/squash3d.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/squash3d.c	(revision 38062)
+++ /trunk/Ohana/src/opihi/cmd.data/squash3d.c	(revision 38062)
@@ -0,0 +1,113 @@
+# include "data.h"
+
+enum {SQUASH_NONE, SQUASH_X, SQUASH_Y, SQUASH_Z};
+
+int squash3d (int argc, char **argv) {
+  
+  int ox, oy, oz;
+  Buffer *src;
+  Buffer *tgt;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: squash3d <3d> <2d> (dir)\n");
+    gprint (GP_ERR, " dir: x -> squash in x-dir, y -> squash in y-dir, z -> squash in z-dir\n");
+    return (FALSE);
+  }
+
+  int dir = SQUASH_NONE;
+  if (!strcasecmp (argv[3], "x")) dir = SQUASH_X;
+  if (!strcasecmp (argv[3], "y")) dir = SQUASH_Y;
+  if (!strcasecmp (argv[3], "z")) dir = SQUASH_Z;
+  if (!dir) {
+    gprint (GP_ERR, "invalid direction %s\n", argv[3]);
+    return FALSE;
+  }
+
+  if ((src = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if (src[0].matrix.Naxes < 3) {
+    gprint (GP_ERR, "buffer is not 3D\n");
+    return FALSE;
+  }
+
+  float *iBuf  = (float *) src[0].matrix.buffer;
+
+  if ((tgt = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  gfits_free_matrix (&tgt[0].matrix);
+  gfits_free_header (&tgt[0].header);
+
+  switch (dir) {
+    case SQUASH_X:
+      {     
+	int iNx = src[0].matrix.Naxis[0];
+	int iNy = src[0].matrix.Naxis[1];
+	int iNz = src[0].matrix.Naxis[2];
+
+	// output is Nz,Ny
+	int oNx = iNz;
+	int oNy = iNy;
+	CreateBuffer (tgt, oNx, oNy, -32, 0.0, 1.0);
+	float *oBuf  = (float *) tgt[0].matrix.buffer;
+
+	for (ox = 0; ox < oNx; ox ++) {
+	  for (oy = 0; oy < oNy; oy ++) {
+	    float val = 0.0;
+	    for (oz = 0; oz < iNx; oz ++) { // src x is tgt z
+	      val += iBuf[oz + oy*iNx + ox*iNx*iNy];
+	    }
+	    oBuf[ox + oy*oNx] = val;
+	  }
+	}
+      }
+      break;
+      
+    case SQUASH_Y:
+      {     
+	int iNx = src[0].matrix.Naxis[0];
+	int iNy = src[0].matrix.Naxis[1];
+	int iNz = src[0].matrix.Naxis[2];
+
+	// output is Nx,Nz
+	int oNx = iNx;
+	int oNy = iNz;
+	CreateBuffer (tgt, oNx, oNy, -32, 0.0, 1.0);
+	float *oBuf  = (float *) tgt[0].matrix.buffer;
+
+	for (ox = 0; ox < oNx; ox ++) {
+	  for (oy = 0; oy < oNy; oy ++) { // src z is tgt y
+	    float val = 0.0;
+	    for (oz = 0; oz < iNy; oz ++) {
+	      val += iBuf[ox + oz*iNx + oy*iNx*iNy];
+	    }
+	    oBuf[ox + oy*oNx] = val;
+	  }
+	}
+      }
+      break;
+      
+    case SQUASH_Z:
+      {     
+	int iNx = src[0].matrix.Naxis[0];
+	int iNy = src[0].matrix.Naxis[1];
+	int iNz = src[0].matrix.Naxis[2];
+
+	// output is Nx,Ny
+	int oNx = iNx;
+	int oNy = iNy;
+	CreateBuffer (tgt, oNx, oNy, -32, 0.0, 1.0);
+	float *oBuf  = (float *) tgt[0].matrix.buffer;
+
+	for (ox = 0; ox < oNx; ox ++) {
+	  for (oy = 0; oy < oNy; oy ++) {
+	    float val = 0.0;
+	    for (oz = 0; oz < iNz; oz ++) {
+	      val += iBuf[ox + oy*iNx + oz*iNx*iNy];
+	    }
+	    oBuf[ox + oy*oNx] = val;
+	  }
+	}
+      }
+      break;
+  }
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/opihi/cmd.data/tdhistogram.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/tdhistogram.c	(revision 38062)
+++ /trunk/Ohana/src/opihi/cmd.data/tdhistogram.c	(revision 38062)
@@ -0,0 +1,176 @@
+# include "data.h"
+
+# define CHECKVAL(ARG) if (!isfinite(ARG)) { gprint (GP_ERR, "illegal value for %s: %f\n", #ARG, ARG); return (FALSE); }
+
+int tdhistogram (int argc, char **argv) {
+
+  int i, Nx, Ny, Nz, N;
+  float *val;
+  Buffer *bf;
+  Vector *vx, *vy, *vz, *range;
+  opihi_flt *x, *y, *z;
+
+  int reuse = FALSE;
+  if ((N = get_argument (argc, argv, "-reuse"))) {
+    remove_argument (N, &argc, argv);
+    reuse = TRUE;
+  }
+
+  range = NULL;
+  if ((N = get_argument (argc, argv, "-range"))) {
+    remove_argument (N, &argc, argv);
+    if ((range = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+
+  double dx = NAN;
+  if ((N = get_argument (argc, argv, "-dx"))) {
+    remove_argument (N, &argc, argv);
+    dx = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  double dy = NAN;
+  if ((N = get_argument (argc, argv, "-dy"))) {
+    remove_argument (N, &argc, argv);
+    dy = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  double dz = NAN;
+  if ((N = get_argument (argc, argv, "-dz"))) {
+    remove_argument (N, &argc, argv);
+    dz = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  int valid = (!reuse && (argc == 11)) || (reuse && (argc == 5));
+  if (!valid) {
+    gprint (GP_ERR, "USAGE: tdhistogram buffer x y z (Xmin) (Xmax) (Ymin) (Ymax) (Zmin) (Zmax) [-dx dx] [-dy dy] [-dz dz]\n");
+    gprint (GP_ERR, "   OR: tdhistogram buffer x y z -reuse\n");
+    gprint (GP_ERR, " output buffer is 3D\n");
+    return (FALSE);
+  }
+  
+  if ((bf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vx = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vy = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vz = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (vx[0].Nelements != vy[0].Nelements) return (FALSE);
+  if (vx[0].Nelements != vz[0].Nelements) return (FALSE);
+
+  double Xmin, Xmax, Ymin, Ymax, Zmin, Zmax;
+
+  if (!reuse) {
+    Xmin = atof(argv[5]);
+    Xmax = atof(argv[6]);
+    if (!isfinite(dx)) {
+      Nx = 100;
+      dx = (Xmax - Xmin) / (Nx - 1);
+    } else {
+      Nx = (Xmax - Xmin) / dx + 1;
+    }
+    if (dx < 0) {
+      gprint (GP_ERR, "invalid value for delta: %f\n", dx);
+      return (FALSE);
+    }
+    Ymin = atof(argv[7]);
+    Ymax = atof(argv[8]);
+    if (!isfinite(dy)) {
+      Ny = 100;
+      dy = (Ymax - Ymin) / (Ny - 1);
+    } else {
+      Ny = (Ymax - Ymin) / dy + 1;
+    }
+    if (dy < 0) {
+      gprint (GP_ERR, "invalid value for delta: %f\n", dy);
+      return (FALSE);
+    }
+    Zmin = atof(argv[9]);
+    Zmax = atof(argv[10]);
+    if (!isfinite(dz)) {
+      Nz = 100;
+      dz = (Zmax - Zmin) / (Nz - 1);
+    } else {
+      Nz = (Zmax - Zmin) / dz + 1;
+    }
+    if (dz < 0) {
+      gprint (GP_ERR, "invalid value for delta: %f\n", dz);
+      return (FALSE);
+    }
+
+    if (Nz > 1000) {
+      gprint (GP_ERR, "warning: delta of %f will result in %d histogram bins\n", dz, Nz);
+      return (FALSE);
+    }
+  } else {
+    gfits_scan (&bf[0].header, "XMIN", "%lf", 1, &Xmin);
+    gfits_scan (&bf[0].header, "XMAX", "%lf", 1, &Xmax);
+    gfits_scan (&bf[0].header, "XDEL", "%lf", 1, &dx);
+    gfits_scan (&bf[0].header, "YMIN", "%lf", 1, &Ymin);
+    gfits_scan (&bf[0].header, "YMAX", "%lf", 1, &Ymax);
+    gfits_scan (&bf[0].header, "YDEL", "%lf", 1, &dy);
+    gfits_scan (&bf[0].header, "ZMIN", "%lf", 1, &Zmin);
+    gfits_scan (&bf[0].header, "ZMAX", "%lf", 1, &Zmax);
+    gfits_scan (&bf[0].header, "ZDEL", "%lf", 1, &dz);
+    Nx = bf[0].header.Naxis[0];
+    Ny = bf[0].header.Naxis[1];
+    Nz = bf[0].header.Naxis[2];
+  }
+
+  REQUIRE_VECTOR_FLT (vx, FALSE); 
+  REQUIRE_VECTOR_FLT (vy, FALSE); 
+  REQUIRE_VECTOR_FLT (vz, FALSE); 
+
+  CHECKVAL(Xmin);
+  CHECKVAL(Xmax);
+  CHECKVAL(dx);
+
+  CHECKVAL(Ymin);
+  CHECKVAL(Ymax);
+  CHECKVAL(dy);
+
+  if (range) {
+    ResetVector (range, OPIHI_FLT, Nz);
+    for (i = 0; i < range[0].Nelements; i++) {
+      range[0].elements.Flt[i] = Zmin + i*dz;
+    }
+  }
+
+  if (!reuse) {
+    gfits_free_matrix (&bf[0].matrix);
+    gfits_free_header (&bf[0].header);
+    CreateBuffer3D (bf, Nx, Ny, Nz, -32, 0.0, 1.0);
+    strcpy (bf[0].file, "(empty)");
+
+    gfits_modify (&bf[0].header, "XMIN", "%lf", 1, Xmin);
+    gfits_modify (&bf[0].header, "XMAX", "%lf", 1, Xmax);
+    gfits_modify (&bf[0].header, "XDEL", "%lf", 1, dx);
+    gfits_modify (&bf[0].header, "YMIN", "%lf", 1, Ymin);
+    gfits_modify (&bf[0].header, "YMAX", "%lf", 1, Ymax);
+    gfits_modify (&bf[0].header, "YDEL", "%lf", 1, dy);
+    gfits_modify (&bf[0].header, "ZMIN", "%lf", 1, Zmin);
+    gfits_modify (&bf[0].header, "ZMAX", "%lf", 1, Zmax);
+    gfits_modify (&bf[0].header, "ZDEL", "%lf", 1, dz);
+  }
+  
+  x = vx[0].elements.Flt;
+  y = vy[0].elements.Flt;
+  z = vz[0].elements.Flt;
+
+  val = (float *) bf[0].matrix.buffer;
+
+  for (i = 0; i < vx[0].Nelements; i++, x++, y++, z++) {
+    int Xb = (*x - Xmin) / dx;
+    int Yb = (*y - Ymin) / dy;
+    int Zb = (*z - Zmin) / dz;
+
+    if (Xb >= Nx) continue;
+    if (Yb >= Ny) continue;
+    if (Zb >= Nz) continue;
+    if (Xb < 0) continue;
+    if (Yb < 0) continue;
+    if (Zb < 0) continue;
+    val[Xb + Yb*Nx + Zb*Nx*Ny] ++;
+  }
+  return (TRUE);
+}
Index: /trunk/Ohana/src/opihi/cmd.data/tv.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/tv.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.data/tv.c	(revision 38062)
@@ -28,4 +28,15 @@
   }
 
+  int plane = 0;
+  if ((N = get_argument (argc, argv, "-plane"))) {
+    remove_argument (N, &argc, argv);
+    plane = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (plane < 0) {
+    gprint (GP_ERR, " ERROR: -plane (plane) : cannot be negative\n");
+    return (FALSE);
+  }
+
   /* shell exits on pipe close, FIX */
   if ((N = get_argument (argc, argv, "-kill"))) {
@@ -55,7 +66,16 @@
   GetCoords (&coords, &buf[0].header);
   
-  image.data1d = (float *) buf[0].matrix.buffer;
   image.Nx = buf[0].matrix.Naxis[0];
   image.Ny = buf[0].matrix.Naxis[1];
+
+  int tooBig = buf[0].matrix.Naxis[2] ? (plane >= buf[0].matrix.Naxis[2]) : plane > 0;
+  if (tooBig) {
+    gprint (GP_ERR, " ERROR: -plane (plane) : out of bounds (%d vs %d)\n", plane, buf[0].matrix.Naxis[2]);
+    return (FALSE);
+  }
+  int Npix2D = image.Nx * image.Ny;
+
+  float *imdata = (float *) buf[0].matrix.buffer;
+  image.data1d = &imdata[plane*Npix2D];
 
   // send only the root of the file, not the full path
Index: /trunk/Ohana/src/opihi/cmd.data/wd.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/wd.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.data/wd.c	(revision 38062)
@@ -81,14 +81,9 @@
   memcpy (temp_header.buffer, buf[0].header.buffer, temp_header.datasize);
 
-  if (temp_header.Naxes) {
-    // the inBlank value probably does not matter: temp_matrix is float, so nan is used
-    gfits_convert_format (&temp_header, &temp_matrix, outBitpix, outScale, outZero, 0xffff, outUnsign);
-  } else {
-    gfits_modify (&temp_header, "BITPIX", "%d", 1, outBitpix);
-    gfits_modify (&temp_header, "BSCALE", "%lf", 1, outScale);
-    gfits_modify (&temp_header, "BZERO",  "%lf", 1, outZero);
-    gfits_modify_alt (&temp_header, "UNSIGN", "%t", 1, outUnsign);
-  }
+  gfits_convert_format (&temp_header, &temp_matrix, outBitpix, outScale, outZero, 0xffff, outUnsign);
 
+  // Extend puts the output matrix in the first available non-PHU slot (ie, the last one)
+  // it updates NEXTEND and set EXTEND to TRUE, and modifies the PHU header (neither should happen)
+  // if those keywords do not exist...
   if (Extend) {
     Header Xhead;
Index: /trunk/Ohana/src/opihi/cmd.data/zplot.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/zplot.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/cmd.data/zplot.c	(revision 38062)
@@ -4,11 +4,34 @@
   
   char *outname = NULL;
-  int i, kapa, valid, size;
+  int i, N, kapa, valid, size;
   opihi_flt *out;
   double min, range;
   Graphdata graphmode;
-  Vector *xvec, *yvec, *zvec, Zvec;
+  Vector *xvec, *yvec, *zvec, *dxmvec, *dxpvec, *dymvec, *dypvec, Zvec;
 
   if (!style_args (&graphmode, &argc, argv, &kapa)) return (FALSE);
+
+  /* decide on error bars */
+  dxmvec = dxpvec = dymvec = dypvec = NULL;
+  if ((N = get_argument (argc, argv, "-dx"))) {
+    remove_argument (N, &argc, argv);
+    if ((dxmvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "+dx"))) {
+    remove_argument (N, &argc, argv);
+    if ((dxpvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-dy"))) {
+    remove_argument (N, &argc, argv);
+    if ((dymvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "+dy"))) {
+    remove_argument (N, &argc, argv);
+    if ((dypvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
 
   valid  = (argc == 6);
@@ -40,4 +63,13 @@
   }
 
+  /* set errorbar mode (these are NOT sticky) */
+  graphmode.etype = 0;
+  if ((dymvec != NULL) && (dypvec == NULL)) dypvec = dymvec;
+  if ((dypvec != NULL) && (dymvec == NULL)) dymvec = dypvec;
+  if ((dypvec != NULL) || (dymvec != NULL)) graphmode.etype |= 0x01;
+  if ((dxmvec != NULL) && (dxpvec == NULL)) dxpvec = dxmvec;
+  if ((dxpvec != NULL) && (dxmvec == NULL)) dxmvec = dxpvec;
+  if ((dxpvec != NULL) || (dxmvec != NULL)) graphmode.etype |= 0x02;
+  
   /* find vectors */
   if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
@@ -56,7 +88,13 @@
     return (FALSE);
   }
+  if (dypvec && (dypvec->Nelements != xvec->Nelements)) goto mismatch;
+  if (dymvec && (dymvec->Nelements != xvec->Nelements)) goto mismatch;
+  if (dxpvec && (dxpvec->Nelements != xvec->Nelements)) goto mismatch;
+  if (dxmvec && (dxmvec->Nelements != xvec->Nelements)) goto mismatch;
+
   SetVector (&Zvec, OPIHI_FLT, zvec[0].Nelements);
   out = Zvec.elements.Flt;
  
+  // note actual size is 3.3x plot -sz sizes. (DrawObjects.c:399)
   if (zvec[0].type == OPIHI_FLT) {
     opihi_flt *in = zvec[0].elements.Flt;
@@ -81,13 +119,31 @@
   graphmode.style = 2; /* plot points */
   graphmode.size = -1; /* point size determined by Zvec */
-  graphmode.etype = 0; /* no errorbars */
   PlotVectorTriplet (kapa, xvec, yvec, &Zvec, mask, &graphmode);
+  if (graphmode.etype & 0x01) {
+    PlotVectorSingle (kapa, dymvec, mask, "dym");
+    PlotVectorSingle (kapa, dypvec, mask, "dyp");
+  }
+  if (graphmode.etype & 0x02) {
+    PlotVectorSingle (kapa, dxmvec, mask, "dxm");
+    PlotVectorSingle (kapa, dxpvec, mask, "dxp");
+  }
 
   free (Zvec.elements.Ptr);
   if (mask) free (mask);
-  DeleteNamedVector (outname);
+
+  if (outname) {
+    DeleteNamedVector (outname);
+    free (outname);
+  }
 
   return (TRUE);
 
+mismatch:
+  gprint (GP_ERR, "error and data vector lengths are mismatched\n");
+  if (outname) {
+    DeleteNamedVector (outname);
+    free (outname);
+  }
+  return (FALSE);
 }
 
Index: /trunk/Ohana/src/opihi/doc/BufferMath.txt
===================================================================
--- /trunk/Ohana/src/opihi/doc/BufferMath.txt	(revision 38062)
+++ /trunk/Ohana/src/opihi/doc/BufferMath.txt	(revision 38062)
@@ -0,0 +1,46 @@
+
+Opihi has the main data types: scalar, vector, buffer.  these are all
+handled somewhat different, with different internal structures.  
+
+In most places, the buffer is essentially an image or a 2D matrix.
+However, it is not really restricted as such.  I recently (2015.01.16)
+updated dvomath operations to handle 3D images as well as 2D images.  
+
+Here are some of the places where the difference matters:
+
+* stack_math.c & vector OP matrix and matrix OP vector: these
+  operations are explicitly only valid for 2D matrices (and order
+  determines if the vector is applied to a row (vector first) or a
+  column (vector last).
+
+* stack_math.c & xramp(a) or yramp(a) : these only are applied to the
+  1st 2D plane of an N-D matrix
+
+* check_stack only tests Nx,Ny,Nz.  it probably ignores higher
+  dimensions, but probably does not disallow them.
+
+* concepts like A[x][y] only work for 2D buffers
+
+* lots of the functions which operate on buffers assume the buffer is
+  an image.  Most of the functions in cmd.astro would not be
+  well-defined for a higher-dimension object.  these should probably
+  at least test for 2D and exit / warn if the selected buffer is not
+  2D
+
+* for some of the functions in cmd.data, a higher-dimension object
+  could make sense, but is currently not allowed.  for example, tv A
+  could be extended to display a given slice.  
+
+* rd and wd should really be extended to allow read/write to/from a 3D
+  file.  actually, rd already can read a plane and wd used to be able
+  to write to a plane.  
+
+* some of the subset-like operations should be extended:
+
+  * mget, mset -- i've added mget3d, but a better abstraction would be
+    good
+   
+  * extract is a problem anyway
+
+  * dimendown and dimenup have similar issues
+
Index: /trunk/Ohana/src/opihi/dvo/avextract.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/avextract.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/dvo/avextract.c	(revision 38062)
@@ -221,4 +221,5 @@
 
       for (n = 0; n < Nfields; n++) {
+	// we are passing in the *first* measure, but average->Nmeasure gives the count
 	values[n] = dbExtractAverages (average, secfilt, measure, lensobj, starpar, &fields[n]);
       }
Index: /trunk/Ohana/src/opihi/include/dvomath.h
===================================================================
--- /trunk/Ohana/src/opihi/include/dvomath.h	(revision 38061)
+++ /trunk/Ohana/src/opihi/include/dvomath.h	(revision 38062)
@@ -187,4 +187,5 @@
 int           ListBuffersToList     PROTO((char *name));
 int           CreateBuffer          PROTO((Buffer *buf, int Nx, int Ny, int bitpix, float bzero, float bscale));
+int           CreateBuffer3D        PROTO((Buffer *buf, int Nx, int Ny, int Nz, int bitpix, float bzero, float bscale));
 int           ResetBuffer           PROTO((Buffer *buf, int Nx, int Ny, int bitpix, float bzero, float bscale));
 Buffer       *SelectBuffer          PROTO((char *name, int mode, int verbose));
Index: /trunk/Ohana/src/opihi/lib.shell/BufferOps.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/BufferOps.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/lib.shell/BufferOps.c	(revision 38062)
@@ -120,4 +120,31 @@
 }
   
+// buffer is 1D array referenced in the order:
+// buffer[x + Nx*y + Nx*Ny*z + ...]
+int CreateBuffer3D (Buffer *buf, int Nx, int Ny, int Nz, int bitpix, float bzero, float bscale) {
+
+  /* store the default output values */
+  gfits_init_header (&buf[0].header);
+
+  /* assign the necessary internal values */
+  buf[0].header.bitpix   = -32;
+  buf[0].header.Naxes = 3;
+  buf[0].header.Naxis[0] = Nx;
+  buf[0].header.Naxis[1] = Ny;
+  buf[0].header.Naxis[2] = Nz;
+
+  buf[0].bitpix = bitpix;
+  buf[0].bzero  = bzero;
+  buf[0].bscale = bscale;
+  
+  /* make some test of the validity of the values */
+
+  /* create the appropriate header and matrix */
+  gfits_create_header (&buf[0].header);
+  gfits_create_matrix (&buf[0].header, &buf[0].matrix);
+
+  return (TRUE);
+}
+  
 /* copy data from in to out - new memory space */
 int CopyNamedBuffer (char *out, char *in) {
Index: /trunk/Ohana/src/opihi/lib.shell/check_stack.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/check_stack.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/lib.shell/check_stack.c	(revision 38062)
@@ -6,8 +6,8 @@
 int check_stack (StackVar *stack, int Nstack, int validsize) {
 
-  int i, Nx, Ny, Nv, size;
+  int i, Nx, Ny, Nz, Nv, size;
   char *c1, *c2;
 
-  Nv = Nx = Ny = -1;
+  Nv = Nx = Ny = Nz = -1;
 
   for (i = 0; i < Nstack; i++) {
@@ -46,6 +46,9 @@
 	  Nx = stack[i].buffer[0].matrix.Naxis[0];
 	  Ny = stack[i].buffer[0].matrix.Naxis[1];
+	  Nz = stack[i].buffer[0].matrix.Naxis[2];
 	} 
-	if ((Nx != stack[i].buffer[0].matrix.Naxis[0]) && (Ny != stack[i].buffer[0].matrix.Naxis[1])) {
+	if ((Nx != stack[i].buffer[0].matrix.Naxis[0]) && 
+	    (Ny != stack[i].buffer[0].matrix.Naxis[1]) && 
+	    (Nz != stack[i].buffer[0].matrix.Naxis[2])) {
 	  push_error ("dimensions don't match");
 	  return (-1);
Index: /trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 38062)
@@ -60,4 +60,5 @@
     if (!strcmp (argv[i], "xramp"))  { type = ST_UNARY; goto gotit; }
     if (!strcmp (argv[i], "yramp"))  { type = ST_UNARY; goto gotit; }
+    if (!strcmp (argv[i], "zramp"))  { type = ST_UNARY; goto gotit; }
     if (!strcmp (argv[i], "ramp"))   { type = ST_UNARY; goto gotit; }
     if (!strcmp (argv[i], "zero"))   { type = ST_UNARY; goto gotit; }
Index: /trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 38062)
@@ -121,5 +121,5 @@
       got_three_op:
 	if (!status) {
-	  snprintf (line, 512, "syntax error: invalid operand for binary operation: %s or %s or %s\n", stack[i-1].name, stack[i-2].name, stack[i-3].name);
+	  snprintf (line, 512, "syntax error: invalid operand for trinary operation: %s or %s or %s\n", stack[i-1].name, stack[i-2].name, stack[i-3].name);
 	  push_error (line);
 	  clear_stack (&tmp_stack);
Index: /trunk/Ohana/src/opihi/lib.shell/stack_math.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/stack_math.c	(revision 38061)
+++ /trunk/Ohana/src/opihi/lib.shell/stack_math.c	(revision 38062)
@@ -80,4 +80,70 @@
       break;								\
     }									\
+    if ((V1->vector->type == OPIHI_FLT) && (V2->vector->type == OPIHI_FLT) && (V3->vector->type == OPIHI_INT)) { \
+      CopyVector (OUT[0].vector, V1[0].vector);				\
+      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;			\
+      opihi_flt *M2  =  V2[0].vector[0].elements.Flt;			\
+      opihi_int *M3  =  V3[0].vector[0].elements.Int;			\
+      opihi_flt *out = OUT[0].vector[0].elements.Flt;			\
+      for (i = 0; i < Nx; i++, out++, M1++, M2++, M3++) {		\
+  	*out = OP;							\
+      }									\
+      break;								\
+    }									\
+    if ((V1->vector->type == OPIHI_FLT) && (V2->vector->type == OPIHI_INT) && (V3->vector->type == OPIHI_FLT)) { \
+      CopyVector (OUT[0].vector, V1[0].vector);				\
+      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;			\
+      opihi_int *M2  =  V2[0].vector[0].elements.Int;			\
+      opihi_flt *M3  =  V3[0].vector[0].elements.Flt;			\
+      opihi_flt *out = OUT[0].vector[0].elements.Flt;			\
+      for (i = 0; i < Nx; i++, out++, M1++, M2++, M3++) {		\
+  	*out = OP;							\
+      }									\
+      break;								\
+    }									\
+    if ((V1->vector->type == OPIHI_FLT) && (V2->vector->type == OPIHI_INT) && (V3->vector->type == OPIHI_INT)) { \
+      CopyVector (OUT[0].vector, V2[0].vector);				\
+      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;			\
+      opihi_int *M2  =  V2[0].vector[0].elements.Int;			\
+      opihi_int *M3  =  V3[0].vector[0].elements.Int;			\
+      opihi_int *out = OUT[0].vector[0].elements.Int;			\
+      for (i = 0; i < Nx; i++, out++, M1++, M2++, M3++) {		\
+  	*out = OP;							\
+      }									\
+      break;								\
+    }									\
+    if ((V1->vector->type == OPIHI_INT) && (V2->vector->type == OPIHI_FLT) && (V3->vector->type == OPIHI_FLT)) { \
+      CopyVector (OUT[0].vector, V2[0].vector);				\
+      opihi_int *M1  =  V1[0].vector[0].elements.Int;			\
+      opihi_flt *M2  =  V2[0].vector[0].elements.Flt;			\
+      opihi_flt *M3  =  V3[0].vector[0].elements.Flt;			\
+      opihi_flt *out = OUT[0].vector[0].elements.Flt;			\
+      for (i = 0; i < Nx; i++, out++, M1++, M2++, M3++) {		\
+  	*out = OP;							\
+      }									\
+      break;								\
+    }									\
+    if ((V1->vector->type == OPIHI_INT) && (V2->vector->type == OPIHI_FLT) && (V3->vector->type == OPIHI_INT)) { \
+      CopyVector (OUT[0].vector, V2[0].vector);				\
+      opihi_int *M1  =  V1[0].vector[0].elements.Int;			\
+      opihi_flt *M2  =  V2[0].vector[0].elements.Flt;			\
+      opihi_int *M3  =  V3[0].vector[0].elements.Int;			\
+      opihi_flt *out = OUT[0].vector[0].elements.Flt;			\
+      for (i = 0; i < Nx; i++, out++, M1++, M2++, M3++) {		\
+  	*out = OP;							\
+      }									\
+      break;								\
+    }									\
+    if ((V1->vector->type == OPIHI_INT) && (V2->vector->type == OPIHI_INT) && (V3->vector->type == OPIHI_FLT)) { \
+      CopyVector (OUT[0].vector, V3[0].vector);				\
+      opihi_int *M1  =  V1[0].vector[0].elements.Int;			\
+      opihi_int *M2  =  V2[0].vector[0].elements.Int;			\
+      opihi_flt *M3  =  V3[0].vector[0].elements.Flt;			\
+      opihi_flt *out = OUT[0].vector[0].elements.Flt;			\
+      for (i = 0; i < Nx; i++, out++, M1++, M2++, M3++) {		\
+  	*out = OP;							\
+      }									\
+      break;								\
+    }									\
     if ((V1->vector->type == OPIHI_INT) && (V2->vector->type == OPIHI_INT) && (V3->vector->type == OPIHI_INT)) { \
       CopyVector (OUT[0].vector, V1[0].vector);				\
@@ -127,11 +193,10 @@
 int MMM_trinary (StackVar *OUT, StackVar *V1, StackVar *V2, StackVar *V3, char *op) {
 
-  int i, Nx, Ny;
+  int i;
   float *out, *M1, *M2, *M3;
   char line[512]; // this is only used to report an error 
   
-  Nx = V1[0].buffer[0].matrix.Naxis[0];
-  Ny = V1[0].buffer[0].matrix.Naxis[1];
-
+  int Npix = gfits_npix_matrix (&V1[0].buffer[0].matrix);
+  
   if (V1[0].type == ST_MATRIX_TMP) {  /** use V1 as temp buffer **/
     OUT[0].buffer = V1[0].buffer;
@@ -154,5 +219,5 @@
 
 # define MMM_FUNC(OP)					\
-  for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++, M3++) {	\
+  for (i = 0; i < Npix; i++, out++, M1++, M2++, M3++) {	\
     *out = OP;						\
   }							\
@@ -531,5 +596,5 @@
 }
 
-// the vector is applied to each column
+// the vector is applied to each column (currently only valid for 2D matrix)
 int MV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
 
@@ -626,5 +691,5 @@
 }
 
-// the vector is applied to each row
+// the vector is applied to each row (currently only valid for 2D matrix)
 int VM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
 
@@ -722,11 +787,10 @@
 int MM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
 
-  int i, Nx, Ny;
+  int i;
   float *out, *M1, *M2;
   char line[512]; // this is only used to report an error 
   
-  Nx = V1[0].buffer[0].matrix.Naxis[0];
-  Ny = V1[0].buffer[0].matrix.Naxis[1];
-
+  int Npix = gfits_npix_matrix (&V1[0].buffer[0].matrix);
+  
   if (V1[0].type == ST_MATRIX_TMP) {  /** use V1 as temp buffer **/
     OUT[0].buffer = V1[0].buffer;
@@ -748,5 +812,5 @@
 
 # define MM_FUNC(OP)					\
-  for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) {	\
+  for (i = 0; i < Npix; i++, out++, M1++, M2++) {	\
     *out = OP;						\
   }							\
@@ -803,9 +867,8 @@
 int MS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
 
-  int i, Nx, Ny;
+  int i;
   char line[512]; // this is only used to report an error 
   
-  Nx = V1[0].buffer[0].matrix.Naxis[0];
-  Ny = V1[0].buffer[0].matrix.Naxis[1];
+  int Npix = gfits_npix_matrix (&V1[0].buffer[0].matrix);
 
   /* if possible, use V1 as temp buffer, otherwise create new one */
@@ -825,5 +888,5 @@
     if (V2->type == ST_SCALAR_FLT)  {				\
       opihi_flt M2 = V2[0].FltValue;			\
-      for (i = 0; i < Nx*Ny; i++, out++, M1++) {	\
+      for (i = 0; i < Npix; i++, out++, M1++) {	\
 	*out = OP;					\
       }							\
@@ -832,5 +895,5 @@
     if (V2->type == ST_SCALAR_INT)  {				\
       opihi_int M2 = V2[0].IntValue;			\
-      for (i = 0; i < Nx*Ny; i++, out++, M1++) {	\
+      for (i = 0; i < Npix; i++, out++, M1++) {	\
 	*out = OP;					\
       }							\
@@ -881,10 +944,9 @@
 int SM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
 
-  int i, Nx, Ny;
+  int i;
   char line[512]; // this is only used to report an error 
   
-  Nx = V2[0].buffer[0].matrix.Naxis[0];
-  Ny = V2[0].buffer[0].matrix.Naxis[1];
-
+  int Npix = gfits_npix_matrix (&V2[0].buffer[0].matrix);
+  
   if (V2[0].type == ST_MATRIX_TMP) {  /* V2[0] is NOT temporary, we can't use it for storage */
     OUT[0].buffer = V2[0].buffer;
@@ -902,5 +964,5 @@
     if (V1->type == ST_SCALAR_FLT)  {				\
       opihi_flt M1 = V1[0].FltValue;			\
-      for (i = 0; i < Nx*Ny; i++, out++, M2++) {	\
+      for (i = 0; i < Npix; i++, out++, M2++) {	\
 	*out = OP;					\
       }							\
@@ -909,5 +971,5 @@
     if (V1->type == ST_SCALAR_INT)  {				\
       opihi_int M1 = V1[0].IntValue;			\
-      for (i = 0; i < Nx*Ny; i++, out++, M2++) {	\
+      for (i = 0; i < Npix; i++, out++, M2++) {	\
 	*out = OP;					\
       }							\
@@ -1240,5 +1302,6 @@
   if (!strcmp (op, "xramp"))  V_FUNC(i, ST_SCALAR_INT);
   if (!strcmp (op, "yramp"))  V_FUNC(0, ST_SCALAR_INT);
-  /* xramp and yramp above only make sense for matrices. for vectors, xramp = ramp, yramp = zero */
+  if (!strcmp (op, "zramp"))  V_FUNC(0, ST_SCALAR_INT);
+  /* xramp, yramp, zramp above only make sense for matrices. for vectors, xramp = ramp, yramp = zero */
 
 # undef V_FUNC
@@ -1259,10 +1322,9 @@
 int M_unary (StackVar *OUT, StackVar *V1, char *op) {
 
-  int i, j, Nx, Ny;
+  int i, j, k;
   float *out, *M1;
   
-  Nx = V1[0].buffer[0].matrix.Naxis[0];
-  Ny = V1[0].buffer[0].matrix.Naxis[1];
-
+  int Npix = gfits_npix_matrix (&V1[0].buffer[0].matrix);
+  
   if (V1[0].type == ST_MATRIX_TMP) {
     OUT[0].buffer = V1[0].buffer;
@@ -1277,56 +1339,78 @@
 
   if (!strcmp (op, "="))     { }
-  if (!strcmp (op, "abs"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = fabs(*M1);         }}
-  if (!strcmp (op, "int"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = (opihi_flt)(long long)(*M1); }}
-
-  if (!strcmp (op, "floor")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = floor (*M1); }}
-  if (!strcmp (op, "ceil"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = ceil (*M1); }}
-  // if (!strcmp (op, "rint"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = nearbyint (*M1); }}
-
-  if (!strcmp (op, "exp"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = exp(*M1);          }}
-  if (!strcmp (op, "ten"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = pow(10.0,*M1);     }}
-  if (!strcmp (op, "log"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = log10(*M1);        }}
-  if (!strcmp (op, "ln"))    { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = log(*M1);          }}
-  if (!strcmp (op, "sqrt"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sqrt(*M1);         }}
-  if (!strcmp (op, "erf"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = erf(*M1);          }}
-
-  if (!strcmp (op, "sinh"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sinh(*M1);         }}
-  if (!strcmp (op, "cosh"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = cosh(*M1);         }}
-  if (!strcmp (op, "asinh")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = asinh(*M1);        }}
-  if (!strcmp (op, "acosh")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = acosh(*M1);        }}
-  if (!strcmp (op, "lgamma")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = lgamma(*M1);      }}
-
-  if (!strcmp (op, "sin"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sin(*M1);          }}
-  if (!strcmp (op, "cos"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = cos(*M1);          }}
-  if (!strcmp (op, "tan"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = tan(*M1);          }}
-  if (!strcmp (op, "dsin"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sin(*M1*RAD_DEG);  }}
-  if (!strcmp (op, "dcos"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = cos(*M1*RAD_DEG);  }}
-  if (!strcmp (op, "dtan"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = tan(*M1*RAD_DEG);  }}
-  if (!strcmp (op, "asin"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = asin(*M1);         }}
-  if (!strcmp (op, "acos"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = acos(*M1);         }}
-  if (!strcmp (op, "atan"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = atan(*M1);         }}
-  if (!strcmp (op, "dasin")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = asin(*M1)*DEG_RAD; }}
-  if (!strcmp (op, "dacos")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = acos(*M1)*DEG_RAD; }}
-  if (!strcmp (op, "datan")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = atan(*M1)*DEG_RAD; }}
-  if (!strcmp (op, "not"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = !(*M1);            }}
-  if (!strcmp (op, "--"))    { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = -(*M1);            }}
-  if (!strcmp (op, "rnd"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = drand48();         }}
-  if (!strcmp (op, "ramp"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = i;                 }}
-  if (!strcmp (op, "zero"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = 0;                 }}
-  if (!strcmp (op, "isinf")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = !finite(*M1);      }}
-  if (!strcmp (op, "isnan")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = isnan(*M1);        }}
-
-  /* xrm and yrm only make sense in for matrices. see special meaning for vectors */
+  if (!strcmp (op, "abs"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = fabs(*M1);         }}
+  if (!strcmp (op, "int"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = (opihi_flt)(long long)(*M1); }}
+
+  if (!strcmp (op, "floor")) { for (i = 0; i < Npix; i++, out++, M1++) { *out = floor (*M1); }}
+  if (!strcmp (op, "ceil"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = ceil (*M1); }}
+  // if (!strcmp (op, "rint"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = nearbyint (*M1); }}
+
+  if (!strcmp (op, "exp"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = exp(*M1);          }}
+  if (!strcmp (op, "ten"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = pow(10.0,*M1);     }}
+  if (!strcmp (op, "log"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = log10(*M1);        }}
+  if (!strcmp (op, "ln"))    { for (i = 0; i < Npix; i++, out++, M1++) { *out = log(*M1);          }}
+  if (!strcmp (op, "sqrt"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = sqrt(*M1);         }}
+  if (!strcmp (op, "erf"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = erf(*M1);          }}
+
+  if (!strcmp (op, "sinh"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = sinh(*M1);         }}
+  if (!strcmp (op, "cosh"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = cosh(*M1);         }}
+  if (!strcmp (op, "asinh")) { for (i = 0; i < Npix; i++, out++, M1++) { *out = asinh(*M1);        }}
+  if (!strcmp (op, "acosh")) { for (i = 0; i < Npix; i++, out++, M1++) { *out = acosh(*M1);        }}
+  if (!strcmp (op, "lgamma")) { for (i = 0; i < Npix; i++, out++, M1++) { *out = lgamma(*M1);      }}
+
+  if (!strcmp (op, "sin"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = sin(*M1);          }}
+  if (!strcmp (op, "cos"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = cos(*M1);          }}
+  if (!strcmp (op, "tan"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = tan(*M1);          }}
+  if (!strcmp (op, "dsin"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = sin(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dcos"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = cos(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dtan"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = tan(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "asin"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = asin(*M1);         }}
+  if (!strcmp (op, "acos"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = acos(*M1);         }}
+  if (!strcmp (op, "atan"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = atan(*M1);         }}
+  if (!strcmp (op, "dasin")) { for (i = 0; i < Npix; i++, out++, M1++) { *out = asin(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "dacos")) { for (i = 0; i < Npix; i++, out++, M1++) { *out = acos(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "datan")) { for (i = 0; i < Npix; i++, out++, M1++) { *out = atan(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "not"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = !(*M1);            }}
+  if (!strcmp (op, "--"))    { for (i = 0; i < Npix; i++, out++, M1++) { *out = -(*M1);            }}
+  if (!strcmp (op, "rnd"))   { for (i = 0; i < Npix; i++, out++, M1++) { *out = drand48();         }}
+  if (!strcmp (op, "ramp"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = i;                 }}
+  if (!strcmp (op, "zero"))  { for (i = 0; i < Npix; i++, out++, M1++) { *out = 0;                 }}
+  if (!strcmp (op, "isinf")) { for (i = 0; i < Npix; i++, out++, M1++) { *out = !finite(*M1);      }}
+  if (!strcmp (op, "isnan")) { for (i = 0; i < Npix; i++, out++, M1++) { *out = isnan(*M1);        }}
+
+  /* xrm and yrm only make sense for 2D matrices. see special meaning for vectors */
   if (!strcmp (op, "xramp")) {
-    for (j = 0; j < Ny; j++) {
-      for (i = 0; i < Nx; i++, out++, M1++) {
-	*out = i;
+    int Nx = V1[0].buffer[0].matrix.Naxis[0];
+    int Ny = V1[0].buffer[0].matrix.Naxis[1];
+    int Nz = MAX (1, V1[0].buffer[0].matrix.Naxis[2]);
+    for (k = 0; k < Nz; k++) {
+      for (j = 0; j < Ny; j++) {
+	for (i = 0; i < Nx; i++, out++, M1++) {
+	  *out = i;
+	}
       }
     }
   }
   if (!strcmp (op, "yramp")) {
-    for (j = 0; j < Ny; j++) {
-      for (i = 0; i < Nx; i++, out++, M1++) {
-	*out = j;
+    int Nx = V1[0].buffer[0].matrix.Naxis[0];
+    int Ny = V1[0].buffer[0].matrix.Naxis[1];
+    int Nz = MAX (1, V1[0].buffer[0].matrix.Naxis[2]);
+    for (k = 0; k < Nz; k++) {
+      for (j = 0; j < Ny; j++) {
+	for (i = 0; i < Nx; i++, out++, M1++) {
+	  *out = j;
+	}
+      }
+    }
+  }
+  if (!strcmp (op, "zramp")) {
+    int Nx = V1[0].buffer[0].matrix.Naxis[0];
+    int Ny = V1[0].buffer[0].matrix.Naxis[1];
+    int Nz = MAX (1, V1[0].buffer[0].matrix.Naxis[2]);
+    for (k = 0; k < Nz; k++) {
+      for (j = 0; j < Ny; j++) {
+	for (i = 0; i < Nx; i++, out++, M1++) {
+	  *out = k;
+	}
       }
     }
Index: /trunk/Ohana/src/opihi/test/ellipse.sh
===================================================================
--- /trunk/Ohana/src/opihi/test/ellipse.sh	(revision 38062)
+++ /trunk/Ohana/src/opihi/test/ellipse.sh	(revision 38062)
@@ -0,0 +1,122 @@
+
+macro ShapeToAxes
+  if ($0 != 7)
+    echo "USAGE: ShapeToAxes (sxx) (sxy) (syy) (major) (minor) (theta)"
+    echo " theta is returned in degrees"
+    break
+  end
+
+  # I need the concept of a local vector...
+  # I should be able to test if these are vectors or scalars
+  set _sxx = $1
+  set _sxy = $2
+  set _syy = $3
+
+  set f1 = _syy^-2 + _sxx^-2
+  set f2 = _syy^-2 - _sxx^-2
+  set f3 = sqrt(f2^2 + 4*_sxy^2)
+
+  set _minor = sqrt (2.0 / (f1 + f3))
+
+  # this returns theta in degrees
+  # @ == atan2 -- I should really replace this..
+  set _theta = -0.5 * (+2.0*_sxy @ f2)
+  set aratio2 = (f1 - f3) / (f1 + f3)
+
+  # I can test here if aratio2 is too large/small/nan
+  set _major = sqrt (2.0 / (f1 - f3))
+
+  set $4 = _major
+  set $5 = _minor
+  set $6 = _theta
+end
+
+macro AxesToShapeAlt
+  if ($0 != 7)
+    echo "USAGE: ShapeToAxes (major) (minor) (theta) (sxx) (sxy) (syy)"
+    echo " theta is supplied in degrees"
+    break
+  end
+
+  set _major = $1
+  set _minor = $2
+  set _theta = -1*$3
+
+  set tc2 = dcos(_theta)^2
+  set ts2 = dsin(_theta)^2
+
+  set f1 = tc2*_major^-2 + ts2*_minor^-2
+  set f2 = ts2*_major^-2 + tc2*_minor^-2
+  set f3 = _minor^-2 - _major^-2
+
+  set $4 = +1.0 / sqrt(f1);
+  set $6 = +1.0 / sqrt(f2);
+  set $5 = 0.5*f3*dsin(2*_theta);
+end
+
+macro AxesToShape
+  if ($0 != 7)
+    echo "USAGE: ShapeToAxes (major) (minor) (theta) (sxx) (sxy) (syy)"
+    echo " theta is supplied in degrees"
+    break
+  end
+
+  set _major = $1
+  set _minor = $2
+  set _theta = $3
+
+  set f1 = _minor^-2 + _major^-2
+  set f2 = _minor^-2 - _major^-2
+
+  set sxr = 0.5*f1 - 0.5*f2*dcos(2*_theta);
+  set syr = 0.5*f1 + 0.5*f2*dcos(2*_theta);
+
+  set $4 = +1.0 / sqrt(sxr);
+  set $6 = +1.0 / sqrt(syr);
+  set $5 = -0.5*f2*dsin(2*_theta);
+end
+
+macro test1
+
+  # create a series of ellipses with theta spinning and AR = 2.0
+  $DX = 201
+
+  create theta 0 360 10
+  set major = 20.0 + zero(theta)
+  set minor = 10.0 + zero(theta)
+
+  # AxesToShape major minor theta sxx sxy syy
+  AxesToShape major minor theta sxx sxy syy
+
+  mcreate mosaic {6*($DX + 2)} {6*($DX + 2)} 
+  mcreate base $DX $DX
+  set x = xramp(base) - int(0.5*$DX)
+  set y = yramp(base) - int(0.5*$DX)
+  
+  for i 0 theta[]
+    set r = 0.5*(x/sxx[$i])^2 + 0.5*(y/syy[$i])^2 + sxy[$i]*x*y
+    set object = exp(-r)
+    $ix = $i % 6
+    $iy = int($i / 6)
+    extract object mosaic 0 0 $DX $DX {$ix * ($DX + 1)} {$iy * ($DX + 1)}  {6*($DX + 2)} {6*($DX + 2)} 
+  end    
+
+  tv mosaic -0.01 0.5
+  lim -image
+  clear; box
+
+  for i 0 theta[]
+    $ix = $i % 6
+    $iy = int($i / 6)
+    
+    $dX = $ix * ($DX + 1) + int(0.5*$DX)
+    $dY = $iy * ($DX + 1) + int(0.5*$DX)
+
+    create T 0 360 0.1
+    set Xr = major[$i]*dcos(T)
+    set Yr = minor[$i]*dsin(T)
+    set Xo = Xr*dcos(theta[$i]) - Yr*dsin(theta[$i]) + $dX
+    set Yo = Yr*dcos(theta[$i]) + Xr*dsin(theta[$i]) + $dY
+    plot Xo Yo -x 0 -c red
+  end    
+end
Index: /trunk/Ohana/src/photdbc/src/photdbc.c
===================================================================
--- /trunk/Ohana/src/photdbc/src/photdbc.c	(revision 38061)
+++ /trunk/Ohana/src/photdbc/src/photdbc.c	(revision 38062)
@@ -10,5 +10,10 @@
 
   // the output catalog needs to inherit the SKY_DEPTH of the input catalog
-  sky = SkyTableLoadOptimal (CATDIR, NULL, NULL, TRUE, 0, VERBOSE);
+  sky = SkyTableLoadOptimal (CATDIR, NULL, NULL, FALSE, 0, VERBOSE);
+  if (!sky) {
+      fprintf (stderr, "ERROR loading sky table from %s\n", CATDIR);
+      exit (2);
+  }
+
   SkyTableSetFilenames (sky, CATDIR, "cpt");
   skylist = SkyListByPatch (sky, -1, &REGION);
Index: /trunk/Ohana/src/photdbc/src/photdbc_client.c
===================================================================
--- /trunk/Ohana/src/photdbc/src/photdbc_client.c	(revision 38061)
+++ /trunk/Ohana/src/photdbc/src/photdbc_client.c	(revision 38062)
@@ -6,7 +6,7 @@
 
   // load the current sky table (layout of all SkyRegions) 
-  SkyTable *sky = SkyTableLoadOptimal (CATDIR, NULL, NULL, TRUE, -1, VERBOSE);
+  SkyTable *sky = SkyTableLoadOptimal (CATDIR, NULL, NULL, FALSE, -1, VERBOSE);
   if (!sky) {
-      fprintf (stderr, "ERROR running loading sky table from %s\n", CATDIR);
+      fprintf (stderr, "ERROR loading sky table from %s\n", CATDIR);
       exit (2);
   }
Index: /trunk/Ohana/src/relastro/Makefile
===================================================================
--- /trunk/Ohana/src/relastro/Makefile	(revision 38061)
+++ /trunk/Ohana/src/relastro/Makefile	(revision 38062)
@@ -138,4 +138,5 @@
 $(SRC)/relastroVisual.$(ARCH).o \
 $(SRC)/syncfile.$(ARCH).o \
+$(SRC)/client_logger.$(ARCH).o \
 $(SRC)/BrightCatalog.$(ARCH).o 
 
Index: /trunk/Ohana/src/relastro/include/relastro.h
===================================================================
--- /trunk/Ohana/src/relastro/include/relastro.h	(revision 38061)
+++ /trunk/Ohana/src/relastro/include/relastro.h	(revision 38062)
@@ -9,4 +9,9 @@
 // # define IDX_T off_t
 # define IDX_T int 
+
+# define LOGRTIME(MSG,...) {				\
+    gettimeofday (&stopTimer, (void *) NULL);		\
+    float dtime = DTIME (stopTimer, startTimer);	\
+    client_logger_message (MSG, __VA_ARGS__); }
 
 typedef enum {
Index: /trunk/Ohana/src/relastro/src/BrightCatalog.c
===================================================================
--- /trunk/Ohana/src/relastro/src/BrightCatalog.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/BrightCatalog.c	(revision 38062)
@@ -91,4 +91,5 @@
     ALLOCATE (measure, MeasureTiny, Nrow);
     for (i = 0; i < Nrow; i++) {
+      memset (&measure[i], 0, sizeof(MeasureTiny));
       measure[i].R         = R[i];
       measure[i].D         = D[i];
@@ -111,4 +112,8 @@
       measure[i].catID     = catID[i];
       measure[i].photcode  = photcode[i];
+      measure[i].dXccd     = 0.0;
+      measure[i].dYccd     = 0.0;
+      measure[i].dRsys     = 0.0;
+      measure[i].myDet     = 0;
     }
     // fprintf (stderr, "loaded data for %lld measures\n", (long long) Nrow);
@@ -344,6 +349,8 @@
   /*** MeasureTiny ***/
   {
+    ohana_memcheck_func (1);
     gfits_create_table_header (&theader, "BINTABLE", "MEASURE_TINY");
 
+    ohana_memcheck_func (1);
     gfits_define_bintable_column (&theader, "D", "RA",       "ra",                         "degrees", 1.0, 0.0);
     gfits_define_bintable_column (&theader, "D", "DEC",      "dec",                        "degrees", 1.0, 0.0);
@@ -368,5 +375,7 @@
 
     // generate the output array that carries the data
+    ohana_memcheck_func (1);
     gfits_create_table (&theader, &ftable);
+    ohana_memcheck_func (1);
 
     // create intermediate storage arrays
@@ -391,4 +400,5 @@
     int    *catID     ; ALLOCATE (catID    ,  int  ,  catalog->Nmeasure);
     short  *photcode  ; ALLOCATE (photcode ,  short,  catalog->Nmeasure);
+    ohana_memcheck_func (1);
 
     // assign the storage arrays
@@ -416,8 +426,11 @@
       photcode[i] = measure[i].photcode ;
     }
+    ohana_memcheck_func (1);
 
     // add the columns to the output array
     gfits_set_bintable_column (&theader, &ftable, "RA",   	R,         catalog->Nmeasure);
+    ohana_memcheck_func (1);
     gfits_set_bintable_column (&theader, &ftable, "DEC",  	D,         catalog->Nmeasure);
+    ohana_memcheck_func (1);
     gfits_set_bintable_column (&theader, &ftable, "ROFF_GAL",   RoffGAL,   catalog->Nmeasure);
     gfits_set_bintable_column (&theader, &ftable, "DOFF_GAL",   DoffGAL,   catalog->Nmeasure);
Index: /trunk/Ohana/src/relastro/src/FrameCorrection.c
===================================================================
--- /trunk/Ohana/src/relastro/src/FrameCorrection.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/FrameCorrection.c	(revision 38062)
@@ -56,6 +56,7 @@
   free (filename);
 
+  // XXX NOTE : do not apply correction for now.  let's just measure it and see how it evolves
   // Now apply the correction to all of the average.R,D values
-  FrameCorrectionApply (catalog, Ncatalog, set->frame, set->coords);
+  // FrameCorrectionApply (catalog, Ncatalog, set->frame, set->coords);
   FrameCorrectionSetFree(set);
 
Index: /trunk/Ohana/src/relastro/src/ImageOps.c
===================================================================
--- /trunk/Ohana/src/relastro/src/ImageOps.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/ImageOps.c	(revision 38062)
@@ -763,4 +763,6 @@
     ref[i].dMag = measure[0].dM;
     ref[i].dPos = GetAstromErrorTiny (&measure[0], ERROR_MODE_POS);
+    ref[i].ColorBlue = NAN;
+    ref[i].ColorRed = NAN;
 
     if ((DCR_BLUE_NSEC_POS >= 0) && (DCR_BLUE_NSEC_NEG >= -1)) {
Index: /trunk/Ohana/src/relastro/src/MeasPosIO.c
===================================================================
--- /trunk/Ohana/src/relastro/src/MeasPosIO.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/MeasPosIO.c	(revision 38062)
@@ -19,4 +19,6 @@
   MeasPos *measpos = NULL;
 
+  INITTIME;
+
   FILE *f = fopen (filename, "r");
   if (!f) {
@@ -46,4 +48,6 @@
   }
 
+  LOGRTIME("MeasPosLoad_init %s: %f sec\n", filename, dtime);
+
   // read the fits table bytes
   if (!gfits_fread_ftable_data (f, &ftable, FALSE)) {
@@ -52,4 +56,5 @@
   }
   fclose (f);
+  LOGRTIME("MeasPosLoad_read %s: %f sec\n", filename, dtime);
 
   // a bit annoying : we read the entire block of data, then extract the columns, then set the image structure values.
@@ -63,6 +68,9 @@
   GET_COLUMN (catID, 	 "CAT_ID",       int);
   GET_COLUMN (imageID, 	 "IMAGE_ID",     int);
+  LOGRTIME("MeasPosLoad_getcol %s: %f sec\n", filename, dtime);
 
   ALLOCATE (measpos, MeasPos, Nrow);
+  LOGRTIME("MeasPosLoad_alloc %s: %f sec\n", filename, dtime);
+
   for (i = 0; i < Nrow; i++) {
     measpos[i].R              = R    [i];
@@ -72,4 +80,6 @@
     measpos[i].imageID        = imageID[i];
   }
+  LOGRTIME("MeasPosLoad_convert %s: %f sec\n", filename, dtime);
+
   fprintf (stderr, "loaded data for %lld objects (* filters)\n", (long long) Nrow);
 
@@ -85,4 +95,5 @@
   gfits_free_header (&theader);
   gfits_free_table  (&ftable);
+  LOGRTIME("MeasPosLoad_cleanup %s: %f sec\n", filename, dtime);
 
   *nmeaspos = Nrow;
Index: /trunk/Ohana/src/relastro/src/UpdateChips.c
===================================================================
--- /trunk/Ohana/src/relastro/src/UpdateChips.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/UpdateChips.c	(revision 38062)
@@ -223,4 +223,7 @@
 
   // all threads are done, free the threads array and grab the info
+  for (i = 0; i < NTHREADS; i++) {
+    pthread_detach (threads[i]);
+  }
   free (threads);
   
Index: /trunk/Ohana/src/relastro/src/client_logger.c
===================================================================
--- /trunk/Ohana/src/relastro/src/client_logger.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/client_logger.c	(revision 38062)
@@ -27,4 +27,6 @@
 int client_logger_message (char *format,...) {
 
+  if (!logfile) return FALSE;
+
   va_list argp;
 
Index: /trunk/Ohana/src/relastro/src/load_catalogs.c
===================================================================
--- /trunk/Ohana/src/relastro/src/load_catalogs.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/load_catalogs.c	(revision 38062)
@@ -17,4 +17,5 @@
 
   if (VERBOSE) fprintf (stderr, "loading catalog data\n");
+  client_logger_message ("loading catalog data\n");
 
   ALLOCATE (catalog, Catalog, skylist[0].Nregions);
@@ -255,5 +256,8 @@
 
     BrightCatalog *bcatalog = BrightCatalogLoad (table->hosts[i].results);
-    assert (bcatalog);
+    if (!bcatalog) {
+      client_logger_message ("problem loading table from %s\n", table->hosts[i].hostname);
+      exit (2);
+    }
     
     BrightCatalogSplit (catalogs, bcatalog);
@@ -267,5 +271,4 @@
   Catalog *catalog = catalogs->catalog;
   *Ncatalog = catalogs->Ncatalog;
-  BrightCatalogSplitFree (catalogs);
 
   int Nmeasure = 0;
@@ -275,6 +278,8 @@
     Naverage += catalogs->catalog[i].Naverage;
   }
-
   fprintf (stderr, "loaded %d catalogs, using a total of %d stars (%d measures)\n", catalogs->Ncatalog, Naverage, Nmeasure);
+  client_logger_message ("loaded %d catalogs, using a total of %d stars (%d measures)\n", catalogs->Ncatalog, Naverage, Nmeasure);
+
+  BrightCatalogSplitFree (catalogs);
 
   return (catalog);
Index: /trunk/Ohana/src/relastro/src/relastro_parallel_images.c
===================================================================
--- /trunk/Ohana/src/relastro/src/relastro_parallel_images.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/relastro_parallel_images.c	(revision 38062)
@@ -22,6 +22,8 @@
   RegionHostTable *regionHosts = RegionHostTableLoad (CATDIR, REGION_FILE);
   int myHost = regionHosts->index[REGION_HOST_ID];
+  char *myHostName = regionHosts->hosts[myHost].hostname;
+
   RegionHostFindNeighbors (regionHosts, myHost);
-  client_logger_message ("started parallel images on %s\n", regionHosts->hosts[myHost].hostname);
+  client_logger_message ("started parallel images on %s\n", myHostName);
 
   // load the subset images belonging to this host
@@ -47,5 +49,5 @@
   }
   put_astrom_table (table);
-  client_logger_message ("loaded images on %s\n", regionHosts->hosts[myHost].hostname);
+  client_logger_message ("loaded images on %s\n", myHostName);
 
   // once we have read this table, we should remove it for repeat runs
@@ -62,10 +64,10 @@
 
   /* load catalog data from region files (hostID is 0 since we are not a client */
-  char *syncfile = make_filename (CATDIR, regionHosts->hosts[myHost].hostname, REGION_HOST_ID, "loadcat.sync");
+  char *syncfile = make_filename (CATDIR, myHostName, REGION_HOST_ID, "loadcat.sync");
   catalog = load_catalogs (skylist, &Ncatalog, TRUE, 0, NULL, syncfile);
   MARKTIME("-- load catalog data, host %d: %f sec\n", REGION_HOST_ID, dtime);
   free (syncfile);
   
-  client_logger_message ("loaded catalog data %s\n", regionHosts->hosts[myHost].hostname);
+  client_logger_message ("loaded catalog data %s\n", myHostName);
 
   // find ICRF QSOs for reference downstream (only if USE_ICRF_CORRECT)
@@ -90,5 +92,5 @@
   createStarMap (catalog, Ncatalog);
 
-  client_logger_message ("set up image indexes on %s\n", regionHosts->hosts[myHost].hostname);
+  client_logger_message ("set up image indexes on %s\n", myHostName);
 
   markObjects (catalog, Ncatalog);
@@ -96,5 +98,5 @@
   SAVEPLOT = FALSE;
 
-  client_logger_message ("starting the loops: %s\n", regionHosts->hosts[myHost].hostname);
+  client_logger_message ("starting the loops: %s\n", myHostName);
 
   /* major modes */
@@ -114,34 +116,33 @@
       if (RESET_IMAGES) {
 	UpdateMeasures (catalog, Ncatalog);
-	MARKTIME("reset measures, host %d: %f sec\n", REGION_HOST_ID, dtime);
-	client_logger_message ("reset measures: %s\n", regionHosts->hosts[myHost].hostname);
+	MARKTIME("UpdateMeasures on %s, host %d: %f sec\n", myHostName, REGION_HOST_ID, dtime);
+	LOGRTIME("UpdateMeasures on %s, host %d: %f sec\n", myHostName, REGION_HOST_ID, dtime);
       }
       for (i = 0; i < NLOOP; i++) {
 	UpdateObjects (catalog, Ncatalog, (i > 0));
-	MARKTIME("update objects loop %d, host %d: %f sec\n", i, REGION_HOST_ID, dtime);
-	client_logger_message ("update objects loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);
+	LOGRTIME("UpdateObjects loop %d on %s, host %d: %f sec\n", i, myHostName, REGION_HOST_ID, dtime);
 	if ((i > 1) || !USE_GALAXY_MODEL) {
 	  // if GALAXY_MODEL is selected, we want to delay the frame correction until we have 
 	  // applied the galaxy model a couple of times.
 	  FrameCorrectionParallelSlave (catalog, Ncatalog, regionHosts, i); 
-	  MARKTIME("frame correction loop %d, host %d: %f sec\n", i, REGION_HOST_ID, dtime);
-	  client_logger_message ("frame correction loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);
+	  LOGRTIME("FrameCorrection loop %d on %s, host %d: %f sec\n", i, myHostName, REGION_HOST_ID, dtime);
 	}
 	share_mean_pos (catalog, Ncatalog, regionHosts, i);
+	LOGRTIME("share_mean_pos loop %d on %s, host %d: %f sec\n", i, myHostName, REGION_HOST_ID, dtime);
 	slurp_mean_pos (catalog, Ncatalog, regionHosts, i);
-	client_logger_message ("slurp mags loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);
+	LOGRTIME("slurp_mean_pos loop %d on %s, host %d: %f sec\n", i, myHostName, REGION_HOST_ID, dtime);
 
 	UpdateChips (catalog, Ncatalog);
-	MARKTIME("update chips loop %d, host %d: %f sec\n", i, REGION_HOST_ID, dtime);
-	client_logger_message ("update chips loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);
+	LOGRTIME("UpdateChips loop %d on %s, host %d: %f sec\n", i, myHostName, REGION_HOST_ID, dtime);
 
 	share_image_pos (regionHosts, i);
+	LOGRTIME("share_image_pos loop on %d on %s, host %d: %f sec\n", i, myHostName, REGION_HOST_ID, dtime);
 	slurp_image_pos (catalog, Ncatalog, regionHosts, i);
-	client_logger_message ("slurp image pos loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);
+	LOGRTIME("slurp_image_pos loop on %d on %s, host %d: %f sec\n", i, myHostName, REGION_HOST_ID, dtime);
 
 	share_meas_pos (catalog, Ncatalog, regionHosts, i);
+	LOGRTIME("share_meas_pos loop %d on %s, host %d: %f sec\n", i, myHostName, REGION_HOST_ID, dtime);
 	slurp_meas_pos (catalog, Ncatalog, regionHosts, i);
-	MARKTIME("done exchange loop %d, host %d: %f sec\n", i, REGION_HOST_ID, dtime);
-	client_logger_message ("slurp meas loop %d: %s\n", i, regionHosts->hosts[myHost].hostname);
+	LOGRTIME("slurp_meas_pos loop %d on %s, host %d: %f sec\n", i, myHostName, REGION_HOST_ID, dtime);
       }
       // create summary plots of the process
@@ -166,5 +167,5 @@
 
   // this is a checkpoint to make sure all hosts have finished the loop above
-  char *loopsyncfile = make_filename (CATDIR, regionHosts->hosts[myHost].hostname, REGION_HOST_ID, "loop.sync");
+  char *loopsyncfile = make_filename (CATDIR, myHostName, REGION_HOST_ID, "loop.sync");
   update_sync_file (loopsyncfile, 0);
   free (loopsyncfile);
@@ -178,5 +179,5 @@
 
   share_image_pos (regionHosts, -1);
-  client_logger_message ("share image pos loop %d: %s\n", -1, regionHosts->hosts[myHost].hostname);
+  LOGRTIME("share image pos loop %d on %s, host %d: %f sec\n", -1, myHostName, REGION_HOST_ID, dtime);
 
   exit (0);
Index: /trunk/Ohana/src/relastro/src/share_images_pos.c
===================================================================
--- /trunk/Ohana/src/relastro/src/share_images_pos.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/share_images_pos.c	(revision 38062)
@@ -51,4 +51,5 @@
 }
 
+static char *masterHost = "master";
 int slurp_image_pos (Catalog *catalog, int Ncatalog, RegionHostTable *regionHosts, int nloop) {
 
@@ -60,6 +61,11 @@
   ALLOCATE (image_pos, ImagePos, 1);
 
+  INITTIME;
+  int myHost = regionHosts->index[REGION_HOST_ID];
+  char *myHostName = (myHost == -1) ? masterHost : regionHosts->hosts[myHost].hostname;
+
   fprintf (stderr, "grabbing image mags from other hosts...\n");
 
+  LOGRTIME("image_load_start loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
   for (i = 0; i < regionHosts->Nhosts; i++) {
     if (regionHosts->hosts[i].hostID == REGION_HOST_ID) continue;
@@ -69,4 +75,5 @@
     check_sync_file (syncfile, nloop);
     free (syncfile);
+    LOGRTIME("image_load_sync host %d loop %d on %s, host %d: %f sec\n", i, nloop, myHostName, REGION_HOST_ID, dtime);
     
     off_t Nsubset;
@@ -74,6 +81,8 @@
     ImagePos *image_pos_subset = ImagePosLoad (iposfile, &Nsubset);
     free (iposfile);
+    LOGRTIME("image_load_read host %d loop %d on %s, host %d: %f sec\n", i, nloop, myHostName, REGION_HOST_ID, dtime);
 
     image_pos = merge_image_pos (image_pos, &Nimage_pos, image_pos_subset, Nsubset);
+    LOGRTIME("image_load_merge host %d loop %d on %s, host %d: %f sec\n", i, nloop, myHostName, REGION_HOST_ID, dtime);
   }
 
@@ -96,4 +105,5 @@
     images[seq].flags        = image_pos[i].flags     ;
   }
+  LOGRTIME("image_load_convert loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   // load the astrometry offset maps, if they exist, and apply 
@@ -106,4 +116,5 @@
     
     AstromOffsetTable *table = AstromOffsetMapLoad (mapname, VERBOSE);
+    LOGRTIME("image_maps_load host %d loop %d on %s, host %d: %f sec\n", i, nloop, myHostName, REGION_HOST_ID, dtime);
   
     // apply table entries here to existing images
@@ -127,5 +138,8 @@
       }
     }
+    LOGRTIME("image_maps_copy host %d loop %d on %s, host %d: %f sec\n", i, nloop, myHostName, REGION_HOST_ID, dtime);
+
     AstromOffsetTableFree(table);
+    LOGRTIME("image_maps_free host %d loop %d on %s, host %d: %f sec\n", i, nloop, myHostName, REGION_HOST_ID, dtime);
   }
 
@@ -137,4 +151,5 @@
   }
   free (image_pos);
+  LOGRTIME("image_load_apply loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   fprintf (stderr, "DONE grabbing image mags from other hosts\n");
Index: /trunk/Ohana/src/relastro/src/share_mean_pos.c
===================================================================
--- /trunk/Ohana/src/relastro/src/share_mean_pos.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/share_mean_pos.c	(revision 38062)
@@ -15,8 +15,12 @@
 
   int myHost = regionHosts->index[REGION_HOST_ID];
+  char *myHostName = regionHosts->hosts[myHost].hostname;
+
   double Rmin = regionHosts->hosts[myHost].Rmin;
   double Rmax = regionHosts->hosts[myHost].Rmax;
   double Dmin = regionHosts->hosts[myHost].Dmin;
   double Dmax = regionHosts->hosts[myHost].Dmax;
+
+  INITTIME;
 
   // XXX skip some catalogs based on UserPatch?
@@ -40,4 +44,5 @@
     }
   }
+  LOGRTIME("set_mean_pos loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   // write out the meanmag fits table AND write state in some file
@@ -48,8 +53,10 @@
   free (meanpos);
   free (posfile);
+  LOGRTIME("MeanPosSave loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   char *syncfile = make_filename (CATDIR, hostname, REGION_HOST_ID, "meanpos.sync");
   update_sync_file (syncfile, nloop);
   free (syncfile);
+  LOGRTIME("update_sync_file loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   return TRUE;
@@ -64,5 +71,10 @@
   ALLOCATE (meanpos, MeanPos, 1);
 
+  int myHost = regionHosts->index[REGION_HOST_ID];
+  char *myHostName = regionHosts->hosts[myHost].hostname;
+
   fprintf (stderr, "grabbing mean object pos from other hosts...\n");
+
+  INITTIME;
 
   for (i = 0; i < regionHosts->Nhosts; i++) {
@@ -82,4 +94,5 @@
     meanpos = merge_mean_pos (meanpos, &Nmeanpos, meanposSubset, Nsubset);
   }
+  LOGRTIME("MeanPosLoad/merge_mean_pos loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   for (i = 0; i < Nmeanpos; i++) {
@@ -99,4 +112,5 @@
   }
   free (meanpos);
+  LOGRTIME("match_catID_and_objID loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   fprintf (stderr, "DONE grabbing mean object pos from other hosts...\n");
Index: /trunk/Ohana/src/relastro/src/share_meas_pos.c
===================================================================
--- /trunk/Ohana/src/relastro/src/share_meas_pos.c	(revision 38061)
+++ /trunk/Ohana/src/relastro/src/share_meas_pos.c	(revision 38062)
@@ -14,5 +14,7 @@
   ALLOCATE (measpos, MeasPos, NMEASPOS);
 
+  INITTIME;
   int myHost = regionHosts->index[REGION_HOST_ID];
+  char *myHostName = regionHosts->hosts[myHost].hostname;
 
   // XXX skip some catalogs based on UserPatch?
@@ -33,4 +35,5 @@
     }
   }
+  LOGRTIME("set_meas_pos loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   // write out the measmag fits table AND write state in some file
@@ -41,8 +44,10 @@
   free (measpos);
   free (posfile);
+  LOGRTIME("MeasPosSave loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   char *syncfile = make_filename (CATDIR, hostname, REGION_HOST_ID, "measpos.sync");
   update_sync_file (syncfile, nloop);
   free (syncfile);
+  LOGRTIME("update_sync_file loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   return TRUE;
@@ -59,4 +64,9 @@
   fprintf (stderr, "grabbing meas object pos from other hosts...\n");
 
+  INITTIME;
+  int myHost = regionHosts->index[REGION_HOST_ID];
+  char *myHostName = regionHosts->hosts[myHost].hostname;
+
+  LOGRTIME("meas_load_start loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
   for (i = 0; i < regionHosts->Nhosts; i++) {
     if (regionHosts->hosts[i].hostID == REGION_HOST_ID) continue;
@@ -66,4 +76,5 @@
     check_sync_file (syncfile, nloop);
     free (syncfile);
+    LOGRTIME("meas_load_sync host %d loop %d on %s, host %d: %f sec\n", i, nloop, myHostName, REGION_HOST_ID, dtime);
     
     off_t Nsubset = 0;
@@ -71,8 +82,11 @@
     MeasPos *measposSubset = MeasPosLoad (posfile, &Nsubset);
     free (posfile);
+    LOGRTIME("MeasPosLoad host %d loop %d on %s, host %d: %f sec\n", i, nloop, myHostName, REGION_HOST_ID, dtime);
 
     // merge_meas_pos reallocs measpos and frees the input measposSubset
     measpos = merge_meas_pos (measpos, &Nmeaspos, measposSubset, Nsubset);
+    LOGRTIME("merge_meas_pos host %d loop %d on %s, host %d: %f sec\n", i, nloop, myHostName, REGION_HOST_ID, dtime);
   }
+  LOGRTIME("meas_load_done loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   for (i = 0; i < Nmeaspos; i++) {
@@ -99,4 +113,5 @@
   }
   free (measpos);
+  LOGRTIME("match_catID_and_objID/meas loop %d on %s, host %d: %f sec\n", nloop, myHostName, REGION_HOST_ID, dtime);
 
   fprintf (stderr, "DONE grabbing meas object pos from other hosts...\n");
Index: /trunk/Ohana/src/relphot/Makefile
===================================================================
--- /trunk/Ohana/src/relphot/Makefile	(revision 38061)
+++ /trunk/Ohana/src/relphot/Makefile	(revision 38062)
@@ -50,4 +50,7 @@
 $(SRC)/relphot_parallel_regions.$(ARCH).o \
 $(SRC)/relphot_parallel_images.$(ARCH).o \
+$(SRC)/relphot_synthphot.$(ARCH).o	 \
+$(SRC)/relphot_synthphot_catalog.$(ARCH).o	 \
+$(SRC)/synthetic_zpts.$(ARCH).o	 \
 $(SRC)/select_images.$(ARCH).o	 \
 $(SRC)/assign_images.$(ARCH).o	 \
@@ -93,4 +96,7 @@
 $(SRC)/relphot_objects.$(ARCH).o	 \
 $(SRC)/relphot_client.$(ARCH).o	 \
+$(SRC)/relphot_synthphot.$(ARCH).o	 \
+$(SRC)/relphot_synthphot_catalog.$(ARCH).o	 \
+$(SRC)/synthetic_zpts.$(ARCH).o	 \
 $(SRC)/client_logger.$(ARCH).o	 \
 $(SRC)/setExclusions.$(ARCH).o 	 \
Index: /trunk/Ohana/src/relphot/include/relphot.h
===================================================================
--- /trunk/Ohana/src/relphot/include/relphot.h	(revision 38061)
+++ /trunk/Ohana/src/relphot/include/relphot.h	(revision 38062)
@@ -22,4 +22,5 @@
   PARALLEL_IMAGES,
   APPLY_OFFSETS,
+  SYNTH_PHOT,
 } RelphotMode;
 
@@ -29,5 +30,26 @@
     MODE_UPDATE = 2,
     MODE_UPDATE_OBJECTS = 3,
+    MODE_SYNTH_PHOT = 4,
 } ModeType;
+
+// NOTE: this is only used in special cases where we limit photcode ranges
+typedef enum {
+  PS1_none, 
+  PS1_g = 1, 
+  PS1_r = 2, 
+  PS1_i = 3, 
+  PS1_z = 4, 
+  PS1_y = 5,
+  PS1_w = 6,
+} PS1filters;
+
+typedef struct {
+  Header PHU;
+  Header header[5]; // grizy (matches Nsec in photcodes)
+  Matrix matrix[5];
+  Coords coords;
+  int Nx;
+  int Ny;
+} SynthZeroPoints;
 
 typedef struct {
@@ -175,4 +197,5 @@
 char   SKY_TABLE[DVO_MAX_PATH];
 int    SKY_DEPTH;  /** XXX EAM : depth of catalog tables, fix usage */
+char  *SYNTH_ZERO_POINTS;
 
 // globals for parallel region operations
@@ -509,4 +532,13 @@
 int isGPC1stack (int photcode);
 int isGPC1warp  (int photcode);
-
-
+int isGPC1synth (int photcode);
+int whichGPC1filter (int photcode);
+
+
+SynthZeroPoints *SynthZeroPointsLoad (char *filename);
+
+int relphot_synthphot (int hostID, char *hostpath);
+int relphot_synthphot_parallel (SkyList *sky);
+
+int relphot_synthphot_catalog (Catalog *catalog, SynthZeroPoints *zpts);
+int relphot_synthphot_average (Average *average, SecFilt *secfilt, Measure *measure, SynthZeroPoints *zpts);
Index: /trunk/Ohana/src/relphot/src/args.c
===================================================================
--- /trunk/Ohana/src/relphot/src/args.c	(revision 38061)
+++ /trunk/Ohana/src/relphot/src/args.c	(revision 38062)
@@ -372,4 +372,12 @@
     mode = UPDATE_AVERAGES;
   }
+  SYNTH_ZERO_POINTS = NULL;
+  if ((N = get_argument (argc, argv, "-synthphot_means"))) {
+    mode = SYNTH_PHOT;
+    remove_argument (N, &argc, argv);
+    myAssert (N < argc, "missing argument to -synthphot_means");
+    SYNTH_ZERO_POINTS = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
   if ((N = get_argument (argc, argv, "-apply-offsets"))) {
     remove_argument (N, &argc, argv);
@@ -398,4 +406,5 @@
 
   switch (mode) {
+    case SYNTH_PHOT:
     case UPDATE_AVERAGES:
       if (argc != 1) relphot_usage();
@@ -471,4 +480,11 @@
     }
     MODE = MODE_UPDATE_OBJECTS;
+    remove_argument (N, &argc, argv);
+  }
+  SYNTH_ZERO_POINTS = NULL;
+  if ((N = get_argument (argc, argv, "-synthphot_means"))) {
+    MODE = MODE_SYNTH_PHOT;
+    remove_argument (N, &argc, argv);
+    SYNTH_ZERO_POINTS = strcreate (argv[N]);
     remove_argument (N, &argc, argv);
   }
@@ -644,4 +660,5 @@
   }
 
+  if ((MODE == MODE_SYNTH_PHOT)  && (argc == 1)) return TRUE;
   if ((MODE == MODE_UPDATE_OBJECTS)  && (argc == 1)) return TRUE;
   if (argc != 2) relphot_client_usage ();
Index: /trunk/Ohana/src/relphot/src/extra.c
===================================================================
--- /trunk/Ohana/src/relphot/src/extra.c	(revision 38061)
+++ /trunk/Ohana/src/relphot/src/extra.c	(revision 38062)
@@ -1,3 +1,16 @@
 # include "relphot.h"
+
+// for now (20140710) I need to identify gpc1 chips explicitly.  generalize in the future
+int whichGPC1filter (int photcode) {
+
+  if ((photcode > 10000) && (photcode < 10077)) return PS1_g; // g-band
+  if ((photcode > 10100) && (photcode < 10177)) return PS1_r; // r-band
+  if ((photcode > 10200) && (photcode < 10277)) return PS1_i; // i-band
+  if ((photcode > 10300) && (photcode < 10377)) return PS1_z; // z-band
+  if ((photcode > 10400) && (photcode < 10477)) return PS1_y; // y-band
+  if ((photcode > 10500) && (photcode < 10577)) return PS1_w; // w-band
+
+  return PS1_none;
+}
 
 // for now (20140710) I need to identify gpc1 chips explicitly.  generalize in the future
@@ -50,2 +63,9 @@
   return FALSE;
 }
+
+int isGPC1synth (int photcode) {
+
+  if ((photcode >= 3001) && (photcode <= 3006)) return TRUE; // g-band
+
+  return FALSE;
+}
Index: /trunk/Ohana/src/relphot/src/help.c
===================================================================
--- /trunk/Ohana/src/relphot/src/help.c	(revision 38061)
+++ /trunk/Ohana/src/relphot/src/help.c	(revision 38062)
@@ -5,4 +5,5 @@
   fprintf (stderr, "       or:    relphot -averages\n");
   fprintf (stderr, "       or:    relphot -apply-offsets\n");
+  fprintf (stderr, "       or:    relphot -synthphot_means\n");
   fprintf (stderr, "       or:    relphot (photcodes) -parallel-regions -region-hosts (RegionFile)\n");
   fprintf (stderr, "       or:    relphot (photcodes) -parallel-images (ImageTable) -region-hosts (RegionFile)\n\n");
Index: /trunk/Ohana/src/relphot/src/initialize.c
===================================================================
--- /trunk/Ohana/src/relphot/src/initialize.c	(revision 38061)
+++ /trunk/Ohana/src/relphot/src/initialize.c	(revision 38062)
@@ -97,4 +97,6 @@
   args_client (argc, argv);
 
+  if (MODE == MODE_SYNTH_PHOT) return;
+
   if (MODE == MODE_UPDATE_OBJECTS) {
     char tmpline1[256];
Index: /trunk/Ohana/src/relphot/src/relphot.c
===================================================================
--- /trunk/Ohana/src/relphot/src/relphot.c	(revision 38061)
+++ /trunk/Ohana/src/relphot/src/relphot.c	(revision 38062)
@@ -17,4 +17,9 @@
       // DOES NOT LOAD THE IMAGE TABLE
       relphot_objects (0, NULL);
+      exit (0);
+
+    case SYNTH_PHOT:
+      // set the mean magnitudes ONLY for SYNPHOT objects
+      relphot_synthphot (0, NULL);
       exit (0);
 
Index: /trunk/Ohana/src/relphot/src/relphot_client.c
===================================================================
--- /trunk/Ohana/src/relphot/src/relphot_client.c	(revision 38061)
+++ /trunk/Ohana/src/relphot/src/relphot_client.c	(revision 38062)
@@ -87,4 +87,10 @@
     }
 
+    case MODE_SYNTH_PHOT:
+      // set the mean magnitudes ONLY for SYNPHOT objects
+      relphot_synthphot (HOST_ID, HOSTDIR);
+      client_logger_message ("set synth photometry\n");
+      break;
+
     default:
       fprintf (stderr, "impossible!");
Index: /trunk/Ohana/src/relphot/src/relphot_synthphot.c
===================================================================
--- /trunk/Ohana/src/relphot/src/relphot_synthphot.c	(revision 38062)
+++ /trunk/Ohana/src/relphot/src/relphot_synthphot.c	(revision 38062)
@@ -0,0 +1,151 @@
+# include "relphot.h"
+
+// 1) Look for objects which have only synthetic photometry for any of the grizy filters.
+// 2) apply spatial zero point offsets to synth photometry, then set mean mag based on synth.
+
+int relphot_synthphot_parallel (SkyList *sky);
+
+int relphot_synthphot (int hostID, char *hostpath) {
+
+  off_t i;
+
+  SkyTable *sky = NULL;
+  SkyList *skylist = NULL;
+  Catalog catalog;
+
+  // load the current sky table (layout of all SkyRegions) 
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  // determine the populated SkyRegions overlapping the requested area (default depth)
+  skylist = SkyListByPatch (sky, -1, &UserPatch);
+
+  // XXX need to decide how to determine PARALLEL mode...
+  if (PARALLEL && !hostID) {
+    relphot_synthphot_parallel (skylist);
+    return TRUE;
+  }
+
+  // load the ZP corrections here
+  SynthZeroPoints *zpts = SynthZeroPointsLoad (SYNTH_ZERO_POINTS);
+  if (!zpts) exit (2);
+
+  // load data from each region file, only use bright stars
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // does this host ID match the desired location for the table?
+    if (!HostTableTestHost(skylist[0].regions[i], hostID)) continue;
+
+    // set up the basic catalog info
+    char hostfile[1024];
+    snprintf (hostfile, 1024, "%s/%s.cpt", hostpath, skylist[0].regions[i]->name);
+    catalog.filename  = hostID ? hostfile : skylist[0].filename[i];
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);    // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);        // set the default catmode from config data
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", catalog.filename);
+      exit (1);
+    }
+    if (!catalog.Naves_disk) {
+      if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    relphot_synthphot_catalog (&catalog, zpts);
+
+    if (!UPDATE) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+    
+    if (VERBOSE) fprintf (stderr, "saving catalog %s\n", catalog.filename);
+    
+    // we can optionally convert output format here
+    // but it would be better to define a dvo crawler program to do this
+    // catalog.catformat = DVO_FORMAT_PS1_V1;  
+    dvo_catalog_save (&catalog, VERBOSE); 
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+  
+  return (TRUE);
+}
+
+// CATDIR is supplied globally
+# define DEBUG 1
+int relphot_synthphot_parallel (SkyList *sky) {
+
+  // launch the setphot_client jobs to the parallel hosts
+
+  // load the list of hosts
+  HostTable *table = HostTableLoad (CATDIR, sky->hosts);
+  if (!table) {
+    fprintf (stderr, "ERROR: failure reading Host Table %s for database %s\n", sky->hosts, CATDIR);
+    exit (1);
+  }    
+
+  // ensure that the path for the zero point is absolute
+  { 
+    char *tmppath = abspath (SYNTH_ZERO_POINTS, DVO_MAX_PATH);
+    free (SYNTH_ZERO_POINTS);
+    SYNTH_ZERO_POINTS = tmppath;
+  }
+
+  int i;
+  for (i = 0; i < table->Nhosts; i++) {
+
+    // ensure that the paths are absolute path names
+    char *tmppath = abspath (table->hosts[i].pathname, DVO_MAX_PATH);
+    free (table->hosts[i].pathname);
+    table->hosts[i].pathname = tmppath;
+
+    // options / arguments that can affect relphot_client -synthphot_means:
+    // VERBOSE, VERBOSE2
+
+    char command[1024];
+    snprintf (command, 1024, "relphot_client -synthphot_means %s -hostID %d -D CATDIR %s -hostdir %s -region %f %f %f %f", 
+	      SYNTH_ZERO_POINTS, table->hosts[i].hostID, CATDIR, table->hosts[i].pathname, UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax);
+
+    char tmpline[1024];
+    if (VERBOSE)       { snprintf (tmpline, 1024, "%s -v",              command);                    strcpy (command, tmpline); }
+    if (VERBOSE2)      { snprintf (tmpline, 1024, "%s -vv",             command); 		     strcpy (command, tmpline); }
+    if (UPDATE)        { snprintf (tmpline, 1024, "%s -update",         command); 		     strcpy (command, tmpline); }
+
+    fprintf (stderr, "command: %s\n", command);
+
+    if (PARALLEL_MANUAL) continue;
+
+    if (PARALLEL_SERIAL) {
+      int status = system (command);
+      if (status) {
+	fprintf (stderr, "ERROR running relphot_client\n");
+	exit (2);
+      }
+    } else {
+      // launch the job on the remote machine (no handshake)
+      int errorInfo = 0;
+      int pid = rconnect ("ssh", table->hosts[i].hostname, command, table->hosts[i].stdio, &errorInfo, FALSE);
+      if (!pid) {
+	if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", table->hosts[i].hostname, errorInfo);
+	exit (1);
+      }
+      table->hosts[i].pid = pid; // save for future reference
+    }
+  }
+
+  if (PARALLEL_MANUAL) {
+    fprintf (stderr, "run the relphot_client commands above.  when these are done, hit return\n");
+    getchar();
+  }
+  if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
+    HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+  }
+
+  return TRUE;
+}      
Index: /trunk/Ohana/src/relphot/src/relphot_synthphot_catalog.c
===================================================================
--- /trunk/Ohana/src/relphot/src/relphot_synthphot_catalog.c	(revision 38062)
+++ /trunk/Ohana/src/relphot/src/relphot_synthphot_catalog.c	(revision 38062)
@@ -0,0 +1,103 @@
+# include "relphot.h"
+
+// we've just reloaded the data from disk; we now need to apply the Image/Mosaic/Grid
+// calibrations determined by the rest of the program.  We also need to set the final
+// output dbFlags values
+
+int relphot_synthphot_catalog (Catalog *catalog, SynthZeroPoints *zpts) {
+
+  off_t j;
+
+  int Nsecfilt = catalog[0].Nsecfilt;
+
+  for (j = 0; j < catalog[0].Naverage; j++) {
+    off_t m = catalog[0].average[j].measureOffset;
+    Average *average = &catalog[0].average[j];
+    Measure *measure = &catalog[0].measure[m];
+    SecFilt *secfilt = &catalog[0].secfilt[j*Nsecfilt];
+
+    relphot_synthphot_average (average, secfilt, measure, zpts);
+  }
+  return TRUE;
+}
+
+// set mean of chip measurements (selected by photcode range for now):
+int relphot_synthphot_average (Average *average, SecFilt *secfilt, Measure *measure, SynthZeroPoints *zpts) {
+
+  int i;
+  off_t k;
+
+  // first, determine the state of things for each of the main filters:
+  // in this bit, we are using hardwired photcode values:
+  // PS1_g, PS1_r, PS1_i, PS1_z, PS1_y, PS1_w == (1,2,3,4,5,6); 0 == none
+  // note that Nsec = PS_N - 1
+
+  int havePS1[7];
+  int haveSYN[7];
+  int needSYN[7];
+  int measSYN[7];
+
+  // was: 13.64, 13.76, 13.74, 12.94, 12.01
+  float MaxMagForceSynth[] = {0.0, 13.5, 13.5, 13.5, 13.0, 12.0, 13.5};
+
+  for (i = 0; i < 7; i++) {
+    havePS1[i] = FALSE; // do we have any PS1 measurement for this filter?
+    haveSYN[i] = FALSE; // do we have any synthetic measurement for this filter?
+    needSYN[i] = FALSE; // force the use of the synthetic measurement for this filter?
+    measSYN[i] = -1; // which entries carries the synthetic measurement for this filter?
+  }
+
+  // need to look up the (X,Y) coords from this (R,D) location
+  double X, Y;
+  double R = ohana_normalize_angle_to_midpoint (average->R, 0.0);
+  RD_to_XY (&X, &Y, R, average->D, &zpts->coords);
+  if (X < 0) return FALSE;
+  if (Y < 0) return FALSE;
+  if (X >= zpts->Nx) return FALSE;
+  if (Y >= zpts->Ny) return FALSE;
+
+  int Xpix = X;
+  int Ypix = Y;
+  int Npix = Xpix + Ypix*zpts->Nx;
+
+  for (k = 0; k < average[0].Nmeasure; k++) {
+
+    // skip measurements that do not have a valid photcode
+    PhotCode *code = GetPhotcodebyCode (measure[k].photcode);
+    if (!code) continue;
+
+    // is this synth_grizy?
+    // is this PS1?
+
+    // are we a PS1 exposure photcode?
+    if (isGPC1chip(measure[k].photcode)) {
+      int Nfilter = whichGPC1filter (measure[k].photcode);
+      havePS1[Nfilter] = TRUE;
+    }
+    if (isGPC1synth(measure[k].photcode)) {
+      int Nfilter = measure[k].photcode - 3000;
+      haveSYN[Nfilter] = TRUE;
+      measSYN[Nfilter] = k;
+
+      // force the use of SYN even if we have PS1 mags?
+      if (measure[k].M < MaxMagForceSynth[Nfilter]) {
+	needSYN[Nfilter] = TRUE;
+      } 
+    }
+  }
+
+  for (i = 1; i < 6; i++) {
+    if (needSYN[i] || (haveSYN[i] && !havePS1[i])) {
+      int Nsec = i - 1;
+      float *value = (float *) zpts->matrix[Nsec].buffer;
+      float ZP = !isnan(value[Npix]) ? value[Npix] : 0.0;
+      secfilt[Nsec].M  	 = measure[measSYN[i]].M + ZP;
+      secfilt[Nsec].dM 	 = 0.6;
+      secfilt[Nsec].Mchisq = NAN;
+      secfilt[Nsec].flags |= ID_SECF_USE_SYNTH;
+    }
+  }
+
+  return (TRUE);
+}
+
Index: /trunk/Ohana/src/relphot/src/synthetic_zpts.c
===================================================================
--- /trunk/Ohana/src/relphot/src/synthetic_zpts.c	(revision 38062)
+++ /trunk/Ohana/src/relphot/src/synthetic_zpts.c	(revision 38062)
@@ -0,0 +1,53 @@
+# include "relphot.h"
+
+// the PS1 Synthetic magnitudes (Pitts & Magnier) have known systematic errors due to the
+// POSS plate photometry.  This file contains support code to correct that error based on
+// sky maps of the mean offsets.
+
+static char *extname[5] = {"map_g", "map_r", "map_i", "map_z", "map_y"};
+
+SynthZeroPoints *SynthZeroPointsLoad (char *filename) {
+
+  FILE *f = fopen (filename, "r");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open file %s\n", filename);
+    return NULL;
+  }
+
+  // SynthZeroPoint file contains:
+  // PHU header (including WCS)
+  // map_g
+  // map_r
+  // map_i
+  // map_z
+  // map_y
+
+  SynthZeroPoints *zpts = NULL;
+  ALLOCATE (zpts, SynthZeroPoints, 1);
+  
+  if (!gfits_fread_header (f, &zpts->PHU)) {
+    if (VERBOSE) fprintf (stderr, "can't read header\n");
+    fclose (f);
+    return NULL;
+  }
+
+  int i;
+  for (i = 0; i < 5; i++) {
+    if (!gfits_find_Xheader(f, &zpts->header[i], extname[i])) {
+      fprintf (stderr, "ERROR: file %s is missing extension %s\n", filename, extname[i]);
+      exit (2);
+    }
+
+    if (!gfits_fread_matrix (f, &zpts->matrix[i], &zpts->header[i])) {
+      if (VERBOSE) fprintf (stderr, "can't read image for %s\n", extname[i]);
+      exit (2);
+    }
+  }
+
+  GetCoords (&zpts->coords, &zpts->PHU);
+  zpts->Nx = zpts->matrix[0].Naxis[0];
+  zpts->Ny = zpts->matrix[0].Naxis[1];
+
+  return zpts;
+}
+
Index: /trunk/Ohana/src/uniphot/Makefile
===================================================================
--- /trunk/Ohana/src/uniphot/Makefile	(revision 38061)
+++ /trunk/Ohana/src/uniphot/Makefile	(revision 38062)
@@ -112,4 +112,5 @@
 $(SRC)/setastrom.$(ARCH).o	    \
 $(SRC)/initialize_setastrom.$(ARCH).o \
+$(SRC)/cam_correction.$(ARCH).o \
 $(SRC)/dcr_correction.$(ARCH).o \
 $(SRC)/kh_correction.$(ARCH).o \
@@ -127,4 +128,5 @@
 $(SRC)/update_dvo_setastrom.$(ARCH).o \
 $(SRC)/update_catalog_setastrom.$(ARCH).o \
+$(SRC)/cam_correction.$(ARCH).o \
 $(SRC)/dcr_correction.$(ARCH).o \
 $(SRC)/kh_correction.$(ARCH).o \
Index: /trunk/Ohana/src/uniphot/include/setastrom.h
===================================================================
--- /trunk/Ohana/src/uniphot/include/setastrom.h	(revision 38061)
+++ /trunk/Ohana/src/uniphot/include/setastrom.h	(revision 38062)
@@ -10,4 +10,25 @@
   double *y2;
 } Spline;
+
+// we have one correction (an image) for each filter and chip
+typedef struct {
+  int Nx;       // number of chips in x
+  int Ny;       // number of chips in y
+  int Nfilter;  // number of filters
+  int Ndir;     // number of correction dimensions
+
+  int Nchips;	// chip offset (Nx*Ny)
+  int Ngroup;	// direction offset (Nx*Ny*Nfilters)
+  int Nvalues;  // Nx*Ny*Nfilters*Ndir
+
+  int dX;       // superpixel size
+  int dY;	// superpixel size
+
+  int NxCCD;	// number of pixels
+  int NyCCD;	// number of pixels
+
+  Matrix **matrix; // allocate an array of pointers
+  // index = ix + iy*Nx + filter*Nchips + dir*Ngroup
+} CamCorrection;
 
 /* global variables set in parameter file */
@@ -27,7 +48,9 @@
 char        *KH_FILE;
 char        *DCR_FILE;
+char        *CAM_FILE;
 
 int          KH_RESET;
 int          DCR_RESET;
+int          CAM_RESET;
 
 SkyRegion    UserPatch;
@@ -65,2 +88,5 @@
 int load_dcr_correction (char *filename);
 int get_dcr_correction (int filter, double *dX, double *dY, float Color);
+
+int load_cam_correction (char *filename);
+int get_cam_correction (int chipID, int filter, float Xccd, float Yccd, double *dX, double *dY);
Index: /trunk/Ohana/src/uniphot/src/cam_correction.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/cam_correction.c	(revision 38062)
+++ /trunk/Ohana/src/uniphot/src/cam_correction.c	(revision 38062)
@@ -0,0 +1,147 @@
+# 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)
+
+static CamCorrection *cam = NULL;
+
+int load_cam_correction (char *filename) {
+
+  int i, ix, iy, dir, filter;
+  Header header;
+
+  /* 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;
+  }
+
+  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);
+
+  int Ndir, Nfilter, Nx, Ny, dX, dY, NxCCD, NyCCD;
+  if (!gfits_scan (&header, "NDIR",    "%d", 1, &Ndir))    return FALSE;
+  if (!gfits_scan (&header, "NFILTER", "%d", 1, &Nfilter)) return FALSE;
+  if (!gfits_scan (&header, "NX", 	"%d", 1, &Nx)) 	    return FALSE;
+  if (!gfits_scan (&header, "NY", 	"%d", 1, &Ny)) 	    return FALSE;
+  if (!gfits_scan (&header, "DX", 	"%d", 1, &dX)) 	    return FALSE;
+  if (!gfits_scan (&header, "DY", 	"%d", 1, &dY)) 	    return FALSE;
+
+  if (!gfits_scan (&header, "NX_CHIP", "%d", 1, &NxCCD))   return FALSE;
+  if (!gfits_scan (&header, "NY_CHIP", "%d", 1, &NyCCD))   return FALSE;
+
+  ALLOCATE (cam->matrix, Matrix *, Ndir*Nfilter*Nx*Ny);
+
+  cam->Nx      = Nx;  	   // for gpc1, should be 8
+  cam->Ny      = Ny;  	   // for gpc1, should be 8
+  cam->Nfilter = Nfilter;  // for gpc1, should be 5
+  cam->Ndir    = Ndir;     // for gpc1, should be 2
+
+  cam->dX      = dX;  	   // superpixel sampling, x-dir
+  cam->dY      = dY;  	   // superpixel sampling, y-dir
+
+  cam->NxCCD   = NxCCD;    // pixels per chip
+  cam->NyCCD   = NyCCD;    // pixels per chip
+
+  cam->Nchips  = Nx * Ny;
+  cam->Ngroup  = Nx * Ny * Nfilter;
+  cam->Nvalues = Nx * Ny * Nfilter * Ndir;
+
+  ALLOCATE (cam->matrix, Matrix *, cam->Nvalues);
+  for (i = 0; i < cam->Nvalues; i++) {
+    cam->matrix[i] = NULL;
+  }
+
+  int found = FALSE;
+  while (TRUE) {
+    Header theader;
+
+    // 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;
+
+    // XXX NOTE: astroflat.20150209.fits has ix and iy backwards in header
+    // if (!gfits_scan (&theader, "X_CHIP",  "%d", 1, &ix))      return FALSE;
+    // if (!gfits_scan (&theader, "Y_CHIP",  "%d", 1, &iy))      return FALSE;
+
+    if (!gfits_scan (&theader, "X_CHIP",  "%d", 1, &iy))      return FALSE;
+    if (!gfits_scan (&theader, "Y_CHIP",  "%d", 1, &ix))      return FALSE;
+
+    Matrix *matrix = NULL;
+    ALLOCATE (matrix, Matrix, 1);
+    if (!gfits_load_matrix (f, matrix, &theader)) break;
+
+    int index = ix + iy*cam->Nx + filter*cam->Nchips + dir*cam->Ngroup;
+    myAssert (index >= 0, "index too small");
+    myAssert (index < cam->Nvalues, "index too big");
+
+    myAssert (!cam->matrix[index], "entry already assigned?");
+
+    // assert that cam->matrix[index] is NULL?
+    cam->matrix[index] = matrix;
+
+    if (!found) {
+      
+    }
+  }
+  return TRUE;
+}
+
+// input is:
+// chipID == octal chip ID (eg 40 for XY40)
+// filter == (01234 = grizy)
+int get_cam_correction (int chipID, int filter, float Xccd, float Yccd, double *dX, double *dY) {
+
+  *dX = 0.0;
+  *dY = 0.0;
+
+  int index, jx, jy, NxModel;
+  Matrix *matrix;
+  float *buffer, value;
+
+  // split out the chipID number (eg 43 for XY43) into X and Y elements
+  int ix = (int) (chipID / 10);
+  int iy = (int) (chipID % 10);
+
+  // dX (dir == 0)
+  index = ix + iy*cam->Nx + filter*cam->Nchips;
+
+  matrix = cam->matrix[index];
+  NxModel = cam->matrix[index]->Naxis[0];
+
+  buffer = (float *) matrix->buffer;
+
+  jx = MAX(MIN(cam->NxCCD, Xccd / cam->dX), 0);
+  jy = MAX(MIN(cam->NyCCD, Yccd / cam->dY), 0);
+
+  value = buffer[jx + jy*NxModel];
+
+  *dX = isnan(value) ? 0.0 : value;
+
+  // dY (dir == 1) uses the next block
+  index += cam->Ngroup;
+
+  matrix = cam->matrix[index];
+  NxModel = cam->matrix[index]->Naxis[0];
+
+  buffer = (float *) matrix->buffer;
+
+  jx = MAX(MIN(cam->NxCCD, Xccd / cam->dX), 0);
+  jy = MAX(MIN(cam->NyCCD, Yccd / cam->dY), 0);
+
+  value = buffer[jx + jy*NxModel];
+
+  *dY = isnan(value) ? 0.0 : value;
+
+  return TRUE;
+}
Index: /trunk/Ohana/src/uniphot/src/initialize_setastrom.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/initialize_setastrom.c	(revision 38061)
+++ /trunk/Ohana/src/uniphot/src/initialize_setastrom.c	(revision 38062)
@@ -4,6 +4,7 @@
     fprintf (stderr, "USAGE: setastrom [options]\n");
     fprintf (stderr, "  options:\n");
+    fprintf (stderr, "    -KH (file) : supply Koppenhoefer correction splines\n");
     fprintf (stderr, "    -DCR (file) : supply DCR correction splines\n");
-    fprintf (stderr, "    -KH (file) : supply Koppenhoefer correction splines\n");
+    fprintf (stderr, "    -CAM (file) : supply camera-static correction file\n");
     fprintf (stderr, "    -v : verbose mode\n");
     fprintf (stderr, "    -region Rmin Rmax Dmin Dmax\n");
@@ -77,4 +78,17 @@
   }
 
+  CAM_FILE = NULL;
+  if ((N = get_argument (argc, argv, "-CAM"))) {
+    remove_argument (N, &argc, argv);
+    char *tmpfile = strcreate (argv[N]);
+    CAM_FILE = abspath (tmpfile, DVO_MAX_PATH);
+    remove_argument (N, &argc, argv);
+  }
+  CAM_RESET = FALSE;
+  if ((N = get_argument (argc, argv, "-CAM-reset"))) {
+    remove_argument (N, &argc, argv);
+    CAM_RESET = TRUE;
+  }
+
   SINGLE_CPT = NULL;
   if ((N = get_argument (argc, argv, "-cpt"))) {
@@ -146,7 +160,6 @@
   }
 
-  if (!KH_FILE && !DCR_FILE) {
-    fprintf (stderr, "at least one of -KH and -DCR must be supplied\n");
-    exit (1);
+  if (!KH_FILE && !DCR_FILE && !CAM_FILE) {
+    fprintf (stderr, "WARNING: none of -CAM, -KH, -DCR supplied\n");
   }
 
@@ -159,6 +172,7 @@
   fprintf (stderr, "USAGE: setastrom_client -hostID (hostID) -catdir (catdir) -hostdir (hostdir) [options]\n");
   fprintf (stderr, "  options:\n");
+  fprintf (stderr, "    -KH  (file) : supply Koppenhoefer correction splines\n");
   fprintf (stderr, "    -DCR (file) : supply DCR correction splines\n");
-  fprintf (stderr, "    -KH (file) : supply Koppenhoefer correction splines\n");
+  fprintf (stderr, "    -CAM (file) : supply camera-static correction file\n");
   fprintf (stderr, "    -region Rmin Rmax Dmin Dmax\n");
   fprintf (stderr, "    -update-catformat (format) : change database schema on output\n");
@@ -221,4 +235,16 @@
     remove_argument (N, &argc, argv);
     DCR_RESET = TRUE;
+  }
+
+  CAM_FILE = NULL;
+  if ((N = get_argument (argc, argv, "-CAM"))) {
+    remove_argument (N, &argc, argv);
+    CAM_FILE = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  CAM_RESET = FALSE;
+  if ((N = get_argument (argc, argv, "-CAM-reset"))) {
+    remove_argument (N, &argc, argv);
+    CAM_RESET = TRUE;
   }
 
@@ -282,7 +308,6 @@
   if (!CATDIR) usage_setastrom_client();
 
-  if (!KH_FILE && !DCR_FILE) {
-    fprintf (stderr, "at least one of -KH and -DCR must be supplied\n");
-    exit (1);
+  if (!KH_FILE && !DCR_FILE && !CAM_FILE) {
+    fprintf (stderr, "WARNING: none of -CAM, -KH, -DCR supplied\n");
   }
 
Index: /trunk/Ohana/src/uniphot/src/update_catalog_setastrom.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/update_catalog_setastrom.c	(revision 38061)
+++ /trunk/Ohana/src/uniphot/src/update_catalog_setastrom.c	(revision 38062)
@@ -117,4 +117,20 @@
     }
 
+    /**** CAM section ****/
+
+    double dX_CAM = 0.0;
+    double dY_CAM = 0.0;
+    if (CAM_FILE) {
+
+      // camera systematic correction ("astroflat") depends on only the X,Y coordinate,
+      // the filter, and the chip
+      
+      // 10134 : r, XY34 -> filtCode = 1
+      int filtCode = (int)((measure->photcode % 1000) / 100); 
+
+      // correction is in arcseconds
+      get_cam_correction (chipID, filtCode, measure->Xccd, measure->Yccd, &dX_CAM, &dY_CAM);
+    }
+
     /**** DCR section ****/
 
@@ -245,6 +261,14 @@
     }
     if (DCR_RESET) {
-      measure[0].XoffDCR = -dX_DCR / pltScale;
-      measure[0].YoffDCR = -dY_DCR / pltScale;
+      measure[0].XoffDCR = 0.0;
+      measure[0].YoffDCR = 0.0;
+    }
+    if (CAM_FILE) {
+      measure[0].XoffCAM = -dX_CAM / pltScale;
+      measure[0].YoffCAM = -dY_CAM / pltScale;
+    }
+    if (CAM_RESET) {
+      measure[0].XoffDCR = 0.0;
+      measure[0].YoffDCR = 0.0;
     }
 
@@ -259,4 +283,8 @@
       measure[0].Yfix += measure[0].YoffDCR;
     }
+    if (isfinite(measure[0].XoffCAM) && isfinite(measure[0].YoffCAM)) {
+      measure[0].Xfix += measure[0].XoffCAM;
+      measure[0].Yfix += measure[0].YoffCAM;
+    }
     found ++;
   }
Index: /trunk/Ohana/src/uniphot/src/update_dvo_setastrom.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/update_dvo_setastrom.c	(revision 38061)
+++ /trunk/Ohana/src/uniphot/src/update_dvo_setastrom.c	(revision 38062)
@@ -17,6 +17,7 @@
   }
 
-  if (KH_FILE)  load_kh_correction (KH_FILE);
-  if (DCR_FILE) load_dcr_correction (DCR_FILE);
+  if (KH_FILE)  if (!load_kh_correction  (KH_FILE))  { fprintf (stderr, "failed to load KH  correction %s\n", KH_FILE ); exit (1); }
+  if (DCR_FILE) if (!load_dcr_correction (DCR_FILE)) { fprintf (stderr, "failed to load DCR correction %s\n", DCR_FILE); exit (1); }
+  if (CAM_FILE) if (!load_cam_correction (CAM_FILE)) { fprintf (stderr, "failed to load CAM correction %s\n", CAM_FILE); exit (1); }
 
   // determine the populated SkyRegions overlapping the requested area (default depth)
@@ -104,8 +105,10 @@
     if (KH_FILE)      	  { snprintf (tmpline, 1024, "%s -KH %s",           	command, KH_FILE);	    strcpy (command, tmpline); }
     if (DCR_FILE)      	  { snprintf (tmpline, 1024, "%s -DCR %s",           	command, DCR_FILE);	    strcpy (command, tmpline); }
+    if (CAM_FILE)      	  { snprintf (tmpline, 1024, "%s -CAM %s",           	command, CAM_FILE);	    strcpy (command, tmpline); }
     if (UPDATE_CATFORMAT) { snprintf (tmpline, 1024, "%s -update-catformat %s", command, UPDATE_CATFORMAT); strcpy (command, tmpline); }
 
     if (KH_RESET)      	  { snprintf (tmpline, 1024, "%s -KH-reset",           	command);	            strcpy (command, tmpline); }
     if (DCR_RESET)     	  { snprintf (tmpline, 1024, "%s -DCR-reset",           command);	            strcpy (command, tmpline); }
+    if (CAM_RESET)     	  { snprintf (tmpline, 1024, "%s -CAM-reset",           command);	            strcpy (command, tmpline); }
 
     fprintf (stderr, "command: %s\n", command);
