Index: /trunk/Ohana/src/kapa2/include/prototypes.h
===================================================================
--- /trunk/Ohana/src/kapa2/include/prototypes.h	(revision 40164)
+++ /trunk/Ohana/src/kapa2/include/prototypes.h	(revision 40165)
@@ -36,4 +36,5 @@
 int           DrawObjectN         PROTO((Graphic *graphic, KapaGraphWidget *graph, Gobjects *objects));
 void          DrawPoints          PROTO((Graphic *graphic, KapaGraphWidget *graph, Gobjects *objects));
+void          DrawBars            PROTO((Graphic *graphic, KapaGraphWidget *graph, Gobjects *object, int mode));
 void          ClipLine            PROTO((Graphic *graphic, double x0, double y0, double x1, double y1, double X0, double Y0, double X1, double Y1));
 void          DrawXErrors         PROTO((Graphic *graphic, KapaGraphWidget *graph, Gobjects *objects));
@@ -139,4 +140,5 @@
 void	      bDrawConnect	  PROTO((bDrawBuffer *buffer, KapaGraphWidget *graph, Gobjects *object));
 void	      bDrawHistogram	  PROTO((bDrawBuffer *buffer, KapaGraphWidget *graph, Gobjects *object));
+void          bDrawBars           PROTO((bDrawBuffer *buffer, KapaGraphWidget *graph, Gobjects *object, int mode));
 void	      bDrawPoints	  PROTO((bDrawBuffer *buffer, KapaGraphWidget *graph, Gobjects *object));
 void	      bDrawXErrors	  PROTO((bDrawBuffer *buffer, KapaGraphWidget *graph, Gobjects *object));
Index: /trunk/Ohana/src/kapa2/src/DrawObjects.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/DrawObjects.c	(revision 40164)
+++ /trunk/Ohana/src/kapa2/src/DrawObjects.c	(revision 40165)
@@ -1,10 +1,11 @@
 # include "Ximage.h"
 
-void DrawBars (Graphic *graphic, KapaGraphWidget *graph, Gobjects *object, int mode);
+/* DrawRectangle & FillRectangle : take rectangle lower-left corner and widths 
+   DrawCircle & FillCircle : take circle center and radius
+*/
 
 # define DrawLine(X1,Y1,X2,Y2) (XDrawLine (graphic->display, graphic->window, graphic->gc, (int)(X1), (int)(Y1), (int)(X2), (int)(Y2)))
-# define DrawRectangle(X1,Y1,X2,Y2) (XDrawRectangle (graphic->display, graphic->window, graphic->gc, (int)(X1), (int)(Y1), (int)(X2), (int)(Y2)))
-# define FillRectangle(X1,Y1,X2,Y2) (XFillRectangle (graphic->display, graphic->window, graphic->gc, (int)(X1), (int)(Y1), (int)(X2), (int)(Y2)))
-// # define FillRectangle(X1,Y1,X2,Y2) ;
+# define DrawRectangle(X,Y,dX,dY) (XDrawRectangle (graphic->display, graphic->window, graphic->gc, (int)(X), (int)(Y), (int)(dX), (int)(dY)))
+# define FillRectangle(X,Y,dX,dY) (XFillRectangle (graphic->display, graphic->window, graphic->gc, (int)(X), (int)(Y), (int)(dX), (int)(dY)))
 # define DrawCircle(X,Y,R) (XDrawArc (graphic->display, graphic->window, graphic->gc, (int)(X-R), (int)(Y-R), abs(2*R), abs(2*R), 0, 23040))
 # define FillCircle(X,Y,R) (XFillArc (graphic->display, graphic->window, graphic->gc, (int)(X-R), (int)(Y-R), abs(2*R), abs(2*R), 0, 23040))
@@ -162,7 +163,5 @@
     sx1 = x[i]*mxi + y[i]*mxj + bx + XCENTER;
     sy1 = x[i]*myi + y[i]*myj + by + YCENTER;
-    
     ClipLine (graphic, sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
-    /* DrawLine (sx0, sy0, sx1, sy1); */
     sx0 = sx1; sy0 = sy1;
   }
@@ -225,5 +224,4 @@
 /******/
 /* simplify the code abit by finding triplets, watch out for a histogram of 2 points */
-# if (1)
 void DrawHistogram (Graphic *graphic, KapaGraphWidget *graph, Gobjects *object) {
 
@@ -309,114 +307,4 @@
   DrawLine (sxa, sy1, sxa, sya);
 }
-
-# else 
-
-void DrawHistogram (Graphic *graphic, KapaGraphWidget *graph, Gobjects *object) {
-
-  int i;
-  float *x, *y;
-  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
-  double sx0, sy0, sx1, sy1, sxa, sya, sxo, syo;
-  double X0, X1, Y0, Y1;
-
-  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
-  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
-  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
-  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
-  
-  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
-  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
-  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
-  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
-  
-  bx = bxi + bxj;
-  by = byi + byj;
-  
-  X0 = graph[0].axis[0].fx;
-  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
-  Y0 = graph[0].axis[1].fy;
-  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
-
-  /* find the first valid datapoint */
-  x = object[0].x; y = object[0].y;
-  
-  /* we only worry about pairs of points of which one is on the screen.  for each such
-    pair, we draw the connecting lines from sx0,sy0 to sx1,sy1, passing through the point
-    halfway between.  
-
-    if, for a given point, there was no valid x0,y0, then we call this the first point
-    save both the current and previous points.
-  */
-
-  int firstPair = TRUE;
-  sx0r = sy0r = NAN;
-  sxPr = syPr = NAN;
-  for (i = 0; i < object[0].Npts; i++) {
-    if (!(finite(x[i]) && finite(y[i]))) continue;
-    sx1r = x[i]*mxi + y[i]*mxj + bx + XCENTER;
-    sy1r = x[i]*myi + y[i]*myj + by + YCENTER;
-
-    // we have hit the first valid point, but not yet the second one
-    if (!isfinite (sx0r)) {
-      sx0r = sx1r; sy0r = sy1r;
-      continue;
-    }
-
-    if ((sx1r < X0) && (sx0r < X0)) {
-      // both points to left, skip the pair
-      sxPr = sx0r; syPr = sy0r;
-      sx0r = sx1r; sy0r = sy1r;
-      continue;
-    }
-    if ((sx1r > X0) && (sx0r > X0)) {
-      // both points to right, skip the pair
-      sxPr = sx0r; syPr = sy0r;
-      sx0r = sx1r; sy0r = sy1r;
-      continue;
-    }
-
-    // saturated values for sx0,sy0
-    sx0 = MIN (MAX (sx0r, X0), X1);
-    sy0 = MAX (MIN (sy0r, Y0), Y1);
-
-    // saturated values for sx1,sy1
-    sx1 = MIN (MAX (sx1r, X0), X1);
-    sy1 = MAX (MIN (sy1r, Y0), Y1);
-
-    if (firstPair) {
-      /* draw segment equal distance behind first point and down to x-axis */
-      sxar = sx0r - 0.5*(sx1r - sx0r);
-      sxa = MIN (MAX (sxar, X0), X1);
-      sya = MAX (sy0r, Y0);
-      XSetForeground (graphic->display, graphic->gc, graphic->fore);
-      DrawLine (sx0, sy0, sxa, sy0);
-      DrawLine (sxa, sy0, sxa, sya);
-      XSetForeground (graphic->display, graphic->gc, graphic->color[object[0].color]);
-      FillRectangle (sxa + 3, sy0 + 3, sx0 - sxa - 6, sya - sy0 - 6);
-      firstPair = FALSE;
-    }
-
-    // midpoint & saturated version
-    sxar = 0.5*(sx0r + sx1r);
-    sxa = MIN (MAX (sxar, X0), X1);
-
-    XSetForeground (graphic->display, graphic->gc, graphic->fore);
-    DrawLine (sx0, sy0, sxa, sy0);
-    DrawLine (sxa, sy0, sxa, sy1);
-    DrawLine (sxa, sy1, sx1, sy1);
-    XSetForeground (graphic->display, graphic->gc, graphic->color[object[0].color]);
-    FillRectangle (sx0 + 3, sy0 + 3, sxa - sx0 - 6, Y0 - sy0 - 6);
-    FillRectangle (sxa + 3, sy1 + 3, sx1 - sxa - 6, Y0 - sy1 - 6);
-    sxPr = sx0r; syPr = sy0r;
-    sx0r = sx1r; sy0r = sy1r;
-  }
-  
-  /* draw segment equal distance after last point and down to x-axis */
-  sxa = MIN (MAX (sx1 + 0.5*(sx1 - sxo), X0), X1);
-  sya = MAX (sy1, Y0);
-  DrawLine (sx1, sy1, sxa, sy1);
-  DrawLine (sxa, sy1, sxa, sya);
-}
-# endif
 
 // uses object->color
@@ -498,14 +386,14 @@
   /* we are drawing bars which are filled rectangles of height y[i] and width 0.5*dx
      one point at a time
+
+     I need to know the distance to the next and prev points to calculate dx
+     for the first point, dx is x[1] - x[0]
+     for the last point, dx is x[-1] - x[-2] (x[-1] is the last point)
+     for the rest, dx is 0.5*(x[i+1] - x[i-1])
+    
+     rather than working out complex on-the-fly logic, I want to find the first and last
+     valid point in an initial pass, then calculate the above for the remainder.
+     TBD: make an index vector of only valid points?
   */
-
-  // I need to know the distance to the next and prev points to calculate dx
-  // for the first point, dx is x[1] - x[0]
-  // for the last point, dx is x[-1] - x[-2] (x[-1] is the last point)
-  // for the rest, dx is 0.5*(x[i+1] - x[i-1])
-
-  // rather than working out complex on-the-fly logic, I want to find the first and last
-  // valid point in an initial pass, the calculate the above for the remainder.
-  // or make an index vector of only valid points?
 
   int Ngood = 0;
@@ -522,5 +410,4 @@
     // coordinate on the screen of the point:
     double sx1r = x[i]*mxi + y[i]*mxj + bx + XCENTER;
-    // double sy1r = x[i]*myi + y[i]*myj + by + YCENTER;
 
     if (sx1r < X0) {
@@ -576,5 +463,4 @@
     n = goodPoint[1];
     double sx1r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
-//  double sy1r = x[n]*myi + y[n]*myj + by + YCENTER;
 
     n = goodPoint[0];
@@ -605,11 +491,10 @@
     n = goodPoint[i + 1];
     double sx2r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
-    // double sy2r = x[n]*myi + y[n]*myj + by + YCENTER;
 
     n = goodPoint[i - 1];
     double sx0r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
-    // double sy0r = x[n]*myi + y[n]*myj + by + YCENTER;
-
-    double dx = 0.5*0.5*object->size*(sx2r - sx0r); // 2 factors of 0.5 (we want half of the average spacing)
+
+    // below we have 2 factors of 0.5 (we want half of the average spacing)
+    double dx = 0.5*0.5*object->size*(sx2r - sx0r);
 
     n = goodPoint[i];
@@ -642,5 +527,4 @@
     n = goodPoint[Ngood - 2];
     double sx0r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
-//  double sy0r = x[n]*myi + y[n]*myj + by + YCENTER;
 
     double dx = 0.5*object->size*(sx1r - sx0r);
Index: /trunk/Ohana/src/kapa2/src/LoadObject.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/LoadObject.c	(revision 40164)
+++ /trunk/Ohana/src/kapa2/src/LoadObject.c	(revision 40165)
@@ -42,5 +42,5 @@
       graph[0].objects[N].color = KapaColormapSize() - 1;
   }
-  if ((graph[0].objects[N].style != 2) && (graph[0].objects[N].color < 0)) {
+  if ((graph[0].objects[N].style != KAPA_PLOT_POINTS) && (graph[0].objects[N].color < 0)) {
       graph[0].objects[N].color = 0;
   }
Index: /trunk/Ohana/src/kapa2/src/PSObjects.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/PSObjects.c	(revision 40164)
+++ /trunk/Ohana/src/kapa2/src/PSObjects.c	(revision 40165)
@@ -1,7 +1,13 @@
 # include "Ximage.h"
 
+void PSBars (KapaGraphWidget *graph, Gobjects *object, FILE *f, int mode);
+
+/* DrawRectangle & FillRectangle : take rectangle lower-left corner and widths 
+   DrawCircle & FillCircle : take circle center and radius
+*/
+
 # define DrawLine(X1,Y1,X2,Y2) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, graphic->dy - Y1, X2, graphic->dy - Y2))
-# define DrawRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f B\n", (dX), (dY), (X-0.5*dX), (graphic->dy-Y-0.5*dY)))
-# define FillRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f F\n", (dX), (dY), (X-0.5*dX), (graphic->dy-Y-0.5*dY)))
+# define DrawRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f B\n", (dX), (dY), (X), (graphic->dy-Y)))
+# define FillRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f F\n", (dX), (dY), (X), (graphic->dy-Y)))
 # define DrawCircle(X1,Y1,R) (fprintf (f, " %6.2f %6.2f %6.2f C\n", (X1), (graphic->dy - Y1), (R)))
 # define FillCircle(X1,Y1,R) (fprintf (f, " %6.2f %6.2f %6.2f FC\n", (X1), (graphic->dy - Y1), (R)))
@@ -32,6 +38,6 @@
 }
 
-int PSObjectsN (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
-  
+void PSLineStyle (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+
   static char short_dash[] = "4 4";
   static char long_dash[] = "8 8";
@@ -64,4 +70,9 @@
     fprintf (f, "%s setrgbcolor\n", KapaColorRGBString(object->color));
   }
+}
+
+int PSObjectsN (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+  
+  PSLineStyle (graph, object, f);
 
   switch (object->style) {
@@ -71,4 +82,13 @@
     case KAPA_PLOT_HISTOGRAM: 
       PSHistogram (graph, object, f);
+      break;
+    case KAPA_PLOT_BARS_SOLID:
+      PSBars (graph, object, f, KAPA_PLOT_BARS_SOLID);
+      break;
+    case KAPA_PLOT_BARS_OUTLINE:
+      PSBars (graph, object, f, KAPA_PLOT_BARS_OUTLINE);
+      break;
+    case KAPA_PLOT_BARS_OUTFILL:
+      PSBars (graph, object, f, KAPA_PLOT_BARS_OUTFILL);
       break;
     case KAPA_PLOT_POINTS: 
@@ -265,25 +285,246 @@
   DrawLine (sx1, sy1, sxa, sy1);
   DrawLine (sxa, sy1, sxa, sya);
-
-# if (0)
-  sx0 = x[i]*mxi + y[i]*mxj + bx;
-  sy0 = x[i]*myi + y[i]*myj + by;
-  sx0 = MIN (MAX (sx0, X0), X1);
-  sy0 = MAX (MIN (sy0, Y0), Y1);
-  
-  /* continue with rest of points */
-  for (i++; i < object[0].Npts; i++) {
+}
+
+// uses object->color
+# define HISTOGRAM_SOLID(X_VALUE, Y_VALUE, DX_VAL) {			\
+  /* histogram bar corners */						\
+  double sxmin = (X_VALUE) - 0.5*(DX_VAL);				\
+  double sxmax = (X_VALUE) + 0.5*(DX_VAL);				\
+  double symin = Xaxis;							\
+  double symax = (Y_VALUE);						\
+  /* saturated values for corner coords: */				\
+  sxmin = MIN (MAX (sxmin, X0), X1);					\
+  sxmax = MIN (MAX (sxmax, X0), X1);					\
+  symin = MAX (MIN (symin, Y0), Y1);					\
+  symax = MAX (MIN (symax, Y0), Y1);					\
+  double dy = fabs(symax - symin);					\
+  double ylow = MAX(symin, symax);					\
+  FillRectangle (sxmin, ylow, (DX_VAL), dy); }
+
+// uses object->color
+# define HISTOGRAM_OUTLINE(X_VALUE, Y_VALUE, DX_VAL) {			\
+  /* histogram bar corners */						\
+  double sxmin = (X_VALUE) - 0.5*(DX_VAL);				\
+  double sxmax = (X_VALUE) + 0.5*(DX_VAL);				\
+  double symin = Xaxis;							\
+  double symax = (Y_VALUE);						\
+  /* saturated values for corner coords: */				\
+  sxmin = MIN (MAX (sxmin, X0), X1);					\
+  sxmax = MIN (MAX (sxmax, X0), X1);					\
+  symin = MAX (MIN (symin, Y0), Y1);					\
+  symax = MAX (MIN (symax, Y0), Y1);					\
+  double dy = fabs(symax - symin);					\
+  double ylow = MAX(symin, symax);					\
+  DrawRectangle (sxmin, ylow, (DX_VAL), dy); }
+
+# define HISTOGRAM_OUTFILL(X_VALUE, Y_VALUE, DX_VAL) {			\
+  /* histogram bar corners */						\
+  double sxmin = (X_VALUE) - 0.5*(DX_VAL);				\
+  double sxmax = (X_VALUE) + 0.5*(DX_VAL);				\
+  double symin = Xaxis;							\
+  double symax = (Y_VALUE);						\
+  /* saturated values for corner coords: */				\
+  sxmin = MIN (MAX (sxmin, X0), X1);					\
+  sxmax = MIN (MAX (sxmax, X0), X1);					\
+  symin = MAX (MIN (symin, Y0), Y1);					\
+  symax = MAX (MIN (symax, Y0), Y1);					\
+  double dy = fabs(symax - symin);					\
+  double ylow = MAX(symin, symax);					\
+  FillRectangle (sxmin, ylow, (DX_VAL), dy);				\
+  fprintf (f, "0.00 0.00 0.00 setrgbcolor\n");				\
+  DrawRectangle (sxmin, ylow, (DX_VAL), dy);				\
+  fprintf (f, "%s setrgbcolor\n", KapaColorRGBString(object->color)); }
+
+void PSBars (KapaGraphWidget *graph, Gobjects *object, FILE *f, int mode) {
+
+  double mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0); // slope of the x-axis in x-pixels
+  double mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0); // slope of the x-axis in y-pixels (always 0 for now)
+  double myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0); // slope of the x-axis in x-pixels (always 0 for now)
+  double myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); // slope of the x-axis in x-pixels
+  
+  // intercepts of axes
+  double bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  double bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  double byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  double byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  double bx = bxi + bxj;
+  double by = byi + byj;
+  
+  // corner coords
+  double X0 = graph[0].axis[0].fx;
+  double X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  double Y0 = graph[0].axis[1].fy;
+  double Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+  // NOTE: Y0 > Y1 (dfy is negative)
+
+  /* find the first valid datapoint */
+  float *x = object[0].x;
+  float *y = object[0].y;
+  
+  /* we are drawing bars which are filled rectangles of height y[i] and width 0.5*dx
+     one point at a time
+
+     I need to know the distance to the next and prev points to calculate dx
+     for the first point, dx is x[1] - x[0]
+     for the last point, dx is x[-1] - x[-2] (x[-1] is the last point)
+     for the rest, dx is 0.5*(x[i+1] - x[i-1])
+    
+     rather than working out complex on-the-fly logic, I want to find the first and last
+     valid point in an initial pass, then calculate the above for the remainder.
+     TBD: make an index vector of only valid points?
+  */
+
+  int Ngood = 0;
+  ALLOCATE_PTR (goodPoint, int, object[0].Npts);
+
+  // x = ??, y = 0: this assumes the xaxis is parallel to the plot window (myi = 0)
+  // note: Y0 > Y1 : y runs from large on bottom to small on top
+  float Xaxis = by;
+  Xaxis = MAX (Y1, MIN (Xaxis, Y0));
+
+  for (int i = 0; i < object[0].Npts; i++) {
     if (!(finite(x[i]) && finite(y[i]))) continue;
-    sx1 = x[i]*mxi + y[i]*mxj + bx;
-    sy1 = x[i]*myi + y[i]*myj + by;
-    sx1 = MIN (MAX (sx1, X0), X1);
-    sy1 = MAX (MIN (sy1, Y0), Y1);
-    sxa = 0.5*(sx0 + sx1);
-    DrawLine (sx0, sy0, sxa, sy0);
-    DrawLine (sxa, sy0, sxa, sy1);
-    DrawLine (sxa, sy1, sx1, sy1);
-    sx0 = sx1; sy0 = sy1;
-  }
-# endif
+
+    // coordinate on the screen of the point:
+    double sx1r = x[i]*mxi + y[i]*mxj + bx;
+
+    if (sx1r < X0) {
+      // point to the left, skip it
+      continue;
+    }
+    if (sx1r > X1) {
+      // point to the right, skip it
+      continue;
+    }
+
+    goodPoint[Ngood] = i;
+    Ngood ++;
+  }
+    
+  if (Ngood == 0) {
+    free (goodPoint);
+    return;
+  }
+
+  // if we only have 1 point, draw bar half the width of the screen
+  // this works fine, but the auto limits for 1 value are somewhat silly
+  if (Ngood == 1) {
+    // coordinate on the screen of the point:
+    int n = goodPoint[0];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+    double sy1r = x[n]*myi + y[n]*myj + by;
+
+    float dx = 0.5*object->size*(X1 - X0);
+    
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+    }
+
+    free (goodPoint);
+    return;
+  }
+
+  // first point:
+  {
+    int n;
+    n = goodPoint[1];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+
+    n = goodPoint[0];
+    double sx0r = x[n]*mxi + y[n]*mxj + bx;
+    double sy0r = x[n]*myi + y[n]*myj + by;
+
+    double dx = 0.5*object->size*(sx1r - sx0r);
+    
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx0r, sy0r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx0r, sy0r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx0r, sy0r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx0r, sy0r, dx);
+	break;
+    }
+  }
+
+  for (int i = 1; i < Ngood - 1; i++) {
+
+    int n;
+    n = goodPoint[i + 1];
+    double sx2r = x[n]*mxi + y[n]*mxj + bx;
+
+    n = goodPoint[i - 1];
+    double sx0r = x[n]*mxi + y[n]*mxj + bx;
+
+    // below we have 2 factors of 0.5 (we want half of the average spacing)
+    double dx = 0.5*0.5*object->size*(sx2r - sx0r);
+
+    n = goodPoint[i];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+    double sy1r = x[n]*myi + y[n]*myj + by;
+
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+    }
+  }
+  
+  // last point:
+  {
+    int n;
+    n = goodPoint[Ngood - 1];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+    double sy1r = x[n]*myi + y[n]*myj + by;
+
+    n = goodPoint[Ngood - 2];
+    double sx0r = x[n]*mxi + y[n]*mxj + bx;
+
+    double dx = 0.5*object->size*(sx1r - sx0r);
+
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+    }
+  }
+  free (goodPoint);
+  return;
 }
 
@@ -310,6 +551,5 @@
   by = byi + byj;
   
-  Graphic *graphic = GetGraphic();
-
+  // scaled colors use the colormap defined for the graphic
   ALLOCATE (pixel1, float, graphic[0].Npixels);
   ALLOCATE (pixel2, float, graphic[0].Npixels);
@@ -347,5 +587,5 @@
 	  }
 	  D = scaleSize ? dz*z[i] : ds;
-	  DrawRectangle (sx, sy, 2*D, 2*D);
+	  DrawRectangle (sx - D, sy - D, 2*D, 2*D);
 	}
       }
@@ -605,5 +845,5 @@
 	  }
 	  D = scaleSize ? dz*z[i] : ds;
-	  FillRectangle (sx, sy, 2*D, 2*D);
+	  FillRectangle (sx - D, sy - D, 2*D, 2*D);
 	}
       }
Index: /trunk/Ohana/src/kapa2/src/bDrawObjects.c
===================================================================
--- /trunk/Ohana/src/kapa2/src/bDrawObjects.c	(revision 40164)
+++ /trunk/Ohana/src/kapa2/src/bDrawObjects.c	(revision 40165)
@@ -2,6 +2,6 @@
 
 # define DrawLine(BUF,X1,Y1,X2,Y2) (bDrawLine (BUF, (X1), (Y1), (X2), (Y2)))
-# define DrawRectangle(BUF,X,Y,dX,dY) (bDrawRectOpen (BUF, (X-0.5*dX), (Y-0.5*dY), (X+0.5*dX), (Y+0.5*dY)))
-# define FillRectangle(BUF,X,Y,dX,dY) (bDrawRectFill (BUF, (X-0.5*dX), (Y-0.5*dY), (X+0.5*dX+1), (Y+0.5*dY+1)))
+# define DrawRectangle(BUF,X,Y,dX,dY) (bDrawRectOpen (BUF, (X), (Y), (X+dX), (Y+dY)))
+# define FillRectangle(BUF,X,Y,dX,dY) (bDrawRectFill (BUF, (X), (Y), (X+dX+1), (Y+dY+1)))
 # define DrawCircle(BUF,X1,Y1,R) (bDrawCircle (BUF, (X1), (Y1), (R)))
 # define FillCircle(BUF,X1,Y1,R) (bDrawCircleFill (BUF, (X1), (Y1), (R)))
@@ -9,8 +9,4 @@
 # define OpenTriangle(BUF,X1,Y1,X2,Y2,X3,Y3) (bDrawTriOpen (BUF, (X1), (Y1), (X2), (Y2), (X3), (Y3)))
 
-# define CONNECT 0
-# define HISTOGRAM 1
-# define POINTS 2
-
 static Graphic *graphic;
 
@@ -42,4 +38,13 @@
     case KAPA_PLOT_HISTOGRAM:
       bDrawHistogram (buffer, graph, object);
+      break;
+    case KAPA_PLOT_BARS_SOLID:
+      bDrawBars (buffer, graph, object, KAPA_PLOT_BARS_SOLID);
+      break;
+    case KAPA_PLOT_BARS_OUTLINE:
+      bDrawBars (buffer, graph, object, KAPA_PLOT_BARS_OUTLINE);
+      break;
+    case KAPA_PLOT_BARS_OUTFILL:
+      bDrawBars (buffer, graph, object, KAPA_PLOT_BARS_OUTFILL);
       break;
     case KAPA_PLOT_POINTS:
@@ -235,25 +240,246 @@
   DrawLine (buffer, sx1, sy1, sxa, sy1);
   DrawLine (buffer, sxa, sy1, sxa, sya);
-
-# if (0)
-  sx0 = x[i]*mxi + y[i]*mxj + bx;
-  sy0 = x[i]*myi + y[i]*myj + by;
-  sx0 = MIN (MAX (sx0, X0), X1);
-  sy0 = MAX (MIN (sy0, Y0), Y1);
-  
-  /* continue with rest of points */
-  for (i++; i < object[0].Npts; i++) {
+}
+
+// uses object->color
+# define HISTOGRAM_SOLID(X_VALUE, Y_VALUE, DX_VAL) {			\
+  /* histogram bar corners */						\
+  double sxmin = (X_VALUE) - 0.5*(DX_VAL);				\
+  double sxmax = (X_VALUE) + 0.5*(DX_VAL);				\
+  double symin = Xaxis;							\
+  double symax = (Y_VALUE);						\
+  /* saturated values for corner coords: */				\
+  sxmin = MIN (MAX (sxmin, X0), X1);					\
+  sxmax = MIN (MAX (sxmax, X0), X1);					\
+  symin = MAX (MIN (symin, Y0), Y1);					\
+  symax = MAX (MIN (symax, Y0), Y1);					\
+  double dy = fabs(symax - symin);					\
+  double ylow = MIN(symin, symax);					\
+  FillRectangle (buffer, sxmin, ylow, (DX_VAL), dy); }
+
+// uses object->color
+# define HISTOGRAM_OUTLINE(X_VALUE, Y_VALUE, DX_VAL) {			\
+  /* histogram bar corners */						\
+  double sxmin = (X_VALUE) - 0.5*(DX_VAL);				\
+  double sxmax = (X_VALUE) + 0.5*(DX_VAL);				\
+  double symin = Xaxis;							\
+  double symax = (Y_VALUE);						\
+  /* saturated values for corner coords: */				\
+  sxmin = MIN (MAX (sxmin, X0), X1);					\
+  sxmax = MIN (MAX (sxmax, X0), X1);					\
+  symin = MAX (MIN (symin, Y0), Y1);					\
+  symax = MAX (MIN (symax, Y0), Y1);					\
+  double dy = fabs(symax - symin);					\
+  double ylow = MIN(symin, symax);					\
+  DrawRectangle (buffer, sxmin, ylow, (DX_VAL), dy); }
+
+# define HISTOGRAM_OUTFILL(X_VALUE, Y_VALUE, DX_VAL) {			\
+  /* histogram bar corners */						\
+  double sxmin = (X_VALUE) - 0.5*(DX_VAL);				\
+  double sxmax = (X_VALUE) + 0.5*(DX_VAL);				\
+  double symin = Xaxis;							\
+  double symax = (Y_VALUE);						\
+  /* saturated values for corner coords: */				\
+  sxmin = MIN (MAX (sxmin, X0), X1);					\
+  sxmax = MIN (MAX (sxmax, X0), X1);					\
+  symin = MAX (MIN (symin, Y0), Y1);					\
+  symax = MAX (MIN (symax, Y0), Y1);					\
+  double dy = fabs(symax - symin);					\
+  double ylow = MIN(symin, symax);					\
+  FillRectangle (buffer, sxmin, ylow, (DX_VAL), dy);			\
+  bDrawSetColor (buffer, graphic->fore);				\
+  DrawRectangle (buffer, sxmin, ylow, (DX_VAL), dy);			\
+  bDrawSetColor (buffer, object[0].color); }
+
+void bDrawBars (bDrawBuffer *buffer, KapaGraphWidget *graph, Gobjects *object, int mode) {
+
+  double mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0); // slope of the x-axis in x-pixels
+  double mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0); // slope of the x-axis in y-pixels (always 0 for now)
+  double myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0); // slope of the x-axis in x-pixels (always 0 for now)
+  double myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); // slope of the x-axis in x-pixels
+  
+  // intercepts of axes
+  double bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  double bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  double byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  double byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  double bx = bxi + bxj;
+  double by = byi + byj;
+  
+  // corner coords
+  double X0 = graph[0].axis[0].fx;
+  double X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  double Y0 = graph[0].axis[1].fy;
+  double Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  float *x = object[0].x;
+  float *y = object[0].y;
+  
+  /* we are drawing bars which are filled rectangles of height y[i] and width 0.5*dx
+     one point at a time
+
+     I need to know the distance to the next and prev points to calculate dx
+     for the first point, dx is x[1] - x[0]
+     for the last point, dx is x[-1] - x[-2] (x[-1] is the last point)
+     for the rest, dx is 0.5*(x[i+1] - x[i-1])
+    
+     rather than working out complex on-the-fly logic, I want to draw the first and last
+     valid points in an initial pass, then calculate the above for the remainder.
+
+     First, make an index vector of only valid points
+  */
+
+  int Ngood = 0;
+  ALLOCATE_PTR (goodPoint, int, object[0].Npts);
+
+  // x = ??, y = 0: this assumes the xaxis is parallel to the plot window (myi = 0)
+  // since y runs from large on bottom to small on top, this is slightly backwards
+  float Xaxis = by;
+  Xaxis = MAX (Y1, MIN (Xaxis, Y0)); // MIN & MAX reversed for neg y dir
+
+  for (int i = 0; i < object[0].Npts; i++) {
     if (!(finite(x[i]) && finite(y[i]))) continue;
-    sx1 = x[i]*mxi + y[i]*mxj + bx;
-    sy1 = x[i]*myi + y[i]*myj + by;
-    sx1 = MIN (MAX (sx1, X0), X1);
-    sy1 = MAX (MIN (sy1, Y0), Y1);
-    sxa = 0.5*(sx0 + sx1);
-    DrawLine (buffer, sx0, sy0, sxa, sy0);
-    DrawLine (buffer, sxa, sy0, sxa, sy1);
-    DrawLine (buffer, sxa, sy1, sx1, sy1);
-    sx0 = sx1; sy0 = sy1;
-  }
-# endif
+
+    // coordinate on the screen of the point:
+    double sx1r = x[i]*mxi + y[i]*mxj + bx;
+
+    if (sx1r < X0) {
+      // point to the left, skip it
+      continue;
+    }
+    if (sx1r > X1) {
+      // point to the right, skip it
+      continue;
+    }
+
+    goodPoint[Ngood] = i;
+    Ngood ++;
+  }
+    
+  if (Ngood == 0) {
+    free (goodPoint);
+    return;
+  }
+
+  // if we only have 1 point, draw bar half the width of the screen
+  // this works fine, but the auto limits for 1 value are somewhat silly
+  if (Ngood == 1) {
+    // coordinate on the screen of the point:
+    int n = goodPoint[0];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+    double sy1r = x[n]*myi + y[n]*myj + by;
+
+    float dx = 0.5*object->size*(X1 - X0);
+    
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+    }
+
+    free (goodPoint);
+    return;
+  }
+
+  // first point:
+  {
+    int n;
+    n = goodPoint[1];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+
+    n = goodPoint[0];
+    double sx0r = x[n]*mxi + y[n]*mxj + bx;
+    double sy0r = x[n]*myi + y[n]*myj + by;
+
+    double dx = 0.5*object->size*(sx1r - sx0r);
+    
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx0r, sy0r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx0r, sy0r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx0r, sy0r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx0r, sy0r, dx);
+	break;
+    }
+  }
+
+  for (int i = 1; i < Ngood - 1; i++) {
+
+    int n;
+    n = goodPoint[i + 1];
+    double sx2r = x[n]*mxi + y[n]*mxj + bx;
+
+    n = goodPoint[i - 1];
+    double sx0r = x[n]*mxi + y[n]*mxj + bx;
+
+    // below we have 2 factors of 0.5 (we want half of the average spacing)
+    double dx = 0.5*0.5*object->size*(sx2r - sx0r);
+
+    n = goodPoint[i];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+    double sy1r = x[n]*myi + y[n]*myj + by;
+
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+    }
+  }
+  
+  // last point:
+  {
+    int n;
+    n = goodPoint[Ngood - 1];
+    double sx1r = x[n]*mxi + y[n]*mxj + bx;
+    double sy1r = x[n]*myi + y[n]*myj + by;
+
+    n = goodPoint[Ngood - 2];
+    double sx0r = x[n]*mxi + y[n]*mxj + bx;
+
+    double dx = 0.5*object->size*(sx1r - sx0r);
+
+    switch (mode) {
+      case KAPA_PLOT_BARS_SOLID:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTLINE:
+	HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
+	break;
+      case KAPA_PLOT_BARS_OUTFILL:
+	HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
+	break;
+      default:
+	HISTOGRAM_SOLID(sx1r, sy1r, dx);
+	break;
+    }
+  }
+  free (goodPoint);
+  return;
 }
 
@@ -280,6 +506,5 @@
   by = byi + byj;
   
-  Graphic *graphic = GetGraphic();
-
+  // scaled colors use the colormap defined for the graphic
   ALLOCATE (pixel1, unsigned char, graphic[0].Npixels);
   ALLOCATE (pixel2, unsigned char, graphic[0].Npixels);
@@ -293,5 +518,5 @@
   }
 
-  /**** points are scaled by object.z ***/
+  /**** point sizes are scaled by object.size, colors by object.color ***/
   int scaleSize = (object[0].size < 0);
   int scaleColor = (object[0].color < 0);
@@ -317,5 +542,5 @@
 	  }
 	  D = scaleSize ? dz*z[i] : ds;
-	  DrawRectangle (buffer, sx, sy, 2*D, 2*D);
+	  DrawRectangle (buffer, sx - D, sy - D, 2*D, 2*D); // DrawRectangle takes corner point
 	  // plot range saturated by bDrawRectOpen
 	}
@@ -611,5 +836,5 @@
 	  }
 	  D = scaleSize ? dz*z[i] : ds;
-	  FillRectangle (buffer, sx, sy, 2*D, 2*D);
+	  FillRectangle (buffer, sx - D, sy - D, 2*D, 2*D);
 	  // plot range saturated by bDrawRectFill
 	}
Index: /trunk/Ohana/src/libkapa/include/kapa.h
===================================================================
--- /trunk/Ohana/src/libkapa/include/kapa.h	(revision 40164)
+++ /trunk/Ohana/src/libkapa/include/kapa.h	(revision 40165)
@@ -292,4 +292,5 @@
 void bDrawBufferFree (bDrawBuffer *buffer);
 void bDrawSetBuffer (bDrawBuffer *buffer);
+void bDrawSetColor (bDrawBuffer *buffer, bDrawColor color);
 void bDrawSetStyle (bDrawBuffer *buffer, bDrawColor color, int lw, int lt);
 void bDrawPoint (bDrawBuffer *buffer, int x, int y);
Index: /trunk/Ohana/src/libkapa/src/KapaWindow.c
===================================================================
--- /trunk/Ohana/src/libkapa/src/KapaWindow.c	(revision 40164)
+++ /trunk/Ohana/src/libkapa/src/KapaWindow.c	(revision 40165)
@@ -94,5 +94,6 @@
   graphdata[0].xmax = graphdata[0].ymax = 1.0;
 
-  graphdata[0].style = graphdata[0].ptype = 2;
+  graphdata[0].style = KAPA_PLOT_POINTS;
+  graphdata[0].ptype = KAPA_POINT_BOX_SOLID;
   graphdata[0].ltype = graphdata[0].color = 0;
   graphdata[0].etype = graphdata[0].ebar = 0;
Index: /trunk/Ohana/src/libkapa/src/PSRotFont.c
===================================================================
--- /trunk/Ohana/src/libkapa/src/PSRotFont.c	(revision 40164)
+++ /trunk/Ohana/src/libkapa/src/PSRotFont.c	(revision 40165)
@@ -90,24 +90,24 @@
     /* check for special characters */
     if (!code && !protect) {
-      /* superscript character (^) */
+      /* subscript character (_) */
       if (N == 94) {
 	PSDumpRotSegment (f, segment, &Nseg);
-	SetRotFont (currentname, (int)(0.8*currentsize));
+	PSSetFont (f, currentname, (int)(0.8*currentsize));
 	currentfont = GetRotFontData (&currentscale);
 	Yoff = 0.75*currentscale*dY;
 	fprintf (f, "0 %d rmoveto\n", Yoff);
 	YoffBase += Yoff;
-	PSSetFont (f, currentname, currentsize);
-	continue;
-      }
-      /* subscript character (_) */
+	// PSSetFont (f, currentname, currentsize);
+	continue;
+      }
+      /* superscript character (^) */
       if (N == 95) { 
 	PSDumpRotSegment (f, segment, &Nseg);
-	SetRotFont (currentname, (int)(0.8*currentsize));
+	PSSetFont (f, currentname, (int)(0.8*currentsize));
 	currentfont = GetRotFontData (&currentscale);
 	Yoff = -0.5*currentscale*dY;
 	fprintf (f, "0 %d rmoveto\n", Yoff);
 	YoffBase += Yoff;
-	PSSetFont (f, currentname, currentsize);
+	// PSSetFont (f, currentname, currentsize);
 	continue;
       }
@@ -115,9 +115,9 @@
       if (N == 124) {
 	PSDumpRotSegment (f, segment, &Nseg);
-	SetRotFont (currentname, basesize);
+	PSSetFont (f, currentname, basesize);
 	currentfont = GetRotFontData (&currentscale);
 	fprintf (f, "0 %d rmoveto\n", -YoffBase);
 	YoffBase = 0;
-	PSSetFont (f, currentname, currentsize);
+	// PSSetFont (f, currentname, currentsize);
 	continue;
       }
@@ -145,22 +145,22 @@
 	PSDumpRotSegment (f, segment, &Nseg);
 	if (string[i+1] == 'h') {
-	  SetRotFont ("helvetica", currentsize);
-	  currentfont = GetRotFontData (&currentscale);
-	  PSSetFont (f, currentname, currentsize);
+	  PSSetFont (f, "helvetica", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	  // PSSetFont (f, currentname, currentsize);
 	}
 	if (string[i+1] == 't') {
-	  SetRotFont ("times", currentsize);
-	  currentfont = GetRotFontData (&currentscale);
-	  PSSetFont (f, currentname, currentsize);
+	  PSSetFont (f, "times", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	  // PSSetFont (f, currentname, currentsize);
 	}
 	if (string[i+1] == 'c') {
-	  SetRotFont ("courier", currentsize);
-	  currentfont = GetRotFontData (&currentscale);
-	  PSSetFont (f, currentname, currentsize);
+	  PSSetFont (f, "courier", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	  // PSSetFont (f, currentname, currentsize);
 	}
 	if (string[i+1] == 's') {
-	  SetRotFont ("symbol", currentsize);
-	  currentfont = GetRotFontData (&currentscale);
-	  PSSetFont (f, currentname, currentsize);
+	  PSSetFont (f, "symbol", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	  // PSSetFont (f, currentname, currentsize);
 	}
 	i++;
@@ -176,5 +176,5 @@
   fprintf (f, "stroke grestore\n");
   free (segment);
-  SetRotFont (basename, basesize);
+  PSSetFont (f, basename, basesize);
 }
 
Index: /trunk/Ohana/src/libkapa/src/bDrawFuncs.c
===================================================================
--- /trunk/Ohana/src/libkapa/src/bDrawFuncs.c	(revision 40164)
+++ /trunk/Ohana/src/libkapa/src/bDrawFuncs.c	(revision 40165)
@@ -76,9 +76,16 @@
 // }
 
-void bDrawSetStyle (bDrawBuffer *buffer, bDrawColor color, int lw, int lt) {
+// "bDrawColor color" is one of the hardwired colors in KapaColors.c
+void bDrawSetColor (bDrawBuffer *buffer, bDrawColor color) {
   buffer->bColor = color;
   buffer->bColor_R = buffer->palette[color].red;
   buffer->bColor_G = buffer->palette[color].green;
   buffer->bColor_B = buffer->palette[color].blue;
+
+  return;
+}
+
+void bDrawSetStyle (bDrawBuffer *buffer, bDrawColor color, int lw, int lt) {
+  bDrawSetColor (buffer, color);
 
   buffer->bWeight = lw;
@@ -121,4 +128,5 @@
 }
 
+// x1,y1 is lower-left corner, x2,y2 is upper-right corner
 void bDrawRectOpen (bDrawBuffer *buffer, double x1, double y1, double x2, double y2) {
 
Index: /trunk/Ohana/src/opihi/cmd.astro/cdot.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/cdot.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.astro/cdot.c	(revision 40165)
@@ -22,5 +22,5 @@
 
   /* set point style and errorbar mode (these are NOT sticky) */
-  graphmode.style = 2;
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
   graphmode.etype = 0;
 
Index: /trunk/Ohana/src/opihi/cmd.astro/cgrid.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/cgrid.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.astro/cgrid.c	(revision 40165)
@@ -276,6 +276,6 @@
   /* send the line segments as connect-points */
   Xvec.Nelements = Yvec.Nelements = N;
-  graphmode.style = 2; /* points */
-  graphmode.ptype = 100; /* connect a pair */
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
+  graphmode.ptype = KAPA_POINT_PAIR_CONNECT; /* connect pairs of points */
   graphmode.etype = 0;
   PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
Index: /trunk/Ohana/src/opihi/cmd.astro/cline.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/cline.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.astro/cline.c	(revision 40165)
@@ -20,5 +20,5 @@
 
   /* set point style and errorbar mode (these are NOT sticky) */
-  graphmode.style = 0;
+  graphmode.style = KAPA_PLOT_CONNECT;
   graphmode.etype = 0;
 
Index: /trunk/Ohana/src/opihi/cmd.astro/czplot.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/czplot.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.astro/czplot.c	(revision 40165)
@@ -111,5 +111,5 @@
   Zvec.Nelements = Npts;
 
-  graphmode.style = 2;
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
   graphmode.size = -1; /* point size determined by Zvec */
   graphmode.etype = 0;
@@ -236,5 +236,5 @@
   Zvec.Nelements = Npts;
 
-  graphmode.style = 2;
+  graphmode.style = KAPA_PLOT_POINTS;
   graphmode.color = -1; /* point color determined by Zvec */
   graphmode.etype = 0;
Index: /trunk/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 40165)
@@ -102,4 +102,5 @@
 $(SRC)/peak.$(ARCH).o		\
 $(SRC)/periodogram.$(ARCH).o	\
+$(SRC)/periodogram-fm.$(ARCH).o	\
 $(SRC)/plot.$(ARCH).o		\
 $(SRC)/dot.$(ARCH).o		\
Index: /trunk/Ohana/src/opihi/cmd.data/dot.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/dot.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.data/dot.c	(revision 40165)
@@ -29,5 +29,5 @@
 
   /* set point style and errorbar mode (these are NOT sticky) */
-  graphmode.style = 2;
+  graphmode.style = KAPA_PLOT_POINTS;
   graphmode.etype = 0;
 
Index: /trunk/Ohana/src/opihi/cmd.data/grid.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/grid.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.data/grid.c	(revision 40165)
@@ -175,6 +175,6 @@
 
   Xvec.Nelements = Yvec.Nelements = N;
-  graphmode.style = 2; /* points */
-  graphmode.ptype = 100; /* connect a pair */
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
+  graphmode.ptype = KAPA_POINT_PAIR_CONNECT; /* connect pairs of points */
   graphmode.etype = 0;
   PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
Index: /trunk/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/init.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.data/init.c	(revision 40165)
@@ -91,4 +91,5 @@
 int peak             PROTO((int, char **));
 int periodogram      PROTO((int, char **));
+int periodogram_fm   PROTO((int, char **));
 int plot             PROTO((int, char **));
 int dot              PROTO((int, char **));
@@ -270,5 +271,6 @@
   {1, "parity",       parity,           "set image parity"},
   {1, "peak",         peak,             "find vector peak in range"},
-  {1, "periodogram",  periodogram,      "measure periods in unevenly sampled data"},
+  {1, "periodogram",    periodogram,    "measure periods in unevenly sampled data (Lomb-Scargle)"},
+  {1, "periodogram_fm", periodogram_fm, "measure periods in unevenly sampled data (generalized Lomb-Scargle; floating mean)"},
   {1, "plot",         plot,             "plot a pair of vectors"},
   {1, "png",          jpeg,             "convert display graphic to PNG"},
Index: /trunk/Ohana/src/opihi/cmd.data/line.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/line.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.data/line.c	(revision 40165)
@@ -33,5 +33,5 @@
 
   /* set point style and errorbar mode (these are NOT sticky) */
-  graphmode.style = 0;
+  graphmode.style = KAPA_PLOT_CONNECT;
   graphmode.etype = 0;
 
Index: /trunk/Ohana/src/opihi/cmd.data/periodogram-fm.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/periodogram-fm.c	(revision 40165)
+++ /trunk/Ohana/src/opihi/cmd.data/periodogram-fm.c	(revision 40165)
@@ -0,0 +1,146 @@
+# include "data.h"
+# define MIN_VAR 1e-8
+int periodogram_fm (int argc, char **argv) {
+  
+  int N;
+
+  int VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 8) {
+    gprint (GP_ERR, "USAGE: periodogram_fm (time) (flux) (dflux) (minP) (maxP) (period) (power)\n");
+    return (FALSE);
+  }
+  
+  // XXX allow dflux to be dropped?
+
+  Vector *time, *flux, *dflux, *power, *period;
+  if ((time   = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((flux   = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dflux  = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((period = SelectVector (argv[6], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((power  = SelectVector (argv[7], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  double minP = atof(argv[4]);
+  double maxP = atof(argv[5]);
+
+  REQUIRE_VECTOR_FLT (time, FALSE); 
+  REQUIRE_VECTOR_FLT (flux, FALSE); 
+  REQUIRE_VECTOR_FLT (dflux, FALSE); 
+
+  /* find the max baseline, sum the inverse variances */
+  double minT = time[0].elements.Flt[0];
+  double maxT = time[0].elements.Flt[0];
+  opihi_flt Weight = 0;
+  int Npt = time[0].Nelements;
+
+  opihi_flt *tv =  time[0].elements.Flt;
+  opihi_flt *df = dflux[0].elements.Flt;
+  for (int i = 0; i < Npt; i++, tv++, df++) {
+    minT = MIN (minT, *tv);
+    maxT = MAX (maxT, *tv);
+    // skip points with 0.0 error? or add minimum variance?
+    Weight += 1.0 / (SQ(*df) + MIN_VAR); // MIN_VAR : added in quadrature to avoid Inf (XXX make this a user parameter?)
+  }
+
+  double WeightInv = 1.0 / Weight;
+  double dTime = maxT - minT;
+  if (dTime == 0) {
+    gprint (GP_ERR, "ERROR: time range is zero\n");
+    return (FALSE);
+  }
+
+  int Np = 0;
+  int NP = 100;
+  ResetVector (power,  OPIHI_FLT, NP);
+  ResetVector (period, OPIHI_FLT, NP);
+
+  // for testing, we are going to write out the terms explicitly 
+  // for optimization, some of the tri functions can be calculated more efficiently 
+  // by storing cos,sin(w t) and using some recurrence rules
+
+  // XXX consider choice of period or frequency step
+  double P = minP;
+  while (P <= maxP) {
+    double w = 2*M_PI/P;
+    
+    /* find the period offset tau  */
+    tv = time[0].elements.Flt;
+    df = dflux[0].elements.Flt;
+
+    double cs = 0.0, sn = 0.0, sn2 = 0.0, cs2 = 0.0;
+
+    for (int i = 0; i < Npt; i++, tv++, df++) {
+      opihi_flt wt = WeightInv / (SQ(*df) + MIN_VAR);
+      cs  += wt*cos (*tv*w);
+      sn  += wt*sin (*tv*w);
+      cs2 += wt*cos (*tv*w*2);
+      sn2 += wt*sin (*tv*w*2);
+    }
+    double ytan = sn2 - 2*cs*sn;
+    double xtan = cs2 - (SQ(cs) - SQ(sn));
+    double tau = 0.5*atan2 (ytan, xtan) / w;
+      
+    /* find the power at this period */
+    tv = time[0].elements.Flt;
+    df = dflux[0].elements.Flt;
+    opihi_flt *fv = flux[0].elements.Flt;
+
+    // YY = YY_s - Y_s*Y_s
+    // CC = CC_s - C_s*C_s
+    // SS = SS_s - S_s*S_s
+    // YC = YC_s - Y_s*C_s
+    // YS = YS_s - Y_s*S_s
+    
+    double YY_s = 0.0, CC_s = 0.0, SS_s = 0.0, YC_s = 0.0, YS_s = 0.0;
+    double Y_s = 0.0, C_s = 0.0, S_s = 0.0;
+    for (int i = 0; i < Npt; i++, tv++, fv++, df++) {
+      opihi_flt wt = WeightInv / (SQ(*df) + MIN_VAR);
+      cs = cos (w*(*tv-tau));
+      sn = sin (w*(*tv-tau));
+
+      double wtf = *fv*wt;
+      Y_s += wtf;
+      C_s += wt*cs;
+      S_s += wt*sn;
+
+      YY_s += wtf*(*fv);
+      YC_s += wtf*cs;
+      YS_s += wtf*sn;
+
+      CC_s += wt*cs*cs;
+      SS_s += wt*sn*sn;
+    }
+    double YY = YY_s - SQ(Y_s);
+    double YC = YC_s - Y_s*C_s;
+    double YS = YS_s - Y_s*S_s;
+    double CC = CC_s - SQ(C_s);
+    double SS = SS_s - SQ(S_s);
+
+    double Pa = SQ(YC) / CC;
+    double Pb = SQ(YS) / SS;
+    double Po = (Pa + Pb) / YY;
+
+    power[0].elements.Flt[Np] = Po;
+    period[0].elements.Flt[Np] = P;
+    Np ++;
+    if (Np >= NP) {
+      NP += 100;
+      REALLOCATE (power[0].elements.Flt, opihi_flt, NP);
+      REALLOCATE (period[0].elements.Flt, opihi_flt, NP);
+    }
+
+    double ratio = 1 + 0.1*P/dTime;
+
+    if (VERBOSE) gprint (GP_ERR, "tau: %f, P: %f, ratio: %f, dTime: %f, nextP: %f\n", tau, P, ratio, dTime, P*ratio);
+
+    P *= ratio;
+  }
+
+  ResetVector (power,  OPIHI_FLT, Np);
+  ResetVector (period, OPIHI_FLT, Np);
+ 
+  return (TRUE);
+}
Index: /trunk/Ohana/src/opihi/cmd.data/test/periodogram-fm.sh
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/test/periodogram-fm.sh	(revision 40165)
+++ /trunk/Ohana/src/opihi/cmd.data/test/periodogram-fm.sh	(revision 40165)
@@ -0,0 +1,313 @@
+
+if (not($?PLOT)) set PLOT = 0
+
+list tests
+ test1
+ test2
+ test3
+ memtest1
+end
+
+# test using even samples
+macro test1
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q t f period power
+
+ create t 0 100
+ set f = sin(2*$PI*t/$P)
+ set df = 0.01 + zero(f)
+
+ periodogram_fm t f df 5 50 period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.5)
+   $PASS = 0
+   echo "OFFSET: {$peakpos - $P}"
+ end
+
+ if ($PLOT)
+  lim period power; clear; box; line -c red70 -lw 3 $P 0 to $P $peakval; plot period power -x line
+ end
+end
+
+# test using random samples
+macro test2
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 0 100
+ set t = 100 * rnd(x) 
+ set f = sin(2*$PI*t/$P)
+ set df = 0.01 + zero(f)
+
+ periodogram_fm t f df 5 50 period power
+#periodogram t f 5 50 period power
+
+ # lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+ # lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.5)
+   $PASS = 0
+ end
+
+ if ($PLOT)
+  lim period power; clear; box; line -c red70 -lw 3 $P 0 to $P $peakval; plot period power -x line
+ end
+end
+
+# test using random samples, higher frequency
+macro test3
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 2.0
+
+ delete -q x t f period power
+
+ create x 0 100
+ set t = 100 * rnd(x) 
+ set f = sin(2*$PI*t/$P)
+ set df = 0.01 + zero(f)
+
+ periodogram_fm t f df 1 10 period power
+#periodogram t f 1 10 period power
+
+ # lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+ # lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using random samples, offset start
+macro test4
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 500 800
+ set t = 300 * rnd(x) + 500
+ set f = sin(2*$PI*t/$P)
+ set df = 0.01 + zero(f)
+
+ periodogram_fm t f df 2 30 period power
+#periodogram t f 2 30 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using random samples, offset start, non-zero DC
+macro test5
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 500 800
+ set t = 300 * rnd(x) + 500
+ set f = sin(2*$PI*t/$P) + 0.5
+ set df = 0.01 + zero(f)
+
+ periodogram_fm t f 2 30 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using random samples, offset start, non-zero DC, some noise
+macro test6
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 500 800
+ set t = 300 * rnd(x) + 500
+ set fraw = sin(2*$PI*t/$P) + 0.5
+
+ # 0.05 : peakpos = 14.95
+ # 0.10 : peakpos = 15.04 (
+ gaussdev df t[] 0.0 0.25
+ set f = fraw + df
+ set df = 0.01 + zero(f)
+
+ periodogram_fm t f 2 30 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using fewer random samples, offset start, non-zero DC, some noise
+macro test7
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 0 100
+ set t = 100 * rnd(x)
+ set fraw = sin(2*$PI*t/$P) + 0.5
+
+ # 0.05 : peakpos = 14.95
+ # 0.10 : peakpos = 15.04 (
+ gaussdev df t[] 0.0 0.25
+ set f = fraw + df
+ set df = 0.01 + zero(f)
+
+ periodogram_fm t f 2 30 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using fewer random samples, high frequency, non-zero DC, some noise
+macro test8
+ if ($0 != 2)
+   echo "USAGE: test8: Ndays")
+   break
+ end
+ 
+ local Ndays 
+ $Ndays = $1
+
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 0.8*rnd(0) + 0.2
+ $trueP = $P
+
+ delete -q x t f period power
+
+ create x 0 $Ndays
+
+ # t is a time in days, but we always have 4 within 1 hour:
+ set t0 = int(100 * rnd(x))
+ set dtx = (3/24) * rnd(x)
+ set t0 = t0 + dtx
+
+ set dt1 = (15.0 / 1440) * rnd(x) + ( 0 + 7.5) / 1440
+ set dt2 = (15.0 / 1440) * rnd(x) + (15 + 7.5) / 1440
+ set dt3 = (15.0 / 1440) * rnd(x) + (30 + 7.5) / 1440
+
+ delete -q t
+ concat t0 t
+ set tmp = t0 + dt1; concat tmp t
+ set tmp = t0 + dt2; concat tmp t
+ set tmp = t0 + dt3; concat tmp t
+
+ set fraw = sin(2*$PI*t/$P) + 0.5
+
+ # 0.05 : peakpos = 14.95
+ # 0.10 : peakpos = 15.04 (
+ gaussdev df t[] 0.0 0.25
+ set f = fraw + df
+ set df = 0.01 + zero(f)
+
+ periodogram_fm t f 0.1 2.0 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# Memory test
+macro memtest1
+
+ local i
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 500 800
+ set t = 300 * rnd(x) + 500
+ set f = sin(2*$PI*t/$P)
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 100
+  periodogram_fm t f 2 30 period power
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 180)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/100}"
+ end
+end
Index: /trunk/Ohana/src/opihi/cmd.data/test/periodogram.sh
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/test/periodogram.sh	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.data/test/periodogram.sh	(revision 40165)
@@ -1,2 +1,4 @@
+
+if (not($?PLOT)) set PLOT = 0
 
 list tests
@@ -28,4 +30,8 @@
    echo "OFFSET: {$peakpos - $P}"
  end
+
+ if ($PLOT)
+  lim period power; clear; box; line -c red70 -lw 3 $P 0 to $P $peakval; plot period power -x line
+ end
 end
 
@@ -99,4 +105,151 @@
 
  periodogram t f 2 30 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using random samples, offset start, non-zero DC
+macro test5
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 500 800
+ set t = 300 * rnd(x) + 500
+ set f = sin(2*$PI*t/$P) + 0.5
+
+ periodogram t f 2 30 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using random samples, offset start, non-zero DC, some noise
+macro test6
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 500 800
+ set t = 300 * rnd(x) + 500
+ set fraw = sin(2*$PI*t/$P) + 0.5
+
+ # 0.05 : peakpos = 14.95
+ # 0.10 : peakpos = 15.04 (
+ gaussdev df t[] 0.0 0.25
+ set f = fraw + df
+
+ periodogram t f 2 30 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using fewer random samples, offset start, non-zero DC, some noise
+macro test7
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 0 100
+ set t = 100 * rnd(x)
+ set fraw = sin(2*$PI*t/$P) + 0.5
+
+ # 0.05 : peakpos = 14.95
+ # 0.10 : peakpos = 15.04 (
+ gaussdev df t[] 0.0 0.25
+ set f = fraw + df
+
+ periodogram t f 2 30 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using fewer random samples, high frequency, non-zero DC, some noise
+macro test8
+ if ($0 != 2)
+   echo "USAGE: test8: Ndays")
+   break
+ end
+ 
+ local Ndays 
+ $Ndays = $1
+
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 0.8*rnd(0) + 0.2
+ $trueP = $P
+
+ delete -q x t f period power
+
+ create x 0 $Ndays
+
+ # t is a time in days, but we always have 4 within 1 hour:
+ set t0 = int(100 * rnd(x))
+ set dtx = (3/24) * rnd(x)
+ set t0 = t0 + dtx
+
+ set dt1 = (15.0 / 1440) * rnd(x) + ( 0 + 7.5) / 1440
+ set dt2 = (15.0 / 1440) * rnd(x) + (15 + 7.5) / 1440
+ set dt3 = (15.0 / 1440) * rnd(x) + (30 + 7.5) / 1440
+
+ delete -q t
+ concat t0 t
+ set tmp = t0 + dt1; concat tmp t
+ set tmp = t0 + dt2; concat tmp t
+ set tmp = t0 + dt3; concat tmp t
+
+ set fraw = sin(2*$PI*t/$P) + 0.5
+
+ # 0.05 : peakpos = 14.95
+ # 0.10 : peakpos = 15.04 (
+ gaussdev df t[] 0.0 0.25
+ set f = fraw + df
+
+ periodogram t f 0.1 2.0 period power
 
 #  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
Index: /trunk/Ohana/src/opihi/cmd.data/zplot.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/zplot.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/cmd.data/zplot.c	(revision 40165)
@@ -117,5 +117,5 @@
 
   /* point size determined by Zvec */
-  graphmode.style = 2; /* plot points */
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
   graphmode.size = -1; /* point size determined by Zvec */
   PlotVectorTriplet (kapa, xvec, yvec, &Zvec, mask, &graphmode);
@@ -226,5 +226,5 @@
 
   /* point size determined by Zvec */
-  graphmode.style = 2; /* plot points */
+  graphmode.style = KAPA_PLOT_POINTS; /* plot points */
   graphmode.color = -1; /* point color determined by Zvec */
   graphmode.etype = 0; /* no errorbars */
Index: /trunk/Ohana/src/opihi/dvo/catalog.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/catalog.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/catalog.c	(revision 40165)
@@ -390,5 +390,5 @@
     REALLOCATE (Zvec.elements, float, MAX (Zvec.Nelements, 1));
     
-    graphmode.style = 2; /* set style to points */
+    graphmode.style = KAPA_PLOT_POINTS; /* points */
     graphmode.size = -1; /* point size determined by Zvec */
     graphmode.etype = 0; /* no errorbars */
Index: /trunk/Ohana/src/opihi/dvo/dmt.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/dmt.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/dmt.c	(revision 40165)
@@ -150,5 +150,5 @@
     vec5[0].Nelements = Dvec.Nelements;
   } else {
-    graphmode.style = 2; /* set style to points */
+    graphmode.style = KAPA_PLOT_POINTS; /* points */
     PlotVector (kapa, N, Xvec.elements, Yvec.elements, &graphmode);
 
Index: /trunk/Ohana/src/opihi/dvo/fitcolors.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/fitcolors.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/fitcolors.c	(revision 40165)
@@ -92,6 +92,6 @@
     graphdata.ymin = minDelta;
     graphdata.ymax = maxDelta;
-    graphdata.style = 2;
-    graphdata.ptype = 2;
+    graphmode.style = KAPA_PLOT_POINTS; /* points */
+    graphmode.ptype = KAPA_POINT_CIRCLE_SOLID; /* connect pairs of points */
     KapaClearSections (kapa);
     KapaSetFont (kapa, "helvetica", 14);
@@ -192,6 +192,6 @@
     graphdata.ymin = minDelta;
     graphdata.ymax = maxDelta;
-    graphdata.style = 2;
-    graphdata.ptype = 2;
+    graphmode.style = KAPA_PLOT_POINTS; /* points */
+    graphmode.ptype = KAPA_POINT_CIRCLE_SOLID; /* connect pairs of points */
   }
 
@@ -315,5 +315,5 @@
 	  deltaFit[i] = C0 + C1*colorFit[i];
 	}
-	graphdata.style = 0;
+	graphmode.style = KAPA_PLOT_CONNECT; /* lines */
 	graphdata.color = KapaColorByName ("red");
 
@@ -329,5 +329,5 @@
 	KapaSetFont (kapa, "helvetica", 14);
 
-	graphdata.style = 2;
+	graphmode.style = KAPA_PLOT_POINTS; /* points */
 	graphdata.color = KapaColorByName ("black");
 
Index: /trunk/Ohana/src/opihi/dvo/fitsed.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/fitsed.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/fitsed.c	(revision 40165)
@@ -157,6 +157,6 @@
     if (!GetGraph (&graphdata, &kapa, NULL)) return (FALSE);
     SetLimitsRaw (wavecode, NULL, Nfilter, &graphdata);
-    graphdata.style = 2;
-    graphdata.ptype = 2;
+    graphdata.style = KAPA_PLOT_POINTS; /* points */
+    graphdata.ptype = KAPA_POINT_CIRCLE_SOLID;
     KapaClearSections (kapa);
     magSection.name = strcreate ("mag");
Index: /trunk/Ohana/src/opihi/dvo/images.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/images.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/images.c	(revision 40165)
@@ -352,6 +352,6 @@
   Xvec.Nelements = Yvec.Nelements = N;
   if (N > 0) {
-    graphmode.style = 2; /* points */
-    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.style = KAPA_PLOT_POINTS; /* points */
+    graphmode.ptype = KAPA_POINT_PAIR_CONNECT; /* connect pairs of points */
     graphmode.etype = 0;
     PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
Index: /trunk/Ohana/src/opihi/dvo/imbox.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/imbox.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/imbox.c	(revision 40165)
@@ -156,6 +156,6 @@
   Xvec.Nelements = Yvec.Nelements = Npts;
   if (Npts > 0) {
-    graphmode.style = 2; /* points */
-    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.style = KAPA_PLOT_POINTS; /* points */
+    graphmode.ptype = KAPA_POINT_PAIR_CONNECT; /* connect pairs of points */
     graphmode.etype = 0;
     PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
Index: /trunk/Ohana/src/opihi/dvo/imdense.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/imdense.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/imdense.c	(revision 40165)
@@ -59,5 +59,5 @@
   Xvec.Nelements = Yvec.Nelements = N;
   if (N > 0) {
-    graphmode.style = 2; /* points */
+    graphmode.style = KAPA_PLOT_POINTS; /* points */
     graphmode.etype = 0;
     PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
Index: /trunk/Ohana/src/opihi/dvo/imstats.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/imstats.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/imstats.c	(revision 40165)
@@ -51,5 +51,5 @@
   if (AutoLimits) SetLimits (&Xvec, &Yvec, &graphmode);
 
-  graphmode.style = 2;
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
   graphmode.etype = 0;
   PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
Index: /trunk/Ohana/src/opihi/dvo/paverage.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/paverage.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/paverage.c	(revision 40165)
@@ -81,5 +81,5 @@
     return (FALSE);
   }
-  graphmode.style = 2; /* set style to points */
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
   graphmode.size = -1; /* point size determined by Zvec */
   graphmode.etype = 0; /* no errorbars */
Index: /trunk/Ohana/src/opihi/dvo/pmeasure.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/pmeasure.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/pmeasure.c	(revision 40165)
@@ -154,5 +154,5 @@
     return (FALSE);
   }
-  graphmode.style = 2; /* set style to points */
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
   graphmode.size = -1; /* point size determined by Zvec */
   graphmode.etype = 0; /* no errorbars */
Index: /trunk/Ohana/src/opihi/dvo/procks.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/procks.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/procks.c	(revision 40165)
@@ -111,5 +111,5 @@
   Yvec.Nelements = Xvec.Nelements = N;
   
-  graphmode.style = 2; /* set style to points */
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
   graphmode.etype = 0; /* no errorbars */
   PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
@@ -142,6 +142,6 @@
   Yvec.Nelements = Xvec.Nelements = N;
   
-  graphmode.style = 2; /* set style to points */
-  graphmode.ptype = 100; /* connect pairs */
+  graphmode.style = KAPA_PLOT_POINTS; /* points */
+  graphmode.ptype = KAPA_POINT_PAIR_CONNECT; /* connect pairs of points */
   graphmode.etype = 0; /* no errorbars */
 
Index: /trunk/Ohana/src/opihi/dvo/showtile.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/showtile.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/showtile.c	(revision 40165)
@@ -78,6 +78,6 @@
   Xvec.Nelements = Yvec.Nelements = N;
   if (N > 0) {
-    graphmode.style = 2; /* points */
-    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.style = KAPA_PLOT_POINTS; /* points */
+    graphmode.ptype = KAPA_POINT_PAIR_CONNECT; /* connect pairs of points */
     graphmode.etype = 0;
     PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
Index: /trunk/Ohana/src/opihi/dvo/simage.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/simage.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/simage.c	(revision 40165)
@@ -118,5 +118,5 @@
   }
 
-  graphmode.style = 2;
+  graphmode.style = KAPA_PLOT_POINTS;
   graphmode.size = -1;
   graphmode.etype = 0;
Index: /trunk/Ohana/src/opihi/dvo/skycat.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/skycat.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/dvo/skycat.c	(revision 40165)
@@ -121,6 +121,6 @@
   Xvec.Nelements = Yvec.Nelements = Npts;
   if (Npts > 0) {
-    graphmode.style = 2; /* points */
-    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.style = KAPA_PLOT_POINTS; /* points */
+    graphmode.ptype = KAPA_POINT_PAIR_CONNECT; /* connect pairs of points */
     graphmode.etype = 0;
     PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
Index: /trunk/Ohana/src/opihi/pantasks/JobIDOps.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/JobIDOps.c	(revision 40164)
+++ /trunk/Ohana/src/opihi/pantasks/JobIDOps.c	(revision 40165)
@@ -1,5 +1,5 @@
 # include "pantasks.h"
 
-# define MAX_N_JOBS 10000
+# define MAX_N_JOBS 50000
 static char *JobIDList;
 static int   JobIDPtr;
Index: /trunk/Ohana/src/opihi/pantasks/test/nice_remote.sh
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/test/nice_remote.sh	(revision 40164)
+++ /trunk/Ohana/src/opihi/pantasks/test/nice_remote.sh	(revision 40165)
@@ -10,5 +10,5 @@
   periods      -timeout 20
   active       true
-  npending 5
+  npending 50
   
   stdout tmp.txt
@@ -38,5 +38,5 @@
 task	       meantask_local
   command      sleep 10
-  host         anyhost
+  host         local
 
   periods      -poll 0.1
@@ -44,5 +44,5 @@
   periods      -timeout 20
   active       true
-  npending 5
+  npending 50
   
   stdout tmp.txt
