Index: trunk/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 42962)
+++ trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 42967)
@@ -185,4 +185,5 @@
 $(SRC)/vbin.$(ARCH).o		   \
 $(SRC)/vgroup.$(ARCH).o		   \
+$(SRC)/vweave.$(ARCH).o		   \
 $(SRC)/vclip.$(ARCH).o		   \
 $(SRC)/vgauss.$(ARCH).o            \
Index: trunk/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/init.c	(revision 42962)
+++ trunk/Ohana/src/opihi/cmd.data/init.c	(revision 42967)
@@ -170,4 +170,5 @@
 int vbin             PROTO((int, char **));
 int vgroup           PROTO((int, char **));
+int vweave           PROTO((int, char **));
 int vclip            PROTO((int, char **));
 int vect_select      PROTO((int, char **));
@@ -386,4 +387,5 @@
   {1, "vbin",         vbin,             "rebin vector data by a factor of N"},
   {1, "vgroup",       vgroup,           "group y vector into bins defined by x vector values"},
+  {1, "vweave",       vweave,           "drizzle input vectors to output vector with correct fractional bin weighting"},
   {1, "vclip",        vclip,            "clip values in a vector to be within a range"},
   {1, "vectors",      list_vectors,     "list vectors"},
Index: trunk/Ohana/src/opihi/cmd.data/spline_commands.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/spline_commands.c	(revision 42962)
+++ trunk/Ohana/src/opihi/cmd.data/spline_commands.c	(revision 42967)
@@ -62,6 +62,12 @@
 int spline_apply (int argc, char **argv) {
 
-  int i;
+  int i, N;
   Vector *xvec, *yvec;
+
+  spline_contruct_mode (SPLINE_SATURATE);
+  if ((N = get_argument (argc, argv, "-extrapolate"))) {
+    spline_contruct_mode (SPLINE_EXTRAPOLATE);
+    remove_argument (N, &argc, argv);
+  }
 
   if (argc != 4) {
Index: trunk/Ohana/src/opihi/cmd.data/test/spline.sh
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/test/spline.sh	(revision 42962)
+++ trunk/Ohana/src/opihi/cmd.data/test/spline.sh	(revision 42967)
@@ -1,5 +1,4 @@
 
 macro test1
-
   for i 0 100
     create x 0 50
@@ -10,2 +9,27 @@
   end
 end
+
+macro mytest.saturate
+  vlist x 400 500  600  700  800  900
+  vlist y  15 425  610  700  745  775
+
+  spline create t1 x y
+
+  create X 300 1000 5
+  spline apply t1 X Y
+
+  lim X Y; clear; box; plot x y; plot -c red -x line X Y
+end
+ 
+macro mytest.extrapolate
+  vlist x 400 500  600  700  800  900
+  vlist y  15 425  610  700  745  775
+
+  spline create t1 x y
+
+  create X 300 1000 5
+  spline apply t1 X Y -extrapolate
+
+  lim X Y; clear; box; plot x y; plot -c red -x line X Y
+end
+ 
Index: trunk/Ohana/src/opihi/cmd.data/vweave.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/vweave.c	(revision 42967)
+++ trunk/Ohana/src/opihi/cmd.data/vweave.c	(revision 42967)
@@ -0,0 +1,131 @@
+# include "data.h"
+
+enum {USE_DENSE, USE_SUM};
+
+int vweave (int argc, char **argv) {
+  
+  int i, j, N;
+  Vector *xin, *yin, *yout;
+  Vector *xminV = NULL, *xmaxV = NULL, *xout = NULL;
+  opihi_flt xmin, xmax, Xmin, Xmax;
+
+  int mode = USE_SUM;
+  if ((N = get_argument (argc, argv, "-dense"))) {
+    remove_argument (N, &argc, argv);
+    mode = USE_DENSE;
+  }
+
+  float binsize = NAN;
+  if ((N = get_argument (argc, argv, "-binsize"))) {
+    remove_argument (N, &argc, argv);
+    binsize = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc != 5) && (argc != 6)) {
+    gprint (GP_ERR, "USAGE: vweave <xin> <yin> <xout> <yout>\n");
+    gprint (GP_ERR, "   OR: vweave <xin> <yin> <xmin> <xmax> <yout>\n");
+    gprint (GP_ERR, " fully interpolate input bin values into output bins, using fractional input bin contributions\n");
+    gprint (GP_ERR, " by default, yout has the sum of the associated input values\n");
+    gprint (GP_ERR, " use -count to find the fractional input bin contributions\n");
+    gprint (GP_ERR, " with a single <xout> vector, output bin boundaries defined as midpoint of xout values\n");
+    gprint (GP_ERR, " with <xmin> and <xmax>, the output bin boundaries are explicitly provided\n");
+    gprint (GP_ERR, " use -binsize to specify a fixed bin width (<xout> will define the bin center)\n");
+    gprint (GP_ERR, " input values are treated as uniformly spread between midpoints of xin values\n");
+    return (FALSE);
+  }
+
+  if ((xin  = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (xin->Nelements < 2) {
+    gprint (GP_ERR, "input vector of length < 2 is invalid\n");
+    return FALSE;
+  }
+  if ((yin  = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  int Nout = -1;
+  if (argc == 5) {
+    if ((xout = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    if (xout->Nelements < 2) {
+      gprint (GP_ERR, "output vector of length < 2 is invalid\n");
+      return FALSE;
+    }
+    Nout = xout->Nelements;
+    if ((yout = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  } else {
+    if (!isnan(binsize)) {
+      gprint (GP_ERR, "-binsize is incompatible with <xmin>, <xmax>\n");
+      return FALSE;
+    }
+    if ((xminV = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    if (xminV->Nelements < 2) {
+      gprint (GP_ERR, "output vector of length < 2 is invalid\n");
+      return FALSE;
+    }
+    Nout = xminV->Nelements;
+    if ((xmaxV = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    if (xmaxV->Nelements != Nout) {
+      gprint (GP_ERR, "<xmin> and <xmax> lengths must match\n");
+      return FALSE;
+    }
+    if ((yout = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  }
+
+  // re-binning creates a float vector
+  ResetVector (yout, OPIHI_FLT, Nout);
+
+  // XXX this algorithm is not optimized: full scale of input vector for each output bin
+  // could speed up with sorting and pre-defined boundaries
+  for (i = 0; i < Nout; i++) {
+    if (!isnan(binsize)) {
+      xmin = xout[0].elements.Flt[i] - 0.5*binsize;
+      xmax = xout[0].elements.Flt[i] + 0.5*binsize;
+    } else {
+      if (xout) {
+	if (i > 0) {
+	  xmin = 0.5*(xout[0].elements.Flt[i] + xout[0].elements.Flt[i-1]);
+	} else {
+	  xmin = 1.5*xout[0].elements.Flt[i] - 0.5*xout[0].elements.Flt[i+1];
+	}
+	if (i < xout[0].Nelements - 1) {
+	  xmax = 0.5*(xout[0].elements.Flt[i] + xout[0].elements.Flt[i+1]);
+	} else {
+	  xmax = 1.5*xout[0].elements.Flt[i] - 0.5*xout[0].elements.Flt[i-1];
+	}
+      } else {
+	xmin = xminV[0].elements.Flt[i];
+	xmax = xmaxV[0].elements.Flt[i];
+      }
+    }
+
+    opihi_flt valSum = 0.0;
+    for (j = 0; j < xin[0].Nelements; j++) {
+      if (j > 0) {
+	Xmin = 0.5*(xin[0].elements.Flt[j] + xin[0].elements.Flt[j-1]);
+      } else {
+	Xmin = 1.5*xin[0].elements.Flt[j] + 0.5*xin[0].elements.Flt[j+1];
+      }
+      if (j < xin[0].Nelements - 1) {
+	Xmax = 0.5*(xin[0].elements.Flt[j] + xin[0].elements.Flt[j+1]);
+      } else {
+	Xmax = 1.5*xin[0].elements.Flt[j] - 0.5*xin[0].elements.Flt[j-1];
+      }
+      if (Xmax < xmin) continue;
+      if (Xmin > xmax) continue;
+
+      // input bin range is Xmin to Xmax
+      // output bin range is xmin to xmax
+      // what 
+      opihi_flt fmin = MAX(0.0, (xmin - Xmin) / (Xmax - Xmin));
+      opihi_flt fmax = MIN(1.0, (xmax - Xmin) / (Xmax - Xmin));
+      
+      opihi_flt binFrac = fmax - fmin; // what fraction of this input bin is located in the output bin?
+      if (mode == USE_SUM) {
+	valSum += yin[0].elements.Flt[j] * binFrac;
+      } else {
+	valSum += binFrac;
+      }
+    }
+    yout[0].elements.Flt[i] = valSum;
+  }
+  return (TRUE);
+}
