Index: /trunk/Ohana/src/relastro/Makefile
===================================================================
--- /trunk/Ohana/src/relastro/Makefile	(revision 39692)
+++ /trunk/Ohana/src/relastro/Makefile	(revision 39693)
@@ -26,4 +26,6 @@
 RELASTRO = \
 $(SRC)/CheckMeasureToImage.$(ARCH).o \
+$(SRC)/RepairObjectIDs.$(ARCH).o \
+$(SRC)/RepairStacks.$(ARCH).o \
 $(SRC)/RepairStackMeasures.$(ARCH).o \
 $(SRC)/StackImageMaps.$(ARCH).o \
@@ -114,4 +116,6 @@
 RELASTRO_CLIENT = \
 $(SRC)/CheckMeasureToImage.$(ARCH).o \
+$(SRC)/RepairObjectIDs.$(ARCH).o \
+$(SRC)/RepairStacks.$(ARCH).o \
 $(SRC)/RepairStackMeasures.$(ARCH).o \
 $(SRC)/StackImageMaps.$(ARCH).o \
Index: /trunk/Ohana/src/relastro/include/relastro.h
===================================================================
--- /trunk/Ohana/src/relastro/include/relastro.h	(revision 39692)
+++ /trunk/Ohana/src/relastro/include/relastro.h	(revision 39693)
@@ -31,5 +31,5 @@
 typedef enum {FIT_NONE, FIT_AVERAGE, FIT_PM_ONLY, FIT_PAR_ONLY, FIT_PM_AND_PAR} FitMode;
 
-typedef enum {OP_NONE, OP_IMAGES, OP_HIGH_SPEED, OP_MERGE_SOURCE, OP_UPDATE_OBJECTS, OP_UPDATE_OFFSETS, OP_LOAD_OBJECTS, OP_HPM, OP_PARALLEL_REGIONS, OP_PARALLEL_IMAGES, OP_REPAIR_WARPS} RelastroOp;
+typedef enum {OP_NONE, OP_IMAGES, OP_HIGH_SPEED, OP_MERGE_SOURCE, OP_UPDATE_OBJECTS, OP_UPDATE_OFFSETS, OP_LOAD_OBJECTS, OP_HPM, OP_PARALLEL_REGIONS, OP_PARALLEL_IMAGES, OP_REPAIR_STACKS, OP_REPAIR_WARPS, OP_REPAIR_OBJECT_ID} RelastroOp;
 
 typedef enum {TARGET_NONE, TARGET_SIMPLE, TARGET_CHIPS, TARGET_MOSAICS} FitTarget;
@@ -864,4 +864,8 @@
 uint64_t CreatePSPSDetectionID(double tobs, int ccdid, int detID);
 
+int RepairStacks (SkyList *skylist, int hostID, char *hostpath);
+
+int RepairObjectIDs (SkyList *skylist, int hostID, char *hostpath);
+
 void sort_by_ra (double *R, double *D, int *I, int *S, int N);
 void FreeStackGroups (void);
Index: /trunk/Ohana/src/relastro/src/RepairObjectIDs.c
===================================================================
--- /trunk/Ohana/src/relastro/src/RepairObjectIDs.c	(revision 39693)
+++ /trunk/Ohana/src/relastro/src/RepairObjectIDs.c	(revision 39693)
@@ -0,0 +1,177 @@
+# include "relastro.h"
+
+int RepairObjectIDs_parallel (SkyList *sky);
+int RepairObjectIDs_catalog (Catalog *catalog);
+
+// some average entries are missing the PSPS object ID values.  set them correctly here
+int RepairObjectIDs (SkyList *skylist, int hostID, char *hostpath) {
+
+  int i;
+  Catalog catalog;
+
+  if (PARALLEL && !hostID) {
+    RepairObjectIDs_parallel (skylist);
+    return TRUE;
+  }
+
+  // load data from each region file, only use bright stars
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // does this host ID match the desired location for the table?
+    if (!HostTableTestHost(skylist[0].regions[i], hostID)) continue;
+
+    // define the catalog file name
+    char hostfile[1024];
+    snprintf (hostfile, 1024, "%s/%s.cpt", hostpath, skylist[0].regions[i]->name);
+
+    dvo_catalog_init (&catalog, TRUE);
+    catalog.filename = hostID ? hostfile : skylist[0].filename[i];
+
+    // set up the basic catalog info
+    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  = DVO_LOAD_AVERAGE | DVO_LOAD_MEASURE | DVO_LOAD_MISSING | DVO_LOAD_SECFILT;
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE2, "w")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", catalog.filename);
+      exit (1);
+    }
+    if (!catalog.Naverage_disk) {
+      if (VERBOSE2) fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    RepairObjectIDs_catalog (&catalog);
+
+    if (!UPDATE) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+    
+    struct timeval now;
+    gettimeofday (&now, (void *) NULL);
+    char *moddate = ohana_sec_to_date (now.tv_sec);
+    gfits_modify (&catalog.header, "REPAIR", "%s", 1, moddate);      
+    free (moddate);
+
+    // write the updated detections to disk
+    save_catalogs (&catalog, 1);
+  }
+  return (TRUE);
+}
+
+int RepairObjectIDs_parallel_table (HostTable *table, SkyList *sky);
+
+int RepairObjectIDs_parallel (SkyList *sky) {
+
+  // launch the setphot_client jobs to the parallel hosts
+
+  // load the list of hosts
+  HostTable *table = HostTableLoad (CATDIR, sky->hosts);
+  if (!table) {
+    fprintf (stderr, "ERROR: failure reading Host Table %s for database %s\n", sky->hosts, CATDIR);
+    exit (1);
+  }    
+  
+  RepairObjectIDs_parallel_table (table, sky);
+
+  return TRUE;
+}      
+
+// CATDIR is supplied globally
+# define DEBUG 1
+int RepairObjectIDs_parallel_table (HostTable *table, SkyList *sky) {
+
+  // launch the relastro_client jobs to the parallel hosts
+
+  int i, j;
+  for (i = 0; i < table->Nhosts; i++) {
+
+    if (sky->Nregions < table->Nhosts) {
+      // do any of the regions want this host?
+      int wantThisHost = FALSE;
+      for (j = 0; j < sky->Nregions; j++) {
+	if (HostTableTestHost (sky->regions[j], table->hosts[i].hostID)) {
+	  wantThisHost = TRUE;
+	  break;
+	}
+      }
+      if (!wantThisHost) {
+	// fprintf (stderr, "skip host %s\n", table->hosts[i].hostname);
+	continue;
+      }
+    }
+
+    // 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;
+
+    char *command = NULL;
+    strextend (&command, "relastro_client -repair-object-id");
+    strextend (&command, "-hostID %d", table->hosts[i].hostID);
+    strextend (&command, "-D CATDIR %s", CATDIR);
+    strextend (&command, "-hostdir %s", table->hosts[i].pathname);
+    strextend (&command, "-region %f %f %f %f", UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax);
+
+    if (VERBOSE)       strextend (&command, "-v");
+    if (VERBOSE2)      strextend (&command, "-vv");
+    if (UPDATE)        strextend (&command, "-update");
+
+    fprintf (stderr, "command: %s\n", command);
+
+    if (PARALLEL_MANUAL) {
+      free (command);
+      continue;
+    }
+
+    if (PARALLEL_SERIAL) {
+      int status = system (command);
+      if (status) {
+	fprintf (stderr, "ERROR running relastro_client\n");
+	exit (2);
+      }
+    } else {
+      // launch the job on the remote machine (no handshake)
+      int errorInfo = 0;
+      int pid = rconnect ("ssh", table->hosts[i].hostname, command, table->hosts[i].stdio, &errorInfo, FALSE);
+      if (!pid) {
+	if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", table->hosts[i].hostname, errorInfo);
+	exit (1);
+      }
+      table->hosts[i].pid = pid; // save for future reference
+    }
+    free (command);
+  }
+
+  if (PARALLEL_MANUAL) {
+    fprintf (stderr, "run the relastro_client commands above.  when these are done, hit return\n");
+    getchar();
+  }
+  if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
+    HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+  }
+
+  FreeHostTable (table);
+  return TRUE;
+}      
+
+int RepairObjectIDs_catalog (Catalog *catalog) {
+
+  myAssert (!catalog->Naverage || catalog->average, "programming error");
+
+  int onePercent = catalog->Naverage / 100;
+
+  for (off_t j = 0; j < catalog->Naverage; j++) {
+    if (j % onePercent == 0) fprintf (stderr, ".");
+
+    catalog->average[j].extID = CreatePSPSObjectID (catalog->average[j].R, catalog->average[j].D);
+  }
+
+  return TRUE;
+}
+
Index: /trunk/Ohana/src/relastro/src/RepairStacks.c
===================================================================
--- /trunk/Ohana/src/relastro/src/RepairStacks.c	(revision 39693)
+++ /trunk/Ohana/src/relastro/src/RepairStacks.c	(revision 39693)
@@ -0,0 +1,279 @@
+# include "relastro.h"
+
+int RepairStacks_parallel (SkyList *sky);
+
+int RepairStacks (SkyList *skylist, int hostID, char *hostpath) {
+
+  int i;
+  Catalog catalog;
+
+  if (PARALLEL && !hostID) {
+    RepairStacks_parallel (skylist);
+    return TRUE;
+  }
+
+  MakeStackIndex ();
+
+  // load data from each region file, only use bright stars
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // does this host ID match the desired location for the table?
+    if (!HostTableTestHost(skylist[0].regions[i], hostID)) continue;
+
+    // define the catalog file name
+    char hostfile[1024];
+    snprintf (hostfile, 1024, "%s/%s.cpt", hostpath, skylist[0].regions[i]->name);
+
+    dvo_catalog_init (&catalog, TRUE);
+    catalog.filename = hostID ? hostfile : skylist[0].filename[i];
+
+    // set up the basic catalog info
+    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  = DVO_LOAD_AVERAGE | DVO_LOAD_MEASURE | DVO_LOAD_MISSING | DVO_LOAD_SECFILT;
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE2, "w")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", catalog.filename);
+      exit (1);
+    }
+    if (!catalog.Naverage_disk) {
+      if (VERBOSE2) fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    // set the values in MeasureTiny needed by UpdateObjects
+    populate_tiny_values(&catalog, DVO_TV_MEASURE);
+
+    // match measurements with images
+    initImageBins (&catalog, 1, FALSE);
+    findImages (&catalog, 1, FALSE);
+
+    RepairStackMeasures (&catalog);
+
+    free_tiny_values(&catalog);
+
+    freeImageBins (1);
+
+    if (!UPDATE) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+    
+    struct timeval now;
+    gettimeofday (&now, (void *) NULL);
+    char *moddate = ohana_sec_to_date (now.tv_sec);
+    gfits_modify (&catalog.header, "RELASTRO", "%s", 1, moddate);      
+    free (moddate);
+
+    // write the updated detections to disk
+    save_catalogs (&catalog, 1);
+  }
+  printNcatTotal();
+
+  FreeStackGroups ();
+
+  return (TRUE);
+}
+
+int RepairStacks_parallel_group (HostTableGroup *group, SkyList *sky);
+int RepairStacks_parallel_table (HostTable *table, SkyList *sky);
+
+// CATDIR is supplied globally
+# define DEBUG 1
+int RepairStacks_parallel (SkyList *sky) {
+
+  // launch the setphot_client jobs to the parallel hosts
+
+  // load the list of hosts
+  HostTable *table = HostTableLoad (CATDIR, sky->hosts);
+  if (!table) {
+    fprintf (stderr, "ERROR: failure reading Host Table %s for database %s\n", sky->hosts, CATDIR);
+    exit (1);
+  }    
+
+# if (1)
+  
+  RepairStacks_parallel_table (table, sky);
+
+# else
+
+  int Ngroups;
+  HostTableGroup *groups = HostTableGroupsUniqueMachines (table, &Ngroups);
+  // split the table into Ngroups, each with a unique set of machines (this avoids overloading the remote host machines)
+
+  int i;
+  for (i = 0; i < Ngroups; i++) {
+    // update only a group of unique machines at a time
+    RepairStacks_parallel_group (&groups[i], sky);
+  }
+# endif
+
+  return TRUE;
+}      
+
+// CATDIR is supplied globally
+# define DEBUG 1
+int RepairStacks_parallel_group (HostTableGroup *group, SkyList *sky) {
+
+  // launch the relastro_client jobs to the parallel hosts
+
+  int i, j;
+  for (i = 0; i < group->Nhosts; i++) {
+
+    if (sky->Nregions < group->Nhosts) {
+      // do any of the regions want this host?
+      int wantThisHost = FALSE;
+      for (j = 0; j < sky->Nregions; j++) {
+	if (HostTableTestHost (sky->regions[j], group->hosts[i][0].hostID)) {
+	  wantThisHost = TRUE;
+	  break;
+	}
+      }
+      if (!wantThisHost) {
+	// fprintf (stderr, "skip host %s\n", group->hosts[i][0].hostname);
+	continue;
+      }
+    }
+
+    // ensure that the paths are absolute path names
+    char *tmppath = abspath (group->hosts[i][0].pathname, DVO_MAX_PATH);
+    free (group->hosts[i][0].pathname);
+    group->hosts[i][0].pathname = tmppath;
+
+    char *command = NULL;
+    strextend (&command, "relastro_client -repair-stacks");
+    strextend (&command, "-hostID %d", group->hosts[i][0].hostID);
+    strextend (&command, "-D CATDIR %s", CATDIR);
+    strextend (&command, "-hostdir %s", group->hosts[i][0].pathname);
+    strextend (&command, "-region %f %f %f %f", UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax);
+
+    if (VERBOSE)       strextend (&command, "-v");
+    if (VERBOSE2)      strextend (&command, "-vv");
+    if (UPDATE)        strextend (&command, "-update");
+
+    if (USE_BASIC_CHECK) strextend (&command, "-basic-image-search");
+    if (USE_ALL_IMAGES)      strextend (&command, "-use-all-images");
+    if (CHECK_MEASURE_TO_IMAGE) strextend (&command, "-check-measures");
+
+    fprintf (stderr, "command: %s\n", command);
+
+    if (PARALLEL_MANUAL) {
+      free (command);
+      continue;
+    }
+
+    if (PARALLEL_SERIAL) {
+      int status = system (command);
+      if (status) {
+	fprintf (stderr, "ERROR running relastro_client\n");
+	exit (2);
+      }
+    } else {
+      // launch the job on the remote machine (no handshake)
+      int errorInfo = 0;
+      int pid = rconnect ("ssh", group->hosts[i][0].hostname, command, group->hosts[i][0].stdio, &errorInfo, FALSE);
+      if (!pid) {
+	if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", group->hosts[i][0].hostname, errorInfo);
+	exit (1);
+      }
+      group->hosts[i][0].pid = pid; // save for future reference
+    }
+    free (command);
+  }
+
+  if (PARALLEL_MANUAL) {
+    fprintf (stderr, "run the relastro_client commands above.  when these are done, hit return\n");
+    getchar();
+  }
+  if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
+    HostTableGroupWaitJobsGetIO (group, __FILE__, __LINE__, VERBOSE);
+  }
+
+  return TRUE;
+}      
+
+// CATDIR is supplied globally
+# define DEBUG 1
+int RepairStacks_parallel_table (HostTable *table, SkyList *sky) {
+
+  // launch the relastro_client jobs to the parallel hosts
+
+  int i, j;
+  for (i = 0; i < table->Nhosts; i++) {
+
+    if (sky->Nregions < table->Nhosts) {
+      // do any of the regions want this host?
+      int wantThisHost = FALSE;
+      for (j = 0; j < sky->Nregions; j++) {
+	if (HostTableTestHost (sky->regions[j], table->hosts[i].hostID)) {
+	  wantThisHost = TRUE;
+	  break;
+	}
+      }
+      if (!wantThisHost) {
+	// fprintf (stderr, "skip host %s\n", table->hosts[i].hostname);
+	continue;
+      }
+    }
+
+    // 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;
+
+    char *command = NULL;
+    strextend (&command, "relastro_client -repair-stacks");
+    strextend (&command, "-hostID %d", table->hosts[i].hostID);
+    strextend (&command, "-D CATDIR %s", CATDIR);
+    strextend (&command, "-hostdir %s", table->hosts[i].pathname);
+    strextend (&command, "-region %f %f %f %f", UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax);
+
+    if (VERBOSE)       strextend (&command, "-v");
+    if (VERBOSE2)      strextend (&command, "-vv");
+    if (UPDATE)        strextend (&command, "-update");
+
+    if (USE_BASIC_CHECK) strextend (&command, "-basic-image-search");
+    if (USE_ALL_IMAGES)      strextend (&command, "-use-all-images");
+    if (CHECK_MEASURE_TO_IMAGE) strextend (&command, "-check-measures");
+
+    fprintf (stderr, "command: %s\n", command);
+
+    if (PARALLEL_MANUAL) {
+      free (command);
+      continue;
+    }
+
+    if (PARALLEL_SERIAL) {
+      int status = system (command);
+      if (status) {
+	fprintf (stderr, "ERROR running relastro_client\n");
+	exit (2);
+      }
+    } else {
+      // launch the job on the remote machine (no handshake)
+      int errorInfo = 0;
+      int pid = rconnect ("ssh", table->hosts[i].hostname, command, table->hosts[i].stdio, &errorInfo, FALSE);
+      if (!pid) {
+	if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", table->hosts[i].hostname, errorInfo);
+	exit (1);
+      }
+      table->hosts[i].pid = pid; // save for future reference
+    }
+    free (command);
+  }
+
+  if (PARALLEL_MANUAL) {
+    fprintf (stderr, "run the relastro_client commands above.  when these are done, hit return\n");
+    getchar();
+  }
+  if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
+    HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+  }
+
+  FreeHostTable (table);
+  return TRUE;
+}      
Index: /trunk/Ohana/src/relastro/src/UpdateObjectOffsets.c
===================================================================
--- /trunk/Ohana/src/relastro/src/UpdateObjectOffsets.c	(revision 39692)
+++ /trunk/Ohana/src/relastro/src/UpdateObjectOffsets.c	(revision 39693)
@@ -194,5 +194,5 @@
     if (USE_FIXED_PIXCOORDS) strextend (&command, "-D USE_FIXED_PIXCOORDS 1"); 
 
-    if (REPAIR_STACKS)          strextend (&command, "-repair-stacks");
+    if (REPAIR_STACKS)          strextend (&command, "-repair-stacks-on-update");
     if (CHECK_MEASURE_TO_IMAGE) strextend (&command, "-check-measures");
 
@@ -327,5 +327,5 @@
     if (USE_FIXED_PIXCOORDS) strextend (&command, "-D USE_FIXED_PIXCOORDS 1"); 
 
-    if (REPAIR_STACKS)          strextend (&command, "-repair-stacks");
+    if (REPAIR_STACKS)          strextend (&command, "-repair-stacks-on-update");
     if (CHECK_MEASURE_TO_IMAGE) strextend (&command, "-check-measures");
 
Index: /trunk/Ohana/src/relastro/src/args.c
===================================================================
--- /trunk/Ohana/src/relastro/src/args.c	(revision 39692)
+++ /trunk/Ohana/src/relastro/src/args.c	(revision 39693)
@@ -53,4 +53,13 @@
   }
 
+  if ((N = get_argument (argc, argv, "-repair-stacks"))) {
+    remove_argument (N, &argc, argv);
+    RELASTRO_OP = OP_REPAIR_STACKS;
+  }
+  if ((N = get_argument (argc, argv, "-repair-object-id"))) {
+    remove_argument (N, &argc, argv);
+    RELASTRO_OP = OP_REPAIR_OBJECT_ID;
+  }
+
   if ((N = get_argument (argc, argv, "-repair-warps"))) {
     remove_argument (N, &argc, argv);
@@ -59,5 +68,5 @@
 
   REPAIR_STACKS = FALSE;
-  if ((N = get_argument (argc, argv, "-repair-stacks"))) {
+  if ((N = get_argument (argc, argv, "-repair-stacks-on-update"))) {
     remove_argument (N, &argc, argv);
     REPAIR_STACKS = TRUE;
@@ -691,4 +700,14 @@
   }
 
+  if ((N = get_argument (argc, argv, "-repair-stacks"))) {
+    remove_argument (N, &argc, argv);
+    RELASTRO_OP = OP_REPAIR_STACKS;
+  }
+
+  if ((N = get_argument (argc, argv, "-repair-object-id"))) {
+    remove_argument (N, &argc, argv);
+    RELASTRO_OP = OP_REPAIR_OBJECT_ID;
+  }
+
   if ((N = get_argument (argc, argv, "-repair-warps"))) {
     remove_argument (N, &argc, argv);
@@ -697,5 +716,5 @@
 
   REPAIR_STACKS = FALSE;
-  if ((N = get_argument (argc, argv, "-repair-stacks"))) {
+  if ((N = get_argument (argc, argv, "-repair-stacks-on-update"))) {
     remove_argument (N, &argc, argv);
     REPAIR_STACKS = TRUE;
Index: /trunk/Ohana/src/relastro/src/relastro.c
===================================================================
--- /trunk/Ohana/src/relastro/src/relastro.c	(revision 39692)
+++ /trunk/Ohana/src/relastro/src/relastro.c	(revision 39693)
@@ -104,4 +104,44 @@
     }
 
+    case OP_REPAIR_STACKS: {
+      FITS_DB db;
+      if (!PARALLEL) {
+      
+	set_db (&db);
+	gfits_db_init (&db);
+
+	/* lock and load the image db table */
+	int status = dvo_image_lock (&db, ImageCat, 60.0, LCK_SOFT);
+	if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+	if (db.dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
+	if (!dvo_image_load (&db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db.filename);
+	// the raw FITS data is freed by dvo_image_load, leaving only the Image structure data
+
+	/* load regions and images based on specified sky patch (default depth) */
+	load_images (&db, skylist, FALSE, USE_ALL_IMAGES);
+      }
+
+      // iterate over catalogs to make detection coordinates consistant
+      RepairStacks (skylist, 0, NULL);
+
+      if (!PARALLEL) {
+	freeImages (db.ftable.buffer);
+	gfits_db_free (&db);
+	freeMosaics ();
+      }	
+
+      relastro_free (sky, skylist);
+      exit (0);
+    }
+
+    case OP_REPAIR_OBJECT_ID: {
+
+      // iterate over catalogs to make detection coordinates consistant
+      RepairObjectIDs (skylist, 0, NULL);
+
+      relastro_free (sky, skylist);
+      exit (0);
+    }
+
     case OP_HIGH_SPEED:
       /* high-speed is a 2pt cross-correlation process for linking moving objects (high PM) */
Index: /trunk/Ohana/src/relastro/src/relastro_client.c
===================================================================
--- /trunk/Ohana/src/relastro/src/relastro_client.c	(revision 39692)
+++ /trunk/Ohana/src/relastro/src/relastro_client.c	(revision 39693)
@@ -104,4 +104,40 @@
     }
 
+    case OP_REPAIR_OBJECT_ID: {
+
+      // iterate over catalogs to make detection coordinates consistant
+      RepairObjectIDs (skylist, HOST_ID, HOSTDIR);
+
+      relastro_free (sky, skylist);
+      exit (0);
+    }
+
+      // XXX loading the images is fairly costly -- see if we can do an image subset?
+    case OP_REPAIR_STACKS: {
+      FITS_DB db;
+      
+      set_db (&db);
+      gfits_db_init (&db);
+
+      /* lock and load the image db table */
+      int status = dvo_image_lock (&db, ImageCat, 60.0, LCK_SOFT);
+      if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+      if (db.dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
+      if (!dvo_image_load (&db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db.filename);
+      // the raw FITS data is freed by dvo_image_load, leaving only the Image structure data
+
+      /* load regions and images based on specified sky patch (default depth) */
+      load_images (&db, skylist, FALSE, USE_ALL_IMAGES);
+
+      RepairStacks (skylist, HOST_ID, HOSTDIR);
+      
+      freeImages (db.ftable.buffer);
+      gfits_db_free (&db);
+      freeMosaics ();
+
+      relastro_client_free (sky, skylist);
+      break;
+    }
+
       // XXX loading the images is fairly costly -- see if we can do an image subset?
     case OP_REPAIR_WARPS: {
