Index: branches/eam_branches/ipp-20110404/ippTools/src/Makefile.am
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/Makefile.am	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/Makefile.am	(revision 31439)
@@ -28,5 +28,6 @@
 	pubtool \
 	diffphottool \
-	minidvodbtool
+	minidvodbtool \
+	laptool
 
 pkginclude_HEADERS = \
@@ -76,5 +77,6 @@
 	pubtool.h \
 	diffphottool.h \
-	minidvodbtool.h
+	minidvodbtool.h \
+	laptool.h
 
 lib_LTLIBRARIES = libpxtools.la
@@ -290,4 +292,10 @@
     minidvodbtoolConfig.c
 
+laptool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
+laptool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+laptool_SOURCES = \
+    laptool.c \
+    laptoolConfig.c
+
 clean-local:
 	-rm -f TAGS
Index: branches/eam_branches/ipp-20110404/ippTools/src/addtool.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/addtool.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/addtool.c	(revision 31439)
@@ -119,9 +119,26 @@
     pxcamGetSearchArgs (config, where);
     PXOPT_COPY_S64(config->args, where,  "-cam_id",    "camRun.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where,  "-stack_id",    "stackRun.stack_id", "==");
+ PXOPT_COPY_S64(config->args, where,  "-sky_id",    "staticskyRun.sky_id", "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
+    if (strcmp(stage, "cam")== 0) {
+
     pxAddLabelSearchArgs (config, where, "-label",     "camRun.label", "=="); // define using camRun label
     pxAddLabelSearchArgs (config, where, "-data_group","camRun.data_group", "=="); // define using camRun label
     PXOPT_COPY_STR(config->args, where,  "-reduction", "camRun.reduction", "==");
-
-
+    }
+    if (strcmp(stage, "stack")== 0) {
+
+    pxAddLabelSearchArgs (config, where, "-label",     "stackRun.label", "=="); // define using camRun label
+    pxAddLabelSearchArgs (config, where, "-data_group","stackRun.data_group", "=="); // define using camRun label
+    PXOPT_COPY_STR(config->args, where,  "-reduction", "stackRun.reduction", "==");
+    }
+    if (strcmp(stage, "staticsky")== 0) {
+
+    pxAddLabelSearchArgs (config, where, "-label",     "staticskyRun.label", "=="); // define using camRun label
+    pxAddLabelSearchArgs (config, where, "-data_group","staticskyRun.data_group", "=="); // define using camRun label
+    PXOPT_COPY_STR(config->args, where,  "-reduction", "staticskyyRun.reduction", "==");
+    }
+    
     if (!psListLength(where->list)) {
         psFree(where);
@@ -129,5 +146,5 @@
         return false;
     }
-
+    // PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     PXOPT_LOOKUP_STR(workdir,     config->args, "-set_workdir", false, false);
     PXOPT_LOOKUP_STR(dvodb,       config->args, "-set_dvodb", false, false);
@@ -148,6 +165,8 @@
     psString dvodb_string = NULL;
     psString bare_query = NULL;
+
+    if (strcmp(stage,"cam") == 0 ) {
     if (dvodb) {
-      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_cam_id_dvo.sql\n", dvodb);
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_cam_id_dvo.sql\n%s\n", dvodb,stage);
         // find the cam_id of all the exposures that we want to queue up.
         bare_query = pxDataGet("addtool_find_cam_id_dvo.sql");
@@ -155,5 +174,5 @@
 	psStringAppend(&dvodb_string, "addRun.dvodb = '%s'", dvodb);
     } else {
-        psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_find_cam_id.sql\n");
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_find_cam_id.sql\n%s\n",stage);
         // find the cam_id of all the exposures that we want to queue up.
         bare_query = pxDataGet("addtool_find_cam_id.sql");
@@ -161,4 +180,38 @@
         psStringAppend(&dvodb_string, "(camRun.dvodb IS NOT NULL AND previous_dvodb = camRun.dvodb)");
     }
+    }
+    if (strcmp(stage,"stack") == 0) {
+    if (dvodb ) {
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_stack_id_dvo.sql\n%s\n", dvodb,stage);
+        // find the cam_id of all the exposures that we want to queue up.
+        bare_query = pxDataGet("addtool_find_stack_id_dvo.sql");
+	// user supplied dvodb
+	psStringAppend(&dvodb_string, "addRun.dvodb = '%s'", dvodb);
+    } else {
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_find_stack_id.sql\n%s\n",stage);
+        // find the cam_id of all the exposures that we want to queue up.
+        bare_query = pxDataGet("addtool_find_stack_id.sql");
+        // inherit dvodb from camRun, avoid matching NULL
+        psStringAppend(&dvodb_string, "(stackRun.dvodb IS NOT NULL AND previous_dvodb = stackRun.dvodb)");
+    }
+    }
+    if (strcmp(stage,"staticsky") == 0) {
+    if (dvodb ) {
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_sky_id_dvo.sql\n%s\n", dvodb,stage);
+        // find the cam_id of all the exposures that we want to queue up.
+        bare_query = pxDataGet("addtool_find_sky_id_dvo.sql");
+	// user supplied dvodb
+	psStringAppend(&dvodb_string, "addRun.dvodb = '%s'", dvodb);
+    } else {
+      psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_find_sky_id.sql\n%s\n",stage);
+        // find the cam_id of all the exposures that we want to queue up.
+        bare_query = pxDataGet("addtool_find_sky_id.sql");
+        // inherit dvodb from camRun, avoid matching NULL
+        psStringAppend(&dvodb_string, "(staticskyRun.dvodb IS NOT NULL AND previous_dvodb = staticskyRun.dvodb)");
+    }
+    }
+
+
+
     if (!bare_query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
@@ -184,9 +237,17 @@
 
     if (destreaked) {
+      if (strcmp(stage,"cam") == 0) {
         psStringAppend(&query, " AND (camRun.magicked > 0)");
-    }
+      }
+      if (strcmp(stage,"stack") == 0) {
+	psStringAppend(&query, " AND (stackRun.magicked > 0)");
+      }
+      // staticSky has no magicked column.
+    }
+
+    psTrace("addtool.c", PS_LOG_INFO,"query: \n\n%s\n\n",query);
 
     if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
+      psError(PS_ERR_UNKNOWN, false, "database error, \n%s\n", query);
         psFree(query);
         return false;
@@ -217,8 +278,10 @@
 
     // loop over our list of camRun rows to check the supplied and selected dvodb and workdir values:
+    if (strcmp(stage,"cam") == 0) {
     for (long i = 0; i < psArrayLength(output); i++) {
         psMetadata *md = output->data[i];
 
-        camRunRow *row = camRunObjectFromMetadata(md);
+	camRunRow *row = camRunObjectFromMetadata(md);
+	
         if (!row) {
             psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
@@ -240,4 +303,57 @@
         psFree(row);
     }
+    }
+    if (strcmp(stage,"stack") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+	stackRunRow *row = stackRunObjectFromMetadata(md);
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
+            psFree(output);
+            return false;
+        }
+
+        if (!dvodb && !row->dvodb) {
+            psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined dvodb: label: %s, stack_id %" PRId64, row->label, row->stack_id);
+            psFree(output);
+            return false;
+        }
+        if (!workdir && !row->workdir) {
+            psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined workdir: label: %s, stack_id %" PRId64, row->label, row->stack_id);
+            psFree(output);
+            return false;
+        }
+
+        psFree(row);
+    }
+    }
+    if (strcmp(stage,"staticsky") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+	staticskyRunRow *row = staticskyRunObjectFromMetadata(md);
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
+            psFree(output);
+            return false;
+        }
+
+        if (!dvodb) {  //there's no staticsky.dvodb
+            psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined dvodb: label: %s, sky_id %" PRId64, row->label, row->sky_id);
+            psFree(output);
+            return false;
+        }
+        if (!workdir && !row->workdir) {
+            psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined workdir: label: %s, sky_id %" PRId64, row->label, row->sky_id);
+            psFree(output);
+            return false;
+        }
+
+        psFree(row);
+    }
+    }
 
     // start a transaction so we don't end up with an exp without any associted
@@ -255,8 +371,12 @@
 
     // loop over our list of camRun rows
+    if (strcmp(stage,"cam") == 0) {
     for (long i = 0; i < psArrayLength(output); i++) {
         psMetadata *md = output->data[i];
-
-        camRunRow *row = camRunObjectFromMetadata(md);
+	psS64 stage_id =0; 
+	
+		  camRunRow *row = camRunObjectFromMetadata(md);
+	  stage_id = row->cam_id;
+	
         if (!row) {
             psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
@@ -267,5 +387,6 @@
         // queue the exp
         if (!pxaddQueueByCamID(config,
-                               row->cam_id,
+			       stage,
+                               stage_id,
                                workdir     ? workdir   : row->workdir,
                                reduction   ? reduction : row->reduction,
@@ -283,5 +404,5 @@
             }
             psError(PS_ERR_UNKNOWN, false,
-                    "failed to trying to queue chip_id: %" PRId64, row->cam_id);
+                    "failed to trying to queue stage %s %" PRId64,stage, stage_id);
             psFree(row);
             psFree(output);
@@ -290,4 +411,88 @@
         psFree(row);
     }
+      }
+    if (strcmp(stage,"stack") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+	psS64 stage_id =0; 
+	
+		  stackRunRow *row = stackRunObjectFromMetadata(md);
+	  stage_id = row->stack_id;
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        if (!pxaddQueueByCamID(config,
+			       stage,
+                               stage_id,
+                               workdir     ? workdir   : row->workdir,
+                               reduction   ? reduction : row->reduction,
+                               label       ? label     : row->label,
+                               data_group  ? data_group : (row->data_group ? row->data_group :  (label ? label : row->label)),
+                               dvodb       ? dvodb     : row->dvodb,
+                               note        ? note      : NULL,
+                               image_only,
+                               minidvodb,
+                               minidvodb_group,
+                               minidvodb_name
+        )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error sfg");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue stage %s %" PRId64,stage, stage_id);
+            psFree(row);
+            psFree(output);
+            return false;
+        }
+        psFree(row);
+    }
+      }
+    if (strcmp(stage,"staticsky") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+	psS64 stage_id =0; 
+	
+	staticskyRunRow *row = staticskyRunObjectFromMetadata(md);
+	stage_id = row->sky_id;
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into camRun");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        if (!pxaddQueueByCamID(config,
+			       stage,
+                               stage_id,
+                               workdir     ? workdir   : row->workdir,
+                               reduction   ? reduction : row->reduction,
+                               label       ? label     : row->label,
+                               data_group  ? data_group : (row->data_group ? row->data_group :  (label ? label : row->label)),
+                               dvodb       ? dvodb     : NULL,
+                               note        ? note      : NULL,
+                               image_only,
+                               minidvodb,
+                               minidvodb_group,
+                               minidvodb_name
+        )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error sfg");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue stage %s %" PRId64,stage, stage_id);
+            psFree(row);
+            psFree(output);
+            return false;
+        }
+        psFree(row);
+    }
+      }
+
     psFree(output);
 
@@ -308,4 +513,8 @@
     PXOPT_COPY_S64(config->args, where, "-add_id",    "addRun.add_id", "==");
     PXOPT_COPY_S64(config->args, where, "-cam_id",    "camRun.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-stack_id",    "stackRun.stack_id", "==");
+   PXOPT_COPY_S64(config->args, where, "-sky_id",    "staticskyRun.sky_id", "==");
+    
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where); // most search arguments based on camera
     PXOPT_COPY_STR(config->args, where, "-label",     "addRun.label", "==");
@@ -319,6 +528,14 @@
         return false;
     }
-
-    psString query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)");
+    psString query = NULL;
+    if (strcmp(stage, "cam")==0) {
+    query = psStringCopy("UPDATE addRun JOIN camRun on cam_id = stage_id JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)");
+    }
+    if (strcmp(stage, "stack")==0) {
+    query = psStringCopy("UPDATE addRun JOIN stackRun on stack_id = stage_id");
+    }
+    if (strcmp(stage, "staticsky")==0) {
+    query = psStringCopy("UPDATE addRun JOIN staticskyRun on sky_id = stage_id");
+    }
 
     // pxUpdateRun gets parameters from config->args and runs the update query
@@ -340,4 +557,7 @@
     PXOPT_COPY_S64(config->args, where, "-add_id",    "addRun.add_id", "==");
     PXOPT_COPY_S64(config->args, where, "-cam_id",    "camRun.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-stack_id",    "stackRun.stack_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-sky_id",    "staticskyRun.sky_id", "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where);
     pxAddLabelSearchArgs (config, where, "-label", "addRun.label", "==");
@@ -345,6 +565,18 @@
     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
-
-    psString query = pxDataGet("addtool_find_pendingexp.sql");
+    
+    psString query = NULL;
+    
+    if (strcmp(stage, "cam")==0) { 
+    query = pxDataGet("addtool_find_pendingexp_cam.sql");
+    }
+    if (strcmp(stage, "stack")==0) { 
+    query = pxDataGet("addtool_find_pendingexp_stack.sql");
+    }
+    if (strcmp(stage, "staticsky")==0) { 
+    query = pxDataGet("addtool_find_pendingexp_staticsky.sql");
+    }
+
+
     if (!query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -359,4 +591,12 @@
     }
     psFree(where);
+    if (strcmp(stage, "stack") == 0) {
+      //this group by is needed to join against all the warps (to get camera)
+      psStringAppend(&query, " GROUP BY %s", "stack_id");
+    }
+    if (strcmp(stage, "staticsky") == 0) {
+      //this group by is needed to join against all the warps (to get camera)
+      psStringAppend(&query, " GROUP BY %s", "sky_id");
+    }
 
     // treat limit == 0 as "no limit"
@@ -522,5 +762,6 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-add_id",    "addRun.add_id",    "==");
-    PXOPT_COPY_S64(config->args, where, "-cam_id",    "camRun.cam_id",    "==");
+    PXOPT_COPY_S64(config->args, where, "-stage_id",    "addRun.stage_id",    "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where);
     pxAddLabelSearchArgs (config, where, "-label",    "addRun.label",     "==");
@@ -537,6 +778,16 @@
         return false;
     }
-
-    psString query = pxDataGet("addtool_find_processedexp.sql");
+    psString query = NULL;
+
+    if (strcmp (stage,"cam") == 0) {
+    query = pxDataGet("addtool_find_processedexp_cam.sql");
+    }
+    if (strcmp (stage,"stack") == 0) {
+    query = pxDataGet("addtool_find_processedexp_stack.sql");
+    }
+    if (strcmp (stage,"staticsky") == 0) {
+    query = pxDataGet("addtool_find_processedexp_staticsky.sql");
+    }
+   
     if (!query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -567,4 +818,6 @@
         psStringAppend(&query, " %s", " WHERE addProcessedExp.fault = 0");
     }
+    psStringAppend(&query, " AND stage = '%s'", stage);
+
     psFree(where);
 
@@ -616,5 +869,6 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-add_id",    "addRun.add_id",         "==");
-    PXOPT_COPY_S64(config->args, where, "-cam_id",    "camRun.cam_id",         "==");
+    PXOPT_COPY_S64(config->args, where, "-stage_id",    "addRun.stage_id",         "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where);
     pxAddLabelSearchArgs (config, where, "-label",    "addRun.label",     "==");
@@ -634,8 +888,18 @@
 
     {
-        psString query = pxDataGet("addtool_revertprocessedexp.sql");
-        if (!query) {
+      psString query = NULL;
+      if (strcmp(stage, "cam") == 0) {
+         query = pxDataGet("addtool_revertprocessedexp_cam.sql");
+	}
+	
+    if (strcmp(stage, "stack") == 0) {
+	 query = pxDataGet("addtool_revertprocessedexp_stack.sql");
+      }
+     if (strcmp(stage, "staticsky") == 0) {
+	 query = pxDataGet("addtool_revertprocessedexp_staticsky.sql");
+      }
+      if (!query) {
             // rollback
-            if (!psDBRollback(config->dbh)) {
+	if (!psDBRollback(config->dbh)) {
                 psError(PS_ERR_UNKNOWN, false, "database error");
             }
@@ -681,5 +945,6 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-add_id",   "add_id",   "==");
-    PXOPT_COPY_S64(config->args, where, "-cam_id",  "cam_id",  "==");
+    PXOPT_COPY_S64(config->args, where, "-stage_id",  "stage_id",  "==");
+    PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     PXOPT_LOOKUP_S16(fault, config->args, "-fault", true, false);
 
Index: branches/eam_branches/ipp-20110404/ippTools/src/addtoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/addtoolConfig.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/addtoolConfig.c	(revision 31439)
@@ -49,5 +49,8 @@
     // -definebyquery
     psMetadata *definebyqueryArgs = psMetadataAlloc();
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-stage",             0, "set the stage (required)", NULL);
     psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-cam_id",             0, "search by cam_id", 0);
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-stack_id",             0, "search by stack_id", 0);
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-sky_id",             0, "search by sky_id", 0);
     pxcamSetSearchArgs(definebyqueryArgs);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by camRun label", NULL);
@@ -72,6 +75,9 @@
     // -updaterun
     psMetadata *updaterunArgs = psMetadataAlloc();
+    psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-stage",             0, "set the stage (required)", NULL);
     psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-add_id",                 0, "search by add_id", 0);
     psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-cam_id",                 0, "search by cam_id", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-stack_id",                 0, "search by stack_id", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-sky_id",                 0, "search by sky_id", 0);
     pxcamSetSearchArgs(updaterunArgs);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label",                  0, "search by addRun label", NULL);
@@ -89,6 +95,9 @@
     // -pendingexp
     psMetadata *pendingexpArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingexpArgs, PS_LIST_TAIL, "-stage",             0, "set the stage (required)", NULL);
     psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-add_id",            0, "search by add_id", 0);
     psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-cam_id",            0, "search by cam_id", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-stack_id",                 0, "search by stack_id", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-sky_id",                 0, "search by sky_id", 0);
     pxcamSetSearchArgs(pendingexpArgs);
     psMetadataAddStr(pendingexpArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by addRun label", NULL);
@@ -109,5 +118,6 @@
     psMetadata *processedexpArgs = psMetadataAlloc();
     psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-add_id",   0,            "search by add_id", 0);
-    psMetadataAddS64(processedexpArgs, PS_LIST_TAIL, "-cam_id",   0,            "search by cam_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);
     pxcamSetSearchArgs(processedexpArgs);
     psMetadataAddStr(processedexpArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by addRun label", NULL);
@@ -122,5 +132,6 @@
     psMetadata *revertprocessedexpArgs = psMetadataAlloc();
     psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-add_id",   0,            "search by add_id", 0);
-    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-cam_id",   0,            "search by cam_id", 0);
+    psMetadataAddS64(revertprocessedexpArgs, PS_LIST_TAIL, "-stage_id",   0,            "search by stage_id", 0);
+    psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-stage",             0, "set the stage", NULL);
     pxcamSetSearchArgs(revertprocessedexpArgs);
     psMetadataAddStr(revertprocessedexpArgs, PS_LIST_TAIL, "-label",    PS_META_DUPLICATE_OK, "search by addRun label", NULL);
@@ -132,5 +143,6 @@
     psMetadata *updateprocessedexpArgs = psMetadataAlloc();
     psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-add_id", 0,            "search by addtool ID", 0);
-    psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-cam_id",  0,            "search by camtool ID", 0);
+    psMetadataAddS64(updateprocessedexpArgs, PS_LIST_TAIL, "-stage_id",  0,            "search by stage_id", 0);
+    psMetadataAddStr(updateprocessedexpArgs, PS_LIST_TAIL, "-stage",             0, "set the stage", NULL);
     psMetadataAddS16(updateprocessedexpArgs, PS_LIST_TAIL, "-fault",  0,            "set fault code", 0);
 
Index: branches/eam_branches/ipp-20110404/ippTools/src/dettool.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/dettool.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/dettool.c	(revision 31439)
@@ -1351,4 +1351,10 @@
     }
 
+    PXOPT_LOOKUP_STR(det_type, config->args, "-set_det_type", false, false);
+    if (det_type) {
+      updating = true;
+      PXOPT_COPY_STR(config->args,     values,       "-set_det_type", "det_type", "==");
+    }
+
 
     // either -rerun or -state must be specified
Index: branches/eam_branches/ipp-20110404/ippTools/src/dettoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/dettoolConfig.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/dettoolConfig.c	(revision 31439)
@@ -103,5 +103,6 @@
     psMetadataAddF64(definebyqueryArgs, PS_LIST_TAIL, "-sun_angle_max",  0,            "define max solar angle", NAN);
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-registered",  0,            "time detrend run was registered", now);
-    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period (required)", NULL);
+    // i'm requiring time_begin because otherwise if not specified detselect will pick the wrong detrend for old date ranges (it will pick the most recent one with NULL)
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
@@ -848,4 +849,5 @@
     psMetadataAddBool(updatedetrunArgs, PS_LIST_TAIL, "-again",  0,            "start a new iteration of this detrend run", false);
     psMetadataAddStr(updatedetrunArgs, PS_LIST_TAIL, "-state",  0,            "set the state of this detrend run", false);
+    psMetadataAddStr(updatedetrunArgs, PS_LIST_TAIL, "-set_det_type", 0,          "set the det_type", NULL);
     psMetadataAddTime(updatedetrunArgs, PS_LIST_TAIL, "-set_time_begin",  0,            "start of period to apply detrend too", NULL);
     psMetadataAddTime(updatedetrunArgs, PS_LIST_TAIL, "-set_time_end",  0,            "end of period to apply detrend too", NULL);
Index: branches/eam_branches/ipp-20110404/ippTools/src/difftool.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/difftool.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/difftool.c	(revision 31439)
@@ -1625,4 +1625,5 @@
     PXOPT_COPY_S64(config->args, selectWhere, "-exp_id", "inputRawExp.exp_id", "==");
     PXOPT_COPY_S64(config->args, selectWhere, "-template_exp_id", "templateRawExp.exp_id", "==");
+    PXOPT_COPY_S64(config->args, selectWhere, "-template_warp_id", "templateWarpRun.warp_id", "==");
     PXOPT_COPY_STR(config->args, selectWhere, "-filter", "inputRawExp.filter", "==");
     PXOPT_COPY_STR(config->args, selectWhere, "-obs_mode", "inputRawExp.obs_mode", "==");
@@ -2967,4 +2968,6 @@
     pxAddLabelSearchArgs (config, where, "-data_group", "diffRun.data_group", "LIKE");
     pxAddLabelSearchArgs (config, where, "-dist_group", "diffRun.dist_group", "LIKE");
+
+    PXOPT_COPY_S64(config->args, where, "-template_exp_id", "rawTemplate.exp_id", "==");
     
     PXOPT_LOOKUP_BOOL(template, config->args, "-template", false);
Index: branches/eam_branches/ipp-20110404/ippTools/src/difftoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/difftoolConfig.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/difftoolConfig.c	(revision 31439)
@@ -182,4 +182,5 @@
     psMetadataAddTime(listrunArgs, PS_LIST_TAIL, "-dateobs_end", 0,      "search for exposures by time (<=)", NULL);
     psMetadataAddStr(listrunArgs, PS_LIST_TAIL,  "-filter", 0,           "search for filter", NULL);
+    psMetadataAddS64(listrunArgs, PS_LIST_TAIL,  "-template_exp_id",  0, "search by exposure ID of template", 0);
     psMetadataAddStr(listrunArgs,  PS_LIST_TAIL, "-label",  PS_META_DUPLICATE_OK, "search by diffRun label (LIKE comparison)", NULL);
     psMetadataAddStr(listrunArgs,  PS_LIST_TAIL, "-data_group",  PS_META_DUPLICATE_OK, "search by diffRun data_group (LIKE comparison)", NULL);
@@ -277,4 +278,5 @@
     psMetadataAddBool(definewarpwarpArgs, PS_LIST_TAIL, "-not-bothways",  0, "only do the single-direction subtraction?", false);
     psMetadataAddS64(definewarpwarpArgs, PS_LIST_TAIL,  "-template_exp_id",  0,  "search by template exposure ID", 0);
+    psMetadataAddS64(definewarpwarpArgs, PS_LIST_TAIL,  "-template_warp_id",  0,  "search by template warp ID", 0);
     psMetadataAddStr(definewarpwarpArgs, PS_LIST_TAIL, "-filter", 0, "search by filter", NULL);
     psMetadataAddF32(definewarpwarpArgs, PS_LIST_TAIL, "-distance", 0, "limit distance between input and template (deg)", NAN);
Index: branches/eam_branches/ipp-20110404/ippTools/src/flatcorr.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/flatcorr.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/flatcorr.c	(revision 31439)
@@ -664,4 +664,5 @@
         if (!pxaddQueueByCamID(
                 config,
+		"cam",
                 row->cam_id,
                 row->workdir,
Index: branches/eam_branches/ipp-20110404/ippTools/src/laptool.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/laptool.c	(revision 31439)
+++ branches/eam_branches/ipp-20110404/ippTools/src/laptool.c	(revision 31439)
@@ -0,0 +1,816 @@
+/*
+ * laptool.c
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+#include "pxtools.h"
+#include "pxdata.h"
+#include "laptool.h"
+
+
+// Sequence level
+static bool definesequenceMode(pxConfig *config);
+static bool listsequenceMode(pxConfig *config);
+
+// Run level
+static bool definerunMode(pxConfig *config);
+static bool pendingrunMode(pxConfig *config);
+static bool updaterunMode(pxConfig *config);
+// Exposure level
+static bool pendingexpMode(pxConfig *config);
+static bool exposuresMode(pxConfig *config);
+static bool stacksMode(pxConfig *config);
+static bool updateexpMode(pxConfig *config);
+
+static bool inactiveexpMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+  case caseName: \
+  if (!func(config)) { \
+  goto FAIL; \
+  } \
+  break;
+
+int main(int argc, char **argv)
+{
+  psLibInit(NULL);
+
+  pxConfig *config = laptoolConfig(NULL, argc, argv);
+  if (!config) {
+    psError(PXTOOLS_ERR_CONFIG, false, "failed to configure");
+    goto FAIL;
+  }
+
+  switch (config->mode) {
+    MODECASE(LAPTOOL_MODE_DEFINESEQUENCE, definesequenceMode);
+    MODECASE(LAPTOOL_MODE_LISTSEQUENCE,   listsequenceMode);
+    
+    MODECASE(LAPTOOL_MODE_DEFINERUN,     definerunMode);
+    MODECASE(LAPTOOL_MODE_PENDINGRUN,    pendingrunMode);
+    MODECASE(LAPTOOL_MODE_UPDATERUN,     updaterunMode);
+
+    MODECASE(LAPTOOL_MODE_PENDINGEXP,    pendingexpMode);
+    MODECASE(LAPTOOL_MODE_EXPOSURES,     exposuresMode);
+    MODECASE(LAPTOOL_MODE_STACKS,        stacksMode);
+    MODECASE(LAPTOOL_MODE_UPDATEEXP,     updateexpMode);
+
+    MODECASE(LAPTOOL_MODE_INACTIVEEXP,   inactiveexpMode);
+  default:
+    psAbort("invalid option (this should not happen)");
+  }
+  psTrace("laptool", 9, "Attempting to free config\n");
+  psFree(config);
+  pmConfigDone();
+  psLibFinalize();
+  exit(EXIT_SUCCESS);
+
+ FAIL:
+  psErrorStackPrint(stderr, "\n");
+  int exit_status = pxerrorGetExitStatus();
+
+  psFree(config);
+  pmConfigDone();
+  psLibFinalize();
+
+  exit(exit_status);
+}
+
+// Sequence level
+
+static bool definesequenceMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_STR(name,        config->args, "-name",        true, false);
+  PXOPT_LOOKUP_STR(description, config->args, "-description", true, false);
+  PXOPT_LOOKUP_BOOL(simple,     config->args, "-simple",     false);
+
+  lapSequenceRow *run = lapSequenceRowAlloc(0, // seq_id
+					    name,
+					    description);
+  if (!run) {
+    psError(PS_ERR_UNKNOWN, false, "failed to alloc lapSequence object");
+    return(true);
+  }
+
+  if (!psDBTransaction(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  if (!lapSequenceInsertObject(config->dbh, run)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(run);
+    return(true);
+  }
+
+  // point of no return
+  if (!psDBCommit(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  if (!lapSequencePrintObject(stdout, run, !simple)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to print object");
+    psFree(run);
+    return false;
+  }
+
+  psFree(run);
+
+  return true;  
+}
+
+static bool listsequenceMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",  false, false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-seq_id", "seq_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-seq_name",   "name",   "LIKE");
+
+  psString query = pxDataGet("laptool_listsequence.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return false;
+  }
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " WHERE %s", whereClause);
+    psFree(whereClause);
+  }
+
+  if (limit) {
+    psString limitString = psDBGenerateLimitSQL(limit);
+    psStringAppend(&query, " %s", limitString);
+    psFree(limitString);
+  }
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return false;
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+    }
+
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  if (psArrayLength(output)) {
+    if (!ippdbPrintMetadatas(stdout, output, "lapSequence", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+
+  psFree(output);
+
+  return true;
+}
+  
+
+// Run level
+static bool definerunMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_S64(seq_id,          config->args, "-seq_id",          true, false);
+  PXOPT_LOOKUP_STR(projection_cell, config->args, "-projection_cell", true, false);
+  PXOPT_LOOKUP_STR(tess_id,         config->args, "-tess_id",         true, false);
+  PXOPT_LOOKUP_F64(ra,              config->args, "-ra",              true, false);
+  PXOPT_LOOKUP_F64(decl,            config->args, "-decl",            true, false);
+  PXOPT_LOOKUP_F32(radius,          config->args, "-radius",          true, false);
+  PXOPT_LOOKUP_STR(filter,          config->args, "-filter",          true, false);
+  PXOPT_LOOKUP_STR(label,           config->args, "-label",           false, false);
+  PXOPT_LOOKUP_STR(dist_group,      config->args, "-dist_group",      false, false);
+  PXOPT_LOOKUP_BOOL(all_obsmode,    config->args, "-all_obsmode",     false);
+  PXOPT_LOOKUP_BOOL(simple,         config->args, "-simple",          false);
+
+  lapRunRow *run = lapRunRowAlloc(0, // lap_id
+				  seq_id,
+				  tess_id,
+				  projection_cell,
+				  filter,
+				  "new", // state
+				  label,
+				  dist_group,
+				  NULL, // registered
+				  0,    // fault
+				  INT64_MAX,    // quick_sass_id
+				  INT64_MAX     // final_sass_id
+				  );
+  if (!run) {
+    psError(PS_ERR_UNKNOWN, false, "failed to alloc lapRun object");
+    return(true);
+  }
+
+  if (!psDBTransaction(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  if (!lapRunInsertObject(config->dbh, run)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(run);
+    return(true);
+  }
+
+
+  if (!lapRunPrintObject(stdout, run, !simple)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "failed to print object");
+    psFree(run);
+    return false;
+  }
+
+  psS64 lap_id = psDBLastInsertID(config->dbh);
+
+  // Find the input exposures
+  psString query = pxDataGet("laptool_definerun.sql");
+  if (!query) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return(false);
+  }
+
+  // Add constraints to the exposure search:
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_STR(config->args, where, "-filter", "rawExp.filter", "==");
+
+  // This seems unnecessarily clunky.
+  if (!all_obsmode) {
+    //    fprintf(stderr, "Not doing all obsmodes!\n");
+    if (!psMetadataLookupStr(NULL,config->args,"-obsmode")) {
+      //      fprintf(stderr, "Not doing all obsmodes and none specified!\n");
+      psMetadataAddStr(where,PS_LIST_TAIL,"rawExp.obs_mode",0,"==","3PI");
+    }
+    pxAddLabelSearchArgs (config, where, "-obsmode", "rawExp.obsmode", "==");
+  }
+  
+  psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+  if (!pxspaceAddWhere(config, &whereClause, "rawExp")) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psError(psErrorCodeLast(), false, "pxSpaceAddWhere failed");
+    return(false);
+  }
+
+  if (whereClause) {
+    psStringSubstitute(&query,whereClause,"@WHERE@");
+  }
+  psFree(where);
+
+  // Fetch exposures
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return(false);
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return(false);
+  }
+  if (!psArrayLength(output)) {
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return(true);
+  }
+
+  // Insert the exposure data
+  for (long i = 0; i < output->n; i++) {
+    psMetadata *row = output->data[i]; // Row from select
+    // Add default values from this run:
+    psMetadataAddS64(row, PS_LIST_TAIL, "lap_id", 0, "", lap_id);
+    psMetadataAddS64(row, PS_LIST_TAIL, "pair_id", 0, "", INT64_MAX);
+    psMetadataAddStr(row, PS_LIST_TAIL, "data_state", 0, "", "new");
+    lapExpRow *lapExp = lapExpObjectFromMetadata(row);
+    lapExp->lap_id = lap_id;
+
+    if (!lapExpInsertObject(config->dbh,lapExp)) {
+      if (!lapExpPrintObject(stdout, lapExp, !simple)) {
+	if (!psDBRollback(config->dbh)) {
+	  psError(PS_ERR_UNKNOWN, false, "database error");
+	}
+	psError(PS_ERR_UNKNOWN, false, "failed to print object");
+	psFree(run);
+	return false;
+      }
+      
+      if (!psDBRollback(config->dbh)) {
+	psError(PS_ERR_UNKNOWN, false, "database error");
+      }
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(output);
+      psFree(lapExp);
+      return(false);
+    }
+  }
+
+  // point of no return
+  if (!psDBCommit(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  
+  psFree(output);
+  return(true);  
+}
+
+static bool pendingrunMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-seq_id", "seq_id", "==");
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-projection_cell", "projection_cell", "==");
+  PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
+  PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+  PXOPT_COPY_STR(config->args, where, "-state", "state", "==");
+  PXOPT_COPY_STR(config->args, where, "-fault", "fault", "==");
+
+  psString query = pxDataGet("laptool_pendingrun.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return false;
+  }
+  if (psListLength(where->list)) {
+    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;
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+    }
+
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  if (psArrayLength(output)) {
+    if (!ippdbPrintMetadatas(stdout, output, "lapRun", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+
+  psFree(output);
+
+  return true;
+}
+
+static bool updaterunMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_LOOKUP_S64(lap_id, config->args, "-lap_id", true, false);
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+
+  psMetadata *values = psMetadataAlloc();
+  PXOPT_LOOKUP_STR(state, config->args, "-set_state", false, false);
+  PXOPT_COPY_STR(config->args, values, "-set_state", "state", "==");
+  PXOPT_COPY_S16(config->args, values, "-fault",     "fault", "==");
+  PXOPT_COPY_STR(config->args, values, "-set_label", "label", "==");
+  PXOPT_COPY_S64(config->args, values, "-set_quick_sass_id", "quick_sass_id", "==");
+  PXOPT_COPY_S64(config->args, values, "-set_final_sass_id", "final_sass_id", "==");
+
+  long rows = psDBUpdateRows(config->dbh, "lapRun", where, values);
+  psFree(values);
+  
+  if (rows) {
+    // We're done with these exposures now, so mark them as inactive.
+    if (state) {
+      if ((strcmp(state,"drop") == 0)||
+	  (strcmp(state,"full") == 0)) {
+	values = psMetadataAlloc();
+	psMetadataAddBool(values, PS_LIST_TAIL, "active", 0, "", false);
+	long exps = psDBUpdateRows(config->dbh, "lapExp", where, values);
+	
+	if (exps) {
+	  return(true);
+	}
+	else {
+	  return(true); // We shouldn't really fail if we didn't change anything. Maybe there's nothing to change.
+	}
+      }
+    }
+  }
+
+  return(true);
+}
+
+// Exposure level
+
+static bool pendingexpMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",  false, false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+
+  psString query = pxDataGet("laptool_pendingexp.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return false;
+  }
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, "\n AND %s", whereClause);
+    psFree(whereClause);
+  }
+  psStringAppend(&query, " ORDER BY rawExp.dateobs ");
+  
+  if (limit) {
+    psString limitString = psDBGenerateLimitSQL(limit);
+    psStringAppend(&query, "\n %s", limitString);
+    psFree(limitString);
+  }
+
+  
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return false;
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error");
+    }
+
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  if (psArrayLength(output)) {
+    if (!ippdbPrintMetadatas(stdout, output, "lapExp", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+
+  psFree(output);
+
+  return true;
+}
+
+
+static bool exposuresMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+  PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+  
+  psString query = pxDataGet("laptool_exposures.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return(false);
+  }
+  psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+  if (whereClause) {
+    psStringSubstitute(&query,whereClause,"@WHERE@");
+  }
+  
+  psString limitString = NULL;
+  if (limit) {
+    limitString = psDBGenerateLimitSQL(limit);
+    psStringPrepend(&limitString, "\n");
+  }
+
+  if (!p_psDBRunQueryF(config->dbh, query, whereClause, limitString ? limitString : "")) {
+    psError(PXTOOLS_ERR_PROG, false, "database error");
+    psFree(limitString);
+    psFree(query);
+    psFree(whereClause);
+    return(false);
+  }
+  psFree(limitString);
+  psFree(query);
+  psFree(whereClause);
+  
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return(false);
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return(true);
+  }
+  
+  if (!ippdbPrintMetadatas(stdout, output, "lapExp", !simple)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to print array");
+    psFree(output);
+    return(false);
+  }
+
+  psFree(output);
+  return(true);
+}
+
+static bool stacksMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+  PXOPT_LOOKUP_S64(lap_id, config->args, "-lap_id", true, false);
+
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lapRun.lap_id", "==");
+  
+  psString query = pxDataGet("laptool_stacks.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return(false);
+  }
+  
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringPrepend(&whereClause, "\n AND ");
+    psStringSubstitute(&query,whereClause,"@WHERE@");
+    psFree(whereClause);
+  }
+
+  if (limit) {
+    psString limitString = psDBGenerateLimitSQL(limit);
+    psStringAppend(&query, " %s", limitString);
+    psFree(limitString);
+  }
+
+
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return false;
+  }
+  psFree(query);
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psErrorCode err = psErrorCodeLast();
+    switch (err) {
+    case PS_ERR_DB_CLIENT:
+      psError(PXTOOLS_ERR_SYS, false, "database error");
+    case PS_ERR_DB_SERVER:
+      psError(PXTOOLS_ERR_PROG, false, "database error");
+    default:
+      psError(PXTOOLS_ERR_PROG, false, "unknown error %d",err);
+    }
+
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  if (psArrayLength(output)) {
+    if (!ippdbPrintMetadatas(stdout, output, "lapRunStacks", !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+  }
+
+  psFree(output);
+  return(true);
+}
+
+static bool updateexpMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_LOOKUP_S64(lap_id,  config->args, "-lap_id",  true, false);
+  PXOPT_LOOKUP_S64(exp_id,  config->args, "-exp_id",  true, false);
+  PXOPT_LOOKUP_S64(chip_id, config->args, "-chip_id", false, false);
+
+  PXOPT_LOOKUP_S64(set_chip_id, config->args, "-set_chip_id", false, false);
+  PXOPT_LOOKUP_S64(set_pair_id, config->args, "-set_pair_id", false, false);
+  PXOPT_LOOKUP_STR(set_data_state, config->args, "-set_data_state", false, false);
+  PXOPT_LOOKUP_BOOL(private,    config->args, "-private",     false);
+  PXOPT_LOOKUP_BOOL(public,     config->args, "-public",      false);
+  PXOPT_LOOKUP_BOOL(pairwise,   config->args, "-pairwise",    false);
+  PXOPT_LOOKUP_BOOL(nopairwise, config->args, "-nopairwise",  false);
+  PXOPT_LOOKUP_BOOL(active,     config->args, "-active",      false);
+  PXOPT_LOOKUP_BOOL(inactive,   config->args, "-inactive",    false);
+
+
+  if (private && public) {
+    psError(PS_ERR_UNKNOWN, false, "only one of -private and -public may be selected");
+  }
+  if (active && inactive) {
+    psError(PS_ERR_UNKNOWN, false, "only one of -active and -inactive may be selected");
+  }
+  if (pairwise && nopairwise) {
+    psError(PS_ERR_UNKNOWN, false, "only one of -pairwise and -nopairwise may be selected");
+  }
+
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+  PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+  PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+
+
+  psMetadata *values = psMetadataAlloc();
+  if (set_chip_id) {
+    PXOPT_COPY_S64(config->args, values, "-set_chip_id", "chip_id", "==");
+  }
+  if (set_pair_id) {
+    PXOPT_COPY_S64(config->args, values, "-set_pair_id", "pair_id", "==");
+  }
+  if (private) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "private", 0, "==", true);
+  }
+  else if (public) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "private", 0, "==", false);
+  }
+  if (active) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "active", 0, "==", true);
+  }
+  else if (inactive) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "active", 0, "==", false);
+  }
+  if (pairwise) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "pairwise", 0, "==", true);
+  }
+  else if (nopairwise) {
+    psMetadataAddBool(values, PS_LIST_TAIL, "pairwise", 0, "==", false);
+  }
+  if (set_data_state) {
+    PXOPT_COPY_STR(config->args, values, "-set_data_state", "data_state", "==");
+  }
+  long rows = psDBUpdateRows(config->dbh,"lapExp",where,values);
+  if (rows) {
+    return(true);
+  }
+/*   else { */
+/*     return(false); */
+/*   }   */
+  return(true);
+}
+
+
+    
+
+static bool inactiveexpMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, false);
+  PXOPT_LOOKUP_S64(lap_id,          config->args, "-lap_id",          true, false);
+  
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-lap_id", "lap_id", "==");
+  
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+  
+  psString query = pxDataGet("laptool_inactiveexp.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+    return(false);
+  }
+  psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+  if (whereClause) {
+    psStringSubstitute(&query,whereClause,"@WHERE@");
+  }
+  
+  psString limitString = NULL;
+  if (limit) {
+    limitString = psDBGenerateLimitSQL(limit);
+    psStringPrepend(&limitString, "\n");
+  }
+
+  if (!p_psDBRunQueryF(config->dbh, query, whereClause, limitString ? limitString : "")) {
+    psError(PXTOOLS_ERR_PROG, false, "database error");
+    psFree(limitString);
+    psFree(query);
+    psFree(whereClause);
+    return(false);
+  }
+  psFree(limitString);
+  psFree(query);
+  psFree(whereClause);
+  
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return(false);
+  }
+  if (!psArrayLength(output)) {
+    psTrace("laptool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return(true);
+  }
+  
+  if (!ippdbPrintMetadatas(stdout, output, "lapExp", !simple)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to print array");
+    psFree(output);
+    return(false);
+  }
+
+  psFree(output);
+  return(true);
+}
+
Index: branches/eam_branches/ipp-20110404/ippTools/src/laptool.h
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/laptool.h	(revision 31439)
+++ branches/eam_branches/ipp-20110404/ippTools/src/laptool.h	(revision 31439)
@@ -0,0 +1,28 @@
+/*
+ * laptool.h
+ */
+
+#ifndef LAPTOOL_H
+#define LAPTOOL_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+  LAPTOOL_MODE_NONE           = 0x0,
+  LAPTOOL_MODE_DEFINESEQUENCE,
+  LAPTOOL_MODE_LISTSEQUENCE,
+  LAPTOOL_MODE_DEFINERUN,
+  LAPTOOL_MODE_PENDINGRUN,
+  LAPTOOL_MODE_UPDATERUN,
+  LAPTOOL_MODE_PENDINGEXP,
+  LAPTOOL_MODE_EXPOSURES,
+  LAPTOOL_MODE_STACKS,
+  LAPTOOL_MODE_UPDATEEXP,
+  LAPTOOL_MODE_INACTIVEEXP
+} laptoolMode;
+
+pxConfig *laptoolConfig(pxConfig *config, int argc, char **argv);
+
+#endif // LAPTOOL_H
+
+
Index: branches/eam_branches/ipp-20110404/ippTools/src/laptoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/laptoolConfig.c	(revision 31439)
+++ branches/eam_branches/ipp-20110404/ippTools/src/laptoolConfig.c	(revision 31439)
@@ -0,0 +1,165 @@
+/*
+ * laptoolConfig.c
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <stdint.h>
+
+#include <psmodules.h>
+#include "pxtools.h"
+#include "laptool.h"
+
+#define ADD_OPT(TYPE,TARG,NAME,COMMENT,DEFAULT) psMetadataAdd##TYPE(TARG, PS_LIST_TAIL, NAME, 0, COMMENT, DEFAULT)
+
+pxConfig *laptoolConfig(pxConfig *config, int argc, char **argv)
+{
+  if (!config) {
+    config = pxConfigAlloc();
+  }
+
+  pmConfigReadParamsSet(false);
+
+  // setup site config
+  config->modules = pmConfigRead(&argc, argv, NULL);
+  if (!config->modules) {
+    psError(psErrorCodeLast(), false, "Can't find site configuration");
+    psFree(config);
+    return NULL;
+  }
+
+  // -definesequence
+  psMetadata *definesequenceArgs = psMetadataAlloc();
+  ADD_OPT(Str, definesequenceArgs, "-name",                   "short name for this LAP sequence (required)", NULL);
+  ADD_OPT(Str, definesequenceArgs, "-description",            "define the description for this LAP sequence (required)", NULL);
+  ADD_OPT(Bool,definesequenceArgs, "-simple",                 "use the simple output format", false);
+  
+  // -listsequence
+  psMetadata *listsequenceArgs = psMetadataAlloc();
+  ADD_OPT(S64, listsequenceArgs, "-seq_id",                   "search by LAP sequence ID", 0);
+  ADD_OPT(Str, listsequenceArgs, "-seq_name",                 "search by LAP sequence name", 0);
+  ADD_OPT(Bool,listsequenceArgs, "-simple",                   "use the simple output format", false);
+  ADD_OPT(U64, listsequenceArgs, "-limit",                    "limit result set to N items", 0);
+
+  
+  // -definerun
+  psMetadata *definerunArgs = psMetadataAlloc();
+  ADD_OPT(S64, definerunArgs, "-seq_id",                      "define the LAP sequence for this run (required)", 0);
+  ADD_OPT(Str, definerunArgs, "-projection_cell",             "define the projection cell for this run (required)", NULL);
+  ADD_OPT(Str, definerunArgs, "-tess_id",                     "define the tessellation used (required)", NULL);
+  ADD_OPT(F64, definerunArgs, "-ra",                          "define RA center (required)", NAN);
+  ADD_OPT(F64, definerunArgs, "-decl",                        "define DEC center (required)", NAN);
+  ADD_OPT(F32, definerunArgs, "-radius",                      "define radius from center to consider (required)", NAN);
+  ADD_OPT(Str, definerunArgs, "-filter",                      "define the filter used (required)", NULL);
+  ADD_OPT(Str, definerunArgs, "-label",                       "define the label used", NULL);
+  ADD_OPT(Str, definerunArgs, "-dist_group",                  "define the distribution group for this data", NULL);
+
+  psMetadataAddStr(definerunArgs, PS_LIST_TAIL, "-obsmode", PS_META_DUPLICATE_OK, "search by obsmode", NULL);
+  ADD_OPT(Bool,definerunArgs, "-all_obsmode",                 "use all science obsmodes", false);
+  
+  ADD_OPT(Bool,definerunArgs, "-simple",                      "use the simple output format", false);
+  
+  // -pendingrun
+  psMetadata *pendingrunArgs = psMetadataAlloc();
+  ADD_OPT(S64, pendingrunArgs, "-seq_id",                     "search by LAP sequence ID", 0);
+  ADD_OPT(S64, pendingrunArgs, "-lap_id",                     "search by LAP run ID", 0);
+  ADD_OPT(Str, pendingrunArgs, "-projection_cell",            "search by projection cell", NULL);
+  ADD_OPT(Str, pendingrunArgs, "-filter",                     "search by filter", NULL);
+  ADD_OPT(Str, pendingrunArgs, "-label",                      "search by LAP run label", NULL);
+  ADD_OPT(Str, pendingrunArgs, "-state",                      "search by LAP run state", NULL);
+  ADD_OPT(Str, pendingrunArgs, "-fault",                      "search by LAP run fault", NULL);
+  ADD_OPT(Bool,pendingrunArgs, "-simple",                     "use the simple output format", false);
+
+  // -updaterun
+  psMetadata *updaterunArgs = psMetadataAlloc();
+  ADD_OPT(S64, updaterunArgs, "-lap_id",                      "search by lap run ID", 0);
+  ADD_OPT(Str, updaterunArgs, "-set_state",                   "set state", NULL);
+  ADD_OPT(S16, updaterunArgs, "-fault",                       "set fault code", INT16_MAX);
+  ADD_OPT(Str, updaterunArgs, "-set_label",                   "set label", NULL);
+  ADD_OPT(S64, updaterunArgs, "-set_quick_sass_id",           "set quick stack sass_id", 0);
+  ADD_OPT(S64, updaterunArgs, "-set_final_sass_id",           "set final stack sass_id", 0);
+  
+  
+  // -pendingexp
+  psMetadata *pendingexpArgs = psMetadataAlloc();
+  ADD_OPT(S64, pendingexpArgs, "-lap_id",                     "lap run ID", 0);
+  ADD_OPT(Str, pendingexpArgs, "-projection_cell",            "projection cell to consider", NULL);
+  ADD_OPT(U64, pendingexpArgs, "-limit",                      "limit result set to N items", 0);
+  ADD_OPT(Bool,pendingexpArgs, "-simple",                     "use the simple output format", false);
+
+  // -exposures
+  psMetadata *exposuresArgs = psMetadataAlloc();
+  ADD_OPT(S64, exposuresArgs, "-lap_id",                      "search by lap run ID", 0);
+  ADD_OPT(S64, exposuresArgs, "-exp_id",                      "search by exp_id", 0);
+  ADD_OPT(Bool,exposuresArgs, "-simple",                      "use the simple output format", false);
+  ADD_OPT(U64, exposuresArgs, "-limit",                       "limit result set to N items", 0);
+
+  // -stacks
+  psMetadata *stacksArgs = psMetadataAlloc();
+  ADD_OPT(S64, stacksArgs, "-lap_id",                         "search by lap run ID", 0);
+  ADD_OPT(Bool,stacksArgs, "-simple",                         "use the simple output format", false);
+  ADD_OPT(U64, stacksArgs, "-limit",                          "limit result set to N items", 0);
+  
+  // -updateexp
+  psMetadata *updateexpArgs = psMetadataAlloc();
+  ADD_OPT(S64, updateexpArgs, "-lap_id",                      "search by lap run ID", 0);
+  ADD_OPT(S64, updateexpArgs, "-exp_id",                      "search by exposure ID", 0);
+  ADD_OPT(S64, updateexpArgs, "-chip_id",                     "search by chip ID", 0);
+  ADD_OPT(S64, updateexpArgs, "-set_chip_id",                 "set the chip ID", 0);
+  ADD_OPT(S64, updateexpArgs, "-set_pair_id",                 "set the pair ID", 0);
+  ADD_OPT(Str, updateexpArgs, "-set_data_state",              "set the lapExp data_state", NULL);
+  ADD_OPT(Bool,updateexpArgs, "-private",                     "set this exposure as private", 0);
+  ADD_OPT(Bool,updateexpArgs, "-public",                      "set this exposure as public", 0);
+  ADD_OPT(Bool,updateexpArgs, "-pairwise",                    "set this exposure to be pairwise", 0);
+  ADD_OPT(Bool,updateexpArgs, "-nopairwise",                  "set this exposure to not be pairwise", 0);
+  ADD_OPT(Bool,updateexpArgs, "-active",                      "set this exposure to active", 0);
+  ADD_OPT(Bool,updateexpArgs, "-inactive",                    "set this exposure to active", 0);
+
+  // -inactiveexp
+  psMetadata *inactiveexpArgs = psMetadataAlloc();
+  ADD_OPT(S64, inactiveexpArgs, "-lap_id",                    "search by lap run ID", 0);
+  ADD_OPT(Bool,inactiveexpArgs, "-simple",                    "use the simple output format", false);
+  ADD_OPT(U64, inactiveexpArgs, "-limit",                     "limit result set to N items", 0);
+  
+  
+  psMetadata *argSets = psMetadataAlloc();
+  psMetadata *modes = psMetadataAlloc();
+
+  PXOPT_ADD_MODE("-definesequence",          "", LAPTOOL_MODE_DEFINESEQUENCE,   definesequenceArgs);
+  PXOPT_ADD_MODE("-listsequence",            "", LAPTOOL_MODE_LISTSEQUENCE,     listsequenceArgs);
+  PXOPT_ADD_MODE("-definerun",               "", LAPTOOL_MODE_DEFINERUN,        definerunArgs);
+  PXOPT_ADD_MODE("-pendingrun",              "", LAPTOOL_MODE_PENDINGRUN,       pendingrunArgs);
+  PXOPT_ADD_MODE("-updaterun",               "", LAPTOOL_MODE_UPDATERUN,        updaterunArgs);
+  PXOPT_ADD_MODE("-pendingexp",              "", LAPTOOL_MODE_PENDINGEXP,       pendingexpArgs);
+  PXOPT_ADD_MODE("-exposures",               "", LAPTOOL_MODE_EXPOSURES,        exposuresArgs);
+  PXOPT_ADD_MODE("-stacks",                  "", LAPTOOL_MODE_STACKS,           stacksArgs);
+  PXOPT_ADD_MODE("-updateexp",               "", LAPTOOL_MODE_UPDATEEXP,        updateexpArgs);
+  PXOPT_ADD_MODE("-inactiveexp",             "", LAPTOOL_MODE_INACTIVEEXP,      inactiveexpArgs);
+  
+  if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
+    psError(PS_ERR_UNKNOWN, true, "option parsing failed");
+    psFree(argSets);
+    psFree(modes);
+    psFree(config);
+    return NULL;
+  }
+
+  psFree(argSets);
+  psFree(modes);
+
+  // define Database handle, if used
+  config->dbh = psMemIncrRefCounter(pmConfigDB(config->modules));
+  if (!config->dbh) {
+    psError(PXTOOLS_ERR_SYS, false, "Can't configure database");
+    psFree(config);
+    return NULL;
+  }
+
+  return config;
+}
+
+
+  
Index: branches/eam_branches/ipp-20110404/ippTools/src/pxadd.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/pxadd.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/pxadd.c	(revision 31439)
@@ -37,5 +37,5 @@
     if (!pxIsValidState(state)) {
         psError(PS_ERR_UNKNOWN, false,
-                "invalid camRun state: %s", state);
+                "invalid stageRun state: %s", state);
         return false;
     }
@@ -51,5 +51,5 @@
 
 
-bool pxaddRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state)
+bool pxaddRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *stage, const char *state)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -59,10 +59,16 @@
     if (!pxIsValidState(state)) {
         psError(PS_ERR_UNKNOWN, false,
-                "invalid chipRun state: %s", state);
+                "invalid stageRun state: %s", state);
         return false;
     }
-
-    psString query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET addRun.state = '%s'");
-
+    psString query = NULL;
+    if (strcmp(stage, "cam") == 0) {
+      query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET addRun.state = '%s'");
+    } 
+    if (strcmp(stage, "stack") == 0) {
+      ///xxx this needs to be fixed
+     
+      /// psString query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET addRun.state = '%s'");
+    } 
     if (where) {
         psString whereClause = psDBGenerateWhereSQL(where, NULL);
@@ -98,9 +104,9 @@
 }
 
-bool pxaddRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label)
+bool pxaddRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *stage, const char *label)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
     // note label == NULL should be explicitly allowed
-
+    //xxx fix for stack
     psString query = psStringCopy("UPDATE addRun JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) SET addRun.label = '%s'");
 
@@ -123,5 +129,6 @@
 
 bool pxaddQueueByCamID(pxConfig *config,
-                       psS64 cam_id,
+		       char *stage,
+                       psS64 stage_id,
                        char *workdir,
                        char *reduction,
@@ -140,6 +147,16 @@
     static psString query = NULL;
     if (!query) {
+      if (strcmp( stage , "cam") == 0) {
         query = pxDataGet("addtool_queue_cam_id.sql");
         psMemSetPersistent(query, true);
+      }
+      if (strcmp(stage,"stack") == 0) {
+	query = pxDataGet("addtool_queue_stack_id.sql");
+        psMemSetPersistent(query, true);
+      }
+      if (strcmp(stage,"staticsky") == 0) {
+	query = pxDataGet("addtool_queue_sky_id.sql");
+        psMemSetPersistent(query, true);
+      }
         if (!query) {
             psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -148,11 +165,12 @@
     }
 
+    psTrace("addtool.c", PS_LOG_INFO, "pxadd query \n%s\n",query);
     // queue the exp
     // Note: cam_id is being cast here work around psS64 have a different type different
     // on 32/64
     if (!p_psDBRunQueryF(config->dbh, query,
-                         "new", // state
+			 "new", // state
                          workdir  ? workdir   : "NULL",
-                         "dirty", //workdir_state
+			  "dirty", //workdir_state
                          reduction? reduction : "NULL",
                          label    ? label     : "NULL",
@@ -164,5 +182,5 @@
 			 minidvodb_group,
 			 minidvodb_name,
-                         (long long) cam_id
+                         (long long) stage_id
     )) {
       psError(PS_ERR_UNKNOWN, false, "database error %s", query);
Index: branches/eam_branches/ipp-20110404/ippTools/src/pxadd.h
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/pxadd.h	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/pxadd.h	(revision 31439)
@@ -26,10 +26,11 @@
 
 bool pxaddRunSetState(pxConfig *config, psS64 add_id, const char *state);
-bool pxaddRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *state);
+bool pxaddRunSetStateByQuery(pxConfig *config, psMetadata *where, const char *stage, const char *state);
 bool pxaddRunSetLabel(pxConfig *config, psS64 add_id, const char *label);
-bool pxaddRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *label);
+bool pxaddRunSetLabelByQuery(pxConfig *config, psMetadata *where, const char *stage, const char *label);
 
 bool pxaddQueueByCamID(pxConfig *config,
-		       psS64 cam_id,
+		       char *stage,
+		       psS64 stage_id,
 		       char *workdir,
 		       char *reduction,
Index: branches/eam_branches/ipp-20110404/ippTools/src/regtool.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/regtool.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/regtool.c	(revision 31439)
@@ -326,4 +326,5 @@
   query = rep;
 
+  // This matches against summitExp.dateobs
   psStringSubstitute(&query,dateobs_begin,"@DATEOBS_BEGIN@");
   psStringSubstitute(&query,dateobs_end,"@DATEOBS_END@");
Index: branches/eam_branches/ipp-20110404/ippTools/src/stacktool.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/stacktool.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/stacktool.c	(revision 31439)
@@ -243,5 +243,5 @@
     PXOPT_COPY_STR(config->args,  where, "-select_exp_type",           "rawExp.exp_type", "==");
     PXOPT_COPY_F32(config->args,  where, "-select_good_frac_min",      "warpSkyfile.good_frac", ">=");
-    PXOPT_COPY_STR(config->args,  where, "-select_skycell_id",         "warpSkyfile.skycell_id", "==");
+    PXOPT_COPY_STR(config->args,  where, "-select_skycell_id",         "warpSkyfile.skycell_id", "LIKE");
     PXOPT_COPY_STR(config->args,  where, "-select_data_group",         "warpRun.data_group", "==");
     pxAddLabelSearchArgs (config, where, "-select_label",              "warpRun.label", "LIKE"); // define using warp label
Index: branches/eam_branches/ipp-20110404/ippTools/src/staticskytool.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/staticskytool.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/staticskytool.c	(revision 31439)
@@ -115,4 +115,5 @@
     PXOPT_COPY_F32(config->args, whereMD, "-select_good_frac_min", "stackSumSkyfile.good_frac", ">=");
     pxAddLabelSearchArgs(config, whereMD, "-select_label",         "stackRun.label",            "LIKE");
+    pxAddLabelSearchArgs(config, whereMD, "-select_data_group",    "stackRun.data_group",       "LIKE");
     pxAddLabelSearchArgs(config, whereMD, "-select_filter",        "stackRun.filter",           "LIKE");
 
@@ -123,9 +124,4 @@
     psAssert (filters->data.list->n, "-select_filter should at least have a place-holder");
     int num_filter = filters->data.list->n;
-    if (num_filter < 2) {
-        psError(PXTOOLS_ERR_CONFIG, false, "invalid request: only 1 filter selected");
-        psFree(whereMD);
-        return false;
-    }
 
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
@@ -284,5 +280,5 @@
 	}
 
-	// create a chipRun
+	// create a staticskyRun
 	if (!staticskyRunInsert(config->dbh,
 				0x0,	     // sky_id
Index: branches/eam_branches/ipp-20110404/ippTools/src/staticskytoolConfig.c
===================================================================
--- branches/eam_branches/ipp-20110404/ippTools/src/staticskytoolConfig.c	(revision 31278)
+++ branches/eam_branches/ipp-20110404/ippTools/src/staticskytoolConfig.c	(revision 31439)
@@ -52,5 +52,6 @@
     psMetadataAddF32(definebyqueryArgs,  PS_LIST_TAIL, "-select_good_frac_min", 0, "define min good_frac", 0.0);
     psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_label", PS_META_DUPLICATE_OK, "search by stackRun label (LIKE comparison, multiple OK)", NULL);
-    psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_filter", PS_META_DUPLICATE_OK, "search by filter (LIKE comparison, multiple required)", NULL);
+    psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_data_group", PS_META_DUPLICATE_OK, "search by stackRun data_group (LIKE comparison, multiple OK)", NULL);
+    psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-select_filter", PS_META_DUPLICATE_OK, "search by filter (LIKE comparison, multiplei OK)", NULL);
     psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-set_workdir", 0, "define workdir (required)", NULL);
     psMetadataAddStr(definebyqueryArgs,  PS_LIST_TAIL, "-set_label", 0, "define label", NULL);
