Index: trunk/Ohana/src/addstar/Makefile
===================================================================
--- trunk/Ohana/src/addstar/Makefile	(revision 39217)
+++ trunk/Ohana/src/addstar/Makefile	(revision 39225)
@@ -39,6 +39,6 @@
 # programs in 'SERVER' use the client-server concept and are out of date
 
-INSTALL = addstar sedstar loadgalphot loadstarpar loadstarpar_client loadICRF loadICRF_client skycells mkcmf dumpskycells findskycell load2mass loadwise loadtycho loadsupercos
-SERVER  = addstar_client addstarc addstard addstart
+INSTALL = addstar addstar_client sedstar loadgalphot loadstarpar loadstarpar_client loadICRF loadICRF_client skycells mkcmf dumpskycells findskycell load2mass loadwise loadtycho loadsupercos
+SERVER  = addstarc addstard addstart
 
 all: $(INSTALL)
Index: trunk/Ohana/src/dvomerge/Makefile
===================================================================
--- trunk/Ohana/src/dvomerge/Makefile	(revision 39217)
+++ trunk/Ohana/src/dvomerge/Makefile	(revision 39225)
@@ -125,4 +125,5 @@
 $(SRC)/dvorepairFixCPT.$(ARCH).o \
 $(SRC)/dvorepairFixWarpIDs.$(ARCH).o \
+$(SRC)/dvorepairFixStackIDs.$(ARCH).o \
 $(SRC)/dvorepairImagesVsMeasures.$(ARCH).o \
 $(SRC)/dvorepairDeleteImageList.$(ARCH).o \
@@ -171,7 +172,9 @@
 $(SRC)/SetSignals.$(ARCH).o \
 $(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/LoadImages.$(ARCH).o \
 $(SRC)/dvoutils.$(ARCH).o \
 $(SRC)/dvoutils_args.$(ARCH).o \
 $(SRC)/dvoutils_uniq_images.$(ARCH).o \
+$(SRC)/dvoutils_check_images.$(ARCH).o \
 $(SRC)/dvoutils_load_image_index.$(ARCH).o
 
Index: trunk/Ohana/src/dvomerge/include/dvomerge.h
===================================================================
--- trunk/Ohana/src/dvomerge/include/dvomerge.h	(revision 39217)
+++ trunk/Ohana/src/dvomerge/include/dvomerge.h	(revision 39225)
@@ -252,3 +252,4 @@
 int dvorepair_by_objID (int argc, char **argv);
 int dvorepairFixWarpIDs (int argc, char **argv);
-
+int dvorepairFixStackIDs (int argc, char **argv);
+
Index: trunk/Ohana/src/dvomerge/include/dvoutils.h
===================================================================
--- trunk/Ohana/src/dvomerge/include/dvoutils.h	(revision 39217)
+++ trunk/Ohana/src/dvomerge/include/dvoutils.h	(revision 39225)
@@ -20,4 +20,5 @@
   DVOUTILS_NONE,
   DVOUTILS_UNIQ_IMAGES,
+  DVOUTILS_CHECK_IMAGES,
 } DVOUTILS_OP_TYPE;
 
@@ -32,8 +33,11 @@
 
 char *IMAGES_LIST;
+char *CATDIR;
+char *EXTERN_ID_LIST;
 
 int main (int argc, char **argv);
 int dvoutils_args (int *argc, char **argv);
 int dvoutils_uniq_images (char *filename);
+int dvoutils_check_images (void);
 
 ImageData *dvoutils_load_image_index (char *filename);
Index: trunk/Ohana/src/dvomerge/src/dvorepair.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvorepair.c	(revision 39217)
+++ trunk/Ohana/src/dvomerge/src/dvorepair.c	(revision 39225)
@@ -11,4 +11,5 @@
   
   if (!strcmp(argv[1], "-fix-warp-ids")) dvorepairFixWarpIDs(argc, argv);
+  if (!strcmp(argv[1], "-fix-stack-ids")) dvorepairFixStackIDs(argc, argv);
 
   if (!strcmp(argv[1], "-fix-cpt")) dvorepairFixCPT(argc, argv);
Index: trunk/Ohana/src/dvomerge/src/dvorepairFixStackIDs.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvorepairFixStackIDs.c	(revision 39225)
+++ trunk/Ohana/src/dvomerge/src/dvorepairFixStackIDs.c	(revision 39225)
@@ -0,0 +1,75 @@
+# include "dvomerge.h"
+
+# define STRFAIL { fprintf (stderr, "failure on image %s\n", image[i].name); continue; }
+
+int dvorepairFixStackIDs (int argc, char **argv) {
+
+  FITS_DB db;  // database handle pointing to input image table
+
+  off_t Nimage;
+  
+  Image *image;
+
+  int N = get_argument (argc, argv, "-fix-stack-ids");
+  myAssert(N == 1, "programming error: -fix-stack-ids must be first from main");
+  remove_argument (N, &argc, argv);
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: dvorepair -fix-stack-ids (catdir.list)\n");
+    fprintf (stderr, "  catdir.list : list of databases of interest\n");
+    fprintf (stderr, "  image.externID is set based on the image name:\n");
+    fprintf (stderr, "  e.g., for: RINGS.V3.skycell.0798.031.stk.3923362.skycal.3788239.cmf[SkyChip.hdr]\n");
+    fprintf (stderr, "  externID (stackID) follows stk: 3923362\n");
+    exit (2);
+  }
+
+  char *catdir_list  = argv[1];
+
+  char name[DVO_MAX_PATH];
+  char catdir[DVO_MAX_PATH];
+  char imageFilenameOld[DVO_MAX_PATH];
+  char imageFilenameNew[DVO_MAX_PATH];
+
+  // read the list of catdirs and fix image tables for each 
+
+  FILE *f = fopen (catdir_list, "r");
+  myAssert (f, "failed to open catdir.list %s\n", catdir_list);
+
+  while (fscanf (f, "%s", catdir) != EOF) {
+    snprintf (imageFilenameOld, DVO_MAX_PATH, "%s/Images.dat", catdir);
+    snprintf (imageFilenameNew, DVO_MAX_PATH, "%s/Images.dat.fixed", catdir);
+    
+    if ((image = LoadImages (&db, imageFilenameOld, &Nimage)) == NULL) {
+      fprintf (stderr, "error loading images\n");
+      exit (1);
+    }
+
+    int i;
+    for (i = 0; i < Nimage; i++) {
+      if (image[i].externID) continue;
+      
+      strcpy (name, image[i].name);
+    
+      char *p0 = strchr (name  , '.'); if (!p0) STRFAIL;
+      char *p1 = strchr (p0 + 1, '.'); if (!p1) STRFAIL;
+      char *p2 = strchr (p1 + 1, '.'); if (!p2) STRFAIL;
+      char *p3 = strchr (p2 + 1, '.'); if (!p3) STRFAIL;
+      char *p4 = strchr (p3 + 1, '.'); if (!p4) STRFAIL;
+      char *p5 = strchr (p4 + 1, '.'); if (!p5) STRFAIL;
+      char *p6 = strchr (p5 + 1, '.'); if (!p6) STRFAIL;
+    
+      *p6 = 0;
+      int myStackID = atoi (p5 + 1);
+
+      image[i].externID = myStackID;
+      image[i].sourceID = 35; // hard-wired for gpc1 stacks
+    }
+    SaveImages(&db, imageFilenameNew, image, Nimage);
+    gfits_db_free (&db);
+  }
+
+  fclose (f);
+  ohana_memdump (TRUE);
+
+  exit (0);
+}
Index: trunk/Ohana/src/dvomerge/src/dvoutils.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvoutils.c	(revision 39217)
+++ trunk/Ohana/src/dvomerge/src/dvoutils.c	(revision 39225)
@@ -13,4 +13,8 @@
       exit (0);
 
+    case DVOUTILS_CHECK_IMAGES:
+      dvoutils_check_images();
+      exit (0);
+
     default:
       fprintf (stderr, "ERROR: unknown option\n");
Index: trunk/Ohana/src/dvomerge/src/dvoutils_args.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvoutils_args.c	(revision 39217)
+++ trunk/Ohana/src/dvomerge/src/dvoutils_args.c	(revision 39225)
@@ -22,4 +22,19 @@
     remove_argument (N, argc, argv);
   }
+  if ((N = get_argument (*argc, argv, "-check-images"))) {
+    DVOUTILS_OP = DVOUTILS_CHECK_IMAGES;
+    remove_argument (N, argc, argv);
+    CATDIR = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    EXTERN_ID_LIST = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  if (*argc != 1) {
+    fprintf (stderr, "USAGE: dvoutils -uniq-images (filename) [-v,-verbose]\n\n");
+    fprintf (stderr, "USAGE: dvoutils -check-images (catdir) (externIDs) [-v,-verbose]\n\n");
+    fprintf (stderr, "  -v : VERBOSE\n");
+    exit (2);
+  }
 
   if (DVOUTILS_OP == DVOUTILS_NONE) {
@@ -28,10 +43,4 @@
   }
 
-  if (*argc != 1) {
-    fprintf (stderr, "USAGE: dvoutils -uniq-images (filename) [-v,-verbose]\n\n");
-    fprintf (stderr, "  -v : VERBOSE\n");
-    exit (2);
-  }
-
   return TRUE;
 }
Index: trunk/Ohana/src/dvomerge/src/dvoutils_check_images.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvoutils_check_images.c	(revision 39225)
+++ trunk/Ohana/src/dvomerge/src/dvoutils_check_images.c	(revision 39225)
@@ -0,0 +1,256 @@
+# include "dvoutils.h"
+
+static off_t *externIDs = NULL;
+static off_t *externIDc = NULL;
+
+# define STRFAIL { fprintf (stderr, "failure on image %s\n", image[i].name); continue; }
+
+void osort (off_t *value, off_t N);
+off_t load_extern_ids (char *idfile, off_t *nids);
+off_t externIDs_bisection (off_t *values, off_t threshold, off_t Nvalues);
+Image *LoadImages (FITS_DB *db, char *filename, off_t *Nimage);
+
+int dvoutils_check_images (void) {
+
+  FITS_DB db;  // database handle pointing to input image table
+
+  off_t i, k, Nimage;
+  
+  Image *image;
+
+  // load the extern_id table
+  off_t NexternIDs = 0;
+  load_extern_ids (EXTERN_ID_LIST, &NexternIDs);
+  fprintf (stderr, "loaded "OFF_T_FMT" extern IDs\n", NexternIDs);
+
+  char imageFilename[DVO_MAX_PATH];
+
+  snprintf (imageFilename, DVO_MAX_PATH, "%s/Images.dat", CATDIR);
+
+  if ((image = LoadImages (&db, imageFilename, &Nimage)) == NULL) {
+    fprintf (stderr, "error loading images\n");
+    exit (1);
+  }
+  fprintf (stderr, "loaded "OFF_T_FMT" images\n", Nimage);
+
+  off_t NzeroIDs = 0;
+  off_t Nfound = 0;
+  off_t Nmissed = 0;
+  off_t Nextmiss = 0;
+  off_t Nextdups = 0;
+
+  off_t *imageIDs = NULL;
+  off_t *imageIDc = NULL;
+  ALLOCATE (imageIDs, off_t, Nimage);
+  ALLOCATE (imageIDc, off_t, Nimage);
+  for (i = 0; i < Nimage; i++) {
+    imageIDs[i] = image[i].externID;
+    imageIDc[i] = 0;
+  }
+  osort (imageIDs, Nimage);
+
+  for (i = 0, k = 0; (i < Nimage) && (k < NexternIDs); ) {
+
+    // skip zero-valued imageIDs 
+    if (imageIDs[i] == 0) {
+      NzeroIDs ++;
+      i++;
+      continue;
+    }
+
+    // we have either found this one or not, but it is time to move on
+    if (imageIDs[i] < externIDs[k]) { i++; continue; }
+
+    // try the next extern ID
+    if (imageIDs[i] > externIDs[k]) { k++; continue; }
+    
+    // we now have imageIDs[i] == externIDs[k].  
+    // find all imageIDs which match this externID:
+
+    imageIDc[i] ++;
+    externIDc[k] ++;
+
+    // by advancing imageIDs[i], I am ignoring externIDs[k] duplicates.  these are supposed to be uniq in the db
+    i++;
+  }
+
+  FILE *fmiss = fopen ("missed.txt", "w");
+  myAssert (fmiss, "failed to open missed.txt");
+
+  for (i = 0; i < Nimage; i++) {
+    if (imageIDs[i] == 0) continue;
+    if (imageIDc[i] == 0) {
+      fprintf (fmiss, OFF_T_FMT "\n", imageIDs[i]);
+      Nmissed ++;
+    }
+    if (imageIDc[i] == 1) { Nfound ++; continue; }
+    myAssert (imageIDc[i] <= 1, "impossible");
+  }
+  fclose (fmiss);
+
+  fmiss = fopen ("missed.extern.txt", "w");
+  myAssert (fmiss, "failed to open missed.extern.txt");
+
+  FILE *fdups = fopen ("duplicate.txt", "w");
+  myAssert (fdups, "failed to open duplicate.txt");
+
+  for (i = 0; i < NexternIDs; i++) {
+    if (externIDc[i] == 1) continue;
+    if (externIDc[i] == 0) {
+      fprintf (fmiss, "missing " OFF_T_FMT "\n", externIDs[i]);
+      Nextmiss ++;
+    }
+    if (externIDc[i] > 0) {
+      fprintf (fdups, "duplicate " OFF_T_FMT " " OFF_T_FMT "\n", externIDs[i], externIDc[i]);
+      Nextdups ++;
+    }
+  }
+  fclose (fdups);
+  fclose (fmiss);
+
+  fprintf (stderr, OFF_T_FMT " in catdir zero ID\n", NzeroIDs);
+  fprintf (stderr, OFF_T_FMT " in catdir found\n", Nfound);
+  fprintf (stderr, OFF_T_FMT " in catdir not found\n", Nmissed);
+  fprintf (stderr, OFF_T_FMT " in extern not found\n", Nextmiss);
+  fprintf (stderr, OFF_T_FMT " in extern duplicate\n", Nextdups);
+
+  gfits_db_free (&db);
+  free (externIDs);
+  free (externIDc);
+  free (imageIDs);
+  free (imageIDc);
+
+  free (CATDIR);
+  free (EXTERN_ID_LIST);
+
+  ohana_memdump (TRUE);
+
+  exit (0);
+}
+
+// I'm loading a table of expected extern IDs and initing a table of their count
+off_t load_extern_ids (char *idfile, off_t *nids) {
+
+  // load the extern ids
+  FILE *f = fopen (idfile, "r");
+  myAssert (f, "failed to open idfile");
+
+  off_t NBUFFER = 30000000;
+
+  char *buffer;
+  ALLOCATE (buffer, char, NBUFFER);
+
+  off_t Nids = 0;
+  off_t NIDS = 1000;
+  ALLOCATE (externIDs, off_t, NIDS);
+  ALLOCATE (externIDc, off_t, NIDS);
+
+  off_t skipFirst = TRUE;
+
+  off_t Nstart = 0;
+  off_t Ntotal = 0;
+  while (TRUE) {
+    off_t Nbytes = NBUFFER - 1 - Nstart;
+    bzero (&buffer[Nstart], Nbytes + 1);
+
+    off_t Nread = fread (&buffer[Nstart], 1, Nbytes, f);
+
+    Ntotal += Nread;
+    fprintf (stderr, "reading block: " OFF_T_FMT " " OFF_T_FMT " " OFF_T_FMT " " OFF_T_FMT "\n", Nstart, Nbytes, Nread, Ntotal);
+
+    if (ferror (f)) {
+      perror ("error reading data file");
+      break;
+    }
+    if (Nread == 0) break; // end of the file
+
+    off_t Nlines = 0;
+
+    int bufferStatus = TRUE; 
+    char *c0 = buffer; // c0 always marks the start of a line
+    while (bufferStatus) {
+      char *c1 = strchr (c0, '\n'); // find the end of this current line
+      if (!c1) {
+	Nstart = strlen (c0);
+	memmove (buffer, c0, Nstart);
+	bufferStatus = FALSE;
+	continue;
+      }
+      *c1 = 0; // mark the end of the line 
+      Nlines ++;
+
+      if (skipFirst) {
+	skipFirst = FALSE;
+	c0 = c1 + 1;
+	continue;
+      }
+
+      off_t extern_id;
+      int Nscan = sscanf (c0, OFF_T_FMT, &extern_id);
+      myAssert (Nscan == 1, "invalid line");
+
+      externIDs[Nids] = extern_id;
+      externIDc[Nids] = 0;
+      Nids ++;
+
+      if (Nids == NIDS) {
+	NIDS += 1000;
+	REALLOCATE (externIDs, off_t, NIDS);
+	REALLOCATE (externIDc, off_t, NIDS);
+      }
+      c0 = c1 + 1;
+    }
+  }
+  free (buffer);
+  fclose (f);
+
+  osort (externIDs, Nids);
+
+  *nids = Nids;
+  return TRUE;
+}
+
+// return the index of the last value < threshold 
+off_t externIDs_bisection (off_t *values, off_t threshold, off_t Nvalues) {
+
+  off_t Nlo = 0; 
+  off_t Nhi = Nvalues - 1;
+
+  if (Nvalues < 1) return (-1);
+  if (threshold < values[Nlo]) return (-1);
+
+  if (Nvalues < 2) return (0);
+  if (threshold > values[Nhi]) return (-1);
+
+  off_t N;
+  while (Nhi - Nlo > 4) {
+    N = 0.5*(Nlo + Nhi);
+    if (values[N] < threshold) {
+      Nlo = MAX(N, 0);
+    } else {
+      Nhi = MIN(N + 1, Nvalues - 1);
+    }
+  }
+  // values[Nlo] < threshold 
+  // values[Nhi] >= threshold 
+
+  for (N = Nlo; N < Nhi; N++) {
+    if (values[N] >= threshold) {
+      return (N-1);
+    }
+  }
+  return (N);
+}
+
+void osort (off_t *value, off_t N) {
+
+# define SWAPFUNC(A,B){ off_t tmp = value[A]; value[A] = value[B]; value[B] = tmp; }
+# define COMPARE(A,B)(value[A] < value[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
Index: trunk/Ohana/src/dvomerge/src/help.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/help.c	(revision 39217)
+++ trunk/Ohana/src/dvomerge/src/help.c	(revision 39225)
@@ -172,5 +172,6 @@
 
   fprintf (stderr, "USAGE\n");
-  fprintf (stderr, "  dvorepair -fix-warp-ids (catdir) (idfile) - regenerate images.dat warp_skyfile_ids (EXTERN_ID) values\n");
+  fprintf (stderr, "  dvorepair -fix-warp-ids (catdir.list) (idfile) - regenerate images.dat warp_skyfile_ids (EXTERN_ID) values\n");
+  fprintf (stderr, "  dvorepair -fix-stack-ids (catdir.list) - regenerate images.dat stackID (EXTERN_ID) values\n");
   fprintf (stderr, "  dvorepair -fix-cpt (images) (rootlist) - regenerate cpt & cps files from the cpm files\n");
   fprintf (stderr, "  dvorepair -images-vs-measures (catdir) (Ntol) - find images with too many missing detections\n");
Index: trunk/Ohana/src/kapa2/include/constants.h
===================================================================
--- trunk/Ohana/src/kapa2/include/constants.h	(revision 39217)
+++ trunk/Ohana/src/kapa2/include/constants.h	(revision 39225)
@@ -11,9 +11,4 @@
 
 # define NCHANNELS 10
-# define NPIXELS_DYNAMIC 128
-
-// XXX for the moment, this is set to match the values in SetColorScale3D_CC
-# define NPIXELS_STATIC 128
-// # define NPIXELS_STATIC 4600 -- if we want fullcolor to work, need this
 
 # define PAD1  3
Index: trunk/Ohana/src/kapa2/include/globals.h
===================================================================
--- trunk/Ohana/src/kapa2/include/globals.h	(revision 39217)
+++ trunk/Ohana/src/kapa2/include/globals.h	(revision 39225)
@@ -11,4 +11,7 @@
 int   NAN_GREEN;
 int   NAN_BLUE;
+
+int   NPIXELS_DYNAMIC;
+int   NPIXELS_STATIC;
 
 /* these should be absorbed into KapaImageWidget 
Index: trunk/Ohana/src/kapa2/src/CheckVisual.c
===================================================================
--- trunk/Ohana/src/kapa2/src/CheckVisual.c	(revision 39217)
+++ trunk/Ohana/src/kapa2/src/CheckVisual.c	(revision 39225)
@@ -131,11 +131,7 @@
   }
 
+  Npixels = NPIXELS_STATIC;
   if (graphic[0].dynamicColors) {
     Npixels = NPIXELS_DYNAMIC;
-    if ((N = get_argument (*argc, argv, "-ncolors"))) {
-      remove_argument(N, argc, argv);
-      Npixels = atoi (argv[N]);
-      remove_argument(N, argc, argv);
-    } 
 
     /* allocate color cells */
@@ -181,11 +177,4 @@
     }
   } else {
-    Npixels = NPIXELS_STATIC;
-    if ((N = get_argument (*argc, argv, "-ncolors"))) {
-      remove_argument(N, argc, argv);
-      Npixels = atoi (argv[N]);
-      remove_argument(N, argc, argv);
-    } 
-
     // XXX allocate the unsigned long *pixels here and above
     ALLOCATE (graphic[0].pixels, unsigned long, Npixels);
Index: trunk/Ohana/src/kapa2/src/args.c
===================================================================
--- trunk/Ohana/src/kapa2/src/args.c	(revision 39217)
+++ trunk/Ohana/src/kapa2/src/args.c	(revision 39225)
@@ -1,7 +1,14 @@
 # include "Ximage.h"
+
+void help(void);
 
 int args (int *argc, char **argv) {
 
   int N;
+
+  if ((N = get_argument (*argc, argv, "-h"))) help();
+  if ((N = get_argument (*argc, argv, "-help"))) help();
+  if ((N = get_argument (*argc, argv, "--h"))) help();
+  if ((N = get_argument (*argc, argv, "--help"))) help();
 
   MAP_WINDOW = TRUE;
@@ -37,4 +44,13 @@
   }
 
+  NPIXELS_DYNAMIC = 128;
+  NPIXELS_STATIC = 128;
+  if ((N = get_argument (*argc, argv, "-ncolors"))) {
+    remove_argument(N, argc, argv);
+    NPIXELS_DYNAMIC = atoi (argv[N]);
+    NPIXELS_STATIC = NPIXELS_DYNAMIC;
+    remove_argument(N, argc, argv);
+  } 
+
   NAN_RED   = 0;
   NAN_GREEN = 0xffff;
@@ -56,2 +72,17 @@
   return (TRUE);
 }
+
+void help (void) {
+
+  fprintf (stderr, "USAGE: kapa [options]\n");
+  fprintf (stderr, "OPTIONS: \n");
+  fprintf (stderr, "-h, -help, --h, --help : this listing\n");
+  fprintf (stderr, "-nomap : use X but do not generate a window\n");
+  fprintf (stderr, "-name : name for the X window bar\n");
+  fprintf (stderr, "-noX : do not use an X window\n");
+  fprintf (stderr, "-debug : report debug info\n");
+  fprintf (stderr, "-fg : define the foreground color (X color style)\n");
+  fprintf (stderr, "-ncolors : set the number of colors (pixels) available (128 default)\n");
+  fprintf (stderr, "-nan (red) (green) (blue) : set NaN pixels to this color (hex values)\n");
+  exit (2);
+}
Index: trunk/Ohana/src/libautocode/def/measure.d
===================================================================
--- trunk/Ohana/src/libautocode/def/measure.d	(revision 39217)
+++ trunk/Ohana/src/libautocode/def/measure.d	(revision 39225)
@@ -45,4 +45,5 @@
 # XXX I can deprecate these as I am going to apply the correct uR,uD offset
 # XXX not sure how to use this yet...
+# XXX replace RoffGall with Moff -> static component of the zpt correction
 FIELD RoffGAL,        R_OFF_GAL,     float,          RA offset from correction,    arcsec
 FIELD DoffGAL,        D_OFF_GAL,     float,          DEC offset from correction,   arcsec
Index: trunk/Ohana/src/libdvo/src/coordops.c
===================================================================
--- trunk/Ohana/src/libdvo/src/coordops.c	(revision 39217)
+++ trunk/Ohana/src/libdvo/src/coordops.c	(revision 39225)
@@ -990,21 +990,21 @@
 
 OhanaProjection GetProjection (char *ctype) {
-  if (!strcmp(&ctype[4], "-ZEA")) return PROJ_ZEA;
-  if (!strcmp(&ctype[4], "-ZPL")) return PROJ_ZPL;
-  if (!strcmp(&ctype[4], "-ZPN")) return PROJ_ZPN;
-  if (!strcmp(&ctype[4], "-ARC")) return PROJ_ARC;
-  if (!strcmp(&ctype[4], "-STG")) return PROJ_STG;
-  if (!strcmp(&ctype[4], "-SIN")) return PROJ_SIN;
-  if (!strcmp(&ctype[0], "MM"))   return PROJ_SIN; // note ctype[0]
-  if (!strcmp(&ctype[4], "-TAN")) return PROJ_TAN;
-  if (!strcmp(&ctype[4], "-TNX")) return PROJ_TNX;
-  if (!strcmp(&ctype[4], "-DIS")) return PROJ_DIS;
-  if (!strcmp(&ctype[4], "-LIN")) return PROJ_LIN;
-  if (!strcmp(&ctype[0], "GENE")) return PROJ_LIN; // note ctype[0]
-  if (!strcmp(&ctype[4], "-PLY")) return PROJ_PLY;
-  if (!strcmp(&ctype[4], "-WRP")) return PROJ_WRP;
-  if (!strcmp(&ctype[4], "-AIT")) return PROJ_AIT;
-  if (!strcmp(&ctype[4], "-GLS")) return PROJ_GLS;
-  if (!strcmp(&ctype[4], "-PAR")) return PROJ_PAR;
+  if (!strncmp(&ctype[4], "-ZEA", 4)) return PROJ_ZEA;
+  if (!strncmp(&ctype[4], "-ZPL", 4)) return PROJ_ZPL;
+  if (!strncmp(&ctype[4], "-ZPN", 4)) return PROJ_ZPN;
+  if (!strncmp(&ctype[4], "-ARC", 4)) return PROJ_ARC;
+  if (!strncmp(&ctype[4], "-STG", 4)) return PROJ_STG;
+  if (!strncmp(&ctype[4], "-SIN", 4)) return PROJ_SIN;
+  if (!strncmp(&ctype[0], "MM", 2))   return PROJ_SIN; // note ctype[0]
+  if (!strncmp(&ctype[4], "-TAN", 4)) return PROJ_TAN;
+  if (!strncmp(&ctype[4], "-TNX", 4)) return PROJ_TNX;
+  if (!strncmp(&ctype[4], "-DIS", 4)) return PROJ_DIS;
+  if (!strncmp(&ctype[4], "-LIN", 4)) return PROJ_LIN;
+  if (!strncmp(&ctype[0], "GENE", 4)) return PROJ_LIN; // note ctype[0]
+  if (!strncmp(&ctype[4], "-PLY", 4)) return PROJ_PLY;
+  if (!strncmp(&ctype[4], "-WRP", 4)) return PROJ_WRP;
+  if (!strncmp(&ctype[4], "-AIT", 4)) return PROJ_AIT;
+  if (!strncmp(&ctype[4], "-GLS", 4)) return PROJ_GLS;
+  if (!strncmp(&ctype[4], "-PAR", 4)) return PROJ_PAR;
   return PROJ_NONE;
 }
Index: trunk/Ohana/src/libkapa/src/KapaOpen.c
===================================================================
--- trunk/Ohana/src/libkapa/src/KapaOpen.c	(revision 39217)
+++ trunk/Ohana/src/libkapa/src/KapaOpen.c	(revision 39225)
@@ -2,5 +2,5 @@
 
 // kapa connection timeout is N_RETRY * 10000 usec
-# define N_RETRY 2000
+# define N_RETRY 5000
 
 # define MY_PORT 2500
Index: trunk/Ohana/src/opihi/cmd.astro/Makefile
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/Makefile	(revision 39217)
+++ trunk/Ohana/src/opihi/cmd.astro/Makefile	(revision 39225)
@@ -23,4 +23,5 @@
 $(SRC)/cdot.$(ARCH).o		   \
 $(SRC)/cline.$(ARCH).o             \
+$(SRC)/cneedles.$(ARCH).o		   \
 $(SRC)/cplot.$(ARCH).o		   \
 $(SRC)/csystem.$(ARCH).o	   \
@@ -76,4 +77,5 @@
 $(SRC)/vshimage.$(ARCH).o         \
 $(SRC)/shimage.$(ARCH).o         \
+$(SRC)/wcs.$(ARCH).o         \
 $(SRC)/imsub.$(ARCH).o		   \
 $(SRC)/imfit.$(ARCH).o		   \
Index: trunk/Ohana/src/opihi/cmd.astro/cneedles.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/cneedles.c	(revision 39225)
+++ trunk/Ohana/src/opihi/cmd.astro/cneedles.c	(revision 39225)
@@ -0,0 +1,136 @@
+# include "data.h"
+
+// generate needle plots for (x,y) (dx,dy)
+int cneedles (int argc, char **argv) {
+  
+  int i, N, kapa, Npts, valid, size;
+  opihi_flt *x, *y, *r, *d, *dR, *dD, Rmin, Rmax;
+  Vector Xvec, Yvec, *xvec, *yvec, *dxvec, *dyvec;
+  Graphdata graphmode;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  float scale = 1.0;
+  if ((N = get_argument (argc, argv, "-scale"))) {
+    remove_argument (N, &argc, argv);
+    scale = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }    
+
+  valid  = (argc == 5);
+  valid |= (argc > 6) && !strcmp (argv[5], "where");
+  if (!valid) {
+    gprint (GP_ERR, "USAGE: needles <ra> <dec> <dR> <dD> [-scale scale] [style]\n");
+    gprint (GP_ERR, "   OR: needles <ra> <dec> <dR> <dD> [-scale scale] [style] where (condition)\n");
+    return (FALSE);
+  }
+
+  // tvec is used for logical test (truth vector)
+  Vector *tvec = NULL;
+  if (argc > 6) {
+    char *out = dvomath (argc - 6, &argv[6], &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);
+    }
+  }
+
+  graphmode.etype = 0;
+  graphmode.ptype = 100;
+
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dxvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dyvec = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  REQUIRE_VECTOR_FLT (xvec, FALSE); 
+  REQUIRE_VECTOR_FLT (yvec, FALSE); 
+  REQUIRE_VECTOR_FLT (dxvec, FALSE); 
+  REQUIRE_VECTOR_FLT (dyvec, FALSE); 
+
+  if (xvec->Nelements != yvec->Nelements) { gprint (GP_ERR, "vectors are not the same length\n"); return (FALSE); }
+  if (dxvec->Nelements != xvec->Nelements) { gprint (GP_ERR, "vectors are not the same length\n"); return (FALSE); }
+  if (dyvec->Nelements != xvec->Nelements) { gprint (GP_ERR, "vectors are not the same length\n"); return (FALSE); }
+
+  if (tvec && tvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "logic test vector not the same length as data vectors\n");
+    DeleteVector (tvec);
+    return (FALSE);
+  }
+
+  SetVector (&Xvec, OPIHI_FLT, 2*xvec[0].Nelements);
+  SetVector (&Yvec, OPIHI_FLT, 2*xvec[0].Nelements);
+  
+  // input vectors in r,d space
+  r  =  xvec[0].elements.Flt;
+  d  =  yvec[0].elements.Flt;
+  dR = dxvec[0].elements.Flt;
+  dD = dyvec[0].elements.Flt;
+
+  // output vectors after projection & offsets
+  x = Xvec.elements.Flt;
+  y = Yvec.elements.Flt;
+  
+  Npts = 0;
+  for (i = 0; i < xvec->Nelements; i++, r++, d++, dR++, dD++) {
+    if (tvec) {
+      int skip = (tvec->type == OPIHI_FLT) ? (tvec->elements.Flt[i] == 0.0) : (tvec->elements.Int[i] == 0.0);
+      if (skip) continue;
+    }
+
+    double dec = *d;
+    double ra = ohana_normalize_angle (*r);
+    while (ra < Rmin) ra += 360.0;
+    while (ra > Rmax) ra -= 360.0;
+
+    double X1, Y1;
+    int status1 = RD_to_XY (&X1, &Y1, ra, dec, &graphmode.coords);
+
+    float rescale = cos(dec*RAD_DEG);
+    if (fabs(rescale) < 0.01) {
+      rescale = 0.01;
+    }
+    dec = dec + *dD * scale;
+    ra  = ra  + *dR * scale / rescale;
+
+    double X2, Y2;
+    int status2 = RD_to_XY (&X2, &Y2, ra, dec, &graphmode.coords);
+
+    if (!status1 || !status2) continue;
+
+    *x = X1;
+    *y = Y1;
+    x++;
+    y++;
+    Npts++;
+
+    *x = X2;
+    *y = Y2;
+    x++;
+    y++;
+    Npts++;
+  }
+  Xvec.Nelements = Npts;
+  Yvec.Nelements = Npts;
+
+  graphmode.etype = 0;
+  graphmode.ptype = 100;
+  PlotVectorPair (kapa, &Xvec, &Yvec, NULL, &graphmode);
+  
+  free (Xvec.elements.Ptr);
+  free (Yvec.elements.Ptr);
+    
+  if (tvec) DeleteVector (tvec);
+
+  return (TRUE);
+}
Index: trunk/Ohana/src/opihi/cmd.astro/drizzle.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/drizzle.c	(revision 39217)
+++ trunk/Ohana/src/opihi/cmd.astro/drizzle.c	(revision 39225)
@@ -141,4 +141,6 @@
 
 	  if (Vmk && Vmk[Ni]) continue;
+	  if (!isfinite(Vin[Ni])) continue;
+
 	  Vout[No] += Vin[Ni];
 	  Vwt[No] ++;
@@ -195,4 +197,5 @@
 
 	  if (Vmk && Vmk[Ni]) continue;
+	  if (!isfinite(Vin[Ni])) continue;
 	  Vout[No] += Vin[Ni];
 	  Vwt[No] ++;
Index: trunk/Ohana/src/opihi/cmd.astro/init.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/init.c	(revision 39217)
+++ trunk/Ohana/src/opihi/cmd.astro/init.c	(revision 39225)
@@ -7,4 +7,5 @@
 int cdot                    PROTO((int, char **));
 int cline                   PROTO((int, char **));
+int cneedles                PROTO((int, char **));
 int cplot                   PROTO((int, char **));
 int csystem                 PROTO((int, char **));
@@ -66,4 +67,5 @@
 int vshimage                PROTO((int, char **));
 int shimage                 PROTO((int, char **));
+int wcs                     PROTO((int, char **));
 
 static Command cmds[] = {  
@@ -74,4 +76,5 @@
   {1, "cdot",        cdot,         "plot point in sky coordinates"},
   {1, "cline",       cline,        "plot line connecting two sky coordinates"},
+  {1, "cneedles",    cneedles,     "plot vectors in sky coordinates"},
   {1, "cplot",       cplot,        "plot vectors in sky coordinates"},
   {1, "csystem",     csystem,      "convert between coordinate systems"},
@@ -131,4 +134,5 @@
   {1, "vshimage",    vshimage,     "generate images for vector spherical harmonic terms"},
   {1, "shimage",     shimage,      "generate images for spherical harmonic terms"},
+  {1, "wcs",         wcs,          "set the wcs for the given image"},
 }; 
 
Index: trunk/Ohana/src/opihi/cmd.astro/region.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/region.c	(revision 39217)
+++ trunk/Ohana/src/opihi/cmd.astro/region.c	(revision 39225)
@@ -74,7 +74,14 @@
   }
 
+  float Angle = 0.0;
+  if ((N = get_argument (argc, argv, "-angle"))) {
+    remove_argument (N, &argc, argv);
+    Angle = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
   if ((argc != 4) && (argc != 5)) {
     gprint (GP_ERR, "USAGE: region Ra Dec Radius [projection] [orientation]\n");
-    gprint (GP_ERR, "  [-image] [-ew] [+ew] [-ns] [+ns] [-no-clear]\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, 
@@ -111,6 +118,11 @@
   graphmode.coords.crval2 = Dec;
 
-  graphmode.coords.pc1_1 = (graphmode.flipeast) ? -1 : 1;
-  graphmode.coords.pc2_2 = (graphmode.flipnorth) ? -1 : 1;
+  float pc1_1 = (graphmode.flipeast)  ? -1 : 1;
+  float pc2_2 = (graphmode.flipnorth) ? -1 : 1;
+
+  graphmode.coords.pc1_1 =  cos(Angle*RAD_DEG)*pc1_1;
+  graphmode.coords.pc1_2 =  sin(Angle*RAD_DEG)*pc2_2;
+  graphmode.coords.pc2_1 = -sin(Angle*RAD_DEG)*pc1_1;
+  graphmode.coords.pc2_2 =  cos(Angle*RAD_DEG)*pc2_2;
 
   /* ask kapa for coordinate limits, to get the right aspect ratio */
Index: trunk/Ohana/src/opihi/cmd.astro/wcs.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.astro/wcs.c	(revision 39225)
+++ trunk/Ohana/src/opihi/cmd.astro/wcs.c	(revision 39225)
@@ -0,0 +1,93 @@
+# include "astro.h"
+
+int wcs (int argc, char **argv) {
+  
+  int N;
+
+  int flipeast = TRUE;
+  if ((N = get_argument (argc, argv, "-ew"))) {
+    remove_argument (N, &argc, argv);
+    flipeast = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "+ew"))) {
+    remove_argument (N, &argc, argv);
+    flipeast = FALSE;
+  }
+
+  int flipnorth = FALSE;
+  if ((N = get_argument (argc, argv, "-ns"))) {
+    remove_argument (N, &argc, argv);
+    flipnorth = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "+ns"))) {
+    remove_argument (N, &argc, argv);
+    flipnorth = FALSE;
+  }
+
+  float Angle = 0.0;
+  if ((N = get_argument (argc, argv, "-angle"))) {
+    remove_argument (N, &argc, argv);
+    Angle = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc != 5) && (argc != 6)) {
+    gprint (GP_ERR, "USAGE: wcs (buffer) Ra Dec platescale [projection] [orientation]\n");
+    gprint (GP_ERR, "  [-ew] [+ew] [-ns] [+ns] [-angle theta]\n");
+    return (FALSE);
+  }
+  
+  double Ra, Dec;
+  if (!ohana_str_to_radec (&Ra, &Dec, argv[2], argv[3])) return (FALSE);
+  float platescale = atof (argv[4]); // arcsec per pixel
+
+  Buffer *buf = NULL;
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) {
+    gprint (GP_ERR, "cannot define buffer %s\n", argv[1]);
+    return FALSE;
+  }
+
+  Coords coords;
+  InitCoords (&coords, "DEC--TAN");
+
+  if (argc == 6) {
+    if (!strcasecmp (argv[5], "TAN")) 
+      strcpy (coords.ctype, "DEC--TAN");
+    if (!strcasecmp (argv[5], "SIN")) 
+      strcpy (coords.ctype, "DEC--SIN");
+    if (!strcasecmp (argv[5], "ARC")) 
+      strcpy (coords.ctype, "DEC--ARC");
+    if (!strcasecmp (argv[5], "STG")) 
+      strcpy (coords.ctype, "DEC--STG");
+    if (!strcasecmp (argv[5], "ZEA"))
+      strcpy (coords.ctype, "DEC--ZEA");
+    if (!strcasecmp (argv[5], "AIT")) 
+      strcpy (coords.ctype, "DEC--AIT");
+    if (!strcasecmp (argv[5], "GLS")) 
+      strcpy (coords.ctype, "DEC--GLS");
+    if (!strcasecmp (argv[5], "PAR")) 
+      strcpy (coords.ctype, "DEC--PAR");
+  }
+  
+  coords.crval1 = Ra;
+  coords.crval2 = Dec;
+
+  // reference pixel is the image center
+  coords.crpix1 = 0.5 * buf[0].header.Naxis[0]; // Ohana / IPP center of a pixel is X.5,X.5
+  coords.crpix2 = 0.5 * buf[0].header.Naxis[1]; // Ohana / IPP center of a pixel is X.5,X.5
+
+  float pc1_1 = flipeast  ? -1 : 1;
+  float pc2_2 = flipnorth ? -1 : 1;
+
+  coords.pc1_1 =  cos(Angle*RAD_DEG)*pc1_1;
+  coords.pc1_2 =  sin(Angle*RAD_DEG)*pc2_2;
+  coords.pc2_1 = -sin(Angle*RAD_DEG)*pc1_1;
+  coords.pc2_2 =  cos(Angle*RAD_DEG)*pc2_2;
+
+  coords.cdelt1 = platescale / 3600.0;
+  coords.cdelt2 = platescale / 3600.0;
+
+  PutCoords (&coords, &buf[0].header);
+  return (TRUE);
+}
+
Index: trunk/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 39217)
+++ trunk/Ohana/src/opihi/cmd.data/Makefile	(revision 39225)
@@ -97,4 +97,5 @@
 $(SRC)/medimage_commands.$(ARCH).o \
 $(SRC)/mset.$(ARCH).o		\
+$(SRC)/needles.$(ARCH).o		\
 $(SRC)/peak.$(ARCH).o		\
 $(SRC)/periodogram.$(ARCH).o	\
Index: trunk/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/init.c	(revision 39217)
+++ trunk/Ohana/src/opihi/cmd.data/init.c	(revision 39225)
@@ -86,4 +86,5 @@
 int medimage_command PROTO((int, char **));
 int mset             PROTO((int, char **));
+int needles          PROTO((int, char **));
 int peak             PROTO((int, char **));
 int periodogram      PROTO((int, char **));
@@ -261,4 +262,5 @@
   {1, "mset",         mset,             "insert a vector in an image"},
   {1, "imset",        mset,             "insert a vector in an image"},
+  {1, "needles",      needles,          "plot vectors needles"},
   {1, "parity",       parity,           "set image parity"},
   {1, "peak",         peak,             "find vector peak in range"},
Index: trunk/Ohana/src/opihi/cmd.data/needles.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/needles.c	(revision 39225)
+++ trunk/Ohana/src/opihi/cmd.data/needles.c	(revision 39225)
@@ -0,0 +1,121 @@
+# include "data.h"
+
+// generate needle plots for (x,y) (dx,dy)
+int needles (int argc, char **argv) {
+  
+  int kapa, N, Npts, valid, size, i;
+  Graphdata graphmode;
+  Vector *xvec, *yvec, *dxvec, *dyvec;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  float scale = 1.0;
+  if ((N = get_argument (argc, argv, "-scale"))) {
+    remove_argument (N, &argc, argv);
+    scale = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }    
+
+  valid  = (argc == 5);
+  valid |= (argc > 6) && !strcmp (argv[5], "where");
+  if (!valid) {
+    gprint (GP_ERR, "USAGE: needles <x> <y> <dx> <dy> [-scale scale] [style]\n");
+    gprint (GP_ERR, "   OR: needles <x> <y> <dx> <dy> [-scale scale] [style] where (condition)\n");
+    return (FALSE);
+  }
+
+  // tvec is used for logical test (truth vector)
+  Vector *tvec = NULL;
+  char *mask = NULL;
+  if (argc > 6) {
+    char *out = dvomath (argc - 6, &argv[6], &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);
+    }
+  }
+
+  graphmode.etype = 0;
+  graphmode.ptype = 100;
+  
+  /* find vectors */
+  if ((xvec  = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec  = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dxvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dyvec = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "vectors %s and %s not the same length\n", argv[1], argv[2]);
+    return (FALSE);
+  }
+  if (tvec && tvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "logic test vector not the same length as data vectors\n");
+    return (FALSE);
+  }
+  if (dxvec->Nelements != xvec->Nelements) goto mismatch;
+  if (dyvec->Nelements != xvec->Nelements) goto mismatch;
+
+  Npts = xvec[0].Nelements;
+  if (Npts == 0) {
+    if (tvec) DeleteVector (tvec);
+    return (TRUE);
+  }
+
+  if (tvec) {
+    Npts = 0;
+    ALLOCATE (mask, char, tvec->Nelements);
+    for (i = 0; i < tvec->Nelements; i++) {
+      mask[i] = (tvec->type == OPIHI_FLT) ? (tvec->elements.Flt[i] == 0.0) : (tvec->elements.Int[i] == 0.0);
+      if (!mask[i]) Npts ++;
+    }
+    if (Npts == 0) {
+      DeleteVector (tvec);
+      free (mask);
+      return TRUE;
+    }
+  }
+  Npts = 2*Npts;
+
+  // we need to generate the 2x length vectors
+  Vector *xfull = InitVector();
+  Vector *yfull = InitVector();
+  ResetVector (xfull, OPIHI_FLT, Npts);
+  ResetVector (yfull, OPIHI_FLT, Npts);
+
+  N = 0;
+  for (i = 0; i < xvec->Nelements; i++) {
+    if (mask && mask[i]) continue;
+    xfull->elements.Flt[N] = xvec->elements.Flt[i];
+    yfull->elements.Flt[N] = yvec->elements.Flt[i];
+    N ++;
+    myAssert (N <= Npts, "oops");
+    xfull->elements.Flt[N] = xvec->elements.Flt[i] + scale*dxvec->elements.Flt[i];
+    yfull->elements.Flt[N] = yvec->elements.Flt[i] + scale*dyvec->elements.Flt[i];
+    N ++;
+    myAssert (N <= Npts, "oops");
+  }    
+  myAssert (N == Npts, "oops");
+
+  if (!KapaPrepPlot (kapa, Npts, &graphmode)) return (FALSE);
+  PlotVectorSingle (kapa, xfull, NULL, "x");
+  PlotVectorSingle (kapa, yfull, NULL, "y");
+
+  if (tvec) {
+    free (mask);
+    DeleteVector (tvec);
+  }
+
+  FreeVector (xfull);
+  FreeVector (yfull);
+
+  return (TRUE);
+
+mismatch:
+  gprint (GP_ERR, "x,y and dx,dy lengths are mismatched\n");
+  return (FALSE);
+}
Index: trunk/Ohana/src/opihi/dvo/avmatch.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/avmatch.c	(revision 39217)
+++ trunk/Ohana/src/opihi/dvo/avmatch.c	(revision 39225)
@@ -328,4 +328,5 @@
   gprint (GP_ERR, "USAGE: avmatch (RA) (DEC) (RADIUS) field[,field,field...]\n");
   gprint (GP_ERR, "   OR: avmatch -coords (filename.fits) (RADIUS) field[,field,field...]\n");
+  gprint (GP_ERR, "   RADIUS is in arcseconds\n");
 
   if ((argc > N + 1) && !strcasecmp (argv[N+1], "fields")) {
Index: trunk/Ohana/src/opihi/dvo/imlist.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/imlist.c	(revision 39217)
+++ trunk/Ohana/src/opihi/dvo/imlist.c	(revision 39225)
@@ -21,4 +21,14 @@
   }
 
+  int VERBOSE = TRUE;
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    VERBOSE = FALSE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-q"))) {
+    VERBOSE = FALSE;
+    remove_argument (N, &argc, argv);
+  }
+
   TimeSelect = FALSE;
   if ((N = get_argument (argc, argv, "-time"))) {
@@ -35,5 +45,5 @@
     remove_argument (N, &argc, argv);
     TimeSelect = TRUE;
-    gprint (GP_ERR, "plotting in range %ds - %ds (%f seconds)\n", (int)tzero, (int)(tzero + trange), trange);
+    if (VERBOSE) gprint (GP_ERR, "plotting in range %ds - %ds (%f seconds)\n", (int)tzero, (int)(tzero + trange), trange);
   }
 
@@ -88,4 +98,6 @@
   GetTimeFormat (&TimeReference, &TimeFormat);
 
+  int Nfound = 0;
+
   for (j = 0; j < MAX_LIST; j++) {
     i = subset[j];
@@ -104,7 +116,13 @@
       XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
     }
-    gprint (GP_LOG, "%3lld %s %8lld %8.4f %8.4f %f %5d %2d %4.2f %5.3f %5.3f\n", 
-	    (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);
+    if (VERBOSE) gprint (GP_LOG, "%3lld %s %8lld %8.4f %8.4f %f %5d %2d %4.2f %5.3f %5.3f\n", 
+			 (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);
+
+    char name[80];
+    sprintf (name, "imlist:%d", Nfound);
+    set_str_variable (name, image[i].name);
+    Nfound ++;
   }
+  set_int_variable ("imlist:n", Nfound);
 
   FreeImagesDVO(image);
Index: trunk/Ohana/src/opihi/include/dvomath.h
===================================================================
--- trunk/Ohana/src/opihi/include/dvomath.h	(revision 39217)
+++ trunk/Ohana/src/opihi/include/dvomath.h	(revision 39225)
@@ -147,4 +147,5 @@
 Vector       *InitVector            PROTO((void));
 void          FreeVectorArray       PROTO((Vector **vec, int Nvec));
+void          FreeVector            PROTO((Vector *vec));
 int           CopyVector            PROTO((Vector *out, Vector *in));
 int           ResetVector           PROTO((Vector *vec, char type, int Nelements));
Index: trunk/Ohana/src/opihi/lib.shell/VectorOps.c
===================================================================
--- trunk/Ohana/src/opihi/lib.shell/VectorOps.c	(revision 39217)
+++ trunk/Ohana/src/opihi/lib.shell/VectorOps.c	(revision 39225)
@@ -15,4 +15,14 @@
 
 // this function is NOT thread protected : it is only used in startup and/or shutdown
+void FreeVector (Vector *vec) {
+
+  if (!vec) return;
+  if (vec->elements.Int) {
+    free (vec->elements.Int);
+  }
+  free (vec);
+}
+
+// this function is NOT thread protected : it is only used in startup and/or shutdown
 void FreeVectorArray (Vector **vec, int Nvec) {
 
@@ -21,9 +31,5 @@
   if (!vec) return;
   for (i = 0; i < Nvec; i++) {
-    if (!vec[i]) continue;
-    if (vec[i]->elements.Int) {
-      free (vec[i]->elements.Int);
-    }
-    free (vec[i]);
+    FreeVector (vec[i]);
   }
   free (vec);
Index: trunk/Ohana/src/relastro/include/relastro.h
===================================================================
--- trunk/Ohana/src/relastro/include/relastro.h	(revision 39217)
+++ trunk/Ohana/src/relastro/include/relastro.h	(revision 39225)
@@ -254,4 +254,8 @@
 int SRC_MEAS_TOOFEW; //catalog objects wich fewer detections then this are ignored
 double MIN_ERROR;
+
+double MIN_DISTANCE_MOD;  
+double MAX_DISTANCE_MOD;  
+double MAX_DISTANCE_MOD_ERR;
 
 int    IMFIT_TOO_FEW; // need more than this number of stars to fit an image
@@ -323,4 +327,7 @@
 PhotCode     *DCR_RED_PHOTCODE_POS, *DCR_RED_PHOTCODE_NEG; 
 int           DCR_RED_NSEC_POS,      DCR_RED_NSEC_NEG; 
+
+float *LoopWeight2MASS;
+float *LoopWeightTycho;
 
 int ImagSelect;
Index: trunk/Ohana/src/relastro/src/BrightCatalog.c
===================================================================
--- trunk/Ohana/src/relastro/src/BrightCatalog.c	(revision 39217)
+++ trunk/Ohana/src/relastro/src/BrightCatalog.c	(revision 39225)
@@ -159,6 +159,8 @@
     GET_COLUMN(uR,             "U_RA",           float);
     GET_COLUMN(uD,             "U_DEC",          float);
-    GET_COLUMN(duR,            "V_RA_ERR",       float);
-    GET_COLUMN(duD,            "V_DEC_ERR",      float);
+    GET_COLUMN(duR,            "U_RA_ERR",       float);
+    GET_COLUMN(duD,            "U_DEC_ERR",      float);
+    GET_COLUMN(uRgal,          "U_RA_GAL",       float);
+    GET_COLUMN(uDgal,          "U_DEC_GAL",      float);
     GET_COLUMN(P,              "PAR",            float);
     GET_COLUMN(dP,             "PAR_ERR",        float);
@@ -189,4 +191,5 @@
     ALLOCATE (average, Average, Nrow);
     for (i = 0; i < Nrow; i++) {
+      dvo_average_init (&average[i]);
       average[i].R               = R[i]               ;
       average[i].D               = D[i]               ;
@@ -197,4 +200,6 @@
       average[i].duR             = duR[i]             ;
       average[i].duD             = duD[i]             ;
+      average[i].uRgal           = uRgal[i]           ;
+      average[i].uDgal           = uDgal[i]           ;
       average[i].P               = P[i]               ;
       average[i].dP              = dP[i]              ;
@@ -230,4 +235,6 @@
     free (duR);
     free (duD);
+    free (uRgal);
+    free (uDgal);
     free (P);
     free (dP);
@@ -489,6 +496,8 @@
     gfits_define_bintable_column (&theader, "E", "U_RA",           "RA*cos(D) proper-motion", 	         		  "", 1.0, 0.0);
     gfits_define_bintable_column (&theader, "E", "U_DEC",          "DEC proper-motion", 	         	 	  "", 1.0, 0.0);
-    gfits_define_bintable_column (&theader, "E", "V_RA_ERR",       "RA*cos(D) p-m error", 	         	 	  "", 1.0, 0.0);
-    gfits_define_bintable_column (&theader, "E", "V_DEC_ERR",      "DEC p-m error", 	         	 		  "", 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "U_RA_ERR",       "RA*cos(D) p-m error", 	         	 	  "", 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "U_DEC_ERR",      "DEC p-m error", 	         	 		  "", 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "U_RA_GAL",       "RA*cos(D) p-m error", 	         	 	  "", 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "U_DEC_GAL",      "DEC p-m error", 	         	 		  "", 1.0, 0.0);
     gfits_define_bintable_column (&theader, "E", "PAR",            "parallax", 	                         		  "", 1.0, 0.0);
     gfits_define_bintable_column (&theader, "E", "PAR_ERR",        "parallax error", 	                 		  "", 1.0, 0.0);
@@ -526,4 +535,6 @@
     float    *duR           ; ALLOCATE (duR           , float   , catalog->Naverage);
     float    *duD           ; ALLOCATE (duD           , float   , catalog->Naverage);
+    float    *uRgal         ; ALLOCATE (uRgal         , float   , catalog->Naverage);
+    float    *uDgal         ; ALLOCATE (uDgal         , float   , catalog->Naverage);
     float    *P             ; ALLOCATE (P             , float   , catalog->Naverage);
     float    *dP            ; ALLOCATE (dP            , float   , catalog->Naverage);
@@ -560,4 +571,6 @@
       duR[i]             = average[i].duR             ;
       duD[i]             = average[i].duD             ;
+      uRgal[i]           = average[i].uRgal           ;
+      uDgal[i]           = average[i].uDgal           ;
       P[i]               = average[i].P               ;
       dP[i]              = average[i].dP              ;
@@ -591,6 +604,8 @@
     gfits_set_bintable_column (&theader, &ftable, "U_RA",           uR,              catalog->Naverage);
     gfits_set_bintable_column (&theader, &ftable, "U_DEC",          uD,              catalog->Naverage);
-    gfits_set_bintable_column (&theader, &ftable, "V_RA_ERR",       duR,             catalog->Naverage);
-    gfits_set_bintable_column (&theader, &ftable, "V_DEC_ERR",      duD,             catalog->Naverage);
+    gfits_set_bintable_column (&theader, &ftable, "U_RA_ERR",       duR,             catalog->Naverage);
+    gfits_set_bintable_column (&theader, &ftable, "U_DEC_ERR",      duD,             catalog->Naverage);
+    gfits_set_bintable_column (&theader, &ftable, "U_RA_GAL",       uRgal,           catalog->Naverage);
+    gfits_set_bintable_column (&theader, &ftable, "U_DEC_GAL",      uDgal,           catalog->Naverage);
     gfits_set_bintable_column (&theader, &ftable, "PAR",            P,               catalog->Naverage);
     gfits_set_bintable_column (&theader, &ftable, "PAR_ERR",        dP,              catalog->Naverage);
@@ -604,5 +619,5 @@
     gfits_set_bintable_column (&theader, &ftable, "NMEASURE",       Nmeasure,        catalog->Naverage);
     gfits_set_bintable_column (&theader, &ftable, "NMISSING",       Nmissing,        catalog->Naverage);
-    gfits_set_bintable_column (&theader, &ftable, "NGALPHOT",      Ngalphot,       catalog->Naverage);
+    gfits_set_bintable_column (&theader, &ftable, "NGALPHOT",       Ngalphot,        catalog->Naverage);
     gfits_set_bintable_column (&theader, &ftable, "OFF_MEASURE",    measureOffset,   catalog->Naverage);
     gfits_set_bintable_column (&theader, &ftable, "OFF_MISSING",    missingOffset,   catalog->Naverage);
@@ -624,4 +639,6 @@
     free (duR);
     free (duD);
+    free (uRgal);
+    free (uDgal);
     free (P);
     free (dP);
Index: trunk/Ohana/src/relastro/src/ConfigInit.c
===================================================================
--- trunk/Ohana/src/relastro/src/ConfigInit.c	(revision 39217)
+++ trunk/Ohana/src/relastro/src/ConfigInit.c	(revision 39225)
@@ -35,4 +35,8 @@
   if (!ScanConfig (config, "RELASTRO_DPOS_MAX",      "%lf", 0, &DPOS_MAX))	   DPOS_MAX = 6.0;    
   if (!ScanConfig (config, "ADDSTAR_RADIUS",         "%lf", 0, &ADDSTAR_RADIUS))   ADDSTAR_RADIUS = 1.0;
+
+  if (!ScanConfig (config, "RELASTRO_MIN_DISTANCE_MOD",     "%lf", 0, &MIN_DISTANCE_MOD))     MIN_DISTANCE_MOD     =  7.5;
+  if (!ScanConfig (config, "RELASTRO_MAX_DISTANCE_MOD",     "%lf", 0, &MAX_DISTANCE_MOD))     MAX_DISTANCE_MOD     = 15.0;
+  if (!ScanConfig (config, "RELASTRO_MAX_DISTANCE_MOD_ERR", "%lf", 0, &MAX_DISTANCE_MOD_ERR)) MAX_DISTANCE_MOD_ERR =  1.0;
 
   if (!ScanConfig (config, "USE_FIXED_PIXCOORDS", "%d", 0, &USE_FIXED_PIXCOORDS))  USE_FIXED_PIXCOORDS = FALSE;
Index: trunk/Ohana/src/relastro/src/GetAstromError.c
===================================================================
--- trunk/Ohana/src/relastro/src/GetAstromError.c	(revision 39217)
+++ trunk/Ohana/src/relastro/src/GetAstromError.c	(revision 39225)
@@ -73,74 +73,16 @@
   int has2MASS = USE_GALAXY_MODEL &&  isImage && (measure[0].dbFlags & ID_MEAS_OBJECT_HAS_2MASS);
 
-  // serious hack: if the object has 2MASS, we set this internal bit and adjust the
+  // modest hack: if the object has 2MASS or Tycho, we set this internal bit and adjust the
   // weight to ensure the image is tied down to the 2mass frame
 
-  if (has2MASS) {
-    switch (Nloop) {
-      case 0:
-	dPtotal = dPtotal / 1000.0;
-	break;
-      case 1:
-	dPtotal = dPtotal / 300.0;
-	break;
-      case 2:
-	dPtotal = dPtotal / 100.0;
-	break;
-      case 3:
-	dPtotal = dPtotal / 30.0;
-	break;
-      case 4:
-	dPtotal = dPtotal / 10.0;
-	break;
-      case 5:
-	dPtotal = dPtotal / 10.0;
-	break;
-      default:
-	break;
-    }
+  if (has2MASS && LoopWeight2MASS) {
+    dPtotal = dPtotal / LoopWeight2MASS[Nloop];
   }
-  if (is2MASS) {
-    switch (Nloop) {
-      case 0:
-	dPtotal = dPtotal / 1000.0;
-	break;
-      case 1:
-	dPtotal = dPtotal / 300.0;
-	break;
-      case 2:
-	dPtotal = dPtotal / 100.0;
-	break;
-      case 3:
-	dPtotal = dPtotal / 30.0;
-	break;
-      case 4:
-	dPtotal = dPtotal / 10.0;
-	break;
-      case 5:
-	dPtotal = dPtotal / 10.0;
-	break;
-      default:
-	break;
-    }
+  if (is2MASS && LoopWeight2MASS) {
+    dPtotal = dPtotal / LoopWeight2MASS[Nloop];
   }
-  if (isTycho) {
-    switch (Nloop) {
-      case 0:
-      case 1:
-	dPtotal = dPtotal / 200.0;
-	break;
-      case 2:
-      case 3:
-	dPtotal = dPtotal / 100.0;
-	break;
-      case 4:
-      case 5:
-	dPtotal = dPtotal / 50.0;
-	break;
-      default:
-	break;
-    }
+  if (isTycho && LoopWeightTycho) {
+    dPtotal = dPtotal / LoopWeightTycho[Nloop];
   }
-
   return (dPtotal);
 }
@@ -197,8 +139,29 @@
 
   dPtotal = MAX (dPtotal, MIN_ERROR);
+
+  // early on, we want 2MASS and Tycho to have a very high weight.  This will force images
+  // to match the 2MASS / Tycho / ICRS reference frame.  As Nloop gets higher, the weight
+  // needs to drop to allow the ps1 measurements to drive the solution
+  int is2MASS  = USE_GALAXY_MODEL && !isImage && (measure[0].photcode >= 2011) && (measure[0].photcode <= 2013);
+  int isTycho  = USE_GALAXY_MODEL && !isImage && (measure[0].photcode >= 2020) && (measure[0].photcode <= 2021);
+  int has2MASS = USE_GALAXY_MODEL &&  isImage && (measure[0].dbFlags & ID_MEAS_OBJECT_HAS_2MASS);
+
+  // modest hack: if the object has 2MASS or Tycho, we set this internal bit and adjust the
+  // weight to ensure the image is tied down to the 2mass frame
+
+  if (has2MASS && LoopWeight2MASS) {
+    dPtotal = dPtotal / LoopWeight2MASS[Nloop];
+  }
+  if (is2MASS && LoopWeight2MASS) {
+    dPtotal = dPtotal / LoopWeight2MASS[Nloop];
+  }
+  if (isTycho && LoopWeightTycho) {
+    dPtotal = dPtotal / LoopWeightTycho[Nloop];
+  }
+
   return (dPtotal);
 }
 
-/* for a long time, psphot was either not reported position errors, or was reporting
+/* for a long time, psphot was either not reporting position errors, or was reporting
  * completely wrong astrometry errors.  This function lets us handle, in the
  * configuration, different strategies to generating a position error 
Index: trunk/Ohana/src/relastro/src/args.c
===================================================================
--- trunk/Ohana/src/relastro/src/args.c	(revision 39217)
+++ trunk/Ohana/src/relastro/src/args.c	(revision 39225)
@@ -4,4 +4,5 @@
 void usage_merge_source (void);
 void usage_merge_source_id (char *name);
+float *ParseLoopWeights (char *rawlist);
 
 int args (int argc, char **argv) {
@@ -529,4 +530,19 @@
     remove_argument (N, &argc, argv);
     NLOOP = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  // e.g., -loop-weights-2mass 1000,300,300,200,200,100
+  // NOTE: this must come after -nloop above
+  LoopWeight2MASS = NULL;
+  if ((N = get_argument (argc, argv, "-loop-weights-2mass"))) {
+    remove_argument (N, &argc, argv);
+    LoopWeight2MASS = ParseLoopWeights (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  LoopWeightTycho = NULL;
+  if ((N = get_argument (argc, argv, "-loop-weights-tycho"))) {
+    remove_argument (N, &argc, argv);
+    LoopWeightTycho = ParseLoopWeights (argv[N]);
     remove_argument (N, &argc, argv);
   }
@@ -999,2 +1015,33 @@
 }
 
+float *ParseLoopWeights (char *rawlist) {
+
+  float *weights = NULL;
+  ALLOCATE (weights, float, NLOOP);
+
+  int Nloop = 0;
+
+  /* parse the comma-separated list of photcodes */
+  char *myList = strcreate(rawlist);
+  char *list = myList;
+  char *entry = NULL;
+  char *ptr = NULL;
+  while ((Nloop < NLOOP) && ((entry = strtok_r (list, ",", &ptr)) != NULL)) {
+    list = NULL; // pass NULL on successive strtok_r calls
+
+    weights[Nloop] = atof(entry);
+    Nloop ++;
+  }
+  free (myList);
+
+  if (Nloop == 0) {
+    fprintf (stderr, "syntax error parsing weights: %s\n", rawlist);
+    exit (3);
+  }
+
+  while (Nloop < NLOOP) {
+    weights[Nloop] = weights[Nloop - 1];
+    Nloop ++;
+  }
+  return weights;
+}
Index: trunk/Ohana/src/relastro/src/bcatalog.c
===================================================================
--- trunk/Ohana/src/relastro/src/bcatalog.c	(revision 39217)
+++ trunk/Ohana/src/relastro/src/bcatalog.c	(revision 39225)
@@ -117,4 +117,13 @@
       if (!isfinite(catalog[0].average[i].uRgal)) continue;
       if (!isfinite(catalog[0].average[i].uDgal)) continue;
+      
+      // filter stars which are not well-handled by the galactic motion model
+      int mStarpar = catalog[0].average[i].starparOffset;
+      myAssert (mStarpar < catalog[0].Nstarpar, "oops");
+      
+      StarPar *starpar = &catalog[0].starpar[mStarpar];
+      if (starpar->DistMag  < MIN_DISTANCE_MOD) continue;
+      if (starpar->DistMag  > MAX_DISTANCE_MOD) continue;
+      if (starpar->dDistMag > MAX_DISTANCE_MOD_ERR) continue;
     }
 
Index: trunk/Ohana/src/relastro/src/launch_region_hosts.c
===================================================================
--- trunk/Ohana/src/relastro/src/launch_region_hosts.c	(revision 39217)
+++ trunk/Ohana/src/relastro/src/launch_region_hosts.c	(revision 39225)
@@ -134,4 +134,21 @@
     if (MaxMeanOffset != 10.0) strextend (&command, "-max-mean-offset  %f", MaxMeanOffset);
 
+    if (LoopWeight2MASS) {
+      char *weightline = NULL;
+      for (i = 0; i < NLOOP; i++) {
+	strextend (&weightline, "%f,", LoopWeight2MASS[i]);
+      }
+      strextend (&command, "-loop-weights-2mass %s", weightline);
+      free (weightline);
+    }
+    if (LoopWeightTycho) {
+      char *weightline = NULL;
+      for (i = 0; i < NLOOP; i++) {
+	strextend (&weightline, "%f,", LoopWeightTycho[i]);
+      }
+      strextend (&command, "-loop-weights-tycho %s", weightline);
+      free (weightline);
+    }
+
     strextend (&command, "-D RELASTRO_SRC_MEAS_TOOFEW %d", SRC_MEAS_TOOFEW);
     strextend (&command, "-D RELASTRO_SIGMA_LIM %f", SIGMA_LIM);
Index: trunk/Ohana/src/relastro/src/load_catalogs.c
===================================================================
--- trunk/Ohana/src/relastro/src/load_catalogs.c	(revision 39217)
+++ trunk/Ohana/src/relastro/src/load_catalogs.c	(revision 39225)
@@ -44,4 +44,8 @@
     pcatalog->catflags  = DVO_LOAD_AVERAGE | DVO_LOAD_MEASURE | DVO_LOAD_SECFILT; // don't need to load all data at this point
     pcatalog->Nsecfilt  = GetPhotcodeNsecfilt ();
+
+    if (USE_GALAXY_MODEL) {
+      pcatalog->catflags = pcatalog->catflags | DVO_LOAD_STARPAR;
+    }
 
     // loads Average, Measure, SecFilt
@@ -171,4 +175,7 @@
     strextend (&command, " -minerror %f", MIN_ERROR);
     strextend (&command, " -D RELASTRO_SIGMA_LIM %f", SIGMA_LIM);
+    strextend (&command, " -D RELASTRO_MIN_DISTANCE_MOD %f",     MIN_DISTANCE_MOD);
+    strextend (&command, " -D RELASTRO_MAX_DISTANCE_MOD %f",     MAX_DISTANCE_MOD);
+    strextend (&command, " -D RELASTRO_MAX_DISTANCE_MOD_ERR %f", MAX_DISTANCE_MOD_ERR);
 
     if (FIT_MODE == FIT_PM_ONLY)  	 strextend (&command, "-pm");
Index: trunk/Ohana/src/uniphot/doc/galmotion.sh
===================================================================
--- trunk/Ohana/src/uniphot/doc/galmotion.sh	(revision 39225)
+++ trunk/Ohana/src/uniphot/doc/galmotion.sh	(revision 39225)
@@ -0,0 +1,321 @@
+
+# global constants:
+$iFkap    = 0.001 / 4.74047; # (km/sec/kpc) / (arcsec/ year)
+
+## FEAST-HIP
+if (1)
+  $A_oort = +14.82; # km/sec/kpc
+  $B_oort = -12.37; # km/sec/kpc
+  $U_sol  =   9.32; # km/sec
+  $V_sol  =  11.18; # km/sec
+  $W_sol  =   7.61; # km/sec
+end
+
+## ROESSER:
+if (0)
+  $A_oort = +14.50; # km/sec/kpc
+  $B_oort = -13.00; # km/sec/kpc
+  $U_sol  =   9.44; # km/sec
+  $V_sol  =  11.90; # km/sec
+  $W_sol  =   7.20; # km/sec
+end
+
+# galactic to celestial
+$trans_phi = -62.8717488056;
+$trans_Xo  = 282.8594812080;
+$trans_xo  =  32.9319185700;
+
+$trans_sin_phi_cos_Xo = dsin($trans_phi)*dcos($trans_Xo);
+$trans_sin_phi_sin_Xo = dsin($trans_phi)*dsin($trans_Xo);
+$trans_cos_phi        = dcos($trans_phi);
+
+$trans_cos_phi_cos_Xo = dcos($trans_phi)*dcos($trans_Xo);
+$trans_cos_phi_sin_Xo = dcos($trans_phi)*dsin($trans_Xo);
+$trans_sin_phi        = dsin($trans_phi);
+
+$trans_cos_Xo 	      = dcos($trans_Xo);
+$trans_sin_Xo 	      = dsin($trans_Xo);
+
+$disk_radius = 10; # 10 kpc radius disk
+$disk_scale = 0.5; # 200 pc scale height
+
+$halo_scale = 2.0; # 2000 pc scale height
+
+# generate a collection of stars in R,D [L,B] with a range of distances
+# generate the predicted proper motions
+
+macro mkstars_halo
+  if ($0 != 4)
+    echo "USAGE: mkstars_disk (Nstars) (Dm_err) (Nsample)"
+    break
+  end
+
+  local Nstars dDm_o Nsample
+
+  $Nstars = $1
+  $dDm_o = $2
+  $Nsample = $3
+
+  # halo stars are uniformly sampled in a gaussian halo
+  gaussdev Dhalo $Nstars 0.0 $halo_scale
+  set Dm = 5*log(Dhalo * 100)
+  
+  create seq 0 $Nstars
+  set phi   = 2*rnd(seq) - 1
+
+  set L = 360*rnd(seq)
+  set B = dasin(phi)
+end
+
+macro mkstars_disk
+  if ($0 != 5)
+    echo "USAGE: mkstars_disk (Nstars) (Dm_err) (Nsample) (minDm)"
+    break
+  end
+
+  local Nstars dDm_o Nsample minDm
+
+  $Nstars = $1
+  $dDm_o = $2
+  $Nsample = $3
+  $minDm = $4
+
+  gaussdev Zgal $Nstars 0.0 $disk_scale
+  set rgal = $disk_radius * rnd(Zgal)
+
+  set B = atan2(Zgal , rgal)
+  set L = 360*rnd(Zgal)
+
+  set d_kpc_o = sqrt(rgal^2 + Zgal^2)
+
+  set Dm = 5*log(d_kpc_o * 100)
+
+  subset Bs  = B  if (Dm > $minDm)
+  subset Ls  = L  if (Dm > $minDm)
+  subset Dms = Dm if (Dm > $minDm)
+
+  mkmotion_dmerr Ls Bs Dms $dDm_o $Nsample
+end
+
+macro mkstars_uniform
+  if ($0 != 5)
+    echo "USAGE: mkstars_uniform (Nstars) (Rmax) (Dm_err) (Nsample)"
+    break
+  end
+
+  $Nstars = $1
+  $Rmax = $2
+  $dDm_o = $3
+
+  create seq 0 $Nstars
+  set phi   = 2*rnd(seq) - 1
+
+  # uniform density
+  # R ~ R_max^3/2
+  set d_kpc_o = $Rmax*rnd(seq)^(1/3)
+  set Dm = 5*log(d_kpc_o * 100)
+
+  set L = 360*rnd(seq)
+  set B = dasin(phi)
+
+  mkmotion_dmerr L B Dm $3 $4
+end
+
+macro mkstars_single_dm
+  if ($0 != 5)
+    echo "USAGE: mkstars (Nstars) (Dm) (Dm_err) (Nsample)"
+    break
+  end
+
+  create seq 0 $1
+  set phi   = 2*rnd(seq) - 1
+
+  set d_kpc = ten(0.2*$2 - 2) + zero(seq)
+  set Dm = 5*log(d_kpc * 100)
+
+  set L = 360*rnd(seq)
+  set B = dasin(phi)
+
+  mkmotion_dmerr L B Dm $3 $4
+end
+
+# given L,B,Dm and a Dm_err value, find duL, duB
+macro mkmotion_dmerr
+  if ($0 != 6)
+    echo "USAGE: mkmotion (L) (B) (Dm) (Dm_err) (Nsample)"
+    break
+  end
+
+  local i Dm_err Nstars 
+
+  set  _L = $1
+  set  _B = $2
+  set _Dm = $3
+  $Dm_err = $4
+  $Nsample = $5
+
+  $Nstars = _L[]
+
+  set d_kpc_o = ten(0.2*_Dm - 2)
+
+  set R = _L
+  set D = _B
+  csystem G C R D
+
+  set uL_gal =     ($A_oort * dcos(2.0*_L) + $B_oort) * dcos(_B*1.0) * $iFkap;
+  set uB_gal = -0.5*$A_oort * dsin(2.0*_L) *            dsin(_B*2.0) * $iFkap;
+
+  set uL_sol =  ($U_sol * dsin(_L) - $V_sol * dcos(_L))                             * $iFkap / d_kpc_o;
+  set uB_sol = (($U_sol * dcos(_L) + $V_sol * dsin(_L))*dsin(_B) - $W_sol*dcos(_B)) * $iFkap / d_kpc_o;
+
+  set uL_o = uL_gal + uL_sol
+  set uB_o = uB_gal + uB_sol
+
+  set uL_sol_o = uL_sol
+  set uB_sol_o = uB_sol
+
+  # create a buffer to store the results : results for each star are in the y-dir, 
+  mcreate resultsL $Nstars $Nsample
+  mcreate resultsB $Nstars $Nsample
+
+  # now MC a number of distances
+  for i 0 $Nsample
+    gaussdev dDm $Nstars 0.0 $Dm_err
+    set Dm_x = _Dm + dDm
+    set d_kpc = ten(0.2*Dm_x - 2)
+    
+    set uL_sol =  ($U_sol * dsin(_L) - $V_sol * dcos(_L))                             * $iFkap / d_kpc;
+    set uB_sol = (($U_sol * dcos(_L) + $V_sol * dsin(_L))*dsin(_B) - $W_sol*dcos(_B)) * $iFkap / d_kpc;
+
+    set duL = uL_sol - uL_sol_o
+    set duB = uB_sol - uB_sol_o
+
+    mset resultsL duL -x $i    
+    mset resultsB duB -x $i    
+  end
+    
+  set duL = zero(uL_o)
+  set duB = zero(uB_o)
+  set uLoff = zero(uL_o)
+  set uBoff = zero(uB_o)
+
+  for i 0 $Nstars
+    mget resultsL tmp -y $i
+    vstat -q tmp
+    
+    uLoff[$i] = $MEAN
+    duL[$i] = $SIGMA
+
+    mget resultsB tmp -y $i
+    vstat -q tmp
+    
+    uBoff[$i] = $MEAN
+    duB[$i] = $SIGMA  
+  end
+end
+
+macro mkstars
+  if ($0 != 3)
+    echo "USAGE: mkstars (Nstars) (d kpc)"
+    break
+  end
+
+  create seq 0 $1
+  set phi   = 2*rnd(seq) - 1
+
+  set L = 360*rnd(seq)
+  set B = dasin(phi)
+
+  set R = L
+  set D = B
+  csystem G C R D
+
+  set uL_gal =     ($A_oort * dcos(2.0*L) + $B_oort) * dcos(B*1.0) * $iFkap;
+  set uB_gal = -0.5*$A_oort * dsin(2.0*L) *            dsin(B*2.0) * $iFkap;
+
+  set uL_sol =  ($U_sol * dsin(L) - $V_sol * dcos(L))                           * $iFkap / $2;
+  set uB_sol = (($U_sol * dcos(L) + $V_sol * dsin(L))*dsin(B) - $W_sol*dcos(B)) * $iFkap / $2;
+
+  set uL = uL_gal + uL_sol
+  set uB = uB_gal + uB_sol
+
+  # C1, C2 are from http://arxiv.org/pdf/1306.2945v2.pdf
+  set C1 =  dcos(D)*$trans_cos_phi + dsin(D)*(dcos(R)*$trans_sin_phi_sin_Xo - dsin(R)*$trans_sin_phi_cos_Xo);
+  set C2 =                                -1*(dcos(R)*$trans_sin_phi_cos_Xo + dsin(R)*$trans_sin_phi_sin_Xo);
+
+  set cosBinv = 1.0 / sqrt(C1*C1 + C2*C2);
+
+  set uR = cosBinv * (C1 * uL - C2 * uB);
+  set uD = cosBinv * (C1 * uB + C2 * uL);
+end
+
+macro pltstars
+  if ($0 != 2)
+    echo "USAGE: pltstars (scale)"
+    break
+  end
+
+  resize -n galactic 1600 800
+  region 0 0 90 ait; cgrid -c red
+
+  cneedles L B uL uB -scale $1 -c black -lw 0
+  cplot L B -pt 0 -sz 0.3 -c black
+  label +x Galactic -fn courier 24
+
+  resize -n celestial 1600 800
+  region 0 0 90 ait; cgrid -c red
+
+  style -c red -lw 0 -pt 0 -sz 0.3; cggrid; style -c blue; galactic
+  cplot R D -pt 0 -sz 0.3 -c black
+  cneedles R D uR uD -scale $1 -c black -lw 0
+  label +x Celestial -fn courier 24
+end
+
+macro cggrid
+
+ local delta off
+ $delta = 2.0
+
+ delete _lgrid _bgrid
+
+ create _tgrid 0 360 $delta
+ set _n = ramp(_tgrid) 
+ set _lgrid_t = _tgrid * (_n % 2) + (_tgrid - $delta) * (_n % 2 == 0)
+
+ for off -70 90 20
+   set _bgrid_t = zero(_lgrid_t) + $off
+   concat _lgrid_t _lgrid
+   concat _bgrid_t _bgrid
+ end
+
+ create _tgrid -90 90 $delta
+ set _n = ramp(_tgrid) 
+ set _bgrid_t = _tgrid * (_n % 2) + (_tgrid - $delta) * (_n % 2 == 0)
+
+ for off 0 360 30
+   set _lgrid_t = zero(_bgrid_t) + $off
+   concat _lgrid_t _lgrid
+   concat _bgrid_t _bgrid
+ end
+
+ csystem G C _lgrid _bgrid
+ cplot _lgrid _bgrid -pt 100
+end
+
+
+macro check.region
+  if ($0 != 6)
+    echo "USAGE: check.region (Rmin) (Rmax) (Dmin) (Dmax) (dist)"
+    break
+  end
+  
+  mkstars 10000 $5
+
+  set keep = (R > $1) && (R < $2) && (D > $3) && (D < $4)
+  subset  Rs =  R if keep
+  subset  Ds =  D if keep
+  subset uRs = uR if keep
+  subset uDs = uD if keep
+  lim -0.01 0.01 -0.01 0.01; clear; box; plot uRs uDs -pt 0 -sz 0.5
+  dot -0.003 -0.004 -pt 7 -c red -sz 4
+end
Index: trunk/Ohana/src/uniphot/src/initialize_setgalmodel.c
===================================================================
--- trunk/Ohana/src/uniphot/src/initialize_setgalmodel.c	(revision 39217)
+++ trunk/Ohana/src/uniphot/src/initialize_setgalmodel.c	(revision 39225)
@@ -45,5 +45,5 @@
 
   // XXX add to config?
-  if (!InitGalaxyModel ("ROESER")) {
+  if (!InitGalaxyModel ("FEAST-HIPPARCOS")) {
     fprintf (stderr, "failed to init galaxy model\n");
     exit (2);
Index: trunk/Ohana/src/uniphot/src/setgalmodel.c
===================================================================
--- trunk/Ohana/src/uniphot/src/setgalmodel.c	(revision 39217)
+++ trunk/Ohana/src/uniphot/src/setgalmodel.c	(revision 39225)
@@ -11,5 +11,9 @@
   status = update_dvo_setgalmodel ();
 
-  if (!status) exit (1);
+  if (!status) {
+    fprintf (stderr, "ERROR: problem running setgalmodel\n");
+    exit (1);
+  }
+  fprintf (stderr, "SUCCESS running setgalmodel\n");
   exit (0);
 }
Index: trunk/Ohana/src/uniphot/src/setgalmodel_client.c
===================================================================
--- trunk/Ohana/src/uniphot/src/setgalmodel_client.c	(revision 39217)
+++ trunk/Ohana/src/uniphot/src/setgalmodel_client.c	(revision 39225)
@@ -17,4 +17,5 @@
 
   update_dvo_setgalmodel ();
+  fprintf (stderr, "SUCCESS running setgalmodel_client\n");
 
   exit (0);
Index: trunk/Ohana/src/uniphot/src/update_catalog_setgalmodel.c
===================================================================
--- trunk/Ohana/src/uniphot/src/update_catalog_setgalmodel.c	(revision 39217)
+++ trunk/Ohana/src/uniphot/src/update_catalog_setgalmodel.c	(revision 39225)
@@ -28,5 +28,6 @@
     if (fabs(starpar->FeH) > 99.0) continue;
 
-    double distance = pow(10.0, 0.2*(starpar->DistMag + 5.0));
+    // NOTE: distance is in kiloparsec
+    double distance = pow(10.0, 0.2*(starpar->DistMag + 5.0)) / 1000.0;
 
     double Lrad = starpar->galLon * RAD_DEG;
Index: trunk/Ohana/src/uniphot/src/update_dvo_setgalmodel.c
===================================================================
--- trunk/Ohana/src/uniphot/src/update_dvo_setgalmodel.c	(revision 39217)
+++ trunk/Ohana/src/uniphot/src/update_dvo_setgalmodel.c	(revision 39225)
@@ -37,5 +37,5 @@
     dvo_catalog_init (&catalog, TRUE);
     catalog.filename  = HOST_ID ? localFilename : skylist[0].filename[i];
-    catalog.catflags  = DVO_LOAD_AVERAGE | DVO_LOAD_MEASURE | DVO_LOAD_MISSING | DVO_LOAD_SECFILT | DVO_LOAD_STARPAR;
+    catalog.catflags  = DVO_LOAD_AVERAGE | DVO_LOAD_STARPAR;
     catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
 
