Index: /branches/eam_branches/ipp-20120405/Ohana/src/relphot/include/relphot.h
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/relphot/include/relphot.h	(revision 33884)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/relphot/include/relphot.h	(revision 33885)
@@ -145,4 +145,5 @@
 int    PLOTDELAY;
 int    UpdateAverages;
+int    ApplyOffsets;
 
 char  *PhotcodeList;
@@ -250,5 +251,5 @@
 
 SkyList      *load_images         PROTO((FITS_DB *db, char *regionName, SkyRegion *region));
-Image        *select_images       PROTO((SkyList *skylist, Image *timage, off_t Ntimage, char *inSubset, off_t **LineNumber, off_t *Nimage));
+Image        *select_images       PROTO((SkyList *skylist, Image *timage, off_t Ntimage, char *inSubset, off_t **LineNumber, off_t *Nimage, SkyRegion *region));
 
 int           main                PROTO((int argc, char **argv));
Index: /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/ImageSubset.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/ImageSubset.c	(revision 33884)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/ImageSubset.c	(revision 33885)
@@ -92,4 +92,11 @@
 }
 
+// STATUS is value expected for success
+# define CHECK_STATUS(STATUS,MSG,...)					\
+  if (!(STATUS)) {							\
+    fprintf (stderr, MSG, __VA_ARGS__);					\
+    return FALSE;							\
+  }
+
 int ImageSubsetSave(char *filename, ImageSubset *image, off_t Nimage) {
 
@@ -167,8 +174,16 @@
   }
 
-  gfits_fwrite_header  (f, &header);
-  gfits_fwrite_matrix  (f, &matrix);
-  gfits_fwrite_Theader (f, &theader);
-  gfits_fwrite_table  (f, &ftable);
+  int status;
+  status = gfits_fwrite_header  (f, &header);
+  CHECK_STATUS (status, "ERROR: cannot write header for image subset %s\n", filename);
+
+  status = gfits_fwrite_matrix  (f, &matrix);
+  CHECK_STATUS (status, "ERROR: cannot write matrix for image subset %s\n", filename);
+
+  status = gfits_fwrite_Theader (f, &theader);
+  CHECK_STATUS (status, "ERROR: cannot write table header for image subset %s\n", filename);
+
+  status = gfits_fwrite_table  (f, &ftable);
+  CHECK_STATUS (status, "ERROR: cannot write table data for image subset %s\n", filename);
 
   gfits_free_header (&header);
@@ -177,6 +192,14 @@
   gfits_free_table (&ftable);
 
-  fclose (f);
-  fflush (f);
+  int fd = fileno (f);
+
+  status = fflush (f);
+  CHECK_STATUS (!status, "ERROR: cannot flush file image subset %s\n", filename);
+
+  status = fsync (fd);
+  CHECK_STATUS (!status, "ERROR: cannot flush file image subset %s\n", filename);
+
+  status = fclose (f);
+  CHECK_STATUS (!status, "ERROR: problem closing image subset file %s\n", filename);
 
   return TRUE;
Index: /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/args.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/args.c	(revision 33884)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/args.c	(revision 33885)
@@ -307,4 +307,10 @@
   }
 
+  ApplyOffsets = FALSE;
+  if ((N = get_argument (argc, argv, "-apply-offsets"))) {
+    remove_argument (N, &argc, argv);
+    ApplyOffsets = TRUE;
+  }
+
   if (UpdateAverages && (argc == 1)) return TRUE;
   if (argc != 2) relphot_usage ();
Index: /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/load_catalogs.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/load_catalogs.c	(revision 33884)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/load_catalogs.c	(revision 33885)
@@ -190,5 +190,10 @@
   }
   if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
-    HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+    // if any one of the remote jobs fails, we should fail and exit
+    int status = HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+    if (!status) {
+      fprintf (stderr, "at least one remote client job failed to load data, exiting\n");
+      exit (3);
+    }
   }
 
Index: /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/load_images.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/load_images.c	(revision 33884)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/load_images.c	(revision 33885)
@@ -50,5 +50,5 @@
     // select the images which overlap the selected sky regions
     // 'subset' points to a new copy of the data (different from 'image')
-    subset = select_images (skylist, image, Nimage, inSubset, &LineNumber, &Nsubset);
+    subset = select_images (skylist, image, Nimage, inSubset, &LineNumber, &Nsubset, NULL);
     MARKTIME("selected %d overlapping images: %f sec\n", (int) Nsubset, dtime);
   } else {
@@ -59,10 +59,7 @@
       skylist = SkyListByPatch (sky, -1, &subregion);
 
-      subregion.Rmin = region[0].Rmin; subregion.Rmax = 360.0; 
-      SkyList *extraList = SkyListByPatch (sky, -1, &subregion);
-
       // select the images which overlap the selected sky regions
       // 'subset' points to a new copy of the data (different from 'image')
-      subset = select_images (skylist, image, Nimage, inSubset, &LineNumber, &Nsubset);
+      subset = select_images (skylist, image, Nimage, inSubset, &LineNumber, &Nsubset, &subregion);
       MARKTIME("selected %d overlapping images: %f sec\n", (int) Nsubset, dtime);
 
@@ -71,5 +68,8 @@
       off_t *LineNumberExtra, i;
 
-      subsetExtra = select_images (extraList, image, Nimage, inSubset, &LineNumberExtra, &NsubsetExtra);
+      subregion.Rmin = region[0].Rmin; subregion.Rmax = 360.0; 
+      SkyList *extraList = SkyListByPatch (sky, -1, &subregion);
+
+      subsetExtra = select_images (extraList, image, Nimage, inSubset, &LineNumberExtra, &NsubsetExtra, &subregion);
       MARKTIME("selected %d overlapping images: %f sec\n", (int) Nsubset, dtime);
 
@@ -88,8 +88,17 @@
       // select the images which overlap the selected sky regions
       // 'subset' points to a new copy of the data (different from 'image')
-      subset = select_images (skylist, image, Nimage, inSubset, &LineNumber, &Nsubset);
+      subset = select_images (skylist, image, Nimage, inSubset, &LineNumber, &Nsubset, region);
       MARKTIME("selected %d overlapping images: %f sec\n", (int) Nsubset, dtime);
     }
   } 
+
+# if (1)
+  FILE *ftest = fopen ("skydump.dat", "w");
+  int i;
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    fprintf (ftest, "%s : %f %f : %f %f\n", skylist[0].regions[i][0].name, skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmin, skylist[0].regions[i][0].Dmax);
+  }
+  fclose (ftest);
+# endif
 
   // match chips to mosaics (if applicable)
Index: /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/reload_catalogs.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/reload_catalogs.c	(revision 33884)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/reload_catalogs.c	(revision 33885)
@@ -120,15 +120,24 @@
 int reload_catalogs_parallel (SkyList *sky) {
 
-  off_t Nimage;
-  ImageSubset *image = getimages_subset (&Nimage);
-
-  // write out the subset table of image information
+  // name of image subset file:
   char imageFile[512];
   snprintf (imageFile, 512, "%s/Images.subset.dat", CATDIR);
-  if (!ImageSubsetSave (imageFile, image, Nimage)) {
-    fprintf (stderr, "failed to write image subset\n");
-    exit (1);
-  }
-  free (image);
+
+  // the ApplyOffsets option re-uses an existing Images.subset.dat file
+  if (!ApplyOffsets) {
+    off_t Nimage;
+    ImageSubset *image = getimages_subset (&Nimage);
+    if (!ImageSubsetSave (imageFile, image, Nimage)) {
+      fprintf (stderr, "failed to write image subset\n");
+      exit (1);
+    }
+    free (image);
+  } else {
+    // load the current sky table (layout of all SkyRegions) 
+    SkyTable *skytable = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
+    // XXX kind of hackish...
+    ALLOCATE (sky, SkyList, 1);
+    strcpy (sky->hosts, skytable->hosts);
+  }
 
   // now launch the relphot_client jobs to the parallel hosts
@@ -202,5 +211,9 @@
   } 
   if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
-    HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+    int status = HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+    if (!status) {
+      fprintf (stderr, "at least one remote client job failed to load data, exiting\n");
+      exit (3);
+    }
   }
   return (TRUE);
Index: /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/relphot.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/relphot.c	(revision 33884)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/relphot.c	(revision 33885)
@@ -23,4 +23,14 @@
   if (UpdateAverages) {
     relphot_objects (0, NULL);
+    exit (0);
+  }
+
+  if (ApplyOffsets) {
+    // re-run this step from a previous attempt (assumes an existing Images.subset.dat file)
+    if (!PARALLEL) {
+      fprintf (stderr, "-apply-offsets only makes sense in an parallel context\n");
+      exit (2);
+    }
+    reload_catalogs (NULL, NULL, 0, NULL);
     exit (0);
   }
Index: /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/select_images.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/select_images.c	(revision 33884)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/relphot/src/select_images.c	(revision 33885)
@@ -13,4 +13,5 @@
 } SkyRegionCoords;
 
+void MakeSkyCoordIndex (SkyRegionCoords **skycoords_out, double **RmaxSky_out, off_t **index_out, SkyList *skylist);
 void dsortindex (double *X, off_t *Y, int N);
 off_t getRegionStartByRA (double R, double *Rref, off_t Nregions);
@@ -22,5 +23,5 @@
   fprintf (stderr, MSG, __VA_ARGS__); }
 
-Image *select_images (SkyList *skylist, Image *timage, off_t Ntimage, char *inSubset, off_t **LineNumber, off_t *Nimage) {
+Image *select_images (SkyList *skylist, Image *timage, off_t Ntimage, char *inSubset, off_t **LineNumber, off_t *Nimage, SkyRegion *region) {
   
   Image *image;
@@ -28,12 +29,8 @@
   off_t *line_number;
   int InRange, ecode, found;
-  double Ri[5], Di[5], Xi[5], Yi[5], dx, dy;
+  double Ri[5], Di[5], Xi[5], Yi[5];
   Coords tcoords;
-  SkyRegionCoords *skycoords;
   struct timeval start, stop;
   
-  double *RmaxSky;
-  off_t *index;
-
   if (skylist[0].Nregions < 1) {
     *Nimage = 0;
@@ -52,79 +49,10 @@
   strcpy (tcoords.ctype, "RA---TAN");
 
-  ALLOCATE (skycoords, SkyRegionCoords, skylist[0].Nregions);
-
-  ALLOCATE (RmaxSky, double, skylist[0].Nregions);
-  ALLOCATE (index, off_t, skylist[0].Nregions);
-
-  double RminSkyRegion = +360.0;
-  double RmaxSkyRegion = -360.0;
-  double DminSkyRegion = +90.0;
-  double DmaxSkyRegion = -90.0;
-
-  D_NIMAGE = 6000;
-
-  // FILE *ftest = fopen ("relphot.dump.dat", "w");
-
-  // The regions have RA values in the range 0-360, which implies an RA midpoint of 180.
-  // A patch which covers the 0,360 boundary (but not much more) needs to treat the values
-  // as being centered on 0.0.  Run the following test with both and see which yields a
-  // smaller contiguious patch
-
-  double RminSkyRegionAlt = +360.0;
-  double RmaxSkyRegionAlt = -360.0;
-
-  /* compare with each region file */
-  for (i = 0; i < skylist[0].Nregions; i++) { 
-
-    /* we make positional comparisons in the projection of catalog */
-    skycoords[i].Rc = 0.5*(skylist[0].regions[i][0].Rmax + skylist[0].regions[i][0].Rmin);
-    skycoords[i].Dc = 0.5*(skylist[0].regions[i][0].Dmax + skylist[0].regions[i][0].Dmin);
-    tcoords.crval1 = skycoords[i].Rc;
-    tcoords.crval2 = skycoords[i].Dc;
-
-    /* define catalog corners */
-    RD_to_XY (&skycoords[i].Xc[0], &skycoords[i].Yc[0], skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Dmin, &tcoords);
-    RD_to_XY (&skycoords[i].Xc[1], &skycoords[i].Yc[1], skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmin, &tcoords);
-    RD_to_XY (&skycoords[i].Xc[2], &skycoords[i].Yc[2], skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmax, &tcoords);
-    RD_to_XY (&skycoords[i].Xc[3], &skycoords[i].Yc[3], skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Dmax, &tcoords);
-    skycoords[i].Xc[4] = skycoords[i].Xc[0];    
-    skycoords[i].Yc[4] = skycoords[i].Yc[0];    
-
-    RmaxSky[i] = skylist[0].regions[i][0].Rmax;
-    index[i] = i;
-
-    dx = 0.02*(skycoords[i].Xc[2] - skycoords[i].Xc[0]);
-    dy = 0.02*(skycoords[i].Yc[2] - skycoords[i].Yc[0]);
-    skycoords[i].Xc[0] -= dx; skycoords[i].Yc[0] -= dy;
-    skycoords[i].Xc[1] += dx; skycoords[i].Yc[1] -= dy;
-    skycoords[i].Xc[2] += dx; skycoords[i].Yc[2] += dy;
-    skycoords[i].Xc[3] -= dx; skycoords[i].Yc[3] += dy;
-    skycoords[i].Xc[4] -= dx; skycoords[i].Yc[4] -= dy;
-
-    RminSkyRegion = MIN(RminSkyRegion, skylist[0].regions[i][0].Rmin);
-    RmaxSkyRegion = MAX(RmaxSkyRegion, skylist[0].regions[i][0].Rmax);
-    DminSkyRegion = MIN(DminSkyRegion, skylist[0].regions[i][0].Dmin);
-    DmaxSkyRegion = MAX(DmaxSkyRegion, skylist[0].regions[i][0].Dmax);
-
-    double RminAlt   = ohana_normalize_angle_to_midpoint (skylist[0].regions[i][0].Rmin, 0.0);
-    double RmaxAlt   = ohana_normalize_angle_to_midpoint (skylist[0].regions[i][0].Rmax, 0.0);
-    RminSkyRegionAlt = MIN(RminSkyRegionAlt, RminAlt);
-    RmaxSkyRegionAlt = MAX(RmaxSkyRegionAlt, RmaxAlt);
-
-    RminSkyRegion = MIN(RminSkyRegion, skylist[0].regions[i][0].Rmin);
-    RmaxSkyRegion = MAX(RmaxSkyRegion, skylist[0].regions[i][0].Rmax);
-    DminSkyRegion = MIN(DminSkyRegion, skylist[0].regions[i][0].Dmin);
-    DmaxSkyRegion = MAX(DmaxSkyRegion, skylist[0].regions[i][0].Dmax);
-  }
-  // use the option which gives the smaller RA range
-  if ((RmaxSkyRegionAlt - RminSkyRegionAlt) < (RmaxSkyRegion - RminSkyRegion)) {
-    RminSkyRegion = RminSkyRegionAlt;
-    RmaxSkyRegion = RmaxSkyRegionAlt;
-  }
+  double RminSkyRegion = region[0].Rmin;
+  double RmaxSkyRegion = region[0].Rmax;
+  double DminSkyRegion = region[0].Dmin;
+  double DmaxSkyRegion = region[0].Dmax;
+
   double RmidSkyRegion = 0.5*(RminSkyRegion + RmaxSkyRegion);
-  MARKTIME("create sky region coords: %f sec\n", dtime);
-
-  dsortindex (RmaxSky, index, skylist[0].Nregions);
-  MARKTIME("sort sky coords: %f sec\n", dtime);
 
   // generate a set of Rmin/Rmax values using this RmidSkyRegion for DEC bands of width
@@ -154,6 +82,6 @@
   }
 
-# if (0)
-  // XXX quick test
+# if (1)
+  // XXX quick test of the dec bands:
   FILE *fout = fopen ("dec.bands.dat", "w");
   for (i = 0; i < NDecBands; i++) {
@@ -163,7 +91,17 @@
 # endif
 
+  SkyRegionCoords *skycoords = NULL;
+  double *RmaxSky = NULL;
+  off_t *index = NULL;
+
+  if (!USE_BASIC_CHECK) {
+    MakeSkyCoordIndex (&skycoords, &RmaxSky, &index, skylist);
+  }
+
   if (VERBOSE) fprintf (stderr, "finding images\n");
   BuildChipMatch (timage, Ntimage);
   MARKTIME("build chip match for %d images: %f sec\n", (int) Ntimage, dtime);
+
+  D_NIMAGE = 6000;
 
   nimage = 0;
@@ -266,6 +204,4 @@
       continue;
     }
-
-    // fprintf (ftest, "%s %lf %lf - %lf %lf : %lf %lf\n", timage[i].name, RminImage, DminImage, RmaxImage, DmaxImage, 0.5*(RminImage + RmaxImage), 0.5*(DminImage + DmaxImage));
 
     // image overlaps region, keep it
@@ -339,13 +275,14 @@
   MARKTIME("finish image selection: %f sec\n", dtime);
 
-  // fclose (ftest);
-
   if (VERBOSE) fprintf (stderr, "found "OFF_T_FMT" images\n", nimage);
 
   REALLOCATE (image, Image, MAX (nimage, 1));
   REALLOCATE (line_number, off_t, MAX (nimage, 1));
-  free (skycoords);
-  free (RmaxSky);
-  free (index);
+
+  if (!USE_BASIC_CHECK) {
+    free (skycoords);
+    free (RmaxSky);
+    free (index);
+  }
 
   *Nimage  = nimage;
@@ -463,2 +400,61 @@
   return (Nlo);
 }
+
+void MakeSkyCoordIndex (SkyRegionCoords **skycoords_out, double **RmaxSky_out, off_t **index_out, SkyList *skylist) {
+
+  off_t i;
+  SkyRegionCoords *skycoords;
+  Coords tcoords;
+  double *RmaxSky;
+  off_t *index;
+  double dx, dy;
+
+  // the comparison is made in the catalog local projection. below we set crval1,2
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1  = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2  = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  /* compare with each region file */
+  ALLOCATE (skycoords, SkyRegionCoords, skylist[0].Nregions);
+
+  ALLOCATE (RmaxSky, double, skylist[0].Nregions);
+  ALLOCATE (index, off_t, skylist[0].Nregions);
+
+  for (i = 0; i < skylist[0].Nregions; i++) { 
+
+    /* we make positional comparisons in the projection of catalog */
+    skycoords[i].Rc = 0.5*(skylist[0].regions[i][0].Rmax + skylist[0].regions[i][0].Rmin);
+    skycoords[i].Dc = 0.5*(skylist[0].regions[i][0].Dmax + skylist[0].regions[i][0].Dmin);
+    tcoords.crval1 = skycoords[i].Rc;
+    tcoords.crval2 = skycoords[i].Dc;
+
+    /* define catalog corners */
+    RD_to_XY (&skycoords[i].Xc[0], &skycoords[i].Yc[0], skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Dmin, &tcoords);
+    RD_to_XY (&skycoords[i].Xc[1], &skycoords[i].Yc[1], skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmin, &tcoords);
+    RD_to_XY (&skycoords[i].Xc[2], &skycoords[i].Yc[2], skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmax, &tcoords);
+    RD_to_XY (&skycoords[i].Xc[3], &skycoords[i].Yc[3], skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Dmax, &tcoords);
+    skycoords[i].Xc[4] = skycoords[i].Xc[0];    
+    skycoords[i].Yc[4] = skycoords[i].Yc[0];    
+
+    RmaxSky[i] = skylist[0].regions[i][0].Rmax;
+    index[i] = i;
+
+    dx = 0.02*(skycoords[i].Xc[2] - skycoords[i].Xc[0]);
+    dy = 0.02*(skycoords[i].Yc[2] - skycoords[i].Yc[0]);
+    skycoords[i].Xc[0] -= dx; skycoords[i].Yc[0] -= dy;
+    skycoords[i].Xc[1] += dx; skycoords[i].Yc[1] -= dy;
+    skycoords[i].Xc[2] += dx; skycoords[i].Yc[2] += dy;
+    skycoords[i].Xc[3] -= dx; skycoords[i].Yc[3] += dy;
+    skycoords[i].Xc[4] -= dx; skycoords[i].Yc[4] -= dy;
+  }
+
+  dsortindex (RmaxSky, index, skylist[0].Nregions);
+
+  *RmaxSky_out = RmaxSky;
+  *index_out = index;
+  *skycoords_out = skycoords;
+
+  return;
+}
