Index: branches/czw_branch/20100519/ippTools/src/Makefile.am
===================================================================
--- branches/czw_branch/20100519/ippTools/src/Makefile.am	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/Makefile.am	(revision 28164)
@@ -10,4 +10,5 @@
 	flatcorr \
 	dqstatstool \
+	labeltool \
 	magictool \
 	magicdstool \
@@ -21,4 +22,5 @@
 	regtool \
 	stacktool \
+	staticskytool \
 	warptool \
 	receivetool \
@@ -55,4 +57,5 @@
 	faketool.h \
 	dqstatstool.h \
+	labeltool.h \
 	magictool.h \
 	magicdstool.h \
@@ -64,4 +67,5 @@
 	regtool.h \
 	stacktool.h \
+	staticskytool.h \
 	warptool.h \
 	pubtool.h
@@ -153,4 +157,10 @@
     dqstatstoolConfig.c
 
+labeltool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+labeltool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+labeltool_SOURCES = \
+    labeltool.c \
+    labeltoolConfig.c
+
 magictool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
 magictool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
@@ -188,4 +198,10 @@
     stacktool.c \
     stacktoolConfig.c
+
+staticskytool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+staticskytool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+staticskytool_SOURCES = \
+    staticskytool.c \
+    staticskytoolConfig.c
 
 pxadmin_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
Index: branches/czw_branch/20100519/ippTools/src/camtool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/camtool.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/camtool.c	(revision 28164)
@@ -490,12 +490,18 @@
     PXOPT_LOOKUP_STR(ver_streaks, config->args, "-ver_streaks", false, false);
 
-    PXOPT_LOOKUP_S32(maskfrac_npix, config->args, "-maskfrac_npix", false, false);
-    PXOPT_LOOKUP_F32(maskfrac_static, config->args, "-maskfrac_static", false, false);
-    PXOPT_LOOKUP_F32(maskfrac_dynamic, config->args, "-maskfrac_dynamic", false, false);
-    PXOPT_LOOKUP_F32(maskfrac_magic, config->args, "-maskfrac_magic", false, false);
-    PXOPT_LOOKUP_F32(maskfrac_advisory, config->args, "-maskfrac_advisory", false, false);
-
-    psTrace("czw.test",1,"Received versions: pslib %s psmodules %s psphot %s psastro %s ppstats %s ppImage %s streaks %s\n",
-	    ver_pslib,ver_psmodules,ver_psphot,ver_psastro,ver_ppstats,ver_ppimage,ver_streaks);
+    PXOPT_LOOKUP_S32(maskfrac_ref_npix, config->args, "-maskfrac_ref_npix", false, false);
+    PXOPT_LOOKUP_F32(maskfrac_ref_static, config->args, "-maskfrac_ref_static", false, false);
+    PXOPT_LOOKUP_F32(maskfrac_ref_dynamic, config->args, "-maskfrac_ref_dynamic", false, false);
+    PXOPT_LOOKUP_F32(maskfrac_ref_magic, config->args, "-maskfrac_ref_magic", false, false);
+    PXOPT_LOOKUP_F32(maskfrac_ref_advisory, config->args, "-maskfrac_ref_advisory", false, false);
+
+    PXOPT_LOOKUP_S32(maskfrac_max_npix, config->args, "-maskfrac_max_npix", false, false);
+    PXOPT_LOOKUP_F32(maskfrac_max_static, config->args, "-maskfrac_max_static", false, false);
+    PXOPT_LOOKUP_F32(maskfrac_max_dynamic, config->args, "-maskfrac_max_dynamic", false, false);
+    PXOPT_LOOKUP_F32(maskfrac_max_magic, config->args, "-maskfrac_max_magic", false, false);
+    PXOPT_LOOKUP_F32(maskfrac_max_advisory, config->args, "-maskfrac_max_advisory", false, false);
+
+/*     psTrace("czw.test",1,"Received versions: pslib %s psmodules %s psphot %s psastro %s ppstats %s ppImage %s streaks %s\n", */
+/* 	    ver_pslib,ver_psmodules,ver_psphot,ver_psastro,ver_ppstats,ver_ppimage,ver_streaks); */
     psString software_ver = NULL;
     if ((ver_pslib)&&(ver_psmodules)) {
@@ -632,9 +638,14 @@
         fault,
 	software_ver,
-	maskfrac_npix,
-	maskfrac_static,
-	maskfrac_dynamic,
-	maskfrac_magic,
-	maskfrac_advisory,
+	maskfrac_ref_npix,
+	maskfrac_ref_static,
+	maskfrac_ref_dynamic,
+	maskfrac_ref_magic,
+	maskfrac_ref_advisory,
+	maskfrac_max_npix,
+	maskfrac_max_static,
+	maskfrac_max_dynamic,
+	maskfrac_max_magic,
+	maskfrac_max_advisory,
 	quality
         );
@@ -674,7 +685,10 @@
     }
     // Set chipRun.maskfrac* to the appropriate values.
-    if (maskfrac_npix) {
-      if (!pxSetRunMaskfrac(config, "camRun", "cam_id",cam_id, maskfrac_npix, maskfrac_static,
-			    maskfrac_dynamic, maskfrac_magic, maskfrac_advisory)) {
+    if (maskfrac_ref_npix) {
+      if (!pxCamSetRunMaskfrac(config, "camRun", "cam_id",cam_id,
+			       (float) maskfrac_ref_npix, maskfrac_ref_static,
+			       maskfrac_ref_dynamic, maskfrac_ref_magic, maskfrac_ref_advisory,
+			       (float) maskfrac_max_npix, maskfrac_max_static,
+			       maskfrac_max_dynamic, maskfrac_max_magic, maskfrac_max_advisory)) {
 	if (!psDBRollback(config->dbh)) {
 	  psError(PS_ERR_UNKNOWN, false, "database error");
Index: branches/czw_branch/20100519/ippTools/src/camtoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/camtoolConfig.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/camtoolConfig.c	(revision 28164)
@@ -182,9 +182,15 @@
     psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-ver_streaks", 0, "define streaksremove version", NULL);
 
-    psMetadataAddS32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_npix", 0, "define number of pixels used for maskstats", 0);
-    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_static", 0, "define static mask fraction", NAN);
-    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_dynamic", 0, "define dynamic mask fraction", NAN);
-    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_magic", 0, "define magic mask fraction", NAN);
-    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_advisory", 0, "define advisory mask fraction", NAN);
+    psMetadataAddS32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_ref_npix", 0, "define number of pixels used for maskstats", 0);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_ref_static", 0, "define static mask fraction", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_ref_dynamic", 0, "define dynamic mask fraction", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_ref_magic", 0, "define magic mask fraction", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_ref_advisory", 0, "define advisory mask fraction", NAN);
+
+    psMetadataAddS32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_max_npix", 0, "define number of pixels used for maskstats", 0);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_max_static", 0, "define static mask fraction", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_max_dynamic", 0, "define dynamic mask fraction", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_max_magic", 0, "define magic mask fraction", NAN);
+    psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-maskfrac_max_advisory", 0, "define advisory mask fraction", NAN);
 
 
Index: branches/czw_branch/20100519/ippTools/src/chiptool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/chiptool.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/chiptool.c	(revision 28164)
@@ -141,5 +141,5 @@
     )
 {
-    // start a transaction so we don't end up with an exp without any associted
+    // start a transaction so we don't end up with an exp without any associated
     // imfiles
     if (!psDBTransaction(config->dbh)) {
@@ -1398,5 +1398,5 @@
 	
 	psString software_ver = NULL;
-	psS32 maskfrac_npix = 0;
+	psS64 maskfrac_npix = 0;
 	psF32 maskfrac_static = 0;
 	psF32 maskfrac_dynamic = 0;
@@ -1417,10 +1417,10 @@
 	}
 	psMetadataAddStr(row, PS_LIST_TAIL, "software_ver",  0, "Software version", software_ver);
-	psMetadataAddS32(row, PS_LIST_TAIL, "maskfrac_npix",  0, "Number of pixels used for mask stats", maskfrac_npix);
+	psMetadataAddS32(row, PS_LIST_TAIL, "maskfrac_npix",  0, "Number of pixels used for mask stats", (psS32) maskfrac_npix);
 	psMetadataAddF32(row, PS_LIST_TAIL, "maskfrac_static",  0, "Fraction of static masked pixels", maskfrac_static);
 	psMetadataAddF32(row, PS_LIST_TAIL, "maskfrac_dynamic",  0, "Fraction of dynamic masked pixels", maskfrac_dynamic);
 	psMetadataAddF32(row, PS_LIST_TAIL, "maskfrac_magic",  0, "Fraction of magic masked pixels", maskfrac_magic);
 	psMetadataAddF32(row, PS_LIST_TAIL, "maskfrac_advisory",  0, "Fraction of advisory pixels", maskfrac_advisory);
-	psWarning("ADVANCE %ld %s %d %f %f %f %f\n",chip_id,software_ver,maskfrac_npix,maskfrac_static,maskfrac_dynamic,maskfrac_magic,maskfrac_advisory);
+/* 	psWarning("ADVANCE %ld %s %d %f %f %f %f\n",chip_id,software_ver,maskfrac_npix,maskfrac_static,maskfrac_dynamic,maskfrac_magic,maskfrac_advisory); */
         chipRunRow *chipRun = chipRunObjectFromMetadata(row);
         if (!psDBTransaction(config->dbh)) {
@@ -1430,23 +1430,27 @@
 
 	// Set chipRun.software_ver to the appropriate value
-	if (!pxSetRunSoftware(config, "chipRun", "chip_id", chip_id, software_ver)) {
-	  psError(PS_ERR_UNKNOWN, false, "failed to set chipRun.software_ver for chip_id: %" PRId64,
-		  chip_id);
-	  psFree(output);
-	  if (!psDBRollback(config->dbh)) {
-	    psError(PS_ERR_UNKNOWN, false, "database error");
+	if (software_ver) {
+	  if (!pxSetRunSoftware(config, "chipRun", "chip_id", chip_id, software_ver)) {
+	    psError(PS_ERR_UNKNOWN, false, "failed to set chipRun.software_ver for chip_id: %" PRId64,
+		    chip_id);
+	    psFree(output);
+	    if (!psDBRollback(config->dbh)) {
+	      psError(PS_ERR_UNKNOWN, false, "database error");
+	    }
+	    return(false);
 	  }
-	  return(false);
 	}
 	// Set chipRun.maskfrac* to the appropriate values.
-	if (!pxSetRunMaskfrac(config, "chipRun", "chip_id",chip_id, maskfrac_npix, maskfrac_static,
-			      maskfrac_dynamic, maskfrac_magic, maskfrac_advisory)) {
-	  psError(PS_ERR_UNKNOWN, false, "failed to set chipRun.software_ver for chip_id: %" PRId64,
-		  chip_id);
-	  psFree(output);
-	  if (!psDBRollback(config->dbh)) {
-	    psError(PS_ERR_UNKNOWN, false, "database error");
+	if (maskfrac_npix) {
+	  if (!pxSetRunMaskfrac(config, "chipRun", "chip_id",chip_id, maskfrac_npix, maskfrac_static,
+				maskfrac_dynamic, maskfrac_magic, maskfrac_advisory)) {
+	    psError(PS_ERR_UNKNOWN, false, "failed to set chipRun.software_ver for chip_id: %" PRId64,
+		    chip_id);
+	    psFree(output);
+	    if (!psDBRollback(config->dbh)) {
+	      psError(PS_ERR_UNKNOWN, false, "database error");
+	    }
+	    return(false);
 	  }
-	  return(false);
 	}
         // set chipRun.state to 'stop' and update the magicked state
Index: branches/czw_branch/20100519/ippTools/src/chiptoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/chiptoolConfig.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/chiptoolConfig.c	(revision 28164)
@@ -89,7 +89,7 @@
     psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-chip_id",              0,            "search by chip ID", 0);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0,            "search by state", NULL);
-    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label",  0,           "search by label", NULL);
-    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-data_group",  0,      "search by data_group", NULL);
-    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-dist_group",  0,      "search by dist_group", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label",  0,           "search by label (LIKE comparison)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-data_group",  0,      "search by data_group (LIKE comparison)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-dist_group",  0,      "search by dist_group (LIKE comparison)", NULL);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_state", 0,        "set state", NULL);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_label", 0,        "set label", NULL);
@@ -101,5 +101,5 @@
     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, "-class_id", 0,  "search by class_id", NULL);
     psMetadataAddStr(setimfiletoupdateArgs, PS_LIST_TAIL, "-set_label",  0,"new value for label", NULL);
 
Index: branches/czw_branch/20100519/ippTools/src/difftool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/difftool.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/difftool.c	(revision 28164)
@@ -44,4 +44,6 @@
 static bool definewarpwarpMode(pxConfig *config);
 static bool definestackstackMode(pxConfig *config);
+static bool tosummaryMode(pxConfig *config);
+static bool addsummaryMode(pxConfig *config);
 static bool pendingcleanuprunMode(pxConfig *config);
 static bool pendingcleanupskyfileMode(pxConfig *config);
@@ -93,4 +95,6 @@
         MODECASE(DIFFTOOL_MODE_DEFINEWARPWARP,        definewarpwarpMode);
         MODECASE(DIFFTOOL_MODE_DEFINESTACKSTACK,      definestackstackMode);
+	MODECASE(DIFFTOOL_MODE_TOSUMMARY,             tosummaryMode);
+	MODECASE(DIFFTOOL_MODE_ADDSUMMARY,            addsummaryMode);
         MODECASE(DIFFTOOL_MODE_PENDINGCLEANUPRUN,     pendingcleanuprunMode);
         MODECASE(DIFFTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileMode);
@@ -203,6 +207,7 @@
 
     PXOPT_COPY_S64(config->args, where, "-diff_id",  "diff_id",   "==");
-    PXOPT_COPY_STR(config->args, where, "-label",     "label",     "==");
-    PXOPT_COPY_STR(config->args, where, "-data_group","data_group",     "==");
+    PXOPT_COPY_STR(config->args, where, "-label",     "label",     "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-data_group","data_group","LIKE");
+    PXOPT_COPY_STR(config->args, where, "-dist_group","dist_group","LIKE");
     PXOPT_COPY_STR(config->args, where, "-state",     "state",     "==");
     if (!psListLength(where->list)) {
@@ -716,5 +721,5 @@
 
 	psString software_ver = NULL;
-	psS32 maskfrac_npix = 0;
+	psS64 maskfrac_npix = 0;
 	psF32 maskfrac_static = 0;
 	psF32 maskfrac_dynamic = 0;
@@ -2249,4 +2254,135 @@
 }
 
+static bool tosummaryMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-warp_id",    "diffSkyfile.warp_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-tess_id",    "diffSkyfile.tess_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-state",      "diffRun.state", "==");
+  PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "rawExp.dateobs",  ">=");
+  PXOPT_COPY_TIME(config->args, where, "-dateobs_end",   "rawExp.dateobs",  "<=");
+  PXOPT_COPY_STR(config->args, where, "-filter",    "rawExp.filter", "LIKE");
+  PXOPT_COPY_S64(config->args, where, "-magicked", "diffSkyfile.magicked", "==");
+  pxAddLabelSearchArgs (config, where, "-label",   "diffRun.label", "LIKE");
+  pxAddLabelSearchArgs (config, where, "-data_group",   "diffRun.data_group", "LIKE");
+
+  PXOPT_LOOKUP_BOOL(all, config->args, "-all", false);
+
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  
+  // find all rawImfiles matching the default query
+  psString query = pxDataGet("difftool_tosummary.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    return false;
+  }
+
+  // generate where strings for arguments that require extra processing
+  // beyond PXOPT_COPY*
+  psString where2 = NULL;
+  if (!pxmagicAddWhere(config, &where2, "diffSkyfile")) {
+    psError(psErrorCodeLast(), false, "pxMagicAddWhere failed");
+    return false;
+  }
+  
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " WHERE %s", whereClause);
+    psFree(whereClause);
+  } else if (!all && !where2) {
+    psError(PXTOOLS_ERR_CONFIG, true, "search parameters or -all are required");
+    return false;
+  }
+  
+  if (where2) {
+    if (psListLength(where->list)) {
+      psStringAppend(&query, " %s", where2);
+    } else {
+      psStringAppend(&query, " WHERE 1 %s", where2);
+    }
+  }
+  psFree(where);
+
+  // 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) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+    }
+    
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("difftool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+  
+  if (psArrayLength(output)) {
+    // 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);
+}
+static bool addsummaryMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(diff_id, config->args, "-diff_id", true, false);
+  PXOPT_LOOKUP_STR(tangent_plane, config->args, "-tangent_plane", true, false);
+  PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", true, false);
+
+  psString query = pxDataGet("difftool_addsummary.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    return(false);
+  }
+  if (!p_psDBRunQueryF(config->dbh, query, diff_id, tangent_plane, path_base)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return(false);
+  }
+  psS64 numUpdated = psDBAffectedRows(config->dbh);
+  
+  if (numUpdated != 1) {
+    psError(PS_ERR_UNKNOWN, false, "should have affected 1 row");
+    psFree(query);
+    return false;
+  }
+  
+  psFree(query);
+
+  // Print anything here?
+  
+  return(true);
+}
+
+
 static bool pendingcleanuprunMode(pxConfig *config)
 {
Index: branches/czw_branch/20100519/ippTools/src/difftool.h
===================================================================
--- branches/czw_branch/20100519/ippTools/src/difftool.h	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/difftool.h	(revision 28164)
@@ -32,4 +32,6 @@
     DIFFTOOL_MODE_ADDDIFFSKYFILE,
     DIFFTOOL_MODE_ADVANCE,
+    DIFFTOOL_MODE_TOSUMMARY,
+    DIFFTOOL_MODE_ADDSUMMARY,
     DIFFTOOL_MODE_DIFFSKYFILE,
     DIFFTOOL_MODE_REVERTDIFFSKYFILE,
Index: branches/czw_branch/20100519/ippTools/src/difftoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/difftoolConfig.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/difftoolConfig.c	(revision 28164)
@@ -64,11 +64,12 @@
     psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-diff_id", 0,          "define diff ID", 0);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0,            "set state", NULL);
-    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label", 0,            "define by label instead of diff ID", 0);
-    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-data_group", 0,       "define by data_group instead of diff ID", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label", 0,            "define by label instead of diff ID (LIKE comparison)", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-data_group", 0,       "define by data_group instead of diff ID (LIKE comparison)", 0);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-dist_group", 0,       "define by dist_group instead of diff ID (LIKE comparison)", 0);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_label", 0,        "define new value for label", 0);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_state", 0,        "define new state", NULL);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_data_group", 0,   "define new data_group", NULL);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_dist_group", 0,   "define new dist_group", NULL);
-    psMetadataAddS16(updaterunArgs, PS_LIST_TAIL, "-set_diff_mode", 0,       "specify type of difference (WW=1,WS=2,SW=3,SS=4)", 0);
+    psMetadataAddS16(updaterunArgs, PS_LIST_TAIL, "-set_diff_mode", 0,    "specify type of difference (WW=1,WS=2,SW=3,SS=4)", 0);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_note", 0,         "define new note", NULL);
 
@@ -322,4 +323,29 @@
     psMetadataAddU64(pendingcleanuprunArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
 
+    // -tosummary
+    psMetadata *tosummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(tosummaryArgs, PS_LIST_TAIL,  "-diff_id", 0,           "search by diff ID", 0);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL,  "-tess_id",  0,          "search by tessellation ID", NULL);
+    psMetadataAddStr(tosummaryArgs , PS_LIST_TAIL, "-warp_id",  0,         "search by warp_id", NULL);
+    psMetadataAddBool(tosummaryArgs, PS_LIST_TAIL, "-template",  0,        "apply exposure args to template of bothways diff", false);
+    psMetadataAddS64(tosummaryArgs, PS_LIST_TAIL,  "-exp_id",  0,           "search by exposure ID", 0);
+    psMetadataAddStr(tosummaryArgs , PS_LIST_TAIL, "-exp_name",  0,        "search by exposure name", NULL);
+    psMetadataAddTime(tosummaryArgs, PS_LIST_TAIL, "-dateobs_begin", 0,    "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(tosummaryArgs, PS_LIST_TAIL, "-dateobs_end", 0,      "search for exposures by time (<=)", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL,  "-filter", 0,           "search for filter", NULL);
+    psMetadataAddStr(tosummaryArgs,  PS_LIST_TAIL, "-label",  PS_META_DUPLICATE_OK, "search by diffRun label (LIKE comparison)", NULL);
+    psMetadataAddStr(tosummaryArgs,  PS_LIST_TAIL, "-data_group",  PS_META_DUPLICATE_OK, "search by diffRun data_group (LIKE comparison)", NULL);
+    psMetadataAddStr(tosummaryArgs,  PS_LIST_TAIL, "-dist_group",  PS_META_DUPLICATE_OK, "search by diffRun dist_group (LIKE comparison)", NULL);
+
+    psMetadataAddBool(tosummaryArgs, PS_LIST_TAIL, "-all",  0,             "search without arguments", false);
+    psMetadataAddU64(tosummaryArgs, PS_LIST_TAIL,  "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tosummaryArgs, PS_LIST_TAIL, "-simple",  0,          "use the simple output format", false);
+    
+    // -addsummary
+    psMetadata *addsummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(addsummaryArgs, PS_LIST_TAIL,  "-diff_id", 0,           "search by diff ID", 0);
+    psMetadataAddStr(addsummaryArgs, PS_LIST_TAIL, "-tangent_plane", 0, "set tangent plane", NULL);
+    psMetadataAddStr(addsummaryArgs, PS_LIST_TAIL, "-path_base", 0, "set summary path base", NULL);
+
     // -pendingcleanupskyfile
     psMetadata *pendingcleanupskyfileArgs = psMetadataAlloc();
@@ -379,5 +405,4 @@
     psMetadata *importrunArgs = psMetadataAlloc();
     psMetadataAddStr(importrunArgs, PS_LIST_TAIL, "-infile",  0,          "import from this file (required)", NULL);
-
 
 
@@ -414,4 +439,6 @@
     PXOPT_ADD_MODE("-toscrubbedskyfile", "set skyfile as scrubbed", DIFFTOOL_MODE_TOSCRUBBEDSKYFILE, toscrubbedskyfileArgs);
     PXOPT_ADD_MODE("-tofullskyfile", "set skyfile as full", DIFFTOOL_MODE_TOFULLSKYFILE, tofullskyfileArgs);
+    PXOPT_ADD_MODE("-tosummary",            "show runs that can be summarized", DIFFTOOL_MODE_TOSUMMARY, tosummaryArgs);
+    PXOPT_ADD_MODE("-addsummary",           "add entry to the summary table", DIFFTOOL_MODE_ADDSUMMARY, addsummaryArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: branches/czw_branch/20100519/ippTools/src/labeltool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/labeltool.c	(revision 28164)
+++ branches/czw_branch/20100519/ippTools/src/labeltool.c	(revision 28164)
@@ -0,0 +1,290 @@
+/*
+ * magictool.c
+ *
+ * Copyright (C) 2006-2007  Joshua Hoblitt
+ *
+ * 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.
+ */
+
+#ifdef HAVB_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ippdb.h>
+
+#include "pxtools.h"
+#include "labeltool.h"
+
+static bool definelabelMode(pxConfig *config);
+static bool updatelabelMode(pxConfig *config);
+static bool deletelabelMode(pxConfig *config);
+static bool listlabelMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = labeltoolConfig(NULL, argc, argv);
+    if (!config) {
+        psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+        goto FAIL;
+    }
+
+    switch (config->mode) {
+        MODECASE(LABELTOOL_MODE_DEFINELABEL,         definelabelMode);
+        MODECASE(LABELTOOL_MODE_UPDATELABEL,         updatelabelMode);
+        MODECASE(LABELTOOL_MODE_DELETELABEL,         deletelabelMode);
+        MODECASE(LABELTOOL_MODE_LISTLABEL,           listlabelMode);
+        default:
+            psAbort("invalid option (this should not happen)");
+    }
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(EXIT_SUCCESS);
+
+FAIL:
+    psErrorStackPrint(stderr, "\n");
+    int exit_status = pxerrorGetExitStatus();
+
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+    exit(exit_status);
+}
+
+static bool definelabelMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_STR(label,    config->args, "-set_label", true, false);
+    // XXX: perhaps we should have a default priority?
+    PXOPT_LOOKUP_S32(priority, config->args, "-set_priority", true, false);
+
+    // optional
+    PXOPT_LOOKUP_BOOL(inactive, config->args, "-set_inactive", false);
+    PXOPT_LOOKUP_STR(comment, config->args, "-set_comment", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    LabelRow *row = LabelRowAlloc(
+            label,
+            priority,
+            inactive ? false : true,
+            comment
+    );
+
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, false, "failed to allocate Label object");
+        return false;
+    }
+    if (!LabelInsertObject(config->dbh, row)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(row);
+        return false;
+    }
+
+    if (!LabelPrintObject(stdout, row, !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print object");
+            psFree(row);
+            return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+
+static bool updatelabelMode(pxConfig *config)
+{
+    PXOPT_LOOKUP_STR(label,    config->args, "-label", true, false);
+
+
+    // optional (at least one is required)
+    PXOPT_LOOKUP_S32(priority, config->args, "-set_priority", false, false);
+    PXOPT_LOOKUP_BOOL(inactive, config->args, "-set_inactive", false);
+    PXOPT_LOOKUP_BOOL(active, config->args, "-set_active", false);
+    PXOPT_LOOKUP_STR(comment, config->args, "-set_comment", false, false);
+
+    if (! (priority || active || inactive || comment) ) {
+        psError(PS_ERR_UNKNOWN, true, "at least one -set option is required\n");
+        return false;
+    }
+    if (active && inactive) {
+        psError(PS_ERR_UNKNOWN, true, "only one of -active and -inactive may be supplied");
+        return false;
+    }
+
+    psString query = psStringCopy("UPDATE Label SET");
+    char sep = ' ';
+
+    if (priority) {
+        psStringAppend(&query, "%c priority = %d", sep, priority);
+        sep = ',';
+    }
+    if (active) {
+        psStringAppend(&query, "%c active = %d", sep, 1);
+        sep = ',';
+    }
+    if (inactive) {
+        psStringAppend(&query, "%c active = %d", sep, 0);
+        sep = ',';
+    }
+    if (comment) {
+        psStringAppend(&query, "%c comment = '%s'", sep, comment);
+        sep = ',';
+    }
+
+    psStringAppend(&query, " WHERE label = '%s'", label);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    return true;
+}
+
+static bool deletelabelMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(label,    config->args, "-label", true, false);
+
+    psString query = NULL;
+    
+    psStringAppend(&query, "DELETE FROM Label WHERE label = '%s'", label);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    return true;
+}
+
+static bool listlabelMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "LIKE");
+
+    PXOPT_LOOKUP_BOOL(active, config->args,   "-active", false);
+    PXOPT_LOOKUP_BOOL(inactive, config->args, "-inactive", false);
+    if (active && inactive) {
+        psError(PS_ERR_UNKNOWN, true, "only one of -active and inactive may be supplied");
+        return false;
+    }
+    PXOPT_LOOKUP_BOOL(lowtohigh, config->args, "-lowtohigh", false);
+    PXOPT_LOOKUP_BOOL(hightolow, config->args, "-hightolow", false);
+    if (lowtohigh && hightolow) {
+        psError(PS_ERR_UNKNOWN, true, "only one of -lowtohigh and -hightolow may be supplied");
+        return false;
+    }
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // find all rawImfiles matching the default query
+    psString query = psStringCopy("SELECT * FROM Label\n");
+
+    char *sep = " WHERE ";
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " WHERE %s", whereClause);
+        psFree(whereClause);
+        sep = " AND ";
+    }
+    psFree(where);
+
+    if (active) {
+        psStringAppend(&query, "%s active\n", sep);
+        sep = " AND ";
+    } else if (inactive) {
+        psStringAppend(&query, "%s NOT active\n", sep);
+        sep = " AND ";
+    }
+
+    if (lowtohigh || hightolow) {
+        char *order = lowtohigh ? "" : "DESC";
+        psStringAppend(&query, "\nORDER BY priority %s\n", order);
+    }
+
+    // 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) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("labeltool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "Label", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
Index: branches/czw_branch/20100519/ippTools/src/labeltool.h
===================================================================
--- branches/czw_branch/20100519/ippTools/src/labeltool.h	(revision 28164)
+++ branches/czw_branch/20100519/ippTools/src/labeltool.h	(revision 28164)
@@ -0,0 +1,35 @@
+/*
+ * labeltool.h
+ *
+ * Copyright (C) 2010  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.
+ */
+
+#ifndef LABELTOOL_H
+#define LABELTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    LABELTOOL_MODE_NONE           = 0x0,
+    LABELTOOL_MODE_DEFINELABEL,
+    LABELTOOL_MODE_UPDATELABEL,
+    LABELTOOL_MODE_DELETELABEL,
+    LABELTOOL_MODE_LISTLABEL,
+} labeltoolMode;
+
+pxConfig *labeltoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // LABELTOOL_H
Index: branches/czw_branch/20100519/ippTools/src/labeltoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/labeltoolConfig.c	(revision 28164)
+++ branches/czw_branch/20100519/ippTools/src/labeltoolConfig.c	(revision 28164)
@@ -0,0 +1,113 @@
+/*
+ * labeltoolConfig.c
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+
+#include <psmodules.h>
+
+#include "pxtools.h"
+#include "labeltool.h"
+
+pxConfig *labeltoolConfig(pxConfig *config, int argc, char **argv)
+{
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    pmConfigReadParamsSet(false);
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv, NULL);
+    if (!config->modules) {
+        psError(psErrorCodeLast(), false, "Can't find site configuration");
+        psFree(config);
+        return NULL;
+    }
+
+    psTime *now = psTimeGetNow(PS_TIME_TAI);
+
+    // -definelabel
+    psMetadata *definelabelArgs = psMetadataAlloc();
+    psMetadataAddStr(definelabelArgs, PS_LIST_TAIL, "-set_label",   0, "define label (required)", NULL);
+    psMetadataAddS64(definelabelArgs, PS_LIST_TAIL, "-set_priority", 0, "define priority (required)", 0);
+    psMetadataAddBool(definelabelArgs, PS_LIST_TAIL, "-set_inactive", 0, "set label inactive", false);
+    psMetadataAddStr(definelabelArgs, PS_LIST_TAIL, "-set_comment",  0, "define label comment", NULL);
+    psMetadataAddBool(definelabelArgs, PS_LIST_TAIL, "-simple",  0, "use the simple output format", false);
+
+    // -updatelabel
+    psMetadata *updatelabelArgs = psMetadataAlloc();
+    psMetadataAddStr(updatelabelArgs, PS_LIST_TAIL, "-label", 0, "search by label (LIKE comparison) (required)", NULL);
+    psMetadataAddS64(updatelabelArgs, PS_LIST_TAIL, "-set_priority", 0, "define new priority", 0);
+    psMetadataAddBool(updatelabelArgs, PS_LIST_TAIL, "-set_active", 0, "set label active", false);
+    psMetadataAddBool(updatelabelArgs, PS_LIST_TAIL, "-set_inactive", 0, "set label inactive", false);
+    psMetadataAddStr(updatelabelArgs, PS_LIST_TAIL, "-set_comment",  0, "define new label comment", NULL);
+
+    // -deletelabel
+    psMetadata *deletelabelArgs = psMetadataAlloc();
+    psMetadataAddStr(deletelabelArgs, PS_LIST_TAIL, "-label", 0, "label to delete (required)", NULL);
+
+    // -listlabel
+    psMetadata *listlabelArgs = psMetadataAlloc();
+    psMetadataAddStr(listlabelArgs, PS_LIST_TAIL, "-label", 0, "search by label (LIKE comparison)", NULL);
+    psMetadataAddBool(listlabelArgs, PS_LIST_TAIL, "-hightolow", 0, "order by priority high to low", false);
+    psMetadataAddBool(listlabelArgs, PS_LIST_TAIL, "-lowtohigh", 0, "order by priority low to high", false);
+    psMetadataAddBool(listlabelArgs, PS_LIST_TAIL, "-active", 0, "list active labels", false);
+    psMetadataAddBool(listlabelArgs, PS_LIST_TAIL, "-inactive", 0, "list inactive labels", false);
+    psMetadataAddU64(listlabelArgs, PS_LIST_TAIL, "-limit",  0,  "limit result set to N items", 0);
+    psMetadataAddBool(listlabelArgs, PS_LIST_TAIL, "-simple",  0, "use the simple output format", false);
+
+
+
+    psFree(now);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes   = psMetadataAlloc();
+
+    PXOPT_ADD_MODE("-definelabel",   "", LABELTOOL_MODE_DEFINELABEL, definelabelArgs);
+    PXOPT_ADD_MODE("-updatelabel",   "", LABELTOOL_MODE_UPDATELABEL, updatelabelArgs);
+    PXOPT_ADD_MODE("-deletelabel",   "", LABELTOOL_MODE_DELETELABEL, deletelabelArgs);
+    PXOPT_ADD_MODE("-listlabel",     "", LABELTOOL_MODE_LISTLABEL,   listlabelArgs);
+
+    if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+        psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+        psFree(argSets);
+        psFree(modes);
+        psFree(config);
+        return NULL;
+    }
+
+    psFree(argSets);
+    psFree(modes);
+
+    // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
+    config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+    if (!config->dbh) {
+        psError(PS_ERR_UNKNOWN, false, "Can't configure database");
+        psFree(config);
+        return NULL;
+    }
+
+    return config;
+}
Index: branches/czw_branch/20100519/ippTools/src/pxtools.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pxtools.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/pxtools.c	(revision 28164)
@@ -49,108 +49,133 @@
 
 psString pxMergeCodeVersions(psString version1, psString version2) {
-  psString out = NULL;
-
-  bool mod1 = false;
-  bool mod2 = false;
-
-  psS32 num1;
-  psS32 num2;
-  psS32 numO;
-
-  if (!version1) {
-    psStringAppend(&out,version2);
+    psString out = NULL;
+
+    bool mod1 = false;
+    bool mod2 = false;
+
+    psS32 num1;
+    psS32 num2;
+    psS32 numO;
+
+    if (!version1) {
+	psStringAppend(&out, "%s", version2);
+	return(out);
+    }
+    if (!version2) {
+	psStringAppend(&out, "%s", version1);
+	return(out);
+    }
+  
+    if (strchr(version1,'M')) {
+	psStringSubstitute(&version1,"M","");
+	mod1 = true;
+    }
+    if (strchr(version2,'M')) {
+	psStringSubstitute(&version2,"M","");
+	mod2 = true;
+    }
+
+    num1 = strtol(version1,NULL,10);
+    num2 = strtol(version2,NULL,10);
+
+    if (num1 >= num2) {
+	numO = num1;
+    }
+    else {
+	numO = num2;
+    }
+  
+    psStringAppend(&out,"%" PRId32,numO);
+    if (mod1 || mod2) {
+	psStringAppend(&out,"M");
+    }
     return(out);
-  }
-  if (!version2) {
-    psStringAppend(&out,version1);
-    return(out);
-  }
-  
-  if (strchr(version1,'M')) {
-    psStringSubstitute(&version1,"M","");
-    mod1 = true;
-  }
-  if (strchr(version2,'M')) {
-    psStringSubstitute(&version2,"M","");
-    mod2 = true;
-  }
-
-  num1 = strtol(version1,NULL,10);
-  num2 = strtol(version2,NULL,10);
-
-  if (num1 >= num2) {
-    numO = num1;
-  }
-  else {
-    numO = num2;
-  }
-  
-  psStringAppend(&out,"%" PRId32,numO);
-  if (mod1 || mod2) {
-    psStringAppend(&out,"M");
-  }
-  return(out);
 }
 
 bool pxCoalesceRunStatus(pxConfig *config, const psString dbQFile, psS64 stage_id, psString *software_ver,
-			 psS32 *maskfrac_npix, psF32 *maskfrac_static, psF32 *maskfrac_dynamic,
+			 psS64 *maskfrac_npix, psF32 *maskfrac_static, psF32 *maskfrac_dynamic,
 			 psF32 *maskfrac_magic, psF32 *maskfrac_advisory) {
-  psString query = pxDataGet(dbQFile);
+    psString query = pxDataGet(dbQFile);
 /*   psString text_id = NULL; */
 /*   psStringAppend(&text_id," %" PRId64,stage_id); */
 /*   psStringSubstitute(&query,text_id,"@STAGE_ID@"); */
 /*   psFree(text_id); */
-  if (!p_psDBRunQueryF(config->dbh, query, stage_id)) {
-    psError(PS_ERR_UNKNOWN, false, "database error");
+    if (!p_psDBRunQueryF(config->dbh, query, stage_id)) {
+	psError(PS_ERR_UNKNOWN, false, "database error");
+	psFree(query);
+	return(false);
+    }
     psFree(query);
-    return(false);
-  }
-  psFree(query);
-  psArray *output = p_psDBFetchResult(config->dbh);
-  if (!output) {
-    psError(PS_ERR_UNKNOWN, false, "database error");
-    return(false);
-  }
-  
-  for (long i = 0; i < psArrayLength(output); i++) {
-    psMetadata *row = output->data[i];
-
-    psS32 this_npix = psMetadataLookupS32(NULL, row, "maskfrac_npix");
-    psF32 this_static = psMetadataLookupF32(NULL, row, "maskfrac_static");
-    psF32 this_dynamic = psMetadataLookupF32(NULL, row, "maskfrac_dynamic");
-    psF32 this_magic = psMetadataLookupF32(NULL, row, "maskfrac_magic");
-    psF32 this_advisory = psMetadataLookupF32(NULL, row, "maskfrac_advisory");
-    psString this_version = psMetadataLookupStr(NULL, row, "software_ver");
-
-    *software_ver = pxMergeCodeVersions(*software_ver,this_version);
-
-    *maskfrac_static = ((*maskfrac_static * *maskfrac_npix) + (this_npix * this_static)) / (this_npix + *maskfrac_npix);
-    *maskfrac_dynamic = ((*maskfrac_dynamic * *maskfrac_npix) + (this_npix * this_dynamic)) / (this_npix + *maskfrac_npix);
-    *maskfrac_magic = ((*maskfrac_magic * *maskfrac_npix) + (this_npix * this_magic)) / (this_npix + *maskfrac_npix);
-    *maskfrac_advisory = ((*maskfrac_advisory * *maskfrac_npix) + (this_npix * this_advisory)) / (this_npix + *maskfrac_npix);
-    *maskfrac_npix += this_npix;
-  }
-  psFree(output);
-  return(true);
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+	psError(PS_ERR_UNKNOWN, false, "database error");
+	return(false);
+    }
+  
+    for (long i = 0; i < psArrayLength(output); i++) {
+	psMetadata *row = output->data[i];
+
+	psS32 this_npix = psMetadataLookupS32(NULL, row, "maskfrac_npix");
+	psF32 this_static = psMetadataLookupF32(NULL, row, "maskfrac_static");
+	psF32 this_dynamic = psMetadataLookupF32(NULL, row, "maskfrac_dynamic");
+	psF32 this_magic = psMetadataLookupF32(NULL, row, "maskfrac_magic");
+	psF32 this_advisory = psMetadataLookupF32(NULL, row, "maskfrac_advisory");
+	psString this_version = psMetadataLookupStr(NULL, row, "software_ver");
+
+	*software_ver = pxMergeCodeVersions(*software_ver,this_version);
+/*     printf("%ld : %d %f %f %f %f <-> %ld %f %f %f %f\n",i,this_npix,this_static,this_dynamic,this_magic,this_advisory, */
+/* 	   *maskfrac_npix,*maskfrac_static,*maskfrac_dynamic,*maskfrac_magic,*maskfrac_advisory); */
+	if (this_npix > 0) {
+	    *maskfrac_static = ((*maskfrac_static * *maskfrac_npix) + (this_npix * this_static)) / (this_npix + *maskfrac_npix);
+	    *maskfrac_dynamic = ((*maskfrac_dynamic * *maskfrac_npix) + (this_npix * this_dynamic)) / (this_npix + *maskfrac_npix);
+	    *maskfrac_magic = ((*maskfrac_magic * *maskfrac_npix) + (this_npix * this_magic)) / (this_npix + *maskfrac_npix);
+	    *maskfrac_advisory = ((*maskfrac_advisory * *maskfrac_npix) + (this_npix * this_advisory)) / (this_npix + *maskfrac_npix);
+	    *maskfrac_npix += this_npix;
+	}
+    }
+    psFree(output);
+    return(true);
 }
 
 bool pxSetRunSoftware(pxConfig *config, const psString tableName, const psString stage_id_name, const psS64 stage_id,
 		      psString software_ver) {
-  char *query = "UPDATE %s SET software_ver = '%s' WHERE %s = %" PRId64;
-  printf(query,tableName,software_ver,stage_id_name,stage_id);
-  if (!p_psDBRunQueryF(config->dbh,query,tableName,software_ver,stage_id_name,stage_id)) {
-    psError(PS_ERR_UNKNOWN, false,
-	    "failed to set software version for %s %" PRId64,stage_id_name,stage_id);
-    return(false);
-  }
-  
-  return(true);
-}
+    char *query = "UPDATE %s SET software_ver = '%s' WHERE %s = %" PRId64;
+/*   printf(query,tableName,software_ver,stage_id_name,stage_id); */
+    if (!p_psDBRunQueryF(config->dbh,query,tableName,software_ver,stage_id_name,stage_id)) {
+	psError(PS_ERR_UNKNOWN, false,
+		"failed to set software version for %s %" PRId64,stage_id_name,stage_id);
+	return(false);
+    }
+  
+    return(true);
+}
+
 bool pxSetRunMaskfrac(pxConfig *config, const psString tableName, const psString stage_id_name, const psS64 stage_id,
-		      psS32 maskfrac_npix, psF32 maskfrac_static, psF32 maskfrac_dynamic,
+		      psS64 maskfrac_npix, psF32 maskfrac_static, psF32 maskfrac_dynamic,
 		      psF32 maskfrac_magic, psF32 maskfrac_advisory) {
-  char *query = "UPDATE %s SET maskfrac_npix = %d, maskfrac_static = %f, maskfrac_dynamic = %f, maskfrac_magic = %f, maskfrac_advisory = %f WHERE %s = %" PRId64;
-  if (!p_psDBRunQueryF(config->dbh,query,tableName,maskfrac_npix,maskfrac_static,
-		       maskfrac_dynamic, maskfrac_magic,maskfrac_advisory,stage_id_name,stage_id)) {
+    char *query = "UPDATE %s SET maskfrac_npix = %f, maskfrac_static = %f, maskfrac_dynamic = %f, maskfrac_magic = %f, maskfrac_advisory = %f WHERE %s = %" PRId64;
+    if (!p_psDBRunQueryF(config->dbh,query,tableName,(float) maskfrac_npix,maskfrac_static,
+			 maskfrac_dynamic, maskfrac_magic,maskfrac_advisory,stage_id_name,stage_id)) {
+	psError(PS_ERR_UNKNOWN, false,
+		"failed to set maskfrac stats for %s %" PRId64,stage_id_name,stage_id);
+	return(false);
+    }
+  
+
+
+    return(true);
+}
+
+bool pxCamSetRunMaskfrac(pxConfig *config, const psString tableName, const psString stage_id_name, const psS64 stage_id,
+			 psS64 maskfrac_ref_npix, psF32 maskfrac_ref_static, psF32 maskfrac_ref_dynamic,
+			 psF32 maskfrac_ref_magic, psF32 maskfrac_ref_advisory,
+			 psS64 maskfrac_max_npix, psF32 maskfrac_max_static, psF32 maskfrac_max_dynamic,
+			 psF32 maskfrac_max_magic, psF32 maskfrac_max_advisory) {
+  char *query = "UPDATE %s SET maskfrac_ref_npix = %f, maskfrac_ref_static = %f, maskfrac_ref_dynamic = %f, maskfrac_ref_magic = %f, maskfrac_ref_advisory = %f, maskfrac_max_npix = %f, maskfrac_max_static = %f, maskfrac_max_dynamic = %f, maskfrac_max_magic = %f, maskfrac_max_advisory = %f WHERE %s = %" PRId64;
+  if (!p_psDBRunQueryF(config->dbh,query,tableName,(float) maskfrac_ref_npix,maskfrac_ref_static,
+		       maskfrac_ref_dynamic, maskfrac_ref_magic,maskfrac_ref_advisory,
+		       (float) maskfrac_max_npix,maskfrac_max_static,
+		       maskfrac_max_dynamic, maskfrac_max_magic,maskfrac_max_advisory,
+		       stage_id_name,stage_id)) {
     psError(PS_ERR_UNKNOWN, false,
 	    "failed to set maskfrac stats for %s %" PRId64,stage_id_name,stage_id);
@@ -268,11 +293,11 @@
     char *comma = ",";
 
-#   define addColumn(_tab, _val) \
-        do { \
-            if (_val) { \
-                psStringAppend(pQuery, "%s %s.%s = '%s'", separator, _tab, #_val, _val); \
-                separator = comma; \
-            } \
-        } while (0)
+#   define addColumn(_tab, _val)					\
+    do {								\
+	if (_val) {							\
+	    psStringAppend(pQuery, "%s %s.%s = '%s'", separator, _tab, #_val, _val); \
+	    separator = comma;						\
+	}								\
+    } while (0)
 
     addColumn(runTable, state);
@@ -411,5 +436,5 @@
         if (import_version && strcmp(import_version, schema_version)) {
             psError(PS_ERR_UNKNOWN, true, "input file schema_version: %s does not match data base: %s",
-                import_version, schema_version);
+		    import_version, schema_version);
             return false;
         } else if (!import_version) {
Index: branches/czw_branch/20100519/ippTools/src/pxtools.h
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pxtools.h	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/pxtools.h	(revision 28164)
@@ -55,11 +55,16 @@
 psString pxMergeCodeVersions(psString version1, psString version2);
 bool pxCoalesceRunStatus(pxConfig *config, const psString dbQFile, psS64 stage_id, psString *software_ver,
-			 psS32 *maskfrac_npix, psF32 *maskfrac_static, psF32 *maskfrac_dynamic,
+			 psS64 *maskfrac_npix, psF32 *maskfrac_static, psF32 *maskfrac_dynamic,
 			 psF32 *maskfrac_magic, psF32 *maskfrac_advisory);
 bool pxSetRunSoftware(pxConfig *config, const psString tableName, const psString stage_id_name, const psS64 stage_id,
 		      psString software_ver);
 bool pxSetRunMaskfrac(pxConfig *config, const psString tableName, const psString stage_id_name, const psS64 stage_id,
-		      psS32 maskfrac_npix, psF32 maskfrac_static, psF32 maskfrac_dynamic,
+		      psS64 maskfrac_npix, psF32 maskfrac_static, psF32 maskfrac_dynamic,
 		      psF32 maskfrac_magic, psF32 maskfrac_advisory);
+bool pxCamSetRunMaskfrac(pxConfig *config, const psString tableName, const psString stage_id_name, const psS64 stage_id,
+			 psS64 maskfrac_ref_npix, psF32 maskfrac_ref_static, psF32 maskfrac_ref_dynamic,
+			 psF32 maskfrac_ref_magic, psF32 maskfrac_ref_advisory,
+			 psS64 maskfrac_max_npix, psF32 maskfrac_max_static, psF32 maskfrac_max_dynamic,
+			 psF32 maskfrac_max_magic, psF32 maskfrac_max_advisory);
 
 bool pxSetStateCleaned(const psString tableName, const psString columnName, psArray *rows);
Index: branches/czw_branch/20100519/ippTools/src/stacktool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/stacktool.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/stacktool.c	(revision 28164)
@@ -40,4 +40,6 @@
 static bool sumskyfileMode(pxConfig *config);
 static bool revertsumskyfileMode(pxConfig *config);
+static bool tosummaryMode(pxConfig *config);
+static bool addsummaryMode(pxConfig *config);
 static bool pendingcleanuprunMode(pxConfig *config);
 static bool pendingcleanupskyfileMode(pxConfig *config);
@@ -76,4 +78,6 @@
         MODECASE(STACKTOOL_MODE_SUMSKYFILE,            sumskyfileMode);
         MODECASE(STACKTOOL_MODE_REVERTSUMSKYFILE,      revertsumskyfileMode);
+	MODECASE(STACKTOOL_MODE_TOSUMMARY,             tosummaryMode);
+	MODECASE(STACKTOOL_MODE_ADDSUMMARY,            addsummaryMode);
         MODECASE(STACKTOOL_MODE_PENDINGCLEANUPRUN,     pendingcleanuprunMode);
         MODECASE(STACKTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileMode);
@@ -1125,4 +1129,117 @@
 }
 #endif
+static bool tosummaryMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-stack_id",    "stackSumSkyfile.warp_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-tess_id",    "stackSumSkyfile.tess_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-state",      "stackRun.state", "==");
+  PXOPT_COPY_STR(config->args, where, "-filter",    "stackRun.filter", "LIKE");
+  pxAddLabelSearchArgs (config, where, "-label",   "stackRun.label", "LIKE");
+  pxAddLabelSearchArgs (config, where, "-data_group",   "stackRun.data_group", "LIKE");
+  
+  PXOPT_LOOKUP_BOOL(all, config->args, "-all", false);
+
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  
+  // find all rawImfiles matching the default query
+  psString query = pxDataGet("stacktool_tosummary.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    return false;
+  }
+
+  // generate where strings for arguments that require extra processing
+  // beyond PXOPT_COPY*
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " WHERE %s", whereClause);
+    psFree(whereClause);
+  } else if (!all) {
+    psError(PXTOOLS_ERR_CONFIG, true, "search parameters or -all are required");
+    return false;
+  }
+  
+  psFree(where);
+
+  // 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) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+    }
+    
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("stacktool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+  
+  if (psArrayLength(output)) {
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "stackRun", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+  
+  psFree(output);
+  return(true);
+}
+static bool addsummaryMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", true, false);
+  PXOPT_LOOKUP_STR(tangent_plane, config->args, "-tangent_plane", true, false);
+  PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", true, false);
+
+  psString query = pxDataGet("stacktool_addsummary.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    return(false);
+  }
+  if (!p_psDBRunQueryF(config->dbh, query, stack_id, tangent_plane, path_base)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return(false);
+  }
+  psS64 numUpdated = psDBAffectedRows(config->dbh);
+  
+  if (numUpdated != 1) {
+    psError(PS_ERR_UNKNOWN, false, "should have affected 1 row");
+    psFree(query);
+    return false;
+  }
+  
+  psFree(query);
+
+  // Print anything here?
+  
+  return(true);
+}
 
 static bool pendingcleanuprunMode(pxConfig *config)
Index: branches/czw_branch/20100519/ippTools/src/stacktool.h
===================================================================
--- branches/czw_branch/20100519/ippTools/src/stacktool.h	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/stacktool.h	(revision 28164)
@@ -34,4 +34,6 @@
     STACKTOOL_MODE_SUMSKYFILE,
     STACKTOOL_MODE_REVERTSUMSKYFILE,
+    STACKTOOL_MODE_TOSUMMARY,
+    STACKTOOL_MODE_ADDSUMMARY,
     STACKTOOL_MODE_PENDINGCLEANUPRUN,
     STACKTOOL_MODE_PENDINGCLEANUPSKYFILE,
Index: branches/czw_branch/20100519/ippTools/src/stacktoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/stacktoolConfig.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/stacktoolConfig.c	(revision 28164)
@@ -204,4 +204,24 @@
     psMetadataAddBool(revertsumskyfileArgs, PS_LIST_TAIL, "-all",  0, "allow no search terms", 0);
 
+    // -tosummary
+    psMetadata *tosummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(tosummaryArgs, PS_LIST_TAIL, "-stack_id", 0,  "search by stack ID", 0);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL, "-tess_id", 0,   "search by tessellation ID", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL, "-state", 0,     "search by state", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL, "-filter", 0,    "search by filter", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by stackRun label (LIKE comparison)", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL, "-data_group", PS_META_DUPLICATE_OK, "search by stackRun data_group (LIKE comparison)", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL, "-dist_group", PS_META_DUPLICATE_OK, "search by stackRun dist_group (LIKE comparison)", NULL);
+
+    psMetadataAddBool(tosummaryArgs, PS_LIST_TAIL, "-all",  0,             "search without arguments", false);
+    psMetadataAddU64(tosummaryArgs, PS_LIST_TAIL,  "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tosummaryArgs, PS_LIST_TAIL, "-simple",  0,          "use the simple output format", false);
+
+    // -addsummary
+    psMetadata *addsummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(addsummaryArgs, PS_LIST_TAIL, "-stack_id", 0,      "set stack ID", 0);
+    psMetadataAddStr(addsummaryArgs, PS_LIST_TAIL, "-tangent_plane", 0, "set tangent plane", NULL);
+    psMetadataAddStr(addsummaryArgs, PS_LIST_TAIL, "-path_base", 0,     "set summary path base", NULL);		     
+    
     // -pendingcleanuprun
     psMetadata *pendingcleanuprunArgs = psMetadataAlloc();
@@ -257,4 +277,6 @@
     PXOPT_ADD_MODE("-donecleanup",           "show runs that have been cleaned",     STACKTOOL_MODE_DONECLEANUP,          donecleanupArgs);
     PXOPT_ADD_MODE("-updatesumskyfile",      "update fault code for sumskyfile",     STACKTOOL_MODE_UPDATESUMSKYFILE,          updatesumskyfileArgs);
+    PXOPT_ADD_MODE("-tosummary",            "show runs that can be summarized", STACKTOOL_MODE_TOSUMMARY, tosummaryArgs);
+    PXOPT_ADD_MODE("-addsummary",           "add entry to the summary table", STACKTOOL_MODE_ADDSUMMARY, addsummaryArgs);
     PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", STACKTOOL_MODE_EXPORTRUN, exportrunArgs);
     PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           STACKTOOL_MODE_IMPORTRUN, importrunArgs);
Index: branches/czw_branch/20100519/ippTools/src/staticskytool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/staticskytool.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/staticskytool.c	(revision 28164)
@@ -1,4 +1,4 @@
 /*
- * stacktool.c
+ * staticskytool.c
  *
  * Copyright (C) 2007-2010  Joshua Hoblitt, Paul Price
@@ -29,23 +29,16 @@
 
 #include "pxtools.h"
-#include "stacktool.h"
+#include "staticskytool.h"
 
 static bool definebyqueryMode(pxConfig *config);
-static bool definerunMode(pxConfig *config);
 static bool updaterunMode(pxConfig *config);
-static bool addinputskyfileMode(pxConfig *config);
-static bool inputskyfileMode(pxConfig *config);
-static bool tosumMode(pxConfig *config);
-static bool addsumskyfileMode(pxConfig *config);
-static bool sumskyfileMode(pxConfig *config);
-static bool revertsumskyfileMode(pxConfig *config);
-static bool pendingcleanuprunMode(pxConfig *config);
-static bool pendingcleanupskyfileMode(pxConfig *config);
-static bool donecleanupMode(pxConfig *config);
-static bool updatesumskyfileMode(pxConfig *config);
+static bool inputsMode(pxConfig *config);
+static bool todoMode(pxConfig *config);
+static bool addresultMode(pxConfig *config);
+static bool resultMode(pxConfig *config);
+static bool revertMode(pxConfig *config);
+static bool updateresult(pxConfig *config);
 static bool exportrunMode(pxConfig *config);
 static bool importrunMode(pxConfig *config);
-
-static bool setstackRunState(pxConfig *config, psS64 stack_id, const char *state);
 
 # define MODECASE(caseName, func) \
@@ -60,5 +53,5 @@
     psLibInit(NULL);
 
-    pxConfig *config = stacktoolConfig(NULL, argc, argv);
+    pxConfig *config = staticskytoolConfig(NULL, argc, argv);
     if (!config) {
         psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
@@ -67,14 +60,14 @@
 
     switch (config->mode) {
-        MODECASE(STACKTOOL_MODE_DEFINEBYQUERY, definebyqueryMode);
-        MODECASE(STACKTOOL_MODE_UPDATERUN,     updaterunMode);
-        MODECASE(STACKTOOL_MODE_INPUTS,        inputsMode);
-        MODECASE(STACKTOOL_MODE_TODO,          todoMode);
-        MODECASE(STACKTOOL_MODE_ADDRESULT,     addresultMode);
-        MODECASE(STACKTOOL_MODE_RESULT,        resultMode);
-        MODECASE(STACKTOOL_MODE_REVERT,        revertMode);
-        MODECASE(STACKTOOL_MODE_UPDATERESULT,  updateresultMode);
-        MODECASE(STACKTOOL_MODE_EXPORTRUN,     exportrunMode);
-        MODECASE(STACKTOOL_MODE_IMPORTRUN,     importrunMode);
+        MODECASE(STATICSKYTOOL_MODE_DEFINEBYQUERY,     definebyqueryMode);
+        MODECASE(STATICSKYTOOL_MODE_UPDATERUN,         updaterunMode);
+        MODECASE(STATICSKYTOOL_MODE_INPUTS,            inputsMode);
+        MODECASE(STATICSKYTOOL_MODE_TODO,              todoMode);
+        MODECASE(STATICSKYTOOL_MODE_ADDRESULT,         addresultMode);
+        MODECASE(STATICSKYTOOL_MODE_RESULT,            resultMode);
+        MODECASE(STATICSKYTOOL_MODE_REVERT,            revertMode);
+        MODECASE(STATICSKYTOOL_MODE_UPDATERESULT,      updateresult);
+        MODECASE(STATICSKYTOOL_MODE_EXPORTRUN,         exportrunMode);
+        MODECASE(STATICSKYTOOL_MODE_IMPORTRUN,         importrunMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -114,86 +107,57 @@
     PXOPT_LOOKUP_TIME(registered, config->args, "-set_registered", false, false);
 
-    psMetadata *where = psMetadataAlloc();
-    psMetadata *having = psMetadataAlloc(); // HAVING clause
-
-    PXOPT_COPY_F32(config->args, where, "-select_good_frac_min", "stackSumSkyfile.good_frac", ">=");
-    PXOPT_COPY_STR(config->args, where, "-select_skycell_id",    "stackRun.skycell_id",       "==");
-    pxAddLabelSearchArgs(config, where, "-select_label",         "stackRun.label",            "LIKE");
-    pxAddLabelSearchArgs(config, where, "-select_filter",        "stackRun.filter",           "LIKE");
-
-    // these are used to build the HAVING restriction
-    PXOPT_COPY_S32(config->args, having, "-min_num",    "num",        ">=");
-    PXOPT_COPY_S32(config->args, having, "-min_filter", "num_filter", ">=");
+    psMetadata *whereMD = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, whereMD, "-select_skycell_id",    "stackRun.skycell_id",       "==");
+    PXOPT_COPY_STR(config->args, whereMD, "-select_tess_id",       "stackRun.tess_id",          "==");
+    PXOPT_COPY_F32(config->args, whereMD, "-select_good_frac_min", "stackSumSkyfile.good_frac", ">=");
+    pxAddLabelSearchArgs(config, whereMD, "-select_label",         "stackRun.label",            "LIKE");
+    pxAddLabelSearchArgs(config, whereMD, "-select_filter",        "stackRun.filter",           "LIKE");
+
+    // find the number of requested filters:
+    psMetadataItem *filters = psMetadataLookup(config->args, "-select_filter");
+    psAssert (filters, "-select_filter must exist");
+    psAssert (filters->type == PS_DATA_METADATA_MULTI, "-select_filter should be a multi container");
+    psAssert (filters->data.list->n, "-select_filter should at least have a place-holder");
+    int num_filter = filters->data.list->n;
+    if (num_filter < 2) {
+        psError(PXTOOLS_ERR_CONFIG, false, "invalid request: only 1 filter selected");
+        psFree(whereMD);
+        return false;
+    }
 
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
-
-    if (!psListLength(where->list)) {
-        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
-        psFree(where);
-        psFree(having);
-        return false;
-    }
 
     psString select = pxDataGet("staticskytool_definebyquery_select.sql");
     if (!select) {
         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(&where1, "\nAND %s", whereClause);
-        psFree(whereClause);
-    }
-
-    psString where2 = psStringCopy("");
-    if (label) {
-        psStringAppend(&where2, "\nWHERE stackRun.label = '%s'", label);
-    }
-
-    // Restriction on aggregated quantities using HAVING
-    {
-        psString havingClause = NULL;   // HAVING string
-        if (psListLength(having->list)) {
-            havingClause = psDBGenerateWhereConditionSQL(having, NULL);
-        }
-
-        if (min_new > 0) {
-            if (havingClause) {
-                psStringAppend(&havingClause, " AND");
-            }
-            psStringAppend(&havingClause,
-                           " (num_warp - num_stack >= %d OR (num_warp >= %d AND num_stack IS NULL))",
-                           min_new, min_new);
-        }
-        if (isfinite(min_frac)) {
-            if (havingClause) {
-                psStringAppend(&havingClause, " AND");
-            }
-            // Avoiding division by zero
-            psStringAppend(&havingClause, " (num_warp >= %f * num_stack OR num_stack IS NULL)",
-                           (double)min_frac);
-        }
-        if (havingClause) {
-            psStringAppend(&select, " HAVING %s", havingClause);
-            psFree(havingClause);
-        }
-    }
-    psFree(having);
-
-    if (!p_psDBRunQueryF(config->dbh, select, where1, where2)) {
+        psFree(whereMD);
+        return false;
+    }
+
+    if (!psListLength(whereMD->list)) {
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        psFree(whereMD);
+        return false;
+    }
+
+    // this 'where' is used for both staticskytool_definebyquery_select.sql and staticskytool_definebyquery_inputs.sql 
+    psString where = NULL;
+    psString whereClause = psDBGenerateWhereConditionSQL(whereMD, NULL);
+    psStringAppend(&where, "\nAND %s", whereClause);
+    psFree(whereClause);
+    psFree(whereMD);
+
+    if (!p_psDBRunQueryF(config->dbh, select, where, num_filter)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
         psFree(select);
-        psFree(where1);
-        psFree(where2);
         return false;
     }
     psFree(select);
-    psFree(where1);
-    psFree(where2);
+
+    // we now have a list of (tess_id, skycell_id) that (potentially) meet out needs
+    // we now need to loop over all of these and for each pair, select the best set of
+    // inputs
 
     psArray *output = p_psDBFetchResult(config->dbh);
@@ -212,5 +176,5 @@
     }
     if (!psArrayLength(output)) {
-        psWarning("stacktool: no rows found");
+        psWarning("staticskytool: no rows found");
         psFree(output);
         psFree(where);
@@ -219,5 +183,5 @@
     if (pretend) {
         // negative simple so the default is true
-        if (!ippdbPrintMetadatas(stdout, output, "stackSkycells", !simple)) {
+        if (!ippdbPrintMetadatas(stdout, output, "staticskyInput", !simple)) {
             psError(PS_ERR_UNKNOWN, false, "failed to print array");
             psFree(output);
@@ -230,11 +194,6 @@
     }
 
-    psString insert = NULL;             // Insertion query
-    if (randomLimit > 0) {
-        insert = pxDataGet("stacktool_definebyquery_insert_random_part1.sql");
-    } else {
-        insert = pxDataGet("stacktool_definebyquery_insert.sql");
-    }
-    if (!insert) {
+    psString inputsSQL = pxDataGet("staticskytool_definebyquery_inputs.sql");
+    if (!inputsSQL) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
         psFree(where);
@@ -242,29 +201,4 @@
     }
 
-    if (psListLength(where->list)) {
-        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-        psStringAppend(&insert, " AND %s", whereClause);
-        psFree(whereClause);
-    }
-    psFree(where);
-
-    if (randomLimit > 0) {
-        psString part2 = pxDataGet("stacktool_definebyquery_insert_random_part2.sql");
-        if (!part2) {
-            psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
-            psFree(insert);
-            return false;
-        }
-        psStringAppend(&insert, "%s", part2);
-        psFree(part2);
-    }
-
-    if (!psDBTransaction(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(where);
-        return false;
-    }
-
-    psArray *list = psArrayAllocEmpty(16); // List of runs, to print
     for (long i = 0; i < output->n; i++) {
         psMetadata *row = output->data[i]; // Row from select
@@ -276,6 +210,5 @@
             psError(PS_ERR_UNKNOWN, false, "failed to lookup skycell_id");
             psFree(output);
-            psFree(insert);
-            psFree(list);
+            psFree(inputsSQL);
             if (!psDBRollback(config->dbh)) {
                 psError(PS_ERR_UNKNOWN, false, "database error");
@@ -288,6 +221,5 @@
             psError(PS_ERR_UNKNOWN, false, "failed to lookup tess_id");
             psFree(output);
-            psFree(insert);
-            psFree(list);
+            psFree(inputsSQL);
             if (!psDBRollback(config->dbh)) {
                 psError(PS_ERR_UNKNOWN, false, "database error");
@@ -296,139 +228,101 @@
         }
 
-        psString filter = psMetadataLookupStr(&status, row, "filter");
-        if (!status) {
-            psError(PS_ERR_UNKNOWN, false, "failed to lookup filter");
+	// query for the inputs
+	if (!p_psDBRunQueryF(config->dbh, inputsSQL, tess_id, skycell_id, where)) {
+	    psError(PS_ERR_UNKNOWN, false, "database error");
             psFree(output);
-            psFree(insert);
-            psFree(list);
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            return false;
-        }
-
-        // create a new stackRun for this stack
-        stackRunRow *run = stackRunRowAlloc(
-            0,                          // ID
-            "new",                      // state
-            workdir,
-            label,
-            data_group ? data_group : label,
-            dist_group,
-            reduction,
-            dvodb,
-            registered,
-            skycell_id,
-            tess_id,
-            filter,
-            note);
-
-        if (!stackRunInsertObject(config->dbh, run)) {
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "database error");
+	    psFree(inputsSQL);
+	    return false;
+	}
+	
+	psArray *inputs = p_psDBFetchResult(config->dbh);
+	if (!inputs) {
+	    psErrorCode err = psErrorCodeLast();
+	    switch (err) {
+	      case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+	      case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+	      default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+	    }
+	    psFree(inputs);
             psFree(output);
-            psFree(run);
-            psFree(insert);
-            psFree(list);
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            return false;
-        }
-
-        // figure out the new stack_id
-        psS64 stack_id = psDBLastInsertID(config->dbh);
-        run->stack_id = stack_id;
-
-        psArrayAdd(list, list->n, run);
-        psFree(run);
-
-        // Create a suitable insertion query for this run
-        psString thisInsert = psStringCopy(insert);
-        psString idString = NULL;
-        psStringAppend(&idString, "%" PRId64, stack_id);
-        psStringSubstitute(&thisInsert, idString, "@STACK_ID@");
-        psFree(idString);
-
-        // replace @FILTER@, @SKYCELL_ID@, @RANDOM_LIMIT@
-        psStringSubstitute(&thisInsert, filter, "@FILTER@");
-        psStringSubstitute(&thisInsert, skycell_id, "@SKYCELL_ID@");
-
-        if (randomLimit > 0) {
-          psString limString = NULL;
-          psStringAppend(&limString, "%d", randomLimit);
-          psStringSubstitute(&thisInsert, limString, "@RANDOM_LIMIT@");
-          psFree(limString);
-        }
-
-        // XXX this insert uses a select to generate the list of warp_ids for the stack,
-        // we have applied a set of criteria above (WHERE) to select the relevant warps
-        // this insert needs to use exactly the same restrictions (race condition is probably not critical)
-        // the insert below seems to only restrict matches to the skycell, tess, and filter
-        if (!p_psDBRunQuery(config->dbh, thisInsert)) {
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(thisInsert);
-            psFree(insert);
+            psFree(inputsSQL);
+	    return false;
+	}
+	if (!psArrayLength(inputs)) {
+	    psWarning("staticskytool ERROR: no rows found for known tess_id, skycell_id?");
+	    continue;
+	}
+
+	// XXX if we are unable to guarantee that all selected inputs have all and only the
+	// requested filters, see the code at the bottom of this file (ifdef'ed out for now)
+
+	// insert a new staticsky entry and find its new id
+	if (!psDBTransaction(config->dbh)) {
+	    psError(PS_ERR_UNKNOWN, false, "database error");
+	    psFree(inputs);
             psFree(output);
-            psFree(list);
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            return false;
-        }
-        psFree(thisInsert);
-
-# if (0)
-        {
-          psArray *output = p_psDBFetchResult(config->dbh);
-          if (!output) {
-            psErrorCode err = psErrorCodeLast();
-            switch (err) {
-            case PS_ERR_DB_CLIENT:
-              psError(PXTOOLS_ERR_SYS, false, "database error");
-            case PS_ERR_DB_SERVER:
-              psError(PXTOOLS_ERR_PROG, false, "database error");
-            default:
-              psError(PXTOOLS_ERR_PROG, false, "unknown error");
-            }
-            psFree(where);
-            return false;
-          }
-          if (!psArrayLength(output)) {
-            psWarning("stacktool (definebyquery, insert): no rows found");
+            psFree(inputsSQL);
+	    return false;
+	}
+
+	// create a chipRun
+	if (!staticskyRunInsert(config->dbh,
+				0x0,	     // sky_id
+				"new",	     // state
+				workdir,
+				label,
+				data_group,
+				dist_group,
+				reduction,
+				registered,
+				note
+		)
+	    ) {
+	    if (!psDBRollback(config->dbh)) {
+		psError(PS_ERR_UNKNOWN, false, "database error failed to rollback transaction");
+	    }
+	    psError(PS_ERR_UNKNOWN, false, "database error");
+	    psFree(inputs);
             psFree(output);
-            psFree(where);
-            return true;
-          }
-          // negative simple so the default is true
-          if (!ippdbPrintMetadatas(stdout, output, "stackSkycells", !simple)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to print array");
-            psFree(output);
-            psFree(where);
-            return false;
-          }
-          psFree(output);
-          psFree(where);
-          return true;
-        }
-# endif
-
-    }
+            psFree(inputsSQL);
+	    return false;
+	}
+
+	psS64 sky_id =  psDBLastInsertID(config->dbh);
+
+	// loop over the possible inputs and record only the valid ones
+	for (int j = 0; j < inputs->n; j++) {
+	    psMetadata *inputRow = inputs->data[j]; // Row from select
+	    
+	    // pull out the skycell_id, tess_id, filter
+	    psS64 stack_id = psMetadataLookupS64(&status, inputRow, "stack_id");
+	    psAssert(status, "failed to find stack_id?");
+	    
+	    // add a staticskyInput entry
+	    if (!staticskyInputInsert(config->dbh, sky_id, stack_id)) {
+		if (!psDBRollback(config->dbh)) {
+		    psError(PS_ERR_UNKNOWN, false, "database error failed to rollback transaction");
+		}
+		psError(PS_ERR_UNKNOWN, false, "database error");
+		psFree(inputs);
+		psFree(output);
+		psFree(inputsSQL);
+		return false;
+	    }
+	}
+	psFree (inputs);
+	
+	if (!psDBCommit(config->dbh)) {
+	    psError(PS_ERR_UNKNOWN, false, "database error");
+	    psFree(output);
+	    psFree(inputsSQL);
+	    return false;
+	}
+    }
+    psFree(inputsSQL);
     psFree(output);
-
-    if (!psDBCommit(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(list);
-        return false;
-    }
-
-    if (!stackRunPrintObjects(stdout, list, !simple)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to print object");
-        psFree(list);
-        return false;
-    }
-    psFree(list);
     return true;
 }
@@ -438,13 +332,8 @@
     PS_ASSERT_PTR_NON_NULL(config, false);
 
-#ifdef notdef
-    PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", false, false);
-    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
-    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
-#endif
     psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-stack_id",  "stack_id",   "==");
-    PXOPT_COPY_STR(config->args, where, "-label",     "label",     "==");
-    PXOPT_COPY_STR(config->args, where, "-state",     "state",     "==");
+    PXOPT_COPY_S64(config->args, where, "-sky_id",  "sky_id",   "==");
+    PXOPT_COPY_STR(config->args, where, "-label",   "label",    "==");
+    PXOPT_COPY_STR(config->args, where, "-state",   "state",    "==");
     if (!psListLength(where->list)) {
         psFree(where);
@@ -453,29 +342,12 @@
     }
 
-    psString query = psStringCopy("UPDATE stackRun");
+    psString query = psStringCopy("UPDATE staticskyRun");
 
     // pxUpdateRun gets parameters from config->args and updates
-    bool result = pxUpdateRun(config, where, &query, "stackRun", "stack_id", "stackSumSkyfile", true);
-
+    bool result = pxUpdateRun(config, where, &query, "staticskyRun", "sky_id", "staticskyResult", true);
     psFree(query);
     psFree(where);
 
     return result;
-
-#ifdef notdef
-    // Hack-y work around to make stacktool more like the other tools, without breaking other stuff (hopefully).
-
-    if ((state)&&(stack_id)) {
-        // set detRun.state to state
-        return setstackRunState(config, stack_id, state);
-    }
-
-    if ((state)&&(label)) {
-      return setstackRunStateByLabel(config, label, state);
-    }
-
-    psError(PS_ERR_UNKNOWN, false, "Required options not found.");
-    return false;
-#endif
 }
 
@@ -485,15 +357,14 @@
     PS_ASSERT_PTR_NON_NULL(config, false);
 
-    // XXX require at least a stack id (add better search options)
-    PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", true, false);
+    // XXX require at least a sky id (add better search options)
+    PXOPT_LOOKUP_S64(sky_id, config->args, "-sky_id", true, false);
 
     psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
-    PXOPT_COPY_S64(config->args, where, "-stack_id", "stack_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-sky_id", "sky_id", "==");
 
     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
 
-    psString query = pxDataGet("stacktool_inputskyfile.sql");
+    psString query = pxDataGet("staticskytool_inputs.sql");
     if (!query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -502,6 +373,6 @@
 
     if (psListLength(where->list)) {
-        psString whereClause = psDBGenerateWhereConditionSQL(where, "stackInputSkyfile");
-        psStringAppend(&query, " AND %s", whereClause);
+        psString whereClause = psDBGenerateWhereConditionSQL(where, "staticskyInput");
+        psStringAppend(&query, " WHERE %s", whereClause);
         psFree(whereClause);
     }
@@ -537,5 +408,5 @@
     }
     if (!psArrayLength(output)) {
-        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psTrace("staticskytool", PS_LOG_INFO, "no rows found");
         psFree(output);
         return true;
@@ -544,5 +415,5 @@
     if (psArrayLength(output)) {
         // negative simple so the default is true
-        if (!ippdbPrintMetadatas(stdout, output, "stackInputSkyfile", !simple)) {
+        if (!ippdbPrintMetadatas(stdout, output, "staticskyInput", !simple)) {
             psError(PS_ERR_UNKNOWN, false, "failed to print array");
             psFree(output);
@@ -561,13 +432,12 @@
     PS_ASSERT_PTR_NON_NULL(config, false);
 
-    psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
-    PXOPT_COPY_S64(config->args, where, "-stack_id", "stack_id", "==");
-    pxAddLabelSearchArgs (config, where, "-label", "stackRun.label", "==");
+    psMetadata *whereMD = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, whereMD, "-sky_id", "sky_id", "==");
+    pxAddLabelSearchArgs (config, whereMD, "-label", "staticskyRun.label", "==");
 
     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
 
-    psString query = pxDataGet("stacktool_tosum.sql");
+    psString query = pxDataGet("staticskytool_todo.sql");
     if (!query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -575,10 +445,15 @@
     }
 
-    if (psListLength(where->list)) {
-        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-        psStringAppend(&query, " AND %s", whereClause);
-        psFree(whereClause);
-    }
-    psFree(where);
+    if (!psListLength(whereMD->list)) {
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        psFree(whereMD);
+        return false;
+    }
+
+    psString where = NULL;
+    psString whereClause = psDBGenerateWhereConditionSQL(whereMD, NULL);
+    psStringAppend(&where, "\n AND %s", whereClause);
+    psFree(whereClause);
+    psFree(whereMD);
 
     // treat limit == 0 as "no limit"
@@ -589,5 +464,6 @@
     }
 
-    if (!p_psDBRunQuery(config->dbh, query)) {
+    // the where clause is required and matches the WHERE hook format string
+    if (!p_psDBRunQueryF(config->dbh, query, where)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
         psFree(query);
@@ -611,5 +487,5 @@
     }
     if (!psArrayLength(output)) {
-        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psTrace("staticskytool", PS_LOG_INFO, "no rows found");
         psFree(output);
         return true;
@@ -618,5 +494,5 @@
     if (psArrayLength(output)) {
         // negative simple so the default is true
-        if (!ippdbPrintMetadatas(stdout, output, "stackSumSkyfile", !simple)) {
+        if (!ippdbPrintMetadatas(stdout, output, "staticskyResult", !simple)) {
             psError(PS_ERR_UNKNOWN, false, "failed to print array");
             psFree(output);
@@ -626,9 +502,7 @@
 
     psFree(output);
-
     return true;
 }
 
-
 static bool addresultMode(pxConfig *config)
 {
@@ -636,31 +510,14 @@
 
     // required
-    PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", true, false);
+    PXOPT_LOOKUP_S64(sky_id, config->args, "-sky_id", true, false);
 
     // optional
-    PXOPT_LOOKUP_STR(uri, config->args, "-uri", false, false);
     PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
-    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
-    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
-    PXOPT_LOOKUP_F32(dtime_stack, config->args, "-dtime_stack", false, false);
-    PXOPT_LOOKUP_F32(dtime_match_mean, config->args, "-dtime_match_mean", false, false);
-    PXOPT_LOOKUP_F32(dtime_match_stdev, config->args, "-dtime_match_stdev", false, false);
-    PXOPT_LOOKUP_F32(dtime_initial, config->args, "-dtime_initial", false, false);
-    PXOPT_LOOKUP_F32(dtime_reject, config->args, "-dtime_reject", false, false);
-    PXOPT_LOOKUP_F32(dtime_final, config->args, "-dtime_final", false, false);
     PXOPT_LOOKUP_F32(dtime_phot, config->args, "-dtime_phot", false, false);
     PXOPT_LOOKUP_F32(dtime_script, config->args, "-dtime_script", false, false);
-    PXOPT_LOOKUP_F32(match_mean, config->args, "-match_mean", false, false);
-    PXOPT_LOOKUP_F32(match_stdev, config->args, "-match_stdev", false, false);
-    PXOPT_LOOKUP_F32(match_rms, config->args, "-match_rms", false, false);
-    PXOPT_LOOKUP_F32(stamps_mean, config->args, "-stamps_mean", false, false);
-    PXOPT_LOOKUP_F32(stamps_stdev, config->args, "-stamps_stdev", false, false);
-    PXOPT_LOOKUP_S32(stamps_min, config->args, "-stamps_min", false, false);
-    PXOPT_LOOKUP_S32(reject_images, config->args, "-reject_images", false, false);
-    PXOPT_LOOKUP_F32(reject_pix_mean, config->args, "-reject_pix_mean", false, false);
-    PXOPT_LOOKUP_F32(reject_pix_stdev, config->args, "-reject_pix_stdev", false, false);
     PXOPT_LOOKUP_S32(sources, config->args, "-sources", false, false);
     PXOPT_LOOKUP_STR(hostname, config->args, "-hostname", false, false);
     PXOPT_LOOKUP_F32(good_frac, config->args, "-good_frac", false, false);
+    PXOPT_LOOKUP_S32(num_inputs, config->args, "-num_inputs", false, false);
 
     // default values
@@ -668,4 +525,5 @@
     PXOPT_LOOKUP_S16(quality, config->args, "-quality", false, false);
 
+    // XXX not sure we need a transaction here...
     if (!psDBTransaction(config->dbh)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
@@ -673,31 +531,11 @@
     }
 
-    // XXX need to validate the stack_id here
-    // XXX instead of validiting it here we should just use forgein key
-    // constrants
-    if (!stackSumSkyfileInsert(config->dbh,
-                               stack_id,
-                               uri,
+    if (!staticskyResultInsert(config->dbh,
+			       sky_id,
                                path_base,
-                               bg,
-                               bg_stdev,
-                               dtime_stack,
-                               dtime_match_mean,
-                               dtime_match_stdev,
-                               dtime_initial,
-                               dtime_reject,
-                               dtime_final,
                                dtime_phot,
                                dtime_script,
-                               match_mean,
-                               match_stdev,
-                               match_rms,
-                               stamps_mean,
-                               stamps_stdev,
-                               stamps_min,
-                               reject_images,
-                               reject_pix_mean,
-                               reject_pix_stdev,
                                sources,
+			       num_inputs,
                                hostname,
                                good_frac,
@@ -712,14 +550,4 @@
     }
 
-    if (fault == 0) {
-        if (!setstackRunState(config, stack_id, "full")) {
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "failed to change stackRun's state");
-            return false;
-        }
-    }
-
     // point of no return
     if (!psDBCommit(config->dbh)) {
@@ -731,5 +559,5 @@
 }
 
-
+// XXX what is this used by?  what filters are needed?
 static bool resultMode(pxConfig *config)
 {
@@ -737,16 +565,8 @@
 
     psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-stack_id", "stackSumSkyfile.stack_id", "==");
-    PXOPT_COPY_STR(config->args, where, "-tess_id", "stackRun.tess_id", "==");
-    PXOPT_COPY_STR(config->args, where, "-skycell_id", "stackRun.skycell_id", "==");
-    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", "==");
-
-//  The following three selectors are incompatible with the sql so omit them
-//    PXOPT_COPY_S64(config->args, where, "-warp_id", "warpRun.warp_id", "==");
-//     PXOPT_COPY_S64(config->args, where, "-exp_id", "rawExp.exp_id", "==");
-//    PXOPT_COPY_STR(config->args, where, "-exp_name", "rawExp.exp_name", "==");
+    PXOPT_COPY_S64(config->args, where, "-sky_id",     "staticskyRun.sky_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-label",      "staticskyRun.label", "==");
+    PXOPT_COPY_STR(config->args, where, "-data_group", "staticskyRun.data_group", "LIKE");
+    PXOPT_COPY_S16(config->args, where, "-fault",      "staticskyResult.fault", "==");
 
     PXOPT_LOOKUP_BOOL(all, config->args, "-all", false);
@@ -755,5 +575,5 @@
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
 
-    psString query = pxDataGet("stacktool_sumskyfile.sql");
+    psString query = pxDataGet("staticskytool_result.sql");
     if (!query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -801,5 +621,5 @@
     }
     if (!psArrayLength(output)) {
-        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psTrace("staticskytool", PS_LOG_INFO, "no rows found");
         psFree(output);
         return true;
@@ -807,5 +627,5 @@
 
     if (psArrayLength(output)) {
-        if (!ippdbPrintMetadatas(stdout, output, "stackSumSkyfile", !simple)) {
+        if (!ippdbPrintMetadatas(stdout, output, "staticskyResult", !simple)) {
             psError(PS_ERR_UNKNOWN, false, "failed to print array");
             psFree(output);
@@ -819,9 +639,9 @@
 }
 
-
 static bool revertMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
 
+# if (0)
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-stack_id", "stackSumSkyfile.stack_id", "==");
@@ -836,5 +656,5 @@
 
     // Delete product
-    psString delete = pxDataGet("stacktool_revertsumskyfile_delete.sql");
+    psString delete = pxDataGet("staticskytool_revertsumskyfile_delete.sql");
     if (!delete) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -857,16 +677,15 @@
 
     int numRows = psDBAffectedRows(config->dbh); // Number of row affected
-    psLogMsg("stacktool", PS_LOG_INFO, "Deleted %d rows", numRows);
+    psLogMsg("staticskytool", PS_LOG_INFO, "Deleted %d rows", numRows);
 
     psFree(where);
+# endif
 
     return true;
 }
 
-
-static bool updateresultState(pxConfig *config, psS64 stack_id, const char *state)
-{
-    PS_ASSERT_PTR_NON_NULL(state, false);
-
+# if (0)
+static bool updateresultState(pxConfig *config)
+{
     // check that state is a valid string value
     if (!pxIsValidState(state)) {
@@ -881,12 +700,13 @@
         return false;
     }
-
     return true;
 }
-
-static bool updateresultMode(pxConfig *config)
+# endif
+
+static bool updateresult(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
 
+# if (0)
     PXOPT_LOOKUP_S16(fault, config->args, "-fault", true, false);
 
@@ -901,4 +721,5 @@
     psFree (where);
 
+# endif
     return true;
 }
@@ -906,4 +727,5 @@
 bool exportrunMode(pxConfig *config)
 {
+# if (0)
   typedef struct ExportTable {
     char tableName[80];
@@ -934,7 +756,7 @@
 
   ExportTable tables [] = {
-    {"stackRun", "stacktool_export_run.sql"},
-    {"stackInputSkyfile", "stacktool_export_input_skyfile.sql"},
-    {"stackSumSkyfile", "stacktool_export_sum_skyfile.sql"},
+    {"stackRun", "staticskytool_export_run.sql"},
+    {"stackInputSkyfile", "staticskytool_export_input_skyfile.sql"},
+    {"stackSumSkyfile", "staticskytool_export_sum_skyfile.sql"},
   };
 
@@ -999,4 +821,5 @@
     fclose (f);
 
+# endif
     return true;
 }
@@ -1004,4 +827,5 @@
 bool importrunMode(pxConfig *config)
 {
+# if (0)
   unsigned int nFail;
 
@@ -1072,4 +896,39 @@
   }
 
+# endif
   return true;
 }
+
+# if (0)
+	// now we need to loop over all requested filters and check that each is found
+	// XXX is this needed?  haven't we required that we only match the requested filters
+	// and that N unique filters are found?
+
+	psVector *found = psVectorAlloc(inputs->n, PS_TYPE_U8);
+	psVectorInit (found, 0);
+
+	psMetadataItem *filter = NULL;
+	psListIterator *iter = psListIteratorAlloc (filters->data.list, PS_LIST_HEAD, false);
+	while ((filter = psListGetAndIncrement(iter))) {
+
+	    bool foundOne = false;
+
+	    psAssert (filter->type == PS_DATA_STR, "filter is not a string?");
+	    for (int j = 0; !foundOne && (j < inputs->n); j++) {
+		if (found->data.U8[j]) continue;
+		psMetadata *inputRow = inputs->data[j]; // Row from select
+
+		// pull out the skycell_id, tess_id, filter
+		psString inFilter = psMetadataLookupStr(&status, row, "filter");
+		psAssert (status);
+
+		found->data.U8[j] = true;
+		foundOne = true;
+	    }
+	    if (!foundOne) {
+		// this required filter was not found in the inputs, skip the entry
+		skip();
+	    }
+	}	    
+# endif
+
Index: branches/czw_branch/20100519/ippTools/src/staticskytoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/staticskytoolConfig.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/staticskytoolConfig.c	(revision 28164)
@@ -52,5 +52,5 @@
     psMetadataAddF32(definebyqueryArgs,  PS_LIST_TAIL, "-select_good_frac_min", 0, "define min good_frac", 0.0);
     psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_label", PS_META_DUPLICATE_OK, "search by stackRun label (LIKE comparison, multiple OK)", NULL);
-    psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_filter", PS_META_DUPLICATE_OK, "search by filter (LIKE comparison, multiple OK)", NULL);
+    psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_filter", PS_META_DUPLICATE_OK, "search by filter (LIKE comparison, multiple required)", NULL);
     psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-set_workdir", 0, "define workdir (required)", NULL);
     psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-set_label", 0, "define label", NULL);
@@ -89,12 +89,13 @@
     // -addresult
     psMetadata *addresultArgs = psMetadataAlloc();
-    psMetadataAddS64(addresultArgs, PS_LIST_TAIL, "-sky_id", 0, "define stack ID (required)", 0);
+    psMetadataAddS64(addresultArgs, PS_LIST_TAIL, "-sky_id", 0, "define sky ID (required)", 0);
     psMetadataAddStr(addresultArgs, PS_LIST_TAIL, "-path_base", 0, "define base output location", 0);
     psMetadataAddF32(addresultArgs, PS_LIST_TAIL, "-dtime_phot", 0, "define photometry time", NAN);
     psMetadataAddF32(addresultArgs, PS_LIST_TAIL, "-dtime_script", 0, "define elapsed time in script (seconds)", NAN);
     psMetadataAddS32(addresultArgs, PS_LIST_TAIL, "-sources", 0, "number of sources", 0);
+    psMetadataAddS32(addresultArgs, PS_LIST_TAIL, "-num_inputs", 0, "number of inputs", 0);
     psMetadataAddStr(addresultArgs, PS_LIST_TAIL, "-hostname", 0, "define hostname", 0);
     psMetadataAddF32(addresultArgs, PS_LIST_TAIL, "-good_frac", 0, "define fraction of good pixels", NAN);
-    psMetadataAddS16(addresultArgs, PS_LIST_TAIL, "-quality", 0, "set quality", 0)
+    psMetadataAddS16(addresultArgs, PS_LIST_TAIL, "-quality", 0, "set quality", 0);
     psMetadataAddS16(addresultArgs, PS_LIST_TAIL, "-fault", 0, "set fault code", 0);
 
@@ -102,6 +103,6 @@
     psMetadata *resultArgs= psMetadataAlloc();
     psMetadataAddS64(resultArgs, PS_LIST_TAIL, "-sky_id", 0, "search by staticsky ID", 0);
-    psMetadataAddStr(resultArgs, PS_LIST_TAIL, "-tess_id", 0, "search by tess ID", 0);
-    psMetadataAddStr(resultArgs, PS_LIST_TAIL, "-skycell_id", 0, "search by skycell ID", 0);
+    // psMetadataAddStr(resultArgs, PS_LIST_TAIL, "-tess_id", 0, "search by tess ID", 0);
+    // psMetadataAddStr(resultArgs, PS_LIST_TAIL, "-skycell_id", 0, "search by skycell ID", 0);
     psMetadataAddStr(resultArgs, PS_LIST_TAIL, "-label", 0, "search by label", NULL);
     psMetadataAddStr(resultArgs, PS_LIST_TAIL, "-data_group", 0, "search by data_group (LIKE comparison)", NULL);
@@ -109,4 +110,5 @@
     psMetadataAddU64(resultArgs, PS_LIST_TAIL, "-limit", 0, "limit result set to N items", 0);
     psMetadataAddBool(resultArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+    psMetadataAddBool(resultArgs, PS_LIST_TAIL, "-all", 0, "allow no search terms", false);
 
     // -revert
@@ -143,5 +145,5 @@
     PXOPT_ADD_MODE("-inputs",        "Get inputs",           STATICSKYTOOL_MODE_INPUTS,        inputsArgs);
     PXOPT_ADD_MODE("-todo",          "Get runs to do",       STATICSKYTOOL_MODE_TODO,          todoArgs);
-    PXOPT_ADD_MODE("-addresult",     "Add result of run",    STATICSKYTOOL_MODE_ADDRESULT,     addresultsArgs);
+    PXOPT_ADD_MODE("-addresult",     "Add result of run",    STATICSKYTOOL_MODE_ADDRESULT,     addresultArgs);
     PXOPT_ADD_MODE("-result",        "Get result of run",    STATICSKYTOOL_MODE_RESULT,        resultArgs);
     PXOPT_ADD_MODE("-revert",        "Revert failed run",    STATICSKYTOOL_MODE_REVERT,        revertArgs);
Index: branches/czw_branch/20100519/ippTools/src/warptool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/warptool.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/warptool.c	(revision 28164)
@@ -48,4 +48,6 @@
 static bool maskedMode(pxConfig *config);
 static bool unblockMode(pxConfig *config);
+static bool tosummaryMode(pxConfig *config);
+static bool addsummaryMode(pxConfig *config);
 static bool pendingcleanuprunMode(pxConfig *config);
 static bool pendingcleanupwarpMode(pxConfig *config);
@@ -101,4 +103,6 @@
         MODECASE(WARPTOOL_MODE_MASKED,             maskedMode);
         MODECASE(WARPTOOL_MODE_UNBLOCK,            unblockMode);
+	MODECASE(WARPTOOL_MODE_TOSUMMARY,          tosummaryMode);
+	MODECASE(WARPTOOL_MODE_ADDSUMMARY,         addsummaryMode);
         MODECASE(WARPTOOL_MODE_PENDINGCLEANUPRUN,  pendingcleanuprunMode);
         MODECASE(WARPTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupwarpMode);
@@ -408,7 +412,7 @@
     PXOPT_COPY_STR(config->args, where, "-reduction", "warpRun.reduction", "==");
     PXOPT_COPY_STR(config->args, where, "-state",     "warpRun.state",     "==");
-    PXOPT_COPY_STR(config->args, where, "-data_group","warpRun.data_group","==");
-    PXOPT_COPY_STR(config->args, where, "-dist_group","warpRun.dist_group","==");
-    pxAddLabelSearchArgs(config,  where, "-label",    "warpRun.label",     "==");
+    PXOPT_COPY_STR(config->args, where, "-data_group","warpRun.data_group","LIKE");
+    PXOPT_COPY_STR(config->args, where, "-dist_group","warpRun.dist_group","LIKE");
+    pxAddLabelSearchArgs(config,  where, "-label",    "warpRun.label",     "LIKE");
 
     PXOPT_COPY_TIME(config->args, where, "-registered_begin", "warpRun.registered",  ">=");
@@ -940,15 +944,12 @@
 
     // treat limit == 0 as "no limit"
-    psString limitString = psStringCopy("\n");
+    psString limitString = psStringCopy("\nORDER BY priority DESC, warp_id");
     if (limit) {
-        // We apply the limit to both sides of the UNION
-        // to avoid slow queries and to the query itself
-        // to satisfy the user's requested limit
+        // We apply the limit to both sides of the UNION to avoid slow queries
+        // and to the query itself to satisfy the user's requested limit
         psStringAppend(&limitString, "%s", psDBGenerateLimitSQL(limit));
         psStringAppend(&query, " %s", limitString);
     }
 
-#define TWO_WHERES
-#ifdef TWO_WHERES
     if (!p_psDBRunQueryF(config->dbh, query, whereStr, limitString, whereStr,  limitString)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
@@ -956,11 +957,4 @@
         return false;
     }
-#else
-    if (!p_psDBRunQueryF(config->dbh, query, whereStr)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(query);
-        return false;
-    }
-#endif
     psFree(limitString);
     psFree(whereStr);
@@ -1163,5 +1157,5 @@
 
 	psString software_ver = NULL;
-	psS32 maskfrac_npix = 0;
+	psS64 maskfrac_npix = 0;
 	psF32 maskfrac_static = 0;
 	psF32 maskfrac_dynamic = 0;
@@ -1181,25 +1175,29 @@
 	  return(false);
 	}
-	// Set warpRun.software_ver to the appropriate value
-	if (!pxSetRunSoftware(config, "warpRun", "warp_id", warp_id, software_ver)) {
-	  psError(PS_ERR_UNKNOWN, false, "failed to set warpRun.software_ver for warp_id: %" PRId64,
-		  warp_id);
-	  psFree(output);
-	  if (!psDBRollback(config->dbh)) {
-	    psError(PS_ERR_UNKNOWN, false, "database error");
+	// Set warpRun.software_ver to the appropriate value	if (
+	if (software_ver) {
+	  if (!pxSetRunSoftware(config, "warpRun", "warp_id", warp_id, software_ver)) {
+	    psError(PS_ERR_UNKNOWN, false, "failed to set warpRun.software_ver for warp_id: %" PRId64,
+		    warp_id);
+	    psFree(output);
+	    if (!psDBRollback(config->dbh)) {
+	      psError(PS_ERR_UNKNOWN, false, "database error");
+	    }
+	    return(false);
 	  }
-	  return(false);
 	}
 	// Set warpRun.maskfrac* to the appropriate values.
-	if (!pxSetRunMaskfrac(config, "warpRun", "warp_id", warp_id, maskfrac_npix, maskfrac_static,
-			      maskfrac_dynamic, maskfrac_magic, maskfrac_advisory)) {
-	  psError(PS_ERR_UNKNOWN, false, "failed to set warpRun.software_ver for warp_id: %" PRId64,
-		  warp_id);
-	  psFree(output);
-	  if (!psDBRollback(config->dbh)) {
-	    psError(PS_ERR_UNKNOWN, false, "database error");
+	if (maskfrac_npix) {
+	  if (!pxSetRunMaskfrac(config, "warpRun", "warp_id", warp_id, maskfrac_npix, maskfrac_static,
+				maskfrac_dynamic, maskfrac_magic, maskfrac_advisory)) {
+	    psError(PS_ERR_UNKNOWN, false, "failed to set warpRun.software_ver for warp_id: %" PRId64,
+		    warp_id);
+	    psFree(output);
+	    if (!psDBRollback(config->dbh)) {
+	      psError(PS_ERR_UNKNOWN, false, "database error");
+	    }
+	    return(false);
 	  }
-	  return(false);
-	}	
+	}
 
 	
@@ -1554,4 +1552,133 @@
 }
 
+static bool tosummaryMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-warp_id",    "warpSkyfile.warp_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-tess_id",    "warpSkyfile.tess_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-state",      "warpRun.state", "==");
+  PXOPT_COPY_S64(config->args, where, "-exp_id",     "rawExp.exp_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-exp_name",   "rawExp.exp_name", "==");
+  PXOPT_COPY_S64(config->args, where, "-fake_id",    "fakeRun.fake_id", "==");
+  PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "rawExp.dateobs",  ">=");
+  PXOPT_COPY_TIME(config->args, where, "-dateobs_end",   "rawExp.dateobs",  "<=");
+  PXOPT_COPY_STR(config->args, where, "-filter",    "rawExp.filter", "LIKE");
+  PXOPT_COPY_S64(config->args, where, "-magicked", "warpSkyfile.magicked", "==");
+  pxAddLabelSearchArgs (config, where, "-label",   "warpRun.label", "LIKE");
+  pxAddLabelSearchArgs (config, where, "-data_group",   "warpRun.data_group", "LIKE");
+
+  PXOPT_LOOKUP_BOOL(all, config->args, "-all", false);
+
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  
+  // find all rawImfiles matching the default query
+  psString query = pxDataGet("warptool_tosummary.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    return false;
+  }
+
+  // generate where strings for arguments that require extra processing
+  // beyond PXOPT_COPY*
+  psString where2 = NULL;
+  if (!pxmagicAddWhere(config, &where2, "warpSkyfile")) {
+    psError(psErrorCodeLast(), false, "pxMagicAddWhere failed");
+    return false;
+  }
+  
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " AND %s", whereClause);
+    psFree(whereClause);
+  } else if (!all && !where2) {
+    psError(PXTOOLS_ERR_CONFIG, true, "search parameters or -all are required");
+    return false;
+  }
+  
+  if (where2) {
+    psStringAppend(&query, " %s", where2);
+  }
+  psFree(where);
+
+  // 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) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+    }
+    
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("warptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+  
+  if (psArrayLength(output)) {
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "warpRun", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+  
+  psFree(output);
+  return(true);
+}
+static bool addsummaryMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(warp_id, config->args, "-warp_id", true, false);
+  PXOPT_LOOKUP_STR(tangent_plane, config->args, "-tangent_plane", true, false);
+  PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", true, false);
+
+  psString query = pxDataGet("warptool_addsummary.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    return(false);
+  }
+  if (!p_psDBRunQueryF(config->dbh, query, warp_id, tangent_plane, path_base)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return(false);
+  }
+  psS64 numUpdated = psDBAffectedRows(config->dbh);
+  
+  if (numUpdated != 1) {
+    psError(PS_ERR_UNKNOWN, false, "should have affected 1 row");
+    psFree(query);
+    return false;
+  }
+  
+  psFree(query);
+
+  // Print anything here?
+  
+  return(true);
+}
+
 static bool pendingcleanuprunMode(pxConfig *config)
 {
Index: branches/czw_branch/20100519/ippTools/src/warptool.h
===================================================================
--- branches/czw_branch/20100519/ippTools/src/warptool.h	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/warptool.h	(revision 28164)
@@ -44,4 +44,6 @@
     WARPTOOL_MODE_MASKED,
     WARPTOOL_MODE_UNBLOCK,
+    WARPTOOL_MODE_TOSUMMARY,
+    WARPTOOL_MODE_ADDSUMMARY,
     WARPTOOL_MODE_PENDINGCLEANUPRUN,
     WARPTOOL_MODE_PENDINGCLEANUPSKYFILE,
Index: branches/czw_branch/20100519/ippTools/src/warptoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/warptoolConfig.c	(revision 28044)
+++ branches/czw_branch/20100519/ippTools/src/warptoolConfig.c	(revision 28164)
@@ -136,7 +136,7 @@
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-reduction", 0,  "search by warpRun reduction class", NULL);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-state", 0,      "search by warpRun state", NULL);
-    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by warpRun label", NULL);
-    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-data_group", 0, "search by warpRun data_group", NULL);
-    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-dist_group", 0, "search by warpRun dist_group", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by warpRun label (LIKE comparison)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-data_group", 0, "search by warpRun data_group (LIKE comparison)", NULL);
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-dist_group", 0, "search by warpRun dist_group (LIKE comparison)", NULL);
     psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-registered_begin", 0, "search for runs by registration time (>=)", NULL);
     psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-registered_end", 0, "search for runs by registration time (<)", NULL);
@@ -321,4 +321,32 @@
     psMetadataAddStr(unblockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to unmask (required)", NULL);
 
+    // -tosummary
+    psMetadata *tosummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(tosummaryArgs, PS_LIST_TAIL, "-warp_id", 0,         "search by warp ID", 0);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL,  "-tess_id",  0,          "search by tessellation ID", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL, "-state",  0,            "search by state", NULL);
+    psMetadataAddS64(tosummaryArgs, PS_LIST_TAIL, "-exp_id", 0,            "search by exposure tag", 0);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL, "-exp_name", 0,          "search by exposure tag", 0);
+    psMetadataAddS64(tosummaryArgs, PS_LIST_TAIL, "-fake_id", 0,           "search by phase 3 version of exposure tag", 0);
+    psMetadataAddTime(tosummaryArgs, PS_LIST_TAIL, "-dateobs_begin", 0,    "search for exposures by time (>=)", NULL);
+    psMetadataAddTime(tosummaryArgs, PS_LIST_TAIL, "-dateobs_end", 0,      "search for exposures by time (<=)", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL,  "-filter", 0,           "search for exposures by filter", NULL);
+    psMetadataAddS64(tosummaryArgs, PS_LIST_TAIL,  "-magicked", 0,         "search by magic id", 0);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL,  "-label",  PS_META_DUPLICATE_OK, "search by warpRun label", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL,  "-data_group",  PS_META_DUPLICATE_OK, "search by warpRun data_group", NULL);
+    psMetadataAddStr(tosummaryArgs, PS_LIST_TAIL,  "-dist_group",  PS_META_DUPLICATE_OK, "search by warpRun dist_group", NULL);
+    psMetadataAddBool(updaterunArgs, PS_LIST_TAIL, "-destreaked", 0, "search for runs that have been destreaked", false);
+    psMetadataAddBool(updaterunArgs, PS_LIST_TAIL, "-not_destreaked", 0, "search for runs that have not been destreaked", false);
+    
+    psMetadataAddBool(tosummaryArgs, PS_LIST_TAIL, "-all",  0,             "search without arguments", false);
+    psMetadataAddU64(tosummaryArgs, PS_LIST_TAIL,  "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(tosummaryArgs, PS_LIST_TAIL, "-simple",  0,          "use the simple output format", false);
+
+    // -addsummary
+    psMetadata *addsummaryArgs = psMetadataAlloc();
+    psMetadataAddS64(addsummaryArgs, PS_LIST_TAIL, "-warp_id", 0,         "set warp ID", 0);
+    psMetadataAddStr(addsummaryArgs, PS_LIST_TAIL, "-tangent_plane", 0,   "set tangent plane", NULL);
+    psMetadataAddStr(addsummaryArgs, PS_LIST_TAIL, "-path_base", 0,       "set summary path base", NULL);
+    
     // -pendingcleanuprun
     psMetadata *pendingcleanuprunArgs = psMetadataAlloc();
@@ -430,4 +458,7 @@
     PXOPT_ADD_MODE("-updateskyfile", "update fault code for skyfile", WARPTOOL_MODE_UPDATESKYFILE, updateskyfileArgs);
     PXOPT_ADD_MODE("-setskyfiletoupdate", "set cleaned skyfile to be updated", WARPTOOL_MODE_SETSKYFILETOUPDATE, setskyfiletoupdateArgs);
+    PXOPT_ADD_MODE("-tosummary",            "show runs that can be summarized", WARPTOOL_MODE_TOSUMMARY, tosummaryArgs);
+    PXOPT_ADD_MODE("-addsummary",           "add entry to the summary table", WARPTOOL_MODE_ADDSUMMARY, addsummaryArgs);
+
     PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", WARPTOOL_MODE_EXPORTRUN, exportrunArgs);
     PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           WARPTOOL_MODE_IMPORTRUN, importrunArgs);
