Index: branches/eam_branches/ipp-20130207/ippTools/src/addtool.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/addtool.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/addtool.c	(revision 35236)
@@ -988,13 +988,14 @@
     if (strcmp (stage,"cam") == 0) {
       query = pxDataGet("addtool_find_processedexp_cam.sql");
-    }
-    if (strcmp (stage,"stack") == 0) {
+    } else if (strcmp (stage,"stack") == 0) {
       query = pxDataGet("addtool_find_processedexp_stack.sql");
-    }
-    if (strcmp (stage,"staticsky") == 0) {
+    } else if (strcmp (stage,"staticsky") == 0) {
       query = pxDataGet("addtool_find_processedexp_staticsky_multi.sql");
-    }
-    if (strcmp (stage,"skycal") == 0) {
+    } else if (strcmp (stage,"skycal") == 0) {
       query = pxDataGet("addtool_find_processedexp_skycal.sql");
+    } else {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "can't find sql file for stage %s", stage);
+        return false;
     }
 
Index: branches/eam_branches/ipp-20130207/ippTools/src/addtoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/addtoolConfig.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/addtoolConfig.c	(revision 35236)
@@ -125,5 +125,5 @@
     psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-add_id",   0,            "search by add_id", 0);
     psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-stage_id",   0,            "search by stage_id", 0);
-    psMetadataAddStr(processedexpArgs, PS_LIST_TAIL, "-stage",             0, "set the stage", NULL);
+    psMetadataAddStr(processedexpArgs, PS_LIST_TAIL, "-stage",             0, "set the stage", "cam");
     pxcamSetSearchArgs(processedexpArgs);
     psMetadataAddStr(processedexpArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by addRun label", NULL);
Index: branches/eam_branches/ipp-20130207/ippTools/src/bgtool.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/bgtool.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/bgtool.c	(revision 35236)
@@ -285,4 +285,5 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args,   where, "-chip_id",            "chipRun.chip_id",       "==");
+    PXOPT_COPY_S64(config->args,   where, "-cam_id",             "camRun.cam_id",         "==");
     PXOPT_COPY_S64(config->args,   where, "-exp_id",             "rawExp.exp_id",         "==");
     PXOPT_COPY_STR(config->args,   where, "-exp_name",           "rawExp.exp_name",       "==");
@@ -324,5 +325,6 @@
     PXOPT_COPY_F32(config->args,   where, "-sun_angle_min",      "rawExp.sun_angle",      ">=");
     PXOPT_COPY_F32(config->args,   where, "-sun_angle_max",      "rawExp.sun_angle",      "<");
-    pxAddLabelSearchArgs(config,   where, "-label",              "chipRun.label",         "==");
+    PXOPT_COPY_STR(config->args,   where, "-label",              "chipRun.label",         "==");
+    PXOPT_COPY_STR(config->args,   where, "-cam_label",          "camRun.label",          "==");
 
     if (!psListLength(where->list)) {
@@ -343,4 +345,10 @@
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+    PXOPT_LOOKUP_STR(cam_label, config->args, "-cam_label", false, false);
+    PXOPT_LOOKUP_S64(cam_id, config->args, "-cam_id", false, false);
+    if (!cam_id && !cam_label) {
+        psError(PXTOOLS_ERR_CONFIG, true, "either cam_id or cam_label is required");
+        return false;
+    }
 
     // Get chip runs to promote to chipBackgroundRun
@@ -364,24 +372,11 @@
     }
 
+    psString labelHook = psStringCopy("");
     if (!rerun) {
-        psStringAppend(&query, "\nAND chipBackgroundRun.chip_bg_id IS NULL");
         if (label) {
-            psStringAppend(&query,
-                           "\nAND (chipBackgroundRun.label = '%s'"
-                           " OR chipBackgroundRun.label IS NULL)",
-                           label);
-        }
-        if (data_group) {
-            psStringAppend(&query,
-                           "\nAND (chipBackgroundRun.data_group = '%s'"
-                           " OR chipBackgroundRun.data_group IS NULL)",
-                           data_group);
-        }
-        if (dist_group) {
-            psStringAppend(&query,
-                           "\nAND (chipBackgroundRun.dist_group = '%s'"
-                           " OR chipBackgroundRun.dist_group IS NULL)",
-                           dist_group);
-        }
+            // check for run with the newly specified label
+            psStringAppend(&labelHook, "\nAND (chipBackgroundRun.label = '%s')", label);
+        }
+        psStringAppend(&query, "\nAND chip_bg_id IS NULL");
     }
 
@@ -391,7 +386,8 @@
     }
 
-    if (!p_psDBRunQuery(config->dbh, query)) {
+    if (!p_psDBRunQueryF(config->dbh, query, labelHook)) {
         psError(psErrorCodeLast(), false, "database error");
         psFree(query);
+        psFree(labelHook);
         if (!psDBRollback(config->dbh)) {
             psError(psErrorCodeLast(), false, "database error");
@@ -400,4 +396,5 @@
     }
     psFree(query);
+    psFree(labelHook);
 
     psArray *output = p_psDBFetchResult(config->dbh); // Matching rows
@@ -420,5 +417,5 @@
     if (pretend) {
         // negative simple so the default is true
-        if (!ippdbPrintMetadatas(stdout, output, "chipRun", !simple)) {
+        if (!ippdbPrintMetadatas(stdout, output, "chipBackgroundRun", !simple)) {
             psError(psErrorCodeLast(), false, "failed to print array");
             psFree(output);
@@ -435,5 +432,5 @@
         psMetadata *md = output->data[i];
 
-        chipRunRow *row = chipRunObjectFromMetadata(md);
+        chipBackgroundRunRow *row = chipBackgroundRunObjectFromMetadata(md);
         if (!row) {
             psError(psErrorCodeLast(), false, "failed to convert metadata into fakeRun");
@@ -445,5 +442,5 @@
         }
 
-        if (!chipBackgroundRunInsert(config->dbh, 0, row->chip_id, "new",
+        if (!chipBackgroundRunInsert(config->dbh, 0, row->chip_id, row->cam_id, "new",
                                      workdir     ? workdir    : row->workdir,
                                      label       ? label      : row->label,
@@ -560,5 +557,5 @@
 
     if (psArrayLength(output)) {
-        if (!ippdbPrintMetadatas(stdout, output, "chipBackgroundRun", !simple)) {
+        if (!ippdbPrintMetadatas(stdout, output, "pendingchipBackgroundRun", !simple)) {
             psError(psErrorCodeLast(), false, "failed to print array");
             psFree(output);
@@ -621,5 +618,5 @@
         return true;
     }
-    if (!ippdbPrintMetadatas(stdout, output, "chipBackgroundImfile", !simple)) {
+    if (!ippdbPrintMetadatas(stdout, output, "pendingchipBackgroundImfile", !simple)) {
         psError(psErrorCodeLast(), false, "failed to print array");
         psFree(output);
@@ -1295,5 +1292,6 @@
     PXOPT_COPY_F32(config->args,   where, "-sun_angle_max",      "rawExp.sun_angle",      "<");
     pxAddLabelSearchArgs(config,   where, "-warp_label",         "warpRun.label",         "==");
-    pxAddLabelSearchArgs(config,   where, "-chip_label",         "chipBackgroundRun.label", "==");
+    pxAddLabelSearchArgs(config,   where, "-chip_bg_label",      "chipBackgroundRun.label", "==");
+    pxAddLabelSearchArgs(config,   where, "-chip_label",         "chipRun.label",         "==");
 
     if (!psListLength(where->list) && !psMetadataLookupBool(NULL, config->args, "-all")) {
@@ -1335,24 +1333,11 @@
     }
 
+    psString labelHook = psStringCopy("");
     if (!rerun) {
-        psStringAppend(&query, "\nAND warpBackgroundRun.warp_bg_id IS NULL");
         if (label) {
-            psStringAppend(&query,
-                           "\nAND (warpBackgroundRun.label = '%s'"
-                           " OR warpBackgroundRun.label IS NULL)",
-                           label);
-        }
-        if (data_group) {
-            psStringAppend(&query,
-                           "\nAND (warpBackgroundRun.data_group = '%s'"
-                           " OR warpBackgroundRun.data_group IS NULL)",
-                           data_group);
-        }
-        if (dist_group) {
-            psStringAppend(&query,
-                           "\nAND (warpBackgroundRun.dist_group = '%s'"
-                           " OR warpBackgroundRun.dist_group IS NULL)",
-                           dist_group);
-        }
+            // check for run with the newly specified label
+            psStringAppend(&labelHook, "\nAND (warpBackgroundRun.label = '%s')", label);
+        }
+        psStringAppend(&query, "\nAND warp_bg_id IS NULL");
     }
 
@@ -1362,6 +1347,7 @@
     }
 
-    if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(psErrorCodeLast(), false, "database error");
+    if (!p_psDBRunQueryF(config->dbh, query, labelHook)) {
+        psError(psErrorCodeLast(), false, "database error");
+        psFree(labelHook);
         psFree(query);
         if (!psDBRollback(config->dbh)) {
@@ -1370,4 +1356,5 @@
         return false;
     }
+    psFree(labelHook);
     psFree(query);
 
@@ -1391,5 +1378,5 @@
     if (pretend) {
         // negative simple so the default is true
-        if (!ippdbPrintMetadatas(stdout, output, "warpRun", !simple)) {
+        if (!ippdbPrintMetadatas(stdout, output, "warpBackgroundRun", !simple)) {
             psError(psErrorCodeLast(), false, "failed to print array");
             psFree(output);
@@ -1408,7 +1395,8 @@
         psS64 chip_bg_id = psMetadataLookupS64(NULL, md, "chip_bg_id");
 
-        warpRunRow *row = warpRunObjectFromMetadata(md);
+        
+        warpBackgroundRunRow *row = warpBackgroundRunObjectFromMetadata(md);
         if (!row) {
-            psError(psErrorCodeLast(), false, "failed to convert metadata into fakeRun");
+            psError(psErrorCodeLast(), false, "failed to convert metadata into warpRun");
             psFree(output);
             if (!psDBRollback(config->dbh)) {
@@ -1665,7 +1653,9 @@
 
     psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-warp_bg_id",    "warpBackgroundRun.warp_bg_id", "==");
-    PXOPT_COPY_STR(config->args, where, "-skycell_id", "warpBackgroundSkyfile.skycell_id", "==");
-    pxAddLabelSearchArgs(config, where, "-label",   "warpBackgroundRun.label", "LIKE");
+    PXOPT_COPY_S64(config->args, where, "-warp_bg_id",   "warpBackgroundRun.warp_bg_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-warp_id",      "warpBackgroundRun.warp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_bg_id",   "warpBackgroundRun.chip_bg_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-skycell_id",   "warpBackgroundSkyfile.skycell_id", "==");
+    pxAddLabelSearchArgs(config, where, "-label",        "warpBackgroundRun.label", "LIKE");
     pxAddLabelSearchArgs(config, where, "-data_group",   "warpBackgroundRun.data_group", "LIKE");
     pxAddLabelSearchArgs(config, where, "-dist_group",   "warpBackgroundRun.data_group", "LIKE");
Index: branches/eam_branches/ipp-20130207/ippTools/src/bgtoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/bgtoolConfig.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/bgtoolConfig.c	(revision 35236)
@@ -50,4 +50,5 @@
     psMetadata *definechipArgs = psMetadataAlloc();
     psMetadataAddS64(definechipArgs, PS_LIST_TAIL, "-chip_id", 0, "search by chip_id", 0);
+    psMetadataAddS64(definechipArgs, PS_LIST_TAIL, "-cam_id", 0, "choose cam_id", 0);
     psMetadataAddS64(definechipArgs, PS_LIST_TAIL, "-exp_id", 0, "search by exp_id", 0);
     psMetadataAddStr(definechipArgs, PS_LIST_TAIL, "-exp_name", 0, "search by exp_name", NULL);
@@ -89,5 +90,6 @@
     psMetadataAddF32(definechipArgs, PS_LIST_TAIL, "-sun_angle_min", 0, "search by min solar angle", NAN);
     psMetadataAddF32(definechipArgs, PS_LIST_TAIL, "-sun_angle_max", 0, "search by max solar angle", NAN);
-    psMetadataAddStr(definechipArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search on chipRun label", NULL);
+    psMetadataAddStr(definechipArgs, PS_LIST_TAIL, "-label", 0, "search on chipRun label", NULL);
+    psMetadataAddStr(definechipArgs, PS_LIST_TAIL, "-cam_label", 0, "search on camRun label", NULL);
     psMetadataAddBool(definechipArgs, PS_LIST_TAIL, "-destreaked", 0, "search for runs that have been destreaked", false);
     psMetadataAddBool(definechipArgs, PS_LIST_TAIL, "-rerun", 0, "re-run data?", false);
@@ -279,5 +281,6 @@
     psMetadataAddF32(definewarpArgs, PS_LIST_TAIL, "-sun_angle_max", 0, "search by max solar angle", NAN);
     psMetadataAddStr(definewarpArgs, PS_LIST_TAIL, "-warp_label", PS_META_DUPLICATE_OK, "search on warpRun label", NULL);
-    psMetadataAddStr(definewarpArgs, PS_LIST_TAIL, "-chip_label", PS_META_DUPLICATE_OK, "search on chipBackgroundRun label", NULL);
+    psMetadataAddStr(definewarpArgs, PS_LIST_TAIL, "-chip_label", PS_META_DUPLICATE_OK, "search on chipRun label", NULL);
+    psMetadataAddStr(definewarpArgs, PS_LIST_TAIL, "-chip_bg_label", PS_META_DUPLICATE_OK, "search on chipBackgroundRun label", NULL);
     psMetadataAddBool(definewarpArgs, PS_LIST_TAIL, "-destreaked", 0, "search for runs that have been destreaked", false);
     psMetadataAddBool(definewarpArgs, PS_LIST_TAIL, "-rerun", 0, "rerun data?", false);
@@ -352,4 +355,6 @@
     psMetadata *warpArgs = psMetadataAlloc();
     psMetadataAddS64(warpArgs, PS_LIST_TAIL, "-warp_bg_id", 0, "search by warp_bg_id", 0);
+    psMetadataAddS64(warpArgs, PS_LIST_TAIL, "-warp_id", 0, "search by warp_id", 0);
+    psMetadataAddS64(warpArgs, PS_LIST_TAIL, "-chip_bg_id", 0, "search by chip_bg_id", 0);
     psMetadataAddStr(warpArgs, PS_LIST_TAIL, "-skycell_id", 0, "search by skycell_id", NULL);
     psMetadataAddS16(warpArgs, PS_LIST_TAIL, "-fault",  0, "search by fault code", 0);
Index: branches/eam_branches/ipp-20130207/ippTools/src/camtool.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/camtool.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/camtool.c	(revision 35236)
@@ -500,5 +500,6 @@
     PXOPT_LOOKUP_S16(fault, config->args, "-fault", false, false);
     PXOPT_LOOKUP_S16(quality, config->args, "-quality", false, false);
-
+    PXOPT_LOOKUP_S16(background_model, config->args, "-background_model", false, false);
+    
     PXOPT_LOOKUP_STR(ver_pslib, config->args, "-ver_pslib", false, false);
     PXOPT_LOOKUP_STR(ver_psmodules, config->args, "-ver_psmodules", false, false);
@@ -520,5 +521,5 @@
     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);
-
+    
     // we store actual detection efficiency by adding in zpt_obs
     PXOPT_LOOKUP_F32(deteff_inst, config->args, "-deteff_inst", false, false);
@@ -542,6 +543,4 @@
     }
 
-/*     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)) {
@@ -692,5 +691,6 @@
         deteff_lq,
         deteff_uq,
-        quality
+        quality,
+	background_model
         );
 
@@ -817,5 +817,6 @@
     pxAddLabelSearchArgs (config, where, "-data_group", "camRun.data_group",     "LIKE");
     PXOPT_COPY_STR(config->args, where, "-reduction", "camRun.reduction", "==");
-
+    PXOPT_COPY_S16(config->args, where, "-background_model", "camProcessedExp.background_model", "==");
+    
     psString where2 = NULL;
     if (!pxspaceAddWhere(config, &where2, "rawExp")) {
@@ -987,18 +988,32 @@
     PXOPT_LOOKUP_S16(fault, config->args, "-fault", true, false);
     PXOPT_LOOKUP_S16(quality, config->args, "-set_quality", false, false);
-
-    psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-cam_id",   "cam_id",   "==");
-    PXOPT_COPY_S64(config->args, where, "-chip_id",  "chip_id",  "==");
-    PXOPT_COPY_STR(config->args, where, "-class",    "class",    "==");
-    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
-
-    if (!pxSetFaultCode(config->dbh, "camProcessedExp", where, fault, quality)) {
+    PXOPT_LOOKUP_S16(background_model, config->args, "-set_background_model", false, false);
+    if (background_model) {
+      // CZW Copied from warptool.c
+      psMetadata *where = psMetadataAlloc();
+      psMetadata *values = psMetadataAlloc();
+      PXOPT_COPY_S64(config->args, where, "-cam_id", "cam_id", "==");
+      PXOPT_COPY_S16(config->args, values, "-set_background_model", "background_model", "==");
+      long rows = psDBUpdateRows(config->dbh, "camProcessedExp", where, values);
+      psFree(values);
+      psFree(where);
+      if (!rows) {
+	psError(PS_ERR_UNKNOWN, true, "no rows changed");
+      }
+    }
+    else {
+      psMetadata *where = psMetadataAlloc();
+      PXOPT_COPY_S64(config->args, where, "-cam_id",   "cam_id",   "==");
+      PXOPT_COPY_S64(config->args, where, "-chip_id",  "chip_id",  "==");
+      PXOPT_COPY_STR(config->args, where, "-class",    "class",    "==");
+      PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
+      
+      if (!pxSetFaultCode(config->dbh, "camProcessedExp", where, fault, quality)) {
         psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
         psFree (where);
         return false;
-    }
-    psFree (where);
-
+      }
+      psFree (where);
+    }
     return true;
 }
Index: branches/eam_branches/ipp-20130207/ippTools/src/camtoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/camtoolConfig.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/camtoolConfig.c	(revision 35236)
@@ -204,5 +204,5 @@
     psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-deteff_inst_lq", 0, "define deteff_lq", NAN);
     psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-deteff_inst_uq", 0, "define deteff_uq", NAN);
-
+    psMetadataAddS16(addprocessedexpArgs, PS_LIST_TAIL, "-background_model", 0, "set background_model value", 0);
 
     // -processedexp
@@ -222,4 +222,5 @@
     psMetadataAddBool(processedexpArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
     psMetadataAddBool(processedexpArgs, PS_LIST_TAIL, "-faulted", 0,            "only return imfiles with a fault status set", false);
+    psMetadataAddS16(processedexpArgs, PS_LIST_TAIL, "-background_model", 0, "search by background_model value", 0);
 
     // -revertprocessedexp
@@ -246,4 +247,5 @@
     psMetadataAddS16(updateprocessedexpArgs, PS_LIST_TAIL, "-fault",  0,            "set fault code (required)", INT16_MAX);
     psMetadataAddS16(updateprocessedexpArgs, PS_LIST_TAIL, "-set_quality",  0,            "set quality", 0);
+    psMetadataAddS16(updateprocessedexpArgs, PS_LIST_TAIL, "-set_background_model", 0, "set background_model value", 0);
 
     // -block
Index: branches/eam_branches/ipp-20130207/ippTools/src/difftool.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/difftool.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/difftool.c	(revision 35236)
@@ -1226,5 +1226,282 @@
 }
 
-
+static bool definewarpstackMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  psMetadata *where = psMetadataAlloc();
+
+  PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+  PXOPT_COPY_STR(config->args, where, "-comment", "comment", "LIKE");
+  PXOPT_COPY_S64(config->args, where, "-warp_id", "warpRun.warp_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-warp_label", "warpRun.label", "==");
+  PXOPT_COPY_STR(config->args, where, "-tess_id", "warpRun.tess_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-data_group", "warpRun.data_group", "==");
+  PXOPT_COPY_STR(config->args, where, "-skycell_id", "warpSkyfile.skycell_id", "==");
+  PXOPT_COPY_F32(config->args, where,  "-good_frac", "warpSkyfile.good_frac", ">=");
+  PXOPT_COPY_STR(config->args, where, "-stack_label", "stackRun.label", "==");
+  PXOPT_COPY_STR(config->args, where, "-stack_data_group", "stackRun.data_group", "==");
+
+  PXOPT_LOOKUP_BOOL(bothways, config->args, "-bothways", false);
+  
+  PXOPT_LOOKUP_STR(workdir, config->args, "-set_workdir", true, false); // required option
+  PXOPT_LOOKUP_STR(reduction, config->args, "-set_reduction", false, false); // option
+  PXOPT_LOOKUP_STR(label, config->args, "-set_label", true, false); // option
+  PXOPT_LOOKUP_STR(data_group, config->args, "-set_data_group", false, false);
+  PXOPT_LOOKUP_STR(dist_group, config->args, "-set_dist_group", false, false);
+  PXOPT_LOOKUP_STR(note, config->args, "-set_note", false, false);
+  PXOPT_LOOKUP_TIME(registered, config->args, "-set_registered", false, false);
+  
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_BOOL(newTemplates, config->args, "-new-templates", false);
+  PXOPT_LOOKUP_BOOL(reRun, config->args, "-rerun", false);
+  PXOPT_LOOKUP_BOOL(available, config->args, "-available", false);
+  PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+
+
+  // Get query file
+  psString query = pxDataGet("difftool_definewarpstack.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    return false;
+  }
+
+  psString whereClause = psDBGenerateWhereConditionSQL(where,NULL);
+  
+  // Don't queue things that already have diffs.
+  if (! (reRun || newTemplates) ) {
+    psStringAppend(&whereClause, "\nAND diff_id IS NULL\n");
+  }
+  // Append diff qualifiers, if we have them
+  if (label) {
+    psStringAppend(&whereClause, "\nAND ((diffRun.label = '%s') OR (diffRun.label IS NULL))",label);
+  }
+  if (data_group) {
+    psStringAppend(&whereClause, "\nAND ((diffRun.data_group = '%s') OR (diffRun.data_group IS NULL))",data_group);
+  }
+  if (reduction) {
+    psStringAppend(&whereClause, "\nAND ((diffRun.reduction = '%s') OR (diffRun.reduction IS NULL))",reduction);
+  }
+
+  psString whereClauseString = psStringCopy("");
+  psStringAppend(&whereClauseString, " \n AND %s ", whereClause);
+  //  fprintf(stderr,query,whereClauseString);
+
+  // This is just a simple query, so we don't need to do a transaction
+  if (!p_psDBRunQueryF(config->dbh, query, whereClauseString)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    psFree(whereClause);
+    return(false);
+  }
+  psFree(query);
+  psFree(whereClause);
+  psFree(whereClauseString);
+  
+  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");
+      break;
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+      break;
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+      break;
+    }
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("difftool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+  if (pretend) {
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "diffRun", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+    psFree(output);
+    return true;
+  }
+
+  psArray *list = psArrayAllocEmpty(16); // List of runs, to print
+  long numGood = 0;
+  psS64 last_exp_id = 0;
+  psS64 diff_id = 0;
+  for (long i = 0; i < output->n; i++) {
+    psMetadata *row = output->data[i];
+    bool mdok;
+
+    psS64 exp_id = psMetadataLookupS64(&mdok, row, "exp_id");
+    if (!mdok) {
+	psError(PXTOOLS_ERR_PROG, false, "exp_id not found");
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+	return false;
+    }
+    if (exp_id != last_exp_id) {
+      if (diff_id != 0) { // We've added a run already, and are now switching to a new one.
+	// Set state to new
+	if (!setdiffRunState(config, diff_id, "new", false)) {
+	  psError(PS_ERR_UNKNOWN, false, "failed to change diffRun.state for diff_id: %" PRId64, diff_id);
+	  if (!psDBRollback(config->dbh)) {
+	    psError(PS_ERR_UNKNOWN, false, "database error");
+	  }
+	  return false;
+	}
+	// Commit results
+	if (!psDBCommit(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	  psFree(list);
+	  return false;
+	}
+      }
+      
+      // Begin transaction
+      if (!psDBTransaction(config->dbh)) {
+	psError(PS_ERR_UNKNOWN, false, "database error");
+	return false;
+      }
+      // Add a new diffRun row
+      psString tess_id = psMetadataLookupStr(&mdok, row, "tess_id");
+      if (!mdok) {
+	psError(PXTOOLS_ERR_PROG, false, "tess_id not found");
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+	return false;
+      }
+      diffRunRow *run = diffRunRowAlloc(
+					0,        // ID
+					"reg",    // state
+					workdir,
+					label,
+					data_group ? data_group : label,
+					dist_group,
+					reduction,
+					NULL,     // dvodb
+					registered,
+					tess_id,
+					bothways, // bothways (default is false)
+					true,     // exposure
+					0,        // magicked
+					NULL,     // software_version
+					0,        // mask stat npix
+					NAN,      // static
+					NAN,      // dynamic
+					NAN,      // magic
+					NAN,      // advisory
+					IPP_DIFF_MODE_WARP_STACK,
+					note
+					);
+      if (!diffRunInsertObject(config->dbh, run)) {
+	psError(PS_ERR_UNKNOWN, false, "database error");
+	psFree(run);
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+      }
+      diff_id = psDBLastInsertID(config->dbh);
+      run->diff_id = diff_id;
+
+      psArrayAdd(list, list->n, run);
+      numGood++;
+      
+      last_exp_id = exp_id;					
+    } // End Adding diffRun
+    
+    if (exp_id == last_exp_id) {
+      psString skycell_id = psMetadataLookupStr(&mdok, row, "skycell_id");
+      if (!mdok) {
+	psError(PXTOOLS_ERR_PROG, false, "skycell_id not found");
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+	return false;
+      }
+      psString tess_id = psMetadataLookupStr(&mdok, row, "tess_id");
+      if (!mdok) {
+	psError(PXTOOLS_ERR_PROG, false, "tess_id not found");
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+	return false;
+      }
+      psS64 warp_id = psMetadataLookupS64(&mdok, row, "warp_id");
+      if (!mdok) {
+	psError(PXTOOLS_ERR_PROG, false, "warp_id not found");
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+	return false;
+      }
+      psS64 stack_id = psMetadataLookupS64(&mdok, row, "stack_id");
+      if (!mdok) {
+	psError(PXTOOLS_ERR_PROG, false, "stack_id not found");
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+	return false;
+      }
+
+      // Add a new skyfile row
+      diffInputSkyfileRow *skyfile = diffInputSkyfileRowAlloc(
+							      diff_id,   // ID
+							      skycell_id,
+							      warp_id, // warp1_id 
+							      PS_MAX_S64, // stack1 -> NULL
+							      PS_MAX_S64, // warp2_id -> NULL
+							      stack_id, // stack2
+							      tess_id,
+							      0 // diff_skyfile_id
+							      );
+      //      fprintf(stderr,"%"PRId64 " %"PRId64 " %"PRId64 " %s %s\n",diff_id,warp_id,stack_id,skycell_id, tess_id);
+      if (!diffInputSkyfileInsertObject(config->dbh, skyfile)) {
+	psError(PS_ERR_UNKNOWN, false, "database error");
+	psFree(list);
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+	return false;
+      }
+    } // End Adding skyfile
+  } // End parsing result set
+  
+  // Finish the last run's update and close the connection
+  if (diff_id != 0) {
+    if (!setdiffRunState(config, diff_id, "new", false)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to change diffRun.state for diff_id: %" PRId64, diff_id);
+      if (!psDBRollback(config->dbh)) {
+	psError(PS_ERR_UNKNOWN, false, "database error");
+      }
+      return false;
+    }
+    // Commit results
+    if (!psDBCommit(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(list);
+      return false;
+    }
+  }
+  
+  if (numGood && !diffRunPrintObjects(stdout, list, !simple)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to print object");
+    psFree(list);
+    return(false);
+  }
+  psFree(list);
+  // Free things
+  return true;
+}  
+
+#if (0)
 static bool definewarpstackMode(pxConfig *config)
 {
@@ -1614,4 +1891,5 @@
     return true;
 }
+#endif
 
 static bool definewarpwarpMode(pxConfig *config)
Index: branches/eam_branches/ipp-20130207/ippTools/src/disttool.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/disttool.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/disttool.c	(revision 35236)
@@ -143,5 +143,5 @@
     // optional
     PXOPT_LOOKUP_BOOL(use_alternate, config->args, "-use_alternate", false);
-    PXOPT_LOOKUP_BOOL(no_magic, config->args, "-no_magic", false);
+    PXOPT_LOOKUP_BOOL(magic, config->args, "-magic", false);
     PXOPT_LOOKUP_STR(set_label, config->args, "-set_label", false, false);
     PXOPT_LOOKUP_STR(set_data_group, config->args, "-set_data_group", false, false);
@@ -175,5 +175,5 @@
             return false;
         }
-        if (no_magic) {
+        if (!magic) {
             psError(PXTOOLS_ERR_SYS, true, "no_magic forbidden with alternate inputs");
             return false;
@@ -187,5 +187,5 @@
     // an interest)
     // and exp_id to be supplied. We could add -exp_type and dateobs cuts to make it easier
-    if (!strcmp(stage, "raw") && no_magic && !(exp_id && dist_group && exp_type)) {
+    if (!strcmp(stage, "raw") && !magic && !(exp_id && dist_group && exp_type)) {
         psError(PXTOOLS_ERR_SYS, true, "exp_id, exp_type, and dist_group are required for raw stage if no_magic");
         return false;
@@ -204,5 +204,5 @@
             runJoinStr = "camRun.exp_id";
         }
-        if (!no_magic) {
+        if (magic) {
             query = pxDataGet("disttool_definebyquery_raw.sql");
         } else {
@@ -215,5 +215,5 @@
         }
 
-        if (!no_magic) {
+        if (magic) {
             if (label) {
                 psStringAppend(&query, " AND (magicDSRun.label = '%s')", label);
@@ -289,5 +289,5 @@
         }
         // fake stage doesn't require magic
-        no_magic = true;
+        magic = false;
     } else if (!strcmp(stage, "warp")) {
         magicRunType = "warpRun";
@@ -357,5 +357,5 @@
         }
         // stack stage doesn't require magic
-        no_magic = true;
+        magic = false;
     } else if (!strcmp(stage, "sky")) {
         magicRunType = "staticskyRun";
@@ -378,5 +378,5 @@
         }
         // (static)sky stage doesn't require magic
-        no_magic = true;
+        magic = false;
     } else if (!strcmp(stage, "SSdiff")) {
       magicRunType = "diffRun";
@@ -396,5 +396,5 @@
       }
 
-      no_magic = true;
+      magic = false;
     } else {
         psError(PS_ERR_UNKNOWN, true, "unknown value for stage: %s", stage);
@@ -408,5 +408,5 @@
 
     if (!strcmp(stage, "raw")) {
-        if (!no_magic) {
+        if (magic) {
             psStringAppend(&query, " AND (magicDSRun.re_place = %d)", !use_alternate);
             psStringAppend(&query, " AND (camRun.state = 'full')");
@@ -426,5 +426,5 @@
     psString joinHook = NULL;
 
-    if (!no_magic) {
+    if (magic) {
         psStringAppend(&query, " AND (%s.magicked > 0)", magicRunType);
     }
@@ -517,5 +517,5 @@
                 NULL,     // outdir
                 clean,
-                no_magic,
+                !magic,
                 use_alternate,
                 "new",
Index: branches/eam_branches/ipp-20130207/ippTools/src/disttoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/disttoolConfig.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/disttoolConfig.c	(revision 35236)
@@ -48,5 +48,6 @@
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-workdir",   0, "define workdir (required)", NULL);
 
-    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-no_magic", 0, "magic is not needed", false);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-no_magic", 0, "magic is not needed (ignored)", false);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-magic", 0, "magic is needed", false);
     psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-use_alternate", 0, "use alternate inputs", false);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_label",    0, "define label for run", NULL);
Index: branches/eam_branches/ipp-20130207/ippTools/src/releasetool.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/releasetool.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/releasetool.c	(revision 35236)
@@ -41,6 +41,14 @@
 static bool listreleaseMode(pxConfig *config);
 static bool definerelexpMode(pxConfig *config);
+static bool tocalibexpMode(pxConfig *config);
 static bool updaterelexpMode(pxConfig *config);
 static bool listrelexpMode(pxConfig *config);
+static bool definerelstackMode(pxConfig *config);
+static bool updaterelstackMode(pxConfig *config);
+static bool listrelstackMode(pxConfig *config);
+static bool definerelgroupMode(pxConfig *config);
+static bool pendingrelgroupMode(pxConfig *config);
+static bool updaterelgroupMode(pxConfig *config);
+static bool listrelgroupMode(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -66,4 +74,5 @@
         MODECASE(RELEASETOOL_MODE_DEFINERELEASE,    definereleaseMode);
         MODECASE(RELEASETOOL_MODE_UPDATERELEASE,    updatereleaseMode);
+        MODECASE(RELEASETOOL_MODE_TOCALIBEXP,       tocalibexpMode);
         MODECASE(RELEASETOOL_MODE_LISTRELEASE,      listreleaseMode);
 
@@ -71,4 +80,13 @@
         MODECASE(RELEASETOOL_MODE_UPDATERELEXP,     updaterelexpMode);
         MODECASE(RELEASETOOL_MODE_LISTRELEXP,       listrelexpMode);
+
+        MODECASE(RELEASETOOL_MODE_DEFINERELSTACK,   definerelstackMode);
+        MODECASE(RELEASETOOL_MODE_UPDATERELSTACK,   updaterelstackMode);
+        MODECASE(RELEASETOOL_MODE_LISTRELSTACK,     listrelstackMode);
+
+        MODECASE(RELEASETOOL_MODE_DEFINERELGROUP,   definerelgroupMode);
+        MODECASE(RELEASETOOL_MODE_UPDATERELGROUP,   updaterelgroupMode);
+        MODECASE(RELEASETOOL_MODE_PENDINGRELGROUP,  pendingrelgroupMode);
+        MODECASE(RELEASETOOL_MODE_LISTRELGROUP,     listrelgroupMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -163,5 +181,5 @@
 
     PXOPT_LOOKUP_S32(surveyID,    config->args, "-set_surveyID", true, false);
-    PXOPT_LOOKUP_STR(releaseName, config->args, "-set_releaseName", true, false);
+    PXOPT_LOOKUP_STR(release_name, config->args, "-set_release_name", true, false);
     PXOPT_LOOKUP_STR(release_state, config->args, "-set_release_state",  true, false);
     PXOPT_LOOKUP_S32(dataRelease, config->args, "-set_dataRelease", false, false);
@@ -171,5 +189,5 @@
         0,      // rel_id (auto_increment)
         surveyID,
-        releaseName,
+        release_name,
         release_state,
         dataRelease,
@@ -187,20 +205,39 @@
     PS_ASSERT_PTR_NON_NULL(config, false);
 
-    PXOPT_LOOKUP_STR(releaseName, config->args, "-releaseName", false, false);
+    PXOPT_LOOKUP_STR(release_name, config->args, "-release_name", false, false);
     PXOPT_LOOKUP_S32(rel_id, config->args,      "-rel_id", false, false);
 
-    if (!releaseName && !rel_id) {
-        psError(PXTOOLS_ERR_CONFIG, true, "either -releaseName or -rel_id is required\n");
-        return false;
-    }
-    PXOPT_LOOKUP_STR(release_state,       config->args, "-set_release_state",  true, false);
+    if (!release_name && !rel_id) {
+        psError(PXTOOLS_ERR_CONFIG, true, "either -release_name or -rel_id is required\n");
+        return false;
+    }
+    PXOPT_LOOKUP_STR(release_state,    config->args, "-set_release_state",  false, false);
+    PXOPT_LOOKUP_S32(priority,         config->args, "-set_priority",  false, false);
+    PXOPT_LOOKUP_S32(dataRelease,      config->args, "-set_dataRelease",  false, false);
+    if (!release_state && priority == 0 && dataRelease == -1) {
+        psError(PXTOOLS_ERR_CONFIG, true, "at least one of -set_release_state -set_priority and -set_dataRelease is required\n");
+        return false;
+    }
 
     psMetadata *where = psMetadataAlloc();
 
     PXOPT_COPY_S32(config->args, where, "-rel_id",  "rel_id", "==");
-    PXOPT_COPY_STR(config->args, where, "-releaseName", "releaseName", "==");
-
-    psString query = NULL;
-    psStringAppend(&query, "UPDATE ippRelease SET release_state = '%s'", release_state);
+    PXOPT_COPY_STR(config->args, where, "-release_name", "release_name", "==");
+
+    psString sep = "";
+    psString comma = ", ";
+    psString query = psStringCopy("UPDATE ippRelease SET");
+    if (release_state) {
+        psStringAppend(&query, "%s release_state = '%s'", sep, release_state);
+        sep = comma;
+    }
+    if (priority != 0) {
+        psStringAppend(&query, "%s priority = %d", sep, priority);
+        sep = comma;
+    }
+    if (dataRelease != -1) {
+        psStringAppend(&query, "%s dataRelease = %d", sep, dataRelease);
+        sep = comma;
+    }
 
     psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
@@ -232,5 +269,5 @@
 
     PXOPT_COPY_STR(config->args, where, "-surveyName",  "surveyName", "LIKE");
-    PXOPT_COPY_STR(config->args, where, "-releaseName", "releaseName", "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-release_name", "release_name", "LIKE");
     PXOPT_COPY_STR(config->args, where, "-release_state", "release_state", "==");
     PXOPT_COPY_S32(config->args, where, "-rel_id",  "rel_id", "==");
@@ -313,13 +350,13 @@
     // insure that at least one of these is supplied to select the release
     PXOPT_LOOKUP_S64(rel_id, config->args,      "-rel_id", false, false);
-    PXOPT_LOOKUP_STR(releaseName, config->args, "-releaseName", false, false);
-    if (!rel_id && !releaseName) {
-        psError(PXTOOLS_ERR_CONFIG, true, "either -rel_id or -releaseName is required");
-        return false;
-    }
-
-    // limit query to the target release. (Note: this will select nothing of releaseName and rel_id don't match)
+    PXOPT_LOOKUP_STR(release_name, config->args, "-release_name", false, false);
+    if (!rel_id && !release_name) {
+        psError(PXTOOLS_ERR_CONFIG, true, "either -rel_id or -release_name is required");
+        return false;
+    }
+
+    // limit query to the target release. (Note: this will select nothing if release_name and rel_id don't match)
     // note: we add these after above to insure that search args are supplied
-    PXOPT_COPY_STR(config->args, where, "-releaseName", "ippRelease.releaseName", "==");
+    PXOPT_COPY_STR(config->args, where, "-release_name", "ippRelease.release_name", "==");
     PXOPT_COPY_S32(config->args, where, "-rel_id", "ippRelease.rel_id", "==");
 
@@ -327,5 +364,8 @@
     PXOPT_LOOKUP_STR(state, config->args,     "-set_state", true, false);
     PXOPT_LOOKUP_U32(flags, config->args,     "-set_flags", false, false);
+    PXOPT_LOOKUP_F32(user_zpt_obs, config->args,   "-set_zpt_obs", false, false);
+    PXOPT_LOOKUP_F32(user_zpt_stdev, config->args, "-set_zpt_stdev", false, false);
     PXOPT_LOOKUP_STR(path_base, config->args, "-set_path_base", false, false);
+    PXOPT_LOOKUP_S16(fault, config->args,     "-set_fault", false, false);
 
     PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
@@ -391,6 +431,17 @@
         psS64 chip_id = psMetadataLookupS64(&status, md, "chip_id");
         psS64 cam_id = psMetadataLookupS64(&status, md, "cam_id");
-        psF32 zpt_obs = psMetadataLookupF32(&status, md, "zpt_obs");
-        psF32 zpt_stdev = psMetadataLookupF32(&status, md, "zpt_stdev");
+
+        // if zpt_obs or zpt_stdev were not supplied use the results from the camRun
+        psF32 zpt_obs, zpt_stdev;
+        if (!isfinite(user_zpt_obs)) {
+            zpt_obs = psMetadataLookupF32(&status, md, "zpt_obs");
+        } else {
+            zpt_obs = user_zpt_obs;
+        }
+        if (!isfinite(user_zpt_stdev)) {
+            zpt_stdev = psMetadataLookupF32(&status, md, "zpt_stdev");
+        } else {
+            zpt_stdev = user_zpt_stdev;
+        }
 
         if (!relExpInsert(config->dbh,
@@ -400,4 +451,5 @@
             chip_id,
             cam_id,
+            0,          // group_id
             state,
             flags,
@@ -405,4 +457,5 @@
             zpt_stdev,
             path_base,
+            fault,
             now,       // registered
             now        // time_stamp
@@ -430,9 +483,99 @@
 static bool updaterelexpMode(pxConfig *config)
 {
-    psError(PS_ERR_UNKNOWN, true, "not yet implemented");
-    return false;
-}
-
-static bool listrelexpMode(pxConfig *config)
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(release_name, config->args, "-release_name", false, false);
+    PXOPT_LOOKUP_S32(rel_id, config->args,      "-rel_id", false, false);
+    PXOPT_LOOKUP_S32(relexp_id, config->args,   "-relexp_id", false, false);
+
+    if (!relexp_id && !release_name && !rel_id) {
+        psError(PXTOOLS_ERR_CONFIG, true, "at least one of -relexp_id, -release_name, and -rel_id is required\n");
+        return false;
+    }
+
+    PXOPT_LOOKUP_STR(state,    config->args, "-set_state",  false, false);
+    PXOPT_LOOKUP_U32(flags,    config->args, "-set_flags",  false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-set_path_base", false, false);
+    PXOPT_LOOKUP_F32(zpt_obs,  config->args, "-set_zpt_obs",  false, false);
+    PXOPT_LOOKUP_F32(zpt_stdev,config->args, "-set_zpt_stdev",  false, false);
+    PXOPT_LOOKUP_S16(fault,    config->args, "-set_fault",  false, false);
+    PXOPT_LOOKUP_BOOL(clearfault, config->args, "-clearfault",  false);
+    if (!state && !flags && !path_base && !isfinite(zpt_obs) && !isfinite(zpt_stdev) && !fault && !clearfault) {
+        psError(PXTOOLS_ERR_CONFIG, true, "must set at least one column\n");
+        return false;
+    }
+
+    if (fault && clearfault) {
+        psError(PXTOOLS_ERR_CONFIG, true, "cannot set and clear fault at same time\n");
+        return false;
+    }
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "relExp.exp_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-relexp_id", "relExp.relexp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "rawExp.exp_name", "==");
+    // make sure that we have enough parameters to identify the relExp to change
+    if (!psListLength(where->list)){
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required\n");
+        psFree(where);
+        return false;
+    }
+
+    PXOPT_COPY_S32(config->args, where, "-rel_id",  "rel_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-release_name", "release_name", "==");
+
+    psString sep = "";
+    psString comma = ", ";
+    psString query = psStringCopy("UPDATE relExp JOIN ippRelease USING(rel_id) JOIN rawExp USING(exp_id) SET");
+    if (state) {
+        psStringAppend(&query, "%s relExp.state = '%s'", sep, state);
+        sep = comma;
+    }
+    if (path_base) {
+        psStringAppend(&query, "%s relExp.path_base = '%s'", sep, path_base);
+        sep = comma;
+    }
+    if (flags) {
+        psStringAppend(&query, "%s relExp.flags = %d", sep, flags);
+        sep = comma;
+    }
+    if (isfinite(zpt_obs)) {
+        psStringAppend(&query, "%s relExp.zpt_obs = %f", sep, zpt_obs);
+        sep = comma;
+    }
+    if (isfinite(zpt_stdev)) {
+        psStringAppend(&query, "%s relExp.zpt_stdev = %f", sep, zpt_stdev);
+        sep = comma;
+    }
+    if (fault) {
+        psStringAppend(&query, "%s relExp.fault = %d", sep, fault);
+        sep = comma;
+    }
+    if (clearfault) {
+        psStringAppend(&query, "%s relExp.fault = 0", sep);
+        sep = comma;
+    }
+
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " WHERE %s", whereClause);
+    psFree(whereClause);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    psU64 affected = psDBAffectedRows(config->dbh);
+    psLogMsg("releasetool", PS_LOG_INFO, "Updated %" PRIu64 " ippReleases", affected);
+
+
+    psFree(query);
+
+    return true;
+}
+
+static bool tocalibexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, NULL);
@@ -440,5 +583,8 @@
     psMetadata *where = psMetadataAlloc();
 
-    PXOPT_COPY_STR(config->args, where, "-releaseName", "ippRelease.releaseName", "LIKE");
+    PXOPT_COPY_S64(config->args, where, "-relexp_id",   "relExp.relexp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-release_name", "ippRelease.release_name", "LIKE");
+#ifdef notdef
+    PXOPT_COPY_S32(config->args, where, "-rel_id",      "relExp.rel_id", "==");
     pxAddLabelSearchArgs(config, where, "-release_state","ippRelease.state", "==");
     PXOPT_COPY_STR(config->args, where, "-state",       "relExp.state", "==");
@@ -458,4 +604,104 @@
 
     PXOPT_COPY_STR(config->args, where, "-surveyName",  "survey.surveyName", "LIKE");
+
+    PXOPT_LOOKUP_BOOL(priority_order, config->args, "-priority_order", false);
+#endif
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("releasetool_tocalibexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    psString where2 = NULL;
+#ifdef notdef
+    if (!pxspaceAddWhere(config, &where2, "rawExp")) {
+        psError(psErrorCodeLast(), false, "pxspaceAddWhere failed");
+        return false;
+    }
+#endif
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, "\nAND %s", whereClause);
+        psFree(whereClause);
+#ifdef notdef
+    } else if (where2) {
+        psStringAppend(&query, "\nAND ");
+#endif
+    } else {
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required\n");
+        psFree(where);
+        return false;
+    }
+
+    if (where2) {
+        psStringAppend(&query, "\n%s", where2);
+        psFree(where2);
+    }
+
+    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) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psArrayLength(output)) {
+        psTrace("releasetool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (!ippdbPrintMetadatas(stdout, output, "relExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+static bool listrelexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_S64(config->args, where, "-relexp_id",   "relExp.relexp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-release_name", "ippRelease.release_name", "LIKE");
+    pxAddLabelSearchArgs(config, where, "-release_state","ippRelease.state", "==");
+    PXOPT_COPY_STR(config->args, where, "-state",       "relExp.state", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter",      "rawExp.filter", "LIKE");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin","rawExp.dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "rawExp.dateobs", "<=");
+    PXOPT_COPY_F32(config->args, where, "-fwhm_min",    "camProcessedExp.fwhm_major", ">=");
+    PXOPT_COPY_F32(config->args, where, "-fwhm_max",    "camProcessedExp.fwhm_major", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_name",    "rawExp.exp_name", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",      "relExp.exp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id",     "relExp.chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-cam_id",      "relExp.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-warp_id",     "warpRun.warp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-chip_data_group", "chipRun.data_group", "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-cam_data_group",  "camRun.data_group", "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-warp_data_group", "warpRun.data_group", "LIKE");
+
+    PXOPT_COPY_STR(config->args, where, "-surveyName",  "survey.surveyName", "LIKE");
     PXOPT_COPY_S32(config->args, where, "-rel_id",      "relExp.rel_id", "==");
 
@@ -533,3 +779,721 @@
     return true;
 }
-
+static bool definerelstackMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+
+    bool includeSkycal = false;
+
+    PXOPT_COPY_S64(config->args, where, "-skycal_id",  "skycalRun.skycal_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-skycal_label", "skycalRun.label", "==");
+    PXOPT_COPY_STR(config->args, where, "-skycal_data_group", "skycalRun.data_group", "==");
+    if (psListLength(where->list)) {
+        includeSkycal = true;
+    }
+
+    PXOPT_COPY_STR(config->args, where, "-label",      "stackRun.label", "==");
+    PXOPT_COPY_STR(config->args, where, "-data_group", "stackRun.data_group", "==");
+    PXOPT_COPY_S64(config->args, where, "-stack_id",   "stackRun.stack_id", "==");
+
+    // Insure that at least one of the skycalRun selectors is supplied
+    if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "at least one of -label, -data_group, or -skycal_id is required");
+        return false;
+    }
+
+    // PXOPT_COPY_STR(config->args, where, "-tess_id",    "stackRun.tess_id", "==");
+    // PXOPT_COPY_STR(config->args, where, "-skycell_id", "stackRun.skycell_id", "==");
+
+    // insure that at least one of these is supplied to select the release
+    PXOPT_LOOKUP_S64(rel_id, config->args,      "-rel_id", false, false);
+    PXOPT_LOOKUP_STR(release_name, config->args, "-release_name", false, false);
+    if (!rel_id && !release_name) {
+        psError(PXTOOLS_ERR_CONFIG, true, "either -rel_id or -release_name is required");
+        return false;
+    }
+
+    // limit query to the target release. (Note: this will select nothing if release_name and rel_id don't match)
+    // note: we add these after above to insure that search args are supplied
+    PXOPT_COPY_STR(config->args, where, "-release_name", "ippRelease.release_name", "==");
+    PXOPT_COPY_S32(config->args, where, "-rel_id", "ippRelease.rel_id", "==");
+
+
+    PXOPT_LOOKUP_STR(state, config->args,     "-set_state", true, false);
+    PXOPT_LOOKUP_STR(stack_type, config->args,"-set_stack_type", true, false);
+    PXOPT_LOOKUP_U32(flags, config->args,     "-set_flags", false, false);
+    PXOPT_LOOKUP_F32(zpt_obs, config->args,   "-set_zpt_obs", false, false);
+    PXOPT_LOOKUP_F32(zpt_stdev, config->args, "-set_zpt_stdev", false, false);
+    PXOPT_LOOKUP_STR(path_base, config->args, "-set_path_base", false, false);
+    PXOPT_LOOKUP_S16(fault, config->args,     "-set_fault", false, false);
+
+    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+    PXOPT_LOOKUP_BOOL(simple, config->args,  "-simple", false);
+
+    // find the parameters of all the exposures that we want to add to the release
+    psString query;
+    
+    if (includeSkycal) {
+        query = pxDataGet("releasetool_definerelstack_with_skycal.sql");
+    } else {
+        query = pxDataGet("releasetool_definerelstack.sql");
+    }
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " AND %s", whereClause);
+    psFree(whereClause);
+
+    psFree(where);
+
+    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) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("releasetool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (pretend) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "relstack", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+        psFree(output);
+        return true;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    psTime *now = psTimeGetNow(PS_TIME_TAI);
+    // loop over our list of  exposures
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+        bool status = true;
+        psS32 rel_id = psMetadataLookupS32(&status, md, "rel_id");
+        psS64 stack_id = psMetadataLookupS64(&status, md, "stack_id");
+        psS64 skycal_id = psMetadataLookupS64(&status, md, "skycal_id");
+        psString skycell_id = psMetadataLookupStr(&status, md, "skycell_id");
+        psString tess_id = psMetadataLookupStr(&status, md, "tess_id");
+        psString filter = psMetadataLookupStr(&status, md, "filter");
+
+        // use skycal zero point measurement if not supplied with arguments
+        psF32 sc_zpt_obs = psMetadataLookupF32(&status, md, "zpt_obs");
+        psF32 sc_zpt_stdev = psMetadataLookupF32(&status, md, "zpt_stdev");
+        psF32 stack_mjd_obs = psMetadataLookupF32(&status, md, "mjd_obs");
+
+        psU32 mjd_obs = 0;
+        if (!strcmp(stack_type, "nightly")) {
+            // only for nightly stacks do we set mjd_obs to a non zero value
+            // We use integer day because this is part of the key that is used
+            // to make sure entries are unique
+            //      KEY (rel_id, tess_id, skycell_id, filter, mjd_obs),
+            // 1 entry per release, skycell, filter and mjd_obs. 
+            // mjd_obs is zero for deep and reference stacks
+            mjd_obs = (psU32) stack_mjd_obs;
+        }
+
+        if (!relStackInsert(config->dbh,
+            0,          // relstack_id (auto increment)
+            rel_id,
+            stack_id,
+            skycal_id,
+            skycell_id,
+            tess_id,
+            filter,
+            state,
+            flags,
+            stack_type,
+            isfinite(zpt_obs)   ? zpt_obs   : sc_zpt_obs,
+            isfinite(zpt_stdev) ? zpt_stdev : sc_zpt_stdev,
+            mjd_obs,
+            path_base,
+            fault,
+            now,       // registered
+            now        // time_stamp
+        )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to insert relStack for stack_id %" PRId64, stack_id);
+            psFree(output);
+            psFree(now);
+            return false;
+        }
+    }
+    psFree(output);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool updaterelstackMode(pxConfig *config)
+{
+    psError(PS_ERR_UNKNOWN, true, "not yet implemented");
+    return false;
+}
+
+static bool listrelstackMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, where, "-release_name", "ippRelease.release_name", "LIKE");
+    pxAddLabelSearchArgs(config, where, "-release_state","ippRelease.state", "==");
+    PXOPT_COPY_STR(config->args, where, "-state",       "relExp.state", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter",      "rawExp.filter", "LIKE");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin","rawExp.dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "rawExp.dateobs", "<=");
+    PXOPT_COPY_F32(config->args, where, "-fwhm_min",    "skycalResult.fwhm_major", ">=");
+    PXOPT_COPY_F32(config->args, where, "-fwhm_max",    "skycalresult.fwhm_major", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_name",    "rawExp.exp_ame", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",      "relExp.exp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id",     "relExp.chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-cam_id",      "relExp.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-warp_id",     "warpRun.warp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-chip_data_group", "chipRun.data_group", "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-cam_data_group",  "camRun.data_group", "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-warp_data_group", "warpRun.data_group", "LIKE");
+
+    PXOPT_COPY_STR(config->args, where, "-surveyName",  "survey.surveyName", "LIKE");
+    PXOPT_COPY_S32(config->args, where, "-rel_id",      "relExp.rel_id", "==");
+
+    PXOPT_LOOKUP_BOOL(priority_order, config->args, "-priority_order", false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("releasetool_listrelexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    psString where2 = NULL;
+    if (!pxspaceAddWhere(config, &where2, "rawExp")) {
+        psError(psErrorCodeLast(), false, "pxspaceAddWhere failed");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, "\nWHERE %s", whereClause);
+        psFree(whereClause);
+    } else if (where2) {
+        psStringAppend(&query, "\nWHERE ");
+    } else {
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required\n");
+        psFree(where);
+        return false;
+    }
+
+    if (where2) {
+        psStringAppend(&query, "\n%s", where2);
+        psFree(where2);
+    }
+
+    if (priority_order) {
+        psStringAppend(&query, "\nAND priority > 0 order by exp_id, priority");
+    }
+
+    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) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psArrayLength(output)) {
+        psTrace("releasetool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (!ippdbPrintMetadatas(stdout, output, "relExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool definerelgroupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_STR(group_type, config->args, "-set_group_type", true, false);
+    PXOPT_LOOKUP_STR(group_name, config->args, "-set_group_name", false, false);
+    PXOPT_LOOKUP_STR(label, config->args,     "-set_label", true, false);
+
+    PXOPT_LOOKUP_STR(state, config->args,     "-set_state", false, false);
+    PXOPT_LOOKUP_STR(exp_list_path, config->args, "-set_exp_list_path", false, false);
+    PXOPT_LOOKUP_S16(fault, config->args,     "-set_fault", false, false);
+
+    psString query = NULL;
+
+    psMetadata *where = psMetadataAlloc();
+
+    // select sql and paramters based on group type
+    bool type_lap = false;
+    if (!strcmp(group_type, "lap")) {
+        type_lap = true;
+        if (group_name) {
+            psError(PXTOOLS_ERR_CONFIG, true, "group_name is not allowed with group_type lap");
+            psFree(where);
+            return false;
+        }
+        PXOPT_COPY_S64(config->args, where, "-select_seq_id", "lapRun.seq_id", "==");
+        PXOPT_COPY_S64(config->args, where, "-select_lap_id", "lapRun.lap_id", "==");
+        query = pxDataGet("releasetool_definerelgroup_select_lap.sql");
+        if (!query) {
+            psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+            psFree(where);
+            return false;
+        }
+    } else {
+        if (!strcmp(group_type, "date")) {
+            // group_type ok
+        } else if (!strcmp(group_type, "data_group")) {
+            // group_type ok
+        } else {
+            psError(PXTOOLS_ERR_CONFIG, true, "%s is not valid group_type", group_type);
+            return false;
+        }
+        if (!group_name) {
+            psError(PXTOOLS_ERR_CONFIG, true, "group_name is required allowed with group_type %s", group_type);
+            psFree(where);
+            return false;
+        }
+        pxAddLabelSearchArgs (config, where, "-select_data_group", "camRun.data_group", "==");
+        query = pxDataGet("releasetool_definerelgroup_select_data_group.sql");
+        if (!query) {
+            psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+            psFree(where);
+            return false;
+        }
+    }
+
+    // Insure that at least one of the exposure selectors is supplied
+    if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "search arguments are required");
+        return false;
+    }
+
+    // insure that at least one of these is supplied to select the release
+    PXOPT_LOOKUP_S64(rel_id, config->args,      "-rel_id", false, false);
+    PXOPT_LOOKUP_STR(release_name, config->args, "-release_name", false, false);
+    if (!rel_id && !release_name) {
+        psError(PXTOOLS_ERR_CONFIG, true, "either -rel_id or -release_name is required");
+        return false;
+    }
+
+    // limit query to the target release. (Note: this will select nothing if release_name and rel_id don't match)
+    // note: we add these after above to insure that search args are supplied
+    PXOPT_COPY_STR(config->args, where, "-release_name", "ippRelease.release_name", "==");
+    PXOPT_COPY_S32(config->args, where, "-rel_id", "ippRelease.rel_id", "==");
+
+    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+    PXOPT_LOOKUP_BOOL(simple, config->args,  "-simple", false);
+
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " AND %s", whereClause);
+    psFree(whereClause);
+
+    psFree(where);
+
+    if (!type_lap) {
+        psStringAppend(&query, "\nHAVING COUNT(exp_id) > 0");
+    }
+
+    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) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("releasetool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (pretend) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "relGroupToQueue", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+        psFree(output);
+        return true;
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(output);
+        return false;
+    }
+
+    psTime *now = psTimeGetNow(PS_TIME_TAI);
+    // loop over our list of  exposures
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+        bool status = true;
+        psS32 rel_id = psMetadataLookupS32(&status, md, "rel_id");
+        psS64 lap_id = 0;
+        if (type_lap) {
+            lap_id = psMetadataLookupS64(&status, md, "lap_id");
+        }
+
+        if (!relGroupInsert(config->dbh,
+            0,          // group_id (auto increment)
+            rel_id,
+            group_type,
+            lap_id,
+            group_name,
+            "reg",      // state
+            label,
+            exp_list_path,
+            fault,
+            now        // registered
+        )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to trying to insert relGroup");
+            psFree(output);
+            psFree(now);
+            return false;
+        }
+        // Here's our new group_id
+        psS32 group_id = psDBLastInsertID(config->dbh);
+
+        psString query;
+        if (type_lap) {
+            query = pxDataGet("releasetool_definerelgroup_select_exp_lap.sql");
+            if (!query) {
+                psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+                psFree(where);
+                return false;
+            }
+            psStringAppend(&query, " AND relExp.rel_id = %d AND lap_id = %" PRId64, rel_id, lap_id);
+        } else {
+            query = pxDataGet("releasetool_definerelgroup_select_exp_data_group.sql");
+            if (!query) {
+                psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+                psFree(where);
+                return false;
+            }
+            psStringAppend(&query, " AND relExp.rel_id = %d", rel_id);
+
+            psMetadata *where = psMetadataAlloc();
+            pxAddLabelSearchArgs (config, where, "-select_data_group", "camRun.data_group", "==");
+            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+            psStringAppend(&query, " AND %s", whereClause);
+            psFree(whereClause);
+            psFree(where);
+        }
+
+        if (!p_psDBRunQuery(config->dbh, query)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(query);
+            psFree(output);
+            psFree(now);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+        psFree(query);
+
+        psArray *exposures = p_psDBFetchResult(config->dbh);
+        if (!exposures) {
+            psFree(now);
+            psFree(output);
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+        if (!psArrayLength(exposures)) {
+            psFree(now);
+            psFree(output);
+            psFree(exposures);
+            psError(PS_ERR_UNKNOWN, false, "no exposures found error");
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+
+        // assign the relExps to this new group
+        char *updateQuery = "UPDATE relExp SET group_id = %d WHERE relexp_id = %" PRId64;
+        for (int j = 0; j < psArrayLength(exposures); j++) {
+            psMetadata *md = exposures->data[j];
+
+            bool status = true;
+            psS32 relexp_id = psMetadataLookupS32(&status, md, "relexp_id");
+            if (!p_psDBRunQueryF(config->dbh, updateQuery, group_id, relexp_id)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+                psFree(now);
+                psFree(output);
+                psFree(exposures);
+
+                if (!psDBRollback(config->dbh)) {
+                    psError(PS_ERR_UNKNOWN, false, "database error");
+                }
+                return false;
+            }
+        }
+        psFree(exposures);
+
+        // set state of relGroup to 'new'
+        if (!p_psDBRunQueryF(config->dbh, "UPDATE relGroup set state = 'new' WHERE group_id = %d", group_id)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(now);
+            psFree(output);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+    }
+    psFree(output);
+    psFree(now);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+static bool updaterelgroupMode(pxConfig *config)
+{
+    psError(PS_ERR_UNKNOWN, true, "not yet implemented");
+    return false;
+}
+
+static bool pendingrelgroupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+
+    pxAddLabelSearchArgs (config, where, "-label",      "relGroup.label", "==");
+    PXOPT_COPY_S32(config->args, where, "-group_id",    "relGroup.group_id", "==");
+    PXOPT_COPY_S32(config->args, where, "-rel_id",      "relExp.rel_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-release_name", "ippRelease.release_name", "LIKE");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("releasetool_pendingrelgroup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, "\nAND %s", whereClause);
+        psFree(whereClause);
+    } else {
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required\n");
+        psFree(where);
+        return false;
+    }
+
+    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) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psArrayLength(output)) {
+        psTrace("releasetool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (!ippdbPrintMetadatas(stdout, output, "pending_relGroup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool listrelgroupMode(pxConfig *config)
+{
+    return false;
+#ifdef notdef
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, where, "-release_name", "ippRelease.release_name", "LIKE");
+    pxAddLabelSearchArgs(config, where, "-release_state","ippRelease.state", "==");
+    PXOPT_COPY_STR(config->args, where, "-state",       "relExp.state", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter",      "rawExp.filter", "LIKE");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_begin","rawExp.dateobs", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-dateobs_end", "rawExp.dateobs", "<=");
+    PXOPT_COPY_F32(config->args, where, "-fwhm_min",    "skycalResult.fwhm_major", ">=");
+    PXOPT_COPY_F32(config->args, where, "-fwhm_max",    "skycalresult.fwhm_major", "<=");
+    PXOPT_COPY_STR(config->args, where, "-exp_name",    "rawExp.exp_ame", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id",      "relExp.exp_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-chip_id",     "relExp.chip_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-cam_id",      "relExp.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-warp_id",     "warpRun.warp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-chip_data_group", "chipRun.data_group", "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-cam_data_group",  "camRun.data_group", "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-warp_data_group", "warpRun.data_group", "LIKE");
+
+    PXOPT_COPY_STR(config->args, where, "-surveyName",  "survey.surveyName", "LIKE");
+    PXOPT_COPY_S32(config->args, where, "-rel_id",      "relExp.rel_id", "==");
+
+    PXOPT_LOOKUP_BOOL(priority_order, config->args, "-priority_order", false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("releasetool_listrelexp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    psString where2 = NULL;
+    if (!pxspaceAddWhere(config, &where2, "rawExp")) {
+        psError(psErrorCodeLast(), false, "pxspaceAddWhere failed");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, "\nWHERE %s", whereClause);
+        psFree(whereClause);
+    } else if (where2) {
+        psStringAppend(&query, "\nWHERE ");
+    } else {
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required\n");
+        psFree(where);
+        return false;
+    }
+
+    if (where2) {
+        psStringAppend(&query, "\n%s", where2);
+        psFree(where2);
+    }
+
+    if (priority_order) {
+        psStringAppend(&query, "\nAND priority > 0 order by exp_id, priority");
+    }
+
+    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) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psArrayLength(output)) {
+        psTrace("releasetool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (!ippdbPrintMetadatas(stdout, output, "relExp", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+#endif //notdef
+}
+
Index: branches/eam_branches/ipp-20130207/ippTools/src/releasetool.h
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/releasetool.h	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/releasetool.h	(revision 35236)
@@ -32,5 +32,14 @@
     RELEASETOOL_MODE_DEFINERELEXP,
     RELEASETOOL_MODE_UPDATERELEXP,
+    RELEASETOOL_MODE_TOCALIBEXP,
     RELEASETOOL_MODE_LISTRELEXP,
+    RELEASETOOL_MODE_DEFINERELSTACK,
+    RELEASETOOL_MODE_UPDATERELSTACK,
+    RELEASETOOL_MODE_TOCALIBSTACK,
+    RELEASETOOL_MODE_LISTRELSTACK,
+    RELEASETOOL_MODE_DEFINERELGROUP,
+    RELEASETOOL_MODE_PENDINGRELGROUP,
+    RELEASETOOL_MODE_UPDATERELGROUP,
+    RELEASETOOL_MODE_LISTRELGROUP,
 } releasetoolMode;
 
Index: branches/eam_branches/ipp-20130207/ippTools/src/releasetoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/releasetoolConfig.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/releasetoolConfig.c	(revision 35236)
@@ -60,23 +60,19 @@
     psMetadata *definereleaseArgs = psMetadataAlloc();
     psMetadataAddS32(definereleaseArgs, PS_LIST_TAIL, "-set_surveyID", 0,      "define survey ID (required)", 0);
-    psMetadataAddStr(definereleaseArgs, PS_LIST_TAIL, "-set_releaseName", 0,   "define release name (required)", NULL);
+    psMetadataAddStr(definereleaseArgs, PS_LIST_TAIL, "-set_release_name", 0,   "define release name (required)", NULL);
     psMetadataAddS32(definereleaseArgs, PS_LIST_TAIL, "-set_dataRelease", 0,   "define dataRelease", -1);
     psMetadataAddStr(definereleaseArgs, PS_LIST_TAIL, "-set_release_state", 0, "define release state", NULL);
-    psMetadataAddS32(definereleaseArgs, PS_LIST_TAIL, "-set_priority", 0,      "define release priority", -1);
+    psMetadataAddS32(definereleaseArgs, PS_LIST_TAIL, "-set_priority", 0,      "define release priority", 0);
 
     // -uptdaterelease
     psMetadata *updatereleaseArgs = psMetadataAlloc();
 
-    // releaseName and/or rel_id is required. This is handled in updatereleaseMode
-    psMetadataAddStr(updatereleaseArgs, PS_LIST_TAIL, "-releaseName", 0,        "select by release name", NULL);
+    // release_name and/or rel_id is required. This is handled in updatereleaseMode
+    psMetadataAddStr(updatereleaseArgs, PS_LIST_TAIL, "-release_name", 0,        "select by release name", NULL);
     psMetadataAddS32(updatereleaseArgs, PS_LIST_TAIL, "-rel_id", 0,             "select by release ID", 0);
 
-    // Only support changing state and priority for now
-    psMetadataAddStr(updatereleaseArgs, PS_LIST_TAIL, "-set_release_state", 0,  "define new release state(required)", NULL);
+    psMetadataAddStr(updatereleaseArgs, PS_LIST_TAIL, "-set_release_state", 0,  "define new release state", NULL);
     psMetadataAddS32(updatereleaseArgs, PS_LIST_TAIL, "-set_priority", 0,       "define new release priority", 0);
-
-//    psMetadataAddS32(updatereleaseArgs, PS_LIST_TAIL, "-set_surveyID", 0,       "define surveyID (required)", 0);
-//    psMetadataAddStr(updatereleaseArgs, PS_LIST_TAIL, "-set_releaseName", 0,    "define release name (required)", NULL);
-//    psMetadataAddS32(updatereleaseArgs, PS_LIST_TAIL, "-set_dataRelease", 0,    "define dataRelease", -1);
+    psMetadataAddS32(updatereleaseArgs, PS_LIST_TAIL, "-set_dataRelease", 0,    "define data release", -1);
 
 
@@ -84,5 +80,5 @@
     psMetadata *listreleaseArgs = psMetadataAlloc();
     psMetadataAddStr(listreleaseArgs,  PS_LIST_TAIL, "-surveyName", 0,  "select by survey name (LIKE comparision)", NULL);
-    psMetadataAddStr(listreleaseArgs,  PS_LIST_TAIL, "-releaseName", 0, "select by release name (LIKE comparision)", NULL);
+    psMetadataAddStr(listreleaseArgs,  PS_LIST_TAIL, "-release_name", 0, "select by release name (LIKE comparision)", NULL);
     psMetadataAddStr(listreleaseArgs,  PS_LIST_TAIL, "-release_state",  0, "select by release state", NULL);
     psMetadataAddS32(listreleaseArgs, PS_LIST_TAIL,  "-rel_id", 0,      "select by release ID", 0);
@@ -95,5 +91,5 @@
 
         // set the target release
-    psMetadataAddStr(definerelexpArgs,  PS_LIST_TAIL, "-releaseName", 0, "define release name", NULL);
+    psMetadataAddStr(definerelexpArgs,  PS_LIST_TAIL, "-release_name", 0, "define release name", NULL);
     psMetadataAddS32(definerelexpArgs, PS_LIST_TAIL,  "-rel_id", 0,      "define release ID", 0);
 
@@ -109,19 +105,41 @@
         // parameters of the relExp
     psMetadataAddStr(definerelexpArgs,  PS_LIST_TAIL, "-set_state", 0,      "define state (required)", NULL);
+    psMetadataAddU32(definerelexpArgs,  PS_LIST_TAIL, "-set_flags", 0,      "define flags", 0);
+    psMetadataAddF32(definerelexpArgs,  PS_LIST_TAIL, "-set_zpt_obs", 0,    "define zero point", NAN);
+    psMetadataAddF32(definerelexpArgs,  PS_LIST_TAIL, "-set_zpt_stdev", 0,  "define zero point stdev", NAN);
     psMetadataAddStr(definerelexpArgs,  PS_LIST_TAIL, "-set_path_base", 0,  "define state", NULL);
-    psMetadataAddU32(definerelexpArgs,  PS_LIST_TAIL, "-set_flags", 0,      "define flags", 0);
-
-    psMetadataAddBool(definerelexpArgs, PS_LIST_TAIL, "-pretend",  0, "do not actual modify the database", false);
-    psMetadataAddBool(definerelexpArgs, PS_LIST_TAIL, "-simple",  0, "use the simpel output format", false);
-
-
+    psMetadataAddS16(definerelexpArgs,  PS_LIST_TAIL, "-set_fault", 0,      "define fault", 0);
+
+    psMetadataAddBool(definerelexpArgs, PS_LIST_TAIL, "-pretend",  0, "do not actually modify the database", false);
+    psMetadataAddBool(definerelexpArgs, PS_LIST_TAIL, "-simple",  0, "use the simple output format", false);
 
     // -updaterelexp
     psMetadata *updaterelexpArgs = psMetadataAlloc();
-    psMetadataAddStr(updaterelexpArgs,  PS_LIST_TAIL, "-releaseName", 0, "select by release name (LIKE comparision)", NULL);
+    psMetadataAddS64(updaterelexpArgs, PS_LIST_TAIL,  "-relexp_id", 0,   "select by released exposure ID", 0);
+    psMetadataAddS64(updaterelexpArgs, PS_LIST_TAIL,  "-exp_id", 0,      "select by exposure ID", 0);
+    psMetadataAddStr(updaterelexpArgs,  PS_LIST_TAIL, "-exp_name", 0,    "select by exposure name", NULL);
+    psMetadataAddS32(updaterelexpArgs, PS_LIST_TAIL,  "-rel_id", 0,      "select by release ID", 0);
+    psMetadataAddStr(updaterelexpArgs,  PS_LIST_TAIL, "-release_name", 0, "select by release name (LIKE comparision)", NULL);
+
+    psMetadataAddStr(updaterelexpArgs,  PS_LIST_TAIL, "-set_state", 0,      "define new state)", NULL);
+    psMetadataAddU32(updaterelexpArgs,  PS_LIST_TAIL, "-set_flags", 0,      "define new flags", 0);
+    psMetadataAddF32(updaterelexpArgs,  PS_LIST_TAIL, "-set_zpt_obs", 0,    "define new zero point", NAN);
+    psMetadataAddF32(updaterelexpArgs,  PS_LIST_TAIL, "-set_zpt_stdev", 0,  "define new zero point stdev", NAN);
+    psMetadataAddStr(updaterelexpArgs,  PS_LIST_TAIL, "-set_path_base", 0,  "define path_base", NULL);
+    psMetadataAddS16(updaterelexpArgs,  PS_LIST_TAIL, "-set_fault", 0,      "define new fault", 0);
+    psMetadataAddBool(updaterelexpArgs, PS_LIST_TAIL, "-clearfault",  0,   "set fault to zero", false);
+
+    // -tocalibexp
+    psMetadata *tocalibexpArgs = psMetadataAlloc();
+    psMetadataAddS64(tocalibexpArgs, PS_LIST_TAIL,  "-relexp_id", 0,   "select by released exposure ID", 0);
+    psMetadataAddStr(tocalibexpArgs,  PS_LIST_TAIL, "-release_name", 0, "select by release name (LIKE comparision)", NULL);
+
+    psMetadataAddU64(tocalibexpArgs,  PS_LIST_TAIL, "-limit",       0, "limit result set to N items", 0);
+    psMetadataAddBool(tocalibexpArgs, PS_LIST_TAIL, "-simple",      0, "use the simple output format", false);
 
     // -listrelexp
     psMetadata *listrelexpArgs = psMetadataAlloc();
-    psMetadataAddStr(listrelexpArgs,  PS_LIST_TAIL, "-releaseName", 0,  "select by release name (LIKE comparision)", NULL);
+    psMetadataAddS64(listrelexpArgs, PS_LIST_TAIL,  "-relexp_id", 0,   "select by released exposure ID", 0);
+    psMetadataAddStr(listrelexpArgs,  PS_LIST_TAIL, "-release_name", 0, "select by release name (LIKE comparision)", NULL);
     psMetadataAddStr(listrelexpArgs,  PS_LIST_TAIL, "-release_state", PS_META_DUPLICATE_OK, "select by release state", NULL);
     psMetadataAddStr(listrelexpArgs,  PS_LIST_TAIL, "-state", 0,        "select by released exposure state", NULL);
@@ -155,4 +173,88 @@
     psMetadataAddBool(listrelexpArgs, PS_LIST_TAIL, "-simple",      0, "use the simple output format", false);
 
+    // -definerelstack
+    psMetadata *definerelstackArgs = psMetadataAlloc();
+
+        // set the target release
+    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-release_name", 0, "define release name", NULL);
+    psMetadataAddS32(definerelstackArgs, PS_LIST_TAIL,  "-rel_id", 0,      "define release ID", 0);
+
+        // select the processing
+    psMetadataAddS64(definerelstackArgs, PS_LIST_TAIL,  "-stack_id", 0,    "select by stack ID", 0);
+    psMetadataAddS64(definerelstackArgs, PS_LIST_TAIL,  "-skycal_id", 0,   "select by skycal ID", 0);
+    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-label",  0,      "select by stackRun.label", NULL);
+    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-data_group", 0,  "select by stackRun.data_group", NULL);
+    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-skycal_label",  0, "select by skycalRun.label", NULL);
+    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-skycal_data_group", 0,  "select by skycalRun.data_group", NULL);
+
+        // parameters of the relStack
+    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-set_state", 0,      "define state (required)", NULL);
+    psMetadataAddU32(definerelstackArgs,  PS_LIST_TAIL, "-set_flags", 0,      "define flags", 0);
+    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-set_stack_type", 0, "define stack type (required)", NULL);
+    psMetadataAddF32(definerelstackArgs,  PS_LIST_TAIL, "-set_zpt_obs", 0,    "define zero point", NAN);
+    psMetadataAddF32(definerelstackArgs,  PS_LIST_TAIL, "-set_zpt_stdev", 0,  "define zero point stdev", NAN);
+    psMetadataAddF32(definerelstackArgs,  PS_LIST_TAIL, "-set_fwhm_major", 0, "define fwhm_major", NAN);
+    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-set_path_base", 0,  "define state (required)", NULL);
+    psMetadataAddS16(definerelstackArgs,  PS_LIST_TAIL, "-set_fault", 0,      "define fault", 0);
+
+    psMetadataAddBool(definerelstackArgs, PS_LIST_TAIL, "-pretend",  0, "do not actually modify the database", false);
+    psMetadataAddBool(definerelstackArgs, PS_LIST_TAIL, "-simple",  0, "use the simple output format", false);
+
+    // -definerelgroup
+    psMetadata *definerelgroupArgs = psMetadataAlloc();
+
+        // set the target release
+    psMetadataAddStr(definerelgroupArgs, PS_LIST_TAIL, "-release_name", 0, "define release name", NULL);
+    psMetadataAddS32(definerelgroupArgs, PS_LIST_TAIL, "-rel_id", 0,      "define release ID", 0);
+
+        // select the members of the group
+    psMetadataAddS64(definerelgroupArgs, PS_LIST_TAIL, "-select_seq_id", 0,  "select by LAP sequence ID", 0);
+    psMetadataAddS64(definerelgroupArgs, PS_LIST_TAIL, "-select_lap_id", 0,  "select by LAP ID", 0);
+    psMetadataAddStr(definerelgroupArgs, PS_LIST_TAIL, "-select_data_group", PS_META_DUPLICATE_OK,  "select by camRun.data_group", NULL);
+    // do we want this?
+    // psMetadataAddS64(definerelgroupArgs, PS_LIST_TAIL, "-lap_id", 0,  "select by LAP ID", NULL);
+
+        // parameters of the relGroup
+    psMetadataAddStr(definerelgroupArgs, PS_LIST_TAIL, "-set_group_type", 0,  "define group_type (required)", NULL);
+    psMetadataAddStr(definerelgroupArgs, PS_LIST_TAIL, "-set_group_name", 0,  "define group_name (required)", NULL);
+    psMetadataAddStr(definerelgroupArgs, PS_LIST_TAIL, "-set_label", 0, "define relgroup label (required)", NULL);
+    psMetadataAddStr(definerelgroupArgs,  PS_LIST_TAIL, "-set_state", 0,      "define state", NULL);
+    psMetadataAddStr(definerelgroupArgs,  PS_LIST_TAIL, "-set_exp_list_path", 0, "define path in exposure list", NULL);
+    psMetadataAddS16(definerelgroupArgs,  PS_LIST_TAIL, "-set_fault", 0,      "define fault", 0);
+
+        // options
+    psMetadataAddBool(definerelgroupArgs, PS_LIST_TAIL, "-pretend",  0, "do not actually modify the database", false);
+    psMetadataAddBool(definerelgroupArgs, PS_LIST_TAIL, "-simple",  0, "use the simple output format", false);
+
+    // -pendingrelgroup
+    psMetadata *pendingrelgroupArgs = psMetadataAlloc();
+
+    psMetadataAddStr(pendingrelgroupArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK,  "search by relGroup.label", NULL);
+    psMetadataAddS32(pendingrelgroupArgs, PS_LIST_TAIL, "-rel_id", 0,      "select by release ID", 0);
+    psMetadataAddS32(pendingrelgroupArgs, PS_LIST_TAIL, "-group_id", 0,    "select by relGroup ID", 0);
+    psMetadataAddStr(pendingrelgroupArgs, PS_LIST_TAIL, "-release_name", 0, "select by release name", 0);
+    psMetadataAddBool(pendingrelgroupArgs, PS_LIST_TAIL, "-simple",  0, "use the simple output format", false);
+    psMetadataAddU64(pendingrelgroupArgs, PS_LIST_TAIL,  "-limit",       0, "limit result set to N items", 0);
+    
+    // -updaterelgroup
+    psMetadata *updaterelgroupArgs = psMetadataAlloc();
+
+        // set the target release
+    psMetadataAddS32(updaterelgroupArgs,  PS_LIST_TAIL, "-group_id", 0,   "select by group ID (required)", 0);
+
+        // parameters of the relGroup
+    psMetadataAddStr(updaterelgroupArgs,  PS_LIST_TAIL, "-set_state", 0,  "define state", NULL);
+    psMetadataAddStr(updaterelgroupArgs,  PS_LIST_TAIL, "-set_exp_list_path", 0, "define path in exposure list", NULL);
+    psMetadataAddStr(updaterelgroupArgs,  PS_LIST_TAIL, "-set_label", 0,  "define relgroup label", NULL);
+    psMetadataAddS16(updaterelgroupArgs,  PS_LIST_TAIL, "-set_fault", 0,  "define fault", 0);
+    psMetadataAddBool(updaterelgroupArgs, PS_LIST_TAIL, "-clearfault",  0, "set fault to zero", false);
+
+    psMetadata *listrelgroupArgs = psMetadataAlloc();
+    psMetadataAddS32(listrelgroupArgs,  PS_LIST_TAIL, "-group_id", 0,   "select by group ID", 0);
+    psMetadataAddS32(listrelgroupArgs,  PS_LIST_TAIL, "-rel_id", 0,   "select by release ID", 0);
+    psMetadataAddStr(listrelgroupArgs, PS_LIST_TAIL,  "-release_name", 0, "select by release name", 0);
+
+    // ******************************************************************
+
     psMetadata *argSets = psMetadataAlloc();
     psMetadata *modes = psMetadataAlloc();
@@ -160,10 +262,22 @@
     PXOPT_ADD_MODE("-definesurvey",     "define a survey",              RELEASETOOL_MODE_DEFINESURVEY,  definesurveyArgs);
     PXOPT_ADD_MODE("-listsurvey",       "list skycell parameters",      RELEASETOOL_MODE_LISTSURVEY,    listsurveyArgs);
+
     PXOPT_ADD_MODE("-definerelease",    "define a release",             RELEASETOOL_MODE_DEFINERELEASE, definereleaseArgs);
     PXOPT_ADD_MODE("-updaterelease",    "update a release",             RELEASETOOL_MODE_UPDATERELEASE, updatereleaseArgs);
     PXOPT_ADD_MODE("-listrelease",      "list releases",                RELEASETOOL_MODE_LISTRELEASE,   listreleaseArgs);
+
     PXOPT_ADD_MODE("-definerelexp",     "define a released exposure",   RELEASETOOL_MODE_DEFINERELEXP,  definerelexpArgs);
     PXOPT_ADD_MODE("-updaterelexp",     "update a released exposure",   RELEASETOOL_MODE_UPDATERELEXP,  updaterelexpArgs);
+    PXOPT_ADD_MODE("-tocalibexp",       "list relExps pending calibration",  RELEASETOOL_MODE_TOCALIBEXP,  tocalibexpArgs);
     PXOPT_ADD_MODE("-listrelexp",       "list released exposures",      RELEASETOOL_MODE_LISTRELEXP,    listrelexpArgs);
+
+    PXOPT_ADD_MODE("-definerelstack",     "define a released stack",    RELEASETOOL_MODE_DEFINERELSTACK,  definerelstackArgs);
+
+    PXOPT_ADD_MODE("-definerelgroup",     "define a group of exposures", RELEASETOOL_MODE_DEFINERELGROUP,  definerelgroupArgs);
+    PXOPT_ADD_MODE("-pendingrelgroup",     "list relGroups pending processing",    RELEASETOOL_MODE_PENDINGRELGROUP,  pendingrelgroupArgs);
+    PXOPT_ADD_MODE("-updaterelgroup",     "update a relGroup",          RELEASETOOL_MODE_UPDATERELGROUP,  updaterelgroupArgs);
+    PXOPT_ADD_MODE("-listrelgroup",     "define a group of exposures", RELEASETOOL_MODE_LISTRELGROUP,  listrelgroupArgs);
+
+
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: branches/eam_branches/ipp-20130207/ippTools/src/staticskytool.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/staticskytool.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/staticskytool.c	(revision 35236)
@@ -1281,4 +1281,6 @@
     PXOPT_LOOKUP_F32(zpt_obs, config->args,   "-zpt_obs", false, false);
     PXOPT_LOOKUP_F32(zpt_stdev, config->args, "-zpt_stdev", false, false);
+    PXOPT_LOOKUP_F32(fwhm_major, config->args, "-fwhm_major", false, false);
+    PXOPT_LOOKUP_F32(fwhm_minor, config->args, "-fwhm_minor", false, false);
 
 
@@ -1334,4 +1336,6 @@
         zpt_obs,
         zpt_stdev,
+        fwhm_major,
+        fwhm_minor,
         quality,
         software_ver,
Index: branches/eam_branches/ipp-20130207/ippTools/src/staticskytoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20130207/ippTools/src/staticskytoolConfig.c	(revision 35125)
+++ branches/eam_branches/ipp-20130207/ippTools/src/staticskytoolConfig.c	(revision 35236)
@@ -211,6 +211,8 @@
     psMetadataAddF32(addskycalresultArgs, PS_LIST_TAIL, "-sigma_ra", 0,            "define exposure E ra", NAN);
     psMetadataAddF32(addskycalresultArgs, PS_LIST_TAIL, "-sigma_dec", 0,            "define exposure E dec", NAN);
-    psMetadataAddF32(addskycalresultArgs, PS_LIST_TAIL, "-zpt_obs", 0,   "define observed zero point", 0);
-    psMetadataAddF32(addskycalresultArgs, PS_LIST_TAIL, "-zpt_stdev", 0,   "define observed zero point stdandard deviation", 0);
+    psMetadataAddF32(addskycalresultArgs, PS_LIST_TAIL, "-zpt_obs", 0,   "define observed zero point", NAN);
+    psMetadataAddF32(addskycalresultArgs, PS_LIST_TAIL, "-zpt_stdev", 0,   "define observed zero point stdandard deviation", NAN);
+    psMetadataAddF32(addskycalresultArgs, PS_LIST_TAIL, "-fwhm_major", 0,   "define fwhm (major axis; pixels)", NAN);
+    psMetadataAddF32(addskycalresultArgs, PS_LIST_TAIL, "-fwhm_minor", 0,   "define fwhm (minor axis; pixels)", NAN);
 
     psMetadataAddF32(addskycalresultArgs, PS_LIST_TAIL, "-dtime_script", 0, "define elapsed time in script (seconds)", NAN);
