Index: /trunk/Ohana/src/libdvo/Makefile
===================================================================
--- /trunk/Ohana/src/libdvo/Makefile	(revision 26395)
+++ /trunk/Ohana/src/libdvo/Makefile	(revision 26396)
@@ -35,5 +35,5 @@
 $(DESTINC)/ps1_ref_defs.h
 
-INCS = $(DEFS) $(DESTINC)/dvo.h $(DESTINC)/autocode.h
+INCS = $(DEFS) $(DESTINC)/dvo.h $(DESTINC)/autocode.h $(DESTINC)/dvo_util.h
 
 OBJS = \
@@ -72,5 +72,6 @@
 $(SRC)/skyregion_gsc.$(ARCH).o    \
 $(SRC)/skyregion_ops.$(ARCH).o \
-$(SRC)/cmf-ps1-v1-alt.$(ARCH).o
+$(SRC)/cmf-ps1-v1-alt.$(ARCH).o \
+$(SRC)/dvo_util.$(ARCH).o
 
 # $(SRC)/dvo_convert_panstarrs.$(ARCH).o \
Index: /trunk/Ohana/src/libdvo/include/dvo_util.h
===================================================================
--- /trunk/Ohana/src/libdvo/include/dvo_util.h	(revision 26396)
+++ /trunk/Ohana/src/libdvo/include/dvo_util.h	(revision 26396)
@@ -0,0 +1,72 @@
+#ifndef DVO_UTIL_H
+#define DVO_UTIL_H
+
+// dvo_util.h
+// Declares a set of structures and functions useful for doing read only access
+// to a dvo database
+
+#include <dvo.h>
+
+typedef struct {
+    char        gscfile[256];
+    char        catdir[256];
+    char        catmode[256];
+    char        catformat[256];
+    char        photcodeFile[256];
+    char        skyTableFile[256];
+    int         skyDepth;
+    FITS_DB     imageDB;
+    Image       *images;
+    int         nImages;
+    SkyTable    *skyTable;
+#if (DVO_UTIL_READ_CAMERA_CONFIG)
+    char        cameraConfig[256];
+    int         *ccdNum;
+    int         nCCD;
+#endif
+} dvoConfig;
+
+// This structure needs to be fleshed out
+typedef struct {
+    int         valid;
+    int         objID;
+    int         catID;
+    int         detID;
+    uint64_t    pspsObjID;
+    uint64_t    pspsDetID;
+} dvoDetection;
+
+// dvoConfigRead
+// Prepares a program for reading from a dvo database
+// 1. reads configuration files and program's argument list to configure dvo parameters are removed.
+//       e.g. -D CATDIR mycatdir
+// 2. Loads photcode file
+// 3. Saves the resulting data in a structure that is used for calls to other utility functions
+dvoConfig *dvoConfigRead(int *argc, char **argv);
+
+// free's memory associated with the dvoConfig structure
+void dvoConfigFree(dvoConfig *dvoConfig);
+
+// Loads the images database. Saves the results in dvoConfig structure.
+int dvoLoadImages(dvoConfig *dvoConfig);
+
+// finds the dvo Image corresponding to the given external id (and sourceid)
+// There is no need to release memory pointed to by return value. 
+// It will be freed when dvoConfigFree() is invoked.
+Image *dvoImageByExternID(dvoConfig *dvoConfig, int sourceID, int externID);
+
+// Loads the sky table for the database.
+SkyTable *dvoLoadSkyTable(dvoConfig *dvoConfig);
+
+// find a list of catalogs touched by the given external id
+// Use SkyListFree() to free memory pointed to by return value
+SkyList *dvoSkyListByExternID(dvoConfig *dvoConfig, int sourceID, int externID, int *pDvoImageID);
+
+// return a list of detectsions from a particular image id
+// Use dvoFree() to free the memory pointed to by results
+int dvoGetDetections(SkyList *skylist, int imageID, dvoDetection **results, int *pMaxDetID);
+
+// free memory returned by various dvo util functions
+void dvoFree(void *ptr);
+
+#endif // DVO_UTIL_H
Index: /trunk/Ohana/src/libdvo/src/dvo_util.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_util.c	(revision 26396)
+++ /trunk/Ohana/src/libdvo/src/dvo_util.c	(revision 26396)
@@ -0,0 +1,276 @@
+// dvo_util.c
+// This file contains a set of functions that provide simple read-only access to a dvo database
+//
+#include <dvo_util.h>
+
+void dvoFree(void *ptr)
+{
+    if (ptr) {
+        FREE(ptr);
+    }
+}
+
+dvoConfig * dvoConfigAlloc()
+{
+    dvoConfig *config;
+
+    ALLOCATE(config, dvoConfig, 1);
+
+    memset(config, 0, sizeof(dvoConfig));
+}
+
+void dvoConfigFree(dvoConfig *dvoConfig)
+{
+    if (dvoConfig) {
+        if (dvoConfig->skyTable) {
+            SkyTableFree(dvoConfig->skyTable);
+        }
+        if (dvoConfig->images) {
+            gfits_db_free(&dvoConfig->imageDB);
+        }
+        FREE(dvoConfig);
+    }
+}
+
+dvoConfig *dvoConfigRead(int *argc, char **argv)
+{
+    dvoConfig *dvoConfig = dvoConfigAlloc();
+    char MasterPhotcodeFile[256];
+
+    char *file = SelectConfigFile(argc, argv, "ptolemy");
+    char *configData = LoadConfigFile(file);
+    if (!configData) {
+        fprintf(stderr, "ERROR: can't find configuration file %s\n", file);
+        if (file) {
+            FREE(file);
+        }
+        exit(3);
+    }
+    FREE (file);
+    file = NULL;
+
+    ScanConfig (configData, "GSCFILE",         "%s", 0, dvoConfig->gscfile);
+    ScanConfig (configData, "CATDIR",          "%s", 0, dvoConfig->catdir);
+    ScanConfig (configData, "CATMODE",         "%s",  0, dvoConfig->catmode);
+    ScanConfig (configData, "CATFORMAT",       "%s",  0, dvoConfig->catformat);
+    ScanConfig (configData, "PHOTCODE_FILE",   "%s",  0, MasterPhotcodeFile);
+    if (!ScanConfig (configData, "SKY_DEPTH",    "%d",  0, &dvoConfig->skyDepth)) {
+        dvoConfig->skyDepth = 2;
+    }
+    if (!ScanConfig (configData, "SKY_TABLE",    "%s",  0, dvoConfig->skyTableFile)) {
+        dvoConfig->skyTableFile[0] = 0;
+    }
+
+#ifdef notdef
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+#endif
+
+    sprintf (dvoConfig->photcodeFile, "%s/Photcodes.dat", dvoConfig->catdir);
+    if (!LoadPhotcodes (dvoConfig->photcodeFile, MasterPhotcodeFile, FALSE)) {
+        fprintf (stderr, "error loading photcode table %s or master file %s\n",
+            dvoConfig->photcodeFile, MasterPhotcodeFile);
+        exit (1);
+    }
+    SetZeroPoint (25.0);
+
+#ifdef READ_CAMERA_CONFIG
+    if (!ScanConfig (configData, "CAMERA_CONFIG", "%s", 0, dvoConfig->cameraConfig)) {
+        fprintf (stderr, "can't find CAMERA_CONFIG in configuration\n");
+        exit (3);
+    }
+    char * cameraConfigData = LoadConfigFile(dvoConfig->cameraConfig);
+    if (!cameraConfigData) {
+        fprintf (stderr, "failed to load %s\n", dvoConfig->cameraConfig);
+        exit (3);
+    }
+
+    ScanConfig (cameraConfigData, "NCCD", "%d", 1, &dvoConfig->nCCD);
+#endif
+
+    return (dvoConfig);
+}
+
+int dvoLoadImages(dvoConfig *dvoConfig)
+{
+    if (dvoConfig->images) {
+        return TRUE;
+    }
+
+    char *catdir, filename[256];
+  
+    sprintf (filename, "%s/Images.dat", dvoConfig->catdir);
+
+    gfits_db_init (&dvoConfig->imageDB);
+    dvoConfig->imageDB.lockstate = LCK_SOFT;
+    dvoConfig->imageDB.timeout   = 120.0;
+
+    if (!gfits_db_lock (&dvoConfig->imageDB, filename)) {
+        fprintf (stderr, "error opening image catalog %s (1)\n", filename);
+        return (FALSE);
+    }
+
+    if (dvoConfig->imageDB.dbstate == LCK_EMPTY) {
+        fprintf (stderr, "note: image catalog is empty\n");
+        ALLOCATE (dvoConfig->images, Image, 1);
+        dvoConfig->nImages = 1;
+        return (TRUE);
+    }
+
+    int status = dvo_image_load (&dvoConfig->imageDB, TRUE, FALSE);
+    gfits_db_close (&dvoConfig->imageDB);
+
+    if (!status) {
+        fprintf (stderr, "problem loading image database table\n");
+        return (FALSE);
+    }
+
+    dvoConfig->images = gfits_table_get_Image (&dvoConfig->imageDB.ftable, &dvoConfig->nImages, &dvoConfig->imageDB.swapped);
+    if (!dvoConfig->images) {
+        fprintf (stderr, "problem loading images\n");
+        return (FALSE);
+    }
+
+    return (TRUE);
+}
+Image *dvoImageByExternID(dvoConfig *dvoConfig, int sourceID, int externID)
+{
+    Image *images;
+    int Nimage;
+    int i;
+    
+    if (!dvoLoadImages(dvoConfig)) return NULL;
+
+    for (i=0; i<dvoConfig->nImages; i++) {
+        Image *image = dvoConfig->images + i;
+        if ((image->externID == externID) && (image->sourceID == sourceID)) {
+            BuildChipMatch(dvoConfig->images, dvoConfig->nImages);
+            if (FindMosaicForImage(dvoConfig->images, dvoConfig->nImages, i)) {
+                return image;
+            } else {
+                fprintf(stderr, "FindMosaicForImage failed\n");
+                return NULL;
+            }
+        }
+    }
+    fprintf(stderr, "can't find image for %d %d\n", sourceID, externID);
+    return NULL;
+}
+
+SkyTable *dvoLoadSkyTable(dvoConfig *dvoConfig)
+{
+    if (!dvoConfig->skyTable) {
+        char *skyfile = "";
+        dvoConfig->skyTable = SkyTableLoadOptimal(dvoConfig->catdir, skyfile, dvoConfig->gscfile,
+                                                    FALSE, dvoConfig->skyDepth, 0);
+    }
+
+    if (dvoConfig->skyTable == NULL) {
+        fprintf(stderr, "failed to load SkyTable\n");
+        return NULL;
+    }
+
+    SkyTableSetFilenames(dvoConfig->skyTable, dvoConfig->catdir, "cpt");
+
+    return dvoConfig->skyTable;
+}
+
+SkyList *dvoSkyListByExternID(dvoConfig *dvoConfig, int sourceID, int externID, int *pDvoImageID)
+{
+    Image *image = dvoImageByExternID(dvoConfig, sourceID, externID);
+    if (image == NULL) {
+        // fprintf(stderr, "can't find image for %d %d\n", sourceID, externID);
+        return NULL;
+    }
+
+    if (dvoLoadSkyTable(dvoConfig) == NULL) {
+        fprintf(stderr, "failed to load Sky table\n");
+        return NULL;
+    }
+    SkyList *skylist = SkyListByImage(dvoConfig->skyTable, -1, image);
+    if (!skylist->Nregions) {
+        fprintf(stderr, "failed to find SkyList for image  %d %d\n", sourceID, externID);
+        return NULL;
+    }
+
+    *pDvoImageID = image->imageID;
+
+    return skylist;
+}
+
+int dvoGetDetections(SkyList *skylist, int imageID, dvoDetection **results, int *pMaxDetID)
+{
+  int QUIET = 0;
+  int FULL_OUTPUT = 0;
+  int GetMeasures = 1;
+  int SaveVectors = 0;
+  int reg;
+  int Ndetect = 0;
+
+  int detectionsArrayLength = 1000;
+  dvoDetection *detections;
+  ALLOCATE (detections, dvoDetection, detectionsArrayLength);
+  *pMaxDetID = -1;
+  for (reg=0; reg< skylist->Nregions; reg++) {
+      /* lock, load, unlock catalog */
+      Catalog catalog;
+      catalog.filename = skylist->filename[reg];
+      catalog.catflags = GetMeasures ? LOAD_AVES | LOAD_MEAS | LOAD_SECF : LOAD_AVES | LOAD_SECF;
+      catalog.Nsecfilt = 0;
+
+      // an error exit status here is a significant error
+      if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+          fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+          exit (2);
+      }
+      dvo_catalog_unlock (&catalog);
+
+      int Nstars = catalog.Naverage;
+      int Nmeasure = catalog.Nmeasure;
+
+      int i;
+      for (i=0; i< Nmeasure; i++) {
+        Measure *m = catalog.measure + i;
+        if (m->imageID != imageID) {
+            continue;
+        }
+        Average *a = catalog.average + m->averef;
+        
+        dvoDetection *det = detections + Ndetect;
+
+        det->valid     = 1;
+        det->objID     = a->objID;
+        det->catID     = m->catID;
+        det->detID     = m->detID;
+        det->pspsObjID = a->extID;
+        det->pspsDetID = m->extID;
+        
+        if (det->detID > *pMaxDetID) {
+            *pMaxDetID = det->detID;
+        }
+
+        Ndetect++;
+        CHECK_REALLOCATE(detections, dvoDetection, detectionsArrayLength, Ndetect, 1000);
+      }
+
+      dvo_catalog_free (&catalog);
+  }
+  if (Ndetect) {
+      dvoDetection *sorted;
+      ALLOCATE(sorted, dvoDetection, *pMaxDetID + 1);
+
+      memset(sorted, 0, sizeof(dvoDetection) * *pMaxDetID);
+      int i;
+      for (i = 0; i < Ndetect; i++) {
+           sorted[detections[i].detID] = detections[i];
+      }
+      *results = sorted;
+  } else {
+      *results = NULL;
+  }
+
+  FREE(detections);
+
+  return (Ndetect);
+
+}
