Index: /trunk/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 42081)
+++ /trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 42082)
@@ -78,4 +78,6 @@
 $(SRC)/imsmooth.2d.$(ARCH).o	\
 $(SRC)/imconvolve.$(ARCH).o	\
+$(SRC)/imresample.$(ARCH).o	\
+$(SRC)/imcollapse.$(ARCH).o	\
 $(SRC)/integrate.$(ARCH).o	\
 $(SRC)/interpolate.$(ARCH).o	\
Index: /trunk/Ohana/src/opihi/cmd.data/cut.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/cut.c	(revision 42081)
+++ /trunk/Ohana/src/opihi/cmd.data/cut.c	(revision 42082)
@@ -96,4 +96,5 @@
   if (argc != 9) {
     gprint (GP_ERR, "USAGE: cut <buffer> <X vector> <Y vector> <X|Y> sx sy nx ny\n");
+    gprint (GP_ERR, "  extract a vector in the X or Y direction based on the pixel values in window\n");
     return (FALSE);
   }
Index: /trunk/Ohana/src/opihi/cmd.data/imcollapse.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/imcollapse.c	(revision 42082)
+++ /trunk/Ohana/src/opihi/cmd.data/imcollapse.c	(revision 42082)
@@ -0,0 +1,113 @@
+# include "data.h"
+
+enum {CALC_MEDIAN, CALC_MEAN, CALC_IRLS, CALC_WTMEAN, CALC_INNER_FRACTION};
+
+// take an image and collapse to a histogram along x or y 
+int imcollapse (int argc, char **argv) {
+  
+  int N;
+  Buffer *buf;
+  Vector *vecX, *vecY;
+
+  int mode = CALC_MEDIAN;
+  if ((N = get_argument (argc, argv, "-mean"))) {
+    mode = CALC_MEAN;
+    remove_argument (N, &argc, argv);
+  }
+
+  int sx = 0, sy = 0;
+  int nx = 0, ny = 0;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    sx = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    sy = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    nx = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    ny = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: imcollapse <buffer> <x> <y> <X|Y> [-region sx sy nx ny]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  
+  int Nx = buf[0].matrix.Naxis[0];
+  int Ny = buf[0].matrix.Naxis[1];
+
+  /* if either range is set to zero, use the rest of the chip */
+  if (nx == 0) nx = Nx - sx;
+  if (ny == 0) ny = Ny - sy;
+
+  if ((sx < 0) || (sy < 0) || (sx+nx > Nx) || (sy+ny > Ny)) {
+    gprint (GP_ERR, "region out of range\n");
+    return (FALSE);
+  }
+  if ((nx < 0) || (ny < 0)) {
+    gprint (GP_ERR, "invalid region\n");
+    return (FALSE);
+  }
+
+  if ((vecX = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecY = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  int direction = 0;
+  if (!strcasecmp(argv[4], "x")) direction = 1;
+  if (!strcasecmp(argv[4], "y")) direction = 2;
+  if (!direction) { 
+    gprint (GP_ERR, "invalid direction %s\n", argv[4]);
+    return (FALSE);
+  }
+
+  // 'direction' is the direction of collapse 
+  int Nbins = (direction == 1) ? ny : nx;
+  ResetVector (vecX, OPIHI_FLT, Nbins);
+  ResetVector (vecY, OPIHI_FLT, Nbins);
+  bzero (vecX->elements.Flt, vecX->Nelements*sizeof(opihi_flt));
+  bzero (vecY->elements.Flt, vecY->Nelements*sizeof(opihi_flt));
+  opihi_flt *xout = vecX->elements.Flt;
+  opihi_flt *yout = vecY->elements.Flt;
+  
+  float *V = (float *)buf[0].matrix.buffer;
+
+  // temp storage for extracted values
+  int Nvals = (direction == 1) ? nx : ny;
+  ALLOCATE_PTR (values, opihi_flt, Nvals);
+
+  if (direction == 1) {
+    for (int iy = sy; iy < sy + ny; iy++) {
+      xout[iy - sy] = iy;
+      // accumulate the values for this output bin
+      int n = 0;
+      for (int ix = sx; ix < sx + nx; ix++) {
+	double val = V[iy*Nx + ix];
+	if (!isfinite(val)) continue;
+	values[n] = val;
+	n++;
+      }
+      if (n == 0) {
+	yout[iy - sy] = NAN;
+	continue;
+      }
+      // calculate the statistic (mean or median)
+      if (mode == CALC_MEDIAN) {
+	dsort (values, n);
+	int midpt = 0.5*n;
+	yout[iy - sy] = (n % 2) ? values[midpt] : 0.5*(values[midpt] + values[midpt-1]);
+      }
+      if (mode == CALC_MEAN) {
+	opihi_flt sum = 0.0;
+	for (int i = 0; i < n; i++) {	
+	  sum += values[i];
+	}
+	yout[iy - sy] = sum / (float) n;
+      }
+    }
+  }  
+  return (TRUE);
+}
+
Index: /trunk/Ohana/src/opihi/cmd.data/imcut.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/imcut.c	(revision 42081)
+++ /trunk/Ohana/src/opihi/cmd.data/imcut.c	(revision 42082)
@@ -9,8 +9,5 @@
   float *V;
 
-  if (argc != 8) {
-    gprint (GP_ERR, "USAGE: cut <buffer> <X vector> <Y vector> xs ys xe ye\n");
-    return (FALSE);
-  }
+  if (argc != 8) goto usage;
 
   if ((buf  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) goto missed;
@@ -51,5 +48,7 @@
 
  usage: 
-  gprint (GP_ERR, "USAGE: circstats <buffer> x y radius\n");
+  gprint (GP_ERR, "USAGE: imcut <buffer> <X vector> <Y vector> xs ys xe ye\n");
+  gprint (GP_ERR, " extract pixels along the line from (xs,ys) to (xe,ye)\n");
+  gprint (GP_ERR, " (see also imvector)\n");
   return (FALSE);
 
Index: /trunk/Ohana/src/opihi/cmd.data/imresample.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/imresample.c	(revision 42082)
+++ /trunk/Ohana/src/opihi/cmd.data/imresample.c	(revision 42082)
@@ -0,0 +1,78 @@
+# include "data.h"
+
+int imresample (int argc, char **argv) {
+  
+  Buffer *buf, *out;
+
+  if (argc != 8) goto usage;
+
+  if ((buf  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) goto missed;
+  if ((out  = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) goto usage;
+ 
+  double xs = atof (argv[3]);
+  double ys = atof (argv[4]);
+  double xe = atof (argv[5]);
+  double ye = atof (argv[6]);
+  int    Wo = atoi (argv[7]);
+
+  int Nx = buf[0].matrix.Naxis[0];
+  int Ny = buf[0].matrix.Naxis[1];
+
+  // allow window to fall off the edge?
+  if ((xs < 0) || (xs > Nx)) goto range;
+  if ((ys < 0) || (ys > Ny)) goto range;
+  if ((xe < 0) || (xe > Nx)) goto range;
+  if ((ye < 0) || (ye > Ny)) goto range;
+
+  // relationship between a pixel in the output window (x,y) and the input image (X,Y)
+  // (0,0) corner of the output window is:
+  // Xo,Yo = xs + dY * Wo/2, ys - dX * Wo/2
+  // output window has size Lo, Wo
+  // a pixel (x,y) in the output window has coords in the input image of:
+  // (X,Y) = (Xo + x*dX - y*dY, Yo + x*dY + y*dX)
+
+  double dX = xe - xs;
+  double dY = ye - ys;
+  double Lo = hypot (dX, dY);
+  dX = dX / Lo;
+  dY = dY / Lo;
+  double Xo = xs + dY * Wo/2.0;
+  double Yo = ys - dX * Wo/2.0;
+
+  // dimensions of output window:
+  int nx = Lo;
+  int ny = Wo;
+
+  gfits_free_matrix (&out[0].matrix);
+  gfits_free_header (&out[0].header);
+  if (!CreateBuffer (out, nx, ny, -32, 1.0, 0.0)) return FALSE;
+
+  float *Vi = (float *)buf[0].matrix.buffer;
+  float *Vo = (float *)out[0].matrix.buffer;
+  for (int ix = 0; ix < nx; ix++) {
+    for (int iy = 0; iy < ny; iy++) {
+      int xi = Xo + ix*dX - iy*dY;
+      int yi = Yo + ix*dY + iy*dX;
+      if (xi < 0) continue;
+      if (yi < 0) continue;
+      if (xi >= Nx) continue;
+      if (yi >= Ny) continue;
+      Vo[ix + nx*iy] = Vi[xi + Nx*yi];
+    }
+  }
+  return (TRUE);
+
+ usage: 
+  gprint (GP_ERR, "USAGE: imresample <buffer> <output> xs ys xe ye width\n");
+  gprint (GP_ERR, "  resample image in new window along line (xs,ys) to (xe,ye) of given width\n");
+  return (FALSE);
+
+ range:
+  gprint (GP_ERR, "ERROR: coordinates out of range\n");
+  return (FALSE);
+
+ missed:
+  gprint (GP_ERR, "ERROR: buffer not found\n");
+  return (FALSE);
+}
+
Index: /trunk/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/init.c	(revision 42081)
+++ /trunk/Ohana/src/opihi/cmd.data/init.c	(revision 42082)
@@ -18,5 +18,4 @@
 int clear            PROTO((int, char **));
 int clip             PROTO((int, char **));
-int imclip           PROTO((int, char **));
 int close_device     PROTO((int, char **));
 int concat           PROTO((int, char **));
@@ -61,4 +60,5 @@
 int hermitian2d      PROTO((int, char **));
 int idxread          PROTO((int, char **));
+int imclip           PROTO((int, char **));
 int imcut            PROTO((int, char **));
 int imhist           PROTO((int, char **));
@@ -68,4 +68,6 @@
 int imsmooth_2d      PROTO((int, char **));
 int imconvolve       PROTO((int, char **));
+int imresample       PROTO((int, char **));
+int imcollapse       PROTO((int, char **));
 int integrate        PROTO((int, char **));
 int interpolate      PROTO((int, char **));
@@ -266,4 +268,6 @@
   {1, "imclip",       imclip,           "clip values in an image to be within a range"},
   {1, "imcut",        imcut,            "linear image cut between arbitrary coords"},
+  {1, "imresample",   imresample,       "extract arbitrary window from image"},
+  {1, "imcollapse",   imcollapse,       "collapse to histogram along axis"},
   {1, "imhistogram",  imhist,           "histogram of an image region"},
   {1, "impeaks",      impeaks,          "find peaks in an image (return vectors)"},
Index: /trunk/Ohana/src/opihi/cmd.data/match2d.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/match2d.c	(revision 42081)
+++ /trunk/Ohana/src/opihi/cmd.data/match2d.c	(revision 42082)
@@ -140,4 +140,15 @@
   gprint (GP_ERR, "if -index1 or -index2 is not supplied, the vectors are created with names index1 or index2\n");
   gprint (GP_ERR, "use 'reindex' to generate new vectors based on these index vectors\n");
+
+  gprint (GP_ERR, "examples:\n");
+  gprint (GP_ERR, " for 'match2d x1 y1 x2 y2 radius -closest'\n");
+  gprint (GP_ERR, " use 'reindex x2m = x2 using index1 -keep-unmatched'\n");
+  gprint (GP_ERR, "   x2m will have values which correspond to x1 (or NAN if not matched)\n");  
+  gprint (GP_ERR, " \n");  
+  gprint (GP_ERR, " for 'match2d x1 y1 x2 y2 radius'\n");
+  gprint (GP_ERR, " use 'reindex x1m = x1 using index1'\n");
+  gprint (GP_ERR, " use 'reindex x2m = x2 using index2'\n");
+  gprint (GP_ERR, "   x1m will have values which correspond to x2m\n");  
+  gprint (GP_ERR, " \n");  
 
   gprint (GP_ERR, "if -sphere or -sky is supplied, (x1,y1) and (x2,y2) are treaded as (ra,dec) or (long,lat) pairs in degrees\n");
Index: /trunk/Ohana/src/opihi/cmd.data/medacc.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/medacc.c	(revision 42081)
+++ /trunk/Ohana/src/opihi/cmd.data/medacc.c	(revision 42082)
@@ -10,4 +10,8 @@
   if ((argc != 6) && (argc != 7)) {
     gprint (GP_ERR, "USAGE: medacc <value> <vector> <key> start end [delta]\n");
+    gprint (GP_ERR, "  value and key are vectors of the same length\n");
+    gprint (GP_ERR, "  the output vector bins correspond to values ranging from start to end in steps of delta (default 1)\n");
+    gprint (GP_ERR, "  for a given output bin, all input values for which the key matches the output bin are averaged\n");
+
     return (FALSE);
   }
Index: /trunk/Ohana/src/opihi/cmd.data/queueload.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/queueload.c	(revision 42081)
+++ /trunk/Ohana/src/opihi/cmd.data/queueload.c	(revision 42082)
@@ -3,9 +3,16 @@
 int queueload (int argc, char **argv) {
   
-  char *A, *B, *val;
-  int i, status;
-  int Nread, Nbytes, NBYTES;
-  FILE *f;
-  Queue *queue;
+  int N;
+
+  // variable name to save the value
+  int TrapFailure = FALSE;
+  if ((N = get_argument (argc, argv, "-trap-failure"))) {
+    remove_argument (N, &argc, argv);
+    TrapFailure = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-trap"))) {
+    remove_argument (N, &argc, argv);
+    TrapFailure = TRUE;
+  }
 
   if (argc != 4) goto usage;
@@ -13,14 +20,15 @@
   
   /* will create a queue if none exists */
-  queue = CreateQueue (argv[1]);
+  Queue *queue = CreateQueue (argv[1]);
 
   /* val will hold the result of the command */
-  NBYTES = 1024;
-  ALLOCATE (val, char, NBYTES);
+  int NBYTES = 1024;
+  ALLOCATE_PTR (val, char, NBYTES);
     
   /* loop until command produces no more output,  REALLOCATE as needed. */
-  f = popen (argv[3], "r");
-  Nbytes = 0;
-  Nread = 1;
+  FILE *f = popen (argv[3], "r");
+
+  int Nbytes = 0;
+  int Nread = 1;
   while (Nread > 0) {
     Nread = fread (&val[Nbytes], 1, 1023, f);
@@ -35,12 +43,14 @@
   }
   val[Nbytes] = 0;
-  status = pclose (f);
+  int status = pclose (f);
     
+  // XXX 
   if (status) {
     gprint (GP_ERR, "warning: exit status of command %d\n", status);
+    if (TrapFailure) { free (val); return FALSE; }
   }
       
-  A = B = val;
-  for (i = 0; B != (char *) NULL;) {
+  char *A = val, *B = val;
+  for (int i = 0; B != (char *) NULL;) {
     while (isspace (*A) && (*A != 0)) A++;
     B = strchr (A, '\n');
Index: /trunk/Ohana/src/opihi/cmd.data/read_vectors.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 42081)
+++ /trunk/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 42082)
@@ -629,8 +629,9 @@
   }
   if (listFields) {
-    read_table_fields (&header, IsCompressed, VERBOSE);
+    int tstatus = read_table_fields (&header, IsCompressed, VERBOSE);
     if (CCDKeyword != NULL) free (CCDKeyword); 
     gfits_free_header (&header); 
-    return TRUE;
+    if (!tstatus) { gprint (GP_ERR, "error reading table fields\n"); }
+    return tstatus;
   }
   if (IsCompressed) {
@@ -855,6 +856,13 @@
   char field[32], varname[32], type[80], comment[80], format[80], unit[80], null[80], nval[80];
 
-  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
-
+  if (!gfits_scan (header, "TFIELDS", "%d", 1, &Nfields)) {
+    if (VERBOSE) gprint (GP_ERR, "cannot read TFIELDS from header\n"); 
+    set_int_variable ("table:Nx", header->Naxis[0]);
+    set_int_variable ("table:Ny", header->Naxis[1]);
+    set_int_variable ("table:Nfields", 0);
+    set_int_variable ("tfields:n", 0);
+    return TRUE;
+  }
+   
   set_int_variable ("table:Nx", header->Naxis[0]);
   set_int_variable ("table:Ny", header->Naxis[1]);
@@ -872,10 +880,12 @@
 
     snprintf (field, 32, "TTYPE%d", i);
-    gfits_scan (header, field, "%s", 1, type);
+    if (!gfits_scan (header, field, "%s", 1, type)) {
+      if (VERBOSE) gprint (GP_ERR, "cannot read %s from header\n", field); 
+    }
     
     snprintf (varname, 32, "tfields:%d", i - 1);
     set_str_variable (varname, type);
 
-    gfits_scan_alt (header, field, "%C", 1, comment);
+    gfits_scan_alt (header, field, "%C", 1, comment); 
 
     if (!isCompressed) {
@@ -884,5 +894,7 @@
       snprintf (field, 32, "ZFORM%d", i);
     }
-    gfits_scan (header, field, "%s", 1, format);
+    if (!gfits_scan (header, field, "%s", 1, format)) {
+      if (VERBOSE) gprint (GP_ERR, "cannot read %s from header\n", field); 
+    }
 
     snprintf (field, 32, "TUNIT%d", i);
@@ -895,6 +907,4 @@
     if (VERBOSE) gprint (GP_LOG, "%-18s %-15s %-18s %-6s %-8s %-8s %-32s\n", type, varname, unit, format, null, nval, comment); 
   }
-
-
   return TRUE;
 }
Index: /trunk/Ohana/src/opihi/cmd.data/reindex.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/reindex.c	(revision 42081)
+++ /trunk/Ohana/src/opihi/cmd.data/reindex.c	(revision 42082)
@@ -62,5 +62,5 @@
       if (*vx < 0) {
 	if (KEEP_UNMATCH) {
-	  ovec[0].elements.Flt[Npts] = -1;
+	  ovec[0].elements.Int[Npts] = -4096; // XXX use a different or a specified value?
 	  Npts++;
 	} 
