Index: trunk/ippTools/share/Makefile.am
===================================================================
--- trunk/ippTools/share/Makefile.am	(revision 27389)
+++ trunk/ippTools/share/Makefile.am	(revision 27391)
@@ -38,4 +38,5 @@
      chiptool_run.sql \
      chiptool_runstate.sql \
+     chiptool_setimfiletoupdate.sql \
      chiptool_export_imfile.sql \
      chiptool_export_processed_imfile.sql \
Index: trunk/ippTools/share/chiptool_pendingimfile.sql
===================================================================
--- trunk/ippTools/share/chiptool_pendingimfile.sql	(revision 27389)
+++ trunk/ippTools/share/chiptool_pendingimfile.sql	(revision 27391)
@@ -33,5 +33,5 @@
     OR
     (chipRun.state = 'update'
-    AND chipProcessedImfile.data_state = 'cleaned'))
+    AND chipProcessedImfile.data_state = 'update'))
 -- // Restriction to prevent the processing of bad chips. Not needed now.
 --     AND
Index: trunk/ippTools/share/chiptool_setimfiletoupdate.sql
===================================================================
--- trunk/ippTools/share/chiptool_setimfiletoupdate.sql	(revision 27391)
+++ trunk/ippTools/share/chiptool_setimfiletoupdate.sql	(revision 27391)
@@ -0,0 +1,8 @@
+UPDATE chipRun
+    JOIN chipProcessedImfile USING(chip_id)
+SET chipRun.state = 'update', 
+    chipProcessedImfile.data_state = 'update'
+    -- set hook %s
+WHERE chip_id = %lld
+    AND (chipRun.state = 'cleaned' OR chipRun.state = 'update')
+    AND (chipProcessedImfile.data_state = 'cleaned')
Index: trunk/ippTools/share/difftool_todiffskyfile.sql
===================================================================
--- trunk/ippTools/share/difftool_todiffskyfile.sql	(revision 27389)
+++ trunk/ippTools/share/difftool_todiffskyfile.sql	(revision 27391)
@@ -67,10 +67,11 @@
     OR (diffRun.state = 'update'
     AND diffSkyfile.fault = 0
-    AND diffSkyfile.data_state = 'cleaned')
+    AND diffSkyfile.data_state = 'update')
     )
 -- Ensure input warps are available
     AND (diffInputSkyfile.warp1 IS NULL
-    OR (warpRun.state = 'full'
+    OR (warpSkyfile.data_state = 'full'
     AND warpSkyfile.fault = 0
+    AND warpSkyfile.magicked >= 0
     AND warpSkyfile.quality = 0))
 -- Ensure input stacks are available
@@ -81,6 +82,7 @@
 -- Ensure template warps are available
     AND (diffInputSkyfile.warp2 IS NULL
-    OR (warpTemplateRun.state = 'full'
+    OR (warpTemplateSkyfile.data_state = 'full'
     AND warpTemplateSkyfile.fault = 0
+    AND warpSkyfile.magicked >= 0
     AND warpTemplateSkyfile.quality = 0))
 -- Ensure template stacks are available
Index: trunk/ippTools/share/warptool_towarped.sql
===================================================================
--- trunk/ippTools/share/warptool_towarped.sql	(revision 27389)
+++ trunk/ippTools/share/warptool_towarped.sql	(revision 27391)
@@ -1,50 +1,96 @@
-SELECT DISTINCT
-    warpSkyCellMap.warp_id,
-    warpImfile.warp_skyfile_id,
-    warpSkyCellMap.skycell_id,
-    warpSkyCellMap.tess_id,
-    warpRun.fake_id,
-    warpRun.state,
-    warpRun.reduction,
-    camRun.cam_id,
-    rawExp.camera,
-    rawExp.exp_tag,
-    warpRun.workdir,
-    chipRun.magicked
-FROM warpRun
-JOIN warpSkyCellMap
-    USING(warp_id)
-JOIN warpImfile
-    ON warpSkyCellMap.warp_id = warpImfile.warp_id
-    AND warpSkyCellMap.skycell_id = warpImfile.skycell_id
-JOIN fakeRun
-    USING(fake_id)
-JOIN camRun
-    USING(cam_id)
-JOIN chipRun
-    USING(chip_id)
-JOIN chipProcessedImfile
-    USING(chip_id)
-JOIN rawExp
-    ON chipRun.exp_id = rawExp.exp_id
-LEFT JOIN warpSkyfile
-    ON warpRun.warp_id = warpSkyfile.warp_id
-    AND warpSkyCellMap.skycell_id = warpSkyfile.skycell_id
-    AND warpSkyCellMap.tess_id = warpSkyfile.tess_id
-LEFT JOIN warpMask
-    ON warpRun.label = warpMask.label
-WHERE
-    ((warpRun.state = 'new'
+SELECT 
+    warp_id,
+    warp_skyfile_id,
+    skycell_id,
+    tess_id,
+    fake_id,
+    state,
+    reduction,
+    cam_id,
+    camera,
+    exp_tag,
+    workdir,
+    magicked
+FROM (
+    SELECT
+        warpSkyCellMap.warp_id,
+        warpImfile.warp_skyfile_id,
+        warpSkyCellMap.skycell_id,
+        warpSkyCellMap.tess_id,
+        warpRun.fake_id,
+        warpRun.state,
+        warpRun.reduction,
+        camRun.cam_id,
+        rawExp.camera,
+        rawExp.exp_tag,
+        warpRun.workdir,
+        chipRun.magicked
+    FROM warpRun
+    JOIN warpSkyCellMap
+        USING(warp_id)
+    JOIN warpImfile
+        ON warpSkyCellMap.warp_id = warpImfile.warp_id
+        AND warpSkyCellMap.skycell_id = warpImfile.skycell_id
+    JOIN fakeRun
+        USING(fake_id)
+    JOIN camRun
+        USING(cam_id)
+    JOIN chipRun
+        USING(chip_id)
+    JOIN chipProcessedImfile
+        USING(chip_id)
+    JOIN rawExp
+        ON chipRun.exp_id = rawExp.exp_id
+    LEFT JOIN warpSkyfile
+        ON warpRun.warp_id = warpSkyfile.warp_id
+        AND warpSkyCellMap.skycell_id = warpSkyfile.skycell_id
+        AND warpSkyCellMap.tess_id = warpSkyfile.tess_id
+    LEFT JOIN warpMask
+        ON warpRun.label = warpMask.label
+    WHERE
+        warpRun.state = 'new'
         AND warpSkyfile.warp_id IS NULL
         AND warpSkyfile.skycell_id IS NULL
-        AND warpSkyfile.tess_id IS NULL)
-    OR (warpRun.state = 'update'
-        AND chipRun.magicked >= 0
-        AND warpSkyfile.fault = 0
-        AND warpSkyfile.data_state = 'cleaned')
-    )
-    AND fakeRun.state = 'full'
-    AND camRun.state = 'full'
-    AND chipRun.state = 'full'
-    AND warpMask.label IS NULL
-    AND warpSkyCellMap.fault = 0
+        AND warpSkyfile.tess_id IS NULL
+        AND fakeRun.state = 'full'
+        AND camRun.state = 'full'
+        AND chipRun.state = 'full'
+        AND warpMask.label IS NULL
+        AND warpSkyCellMap.fault = 0
+        -- where hook 1 %s
+    GROUP BY warp_id, skycell_id
+UNION
+    SELECT
+        warpSkyCellMap.warp_id,
+        warpImfile.warp_skyfile_id,
+        warpSkyCellMap.skycell_id,
+        warpSkyCellMap.tess_id,
+        warpRun.fake_id,
+        warpRun.state,
+        warpRun.reduction,
+        camRun.cam_id,
+        rawExp.camera,
+        rawExp.exp_tag,
+        warpRun.workdir,
+        MIN(chipProcessedImfile.magicked) AS magicked
+    FROM warpRun
+    JOIN warpSkyCellMap USING(warp_id)
+    JOIN warpImfile USING(warp_id, skycell_id)
+    JOIN warpSkyfile USING(warp_id, skycell_id)
+    JOIN fakeRun USING(fake_id)
+    JOIN camRun USING(cam_id)
+    JOIN chipRun USING(chip_id)
+    JOIN rawExp USING(exp_id)
+    LEFT JOIN chipProcessedImfile USING(chip_id, class_id)
+    WHERE warpRun.state = 'update'
+        AND warpSkyfile.data_state = 'update'
+        AND camRun.state = 'full'
+        AND chipProcessedImfile.data_state = 'full'
+        -- if warpSkyfile was magicked previously require inputs to be magicked
+        -- this blocks processing until all the chip inputs have been destreaked
+        AND (warpSkyfile.magicked = 0 OR chipProcessedImfile.magicked >= 0)
+        -- where hook 2 %s
+    GROUP BY warp_id, skycell_id
+    HAVING COUNT(warpSkyCellMap.class_id) = COUNT(chipProcessedImfile.class_id)
+) as towarped
+
Index: trunk/ippTools/src/addtool.c
===================================================================
--- trunk/ippTools/src/addtool.c	(revision 27389)
+++ trunk/ippTools/src/addtool.c	(revision 27391)
@@ -290,5 +290,6 @@
 
     // pxUpdateRun gets parameters from config->args and runs the update query
-    bool result = pxUpdateRun(config, where, &query, "addRun", false);
+    bool result = pxUpdateRun(config, where, &query, "addRun", "add_id", 
+        "addProcessedExp", false);
 
     psFree(query);
@@ -296,36 +297,4 @@
 
     return result;
-
-
-#ifdef notdef
-    PXOPT_LOOKUP_STR(state, config->args, "-set_state", false, false);
-    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
-
-    if ((!state) && (!label)) {
-        psError(PXTOOLS_ERR_CONFIG, false, "parameters are required");
-        psFree(where);
-        return false;
-    }
-
-    if (state) {
-        // set addRun.state to state
-        if (!pxaddRunSetStateByQuery(config, where, state)) {
-            psFree(where);
-            return false;
-        }
-    }
-
-    if (label) {
-        // set addRun.label to label
-        if (!pxaddRunSetLabelByQuery(config, where, label)) {
-            psFree(where);
-            return false;
-        }
-    }
-
-    psFree(where);
-
-    return true;
-#endif
 }
 
Index: trunk/ippTools/src/camtool.c
===================================================================
--- trunk/ippTools/src/camtool.c	(revision 27389)
+++ trunk/ippTools/src/camtool.c	(revision 27391)
@@ -267,5 +267,5 @@
 
     // pxUpdateRun gets parameters from config->args and updates
-    bool result = pxUpdateRun(config, where, &query, "camRun", true);
+    bool result = pxUpdateRun(config, where, &query, "camRun", "cam_id", "camProcessedExp", true);
     if (!result) {
         psError(psErrorCodeLast(), false, "pxUpdateRun failed");
Index: trunk/ippTools/src/chiptool.c
===================================================================
--- trunk/ippTools/src/chiptool.c	(revision 27389)
+++ trunk/ippTools/src/chiptool.c	(revision 27391)
@@ -59,4 +59,5 @@
 static bool importrunMode(pxConfig *config);
 static bool runstateMode(pxConfig *config);
+static bool setimfiletoupdateMode(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -101,4 +102,5 @@
         MODECASE(CHIPTOOL_MODE_IMPORTRUN,               importrunMode);
         MODECASE(CHIPTOOL_MODE_RUNSTATE,                runstateMode);
+        MODECASE(CHIPTOOL_MODE_SETIMFILETOUPDATE,       setimfiletoupdateMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -428,8 +430,8 @@
         return false;
     }
-    psString query = psStringCopy("UPDATE chipRun JOIN rawExp USING(exp_id)");
+    psString query = psStringCopy("UPDATE chipRun JOIN rawExp USING(exp_id) -- join hook %s\n");
 
     // pxUpdateRun gets parameters from config->args and updates
-    bool result = pxUpdateRun(config, where, &query, "chipRun", true);
+    bool result = pxUpdateRun(config, where, &query, "chipRun", "chip_id", "chipProcessedImfile", true);
     if (!result) {
         psError(psErrorCodeLast(), false, "pxUpdateRun failed");
@@ -1720,2 +1722,37 @@
     return true;
 }
+
+// a very specfic function to queue a cleaned chipProcessedImfile to be updated
+static bool setimfiletoupdateMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(chip_id, config->args, "-chip_id", true, false);
+    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
+
+    psString query = pxDataGet("chiptool_setimfiletoupdate.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    psString setHook = psStringCopy("");
+    if (label) {
+        psStringAppend(&setHook, "\n , chipRun.label = '%s'", label);
+    }
+
+    if (class_id) {
+        psStringAppend(&query, " AND (chipProcessedImfile.class_id = '%s')", class_id);
+    }
+
+    if (!p_psDBRunQueryF(config->dbh, query, setHook, chip_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(setHook);
+    psFree(query);
+
+    return true;
+}
Index: trunk/ippTools/src/chiptool.h
===================================================================
--- trunk/ippTools/src/chiptool.h	(revision 27389)
+++ trunk/ippTools/src/chiptool.h	(revision 27391)
@@ -33,4 +33,5 @@
     CHIPTOOL_MODE_REVERTPROCESSEDIMFILE,
     CHIPTOOL_MODE_UPDATEPROCESSEDIMFILE,
+    CHIPTOOL_MODE_SETIMFILETOUPDATE,
     CHIPTOOL_MODE_ADVANCEEXP,
     CHIPTOOL_MODE_BLOCK,
Index: trunk/ippTools/src/chiptoolConfig.c
===================================================================
--- trunk/ippTools/src/chiptoolConfig.c	(revision 27389)
+++ trunk/ippTools/src/chiptoolConfig.c	(revision 27391)
@@ -97,4 +97,10 @@
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_dist_group", 0,   "set dist group", NULL);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_note", 0,         "set note", NULL);
+
+    // -setimfiletoupdate
+    psMetadata *setimfiletoupdateArgs = psMetadataAlloc();
+    psMetadataAddS64(setimfiletoupdateArgs, PS_LIST_TAIL, "-chip_id", 0,   "search by chip ID (required)", 0);
+    psMetadataAddStr(setimfiletoupdateArgs, PS_LIST_TAIL, "-class_id", 0,  "search by class_id (required)", NULL);
+    psMetadataAddStr(setimfiletoupdateArgs, PS_LIST_TAIL, "-set_label",  0,"new value for label", NULL);
 
     // -pendingimfile
@@ -315,4 +321,5 @@
     PXOPT_ADD_MODE("-definecopy",           "create copy runs",                     CHIPTOOL_MODE_DEFINECOPY,        definecopyArgs);
     PXOPT_ADD_MODE("-updaterun",            "change chip run properties",           CHIPTOOL_MODE_UPDATERUN,            updaterunArgs);
+    PXOPT_ADD_MODE("-setimfiletoupdate",    "set imfile state to update",           CHIPTOOL_MODE_SETIMFILETOUPDATE,    setimfiletoupdateArgs);
     PXOPT_ADD_MODE("-pendingimfile",        "show pending imfiles",                 CHIPTOOL_MODE_PENDINGIMFILE,        pendingimfileArgs);
     PXOPT_ADD_MODE("-addprocessedimfile",   "add a processed imfile",               CHIPTOOL_MODE_ADDPROCESSEDIMFILE,   addprocessedimfileArgs);
Index: trunk/ippTools/src/difftool.c
===================================================================
--- trunk/ippTools/src/difftool.c	(revision 27389)
+++ trunk/ippTools/src/difftool.c	(revision 27391)
@@ -204,5 +204,5 @@
 
     // pxUpdateRun gets parameters from config->args and updates
-    bool result = pxUpdateRun(config, where, &query, "diffRun", true);
+    bool result = pxUpdateRun(config, where, &query, "diffRun", "diff_id", "diffSkyfile", true);
 
     psFree(query);
@@ -210,25 +210,4 @@
 
     return result;
-
-#ifdef notdef
-    // required options
-    PXOPT_LOOKUP_S64(diff_id, config->args, "-diff_id", false, false);
-    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
-    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
-
-    // Copy of my hacky work around from stacktool.c
-    if ((state)&&(diff_id)) {
-        // set detRun.state to state
-        return setdiffRunState(config, diff_id, state, false);
-    }
-
-    if ((state)&&(label)) {
-      return setdiffRunStateByLabel(config, label, state);
-    }
-
-    psError(PS_ERR_UNKNOWN, false, "Required options not found.");
-
-    return false;
-#endif
 }
 
Index: trunk/ippTools/src/faketool.c
===================================================================
--- trunk/ippTools/src/faketool.c	(revision 27389)
+++ trunk/ippTools/src/faketool.c	(revision 27391)
@@ -348,5 +348,5 @@
 
     // pxUpdateRun gets parameters from config->args and updates
-    bool result = pxUpdateRun(config, where, &query, "fakeRun", true);
+    bool result = pxUpdateRun(config, where, &query, "fakeRun", "fake_id", "fakeProcessedImfile", true);
     if (!result) {
         psError(psErrorCodeLast(), false, "pxUpdateRun failed");
Index: trunk/ippTools/src/pxtools.c
===================================================================
--- trunk/ippTools/src/pxtools.c	(revision 27389)
+++ trunk/ippTools/src/pxtools.c	(revision 27391)
@@ -110,5 +110,5 @@
 
 // shared code for updating the various strings for a Run
-bool pxUpdateRun(pxConfig *config, psMetadata *where, psString *pQuery, psString table, bool has_dist_group)
+bool pxUpdateRun(pxConfig *config, psMetadata *where, psString *pQuery, psString runTable, psString idColumn, psString fileTable, bool has_dist_group)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -116,4 +116,7 @@
     PS_ASSERT_PTR_NON_NULL(pQuery, false);
     PS_ASSERT_PTR_NON_NULL(*pQuery, false);
+    PS_ASSERT_PTR_NON_NULL(runTable, false);
+    PS_ASSERT_PTR_NON_NULL(idColumn, false);
+    PS_ASSERT_PTR_NON_NULL(fileTable, false);
 
     // make sure that -state is not the only selection parameter
@@ -158,15 +161,26 @@
         } while (0)
 
-    addColumn(table, state);
-    addColumn(table, data_group);
+    addColumn(runTable, state);
+    addColumn(runTable, data_group);
     if (has_dist_group) {
-        addColumn(table, dist_group);
-    }
-    addColumn(table, note);
-    addColumn(table, label);
+        addColumn(runTable, dist_group);
+    }
+    addColumn(runTable, note);
+    addColumn(runTable, label);
+
+    psString joinHook = psStringCopy("");
+    psString fileWhere = NULL;
+    if (state && !strcmp(state, "update")) {
+        psStringAppend(&joinHook, "\n JOIN %s USING(%s)", fileTable, idColumn);
+        psStringAppend(pQuery, ", %s.data_state = 'update'", fileTable);
+        psStringAppend(&fileWhere, "AND %s.data_state = 'cleaned'", fileTable);
+    }
 
     psString whereClause =  psDBGenerateWhereSQL(where, NULL);
     psStringAppend(pQuery, " %s", whereClause);
     psFree(whereClause);
+    if (fileWhere) {
+        psStringAppend(pQuery, fileWhere);
+    }
 
     bool mdok;                          // Status of MD lookup
@@ -176,5 +190,5 @@
     }
 
-    if (!p_psDBRunQuery(config->dbh, *pQuery)) {
+    if (!p_psDBRunQueryF(config->dbh, *pQuery, joinHook)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
         return false;
Index: trunk/ippTools/src/pxtools.h
===================================================================
--- trunk/ippTools/src/pxtools.h	(revision 27389)
+++ trunk/ippTools/src/pxtools.h	(revision 27391)
@@ -65,5 +65,5 @@
 bool pxGetOptions(FILE *stream, int argc, char **argv, pxConfig *config, psMetadata *modes, psMetadata *argSets);
 
-bool pxUpdateRun(pxConfig *config, psMetadata *where, psString *pQuery, psString table, bool has_dist_group);
+bool pxUpdateRun(pxConfig *config, psMetadata *where, psString *pQuery, psString runTable, psString idColumn, psString fileTable, bool has_dist_group);
 
 #define PXOPT_ADD_MODE(option, comment, modeval, argset) \
Index: trunk/ippTools/src/stacktool.c
===================================================================
--- trunk/ippTools/src/stacktool.c	(revision 27389)
+++ trunk/ippTools/src/stacktool.c	(revision 27391)
@@ -612,5 +612,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);
Index: trunk/ippTools/src/warptool.c
===================================================================
--- trunk/ippTools/src/warptool.c	(revision 27389)
+++ trunk/ippTools/src/warptool.c	(revision 27391)
@@ -402,8 +402,8 @@
     }
 
-    psString query = psStringCopy("UPDATE warpRun JOIN fakeRun USING(fake_id) JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)");
+    psString query = psStringCopy("UPDATE warpRun JOIN warpSkyfile USING(warp_id) JOIN fakeRun USING(fake_id) JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)");
 
     // pxUpdateRun gets parameters from config->args and updates
-    bool result = pxUpdateRun(config, where, &query, "warpRun", true);
+    bool result = pxUpdateRun(config, where, &query, "warpRun", "warp_id", "warpSkyfile", true);
 
     psFree(query);
@@ -907,7 +907,8 @@
     }
 
+    psString whereStr = psStringCopy("");
     if (psListLength(where->list)) {
         psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-        psStringAppend(&query, " AND %s", whereClause);
+        psStringAppend(&whereStr, "\n AND %s", whereClause);
         psFree(whereClause);
     }
@@ -921,9 +922,10 @@
     }
 
-    if (!p_psDBRunQuery(config->dbh, query)) {
+    if (!p_psDBRunQueryF(config->dbh, query, whereStr, whereStr)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
         psFree(query);
         return false;
     }
+    psFree(whereStr);
     psFree(query);
 
