Index: /branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/include/dvopsps.h
===================================================================
--- /branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/include/dvopsps.h	(revision 35063)
+++ /branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/include/dvopsps.h	(revision 35064)
@@ -6,4 +6,21 @@
 # define DVO_MAX_PATH 1024
 # define MAX_BUFFER 0x080000
+
+typedef struct {
+    int imageID;
+    unsigned int ippDetectID;
+    uint64_t detectID;
+    uint64_t ippObjID;
+    uint64_t objID;
+    unsigned int flags;
+    float zp;
+    float zpErr;
+    float airMass;
+    float expTime;
+    double ra;
+    double dec_;
+    float raErr;
+    float decErr;
+} Detections;
 
 /* global variables set in parameter file */
Index: /branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/DetectionOps.c
===================================================================
--- /branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/DetectionOps.c	(revision 35064)
+++ /branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/DetectionOps.c	(revision 35064)
@@ -0,0 +1,468 @@
+# include "dvopsps.h"
+
+# define GET_COLUMN(OUT,NAME,TYPE)					\
+  TYPE *OUT = gfits_get_bintable_column_data (&theader, &ftable, NAME, type, &Nrow, &Ncol); \
+  myAssert (!strcmp(type, #TYPE), "wrong column type");
+
+Detections *DetectionsLoad(char *filename) {
+
+  int i, Ncol;
+  off_t Nrow;
+  char type[16];
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  header.buffer = NULL;
+  matrix.buffer = NULL;
+  ftable.buffer = NULL;
+  theader.buffer = NULL;
+  Detections *detections = 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");
+    goto escape;
+  }
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset matrix\n");
+    goto escape;
+  }
+
+  ftable.header = &theader;
+
+  // load data for this header 
+  if (!gfits_load_header (f, &theader)) goto escape;
+
+  // read the fits table bytes
+  if (!gfits_fread_ftable_data (f, &ftable, FALSE)) goto escape;
+ 
+  // need to create and assign to flat-field correction
+  GET_COLUMN(imageID     , "imageID",     int);
+  GET_COLUMN(ippDetectID , "ippDetectID", int);
+  GET_COLUMN(detectID    , "detectID",    int64_t);
+  GET_COLUMN(ippObjID    , "ippObjID",    int64_t);
+  GET_COLUMN(objID       , "objID",       int64_t);
+  GET_COLUMN(flags       , "flags",       int);
+  GET_COLUMN(zp          , "zp",          float);
+  GET_COLUMN(zpErr       , "zpErr",       float);
+  GET_COLUMN(airMass     , "airMass",     float);
+  GET_COLUMN(expTime     , "expTime",     float);
+  GET_COLUMN(ra          , "ra",          double); // XXX signed vs unsigned?
+  GET_COLUMN(dec         , "dec",         double);
+  GET_COLUMN(raErr       , "raErr",       float);
+  GET_COLUMN(decErr      , "decErr",      float);
+  gfits_free_header (&theader);
+  gfits_free_table  (&ftable);
+
+  ALLOCATE (detections, Detections, Nrow);
+  for (i = 0; i < Nrow; i++) {
+    detections[i].imageID      = imageID[i];    
+    detections[i].ippDetectID  = ippDetectID[i];
+    detections[i].detectID     = detectID[i];   
+    detections[i].ippObjID     = ippObjID[i];   
+    detections[i].objID        = objID[i];      
+    detections[i].flags        = flags[i];      
+    detections[i].zp           = zp[i];         
+    detections[i].zpErr        = zpErr[i];      
+    detections[i].airMass      = airMass[i];    
+    detections[i].expTime      = expTime[i];    
+    detections[i].ra           = ra[i];         
+    detections[i].dec          = dec[i];        
+    detections[i].raErr        = raErr[i];      
+    detections[i].decErr       = decErr[i];     
+  }
+  fprintf (stderr, "loaded data for %lld detections\n", (long long) Nrow);
+
+  free (imageID    );
+  free (ippDetectID);
+  free (detectID   );
+  free (ippObjID   );
+  free (objID      );
+  free (flags      );
+  free (zp         );
+  free (zpErr      );
+  free (airMass    );
+  free (expTime    );
+  free (ra         );
+  free (dec        );
+  free (raErr      );
+  free (decErr     );
+
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  fclose (f);
+
+  return detections;
+
+escape:
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  gfits_free_header (&theader);
+  gfits_free_table  (&ftable);
+  if (detections) free (detections);
+
+  fclose (f);
+  return NULL;
+}
+
+// we are passed a Detections structure, write it to a FITS table (3 ext)
+int DetectionsSave(char *filename, Detections *detections) {
+
+  int i;
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  gfits_init_header (&header);
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+
+  FILE *f = fopen (filename, "w");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open image subset file for output %s\n", filename);
+    return FALSE;
+  }
+
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+
+    gfits_create_table_header (&theader, "BINTABLE", "DETECTIONS");
+
+    // XXX need to get the bzero values right
+    gfits_define_bintable_column (&theader, "J", "imageID",     NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "J", "ippDetectID", NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "K", "detectID",    NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "K", "ippObjID",    NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "K", "objID",       NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "J", "flags",       NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "zp",          NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "zpErr",       NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "airMass",     NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "expTime",     NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "D", "ra",          NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "D", "dec",         NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "raErr",       NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (&theader, "E", "decErr",      NULL, NULL, 1.0, 0.0);
+
+    // generate the output array that carries the data
+    gfits_create_table (&theader, &ftable);
+
+    // create intermediate storage arrays
+    float *dR        ; ALLOCATE (dR       ,  float, catalog->Nmeasure);
+    float *dD        ; ALLOCATE (dD       ,  float, catalog->Nmeasure);
+    float *M         ; ALLOCATE (M        ,  float, catalog->Nmeasure);
+    float *Mcal      ; ALLOCATE (Mcal     ,  float, catalog->Nmeasure);
+    float *dM        ; ALLOCATE (dM       ,  float, catalog->Nmeasure);
+    float *airmass   ; ALLOCATE (airmass  ,  float, catalog->Nmeasure);
+    float *Xccd      ; ALLOCATE (Xccd     ,  float, catalog->Nmeasure);
+    float *Yccd      ; ALLOCATE (Yccd     ,  float, catalog->Nmeasure);
+    float *dt        ; ALLOCATE (dt       ,  float, catalog->Nmeasure);
+    int   *t         ; ALLOCATE (t        ,  int  , catalog->Nmeasure);
+    int   *averef    ; ALLOCATE (averef   ,  int  , catalog->Nmeasure);
+    int   *imageID   ; ALLOCATE (imageID  ,  int  , catalog->Nmeasure);
+    int   *dbFlags   ; ALLOCATE (dbFlags  ,  int  , catalog->Nmeasure);
+    int   *photFlags ; ALLOCATE (photFlags,  int  , catalog->Nmeasure);
+    int   *catID     ; ALLOCATE (catID    ,  int  , catalog->Nmeasure);
+    short *photcode  ; ALLOCATE (photcode ,  short, catalog->Nmeasure);
+
+    // assign the storage arrays
+    MeasureTiny *measure = catalog->measure;
+    for (i = 0; i < catalog->Nmeasure; i++) {
+      imageID[i]     = detections[i].imageID     ;
+      ippDetectID[i] = detections[i].ippDetectID ;
+      detectID[i]    = detections[i].detectID    ;
+      ippObjID[i]    = detections[i].ippObjID    ;
+      objID[i]       = detections[i].objID       ;
+      flags[i]       = detections[i].flags       ;
+      zp[i]          = detections[i].zp          ;
+      zpErr[i]       = detections[i].zpErr       ;
+      airMass[i]     = detections[i].airMass     ;
+      expTime[i]     = detections[i].expTime     ;
+      ra[i]          = detections[i].ra          ;
+      dec[i]         = detections[i].dec         ;
+      raErr[i]       = detections[i].raErr       ;
+      decErr[i]      = detections[i].decErr      ;
+    }
+
+    // add the columns to the output array
+    gfits_set_bintable_column (&theader, &ftable, "RA_OFF",   	dR,        catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "DEC_OFF",  	dD,        catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "MAG_SYS",  	M,         catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "MAG_CAL",  	Mcal,      catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "MAG_ERR",  	dM,        catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "AIRMASS",  	airmass,   catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "X_CCD",    	Xccd,      catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "Y_CCD",    	Yccd,      catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "EXPTIME",  	dt,        catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "TIME",     	t,         catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "AVE_REF",  	averef,    catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "IMAGE_ID", 	imageID,   catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "DB_FLAGS", 	dbFlags,   catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "PHOT_FLAGS", photFlags, catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "CAT_ID",     catID,     catalog->Nmeasure);
+    gfits_set_bintable_column (&theader, &ftable, "PHOTCODE",   photcode,  catalog->Nmeasure);
+
+    free (dR      );
+    free (dD      );
+    free (M       );
+    free (Mcal    );
+    free (dM      );
+    free (airmass );
+    free (Xccd    );
+    free (Yccd    );
+    free (dt      );
+    free (t       );
+    free (averef  );
+    free (imageID );
+    free (dbFlags );
+    free (photFlags );
+    free (catID   );
+    free (photcode);
+
+    gfits_fwrite_Theader (f, &theader);
+    gfits_fwrite_table  (f, &ftable);
+    gfits_free_header (&theader);
+    gfits_free_table (&ftable);
+  return TRUE;
+}
+
+// merge a list of catalogs into a single Detections array set
+Detections *DetectionsMerge (Catalog *catalog, int Ncatalog) {
+
+  off_t i, j, k;
+
+  Detections *bcatalog = NULL;
+  ALLOCATE (bcatalog, Detections, 1);
+  
+  int Nmeas = 0;
+  int Naves = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Nmeas += catalog[i].Nmeasure;
+    Naves += catalog[i].Naverage;
+  }
+    
+  // XXX this prevents different catalogs from having different Nsecfilt values
+  int Nsecfilt = GetPhotcodeNsecfilt();
+
+  ALLOCATE (bcatalog[0].measure, MeasureTiny, Nmeas);
+  ALLOCATE (bcatalog[0].average, AverageTiny, Naves);
+  ALLOCATE (bcatalog[0].secfilt, SecFilt, Naves*Nsecfilt);
+
+  int Nm = 0;
+  int Na = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    if (!catalog[i].Naverage) continue;
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      bcatalog[0].average[Na] = catalog[i].averageT[j];
+      for (k = 0; k < Nsecfilt; k++) {
+	bcatalog[0].secfilt[Nsecfilt*Na + k] = catalog[i].secfilt[Nsecfilt*j + k];
+      }
+      Na++;
+      assert (Na <= Naves);
+    }
+    for (j = 0; j < catalog[i].Nmeasure; j++) {
+      bcatalog[0].measure[Nm] = catalog[i].measureT[j];
+      Nm++;
+      assert (Nm <= Nmeas);
+    }
+  }
+  bcatalog->Naverage = Na;
+  bcatalog->Nmeasure = Nm;
+  return bcatalog;
+}
+
+// distribute a bright catalog across separate catalogs
+CatalogSplitter *DetectionsSplitInit (int Nsecfilt) {
+
+  int i;
+
+  CatalogSplitter *catalogs = NULL;
+
+  ALLOCATE (catalogs, CatalogSplitter, 1);
+
+  // as we see new Detectionss, we will update maxID and extend this array
+  catalogs->maxID = 0;
+  ALLOCATE (catalogs->index, int, catalogs->maxID + 1);
+  for (i = 0; i <= catalogs->maxID; i++) catalogs->index[i] = -1;
+
+  catalogs->Nsecfilt = Nsecfilt;
+
+  catalogs->Ncatalog =  0;
+  catalogs->NCATALOG = 16;
+  catalogs->catalog = NULL;
+  ALLOCATE (catalogs->catalog, Catalog, catalogs->NCATALOG);
+
+  ALLOCATE (catalogs->catIDs,   int,   catalogs->NCATALOG);
+  ALLOCATE (catalogs->NAVERAGE, off_t, catalogs->NCATALOG);
+  ALLOCATE (catalogs->NMEASURE, off_t, catalogs->NCATALOG);
+
+  for (i = 0; i < catalogs->NCATALOG; i++) {
+    dvo_catalog_init (&catalogs->catalog[i], TRUE);
+    catalogs->catIDs[i] = 0;
+    catalogs->NAVERAGE[i] = 256;
+    catalogs->NMEASURE[i] = 256;
+    catalogs->catalog[i].Naverage = 0;
+    catalogs->catalog[i].Nmeasure = 0;
+    ALLOCATE (catalogs->catalog[i].averageT, AverageTiny, catalogs->NAVERAGE[i]);
+    ALLOCATE (catalogs->catalog[i].measureT, MeasureTiny, catalogs->NMEASURE[i]);
+    ALLOCATE (catalogs->catalog[i].secfilt,  SecFilt,     catalogs->NAVERAGE[i]*Nsecfilt);
+  }
+  return catalogs;
+}
+
+// distribute a bright catalog across separate catalogs
+int DetectionsSplitFree (CatalogSplitter *catalogs) {
+
+  // XXX don't free the catalogs : 
+  // for (i = 0; i < NCATALOG; i++) {
+  //   free (catalogs->catalog[i].averageT);
+  //   free (catalogs->catalog[i].measureT);
+  //   free (catalogs->catalog[i].secfilt);
+  // }
+  // free (catalogs->catalog);
+
+  free (catalogs->catIDs);
+  free (catalogs->NAVERAGE);
+  free (catalogs->NMEASURE);
+  free (catalogs->index);
+  free (catalogs);
+  return TRUE;
+}
+
+// distribute a bright catalog across separate catalogs
+int DetectionsSplit (CatalogSplitter *catalogs, Detections *bcatalog) {
+
+  int i;
+
+  int D_NCATALOG = 16;
+
+  int Nsecfilt = catalogs->Nsecfilt;
+
+  // find the max value of catID in this Detections
+  int catIDmax = 0;
+  for (i = 0; i < bcatalog->Naverage; i++) {
+    catIDmax = MAX(catIDmax, bcatalog->average[i].catID);
+  }
+  // XXX validate the measure ID range here
+    
+  int maxIDold = catalogs->maxID;
+  catalogs->maxID = MAX (maxIDold, catIDmax);
+    
+  // extend the index array and init
+  REALLOCATE (catalogs->index, int, catalogs->maxID + 1);
+  for (i = maxIDold + 1; i <= catalogs->maxID; i++) catalogs->index[i] = -1;
+
+  // identify the new catID values
+  for (i = 0; i < bcatalog->Naverage; i++) {
+    int catID = bcatalog->average[i].catID;
+    assert (catID > 0);
+    assert (catID < catalogs->maxID + 1);
+    int idx = catalogs->index[catID];
+    if (idx != -1) continue; // already have seen this one
+
+    // a new catID value
+    int Ncat = catalogs->Ncatalog; // the next available slot
+    catalogs->catIDs[Ncat] = catID;
+    assert (Ncat >= 0);
+    assert (Ncat < catalogs->NCATALOG);
+
+    catalogs->catalog[Ncat].Nsecfilt = Nsecfilt;
+    catalogs->catalog[Ncat].catID = catID;
+
+    catalogs->index[catID] = Ncat;
+    assert (catID > 0);
+    assert (catID < catalogs->maxID + 1);
+
+    catalogs->Ncatalog ++;
+
+    if (catalogs->Ncatalog >= catalogs->NCATALOG) {
+      catalogs->NCATALOG += D_NCATALOG;
+
+      // fprintf (stderr, "realloc catalogs->catalog: old: %llx  ", (long long) catalogs->catalog);
+      REALLOCATE (catalogs->catalog, Catalog, catalogs->NCATALOG);
+      // fprintf (stderr, "new: %llx  -  %llx\n", (long long) catalogs->catalog, (long long) (catalogs->catalog + sizeof(Catalog)*catalogs->NCATALOG));
+
+      // fprintf (stderr, "realloc catalogs->NAVERAGE: old: %llx  ", (long long) catalogs->NAVERAGE);
+      REALLOCATE (catalogs->NAVERAGE, off_t,  catalogs->NCATALOG);
+      // fprintf (stderr, "new: %llx  -  %llx\n", (long long) catalogs->NAVERAGE, (long long) (catalogs->NAVERAGE + sizeof(off_t)*catalogs->NCATALOG));
+
+      // fprintf (stderr, "realloc catalogs->NMEASURE: old: %llx  ", (long long) catalogs->NMEASURE);
+      REALLOCATE (catalogs->NMEASURE, off_t,  catalogs->NCATALOG);
+      // fprintf (stderr, "new: %llx  -  %llx\n", (long long) catalogs->NMEASURE, (long long) (catalogs->NMEASURE + sizeof(off_t)*catalogs->NCATALOG));
+
+      REALLOCATE (catalogs->catIDs,   int,   catalogs->NCATALOG);
+
+      int j;
+      for (j = catalogs->NCATALOG - D_NCATALOG; j < catalogs->NCATALOG; j++) {
+	dvo_catalog_init (&catalogs->catalog[j], TRUE);
+	catalogs->catIDs[j] = 0;
+	catalogs->NAVERAGE[j] = 256;
+	catalogs->NMEASURE[j] = 256;
+	catalogs->catalog[j].Naverage = 0;
+	catalogs->catalog[j].Nmeasure = 0;
+	ALLOCATE (catalogs->catalog[j].averageT, AverageTiny, catalogs->NAVERAGE[j]);
+	ALLOCATE (catalogs->catalog[j].measureT, MeasureTiny, catalogs->NMEASURE[j]);
+	ALLOCATE (catalogs->catalog[j].secfilt,  SecFilt,     catalogs->NAVERAGE[j]*Nsecfilt);
+      }
+      D_NCATALOG = MAX(2000, 2*D_NCATALOG);
+    }
+  }
+
+  // each bcatalog (from each host) has a different set of catID ranges
+  // they also (probably) have contiguous ranges.  But, it is a bit tricky to be sure I
+  // can use that info, so perhaps ignore it
+
+  // assign the averages to the corresponding catalog
+  for (i = 0; i < bcatalog->Naverage; i++) {
+    int ID = bcatalog->average[i].catID;
+    int Nc = catalogs->index[ID];
+    assert (Nc > -1);
+    assert (Nc < catalogs->NCATALOG);
+
+    int Na = catalogs->catalog[Nc].Naverage;
+    catalogs->catalog[Nc].averageT[Na] = bcatalog->average[i];
+
+    // secfilt entries are grouped in blocks for each average
+    int k;
+    for (k = 0; k < Nsecfilt; k++) {
+      catalogs->catalog[Nc].secfilt[Na*Nsecfilt + k] = bcatalog->secfilt[i*Nsecfilt + k];
+    }      
+
+    catalogs->catalog[Nc].Naverage ++;
+    if (catalogs->catalog[Nc].Naverage >= catalogs->NAVERAGE[Nc]) {
+      catalogs->NAVERAGE[Nc] += MAX(catalogs->NAVERAGE[Nc], 1024);
+      REALLOCATE (catalogs->catalog[Nc].averageT, AverageTiny, catalogs->NAVERAGE[Nc]);
+      REALLOCATE (catalogs->catalog[Nc].secfilt,  SecFilt,     catalogs->NAVERAGE[Nc]*Nsecfilt);
+    }	       
+  }
+
+  // assign the measures to the corresponding catalog
+  // XXX what about averef and related links?  Do I need them?
+  for (i = 0; i < bcatalog->Nmeasure; i++) {
+    int ID = bcatalog->measure[i].catID;
+    int Nc = catalogs->index[ID];
+    assert (Nc > -1);
+    assert (Nc < catalogs->NCATALOG);
+    int Na = catalogs->catalog[Nc].Nmeasure;
+    catalogs->catalog[Nc].measureT[Na] = bcatalog->measure[i];
+    catalogs->catalog[Nc].Nmeasure ++;
+    if (catalogs->catalog[Nc].Nmeasure >= catalogs->NMEASURE[Nc]) {
+      catalogs->NMEASURE[Nc] += MAX(catalogs->NMEASURE[Nc], 4096);
+      REALLOCATE (catalogs->catalog[Nc].measureT, MeasureTiny, catalogs->NMEASURE[Nc]);
+    }	       
+  }
+
+  return TRUE;
+}
Index: /branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/insert_detections_dvopsps.c
===================================================================
--- /branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/insert_detections_dvopsps.c	(revision 35063)
+++ /branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/insert_detections_dvopsps.c	(revision 35064)
@@ -67,5 +67,10 @@
 
     // NOTE: this is where the real action happens
-    insert_detections_dvopsps_catalog (&catalog, mysqlReal);
+    if (1) {
+	insert_detections_dvopsps_catalog (&catalog, mysqlReal);
+    } else {
+	// NOTE: this is where the real action happens
+	save_detections_dvopsps_catalog (&catalog, "???");
+    }
 
     // NOTE : unlike setastrom or relphot, this program is read-only wrt dvo
@@ -153,4 +158,20 @@
   }
 
+# if (0)
+  for (i = 0; i < table->Nhosts; i++) {
+    while ((detections = RemoteDetectionsLoad (table->hosts[i].results)) == NULL) {
+      // failed to get the data from this host.  This can happen for various reasons.  Give the user a chance to try again...
+      fprintf (stderr, "failed to read data from %s\n", table->hosts[i].hostname);
+      fprintf (stderr, "you may run the command manually\n");
+    }
+    free (table->hosts[i].results);
+    table->hosts[i].results = NULL;
+    
+    RemoveDetectionsInsert (detections);
+
+    free (detections);
+  }
+# endif
+
   return (TRUE);
 }      
