Index: trunk/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 31160)
+++ trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 31450)
@@ -141,4 +141,5 @@
 $(SRC)/vpop.$(ARCH).o		   \
 $(SRC)/vroll.$(ARCH).o		   \
+$(SRC)/vshift.$(ARCH).o		   \
 $(SRC)/vsmooth.$(ARCH).o	   \
 $(SRC)/vstats.$(ARCH).o		   \
Index: trunk/Ohana/src/opihi/cmd.data/gridify.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/gridify.c	(revision 31160)
+++ trunk/Ohana/src/opihi/cmd.data/gridify.c	(revision 31450)
@@ -4,5 +4,5 @@
 
   int i, Nx, Ny, Xb, Yb, Normalize, N;
-  float Xmin, Xmax, dX, Ymin, Ymax, dY;
+  float Xmin, Xmax, dX, Ymin, Ymax, dY, initValue;
   float *buf, *val;
   int *Nval;
@@ -15,4 +15,11 @@
     remove_argument (N, &argc, argv);
     Normalize = FALSE;
+  }
+
+  initValue = 0.0;
+  if ((N = get_argument (argc, argv, "-init-value"))) {
+    remove_argument (N, &argc, argv);
+    initValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
   }
 
@@ -69,7 +76,7 @@
   buf = (float *) bf[0].matrix.buffer;
   for (i = 0; i < Nx*Ny; i++) {
+    buf[i] = initValue;
     if (Normalize) {
       if (Nval[i] == 0) {
-	buf[i] = 0;
 	continue;
       }
Index: trunk/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/init.c	(revision 31160)
+++ trunk/Ohana/src/opihi/cmd.data/init.c	(revision 31450)
@@ -130,4 +130,5 @@
 int vstats           PROTO((int, char **));
 int vroll            PROTO((int, char **));
+int vshift           PROTO((int, char **));
 int vpop             PROTO((int, char **));
 int vsmooth          PROTO((int, char **));
@@ -274,5 +275,6 @@
   {1, "vmaxwell",     vmaxwell,         "fit a Maxwellian to a vector"},
   {1, "vpop",         vpop,             "remove first element of a vector"},
-  {1, "vroll",        vroll,            "roll vector elements"},
+  {1, "vroll",        vroll,            "roll vector elements by 1 entry"},
+  {1, "vshift",       vshift,           "shift vector elements by arbitrary amount"},
   {1, "vsmooth",      vsmooth,          "Gaussian smooth of a vector"},
   {1, "vstats",       vstats,           "statistics on a vector"},
Index: trunk/Ohana/src/opihi/cmd.data/vshift.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/vshift.c	(revision 31450)
+++ trunk/Ohana/src/opihi/cmd.data/vshift.c	(revision 31450)
@@ -0,0 +1,73 @@
+# include "data.h"
+
+int vshift (int argc, char **argv) {
+
+  int isPos, N, Npix, Nshift, delta, ROLL;
+  Vector *ivec, *ovec;
+
+  ROLL = FALSE;
+  if ((N = get_argument (argc, argv, "-roll"))) {
+    remove_argument (N, &argc, argv);
+    ROLL = TRUE;
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: vshift (input) (output) (delta) [-roll]\n");
+    gprint (GP_ERR, "  shift vector by (delta) elements\n");
+    gprint (GP_ERR, "  a positive value move element (i) to (i+delta)\n");
+    gprint (GP_ERR, "  -roll : move dropped values to the other size (no elements are lost)\n");
+    return (FALSE);
+  }
+
+  if ((ivec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ovec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  delta = atoi(argv[3]);
+  isPos = delta > 0;
+  delta = abs(delta);
+    
+  ResetVector (ovec, ivec->type, ivec->Nelements);
+
+  Npix = ivec[0].Nelements;
+  if (delta > Npix) {
+    if (!ROLL) {
+      if (ivec[0].type == OPIHI_FLT) {
+	memset (ovec[0].elements.Flt, 0, Npix*sizeof(opihi_flt));
+      } else {
+	memset (ovec[0].elements.Flt, 0, Npix*sizeof(opihi_flt));
+      }
+      return TRUE;
+    }
+    delta = delta % Npix;
+  }
+
+  if (ivec[0].type == OPIHI_FLT) {
+    memset (ovec[0].elements.Flt, 0, Npix*sizeof(opihi_flt));
+    Nshift = Npix - delta;
+    if (isPos) {
+      memcpy (&ovec[0].elements.Flt[delta], &ivec[0].elements.Flt[0], Nshift*sizeof(opihi_flt));
+      if (ROLL) {
+	memcpy (&ovec[0].elements.Flt[0], &ivec[0].elements.Flt[Nshift], delta*sizeof(opihi_flt));
+      } 
+    } else {
+      memcpy (&ovec[0].elements.Flt[0], &ivec[0].elements.Flt[delta], Nshift*sizeof(opihi_flt));
+      if (ROLL) {
+	memcpy (&ovec[0].elements.Flt[Nshift], &ivec[0].elements.Flt[0], delta*sizeof(opihi_flt));
+      }
+    }
+  } else {
+    memset (ovec[0].elements.Int, 0, Npix*sizeof(opihi_int));
+    Nshift = Npix - delta;
+    if (isPos) {
+      memcpy (&ovec[0].elements.Int[delta], &ivec[0].elements.Int[0], Nshift*sizeof(opihi_int));
+      if (ROLL) {
+	memcpy (&ovec[0].elements.Int[0], &ivec[0].elements.Int[Nshift], delta*sizeof(opihi_int));
+      } 
+    } else {
+      memcpy (&ovec[0].elements.Int[0], &ivec[0].elements.Int[delta], Nshift*sizeof(opihi_int));
+      if (ROLL) {
+	memcpy (&ovec[0].elements.Int[Nshift], &ivec[0].elements.Int[0], delta*sizeof(opihi_int));
+      }
+    }
+  }
+  return (TRUE);
+}
Index: trunk/Ohana/src/opihi/dvo/Makefile
===================================================================
--- trunk/Ohana/src/opihi/dvo/Makefile	(revision 31160)
+++ trunk/Ohana/src/opihi/dvo/Makefile	(revision 31450)
@@ -80,4 +80,5 @@
 $(SRC)/mextract.$(ARCH).o	  	\
 $(SRC)/mmextract.$(ARCH).o	  	\
+$(SRC)/objectcoverage.$(ARCH).o	  	\
 $(SRC)/photcodes.$(ARCH).o	  	\
 $(SRC)/pmeasure.$(ARCH).o	  	\
Index: trunk/Ohana/src/opihi/dvo/avextract.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/avextract.c	(revision 31160)
+++ trunk/Ohana/src/opihi/dvo/avextract.c	(revision 31450)
@@ -5,5 +5,5 @@
   off_t i, j, n, m;
   int N, Npts, NPTS, last, next, state, Nfields, Nreturn, Ncstack, Nstack;
-  int Nsecfilt, mode, VERBOSE;
+  int Nsecfilt, mode, VERBOSE, needMeasures;
   char **cstack, name[1024];
   void *Signal;
@@ -101,4 +101,13 @@
   }
 
+  // check the requested fields : are all average/secfilt entries, or do we need measures?
+  needMeasures = FALSE;
+  for (i = 0; !needMeasures && (i < Nfields); i++) {
+    if (fields[i].magMode == MAG_NONE) continue;
+    if (fields[i].photcode == NULL) continue; // assert this?
+    if (fields[i].photcode[0].type == PHOT_REF) needMeasures = TRUE;
+    if (fields[i].photcode[0].type == PHOT_DEP) needMeasures = TRUE;
+  }
+
   // grab data from all selected sky regions
   Signal = signal (SIGINT, handle_interrupt);
@@ -107,5 +116,8 @@
     /* lock, load, unlock catalog */
     catalog.filename = skylist[0].filename[i];
-    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.catflags = LOAD_AVES | LOAD_SECF;
+    if (needMeasures) {
+      catalog.catflags |= LOAD_MEAS;
+    }
     catalog.Nsecfilt = 0;
 
Index: trunk/Ohana/src/opihi/dvo/init.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/init.c	(revision 31160)
+++ trunk/Ohana/src/opihi/dvo/init.c	(revision 31450)
@@ -40,5 +40,6 @@
 int lightcurve      PROTO((int, char **));
 int mextract        PROTO((int, char **));
-int mmextract        PROTO((int, char **));
+int mmextract       PROTO((int, char **));
+int objectcoverage  PROTO((int, char **));
 int pcat            PROTO((int, char **));
 int photcodes       PROTO((int, char **));
@@ -92,4 +93,5 @@
   {1, "mextract",    mextract,     "extract measure data values"},
   {1, "mmextract",   mmextract,    "extract joined measurements"},
+  {1, "objectcoverage", objectcoverage, "plot catalog boundaries"},
   {1, "pcat",        skycat,       "plot catalog boundaries"},
   {1, "photcodes",   photcodes,    "list photometry codes"},
Index: trunk/Ohana/src/opihi/dvo/objectcoverage.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/objectcoverage.c	(revision 31450)
+++ trunk/Ohana/src/opihi/dvo/objectcoverage.c	(revision 31450)
@@ -0,0 +1,235 @@
+# include "dvoshell.h"
+
+int wordhash (char *word);
+
+int objectcoverage (int argc, char **argv) {
+
+  void *Signal;
+  int ShowDensity;
+  int N, status, TimeSelect, xs, ys;
+  time_t tzero, tend;
+  double pixscale, r, d, Xs, Ys, trange, RaCenter, DecCenter;
+  char projection[16];
+  float *V;
+  int k, j, invalid, Nx, Ny;
+  Buffer *buf;
+  Coords coords;
+  int Nsecfilt;
+  SkyList *skylist;
+  SkyRegionSelection *selection;
+
+  Catalog catalog; 
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+  skylist = NULL;
+  selection = NULL;
+  RaCenter = 0.0;
+  DecCenter = 0.0;
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) goto escape;
+  if ((N = get_argument (argc, argv, "-center"))) {
+    remove_argument (N, &argc, argv);
+    RaCenter = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    DecCenter = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Nx = 0;
+  Ny = 0;
+  if ((N = get_argument (argc, argv, "-size"))) {
+    remove_argument (N, &argc, argv);
+    Nx = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    Ny = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  pixscale = 1.0;
+  if ((N = get_argument (argc, argv, "-scale"))) {
+    remove_argument (N, &argc, argv);
+    pixscale = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  ShowDensity = FALSE;
+  if ((N = get_argument (argc, argv, "-density"))) {
+    remove_argument (N, &argc, argv);
+    ShowDensity = TRUE;
+  }
+
+  strcpy (projection, "DEC--AIT");
+  if ((N = get_argument (argc, argv, "-proj"))) {
+    remove_argument (N, &argc, argv);
+    if (!strcasecmp(argv[N], "TAN")) {
+	strcpy (projection, "DEC--TAN");
+    }	
+    if (!strcasecmp(argv[N], "SIN")) {
+	strcpy (projection, "DEC--SIN");
+    }	
+    if (!strcasecmp(argv[N], "GLS")) {
+	strcpy (projection, "DEC--GLS");
+    }	
+    if (!strcasecmp(argv[N], "PAR")) {
+	strcpy (projection, "DEC--PAR");
+    }	
+    remove_argument (N, &argc, argv);
+  }
+
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-trange"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tend)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    trange = tend - tzero;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+ 
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: objectcoverage (buffer) (photcode)\n");
+    gprint (GP_ERR, "  options: [-scale pixscale] [-center ra dec] [-size Nx Nx] [-proj projection] [-time start range] [-trange start stop] [-name name] [+mosaic] [-mosaic] [-density]\n");
+    gprint (GP_ERR, "       (buffer) saves bitmapped image\n");
+    gprint (GP_ERR, "       (photcode) ..........\n");
+    gprint (GP_ERR, "       -scale (pixscale)  : specifies the pixel size in degrees [1.0]\n");
+    gprint (GP_ERR, "       -center (ra) (dec) : specifies the center of the field [0.0, 0.0]\n");
+    gprint (GP_ERR, "       -size (Nx) (Ny)    : specifies the size of the image [360/scale, 180/scale]\n");
+    gprint (GP_ERR, "       -proj (projection) : specifies the projection choice [AIT]\n");
+    gprint (GP_ERR, "       -density           : create image with relative density (else binary on/off)\n");
+    gprint (GP_ERR, "       note: we need 64800 / (pixscale)^2 pixels to represent the sky\n");
+    return (FALSE);
+  }
+  
+  if ((buf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  int myCode = GetPhotcodeCodebyName (argv[2]);
+  if (myCode == 0) {
+      gprint (GP_ERR, "invalid photcode\n");
+      return (FALSE);
+  }
+
+  if (!Nx || !Ny) {
+    Nx = 360/pixscale;
+    Ny = 180/pixscale;
+  }
+
+  gfits_free_matrix (&buf[0].matrix);
+  gfits_free_header (&buf[0].header);
+  CreateBuffer (buf, Nx, Ny, -32, 0.0, 1.0);
+  strcpy (buf[0].file, "(empty)");
+
+  coords.crval1 = RaCenter;
+  coords.crval2 = DecCenter;
+  coords.crpix1 = 0.5*Nx;
+  coords.crpix2 = 0.5*Ny;
+  strcpy (coords.ctype, projection);
+  coords.pc1_1 = -1.0;
+  coords.pc2_2 = +1.0;
+  coords.pc1_2 =  0.0;
+  coords.pc2_1 =  0.0;
+  coords.cdelt1 = coords.cdelt2 = pixscale;
+  coords.Npolyterms = 0;
+
+  PutCoords (&coords, &buf[0].header);
+
+  V = (float *)buf[0].matrix.buffer;
+
+  for (ys = 0; ys < Ny; ys++) {
+    for (xs = 0; xs < Nx; xs++) {
+      status = XY_to_RD (&r, &d, (double)(xs), (double)(ys), &coords);
+      status &= (r >= 0);
+      status &= (r <= 360);
+      if (status) {
+	V[ys*Nx + xs] = ShowDensity ?  0 : 2;
+      } else {
+	V[ys*Nx + xs] = ShowDensity ? -1 : 0;
+      }
+    }
+  }
+
+  Nsecfilt = GetPhotcodeNsecfilt();
+  // grab data from all selected sky regions
+  Signal = signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (selection)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (k = 0; (k < skylist[0].Nregions) && !interrupt; k++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[k];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    int Nsec = GetPhotcodeNsec(myCode);
+
+    for (j = 0; j <  catalog.Naverage; j++) {
+	if (catalog.average[j].Nmeasure < 2) { continue; }
+
+	
+	if (catalog.secfilt[j*Nsecfilt+Nsec].Ncode < 2) { continue; }
+
+	invalid = ((catalog.secfilt[j*Nsecfilt + Nsec].M < 1.0) || (isnan(catalog.secfilt[j*Nsecfilt + Nsec].M)));
+	if (invalid) continue;
+	
+	double r = catalog.average[j].R;
+	double d = catalog.average[j].D;
+	status = RD_to_XY (&Xs, &Ys, r, d, &coords);
+	if (Xs < 0) continue;
+	if (Ys < 0) continue;
+	if (Xs >= Nx) continue;
+	if (Ys >= Ny) continue;
+	if (status) {
+	    xs = (int)Xs;
+	    ys = (int)Ys;
+	    if (ShowDensity) {
+		V[ys*Nx + xs] += 1;
+	    } else {
+		V[ys*Nx + xs] = 1;
+	    }
+	}
+    }
+  }
+  return (TRUE);
+
+escape:
+  return (FALSE);
+}
+
+
