Index: /trunk/Ohana/src/addstar/Makefile
===================================================================
--- /trunk/Ohana/src/addstar/Makefile	(revision 39495)
+++ /trunk/Ohana/src/addstar/Makefile	(revision 39496)
@@ -32,4 +32,6 @@
 loadtycho    : $(BIN)/loadtycho.$(ARCH)
 loadbsc      : $(BIN)/loadbsc.$(ARCH)
+setobjflags  : $(BIN)/setobjflags.$(ARCH)
+setobjflags_client : $(BIN)/setobjflags_client.$(ARCH)
 dumpskycells : $(BIN)/dumpskycells.$(ARCH)
 findskycell  : $(BIN)/findskycell.$(ARCH)
@@ -40,5 +42,5 @@
 # programs in 'SERVER' use the client-server concept and are out of date
 
-INSTALL = addstar addstar_client sedstar loadgalphot loadstarpar loadstarpar_client loadICRF loadICRF_client skycells mkcmf dumpskycells findskycell load2mass loadwise loadtycho loadbsc loadsupercos
+INSTALL = addstar addstar_client sedstar loadgalphot loadstarpar loadstarpar_client setobjflags setobjflags_client loadICRF loadICRF_client skycells mkcmf dumpskycells findskycell load2mass loadwise loadtycho loadbsc loadsupercos 
 SERVER  = addstarc addstard addstart
 
@@ -308,4 +310,44 @@
 $(SRC)/psps_ids.$(ARCH).o
 
+SET-OBJFLAGS = \
+$(SRC)/setobjflags.$(ARCH).o \
+$(SRC)/ConfigInit_setobjflags.$(ARCH).o \
+$(SRC)/args_setobjflags.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SkyRegionUtils.$(ARCH).o \
+$(SRC)/find_matches_setobjflags.$(ARCH).o \
+$(SRC)/setobjflags_catalog.$(ARCH).o \
+$(SRC)/setobjflags_io.$(ARCH).o \
+$(SRC)/setobjflags_make_subset.$(ARCH).o \
+$(SRC)/setobjflags_loadfile.$(ARCH).o \
+$(SRC)/setobjflags_remote_hosts.$(ARCH).o \
+$(SRC)/setobjflags_save_remote.$(ARCH).o \
+$(SRC)/setobjflags_table.$(ARCH).o \
+$(SRC)/setobjflags_extras.$(ARCH).o
+
+# $(SRC)/resort_catalog.$(ARCH).o \
+# $(SRC)/psps_ids.$(ARCH).o
+
+SET-OBJFLAGS-CLIENT = \
+$(SRC)/setobjflags_client.$(ARCH).o \
+$(SRC)/ConfigInit_setobjflags.$(ARCH).o \
+$(SRC)/args_setobjflags.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SkyRegionUtils.$(ARCH).o \
+$(SRC)/find_matches_setobjflags.$(ARCH).o \
+$(SRC)/setobjflags_catalog.$(ARCH).o \
+$(SRC)/setobjflags_io.$(ARCH).o \
+$(SRC)/setobjflags_make_subset.$(ARCH).o \
+$(SRC)/setobjflags_loadfile.$(ARCH).o \
+$(SRC)/setobjflags_remote_hosts.$(ARCH).o \
+$(SRC)/setobjflags_save_remote.$(ARCH).o \
+$(SRC)/setobjflags_table.$(ARCH).o \
+$(SRC)/setobjflags_extras.$(ARCH).o
+
+# $(SRC)/resort_catalog.$(ARCH).o \
+# $(SRC)/psps_ids.$(ARCH).o
+
 # drop resort_catalog?
 
@@ -456,4 +498,6 @@
 $(LOAD-ICRF-CLIENT)    : $(INC)/addstar.h $(INC)/loadICRF.h
 $(LOAD-WISE)   	       : $(INC)/addstar.h $(INC)/WISE.h
+$(SET-OBJFLAGS)	       : $(INC)/addstar.h $(INC)/setobjflags.h
+$(SET-OBJFLAGS-CLIENT) : $(INC)/addstar.h $(INC)/setobjflags.h
 $(MKCMF)       	       : $(INC)/mkcmf.h
 
@@ -475,4 +519,6 @@
 $(BIN)/loadICRF_client.$(ARCH): $(LOAD-ICRF-CLIENT)
 $(BIN)/loadsupercos.$(ARCH)   : $(LOAD-SUPERCOS)
+$(BIN)/setobjflags.$(ARCH)    : $(SET-OBJFLAGS)
+$(BIN)/setobjflags_client.$(ARCH) : $(SET-OBJFLAGS-CLIENT)
 $(BIN)/skycells.$(ARCH)       : $(SKYCELLS)
 $(BIN)/dumpskycells.$(ARCH)   : $(DUMPSKYCELLS)
Index: /trunk/Ohana/src/addstar/include/setobjflags.h
===================================================================
--- /trunk/Ohana/src/addstar/include/setobjflags.h	(revision 39496)
+++ /trunk/Ohana/src/addstar/include/setobjflags.h	(revision 39496)
@@ -0,0 +1,53 @@
+
+typedef struct {
+  double R, D;
+  e_time time;
+  int myBit;
+  int flag; // in a subset?
+  int found; // assigned to an object?
+} MyStars;
+
+int   HOST_ID;
+char *HOSTDIR;
+char *CPT_FILE;
+char *INPUT;
+
+char *SRC_FILES;
+int   SRC_MYBIT;
+
+double SRC_RADIUS;
+
+int ConfigInit_setobjflags (int *argc, char **argv);
+
+int args_setobjflags (int *argc, char **argv);
+int args_setobjflags_client (int *argc, char **argv);
+
+int setobjflags_table (SkyList *skylistInput, HostTable *hosts, char *filename, int myBit);
+
+MyStars *setobjflags_make_subset (MyStars *stars, int Nstars, int start, SkyRegion *region, int *nsubset);
+
+int setobjflags_save_remote (MyStars *stars, int Nstars, HostTable *hosts, SkyRegion *region, char *fullname);
+
+int save_remote_host (HostInfo *host);
+
+int init_remote_hosts (void);
+void free_remote_hosts (void);
+int find_empty_slot (void);
+int harvest_all (void);
+int harvest_host (void);
+
+int setobjflags_catalog (MyStars *stars, int Nstars, SkyRegion *region, char *filename);
+
+int galactic_to_celestial (double *R, double *D, double l, double b);
+
+int find_matches_setobjflags (SkyRegion *region, MyStars *stars, int Nstars, Catalog *catalog);
+
+int setobjflags_save_stars (char *filename, MyStars *stars, int Nstars);
+MyStars *setobjflags_load_stars (char *filename, int *nstars);
+
+MyStars *setobjflags_loadfile (char *file, int mybit, int *Nstars);
+// MyStars *setobjflags_readstars (char *filename, int *nstars);
+
+int setobjflags_sortStars (MyStars *stars, int Nstars);
+int setobjflags_tmpdir (void);
+
Index: /trunk/Ohana/src/addstar/src/ConfigInit_setobjflags.c
===================================================================
--- /trunk/Ohana/src/addstar/src/ConfigInit_setobjflags.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/ConfigInit_setobjflags.c	(revision 39496)
@@ -0,0 +1,80 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
+
+int ConfigInit_setobjflags (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char *config, *file;
+  char RadiusWord[80];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  // force CATDIR to be absolute (so parallel mode will work)
+  char tmpcatdir[DVO_MAX_PATH];
+  GetConfig (config, "CATDIR" ,                 "%s",  0, tmpcatdir);
+  CATDIR = abspath (tmpcatdir, DVO_MAX_PATH);
+
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  if (!ScanConfig (config, "CATCOMPRESS",       "%s",  0, CATCOMPRESS)) {
+    strcpy (CATCOMPRESS, "NONE");
+  }
+  GetConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+  SetZeroPoint (ZERO_POINT);
+
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  /* set the default search radius */
+  if (!ScanConfig (config, "ADDSTAR_RADIUS", "%s", 0, RadiusWord)) {
+    GetConfig (config, "RADIUS", "%s", 0, RadiusWord);
+  }
+  SRC_RADIUS = atof (RadiusWord);
+  if (SRC_RADIUS < 1e-6) {
+    fprintf (stderr, "non-sensical correlation radius %f\n", SRC_RADIUS);
+    exit (1);
+  }
+
+  /* default mode, format, if not specified */
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile, TRUE)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  FreeConfigFile();
+  free (config);
+  free (file);
+  return TRUE;
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
+
+void FreeConfig (void) {
+  FREE (CATDIR);
+}
Index: /trunk/Ohana/src/addstar/src/args_setobjflags.c
===================================================================
--- /trunk/Ohana/src/addstar/src/args_setobjflags.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/args_setobjflags.c	(revision 39496)
@@ -0,0 +1,167 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+static void help (char *message);
+static void help_client (char *message);
+
+int args_setobjflags (int *argc, char **argv) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    help (NULL);
+  }
+
+  /* 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;
+
+  // XXX for the moment, make this selection manual.  it needs to be automatic 
+  // based on the state of the SkyTable
+  HOST_ID = 0;
+  PARALLEL = FALSE;
+  if ((N = get_argument (*argc, argv, "-parallel"))) {
+    PARALLEL = TRUE;
+    remove_argument (N, argc, argv);
+  }
+  // this is a test mode : rather than launching the remote jobs and waiting for completion,
+  // relphot will simply list the remote command and wait for the user to signal completion
+  PARALLEL_MANUAL = FALSE;
+  if ((N = get_argument (*argc, argv, "-parallel-manual"))) {
+    PARALLEL = TRUE; // -parallel-manual implies -parallel
+    PARALLEL_MANUAL = TRUE;
+    remove_argument (N, argc, argv);
+  }
+  // this is a test mode : rather than launching the relphot_client jobs remotely, they are 
+  // run in serial via 'system'
+  PARALLEL_SERIAL = FALSE;
+  if ((N = get_argument (*argc, argv, "-parallel-serial"))) {
+    if (PARALLEL_MANUAL) {
+      fprintf (stderr, "ERROR: cannot mix -parallel-manual and -parallel-serial\n");
+      exit (1);
+    }
+    PARALLEL = TRUE; // -parallel-serial implies -parallel
+    PARALLEL_SERIAL = 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);
+  }
+
+  /* extra error messages */
+  SRC_FILES = NULL;
+  SRC_MYBIT = 0;
+  if ((N = get_argument (*argc, argv, "-src")) == 0) help ("missing -src argument: required");
+  if (N > *argc - 3) help("-src is missing (file) or (bits) values");
+  remove_argument (N, argc, argv);
+  SRC_FILES = strcreate (argv[N]);
+  remove_argument (N, argc, argv);
+  SRC_MYBIT = atoi (argv[N]);
+  remove_argument (N, argc, argv);
+
+  if (*argc < 3) help ("insufficient arguments");
+  return TRUE;
+}
+
+int args_setobjflags_client (int *argc, char **argv) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    help_client (NULL);
+  }
+
+  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("missing -hostID");
+
+  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("missing -hostdir");
+
+  // ???
+  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("missing cptfile");
+  
+  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("missing input file");
+
+  /* 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;
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  if (*argc != 1) {
+    fprintf (stderr, "USAGE: setobjflags_client -cpt (file) -input (file)\n");
+    exit (2);
+  }
+  return TRUE;
+}
+
+static void help (char *message) {
+
+  if (message) fprintf (stderr, "ERROR: %s\n\n", message);
+
+  fprintf (stderr, "USAGE: setobjflags [options] -src (file) (flag) [..more -src (file) (flag) sets]\n");
+  fprintf (stderr, "  add flags for specified detection sets\n\n");
+
+  fprintf (stderr, "  options:\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
+
+static void help_client (char *message) {
+
+  if (message) fprintf (stderr, "ERROR: %s\n\n", message);
+
+  fprintf (stderr, "USAGE: setobjflags_client -D CATDIR catdir -hostID ID -hostdir (dir) -cpt (filename) -input (input) [options]\n");
+  fprintf (stderr, "  add flags for specified detection sets\n\n");
+
+  fprintf (stderr, "  options:\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
Index: /trunk/Ohana/src/addstar/src/find_matches_setobjflags.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches_setobjflags.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/find_matches_setobjflags.c	(revision 39496)
@@ -0,0 +1,143 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+// we find matching stars by (R,D).  we add the supplied bit to the average.flags for that star
+int find_matches_setobjflags (SkyRegion *region, MyStars *stars, int Nstars, Catalog *catalog) {
+  
+  off_t i, j, n, N, J, Jmin;
+  double RADIUS, RADIUS2, Rmin;
+  double *X1, *Y1, *X2, *Y2;
+  double dX, dY, dR;
+  off_t *N1, *N2;
+  off_t Nave, NAVE;
+
+  /** 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);
+
+  /* internal counters */
+  off_t Nmatch = 0;
+  off_t Nmissed = 0;
+
+  /* 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++) {
+    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;
+  }
+  sort_coords_index (X2, Y2, N2, Nave);
+
+  /* choose a radius for matches */
+  RADIUS = SRC_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) {
+      /* 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 ***/
+    Nmatch ++;
+    n = N2[Jmin];
+    N = N1[i];
+
+    /** set bit for this star **/
+    catalog[0].average[n].flags |= stars[N].myBit;
+    stars[N].found = TRUE;
+    i++;
+  }
+
+  /** count unmatched sources **/
+  for (i = 0; i < Nstars; i++) {
+    // skip already matched stars
+    if (stars[i].found) continue;
+    Nmissed ++;
+  }
+
+  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmatched, Nmissed: %d "OFF_T_FMT" "OFF_T_FMT" "OFF_T_FMT"\n",  Nstars, Nave, Nmatch, Nmissed);
+
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (N2);
+  free (X2);
+  free (Y2);
+
+  return (Nmatch);
+}
Index: /trunk/Ohana/src/addstar/src/setobjflags.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags.c	(revision 39496)
@@ -0,0 +1,63 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+/* This is the DVO program to upload Greg Green's stellar parametersq into a DVO database.
+   It is modeled on the loadwise program and is expected to be run only rarely (once?).
+   The stellar parameter data are delivered as *.fits files.  It does not allow a subset
+   of the sky to be uploaded; entire stellar parameter files are loaded if supplied on the
+   command line.
+
+   USAGE: setobjflags -D CATDIR (catdir) (file.fits) [...more files]
+*/
+
+int main (int argc, char **argv) {
+
+  // need to construct these options with args_setobjflags...
+  SetSignals ();
+  ConfigInit_setobjflags (&argc, argv);
+  args_setobjflags (&argc, argv);
+
+  // load the full sky description table (dvodb must exist)
+  SkyTable *sky = SkyTableLoadOptimal (CATDIR, NULL, NULL, FALSE, -1, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  // make the tmpdir if needed
+  if (!setobjflags_tmpdir()) exit (1);
+
+  // load the list of hosts
+  HostTable *hosts = NULL;
+  if (PARALLEL) {
+    hosts = HostTableLoad (CATDIR, sky->hosts);
+    if (!hosts) {
+      fprintf (stderr, "ERROR: failure reading Host Table %s for database %s\n", sky->hosts, CATDIR);
+      exit (1);
+    }    
+
+    // ensure that the paths are absolute path names
+    for (int i = 0; i < hosts->Nhosts; i++) {
+      char *tmppath = abspath (hosts->hosts[i].pathname, DVO_MAX_PATH);
+      free (hosts->hosts[i].pathname);
+      hosts->hosts[i].pathname = tmppath;
+    }
+
+    // set up the array of active hosts
+    init_remote_hosts ();
+  }
+
+  // generate the subset matching the user-selected region
+  SkyList *skylist = SkyListByPatch (sky, -1, &UserPatch);
+
+  setobjflags_table (skylist, hosts, SRC_FILES, SRC_MYBIT);
+
+  FreeConfig ();
+  FreePhotcodeTable ();
+  SkyListFree (skylist);
+  SkyTableFree (sky);
+  FreeHostTable (hosts);
+
+  free_remote_hosts();
+
+  ohana_memcheck(TRUE);
+  ohana_memdump(TRUE);
+  exit (0);
+}  
Index: /trunk/Ohana/src/addstar/src/setobjflags_catalog.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags_catalog.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags_catalog.c	(revision 39496)
@@ -0,0 +1,30 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+int setobjflags_catalog (MyStars *stars, int Nstars, SkyRegion *region, char *filename) {
+
+  Catalog catalog;
+
+  // now we have all of the loaded stars in this catalog
+  dvo_catalog_init (&catalog, TRUE);
+  catalog.filename = filename;
+  catalog.catflags = DVO_LOAD_AVERAGE;
+  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_setobjflags (region, stars, Nstars, &catalog);
+    
+  SetProtect (TRUE);
+  if (!dvo_catalog_save (&catalog, VERBOSE)) { fprintf (stderr, "ERROR: failed to save %s\n", catalog.filename); exit (1); }
+  if (!dvo_catalog_unlock (&catalog)) { fprintf (stderr, "ERROR: failed to unlock %s\n", catalog.filename); exit (1); }
+  SetProtect (FALSE);
+  
+  dvo_catalog_free (&catalog);
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/addstar/src/setobjflags_client.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags_client.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags_client.c	(revision 39496)
@@ -0,0 +1,41 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+int main (int argc, char **argv) {
+
+
+  // need to construct these options with args_loadstarpar...
+  SetSignals ();
+  ConfigInit_setobjflags (&argc, argv);
+  args_setobjflags_client (&argc, argv);
+
+  // client is called with a pointer to the file to be loaded
+
+  SkyTable *sky = SkyTableLoadOptimal (CATDIR, NULL, NULL, FALSE, -1, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  SkyList *skylist = SkyRegionByCPT (sky, CPT_FILE);
+
+  int Nstars;
+  MyStars *stars = setobjflags_load_stars (INPUT, &Nstars);
+
+  char filename[DVO_MAX_PATH];
+  snprintf (filename, DVO_MAX_PATH, "%s/%s.cpt", HOSTDIR, CPT_FILE);
+
+  setobjflags_catalog (stars, Nstars, skylist->regions[0], filename);
+
+  free (stars);
+
+  FreeConfig ();
+  FreePhotcodeTable ();
+  SkyListFree (skylist);
+  SkyTableFree (sky);
+
+  free (CPT_FILE);
+  free (HOSTDIR);
+  free (INPUT);
+
+  ohana_memcheck(TRUE);
+  ohana_memdump(TRUE);
+  exit (0);
+}
Index: /trunk/Ohana/src/addstar/src/setobjflags_extras.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags_extras.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags_extras.c	(revision 39496)
@@ -0,0 +1,42 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+int setobjflags_tmpdir (void) {
+  
+  struct stat fstats;
+  char fullpath[DVO_MAX_PATH];
+
+  snprintf (fullpath, DVO_MAX_PATH, "%s/tmpdir", CATDIR);
+
+  int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
+  int status = stat (fullpath, &fstats);
+  if (!status) {
+    // path exists, is it a directory?
+    if (!S_ISDIR(fstats.st_mode)) {
+      gprint (GP_ERR, "cannot create directory %s: is an existing file\n", fullpath);
+      return (FALSE);
+    }
+    return (TRUE);
+  }
+
+  status = mkdirhier (fullpath, mode);
+  if (status == -1) {
+    gprint (GP_ERR, "cannot create directory %s\n", fullpath);
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+
+int setobjflags_sortStars (MyStars *stars, int Nstars) {
+
+# define SWAPFUNC(A,B){ MyStars temp = stars[A]; stars[A] = stars[B]; stars[B] = temp; }
+# define COMPARE(A,B)(stars[A].R < stars[B].R)
+
+  OHANA_SORT (Nstars, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+  
+  return TRUE;
+}
Index: /trunk/Ohana/src/addstar/src/setobjflags_io.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags_io.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags_io.c	(revision 39496)
@@ -0,0 +1,148 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+int setobjflags_save_stars (char *filename, MyStars *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", "SETOBJFLAGS");
+
+  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, "J", "MYBIT",    "", "", 1.0, FT_BZERO_INT32);
+//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);
+
+  int i;
+  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      ;
+  unsigned int *myBit    = NULL; ALLOCATE (myBit   , unsigned int, Nstars); for (i = 0; i < Nstars; i++) myBit   [i] = stars[i].myBit  ;
+//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, "MYBIT",    myBit   , Nstars);
+    
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table (f, &ftable);
+  gfits_free_header (&theader);
+  gfits_free_table (&ftable);
+
+  free (ra      );
+  free (dec     );
+  free (myBit   );
+
+  fflush (f);
+  fclose (f);
+
+  return TRUE;
+}
+
+# define GET_COLUMN(OUT,NAME,TYPE,RTYPE)					\
+  TYPE *OUT = gfits_get_bintable_column_data (&theader, &ftable, NAME, type, &Nrow, &Ncol); \
+  myAssert (!strcmp(type, #RTYPE), "wrong column type");
+
+MyStars *setobjflags_load_stars (char *filename, int *nstars) {
+
+  int i, Ncol;
+  off_t Nrow;
+  char type[16];
+
+  MyStars *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(ra      , "RA"        ,   double      ,   double      );
+  GET_COLUMN(dec     , "DEC"       ,   double      ,   double      );
+  GET_COLUMN(myBit   , "MYBIT"     ,   unsigned int,   int         );
+//GET_COLUMN(averef  , "averef"    ,   unsigned int,   int         );
+//GET_COLUMN(objID   , "objID"     ,   unsigned int,   int         );
+//GET_COLUMN(catID   , "catID"     ,   unsigned int,   int         );
+
+  gfits_free_header (&theader);
+  gfits_free_table  (&ftable);
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+
+  ALLOCATE (stars, MyStars, Nrow);
+
+  for (i = 0; i < Nrow; i++) {
+    stars[i].R                = ra     [i];
+    stars[i].D	              = dec    [i];
+    stars[i].myBit            = myBit  [i];
+  }
+
+  free (ra      );
+  free (dec     );
+  free (myBit   );
+
+  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: /trunk/Ohana/src/addstar/src/setobjflags_loadfile.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags_loadfile.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags_loadfile.c	(revision 39496)
@@ -0,0 +1,43 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+/* read ASCII file with ref star data */
+MyStars *setobjflags_loadfile (char *file, int mybit, int *Nstars) {
+
+  FILE *f;
+  char line[256];
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) Shutdown ("can't read data from %s", file);
+
+  MyStars *stars = NULL;
+  int NSTARS = 1000;
+  ALLOCATE (stars, MyStars, NSTARS);
+
+  /* read in stars line-by-line */
+  int N = 0;
+  while (scan_line (f, line) != EOF) {
+    stripwhite (line);
+    if (line[0] == 0) continue;
+    if (line[0] == '#') continue;
+
+    int status = sscanf (line, "%lf %lf", &stars[N].R, &stars[N].D);
+    if (status != 2) {
+      fprintf (stderr, "error reading line: %s\n", line);
+      continue;
+    }
+    stars[N].R = ohana_normalize_angle (stars[N].R);
+    
+    stars[N].myBit = mybit;
+
+    stars[N].time = 0;
+    stars[N].flag = FALSE;
+    stars[N].found = FALSE;
+
+    N++;
+    CHECK_REALLOCATE (stars, MyStars, NSTARS, N, 1000);
+  }
+  *Nstars = N;
+  return (stars);
+}
Index: /trunk/Ohana/src/addstar/src/setobjflags_make_subset.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags_make_subset.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags_make_subset.c	(revision 39496)
@@ -0,0 +1,44 @@
+# include "addstar.h"
+# include "setobjflags.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)
+
+MyStars *setobjflags_make_subset (MyStars *stars, int Nstars, int start, SkyRegion *region, int *nsubset) {
+
+  int i;
+
+  MyStars *subset = NULL;
+
+  // collect array of (Stars *) stars in a new output catalog
+  int Nsubset = 0;
+  int NSUBSET = 3000;
+  ALLOCATE (subset, MyStars, 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 ++;
+
+    stars[i].flag = TRUE;
+
+    CHECK_REALLOCATE (subset, MyStars, NSUBSET, Nsubset, 10000);
+  }
+
+  *nsubset = Nsubset;
+  return subset;
+}
Index: /trunk/Ohana/src/addstar/src/setobjflags_remote_hosts.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags_remote_hosts.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags_remote_hosts.c	(revision 39496)
@@ -0,0 +1,147 @@
+# include "addstar.h"
+# include "loadstarpar.h"
+# include <sys/types.h>
+# include <sys/wait.h>
+
+# define DEBUG 1
+
+// 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 (void) {
+
+  Nhosts = 10;
+  ALLOCATE (hosts, HostInfo *, Nhosts);
+
+  int i;
+  for (i = 0; i < Nhosts; i++) {
+    hosts[i] = NULL;
+  }
+  return TRUE;
+}
+
+void free_remote_hosts (void) {
+  if (!hosts) return;
+  free (hosts);
+}
+
+int find_empty_slot () {
+
+  int i;
+  for (i = 0; i < Nhosts; i++) {
+    if (hosts[i] == NULL) return i;
+  }
+  return -1;
+}
+
+int harvest_all () {
+
+  int 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) {
+
+  int i;
+  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;
+    break;
+  }
+  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: /trunk/Ohana/src/addstar/src/setobjflags_save_remote.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags_save_remote.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags_save_remote.c	(revision 39496)
@@ -0,0 +1,74 @@
+# include "addstar.h"
+# include "setobjflags.h"
+# define DEBUG 1
+
+int setobjflags_save_remote (MyStars *stars, int Nstars, HostTable *hosts, SkyRegion *region, char *fullname) {
+
+  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 (!PARALLEL) { 
+    setobjflags_catalog (stars, Nstars, region, fullname);
+  } else {
+    int N = hosts->index[region->hostID];
+    HostInfo *hostMach = &hosts->hosts[N];
+
+    // save to a unique filename
+    char filename[DVO_MAX_PATH]; // CATDIR/tmpdir/starpar.PID.index.fits
+    snprintf (filename, DVO_MAX_PATH, "%s/tmpdir/starpar.%s.%05d.fits", CATDIR, uniquer, region->index);
+
+    // write the data to the given FITS file
+    setobjflags_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 (host, HostInfo, 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
+
+    // need to generate the remote command
+    char *command = NULL;
+    strextend (&command, "setobjflags_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);
+
+    fprintf (stderr, "command: %s\n", command);
+
+    // 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
+    free (command);
+    
+    save_remote_host (host);
+  }
+  return TRUE;
+}
Index: /trunk/Ohana/src/addstar/src/setobjflags_table.c
===================================================================
--- /trunk/Ohana/src/addstar/src/setobjflags_table.c	(revision 39496)
+++ /trunk/Ohana/src/addstar/src/setobjflags_table.c	(revision 39496)
@@ -0,0 +1,52 @@
+# include "addstar.h"
+# include "setobjflags.h"
+
+int setobjflags_table (SkyList *skylistInput, HostTable *hosts, char *filename, int mybit) {
+  
+  int i, Nstars;
+
+  fprintf (stderr, "loading %s, using bit 0x%08x\n", filename, mybit);
+  MyStars *stars = setobjflags_loadfile (filename, mybit, &Nstars);
+  if (!stars) return FALSE;
+
+  // sort the stars by RA
+  setobjflags_sortStars (stars, Nstars);
+
+  // 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;
+
+    // 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;
+
+    // identify the relevant catalog
+    SkyList *skylist = SkyRegionByPoint_List (skylistInput, -1, stars[i].R, stars[i].D);
+    if (skylist[0].Nregions == 0) {
+      SkyListFree (skylist);
+      continue;
+    }
+    SkyRegion *region = skylist[0].regions[0];
+
+    // select stars matching this region
+    int Nsubset;
+    MyStars *subset = setobjflags_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
+    setobjflags_save_remote (subset, Nsubset, hosts, region, skylist[0].filename[0]);
+
+    free (subset);
+    SkyListFree (skylist);
+  }
+  free (stars);
+
+  // wait for last remote clients to finish
+  harvest_all ();
+
+  return TRUE;
+}
+
