Index: /branches/eam_branches/ipp-dev-20210817/Ohana/src/opihi/cmd.data/vstats.c
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/Ohana/src/opihi/cmd.data/vstats.c	(revision 41818)
+++ /branches/eam_branches/ipp-dev-20210817/Ohana/src/opihi/cmd.data/vstats.c	(revision 41819)
@@ -48,6 +48,8 @@
   }
 
-  if (argc != 2) {
-    gprint (GP_ERR, "USAGE: vstat (vector) [-ignore value] [-q] [-quiet] [-iter Niter] [-sigma-clip Nsigma]\n");
+  int valid = (argc == 2);
+  valid |= (argc > 3) && !strcmp (argv[2], "where");
+  if (!valid) {
+    gprint (GP_ERR, "USAGE: vstat (vector) [-ignore value] [-q] [-quiet] [-iter Niter] [-sigma-clip Nsigma] [where (logical expression)]\n");
     gprint (GP_ERR, "  default is 1 iteration without sigma clipping or 3 with sigma clipping\n");
     return (FALSE);
@@ -58,10 +60,36 @@
   /* we need two passes, one for max, min, mean, sum, one for median, stdev, etc */
 
-  // set a good / bad mask
+  // tvec is used for logical test (truth vector)
+  Vector *tvec = NULL;
+  if (argc > 3) {
+    int size;
+    char *out = dvomath (argc - 3, &argv[3], &size, 1);
+    if (out == NULL) {
+      print_error ();
+      return FALSE;
+    }
+    if ((tvec = SelectVector (out, OLDVECTOR, TRUE)) == NULL) {
+      gprint (GP_ERR, " invalid logic result\n");
+      DeleteNamedVector (out);
+      free (out);
+      return (FALSE);
+    }
+    if (tvec->Nelements != vec->Nelements) {
+      gprint (GP_ERR, "logical vector does not match in length\n");
+      return FALSE;
+    }
+  }
+
+  // set a good / bad mask (mask == 1 means 'bad')
   ALLOCATE (mask, char, vec[0].Nelements);
   if (vec[0].type == OPIHI_FLT) {
     opihi_flt *X = vec[0].elements.Flt;
     for (i = 0; i < vec[0].Nelements; i++, X++) {
-      mask[i] = 1;
+      if (tvec) {
+	// note the logical vector is 0 == bad (ignore)
+	mask[i] = (tvec->type == OPIHI_FLT) ? (tvec->elements.Flt[i] == 0.0) : (tvec->elements.Int[i] == 0);
+      } else {
+	mask[i] = 1;
+      }
       if (!finite (*X)) continue;
       if (Ignore && (*X == IgnoreValue)) continue;
@@ -71,5 +99,10 @@
     opihi_int *X = vec[0].elements.Int;
     for (i = 0; i < vec[0].Nelements; i++, X++) {
-      mask[i] = 1;
+      if (tvec) {
+	// note the logical vector is 0 == bad (ignore)
+	mask[i] = (tvec->type == OPIHI_FLT) ? (tvec->elements.Flt[i] == 0.0) : (tvec->elements.Int[i] == 0);
+      } else {
+	mask[i] = 1;
+      }
       if (!finite (*X)) continue;
       if (Ignore && (*X == IgnoreValue)) continue;
