Index: branches/tap_branches/ippTools/src/stacktool.c
===================================================================
--- branches/tap_branches/ippTools/src/stacktool.c	(revision 25900)
+++ branches/tap_branches/ippTools/src/stacktool.c	(revision 27838)
@@ -124,4 +124,5 @@
 
     // select based on properties of the raw exposures
+    PXOPT_COPY_STR(config->args,  where, "-select_comment",            "rawExp.comment", "LIKE");
     PXOPT_COPY_STR(config->args,  where, "-select_inst",               "rawExp.camera", "==");
     PXOPT_COPY_STR(config->args,  where, "-select_telescope",          "rawExp.telescope", "==");
@@ -145,17 +146,26 @@
     PXOPT_COPY_F32(config->args,  where, "-select_fwhm_minor_min",     "camProcessedExp.fwhm_minor", ">=");
     PXOPT_COPY_F32(config->args,  where, "-select_fwhm_minor_max",     "camProcessedExp.fwhm_minor", "<=");
-    PXOPT_COPY_F32(config->args,  where, "-select_iq_m2_max",     "camProcessedExp.iq_m2", "<=");
-    PXOPT_COPY_F32(config->args,  where, "-select_iq_m2_min",     "camProcessedExp.iq_m2", ">=");
-    PXOPT_COPY_F32(config->args,  where, "-select_iq_m3_max",     "camProcessedExp.iq_m3", "<=");
-    PXOPT_COPY_F32(config->args,  where, "-select_iq_m4_min",     "camProcessedExp.iq_m4", ">=");
-    PXOPT_COPY_F32(config->args,  where, "-select_iq_m4_max",     "camProcessedExp.iq_m4", "<=");
-    
+    PXOPT_COPY_F32(config->args,  where, "-select_iq_m2_max",          "camProcessedExp.iq_m2", "<=");
+    PXOPT_COPY_F32(config->args,  where, "-select_iq_m2_min",          "camProcessedExp.iq_m2", ">=");
+    PXOPT_COPY_F32(config->args,  where, "-select_iq_m3_max",          "camProcessedExp.iq_m3", "<=");
+    PXOPT_COPY_F32(config->args,  where, "-select_iq_m4_min",          "camProcessedExp.iq_m4", ">=");
+    PXOPT_COPY_F32(config->args,  where, "-select_iq_m4_max",          "camProcessedExp.iq_m4", "<=");
+
     PXOPT_COPY_STR(config->args,  where, "-select_exp_type",           "rawExp.exp_type", "==");
     PXOPT_COPY_F32(config->args,  where, "-select_good_frac_min",      "warpSkyfile.good_frac", ">=");
     PXOPT_COPY_STR(config->args,  where, "-select_skycell_id",         "warpSkyfile.skycell_id", "==");
-    pxAddLabelSearchArgs (config, where, "-select_label",              "warpRun.label", "LIKE");
+    PXOPT_COPY_STR(config->args,  where, "-select_data_group",         "warpRun.data_group", "==");
+    pxAddLabelSearchArgs (config, where, "-select_label",              "warpRun.label", "LIKE"); // define using warp label
 
     // these are used to build the HAVING restriction
     PXOPT_COPY_S32(config->args, having, "-min_num", "num_warp", ">=");
+    PXOPT_LOOKUP_S32(min_num,     config->args, "-min_num",  false, false);
+    if (min_num < 2) {
+        psError(PXTOOLS_ERR_CONFIG, true, "Require at least two inputs for a stack, but min_num = %d",
+                min_num);
+        psFree(where);
+        psFree(having);
+        return false;
+    }
 
     // other options applied outside of the WHERE
@@ -168,29 +178,29 @@
 
     if (!psListLength(where->list)) {
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
         psFree(where);
-        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
-        return false;
-    }
-
-    psString select = pxDataGet("stacktool_definebyquery_part1.sql");
+        psFree(having);
+        return false;
+    }
+
+    psString select = pxDataGet("stacktool_definebyquery_select.sql");
     if (!select) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        psFree(where);
+        psFree(having);
+        return false;
+    }
+
+    psString where1 = psStringCopy("");
     if (psListLength(where->list)) {
         psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-        psStringAppend(&select, " AND %s", whereClause);
+        psStringAppend(&where1, "\nAND %s", whereClause);
         psFree(whereClause);
     }
 
-    psString groupby = pxDataGet("stacktool_definebyquery_part2.sql");
-    if (!groupby) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        psFree(where);
-        return false;
-    }
-    psStringAppend(&select, " %s", groupby);
-    psFree(groupby);
+    psString where2 = psStringCopy("");
+    if (label) {
+        psStringAppend(&where2, "\nWHERE stackRun.label = '%s'", label);
+    }
 
     // Restriction on aggregated quantities using HAVING
@@ -224,11 +234,14 @@
     psFree(having);
 
-    if (!p_psDBRunQuery(config->dbh, select)) {
+    if (!p_psDBRunQueryF(config->dbh, select, where1, where2)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
         psFree(select);
-        psFree(where);
+        psFree(where1);
+        psFree(where2);
         return false;
     }
     psFree(select);
+    psFree(where1);
+    psFree(where2);
 
     psArray *output = p_psDBFetchResult(config->dbh);
@@ -272,5 +285,5 @@
     }
     if (!insert) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
         psFree(where);
         return false;
@@ -287,5 +300,5 @@
         psString part2 = pxDataGet("stacktool_definebyquery_insert_random_part2.sql");
         if (!part2) {
-            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
             psFree(insert);
             return false;
@@ -593,5 +606,5 @@
     if (!psListLength(where->list)) {
         psFree(where);
-        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
         return false;
     }
@@ -600,5 +613,5 @@
 
     // pxUpdateRun gets parameters from config->args and updates
-    bool result = pxUpdateRun(config, where, &query, "stackRun", true);
+    bool result = pxUpdateRun(config, where, &query, "stackRun", "stack_id", "stackSumSkyfile", true);
 
     psFree(query);
@@ -663,5 +676,5 @@
     psString query = pxDataGet("stacktool_inputskyfile.sql");
     if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
         return false;
     }
@@ -669,5 +682,5 @@
     if (psListLength(where->list)) {
         psString whereClause = psDBGenerateWhereConditionSQL(where, "stackInputSkyfile");
-        psStringAppend(&query, " AND %s", whereClause);
+        psStringAppend(&query, " WHERE %s", whereClause);
         psFree(whereClause);
     }
@@ -737,12 +750,13 @@
     psString query = pxDataGet("stacktool_tosum.sql");
     if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    psString whereClause = psStringCopy(""); // WHERE conditions to add
     if (psListLength(where->list)) {
-        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-        psStringAppend(&query, " AND %s", whereClause);
-        psFree(whereClause);
+        psString new = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&whereClause, "\nAND %s", new);
+        psFree(new);
     }
     psFree(where);
@@ -755,5 +769,5 @@
     }
 
-    if (!p_psDBRunQuery(config->dbh, query)) {
+    if (!p_psDBRunQueryF(config->dbh, query, whereClause)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
         psFree(query);
@@ -908,4 +922,5 @@
     PXOPT_COPY_STR(config->args, where, "-filter", "stackRun.filter", "LIKE");
     PXOPT_COPY_STR(config->args, where, "-label", "stackRun.label", "==");
+    PXOPT_COPY_STR(config->args, where, "-data_group", "stackRun.data_group", "LIKE");
     PXOPT_COPY_S16(config->args, where, "-fault", "stackSumSkyfile.fault", "==");
 
@@ -922,5 +937,5 @@
     psString query = pxDataGet("stacktool_sumskyfile.sql");
     if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
         return false;
     }
@@ -931,5 +946,5 @@
         psFree(whereClause);
     } else if (!all) {
-        psError(PXTOOLS_ERR_DATA, true, "search parameters or -all are required");
+        psError(PXTOOLS_ERR_CONFIG, true, "search parameters or -all are required");
         return false;
     }
@@ -991,10 +1006,10 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-stack_id", "stackSumSkyfile.stack_id", "==");
-    PXOPT_COPY_STR(config->args, where, "-label", "stackRun.label", "==");
+    pxAddLabelSearchArgs(config, where, "-label", "stackRun.label", "==");
     PXOPT_COPY_S16(config->args, where, "-fault", "stackSumSkyfile.fault", "==");
 
     if (!psListLength(where->list) && !psMetadataLookupBool(NULL, config->args, "-all")) {
         psFree(where);
-        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
         return false;
     }
@@ -1003,5 +1018,5 @@
     psString delete = pxDataGet("stacktool_revertsumskyfile_delete.sql");
     if (!delete) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
         return false;
     }
@@ -1084,5 +1099,5 @@
     psString query = pxDataGet("stacktool_pendingcleanuprun.sql");
     if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
         return false;
     }
@@ -1148,5 +1163,5 @@
     psString query = pxDataGet("stacktool_pendingcleanupskyfile.sql");
     if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
         return false;
     }
@@ -1209,5 +1224,5 @@
     psString query = pxDataGet("stacktool_donecleanup.sql");
     if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
         return false;
     }
@@ -1313,5 +1328,5 @@
     psString query = pxDataGet(tables[i].sqlFilename);
     if (!query) {
-      psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+      psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
       return false;
     }
