Index: trunk/Ohana/src/relphot/doc/timeline.txt
===================================================================
--- trunk/Ohana/src/relphot/doc/timeline.txt	(revision 37807)
+++ trunk/Ohana/src/relphot/doc/timeline.txt	(revision 37807)
@@ -0,0 +1,36 @@
+
+timeline for processing on PV2 (31 remote hosts):
+
+load images, ready to launch hosts : 160s
+remote hosts begin:
+ * set up mosaic indexes: 388s - 1330s (from client launch time)
+ * loop 0 done: 1086s - 15870s (~ synchronous, thus clients took ~15ksec to load)
+ * loop 7 done: 4443s - 19251s (~ 3400sec total after load is done)
+ * finalized Mcal : 4444s - 19315s
+ * remote hosts done (5.4hr)
+
+remote client update Mcal average times:
+ * load catalog : 5963s (longest one is 11569s)
+ * make tiny : 113s
+ * find images: 576s
+ * set Mrel : 4793s
+ * save catalog: 2531s
+
+elapsed time for update Mcal: 51318s (14.3h)
+
+--> consistent with 3x longest single client times
+
+end of relphot: 70633s (19.6h)
+
+
+relastro timeline:
+on remote hosts:
+  * load catalog data: 247s - 4444s (loading more detections than relphot), 
+    * wall time of the load is NOT sum(load time), because clients are launched before slurp is started
+  * update chips: 23981s for last one 
+  ** end of load + analysis ~ 7hr
+  * analysis takes ~1-2hr
+
+update time ~ 9hr (compare with ~3-4h for relphot) 
+
+*** the I/O is NOT dominant. 
Index: trunk/Ohana/src/relphot/include/relphot.h
===================================================================
--- trunk/Ohana/src/relphot/include/relphot.h	(revision 37740)
+++ trunk/Ohana/src/relphot/include/relphot.h	(revision 37807)
@@ -452,5 +452,7 @@
 int setMrel_catalog_alt (Catalog *catalog, int Nc, int pass, FlatCorrectionTable *flatcorr, SetMrelInfo *results, int Nsecfilt);
 int setMrelAverageExposure (off_t meas, int cat, int pass, FlatCorrectionTable *flatcorr, SetMrelInfo *results, Average *average, AverageTiny *averageT, SecFilt *secfilt, Measure *measure, MeasureTiny *measureT, off_t *found);
-int setMrelAverageStack (off_t meas, int cat, FlatCorrectionTable *flatcorr, SetMrelInfo *results, Average *average, SecFilt *secfilt, Measure *measure);
+int setMrelAverageStack (off_t measureOffset, int cat, FlatCorrectionTable *flatcorr, SetMrelInfo *results, Average *average, SecFilt *secfilt, Measure *measure, off_t Nmeasure);
+int setMrelAverageForcedWarp (off_t measureOffset, int cat, int pass, SetMrelInfo *results, Average *average, SecFilt *secfilt, Measure *measure, off_t *found, off_t Nmeasure);
+
 int setGlobalObjStats (Average *average, Measure *measure);
 
Index: trunk/Ohana/src/relphot/src/BoundaryTreeOps.c
===================================================================
--- trunk/Ohana/src/relphot/src/BoundaryTreeOps.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/BoundaryTreeOps.c	(revision 37807)
@@ -51,5 +51,6 @@
   if (!tess) return FALSE;
 
-  status = TessellationPrimaryCellIDs(tess, Ntess, tessID, projID, skycellID, ra, dec);
+  double R = ohana_normalize_angle(ra);
+  status = TessellationPrimaryCellIDs(tess, Ntess, tessID, projID, skycellID, R, dec);
   return status;
 }
Index: trunk/Ohana/src/relphot/src/ImageOps.c
===================================================================
--- trunk/Ohana/src/relphot/src/ImageOps.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/ImageOps.c	(revision 37807)
@@ -35,4 +35,12 @@
 static off_t        *imageIdx; // list of index for image IDs 
 
+// QQ // as an alternative, we generate imageSeq, which directly maps imageID -> seq
+// QQ static off_t        *imageSeq; // list of index for image IDs 
+// QQ 
+// QQ // MAX_ID requires 512M to store the image index
+// QQ # define MAX_ID 0x8000000
+// QQ static off_t         minImageID = MAX_ID;
+// QQ static off_t         maxImageID = 0;
+
 // elsewhere, we have loaded a set of catalogs with measures (catalog[cat].measure[meas])
 // each image has N_onImage[ImageIndex] measurements
@@ -95,4 +103,8 @@
 
     TessellationIDsByImageName (&tessID[i], &projectID[i], &skycellID[i], image[i].name);
+
+    // QQ minImageID = MIN(minImageID, image[i].imageID);
+    // QQ maxImageID = MAX(maxImageID, image[i].imageID);
+    // QQ myAssert (image[i].imageID < MAX_ID, "image IDs too large for index memory");
   }
 
@@ -100,4 +112,15 @@
   // XXX does this break the imageID <-> projectID, etc match?
   llsortpair (imageIDs, imageIdx, Nimage);
+
+  // QQ ALLOCATE (imageSeq, off_t, maxImageID + 1);
+  // QQ for (i = 0; i < maxImageID + 1; i++)  {
+  // QQ   imageSeq[i] = -1; // not yet assigned
+  // QQ }
+  // QQ 
+  // QQ for (i = 0; i < Nimage; i++) {
+  // QQ   off_t N = image[i].imageID;
+  // QQ   myAssert (imageSeq[N] == -1, "previously assigned");
+  // QQ   imageSeq[N] = i;
+  // QQ }
 }
 
@@ -167,4 +190,11 @@
 
 off_t getImageByID (off_t ID) {
+
+  // QQ  if (imageSeq) {
+  // QQ    myAssert (ID >= minImageID, "oops");
+  // QQ    myAssert (ID <= maxImageID, "oops");
+  // QQ    off_t N = imageSeq[ID];
+  // QQ    return N;
+  // QQ  }
 
   // we have a pair of vectors (imageIDs, imageIdx) sorted by imageIDs
Index: trunk/Ohana/src/relphot/src/ImageTable.c
===================================================================
--- trunk/Ohana/src/relphot/src/ImageTable.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/ImageTable.c	(revision 37807)
@@ -32,4 +32,7 @@
   }
 
+  // XXX do not make the chip match -- we have not loaded the PHU entries (and do not need them here)
+  // BuildChipMatch (image, Nimage);
+
   *nimage = Nimage;
   return image;
Index: trunk/Ohana/src/relphot/src/MosaicOps.c
===================================================================
--- trunk/Ohana/src/relphot/src/MosaicOps.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/MosaicOps.c	(revision 37807)
@@ -520,12 +520,7 @@
       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);
+      if (!XY_to_RD (&R, &D, 0.5*NX, 0.5*NY, &image[m].coords)) continue;
       R = ohana_normalize_angle_to_midpoint (R, 180.0);
 
@@ -587,15 +582,9 @@
     }
 
-    strcpy (mosaic[i].coords.ctype, "DEC--TAN");
+    InitCoords (&mosaic[i].coords, "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   = 0.0;
@@ -631,20 +620,41 @@
       NY = image[m].NY;
       dS += hypot (image[m].coords.cdelt1*image[m].coords.pc1_1, image[m].coords.cdelt1*image[m].coords.pc2_1);
-      XY_to_RD (&R, &D, 0.0, 0.0, &image[m].coords);
+
+      OhanaProjection proj = GetProjection (image[m].coords.ctype);
+      if ((proj == PROJ_WRP) && !image[m].coords.mosaic) {
+	XY_to_LM (&R, &D, 0.0, 0.0, &image[m].coords);
+      } else {
+	XY_to_RD (&R, &D, 0.0, 0.0, &image[m].coords);
+      }
       Rmin = MIN (Rmin, R);
       Rmax = MAX (Rmax, R);
       Dmin = MIN (Dmin, D);
       Dmax = MAX (Dmax, D);
-      XY_to_RD (&R, &D, (double) NX, 0.0, &image[m].coords);
+
+      if ((proj == PROJ_WRP) && !image[m].coords.mosaic) {
+	XY_to_LM (&R, &D, (double) NX, 0.0, &image[m].coords);
+      } else {
+	XY_to_RD (&R, &D, (double) NX, 0.0, &image[m].coords);
+      }
       Rmin = MIN (Rmin, R);
       Rmax = MAX (Rmax, R);
       Dmin = MIN (Dmin, D);
       Dmax = MAX (Dmax, D);
-      XY_to_RD (&R, &D, (double) NX, (double) NY, &image[m].coords);
+
+      if ((proj == PROJ_WRP) && !image[m].coords.mosaic) {
+	XY_to_LM (&R, &D, (double) NX, (double) NY, &image[m].coords);
+      } else {
+	XY_to_RD (&R, &D, (double) NX, (double) NY, &image[m].coords);
+      }
       Rmin = MIN (Rmin, R);
       Rmax = MAX (Rmax, R);
       Dmin = MIN (Dmin, D);
       Dmax = MAX (Dmax, D);
-      XY_to_RD (&R, &D, 0.0, (double) NY, &image[m].coords);
+
+      if ((proj == PROJ_WRP) && !image[m].coords.mosaic) {
+	XY_to_LM (&R, &D, 0.0, (double) NY, &image[m].coords);
+      } else {
+	XY_to_RD (&R, &D, 0.0, (double) NY, &image[m].coords);
+      }
       Rmin = MIN (Rmin, R);
       Rmax = MAX (Rmax, R);
@@ -652,4 +662,6 @@
       Dmax = MAX (Dmax, D);
 
+      // XXX : this probably does not handle mosaics at RA = 0,360 well
+
       /* we are using mosaic.Mcal, not image.Mcal. reset image.Mcal */
 
@@ -668,15 +680,11 @@
     }
     dS /= MosaicN_Image[i];
-    strcpy (mosaic[i].coords.ctype, "DEC--TAN");
+
+    InitCoords (&mosaic[i].coords, "DEC--TAN");
     mosaic[i].coords.crval1 = Rmin;
     mosaic[i].coords.crval2 = Dmin;
-    mosaic[i].coords.crpix1 = 0.0;
-    mosaic[i].coords.crpix2 = 0.0;
     mosaic[i].coords.cdelt1 = dS;
     mosaic[i].coords.cdelt2 = dS;
-    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;
+
     RD_to_XY (&dX, &dY, Rmax, Dmax, &mosaic[i].coords);
 
Index: trunk/Ohana/src/relphot/src/assign_images.c
===================================================================
--- trunk/Ohana/src/relphot/src/assign_images.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/assign_images.c	(revision 37807)
@@ -80,10 +80,4 @@
     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;
-    }
-    
     // Exclude images with crazy astrometry
     // XXX NOTE : this is gpc1-specific
@@ -123,11 +117,13 @@
 
     if (MOSAIC_ZEROPT) {
-      // use the coords of the associated mosaic to select
+      // use the coords of the associated mosaic to select (only for chips; stacks use their own center)
       Mosaic *mosaic = getMosaicForImage (j); 
-      Rc = mosaic->coords.crval1;
-      Dc = mosaic->coords.crval2;
-      // NOTE : have defined mosaic Rc,Dc to choose the side of 0,360 on which most of the
-      // chips are located.  but, for host assignment, we rationalize to 0.0 - 360.0
-      Rc = ohana_normalize_angle_to_midpoint (Rc, 180.0);
+      if (mosaic) {
+	Rc = mosaic->coords.crval1;
+	Dc = mosaic->coords.crval2;
+	// NOTE : have defined mosaic Rc,Dc to choose the side of 0,360 on which most of the
+	// chips are located.  but, for host assignment, we rationalize to 0.0 - 360.0
+	Rc = ohana_normalize_angle_to_midpoint (Rc, 180.0);
+      }
     }
 
@@ -206,65 +202,4 @@
 }
 
-int calculate_host_image_bounds (RegionHostTable *regionHosts, double Rmid) {
-
-  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 =  720.0;
-    double Rmax = -360.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, Rmid);
-      
-	Rmin = MIN (Rmin, Rc);
-	Dmin = MIN (Dmin, Rc);
-	
-	Rmax = MAX (Rmax, Rc);
-	Dmax = MAX (Dmax, Rc);
-      }
-
-    }
-
-    // RminCat, RmaxCat may extended beyond 0.0 - 360.0
-    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;
-}
-
-
 // Rc is in range 0.0 - 360.0, hosts Rmin,Rmax in range 0.0 - 360.0
 int find_host_for_coords (RegionHostTable *regionHosts, double Rc, double Dc) {
Index: trunk/Ohana/src/relphot/src/load_images.c
===================================================================
--- trunk/Ohana/src/relphot/src/load_images.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/load_images.c	(revision 37807)
@@ -27,4 +27,16 @@
   }
   MARKTIME("read image table: %f sec\n", dtime);
+
+  BuildChipMatch (image, Nimage);
+  MARKTIME("build chip match for %d images: %f sec\n", (int) Nimage, dtime);
+
+  char mapfile[DVO_MAX_PATH];
+  snprintf (mapfile, DVO_MAX_PATH, "%s/AstroMap.fits", CATDIR);
+  AstromOffsetTable *table = AstromOffsetMapLoad (mapfile, VERBOSE);
+
+  // assign images.coords.offsetMap -> table->map[i]
+  if (table) {
+    AstromOffsetTableMatchChips (image, Nimage, table);
+  }
 
   // allocate and init an array to identify the images included in the subset
Index: trunk/Ohana/src/relphot/src/reload_catalogs.c
===================================================================
--- trunk/Ohana/src/relphot/src/reload_catalogs.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/reload_catalogs.c	(revision 37807)
@@ -128,4 +128,6 @@
 }
 
+int reload_catalog_parallel_group (HostTableGroup *group, SkyList *sky, char *imageFile);
+
 // XXX Image to Image Subset
 int reload_catalogs_parallel (SkyList *sky) {
@@ -165,15 +167,28 @@
     free (BOUNDARY_TREE);
     BOUNDARY_TREE = tmppath;
-    
-  }
+  }
+
+  int Ngroups;
+  HostTableGroup *groups = HostTableGroups (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
+    reload_catalog_parallel_group (&groups[i], sky, imageFile);
+  }
+  return TRUE;
+}
+
+int reload_catalog_parallel_group (HostTableGroup *group, SkyList *sky, char *imageFile) {
 
   int i, j;
-  for (i = 0; i < table->Nhosts; i++) {
-
-    if (sky->Nregions < table->Nhosts) {
+  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], table->hosts[i].hostID)) {
+	if (HostTableTestHost (sky->regions[j], group->hosts[i][0].hostID)) {
 	  wantThisHost = TRUE;
 	  break;
@@ -181,5 +196,5 @@
       }
       if (!wantThisHost) {
-	// fprintf (stderr, "skip host %s\n", table->hosts[i].hostname);
+	// fprintf (stderr, "skip host %s\n", group->hosts[i][0].hostname);
 	continue;
       }
@@ -187,11 +202,11 @@
 
     // 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 *tmppath = abspath (group->hosts[i][0].pathname, DVO_MAX_PATH);
+    free (group->hosts[i][0].pathname);
+    group->hosts[i][0].pathname = tmppath;
 
     char command[1024];
     snprintf (command, 1024, "relphot_client %s -update-catalogs %s -hostID %d -D CATDIR %s -hostdir %s -region %f %f %f %f -statmode %s -D CAMERA %s -D STAR_TOOFEW %d -minerror %f", 
-	      PhotcodeList, imageFile, table->hosts[i].hostID, CATDIR, table->hosts[i].pathname, UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax, STATMODE, CAMERA, STAR_TOOFEW, MIN_ERROR);
+	      PhotcodeList, imageFile, group->hosts[i][0].hostID, CATDIR, group->hosts[i][0].pathname, UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax, STATMODE, CAMERA, STAR_TOOFEW, MIN_ERROR);
 
     // options & configs which affect relphot_client -update-catalogs
@@ -238,10 +253,10 @@
       // 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);
+      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", table->hosts[i].hostname, errorInfo);
+	if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", group->hosts[i][0].hostname, errorInfo);
 	exit (1);
       }
-      table->hosts[i].pid = pid; // save for future reference
+      group->hosts[i][0].pid = pid; // save for future reference
     }
   }
@@ -252,5 +267,5 @@
   } 
   if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
-    int status = HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+    int status = HostTableGroupWaitJobsGetIO (group, __FILE__, __LINE__, VERBOSE);
     if (!status) {
       fprintf (stderr, "at least one remote client job failed to load data, exiting\n");
Index: trunk/Ohana/src/relphot/src/relphot.c
===================================================================
--- trunk/Ohana/src/relphot/src/relphot.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/relphot.c	(revision 37807)
@@ -9,4 +9,5 @@
   switch (mode) {
     case UPDATE_IMAGES:
+      // IF CALLED WITH NLOOP == 0, DOES NOT LOAD bcatalog, just loads image table and generates ImageSubset.dat
       relphot_images ();
       exit (0);
@@ -14,4 +15,5 @@
     case UPDATE_AVERAGES:
       // take the current set of detections and set the mean magnitudes
+      // DOES NOT LOAD THE IMAGE TABLE
       relphot_objects (0, NULL);
       exit (0);
@@ -43,2 +45,8 @@
   exit (1);
 }
+
+/***
+
+    I would like to merge the functionality of relphot_images (Nloop == 0), relphot_objects, and apply_offsets
+    
+***/
Index: trunk/Ohana/src/relphot/src/relphot_objects.c
===================================================================
--- trunk/Ohana/src/relphot/src/relphot_objects.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/relphot_objects.c	(revision 37807)
@@ -36,5 +36,4 @@
     if (!HostTableTestHost(skylist[0].regions[i], hostID)) continue;
 
-    // set up the basic catalog info
     // set up the basic catalog info
     char hostfile[1024];
Index: trunk/Ohana/src/relphot/src/relphot_parallel_regions.c
===================================================================
--- trunk/Ohana/src/relphot/src/relphot_parallel_regions.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/relphot_parallel_regions.c	(revision 37807)
@@ -43,4 +43,10 @@
   MARKTIME("-- load image data: %f sec\n", dtime);
 
+  // save Images.dat using the copied structure
+  if (UPDATE_CATFORMAT) {
+    // ensure the db format is updated
+    db.format = dvo_catalog_catformat (UPDATE_CATFORMAT);
+  }
+
   /* assign the images to the different region hosts */
   if (!assign_images (&db, regionHosts)) Shutdown ("error assigning images to region hosts");
@@ -49,4 +55,5 @@
   /* launch processing on the parallel region hosts */
   if (!launch_region_hosts (regionHosts)) Shutdown ("error launching region hosts");
+  MARKTIME ("finished relphot -parallel-regions: %f sec total\n", dtime);
 
   // retrieve updated image parameters from the remote hosts (also set Image.mcal)
Index: trunk/Ohana/src/relphot/src/select_images.c
===================================================================
--- trunk/Ohana/src/relphot/src/select_images.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/select_images.c	(revision 37807)
@@ -36,9 +36,6 @@
 
   // the comparison is made in the catalog local projection. below we set crval1,2
-  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  InitCoords (&tcoords, "DEC--TAN");
   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, "DEC--TAN");
 
   double RminSkyRegion = region[0].Rmin;
@@ -93,6 +90,4 @@
 
   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;
@@ -107,4 +102,7 @@
       
     if (!(i % 300000)) fprintf (stderr, ".");
+
+    // XXX I am just going for force this for the moment:
+    goto found_it;
 
     /* exclude images by photcode */
@@ -123,10 +121,4 @@
     }
     
-    // this adds 1.3 sec for 3M images
-    if (!FindMosaicForImage (timage, Ntimage, i)) {
-      if (VERBOSE2) fprintf (stderr, "cannot find mosaic for "OFF_T_FMT"\n", i);
-      continue;
-    }
-
     /* define image corners - note the DIS images (mosaic phu) are special */
     if (!strcmp(&timage[i].coords.ctype[4], "-DIS")) {
@@ -405,12 +397,6 @@
 
   // the comparison is made in the catalog local projection. below we set crval1,2
-  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  InitCoords (&tcoords, "DEC--TAN");
   tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
-  tcoords.pc1_1  = tcoords.pc2_2 = 1.0;
-  tcoords.pc1_2  = tcoords.pc2_1 = 0.0;
-
-  tcoords.Npolyterms = 0;
-  memset (tcoords.polyterms, 0, 14*sizeof(float));
-  strcpy (tcoords.ctype, "DEC--TAN");
 
   /* compare with each region file */
Index: trunk/Ohana/src/relphot/src/setMrelCatalog.c
===================================================================
--- trunk/Ohana/src/relphot/src/setMrelCatalog.c	(revision 37740)
+++ trunk/Ohana/src/relphot/src/setMrelCatalog.c	(revision 37807)
@@ -36,6 +36,4 @@
 }
 
-int setMrelAverageForcedWarp (off_t measureOffset, int cat, int pass, SetMrelInfo *results, Average *average, SecFilt *secfilt, Measure *measure, off_t *found);
-
 int setMrel_catalog_alt (Catalog *catalog, int Nc, int pass, FlatCorrectionTable *flatcorr, SetMrelInfo *results, int Nsecfilt) {
 
@@ -60,9 +58,10 @@
     Average *average = catalog[Nc].average ? &catalog[Nc].average[j] : NULL;
     Measure *measure = catalog[Nc].measure ? &catalog[Nc].measure[m] : NULL;
-    setMrelAverageExposure (m, Nc, pass, flatcorr, results, average, &catalog[Nc].averageT[j], &catalog[Nc].secfilt[j*Nsecfilt], measure, &catalog[Nc].measureT[m], &catalog[Nc].found_t[Nsecfilt*j]);
+    SecFilt *secfilt = catalog[Nc].secfilt ? &catalog[Nc].secfilt[j*Nsecfilt] : NULL;
+    setMrelAverageExposure (m, Nc, pass, flatcorr, results, average, &catalog[Nc].averageT[j], secfilt, measure, &catalog[Nc].measureT[m], &catalog[Nc].found_t[Nsecfilt*j]);
 
     // only apply Stack operation on setMrelFinal in first pass 
     if (isSetMrelFinal && (pass == 0)) {
-      setMrelAverageStack (m, Nc, flatcorr, results, &catalog[Nc].average[j], &catalog[Nc].secfilt[j*Nsecfilt], &catalog[Nc].measure[m]);
+      setMrelAverageStack (m, Nc, flatcorr, results, average, secfilt, &catalog[Nc].measure[m], catalog[Nc].Nmeasure);
       setGlobalObjStats (&catalog[Nc].average[j], &catalog[Nc].measure[m]);
     }
@@ -70,6 +69,6 @@
     // only measure force-warp mean values if issetMrelFinal (make it optional?)
     if (isSetMrelFinal) {
-      setMrelAverageForcedWarp (m, Nc, pass, results, &catalog[Nc].average[j], &catalog[Nc].secfilt[j*Nsecfilt], &catalog[Nc].measure[m], &catalog[Nc].foundWarp_t[Nsecfilt*j]);
-      setGlobalObjStats (&catalog[Nc].average[j], &catalog[Nc].measure[m]);
+      setMrelAverageForcedWarp (m, Nc, pass, results, average, secfilt, measure, &catalog[Nc].foundWarp_t[Nsecfilt*j], catalog[Nc].Nmeasure);
+      setGlobalObjStats (average, measure);
     }
   }
@@ -456,5 +455,5 @@
 // 2) select the BEST detections per filter (regardless of PRIMARY)
 // 3) apply the zero point and AB->Jy transformations
-int setMrelAverageStack (off_t measureOffset, int cat, FlatCorrectionTable *flatcorr, SetMrelInfo *results, Average *average, SecFilt *secfilt, Measure *measure) {
+int setMrelAverageStack (off_t measureOffset, int cat, FlatCorrectionTable *flatcorr, SetMrelInfo *results, Average *average, SecFilt *secfilt, Measure *measure, off_t Nmeasure) {
 
   off_t k;
@@ -496,4 +495,7 @@
     int Nstack = 0; // number for this photcode
     int NstackDet = 0; // number for this photcode
+
+    secfilt[Nsec].stackBestOff = -1;
+    secfilt[Nsec].stackPrmryOff = -1;
 
     off_t meas = measureOffset;
@@ -526,4 +528,5 @@
 	measure[k].dbFlags |= ID_MEAS_STACK_PRIMARY;
 	secfilt[Nsec].stackPrmryOff = meas;
+	myAssert (secfilt[Nsec].stackPrmryOff <= Nmeasure, "stackPrmryOff out of range");
       }
 
@@ -637,4 +640,5 @@
 
     secfilt[Nsec].stackBestOff = k + measureOffset;
+    myAssert (secfilt[Nsec].stackBestOff <= Nmeasure, "stackBestOff out of range");
 
     secfilt[Nsec].Nstack    = Nstack;
@@ -669,5 +673,5 @@
 // somewhat simplified relative to chip-photometry:
 // * no grid, no mosaic, no 2MASS, no SYNTH, no Ubercal, no flatcorr
-int setMrelAverageForcedWarp (off_t measureOffset, int cat, int pass, SetMrelInfo *results, Average *average, SecFilt *secfilt, Measure *measure, off_t *found) {
+int setMrelAverageForcedWarp (off_t measureOffset, int cat, int pass, SetMrelInfo *results, Average *average, SecFilt *secfilt, Measure *measure, off_t *found, off_t Nmeasure) {
 
   off_t k;
@@ -713,4 +717,6 @@
     // if we cannot make that association, skip this set of warps
     int stkTessID, stkProjID, stkSkycellID;
+
+    myAssert (secfilt[Nsec].stackBestOff <= Nmeasure, "stackBestOff out of range");
     if (!FindImageSkycellID (secfilt[Nsec].stackBestOff, cat, &stkTessID, &stkProjID, &stkSkycellID)) continue;
 
