Index: branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/Makefile
===================================================================
--- branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/Makefile	(revision 29787)
+++ branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/Makefile	(revision 29788)
@@ -26,4 +26,5 @@
 $(SRC)/dvomergeUpdate.$(ARCH).o \
 $(SRC)/dvomergeCreate.$(ARCH).o \
+$(SRC)/dvomergeContinue.$(ARCH).o \
 $(SRC)/dvo_image_merge_dbs.$(ARCH).o \
 $(SRC)/SetSignals.$(ARCH).o \
Index: branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/include/dvomerge.h
===================================================================
--- branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/include/dvomerge.h	(revision 29787)
+++ branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/include/dvomerge.h	(revision 29788)
@@ -105,2 +105,8 @@
 int 	   RepairTableCPT         PROTO((char *cptFilenameSrc, char *cptFilenameTgt, char *cpsFilenameSrc, char *cpsFilenameTgt, Measure *measure, off_t Nmeasure, Image *image, off_t Nimage, char catformat));
 void       dvorepair_help         PROTO((int argc, char **argv));
+
+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 	   dvomergeContinue       PROTO((int argc, char **argv));
Index: branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/args.c
===================================================================
--- branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/args.c	(revision 29787)
+++ branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/args.c	(revision 29788)
@@ -36,5 +36,5 @@
   }
 
-  if ((*argc != 6) && (*argc != 4)) dvomerge_usage();
+  if ((*argc < 4) || (*argc > 6)) dvomerge_usage();
   return TRUE;
 }
Index: branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c
===================================================================
--- branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 29787)
+++ branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 29788)
@@ -2,4 +2,108 @@
 
 void sort_IDmap (IDmapType *IDmap);
+
+off_t getTgtIndex (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
+
+  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 (TgtTimes[N] < start) {
+      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 (TgtTimes[N] < start) continue;
+    if (TgtTimes[N] > stop) return (-1);
+    if (TgtCodes[N] != photcode) continue;
+    return (TgtIndex[N]);
+  }
+  return (-1);
+}
+
+// sort two times vectors and an index by first time vector
+void SortTgtByTimes (e_time *S, off_t *I, short *C, off_t N) {
+
+# define SWAPFUNC(A,B){ e_time tmp_t; off_t tmp_i; short tmp_c; 	\
+  tmp_t = S[A]; S[A] = S[B]; S[B] = tmp_t; \
+  tmp_i = I[A]; I[A] = I[B]; I[B] = tmp_i; \
+  tmp_c = C[A]; C[A] = C[B]; C[B] = tmp_c; \
+}
+# define COMPARE(A,B)(S[A] < S[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+// 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) {
+
+  Image *imagesSrc, *imagesTgt;
+  off_t NimagesSrc, NimagesTgt;
+  off_t iSrc, iTgt;
+  off_t  *TgtIndex;
+  e_time *TgtTimes;
+  short  *TgtCodes;
+ 
+  imagesSrc = gfits_table_get_Image (&src[0].ftable, &NimagesSrc, &src[0].swapped);
+  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].swapped);
+  if (!imagesTgt) {
+    fprintf (stderr, "ERROR: failed to read images from tgt\n");
+    exit (2);
+  }
+
+  ALLOCATE (IDmap->old, off_t, NimagesSrc);
+  ALLOCATE (IDmap->new, off_t, NimagesSrc);
+  IDmap->Nmap = NimagesSrc;
+
+  // match by time and photcode
+  ALLOCATE (TgtIndex, off_t,  NimagesTgt);
+  ALLOCATE (TgtTimes, e_time, NimagesTgt);
+  ALLOCATE (TgtCodes, short,  NimagesTgt);
+
+  // save the Index, Times, Codes for all TGT images
+  for (iTgt = 0; iTgt < NimagesTgt; iTgt++) {
+    TgtIndex[iTgt] = iTgt;
+    TgtTimes[iTgt] = imagesTgt[iTgt].tzero;
+    TgtCodes[iTgt] = imagesTgt[iTgt].photcode;
+  }
+
+  // sort the index, start, and stop by the start times:
+  SortTgtByTimes (TgtTimes, TgtIndex, TgtCodes, NimagesTgt);
+
+  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);
+    if (iTgt < 0) Shutdown ("failure to match images: %s\n", imagesSrc[iSrc].name);
+    IDmap[0].old[iSrc] = imagesSrc[iSrc].imageID;
+    IDmap[0].new[iSrc] = imagesTgt[iTgt].imageID;
+  }
+
+  FREE(TgtIndex);
+  FREE(TgtTimes);
+  FREE(TgtCodes);
+
+  // sort IDmap->old,new on the basis of IDmap->old:
+  sort_IDmap (IDmap);
+
+  return TRUE;
+}
 
 // merge db2 into db1
Index: branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/dvomerge.c
===================================================================
--- branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/dvomerge.c	(revision 29787)
+++ branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/dvomerge.c	(revision 29788)
@@ -12,4 +12,5 @@
   if (argc == 6) dvomergeCreate (argc, argv);
   if (argc == 4) dvomergeUpdate (argc, argv);
+  if (argc == 5) dvomergeContinue (argc, argv);
   dvomerge_usage();
   exit (2); // cannot reach here.
@@ -18,6 +19,7 @@
 /* we have two possible modes of operation:
 
-   Create : dvomerge (in1) and (in2) to (out) -- create a new db from two input dbs
-   Update : dvomerge (in) into (out)          -- merge a new db into an existing db
+   Create   : dvomerge (in1) and (in2) to (out) -- create a new db from two input dbs
+   Update   : dvomerge (in) into (out)          -- merge a new db into an existing db
+   Continue : dvomerge (in) into (out) continue -- merge a new db into an existing db
 
 */
Index: branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/dvomergeContinue.c
===================================================================
--- branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/dvomergeContinue.c	(revision 29788)
+++ branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/dvomergeContinue.c	(revision 29788)
@@ -0,0 +1,195 @@
+# include "dvomerge.h"
+
+int dvomergeContinue (int argc, char **argv) {
+
+  int depth;
+  off_t i, j, Ns, Ne;
+  SkyTable *outsky, *insky;
+  SkyList *outlist, *inlist;
+  Catalog incatalog, outcatalog;
+  char filename[256], *input, *output;
+  IDmapType IDmap;
+  PhotCodeData *inputPhotcodes;
+  PhotCodeData *outputPhotcodes;
+  int *secfiltMap = NULL;
+
+  if (strcasecmp (argv[2], "into")) dvomerge_usage();
+
+  input  = argv[1];
+  output = argv[3];
+
+  if (ALTERNATE_PHOTCODE_FILE) {
+    fprintf (stderr, "cannot specify photcodes when merging into an existing catdir\n");
+    exit (1);
+  }
+
+  SetPhotcodeTable(NULL);
+  sprintf (filename, "%s/Photcodes.dat", input);
+  if (!LoadPhotcodes (filename, NULL, FALSE)) {
+    fprintf (stderr, "error reading input database directory %s\n", input);
+    exit (1);
+  }	
+  inputPhotcodes = GetPhotcodeTable();
+
+  // since we are merging the input db into the output db, the output defines the photcode
+  // table & db layout but, this requires the output to exist.  if it does not, instead use the
+  // input.
+
+  SetPhotcodeTable(NULL);
+  sprintf (filename, "%s/Photcodes.dat", output);
+  if (LoadPhotcodes (filename, NULL, FALSE)) {
+
+    outputPhotcodes = GetPhotcodeTable();
+
+    secfiltMap = GetSecFiltMap(outputPhotcodes, inputPhotcodes);
+    if (!secfiltMap) {
+      fprintf (stderr, "failed to map input secfilt photcodes to output photcodes table\n");
+      exit (1);
+    }
+  } else {
+    fprintf(stderr, "%s not found using photcodes from %s/Photcodes.dat\n", filename, input);
+    outputPhotcodes = inputPhotcodes;
+    if (!check_dir_access (output, VERBOSE)) {
+      fprintf (stderr, "error creating output database directory %s\n", output);
+      exit (1);
+    }
+    SetPhotcodeTable(inputPhotcodes);
+    if (!SavePhotcodesFITS (filename)) {
+      fprintf (stderr, "error saving photcode table in %s/Photcodes.dat\n", output);
+      exit (1);
+    }
+  }
+
+  // XXX need to determine the mapping from the input to the output images
+  dvomergeImagesGetMap (&IDmap, input, output);
+
+  // load the sky table for the existing database
+  insky = SkyTableLoadOptimal (input, NULL, NULL, FALSE, SKY_DEPTH_HST, VERBOSE);
+  if (!insky) {
+      Shutdown ("can't read SkyTable for %s", input);
+  }
+  SkyTableSetFilenames (insky, input, "cpt");
+
+  // XXX apply this...generate the subset matching the user-selected region
+  inlist = SkyListByPatch (insky, -1, &UserPatch);
+
+  // generate an output table populated at the desired depth
+  outsky = SkyTableLoadOptimal (output, NULL, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
+  if (!outsky) {
+      Shutdown ("can't read or create SkyTable for %s", output);
+  }
+  SkyTableSetFilenames (outsky, output, "cpt");
+
+  // loop over the populatable output tables; check for data in input in the corresponding regions
+
+  SkyListPopulatedRange (&Ns, &Ne, inlist, 0);
+  depth = inlist[0].regions[Ns][0].depth;
+  
+  // loop over the populated input regions
+  for (i = 0; i < inlist[0].Nregions; i++) {
+    if (!inlist[0].regions[i][0].table) continue;
+    if (VERBOSE) fprintf (stderr, "input: %s\n", inlist[0].regions[i][0].name);
+
+    SetPhotcodeTable(inputPhotcodes);
+    // load / create output catalog (if catalog does not exist, it will be created)
+    LoadCatalog (&incatalog, &inlist[0].regions[i][0], inlist[0].filename[i], "r");
+    // skip empty input catalogs
+    if (!incatalog.Naves_disk) {
+	dvo_catalog_unlock (&incatalog);
+	dvo_catalog_free (&incatalog);
+	continue;
+    }
+
+    // combine only tables at equal or larger depth
+      
+    // load in all of the tables from input for this region
+    // 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;
+    outlist = SkyListByBounds (outsky, depth, inlist[0].regions[i][0].Rmin + dPos, inlist[0].regions[i][0].Rmax - dPos, inlist[0].regions[i][0].Dmin + dPos, inlist[0].regions[i][0].Dmax - dPos);
+    for (j = 0; j < outlist[0].Nregions; j++) {
+      if (VERBOSE) fprintf (stderr, "output : %s\n", outlist[0].regions[j][0].name);
+
+      // load input catalog
+      SetPhotcodeTable(outputPhotcodes);
+      LoadCatalog (&outcatalog, outlist[0].regions[j], outlist[0].filename[j], "w");
+
+      dvo_update_image_IDs (&IDmap, &incatalog);
+      merge_catalogs_old (&outsky[0].regions[j], &outcatalog, &incatalog, RADIUS, secfiltMap);
+
+      outcatalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+      // if we receive a signal which would cause us to exit, wait until the full catalog is written
+      SetProtect (TRUE);
+      if (!dvo_catalog_save (&outcatalog, VERBOSE)) {
+	fprintf (stderr, "ERROR: failed to save catalog %s\n", outlist[0].filename[j]);
+	exit (1);
+      }
+      SetProtect (FALSE);
+
+      dvo_catalog_unlock (&outcatalog);
+      dvo_catalog_free (&outcatalog);
+
+      fprintf (stderr, "merged %s into %s\n", inlist[0].regions[i][0].name, outlist[0].regions[j][0].name);
+    }
+    SkyListFree (outlist);
+
+    dvo_catalog_unlock (&incatalog);
+    dvo_catalog_free (&incatalog);
+  }
+
+  // save the output sky table copy
+  sprintf (filename, "%s/SkyTable.fits", output);
+  check_file_access (filename, TRUE, TRUE, VERBOSE);
+  if (!SkyTableSave (outsky, filename)) {
+    fprintf (stderr, "ERROR: failed to save sky table for %s\n", output);
+    exit (1);
+  }
+
+  exit (0);
+}
+
+/*** update the image table ***/
+int dvomergeImagesGetMap (IDmapType *IDmap, char *input, char *output) { 
+
+  FITS_DB inDB;
+  FITS_DB outDB;
+  int    status;
+
+  /*** load input1/Images.dat ***/
+  sprintf (ImageCat, "%s/Images.dat", input);
+  inDB.mode   = dvo_catalog_catmode (CATMODE);
+  inDB.format = dvo_catalog_catformat (CATFORMAT);
+  status       = dvo_image_lock (&inDB, ImageCat, 3600.0, LCK_XCLD);  // shorter timeout?
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", inDB.filename);
+
+  // load the image table 
+  if (inDB.dbstate == LCK_EMPTY) {
+    Shutdown ("only use -continue for an existing, partially merged database");
+  }
+  if (!dvo_image_load (&inDB, VERBOSE, TRUE)) {
+    Shutdown ("can't read input image catalog %s", inDB.filename);
+  }
+
+  /*** load output/Images.dat ***/
+  sprintf (ImageCat, "%s/Images.dat", output);
+  outDB.mode   = dvo_catalog_catmode (CATMODE);
+  outDB.format = dvo_catalog_catformat (CATFORMAT);
+  status       = dvo_image_lock (&outDB, ImageCat, 3600.0, LCK_XCLD);  // shorter timeout?
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", outDB.filename);
+
+  /* load the image table */
+  if (outDB.dbstate == LCK_EMPTY) {
+    Shutdown ("only use -continue for an existing, partially merged database");
+  } 
+  if (!dvo_image_load (&outDB, VERBOSE, TRUE)) {
+    Shutdown ("can't read output image catalog %s", outDB.filename);
+  }
+
+  // convert database table to internal structure & add to output image db
+  dvo_image_match_dbs(IDmap, &outDB, &inDB);
+  dvo_image_unlock (&inDB); // unlock input
+  dvo_image_unlock (&outDB); // unlock output
+
+  return TRUE;
+}
Index: branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/help.c
===================================================================
--- branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/help.c	(revision 29787)
+++ branches/eam_branches/ipp-20101103/Ohana/src/dvomerge/src/help.c	(revision 29788)
@@ -4,4 +4,5 @@
   fprintf (stderr, "USAGE: dvomerge (input1) and (input2) to (output)\n");
   fprintf (stderr, "   OR: dvomerge (input) into (output)\n");
+  fprintf (stderr, "   OR: dvomerge (input) into (output) continue\n");
   fprintf (stderr, "   [-region Rmin Rmax Dmin Dmax]\n");
   exit (2);
@@ -33,5 +34,6 @@
   fprintf (stderr, "USAGE\n");
   fprintf (stderr, "  dvomerge (input1) and (input2) to (output)\n");
-  fprintf (stderr, "  dvomerge (input) into (output)\n\n");
+  fprintf (stderr, "  dvomerge (input) into (output)\n");
+  fprintf (stderr, "  dvomerge (input) into (output) continue\n\n");
   fprintf (stderr, "  merge DVO databases\n");
   fprintf (stderr, "  optional flags:\n");
@@ -39,4 +41,5 @@
   fprintf (stderr, "  -help                 	  : this list\n");
   fprintf (stderr, "  -h                    	  : this list\n\n");
+  fprintf (stderr, "  -region Rmin Rmax Dmin Dmax : region to merge\n\n");
   exit (2);
 }
