Index: trunk/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 42552)
+++ trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 42821)
@@ -67,4 +67,5 @@
 $(SRC)/ungridify.$(ARCH).o     \
 $(SRC)/histogram.$(ARCH).o	\
+$(SRC)/histbins.$(ARCH).o	\
 $(SRC)/tdhistogram.$(ARCH).o	\
 $(SRC)/hermitian1d.$(ARCH).o	\
@@ -80,4 +81,5 @@
 $(SRC)/imresample.$(ARCH).o	\
 $(SRC)/imcollapse.$(ARCH).o	\
+$(SRC)/impoints.$(ARCH).o	\
 $(SRC)/integrate.$(ARCH).o	\
 $(SRC)/interpolate.$(ARCH).o	\
Index: trunk/Ohana/src/opihi/cmd.data/histbins.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/histbins.c	(revision 42821)
+++ trunk/Ohana/src/opihi/cmd.data/histbins.c	(revision 42821)
@@ -0,0 +1,47 @@
+# include "data.h"
+
+int histbins (int argc, char **argv) {
+  
+  Vector *vals, *mins, *maxs, *out;
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: histbins <values> <output> <binmin> <binmax>\n");
+    gprint (GP_ERR, "  count <values> in each bin defined by the limit vectors\n");
+    return (FALSE);
+  }
+
+  if ((vals = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((mins = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((maxs = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (mins[0].Nelements != maxs[0].Nelements) {
+    gprint (GP_ERR, "binmin and binmax number of elements don't match\n");
+    return (FALSE);
+  }
+  if ((out = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  REQUIRE_VECTOR_FLT (vals, FALSE); 
+  REQUIRE_VECTOR_FLT (mins, FALSE); 
+  REQUIRE_VECTOR_FLT (maxs, FALSE); 
+
+  int Nbins = mins->Nelements;
+  ResetVector (out, OPIHI_FLT, Nbins);
+  bzero (out[0].elements.Flt, sizeof(opihi_flt)*out[0].Nelements);
+
+  opihi_flt *V = vals[0].elements.Flt;
+
+  // this function allows the bins to be completely arbitrary and potentially overlapping
+  // find all bins which contain each value
+  for (int i = 0; i < vals->Nelements; i++, V++) {
+    opihi_flt *S = mins[0].elements.Flt;
+    opihi_flt *E = maxs[0].elements.Flt;
+    opihi_flt *O = out[0].elements.Flt;
+    for (int j = 0; j < mins->Nelements; j++, S++, E++, O++) {
+      // note lower bound is inclusive, upper bound is exclusive:
+      if (*V <  *S) continue;
+      if (*V >= *E) continue;
+      *O += 1.0;
+    }
+  }      
+  return (TRUE);
+}
+
Index: trunk/Ohana/src/opihi/cmd.data/impoints.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/impoints.c	(revision 42821)
+++ trunk/Ohana/src/opihi/cmd.data/impoints.c	(revision 42821)
@@ -0,0 +1,47 @@
+# include "data.h"
+
+// insert the vector values into the image
+int impoints (int argc, char **argv) {
+  
+  Vector *vecx = NULL, *vecy = NULL, *vecf = NULL;
+  Buffer *buff;
+
+  if (argc < 4) {
+    gprint (GP_ERR, "USAGE: impoints (buffer) <xvec> <yvec> [fvec]\n");
+    gprint (GP_ERR, " inserts the points in the image, using the value in fvec if supplied (else 1)\n");
+    return (FALSE);
+  }
+
+  if ((buff = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vecx = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  // require vecx and vecy to be same length and floats
+
+
+  if (argc == 5) {
+      if ((vecf = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  }
+
+  float *image = (float *) buff[0].matrix.buffer;
+  int Nx = buff[0].matrix.Naxis[0];
+  int Ny = buff[0].matrix.Naxis[1];
+
+  for (int i = 0; i < vecx->Nelements; i++) {
+
+      int ix = vecx->elements.Flt[i];
+      int iy = vecy->elements.Flt[i];
+
+      if (ix < 0) continue;
+      if (iy < 0) continue;
+      if (ix >= Nx) continue;
+      if (iy >= Ny) continue;
+
+      if (vecf) {
+	  image[ix + iy*Nx] += vecf->elements.Flt[i];
+      } else {
+	  image[ix + iy*Nx] ++;
+      }
+  }
+  return (TRUE);
+}
Index: trunk/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/init.c	(revision 42552)
+++ trunk/Ohana/src/opihi/cmd.data/init.c	(revision 42821)
@@ -56,4 +56,5 @@
 int ungridify        PROTO((int, char **));
 int histogram        PROTO((int, char **));
+int histbins         PROTO((int, char **));
 int tdhistogram      PROTO((int, char **));
 int hermitian1d      PROTO((int, char **));
@@ -70,4 +71,5 @@
 int imresample       PROTO((int, char **));
 int imcollapse       PROTO((int, char **));
+int impoints         PROTO((int, char **));
 int integrate        PROTO((int, char **));
 int interpolate      PROTO((int, char **));
@@ -265,4 +267,5 @@
   {1, "header",       header,           "print image header"},
   {1, "histogram",    histogram,        "generate histogram from vector"},
+  {1, "histbins",     histbins,         "generate histogram from vector, bins specified by vectors"},
   {1, "tdhistogram",  tdhistogram,      "generate 2D histogram image from vector set"},
   {1, "hermitian1d",  hermitian1d,      "generate 1-D Hermitian Polynomial"},
@@ -281,4 +284,5 @@
   {1, "imconvolve",   imconvolve,       "full 2D real-space convolution"},
   {1, "imstats",      imstats,          "statistics on a portion of an image"},
+  {1, "impoints",     impoints,         "insert points into an image by vector pair"},
   {1, "integrate",    integrate,        "integrate a vector"},
   {1, "interpolate_presort",  interpolate_presort,      "interpolate between vector pairs"},
Index: trunk/Ohana/src/opihi/cmd.data/interpolate_presort.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/interpolate_presort.c	(revision 42552)
+++ trunk/Ohana/src/opihi/cmd.data/interpolate_presort.c	(revision 42821)
@@ -17,5 +17,5 @@
   /** check basic syntax **/
   if (argc != 5) {
-    gprint (GP_ERR, "USAGE: interpolate Xi Yi Xo Yo\n");
+    gprint (GP_ERR, "USAGE: interpolate Xi Yi Xo Yo [-fill-ends]\n");
     gprint (GP_ERR, "  Xi Yi - sorted reference vectors\n");
     gprint (GP_ERR, "  Xo    - output positions (vector)\n");
@@ -23,4 +23,5 @@
     gprint (GP_ERR, "  (vectors must be pre-sorted)\n");
     gprint (GP_ERR, "  (use 'threshold' to interpolate to a value)\n");
+    gprint (GP_ERR, "  -fill-ends : values outside of range are set to end-point values\n");
     return (FALSE);
   }
Index: trunk/Ohana/src/opihi/cmd.data/vgroup.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/vgroup.c	(revision 42552)
+++ trunk/Ohana/src/opihi/cmd.data/vgroup.c	(revision 42821)
@@ -70,5 +70,7 @@
   ALLOCATE (values, double, xin[0].Nelements);
 
-  for (i = 0; i < xout[0].Nelements - 1; i++) {
+  // if we specify binsize, then we need to examine all bins
+  int Nout = isnan(binsize) ? xout[0].Nelements - 1 : xout[0].Nelements;
+  for (i = 0; i < Nout; i++) {
     if (isnan(binsize)) {
       xmin = xout[0].elements.Flt[i];
@@ -81,6 +83,6 @@
     N = 0;
     for (j = 0; j < xin[0].Nelements; j++) {
-      if (xin[0].elements.Flt[j] < xmin) continue;
-      if (xin[0].elements.Flt[j] > xmax) continue;
+      if (xin[0].elements.Flt[j] <  xmin) continue;
+      if (xin[0].elements.Flt[j] >= xmax) continue;
       if (yin) {
 	values[N] = yin[0].elements.Flt[j];
