Index: trunk/Ohana/src/opihi/cmd.astro/cdensify.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/cdensify.c	(revision 41157)
+++ trunk/Ohana/src/opihi/cmd.astro/cdensify.c	(revision 41158)
@@ -39,4 +39,11 @@
   }
 
+  int binning = 1;
+  if ((N = get_argument (argc, argv, "-binning"))) {
+    remove_argument (N, &argc, argv);
+    binning = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
   int PSFTYPE = IS_DOT;
   if ((N = get_argument (argc, argv, "-psf"))) {
@@ -80,6 +87,9 @@
   Ymax = graphmode.ymax;
   Ymin = graphmode.ymin;
-  dX = (Xmax - Xmin) / (Xpix - 1);
-  dY = (Ymax - Ymin) / (Ypix - 1);
+
+  // (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);
 
   CHECKVAL(Xmin);
Index: trunk/Ohana/src/opihi/cmd.astro/cdhistogram.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/cdhistogram.c	(revision 41157)
+++ trunk/Ohana/src/opihi/cmd.astro/cdhistogram.c	(revision 41158)
@@ -13,4 +13,11 @@
   int kapa;
   Graphdata graphmode;
+
+  int binning = 1;
+  if ((N = get_argument (argc, argv, "-binning"))) {
+    remove_argument (N, &argc, argv);
+    binning = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
 
   range = NULL;
@@ -79,6 +86,9 @@
   Ymax = graphmode.ymax;
   Ymin = graphmode.ymin;
-  dX = (Xmax - Xmin) / (Xpix - 1);
-  dY = (Ymax - Ymin) / (Ypix - 1);
+
+  // (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);
 
   CHECKVAL(Xmin);
@@ -90,6 +100,6 @@
   CHECKVAL(dY);
 
-  int Nx = (Xmax - Xmin) / dX + 1;
-  int Ny = (Ymax - Ymin) / dY + 1;
+  int Nx = abs((Xmax - Xmin) / dX) + 1;
+  int Ny = abs((Ymax - Ymin) / dY) + 1;
   
   Coords newcoords = graphmode.coords;
Index: trunk/Ohana/src/opihi/cmd.astro/region.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/region.c	(revision 41157)
+++ trunk/Ohana/src/opihi/cmd.astro/region.c	(revision 41158)
@@ -3,5 +3,5 @@
 int region (int argc, char **argv) {
   
-  double Ra, Dec, Radius;
+  double Ra, Dec;
   float dx, dy;
   int N, kapa, NoClear, dXpix, dYpix;
@@ -54,4 +54,26 @@
   }
 
+  float XSIZE = NAN;
+  if ((N = get_argument (argc, argv, "-xsize"))) {
+    remove_argument (N, &argc, argv);
+    XSIZE = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    if (XSIZE <= 0) {
+      gprint (GP_ERR, "ERROR: xsize <= 0\n");
+      return FALSE;
+    }
+  }
+
+  float YSIZE = NAN;
+  if ((N = get_argument (argc, argv, "-ysize"))) {
+    remove_argument (N, &argc, argv);
+    YSIZE = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    if (YSIZE <= 0) {
+      gprint (GP_ERR, "ERROR: xsize <= 0\n");
+      return FALSE;
+    }
+  }
+
   if ((N = get_argument (argc, argv, "-ew"))) {
     remove_argument (N, &argc, argv);
@@ -81,6 +103,11 @@
   }
 
-  if ((argc != 4) && (argc != 5)) {
-    gprint (GP_ERR, "USAGE: region Ra Dec Radius [projection] [orientation]\n");
+  int RadiusArg, CtypeArg;
+  if (!isnan(XSIZE) || !isnan(YSIZE)) {
+    RadiusArg = -1;
+    CtypeArg = 3;
+    if ((argc != 3) && (argc != 4)) {
+    gprint (GP_ERR, "USAGE: region Ra Dec [projection] [-xsize deg] [-ysize deg]\n");
+    gprint (GP_ERR, "   OR: region Ra Dec Radius [projection]\n");
     gprint (GP_ERR, "  [-image] [-ew] [+ew] [-ns] [+ns] [-no-clear] [-angle theta]\n");
     gprint (GP_ERR, " current: %f %f (%f x %f) (%s)\n", 
@@ -90,28 +117,51 @@
 	     &graphmode.coords.ctype[5]);
     return (FALSE);
-  }
-  
+    }
+  } else {
+    RadiusArg = 3;
+    CtypeArg = 4;
+    if ((argc != 4) && (argc != 5)) {
+      gprint (GP_ERR, "USAGE: region Ra Dec Radius [projection]\n");
+      gprint (GP_ERR, "   OR: region Ra Dec [projection] [-xsize deg] [-ysize deg]\n");
+      gprint (GP_ERR, "  [-image] [-ew] [+ew] [-ns] [+ns] [-no-clear] [-angle theta]\n");
+      gprint (GP_ERR, " current: %f %f (%f x %f) (%s)\n", 
+	      graphmode.coords.crval1, graphmode.coords.crval2, 
+	      fabs(graphmode.xmax - graphmode.xmin), 
+	      fabs(graphmode.ymax - graphmode.ymin), 
+	      &graphmode.coords.ctype[5]);
+      return (FALSE);
+    }
+  }  
   if (!ohana_str_to_radec (&Ra, &Dec, argv[1], argv[2])) return (FALSE);
-  Radius = atof (argv[3]);
+
+  // region 0 0 sin -- should raise an error (radius = 0 or non-numeric)
+
+  // I want to be able to support the old style call in which both of these were valid:
+  // region 0 0 90 ait
+  // region 0 0 90      <- uses existing, sticky projection type
+  // but I also want to be able to use
+  // region 0 0 ait -xsize 5
+  // region 0 0 ait -ysize 5
+
+  double Radius = NAN;
+  if (RadiusArg >= 0) {
+    Radius = atof (argv[RadiusArg]);
+  }
+
   InitCoords (&graphmode.coords, "DEC--TAN");
-
-  if (argc == 5) {
-    if (!strcasecmp (argv[4], "TAN")) 
-      strcpy (graphmode.coords.ctype, "DEC--TAN");
-    if (!strcasecmp (argv[4], "SIN")) 
-      strcpy (graphmode.coords.ctype, "DEC--SIN");
-    if (!strcasecmp (argv[4], "ARC")) 
-      strcpy (graphmode.coords.ctype, "DEC--ARC");
-    if (!strcasecmp (argv[4], "STG")) 
-      strcpy (graphmode.coords.ctype, "DEC--STG");
-    if (!strcasecmp (argv[4], "ZEA"))
-      strcpy (graphmode.coords.ctype, "DEC--ZEA");
-    if (!strcasecmp (argv[4], "AIT")) 
-      strcpy (graphmode.coords.ctype, "DEC--AIT");
-    if (!strcasecmp (argv[4], "GLS")) 
-      strcpy (graphmode.coords.ctype, "DEC--GLS");
-    if (!strcasecmp (argv[4], "PAR")) 
-      strcpy (graphmode.coords.ctype, "DEC--PAR");
-  }
+  if (argc == CtypeArg + 1) {
+    if (!strcasecmp (argv[CtypeArg], "TAN")) { strcpy (graphmode.coords.ctype, "DEC--TAN"); goto got_ctype; }
+    if (!strcasecmp (argv[CtypeArg], "SIN")) { strcpy (graphmode.coords.ctype, "DEC--SIN"); goto got_ctype; }
+    if (!strcasecmp (argv[CtypeArg], "ARC")) { strcpy (graphmode.coords.ctype, "DEC--ARC"); goto got_ctype; }
+    if (!strcasecmp (argv[CtypeArg], "STG")) { strcpy (graphmode.coords.ctype, "DEC--STG"); goto got_ctype; }
+    if (!strcasecmp (argv[CtypeArg], "ZEA")) { strcpy (graphmode.coords.ctype, "DEC--ZEA"); goto got_ctype; }
+    if (!strcasecmp (argv[CtypeArg], "AIT")) { strcpy (graphmode.coords.ctype, "DEC--AIT"); goto got_ctype; }
+    if (!strcasecmp (argv[CtypeArg], "GLS")) { strcpy (graphmode.coords.ctype, "DEC--GLS"); goto got_ctype; }
+    if (!strcasecmp (argv[CtypeArg], "PAR")) { strcpy (graphmode.coords.ctype, "DEC--PAR"); goto got_ctype; }
+    gprint (GP_ERR, "ERROR: invalid projection type %s\n", argv[CtypeArg]);
+    gprint (GP_ERR, "allowed values: TAN, SIN, ARC, STG, ZEA, AIT, GLS, PAR\n");
+    return FALSE;
+  }
+got_ctype:
   
   graphmode.coords.crval1 = Ra;
@@ -126,5 +176,6 @@
   graphmode.coords.pc2_2 =  cos(Angle*RAD_DEG)*pc2_2;
 
-  /* ask kapa for coordinate limits, to get the right aspect ratio */
+  // ask kapa for coordinate limits, to get the right aspect ratio 
+  // dx, dy are the size of the graph region in pixels
   KapaGetLimits (kapa, &dx, &dy);
   dx = fabs (dx);
@@ -132,15 +183,38 @@
 
   /* define limits for Ra, Dec at center, grid in degrees */
-  if (dy < dx) {
-    graphmode.xmin = -(dx/dy)*Radius;
-    graphmode.ymin = -Radius;
-    graphmode.xmax = (dx/dy)*Radius;
-    graphmode.ymax = Radius;
+  if (RadiusArg >= 0) {
+    // force non-anamorphic projection with Radius set to smaller axis
+    if (dy < dx) {
+      graphmode.xmin = -(dx/dy)*Radius;
+      graphmode.ymin = -Radius;
+      graphmode.xmax = (dx/dy)*Radius;
+      graphmode.ymax = Radius;
+    } else {
+      graphmode.xmin = -Radius;
+      graphmode.ymin = -(dy/dx)*Radius;
+      graphmode.xmax = Radius;
+      graphmode.ymax = (dy/dx)*Radius;
+    } 
   } else {
-    graphmode.xmin = -Radius;
-    graphmode.ymin = -(dy/dx)*Radius;
-    graphmode.xmax = Radius;
-    graphmode.ymax = (dy/dx)*Radius;
-  } 
+    if (isnan(XSIZE)) {
+      graphmode.xmin = -(dx/dy)*YSIZE/2.0;
+      graphmode.ymin = -YSIZE/2.0;
+      graphmode.xmax = (dx/dy)*YSIZE/2.0;
+      graphmode.ymax = YSIZE/2.0;
+    }
+    if (isnan(YSIZE)) {
+      graphmode.xmin = -XSIZE/2.0;
+      graphmode.ymin = -(dy/dx)*XSIZE/2.0;
+      graphmode.xmax = XSIZE/2.0;
+      graphmode.ymax = (dy/dx)*XSIZE/2.0;
+    }
+    // anamorphic projection:
+    if (!isnan(XSIZE) && !isnan(YSIZE)) {
+      graphmode.xmin = -XSIZE/2.0;
+      graphmode.ymin = -YSIZE/2.0;
+      graphmode.xmax =  XSIZE/2.0;
+      graphmode.ymax =  YSIZE/2.0;
+    }
+  }
 
   set_variable ("XMIN", graphmode.xmin);
