Index: /branches/eam_branches/ipp-20140206/Ohana/src/libdvo/include/dvo.h
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/libdvo/include/dvo.h	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/libdvo/include/dvo.h	(revision 36558)
@@ -291,4 +291,9 @@
   double Dmin;
   double Dmax;
+
+  double RminCat;
+  double RmaxCat;
+  double DminCat;
+  double DmaxCat;
 
   char *hostname;
Index: /branches/eam_branches/ipp-20140206/Ohana/src/libdvo/src/RegionHostTable.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/libdvo/src/RegionHostTable.c	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/libdvo/src/RegionHostTable.c	(revision 36558)
@@ -11,4 +11,9 @@
     hosts[i].Dmin = NAN;
     hosts[i].Dmax = NAN;
+
+    hosts[i].RminCat = NAN;
+    hosts[i].RmaxCat = NAN;
+    hosts[i].DminCat = NAN;
+    hosts[i].DmaxCat = NAN;
 
     hosts[i].hostname = NULL;
@@ -122,4 +127,9 @@
     hosts[Nhosts].Dmin = Dmin;
     hosts[Nhosts].Dmax = Dmax;
+    
+    hosts[Nhosts].RminCat = Rmin;
+    hosts[Nhosts].RmaxCat = Rmax;
+    hosts[Nhosts].DminCat = Dmin;
+    hosts[Nhosts].DmaxCat = Dmax;
     
     table->Rmin = MIN(Rmin, table->Rmin);
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/include/relphot.h
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/include/relphot.h	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/include/relphot.h	(revision 36558)
@@ -214,4 +214,6 @@
 int    PARALLEL_MANUAL;
 int    PARALLEL_SERIAL;
+
+int    PARALLEL_REGIONS_MANUAL;
 
 int    NTHREADS;
@@ -314,4 +316,8 @@
 void          findImages          PROTO((Catalog *catalog, int Ncatalog, int doImageList));
 int           findMosaics         PROTO((Catalog *catalog, int Ncatalog, int doMosaicList));
+
+void makeMosaics (Image *image, off_t Nimage);
+Mosaic *getMosaicForImage (off_t im);
+void setMosaicCenters (Image *image, off_t Nimage);
 
 void set_db (FITS_DB *in);
@@ -467,4 +473,5 @@
 int select_images_hostregion (RegionHostTable *hosts, Image *image, off_t Nimage);
 int find_host_for_coords (RegionHostTable *regionHosts, double R, double d);
+int calculate_image_bounds (Image *image, double *rmin, double *rmax, double *dmin, double *dmax);
 
 int launch_region_hosts (RegionHostTable *regionHosts);
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/MosaicOps.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/MosaicOps.c	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/MosaicOps.c	(revision 36558)
@@ -320,4 +320,157 @@
 }
 
+/* find mosaic frames (unique time periods) (NOTE : we do NOT require matching photcodes but we 
+   match images by MOSAICNAME.  this last point is weak: it forces a single camera at a time.
+   we can extend the logic to multiple cameras if we make list of MOSAICNAMES (better to assign a camera ID)
+ */
+void makeMosaics (Image *image, off_t Nimage) {
+
+  off_t i, j, status, found, NMOSAIC, *MosaicN_IMAGE;
+  unsigned int start, stop, *startTimes, *startTimesMosaic;
+  char *pname;
+
+  if (!MOSAIC_ZEROPT) return;
+
+  INITTIME;
+
+  /* a 'mosaic' in relphot is (unlike relastro) a virtual concept: there is no 
+   * entry in the image table that represents this mosaic.  Instead, it is an
+   * internal construct that defines a group of related images 
+   */
+
+  // generate a list of all image start times
+  ALLOCATE (startTimes, unsigned int, Nimage);
+  for (i = 0; i < Nimage; i++) {
+    startTimes[i] = image[i].tzero;
+  }
+  sort_times (startTimes, Nimage);
+  MARKTIME("create array of all image obstimes: %f sec\n", dtime);
+  
+  Nmosaic = 0;
+  NMOSAIC = 1000;
+  ALLOCATE (startTimesMosaic, unsigned int, NMOSAIC);
+  startTimesMosaic[0] = startTimes[0];
+
+  // generate a list of the unique start times (these define the mosaics)
+  for (i = 0; i < Nimage; i++) {
+    if (startTimes[i] < startTimesMosaic[Nmosaic]) {
+      fprintf (stderr, "error?\n");
+      abort();
+    }
+    if (startTimes[i] == startTimesMosaic[Nmosaic]) continue;
+    Nmosaic ++;
+    if (Nmosaic >= NMOSAIC) {
+      NMOSAIC += 1000;
+      REALLOCATE (startTimesMosaic, unsigned int, NMOSAIC);
+    }
+    startTimesMosaic[Nmosaic] = startTimes[i];
+  }
+  Nmosaic ++;
+  MARKTIME("create array of mosaic obstimes: %f sec\n", dtime);
+
+  // now I have a list of uniq start times, and they are in order
+  // create the mosaic arrays for these times
+  ALLOCATE (mosaic, Mosaic, Nmosaic);
+
+  ALLOCATE (MosaicToImage, off_t *, Nmosaic);
+  ALLOCATE (MosaicN_Image, off_t,   Nmosaic);
+  ALLOCATE (MosaicN_IMAGE, off_t,   Nmosaic);
+
+  // init the mosaic array values
+  for (i = 0; i < Nmosaic; i++) {
+    mosaic[i].start = startTimesMosaic[i];
+    mosaic[i].stop  = 0;
+    mosaic[i].Mcal  = 0.0;
+    mosaic[i].dMcal = 0.0;
+    mosaic[i].dMsys = 0.0;
+    mosaic[i].Xm    = 0.0;
+    mosaic[i].flags = 0;
+    mosaic[i].secz  = NAN;
+    mosaic[i].photcode = 0;
+    mosaic[i].skipCal = FALSE;
+    
+    memset (&mosaic[i].coords, 0, sizeof(Coords));
+
+    MosaicN_IMAGE[i] = 10;
+    MosaicN_Image[i] = 0;
+    ALLOCATE (MosaicToImage[i], off_t, MosaicN_IMAGE[i]);
+    MosaicToImage[i][0] = -1;
+  }
+
+  ALLOCATE (ImageToMosaic, off_t, Nimage); // mosaic to which image belongs
+
+  // assign each image to a mosaic
+  for (i = 0; i < Nimage; i++) {
+    ImageToMosaic[i] = -1;
+
+    /* select valid mosaic images by photcode */
+    pname = GetPhotcodeNamebyCode (image[i].photcode);
+    if (!pname) continue;
+
+    status = strncmp (pname, MOSAICNAME, strlen (MOSAICNAME));
+    if (status) continue;
+
+    start = image[i].tzero;
+    stop  = image[i].tzero + MAX(1.01*image[i].trate*image[i].NY, 1);
+
+    j = findMosaic(startTimesMosaic, Nmosaic, start);
+    if (j == -1) {
+      fprintf (stderr, "programming error? all image images should belong to a mosaic\n");
+      abort();
+    }
+
+    // add reference from image to mosaic
+    ImageToMosaic[i] = j;
+
+    // have we already found this mosaic?
+    found = (MosaicN_Image[j] > 0);
+
+    /* add image to mosaic image list */
+    MosaicToImage[j][MosaicN_Image[j]] = i;
+    MosaicN_Image[j] ++;
+    if (MosaicN_Image[j] == MosaicN_IMAGE[j]) {
+      MosaicN_IMAGE[j] += 10;
+      REALLOCATE (MosaicToImage[j], off_t, MosaicN_IMAGE[j]);
+    }
+    if (found) continue;
+    
+    /* a new mosaic, define ranges */
+    if (mosaic[j].start != start) { 
+      fprintf (stderr, "error?\n");
+      abort();
+    }
+    mosaic[j].stop  = stop;
+    mosaic[j].Mcal  = 0.0;
+    mosaic[j].dMcal = 0.0;
+    mosaic[j].Xm    = 0.0;
+    mosaic[j].dMsys = image[i].flags;
+    mosaic[j].flags = image[i].flags;
+    mosaic[j].secz  = image[i].secz;
+    mosaic[j].photcode = GetPhotcodeEquivCodebyCode (image[i].photcode);
+  }
+  MARKTIME("assign images to mosaic: %f sec\n", dtime);
+
+  // free this or not?
+  free (MosaicN_IMAGE);
+  free (startTimes);
+  free (startTimesMosaic);
+
+  fprintf (stderr, "matched %d images to %d mosaics\n", (int) Nimage, (int) Nmosaic);
+
+  return;
+}
+
+Mosaic *getMosaicForImage (off_t im) {
+
+  if (im < 0) return NULL;
+  if (!ImageToMosaic) return NULL;
+
+  off_t m = ImageToMosaic[im];
+  if (m < 0) return NULL;
+  if (m >= Nmosaic) return NULL;
+
+  return (&mosaic[m]);
+}
+
 // use bisection to find the overlapping mosaic (returns exact match)
 // startTimes is a sorted, unique list of times
@@ -350,4 +503,65 @@
   }
   return (-1);
+}
+
+void setMosaicCenters (Image *image, off_t Nimage) {
+
+  /* find max dR, dD range for all mosaics */
+  /* define mosaic.coords to cover dR, dD */
+  /* send results to initGridBins */
+
+  off_t i, j, m, NX, NY;
+  double R, D, Rmid, Dmid;
+  double Mcal, dMcal, Xm;
+
+  for (i = 0; i < Nmosaic; i++) {
+    Rmid = Dmid = 0.0;
+    Mcal = dMcal = Xm = 0;
+    for (j = 0; j < MosaicN_Image[i]; j++) {
+      m = MosaicToImage[i][j];
+
+      if (!FindMosaicForImage (image, Nimage, m)) {
+	if (VERBOSE2) fprintf (stderr, "cannot find mosaic for "OFF_T_FMT"\n", i);
+	continue;
+      }
+
+      NX = image[m].NX;
+      NY = image[m].NY;
+      XY_to_RD (&R, &D, 0.5*NX, 0.5*NY, &image[m].coords);
+
+      Rmid += R;
+      Dmid += D;
+
+      Mcal  += image[m].Mcal;
+      dMcal += image[m].dMcal;
+      Xm    += image[m].Xm;
+
+      // for ubercal images, we (elsewhere) keep Mcal frozen
+
+      /* we are using mosaic.Mcal, not image.Mcal. reset image.Mcal */
+      image[m].Mcal  = 0.0;
+      image[m].dMcal = NAN;
+      image[m].Xm    = NAN_S_SHORT;
+    }
+    Rmid = Rmid / MosaicN_Image[i];
+    Dmid = Dmid / MosaicN_Image[i];
+
+    strcpy (mosaic[i].coords.ctype, "DEC--TAN");
+    mosaic[i].coords.crval1 = Rmid;
+    mosaic[i].coords.crval2 = Dmid;
+    mosaic[i].coords.crpix1 = 0.0;
+    mosaic[i].coords.crpix2 = 0.0;
+    mosaic[i].coords.cdelt1 = 1.0 / 3600.0;
+    mosaic[i].coords.cdelt2 = 1.0 / 3600.0;
+    mosaic[i].coords.pc1_1  = 1.0;
+    mosaic[i].coords.pc2_2  = 1.0;
+    mosaic[i].coords.pc1_2  = 0.0;
+    mosaic[i].coords.pc2_1  = 0.0;
+
+    mosaic[i].Mcal  = Mcal / MosaicN_Image[i];
+    mosaic[i].dMcal = dMcal / MosaicN_Image[i];
+    mosaic[i].Xm    = Xm / MosaicN_Image[i];
+  }
+  return;
 }
 
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/args.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/args.c	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/args.c	(revision 36558)
@@ -358,4 +358,8 @@
 
   RelphotMode mode = MODE_ERROR;
+  if ((N = get_argument (argc, argv, "-images"))) {
+    remove_argument (N, &argc, argv);
+    mode = UPDATE_IMAGES;
+  }
   if ((N = get_argument (argc, argv, "-averages"))) {
     remove_argument (N, &argc, argv);
@@ -375,8 +379,14 @@
     if (!REGION_FILE) relphot_usage();
   }
+
+  PARALLEL_REGIONS_MANUAL = FALSE;
   if ((N = get_argument (argc, argv, "-parallel-regions"))) {
     remove_argument (N, &argc, argv);
     mode = PARALLEL_REGIONS;
     if (!REGION_FILE) relphot_usage();
+    if ((N = get_argument (argc, argv, "-parallel-regions-manual"))) {
+      remove_argument (N, &argc, argv);
+      PARALLEL_REGIONS_MANUAL = FALSE;
+    }
   }
 
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/assign_images.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/assign_images.c	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/assign_images.c	(revision 36558)
@@ -20,11 +20,26 @@
   // *** NOTE : for the moment, regions must be in the range 0 - 360, -90 - +90
 
-  if (VERBOSE) fprintf (stderr, "finding images\n");
+  // generate the chip match here so we can define the mosaic centers (if needed)
   BuildChipMatch (image, Nimage);
   MARKTIME("build chip match for %d images: %f sec\n", (int) Nimage, dtime);
+
+  if (MOSAIC_ZEROPT) {
+    makeMosaics (image, Nimage);
+
+    // center coords and Mcal, dMcal, Xm for the mosaics
+    setMosaicCenters (image, Nimage);
+    MARKTIME("set mosaic coordinates and Mcal values: %f sec\n", dtime);
+  }
+
+  // register the image array with ImageOps.c for later getimageByID calls
+  initImages (image, NULL, Nimage);
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
 
   // for each regionHost, select images which are contained by the region
   // even faster would be to use a tree to get to the real regions...
   select_images_hostregion (regionHosts, image, Nimage);
+
+  // calculate_host_image_bounds (regionHosts);
 
   return TRUE;
@@ -64,28 +79,51 @@
     }
     
-    // this adds 1.3 sec for 3M images
+    // do not include DIS (PHU-level mosaics) in the output list
+    if (!strcmp(&image[j].coords.ctype[4], "-DIS")) continue;
+
+    // match the image to its corresponding ASTROMETRIC mosaic (not the same as the Mosaic above)
     if (!FindMosaicForImage (image, Nimage, j)) {
       if (VERBOSE2) fprintf (stderr, "cannot find mosaic for "OFF_T_FMT"\n", i);
       continue;
     }
-
-    // XXX need to make sure mosaics for each saved image are also saved
-    // skip them here and add explicitly below.
-
-    /* define image center - note the DIS images (mosaic phu) are special */
-    double Xc, Yc, Rc, Dc;
-    if (!strcmp(&image[j].coords.ctype[4], "-DIS")) {
-      Xc = 0.0; Yc = 0.0;
+    
+    // use a reference coordinate for each image to assign to hosts
+    double Rc, Dc;
+    if (MOSAIC_ZEROPT) {
+      // use the coords of the associated mosaic to select
+      Mosaic *mosaic = getMosaicForImage (j); 
+      Rc = mosaic->coords.crval1;
+      Dc = mosaic->coords.crval2;
     } else {
+
+      // define image center - note the DIS images (mosaic phu) are special
+      double Xc, Yc;
       Xc = 0.5*image[j].NX; 
       Yc = 0.5*image[j].NY;
-    }
-
-    XY_to_RD (&Rc, &Dc, Xc, Yc, &image[j].coords);
-    Rc = ohana_normalize_angle_to_midpoint (Rc, 180.0);
+
+      XY_to_RD (&Rc, &Dc, Xc, Yc, &image[j].coords);
+      Rc = ohana_normalize_angle_to_midpoint (Rc, 180.0);
+    }
 
     i = find_host_for_coords (regionHosts, Rc, Dc);
 
     if (i == -1) continue;
+
+    RegionHostInfo *host = &regionHosts->hosts[i];
+
+    double Rmin, Rmax, Dmin, Dmax;
+    calculate_image_bounds (&image[j], &Rmin, &Rmax, &Dmin, &Dmax);
+
+    host->RminCat = MIN(Rmin, host->RminCat);
+    host->RmaxCat = MAX(Rmax, host->RmaxCat);
+    host->DminCat = MIN(Dmin, host->DminCat);
+    host->DmaxCat = MAX(Dmax, host->DmaxCat);
+
+    // regionHosts needs to have the full outer boundary
+    // (so reload_catalogs covers the correct region)
+    regionHosts->Rmin = MIN(Rmin, regionHosts->Rmin);
+    regionHosts->Rmax = MAX(Rmax, regionHosts->Rmax);
+    regionHosts->Dmin = MIN(Dmin, regionHosts->Dmin);
+    regionHosts->Dmax = MAX(Dmax, regionHosts->Dmax);
 
     // this is a bit memory expensive : I am making a complete copy of the image table here
@@ -105,4 +143,98 @@
 }
 
+double Xf[] = {0.0, 1.0, 0.0, 1.0};
+double Yf[] = {0.0, 0.0, 1.0, 1.0};
+
+int calculate_image_bounds (Image *image, double *rmin, double *rmax, double *dmin, double *dmax) {
+
+  int n;
+
+  double Rmin = 360.0;
+  double Rmax =   0.0;
+  double Dmin = +90.0;
+  double Dmax = -90.0;
+
+  // define image corners
+  for (n = 0; n < 4; n++) {
+    double Xc, Yc, Rc, Dc;
+    Xc = Xf[n]*image->NX; 
+    Yc = Yf[n]*image->NY;
+    XY_to_RD (&Rc, &Dc, Xc, Yc, &image->coords);
+    Rc = ohana_normalize_angle_to_midpoint (Rc, 180.0);
+      
+    Rmin = MIN (Rmin, Rc);
+    Rmax = MAX (Rmax, Rc);
+    Dmin = MIN (Dmin, Dc);
+    Dmax = MAX (Dmax, Dc);
+  }
+
+  *rmin = Rmin;
+  *rmax = Rmax;
+  *dmin = Dmin;
+  *dmax = Dmax;
+
+  return TRUE;
+}
+
+int calculate_host_image_bounds (RegionHostTable *regionHosts) {
+
+  int i, n;
+  off_t j;
+
+  for (i = 0; i < regionHosts->Nhosts; i++) {
+
+    RegionHostInfo *host = &regionHosts->hosts[i];
+
+    // XXX clear the chip match?
+
+    BuildChipMatch (host->image, host->Nimage);
+
+    double Rmin = 360.0;
+    double Rmax =   0.0;
+    double Dmin = +90.0;
+    double Dmax = -90.0;
+
+    for (j = 0; j < host->Nimage; j++) {
+
+      Image *image = &host->image[j];
+
+      if (!FindMosaicForImage (host->image, host->Nimage, j)) {
+	fprintf (stderr, "missing astrometry? programming error?\n");
+	abort ();
+      }
+      
+      // define image corners
+      for (n = 0; n < 4; n++) {
+	double Xc, Yc, Rc, Dc;
+	Xc = Xf[n]*image->NX; 
+	Yc = Yf[n]*image->NY;
+	XY_to_RD (&Rc, &Dc, Xc, Yc, &image->coords);
+	Rc = ohana_normalize_angle_to_midpoint (Rc, 180.0);
+      
+	Rmin = MIN (Rmin, Rc);
+	Dmin = MIN (Dmin, Rc);
+	
+	Rmax = MAX (Rmax, Rc);
+	Dmax = MAX (Dmax, Rc);
+      }
+
+    }
+
+    host->RminCat = Rmin;
+    host->DminCat = Dmin;
+    host->RmaxCat = Rmax;
+    host->DmaxCat = Dmax;
+
+    // regionHosts needs to have the full outer boundary
+    // (so reload_catalogs covers the correct region)
+    regionHosts->Rmin = MIN(Rmin, regionHosts->Rmin);
+    regionHosts->Rmax = MAX(Rmax, regionHosts->Rmax);
+    regionHosts->Dmin = MIN(Dmin, regionHosts->Dmin);
+    regionHosts->Dmax = MAX(Dmax, regionHosts->Dmax);
+  }
+  return TRUE;
+}
+
+
 // XXX add a search tree to speed this up?
 int find_host_for_coords (RegionHostTable *regionHosts, double Rc, double Dc) {
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/launch_region_hosts.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/launch_region_hosts.c	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/launch_region_hosts.c	(revision 36558)
@@ -56,12 +56,18 @@
     char command[1024];
     snprintf (command, 1024, "relphot %s -parallel-images %s -region-hosts %s -region-hostID %d -D CATDIR %s -region %f %f %f %f -statmode %s -D CAMERA %s -D STAR_TOOFEW %d -minerror %f", 
-	      PhotcodeList, filename, REGION_FILE, host->hostID, CATDIR, host->Rmin, host->Rmax, host->Dmin, host->Dmax, STATMODE, CAMERA, STAR_TOOFEW, MIN_ERROR);
+	      PhotcodeList, filename, REGION_FILE, host->hostID, CATDIR, host->RminCat, host->RmaxCat, host->DminCat, host->DmaxCat, STATMODE, CAMERA, STAR_TOOFEW, MIN_ERROR);
 
-    if (VERBOSE)       strextend (command, "-v");
-    if (VERBOSE2)      strextend (command, "-vv");
-    if (RESET)         strextend (command, "-reset");
-    if (RESET_ZEROPTS) strextend (command, "-reset-zpts");
-    if (UPDATE)        strextend (command, "-update");
-    if (!KEEP_UBERCAL) strextend (command, "-reset-ubercal");
+    if (VERBOSE)       	 strextend (command, "-v");
+    if (VERBOSE2)      	 strextend (command, "-vv");
+    if (RESET)         	 strextend (command, "-reset");
+    if (RESET_ZEROPTS) 	 strextend (command, "-reset-zpts");
+    if (UPDATE)        	 strextend (command, "-update");
+    if (MOSAIC_ZEROPT) 	 strextend (command, "-mosaic");
+    if (FREEZE_IMAGES) 	 strextend (command, "-imfreeze");
+    if (FREEZE_MOSAICS)	 strextend (command, "-mosfreeze");
+    if (!KEEP_UBERCAL) 	 strextend (command, "-reset-ubercal");
+    if (PARALLEL)      	 strextend (command, "-parallel");
+    if (PARALLEL_MANUAL) strextend (command, "-parallel-manual");
+    if (PARALLEL_SERIAL) strextend (command, "-parallel-serial");
 
     // XXX deprecate this if we are happy with the new version
@@ -70,5 +76,5 @@
     fprintf (stderr, "command: %s\n", command);
     
-    if (PARALLEL_MANUAL) continue;
+    if (PARALLEL_REGIONS_MANUAL) continue;
 
     // launch the job on the remote machine (no handshake)
@@ -82,5 +88,5 @@
   }
 
-  if (PARALLEL_MANUAL) {
+  if (PARALLEL_REGIONS_MANUAL) {
     fprintf (stderr, "run the relphot_client commands above.  when these are done, hit return\n");
     getchar();
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/reload_catalogs.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/reload_catalogs.c	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/reload_catalogs.c	(revision 36558)
@@ -156,4 +156,8 @@
   // load the list of hosts
   HostTable *table = HostTableLoad (CATDIR, sky->hosts);
+  if (!table) {
+    fprintf (stderr, "ERROR: problem with parallel host table\n");
+    exit (2);
+  }
 
   if (BOUNDARY_TREE) {
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/relphot_parallel_images.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/relphot_parallel_images.c	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/relphot_parallel_images.c	(revision 36558)
@@ -30,6 +30,9 @@
   }
 
+  // once we have read this table, we should remove it for repeat runs
+  unlink (IMAGE_TABLE); // XXX a bit risky, add some protection?
+
   // XXX need to deal with mosaic vs image...
-  // initMosaics (image, Nimage...)
+  makeMosaics (image, Nimage);
 
   initImages (image, NULL, Nimage);
@@ -131,7 +134,7 @@
   MARKTIME("-- finalize Mcal values: %f sec\n", dtime);
 
+  setMcalFinal (); // copy per-mosaic calibrations to the images
+
   share_image_mags (regionHosts, -1);
-
-  // save_image_subset ();
 
   exit (0);
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/share_mean_mags.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/share_mean_mags.c	(revision 36557)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/share_mean_mags.c	(revision 36558)
@@ -17,4 +17,10 @@
   int Nsecfilt = GetPhotcodeNsecfilt();
 
+  int myHost = regionHosts->index[REGION_HOST_ID];
+  double Rmin = regionHosts->hosts[myHost].Rmin;
+  double Rmax = regionHosts->hosts[myHost].Rmax;
+  double Dmin = regionHosts->hosts[myHost].Dmin;
+  double Dmax = regionHosts->hosts[myHost].Dmax;
+
   // XXX skip some catalogs based on UserPatch?
   for (i = 0; i < Ncatalog; i++) {
@@ -22,8 +28,8 @@
 
       // do I own this object? (in region range?)
-      if (catalog[i].averageT[j].R <  UserPatch.Rmin) continue;
-      if (catalog[i].averageT[j].R >= UserPatch.Rmax) continue;
-      if (catalog[i].averageT[j].D <  UserPatch.Dmin) continue;
-      if (catalog[i].averageT[j].D >= UserPatch.Dmax) continue;
+      if (catalog[i].averageT[j].R <  Rmin) continue;
+      if (catalog[i].averageT[j].R >= Rmax) continue;
+      if (catalog[i].averageT[j].D <  Dmin) continue;
+      if (catalog[i].averageT[j].D >= Dmax) continue;
 
       // does this object have missing detections (does someone else need it?)
@@ -43,5 +49,4 @@
 
   // write out the meanmag fits table AND write state in some file
-  int myHost = regionHosts->index[REGION_HOST_ID];
   char *hostname = regionHosts->hosts[myHost].hostname;
 
