Index: trunk/ippdb/src/ippdb.c
===================================================================
--- trunk/ippdb/src/ippdb.c	(revision 8380)
+++ trunk/ippdb/src/ippdb.c	(revision 8528)
@@ -68,4 +68,6 @@
 #define DETRESIDEXP_TABLE_NAME "detResidExp"
 #define DETRESIDEXP_INDEX_NAME IPPDB_DEFAULT_INDEX_NAME
+#define DETRUNSUMMARY_TABLE_NAME "detRunSummary"
+#define DETRUNSUMMARY_INDEX_NAME IPPDB_DEFAULT_INDEX_NAME
 #define MAX_STRING_LENGTH 1024
 
@@ -12607,5 +12609,5 @@
         return false;
     }
-    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, 0)) {
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, "Key", 0)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
         psFree(md);
@@ -12992,5 +12994,5 @@
 static void detInputExpRowFree(detInputExpRow *object);
 
-detInputExpRow *detInputExpRowAlloc(psS32 det_id, psS32 iteration, const char *exp_id, bool include, bool accept)
+detInputExpRow *detInputExpRowAlloc(psS32 det_id, psS32 iteration, const char *exp_id, bool include)
 {
     detInputExpRow  *object;
@@ -13003,5 +13005,4 @@
     object->exp_id = psStringCopy(exp_id);
     object->include = include;
-    object->accept = accept;
 
     return object;
@@ -13044,9 +13045,4 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, false)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
-        psFree(md);
-        return false;
-    }
 
     status = psDBCreateTable(dbh, DETINPUTEXP_TABLE_NAME, md);
@@ -13062,5 +13058,5 @@
 }
 
-bool detInputExpInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *exp_id, bool include, bool accept)
+bool detInputExpInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *exp_id, bool include)
 {
     psMetadata      *md;
@@ -13085,9 +13081,4 @@
     if (!psMetadataAdd(md, PS_LIST_TAIL, "include", PS_DATA_BOOL, NULL, include)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item include");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, accept)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
         psFree(md);
         return false;
@@ -13114,5 +13105,5 @@
     return deleted;
 }
-bool detInputExpPop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **exp_id, bool *include, bool *accept)
+bool detInputExpPop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **exp_id, bool *include)
 {
     psArray         *rowSet;
@@ -13182,10 +13173,4 @@
         return false;
     }
-    *accept = psMetadataLookupBool(&status, row, "accept");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item accept");
-        psFree(row);
-        return false;
-    }
 
     psFree(row);
@@ -13196,5 +13181,5 @@
 bool detInputExpInsertObject(psDB *dbh, detInputExpRow *object)
 {
-    return detInputExpInsert(dbh, object->det_id, object->iteration, object->exp_id, object->include, object->accept);
+    return detInputExpInsert(dbh, object->det_id, object->iteration, object->exp_id, object->include);
 }
 
@@ -13216,12 +13201,11 @@
     char            exp_id[256];
     bool            include;
-    bool            accept;
-
-    if (!detInputExpPop(dbh, &det_id, &iteration, (char **)&exp_id, &include, &accept)) {
+
+    if (!detInputExpPop(dbh, &det_id, &iteration, (char **)&exp_id, &include)) {
         psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
         return NULL;
     }
 
-    return detInputExpRowAlloc(det_id, iteration, exp_id, include, accept);
+    return detInputExpRowAlloc(det_id, iteration, exp_id, include);
 }
 
@@ -13342,9 +13326,4 @@
         return NULL;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, object->accept)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
-        psFree(md);
-        return NULL;
-    }
 
     return md;
@@ -13358,5 +13337,4 @@
     char            *exp_id;
     bool            include;
-    bool            accept;
 
     det_id = psMetadataLookupS32(&status, md, "det_id");
@@ -13380,11 +13358,6 @@
         return false;
     }
-    accept = psMetadataLookupBool(&status, md, "accept");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item accept");
-        return false;
-    }
-
-    return detInputExpRowAlloc(det_id, iteration, exp_id, include, accept);
+
+    return detInputExpRowAlloc(det_id, iteration, exp_id, include);
 }
 psArray *detInputExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
@@ -14084,5 +14057,5 @@
 static void detStackedImfileRowFree(detStackedImfileRow *object);
 
-detStackedImfileRow *detStackedImfileRowAlloc(psS32 det_id, psS32 iteration, const char *class_id, const char *uri, const char *recipe)
+detStackedImfileRow *detStackedImfileRowAlloc(psS32 det_id, psS32 iteration, const char *class_id, const char *uri, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev)
 {
     detStackedImfileRow *object;
@@ -14096,4 +14069,7 @@
     object->uri = psStringCopy(uri);
     object->recipe = psStringCopy(recipe);
+    object->bg = bg;
+    object->bg_stdev = bg_stdev;
+    object->bg_mean_stdev = bg_mean_stdev;
 
     return object;
@@ -14143,4 +14119,19 @@
         return false;
     }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
+        psFree(md);
+        return false;
+    }
 
     status = psDBCreateTable(dbh, DETSTACKEDIMFILE_TABLE_NAME, md);
@@ -14156,5 +14147,5 @@
 }
 
-bool detStackedImfileInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *class_id, const char *uri, const char *recipe)
+bool detStackedImfileInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *class_id, const char *uri, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev)
 {
     psMetadata      *md;
@@ -14184,4 +14175,19 @@
     if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, recipe)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, bg)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, bg_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, bg_mean_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
         psFree(md);
         return false;
@@ -14208,5 +14214,5 @@
     return deleted;
 }
-bool detStackedImfilePop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **class_id, char **uri, char **recipe)
+bool detStackedImfilePop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **class_id, char **uri, char **recipe, psF64 *bg, psF64 *bg_stdev, psF64 *bg_mean_stdev)
 {
     psArray         *rowSet;
@@ -14282,4 +14288,22 @@
         return false;
     }
+    *bg = psMetadataLookupF64(&status, row, "bg");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg");
+        psFree(row);
+        return false;
+    }
+    *bg_stdev = psMetadataLookupF64(&status, row, "bg_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_stdev");
+        psFree(row);
+        return false;
+    }
+    *bg_mean_stdev = psMetadataLookupF64(&status, row, "bg_mean_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_mean_stdev");
+        psFree(row);
+        return false;
+    }
 
     psFree(row);
@@ -14290,5 +14314,5 @@
 bool detStackedImfileInsertObject(psDB *dbh, detStackedImfileRow *object)
 {
-    return detStackedImfileInsert(dbh, object->det_id, object->iteration, object->class_id, object->uri, object->recipe);
+    return detStackedImfileInsert(dbh, object->det_id, object->iteration, object->class_id, object->uri, object->recipe, object->bg, object->bg_stdev, object->bg_mean_stdev);
 }
 
@@ -14311,11 +14335,14 @@
     char            uri[256];
     char            recipe[256];
-
-    if (!detStackedImfilePop(dbh, &det_id, &iteration, (char **)&class_id, (char **)&uri, (char **)&recipe)) {
+    psF64           bg;
+    psF64           bg_stdev;
+    psF64           bg_mean_stdev;
+
+    if (!detStackedImfilePop(dbh, &det_id, &iteration, (char **)&class_id, (char **)&uri, (char **)&recipe, &bg, &bg_stdev, &bg_mean_stdev)) {
         psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
         return NULL;
     }
 
-    return detStackedImfileRowAlloc(det_id, iteration, class_id, uri, recipe);
+    return detStackedImfileRowAlloc(det_id, iteration, class_id, uri, recipe, bg, bg_stdev, bg_mean_stdev);
 }
 
@@ -14441,4 +14468,19 @@
         return NULL;
     }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, object->bg)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, object->bg_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, object->bg_mean_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
+        psFree(md);
+        return NULL;
+    }
 
     return md;
@@ -14453,4 +14495,7 @@
     char            *uri;
     char            *recipe;
+    psF64           bg;
+    psF64           bg_stdev;
+    psF64           bg_mean_stdev;
 
     det_id = psMetadataLookupS32(&status, md, "det_id");
@@ -14479,6 +14524,21 @@
         return false;
     }
-
-    return detStackedImfileRowAlloc(det_id, iteration, class_id, uri, recipe);
+    bg = psMetadataLookupF64(&status, md, "bg");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg");
+        return false;
+    }
+    bg_stdev = psMetadataLookupF64(&status, md, "bg_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_stdev");
+        return false;
+    }
+    bg_mean_stdev = psMetadataLookupF64(&status, md, "bg_mean_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_mean_stdev");
+        return false;
+    }
+
+    return detStackedImfileRowAlloc(det_id, iteration, class_id, uri, recipe, bg, bg_stdev, bg_mean_stdev);
 }
 psArray *detStackedImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
@@ -16449,5 +16509,5 @@
 static void detResidImfileRowFree(detResidImfileRow *object);
 
-detResidImfileRow *detResidImfileRowAlloc(psS32 det_id, psS32 iteration, const char *exp_id, const char *class_id, const char *recipe, const char *uri, const char *b1_uri, const char *b2_uri)
+detResidImfileRow *detResidImfileRowAlloc(psS32 det_id, psS32 iteration, const char *exp_id, const char *class_id, const char *uri, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, const char *b1_uri, const char *b2_uri)
 {
     detResidImfileRow *object;
@@ -16460,6 +16520,9 @@
     object->exp_id = psStringCopy(exp_id);
     object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
     object->recipe = psStringCopy(recipe);
-    object->uri = psStringCopy(uri);
+    object->bg = bg;
+    object->bg_stdev = bg_stdev;
+    object->bg_mean_stdev = bg_mean_stdev;
     object->b1_uri = psStringCopy(b1_uri);
     object->b2_uri = psStringCopy(b2_uri);
@@ -16472,6 +16535,6 @@
     psFree(object->exp_id);
     psFree(object->class_id);
+    psFree(object->uri);
     psFree(object->recipe);
-    psFree(object->uri);
     psFree(object->b1_uri);
     psFree(object->b2_uri);
@@ -16509,4 +16572,9 @@
         return false;
     }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
     if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
@@ -16514,6 +16582,16 @@
         return false;
     }
-    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "64")) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
         psFree(md);
         return false;
@@ -16542,5 +16620,5 @@
 }
 
-bool detResidImfileInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *exp_id, const char *class_id, const char *recipe, const char *uri, const char *b1_uri, const char *b2_uri)
+bool detResidImfileInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *exp_id, const char *class_id, const char *uri, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, const char *b1_uri, const char *b2_uri)
 {
     psMetadata      *md;
@@ -16568,4 +16646,9 @@
         return false;
     }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
     if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, recipe)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
@@ -16573,6 +16656,16 @@
         return false;
     }
-    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, uri)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, bg)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, bg_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, bg_mean_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
         psFree(md);
         return false;
@@ -16609,5 +16702,5 @@
     return deleted;
 }
-bool detResidImfilePop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **exp_id, char **class_id, char **recipe, char **uri, char **b1_uri, char **b2_uri)
+bool detResidImfilePop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **exp_id, char **class_id, char **uri, char **recipe, psF64 *bg, psF64 *bg_stdev, psF64 *bg_mean_stdev, char **b1_uri, char **b2_uri)
 {
     psArray         *rowSet;
@@ -16677,4 +16770,10 @@
         return false;
     }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
     *recipe = psMetadataLookupPtr(&status, row, "recipe");
     if (!status) {
@@ -16683,7 +16782,19 @@
         return false;
     }
-    *uri = psMetadataLookupPtr(&status, row, "uri");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+    *bg = psMetadataLookupF64(&status, row, "bg");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg");
+        psFree(row);
+        return false;
+    }
+    *bg_stdev = psMetadataLookupF64(&status, row, "bg_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_stdev");
+        psFree(row);
+        return false;
+    }
+    *bg_mean_stdev = psMetadataLookupF64(&status, row, "bg_mean_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_mean_stdev");
         psFree(row);
         return false;
@@ -16709,5 +16820,5 @@
 bool detResidImfileInsertObject(psDB *dbh, detResidImfileRow *object)
 {
-    return detResidImfileInsert(dbh, object->det_id, object->iteration, object->exp_id, object->class_id, object->recipe, object->uri, object->b1_uri, object->b2_uri);
+    return detResidImfileInsert(dbh, object->det_id, object->iteration, object->exp_id, object->class_id, object->uri, object->recipe, object->bg, object->bg_stdev, object->bg_mean_stdev, object->b1_uri, object->b2_uri);
 }
 
@@ -16729,15 +16840,18 @@
     char            exp_id[256];
     char            class_id[256];
+    char            uri[256];
     char            recipe[256];
-    char            uri[256];
+    psF64           bg;
+    psF64           bg_stdev;
+    psF64           bg_mean_stdev;
     char            b1_uri[256];
     char            b2_uri[256];
 
-    if (!detResidImfilePop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&class_id, (char **)&recipe, (char **)&uri, (char **)&b1_uri, (char **)&b2_uri)) {
+    if (!detResidImfilePop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&class_id, (char **)&uri, (char **)&recipe, &bg, &bg_stdev, &bg_mean_stdev, (char **)&b1_uri, (char **)&b2_uri)) {
         psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
         return NULL;
     }
 
-    return detResidImfileRowAlloc(det_id, iteration, exp_id, class_id, recipe, uri, b1_uri, b2_uri);
+    return detResidImfileRowAlloc(det_id, iteration, exp_id, class_id, uri, recipe, bg, bg_stdev, bg_mean_stdev, b1_uri, b2_uri);
 }
 
@@ -16858,4 +16972,9 @@
         return NULL;
     }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, object->uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
     if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, object->recipe)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
@@ -16863,6 +16982,16 @@
         return NULL;
     }
-    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, object->uri)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, object->bg)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, object->bg_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, object->bg_mean_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
         psFree(md);
         return NULL;
@@ -16889,6 +17018,9 @@
     char            *exp_id;
     char            *class_id;
+    char            *uri;
     char            *recipe;
-    char            *uri;
+    psF64           bg;
+    psF64           bg_stdev;
+    psF64           bg_mean_stdev;
     char            *b1_uri;
     char            *b2_uri;
@@ -16914,4 +17046,9 @@
         return false;
     }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
     recipe = psMetadataLookupPtr(&status, md, "recipe");
     if (!status) {
@@ -16919,7 +17056,17 @@
         return false;
     }
-    uri = psMetadataLookupPtr(&status, md, "uri");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+    bg = psMetadataLookupF64(&status, md, "bg");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg");
+        return false;
+    }
+    bg_stdev = psMetadataLookupF64(&status, md, "bg_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_stdev");
+        return false;
+    }
+    bg_mean_stdev = psMetadataLookupF64(&status, md, "bg_mean_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_mean_stdev");
         return false;
     }
@@ -16935,5 +17082,5 @@
     }
 
-    return detResidImfileRowAlloc(det_id, iteration, exp_id, class_id, recipe, uri, b1_uri, b2_uri);
+    return detResidImfileRowAlloc(det_id, iteration, exp_id, class_id, uri, recipe, bg, bg_stdev, bg_mean_stdev, b1_uri, b2_uri);
 }
 psArray *detResidImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
@@ -17042,5 +17189,5 @@
 static void detResidExpRowFree(detResidExpRow *object);
 
-detResidExpRow *detResidExpRowAlloc(psS32 det_id, psS32 iteration, const char *exp_id, const char *recipe, bool keep, bool accept)
+detResidExpRow *detResidExpRowAlloc(psS32 det_id, psS32 iteration, const char *exp_id, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, const char *b1_uri, const char *b2_uri, bool accept)
 {
     detResidExpRow  *object;
@@ -17053,5 +17200,9 @@
     object->exp_id = psStringCopy(exp_id);
     object->recipe = psStringCopy(recipe);
-    object->keep = keep;
+    object->bg = bg;
+    object->bg_stdev = bg_stdev;
+    object->bg_mean_stdev = bg_mean_stdev;
+    object->b1_uri = psStringCopy(b1_uri);
+    object->b2_uri = psStringCopy(b2_uri);
     object->accept = accept;
 
@@ -17063,4 +17214,6 @@
     psFree(object->exp_id);
     psFree(object->recipe);
+    psFree(object->b1_uri);
+    psFree(object->b2_uri);
 }
 
@@ -17096,6 +17249,26 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "keep", PS_DATA_BOOL, NULL, false)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item keep");
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "b1_uri", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "b2_uri", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
         psFree(md);
         return false;
@@ -17119,5 +17292,5 @@
 }
 
-bool detResidExpInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *exp_id, const char *recipe, bool keep, bool accept)
+bool detResidExpInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *exp_id, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, const char *b1_uri, const char *b2_uri, bool accept)
 {
     psMetadata      *md;
@@ -17145,6 +17318,26 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "keep", PS_DATA_BOOL, NULL, keep)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item keep");
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, bg)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, bg_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, bg_mean_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "b1_uri", 0, NULL, b1_uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "b2_uri", 0, NULL, b2_uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
         psFree(md);
         return false;
@@ -17176,5 +17369,5 @@
     return deleted;
 }
-bool detResidExpPop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **exp_id, char **recipe, bool *keep, bool *accept)
+bool detResidExpPop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **exp_id, char **recipe, psF64 *bg, psF64 *bg_stdev, psF64 *bg_mean_stdev, char **b1_uri, char **b2_uri, bool *accept)
 {
     psArray         *rowSet;
@@ -17244,7 +17437,31 @@
         return false;
     }
-    *keep = psMetadataLookupBool(&status, row, "keep");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item keep");
+    *bg = psMetadataLookupF64(&status, row, "bg");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg");
+        psFree(row);
+        return false;
+    }
+    *bg_stdev = psMetadataLookupF64(&status, row, "bg_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_stdev");
+        psFree(row);
+        return false;
+    }
+    *bg_mean_stdev = psMetadataLookupF64(&status, row, "bg_mean_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_mean_stdev");
+        psFree(row);
+        return false;
+    }
+    *b1_uri = psMetadataLookupPtr(&status, row, "b1_uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b1_uri");
+        psFree(row);
+        return false;
+    }
+    *b2_uri = psMetadataLookupPtr(&status, row, "b2_uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b2_uri");
         psFree(row);
         return false;
@@ -17264,5 +17481,5 @@
 bool detResidExpInsertObject(psDB *dbh, detResidExpRow *object)
 {
-    return detResidExpInsert(dbh, object->det_id, object->iteration, object->exp_id, object->recipe, object->keep, object->accept);
+    return detResidExpInsert(dbh, object->det_id, object->iteration, object->exp_id, object->recipe, object->bg, object->bg_stdev, object->bg_mean_stdev, object->b1_uri, object->b2_uri, object->accept);
 }
 
@@ -17284,13 +17501,17 @@
     char            exp_id[256];
     char            recipe[256];
-    bool            keep;
+    psF64           bg;
+    psF64           bg_stdev;
+    psF64           bg_mean_stdev;
+    char            b1_uri[256];
+    char            b2_uri[256];
     bool            accept;
 
-    if (!detResidExpPop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&recipe, &keep, &accept)) {
+    if (!detResidExpPop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&recipe, &bg, &bg_stdev, &bg_mean_stdev, (char **)&b1_uri, (char **)&b2_uri, &accept)) {
         psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
         return NULL;
     }
 
-    return detResidExpRowAlloc(det_id, iteration, exp_id, recipe, keep, accept);
+    return detResidExpRowAlloc(det_id, iteration, exp_id, recipe, bg, bg_stdev, bg_mean_stdev, b1_uri, b2_uri, accept);
 }
 
@@ -17411,6 +17632,26 @@
         return NULL;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "keep", PS_DATA_BOOL, NULL, object->keep)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item keep");
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, object->bg)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, object->bg_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, object->bg_mean_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "b1_uri", 0, NULL, object->b1_uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "b2_uri", 0, NULL, object->b2_uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
         psFree(md);
         return NULL;
@@ -17432,5 +17673,9 @@
     char            *exp_id;
     char            *recipe;
-    bool            keep;
+    psF64           bg;
+    psF64           bg_stdev;
+    psF64           bg_mean_stdev;
+    char            *b1_uri;
+    char            *b2_uri;
     bool            accept;
 
@@ -17455,7 +17700,27 @@
         return false;
     }
-    keep = psMetadataLookupBool(&status, md, "keep");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item keep");
+    bg = psMetadataLookupF64(&status, md, "bg");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg");
+        return false;
+    }
+    bg_stdev = psMetadataLookupF64(&status, md, "bg_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_stdev");
+        return false;
+    }
+    bg_mean_stdev = psMetadataLookupF64(&status, md, "bg_mean_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_mean_stdev");
+        return false;
+    }
+    b1_uri = psMetadataLookupPtr(&status, md, "b1_uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b1_uri");
+        return false;
+    }
+    b2_uri = psMetadataLookupPtr(&status, md, "b2_uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b2_uri");
         return false;
     }
@@ -17466,5 +17731,5 @@
     }
 
-    return detResidExpRowAlloc(det_id, iteration, exp_id, recipe, keep, accept);
+    return detResidExpRowAlloc(det_id, iteration, exp_id, recipe, bg, bg_stdev, bg_mean_stdev, b1_uri, b2_uri, accept);
 }
 psArray *detResidExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
@@ -17571,2 +17836,531 @@
     return true;
 }
+static void detRunSummaryRowFree(detRunSummaryRow *object);
+
+detRunSummaryRow *detRunSummaryRowAlloc(psS32 det_id, psS32 iteration, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, bool accept)
+{
+    detRunSummaryRow *object;
+
+    object = psAlloc(sizeof(detRunSummaryRow));
+    psMemSetDeallocator(object, (psFreeFunc)detRunSummaryRowFree);
+
+    object->det_id = det_id;
+    object->iteration = iteration;
+    object->bg = bg;
+    object->bg_stdev = bg_stdev;
+    object->bg_mean_stdev = bg_mean_stdev;
+    object->accept = accept;
+
+    return object;
+}
+
+static void detRunSummaryRowFree(detRunSummaryRow *object)
+{
+}
+
+bool detRunSummaryCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETRUNSUMMARY_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETRUNSUMMARY_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, false)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETRUNSUMMARY_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detRunSummaryDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETRUNSUMMARY_TABLE_NAME);
+}
+
+bool detRunSummaryInsert(psDB * dbh, psS32 det_id, psS32 iteration, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, bool accept)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, bg)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, bg_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, bg_mean_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, accept)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETRUNSUMMARY_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+long long detRunSummaryDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    long long count = psDBDeleteRows(dbh, DETRUNSUMMARY_TABLE_NAME, where, limit);
+    if (count < 0) {
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from detRunSummary");
+        return count;
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+bool detRunSummaryPop(psDB *dbh, psS32 *det_id, psS32 *iteration, psF64 *bg, psF64 *bg_stdev, psF64 *bg_mean_stdev, bool *accept)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETRUNSUMMARY_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETRUNSUMMARY_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETRUNSUMMARY_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETRUNSUMMARY_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETRUNSUMMARY_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETRUNSUMMARY_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_id = psMetadataLookupS32(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        psFree(row);
+        return false;
+    }
+    *iteration = psMetadataLookupS32(&status, row, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        psFree(row);
+        return false;
+    }
+    *bg = psMetadataLookupF64(&status, row, "bg");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg");
+        psFree(row);
+        return false;
+    }
+    *bg_stdev = psMetadataLookupF64(&status, row, "bg_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_stdev");
+        psFree(row);
+        return false;
+    }
+    *bg_mean_stdev = psMetadataLookupF64(&status, row, "bg_mean_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_mean_stdev");
+        psFree(row);
+        return false;
+    }
+    *accept = psMetadataLookupBool(&status, row, "accept");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item accept");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detRunSummaryInsertObject(psDB *dbh, detRunSummaryRow *object)
+{
+    return detRunSummaryInsert(dbh, object->det_id, object->iteration, object->bg, object->bg_stdev, object->bg_mean_stdev, object->accept);
+}
+
+bool detRunSummaryInsertObjects(psDB *dbh, psArray *objects)
+{
+    for (long i = 0; i < psArrayLength(objects); i++) {
+        if (!detRunSummaryInsertObject(dbh, objects->data[i])) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+detRunSummaryRow *detRunSummaryPopObject(psDB *dbh)
+{
+    psS32           det_id;
+    psS32           iteration;
+    psF64           bg;
+    psF64           bg_stdev;
+    psF64           bg_mean_stdev;
+    bool            accept;
+
+    if (!detRunSummaryPop(dbh, &det_id, &iteration, &bg, &bg_stdev, &bg_mean_stdev, &accept)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detRunSummaryRowAlloc(det_id, iteration, bg, bg_stdev, bg_mean_stdev, accept);
+}
+
+bool detRunSummaryInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETRUNSUMMARY_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETRUNSUMMARY_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETRUNSUMMARY_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETRUNSUMMARY_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detRunSummaryPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detRunSummarySelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETRUNSUMMARY_TABLE_NAME, DETRUNSUMMARY_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detRunSummarySelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETRUNSUMMARY_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETRUNSUMMARY_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETRUNSUMMARY_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETRUNSUMMARY_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detRunSummaryMetadataFromObject(const detRunSummaryRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, object->det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, object->iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg", 0, NULL, object->bg)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_stdev", 0, NULL, object->bg_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "bg_mean_stdev", 0, NULL, object->bg_mean_stdev)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, object->accept)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detRunSummaryRow *detRunSummaryObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psS32           det_id;
+    psS32           iteration;
+    psF64           bg;
+    psF64           bg_stdev;
+    psF64           bg_mean_stdev;
+    bool            accept;
+
+    det_id = psMetadataLookupS32(&status, md, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        return false;
+    }
+    iteration = psMetadataLookupS32(&status, md, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        return false;
+    }
+    bg = psMetadataLookupF64(&status, md, "bg");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg");
+        return false;
+    }
+    bg_stdev = psMetadataLookupF64(&status, md, "bg_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_stdev");
+        return false;
+    }
+    bg_mean_stdev = psMetadataLookupF64(&status, md, "bg_mean_stdev");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_mean_stdev");
+        return false;
+    }
+    accept = psMetadataLookupBool(&status, md, "accept");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item accept");
+        return false;
+    }
+
+    return detRunSummaryRowAlloc(det_id, iteration, bg, bg_stdev, bg_mean_stdev, accept);
+}
+psArray *detRunSummarySelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETRUNSUMMARY_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETRUNSUMMARY_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETRUNSUMMARY_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        detRunSummaryRow *object = detRunSummaryObjectFromMetadata(rowSet->data[i]);
+        psArrayAdd(returnSet, 0, object);
+        psFree(object);
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+bool detRunSummaryDeleteObject(psDB *dbh, const detRunSummaryRow *object)
+{
+    psMetadata *where = detRunSummaryMetadataFromObject(object);
+    long long count = psDBDeleteRows(dbh, DETRUNSUMMARY_TABLE_NAME, where, 0);
+    psFree(where)
+    if (count < 0) {
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from detRunSummary");
+        return false;
+    }
+    if (count > 1) {
+        // XXX should this be a psAbort() instead?  It is possible that
+        // having an object match multiple rows was by design.
+        psError(PS_ERR_UNKNOWN, true, "detRunSummaryRow object matched more then one row.  Check your database schema");
+        return false;
+    }
+
+    return true;
+}
+long long detRunSummaryDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detRunSummaryRow *object = objects->data[i];
+        psMetadata *where = detRunSummaryMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETRUNSUMMARY_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detRunSummary");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+bool detRunSummaryPrintObjects(FILE *stream, psArray *objects, bool mdcf)
+{
+    PS_ASSERT_PTR_NON_NULL(objects, false);
+
+    psMetadata *output = psMetadataAlloc();
+    for (long i = 0; i < psArrayLength(objects); i++) {
+        psMetadata *md = detRunSummaryMetadataFromObject(objects->data[i]);
+        if (!psMetadataAddMetadata(
+            output,
+            PS_LIST_TAIL,
+            DETRUNSUMMARY_TABLE_NAME,
+            PS_META_DUPLICATE_OK,
+            NULL,
+            md
+        )) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
+            psFree(md);
+            psFree(output);
+            return false;
+        }
+        psFree(md);
+    }
+
+    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
+        psFree(output);
+    }
+    psFree(output);
+
+    return true;
+}
