Index: /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/Makefile
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/Makefile	(revision 33905)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/Makefile	(revision 33906)
@@ -34,4 +34,5 @@
 $(SRC)/dvomergeImageIDs.$(ARCH).o \
 $(SRC)/dvo_image_merge_dbs.$(ARCH).o \
+$(SRC)/IDmapIO.$(ARCH).o \
 $(SRC)/SetSignals.$(ARCH).o \
 $(SRC)/ConfigInit.$(ARCH).o \
@@ -56,4 +57,5 @@
 $(SRC)/dvomergeImageIDs.$(ARCH).o \
 $(SRC)/dvo_image_merge_dbs.$(ARCH).o \
+$(SRC)/IDmapIO.$(ARCH).o \
 $(SRC)/SetSignals.$(ARCH).o \
 $(SRC)/ConfigInit.$(ARCH).o \
Index: /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/include/dvomerge.h
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/include/dvomerge.h	(revision 33905)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/include/dvomerge.h	(revision 33906)
@@ -42,7 +42,7 @@
 
 typedef struct {
-  off_t Nmap;
-  off_t *old;
-  off_t *new;
+  unsigned int Nmap;
+  unsigned int *old;
+  unsigned int *new;
 } IDmapType;
 
@@ -125,5 +125,8 @@
 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        dvomergeUpdate_catalogs PROTO((char *input, char *output, SkyTable *outsky, SkyList *inlist, int NsecfiltInput, int NsecfiltOutput, IDmapType *IDmap, int *secfiltMap));
 
 int        replace_match           PROTO((Average *average_out, Measure *measure_out, Average *average_in, Measure *measure_in));
+
+int        IDmapSave               PROTO((char *filename, IDmapType *IDmap));
+IDmapType *IDmapLoad               PROTO((char *filename));
Index: /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/IDmapIO.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/IDmapIO.c	(revision 33906)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/IDmapIO.c	(revision 33906)
@@ -0,0 +1,137 @@
+# include "dvomerge.h"
+
+# define GET_COLUMN(OUT,NAME,TYPE) \
+  OUT = gfits_get_bintable_column_data (&theader, &ftable, NAME, type, &Nrow, &Ncol); \
+  myAssert (!strcmp(type, #TYPE), "wrong column type");
+
+// STATUS is value expected for success
+# define CHECK_STATUS(STATUS,MSG,...)					\
+  if (!(STATUS)) {							\
+    fprintf (stderr, MSG, __VA_ARGS__);					\
+    return FALSE;							\
+  }
+
+// write out the IDmap data for clients to read
+int IDmapSave(char *filename, IDmapType *IDmap) {
+
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  gfits_init_header (&header);
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+
+  gfits_create_table_header (&theader, "BINTABLE", "IMAGE_ID_MAP");
+
+  gfits_define_bintable_column (&theader, "J", "OLD_IDS", "old image IDs", NULL, 1.0, 1.0*0x8000);
+  gfits_define_bintable_column (&theader, "J", "NEW_IDS", "new image IDs", NULL, 1.0, 1.0*0x8000);
+
+  // generate the output array that carries the data
+  gfits_create_table (&theader, &ftable);
+
+  // add the columns to the output array
+  // XXX does this damage the data (due to byte swaps?) 
+  // XXX does it matter?
+  gfits_set_bintable_column (&theader, &ftable, "OLD_IDS", IDmap->old, IDmap->Nmap);
+  gfits_set_bintable_column (&theader, &ftable, "NEW_IDS", IDmap->new, IDmap->Nmap);
+
+  FILE *f = fopen (filename, "w");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open ID map file for output %s\n", filename);
+    return FALSE;
+  }
+
+  int status;
+  status = gfits_fwrite_header  (f, &header);
+  CHECK_STATUS (status, "ERROR: cannot write header for image subset %s\n", filename);
+
+  status = gfits_fwrite_matrix  (f, &matrix);
+  CHECK_STATUS (status, "ERROR: cannot write matrix for image subset %s\n", filename);
+
+  status = gfits_fwrite_Theader (f, &theader);
+  CHECK_STATUS (status, "ERROR: cannot write table header for image subset %s\n", filename);
+
+  status = gfits_fwrite_table  (f, &ftable);
+  CHECK_STATUS (status, "ERROR: cannot write table data for image subset %s\n", filename);
+
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  gfits_free_header (&theader);
+  gfits_free_table (&ftable);
+
+  int fd = fileno (f);
+
+  status = fflush (f);
+  CHECK_STATUS (!status, "ERROR: cannot flush file image subset %s\n", filename);
+
+  status = fsync (fd);
+  CHECK_STATUS (!status, "ERROR: cannot flush file image subset %s\n", filename);
+
+  status = fclose (f);
+  CHECK_STATUS (!status, "ERROR: problem closing image subset file %s\n", filename);
+
+  return TRUE;
+}
+
+IDmapType *IDmapLoad (char *filename) {
+
+  int Ncol;
+  off_t Nrow;
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+  IDmapType *IDmap;
+
+  ALLOCATE (IDmap, IDmapType, 1);
+  IDmap->Nmap = 0;
+  IDmap->old = NULL;
+  IDmap->new = NULL;
+
+  FILE *f = fopen (filename, "r");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open image subset file %s\n", filename);
+    return NULL;
+  }
+
+  /* load in PHU segment (ignore) */
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset header\n");
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset matrix\n");
+    gfits_free_header (&header);
+    fclose (f);
+    return NULL;
+  }
+
+  ftable.header = &theader;
+
+  // load data for this header 
+  if (!gfits_load_header (f, &theader)) {
+    fclose (f);
+    return NULL;
+  }
+
+  // read the fits table bytes
+  if (!gfits_fread_ftable_data (f, &ftable, FALSE)) {
+    fclose (f);
+    return (NULL);
+  }
+  fclose (f);
+
+  char type[16];
+
+  GET_COLUMN (IDmap->old, "OLD_IDS", int);
+  GET_COLUMN (IDmap->new, "NEW_IDS", int);
+  IDmap->Nmap = Nrow;
+  fprintf (stderr, "loaded data for %lld images\n", (long long) Nrow);
+
+  return IDmap;
+}
+
Index: /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 33905)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 33906)
@@ -1,51 +1,8 @@
 # include "dvomerge.h"
 
+// utility functions
 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
-
-}
+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);
 
 // we have two tables; 'tgt' contains some exposures from 'src' : find them and match a map
@@ -71,6 +28,6 @@
   }
 
-  ALLOCATE (IDmap->old, off_t, NimagesSrc);
-  ALLOCATE (IDmap->new, off_t, NimagesSrc);
+  ALLOCATE (IDmap->old, unsigned int, NimagesSrc);
+  ALLOCATE (IDmap->new, unsigned int, NimagesSrc);
   IDmap->Nmap = NimagesSrc;
 
@@ -130,6 +87,6 @@
   }
 
-  ALLOCATE (IDmap->old, off_t, Nimages);
-  ALLOCATE (IDmap->new, off_t, Nimages);
+  ALLOCATE (IDmap->old, unsigned int, Nimages);
+  ALLOCATE (IDmap->new, unsigned int, Nimages);
   IDmap->Nmap = Nimages;
 
@@ -165,5 +122,6 @@
 }
 
-// XXX isn't the map just ID_new = ID_old + offset ??
+// map this ID to the new table
+// XXX isn't the map just ID_new = ID_old + offset ?? (probably not)
 off_t dvo_map_image_ID (IDmapType *IDmap, off_t oldID) {
 
@@ -199,4 +157,5 @@
 }
 
+// given a table of detections, update their image IDs based on the new map
 int dvo_update_image_IDs (IDmapType *IDmap, Catalog *catalog) {
 
@@ -237,2 +196,48 @@
 }
 
+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
+
+}
+
Index: /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomergeImageIDs.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomergeImageIDs.c	(revision 33905)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomergeImageIDs.c	(revision 33906)
@@ -1,5 +1,5 @@
 # include "dvomerge.h"
 
-/*** update the image table ***/
+/*** generate the IDmap for the given databases, and update the output image table ***/
 int dvomergeImagesUpdate (IDmapType *IDmap, char *input, char *output) { 
 
@@ -53,5 +53,5 @@
 }
 
-/*** update the image table ***/
+/*** generate the map for the given 2 databases ***/
 int dvomergeImagesGetMap (IDmapType *IDmap, char *input, char *output) { 
 
Index: /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomergeUpdate.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomergeUpdate.c	(revision 33905)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomergeUpdate.c	(revision 33906)
@@ -105,5 +105,5 @@
   SetPhotcodeTable(NULL);
 
-  dvomergeUpdate_catalogs (input, output, outsky, inlist, NsecfiltInput, NsecfiltOutput, IDmap, secfiltMap);
+  dvomergeUpdate_catalogs (input, output, outsky, inlist, NsecfiltInput, NsecfiltOutput, &IDmap, secfiltMap);
 
   // save the output sky table copy
Index: /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c	(revision 33905)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c	(revision 33906)
@@ -8,7 +8,7 @@
 // output tables
 
-int dvomergeUpdate_parallel (char *input, char *output, SkyTable *outsky);
-
-int dvomergeUpdate_catalogs (char *input, char *output, SkyTable *outsky, SkyList *inlist, int NsecfiltInput, int NsecfiltOutput, IDmapType IDmap, int *secfiltMap) {
+int dvomergeUpdate_parallel (char *input, char *output, SkyTable *outsky, IDmapType *IDmap);
+
+int dvomergeUpdate_catalogs (char *input, char *output, SkyTable *outsky, SkyList *inlist, int NsecfiltInput, int NsecfiltOutput, IDmapType *IDmap, int *secfiltMap) {
 
   off_t i, j;
@@ -17,5 +17,5 @@
 
   if (PARALLEL && !HOST_ID) {
-    int status = dvomergeUpdate_parallel (input, output, outsky);
+    int status = dvomergeUpdate_parallel (input, output, outsky, IDmap);
     return status;
   }
@@ -145,5 +145,5 @@
       LoadCatalog (&outcatalog, outlist[0].regions[j], outcatalog.filename, "w", NsecfiltOutput);
 
-      dvo_update_image_IDs (&IDmap, &incatalog);
+      dvo_update_image_IDs (IDmap, &incatalog);
       merge_catalogs_old (outlist[0].regions[j], &outcatalog, &incatalog, RADIUS, secfiltMap);
 
@@ -185,7 +185,20 @@
 }
 
-int dvomergeUpdate_parallel (char *input, char *output, SkyTable *outsky) {
-
-  // launch the dvomergeUpdate_client jobs to the parallel hosts
+// launch the dvomergeUpdate_client jobs to the parallel hosts
+int dvomergeUpdate_parallel (char *input, char *output, SkyTable *outsky, IDmapType *IDmap) {
+
+  // ensure that the paths are absolute path names
+  char *absinput  = abspath (input,  DVO_MAX_PATH);
+  char *absoutput = abspath (output, DVO_MAX_PATH);
+
+  // name of image subset file:
+  char IDmapFilename[DVO_MAX_PATH];
+  snprintf (IDmapFilename, DVO_MAX_PATH, "%s/IDmap.fits", absoutput);
+
+  // save IDmap information
+  if (!IDmapSave (IDmapFilename, IDmap)) {
+    fprintf (stderr, "ERROR: failure to save the image ID map\n");
+    exit (1);
+  }
 
   // load the list of hosts
@@ -203,8 +216,4 @@
     free (table->hosts[i].pathname);
     table->hosts[i].pathname = tmppath;
-
-    // ensure that the paths are absolute path names
-    char *absinput  = abspath (input,  DVO_MAX_PATH);
-    char *absoutput = abspath (output, DVO_MAX_PATH);
 
     // options / arguments that can affect relastro_client -update-objects:
Index: /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomerge_client.c
===================================================================
--- /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomerge_client.c	(revision 33905)
+++ /branches/eam_branches/ipp-20120405/Ohana/src/dvomerge/src/dvomerge_client.c	(revision 33906)
@@ -10,5 +10,5 @@
   SkyList *inlist;
   char filename[256], *input, *output;
-  IDmapType IDmap;
+  IDmapType *IDmap;
   PhotCodeData *inputPhotcodes;
   PhotCodeData *outputPhotcodes;
@@ -51,5 +51,14 @@
   }
 
-  dvomergeImagesGetMap (&IDmap, input, output);
+  char *absoutput = abspath (output, DVO_MAX_PATH);
+  char IDmapFilename[DVO_MAX_PATH];
+  snprintf (IDmapFilename, DVO_MAX_PATH, "%s/IDmap.fits", absoutput);
+
+  // save IDmap information
+  IDmap = IDmapLoad (IDmapFilename);
+  if (!IDmap) {
+    fprintf (stderr, "ERROR: failure to save the image ID map\n");
+    exit (1);
+  }
 
   // load the sky table for the existing database
@@ -74,5 +83,5 @@
   SetPhotcodeTable(NULL);
   
-   dvomergeUpdate_catalogs (input, output, outsky, inlist, NsecfiltInput, NsecfiltOutput, IDmap, secfiltMap);
+  dvomergeUpdate_catalogs (input, output, outsky, inlist, NsecfiltInput, NsecfiltOutput, IDmap, secfiltMap);
 
   exit (0);
