Index: /trunk/ippTools/src/difftool.c
===================================================================
--- /trunk/ippTools/src/difftool.c	(revision 15414)
+++ /trunk/ippTools/src/difftool.c	(revision 15415)
@@ -39,4 +39,5 @@
 static bool diffskyfileMode(pxConfig *config);
 static bool revertdiffskyfileMode(pxConfig *config);
+static bool definepoprunMode(pxConfig *config);
 
 static bool setdiffRunState(pxConfig *config, const char *diff_id, const char *state);
@@ -62,10 +63,11 @@
         MODECASE(DIFFTOOL_MODE_DEFINERUN,         definerunMode);
         MODECASE(DIFFTOOL_MODE_UPDATERUN,         updaterunMode);
-        MODECASE(DIFFTOOL_MODE_ADDINPUTSKYFILE,    addinputskyfileMode);
-        MODECASE(DIFFTOOL_MODE_INPUTSKYFILE,       inputskyfileMode);
-        MODECASE(DIFFTOOL_MODE_TODIFFSKYFILE,      todiffskyfileMode);
-        MODECASE(DIFFTOOL_MODE_ADDDIFFSKYFILE,     adddiffskyfileMode);
-        MODECASE(DIFFTOOL_MODE_DIFFSKYFILE,        diffskyfileMode);
-        MODECASE(DIFFTOOL_MODE_REVERTDIFFSKYFILE,  revertdiffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_ADDINPUTSKYFILE,   addinputskyfileMode);
+        MODECASE(DIFFTOOL_MODE_INPUTSKYFILE,      inputskyfileMode);
+        MODECASE(DIFFTOOL_MODE_TODIFFSKYFILE,     todiffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_ADDDIFFSKYFILE,    adddiffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_DIFFSKYFILE,       diffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_REVERTDIFFSKYFILE, revertdiffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_DEFINEPOPRUN,      definepoprunMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -787,2 +789,201 @@
     return true;
 }
+
+
+
+
+
+static bool definepoprunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required options
+    bool status = false;
+    psString workdir = psMetadataLookupStr(&status, config->args, "-workdir");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -workdir");
+        return false;
+    }
+    if (!workdir) {
+        psError(PS_ERR_UNKNOWN, true, "-workdir is required");
+        return false;
+    }
+
+    psString skycell_id = psMetadataLookupStr(&status, config->args, "-skycell_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -skycell_id");
+        return false;
+    }
+    if (!skycell_id) {
+        psError(PS_ERR_UNKNOWN, true, "-skycell_id is required");
+        return false;
+    }
+
+    psString tess_id = psMetadataLookupStr(&status, config->args, "-tess_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -tess_id");
+        return false;
+    }
+    if (!tess_id) {
+        psError(PS_ERR_UNKNOWN, true, "-tess_id is required");
+        return false;
+    }
+
+    psString template_stack_id = psMetadataLookupStr(&status, config->args, "-template_stack_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -template_stack_id");
+        return false;
+    }
+    psString template_warp_id = psMetadataLookupStr(&status, config->args, "-template_warp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -template_warp_id");
+        return false;
+    }
+    if (template_stack_id && template_warp_id) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Only one template can be defined.");
+        return false;
+    }
+    if (!template_stack_id && !template_warp_id) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "No template has been defined (-template_stack_id or -template_warp_id)");
+        return false;
+    }
+
+    psString input_stack_id = psMetadataLookupStr(&status, config->args, "-input_stack_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -input_stack_id");
+        return false;
+    }
+    psString input_warp_id = psMetadataLookupStr(&status, config->args, "-input_warp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -input_warp_id");
+        return false;
+    }
+    if (input_stack_id && input_warp_id) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Only one input can be defined.");
+        return false;
+    }
+    if (!input_stack_id && !input_warp_id) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "No input has been defined (-input_stack_id or -input_warp_id)");
+        return false;
+    }
+
+    psString kind = NULL;
+
+    psTime *registered = NULL;
+    {
+        psString registeredStr = psMetadataLookupStr(&status, config->args, "-registered");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -registered");
+            return false;
+        }
+        // pass through NULL as this is an optional field
+        if (registeredStr) {
+            registered = psTimeFromISO(registeredStr, PS_TIME_UTC);
+        } else {
+            registered = NULL;
+        }
+    }
+
+    bool simple = false;
+    {
+        bool status = false;
+        simple = psMetadataLookupBool(&status, config->args, "-simple");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -simple");
+            return false;
+        }
+    }
+
+    diffRunRow *run = diffRunRowAlloc(
+            0,          // ID
+            "reg",      // state
+            workdir,
+            NULL,       // dvodb
+            registered,
+            skycell_id,
+            tess_id
+    );
+    psFree(registered);
+
+    if (!run) {
+        psError(PS_ERR_UNKNOWN, false, "failed to alloc diffRun object");
+        return true;
+    }
+
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!diffRunInsertObject(config->dbh, run)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(run);
+        return true;
+    }
+
+    // get the assigned diff_id
+    run->diff_id = psDBLastInsertID(config->dbh);
+
+    // Template
+    if (!diffInputSkyfileInsert(config->dbh,
+            run->diff_id,
+            true,
+            template_stack_id ? (psS64)atoll(template_stack_id) : PS_MAX_S64, // defined or NULL
+            template_warp_id ? (psS64)atoll(template_warp_id) : PS_MAX_S64, // defined or NULL
+            skycell_id,
+            tess_id,
+            kind
+        )) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // Input
+    if (!diffInputSkyfileInsert(config->dbh,
+            run->diff_id,
+            false,
+            input_stack_id ? (psS64)atoll(input_stack_id) : PS_MAX_S64, // defined or NULL
+            input_warp_id ? (psS64)atoll(input_warp_id) : PS_MAX_S64, // defined or NULL
+            skycell_id,
+            tess_id,
+            kind
+        )) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    char *query = "UPDATE diffRun SET state = 'run' WHERE diff_id = '%" PRId64 "'";
+    if (!p_psDBRunQuery(config->dbh, query, run->diff_id)) {
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to set state to run for diff_id %" PRId64, run->diff_id);
+        return false;
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!diffRunPrintObject(stdout, run, !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print object");
+            psFree(run);
+            return false;
+    }
+
+    psFree(run);
+
+    return true;
+}
Index: /trunk/ippTools/src/difftool.h
===================================================================
--- /trunk/ippTools/src/difftool.h	(revision 15414)
+++ /trunk/ippTools/src/difftool.h	(revision 15415)
@@ -33,4 +33,5 @@
     DIFFTOOL_MODE_DIFFSKYFILE,
     DIFFTOOL_MODE_REVERTDIFFSKYFILE,
+    DIFFTOOL_MODE_DEFINEPOPRUN,
 } difftoolMode;
 
Index: /trunk/ippTools/src/difftoolConfig.c
===================================================================
--- /trunk/ippTools/src/difftoolConfig.c	(revision 15414)
+++ /trunk/ippTools/src/difftoolConfig.c	(revision 15415)
@@ -80,5 +80,5 @@
             "define warp ID", NULL);
     psMetadataAddStr(addinputskyfileArgs, PS_LIST_TAIL, "-stack_id", 0,
-            "define stack ID)", NULL);
+            "define stack ID", NULL);
     psMetadataAddStr(addinputskyfileArgs, PS_LIST_TAIL, "-kind", 0,
             "define kind", NULL);
@@ -151,4 +151,25 @@
             "search by fault code", 0);
 
+    // -definepoprun
+    psMetadata *definepoprunArgs = psMetadataAlloc();
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-workdir", 0,
+            "define workdir (required)", NULL);
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-registered",  0,
+            "time detrend run was registered", now);
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-skycell_id",  0,
+            "define skycell ID (required)", NULL);
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-tess_id",  0,
+            "define tessellation ID (required)", NULL);
+    psMetadataAddBool(definepoprunArgs, PS_LIST_TAIL, "-simple",  0,
+            "use the simple output format", false);
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-template_warp_id", 0,
+            "define warp ID for template", NULL);
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-template_stack_id", 0,
+            "define stack ID for template", NULL);
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-input_warp_id", 0,
+            "define warp ID for input", NULL);
+    psMetadataAddStr(definepoprunArgs, PS_LIST_TAIL, "-input_stack_id", 0,
+            "define stack ID for input", NULL);
+
     psFree(now);
 
@@ -156,12 +177,13 @@
     psMetadata *modes = psMetadataAlloc();
 
-    PXTOOL_ADD_MODE("-definerun",       "",     DIFFTOOL_MODE_DEFINERUN,      definerunArgs);
-    PXTOOL_ADD_MODE("-updaterun",       "",     DIFFTOOL_MODE_UPDATERUN,      updaterunArgs);
-    PXTOOL_ADD_MODE("-addinputskyfile", "",     DIFFTOOL_MODE_ADDINPUTSKYFILE, addinputskyfileArgs);
-    PXTOOL_ADD_MODE("-inputskyfile",    "",     DIFFTOOL_MODE_INPUTSKYFILE,    inputskyfileArgs);
-    PXTOOL_ADD_MODE("-todiffskyfile",   "",     DIFFTOOL_MODE_TODIFFSKYFILE,   todiffskyfileArgs);
-    PXTOOL_ADD_MODE("-adddiffskyfile",  "",     DIFFTOOL_MODE_ADDDIFFSKYFILE,  adddiffskyfileArgs);
-    PXTOOL_ADD_MODE("-diffskyfile",     "",     DIFFTOOL_MODE_DIFFSKYFILE,     diffskyfileArgs);
-    PXTOOL_ADD_MODE("-revertdiffskyfile","",    DIFFTOOL_MODE_REVERTDIFFSKYFILE,     revertdiffskyfileArgs);
+    PXTOOL_ADD_MODE("-definerun",        "", DIFFTOOL_MODE_DEFINERUN,         definerunArgs);
+    PXTOOL_ADD_MODE("-updaterun",        "", DIFFTOOL_MODE_UPDATERUN,         updaterunArgs);
+    PXTOOL_ADD_MODE("-addinputskyfile",  "", DIFFTOOL_MODE_ADDINPUTSKYFILE,   addinputskyfileArgs);
+    PXTOOL_ADD_MODE("-inputskyfile",     "", DIFFTOOL_MODE_INPUTSKYFILE,      inputskyfileArgs);
+    PXTOOL_ADD_MODE("-todiffskyfile",    "", DIFFTOOL_MODE_TODIFFSKYFILE,     todiffskyfileArgs);
+    PXTOOL_ADD_MODE("-adddiffskyfile",   "", DIFFTOOL_MODE_ADDDIFFSKYFILE,    adddiffskyfileArgs);
+    PXTOOL_ADD_MODE("-diffskyfile",      "", DIFFTOOL_MODE_DIFFSKYFILE,       diffskyfileArgs);
+    PXTOOL_ADD_MODE("-revertdiffskyfile","", DIFFTOOL_MODE_REVERTDIFFSKYFILE, revertdiffskyfileArgs);
+    PXTOOL_ADD_MODE("-definepoprun",     "", DIFFTOOL_MODE_DEFINEPOPRUN,      definepoprunArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
