Index: trunk/Ohana/src/dvomerge/Makefile
===================================================================
--- trunk/Ohana/src/dvomerge/Makefile	(revision 39280)
+++ trunk/Ohana/src/dvomerge/Makefile	(revision 39281)
@@ -129,5 +129,5 @@
 $(SRC)/dvorepairDeleteImageList.$(ARCH).o \
 $(SRC)/dvorepairDeleteImagesByExternID.$(ARCH).o \
-$(SRC)/dvorepairDeleteImagesByExternID.$(ARCH).o \
+$(SRC)/dvorepairDeleteImagesByExternID_v2.$(ARCH).o \
 $(SRC)/dvorepairFixImages.$(ARCH).o \
 $(SRC)/dvorepair_by_objID.$(ARCH).o \
Index: trunk/Ohana/src/dvomerge/include/dvomerge.h
===================================================================
--- trunk/Ohana/src/dvomerge/include/dvomerge.h	(revision 39280)
+++ trunk/Ohana/src/dvomerge/include/dvomerge.h	(revision 39281)
@@ -246,4 +246,7 @@
 int *ReadDeleteListExternID(char *filename, int *nindex);
 
+int dvorepairDeleteImagesByExternID_v2 (int argc, char **argv);
+int *ReadDeleteListExternID_v2(char *filename, int *nindex);
+
 void replace_tycho_init ();
 int  replace_tycho (Average *averageInp, Measure *measureInp, off_t *next_meas, Average *averageOut, Measure *measureOut);
Index: trunk/Ohana/src/dvomerge/src/ReadDeleteListExternID.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/ReadDeleteListExternID.c	(revision 39280)
+++ trunk/Ohana/src/dvomerge/src/ReadDeleteListExternID.c	(revision 39281)
@@ -1,3 +1,15 @@
 # include "dvomerge.h"
+
+/* Delete List Format:
+   image o5252g0035o.140669.cm.51017.smf[XY11.hdr] (219974) : 368 vs 375
+   image o5252g0051o.140685.cm.51123.smf[XY11.hdr] (226417) : 350 vs 356
+   image o5399g0207o.194950.cm.98351.smf[XY46.hdr] (1683277) : 10341 vs 10347
+   image o5464g0284o.230438.cm.123774.smf[XY21.hdr] (2634913) : 214 vs 242
+   image o5464g0305o.230459.cm.123795.smf[XY21.hdr] (2635758) : 232 vs 257
+   image o5465g0306o.231171.cm.124201.smf[XY01.hdr] (2654941) : 0 vs 494
+   image o5465g0306o.231171.cm.124201.smf[XY02.hdr] (2654942) : 10 vs 813
+   image o5465g0306o.231171.cm.124201.smf[XY10.hdr] (2654947) : 0 vs 534
+   image o5465g0306o.231171.cm.124201.smf[XY11.hdr] (2654948) : 0 vs 447
+*/
 
 int *ReadDeleteListExternID(char *filename, int *nindex) {
@@ -81,13 +93,86 @@
 
 /* Delete List Format:
-   image o5252g0035o.140669.cm.51017.smf[XY11.hdr] (219974) : 368 vs 375
-   image o5252g0051o.140685.cm.51123.smf[XY11.hdr] (226417) : 350 vs 356
-   image o5399g0207o.194950.cm.98351.smf[XY46.hdr] (1683277) : 10341 vs 10347
-   image o5464g0284o.230438.cm.123774.smf[XY21.hdr] (2634913) : 214 vs 242
-   image o5464g0305o.230459.cm.123795.smf[XY21.hdr] (2635758) : 232 vs 257
-   image o5465g0306o.231171.cm.124201.smf[XY01.hdr] (2654941) : 0 vs 494
-   image o5465g0306o.231171.cm.124201.smf[XY02.hdr] (2654942) : 10 vs 813
-   image o5465g0306o.231171.cm.124201.smf[XY10.hdr] (2654947) : 0 vs 534
-   image o5465g0306o.231171.cm.124201.smf[XY11.hdr] (2654948) : 0 vs 447
+  duplicate 78853625 2
+  duplicate 78853626 2
+  duplicate 78853627 2
 */
 
+int *ReadDeleteListExternID_v2(char *filename, int *nindex) {
+
+  int j, index, Nindex, NINDEX, *indexList, Nline;
+  int Nstart, Nbytes, Nread, status;
+  char *c0, *c1, *space, *buffer;
+
+  char *indexPoint = NULL;
+  FILE *f = fopen (filename, "r");
+  myAssert(f, "failed to open delete list");
+  
+  Nindex = 0;
+  NINDEX = 1000;
+  ALLOCATE(indexList, int, NINDEX);
+
+  ALLOCATE (buffer, char, 0x10001);
+  bzero (buffer, 0x10001);
+
+  Nstart = 0;
+  Nline = 0;
+  while (1) {
+    Nbytes = 0x10000 - Nstart;
+    bzero (&buffer[Nstart], Nbytes);
+    Nread = fread (&buffer[Nstart], 1, Nbytes, f);
+    if (ferror (f)) {
+      perror ("error reading data file");
+      exit (1);
+    }
+    if (Nread == 0) break; // end of data
+    // nbytes = Nread + Nstart;
+    
+    status = TRUE;
+    c0 = buffer; 
+    while (status) {
+      // identify the range of the line
+      c1 = strchr (c0, '\n');
+      if (c1 == (char *) NULL) {
+	Nstart = strlen (c0);
+	memmove (buffer, c0, Nstart);
+	break;
+      } else {
+	*c1 = 0;
+      }      
+      if (*c0 == '#') goto next_line;
+
+      // confirm we have 3 fields broken by 2 spaces:
+      space = c0; // pointer to track the space-separated words
+      indexPoint = strchr(c0, ' '); // pointer to the ID on this line
+
+      for (j = 0; j < 3; j++) {
+	space = strchr(space, ' '); 
+	if (!space) {
+	  fprintf (stderr, "line only has %d word(s)\n", j + 1);
+	  goto next_line;
+	}
+	space ++;
+      }
+
+      // save the value we have found:
+      index = atoi(indexPoint);
+      indexList[Nindex] = index;
+
+      fprintf (stderr, "index: %d, line: %s\n", index, c0);
+
+      Nindex ++;
+      if (Nindex == NINDEX) {
+	NINDEX += 1000;
+	REALLOCATE (indexList, int, NINDEX);
+      }
+      
+    next_line:
+      Nline ++;
+      c0 = c1 + 1;
+    }
+  }
+
+  *nindex = Nindex;
+  return (indexList);
+}
+
Index: trunk/Ohana/src/dvomerge/src/dvorepair.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvorepair.c	(revision 39280)
+++ trunk/Ohana/src/dvomerge/src/dvorepair.c	(revision 39281)
@@ -19,4 +19,5 @@
   if (!strcmp(argv[1], "-delete-image-list")) dvorepairDeleteImageList(argc, argv);
   if (!strcmp(argv[1], "-delete-images-by-extern-id")) dvorepairDeleteImagesByExternID(argc, argv);
+  if (!strcmp(argv[1], "-delete-images-by-extern-id-v2")) dvorepairDeleteImagesByExternID_v2(argc, argv);
   if (!strcmp(argv[1], "-fix-images")) dvorepairFixImages(argc, argv);
   dvorepair_help(0, NULL);
Index: trunk/Ohana/src/dvomerge/src/dvorepairDeleteImagesByExternID_v2.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvorepairDeleteImagesByExternID_v2.c	(revision 39281)
+++ trunk/Ohana/src/dvomerge/src/dvorepairDeleteImagesByExternID_v2.c	(revision 39281)
@@ -0,0 +1,145 @@
+# include "dvomerge.h"
+
+// delete images based on a text table of the target IDs
+// * load the delete table file (validate format)
+// * load the Images.dat file
+// * create an index for imageID (seq = imageIDindex[i])
+// * create an index of the imageIDs to be deleted (delete (T/F) = imageDELindex[i])
+// * determine the full RA & DEC range of the images to be deleted
+// * scan over all catalog files in the specified RA & DEC range
+// * load the cpm file (pad if short, identify the padded section)
+// * create a new cpm file
+// * loop over detections : only keep those not from images to be deleted
+// * load the cpt file
+// * rebuild the cpt file or delete the matching entries?
+
+int SaveImageTable (Image *image, off_t Nimage, char *catdir, FITS_DB *oldDB);
+Image *DeleteSelectedImages (Image *image, off_t Nimage, int *deleteImage, myIndexType *imageIDindex, off_t *NnewImage);
+int DeleteLensing (Catalog *catalog, myIndexType *imageIDindex, int *deleteImage, int *nDelete);
+int DeleteMeasure (Catalog *catalog, myIndexType *imageIDindex, int *deleteImage, int *nDelete);
+int RepairAverage (Catalog *catalog);
+
+int dvorepairDeleteImagesByExternID_v2 (int argc, char **argv) {
+
+  FITS_DB db;  // database handle pointing to input image table
+  
+  int i, N;
+  off_t Nimage;
+
+  Image *image;
+  char *imageFilename = NULL;
+  char filename[DVO_MAX_PATH];
+
+  N = get_argument (argc, argv, "-delete-images-by-extern-id-v2");
+  myAssert(N == 1, "programming error: -delete-images-by-extern-id must be first argument");
+  remove_argument (N, &argc, argv);
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: dvorepair -delete-images-by-extern-id (catdir) (deleteList)\n");
+    fprintf (stderr, "  catdir : database of interest\n");
+    fprintf (stderr, "  deleteList : table from dvorepair giving images to be deleted\n");
+    exit (2);
+  }
+
+  char *catdir = argv[1];
+  char *delList = argv[2];
+
+  sprintf (filename, "%s/Photcodes.dat", catdir);
+  if (!LoadPhotcodes (filename, NULL, FALSE)) {
+    fprintf (stderr, "error reading photcodes from %s\n", catdir);
+    exit (1);
+  }	
+
+  // load the image data
+  ALLOCATE(imageFilename, char, strlen(catdir) + 12);
+  sprintf (imageFilename, "%s/Images.dat", catdir);
+  if ((image = LoadImages (&db, imageFilename, &Nimage)) == NULL) return (FALSE);
+  BuildChipMatch (image, Nimage); // needed for astrometric tranformations
+
+  // generate an index for imageIDs
+  myIndexType *externIDindex = myIndexInit();
+  myIndexType *imageIDindex = myIndexInit();
+
+  // set the min and max ID values for the two strucures:
+  for (i = 0; i < Nimage; i++) {
+    myIndexUpdateLimits (imageIDindex,  image[i].imageID);
+
+    if (!image[i].externID) continue;
+    myAssert (image[i].imageID, "image must have imageID > 0");
+    myIndexUpdateLimits (externIDindex, image[i].externID);
+  }
+
+  myIndexSetRange (externIDindex);
+  myIndexSetRange (imageIDindex);
+
+  fprintf (stderr, "loaded %d images, image ID range: %d - %d, extern ID range: %d - %d\n", (int) Nimage, imageIDindex->minID, imageIDindex->maxID, externIDindex->minID, externIDindex->maxID);
+			
+  // deleteImage[i] will be TRUE if we want to delete that image
+  int *deleteImage = NULL;
+  ALLOCATE (deleteImage, int, Nimage);
+  for (i = 0; i < Nimage; i++) {
+    deleteImage[i] = FALSE;
+  }
+
+  // assign the externIDs and imageIDs to their index structures
+  for (i = 0; i < Nimage; i++) {
+    myIndexSetEntry (imageIDindex,  image[i].imageID,  i);
+
+    if (!image[i].externID) continue;
+    myIndexSetEntry (externIDindex, image[i].externID, i);
+  }
+
+  // read the list of externIDs to delete
+  int NdeleteIDs;
+  int *deleteIDs = ReadDeleteListExternID_v2(delList, &NdeleteIDs);
+
+  int NdeleteImages = 0;
+  for (i = 0; i < NdeleteIDs; i++) {
+    int externID = deleteIDs[i];
+    myAssert(externID > 0, "extern ID to delete cannot be <= 0");
+    
+    // we do not require all externIDs to be deleted to actually be in this db,
+    // but skip any externIDs not in this db (myIndexGetEntry returns -1)
+    int n = myIndexGetEntry(externIDindex, externID);
+    if (n < 0) continue;
+
+    if (deleteImage[n]) {
+      fprintf (stderr, "multiple entries for extern ID %d == imageID %d, re-run\n", externID, image[n].imageID);
+    }
+    deleteImage[n] = TRUE;
+    NdeleteImages ++;
+
+    if (VERBOSE) fprintf (stderr, "delete %s extern ID: %d = image ID %d (seq %d)\n", image[n].name, externID, image[n].imageID, n);
+  }
+
+  if (NdeleteImages == 0) {
+    fprintf (stderr, "no images to be deleted in this database, exiting\n");
+    exit (0);
+  }
+
+  off_t NnewImage;
+  Image *newImage = DeleteSelectedImages (image, Nimage, deleteImage, imageIDindex, &NnewImage);
+
+  SaveImageTable (newImage, NnewImage, catdir, &db);
+
+  myIndexFree (externIDindex);
+  myIndexFree (imageIDindex);
+
+  free (imageFilename);
+  free (deleteImage);
+  free (deleteIDs);
+
+  gfits_db_free (&db);
+
+  ohana_memcheck (TRUE);
+
+  exit (0);
+}
+
+
