Index: /trunk/Ohana/src/opihi/cmd.astro/cdhistogram.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/cdhistogram.c	(revision 42941)
+++ /trunk/Ohana/src/opihi/cmd.astro/cdhistogram.c	(revision 42942)
@@ -40,5 +40,5 @@
 
   if (argc != 7) {
-    gprint (GP_ERR, "USAGE: cdhistogram buffer R D value (min) (max) [-delta dval]\n");
+    gprint (GP_ERR, "USAGE: cdhistogram buffer R D value (min) (max) [-delta dval] [-range vec] [-binning N]\n");
     gprint (GP_ERR, " output buffer is 3D\n");
     return (FALSE);
Index: /trunk/Ohana/src/opihi/cmd.astro/cgrid.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/cgrid.c	(revision 42941)
+++ /trunk/Ohana/src/opihi/cmd.astro/cgrid.c	(revision 42942)
@@ -12,6 +12,6 @@
 # define ADD_COORDINATE(RA,DEC)						\
   status = RD_to_XY (&Xvec.elements.Flt[N], &Yvec.elements.Flt[N], (RA), (DEC), &graphmode.coords); \
-  if ((Xvec.elements.Flt[N] >= graphmode.xmin) && (Xvec.elements.Flt[N] <= graphmode.xmax) && \
-      (Yvec.elements.Flt[N] >= graphmode.ymin) && (Yvec.elements.Flt[N] <= graphmode.ymax) && status) { \
+  if ((Xvec.elements.Flt[N] >= Xmin) && (Xvec.elements.Flt[N] <= Xmax) && \
+      (Yvec.elements.Flt[N] >= Ymin) && (Yvec.elements.Flt[N] <= Ymax) && status) { \
     N++;								\
     CHECKELEMENTS;							\
@@ -154,4 +154,10 @@
   if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
 
+  // we need to rationalize graphmode.xmin,xmax (can be flipped)
+  int Xmin = MIN(graphmode.xmin,graphmode.xmax);
+  int Xmax = MAX(graphmode.xmin,graphmode.xmax);
+  int Ymin = MIN(graphmode.ymin,graphmode.ymax);
+  int Ymax = MAX(graphmode.ymin,graphmode.ymax);
+
   if (argc != 1) goto usage;
 
@@ -159,10 +165,11 @@
   NorthPole = SouthPole = FALSE;
   status = RD_to_XY (&x, &y, 0.0, 90.0, &graphmode.coords);
-  if ((x >= graphmode.xmin) && (x <= graphmode.xmax) && 
-      (y >= graphmode.ymin) && (y <= graphmode.ymax) && status)
+  // if the parity is flipped in either direction, xmin > xmax or ymin > ymax
+  if ((x >= Xmin) && (x <= Xmax) && 
+      (y >= Ymin) && (y <= Ymax) && status)
     NorthPole = TRUE;
   status = RD_to_XY (&x, &y, 0.0, -90.0, &graphmode.coords);
-  if ((x >= graphmode.xmin) && (x <= graphmode.xmax) && 
-      (y >= graphmode.ymin) && (y <= graphmode.ymax) && status)
+  if ((x >= Xmin) && (x <= Xmax) && 
+      (y >= Ymin) && (y <= Ymax) && status)
     SouthPole = TRUE;
 
@@ -173,11 +180,11 @@
   if (mode == PROJ_MODE_PSEUDOCYL) {
     // for PSEUDOCYL, the ra range is 360 if the corners are invalid 
-    InvalidCorner |= XY_to_RD (&r, &d, graphmode.xmin, graphmode.ymin, &graphmode.coords); 
-    InvalidCorner |= XY_to_RD (&r, &d, graphmode.xmax, graphmode.ymin, &graphmode.coords); 
-    InvalidCorner |= XY_to_RD (&r, &d, graphmode.xmax, graphmode.ymax, &graphmode.coords); 
-    InvalidCorner |= XY_to_RD (&r, &d, graphmode.xmin, graphmode.ymax, &graphmode.coords); 
+    InvalidCorner |= XY_to_RD (&r, &d, Xmin, Ymin, &graphmode.coords); 
+    InvalidCorner |= XY_to_RD (&r, &d, Xmax, Ymin, &graphmode.coords); 
+    InvalidCorner |= XY_to_RD (&r, &d, Xmax, Ymax, &graphmode.coords); 
+    InvalidCorner |= XY_to_RD (&r, &d, Xmin, Ymax, &graphmode.coords); 
   }    
 
-  range = MIN (fabs(graphmode.coords.cdelt1*(graphmode.xmax-graphmode.xmin)), fabs(graphmode.coords.cdelt2*(graphmode.ymax-graphmode.ymin)));
+  range = MIN (fabs(graphmode.coords.cdelt1*(Xmax-Xmin)), fabs(graphmode.coords.cdelt2*(Ymax-Ymin)));
   if (NorthPole || SouthPole || InvalidCorner) range = 360;
   dR = range * GRID_SPACING;
@@ -266,6 +273,6 @@
     char line[16], format[16];
     double xt, yt, frac;
-    // dx = +0.01 * (graphmode.xmax - graphmode.xmin);
-    // dy = -0.02 * (graphmode.ymax - graphmode.ymin);
+    // dx = +0.01 * (Xmax - Xmin);
+    // dy = -0.02 * (Ymax - Ymin);
 
     if (isnan(LabelRA)) LabelRA = graphmode.coords.crval1;
@@ -274,8 +281,8 @@
       status = RD_to_XY (&xt, &yt, r, LabelDEC, &graphmode.coords);
       if (!status) continue;
-      if (xt < graphmode.xmin) continue;
-      if (xt > graphmode.xmax) continue;
-      if (yt < graphmode.ymin) continue;
-      if (yt > graphmode.ymax) continue;
+      if (xt < Xmin) continue;
+      if (xt > Xmax) continue;
+      if (yt < Ymin) continue;
+      if (yt > Ymax) continue;
       frac = -1.0 * log10(minorRA);
       if (frac != (int)frac) {
@@ -295,8 +302,8 @@
       status = RD_to_XY (&xt, &yt, r, LabelDEC, &graphmode.coords);
       if (!status) continue;
-      if (xt < graphmode.xmin) continue;
-      if (xt > graphmode.xmax) continue;
-      if (yt < graphmode.ymin) continue;
-      if (yt > graphmode.ymax) continue;
+      if (xt < Xmin) continue;
+      if (xt > Xmax) continue;
+      if (yt < Ymin) continue;
+      if (yt > Ymax) continue;
       frac = -1.0 * log10(minorRA);
       if (frac != (int)frac) {
@@ -316,8 +323,8 @@
       status = RD_to_XY (&xt, &yt, LabelRA, d, &graphmode.coords);
       if (!status) continue;
-      if (xt < graphmode.xmin) continue;
-      if (xt > graphmode.xmax) continue;
-      if (yt < graphmode.ymin) continue;
-      if (yt > graphmode.ymax) continue;
+      if (xt < Xmin) continue;
+      if (xt > Xmax) continue;
+      if (yt < Ymin) continue;
+      if (yt > Ymax) continue;
       frac = -1.0 * log10(minorDEC);
       if (frac != (int)frac) {
@@ -332,8 +339,8 @@
       status = RD_to_XY (&xt, &yt, LabelRA, d, &graphmode.coords);
       if (!status) continue;
-      if (xt < graphmode.xmin) continue;
-      if (xt > graphmode.xmax) continue;
-      if (yt < graphmode.ymin) continue;
-      if (yt > graphmode.ymax) continue;
+      if (xt < Xmin) continue;
+      if (xt > Xmax) continue;
+      if (yt < Ymin) continue;
+      if (yt > Ymax) continue;
       frac = -1.0 * log10(minorDEC);
       if (frac != (int)frac) {
Index: /trunk/Ohana/src/opihi/cmd.astro/region.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/region.c	(revision 42941)
+++ /trunk/Ohana/src/opihi/cmd.astro/region.c	(revision 42942)
@@ -35,4 +35,6 @@
     KapaGetImageCoords (kapa, &graphmode.coords);
     KapaGetImageRange (kapa, &graphmode.xmin, &graphmode.xmax, &graphmode.ymax, &graphmode.ymin, &dXpix, &dYpix);
+    // XXX here (xmin,xmax),(ymin,ymax) are ???
+    // below, (xmin,xmax),(ymin,ymax) are set to put 0,0 in the graph center (-dx to +dx)
 
     set_variable ("XMIN", graphmode.xmin);
@@ -40,5 +42,5 @@
     set_variable ("YMIN", graphmode.ymin);
     set_variable ("YMAX", graphmode.ymax);
-
+    // XXX Ra,Dec not defined at this point
     set_variable ("RMIN", Ra  + graphmode.xmin);
     set_variable ("RMAX", Ra  + graphmode.xmax);
Index: /trunk/Ohana/src/opihi/cmd.basic/quit.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.basic/quit.c	(revision 42941)
+++ /trunk/Ohana/src/opihi/cmd.basic/quit.c	(revision 42942)
@@ -3,5 +3,15 @@
 int quit (int argc, char **argv) {
 
-  int state;
+  int N, state;
+
+  int VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-verbose"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
 
   cleanup ();
@@ -18,5 +28,19 @@
 # endif
 
+  if (VERBOSE) {
+    ohana_memcheck (TRUE);
+    ohana_memdump (TRUE);
+    ohana_memdump_strings_file (stderr, TRUE);
+  }
+
   exit (state);
+}
 
-}
+/* values which cannot be freed on quit:
+
+   parse.c:329 (reallocated command line)
+   parse_commands.c:33 (command argv array)
+   command.c:52 (command targv array)
+   command.c:15 (copy of command line)
+
+*/
Index: /trunk/Ohana/src/opihi/cmd.data/section.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/section.c	(revision 42941)
+++ /trunk/Ohana/src/opihi/cmd.data/section.c	(revision 42942)
@@ -1,5 +1,5 @@
 # include "data.h"
 
-enum {NONE, LIST, UP, DOWN, TOP, BOTTOM, TOOL, BG, IMAGE};
+enum {NONE, LIST, UP, DOWN, TOP, BOTTOM, TOOL, BG, IMAGE, IMCENTER};
 
 int section (int argc, char **argv) {
@@ -17,20 +17,25 @@
   }
   if ((N = get_argument (argc, argv, "-up"))) {
+    if (action != NONE) goto escape;
     action = UP;
     remove_argument (N, &argc, argv);
   }
   if ((N = get_argument (argc, argv, "-down"))) {
+    if (action != NONE) goto escape;
     action = DOWN;
     remove_argument (N, &argc, argv);
   }
   if ((N = get_argument (argc, argv, "-top"))) {
+    if (action != NONE) goto escape;
     action = TOP;
     remove_argument (N, &argc, argv);
   }
   if ((N = get_argument (argc, argv, "-bottom"))) {
+    if (action != NONE) goto escape;
     action = BOTTOM;
     remove_argument (N, &argc, argv);
   }
   if ((N = get_argument (argc, argv, "-imtool"))) {
+    if (action != NONE) goto escape;
     action = TOOL;
     remove_argument (N, &argc, argv);
@@ -41,4 +46,5 @@
   background = -1; // invisible
   if ((N = get_argument (argc, argv, "-bg"))) {
+    if (action != NONE) goto escape;
     remove_argument (N, &argc, argv);
     if (!strcasecmp (argv[N], "NONE")) {
@@ -52,6 +58,13 @@
 
   if ((N = get_argument (argc, argv, "-image"))) {
+    if (action != NONE) goto escape;
     remove_argument (N, &argc, argv);
     action = IMAGE;
+  }
+
+  if ((N = get_argument (argc, argv, "-imcenter"))) {
+    if (action != NONE) goto escape;
+    remove_argument (N, &argc, argv);
+    action = IMCENTER;
   }
 
@@ -65,106 +78,136 @@
   FREE (name);
 
-  /* list sections */
-  if ((argc == 1) && (action == NONE)) {
-    KapaGetSection (kapa, "*");
-    gprint (GP_ERR, "USAGE: section name [x y dx dy] or [options]\n");
-    gprint (GP_ERR, "OPTIONS: -list   : show properties of all sections\n");
-    gprint (GP_ERR, "         -up     : move section up in display stack\n");
-    gprint (GP_ERR, "         -down   : move section down in display stack\n");
-    gprint (GP_ERR, "         -top    : move section to top of display stack\n");
-    gprint (GP_ERR, "         -bottom : move section to bottom of display stack\n");
-    gprint (GP_ERR, "         -imtool (position) : set location of image zoom / status box\n");
-    gprint (GP_ERR, "                 (position may be: -x, +x, -y, +y, none)\n");
-    gprint (GP_ERR, "         -image  : define section upper-right corner so image fills the section\n");
-    gprint (GP_ERR, "         -bg (color) : set background color (see style -c help for color choices)\n");
-    
-    return (TRUE);
-  } 
-  
-  if ((argc != 2) && (action != NONE)) {
-      gprint (GP_ERR, "can only use dash options without numbers\n");
+  // deal with these cases first
+  if (action == NONE) {
+    if (argc == 1) { // command: section 
+      gprint (GP_ERR, "USAGE: section name x y dx dy\n");
+      gprint (GP_ERR, "       section name -image x y\n");
+      gprint (GP_ERR, "       section name [options]\n");
+      gprint (GP_ERR, "OPTIONS: -list   : show properties of all sections\n");
+      gprint (GP_ERR, "         -up     : move section up in display stack\n");
+      gprint (GP_ERR, "         -down   : move section down in display stack\n");
+      gprint (GP_ERR, "         -top    : move section to top of display stack\n");
+      gprint (GP_ERR, "         -bottom : move section to bottom of display stack\n");
+      gprint (GP_ERR, "         -imtool (position) : set location of image zoom / status box\n");
+      gprint (GP_ERR, "                 (position may be: -x, +x, -y, +y, none)\n");
+      gprint (GP_ERR, "         -image  : define section upper-right corner so image fills the section\n");
+      gprint (GP_ERR, "         -bg (color) : set background color (see style -c help for color choices or use NONE)\n");
+      return (TRUE);
+    }
+    if (argc == 2) { // command: section name
+      KapaSelectSection (kapa, argv[1]);
+      return TRUE;
+    }
+    if (argc == 6) { // command: section name x y dx dy
+      /* set section */
+      section.name = argv[1];
+      section.x = atof (argv[2]);
+      section.y = atof (argv[3]);
+      section.dx = atof (argv[4]);
+      section.dy = atof (argv[5]);
+      section.bg = -2; // bg must be set on its own
+      KapaSetSection (kapa, &section);
+      return (TRUE);
+    }
+    goto escape;
+  }
+
+  // list properties of the specified section, or all sections
+  if (action == LIST) {
+    if (argc == 1) {
+      KapaGetSection (kapa, "*");
+      return TRUE;
+    } 
+    if (argc == 2) { 
+      KapaGetSection (kapa, argv[1]);
+      KapaSelectSection (kapa, argv[1]);
+      return TRUE;
+    }
+    goto escape;
+  }
+
+  if ((action == IMAGE) || (action == IMCENTER)) {
+    if (argc != 4) goto escape;
+  } else {
+    if (argc != 2) goto escape;
+  }
+
+  /* select / show section */
+  switch (action) {
+    case UP:
+      KapaMoveSection (kapa, argv[1], "up");
+      break;
+    case DOWN:
+      KapaMoveSection (kapa, argv[1], "down");
+      break;
+    case TOP:
+      KapaMoveSection (kapa, argv[1], "top");
+      break;
+    case BOTTOM:
+      KapaMoveSection (kapa, argv[1], "bottom");
+      break;
+
+    case BG:
+      KapaSectionBG (kapa, argv[1], background);
+      break;
+
+    case TOOL:
+      KapaSelectSection (kapa, argv[1]);
+      if (!strcmp(location, "-x")) {
+	KapaSetToolbox (kapa, 1);
+	break;
+      }
+      if (!strcmp(location, "+x")) {
+	KapaSetToolbox (kapa, 3);
+	break;
+      }
+      if (!strcmp(location, "-y")) {
+	KapaSetToolbox (kapa, 2);
+	break;
+      }
+      if (!strcmp(location, "+y")) {
+	KapaSetToolbox (kapa, 4);
+	break;
+      }
+      if (!strcmp(location, "none")) {
+	KapaSetToolbox (kapa, 0);
+	break;
+      }
+      gprint (GP_ERR, "unknown toolbox location %s\n", location);
+      gprint (GP_ERR, "valid values: -x, +x, -y, +y, none\n");
       return (FALSE);
-  }
-
-  if (argc == 2) {
-    /* select / show section */
-    switch (action) {
-      case NONE:
-	KapaSelectSection (kapa, argv[1]);
-	break;
-
-      case UP:
-	KapaMoveSection (kapa, argv[1], "up");
-	break;
-      case DOWN:
-	KapaMoveSection (kapa, argv[1], "down");
-	break;
-      case TOP:
-	KapaMoveSection (kapa, argv[1], "top");
-	break;
-      case BOTTOM:
-	KapaMoveSection (kapa, argv[1], "bottom");
-	break;
-
-      case BG:
-	KapaSectionBG (kapa, argv[1], background);
-	break;
-
-      case TOOL:
-	if (!strcmp(location, "-x")) {
-	  KapaSetToolbox (kapa, 1);
-	  break;
-	}
-	if (!strcmp(location, "+x")) {
-	  KapaSetToolbox (kapa, 3);
-	  break;
-	}
-	if (!strcmp(location, "-y")) {
-	  KapaSetToolbox (kapa, 2);
-	  break;
-	}
-	if (!strcmp(location, "+y")) {
-	  KapaSetToolbox (kapa, 4);
-	  break;
-	}
-	if (!strcmp(location, "none")) {
-	  KapaSetToolbox (kapa, 0);
-	  break;
-	}
-	gprint (GP_ERR, "unknown toolbox location %s\n", location);
-	gprint (GP_ERR, "valid values: -x, +x, -y, +y, none\n");
-	return (FALSE);
-
-      case LIST:
-	KapaGetSection (kapa, argv[1]);
-	break;
-    }
-    return (TRUE);
-  } 
-  
-  if (argc == 4) {
-    /* set section */
-    section.name = argv[1];
-    section.x = atof (argv[2]);
-    section.y = atof (argv[3]);
-    section.bg = background;
-    KapaSetSectionByImage (kapa, &section);
-    return (TRUE);
-  }
-
-  if (argc == 6) {
-    /* set section */
-    section.name = argv[1];
-    section.x = atof (argv[2]);
-    section.y = atof (argv[3]);
-    section.dx = atof (argv[4]);
-    section.dy = atof (argv[5]);
-    section.bg = background;
-    KapaSetSection (kapa, &section);
-    return (TRUE);
-  }
-  gprint (GP_ERR, "USAGE: section name [x y dx dy]\n");
-  gprint (GP_ERR, "USAGE: section name [-image x y] : width based on current image\n");
-  gprint (GP_ERR, "USAGE: section name [-list] [-up] [-down] [-top] [-bottom]\n");
+
+    case IMAGE:
+      /* set section */
+      section.name = argv[1];
+      section.x = atof (argv[2]);
+      section.y = atof (argv[3]);
+      section.bg = -2;
+      KapaSetSectionByImage (kapa, &section);
+      return (TRUE);
+
+    case IMCENTER:
+      /* set section */
+      section.name = argv[1];
+      section.x = atof (argv[2]);
+      section.y = atof (argv[3]);
+      KapaSetSectionCenterByImage (kapa, &section);
+      return (TRUE);
+
+    case NONE:
+    case LIST:
+    default:
+      gprint (GP_ERR, "oops, programming error in section.c:171\n");
+      break;
+  }
+  return (TRUE);
+
+escape:
+  gprint (GP_ERR, "USAGE: section name : select the section\n");
+  gprint (GP_ERR, "USAGE: section name x y dx dy : define section location\n");
+  gprint (GP_ERR, "USAGE: section name -image x y : width based on current image\n");
+  gprint (GP_ERR, "USAGE: section name -imtool (position) : width based on current image\n");
+  gprint (GP_ERR, "USAGE: section name [-list] [-up] [-down] [-top] [-bottom] [-bg color]\n");
+  gprint (GP_ERR, "  only one -OPTION at a time\n");
   return (FALSE);
 }
Index: /trunk/Ohana/src/opihi/cmd.data/tdhistogram.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/tdhistogram.c	(revision 42941)
+++ /trunk/Ohana/src/opihi/cmd.data/tdhistogram.c	(revision 42942)
@@ -5,14 +5,79 @@
 int tdhistogram (int argc, char **argv) {
 
-  int i, Nx, Ny, Nz, N;
+  int i, N;
   float *val;
   Buffer *bf;
   Vector *vx, *vy, *vz, *range;
   opihi_flt *x, *y, *z;
+  int kapa;
+  Graphdata graphmode;
+
+  int useGraph = FALSE;
+  if ((N = get_argument (argc, argv, "-graph"))) {
+    remove_argument (N, &argc, argv);
+    useGraph = TRUE;
+    if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+  }
 
   int reuse = FALSE;
   if ((N = get_argument (argc, argv, "-reuse"))) {
+    if (useGraph) { gprint (GP_ERR, "-reuse and -graph are incompatible\n"); return FALSE; }
     remove_argument (N, &argc, argv);
     reuse = TRUE;
+  }
+
+  int Nx = 100;
+  double dx = NAN;
+  if ((N = get_argument (argc, argv, "-dx"))) {
+    if (useGraph) { gprint (GP_ERR, "-dx and -graph are incompatible\n"); return FALSE; }
+    remove_argument (N, &argc, argv);
+    dx = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-Nx"))) {
+    if (useGraph) { gprint (GP_ERR, "-Nx and -graph are incompatible\n"); return FALSE; }
+    if (isfinite(dx)) { gprint (GP_ERR, "-Nx and -dx are incompatible\n"); return FALSE; }
+    remove_argument (N, &argc, argv);
+    Nx = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  int Ny = 100;
+  double dy = NAN;
+  if ((N = get_argument (argc, argv, "-dy"))) {
+    if (useGraph) { gprint (GP_ERR, "-dx and -graph are incompatible\n"); return FALSE; }
+    remove_argument (N, &argc, argv);
+    dy = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-Ny"))) {
+    if (useGraph) { gprint (GP_ERR, "-Ny and -graph are incompatible\n"); return FALSE; }
+    if (isfinite(dy)) { gprint (GP_ERR, "-Ny and -dy are incompatible\n"); return FALSE; }
+    remove_argument (N, &argc, argv);
+    Ny = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  int Nz = 100;
+  double dz = NAN;
+  if ((N = get_argument (argc, argv, "-dz"))) {
+    remove_argument (N, &argc, argv);
+    dz = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-Nz"))) {
+    if (useGraph) { gprint (GP_ERR, "-Nz and -graph are incompatible\n"); return FALSE; }
+    if (isfinite(dz)) { gprint (GP_ERR, "-Nz and -dz are incompatible\n"); return FALSE; }
+    remove_argument (N, &argc, argv);
+    Nz = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  int binning = 1;
+  if ((N = get_argument (argc, argv, "-binning"))) {
+    if (!useGraph) { gprint (GP_ERR, "-binning requires -graph\n"); return FALSE; }
+    remove_argument (N, &argc, argv);
+    binning = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
   }
 
@@ -24,29 +89,13 @@
   }
 
-  double dx = NAN;
-  if ((N = get_argument (argc, argv, "-dx"))) {
-    remove_argument (N, &argc, argv);
-    dx = atof(argv[N]);
-    remove_argument (N, &argc, argv);
-  }
-  double dy = NAN;
-  if ((N = get_argument (argc, argv, "-dy"))) {
-    remove_argument (N, &argc, argv);
-    dy = atof(argv[N]);
-    remove_argument (N, &argc, argv);
-  }
-  double dz = NAN;
-  if ((N = get_argument (argc, argv, "-dz"))) {
-    remove_argument (N, &argc, argv);
-    dz = atof(argv[N]);
-    remove_argument (N, &argc, argv);
-  }
-
-  int valid = (!reuse && (argc == 11)) || (reuse && (argc == 5));
+  int valid = (reuse && (argc == 5)) || (useGraph && (argc == 7)) || (argc == 11);
   if (!valid) {
     gprint (GP_ERR, "USAGE: tdhistogram buffer x y z (Xmin) (Xmax) (Ymin) (Ymax) (Zmin) (Zmax) [-dx dx] [-dy dy] [-dz dz] [-range range]\n");
+    gprint (GP_ERR, "USAGE: tdhistogram buffer x y z (Zmin) (Zmax) -graph [-binning N] [-dz dz] [-range range]\n");
     gprint (GP_ERR, "   OR: tdhistogram buffer x y z -reuse\n");
     gprint (GP_ERR, "   -dx, -dy, -dy specify the bin size in these directions\n");
     gprint (GP_ERR, "   -range : generate an output vector corresponding to the elements in the z-direction\n");
+    gprint (GP_ERR, "   -graph : use X,Y range from active graph\n");
+    gprint (GP_ERR, "   -binning N : use binning to define bin sizes relative to graph\n");
     gprint (GP_ERR, " output buffer is 3D\n");
     return (FALSE);
@@ -63,47 +112,5 @@
   double Xmin, Xmax, Ymin, Ymax, Zmin, Zmax;
 
-  if (!reuse) {
-    Xmin = atof(argv[5]);
-    Xmax = atof(argv[6]);
-    if (!isfinite(dx)) {
-      Nx = 100;
-      dx = (Xmax - Xmin) / (Nx - 1);
-    } else {
-      Nx = (Xmax - Xmin) / dx + 1;
-    }
-    if (dx < 0) {
-      gprint (GP_ERR, "invalid value for delta: %f\n", dx);
-      return (FALSE);
-    }
-    Ymin = atof(argv[7]);
-    Ymax = atof(argv[8]);
-    if (!isfinite(dy)) {
-      Ny = 100;
-      dy = (Ymax - Ymin) / (Ny - 1);
-    } else {
-      Ny = (Ymax - Ymin) / dy + 1;
-    }
-    if (dy < 0) {
-      gprint (GP_ERR, "invalid value for delta: %f\n", dy);
-      return (FALSE);
-    }
-    Zmin = atof(argv[9]);
-    Zmax = atof(argv[10]);
-    if (!isfinite(dz)) {
-      Nz = 100;
-      dz = (Zmax - Zmin) / (Nz - 1);
-    } else {
-      Nz = (Zmax - Zmin) / dz + 1;
-    }
-    if (dz < 0) {
-      gprint (GP_ERR, "invalid value for delta: %f\n", dz);
-      return (FALSE);
-    }
-
-    if (Nz > 1000) {
-      gprint (GP_ERR, "warning: delta of %f will result in %d histogram bins\n", dz, Nz);
-      return (FALSE);
-    }
-  } else {
+  if (reuse) {
     gfits_scan (&bf[0].header, "XMIN", "%lf", 1, &Xmin);
     gfits_scan (&bf[0].header, "XMAX", "%lf", 1, &Xmax);
@@ -118,6 +125,73 @@
     Ny = bf[0].header.Naxis[1];
     Nz = bf[0].header.Naxis[2];
-  }
-
+    goto got_range;
+  }
+
+  if (useGraph) {
+    int Xpix, Ypix;
+    KapaGetImageRange (kapa, &Xmin, &Xmax, &Ymax, &Ymin, &Xpix, &Ypix);
+    Xmax = graphmode.xmax;
+    Xmin = graphmode.xmin;
+    Ymax = graphmode.ymax;
+    Ymin = graphmode.ymin;
+
+    // (dX, dY) are the pixel scale of the output image (output pixels / input pixels)
+
+    dx = binning * (Xmax - Xmin) / (Xpix - 1);
+    dy = binning * (Ymax - Ymin) / (Ypix - 1);
+
+    Nx = abs((Xmax - Xmin) / dx) + 1;
+    Ny = abs((Ymax - Ymin) / dy) + 1;
+  
+    // XXX : note that Zmin and Zmax have a different argv location in useGraph
+    Zmin = atof(argv[5]);
+    Zmax = atof(argv[6]);
+
+    goto set_Zvalues;
+  }
+
+  // This section is only used if !reuse and !useGraph
+  Xmin = atof(argv[5]);
+  Xmax = atof(argv[6]);
+  if (!isfinite(dx)) {
+    dx = (Xmax - Xmin) / (Nx - 1);
+  } else {
+    Nx = (Xmax - Xmin) / dx + 1;
+  }
+  if (dx < 0) {
+    gprint (GP_ERR, "invalid value for delta: %f\n", dx);
+    return (FALSE);
+  }
+  Ymin = atof(argv[7]);
+  Ymax = atof(argv[8]);
+  if (!isfinite(dy)) {
+    dy = (Ymax - Ymin) / (Ny - 1);
+  } else {
+    Ny = (Ymax - Ymin) / dy + 1;
+  }
+  if (dy < 0) {
+    gprint (GP_ERR, "invalid value for delta: %f\n", dy);
+    return (FALSE);
+  }
+  // XXX : note that Zmin and Zmax have a different argv location in useGraph
+  Zmin = atof(argv[9]);
+  Zmax = atof(argv[10]);
+
+set_Zvalues:
+  if (!isfinite(dz)) {
+    dz = (Zmax - Zmin) / (Nz - 1);
+  } else {
+    Nz = (Zmax - Zmin) / dz + 1;
+  }
+  if (dz < 0) {
+    gprint (GP_ERR, "invalid value for delta: %f\n", dz);
+    return (FALSE);
+  }
+  if (Nz > 1000) {
+    gprint (GP_ERR, "warning: delta of %f will result in %d histogram bins\n", dz, Nz);
+    return (FALSE);
+  }
+
+got_range:
   REQUIRE_VECTOR_FLT (vx, FALSE); 
   REQUIRE_VECTOR_FLT (vy, FALSE); 
