Index: trunk/pstamp/src/Makefile.am
===================================================================
--- trunk/pstamp/src/Makefile.am	(revision 18637)
+++ trunk/pstamp/src/Makefile.am	(revision 18638)
@@ -1,3 +1,3 @@
-bin_PROGRAMS = ppstamp pstamprequest pstampparse pstampdump
+bin_PROGRAMS = ppstamp pstamprequest locateimages pstampdump
 
 noinst_HEADERS = \
@@ -7,5 +7,5 @@
 ppstamp_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) 
 pstamprequest_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) 
-pstampparse_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS)
+locateimages_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS)
 pstampdump_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS)
 
@@ -14,5 +14,5 @@
 ppstamp_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) 
 pstamprequest_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) 
-pstampparse_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) 
+locateimages_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) 
 pstampdump_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS)
 
@@ -35,6 +35,6 @@
 	ppstampOptions.c
 
-pstampparse_SOURCES = \
-	pstampparse.c
+locateimages_SOURCES = \
+	locateimages.c
 
 pstampdump_SOURCES = \
Index: trunk/pstamp/src/locateimages.c
===================================================================
--- trunk/pstamp/src/locateimages.c	(revision 18638)
+++ trunk/pstamp/src/locateimages.c	(revision 18638)
@@ -0,0 +1,752 @@
+// pstampparse ---> imagetool but this program is going to be
+// deleted so we'll just leave the external name alone
+
+#include <pslib.h>
+#include <psmodules.h>
+#include <string.h>
+#include <strings.h>
+#include <ohana.h>
+
+typedef enum {
+    UNKNOWN_IMAGE = -1,
+    RAW_IMAGE,
+    CHIP_IMAGE,
+    WARP_IMAGE,
+    STACK_IMAGE,
+    DIFF_IMAGE
+} itImageType;
+
+typedef enum {
+    BY_ID,
+    BY_EXP,
+    BY_COORD,
+    UNKNOWN_LOOKUP_TYPE
+} itLookupType;
+
+typedef struct {
+    pmConfig        *config;
+    itLookupType    lookupType;
+    itImageType     imageType;
+    psString        id;
+    psString        class_id;
+    bool            verbose;
+    bool            simple;
+    double          mjd_min;
+    double          mjd_max;
+    double          ra;
+    double          dec;
+    psString        filter;
+} itOptions;
+
+
+static void usage()
+{
+    // XXX: fill this out
+    psErrorStackPrint(stderr, "argument error");
+    exit(1);
+}
+
+static itImageType parseImageType(psString type)
+{
+    itImageType itype;
+
+    if (type == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "NULL image type");
+        itype = UNKNOWN_IMAGE;
+        return itype;
+    }
+
+    if (strcmp(type, "raw") == 0) {
+        itype = RAW_IMAGE;
+    } else if (strcmp(type, "chip") == 0) {
+        itype = CHIP_IMAGE;
+    } else if (strcmp(type, "warp") == 0) {
+        itype = WARP_IMAGE;
+    } else if (strcmp(type, "diff") == 0) {
+        itype = DIFF_IMAGE;
+    } else if (strcmp(type, "stack") == 0) {
+        itype = STACK_IMAGE;
+    } else {
+        psError(PS_ERR_UNKNOWN, true, "unknown image type %s", type);
+        itype = UNKNOWN_LOOKUP_TYPE;
+    }
+
+    return itype;
+}
+static void getParams(itOptions *options, int argnum, int *pArgc, char *argv[])
+{
+    if (*pArgc < 3) {
+        fprintf(stderr, "values required for type and id\n");
+        usage();
+    }
+
+    options->imageType = parseImageType(argv[argnum]);
+    psArgumentRemove(argnum, pArgc, argv);
+    options->id = argv[argnum];
+    psArgumentRemove(argnum, pArgc, argv);
+
+    if ((options->imageType == RAW_IMAGE) || (options->imageType == CHIP_IMAGE)) {
+        if (*pArgc < 2) {
+            fprintf(stderr, "value required for class_id\n");
+            usage();
+        }
+        options->class_id = argv[argnum];
+    
+        psArgumentRemove(argnum, pArgc, argv);
+    }
+}
+
+static itOptions *parseArguments(int argc, char *argv[])
+{
+    int argnum;
+    itOptions *options = psAlloc(sizeof(itOptions));
+    bool gotLookupType = false;
+    int gotTime       = 0;
+
+    memset(options, 0, sizeof(*options));
+
+    options->config = pmConfigRead(&argc, argv, NULL);
+    if (!options->config) {
+        psError(PS_ERR_UNKNOWN, false, "cannot find site file");
+        psFree(options);
+        return NULL;
+    }
+    if ((argnum = psArgumentGet(argc, argv, "-mjd_min"))) {
+        psArgumentRemove(argnum, &argc, argv);
+        if ((argnum) == argc) {
+            psError(PS_ERR_UNKNOWN, true, "value required for -mjd_min");
+            usage();
+        }
+        gotTime = 1;
+        options->mjd_min = atof(argv[argnum]);
+        psArgumentRemove(argnum, &argc, argv);
+    }
+    if ((argnum = psArgumentGet(argc, argv, "-mjd_max"))) {
+        psArgumentRemove(argnum, &argc, argv);
+        if ((argnum) == argc) {
+            psError(PS_ERR_UNKNOWN, true, "value required for -mjd_max");
+            usage();
+        }
+        gotTime++;
+        options->mjd_max = atof(argv[argnum]);
+        psArgumentRemove(argnum, &argc, argv);
+    }
+    if ((argnum = psArgumentGet(argc, argv, "-byid"))) {
+        options->lookupType = BY_ID;
+        psArgumentRemove(argnum, &argc, argv);
+        getParams(options, argnum, &argc, argv);
+        gotLookupType = true;
+    }
+    if ((argnum = psArgumentGet(argc, argv, "-byexp"))) {
+        if (gotLookupType) {
+            psError(PS_ERR_UNKNOWN, false, "only one of -byid, -byexp, and -bycoord may be used\n");
+            usage();
+        }
+        gotLookupType = true;
+        options->lookupType = BY_EXP;
+        psArgumentRemove(argnum, &argc, argv);
+        getParams(options, argnum, &argc, argv);
+    }
+    if ((argnum = psArgumentGet(argc, argv, "-bycoord"))) {
+        if (gotLookupType) {
+            psError(PS_ERR_UNKNOWN, false, "only one of -byid, -byexp, and -bycoord may be used\n");
+            usage();
+        }
+        if (gotTime < 2) {
+            psError(PS_ERR_UNKNOWN, true, "-mjd_min and -mjd_max required for -bycoord");
+            usage();
+        } else if (options->mjd_min != options->mjd_max) {
+            psError(PS_ERR_UNKNOWN, true, "mjd_max ignored for now");
+        }
+        psArgumentRemove(argnum, &argc, argv);
+        if (argc < 5) {
+            psError(PS_ERR_UNKNOWN, true, "image_type, ra, and dec are required for bycoord");
+            usage();
+        }
+        gotLookupType = true;
+        options->lookupType = BY_COORD;
+
+        options->imageType = parseImageType(argv[argnum]);
+        psArgumentRemove(argnum, &argc, argv);
+
+        options->ra = atof(argv[argnum]);
+        psArgumentRemove(argnum, &argc, argv);
+
+        options->dec = atof(argv[argnum]);
+        psArgumentRemove(argnum, &argc, argv);
+        // XXX TODO: handle class_id
+        switch (options->imageType) {
+        case RAW_IMAGE:
+        case CHIP_IMAGE:
+            if (argc < 2) {
+                psError(PS_ERR_UNKNOWN, true, "class_id required for bycoord raw|chip");
+                usage();
+            }
+            options->class_id = argv[argnum];
+            psArgumentRemove(argnum, &argc, argv);
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (!gotLookupType) {
+        psError(PS_ERR_BAD_PARAMETER_NULL , true, "one of -byid, -byexp, or -bycoord must be supplied\n");
+        usage();
+    }
+
+    if ((argnum = psArgumentGet(argc, argv, "-verbose"))) {
+        options->verbose = true;
+        psArgumentRemove(argnum, &argc, argv);
+    }
+
+    if ((argnum = psArgumentGet(argc, argv, "-simple"))) {
+        options->simple = true;
+        psArgumentRemove(argnum, &argc, argv);
+    }
+
+    // XXX: Arguments to add for bycoord searches FILTER, DATE_BEGIN, DATE_END
+
+    if (argc > 1) {
+        fprintf(stderr, "unknown arguments supplied: ");
+
+        fprintf(stderr, "%s", argv[1]);
+        for (int i=2; i<argc; i++) {
+            fprintf(stderr, ", %s", argv[i]);
+        }
+        fprintf(stderr, "\n");
+        usage();
+    }
+
+    return options;
+}
+
+static bool setupDB(itOptions *options)
+{
+    // XXX: need to select the database name based on the project name specified in the input
+
+    options->config->database = psMemIncrRefCounter(pmConfigDB(options->config));
+
+    if (!options->config->database) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        return false;
+    }
+
+    return true;
+}
+
+
+// return a string with the contents of a unsigned 64 bit value
+static psString idToStr(psU64 id)
+{
+    psString idstr = psStringAlloc(64);
+    sprintf(idstr, "%" PRIu64, id);
+
+    return idstr;
+}
+
+
+// runQuery
+//
+// run the given database query and return an array of strings containing the values of target
+// the type for the values returned by the query is either a string or psU64.
+
+static psArray *runQuery(itOptions *options, psString query, psString target,
+                psString key1, psString key2, bool targetIsString, psArray *output)
+{
+    // query string must be in the form
+    //  "SELECT %s from sometable WHERE somecolumn = %s and someothercolumn = %s
+    //        target                                key1                       key2
+    //
+    //  or if key2 is null
+    //
+    //  "SELECT %s from sometable WHERE somecolumn = %s"
+    //         target                               key1
+    //
+    //
+    // we return an array containing strings for the values
+
+    if (!p_psDBRunQuery(options->config->database, query, target, key1, key2)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return NULL;
+    }
+
+    psArray *queryOutput = p_psDBFetchResult(options->config->database);
+    if (!queryOutput) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return NULL;
+    }
+
+    psU64 len = psArrayLength(queryOutput);
+    if (!len) {
+        psTrace("pstampparse", PS_LOG_INFO, "no rows found");
+        psFree(queryOutput);
+        return NULL;
+    }
+
+    if (output == NULL) {
+        output = psArrayAlloc(0);
+    }
+
+    for (int i=0; i < len; i++) {
+        psMetadata *row = queryOutput->data[i];
+        if (targetIsString) {
+            psString val = psMetadataLookupStr(NULL, row, target);
+            if (val != 0) {
+                output = psArrayAdd(output, len - i, val);
+            }
+        } else {
+            psU64 val = psMetadataLookupU64(NULL, row, target);
+            if (val != 0) {
+                output = psArrayAdd(output, len - i, idToStr(val));
+            }
+        }
+    }
+
+    psFree(queryOutput);
+
+    return output;
+}
+
+static psArray *findURIs(itOptions *options, psString table, psString id_type, psString id, psString class_id)
+{
+    psString query = NULL;
+
+    psStringAppend(&query, "SELECT %%s from %s WHERE %s = %%s", table, id_type);
+    // append class_id unless it is set to the special value "null"
+    if (class_id && strcmp("null", class_id)) {
+        psStringAppend(&query, "%s", " and class_id = '%s'" );
+    }
+
+    psArray *results = runQuery(options, query, "uri", id, class_id, true, NULL);
+
+    psFree(query);
+
+    return results;
+}
+
+// given an array of strings return the last entry
+
+static psString lastID(psArray *array)
+{
+    if (array == NULL) {
+        return 0;
+    }
+    psU64 len = psArrayLength(array);
+
+    psString id = NULL;
+    if (len > 0) {
+        id = (psString) array->data[len-1];
+        psMemIncrRefCounter(id);
+    }
+
+    // XXX: Hmm if we're doing lastID(runQuery(....)) we need to free the
+    // result array, however freeing this in here seems like a potentially dangerous API
+    // but hey we're a static function
+
+    psFree(array);
+
+    return id;
+}
+
+
+
+#define chipIDForExp(_opt, _id) \
+            lastID(runQuery((_opt), "SELECT %s from chipRun  WHERE exp_id = %s", "chip_id", \
+                            (_id), NULL, false, NULL))
+
+#define camIDForChip(_opt, _id) \
+    lastID(runQuery((_opt), "SELECT %s from camRun  WHERE chip_id = %s", "cam_id", \
+                        (_id), NULL, false, NULL))
+
+#define fakeIDForCam(_opt, _id) \
+        lastID(runQuery((_opt), "SELECT %s from fakeRun  WHERE cam_id = %s", "fake_id", \
+                            (_id), NULL, false, NULL))
+
+#define warpIDForFake(_opt, _id) \
+        lastID(runQuery((_opt), "SELECT %s from warpRun  WHERE fake_id = %s", "warp_id", \
+                            (_id), NULL, false, NULL))
+
+
+
+static psArray *findChipURIs(itOptions *options, psString exp_id, psString class_id)
+{
+    psString chip_id = chipIDForExp(options, exp_id);
+
+    if (chip_id == NULL)
+        return NULL;
+
+    psString query = NULL;
+    psStringAppend(&query, "SELECT %s from chipProcessedImfile WHERE chip_id = %s", "%s", "%s");
+    if (class_id && (strcmp(class_id, "null") != 0)) {
+        psStringAppend(&query, " AND class_id = '%s'", "%s");
+    }
+
+    psArray *chip_files = runQuery(options, query,
+                        "uri", chip_id, class_id, true, NULL);
+    psFree(query);
+    psFree(chip_id);
+
+    return chip_files;
+}
+
+static psArray *findWarpURIs(itOptions *options, psString exp_id)
+{
+    psString chip_id = chipIDForExp(options, exp_id);
+
+    if (chip_id == NULL)
+        return NULL;
+
+    psString cam_id = camIDForChip(options, chip_id);
+    if (cam_id == NULL)
+        return NULL;
+
+    psString fake_id = fakeIDForCam(options, cam_id);
+    if (fake_id == NULL)
+        return NULL;
+
+    psString warp_id = warpIDForFake(options, fake_id);
+    if (warp_id == NULL)
+        return NULL;
+
+    psArray *warp_files = runQuery(options,
+                        "SELECT %s from warpSkyfile WHERE warp_id = %s"
+                        " AND uri IS NOT NULL and (fault = 0 or fault is NULL)",
+                           "uri",   warp_id, NULL, true, NULL);
+
+    psFree(warp_id);
+    psFree(fake_id);
+    psFree(cam_id);
+    psFree(chip_id);
+
+    return warp_files;
+}
+
+static psArray *findStackURIs(itOptions *options, psString exp_id)
+{
+    psString chip_id = chipIDForExp(options, exp_id);
+
+    if (chip_id == NULL)
+        return NULL;
+
+    psString cam_id = camIDForChip(options, chip_id);
+    if (cam_id == NULL)
+        return NULL;
+
+    psString fake_id = fakeIDForCam(options, cam_id);
+    if (fake_id == NULL)
+        return NULL;
+
+    psString warp_id = warpIDForFake(options, fake_id);
+    if (warp_id == NULL)
+        return NULL;
+
+    psArray *stackIDs = runQuery(options, "SELECT %s FROM stackInputSkyfile WHERE warp_id = %s",
+                            "stack_id", warp_id, NULL, false, NULL);
+
+    psFree(warp_id);
+    psFree(fake_id);
+    psFree(cam_id);
+    psFree(chip_id);
+
+    if (stackIDs == NULL) {
+        return NULL;
+    }
+
+    psArray *uris = psArrayAlloc(0);
+
+    psU64 len = psArrayLength(stackIDs);
+
+    // loop over the stack's for this exposure and add the images
+    for (int i = 0; i < len ; i++ ) {
+        psString stack_id = (psString) stackIDs->data[i];
+        uris = runQuery(options, "SELECT %s FROM stackSumSkyfile where stack_id = %s",
+                    "uri", stack_id, NULL, true, uris);
+    }
+    psFree(stackIDs);
+
+    return uris;
+}
+
+static psArray *findDiffURIs(itOptions *options, psString exp_id)
+{
+    psString chip_id = chipIDForExp(options, exp_id);
+
+    if (chip_id == NULL)
+        return NULL;
+
+    psString cam_id = camIDForChip(options, chip_id);
+    if (cam_id == NULL)
+        return NULL;
+
+    psString fake_id = fakeIDForCam(options, cam_id);
+    if (fake_id == NULL)
+        return NULL;
+
+    psString warp_id = warpIDForFake(options, fake_id);
+    if (warp_id == NULL)
+        return NULL;
+
+    psArray *diffIDs = runQuery(options,
+        "SELECT %s FROM diffInputSkyfile WHERE warp_id = %s",
+            "diff_id", warp_id, NULL, false, NULL);
+
+    psFree(warp_id);
+    psFree(fake_id);
+    psFree(cam_id);
+    psFree(chip_id);
+
+    if (diffIDs == NULL) {
+        return NULL;
+    }
+
+    psArray *uris = psArrayAlloc(0);
+
+    psU64 len = psArrayLength(diffIDs);
+
+    for (int i = 0; i < len ; i++ ) {
+        psString diff_id = (psString) diffIDs->data[i];
+        uris = runQuery(options, "SELECT %s FROM diffSkyfile where diff_id = %s",
+                    "uri", diff_id, NULL, true, uris);
+    }
+
+    psFree(diffIDs);
+
+    return uris;
+}
+
+static psArray * parseByID(itOptions *options)
+{
+    psString id = options->id;
+    psString class_id = options->class_id;
+    psArray *uris = NULL;
+
+    if (id == NULL) {
+        fprintf(stderr, "parseByID: need id\n");
+        return NULL;
+    }
+
+    switch (options->imageType) {
+    case RAW_IMAGE:
+        uris = findURIs(options, "rawImfile", "exp_id", id, class_id);
+        break;
+    case CHIP_IMAGE:
+        uris = findURIs(options, "chipProcessedImfile", "chip_id", id, class_id);
+        break;
+    case WARP_IMAGE:
+        uris = findURIs(options, "warpSkyfile", "warp_id", id, NULL);
+        break;
+    case DIFF_IMAGE:
+        uris = findURIs(options, "diffSkyfile", "diff_id", id, NULL);
+        break;
+    case STACK_IMAGE:
+        uris = findURIs(options, "stackSumSkyfile", "stack_id", id, NULL);
+        break;
+    default:
+        // note: parseImageType prints a message
+        return NULL;
+    }
+
+#ifdef VERBOSE
+        for (int i=0; i<psArrayLength(uris); i++) {
+            psString uri = (psString) uris->data[i];
+            printf("uri: %s\n", uri ? (psString) uri : "NULL uri");
+        }
+#endif
+
+
+    return uris;
+}
+
+psString exposureNameToID(itOptions *options, psString exposure)
+{
+    psArray *results;
+
+    results = runQuery(options, "SELECT %s from rawExp WHERE exp_name = '%s'",
+                        "exp_id", exposure, NULL, false, NULL);
+
+    return lastID(results);
+}
+
+static psArray * parseByExp(itOptions *options)
+{
+    psString class_id = options->class_id;
+    psString exposure = options->id;
+    psArray *uris = NULL;
+
+    if (exposure == NULL) {
+        psError(PS_ERR_UNKNOWN, true, "parseByExp: need exposure name");
+        return NULL;
+    }
+
+    psString exp_id = exposureNameToID(options, exposure);
+    if (exp_id == 0) {
+        return NULL;
+    }
+
+    switch (options->imageType) {
+    case RAW_IMAGE:
+        if (class_id == NULL) {
+            // XXX: we could relax this requirement if roi is specified in sky coords and
+            // process the whole fpa. That might even be a useful feature.
+            psError(PS_ERR_UNKNOWN, true, "stamps from raw images require CLASS_ID");
+            return NULL;
+        }
+        uris = findURIs(options, "rawImfile", "exp_id", exp_id, class_id);
+        break;
+    case CHIP_IMAGE:
+        if (class_id == NULL) {
+            // XXX: we could relax this requirement if roi is specified in sky coords and
+            // process the whole fpa. That might even be a useful feature.
+            psError(PS_ERR_UNKNOWN, true, "stamps from chip processed images require CLASS_ID");
+            return NULL;
+        }
+        uris = findChipURIs(options, exp_id, class_id);
+        break;
+    case WARP_IMAGE:
+        uris = findWarpURIs(options, exp_id);
+        break;
+    case DIFF_IMAGE:
+        uris = findDiffURIs(options, exp_id);
+        break;
+    case STACK_IMAGE:
+        uris = findStackURIs(options, exp_id);
+        break;
+    default:
+        // note: parseImageType prints an error message
+        return NULL;
+    }
+
+    psFree(exp_id);
+
+    return uris;
+}
+
+/*
+ * parseByCoord: first version. Looks for exposures with 
+ *      (dateobs >= mjd_min) && (dateobs <= (mjd_min + exp_time))
+ * I think that this meets the requirements that MOPS has for the postage stamp lookup
+ */
+
+static psArray * parseByCoord(itOptions *options)
+{
+    if (!options->mjd_min) {
+        psError(PS_ERR_UNKNOWN, false, "mjd_min is null\n");
+        return NULL;
+    }
+
+    psArray *output = psArrayAlloc(0);
+
+    time_t sec = ohana_mjd_to_sec(options->mjd_min);
+
+    // set time zone to utc so that sec --> dateobs are compared properly
+    // XXX: TODO: make sure that I need to do this
+    if (!p_psDBRunQuery(options->config->database, "set time_zone='+00:00'")) {
+        psError(PS_ERR_UNKNOWN, false, "database error seting time zone");
+        return NULL;
+    }
+    psString query = NULL;
+    psStringAppend(&query, "SELECT exp_name FROM rawExp"
+                " WHERE dateobs >= FROM_UNIXTIME(%ld) AND dateobs <= FROM_UNIXTIME(%ld + exp_time)",
+                                    sec, sec);
+
+    if (!p_psDBRunQuery(options->config->database, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return NULL;
+    }
+
+    psArray *queryOutput = p_psDBFetchResult(options->config->database);
+    if (!queryOutput) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return NULL;
+    }
+
+    psU64 len = psArrayLength(queryOutput);
+    if (!len) {
+        psTrace("pstampparse", PS_LOG_INFO, "no rows found");
+        psFree(queryOutput);
+        return NULL;
+    }
+
+    // For each exp_name found send it to parseByExp and collect the results
+    for (int i=0; i < len; i++) {
+        psMetadata *row = queryOutput->data[i];
+        psString val = psMetadataLookupStr(NULL, row, "exp_name");
+        if (val != NULL) {
+            options->id = val;
+            psArray *uris = parseByExp(options);
+            if (uris) {
+                for (int i=0; i<psArrayLength(uris); i++) {
+                    psString uri = (psString) uris->data[i];
+                    psArrayAdd(output, 0, uri);
+                }
+            }
+        }
+    }
+
+    psFree(queryOutput);
+
+    return output;
+}
+
+static bool
+go(itOptions *options)
+{
+    // how are we to select the images ?
+    if (options->lookupType == UNKNOWN_LOOKUP_TYPE) {
+        psError(PS_ERR_UNKNOWN, true, "request file has no REQ_TYPE");
+        return false;
+    }
+
+    psArray *uris = NULL;
+
+    switch (options->lookupType) {
+    case BY_ID:
+        // directly by exp_id, chip_id, warp_id etc
+        uris = parseByID(options);
+        break;
+    case BY_EXP:
+        // images that resulted from a given exposure
+        uris = parseByExp(options);
+        break;
+    case BY_COORD:
+        // images from a particular region of the sky
+        uris = parseByCoord(options);
+        break;
+    default:
+        psError(PS_ERR_PROGRAMMING, true, "unknown Lookup type: %d\n", options->lookupType);
+        return false;
+    }
+
+    if (uris == NULL) {
+        // XXX we need a finer grained status code: did something go wrong with the system
+        // or are there simply no images matching the request
+        fprintf(stderr, "No matching images found.\n");
+        return false;
+    }
+
+    int numURIs = psArrayLength(uris);
+    // Just list the images that would have jobs queued for them
+    for (int i=0; i<numURIs; i++) {
+        fprintf(stdout, "%s\n", (psString) uris->data[i]);
+    }
+
+    return true;
+}
+
+int main(int argc, char *argv[])
+{
+    itOptions *options = parseArguments(argc, argv);
+
+    if (!setupDB(options)) {
+        psErrorStackPrint(stderr, "unable to set up data base connection");
+        return 1;
+    }
+
+    if (!go(options)) {
+        psErrorStackPrint(stderr, "error processing request");
+        return 1;
+    }
+
+    return 0;
+}
Index: trunk/pstamp/src/pstampparse.c
===================================================================
--- trunk/pstamp/src/pstampparse.c	(revision 18637)
+++ 	(revision )
@@ -1,690 +1,0 @@
-// pstampparse ---> imagetool but this program is going to be
-// deleted so we'll just leave the external name alone
-
-#include <pslib.h>
-#include <psmodules.h>
-#include <string.h>
-#include <strings.h>
-
-typedef enum {
-    UNKNOWN_IMAGE = -1,
-    RAW_IMAGE,
-    CHIP_IMAGE,
-    WARP_IMAGE,
-    STACK_IMAGE,
-    DIFF_IMAGE
-} itImageType;
-
-typedef enum {
-    BY_ID,
-    BY_EXP,
-    BY_COORD,
-    UNKNOWN_LOOKUP_TYPE
-} itLookupType;
-
-typedef struct {
-    pmConfig        *config;
-    itLookupType    lookupType;
-    itImageType     imageType;
-    psString        id;
-    psString        class_id;
-    psString        roiString;
-    bool            verbose;
-    bool            simple;
-} itOptions;
-
-
-static void usage()
-{
-    // XXX: fill this out
-    psErrorStackPrint(stderr, "argument error");
-    exit(1);
-}
-
-static itImageType parseImageType(psString type)
-{
-    itImageType itype;
-
-    if (type == NULL) {
-        psError(PS_ERR_UNKNOWN, true, "NULL image type");
-        itype = UNKNOWN_IMAGE;
-        return itype;
-    }
-
-    if (strcmp(type, "raw") == 0) {
-        itype = RAW_IMAGE;
-    } else if (strcmp(type, "chip") == 0) {
-        itype = CHIP_IMAGE;
-    } else if (strcmp(type, "warp") == 0) {
-        itype = WARP_IMAGE;
-    } else if (strcmp(type, "diff") == 0) {
-        itype = DIFF_IMAGE;
-    } else if (strcmp(type, "stack") == 0) {
-        itype = STACK_IMAGE;
-    } else {
-        psError(PS_ERR_UNKNOWN, true, "unknown image type %s", type);
-        itype = UNKNOWN_LOOKUP_TYPE;
-    }
-
-    return itype;
-}
-static void getParams(itOptions *options, int argnum, int *pArgc, char *argv[])
-{
-    if (*pArgc < 3) {
-        fprintf(stderr, "values required for type and id\n");
-        usage();
-    }
-
-    options->imageType = parseImageType(argv[argnum]);
-    psArgumentRemove(argnum, pArgc, argv);
-    options->id = argv[argnum];
-    psArgumentRemove(argnum, pArgc, argv);
-
-    if ((options->imageType == RAW_IMAGE) || (options->imageType == CHIP_IMAGE)) {
-        if (*pArgc < 2) {
-            fprintf(stderr, "value required for class_id\n");
-            usage();
-        }
-        options->class_id = argv[argnum];
-    
-        psArgumentRemove(argnum, pArgc, argv);
-    }
-}
-
-static itOptions *parseArguments(int argc, char *argv[])
-{
-    int argnum;
-    itOptions *options = psAlloc(sizeof(itOptions));
-    bool gotLookupType = false;
-
-    memset(options, 0, sizeof(*options));
-
-    options->config = pmConfigRead(&argc, argv, NULL);
-    if (!options->config) {
-        psError(PS_ERR_UNKNOWN, false, "cannot find site file");
-        psFree(options);
-        return NULL;
-    }
-
-    if ((argnum = psArgumentGet(argc, argv, "-byid"))) {
-        options->lookupType = BY_ID;
-        psArgumentRemove(argnum, &argc, argv);
-        getParams(options, argnum, &argc, argv);
-        gotLookupType = true;
-    }
-    if ((argnum = psArgumentGet(argc, argv, "-byexp"))) {
-        if (gotLookupType) {
-            psError(PS_ERR_UNKNOWN, false, "only one of -byid, -byexp, and -bycoord may be used\n");
-            usage();
-        }
-        gotLookupType = true;
-        options->lookupType = BY_EXP;
-        psArgumentRemove(argnum, &argc, argv);
-        getParams(options, argnum, &argc, argv);
-    }
-    if ((argnum = psArgumentGet(argc, argv, "-bycoord"))) {
-        if (gotLookupType) {
-            psError(PS_ERR_UNKNOWN, false, "only one of -byid, -byexp, and -bycoord may be used\n");
-            usage();
-        }
-        psArgumentRemove(argnum, &argc, argv);
-        gotLookupType = true;
-        options->lookupType = BY_COORD;
-        getParams(options, argnum, &argc, argv);
-        psError(PS_ERR_UNKNOWN, true, "REQ_TYPE: bycoord not implemented yet");
-        return NULL;
-    }
-    if (!gotLookupType) {
-        psError(PS_ERR_BAD_PARAMETER_NULL , true, "one of -byid, -byexp, or -bycoord must be supplied\n");
-        usage();
-    }
-
-    if ((argnum = psArgumentGet(argc, argv, "-verbose"))) {
-        options->verbose = true;
-        psArgumentRemove(argnum, &argc, argv);
-    }
-
-    if ((argnum = psArgumentGet(argc, argv, "-simple"))) {
-        options->simple = true;
-        psArgumentRemove(argnum, &argc, argv);
-    }
-
-    // XXX: Arguments to add for bycoord searches FILTER, DATE_BEGIN, DATE_END
-
-    if (argc > 1) {
-        fprintf(stderr, "unknown arguments supplied: ");
-
-        fprintf(stderr, "%s", argv[1]);
-        for (int i=2; i<argc; i++) {
-            fprintf(stderr, ", %s", argv[i]);
-        }
-        fprintf(stderr, "\n");
-        usage();
-    }
-
-    return options;
-}
-
-static bool setupDB(itOptions *options)
-{
-    // XXX: need to select the database name based on the project name specified in the input
-
-    options->config->database = psMemIncrRefCounter(pmConfigDB(options->config));
-
-    if (!options->config->database) {
-        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
-        return false;
-    }
-
-    return true;
-}
-
-
-// return a string with the contents of a unsigned 64 bit value
-static psString idToStr(psU64 id)
-{
-    psString idstr = psStringAlloc(64);
-    sprintf(idstr, "%" PRIu64, id);
-
-    return idstr;
-}
-
-
-// runQuery
-//
-// run the given database query and return an array of strings containing the values of target
-// the type for the values returned by the query is either a string or psU64.
-
-static psArray *runQuery(itOptions *options, psString query, psString target,
-                psString key1, psString key2, bool targetIsString, psArray *output)
-{
-    // query string must be in the form
-    //  "SELECT %s from sometable WHERE somecolumn = %s and someothercolumn = %s
-    //        target                                key1                       key2
-    //
-    //  or if key2 is null
-    //
-    //  "SELECT %s from sometable WHERE somecolumn = %s"
-    //         target                               key1
-    //
-    //
-    // we return an array containing strings for the values
-
-    if (!p_psDBRunQuery(options->config->database, query, target, key1, key2)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return NULL;
-    }
-
-    psArray *queryOutput = p_psDBFetchResult(options->config->database);
-    if (!queryOutput) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return NULL;
-    }
-
-    psU64 len = psArrayLength(queryOutput);
-    if (!len) {
-        psTrace("pstampparse", PS_LOG_INFO, "no rows found");
-        psFree(queryOutput);
-        return NULL;
-    }
-
-    if (output == NULL) {
-        output = psArrayAlloc(0);
-    }
-
-    for (int i=0; i < len; i++) {
-        psMetadata *row = queryOutput->data[i];
-        if (targetIsString) {
-            psString val = psMetadataLookupStr(NULL, row, target);
-            if (val != 0) {
-                output = psArrayAdd(output, len - i, val);
-            }
-        } else {
-            psU64 val = psMetadataLookupU64(NULL, row, target);
-            if (val != 0) {
-                output = psArrayAdd(output, len - i, idToStr(val));
-            }
-        }
-    }
-
-    psFree(queryOutput);
-
-    return output;
-}
-
-static psArray *findURIs(itOptions *options, psString table, psString id_type, psString id, psString class_id)
-{
-    psString query = NULL;
-
-    psStringAppend(&query, "SELECT %%s from %s WHERE %s = %%s", table, id_type);
-    // append class_id unless it is set to the special value "null"
-    if (class_id && strcmp("null", class_id)) {
-        psStringAppend(&query, "%s", " and class_id = '%s'" );
-    }
-
-    psArray *results = runQuery(options, query, "uri", id, class_id, true, NULL);
-
-    psFree(query);
-
-    return results;
-}
-
-// given an array of strings return the last entry
-
-static psString lastID(psArray *array)
-{
-    if (array == NULL) {
-        return 0;
-    }
-    psU64 len = psArrayLength(array);
-
-    psString id = NULL;
-    if (len > 0) {
-        id = (psString) array->data[len-1];
-        psMemIncrRefCounter(id);
-    }
-
-    // XXX: Hmm if we're doing lastID(runQuery(....)) we need to free the
-    // result array, however freeing this in here seems like a potentially dangerous API
-    // but hey we're a static function
-
-    psFree(array);
-
-    return id;
-}
-
-
-
-#define chipIDForExp(_opt, _id) \
-            lastID(runQuery((_opt), "SELECT %s from chipRun  WHERE exp_id = %s", "chip_id", \
-                            (_id), NULL, false, NULL))
-
-#define camIDForChip(_opt, _id) \
-    lastID(runQuery((_opt), "SELECT %s from camRun  WHERE chip_id = %s", "cam_id", \
-                        (_id), NULL, false, NULL))
-
-#define fakeIDForCam(_opt, _id) \
-        lastID(runQuery((_opt), "SELECT %s from fakeRun  WHERE cam_id = %s", "fake_id", \
-                            (_id), NULL, false, NULL))
-
-#define warpIDForFake(_opt, _id) \
-        lastID(runQuery((_opt), "SELECT %s from warpRun  WHERE fake_id = %s", "warp_id", \
-                            (_id), NULL, false, NULL))
-
-
-
-static psArray *findChipURIs(itOptions *options, psString exp_id, psString class_id)
-{
-    psString chip_id = chipIDForExp(options, exp_id);
-
-    if (chip_id == NULL)
-        return NULL;
-
-    psString query = NULL;
-    psStringAppend(&query, "SELECT %s from chipProcessedImfile WHERE chip_id = %s", "%s", "%s");
-    if (class_id && (strcmp(class_id, "null") != 0)) {
-        psStringAppend(&query, " AND class_id = '%s'", "%s");
-    }
-
-    psArray *chip_files = runQuery(options, query,
-                        "uri", chip_id, class_id, true, NULL);
-    psFree(query);
-    psFree(chip_id);
-
-    return chip_files;
-}
-
-static psArray *findWarpURIs(itOptions *options, psString exp_id)
-{
-    psString chip_id = chipIDForExp(options, exp_id);
-
-    if (chip_id == NULL)
-        return NULL;
-
-    psString cam_id = camIDForChip(options, chip_id);
-    if (cam_id == NULL)
-        return NULL;
-
-    psString fake_id = fakeIDForCam(options, cam_id);
-    if (fake_id == NULL)
-        return NULL;
-
-    psString warp_id = warpIDForFake(options, fake_id);
-    if (warp_id == NULL)
-        return NULL;
-
-    psArray *warp_files = runQuery(options,
-                        "SELECT %s from warpSkyfile WHERE warp_id = %s"
-                        " AND uri IS NOT NULL and (fault = 0 or fault is NULL)",
-                           "uri",   warp_id, NULL, true, NULL);
-
-    psFree(warp_id);
-    psFree(fake_id);
-    psFree(cam_id);
-    psFree(chip_id);
-
-    return warp_files;
-}
-
-static psArray *findStackURIs(itOptions *options, psString exp_id)
-{
-    psString chip_id = chipIDForExp(options, exp_id);
-
-    if (chip_id == NULL)
-        return NULL;
-
-    psString cam_id = camIDForChip(options, chip_id);
-    if (cam_id == NULL)
-        return NULL;
-
-    psString fake_id = fakeIDForCam(options, cam_id);
-    if (fake_id == NULL)
-        return NULL;
-
-    psString warp_id = warpIDForFake(options, fake_id);
-    if (warp_id == NULL)
-        return NULL;
-
-    psArray *stackIDs = runQuery(options, "SELECT %s FROM stackInputSkyfile WHERE warp_id = %s",
-                            "stack_id", warp_id, NULL, false, NULL);
-
-    psFree(warp_id);
-    psFree(fake_id);
-    psFree(cam_id);
-    psFree(chip_id);
-
-    if (stackIDs == NULL) {
-        return NULL;
-    }
-
-    psArray *uris = psArrayAlloc(0);
-
-    psU64 len = psArrayLength(stackIDs);
-
-    // loop over the stack's for this exposure and add the images
-    for (int i = 0; i < len ; i++ ) {
-        psString stack_id = (psString) stackIDs->data[i];
-        uris = runQuery(options, "SELECT %s FROM stackSumSkyfile where stack_id = %s",
-                    "uri", stack_id, NULL, true, uris);
-    }
-    psFree(stackIDs);
-
-    return uris;
-}
-
-static psArray *findDiffURIs(itOptions *options, psString exp_id)
-{
-    psString chip_id = chipIDForExp(options, exp_id);
-
-    if (chip_id == NULL)
-        return NULL;
-
-    psString cam_id = camIDForChip(options, chip_id);
-    if (cam_id == NULL)
-        return NULL;
-
-    psString fake_id = fakeIDForCam(options, cam_id);
-    if (fake_id == NULL)
-        return NULL;
-
-    psString warp_id = warpIDForFake(options, fake_id);
-    if (warp_id == NULL)
-        return NULL;
-
-    psArray *diffIDs = runQuery(options,
-        "SELECT %s FROM diffInputSkyfile WHERE warp_id = %s",
-            "diff_id", warp_id, NULL, false, NULL);
-
-    psFree(warp_id);
-    psFree(fake_id);
-    psFree(cam_id);
-    psFree(chip_id);
-
-    if (diffIDs == NULL) {
-        return NULL;
-    }
-
-    psArray *uris = psArrayAlloc(0);
-
-    psU64 len = psArrayLength(diffIDs);
-
-    for (int i = 0; i < len ; i++ ) {
-        psString diff_id = (psString) diffIDs->data[i];
-        uris = runQuery(options, "SELECT %s FROM diffSkyfile where diff_id = %s",
-                    "uri", diff_id, NULL, true, uris);
-    }
-
-    psFree(diffIDs);
-
-    return uris;
-}
-
-static psArray * parseByID(itOptions *options)
-{
-    psString id = options->id;
-    psString class_id = options->class_id;
-    psArray *uris = NULL;
-
-    if (id == NULL) {
-        fprintf(stderr, "parseByID: need id\n");
-        return NULL;
-    }
-
-    switch (options->imageType) {
-    case RAW_IMAGE:
-        uris = findURIs(options, "rawImfile", "exp_id", id, class_id);
-        break;
-    case CHIP_IMAGE:
-        uris = findURIs(options, "chipProcessedImfile", "chip_id", id, class_id);
-        break;
-    case WARP_IMAGE:
-        uris = findURIs(options, "warpSkyfile", "warp_id", id, NULL);
-        break;
-    case DIFF_IMAGE:
-        uris = findURIs(options, "diffSkyfile", "diff_id", id, NULL);
-        break;
-    case STACK_IMAGE:
-        uris = findURIs(options, "stackSumSkyfile", "stack_id", id, NULL);
-        break;
-    default:
-        // note: parseImageType prints a message
-        return NULL;
-    }
-
-#ifdef VERBOSE
-        for (int i=0; i<psArrayLength(uris); i++) {
-            psString uri = (psString) uris->data[i];
-            printf("uri: %s\n", uri ? (psString) uri : "NULL uri");
-        }
-#endif
-
-
-    return uris;
-}
-
-psString exposureNameToID(itOptions *options, psString exposure)
-{
-    psArray *results;
-
-    results = runQuery(options, "SELECT %s from rawExp WHERE exp_name = '%s'",
-                        "exp_id", exposure, NULL, false, NULL);
-
-    return lastID(results);
-}
-
-static psArray * parseByExp(itOptions *options)
-{
-    psString class_id = options->class_id;
-    psString exposure = options->id;
-    psArray *uris = NULL;
-
-    if (exposure == NULL) {
-        psError(PS_ERR_UNKNOWN, true, "parseByExp: need exposure name");
-        return NULL;
-    }
-
-    psString exp_id = exposureNameToID(options, exposure);
-    if (exp_id == 0) {
-        return NULL;
-    }
-
-    switch (options->imageType) {
-    case RAW_IMAGE:
-        if (class_id == NULL) {
-            // XXX: we could relax this requirement if roi is specified in sky coords and
-            // process the whole fpa. That might even be a useful feature.
-            psError(PS_ERR_UNKNOWN, true, "stamps from raw images require CLASS_ID");
-            return NULL;
-        }
-        uris = findURIs(options, "rawImfile", "exp_id", exp_id, class_id);
-        break;
-    case CHIP_IMAGE:
-        if (class_id == NULL) {
-            // XXX: we could relax this requirement if roi is specified in sky coords and
-            // process the whole fpa. That might even be a useful feature.
-            psError(PS_ERR_UNKNOWN, true, "stamps from chip processed images require CLASS_ID");
-            return NULL;
-        }
-        uris = findChipURIs(options, exp_id, class_id);
-        break;
-    case WARP_IMAGE:
-        uris = findWarpURIs(options, exp_id);
-        break;
-    case DIFF_IMAGE:
-        uris = findDiffURIs(options, exp_id);
-        break;
-    case STACK_IMAGE:
-        uris = findStackURIs(options, exp_id);
-        break;
-    default:
-        // note: parseImageType prints an error message
-        return NULL;
-    }
-
-    psFree(exp_id);
-
-    return uris;
-}
-
-static psArray * parseByCoord(itOptions *options)
-{
-    psError(PS_ERR_UNKNOWN, true, "REQ_TYPE: bycoord not implemented yet");
-    return NULL;
-}
-
-static psString parseROI(itOptions *options)
-{
-    psString roiString = NULL;
-#ifdef notyet
-    bool status = false;;
-    psU32 coord_mask = psMetadataLookupU32(&status, options->md, "COORD_MASK");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "bad request file: COORD_MASK not specified");
-        return NULL;
-    }
-
-    psString x = psMetadataLookupStr(&status, options->md, "CENTER_X");
-    if (x == NULL) {
-        psError(PS_ERR_UNKNOWN, true, "bad request file: CENTER_X not specified");
-        return NULL;
-    }
-    psString y = psMetadataLookupStr(&status, options->md, "CENTER_Y");
-    if (y == NULL) {
-        psError(PS_ERR_UNKNOWN, true, "bad request file: CENTER_Y not specified");
-        return NULL;
-    }
-
-    if (coord_mask & PSTAMP_CENTER_IN_PIXELS) {
-        psStringAppend(&roiString, "-pixcenter %s %s", x, y);
-    } else {
-        psStringAppend(&roiString, "-skycenter %s %s", x, y);
-    }
-
-    psString w = psMetadataLookupStr(&status, options->md, "WIDTH");
-    if (w == NULL) {
-        psError(PS_ERR_UNKNOWN, true, "bad request file: WIDTH not specified");
-        return NULL;
-    }
-    psString h = psMetadataLookupStr(&status, options->md, "HEIGHT");
-    if (h == NULL) {
-        psError(PS_ERR_UNKNOWN, true, "bad request file: HEIGHT not specified");
-        return NULL;
-    }
-
-    if (coord_mask & PSTAMP_RANGE_IN_PIXELS) {
-        psStringAppend(&roiString, " -pixrange %s %s", w, h);
-    } else {
-        psStringAppend(&roiString, " -arcrange %s %s", w, h);
-    }
-
-#endif
-    return roiString;
-}
-
-static bool
-go(itOptions *options)
-{
-    // how are we to select the images ?
-    if (options->lookupType == UNKNOWN_LOOKUP_TYPE) {
-        psError(PS_ERR_UNKNOWN, true, "request file has no REQ_TYPE");
-        return false;
-    }
-
-    psString roiString = parseROI(options);
-
-    psArray *uris = NULL;
-
-    switch (options->lookupType) {
-    case BY_ID:
-        // directly by exp_id, chip_id, warp_id etc
-        uris = parseByID(options);
-        break;
-    case BY_EXP:
-        // images that resulted from a given exposure
-        uris = parseByExp(options);
-        break;
-    case BY_COORD:
-        // images from a particular region of the sky
-        if (!roiString) {
-            fprintf(stderr, "Region of interest required with lookupType: bycoord\n");
-            return false;
-        }
-        uris = parseByCoord(options);
-        break;
-    default:
-        psError(PS_ERR_PROGRAMMING, true, "unknown Lookup type: %d\n", options->lookupType);
-        return false;
-    }
-
-    if (uris == NULL) {
-        // XXX we need a finer grained status code: did something go wrong with the system
-        // or are there simply no images matching the request
-        fprintf(stderr, "No matching images found.\n");
-        return false;
-    }
-
-    int numURIs = psArrayLength(uris);
-    // Just list the images that would have jobs queued for them
-    for (int i=0; i<numURIs; i++) {
-        fprintf(stdout, "%s\n", (psString) uris->data[i]);
-    }
-
-    return true;
-}
-
-int main(int argc, char *argv[])
-{
-    itOptions *options = parseArguments(argc, argv);
-
-    if (!setupDB(options)) {
-        psErrorStackPrint(stderr, "unable to set up data base connection");
-        return 1;
-    }
-
-    if (!go(options)) {
-        psErrorStackPrint(stderr, "error processing request");
-        return 1;
-    }
-
-    return 0;
-}
