Index: /branches/eam_branches/ipp-20120905/Ohana/src/delstar/doc/delete_photcodes.txt
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/delstar/doc/delete_photcodes.txt	(revision 34685)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/delstar/doc/delete_photcodes.txt	(revision 34685)
@@ -0,0 +1,33 @@
+
+2012.11.21
+
+I'm working on the code to delete a subset of photcodes.  I'm
+basically re-writing the delstar core code because I don't trust this
+old stuff to work any more.
+
+But, I'm getting myself confused, so I need to map this out:
+
+we start with Measure, Average, where
+
+ measure[i].averef -> average[averef]
+ measure[i].objID   = average[averef].objID
+ measure[i].catID   = average[averef].catID
+
+I am not assuming the input Measure array is sorted (in averef order)
+
+Generate the following arrays:
+
+given measure[i], average[averef] in arbitrary order:
+
+n = measureSeqRaw[i] : measure[n] is in averef order (after sort)
+
+n = measureSeqOut[i] : measure[n] in averef order, only valid measurements
+
+n = measureAveRaw[i] : average[n] is matching entry (just an array of the averefs)
+
+averageNmeas[i] : number of measurements after filtering
+
+averageSeqOut[i] : new averef sequence after filtering
+
+n = measureAveOut[i] : average[n] is matching entry, only valid measurements
+
Index: /branches/eam_branches/ipp-20120905/Ohana/src/delstar/include/delstar.h
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/delstar/include/delstar.h	(revision 34684)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/delstar/include/delstar.h	(revision 34685)
@@ -32,5 +32,5 @@
 
 int    MODE;
-enum {MODE_IMAGENAME, MODE_IMAGEFILE, MODE_TIME, MODE_ORPHAN, MODE_MISSED};
+enum {MODE_NONE, MODE_IMAGENAME, MODE_IMAGEFILE, MODE_TIME, MODE_ORPHAN, MODE_MISSED};
 
 char DateKeyword[64], DateMode[64], UTKeyword[64], MJDKeyword[64], JDKeyword[64];
Index: /branches/eam_branches/ipp-20120905/Ohana/src/delstar/src/args.c
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/delstar/src/args.c	(revision 34684)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/delstar/src/args.c	(revision 34685)
@@ -38,4 +38,6 @@
     remove_argument (N, argc, argv);
   }
+
+  // region of interest
 
   MODE = MODE_IMAGEFILE;
@@ -108,2 +110,32 @@
   return (TRUE);
 }
+
+int args_client (int *argc, char **argv) {
+  
+  int N;
+  double trange;
+
+  /* check for help request */
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    help ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MODE = MODE_NONE;
+  if ((N = get_argument (*argc, argv, "-photcodes"))) {
+    if (MODE != MODE_NONE) usage();
+    MODE = MODE_PHOTCODES;
+    remove_argument (N, argc, argv);
+    PHOTCODE_LIST = strcreate(argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  if (MODE == MODE_NONE) usage ();
+  return (TRUE);
+}
Index: /branches/eam_branches/ipp-20120905/Ohana/src/delstar/src/delete_photcodes.c
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/delstar/src/delete_photcodes.c	(revision 34684)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/delstar/src/delete_photcodes.c	(revision 34685)
@@ -1,16 +1,15 @@
 # include "delstar.h"
 
-void delete_times (FITS_DB *db) {
+void delete_photcodes (FITS_DB *db, photcodes, Nphotcodes) {
 
   int found, code;
   off_t i, j, k, n;
-  off_t Nimage, Nimlist;
   off_t Nregions, NREGIONS;
   off_t *imlist;
   SkyList *skylist, *skyset;
   SkyTable *sky;
-  Image *image;
   Catalog catalog;
 
+  // xxx where does this go?
   photcodesDrop = ParsePhotcodeList (PHOTCODE_LIST, &NphotcodesDrop, FALSE);
 
@@ -23,7 +22,4 @@
 
   // delete images with these photcodes
-  delete_photcodes_images (db, photcodesDrop, NphotcodesDrop);
-
-  // delete images with these photcodes
   delete_photcodes_catalogs (db, photcodesDrop, NphotcodesDrop);
 
@@ -32,10 +28,10 @@
 }
 
-void delete_photcodes_catalogs (skylist, photcodesDrop, NphotcodesDrop) {
-
-  // XXX need to decide how to determine PARALLEL mode...
+void delete_photcodes_catalogs (skylist, hostID, photcodesDrop, NphotcodesDrop) {
+
+  // launch the remote jobs
   if (PARALLEL && !hostID) {
-    delete_photcodes_parallel (skylist, photcodesDrop, NphotcodesDrop);
-    return TRUE;
+    int status = delete_photcodes_parallel (skylist, photcodesDrop, NphotcodesDrop);
+    return status;
   }
 
@@ -46,5 +42,4 @@
     if (!HostTableTestHost(skylist[0].regions[i], hostID)) continue;
 
-    // set up the basic catalog info
     // set up the basic catalog info
     char hostfile[1024];
@@ -68,5 +63,5 @@
     }
 
-    find_matches (&catalog, code, START, END);
+    delete_photcodes_from_catalog (&catalog, photcodes, Nphotcodes);
     dvo_catalog_save (&catalog, VERBOSE);
     dvo_catalog_unlock (&catalog);
@@ -98,18 +93,11 @@
 
     // options / arguments that can affect relphot_client -update-objects:
-    // VERBOSE, VERBOSE2
-    // KEEP_UBERCAL
-    // RESET (-reset)
-    // TimeSelect -time
-    // DophotSelect
-    // (note that psfQF is applied rigidly at 0.85, as is the galaxy test)
-    // MAG_LIM
-    // SIGMA_LIM
-    // ImagSelect, ImagMin, ImagMax
-    // MaxDensityUse, MaxDensityValue
+    // VERBOSE
 
     char command[1024];
     snprintf (command, 1024, "delstar_client -hostID %d -D CATDIR %s -hostdir %s -region %f %f %f %f -photcodes %s", 
-	      table->hosts[i].hostID, CATDIR, table->hosts[i].pathname, UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax, PHOTCODE_LIST);
+	      table->hosts[i].hostID, CATDIR, table->hosts[i].pathname, 
+	      UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax, 
+	      PHOTCODE_LIST);
 
     char tmpline[1024];
@@ -123,5 +111,5 @@
       int status = system (command);
       if (status) {
-	fprintf (stderr, "ERROR running relphot_client\n");
+	fprintf (stderr, "ERROR running delstar_client\n");
 	exit (2);
       }
@@ -148,2 +136,200 @@
   return TRUE;
 }      
+
+// sort the measure Sequence based on the average Sequence entries
+void SortAveMeasMatch (off_t *MEAS, off_t *AVE, off_t N) {
+
+# define SWAPFUNC(A,B){ off_t tmp_meas; off_t tmp_ave;	\
+    tmp_meas = MEAS[A]; MEAS[A] = MEAS[B]; MEAS[B] = tmp_meas;		\
+    tmp_ave  = AVE[A];  AVE[A]  = AVE[B];  AVE[B]  = tmp_ave;		\
+  }
+# define COMPARE(A,B)(AVE[A] < AVE[B])
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+# undef SWAPFUNC
+# undef COMPARE
+}
+
+int delete_photcodes_catalog (Catalog *catalog, photcodes, Nphotcodes) {
+
+  off_t i, j, N, currentAve;
+
+  off_t *measureSeq = NULL;
+  off_t *averageSeq = NULL;
+  Measure *measureTMP = NULL;
+
+  /* internal counters */
+  off_t Nmeasure = catalog[0].Nmeasure;
+  off_t Naverage = catalog[0].Naverage;
+
+  Measure *measure = catalog[0].measure;
+  Average *average = catalog[0].average;
+  
+  if (VERBOSE) fprintf (stderr, "starting with Nave, Nmeas: "OFF_T_FMT" "OFF_T_FMT"\n",  catalog[0].Naverage,  catalog[0]Nmeasure);
+
+  // we have a table of average objects and an unsorted table of measurements.  each measurement
+  // has a reference to the average object sequence (as well as an ID)
+  // measure[i].averef -> average[averef]
+  // measure[i].objID = average[averef].objID
+  // measure[i].catID = average[averef].catID
+
+  // we want a sorted measure array with all averef entries in sequence, skipping the entries which match our criteria
+
+  // arrays 
+  ALLOCATE (measureDrop,   off_t, Nmeasure);
+  ALLOCATE (measureSeqRaw, off_t, Nmeasure);
+  ALLOCATE (measureSeqOut, off_t, Nmeasure);
+  ALLOCATE (measureAveRaw, off_t, Nmeasure);
+  ALLOCATE (averageNmeas,  off_t, Naverage);
+  ALLOCATE (averageDmeas,  off_t, Naverage);
+  ALLOCATE (averageSeqOut, off_t, Naverage);
+  ALLOCATE (averageRefOut, off_t, Naverage);
+  ALLOCATE (measureAveOut, off_t, NmeasOut);
+
+  // mark the measures to be dropped
+  for (i = 0; i < Nmeasure; i++) {
+    int drop = FALSE;
+    for (j = 0; !drop && (j < Nphotcodes); j++) {
+      drop |= (photcodes[j].code == measure[i].photcode);
+    }
+    measureDrop[i] = drop;
+  }
+
+  // set up the measure sequence lists
+  for (i = 0; i < Nmeasure; i++) {
+    measureSeqRaw[i] = i;
+    measureAveRaw[i] = measure[i].averef;
+  }
+  // sort measureSeqRaw and measureAveRaw in order of measureAveRaw
+  SortAveMeasMatch(measureSeqRaw, measureAveRaw, Nmeasure);
+
+  // generate the measureSeqOut array
+  off_t NmeasOut = 0;
+  for (i = 0; i < Nmeasure; i++) {
+    j = measureSeqRaw[i];
+    if (measureDrop[j]) continue;
+    measureSeqOut[NmeasOut] = j;
+    measureRefOut[j] = NmeasOut;
+    NmeasOut ++;
+  }
+  // n = measureSeqOut[i] : measureOut[i] = measure[n]  (i = 0 -- NmeasOut, n = 0 -- Nmeasure)
+  // n = measureRefOut[i] : measureOut[n] = measure[i]
+
+  // count the number of measures for each averef
+  off_t N =  0;
+  off_t D = -1;
+  currentAve = measureAveRaw[0];
+  for (i = 0; i < Nmeasure; i++) {
+    if (measureAveRaw[i] != currentAve) {
+      // we have hit the next entry in the list
+      averageNmeas[currentAve] = N; // number of measures
+      averageDmeas[currentAve] = D; // first measure 
+      N =  0;
+      D = -1;
+      currentAve = measureAveRaw[i];
+    }
+    j = measureSeqRaw[i];
+    if (measureDrop[j]) continue;
+    N++;
+    if (D == -1) { 
+      // first valid measureOut for this averef
+      D = measureRefOut[j];
+    }
+  }
+  averageNmeas[currentAve] = N; // number of measures
+  averageDmeas[currentAve] = D; // first measure 
+
+  // generate the new average sequence, skipping entries with no measurements
+  int NaveOut = 0;
+  for (i = 0; i < Naverage; i++) {
+    if (averageNmeas[i] == 0) continue;
+    averageSeqOut[Nave] = i;
+    averageRefOut[i] = Nave;
+    Nave ++;
+  }
+  // n = averageSeqOut[i] : averageOut[i] = average[n]  (i = 0 -- NaveOut, n = 0 -- Naverage)
+  // n = averageRefOut[i] : averageOut[n] = average[i]
+
+  // generate the output averefs
+  for (i = 0; i < NmeasOut; i++) {
+    j = measureSeqOut[i]; // measure[j] = measureOut[i]
+    n = measureAveRaw[j]; // average[n] : measure[j]
+    N = averageRefOut[n]; // averageOut[N] = average[n];
+    measureAveOut[i] = N; // measureOut[i].averef = measureAveOut[i] 
+  }
+
+  // copy the (kept) measurements in the sorted order
+  ALLOCATE (measureOut, Measure, Nmeas);
+  for (i = 0; i < Nmeas; i++) {
+    j = measureSeqOut[i];
+    measureOut[i] = measure[j];
+    measureOut[i].averef = measureAveOut[i];
+  }
+
+  // copy the (kept) average entries
+  ALLOCATE (averageOut, Average, Nave);
+  for (i = 0; i < Nave; i++) {
+    j = averageSeqOut[i];
+    averageOut[i] = average[j];
+    averageOut[i].Nmeasure      = averageNmeas[j]; 
+    averageOut[i].measureOffset = averageDmeas[j];
+  }
+
+  // update the values of average.measureOffset and average.Nmeasure
+  FREE(measure);
+  FREE(average);
+  catalog[0].measure = measureOut;
+  catalog[0].average = averageOut;
+
+  // update catalog.Nmeasure and catalog.Naverage, double check 
+  int NmeasureTotal = 0;
+  int measureOffsetOK = TRUE;
+  for (i = 0; i < Naverage; i++) {
+    NmeasureTotal += catalog[0].average[i].Nmeasure;
+    if (VERBOSE && !(NmeasureTotal <= catalog[0].Nmeasure)) {
+      fprintf (stderr, "too few measurements: %d %d %d\n", (int) i, NmeasureTotal, (int) catalog[0].Nmeasure);
+    }
+    measureOffsetOK &= (catalog[0].average[i].measureOffset < catalog[0].Nmeasure);
+    if (VERBOSE && !(catalog[0].average[i].measureOffset < catalog[0].Nmeasure)) {
+      fprintf (stderr, "offset too large: %d %d %d\n", (int) i, catalog[0].average[i].Nmeasure, (int) catalog[0].Nmeasure);
+    }
+    measureOffsetOK &= (catalog[0].average[i].measureOffset + catalog[0].average[i].Nmeasure <= catalog[0].Nmeasure);
+    if (VERBOSE && !(catalog[0].average[i].measureOffset + catalog[0].average[i].Nmeasure <= catalog[0].Nmeasure)) {
+      fprintf (stderr, "orrset + Nmeasure too large: %d + %d > %d %d\n", (int) i, catalog[0].average[i].measureOffset, catalog[0].average[i].Nmeasure, (int) catalog[0].Nmeasure);
+    }
+    m = catalog[0].average[i].measureOffset;
+    for (j = 0; j < catalog[0].average[i].Nmeasure; j++) {
+      averefOK &= (catalog[0].measure[m+j].averef == i);
+      if (VERBOSE && !(catalog[0].measure[m+j].averef == i)) {
+	fprintf (stderr, "averef broken: %d vs %d (measure %d)\n", (int) i, catalog[0].measure[m+j].averef, m+j);
+      }
+    }
+  }
+
+  if (!measureOffsetOK) {
+    fprintf (stderr, "ERROR: catalog %s has an invalid measureOffset\n", catalog[0].filename);
+  }
+
+  if (!averefOK) {
+    fprintf (stderr, "ERROR: catalog %s has invalid averefs\n", catalog[0].filename);
+  }
+
+  if (NmeasureTotal != catalog[0].Nmeasure) {
+    fprintf (stderr, "ERROR: catalog %s has an invalid Nmeasure\n", catalog[0].filename);
+  }
+
+  // MARKTIME("  match time %9.4f sec for %7lld measures, %6lld average\n", dtime, (long long) Nmeasure, (long long) Naverage);
+
+  catalog[0].sorted = TRUE;
+
+  FREE (measureDrop);
+  FREE (measureSeqRaw);
+  FREE (measureSeqOut);
+  FREE (measureAveRaw);
+  FREE (averageNmeas);
+  FREE (averageDmeas);
+  FREE (averageSeqOut);
+  FREE (averageRefOut);
+  FREE (measureAveOut);
+
+  return TRUE;
+}
Index: /branches/eam_branches/ipp-20120905/Ohana/src/delstar/src/delstar_client.c
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/delstar/src/delstar_client.c	(revision 34684)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/delstar/src/delstar_client.c	(revision 34685)
@@ -29,4 +29,7 @@
       break;
     case MODE_PHOTCODES:
+      // delete images with these photcodes
+      delete_photcodes_images (db, photcodesDrop, NphotcodesDrop);
+
       delete_photcoes (&db);
       break;
