Index: trunk/Ohana/src/opihi/cmd.astro/fitplx.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/fitplx.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.astro/fitplx.c	(revision 40291)
@@ -77,5 +77,5 @@
   double *dD = dDvec->elements.Flt;
 
-  int *mask = NULL;
+  opihi_int *mask = NULL;
   if (mvec) {
     mask = mvec->elements.Int;
@@ -380,5 +380,5 @@
 }
 
-int PlxSetMeanEpoch (double *R, double *D, double *T, double *Rmean, double *Dmean, double *Tmean, int *mask, int Ntotal) {
+int PlxSetMeanEpoch (double *R, double *D, double *T, double *Rmean, double *Dmean, double *Tmean, opihi_int *mask, int Ntotal) {
 
   int i;
@@ -413,5 +413,5 @@
 
 // generate the fit values (projected X,Y; parallax factors; 
-int PlxSetEpochPosition (PlxFitData *fitdata, double *R, double *D, double *dR, double *dD, double *T, int *mask, int Ntotal, Coords *coords, double Tmean) {
+int PlxSetEpochPosition (PlxFitData *fitdata, double *R, double *D, double *dR, double *dD, double *T, opihi_int *mask, int Ntotal, Coords *coords, double Tmean) {
 
   int i;
@@ -464,5 +464,5 @@
 # define MAX_REJECT 0.1
 
-int PlxOutlierClip (PlxFitData *fitdata, int *mask, int Noutlier, float dPsigMax, Vector *dPvec, int VERBOSE) {
+int PlxOutlierClip (PlxFitData *fitdata, opihi_int *mask, int Noutlier, float dPsigMax, Vector *dPvec, int VERBOSE) {
 
   int i, n;
Index: trunk/Ohana/src/opihi/cmd.astro/fitplx_irls.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/fitplx_irls.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.astro/fitplx_irls.c	(revision 40291)
@@ -81,5 +81,5 @@
   double *dD = dDvec->elements.Flt;
 
-  int *mask = NULL;
+  opihi_int *mask = NULL;
   if (mvec) {
     mask = mvec->elements.Int;
@@ -109,6 +109,6 @@
   for (i = 0; (VERBOSE == 2) && (i < fitdata.Npts); i++) {
     int n = fitdata.index[i];
-    int maskValue = mask ? mask[n] : 1;
-    fprintf (stderr, "%f %f : %f %d : %f %f %f\n", R[n], D[n], T[n], maskValue, fitdata.t[i], fitdata.X[i], fitdata.Y[i]);
+    opihi_int maskValue = mask ? mask[n] : 1;
+    fprintf (stderr, "%f %f : %f "OPIHI_INT_FMT" : %f %f %f\n", R[n], D[n], T[n], maskValue, fitdata.t[i], fitdata.X[i], fitdata.Y[i]);
   }
 
@@ -150,5 +150,5 @@
       
       if (VERBOSE == 2) {
-	  fprintf (stderr, "%f %f : %f %d : %f %f %f : %f %f %f %f\n", R[n], D[n], T[n], mask[n], fitdata.t[i], fitdata.X[i], fitdata.Y[i], fitdata.Wx[i], fitdata.Wy[i], Sum_Wx, Sum_Wy);
+	  fprintf (stderr, "%f %f : %f "OPIHI_INT_FMT" : %f %f %f : %f %f %f %f\n", R[n], D[n], T[n], mask[n], fitdata.t[i], fitdata.X[i], fitdata.Y[i], fitdata.Wx[i], fitdata.Wy[i], Sum_Wx, Sum_Wy);
       }
     }
Index: trunk/Ohana/src/opihi/cmd.astro/fitpm.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/fitpm.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.astro/fitpm.c	(revision 40291)
@@ -50,5 +50,5 @@
   double *dD = dDvec->elements.Flt;
 
-  int *mask = NULL;
+  opihi_int *mask = NULL;
   if (mvec) {
     mask = mvec->elements.Int;
Index: trunk/Ohana/src/opihi/cmd.astro/fitpm_irls.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/fitpm_irls.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.astro/fitpm_irls.c	(revision 40291)
@@ -58,5 +58,5 @@
   double *dD = dDvec->elements.Flt;
 
-  int *mask = NULL;
+  opihi_int *mask = NULL;
   if (mvec) {
     mask = mvec->elements.Int;
Index: trunk/Ohana/src/opihi/cmd.astro/star.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/star.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.astro/star.c	(revision 40291)
@@ -3,5 +3,5 @@
 int star (int argc, char **argv) {
 
-  int x, y, N, dx, Nborder;
+  int x, y, N, Nborder;
   double max;
   Buffer *buf;
@@ -33,6 +33,18 @@
   }
   
+  int dx = 11;
+  int dy = 11;
+  int BOX = FALSE;
+  if ((N = get_argument (argc, argv, "-box"))) {
+    remove_argument (N, &argc, argv);
+    dx  = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
+    dy  = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
+    BOX = TRUE;
+  }
+
   if ((argc != 4) && (argc != 5)) {
-    gprint (GP_ERR, "USAGE: star (buffer) x y [dx] [-border N] [-sat cnts]\n");
+    gprint (GP_ERR, "USAGE: star (buffer) x y [dx] [-border N] [-sat cnts] [-box dx dy]\n");
     gprint (GP_ERR, " dx is the aperture diameter, but is adjusted up to the next odd number\n");
     return (FALSE);
@@ -40,5 +52,4 @@
   if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
 
-  dx = 11;
   x = atof (argv[2]);
   y = atof (argv[3]);
@@ -47,5 +58,9 @@
   }
 
-  get_aperture_stats (&buf[0].matrix, x, y, dx, Nborder, max, VERBOSE);
+  if (BOX) {
+    get_box_stats (&buf[0].matrix, x, y, dx, dy, Nborder, max, VERBOSE);
+  } else {
+    get_aperture_stats (&buf[0].matrix, x, y, dx, Nborder, max, VERBOSE);
+  }
   
   return (TRUE);
Index: trunk/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 40291)
@@ -155,4 +155,5 @@
 $(SRC)/type.$(ARCH).o		   \
 $(SRC)/uniq.$(ARCH).o		   \
+$(SRC)/uniqpair.$(ARCH).o		   \
 $(SRC)/unsign.$(ARCH).o	           \
 $(SRC)/vbin.$(ARCH).o		   \
Index: trunk/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/init.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.data/init.c	(revision 40291)
@@ -141,6 +141,7 @@
 int tvcontour        PROTO((int, char **));
 int tvgrid           PROTO((int, char **));
-int opihi_type             PROTO((int, char **));
+int opihi_type       PROTO((int, char **));
 int uniq             PROTO((int, char **));
+int uniqpair         PROTO((int, char **));
 int unsign           PROTO((int, char **));
 int vbin             PROTO((int, char **));
@@ -325,4 +326,5 @@
   {1, "ungridify",    ungridify,        "convert image region to vector triplet"},
   {1, "uniq",         uniq,             "create a uniq vector subset from a vector"},
+  {1, "uniqpair",     uniqpair,         "create a uniq vector subset from a pair of vectors, saving duplicates if desired"},
   {1, "unsign",       unsign,           "toggle the UNSIGN status"},
   {1, "vbin",         vbin,             "rebin vector data by a factor of N"},
Index: trunk/Ohana/src/opihi/cmd.data/limits.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/limits.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.data/limits.c	(revision 40291)
@@ -3,7 +3,6 @@
 int limits (int argc, char **argv) {
 
-  int N, APPLY, dX, dY;
+  int N, dX, dY;
   int kapa;
-  char *name;
   Graphdata graphmode;
   Vector *xvec, *yvec;
@@ -11,10 +10,56 @@
   xvec = yvec = NULL;
 
-  APPLY = FALSE;
+  float minLimitX = NAN;
+  float minLimitY = NAN;
+  float maxLimitX = NAN;
+  float maxLimitY = NAN;
+  float delLimitX = NAN;
+  float delLimitY = NAN;
+
+  if ((N = get_argument (argc, argv, "-minX"))) {
+    remove_argument (N, &argc, argv);
+    minLimitX = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-maxX"))) {
+    remove_argument (N, &argc, argv);
+    maxLimitX = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-delX"))) {
+    if (!isnan(minLimitX) || !isnan(maxLimitX)) {
+      gprint (GP_ERR, "-minX & -maxX cannot be mixed with -delX\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    delLimitX = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-minY"))) {
+    remove_argument (N, &argc, argv);
+    minLimitY = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-maxY"))) {
+    remove_argument (N, &argc, argv);
+    maxLimitY = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-delY"))) {
+    if (!isnan(minLimitY) || !isnan(maxLimitY)) {
+      gprint (GP_ERR, "-minY & -maxY cannot be mixed with -delY\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    delLimitY = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  int APPLY = FALSE;
   if ((N = get_argument (argc, argv, "-a"))) {
     remove_argument (N, &argc, argv);
     APPLY = TRUE;
   }
-  name = NULL;
+  char *name = NULL;
   if ((N = get_argument (argc, argv, "-n"))) {
     remove_argument (N, &argc, argv);
@@ -22,4 +67,5 @@
     remove_argument (N, &argc, argv);
   }
+
   if (!GetGraph (&graphmode, &kapa, name)) return (FALSE);
   FREE (name);
@@ -97,4 +143,27 @@
  success:
   SetLimits (xvec, yvec, &graphmode);
+
+  if (!isnan(minLimitX)) graphmode.xmin = MIN (minLimitX, graphmode.xmin);
+  if (!isnan(maxLimitX)) graphmode.xmax = MAX (maxLimitX, graphmode.xmax);
+  if (!isnan(minLimitY)) graphmode.ymin = MIN (minLimitY, graphmode.ymin);
+  if (!isnan(maxLimitY)) graphmode.ymax = MAX (maxLimitY, graphmode.ymax);
+
+  if (!isnan(delLimitX)) {
+    float delta = graphmode.xmax - graphmode.xmin;
+    if (fabs(delLimitX) > fabs(delta)) {
+      float midpt = 0.5*(graphmode.xmax + graphmode.xmin);
+      graphmode.xmax = midpt + 0.5*delLimitX;
+      graphmode.xmin = midpt - 0.5*delLimitX;
+    }
+  }
+  if (!isnan(delLimitY)) {
+    float delta = graphmode.ymax - graphmode.ymin;
+    if (fabs(delLimitY) > fabs(delta)) {
+      float midpt = 0.5*(graphmode.ymax + graphmode.ymin);
+      graphmode.ymax = midpt + 0.5*delLimitY;
+      graphmode.ymin = midpt - 0.5*delLimitY;
+    }
+  }
+
   if (APPLY) KapaSetLimits (kapa, &graphmode);
   return (TRUE);
Index: trunk/Ohana/src/opihi/cmd.data/print_vectors.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/print_vectors.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.data/print_vectors.c	(revision 40291)
@@ -4,5 +4,19 @@
 
   Vector **vec;
-  int i, j;
+  int i, j, N;
+
+  int START_VALUE = 0;
+  if ((N = get_argument (argc, argv, "-s"))) {
+    remove_argument (N, &argc, argv);
+    START_VALUE = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  int END_VALUE = -1;
+  if ((N = get_argument (argc, argv, "-e"))) {
+    remove_argument (N, &argc, argv);
+    END_VALUE = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
 
   if (argc < 2) {
@@ -27,5 +41,13 @@
   }
 
-  for (j = 0; j < MaxLen; j++) {
+  // start and end may be 0 - N (truncated to N) or may be negative, in which case it refers to 
+  // distance from the end (just like vector[-5])
+  START_VALUE = (START_VALUE < 0) ? MaxLen + START_VALUE + 1 : MIN (START_VALUE, MaxLen);
+  START_VALUE = MAX (0, START_VALUE);
+
+  END_VALUE = (END_VALUE < 0) ? MaxLen + END_VALUE + 1 : MIN (END_VALUE, MaxLen);
+  END_VALUE = MAX (0, END_VALUE);
+
+  for (j = START_VALUE; j < END_VALUE; j++) {
     for (i = 0; i < Nvec; i++) {
       if (j >= vec[i][0].Nelements) {
@@ -35,5 +57,5 @@
 	  gprint (GP_LOG, "%f ", vec[i][0].elements.Flt[j]);
 	} else {
-	  gprint (GP_LOG, "%d ", vec[i][0].elements.Int[j]);
+	  gprint (GP_LOG, OPIHI_INT_FMT" ", vec[i][0].elements.Int[j]);
 	}
       }
Index: trunk/Ohana/src/opihi/cmd.data/reindex.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/reindex.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.data/reindex.c	(revision 40291)
@@ -47,5 +47,5 @@
 	continue;
       }
-      if (*vx > Nmax) ESCAPE("unexpected value in index: %d (%d)\n", *vx, i);
+      if (*vx > Nmax) ESCAPE("unexpected value in index: "OPIHI_INT_FMT" (%d)\n", *vx, i);
       ovec[0].elements.Flt[Npts] = vi[*vx];
       Npts++;
@@ -67,5 +67,5 @@
 	continue;
       }
-      if (*vx > Nmax) ESCAPE("unexpected value in index: %d (%d)\n", *vx, i);
+      if (*vx > Nmax) ESCAPE("unexpected value in index: "OPIHI_INT_FMT" (%d)\n", *vx, i);
       ovec[0].elements.Int[Npts] = vi[*vx];
       Npts++;
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 40291)
@@ -55,5 +55,4 @@
 
  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
@@ -88,5 +87,4 @@
 
  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
@@ -97,4 +95,8 @@
  if (abs ($peakpos - $P) > 0.05)
    $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
@@ -117,5 +119,4 @@
 
  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
@@ -126,4 +127,8 @@
  if (abs ($peakpos - $P) > 0.05)
    $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
@@ -145,5 +150,5 @@
  set df = 0.01 + zero(f)
 
- periodogram_fm t f 2 30 period power
+ periodogram_fm t f df 2 30 period power
 
 #  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
@@ -155,7 +160,11 @@
    $PASS = 0
  end
-end
-
-# test using random samples, offset start, non-zero DC, some noise
+
+ 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 300 random samples, offset start, non-zero DC, some noise
 macro test6
  $PASS = 1
@@ -178,5 +187,5 @@
  set df = 0.01 + zero(f)
 
- periodogram_fm t f 2 30 period power
+ periodogram_fm t f df 2 30 period power
 
 #  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
@@ -188,7 +197,11 @@
    $PASS = 0
  end
-end
-
-# test using fewer random samples, offset start, non-zero DC, some noise
+
+ 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 100 fewer random samples, offset start, non-zero DC, some noise
 macro test7
  $PASS = 1
@@ -211,5 +224,5 @@
  set df = 0.01 + zero(f)
 
- periodogram_fm t f 2 30 period power
+ periodogram_fm t f df 2 30 period power
 
 #  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
@@ -221,22 +234,28 @@
    $PASS = 0
  end
-end
-
-# test using fewer random samples, high frequency, non-zero DC, some noise
+
+ 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 Ndays random samples, RR Lyrae-sized light curves (0.7 mag),
+# optional noise level 
 macro test8
- if ($0 != 2)
-   echo "USAGE: test8: Ndays")
+ if ($0 != 4)
+   echo "USAGE: test8: Period Ndays (df)"
    break
  end
  
  local Ndays 
- $Ndays = $1
-
- $PASS = 1
- break -auto off
-
- local P PI
- $PI = 3.14159265359
- $P  = 0.8*rnd(0) + 0.2
+ $P = $1
+ $Ndays = $2
+ $dM = $3
+
+ $PASS = 1
+ break -auto off
+
+ local PI
+ $PI = 3.14159265359
  $trueP = $P
 
@@ -246,7 +265,7 @@
 
  # 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 tday = int(100 * rnd(x)); # choose Ndays random days between 0 and 100
+ set dtx = (3/24) * rnd(x);  # choose a starting time within that night
+ set t0 = tday + dtx
 
  set dt1 = (15.0 / 1440) * rnd(x) + ( 0 + 7.5) / 1440
@@ -260,13 +279,13 @@
  set tmp = t0 + dt3; concat tmp t
 
- set fraw = sin(2*$PI*t/$P) + 0.5
+ set fraw = 0.75*sin(2*$PI*t/$P)
 
  # 0.05 : peakpos = 14.95
  # 0.10 : peakpos = 15.04 (
- gaussdev df t[] 0.0 0.25
+ gaussdev df t[] 0.0 $dM
  set f = fraw + df
- set df = 0.01 + zero(f)
-
- periodogram_fm t f 0.1 2.0 period power
+ set df = $dM + zero(f)
+
+ periodogram_fm t f df 0.1 20.0 period power
 
 #  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
@@ -278,5 +297,233 @@
    $PASS = 0
  end
-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 Ndays random samples, RR Lyrae-sized light curves (0.7 mag),
+# optional noise level 
+# compare periodogram and periodogram_fm
+macro test9
+ if ($0 != 4)
+   echo "USAGE: test8: Period Ndays (df)"
+   break
+ end
+ 
+ local Ndays 
+ $P = $1
+ $Ndays = $2
+ $dM = $3
+
+ $PASS = 1
+ break -auto off
+
+ local PI
+ $PI = 3.14159265359
+ $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 tday = int(100 * rnd(x)); # choose Ndays random days between 0 and 100
+ set dtx = (3/24) * rnd(x);  # choose a starting time within that night
+ set t0 = tday + 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 = 0.75*sin(2*$PI*t/$P)
+
+ # 0.05 : peakpos = 14.95
+ # 0.10 : peakpos = 15.04 (
+ gaussdev df t[] 0.0 $dM
+ set f = fraw + df
+ set df = $dM + zero(f)
+
+ periodogram_fm t f df 0.1 20.0 period_fm power_fm
+ periodogram t f 0.1 20.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_fm power_fm
+ $peakval_fm = $peakval
+
+ peak -q period power
+ vstat -q power
+ set power = power / $MAX
+
+# if (abs ($peakpos - $P) > 0.05)
+#   $PASS = 0
+# end
+
+ set freq = 1 / period
+ set freq_fm = 1 / period_fm
+ $Freq = 1 / $P
+
+ if ($PLOT)
+  if (1)
+    lim period power; clear; box
+    line -c red70 -lw 3 $P 0 to $P $peakval_fm;
+    plot period power -x line -c grey70 -lw 2
+    plot period_fm power_fm -x line -c black
+  else
+    lim freq power; clear; box
+    line -c red70 -lw 3 $Freq 0 to $Freq 1.0
+    plot freq power -x line -c grey70 -lw 2
+    plot freq_fm power_fm -x line -c black
+  end
+ end
+end
+
+
+# test using Ndays random samples, RR Lyrae-sized light curves (0.7 mag),
+# optional noise level 
+# compare periodogram and periodogram_fm
+macro test10
+ if ($0 != 4)
+   echo "USAGE: test8: Period Ndays (df)"
+   break
+ end
+ 
+ local Ndays 
+ $P = $1
+ $Ndays = $2
+ $dM = $3
+
+ $PASS = 1
+ break -auto off
+
+ local PI
+ $PI = 3.14159265359
+ $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 tday = int(100 * rnd(x)); # choose Ndays random days between 0 and 100
+ set dtx = (3/24) * rnd(x);  # choose a starting time within that night
+ set t0 = tday + 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 = 0.75*sin(2*$PI*t/$P)
+
+ # 0.05 : peakpos = 14.95
+ # 0.10 : peakpos = 15.04 (
+ gaussdev df t[] 0.0 $dM
+ set f = fraw + df
+ set df = $dM + zero(f)
+
+ periodogram_fm t f df 0.05 20.0 period_fm power_fm
+
+ gaussdev df t[] 0.0 $dM
+ set Fo = df
+ periodogram_fm t Fo df 0.05 20.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_fm power_fm
+ $peakval_fm = $peakval
+
+ peak -q period power
+
+# if (abs ($peakpos - $P) > 0.05)
+#   $PASS = 0
+# end
+
+ set freq = 1 / period
+ set freq_fm = 1 / period_fm
+ $Freq = 1 / $P
+
+ if ($PLOT)
+  if (1)
+    lim period_fm power_fm; clear; box
+    line -c red70 -lw 3 $P 0 to $P $peakval_fm;
+    plot period power -x line -c grey70 -lw 2
+    plot period_fm power_fm -x line -c black
+  else
+    lim freq power; clear; box
+    line -c red70 -lw 3 $Freq 0 to $Freq 1.0
+    plot freq power -x line -c grey70 -lw 2
+    plot freq_fm power_fm -x line -c black
+  end
+ end
+end
+
+# we have time (MJD) and mag
+# we generate the folded lightcure and measure sigma relative to the smoothed version (bins of 0.1 period)
+macro fold.one.period
+  if ($0 != 5)
+    echo "USAGE: fold.one.period (time) (mag) (magErr) (period)"
+    break
+  end
+
+  local myTime myMag myMagErr myPeriod
+  $myTime = $1
+  $myMag  = $2
+  $myMagErr  = $3
+  $myPeriod = $4
+
+  set phi = $myTime / $myPeriod - int($myTime / $myPeriod)
+
+  if ($PLOT_FOLD)
+    lim -n phi phi $myMag; clear; box; 
+  end
+
+  delete -q magResid
+
+  $dPhi = 0.05; # half of bin size
+  create nphi $dPhi {1 + $dPhi} {2*$dPhi}
+  set magR = zero(nphi)
+  set magS = zero(nphi)
+  for i 0 nphi[]
+    subset tmp_mag_sub = $myMag where (phi >= nphi[$i] - $dPhi) && (phi < nphi[$i] + $dPhi)
+    vstat -q tmp_mag_sub
+    magR[$i] = $MEDIAN
+    magS[$i] = $SIGMA
+
+    set magDelta = tmp_mag_sub - $MEDIAN
+    concat magDelta magResid 
+
+    if ($PLOT_FOLD)
+      subset tmp_phi_sub = phi where (phi >= nphi[$i] - $dPhi) && (phi < nphi[$i] + $dPhi)
+      if ($i % 2)
+        plot tmp_phi_sub tmp_mag_sub -pt 7 -sz 3 -c blue -lw 2
+      else
+        plot tmp_phi_sub tmp_mag_sub -pt 7 -sz 3 -c red -lw 2
+      end
+    end  
+  end
+
+  if ($PLOT_FOLD)  
+    plot -pt 10 -sz 1.5 phi $myMag -dy $myMagErr
+    plot -pt 2 -sz 2.0 -c red nphi magR -dy magS
+  end
+
+  vstat -q magResid
+end
+
+
 
 # Memory test
@@ -298,5 +545,5 @@
 
  for i 0 100
-  periodogram_fm t f 2 30 period power
+  periodogram_fm t f df 2 30 period power
  end
   
Index: trunk/Ohana/src/opihi/cmd.data/test/periodogram.sh
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/test/periodogram.sh	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.data/test/periodogram.sh	(revision 40291)
@@ -209,18 +209,19 @@
 # test using fewer random samples, high frequency, non-zero DC, some noise
 macro test8
- if ($0 != 2)
-   echo "USAGE: test8: Ndays")
+ if ($0 != 4)
+   echo "USAGE: test8: Period Ndays df"
    break
  end
  
  local Ndays 
- $Ndays = $1
-
- $PASS = 1
- break -auto off
-
- local P PI
- $PI = 3.14159265359
- $P  = 0.8*rnd(0) + 0.2
+ $P = $1
+ $Ndays = $2
+ $dM = $3
+
+ $PASS = 1
+ break -auto off
+
+ local PI
+ $PI = 3.14159265359
  $trueP = $P
 
@@ -230,7 +231,7 @@
 
  # 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 tday = int(100 * rnd(x)); # choose Ndays random days between 0 and 100
+ set dtx = (3/24) * rnd(x);  # choose a starting time within that night
+ set t0 = tday + dtx
 
  set dt1 = (15.0 / 1440) * rnd(x) + ( 0 + 7.5) / 1440
@@ -244,9 +245,9 @@
  set tmp = t0 + dt3; concat tmp t
 
- set fraw = sin(2*$PI*t/$P) + 0.5
+ set fraw = 0.75*sin(2*$PI*t/$P)
 
  # 0.05 : peakpos = 14.95
  # 0.10 : peakpos = 15.04 (
- gaussdev df t[] 0.0 0.25
+ gaussdev df t[] 0.0 $dM
  set f = fraw + df
 
@@ -260,4 +261,7 @@
  if (abs ($peakpos - $P) > 0.05)
    $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
Index: trunk/Ohana/src/opihi/cmd.data/test/uniqpair.sh
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/test/uniqpair.sh	(revision 40291)
+++ trunk/Ohana/src/opihi/cmd.data/test/uniqpair.sh	(revision 40291)
@@ -0,0 +1,83 @@
+
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if uniqpair works
+macro test1
+
+ $PASS = 1
+
+ local i
+
+ delete ID1 ID2
+
+ vlist -int ID1 1   1   2   3   3   4   5   6
+ vlist -int ID2 2   3   4   5   5   6   7   8
+
+ uniqpair ID1 ID2 IDu -c IDn -d index
+
+ # if ((xvec[1024] != 17) || (yvec[1024] != 100))
+ #  $PASS = 0
+ #  echo "Value mismatch: xvec[1024] yvec[1024] (should be 17,100)"
+ # end
+ # 
+ # imhist -q buff xvec yvec -region 40 0 25 10 -range 0 10
+ # 
+ # if ((xvec[1024] != 10) || (yvec[1024] != 100))
+ #  $PASS = 0
+ #  echo "Value mismatch: xvec[1024] yvec[1024] (should be 10,100)"
+ # end
+
+end
+
+# Test if uniqpair works
+macro test2
+
+ $PASS = 1
+
+ delete ID1 ID2
+
+ vlist -int ID1 {2^16 + 2} {2^17}     {2^18 + 3} {2^16 + 2} {2^17 + 2} {2^18 + 3} 
+ vlist -int ID2 {2^16 + 0} {2^17 + 2} {2^18 + 5} {2^16 + 0} {2^17 + 2} {2^18 + 5} 
+
+ uniqpair ID1 ID2 IDu -c IDn -d index
+
+ reindex ID2s = ID2 using index
+ reindex ID1s = ID1 using index
+
+ vectors
+
+ echo "unique"
+ print_v IDu IDn
+
+ echo "dups"
+ print_v ID1s ID2s index
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  imhist -q buff xvec yvec -region 40 0 25 10 -range 0 10
+ end
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: trunk/Ohana/src/opihi/cmd.data/uniq.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/uniq.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.data/uniq.c	(revision 40291)
@@ -80,5 +80,5 @@
     memcpy (indata, ivec->elements.Int, ivec[0].Nelements*sizeof(opihi_int));
 
-    isort (indata, ivec->Nelements);
+    llsort (indata, ivec->Nelements);
 
     Nnew = 0;
Index: trunk/Ohana/src/opihi/cmd.data/uniqpair.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/uniqpair.c	(revision 40291)
+++ trunk/Ohana/src/opihi/cmd.data/uniqpair.c	(revision 40291)
@@ -0,0 +1,146 @@
+# include "data.h"
+
+/* given two 32bit IDs, a 64bit joint ID and sort it, along with an index (sequence) vector */ 
+int uniqpair (int argc, char **argv) {
+
+  int N;
+  Vector *ID1vec = NULL, *ID2vec = NULL, *OUTvec = NULL;
+
+  int VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  Vector *SEQdup = NULL;
+  if ((N = get_argument (argc, argv, "-d"))) {
+    remove_argument (N, &argc, argv);
+    if ((SEQdup = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) {
+      gprint (GP_ERR, "invalid vector %s\n", "SEQdups");
+      return FALSE;
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  Vector *CNTvec = NULL;
+  if ((N = get_argument (argc, argv, "-c"))) {
+    remove_argument (N, &argc, argv);
+    if ((CNTvec = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) {
+      gprint (GP_ERR, "invalid vector %s\n", argv[N]);
+      return FALSE;
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: uniqpair (ID1) (ID2) (IDout) [-c count] [-d dupindex]\n");
+    gprint (GP_ERR, "  merge ID1 and ID2 (32 bit int values) into a single index and find unique entries\n");
+    gprint (GP_ERR, "  -c count: save the number of each unique entry in the count vector\n");
+    gprint (GP_ERR, "  -d dupindex: save the sequence number of duplicate entries in the dupindex vector\n");
+    return (FALSE);
+  }
+
+  if ((ID1vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ID2vec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((OUTvec = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if ((ID1vec->type == OPIHI_FLT) || (ID2vec->type == OPIHI_FLT)) {
+    gprint (GP_ERR, "ERROR: ID vectors much be int\n");
+    return (FALSE);
+  }
+  if (ID1vec->Nelements != ID2vec->Nelements) {
+    gprint (GP_ERR, "ERROR: ID vectors not all the same length\n");
+    return (FALSE);
+  }
+
+  // storage for the output and count vectors
+  int D_NOUT = 0.02*ID1vec->Nelements;
+
+  int Nout = 0;
+  int NOUT = D_NOUT;
+  ResetVector (OUTvec, OPIHI_INT, NOUT);
+  if (CNTvec) {
+    ResetVector (CNTvec, OPIHI_INT, NOUT);
+  }
+
+  // storage for the duplicate sequences
+  int NseqDup = 0;
+  int NSEQDUP = 10000;
+  if (SEQdup) {
+    ResetVector (SEQdup, OPIHI_INT, NSEQDUP);
+  }
+  
+  // incrementing pointers to the input IDs
+  opihi_int *ID1 = ID1vec->elements.Int;
+  opihi_int *ID2 = ID2vec->elements.Int;
+
+  // generate the joined and sequence vectors
+  opihi_int *IDfull = NULL;
+  opihi_int *SEQdata = NULL;
+  ALLOCATE (IDfull, opihi_int, ID1vec->Nelements);
+  ALLOCATE (SEQdata, opihi_int, ID1vec->Nelements);
+  for (int i = 0; i < ID1vec->Nelements; i++) {
+    IDfull[i] = ID1[i] + (ID2[i] << 32);
+    SEQdata[i] = i;
+  }
+
+  // XXX watch out: this all needs to get rationalized...
+  llsortpair ((off_t *)IDfull, (off_t *)SEQdata, ID1vec->Nelements);
+
+  opihi_int *vtgt = OUTvec->elements.Int;
+  opihi_int *vsrc = IDfull;
+
+  int onePercent = ID1vec->Nelements / 100;
+
+  struct sigaction *old_sigaction = SetInterrupt();
+  for (int i = 0; (i < ID1vec->Nelements) && !interrupt; Nout++) {
+    if (Nout >= NOUT) {
+      NOUT += D_NOUT;
+      REALLOCATE (vtgt, opihi_int, NOUT);
+      if (CNTvec) {
+	REALLOCATE (CNTvec->elements.Int, opihi_int, NOUT);
+      }
+    }
+    vtgt[Nout] = *vsrc;
+    int Ndup = 0;
+    opihi_int lastValue = *vsrc;
+    while ((i < ID1vec->Nelements) && (*vsrc == lastValue)) {
+      i++;
+      vsrc ++;
+      Ndup ++;
+      if (VERBOSE && (i % onePercent == 0)) gprint (GP_ERR, ".");
+    }
+    if (CNTvec) {
+      CNTvec->elements.Int[Nout] = Ndup;
+    }
+    if (SEQdup && (Ndup > 1)) {
+      // we want to save SEQdata values for the duplicates
+      // SEQdata[i-Ndup] .. SEQdata[i-N
+      for (int j = i - Ndup; j < i; j++) {
+	SEQdup->elements.Int[NseqDup] = SEQdata[j];
+	NseqDup ++;
+	if (NseqDup >= NSEQDUP) {
+	  NSEQDUP += 10000;
+	  REALLOCATE (SEQdup->elements.Int, opihi_int, NSEQDUP);
+	}
+      }
+    }
+  }
+  ClearInterrupt (old_sigaction);
+  if (VERBOSE) gprint (GP_ERR, "\n");
+
+  free (SEQdata);
+  free (IDfull);
+
+  if (SEQdup) {
+    SEQdup->Nelements = NseqDup;
+    REALLOCATE (SEQdup->elements.Int, opihi_int, NseqDup);
+  }
+
+  // fix references and free up extra memory:
+  OUTvec->elements.Int = vtgt;
+  ResetVector (OUTvec, OPIHI_INT, Nout);
+  if (CNTvec) ResetVector (CNTvec, OPIHI_INT, Nout);
+
+  return (TRUE);
+}
Index: trunk/Ohana/src/opihi/cmd.data/write_vectors.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 40165)
+++ trunk/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 40291)
@@ -165,7 +165,7 @@
 	} else {
 	  if (CSV) {
-	    fprintf (f, "%d,", vec[j][0].elements.Int[i]);
+	    fprintf (f, OPIHI_INT_FMT",", vec[j][0].elements.Int[i]);
 	  } else {
-	    fprintf (f, "%d ", vec[j][0].elements.Int[i]);
+	    fprintf (f, OPIHI_INT_FMT" ", vec[j][0].elements.Int[i]);
 	  }
 	}
Index: trunk/Ohana/src/opihi/dvo/dvo_host_utils.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/dvo_host_utils.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/dvo_host_utils.c	(revision 40291)
@@ -284,5 +284,5 @@
     // XXX a bit of a waste (but only 1024 * 60 bytes or so
     ALLOCATE (table->hosts[i].results, char, DVO_MAX_PATH);
-    snprintf (table->hosts[i].results, DVO_MAX_PATH, "%s/dvo.results.%s.fits", table->hosts[i].pathname, uniquer);
+    snprintf (table->hosts[i].results, DVO_MAX_PATH, "%s/dvo.results.%s.%04d.fits", table->hosts[i].pathname, uniquer, table->hosts[i].hostID);
 
     int    Ninvec = 0;
Index: trunk/Ohana/src/opihi/dvo/gimages.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/gimages.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/gimages.c	(revision 40291)
@@ -214,9 +214,9 @@
     if (PixelCoords) {
       gprint (GP_LOG, "%3d %5d %s %6.1f %6.1f %20s %5d %2d %4.2f %6.3f %5.3f %5.3f %4x %7d\n", 
-	      Nfound, (int) i, image[i].name, X, Y, date, image[i].nstar, image[i].photcode, image[i].secz, image[i].Mcal, image[i].dMcal, image[i].exptime, image[i].flags, image[i].imageID);
+	      Nfound, (int) i, image[i].name, X, Y, date, image[i].nstar, image[i].photcode, image[i].secz, image[i].McalPSF, image[i].dMcal, image[i].exptime, image[i].flags, image[i].imageID);
     } else {
       XY_to_RD (&ra, &dec, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
       gprint (GP_LOG, "%3d %5d %s %8.4f %8.4f %20s %5d %2d %4.2f %6.3f %5.3f %5.3f %4x %7d\n", 
-	      Nfound, (int) i, image[i].name, ra, dec, date, image[i].nstar, image[i].photcode, image[i].secz, image[i].Mcal, image[i].dMcal, image[i].exptime, image[i].flags, image[i].imageID);
+	      Nfound, (int) i, image[i].name, ra, dec, date, image[i].nstar, image[i].photcode, image[i].secz, image[i].McalPSF, image[i].dMcal, image[i].exptime, image[i].flags, image[i].imageID);
     }
     sprintf (name, "IMAGEx:%d", Nfound);
Index: trunk/Ohana/src/opihi/dvo/gstar.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/gstar.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/gstar.c	(revision 40291)
@@ -760,8 +760,11 @@
 
 	    if (FULL_OUTPUT) {
-	      gprint (GP_LOG, "%6.3f ", catalog.measure[Nv].Mcal);
+	      gprint (GP_LOG, "%6.3f ", catalog.measure[Nv].McalPSF);
+	      gprint (GP_LOG, "%6.3f ", catalog.measure[Nv].McalAPER);
 	      gprint (GP_LOG, "%6.3f ", catalog.measure[Nv].Mflat);
-	      gprint (GP_LOG, "%6.3f ", catalog.measure[Nv].Map);
-	      gprint (GP_LOG, "%6.3f ", catalog.measure[Nv].Mkron);
+	      Mrel = PhotRel (&catalog.measure[Nv], &catalog.average[k], &catalog.secfilt[k*Nsecfilt], MAG_CLASS_APER);
+	      gprint (GP_LOG, "%6.3f ", Mrel);
+	      Mrel = PhotRel (&catalog.measure[Nv], &catalog.average[k], &catalog.secfilt[k*Nsecfilt], MAG_CLASS_KRON);
+	      gprint (GP_LOG, "%6.3f ", Mrel);
 	      gprint (GP_LOG, "%6.3f ", catalog.measure[Nv].dMkron);
 	      gprint (GP_LOG, "%5.1f ", pow(10.0, 0.4*catalog.measure[Nv].dt));
@@ -960,5 +963,5 @@
 	print_double (NAN);
       } else {
-	print_double_exp (secfilt[seq].Mstdev);
+	print_double_exp (secfilt[seq].sMpsfChp);
       }
       break;
@@ -1023,5 +1026,5 @@
 	print_double (NAN);
       } else {
-	print_double (secfilt[seq].M);
+	print_double (secfilt[seq].MpsfChp);
       }
       break;
@@ -1031,5 +1034,5 @@
 	print_double (NAN);
       } else {
-	print_double (secfilt[seq].dM);
+	print_double (secfilt[seq].dMpsfChp);
       }
       break;
@@ -1039,5 +1042,5 @@
 	print_double (NAN);
       } else {
-	print_double (secfilt[seq].Map);
+	print_double (secfilt[seq].MapChp);
       }
       break;
@@ -1047,5 +1050,5 @@
 	print_double (NAN);
       } else {
-	print_double (secfilt[seq].dMap);
+	print_double (secfilt[seq].dMapChp);
       }
       break;
@@ -1055,5 +1058,5 @@
 	print_double (NAN);
       } else {
-	print_double_exp (secfilt[seq].sMap);
+	print_double_exp (secfilt[seq].sMapChp);
       }
       break;
@@ -1063,5 +1066,5 @@
 	print_double (NAN);
       } else {
-	print_double_exp (secfilt[seq].dMap);
+	print_double_exp (secfilt[seq].dMapChp);
       }
       break;
@@ -1071,5 +1074,5 @@
 	print_double (NAN);
       } else {
-	print_double (secfilt[seq].Mkron);
+	print_double (secfilt[seq].MkronChp);
       }
       break;
@@ -1079,5 +1082,5 @@
 	print_double (NAN);
       } else {
-	print_double (secfilt[seq].dMkron);
+	print_double (secfilt[seq].dMkronChp);
       }
       break;
@@ -1087,5 +1090,5 @@
 	print_double (NAN);
       } else {
-	print_double_exp (secfilt[seq].sMkron);
+	print_double_exp (secfilt[seq].sMkronChp);
       }
       break;
@@ -1095,5 +1098,5 @@
 	print_double (NAN);
       } else {
-	print_double_exp (secfilt[seq].dMkron);
+	print_double_exp (secfilt[seq].dMkronChp);
       }
       break;
Index: trunk/Ohana/src/opihi/dvo/imdata.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/imdata.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/imdata.c	(revision 40291)
@@ -183,5 +183,5 @@
 	for (i = 0; i < catalog.Nmeasure; i++) {
 	  if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
-	  vec[0].elements.Flt[N] = catalog.measure[i].Mcal;
+	  vec[0].elements.Flt[N] = catalog.measure[i].McalPSF;
 	  N++;
 	  CHECK_REALLOCATE (vec[0].elements.Flt, opihi_flt, NPTS, N, 1000);
Index: trunk/Ohana/src/opihi/dvo/imlist.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/imlist.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/imlist.c	(revision 40291)
@@ -141,5 +141,5 @@
     if (VERBOSE) {
       gprint (GP_LOG, "%3lld %s %8lld %8.4f %8.4f %f %5d %2d %4.2f %5.3f %5.3f", 
-			 (long long) i, image[i].name, (long long) image[i].imageID, r, d, t, image[i].nstar, image[i].photcode, image[i].secz, image[i].Mcal, image[i].dMcal);
+			 (long long) i, image[i].name, (long long) image[i].imageID, r, d, t, image[i].nstar, image[i].photcode, image[i].secz, image[i].McalPSF, image[i].dMcal);
 
       if (showUR) {
Index: trunk/Ohana/src/opihi/dvo/imphot.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/imphot.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/imphot.c	(revision 40291)
@@ -64,5 +64,5 @@
       for (x = 0; x < 100; x+=1.0, p++) {
 	// *p = applyMcal (&image[subset[0]], (fx*x), (fy*y));
-	*p = image[subset[0]].Mcal;
+	*p = image[subset[0]].McalPSF;
       }
     }
@@ -71,5 +71,5 @@
   for (j = 0; j < Nsubset; j++) {
     i = subset[j];
-    gprint (GP_ERR, "%s: %f\n", image[i].name, image[i].Mcal);
+    gprint (GP_ERR, "%s: %f\n", image[i].name, image[i].McalPSF);
 
 // XXX old code when we had the option of a 2D zero point model
@@ -77,18 +77,18 @@
     switch (image[i].order) {
     case 0:
-      gprint (GP_ERR, "%s: %d - %f\n", image[i].name, image[i].order, image[i].Mcal);
+      gprint (GP_ERR, "%s: %d - %f\n", image[i].name, image[i].order, image[i].McalPSF);
       break;
     case 1:
-      gprint (GP_ERR, "%s: %d - %f, %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My);
+      gprint (GP_ERR, "%s: %d - %f, %d %d\n", image[i].name, image[i].order, image[i].McalPSF, image[i].Mx, image[i].My);
       break;
     case 2:
-      gprint (GP_ERR, "%s: %d - %f, %d %d, %d %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My, image[i].Mxx, image[i].Mxy, image[i].Myy);
+      gprint (GP_ERR, "%s: %d - %f, %d %d, %d %d %d\n", image[i].name, image[i].order, image[i].McalPSF, image[i].Mx, image[i].My, image[i].Mxx, image[i].Mxy, image[i].Myy);
       break;
     case 3:
-      gprint (GP_ERR, "%s: %d - %f, %d %d, %d %d %d, %d %d %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My, 
+      gprint (GP_ERR, "%s: %d - %f, %d %d, %d %d %d, %d %d %d %d\n", image[i].name, image[i].order, image[i].McalPSF, image[i].Mx, image[i].My, 
 	       image[i].Mxx, image[i].Mxy, image[i].Myy, image[i].Mxxx, image[i].Mxxy, image[i].Mxyy, image[i].Myyy);
       break;
     case 4:
-      gprint (GP_ERR, "%s: %d - %f, %d %d, %d %d %d, %d %d %d %d, %d %d %d %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My, 
+      gprint (GP_ERR, "%s: %d - %f, %d %d, %d %d %d, %d %d %d %d, %d %d %d %d %d\n", image[i].name, image[i].order, image[i].McalPSF, image[i].Mx, image[i].My, 
 	       image[i].Mxx, image[i].Mxy, image[i].Myy, image[i].Mxxx, image[i].Mxxy, image[i].Mxyy, image[i].Myyy,
 	       image[i].Mxxxx, image[i].Mxxxy, image[i].Mxxyy, image[i].Mxyyy, image[i].Myyyy);
Index: trunk/Ohana/src/opihi/dvo/imstats.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/imstats.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/imstats.c	(revision 40291)
@@ -41,5 +41,5 @@
     Xvec.elements.Flt[i] = image[i].secz;
     if (Mcal) 
-      Yvec.elements.Flt[i] = image[i].Mcal;
+      Yvec.elements.Flt[i] = image[i].McalPSF;
     else 
       Yvec.elements.Flt[i] = image[i].dMcal;
@@ -47,5 +47,5 @@
     gprint (GP_ERR, "%d %8.4f %8.4f %10d %6d  %5.3f %6.3f %6.3f\n", 
 	     i, r, d, image[i].tzero, image[i].nstar, Xvec.elements.Flt[i], 
-	     image[i].Mcal, image[i].dMcal);
+	     image[i].McalPSF, image[i].dMcal);
   } 
   if (AutoLimits) SetLimits (&Xvec, &Yvec, &graphmode);
Index: trunk/Ohana/src/opihi/dvo/objectcoverage.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/objectcoverage.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/objectcoverage.c	(revision 40291)
@@ -203,5 +203,5 @@
 	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)));
+	invalid = ((catalog.secfilt[j*Nsecfilt + Nsec].MpsfChp < 1.0) || (isnan(catalog.secfilt[j*Nsecfilt + Nsec].MpsfChp)));
 	if (invalid) continue;
 	
Index: trunk/Ohana/src/opihi/dvo/paverage.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/paverage.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/paverage.c	(revision 40291)
@@ -125,5 +125,5 @@
       while (average[i].R > Rmax) average[i].R -= 360.0;
 
-      mag = secfilt[i*Nsecfilt+Nsec].M;
+      mag = secfilt[i*Nsecfilt+Nsec].MpsfChp;
       Zvec[Npts] = MIN (1.0, MAX (0.01, (mag - Mz) / Mr));
       if (LimExclude && (Zvec[Npts] > 0.99)) continue;
Index: trunk/Ohana/src/opihi/dvo/remote.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/remote.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/remote.c	(revision 40291)
@@ -27,5 +27,8 @@
     gprint (GP_ERR, "  -skip-result : do not try to read from the result file\n");
     gprint (GP_ERR, "OR:    remote -reload (uniquer)\n");
+    gprint (GP_ERR, "       (reloads the remote host results into vectors as if a parallel command were run)\n");
     gprint (GP_ERR, "OR:    remote -get-results (uniquer)\n");
+    gprint (GP_ERR, "       (generates the list of remote result filenames and status variables)\n");
+    gprint (GP_ERR, "       (RESULT_FILE:i is the filenme, RESULT_STATUS:i is the dvo_client exit status)\n");
     return FALSE;
   }
Index: trunk/Ohana/src/opihi/dvo/skycoverage.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/skycoverage.c	(revision 40165)
+++ trunk/Ohana/src/opihi/dvo/skycoverage.c	(revision 40291)
@@ -330,8 +330,8 @@
 	      break;
 	    case MIN_MCAL:
-	      V[ys*Nx + xs] = MIN(V[ys*Nx + xs], image[i].Mcal);
+	      V[ys*Nx + xs] = MIN(V[ys*Nx + xs], image[i].McalPSF);
 	      break;
 	    case MAX_MCAL:
-	      V[ys*Nx + xs] = MAX(V[ys*Nx + xs], image[i].Mcal);
+	      V[ys*Nx + xs] = MAX(V[ys*Nx + xs], image[i].McalPSF);
 	      break;
 	    case MIN_TIME: {
Index: trunk/Ohana/src/opihi/include/astro.h
===================================================================
--- trunk/Ohana/src/opihi/include/astro.h	(revision 40165)
+++ trunk/Ohana/src/opihi/include/astro.h	(revision 40291)
@@ -47,7 +47,7 @@
 double VectorFractionInterpolate (double *values, float fraction, int Npts);
 
-int PlxSetMeanEpoch (double *R, double *D, double *T, double *Rmean, double *Dmean, double *Tmean, int *mask, int Ntotal);
-int PlxSetEpochPosition (PlxFitData *fitdata, double *R, double *D, double *dR, double *dD, double *T, int *mask, int Ntotal, Coords *coords, double Tmean);
-int PlxOutlierClip (PlxFitData *fitdata, int *mask, int Noutlier, float dPsigMax, Vector *dPvec, int VERBOSE);
+int PlxSetMeanEpoch (double *R, double *D, double *T, double *Rmean, double *Dmean, double *Tmean, opihi_int *mask, int Ntotal);
+int PlxSetEpochPosition (PlxFitData *fitdata, double *R, double *D, double *dR, double *dD, double *T, opihi_int *mask, int Ntotal, Coords *coords, double Tmean);
+int PlxOutlierClip (PlxFitData *fitdata, opihi_int *mask, int Noutlier, float dPsigMax, Vector *dPvec, int VERBOSE);
 
 int PlxFitDataAlloc (PlxFitData *data, int N);
Index: trunk/Ohana/src/opihi/include/data.h
===================================================================
--- trunk/Ohana/src/opihi/include/data.h	(revision 40165)
+++ trunk/Ohana/src/opihi/include/data.h	(revision 40291)
@@ -162,4 +162,6 @@
 /* starfuncs.c */
 double get_aperture_stats (Matrix *matrix, int X, int Y, int Npix, int Nborder, double max, int VERBOSE);
+double get_box_stats (Matrix *matrix, int X, int Y, int dX, int dY, int Nborder, double max, int VERBOSE);
+
 int set_rough_radii (double Ra, double Ri, double Ro);
 int get_rough_star (float *data, int Nx, int Ny, int x, int y, opihi_flt *xc, opihi_flt *yc, opihi_flt *sx, opihi_flt *sy, opihi_flt *sxy, opihi_flt *zs, opihi_flt *zp, opihi_flt *sk);
Index: trunk/Ohana/src/opihi/lib.data/graphtools.c
===================================================================
--- trunk/Ohana/src/opihi/lib.data/graphtools.c	(revision 40165)
+++ trunk/Ohana/src/opihi/lib.data/graphtools.c	(revision 40291)
@@ -10,5 +10,5 @@
   if (xvec != NULL) {
     if (xvec->type == OPIHI_FLT) {
-      maxX = DBL_MIN;
+      maxX = -DBL_MAX;
       minX = DBL_MAX;
       for (i = 0; i < xvec[0].Nelements; i++) {
@@ -33,5 +33,5 @@
   if (yvec != NULL) {
     if (yvec->type == OPIHI_FLT) {
-      maxY = DBL_MIN;
+      maxY = -DBL_MAX;
       minY = DBL_MAX;
       for (i = 0; i < yvec[0].Nelements; i++) {
Index: trunk/Ohana/src/opihi/lib.data/starfuncs.c
===================================================================
--- trunk/Ohana/src/opihi/lib.data/starfuncs.c	(revision 40165)
+++ trunk/Ohana/src/opihi/lib.data/starfuncs.c	(revision 40291)
@@ -101,4 +101,118 @@
 }
 
+double get_box_stats (Matrix *matrix, int X, int Y, int dX, int dY, int Nborder, double max, int VERBOSE) {
+
+  double *ring;
+  double x, y, x2, y2, xy, I, sky, FWHMx, FWHMy, value, mag, Sxy;
+  int i, j, n, Nring, Nmax;
+  double Npts, gain, dsky2, dmag, peak, offset;
+  char *string;
+  
+  string = get_variable ("GAIN");
+  if (string == (char *) NULL) {
+    gprint (GP_ERR, "assuming a value of 1.0\n");
+    gain = 1.0;
+  } else {
+    gain = atof (string);
+  }
+  Nborder = MAX (1, Nborder);
+  Nborder = MIN (1000, Nborder);
+  
+  int dX2 = (int)(0.5*dX);
+  int dY2 = (int)(0.5*dY);
+  dX = 2 * dX2 + 1;
+  dY = 2 * dY2 + 1;
+
+  Nring = 2*Nborder*(dX + 2*Nborder) + 2*Nborder*(dY + 2*Nborder);
+  ALLOCATE (ring, double, Nring);
+  bzero (ring, sizeof(double)*Nring);
+
+  // get the pixels in the border regions:
+  // XXX gfits_get_matrix_value returns 0 for out-of-bounds pixels, but should return NAN
+  // and they should be skipped
+  n = 0;  
+  for (j = 0; j < Nborder; j++) {
+    for (i = X - dX2 - Nborder; i < X + dX2 + Nborder + 1; i++) {
+      value = gfits_get_matrix_value (matrix, i, (int)(Y - dY2 - j));
+      if (isfinite(value)) { ring[n] = value; n++; }
+      value = gfits_get_matrix_value (matrix, i, (int)(Y + dY2 + j));
+      if (isfinite(value)) { ring[n] = value; n++; }
+    }
+    for (i = Y - dY2; i < Y + dY2 + 1; i++) {
+      value = gfits_get_matrix_value (matrix, (int)(X - dX2 - j), i);
+      if (isfinite(value)) { ring[n] = value; n++; }
+      value = gfits_get_matrix_value (matrix, (int)(X + dX2 + j), i);
+      if (isfinite(value)) { ring[n] = value; n++; }
+    }
+  }
+  Nring = n;
+  dsort (ring, Nring);
+  for (Npts = sky = dsky2 = 0, i = 0.25*Nring; i < 0.75*Nring; i++, Npts += 1.0) {
+    sky += ring[i];
+    dsky2 += ring[i]*ring[i];
+  }
+  sky = sky / Npts;
+  dsky2 = dsky2 / Npts - sky*sky;
+  free (ring);
+
+  float dx, dy;
+
+  peak = 0;
+  Npts = Nmax = 0;
+  x = y = x2 = y2 = xy = I = 0;
+  for (i = X - dX2; i < X + dX2 + 1; i++) {
+    for (j = Y - dY2; j < Y + dY2 + 1; j++) {
+      value = gfits_get_matrix_value (matrix, i, j);
+      if (!isfinite(value)) continue;
+      offset = value - sky;
+      dx = i - X;
+      dy = j - Y;
+      x  += dx*offset;
+      y  += dy*offset;
+      x2 += dx*dx*offset;
+      y2 += dy*dy*offset;
+      xy += dx*dy*offset;
+      I  += offset;
+      Npts ++;
+      if (value > max) {
+	Nmax ++;
+      }
+      if (value > peak) peak = value;
+    }
+  }
+
+  x = x / I;
+  y = y / I;
+  FWHMx = 2.355*sqrt (fabs(x2 / I - x*x));
+  FWHMy = 2.355*sqrt (fabs(y2 / I - y*y));
+  Sxy   = xy / I - x*y;
+  mag = -2.5*log10(I);
+
+  // flux_error = sqrt( I + Npts*dsky2 )
+  // dmag = 1.086 * flux_error / flux
+  dmag = 1.086 * sqrt (fabs(I + Npts*dsky2)) / (gain * I);
+  x = x + X;
+  y = y + Y;
+  
+  set_variable ("Xg", x);
+  set_variable ("Yg", y);
+  set_variable ("SXg", FWHMx);
+  set_variable ("SYg", FWHMy);
+  set_variable ("SXYg", Sxy);
+  set_variable ("Sg", sky);
+  set_variable ("dSg", sqrt (fabs (dsky2)));
+  set_variable ("Zg", mag);
+  set_variable ("dZg", dmag);
+  set_variable ("Zcg", I);
+  set_variable ("Zpk", peak);
+  set_int_variable ("Nsat", Nmax);
+  set_int_variable ("Npts", Npts);
+  
+  if (VERBOSE) gprint (GP_LOG, "%f %f %f %f %f %f %f %f\n", x, y, FWHMx, FWHMy, sky, I, mag, dmag);
+
+  return (mag);
+
+}
+
 static double Raper  =  5;
 static double Rinner = 10;
Index: trunk/Ohana/src/opihi/lib.shell/VectorIO.c
===================================================================
--- trunk/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 40165)
+++ trunk/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 40291)
@@ -41,5 +41,5 @@
     for (j = 0; j < Nvec; j++) {
       // if the format is not defined, just use the native byte-widths
-      tformat[2*j + 0] = (vec[j][0].type == OPIHI_FLT) ? 'D' : 'J';
+      tformat[2*j + 0] = (vec[j][0].type == OPIHI_FLT) ? 'D' : 'K'; // this depends on opihi_int == int64_t for Int
       tformat[2*j + 1] = 0;
     }
@@ -60,7 +60,8 @@
   for (j = 0; j < Nvec; j++) {
     if (vec[j][0].type == OPIHI_FLT) {
-      gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "double", vec[j][0].elements.Flt, vec[j][0].Nelements, nativeOrder);
+      gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "double",  vec[j][0].elements.Flt, vec[j][0].Nelements, nativeOrder);
     } else {
-      gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "int", vec[j][0].elements.Int, vec[j][0].Nelements, nativeOrder);
+//    gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "int",     vec[j][0].elements.Int, vec[j][0].Nelements, nativeOrder);
+      gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "int64_t", vec[j][0].elements.Int, vec[j][0].Nelements, nativeOrder);
     }
   }
@@ -328,5 +329,6 @@
   ASSIGN_DATA(short,   short,   Int);
   ASSIGN_DATA(int,     int,     Int);
-  ASSIGN_DATA(int64_t, int64_t, Flt); // int64_t has a problem: Int is too small, Flt is wrong precision
+  ASSIGN_DATA(int64_t, int64_t, Int); // XXX this works if opihi_int is assigned to int64_t
+//ASSIGN_DATA(int64_t, int64_t, Flt); // int64_t has a problem: Int is too small, Flt is wrong precision
   ASSIGN_DATA(float,   float,   Flt);
   ASSIGN_DATA(double,  double,  Flt);
@@ -353,5 +355,6 @@
   ASSIGN_DATA_TRANSPOSE(short,   short,   Int);
   ASSIGN_DATA_TRANSPOSE(int,     int,     Int);
-  ASSIGN_DATA_TRANSPOSE(int64_t, int64_t, Flt);
+  ASSIGN_DATA_TRANSPOSE(int64_t, int64_t, Int);
+//ASSIGN_DATA_TRANSPOSE(int64_t, int64_t, Flt); // see above comment
   ASSIGN_DATA_TRANSPOSE(float,   float,   Flt);
   ASSIGN_DATA_TRANSPOSE(double,  double,  Flt);
Index: trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c
===================================================================
--- trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 40165)
+++ trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 40291)
@@ -120,5 +120,4 @@
 	Nop_stack ++;
 	break;
-      case ST_UNARY: 
       case ST_BINARY: 
       case ST_TRINARY:
@@ -139,4 +138,5 @@
 	Nop_stack ++;
 	break;
+      case ST_UNARY: 
       case ST_LEFT:  
 	/* push operator on OP stack */
Index: trunk/Ohana/src/opihi/lib.shell/dvomath.c
===================================================================
--- trunk/Ohana/src/opihi/lib.shell/dvomath.c	(revision 40165)
+++ trunk/Ohana/src/opihi/lib.shell/dvomath.c	(revision 40291)
@@ -29,4 +29,8 @@
   unsigned int Ncstack;
   cstack = isolate_elements (argc, argv, &Ncstack); 
+
+  // for (i = 0; i < Ncstack; i++) {
+  //   fprintf (stderr, "%d : %s\n", i, cstack[i]);
+  // }
 
   /* generate RPN stack from cstack arguments */
@@ -82,5 +86,5 @@
       } else {
 	if (stack[0].type == ST_SCALAR_INT) {
-	  sprintf (outname, "%d", stack[0].IntValue);
+	  sprintf (outname, OPIHI_INT_FMT, stack[0].IntValue);
 	} else {
 	  sprintf (outname, "%.12g", stack[0].FltValue);
Index: trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c
===================================================================
--- trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 40165)
+++ trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 40291)
@@ -89,5 +89,5 @@
       }
       if (tmp_stack.type == ST_SCALAR_INT) {
-	gprint (GP_ERR, "---> %d ", tmp_stack.IntValue);
+	gprint (GP_ERR, "---> "OPIHI_INT_FMT" ", tmp_stack.IntValue);
       }
       if (tmp_stack.type == ST_SCALAR_FLT) {
@@ -110,5 +110,5 @@
 
 	if (i < 3) {  /* need two variables to operate on */
-	  snprintf (line, 512, "syntax error: trinary operator without three operands: %s\n", stack[i].name);
+	  snprintf (line, 512, "syntax error: trinary operator without three operands: %s\n(Note that the : in a trinary operation must be protected by spaces", stack[i].name);
 	  push_error (line);
 	  clear_stack (&tmp_stack);
@@ -124,5 +124,5 @@
 
 	/* there are no valid unary string operators */
-	snprintf (line, 512, "invalid operands for trinary operator %s (mismatch types?)", stack[i].name);
+	snprintf (line, 512, "invalid operands for trinary operator %s (mismatch types?)\n(Note that the : in a trinary operation must be protected by spaces)", stack[i].name);
 	push_error (line);
 	clear_stack (&tmp_stack);
@@ -131,5 +131,5 @@
       got_three_op:
 	if (!status) {
-	  snprintf (line, 512, "syntax error: invalid operand for trinary operation: %s or %s or %s\n", stack[i-1].name, stack[i-2].name, stack[i-3].name);
+	  snprintf (line, 512, "syntax error: invalid operand for trinary operation: %s or %s or %s\n(Note that the : in a trinary operation must be protected by spaces)", stack[i-1].name, stack[i-2].name, stack[i-3].name);
 	  push_error (line);
 	  clear_stack (&tmp_stack);
@@ -188,4 +188,8 @@
 	  snprintf (line, 512, "syntax error: invalid operand for binary operation: %s or %s\n", stack[i-1].name, stack[i-2].name);
 	  push_error (line);
+	  if (strchr(stack[i-1].name, ':') || strchr(stack[i-2].name, ':')) {
+	    snprintf (line, 512, "syntax error: invalid operand for binary operation: %s or %s\n(Note that the : in a trinary operation must be protected by spaces)\n", stack[i-1].name, stack[i-2].name);
+	    push_error (line);
+	  }
 	  clear_stack (&tmp_stack);
 	  return (FALSE);
Index: trunk/Ohana/src/opihi/lib.shell/parse.c
===================================================================
--- trunk/Ohana/src/opihi/lib.shell/parse.c	(revision 40165)
+++ trunk/Ohana/src/opihi/lib.shell/parse.c	(revision 40291)
@@ -245,5 +245,5 @@
 	vec[0].elements.Flt[Nx] = atof (val);
       } else {
-	vec[0].elements.Int[Nx] = atol (val);
+	vec[0].elements.Int[Nx] = atoll (val);
       }
     }
