Index: trunk/Ohana/src/dvomerge/include/dvomerge.h
===================================================================
--- trunk/Ohana/src/dvomerge/include/dvomerge.h	(revision 39298)
+++ trunk/Ohana/src/dvomerge/include/dvomerge.h	(revision 39299)
@@ -46,4 +46,6 @@
 char  *UPDATE_CATCOMPRESS;
 
+int    MATCH_BY_EXTERN_ID;
+
 int    MATCHED_TABLES;
 int    REPAIR_BY_OBJID;
@@ -202,9 +204,11 @@
 off_t      getTgtIndex            PROTO((e_time start, e_time stop, short photcode, off_t *TgtIndex, e_time *TgtTimes, short *TgtCodes, off_t NimagesTgt));
 void       SortTgtByTimes         PROTO((e_time *S, off_t *I, short *C, off_t N));
-int 	   dvo_image_match_dbs    PROTO((IDmapType *IDmap, FITS_DB *tgt, FITS_DB *src));
 int 	   dvomergeImagesGetMap   PROTO((IDmapType *IDmap, char *input, char *output));
 int        dvomergeFromList       PROTO((int argc, char **argv));
 int 	   dvomergeUpdate_threaded PROTO((int argc, char **argv));
 int        dvomergeUpdate_catalogs PROTO((char *input, char *output, SkyTable *outsky, SkyList *inlist, int NsecfiltInput, int NsecfiltOutput, IDmapType *IDmap, int *secfiltMap));
+
+int 	   dvo_image_match_dbs_by_time_and_photcode PROTO((IDmapType *IDmap, FITS_DB *tgt, FITS_DB *src));
+int 	   dvo_image_match_dbs_by_extern_id         PROTO((IDmapType *IDmap, FITS_DB *tgt, FITS_DB *src));
 
 int        replace_match           PROTO((Average *average_out, Measure *measure_out, off_t *next_meas, Average *average_in, Measure *measure_in));
Index: trunk/Ohana/src/dvomerge/src/args.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/args.c	(revision 39298)
+++ trunk/Ohana/src/dvomerge/src/args.c	(revision 39299)
@@ -44,4 +44,11 @@
   if ((N = get_argument (*argc, argv, "-matched-tables"))) {
     MATCHED_TABLES = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  /* extra error messages */
+  MATCH_BY_EXTERN_ID = FALSE;
+  if ((N = get_argument (*argc, argv, "-match-by-extern-id"))) {
+    MATCH_BY_EXTERN_ID = TRUE;
     remove_argument (N, argc, argv);
   }
@@ -245,4 +252,11 @@
   }
 
+  /* extra error messages */
+  MATCH_BY_EXTERN_ID = FALSE;
+  if ((N = get_argument (*argc, argv, "-match-by-extern-id"))) {
+    MATCH_BY_EXTERN_ID = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
   UPDATE_CATFORMAT = NULL;
   if ((N = get_argument (*argc, argv, "-update-catformat"))) {
Index: trunk/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 39298)
+++ trunk/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 39299)
@@ -3,6 +3,10 @@
 // utility functions
 void sort_IDmap (IDmapType *IDmap);
+
 void SortTgtByTimes (e_time *S, off_t *I, short *C, off_t N);
-off_t getTgtIndex (e_time start, e_time stop, short photcode, off_t *TgtIndex, e_time *TgtTimes, short *TgtCodes, off_t NimagesTgt);
+void SortTgtByExtID (unsigned int *S, off_t *I, off_t N);
+
+off_t getTgtIndexByExtID (unsigned int extID, off_t *TgtIndex, unsigned int *TgtExtID, off_t NimagesTgt);
+off_t getTgtIndexByTimeAndPhotcode (e_time start, e_time stop, short photcode, off_t *TgtIndex, e_time *TgtTimes, short *TgtCodes, off_t NimagesTgt);
 
 void dvo_image_map_init (IDmapType *IDmap) {
@@ -22,5 +26,61 @@
 
 // we have two tables; 'tgt' contains some exposures from 'src' : find them and match a map
-int dvo_image_match_dbs (IDmapType *IDmap, FITS_DB *tgt, FITS_DB *src) {
+int dvo_image_match_dbs_by_extern_id (IDmapType *IDmap, FITS_DB *tgt, FITS_DB *src) {
+
+  Image *imagesSrc, *imagesTgt;
+  off_t NimagesSrc, NimagesTgt;
+  off_t iSrc, iTgt;
+  off_t  *TgtIndex;
+  unsigned int *TgtExtID;
+ 
+  imagesSrc = gfits_table_get_Image (&src[0].ftable, &NimagesSrc, &src[0].scaledValue, &src[0].nativeOrder);
+  if (!imagesSrc) {
+    fprintf (stderr, "ERROR: failed to read images from src\n");
+    exit (2);
+  }
+
+  imagesTgt = gfits_table_get_Image (&tgt[0].ftable, &NimagesTgt, &tgt[0].scaledValue, &tgt[0].nativeOrder);
+  if (!imagesTgt) {
+    fprintf (stderr, "ERROR: failed to read images from tgt\n");
+    exit (2);
+  }
+
+  ALLOCATE (IDmap->old, unsigned int, NimagesSrc);
+  ALLOCATE (IDmap->new, unsigned int, NimagesSrc);
+  IDmap->Nmap = NimagesSrc;
+
+  // match by time and photcode
+  ALLOCATE (TgtIndex, off_t,        NimagesTgt);
+  ALLOCATE (TgtExtID, unsigned int, NimagesTgt);
+
+  // save the Index, Times, Codes for all TGT images
+  for (iTgt = 0; iTgt < NimagesTgt; iTgt++) {
+    TgtIndex[iTgt] = iTgt;
+    TgtExtID[iTgt] = imagesTgt[iTgt].externID;
+  }
+
+  // sort the index, start, and stop by the start times:
+  SortTgtByExtID (TgtExtID, TgtIndex, NimagesTgt);
+
+  for (iSrc = 0; iSrc < NimagesSrc; iSrc++) {
+    iTgt = getTgtIndexByExtID (imagesSrc[iSrc].externID, TgtIndex, TgtExtID, NimagesTgt);
+    if (iTgt < 0) Shutdown ("failure to find matching image: %s\n", imagesSrc[iSrc].name);
+    IDmap[0].old[iSrc] = imagesSrc[iSrc].imageID;
+    IDmap[0].new[iSrc] = imagesTgt[iTgt].imageID;
+  }
+
+  create_IDmap_lookup (IDmap);
+
+  FREE(TgtIndex);
+  FREE(TgtExtID);
+
+  // sort IDmap->old,new on the basis of IDmap->old:
+  sort_IDmap (IDmap);
+
+  return TRUE;
+}
+
+// we have two tables; 'tgt' contains some exposures from 'src' : find them and match a map
+int dvo_image_match_dbs_by_time_and_photcode (IDmapType *IDmap, FITS_DB *tgt, FITS_DB *src) {
 
   Image *imagesSrc, *imagesTgt;
@@ -63,5 +123,5 @@
 
   for (iSrc = 0; iSrc < NimagesSrc; iSrc++) {
-    iTgt = getTgtIndex (imagesSrc[iSrc].tzero, imagesSrc[iSrc].tzero + (int) imagesSrc[iSrc].exptime, imagesSrc[iSrc].photcode, TgtIndex, TgtTimes, TgtCodes, NimagesTgt);
+    iTgt = getTgtIndexByTimeAndPhotcode (imagesSrc[iSrc].tzero, imagesSrc[iSrc].tzero + (int) imagesSrc[iSrc].exptime, imagesSrc[iSrc].photcode, TgtIndex, TgtTimes, TgtCodes, NimagesTgt);
     if (iTgt < 0) Shutdown ("failure to match images: %s\n", imagesSrc[iSrc].name);
     IDmap[0].old[iSrc] = imagesSrc[iSrc].imageID;
@@ -256,5 +316,33 @@
 }
 
-off_t getTgtIndex (e_time start, e_time stop, short photcode, off_t *TgtIndex, e_time *TgtTimes, short *TgtCodes, off_t NimagesTgt) {
+off_t getTgtIndexByExtID (unsigned int extID, off_t *TgtIndex, unsigned int *TgtExtID, off_t NimagesTgt) {
+
+  // use bisection to find the starting entry by time
+
+  off_t Nlo, Nhi, N;
+
+  // find the last TGT before start
+  Nlo = 0; Nhi = NimagesTgt;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (TgtExtID[N] < extID) {
+      Nlo = MAX(N, 0);
+    } else {
+      Nhi = MIN(N + 1, NimagesTgt);
+    }
+  }
+
+  // check for the matched mosaic starting from Nlo 
+  // we may have to go much beyond Nlo since stop is not sorted
+  // can we use a sorted version of stop to check when we are beyond the valid range??
+  for (N = Nlo; N < NimagesTgt; N++) { 
+    if (TgtExtID[N] < extID) continue;
+    if (TgtExtID[N] > extID) return (-1);
+    return (TgtIndex[N]);
+  }
+  return (-1);
+}
+
+off_t getTgtIndexByTimeAndPhotcode (e_time start, e_time stop, short photcode, off_t *TgtIndex, e_time *TgtTimes, short *TgtCodes, off_t NimagesTgt) {
 
   // use bisection to find the starting entry by time
@@ -302,4 +390,19 @@
 }
 
+// sort two times vectors and an index by first time vector
+void SortTgtByExtID (unsigned int *S, off_t *I, off_t N) {
+
+# define SWAPFUNC(A,B){ unsigned int tmp_s; off_t tmp_i; 	\
+  tmp_s = S[A]; S[A] = S[B]; S[B] = tmp_s; \
+  tmp_i = I[A]; I[A] = I[B]; I[B] = tmp_i; \
+}
+# define COMPARE(A,B)(S[A] < S[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+}
+
 // we need a lookup table of length (oldIDmax + 1) to record if a given oldIDmax has not been found in Tgt
 int create_IDmap_lookup (IDmapType *IDmap) {
Index: trunk/Ohana/src/dvomerge/src/dvomergeImageIDs.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvomergeImageIDs.c	(revision 39298)
+++ trunk/Ohana/src/dvomerge/src/dvomergeImageIDs.c	(revision 39299)
@@ -62,5 +62,9 @@
     // if so, then just match the image IDs 
     if (VERBOSE) fprintf (stderr, "already merged image table\n");
-    dvo_image_match_dbs(IDmap, &outDB, &inDB);
+    if (MATCH_BY_EXTERN_ID) {
+      dvo_image_match_dbs_by_extern_id(IDmap, &outDB, &inDB);
+    } else {
+      dvo_image_match_dbs_by_time_and_photcode(IDmap, &outDB, &inDB);
+    }
     dvo_image_unlock (&outDB); // unlock output
 
@@ -145,5 +149,10 @@
 
   // convert database table to internal structure & add to output image db
-  dvo_image_match_dbs(IDmap, &outDB, &inDB);
+  if (MATCH_BY_EXTERN_ID) {
+    dvo_image_match_dbs_by_extern_id(IDmap, &outDB, &inDB);
+  } else {
+    dvo_image_match_dbs_by_time_and_photcode(IDmap, &outDB, &inDB);
+  }
+  // dvo_image_match_dbs(IDmap, &outDB, &inDB);
 
   gfits_db_free (&inDB);
Index: trunk/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c	(revision 39298)
+++ trunk/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c	(revision 39299)
@@ -300,4 +300,5 @@
     if (FORCE_MERGE)         { strextend (&command, "-force-merge"); }
     if (MATCHED_TABLES)      { strextend (&command, "-matched-tables"); }
+    if (MATCH_BY_EXTERN_ID)  { strextend (&command, "-match-by-extern-id"); }
     if (UPDATE_CATFORMAT)    { strextend (&command, "-update-catformat %s", UPDATE_CATFORMAT); }
     if (UPDATE_CATCOMPRESS)  { strextend (&command, "-update-catcompress %s", UPDATE_CATCOMPRESS); }
