Index: /trunk/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c
===================================================================
--- /trunk/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 28353)
+++ /trunk/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 28354)
@@ -1,3 +1,5 @@
 # include "dvomerge.h"
+
+void sort_IDmap (IDmapType *IDmap);
 
 // merge db2 into db1
@@ -29,4 +31,7 @@
   }
 
+  // sort IDmap->old,new on the basis of IDmap->old:
+  sort_IDmap (IDmap);
+
   if (!out[0].swapped) {
     gfits_convert_Image ((Image *) out[0].ftable.buffer, sizeof(Image), Nout);
@@ -43,12 +48,32 @@
 }
 
-// optimize with sort and bisection
+// XXX isn't the map just ID_new = ID_old + offset ??
 off_t dvo_map_image_ID (IDmapType *IDmap, off_t oldID) {
 
-  off_t i;
+  // off_t i;
+  // 
+  // for (i = 0; i < IDmap->Nmap; i++) {
+  //   if (IDmap->old[i] != oldID) continue;
+  //   return (IDmap->new[i]);
+  // }
 
-  for (i = 0; i < IDmap->Nmap; i++) {
-    if (IDmap->old[i] != oldID) continue;
-    return (IDmap->new[i]);
+  off_t Nlo, Nhi, N;
+
+  // find the a close entry below desired ID
+  Nlo = 0; Nhi = IDmap->Nmap;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (IDmap->old[N] < oldID) {
+      Nlo = MAX(N, 0);
+    } else {
+      Nhi = MIN(N + 1, IDmap->Nmap);
+    }
+  }
+
+  // search for the desired ID starting from Nlo, give up at Nhi
+  for (N = Nlo; N < Nhi; N++) { 
+    if (IDmap->old[N] < oldID) continue;
+    if (IDmap->old[N] > oldID) return 0;
+    return (IDmap->new[N]);
   }
   return 0;
@@ -72,2 +97,19 @@
   return TRUE;
 }
+
+// sort two times vectors and an index by first time vector
+void sort_IDmap (IDmapType *IDmap) {
+
+# define SWAPFUNC(A,B){ off_t tmp_old, tmp_new;	   \
+  tmp_old = IDmap->old[A]; IDmap->old[A] = IDmap->old[B]; IDmap->old[B] = tmp_old; \
+  tmp_new = IDmap->new[A]; IDmap->new[A] = IDmap->new[B]; IDmap->new[B] = tmp_new; \
+}
+# define COMPARE(A,B)(IDmap->old[A] < IDmap->old[B])
+
+  OHANA_SORT (IDmap->Nmap, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
Index: /trunk/Ohana/src/dvomerge/src/dvomergeUpdate.c
===================================================================
--- /trunk/Ohana/src/dvomerge/src/dvomergeUpdate.c	(revision 28353)
+++ /trunk/Ohana/src/dvomerge/src/dvomergeUpdate.c	(revision 28354)
@@ -69,5 +69,8 @@
       
     // load in all of the tables from input for this region
-    inlist = SkyListByBounds (insky, depth, outsky[0].regions[i].Rmin, outsky[0].regions[i].Rmax, outsky[0].regions[i].Dmin, outsky[0].regions[i].Dmax);
+    // SkyListByBounds will return neighbor catalogs if the boundaries exactly match (due to rounding).  Since the regions are not infinitely small, 
+    // compare to a slightly reduced footprint
+    float dPos = 2.0/3600.0;
+    inlist = SkyListByBounds (insky, depth, outsky[0].regions[i].Rmin + dPos, outsky[0].regions[i].Rmax - dPos, outsky[0].regions[i].Dmin + dPos, outsky[0].regions[i].Dmax - dPos);
     for (j = 0; j < inlist[0].Nregions; j++) {
       if (VERBOSE) fprintf (stderr, "input : %s\n", inlist[0].regions[j][0].name);
@@ -86,4 +89,6 @@
       dvo_catalog_unlock (&incatalog);
       dvo_catalog_free (&incatalog);
+
+      fprintf (stderr, "merged %s into %s\n", outsky[0].regions[i].name, inlist[0].regions[j][0].name);
     }
     SkyListFree (inlist);
Index: /trunk/Ohana/src/dvomerge/src/merge_catalogs_old.c
===================================================================
--- /trunk/Ohana/src/dvomerge/src/merge_catalogs_old.c	(revision 28353)
+++ /trunk/Ohana/src/dvomerge/src/merge_catalogs_old.c	(revision 28354)
@@ -2,7 +2,15 @@
 # define PSPS_ID TRUE
 
-# define IN_REGION(R,D) ( \
-((D) >= region[0].Dmin) && ((D) < region[0].Dmax) && \
-((R) >= region[0].Rmin)  && ((R) < region[0].Rmax))
+# define MARKTIME(MSG,...) {			\
+    float dtime;				\
+    gettimeofday (&stop, (void *) NULL);	\
+    dtime = DTIME (stop, start);		\
+    fprintf (stderr, MSG, __VA_ARGS__);		\
+    gettimeofday (&start, (void *) NULL);	\
+  }
+
+# define IN_REGION(R,D) (					\
+    ((D) >= region[0].Dmin) && ((D) < region[0].Dmax) &&	\
+    ((R) >= region[0].Rmin)  && ((R) < region[0].Rmax))
 
 // merge the input data into the output catalog
@@ -10,5 +18,5 @@
 int merge_catalogs_old (SkyRegion *region, Catalog *output, Catalog *input, double RADIUS) {
 
-  off_t i, j, Nin, offset, J, Jmin, status, Nstars;
+  off_t i, j, k, Nin, offset, J, Jmin, status, Nstars;
   double RADIUS2, Rmin, Rin, Din;
   double *X1, *Y1, *X2, *Y2;
@@ -19,4 +27,7 @@
   unsigned int objID, catID;
   Coords tcoords;
+
+  // struct timeval start, stop;
+  // gettimeofday (&start, (void *) NULL);
 
   Nsecfilt = output[0].Nsecfilt;
@@ -108,4 +119,6 @@
   /* choose a radius for matches */
   RADIUS2 = RADIUS*RADIUS;
+
+  // MARKTIME("set up structures: %f sec\n", dtime);
 
   /** find matched stars **/
@@ -215,14 +228,8 @@
     // update the average properties to reflect the incoming entries:
     // if the original value is NAN but the input value is not, accept the input:
-    for (j = 0; j < Nsecfilt; j++) {
-      if ( isfinite(output[0].secfilt[n*Nsecfilt+j].M)) continue;
-      if (!isfinite( input[0].secfilt[N*Nsecfilt+j].M)) continue;
-      output[0].secfilt[n*Nsecfilt+j].M     = input[0].secfilt[N*Nsecfilt+j].M;
-      output[0].secfilt[n*Nsecfilt+j].dM    = input[0].secfilt[N*Nsecfilt+j].dM;
-      output[0].secfilt[n*Nsecfilt+j].Xm    = input[0].secfilt[N*Nsecfilt+j].Xm;
-      output[0].secfilt[n*Nsecfilt+j].M_20  = input[0].secfilt[N*Nsecfilt+j].M_20;
-      output[0].secfilt[n*Nsecfilt+j].M_80  = input[0].secfilt[N*Nsecfilt+j].M_80;
-      output[0].secfilt[n*Nsecfilt+j].Ncode = input[0].secfilt[N*Nsecfilt+j].Ncode;
-      output[0].secfilt[n*Nsecfilt+j].Nused = input[0].secfilt[N*Nsecfilt+j].Nused;
+    for (k = 0; k < Nsecfilt; k++) {
+      if ( isfinite(output[0].secfilt[n*Nsecfilt+k].M)) continue;
+      if (!isfinite( input[0].secfilt[N*Nsecfilt+k].M)) continue;
+      output[0].secfilt[n*Nsecfilt+k] = input[0].secfilt[N*Nsecfilt+k];
     }
 
@@ -232,11 +239,5 @@
     i++;
   }
-
-# if (0)
-  fprintf (stderr, "--- 1 ---\n");
-  for (i = 0; i < Nmeas; i++) {
-    fprintf (stderr, "Nave : %d, Nmeas : "OFF_T_FMT", dR: %f, dD: %f, catID: %d\n", output[0].measure[i].averef,  i, output[0].measure[i].dR, output[0].measure[i].dD, output[0].measure[i].catID);
-  }
-# endif
+  // MARKTIME("find matched stars: %f sec for "OFF_T_FMT","OFF_T_FMT" stars\n", dtime, Nstars, Nave);
 
   /** incorporate unmatched image stars, if this star is in field of this catalog **/
@@ -260,5 +261,5 @@
     if (!IN_REGION (input[0].average[N].R, input[0].average[N].D)) continue;
 
-    // XXX should we accept the input measurements for the fields?
+    // XXX should we accept the input measurements for these fields?
 
     output[0].average[Nave].R         	   = input[0].average[N].R;
@@ -344,19 +345,14 @@
     int Ngroup = input[0].average[N].Nmeasure;
     for (j = 0; j < Ngroup - 1; j++) {
-	next_meas[Nmeas - Ngroup + j] = Nmeas - Ngroup + j + 1;
+      next_meas[Nmeas - Ngroup + j] = Nmeas - Ngroup + j + 1;
     }
     Nave ++;
   }
       
+  // MARKTIME("save unmatched stars: %f sec\n", dtime);
+
   REALLOCATE (output[0].average, Average, Nave);
   REALLOCATE (output[0].measure, Measure, Nmeas);
  
-# if (0)
-  fprintf (stderr, "--- 2 ---\n");
-  for (i = 0; i < Nmeas; i++) {
-    fprintf (stderr, "Nave : %d, Nmeas : "OFF_T_FMT", dR: %f, dD: %f, catID: %d\n", output[0].measure[i].averef,  i, output[0].measure[i].dR, output[0].measure[i].dD, output[0].measure[i].catID);
-  }
-# endif
-
 # define NOSORT 0
   if (NOSORT) {
@@ -366,11 +362,4 @@
     output[0].measure = sort_measure (output[0].average, Nave, output[0].measure, Nmeas, next_meas);
   }
-
-# if (0)
-  fprintf (stderr, "--- 3 ---\n");
-  for (i = 0; i < Nmeas; i++) {
-    fprintf (stderr, "Nave : %d, Nmeas : "OFF_T_FMT", dR: %f, dD: %f, catID: %d\n", output[0].measure[i].averef,  i, output[0].measure[i].dR, output[0].measure[i].dD, output[0].measure[i].catID);
-  }
-# endif
 
   /* note stars which have been found in this catalog */
@@ -400,4 +389,6 @@
   free (Y1);
   free (N1);
+
+  // MARKTIME("cleanup: %f sec\n", dtime);
   return (Nmatch);
 }
