Index: /branches/pap_magic/dbconfig/changes.txt
===================================================================
--- /branches/pap_magic/dbconfig/changes.txt	(revision 24135)
+++ /branches/pap_magic/dbconfig/changes.txt	(revision 24136)
@@ -1111,2 +1111,4 @@
 UPDATE diffRun, diffInputSkyfile SET diffRun.exposure = 1 WHERE diffRun.diff_id = diffInputSkyfile.diff_id and diffInputSkyfile.warp1 IS NOT NULL;
 ALTER TABLE stackRun ADD KEY(label);
+
+ALTER TABLE magicRun ADD COLUMN inverse TINYINT NOT NULL DEFAULT 0 AFTER diff_id;
Index: /branches/pap_magic/dbconfig/magic.md
===================================================================
--- /branches/pap_magic/dbconfig/magic.md	(revision 24135)
+++ /branches/pap_magic/dbconfig/magic.md	(revision 24136)
@@ -6,4 +6,5 @@
     exp_id      S64         0       # Key
     diff_id     S64         0       # Key
+    inverse     BOOL	    FALSE	    
     state       STR         64      # Key
     workdir     STR         255
Index: /branches/pap_magic/ippTools/share/magictool_definebyquery_select.sql
===================================================================
--- /branches/pap_magic/ippTools/share/magictool_definebyquery_select.sql	(revision 24135)
+++ /branches/pap_magic/ippTools/share/magictool_definebyquery_select.sql	(revision 24136)
@@ -1,8 +1,36 @@
 -- Get a list of exposures on which magic may be performed
-SELECT 
+SELECT
     exp_id,
-    MAX(diffRun.diff_id) AS diff_id
-FROM diffRun
-JOIN rawExp USING(exp_id)
+    MAX(diffWarps.diff_id) AS diff_id,
+    -- The following trick pulls out the 'inverse' value for the maximum diff_id
+    CONVERT(SUBSTRING_INDEX(GROUP_CONCAT(diffWarps.inverse ORDER BY diffWarps.diff_id), ',', 1), UNSIGNED) AS inverse
+FROM (
+    -- Forward diffs
+    SELECT
+        diffRun.diff_id,
+        warp1 AS warp_id,
+        0 AS inverse
+    FROM diffRun
+    JOIN diffInputSkyfile USING(diff_id)
+    WHERE diffInputSkyfile.warp1 IS NOT NULL
+        AND diffRun.exposure = 1
+    -- WHERE hook %s
+    UNION
+    -- Backward diffs
+    SELECT
+        diffRun.diff_id,
+        warp2 AS warp_id,
+        1 AS inverse
+    FROM diffRun
+    JOIN diffInputSkyfile USING(diff_id)
+    WHERE diffInputSkyfile.warp2 IS NOT NULL
+        AND diffRun.exposure = 1
+        AND diffRun.bothways = 1
+    -- WHERE hook %s
+    ) AS diffWarps
+JOIN warpRun USING(warp_id)
+JOIN fakeRun USING(fake_id)
+JOIN camRun USING(cam_id)
+JOIN chipRun USING(chip_id)
 LEFT JOIN magicRun USING(exp_id)
 -- WHERE hook %s
Index: /branches/pap_magic/ippTools/share/pxadmin_create_tables.sql
===================================================================
--- /branches/pap_magic/ippTools/share/pxadmin_create_tables.sql	(revision 24135)
+++ /branches/pap_magic/ippTools/share/pxadmin_create_tables.sql	(revision 24136)
@@ -1009,4 +1009,5 @@
         exp_id BIGINT,
         diff_id BIGINT,
+        inverse TINYINT NOT NULL DEFAULT 0,
         state VARCHAR(64),
         workdir VARCHAR(255),
Index: /branches/pap_magic/ippTools/src/magictool.c
===================================================================
--- /branches/pap_magic/ippTools/src/magictool.c	(revision 24135)
+++ /branches/pap_magic/ippTools/src/magictool.c	(revision 24136)
@@ -127,9 +127,11 @@
     PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
-
-    psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
-    PXOPT_COPY_STR(config->args, where, "-diff_label", "diffRun.label", "==");
-
+    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+
+    psMetadata *diffWhere = psMetadataAlloc(); // WHERE conditions for diffRuns
+    PXOPT_COPY_STR(config->args, diffWhere, "-diff_label", "diffRun.label", "==");
+
+    psMetadata *queryWhere = psMetadataAlloc(); // WHERE conditions for everything else
+    PXOPT_COPY_S64(config->args, queryWhere, "-exp_id", "exp_id", "==");
 
     // Get list of exposures ready to magic
@@ -146,36 +148,46 @@
         PXOPT_LOOKUP_BOOL(rerun, config->args, "-rerun", false);
 
-        psString queryWhere = NULL;     // WHERE conditions for entire query
+        psString diffWhereStr = NULL;   // WHERE conditions for diffRuns
+        psString queryWhereStr = NULL;  // WHERE conditions for entire query
         if (!available) {
-            psStringAppend(&queryWhere, " \nWHERE diffRun.state = 'full'");
-        } else {
-            // what if no skycells for the diff run completed?
-        }
+            psStringAppend(&diffWhereStr, "\nAND diffRun.state = 'full'");
+        }
+        // what if no skycells for the diff run completed?
+
         if (!rerun) {
-            const char *newWhere = " magic_id IS NULL"; // String to add
-            if (queryWhere) {
-                psStringAppend(&queryWhere, " AND %s", newWhere);
-            } else {
-                psStringAppend(&queryWhere, "\nWHERE %s", newWhere);
-            }
-        }
+            psStringAppend(&queryWhereStr, "\n%s magic_id IS NULL", queryWhereStr ? "AND" : "WHERE");
+        }
+
         // now add the user specified qualifiers
-        if (psListLength(where->list)) {
-            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-            psStringAppend(&queryWhere, "\n%s %s", queryWhere == NULL ? "WHERE" : "AND", whereClause);
+        if (psListLength(diffWhere->list)) {
+            psString whereClause = psDBGenerateWhereConditionSQL(diffWhere, NULL);
+            psStringAppend(&diffWhereStr, "\nAND %s", whereClause);
             psFree(whereClause);
         }
-        psFree(where);
-        if (!queryWhere) {
-            psStringAppend(&queryWhere, " ");
-        }
-
-        if (!p_psDBRunQueryF(config->dbh, query, queryWhere)) {
+        if (psListLength(queryWhere->list)) {
+            psString whereClause = psDBGenerateWhereConditionSQL(queryWhere, NULL);
+            psStringAppend(&queryWhereStr, "\n%s %s", queryWhereStr ? "AND" : "WHERE", whereClause);
+            psFree(whereClause);
+        }
+        psFree(diffWhere);
+        psFree(queryWhere);
+
+        // Ensure the WHERE strings have something
+        if (!diffWhereStr) {
+            diffWhereStr = psStringCopy("");
+        }
+        if (!queryWhereStr) {
+            queryWhereStr = psStringCopy("");
+        }
+
+        if (!p_psDBRunQueryF(config->dbh, query, diffWhereStr, diffWhereStr, queryWhereStr)) {
             psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(queryWhere);
+            psFree(diffWhereStr);
+            psFree(queryWhereStr);
             psFree(query);
             return false;
         }
-        psFree(queryWhere);
+        psFree(diffWhereStr);
+        psFree(queryWhereStr);
         psFree(query);
     }
@@ -201,6 +213,18 @@
     }
 
+
+    if (pretend) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "diffRun", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+        psFree(output);
+        return true;
+    }
+
+
     // Parse the list of exposures ready to magic
-
     if (!psDBTransaction(config->dbh)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
@@ -215,7 +239,9 @@
         psS64 exp_id = psMetadataLookupS64(NULL, row, "exp_id"); // Exposure identifier
         psS64 diff_id = psMetadataLookupS64(NULL, row, "diff_id"); // difference identifier
+        bool inverse = psMetadataLookupU64(NULL, row, "inverse"); // Inverse subtraction? Note types!
 
         // create a new magicRun for this group
-        magicRunRow *run = magicRunRowAlloc(0, exp_id, diff_id, "new", workdir, "dirty", label, dvodb, registered, 0);
+        magicRunRow *run = magicRunRowAlloc(0, exp_id, diff_id, inverse, "new", workdir, "dirty", label,
+                                            dvodb, registered, 0);
         if (!run) {
             psAbort("failed to alloc magicRun object");
@@ -296,4 +322,5 @@
 
     // optional
+    PXOPT_LOOKUP_BOOL(inverse, config->args, "-inverse", false);
     PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
     PXOPT_LOOKUP_STR(dvodb, config->args, "-dvodb", false, false);
@@ -305,4 +332,5 @@
             exp_id,
             diff_id ? diff_id : PS_MAX_S64,
+            inverse,
             "reg",      // state
             workdir,
Index: /branches/pap_magic/ippTools/src/magictoolConfig.c
===================================================================
--- /branches/pap_magic/ippTools/src/magictoolConfig.c	(revision 24135)
+++ /branches/pap_magic/ippTools/src/magictoolConfig.c	(revision 24136)
@@ -58,4 +58,5 @@
     psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-rerun", 0, "generate new run even if existing?", false);
     psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-pretend", 0, "list results but do not queue", false);
 
     // -definerun
@@ -65,4 +66,5 @@
     // following argument is for compatability
     psMetadataAddS64(definerunArgs, PS_LIST_TAIL, "-diff_id", 0, "define diff_id", 0);
+    psMetadataAddBool(definerunArgs, PS_LIST_TAIL, "-inverse", 0, "use the inverse subtraction?", false);
     psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-label", 0, "define label", NULL);
     psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-dvodb", 0, "define dvodb", NULL);
