Index: /trunk/ippTools/scripts/camtest.sh
===================================================================
--- /trunk/ippTools/scripts/camtest.sh	(revision 9311)
+++ /trunk/ippTools/scripts/camtest.sh	(revision 9311)
@@ -0,0 +1,11 @@
+#!//bin/sh
+
+set -o verbose
+
+p2test.sh || exit 1
+
+p3tool -pendingexp || exit 1
+p3tool -pendingimfile || exit 1
+
+p3tool -addprocessedexp -exp_tag t10 -uri file://p3p -recip myrecipe -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -sigma_ra 1 -sigma_dec 2 -nastro 42 -b1_uri file:///foo -b2_uri file://bar -zp_mean 1 -zp_stdev 2 || exit 1
+p3tool -addprocessedexp -exp_tag t11 -uri file://p3p -recip myrecipe -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -sigma_ra 1 -sigma_dec 2 -nastro 42 -b1_uri file:///foo -b2_uri file://bar -zp_mean 1 -zp_stdev 2 || exit 1
Index: /trunk/ippTools/src/camtool.c
===================================================================
--- /trunk/ippTools/src/camtool.c	(revision 9310)
+++ /trunk/ippTools/src/camtool.c	(revision 9311)
@@ -53,5 +53,6 @@
 
     psString query = psStringCopy(
-            "SELECT * FROM p3PendingExp"
+            "SELECT p3PendingExp.*"
+            " FROM p3PendingExp"
             " LEFT JOIN p3ProcessedExp"
             "   USING(exp_tag)"
@@ -169,4 +170,177 @@
     PS_ASSERT_PTR_NON_NULL(config, false);
 
+    // det_id, exp_tag, recip, -bg, -bg_stdev, & -bg_mean_stdev
+    // are required
+    bool status = false;
+    psString exp_tag = psMetadataLookupStr(&status, config->args, "-exp_tag");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -exp_tag");
+        return false;
+    }
+    if (!exp_tag) {
+        psError(PS_ERR_UNKNOWN, true, "-exp_tag is required");
+        return false;
+    }
+    psString uri = psMetadataLookupStr(&status, config->args, "-uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -uri");
+        return false;
+    }
+    if (!uri) {
+        psError(PS_ERR_UNKNOWN, true, "-uri is required");
+        return false;
+    }
+    psString recipe = psMetadataLookupStr(&status, config->args, "-recip");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -recip");
+        return false;
+    }
+    if (!recipe) {
+        psError(PS_ERR_UNKNOWN, true, "-recip is required");
+        return false;
+    }
+    psF64 bg = psMetadataLookupF64(&status, config->args, "-bg");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -bg");
+        return false;
+    }
+    if (isnan(bg)) {
+        psError(PS_ERR_UNKNOWN, true, "-bg is required");
+        return false;
+    }
+    psF64 bg_stdev = psMetadataLookupF64(&status, config->args, "-bg_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -bg_stdev");
+        return false;
+    }
+    if (isnan(bg_stdev)) {
+        psError(PS_ERR_UNKNOWN, true, "-bg_stdev is required");
+        return false;
+    }
+    psF64 bg_mean_stdev = psMetadataLookupF64(&status, config->args, "-bg_mean_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -bg_mean_stdev");
+        return false;
+    }
+    if (isnan(bg_mean_stdev)) {
+        psError(PS_ERR_UNKNOWN, true, "-bg_mean_stdev is required");
+        return false;
+    }
+    psF32 sigma_ra = psMetadataLookupF32(&status, config->args, "-sigma_ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -sigma_ra");
+        return false;
+    }
+    if (isnan(sigma_ra)) {
+        psError(PS_ERR_UNKNOWN, true, "-sigma_ra is required");
+        return false;
+    }
+    psF32 sigma_dec = psMetadataLookupF32(&status, config->args, "-sigma_dec");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -sigma_dec");
+        return false;
+    }
+    if (isnan(sigma_dec)) {
+        psError(PS_ERR_UNKNOWN, true, "-sigma_dec is required");
+        return false;
+    }
+    psS32 nastro = psMetadataLookupS32(&status, config->args, "-nastro");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -nastro");
+        return false;
+    }
+    if (nastro < 0) {
+        psError(PS_ERR_UNKNOWN, true, "-nastro is required");
+        return false;
+    }
+    psF32 zp_mean = psMetadataLookupF32(&status, config->args, "-zp_mean");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -zp_mean");
+        return false;
+    }
+    if (isnan(zp_mean)) {
+        psError(PS_ERR_UNKNOWN, true, "-zp_mean is required");
+        return false;
+    }
+    psF32 zp_stdev = psMetadataLookupF32(&status, config->args, "-zp_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -zp_stdev");
+        return false;
+    }
+    if (isnan(zp_stdev)) {
+        psError(PS_ERR_UNKNOWN, true, "-zp_stdev is required");
+        return false;
+    }
+    // optional
+    psString b1_uri = psMetadataLookupStr(&status, config->args, "-b1_uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -b1_uri");
+        return false;
+    }
+    psString b2_uri = psMetadataLookupStr(&status, config->args, "-b2_uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -b2_uri");
+        return false;
+    }
+
+    psString query = psStringCopy(
+        "SELECT p3PendingExp.*"
+        " FROM p3PendingExp"
+        " LEFT JOIN p3ProcessedExp"
+        "   USING(exp_tag)"
+        " WHERE"
+        "   p3ProcessedExp.exp_tag IS NULL"
+        "   AND p3PendingExp.exp_tag = '%s'"
+    );
+
+    if (!p_psDBRunQuery(config->dbh, query, exp_tag)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        // XXX check psError here
+        psError(PS_ERR_UNKNOWN, false, "no p3PendingExp rows found");
+        return true;
+    }
+
+    p3PendingExpRow *pendingRow = p3PendingExpObjectFromMetadata(output->data[0]);
+    psFree(output);
+    // create a new p3ProcessedImfile object
+    p3ProcessedExpRow *row = p3ProcessedExpRowAlloc(
+        exp_tag,
+        uri,
+        recipe,
+        bg,
+        bg_stdev,
+        bg_mean_stdev,
+        sigma_ra,
+        sigma_dec,
+        nastro,
+        b1_uri,
+        b2_uri,
+        zp_mean,
+        zp_stdev,
+        pendingRow->p2_version,
+        pendingRow->p3_version
+    );
+    psFree(pendingRow);
+
+    // insert the new row into the p3ProcessedImfile table
+    if (!p3ProcessedExpInsertObject(config->dbh, row)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
     return true;
 }
Index: /trunk/ippTools/src/camtoolConfig.c
===================================================================
--- /trunk/ippTools/src/camtoolConfig.c	(revision 9310)
+++ /trunk/ippTools/src/camtoolConfig.c	(revision 9311)
@@ -49,8 +49,8 @@
     psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-exp_tag", 0,
             "define exp ID (required)", NULL);
-    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-class_id", 0,
-            "define class ID (required)", NULL);
     psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-uri", 0,
             "define URI (required)", NULL);
+    psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-recip",  0,
+            "define recipe (required)", NULL);
     psMetadataAddF64(addprocessedexpArgs, PS_LIST_TAIL, "-bg", 0,
             "define exposue background (required)", NAN);
@@ -65,9 +65,12 @@
     psMetadataAddS32(addprocessedexpArgs, PS_LIST_TAIL, "-nastro", 0,
             "define number of objects (required)", -1);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-zp_mean", 0,
+            "define zero point mean (required)", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-zp_stdev", 0,
+            "define zero point stdev (required)", NAN);
     psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-b1_uri", 0,
             "define banana 1", NULL);
     psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-b2_uri", 0,
             "define banana 2", NULL);
-
 
 #define PXTOOL_MODE(option, modeval, argset) \
