Index: branches/eam_branches/ipp-20230313/ippTools/src/xcfftool.c
===================================================================
--- branches/eam_branches/ipp-20230313/ippTools/src/xcfftool.c	(revision 42591)
+++ branches/eam_branches/ipp-20230313/ippTools/src/xcfftool.c	(revision 42594)
@@ -105,5 +105,5 @@
 }
 
-// NOTE: if I denormalize and populate (tess_id, skycell_id) in xcForceRun the  I do not need
+// NOTE: if I denormalize and populate (tess_id, skycell_id) in xcForceRun then I do not need
 // to join back to xcstackRun to get that info
 static bool definebyqueryMode(pxConfig *config)
@@ -131,6 +131,10 @@
     PXOPT_LOOKUP_STR(reduction,   config->args, "-set_reduction", false, false);
 
-    // XXX is the needed or wanted?
+    // XXX is needed or wanted?
     // PXOPT_LOOKUP_STR(sources_path_base,   config->args, "-set_sources_path_base", false, false);
+
+    // first, we need to select the xccalRun(s) which need to have xcForceRuns.  we can limit the selection based on
+    // qualities of the xccalRun or the xcstackRun.  There will be one xcForceRun for each
+    // identified xccalRun.
 
     psMetadata *xccalWhereMD = psMetadataAlloc();
@@ -145,5 +149,4 @@
     }
 
-    // XXX do these need to specify stackRun?  can the filters be different between stackRun and xcstackRun?
     PXOPT_COPY_STR(config->args, xccalWhereMD, "-select_skycell_id",    "xcstackRun.skycell_id",      "LIKE");
     PXOPT_COPY_STR(config->args, xccalWhereMD, "-select_tess_id",       "xcstackRun.tess_id",         "==");
@@ -155,8 +158,14 @@
     }
 
+    // once we have identified the xccalRun(s) for which we will generate the xcForceRuns, we
+    // need to select the input warps.  Normally, these would be all warps used to generate all
+    // stacks used to generate the xcstack skyfile associated with the xccalRun.  But we have
+    // the options to limit which warps we actually include.  
+
     psMetadata *warpWhereMD = psMetadataAlloc();
     pxAddLabelSearchArgs(config, warpWhereMD, "-select_warp_label",      "warpRun.label",           "LIKE");
     pxAddLabelSearchArgs(config, warpWhereMD, "-select_warp_data_group", "warpRun.data_group",      "LIKE");
     PXOPT_COPY_S64(config->args, warpWhereMD, "-select_warp_id",         "warpRun.warp_id",         "==");
+    // XXX is is really necessary to limit the warps?
     if (!psListLength(warpWhereMD->list)) {
         psError(PXTOOLS_ERR_CONFIG, false, "warp search parameters are required");
@@ -166,7 +175,4 @@
     }
     PXOPT_COPY_F32(config->args, warpWhereMD, "-select_good_frac_min",   "warpSkyfile.good_frac",  ">=");
-    // XXX do I need these or not?  the warp skyfiles need to match the stack skycells
-    PXOPT_COPY_STR(config->args, warpWhereMD, "-select_tess_id",         "warpRun.tess_id",        "==");
-    pxAddLabelSearchArgs(config, warpWhereMD, "-select_filter",          "rawExp.filter",          "LIKE");
 
     PXOPT_LOOKUP_BOOL(rerun, config->args, "-rerun", false);
@@ -186,4 +192,5 @@
     psStringAppend(&where, "\nAND %s", whereClause);
     psStringAppend(&select, " %s", where);
+
     psFree(whereClause);
     psFree(xccalWhereMD);
@@ -192,4 +199,9 @@
     if (!rerun) {
       psStringAppend(&joinHook, "\nLEFT JOIN xcForceRun ON xcForceRun.xccal_id = %s.xccalRun.xccal_id", xcamera);
+    }
+
+    psStringAppend(&joinHook, "\n %s, where);
+
+    if (
         psStringAppend(&joinHook, "\n %s\nAND xcForceRun.label = '%s'", where, label);
         psStringAppend(&select, "\nAND ff_id IS NULL");
