Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/include/addstar.h
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/include/addstar.h	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/include/addstar.h	(revision 37395)
@@ -20,5 +20,5 @@
 # define IN_REGION(R,D) ( \
 ((D) >= region[0].Dmin) && ((D) < region[0].Dmax) && \
-((R) >= region[0].Rmin)  && ((R) < region[0].Rmax))
+((R) >= region[0].Rmin) && ((R) < region[0].Rmax))
 
 /* grab named photcode */
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/include/loadstarpar.h
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/include/loadstarpar.h	(revision 37395)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/include/loadstarpar.h	(revision 37395)
@@ -0,0 +1,12 @@
+
+typedef struct {
+  double R, D;
+  StarPar starpar;
+  int flag; // XXX how is this used?
+  int found; // assigned to an object?
+} StarPar_Stars;
+
+int   HOST_ID
+char *HOSTDIR;
+char *CPT_FILE;
+char *INPUT;
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/args_loadstarpar.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/args_loadstarpar.c	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/args_loadstarpar.c	(revision 37395)
@@ -85,4 +85,100 @@
 }
 
+AddstarClientOptions args_loadstarpar_client (int argc, char **argv, AddstarClientOptions options) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  PARALLEL = FALSE;
+  PARALLEL_MANUAL = FALSE;
+  PARALLEL_SERIAL = FALSE;
+
+  HOST_ID = 0;
+  if ((N = get_argument (argc, argv, "-hostID"))) {
+    remove_argument (N, &argc, argv);
+    HOST_ID = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!HOST_ID) help_client();
+
+  HOSTDIR = NULL;
+  if ((N = get_argument (argc, argv, "-hostdir"))) {
+    remove_argument (N, &argc, argv);
+    HOSTDIR = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!HOSTDIR) help_client();
+
+  CPT_FILE = NULL;
+  if ((N = get_argument (argc, argv, "-cpt"))) {
+    remove_argument (N, &argc, argv);
+    CPT_FILE = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!CPT_FILE) help_client();
+  
+  INPUT = NULL;
+  if ((N = get_argument (argc, argv, "-input"))) {
+    remove_argument (N, &argc, argv);
+    INPUT = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!INPUT) help_client();
+
+  /* we do not allow a subset to be extracted -- all or nothing, babe */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax= 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+
+  /* only add to existing objects */
+  options.only_match = FALSE;
+  if ((N = get_argument (argc, argv, "-only-match"))) {
+    options.only_match = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* replace measurement, don't duplicate (ref/cat only) */
+  options.replace = FALSE;
+  if ((N = get_argument (argc, argv, "-replace"))) {
+    options.replace = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* other addstar options which cannot be used in loadstarpar */
+  options.photcode = 0;
+  options.timeref = 0; 
+  options.mosaic = FALSE;
+  options.skip_missed = FALSE;
+  options.closest = FALSE;
+  options.nosort = FALSE;
+  options.update = FALSE;
+  options.only_images = FALSE;
+  options.calibrate = FALSE;
+  options.quality_airmass = FALSE;
+  ACCEPT_ASTROM = FALSE;
+  FORCE_READ = FALSE;
+  TEXTMODE = FALSE;
+  SUBPIX = FALSE;
+  DUMP = NULL;
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: loadstarpar_client -cpt (file) -input (file)\n");
+    exit (2);
+  }
+  return (options);
+}
+
 static void help () {
 
@@ -98,2 +194,16 @@
   exit (2);
 }
+
+static void help_client () {
+
+  fprintf (stderr, "USAGE: loadstarpar_client -D CATDIR catdir -hostID ID -hostdir (dir) -cpt (filename) -input (input) [options]\n");
+  fprintf (stderr, "  add data from stellar parameter file to DVO\n\n");
+
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -only-match           	  : only add measurements to existing objects\n");
+  fprintf (stderr, "  -replace              	  : replace time/photcode measurements (no duplication)\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/find_matches_starpar.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/find_matches_starpar.c	(revision 37395)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/find_matches_starpar.c	(revision 37395)
@@ -0,0 +1,229 @@
+# include "addstar.h"
+# include "loadstarpar.h"
+
+// we find matching stars by (R,D).  we add the starpar to the array of starpars with appropriate links.  
+int find_matches_starpar (SkyRegion *region, StarPar_Stars *stars, int Nstars, Catalog *catalog, AddstarClientOptions options) {
+  
+  off_t i, j, n, N, J, Jmin, status, Nstars;
+  double RADIUS, RADIUS2, Rmin;
+  double *X1, *Y1, *X2, *Y2;
+  double dX, dY, dR;
+  off_t *N1, *N2;
+  off_t Nave, NAVE, Nstarpar, NSTARPAR, Nmatch;
+
+  /** allocate local arrays (stars) **/
+  ALLOCATE (X1, double, Nstars);
+  ALLOCATE (Y1, double, Nstars);
+  ALLOCATE (N1, off_t,  Nstars);
+
+  /** allocate local arrays (catalog) **/
+  NAVE = Nave = catalog[0].Naverage;
+  ALLOCATE (X2, double, NAVE);
+  ALLOCATE (Y2, double, NAVE);
+  ALLOCATE (N2, off_t,  NAVE);
+
+  ALLOCATE (catalog[0].found_t, off_t, NAVE);
+
+  /* internal counters */
+  Nmatch = 0;
+  NSTARPAR = Nstarpar = catalog[0].Nstarpar;
+
+  // current max obj ID for this catalog
+  unsigned int objID = catalog[0].objID;
+  unsigned int catID = catalog[0].catID;
+
+  int Nsecfilt = catalog[0].Nsecfilt;
+
+  /* project onto rectilinear grid with 1 arcsec pixels. the choice of ARC projection has
+   * the advantage that every point in R,D has a mapping to a unique X,Y.  However, note
+   * that not all possible X,Y points map back to R,D and the local plate scale changes
+   * far from the projection pole. We use the center of the region (catalog) for crval1,2.
+   */
+  Coords tcoords;
+  InitCoords (&tcoords, "DEC--ARC");
+  tcoords.crval1 = 0.5*(region[0].Rmin + region[0].Rmax);
+  tcoords.crval2 = (region[0].Dmax < 90) ? 0.5*(region[0].Dmin + region[0].Dmax) : 90.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+
+  /* build spatial index (RA sort) referencing input array sequence */
+  for (i = 0; i < Nstars; i++) {
+    status = RD_to_XY (&X1[i], &Y1[i], stars[i].R, stars[i].D, &tcoords);
+    N1[i] = i;
+  }
+  sort_coords_index (X1, Y1, N1, Nstars);
+
+  /* build spatial index (RA sort) */
+  for (i = 0; i < Nave; i++) {
+    RD_to_XY (&X2[i], &Y2[i], catalog[0].average[i].R, catalog[0].average[i].D, &tcoords);
+    N2[i] = i;
+    catalog[0].found_t[N2[i]] = -1;
+  }
+  sort_coords_index (X2, Y2, N2, Nave);
+
+  /* choose a radius for matches */
+  RADIUS = options.radius; /* provided by config */
+  RADIUS2 = RADIUS*RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nstars) && (j < Nave); ) {
+    if (!finite(X1[i]) || !finite(Y1[i])) { 
+      i++; 
+      continue;
+    }
+    if (!finite(X2[j]) || !finite(Y2[j])) { 
+      j++; 
+      continue;
+    }
+    
+    /* negative dX: j is too large */
+    dX = X1[i] - X2[j];
+    if (dX <= -1.02*RADIUS) {
+      i++;
+      continue;
+    }
+    /* positive dX, i is too large */
+    if (dX >= 1.02*RADIUS) {
+      j++;
+      continue;
+    }
+
+    if (stars[N1[i]].found != -1) {
+      /* this star has already been assigned to an object in this or another catalog */
+      i++;
+      continue;
+    }
+
+    /* this block will match a given detection to the closest object within range of that detection.
+       XXX note that this matches ALL detections within range of the single object to that same object 
+       this is bad, but I cannot just go in linear order (ie, mark off each object as they are
+       used).  I should make a list of all Nobj * Ndet pairs in range and choose the matches
+       based on their separations.  UGH
+     */
+    
+    /* within match range; look for matches */
+    Jmin = -1;
+    Rmin = RADIUS2;
+    for (J = j; (dX > -1.02*RADIUS) && (J < Nave); J++) {
+      /* find closest match for this detection */
+      dX = X1[i] - X2[J];
+      dY = Y1[i] - Y2[J];
+      dR = dX*dX + dY*dY;
+      if (dR > RADIUS2) continue;
+      if (dR < Rmin) {
+	Rmin = dR;
+	Jmin  = J;
+      }
+    }
+
+    /* no match, try next detection */ 
+    if (Jmin == -1) {
+      i++;
+      continue;
+    }
+
+    /*** a match is found, add to starpar with links to average ***/
+    Nmatch ++;
+    n = N2[Jmin];
+    N = N1[i];
+
+    /* make sure there is space for next entry */
+    if (Nstarpar >= NSTARPAR) {
+      NSTARPAR = Nstarpar + 1000;
+      REALLOCATE (catalog[0].starpar, StarPar, NSTARPAR);
+    }
+
+    /** add starpar for this star **/
+
+    // set the new starparments
+    catalog[0].starpar[Nstarpar]          = stars[N].starpar;
+    catalog[0].starpar[Nstarpar].averef   = n;
+    catalog[0].starpar[Nstarpar].objID    = catalog[0].average[n].objID;
+    catalog[0].starpar[Nstarpar].catID    = catID;
+
+    // NOTE: include R,D in starpar?
+    // XXX if I add R,D to starpar, I should rationalize R,D to the same boundary?
+
+    stars[N].found = Nstarpar;
+    catalog[0].found_t[n] = Nstarpar;
+    catalog[0].average[n].Nstarpar ++;
+    Nstarpar ++;
+    i++;
+  }
+
+# if (0)
+  /** incorporate unmatched image stars? **/
+  for (i = 0; (i < Nstars) && !options.only_match; i++) {
+
+    // skip already matched stars
+    if (stars[i].found != -1) continue;
+    if (!IN_REGION (stars[i].average.R, stars[i].average.D)) continue;
+
+    /* make sure there is space for next entry */
+    if (Nstarpar >= NSTARPAR) {
+      NSTARPAR = Nstarpar + 1000;
+      REALLOCATE (catalog[0].starpar, Starpar, NSTARPAR);
+    }
+    if (Nave >= NAVE) {
+      NAVE = Nave + 1000;
+      REALLOCATE (catalog[0].average, Average, NAVE);
+      REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*Nsecfilt);
+    }
+
+    dvo_average_init (&catalog[0].average[Nave]);
+    catalog[0].average[Nave].R         	   = stars[i].R;
+    catalog[0].average[Nave].D         	   = stars[i].D;
+
+    catalog[0].average[Nave].Nstarpar  	   = 1;
+    catalog[0].average[Nave].starparOffset = Nstarpar;
+    catalog[0].average[Nave].objID     	   = objID;
+    catalog[0].average[Nave].catID     	   = catID;
+
+    if (PSPS_ID) {
+      catalog[0].average[Nave].extID = CreatePSPSObjectID(catalog[0].average[Nave].R, catalog[0].average[Nave].D);
+    }
+
+    objID ++;
+
+    for (j = 0; j < Nsecfilt; j++) {
+      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j]);
+    }
+
+    catalog[0].starpar[Nstarpar]        = stars[i].starpar;
+    catalog[0].starpar[Nstarpar].averef = Nave;
+    catalog[0].starpar[Nstarpar].objID  = catalog[0].average[Nave].objID;
+    catalog[0].starpar[Nstarpar].catID  = catID;
+
+    stars[i].found = Nstarpar;
+    Nstarpar ++;
+    Nave ++;
+  }
+# endif      
+
+  REALLOCATE (catalog[0].average, Average, Nave);
+  REALLOCATE (catalog[0].starpar, StarPar, Nstarpar);
+ 
+  catalog[0].sorted = FALSE;
+
+  /* note stars which have been found in this catalog */
+  for (i = 0; i < NstarsIn; i++) {
+    if (stars[i].found > -1) {
+      stars[i].found = -2;
+    }
+  }
+
+  /* check if the catalog has changed?  if no change, no need to write */
+  catalog[0].objID     = objID; // new max value, save on catalog close
+  catalog[0].Naverage  = Nave;
+  catalog[0].Nstarpar  = Nstarpar;
+  catalog[0].Nsecf_mem = Nave*Nsecfilt;
+  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nstarpar, Nlens: "OFF_T_FMT" "OFF_T_FMT" "OFF_T_FMT" "OFF_T_FMT", ("OFF_T_FMT" matches)\n",  Nstars,  Nave, Nmatch);
+
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (N2);
+  free (X2);
+  free (Y2);
+
+  return (Nmatch);
+}
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar.c	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar.c	(revision 37395)
@@ -14,6 +14,4 @@
 
   int i;
-  SkyTable *sky;
-  SkyList *skylist = NULL;
   AddstarClientOptions options;
 
@@ -23,21 +21,20 @@
 
   // load the full sky description table (dvodb must exist)
-  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, FALSE, SKY_DEPTH, VERBOSE);
+  SkyTable *sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, FALSE, SKY_DEPTH, VERBOSE);
   SkyTableSetFilenames (sky, CATDIR, "cpt");
   
+  // load the list of hosts
+  HostTable *hosts = HostTableLoad (CATDIR, sky->hosts);
+  if (!hosts) {
+    fprintf (stderr, "ERROR: failure reading Host Table %s for database %s\n", sky->hosts, CATDIR);
+    exit (1);
+  }    
+
   // generate the subset matching the user-selected region
-  skylist = SkyListByPatch (sky, -1, &UserPatch);
-
-  // if we only match to existing (already populated) regions, limit the select to those regions:
-  if (options.existing_regions) {
-    SkyList *tmp;
-    tmp = SkyListExistingSubset (skylist, CATDIR);
-    SkyListFree (skylist);
-    skylist = tmp;
-  }
+  SkyList *skylist = SkyListByPatch (sky, -1, &UserPatch);
 
   for (i = 1; i < argc; i++) {
       fprintf (stderr, "loading %s\n", argv[i]);
-      loadstarpar_rawdata (skylist, argv[i], options, ALLSKY);
+      loadstarpar_rawdata (skylist, hosts, argv[i], options);
   }
   exit (0);
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_catalog.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_catalog.c	(revision 37395)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_catalog.c	(revision 37395)
@@ -0,0 +1,28 @@
+# include "addstar.h"
+# include "loadstarpar.h"
+
+int loadstarpar_catalog (StarPar_Stars *stars, int Nstars, SkyRegion *region, char *filename) {
+
+  Catalog catalog;
+
+  // now we have all of the loaded stars in this catalog
+  catalog.filename = filename;
+  catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+  catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+  catalog.catflags = LOAD_AVES | LOAD_SECF | LOAD_STARPAR;
+  catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+    
+  // an error exit status here is a significant error
+  if (!dvo_catalog_open (&catalog, region, VERBOSE, "w")) {
+    fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+    exit (2);
+  }
+
+  find_matches_starpar (region, stars, Nstars, &catalog, options);
+    
+  dvo_catalog_save (&catalog, VERBOSE);
+  dvo_catalog_unlock (&catalog);
+  dvo_catalog_free (&catalog);
+
+  return (TRUE);
+}
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_client.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_client.c	(revision 37395)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_client.c	(revision 37395)
@@ -0,0 +1,22 @@
+# include "addstar.h"
+# include "loadstarpar.h"
+
+int main (int argc, char **argv) {
+
+  int i;
+  AddstarClientOptions options;
+
+  // need to construct these options with args_loadstarpar...
+  options = ConfigInit (&argc, argv);
+  options = args_loadstarpar_client (argc, argv, options);
+
+  // client is called with a pointer to the file to be loaded
+
+  StarPar_Stars *stars = loadstarpar_load_stars (INPUT, &Nstars);
+
+  loadstarpar_catalog (stars, Nstars, region);
+
+  free (stars);
+
+  exit (0);
+}
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_io.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_io.c	(revision 37395)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_io.c	(revision 37395)
@@ -0,0 +1,186 @@
+# include "addstar.h"
+# include "loadstarpar.h"
+
+int loadstarpar_save_stars (char *filename, StarPar_Stars *stars, int Nstars) {
+
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  gfits_init_header (&header);
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+
+  FILE *f = fopen (filename, "w");
+  if (!f) {
+    myAbortF ("ERROR: cannot open file for output %s\n", filename);
+  }
+
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+
+  gfits_create_table_header (&theader, "BINTABLE", "STARPAR");
+
+  gfits_define_bintable_column (&theader, "D", "RA",       "", "degree", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "D", "DEC",      "", "degree", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "D", "GLON",     "", "degree", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "D", "GLAT",     "", "degree", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "Ebv",      "", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "dEbv",     "", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "DistMag",  "", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "dDistMag", "", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "M_r",      "", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "dM_r",     "", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "FeH",      "", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "dFeH",     "", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "J", "averef",   "", 1.0, FT_BZERO_INT32);
+  gfits_define_bintable_column (&theader, "J", "objID",    "", 1.0, FT_BZERO_INT32);
+  gfits_define_bintable_column (&theader, "J", "catID",    "", 1.0, FT_BZERO_INT32);
+
+  double       *ra       = NULL; ALLOCATE (ra      , double	 , Nstars); for (i = 0; i < Nstars; i++) ra      [i] = stars[i].R               ;
+  double       *dec      = NULL; ALLOCATE (dec     , double	 , Nstars); for (i = 0; i < Nstars; i++) dec     [i] = stars[i].D               ;
+  double       *glon     = NULL; ALLOCATE (glon    , double	 , Nstars); for (i = 0; i < Nstars; i++) glon    [i] = stars[i].starpar.galLon  ;
+  double       *glat     = NULL; ALLOCATE (glat    , double	 , Nstars); for (i = 0; i < Nstars; i++) glat    [i] = stars[i].starpar.galLat  ;
+  float        *Ebv      = NULL; ALLOCATE (Ebv     , float	 , Nstars); for (i = 0; i < Nstars; i++) Ebv     [i] = stars[i].starpar.Ebv     ;
+  float        *dEbv     = NULL; ALLOCATE (dEbv    , float	 , Nstars); for (i = 0; i < Nstars; i++) dEbv    [i] = stars[i].starpar.dEbv    ;
+  float        *DistMag  = NULL; ALLOCATE (DistMag , float	 , Nstars); for (i = 0; i < Nstars; i++) DistMag [i] = stars[i].starpar.DistMag ;
+  float        *dDistMag = NULL; ALLOCATE (dDistMag, float	 , Nstars); for (i = 0; i < Nstars; i++) dDistMag[i] = stars[i].starpar.dDistMag;
+  float        *M_r      = NULL; ALLOCATE (M_r     , float	 , Nstars); for (i = 0; i < Nstars; i++) M_r     [i] = stars[i].starpar.M_r     ;
+  float        *dM_r     = NULL; ALLOCATE (dM_r    , float	 , Nstars); for (i = 0; i < Nstars; i++) dM_r    [i] = stars[i].starpar.dM_r    ;
+  float        *FeH      = NULL; ALLOCATE (FeH     , float	 , Nstars); for (i = 0; i < Nstars; i++) FeH     [i] = stars[i].starpar.FeH     ;
+  float        *dFeH     = NULL; ALLOCATE (dFeH    , float	 , Nstars); for (i = 0; i < Nstars; i++) dFeH    [i] = stars[i].starpar.dFeH    ;
+  unsigned int *averef   = NULL; ALLOCATE (averef  , unsigned int, Nstars); for (i = 0; i < Nstars; i++) averef  [i] = stars[i].starpar.averef  ;
+  unsigned int *objID    = NULL; ALLOCATE (objID   , unsigned int, Nstars); for (i = 0; i < Nstars; i++) objID   [i] = stars[i].starpar.objID   ;
+  unsigned int *catID    = NULL; ALLOCATE (catID   , unsigned int, Nstars); for (i = 0; i < Nstars; i++) catID   [i] = stars[i].starpar.catID   ;
+
+  // generate the output array that carries the data
+  gfits_create_table (&theader, &ftable);
+
+  // add the columns to the output array
+  gfits_set_bintable_column (&theader, &ftable, "RA",       ra      , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "DEC",      dec     , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "GLON",     glon    , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "GLAT",     glat    , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "Ebv",      Ebv     , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "dEbv",     dEbv    , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "DistMag",  DistMag , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "dDistMag", dDistMag, Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "M_r",      M_r     , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "dM_r",     dM_r    , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "FeH",      FeH     , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "dFeH",     dFeH    , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "averef",   averef  , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "objID",    objID   , Nstars);
+  gfits_set_bintable_column (&theader, &ftable, "catID",    catID   , Nstars);
+    
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table (f, &ftable);
+  gfits_free_header (&theader);
+  gfits_free_table (&ftable);
+}
+
+
+# define GET_COLUMN(OUT,NAME,TYPE)					\
+  TYPE *OUT = gfits_get_bintable_column_data (&theader, &ftable, NAME, type, &Nrow, &Ncol); \
+  myAssert (!strcmp(type, #TYPE), "wrong column type");
+
+StarPar_Stars *loadstarpar_load_stars (char *filename, int *nstars) {
+
+  int i, Ncol;
+  off_t Nrow;
+  char type[16];
+
+  StarPar_Stars *stars = NULL;
+
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  header.buffer = NULL;
+  matrix.buffer = NULL;
+  ftable.buffer = NULL;
+  theader.buffer = NULL;
+
+  FILE *f = fopen (filename, "r");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open image subset file %s\n", filename);
+    return NULL;
+  }
+
+  /* load in PHU segment (ignore) */
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read header\n");
+    goto escape;
+  }
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read matrix\n");
+    goto escape;
+  }
+
+  ftable.header = &theader;
+
+  // load data for this header 
+  if (!gfits_load_header (f, &theader)) goto escape;
+
+  // read the fits table bytes
+  if (!gfits_fread_ftable_data (f, &ftable, FALSE)) goto escape;
+ 
+  GET_COLUMN_NEW(ra      , "RA"        ,   double);
+  GET_COLUMN_NEW(dec     , "DEC"       ,   double);
+  GET_COLUMN_NEW(glon    , "GLON"      ,   double);
+  GET_COLUMN_NEW(glat    , "GLAT"      ,   double);
+  GET_COLUMN_NEW(Ebv     , "Ebv"       ,   float);
+  GET_COLUMN_NEW(dEbv    , "dEbv"      ,   float);
+  GET_COLUMN_NEW(DistMag , "DistMag"   ,   float);
+  GET_COLUMN_NEW(dDistMag, "dDistMag"  ,   float);
+  GET_COLUMN_NEW(M_r     , "M_r"       ,   float);
+  GET_COLUMN_NEW(dM_r    , "dM_r"      ,   float);
+  GET_COLUMN_NEW(FeH     , "FeH"       ,   float);
+  GET_COLUMN_NEW(dFeH    , "dFeH"      ,   float);
+  GET_COLUMN_NEW(averef  , "averef"    ,   unsigned int);
+  GET_COLUMN_NEW(objID   , "objID"     ,   unsigned int);
+  GET_COLUMN_NEW(catID   , "catID"     ,   unsigned int);
+
+  gfits_free_header (&theader);
+  gfits_free_table  (&ftable);
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+
+  ALLOCATE (StarPar_Stars, stars, Nrow);
+
+  for (i = 0; i < Nrow; i++) {
+    stars[i].R                = ra      [i];
+    stars[i].D                = dec     [i];
+    stars[i].starpar.galLon   = glon    [i];
+    stars[i].starpar.galLat   = glat    [i];
+    stars[i].starpar.Ebv      = Ebv     [i];
+    stars[i].starpar.dEbv     = dEbv    [i];
+    stars[i].starpar.DistMag  = DistMag [i];
+    stars[i].starpar.dDistMag = dDistMag[i];
+    stars[i].starpar.M_r      = M_r     [i];
+    stars[i].starpar.dM_r     = dM_r    [i];
+    stars[i].starpar.FeH      = FeH     [i];
+    stars[i].starpar.dFeH     = dFeH    [i];
+    stars[i].starpar.averef   = averef  [i];
+    stars[i].starpar.objID    = objID   [i];
+    stars[i].starpar.catID    = catID   [i];
+  }
+
+  fclose (f);
+  *nstars = Nrow;
+  return stars;
+
+escape:
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  gfits_free_header (&theader);
+  gfits_free_table  (&ftable);
+
+  fclose (f);
+  return NULL;
+}
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_make_subset.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_make_subset.c	(revision 37395)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_make_subset.c	(revision 37395)
@@ -0,0 +1,40 @@
+# include "addstar.h"
+# include "loadstarpar.h"
+
+// assign stars in the given region to the subset (NOTE: stars are sorted by RA, start is
+// first entry in stars array in this region)
+
+StarPar_Stars *loadstarpar_make_subset (StarPar_Stars *stars, int Nstars, int start, SkyRegion *region, int *nsubset) {
+
+  StarPar_Stars *subset = NULL;
+
+  // collect array of (Stars *) stars in a new output catalog
+  int Nsubset = 0;
+  int NSUBSET = 3000;
+  ALLOCATE (subset, StarPar_Stars *, NSUBSET);
+
+  // find the rest of the stars in this output region
+  for (i = start; i < Nstars; i++) {
+    if (stars[i].flag) continue;
+
+    // check if in skyregion
+    if (stars[i].R < region[0].Rmin) continue;
+    if (stars[i].R > region[0].Rmax) break;
+    if (stars[i].D < region[0].Dmin) continue;
+    if (stars[i].D > region[0].Dmax) continue;
+	  
+    // check if in UserPatch (a GLOBAL)
+    if (stars[i].R < UserPatch.Rmin) continue;
+    if (stars[i].R > UserPatch.Rmax) break;
+    if (stars[i].D < UserPatch.Dmin) continue;
+    if (stars[i].D > UserPatch.Dmax) continue;
+	  
+    subset[Nsubset] = stars[i];
+    Nsubset ++
+
+    CHECK_REALLOCATE (subset, StarPar_Stars, NSUBSET, Nsubset, 10000);
+  }
+
+  *nsubset = Nsubset;
+  return subset;
+}
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_rawdata.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_rawdata.c	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_rawdata.c	(revision 37395)
@@ -1,8 +1,4 @@
 # include "addstar.h"
-# include "WISE.h"
-
-/* WISE raw data tables are not fixed bytes per row.  split lines at the RETURN char.
- * handle fractional lines at the end of each read block
- */
+# include "loadstarpar.h"
 
 # define GET_COLUMN(OUT,NAME,TYPE) \
@@ -10,235 +6,44 @@
   myAssert (!strcmp(type, #TYPE), "wrong column type");
 
-int loadstarpar_rawdata (SkyList *skytable, char *filename, AddstarClientOptions options, int ALLSKY) {
+int loadstarpar_foobar (SkyList *skylistInput, HostTable *hosts, char *filename, AddstarClientOptions options) {
   
-  int i, j, verbose;
-  int Nstars, NSTARS, Ntstars, NTSTARS;
-  int Nbyte, Nextra, offset;
+  SkyRegion *region;
 
-  double Rmin, Rmax, Dmin, Dmax;
+  StarPar_Stars *stars = loadstarpar_readstars (filename, &Nstars);
 
-  FILE *f;
-  char *buffer, *p, *q;
+  // sort the stars by RA
+  loadstarpar_sortStars (stars, Nstars);
 
-  Stars **stars; // this is an array of pointers to be consistent with input to find_match_refstars
-  WISE_Stars *tstars;
-  SkyList *skylist;
-  SkyRegion *region;
-  Catalog catalog;
+  // scan through the stars, loading the containing catalogs
+  // skip through table for unsaved stars
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].flag) continue;
 
-  // read in the full FITS files ('cause I don't have a partial read option)
-  f = fopen (filename, "r");
-  if (f == NULL) Shutdown ("can't read stellar parameter file: %s", filename);
+    // scan forward until we read the UserPatch
+    if (stars[i].R < UserPatch.Rmin) continue;
+    if (stars[i].R > UserPatch.Rmax) break;
+    if (stars[i].D < UserPatch.Dmin) continue;
+    if (stars[i].D > UserPatch.Dmax) continue;
 
-  Header header;
-  Matrix matrix;
-  Header theader;
-  FTable ftable;
-  
-  // load in PHU segment (ignore)
-  if (!gfits_fread_header (f, &header)) {
-    if (VERBOSE) fprintf (stderr, "can't read image subset header\n");
-    fclose (f);
-    return NULL;
-  }
-  if (!gfits_fread_matrix (f, &matrix, &header)) {
-    if (VERBOSE) fprintf (stderr, "can't read image subset matrix\n");
-    gfits_free_header (&header);
-    fclose (f);
-    return NULL;
+    // identify the relevant catalog
+    skylist = SkyRegionByPoint_List (skylistInput, -1, stars[i].R, stars[i].D);
+    if (skylist[0].Nregions == 0) {
+      SkyListFree (skylist);
+      continue;
+    }
+    region = skylist[0].regions[0];
+
+    // select stars matching this region
+    StarPar_Stars *subset = loadstarpar_make_subset (stars, Nstars, i, region, &Nsubset);
+
+    // In parallel mode, write out the subset to a disk file.  Block until a remote host
+    // is available.  In serial mode, just match against the appropriate region and save
+    loadstarpar_save_remote (subset, Nsubset, hosts, region);
   }
 
-  ftable.header = &theader;
+  // wait for last remote clients to finish
+  harvest_all ();
 
-  // load data for this header 
-  if (!gfits_load_header (f, &theader)) {
-    fclose (f);
-    return NULL;
-  }
-  if (!gfits_fread_ftable_data (f, &ftable, FALSE)) {
-    fclose (f);
-    return (NULL);
-  }
-  fclose (f);
-
-  // we read the entire block of data, then extract the columns, then set the image structure values.
-  // I free the FITS table data after extracting the colums to avoid having 3 copies in memory.
-
-  char type[16];
-
-  GET_COLUMN (glat, "l", float);
-  GET_COLUMN (glon, "b", float);
-
-  // free the memory associated with the FITS files
-  gfits_free_header (&header);
-  gfits_free_matrix (&matrix);
-  gfits_free_header (&theader);
-  gfits_free_table (&ftable);
-
-  Rmin = 360.0;
-  Rmax = 360.0;
-  Dmin = 360.0;
-  Dmax = 360.0;
-
-  for (i = 0; i < Nrow; i++) {
-    galactic_to_celestial (&R, &D, glat[i], glon[i]);
-
-    Rmin = MIN (Rmin, R);
-    Rmax = MAX (Rmax, R);
-    Dmin = MIN (Dmin, D);
-    Dmax = MAX (Dmax, D);
-
-      Ntstars ++;
-      CHECK_REALLOCATE (tstars, WISE_Stars, NTSTARS, Ntstars, 10000);
-  }
-
-    // sort the tstars by RA
-    getWISE_sortStars (tstars, Ntstars);
-
-    // scan through the stars, loading the containing catalogs
-    // skip through table for unsaved stars
-    for (i = 0; i < Ntstars; i++) {
-      if (tstars[i].flag) continue;
-
-      // scan forward until we read the UserPatch
-      if (tstars[i].R < UserPatch.Rmin) continue;
-      if (tstars[i].R > UserPatch.Rmax) break;
-      if (tstars[i].D < UserPatch.Dmin) continue;
-      if (tstars[i].D > UserPatch.Dmax) continue;
-
-      // identify the relevant catalog
-      skylist = SkyRegionByPoint_List (skytable, -1, tstars[i].R, tstars[i].D);
-      if (skylist[0].Nregions == 0) {
-	  SkyListFree (skylist);
-	  continue;
-      }
-      region = skylist[0].regions[0];
-      if (DEBUG) fprintf (stderr, "writing to %s\n", skylist[0].filename[0]);
-
-      // collect array of (Stars *) stars in a new output catalog
-      Nstars = 0;
-      NSTARS = 3000;
-      ALLOCATE (stars, Stars *, NSTARS);
-
-      // loop over stars in this WISE region that are also in this output region
-      for (j = i; j < Ntstars; j++) {
-	if (tstars[j].flag) continue;
-
-	// check if in skyregion
-	if (tstars[j].R < region[0].Rmin) continue;
-	if (tstars[j].R > region[0].Rmax) break;
-	if (tstars[j].D < region[0].Dmin) continue;
-	if (tstars[j].D > region[0].Dmax) continue;
-	  
-	// check if in UserPatch
-	if (tstars[j].R < UserPatch.Rmin) continue;
-	if (tstars[j].R > UserPatch.Rmax) break;
-	if (tstars[j].D < UserPatch.Dmin) continue;
-	if (tstars[j].D > UserPatch.Dmax) continue;
-	  
-	offset = tstars[j].offset;
-
-	ALLOCATE (stars[Nstars+0], Stars, 1);
-	ALLOCATE (stars[Nstars+1], Stars, 1);
-	ALLOCATE (stars[Nstars+2], Stars, 1);
-	ALLOCATE (stars[Nstars+3], Stars, 1);
-
-	InitStar (stars[Nstars+0]);
-	InitStar (stars[Nstars+1]);
-	InitStar (stars[Nstars+2]);
-	InitStar (stars[Nstars+3]);
-
-	stars[Nstars+0][0].average.R = tstars[j].R;
-	stars[Nstars+0][0].average.D = tstars[j].D;
-	stars[Nstars+1][0].average.R = tstars[j].R;
-	stars[Nstars+1][0].average.D = tstars[j].D;
-	stars[Nstars+2][0].average.R = tstars[j].R;
-	stars[Nstars+2][0].average.D = tstars[j].D;
-	stars[Nstars+3][0].average.R = tstars[j].R;
-	stars[Nstars+3][0].average.D = tstars[j].D;
-	
-	if (ALLSKY) {
-	  loadwise_star_allsky (&stars[Nstars], &buffer[offset], Nbyte - offset);
-	} else {
-	  loadwise_star_prelim (&stars[Nstars], &buffer[offset], Nbyte - offset);
-	}
-
-	tstars[j].flag = TRUE;
-
-	Nstars += 4;
-	if (Nstars >= NSTARS - 4) {
-	  NSTARS += 4000;
-	  REALLOCATE (stars, Stars *, NSTARS);
-	}
-      }
-
-      if (!Nstars) {
-	free (stars);
-	continue;
-      }
-
-      if (DEBUG) fprintf (stderr, "selected %d stars (%10.6f - %10.6f, %10.6f - %10.6f)\n", Nstars, 
-			  region[0].Rmin, region[0].Rmax, region[0].Dmin, region[0].Dmax);
-
-      if (1) {
-	verbose = VERBOSE;
-	VERBOSE = FALSE;
-
-	// now we have all of the loaded stars in this catalog
-	catalog.filename = skylist[0].filename[0];
-	catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
-	catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
-	catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
-	catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
-
-	// an error exit status here is a significant error
-	if (!dvo_catalog_open (&catalog, skylist[0].regions[0], VERBOSE, "w")) {
-	  fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
-	  exit (2);
-	}
-
-	// assume no input star matches an existing star 
-	// simply add to the existing table
-	// loadWISE_catalog (&catalog, stars, Nstars);
-	find_matches_refstars (skylist[0].regions[0], stars, Nstars, &catalog, options);
-	// loadWISE_catalog (&catalog, stars, Nstars);
-
-	dvo_catalog_save (&catalog, VERBOSE);
-	dvo_catalog_unlock (&catalog);
-	dvo_catalog_free (&catalog);
-	// free (catalog.filename);
-	// XXX don't free this! it points to an element of the skytable
-      }
-
-      SkyListFree (skylist);
-      for (j = 0; j < Nstars; j++) free (stars[j]);
-      free (stars);
-      VERBOSE = verbose;
-    }
-    free (tstars);
-    if (VERBOSE) fprintf (stderr, "done\n");
-
-    // at end, p points at the start of last, partial line
-    if (Nextra) memmove (buffer, p, Nextra);
-  }
-
-  if (VERBOSE) fprintf (stderr, "\n");
-  
-  fclose (f);
-  free (buffer);
-  return (TRUE);
+  return TRUE;
 }
 
-/*
-  for each WISE file:
-  for each data block
-  generate a table of: R, D, byte, flag
-  for each unsaved star
-  find containing catalog
-  load catalog
-  find all contained stars
-  add to catalog
-  save catalog 
-  mark all contained stars
-*/
-
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_readstars.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_readstars.c	(revision 37395)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_readstars.c	(revision 37395)
@@ -0,0 +1,134 @@
+# include "addstar.h"
+# include "loadstarpar.h"
+
+# define GET_COLUMN(OUT,NAME,TYPE) \
+  TYPE *OUT = gfits_get_bintable_column_data (&theader, &ftable, NAME, type, &Nrow, &Ncol); \
+  myAssert (!strcmp(type, #TYPE), "wrong column type");
+
+StarPar_Stars *loadstarpar_readstars (char *filename, int *nstars) {
+
+  // read in the full FITS files ('cause I don't have a partial read option)
+  f = fopen (filename, "r");
+  if (f == NULL) Shutdown ("can't read stellar parameter file: %s", filename);
+
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  
+  // load in PHU segment (ignore)
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset header\n");
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset matrix\n");
+    gfits_free_header (&header);
+    fclose (f);
+    return NULL;
+  }
+
+  ftable.header = &theader;
+
+  // load data for this header 
+  if (!gfits_load_header (f, &theader)) {
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_fread_ftable_data (f, &ftable, FALSE)) {
+    fclose (f);
+    return (NULL);
+  }
+  fclose (f);
+
+  char type[16];
+
+  GET_COLUMN (glat,    "l",    float);
+  GET_COLUMN (glon,    "b",    float);
+  GET_COLUMN (conv,    "conv", char);
+  GET_COLUMN (lnZ,     "lnZ",  float);
+  GET_COLUMN (DistMag, "DM",   float);
+  GET_COLUMN (Ebv,     "EBV",  float);
+  GET_COLUMN (M_r,     "Mr",   float);
+  GET_COLUMN (FeH,     "FeH",  float);
+
+  // free the memory associated with the FITS files
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  gfits_free_header (&theader);
+  gfits_free_table (&ftable);
+
+  // the next FITS extension contains the error information
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset header\n");
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset matrix\n");
+    gfits_free_header (&header);
+    fclose (f);
+    return NULL;
+  }
+
+  double *errImage = (double *) matrix.buffer;
+
+  myAssert (Nrow == matrix.Naxis[2], "size mismatch?");
+
+  int NstarsIn = matrix.Naxis[2];
+
+  Rmin = 360.0;
+  Rmax = 360.0;
+  Dmin = 360.0;
+  Dmax = 360.0;
+
+  int Nstars = 0;
+  int NSTARS = 0.1*NstarsIn;
+
+  StarPar_Stars *stars = NULL;
+  ALLOCATE (stars, StarPar_Stars, NSTARS);
+
+  for (i = 0; i < NstarsIn; i++) {
+
+    // skip stars based on conv and lnZ
+    if (!conv[i]) continue;
+    if (lnZ[i] < -15.0) continue;
+
+    galactic_to_celestial (&R, &D, glat[i], glon[i]);
+
+    Rmin = MIN (Rmin, R);
+    Rmax = MAX (Rmax, R);
+    Dmin = MIN (Dmin, D);
+    Dmax = MAX (Dmax, D);
+
+    float dEbv     = 0.5*(errImage[i*20 + 5*0 + 3] - errImage[i*20 + 5*0 + 1]);
+    float dDistMag = 0.5*(errImage[i*20 + 5*1 + 3] - errImage[i*20 + 5*1 + 1]);
+    float dFeH     = 0.5*(errImage[i*20 + 5*2 + 3] - errImage[i*20 + 5*2 + 1]);
+    float dMr      = 0.5*(errImage[i*20 + 5*3 + 3] - errImage[i*20 + 5*3 + 1]);
+
+    stars[Nstars].R = R;
+    stars[Nstars].D = D;
+
+    stars[Nstars].starpar.galLon = l;
+    stars[Nstars].starpar.galLat = b;
+
+    stars[Nstars].starpar.Ebv      = Ebv[i]    ;
+    stars[Nstars].starpar.dEbv     = dEbv      ;
+    stars[Nstars].starpar.DistMag  = DistMag[i];
+    stars[Nstars].starpar.dDistMag = dDistMag  ;
+    stars[Nstars].starpar.M_r      = M_r[i]    ;
+    stars[Nstars].starpar.dM_r     = dM_r      ;
+    stars[Nstars].starpar.FeH      = FeH[i]    ;
+    stars[Nstars].starpar.dFeH     = dFeH      ;
+
+    Nstars ++;
+
+    CHECK_REALLOCATE (stars, StarPar_Stars, NSTARS, Nstars, 10000);
+  }
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+
+  *nstars = Nstars;
+  return (stars);
+}
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_remote_hosts.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_remote_hosts.c	(revision 37395)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_remote_hosts.c	(revision 37395)
@@ -0,0 +1,134 @@
+# include "addstar.h"
+# include "loadstarpar.h"
+
+// we are running N parallel remote jobs on the remote hosts.  In the usual remote
+// processing (eg, relphot or relastro), we launch one job per remote host.  In this case,
+// we are launching one job foreach table (catalog.cpt) being touched.  individual hosts
+// may have more than one job active at a time.  
+
+int       Nhosts = 0;
+HostInfo **hosts = NULL;
+
+int init_remote_hosts () {
+
+  Nhosts = 10;
+  ALLOCATE (hosts, HostInfo *, Nhosts);
+
+  int i;
+  for (i = 0; i < Nhosts; i++) {
+    hosts[i] = NULL;
+  }
+}
+
+int find_empty_slot () {
+
+  for (i = 0; i < Nhosts; i++) {
+    if (hosts[i] == NULL) return i;
+  }
+  return -1;
+}
+
+int harvest_all () {
+
+  slot = -1;
+
+  while (slot != -2) {
+    slot = harvest_host ();
+    usleep (50000);
+  }
+  return TRUE;
+}
+ 
+// put the host in the list in a free slot. NOTE: this should never be called if we do not
+// already have a free slot.
+int save_remote_host (HostInfo *host) {
+
+  for (i = 0; i < Nhosts; i++) {
+    if (hosts[i] == NULL) {
+      hosts[i] = host;
+      return TRUE;
+    }
+  }
+  myAbort ("failed to find an empty slot: this is a programming error");
+  return FALSE;
+}
+
+// wait for all children to complete, report output to stdout
+// possible states when function is finished:
+// * no child was harvested, but children still exist
+// * no outstanding children
+// * a child was harvested
+int harvest_host () {
+
+  // check if any children have finished...
+  int status = 0;
+  int pid = waitpid (-1, &status, WNOHANG);
+
+  if (!pid) return -1; // there are outstanding children, but none have exited, no slot was opened
+  if ((pid == -1) && (errno == ECHILD)) return -2; // there are no outstanding children
+  if ((pid == -1) && (errno != ECHILD)) myAbort ("programming error?");
+
+  // find the host which has finished
+  int i;
+  int found = FALSE;
+  for (i = 0; (i < Nhosts) && !found; i++) {
+    if (!hosts[i]) continue; // unassigned slot
+    if (hosts[i][0].pid != pid) continue;
+    found = TRUE;
+  }
+  myAssert (found, "Programming error: failed to matched finished job to known host!");
+  int slot = i;
+
+  HostInfo *host = hosts[slot];
+
+  // check on the status of this job and report any output
+  if (DEBUG) fprintf (stdout, "job finished for %s (%d)\n", host->hostname, pid);
+
+  int Nout, printHead;
+
+  // read stdout
+  EmptyIOBuffer (&host->stdout, 100, host->stdio[HOST_STDOUT]);
+  printHead = VERBOSE || (host->stdout.Nbuffer > 0);
+  if (printHead) fprintf (stdout, "--- stdout from %s --- (%d bytes, v2)\n", host->hostname, host->stdout.Nbuffer);
+  Nout = write (STDOUT_FILENO, host->stdout.buffer, host->stdout.Nbuffer);
+  if (Nout != host->stdout.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
+  FlushIOBuffer (&host->stdout);
+  if (printHead) fprintf (stdout, "\n");
+	    
+  // read stderr
+  EmptyIOBuffer (&host->stderr, 100, host->stdio[HOST_STDERR]);
+  printHead = VERBOSE || (host->stderr.Nbuffer > 0);
+  if (printHead) fprintf (stdout, "--- stderr from %s --- (%d bytes, v2)\n", host->hostname, host->stderr.Nbuffer);
+  Nout = write (STDOUT_FILENO, host->stderr.buffer, host->stderr.Nbuffer);
+  if (Nout != host->stderr.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
+  FlushIOBuffer (&host->stderr);
+  if (printHead) fprintf (stdout, "\n");
+
+  if (WIFEXITED(status)) {
+    if (DEBUG) fprintf (stdout, "normal completion, exit status is %d\n", WEXITSTATUS(status));
+    host->status = WEXITSTATUS(status);
+    if (host->status) {
+      fprintf (stdout, "job failed on %s\n", host->hostname);
+    }
+  } else {
+    host->status = -1;
+    fprintf (stdout, "job exited abnormally on %s\n", host->hostname);
+  }
+
+  // close opened connections
+  close (host->stdio[HOST_STDIN]);
+  close (host->stdio[HOST_STDOUT]);
+  close (host->stdio[HOST_STDERR]);
+
+  // free data associated with the host
+  free (host->hostname);
+  free (host->pathname);
+  FreeIOBuffer (host->stdout);
+  FreeIOBuffer (host->stderr);
+  free (host);
+
+  // free the slot
+  hosts[slot] = NULL;
+  return slot; 
+}
+
Index: /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_save_remote.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_save_remote.c	(revision 37395)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/addstar/src/loadstarpar_save_remote.c	(revision 37395)
@@ -0,0 +1,74 @@
+# include "addstar.h"
+# include "loadstarpar.h"
+
+int loadstarpar_save_remote (StarPar_Stars *stars, int Nstars, HostTable *hosts, SkyRegion *region) {
+
+  char uniquer[12];
+  int TIME = time(NULL);
+  int PID = getpid();
+  snprintf (uniquer, 12, "%05d.%05d", PID, TIME % 100000);
+
+  // if this region is a parallel thing, save and launch remote
+  if (region->hostID) { 
+    int N = hosts->index[region->hostID];
+    HostInfo *hostMach = hosts->hosts[N];
+
+    // save to a unique filename
+    char filename[1024]; // CATDIR/tmpdir/starpar.PID.index.fits
+    snprintf (filename, 1024, "%s/tmpdir/starpar.%s.%05d.fits", CATDIR, uniquer, region->index);
+
+    // write the data to the given FITS file
+    loadstarpar_save_stars (filename, stars, Nstars);
+
+    int slot = -1;
+    while (slot == -1) {
+      slot = find_empty_slot ();
+      if (slot == -1) {
+	usleep (50000);
+	slot = harvest_host();
+	myAssert (slot != -2, "we should not call harvest_host here if we have open slots");
+      }
+    }
+
+    // allocate a host for this job
+    HostInfo *host = NULL;
+    ALLOCATE (HostInfo, host, 1);
+
+    // we want to run this job on the host described by hostMach.  copy
+    // immutable data from hostMach to a locally allocated host:
+    host->hostID = hostMach->hostID;
+    host->hostname = strcreate (hostMach->hostname);
+    host->pathname = strcreate (hostMach->pathname);
+    InitIOBuffer (host->stdout, 1000);
+    InitIOBuffer (host->stderr, 1000);
+
+    // got a valid slot, so launch a new host
+
+    // XXX do this after we load the host table:
+    // ensure that the paths are absolute path names
+    // char *tmppath = abspath (table->hosts[i].pathname, DVO_MAX_PATH);
+    // free (table->hosts[i].pathname);
+    // table->hosts[i].pathname = tmppath;
+
+    // need to generate the remote command
+    char command[1024];
+    snprintf (command, 1024, "loadstarpar_client");
+    strextend (command, "-hostID %d", host->hostID);
+    strextend (command, "-D CATDIR %s", CATDIR);
+    strextend (command, "-hostdir %s", host->pathname);
+    strextend (command, "-cpt %s", region->name);
+    strextend (command, "-input %s", filename);
+
+    // launch the job on the remote machine (no handshake)
+    int errorInfo = 0;
+    int pid = rconnect ("ssh", host->hostname, command, host->stdio, &errorInfo, FALSE);
+    if (!pid) {
+      if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", host->hostname, errorInfo);
+      exit (1);
+    }
+    host->pid = pid; // save for future reference
+    
+    save_remote_host (host);
+  }
+  return TRUE;
+}
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/average-ps1-v5.d
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/average-ps1-v5.d	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/average-ps1-v5.d	(revision 37395)
@@ -47,6 +47,6 @@
 FIELD lensingOffset,  OFF_LENSING, int,   	    offset to first lensing obs
 FIELD lensobjOffset,  OFF_LENSOBJ, int,   	    offset to mean lensing data
+FIELD starparOffset,  OFF_STARPAR, int,   	    offset to stellar parameter data
 FIELD extendOffset,   OFF_EXTEND,  int,   	    offset to extended object entry
-FIELD paramsOffset,   OFF_PARAMS,  int,   	    offset to stellar parameter data
 
 FIELD refColorBlue,   REF_COLOR_BLUE, float,   	    color of astrometry ref stars
@@ -57,5 +57,6 @@
 FIELD projectionID,   PROJECTION_ID, short,	    ID of projection for primary skycell
 
-FIELD dummy,          DUMMY,         int,           unassigned bytes
+FIELD Nstarpar,       DUMMY,         short,         number of stellar parameter entries
+FIELD dummy,          DUMMY,         short,         unassigned bytes
 
 # 'flags' was called 'code' prior to 2009.02.07
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/average.d
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/average.d	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/average.d	(revision 37395)
@@ -47,6 +47,6 @@
 FIELD lensingOffset,  OFF_LENSING, int,   	    offset to first lensing obs
 FIELD lensobjOffset,  OFF_LENSOBJ, int,   	    offset to mean lensing data
+FIELD starparOffset,  OFF_STARPAR, int,   	    offset to stellar parameter data
 FIELD extendOffset,   OFF_EXTEND,  int,   	    offset to extended object entry
-FIELD paramsOffset,   OFF_PARAMS,  int,   	    offset to stellar parameter data
 
 FIELD refColorBlue,   REF_COLOR_BLUE, float,   	    color of astrometry ref stars
@@ -57,5 +57,6 @@
 FIELD projectionID,   PROJECTION_ID, short,	    ID of projection for primary skycell
 
-FIELD dummy,          DUMMY,         int,           unassigned bytes
+FIELD Nstarpar,       DUMMY,         short,         number of stellar parameter entries
+FIELD dummy,          DUMMY,         short,         unassigned bytes
 
 # 'flags' was called 'code' prior to 2009.02.07
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/starpar.d
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/starpar.d	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/starpar.d	(revision 37395)
@@ -7,7 +7,12 @@
 FIELD galLat,         GAL_LAT,       double,         galactic latitude
 FIELD galLon,         GAL_LON,       double,         galactic longitude
-FIELD MKtype,         MK_TYPE,       float,          O0 = 0.0?
-FIELD Par,            PARALLAX,      float,          1/pc
-FIELD dPar,           PARALLAX_ERR,  float,          1/pc
+FIELD Ebv,            E_BV,          float,          extinction
+FIELD dEbv,           E_BV_ERR,      float,          extinction error
+FIELD DistMag,        DISTANCE_MOD,     float,       mag
+FIELD dDistMag,       DISTANCE_MOD_ERR, float,       mag
+FIELD M_r,            M_R_ABS,       float,          r-band abs magnitude
+FIELD dM_r,           M_R_ABS_ERR,   float,          r-band abs magnitude error
+FIELD FeH,            F_E_H,         float,          metallicity
+FIELD dFeH,           F_E_H_ERR,     float,          metallicity error
 FIELD uRA,            U_RA,          float,          model guess for proper motion
 FIELD uDEC,           U_DEC,         float,          model guess for proper motion
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/include/dvo.h
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/include/dvo.h	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/include/dvo.h	(revision 37395)
@@ -620,5 +620,5 @@
   int              lensobjOffset;        // offset to mean lensing data
   int              extendOffset;         // offset to extended object entry
-  int              paramsOffset;         // offset to stellar parameter data
+  int              starparOffset;        // offset to stellar parameter data
   float            refColorBlue;         // color of astrometry ref stars
   float            refColorRed;          // color of astrometry ref stars
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/coordops.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/coordops.c	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/coordops.c	(revision 37395)
@@ -655,7 +655,22 @@
 
   if (status) {
-    if (!gfits_scan (header, "EQUINOX", "%lf", 1, &equinox)) {
-      if (!gfits_scan (header, "EPOCH", "%lf", 1, &equinox)) {
-	equinox = 2000.0;
+    char equinoxString[80];
+    int haveEquinox = gfits_scan (header, "EQUINOX", "%s", 1, &equinoxString);
+    if (haveEquinox) {
+      // is the string a valid number (it is bad to interpret an error message as year 0.0)
+      char *endptr;
+      equinox = strtod (equinoxString, &endptr);
+      if (endptr == equinoxString) haveEquinox = FALSE;
+    }
+    if (!haveEquinox) {
+      haveEquinox = gfits_scan (header, "EPOCH", "%s", 1, &equinoxString);
+      if (haveEquinox) {
+	// is the string a valid number (it is bad to interpret an error message as year 0.0)
+	char *endptr;
+	equinox = strtod (equinoxString, &endptr);
+	if (endptr == equinoxString) haveEquinox = FALSE;
+	if (!haveEquinox) {
+	  equinox = 2000.0;
+	}
       }
     }
@@ -664,5 +679,5 @@
     } 
   }
-
+  
   if (!status) {
     // fprintf (stderr, "error getting all elements for coordinate mode %s\n", coords[0].ctype);
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog.c	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog.c	(revision 37395)
@@ -129,4 +129,5 @@
   average->Nlensing        = 0;
   average->Nlensobj        = 0;
+  average->Nstarpar        = 0;
   average->Nextend         = 0;
 
@@ -135,6 +136,6 @@
   average->lensingOffset   = -1;
   average->lensobjOffset   = -1;
+  average->starparOffset   = -1;
   average->extendOffset    = -1;
-  average->paramsOffset    = -1;
 
   average->refColorBlue    = NAN;
@@ -144,4 +145,5 @@
   average->skycellID       = 0;
   average->projectionID    = 0;
+
   average->dummy           = 0;
 
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_convert_PS1_V5.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_convert_PS1_V5.c	(revision 37394)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_convert_PS1_V5.c	(revision 37395)
@@ -191,4 +191,5 @@
     out[i].Nlensing      = in[i].Nlensing;     
     out[i].Nlensobj      = in[i].Nlensobj;     
+    out[i].Nstarpar      = in[i].Nstarpar;     
     out[i].Nextend       = in[i].Nextend;     
 
@@ -197,6 +198,6 @@
     out[i].lensingOffset = in[i].lensingOffset;
     out[i].lensobjOffset = in[i].lensobjOffset;
+    out[i].starparOffset = in[i].starparOffset;
     out[i].extendOffset  = in[i].extendOffset;
-    out[i].paramsOffset  = in[i].paramsOffset;
 
     out[i].refColorBlue  = in[i].refColorBlue;
@@ -258,4 +259,5 @@
     out[i].Nlensing       = in[i].Nlensing;     
     out[i].Nlensobj       = in[i].Nlensobj;     
+    out[i].Nstarpar       = in[i].Nstarpar;     
     out[i].Nextend        = in[i].Nextend;     
 			  
@@ -264,6 +266,6 @@
     out[i].lensingOffset  = in[i].lensingOffset;
     out[i].lensobjOffset  = in[i].lensobjOffset;
+    out[i].starparOffset  = in[i].starparOffset;
     out[i].extendOffset   = in[i].extendOffset;
-    out[i].paramsOffset   = in[i].paramsOffset;
 			  
     out[i].refColorBlue   = in[i].refColorBlue;
@@ -975,6 +977,6 @@
     out[i].lensingOffset  = in[i].lensingOffset;
     out[i].lensobjOffset  = in[i].lensobjOffset;
+    out[i].starparOffset  = in[i].starparOffset;
     out[i].extendOffset   = in[i].extendOffset;
-    out[i].paramsOffset   = in[i].paramsOffset;
 			  
     out[i].refColorBlue   = in[i].refColorBlue;
