Index: /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/Makefile	(revision 42945)
+++ /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/Makefile	(revision 42946)
@@ -183,4 +183,5 @@
 $(SRC)/vbin.$(ARCH).o		   \
 $(SRC)/vgroup.$(ARCH).o		   \
+$(SRC)/vweave.$(ARCH).o		   \
 $(SRC)/vclip.$(ARCH).o		   \
 $(SRC)/vgauss.$(ARCH).o            \
Index: /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/init.c	(revision 42945)
+++ /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/init.c	(revision 42946)
@@ -168,4 +168,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 **));
@@ -382,4 +383,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: /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/spline_commands.c
===================================================================
--- /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/spline_commands.c	(revision 42945)
+++ /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/spline_commands.c	(revision 42946)
@@ -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: /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/test/spline.sh
===================================================================
--- /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/test/spline.sh	(revision 42945)
+++ /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/test/spline.sh	(revision 42946)
@@ -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: /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/vweave.c
===================================================================
--- /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/vweave.c	(revision 42946)
+++ /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/cmd.data/vweave.c	(revision 42946)
@@ -0,0 +1,102 @@
+# include "data.h"
+
+enum {USE_DENSE, USE_SUM};
+
+int vweave (int argc, char **argv) {
+  
+  int i, j, N;
+  Vector *xin, *yin, *xout, *yout;
+  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) {
+    gprint (GP_ERR, "USAGE: vweave <xin> <yin> <xout> <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, " output bin boundaries defined as midpoint of xout values\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 ((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;
+  }
+
+  if ((yin  = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yout = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  // re-binning creates a float vector
+  ResetVector (yout, OPIHI_FLT, xout[0].Nelements);
+
+  // 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 < xout[0].Nelements; i++) {
+    if (!isnan(binsize)) {
+      xmin = xout[0].elements.Flt[i] - 0.5*binsize;
+      xmax = xout[0].elements.Flt[i] + 0.5*binsize;
+    } else {
+      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];
+      }
+    }
+
+    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);
+}
Index: /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/include/data.h
===================================================================
--- /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/include/data.h	(revision 42945)
+++ /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/include/data.h	(revision 42946)
@@ -33,4 +33,6 @@
   char **pageIDs;
 } Book;
+
+typedef enum {SPLINE_SATURATE, SPLINE_EXTRAPOLATE} SplineMode;
 
 // the interpolating spline has valu
@@ -138,4 +140,5 @@
 void spline_construct_dbl (opihi_flt *x, opihi_flt *y, int N, opihi_flt *y2, opihi_flt dyLower, opihi_flt dyUpper);
 opihi_flt spline_apply_dbl (opihi_flt *x, opihi_flt *y, opihi_flt *y2, int N, opihi_flt X);
+int spline_contruct_mode (SplineMode mode);
 
 /* in svdcmp.c */
Index: /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/lib.data/spline.c
===================================================================
--- /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/lib.data/spline.c	(revision 42945)
+++ /branches/eam_branches/ipp-ppmerge-20241229/Ohana/src/opihi/lib.data/spline.c	(revision 42946)
@@ -1,3 +1,18 @@
 # include "data.h"
+
+static SplineMode MODE = SPLINE_SATURATE; // SATURATE or EXTRAPOLATE?
+
+int spline_contruct_mode (SplineMode mode) {
+  
+  switch (mode) {
+  case SPLINE_SATURATE:
+  case SPLINE_EXTRAPOLATE:
+    MODE = mode;
+    break;
+  default:
+    return FALSE;
+  }
+  return TRUE;
+}
 
 /* construct the natural spline for x, y in y2 */
@@ -36,6 +51,8 @@
   
   // saturate correction at high and low ends
-  if (X < x[0]) return y[0];
-  if (X > x[N-1]) return y[N-1];
+  if (MODE == SPLINE_SATURATE) {
+    if (X < x[0]) return y[0];
+    if (X > x[N-1]) return y[N-1];
+  }
 
   /* find correct element in array (x must be sorted) */
@@ -114,6 +131,8 @@
   
   // saturate correction at high and low ends
-  if (X < x[0]) return y[0];
-  if (X > x[N-1]) return y[N-1];
+  if (MODE == SPLINE_SATURATE) {
+    if (X < x[0]) return y[0];
+    if (X > x[N-1]) return y[N-1];
+  }
 
   /* find correct element in array (x must be sorted) */
