Index: /branches/eam_branch_20080719/ippTools/src/Makefile.am
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/Makefile.am	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/Makefile.am	(revision 18641)
@@ -180,5 +180,14 @@
     dettool.c \
     dettoolConfig.c \
-    dettool_correction.c
+    dettool_correction.c \
+    dettool_detrunsummary.c \
+    dettool_normalizedexp.c \
+    dettool_normalizedimfile.c \
+    dettool_normalizedstat.c \
+    dettool_processedexp.c \
+    dettool_processedimfile.c \
+    dettool_residexp.c \
+    dettool_residimfile.c \
+    dettool_stack.c
 
 detselect_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
Index: /branches/eam_branch_20080719/ippTools/src/dettool.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool.c	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/dettool.c	(revision 18641)
@@ -28,51 +28,5 @@
 static bool inputMode(pxConfig *config);
 static bool rawMode(pxConfig *config);
-// processedimfile
-static bool toprocessedimfileMode(pxConfig *config);
-static bool addprocessedimfileMode(pxConfig *config);
-static bool processedimfileMode(pxConfig *config);
-static bool revertprocessedimfileMode(pxConfig *config);
-// processedexp
-static bool toprocessedexpMode(pxConfig *config);
-static bool addprocessedexpMode(pxConfig *config);
-static bool processedexpMode(pxConfig *config);
-static bool revertprocessedexpMode(pxConfig *config);
-// stackedimfile
-static bool tostackedMode(pxConfig *config);
-static bool addstackedMode(pxConfig *config);
-static bool stackedMode(pxConfig *config);
-static bool revertstackedMode(pxConfig *config);
-// normalizedstat
-static bool tonormalizedstatMode(pxConfig *config);
-static bool addnormalizedstatMode(pxConfig *config);
-static bool normalizedstatMode(pxConfig *config);
-static bool revertnormalizedstatMode(pxConfig *config);
-// normalizedimfile
-static bool tonormalizeMode(pxConfig *config);
-static bool addnormalizedimfileMode(pxConfig *config);
-static bool normalizedimfileMode(pxConfig *config);
-static bool revertnormalizedimfileMode(pxConfig *config);
-// normalizedexp
-static bool tonormalizedexpMode(pxConfig *config);
-static bool addnormalizedexpMode(pxConfig *config);
-static bool normalizedexpMode(pxConfig *config);
-static bool revertnormalizedexpMode(pxConfig *config);
-// residimfile
-static bool toresidimfileMode(pxConfig *config);
-static bool addresidimfileMode(pxConfig *config);
-static bool residimfileMode(pxConfig *config);
-static bool revertresidimfileMode(pxConfig *config);
-// residexp
-static bool toresidexpMode(pxConfig *config);
-static bool addresidexpMode(pxConfig *config);
-static bool residexpMode(pxConfig *config);
-static bool revertresidexpMode(pxConfig *config);
-static bool updateresidexpMode(pxConfig *config);
-// detrunsummary
-static bool todetrunsummaryMode(pxConfig *config);
-static bool adddetrunsummaryMode(pxConfig *config);
-static bool detrunsummaryMode(pxConfig *config);
-static bool revertdetrunsummaryMode(pxConfig *config);
-static bool updatedetrunsummaryMode(pxConfig *config);
+
 // run
 static bool updatedetrunMode(pxConfig *config);
@@ -81,12 +35,8 @@
 static bool register_detrendMode(pxConfig *config);
 
-static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row);
 //static psArray *validDetInputClassIds(pxConfig *config, const char *det_id);
 //static psArray *searchInputImfiles(pxConfig *config, const char *det_id);
 static detInputExpRow *rawDetrenTodetInputExpRow(rawExpRow *rawExp, psS64 det_id, psS32 iteration);
-static psArray *searchRawImfiles(pxConfig *config);
-static bool startNewIteration(pxConfig *config, psS64 det_id);
 static psS32 incrementIteration(pxConfig *config, psS64 det_id);
-static bool setDetRunState(pxConfig *config, psS64 det_id, const char *state);
 static bool isValidMode(pxConfig *config, const char *mode);
 
@@ -1251,348 +1201,4 @@
 }
 
-
-
-
-/* The SQL returns a list of detrend runs (with detrend id, iteration and detrend type) which
- * have completed all residexps.
- */
-
-static bool todetrunsummaryMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
-    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
-
-    psString query = pxDataGet("dettool_todetrunsummary.sql");
-    if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
-    // treat limit == 0 as "no limit"
-    if (limit) {
-        psString limitString = psDBGenerateLimitSQL(limit);
-        psStringAppend(&query, " %s", limitString);
-        psFree(limitString);
-    }
-
-    if (!p_psDBRunQuery(config->dbh, query)) {
-        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)) {
-        psTrace("dettool", PS_LOG_INFO, "no rows found");
-        psFree(output);
-        return true;
-    }
-
-    // negative simple so the default is true
-    if (!ippdbPrintMetadatas(stdout, output, "detRejectExp", !simple)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to print array");
-        psFree(output);
-        return false;
-    }
-
-    psFree(output);
-
-    return true;
-}
-
-// this function is used to generate the detrunSummary entries used below
-// XXX why is this a separate function?  roll it back into adddetrunsummary?
-static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    bool status = false;
-    // from row
-    psS64 det_id = psMetadataLookupS64(&status, row, "det_id");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for det_id");
-        return false;
-    }
-    psS32 iteration = psMetadataLookupS32(&status, row, "iteration");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for iteration");
-        return false;
-    }
-
-    // optional
-    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
-    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
-    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
-
-    // default values
-    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
-    PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
-
-    return detRunSummaryRowAlloc(
-            det_id,
-            iteration,
-            bg,
-            bg_stdev,
-            bg_mean_stdev,
-            accept,
-            code
-        );
-}
-
-static bool adddetrunsummaryMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-    
-    // build a query to search by det_id, iteration, exp_id
-    psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
-    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
-
-    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
-    PXOPT_LOOKUP_BOOL(again, config->args, "-again", false);
-
-    // The values supplied as arguments on the command (eg, -bg) are parsed 
-    // by mdToDetRunSummary below. 
-    // XXX why is there ever more than one?
-
-    psString query = pxDataGet("dettool_find_completed_runs.sql");
-    if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
-    if (psListLength(where->list)) {
-        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-	psStringAppend(&query, " WHERE %s", whereClause);
-	psFree(whereClause);
-    }
-    psFree(where);
-
-    if (!p_psDBRunQuery(config->dbh, query)) {
-        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)) {
-        psTrace("dettool", PS_LOG_INFO, "no rows found");
-        psFree(output);
-        return true;
-    }
-
-    // start a transaction so it's all rows or nothing
-    if (!psDBTransaction(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(output);
-        return false;
-    }
-
-    // XXX why is there ever more than one result here?
-    for (long i = 0; i < psArrayLength(output); i++) {
-        psMetadata *row = output->data[i];
-        // convert metadata into a detResidExp object
-        detRunSummaryRow *runSummary = mdToDetRunSummary(config, row);
-        if (!runSummary) {
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata to detResidExp");
-            psFree(output);
-            return false;
-        }
-        // insert detResidExp object into the database
-        if (!detRunSummaryInsertObject(config->dbh, runSummary)) {
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(runSummary);
-            psFree(output);
-            return false;
-        }
-        psFree(runSummary);
-    }
-
-    psFree(output);
-
-    // XXX this logic does not deal with the case of -code being set
-    // XXX it should be an error for -again and -code to both be set
-    if (again) {
-        if (!startNewIteration(config, (psS64)atoll(det_id))) {
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "failed to start new iteration");
-            return false;
-        }
-    } else {
-        // set detRun.state to stop
-        if (!setDetRunState(config, (psS64)atoll(det_id), "stop")) {
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "failed to set detRun.state");
-            return false;
-        }
-    }
-
-    if (!psDBCommit(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-    return true;
-}
-
-static bool detrunsummaryMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
-    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
-
-    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
-    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
-    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
-
-    psString query = pxDataGet("dettool_detrunsummary.sql");
-    if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        psFree(where);
-        return false;
-    }
-
-    if (psListLength(where->list)) {
-        psString whereClause = psDBGenerateWhereConditionSQL(where, "NULL");
-        psStringAppend(&query, " AND %s", whereClause);
-        psFree(whereClause);
-    }
-    psFree(where);
-
-    if (faulted) {
-        // list only faulted rows
-        psStringAppend(&query, " %s", "AND detRunSummary.fault != 0");
-    } else {
-        // don't list faulted rows
-        psStringAppend(&query, " %s", "AND detRunSummary.fault = 0");
-    }
-
-    // treat limit == 0 as "no limit"
-    if (limit) {
-        psString limitString = psDBGenerateLimitSQL(limit);
-        psStringAppend(&query, " %s", limitString);
-        psFree(limitString);
-    }
-
-    if (!p_psDBRunQuery(config->dbh, query)) {
-        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)) {
-        psTrace("dettool", PS_LOG_INFO, "no rows found");
-        psFree(output);
-        return true;
-    }
-
-    // negative simple so the default is true
-    if (!ippdbPrintMetadatas(stdout, output, "rawDetrendImfile", !simple)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to print array");
-        psFree(output);
-        return false;
-    }
-
-    psFree(output);
-
-    return true;
-}
-
-
-static bool revertdetrunsummaryMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
-    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
-    PXOPT_COPY_STR(config->args, where, "-code",      "fault", "==");
-
-    psString query = pxDataGet("dettool_revertdetrunsummary.sql");
-    if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
-    if (psListLength(where->list)) {
-        psString whereClause = psDBGenerateWhereConditionSQL(where, "detRunSummary");
-        psStringAppend(&query, " AND %s", whereClause);
-        psFree(whereClause);
-    }
-    psFree(where);
-
-    if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(query);
-        return false;
-    }
-    psFree(query);
-
-    if (psDBAffectedRows(config->dbh) < 1) {
-        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
-        return false;
-    }
-
-    return true;
-}
-
-
-static bool updatedetrunsummaryMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-    
-    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
-    PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
-    PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
-
-    if (accept && reject) {
-        psError(PS_ERR_UNKNOWN, true, "-accept and -reject are exclusive");
-        return false;
-    }
-
-    if (!(accept || reject)) {
-        psError(PS_ERR_UNKNOWN, true, "either -accept or -reject is required");
-        return false;
-    }
-
-    char *query = "UPDATE detRunSummary SET accept = %d WHERE det_id = %"PRId64; 
-    if (!p_psDBRunQuery(config->dbh, query, accept, (psS64)atoll(det_id))) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
-    return true;
-}
-
-
 static bool updatedetrunMode(pxConfig *config)
 {
@@ -1629,5 +1235,5 @@
 
 // used by updatedetrunMode 
-static bool startNewIteration(pxConfig *config, psS64 det_id)
+bool startNewIteration(pxConfig *config, psS64 det_id)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -2077,5 +1683,5 @@
 }
 
-static bool setDetRunState(pxConfig *config, psS64 det_id, const char *state)
+bool setDetRunState(pxConfig *config, psS64 det_id, const char *state)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
Index: /branches/eam_branch_20080719/ippTools/src/dettool_detrunsummary.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool_detrunsummary.c	(revision 18641)
+++ /branches/eam_branch_20080719/ippTools/src/dettool_detrunsummary.c	(revision 18641)
@@ -0,0 +1,364 @@
+/*
+ * dettool_detrunsummary.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row);
+
+/* The SQL returns a list of detrend runs (with detrend id, iteration and detrend type) which
+ * have completed all residexps.
+ */
+
+bool todetrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("dettool_todetrunsummary.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        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)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "detRejectExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+// this function is used to generate the detrunSummary entries used below
+// XXX why is this a separate function?  roll it back into adddetrunsummary?
+static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    bool status = false;
+    // from row
+    psS64 det_id = psMetadataLookupS64(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for det_id");
+        return false;
+    }
+    psS32 iteration = psMetadataLookupS32(&status, row, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for iteration");
+        return false;
+    }
+
+    // optional
+    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
+    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
+    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
+
+    // default values
+    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
+    PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
+
+    return detRunSummaryRowAlloc(
+            det_id,
+            iteration,
+            bg,
+            bg_stdev,
+            bg_mean_stdev,
+            accept,
+            code
+        );
+}
+
+bool adddetrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    
+    // build a query to search by det_id, iteration, exp_id
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+
+    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_BOOL(again, config->args, "-again", false);
+
+    // The values supplied as arguments on the command (eg, -bg) are parsed 
+    // by mdToDetRunSummary below. 
+    // XXX why is there ever more than one?
+
+    psString query = pxDataGet("dettool_find_completed_runs.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+	psStringAppend(&query, " WHERE %s", whereClause);
+	psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        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)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // start a transaction so it's all rows or nothing
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    // XXX why is there ever more than one result here?
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *row = output->data[i];
+        // convert metadata into a detResidExp object
+        detRunSummaryRow *runSummary = mdToDetRunSummary(config, row);
+        if (!runSummary) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata to detResidExp");
+            psFree(output);
+            return false;
+        }
+        // insert detResidExp object into the database
+        if (!detRunSummaryInsertObject(config->dbh, runSummary)) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(runSummary);
+            psFree(output);
+            return false;
+        }
+        psFree(runSummary);
+    }
+
+    psFree(output);
+
+    // XXX this logic does not deal with the case of -code being set
+    // XXX it should be an error for -again and -code to both be set
+    if (again) {
+        if (!startNewIteration(config, (psS64)atoll(det_id))) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to start new iteration");
+            return false;
+        }
+    } else {
+        // set detRun.state to stop
+        if (!setDetRunState(config, (psS64)atoll(det_id), "stop")) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to set detRun.state");
+            return false;
+        }
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    return true;
+}
+
+bool detrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+
+    psString query = pxDataGet("dettool_detrunsummary.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "NULL");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND detRunSummary.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND detRunSummary.fault = 0");
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        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)) {
+        psTrace("dettool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "rawDetrendImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+bool revertdetrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
+    PXOPT_COPY_STR(config->args, where, "-code",      "fault", "==");
+
+    psString query = pxDataGet("dettool_revertdetrunsummary.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "detRunSummary");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool updatedetrunsummaryMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    
+    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
+    PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
+    PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
+
+    if (accept && reject) {
+        psError(PS_ERR_UNKNOWN, true, "-accept and -reject are exclusive");
+        return false;
+    }
+
+    if (!(accept || reject)) {
+        psError(PS_ERR_UNKNOWN, true, "either -accept or -reject is required");
+        return false;
+    }
+
+    char *query = "UPDATE detRunSummary SET accept = %d WHERE det_id = %"PRId64; 
+    if (!p_psDBRunQuery(config->dbh, query, accept, (psS64)atoll(det_id))) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
Index: /branches/eam_branch_20080719/ippTools/src/dettool_normalizedexp.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool_normalizedexp.c	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/dettool_normalizedexp.c	(revision 18641)
@@ -1,4 +1,24 @@
-
-static bool tonormalizedexpMode(pxConfig *config)
+/*
+ * dettool_normalizedexp.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool tonormalizedexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -49,5 +69,5 @@
     return true;
 }
-static bool addnormalizedexpMode(pxConfig *config)
+bool addnormalizedexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -119,5 +139,5 @@
 
 
-static bool normalizedexpMode(pxConfig *config)
+bool normalizedexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -192,5 +212,5 @@
 
 
-static bool revertnormalizedexpMode(pxConfig *config)
+bool revertnormalizedexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
Index: /branches/eam_branch_20080719/ippTools/src/dettool_normalizedimfile.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool_normalizedimfile.c	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/dettool_normalizedimfile.c	(revision 18641)
@@ -1,4 +1,25 @@
-
-static bool tonormalizeMode(pxConfig *config)
+/*
+ * dettool_normalizedimfile.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+// XXX this one is inconsistent - rename 'tonormalizedimfile' and change ipp_serial_detrend.pl and detrend.norm.pro
+bool tonormalizeMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -50,5 +71,5 @@
 }
 
-static bool addnormalizedimfileMode(pxConfig *config)
+bool addnormalizedimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -98,5 +119,5 @@
 }
 
-static bool normalizedimfileMode(pxConfig *config)
+bool normalizedimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -170,5 +191,5 @@
 }
 
-static bool revertnormalizedimfileMode(pxConfig *config)
+bool revertnormalizedimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
Index: /branches/eam_branch_20080719/ippTools/src/dettool_normalizedstat.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool_normalizedstat.c	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/dettool_normalizedstat.c	(revision 18641)
@@ -1,3 +1,24 @@
-static bool tonormalizedstatMode(pxConfig *config)
+/*
+ * dettool_normalizedstat.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool tonormalizedstatMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -49,5 +70,5 @@
 }
 
-static bool addnormalizedstatMode(pxConfig *config)
+bool addnormalizedstatMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, NULL);
@@ -79,5 +100,5 @@
 
 
-static bool normalizedstatMode(pxConfig *config)
+bool normalizedstatMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -150,5 +171,5 @@
 }
 
-static bool revertnormalizedstatMode(pxConfig *config)
+bool revertnormalizedstatMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
Index: /branches/eam_branch_20080719/ippTools/src/dettool_processedexp.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool_processedexp.c	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/dettool_processedexp.c	(revision 18641)
@@ -1,3 +1,24 @@
-static bool toprocessedexpMode(pxConfig *config)
+/*
+ * dettool_processedexp.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool toprocessedexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -49,5 +70,5 @@
 }
 
-static bool addprocessedexpMode(pxConfig *config)
+bool addprocessedexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -135,5 +156,5 @@
 }
 
-static bool processedexpMode(pxConfig *config)
+bool processedexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -202,5 +223,5 @@
 
 
-static bool revertprocessedexpMode(pxConfig *config)
+bool revertprocessedexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
Index: /branches/eam_branch_20080719/ippTools/src/dettool_processedimfile.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool_processedimfile.c	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/dettool_processedimfile.c	(revision 18641)
@@ -1,4 +1,24 @@
-
-static bool toprocessedimfileMode(pxConfig *config)
+/*
+ * dettool_processedimfile.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool toprocessedimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -62,5 +82,5 @@
 }
 
-static bool addprocessedimfileMode(pxConfig *config)
+bool addprocessedimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -140,5 +160,5 @@
 }
 
-static bool processedimfileMode(pxConfig *config)
+bool processedimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -236,5 +256,5 @@
 }
 
-static bool revertprocessedimfileMode(pxConfig *config)
+bool revertprocessedimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
Index: /branches/eam_branch_20080719/ippTools/src/dettool_residexp.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool_residexp.c	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/dettool_residexp.c	(revision 18641)
@@ -1,2 +1,23 @@
+/*
+ * dettool_residexp.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
 /*
   The SQL returns a list of exposures for which all component class ids have had residuals
@@ -5,5 +26,5 @@
 */
 
-static bool toresidexpMode(pxConfig *config)
+bool toresidexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -61,5 +82,5 @@
 */
 
-static bool addresidexpMode(pxConfig *config)
+bool addresidexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -162,5 +183,5 @@
 }
 
-static bool residexpMode(pxConfig *config)
+bool residexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -242,5 +263,5 @@
 
 
-static bool revertresidexpMode(pxConfig *config)
+bool revertresidexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -281,5 +302,5 @@
 
 
-static bool updateresidexpMode(pxConfig *config)
+bool updateresidexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
Index: /branches/eam_branch_20080719/ippTools/src/dettool_residimfile.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool_residimfile.c	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/dettool_residimfile.c	(revision 18641)
@@ -1,3 +1,24 @@
-static bool toresidimfileMode(pxConfig *config)
+/*
+ * dettool_residimfile.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+bool toresidimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -50,5 +71,5 @@
 
 
-static bool addresidimfileMode(pxConfig *config)
+bool addresidimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -116,5 +137,5 @@
 
 
-static bool residimfileMode(pxConfig *config)
+bool residimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -199,5 +220,5 @@
 
 
-static bool revertresidimfileMode(pxConfig *config)
+bool revertresidimfileMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
Index: /branches/eam_branch_20080719/ippTools/src/dettool_stack.c
===================================================================
--- /branches/eam_branch_20080719/ippTools/src/dettool_stack.c	(revision 18640)
+++ /branches/eam_branch_20080719/ippTools/src/dettool_stack.c	(revision 18641)
@@ -1,3 +1,26 @@
-static bool tostackedMode(pxConfig *config)
+/*
+ * dettool_stack.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt & EAM; IfA
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dettool.h"
+
+static psArray *searchRawImfiles(pxConfig *config);
+
+bool tostackedMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -95,5 +118,5 @@
 }
 
-static bool addstackedMode(pxConfig *config)
+bool addstackedMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -180,5 +203,5 @@
 }
 
-static bool stackedMode(pxConfig *config)
+bool stackedMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -254,5 +277,5 @@
 
 
-static bool revertstackedMode(pxConfig *config)
+bool revertstackedMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
