Index: trunk/ippTools/share/Makefile.am
===================================================================
--- trunk/ippTools/share/Makefile.am	(revision 35197)
+++ trunk/ippTools/share/Makefile.am	(revision 35213)
@@ -464,8 +464,13 @@
 	sctool_list.sql \
 	releasetool_listsurvey.sql \
+	releasetool_tocalibexp.sql \
 	releasetool_listrelease.sql \
 	releasetool_listrelexp.sql \
 	releasetool_definerelexp.sql \
 	releasetool_definerelstack.sql \
-	releasetool_definerelstack_with_skycal.sql
+	releasetool_definerelstack_with_skycal.sql \
+	releasetool_definerelgroup_select_lap.sql \
+	releasetool_definerelgroup_select_data_group.sql \
+	releasetool_definerelgroup_select_exp_data_group.sql \
+	releasetool_definerelgroup_select_exp_lap.sql
 
Index: trunk/ippTools/share/pxadmin_create_tables.sql
===================================================================
--- trunk/ippTools/share/pxadmin_create_tables.sql	(revision 35197)
+++ trunk/ippTools/share/pxadmin_create_tables.sql	(revision 35213)
@@ -2164,10 +2164,10 @@
     rel_id      INT(8) AUTO_INCREMENT,
     surveyID    INT(8),
-    releaseName VARCHAR(64),
+    release_name VARCHAR(64),
     relase_state VARCHAR(16),   -- active, pending, archive, drop 
     dataRelease INT(8),         -- PSPS dataRelease
     priority    INT(8),
     PRIMARY KEY(rel_id),
-    KEY(releaseName),
+    KEY(release_name),
     KEY(state),
     KEY(priority),
@@ -2181,4 +2181,5 @@
     chip_id     BIGINT,         -- links to the runs that supplied the data
     cam_id      BIGINT,         -- for this release
+    group_id    INT(8),         -- id of relGroup that this exposure is contained in
     state       VARCHAR(16),    -- released, pending, archive, drop  
     flags       INT UNSIGNED,   -- flags for relphot, relastro, ??
@@ -2229,4 +2230,26 @@
 ) ENGINE=innodb DEFAULT CHARSET=latin1;
 
+CREATE TABLE relGroup (
+    group_id    INT(8) AUTO_INCREMENT,
+    rel_id      INT(8),
+    group_type  VARCHAR(16),
+    lap_id      BIGINT,
+    group_name  VARCHAR(16),
+    state       VARCHAR(16),    -- new full
+    label       VARCHAR(64),
+    exp_list_path   VARCHAR(255),
+    fault SMALLINT NOT NULL,
+    registered  DATETIME,
+    PRIMARY KEY (group_id),
+    KEY (rel_id, group_name),
+    KEY (group_type),
+    KEY (lap_id),
+    KEY (group_name),
+    KEY (state),
+    KEY (label),
+    KEY (fault),
+    FOREIGN KEY(rel_id) REFERENCES ippRelease(rel_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
 
 
Index: trunk/ippTools/share/releasetool_definerelexp.sql
===================================================================
--- trunk/ippTools/share/releasetool_definerelexp.sql	(revision 35197)
+++ trunk/ippTools/share/releasetool_definerelexp.sql	(revision 35213)
@@ -1,5 +1,5 @@
 SELECT
     ippRelease.rel_id,
-    ippRelease.releaseName,
+    ippRelease.release_name,
     rawExp.exp_name,
     rawExp.filter,
Index: trunk/ippTools/share/releasetool_definerelgroup_select_data_group.sql
===================================================================
--- trunk/ippTools/share/releasetool_definerelgroup_select_data_group.sql	(revision 35213)
+++ trunk/ippTools/share/releasetool_definerelgroup_select_data_group.sql	(revision 35213)
@@ -0,0 +1,9 @@
+SELECT
+    ippRelease.rel_id,
+    count(exp_id) AS num_exposures
+FROM ippRelease
+    LEFT JOIN relExp using(rel_id)
+    LEFT JOIN camRun using(cam_id)
+    WHERE relExp.group_id = 0
+    AND relExp.state != 'drop'
+
Index: trunk/ippTools/share/releasetool_definerelgroup_select_exp_data_group.sql
===================================================================
--- trunk/ippTools/share/releasetool_definerelgroup_select_exp_data_group.sql	(revision 35213)
+++ trunk/ippTools/share/releasetool_definerelgroup_select_exp_data_group.sql	(revision 35213)
@@ -0,0 +1,6 @@
+SELECT relExp.relexp_id
+FROM relExp
+    JOIN camRun USING(cam_id)
+WHERE 
+    relExp.group_id = 0
+    AND relExp.state != 'drop'
Index: trunk/ippTools/share/releasetool_definerelgroup_select_exp_lap.sql
===================================================================
--- trunk/ippTools/share/releasetool_definerelgroup_select_exp_lap.sql	(revision 35213)
+++ trunk/ippTools/share/releasetool_definerelgroup_select_exp_lap.sql	(revision 35213)
@@ -0,0 +1,4 @@
+SELECT relExp.relexp_id
+FROM relGroup JOIN lapRun USING(lap_id)
+    JOIN relExp using(rel_id, exp_id)
+WHERE relExp.group_id = 0
Index: trunk/ippTools/share/releasetool_definerelgroup_select_lap.sql
===================================================================
--- trunk/ippTools/share/releasetool_definerelgroup_select_lap.sql	(revision 35213)
+++ trunk/ippTools/share/releasetool_definerelgroup_select_lap.sql	(revision 35213)
@@ -0,0 +1,11 @@
+SELECT 
+    lapRun.seq_id,
+    lapRun.lap_id,
+    ippRelease.rel_id
+FROM lapRun
+    JOIN ippRelease
+    LEFT JOIN relGroup USING(lap_id)
+WHERE (lapRun.state = 'done' or lapRun.state = 'full')
+    AND relGroup.group_id IS NULL
+-- AND lapRun.seq_id = xxx
+
Index: trunk/ippTools/share/releasetool_listrelexp.sql
===================================================================
--- trunk/ippTools/share/releasetool_listrelexp.sql	(revision 35197)
+++ trunk/ippTools/share/releasetool_listrelexp.sql	(revision 35213)
@@ -2,5 +2,6 @@
     relexp_id,
     relExp.state,
-    ippRelease.releaseName,
+    relExp.fault,
+    ippRelease.release_name,
     ippRelease.release_state,
     ippRelease.rel_id,
@@ -21,4 +22,5 @@
     camProcessedExp.path_base as cam_path_base,
     camProcessedExp.fwhm_major,
+    camProcessedExp.fwhm_minor,
     warpRun.warp_id,
     warpRun.state as warp_state,
Index: trunk/ippTools/share/releasetool_tocalibexp.sql
===================================================================
--- trunk/ippTools/share/releasetool_tocalibexp.sql	(revision 35213)
+++ trunk/ippTools/share/releasetool_tocalibexp.sql	(revision 35213)
@@ -0,0 +1,5 @@
+SELECT relExp.*,
+ippRelease.release_name,
+ippRelease.release_state
+FROM relExp JOIN ippRelease USING(rel_id)
+WHERE relExp.state = 'goto_calib' AND relExp.fault = 0
Index: trunk/ippTools/share/reltool_pendinggroup.sql
===================================================================
--- trunk/ippTools/share/reltool_pendinggroup.sql	(revision 35213)
+++ trunk/ippTools/share/reltool_pendinggroup.sql	(revision 35213)
@@ -0,0 +1,8 @@
+-- relGroups to process
+SELECT relGroup.*,
+    ippRelease.release_id,
+    ippRelease.release_name
+FROM relGroup 
+    JOIN ippRelease USING(rel_id)
+WHERE relGroup.state ='new'
+    AND relGroup.fault = 0
Index: trunk/ippTools/src/releasetool.c
===================================================================
--- trunk/ippTools/src/releasetool.c	(revision 35197)
+++ trunk/ippTools/src/releasetool.c	(revision 35213)
@@ -41,4 +41,5 @@
 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);
@@ -46,4 +47,8 @@
 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) \
@@ -69,4 +74,5 @@
         MODECASE(RELEASETOOL_MODE_DEFINERELEASE,    definereleaseMode);
         MODECASE(RELEASETOOL_MODE_UPDATERELEASE,    updatereleaseMode);
+        MODECASE(RELEASETOOL_MODE_TOCALIBEXP,       tocalibexpMode);
         MODECASE(RELEASETOOL_MODE_LISTRELEASE,      listreleaseMode);
 
@@ -78,4 +84,9 @@
         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)");
@@ -170,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);
@@ -178,5 +189,5 @@
         0,      // rel_id (auto_increment)
         surveyID,
-        releaseName,
+        release_name,
         release_state,
         dataRelease,
@@ -194,9 +205,9 @@
     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");
+    if (!release_name && !rel_id) {
+        psError(PXTOOLS_ERR_CONFIG, true, "either -release_name or -rel_id is required\n");
         return false;
     }
@@ -211,5 +222,5 @@
 
     PXOPT_COPY_S32(config->args, where, "-rel_id",  "rel_id", "==");
-    PXOPT_COPY_STR(config->args, where, "-releaseName", "releaseName", "==");
+    PXOPT_COPY_STR(config->args, where, "-release_name", "release_name", "==");
 
     psString sep = "";
@@ -253,5 +264,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", "==");
@@ -334,13 +345,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", "==");
 
@@ -429,4 +440,5 @@
             chip_id,
             cam_id,
+            0,          // group_id
             state,
             flags,
@@ -460,9 +472,99 @@
 static bool updaterelexpMode(pxConfig *config)
 {
-    psError(PS_ERR_UNKNOWN, true, "not yet implemented");
-    return false;
+    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 listrelexpMode(pxConfig *config)
+static bool tocalibexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, NULL);
@@ -470,5 +572,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", "==");
@@ -488,4 +593,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", "==");
 
@@ -594,13 +799,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", "==");
 
@@ -752,5 +957,5 @@
     psMetadata *where = psMetadataAlloc();
 
-    PXOPT_COPY_STR(config->args, where, "-releaseName", "ippRelease.releaseName", "LIKE");
+    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", "==");
@@ -846,2 +1051,471 @@
 }
 
+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", true, 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;
+        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;
+        }
+        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)
+{
+    psError(PS_ERR_UNKNOWN, true, "not yet implemented");
+    return false;
+#ifdef notdef
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psMetadata *where = psMetadataAlloc();
+
+    pxAddLabelSearchArgs (config, where, "-label", "relGroup.label", "==");
+
+    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", "==");
+    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_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;
+#endif // notdef
+}
+
+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: trunk/ippTools/src/releasetool.h
===================================================================
--- trunk/ippTools/src/releasetool.h	(revision 35197)
+++ trunk/ippTools/src/releasetool.h	(revision 35213)
@@ -32,8 +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: trunk/ippTools/src/releasetoolConfig.c
===================================================================
--- trunk/ippTools/src/releasetoolConfig.c	(revision 35197)
+++ trunk/ippTools/src/releasetoolConfig.c	(revision 35213)
@@ -60,5 +60,5 @@
     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);
@@ -68,14 +68,14 @@
     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", NULL);
     psMetadataAddS32(updatereleaseArgs, PS_LIST_TAIL, "-set_priority", 0,       "define new release priority", 0);
 
+    // Only support changing state and priority for now
 //    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);
+//    psMetadataAddStr(updatereleaseArgs, PS_LIST_TAIL, "-set_release_name", 0,    "define release name (required)", NULL);
 //    psMetadataAddS32(updatereleaseArgs, PS_LIST_TAIL, "-set_dataRelease", 0,    "define dataRelease", -1);
 
@@ -84,5 +84,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 +95,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);
 
@@ -112,19 +112,38 @@
     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 (required)", NULL);
+    psMetadataAddStr(definerelexpArgs,  PS_LIST_TAIL, "-set_path_base", 0,  "define state", NULL);
     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 simpel output format", 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);
@@ -162,5 +181,5 @@
 
         // set the target release
-    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-releaseName", 0, "define release name", NULL);
+    psMetadataAddStr(definerelstackArgs,  PS_LIST_TAIL, "-release_name", 0, "define release name", NULL);
     psMetadataAddS32(definerelstackArgs, PS_LIST_TAIL,  "-rel_id", 0,      "define release ID", 0);
 
@@ -184,5 +203,57 @@
 
     psMetadataAddBool(definerelstackArgs, PS_LIST_TAIL, "-pretend",  0, "do not actually modify the database", false);
-    psMetadataAddBool(definerelstackArgs, PS_LIST_TAIL, "-simple",  0, "use the simpel output format", 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();
+
+    psMetadataAddS64(pendingrelgroupArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK,  "search by relGroup.label", 0);
+    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);
+    
+    // -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);
 
     // ******************************************************************
@@ -200,7 +271,14 @@
     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);
+
 
 
