52dc09ab871802c22d2459816b52cf2828c461b7
aamp
  Tue Apr 26 16:01:35 2011 -0700
A bit more persistence for settings.  They would reset after running the program. now settings reset if page is refreshed and the chain changes.
diff --git src/hg/hgLiftOver/hgLiftOver.c src/hg/hgLiftOver/hgLiftOver.c
index 6d78226..a844c88 100644
--- src/hg/hgLiftOver/hgLiftOver.c
+++ src/hg/hgLiftOver/hgLiftOver.c
@@ -16,60 +16,71 @@
 #include "hash.h"
 #include "liftOver.h"
 #include "liftOverChain.h"
 
 static char const rcsid[] = "$Id: hgLiftOver.c,v 1.62 2009/07/14 20:17:30 markd Exp $";
 
 /* CGI Variables */
 #define HGLFT_USERDATA_VAR "hglft_userData"     /* typed/pasted in data */
 #define HGLFT_DATAFILE_VAR "hglft_dataFile"     /* file of data to convert */
 #define HGLFT_FROMORG_VAR "hglft_fromOrg"         /* FROM organism */
 #define HGLFT_FROMDB_VAR "hglft_fromDb"         /* FROM assembly */
 #define HGLFT_TOORG_VAR   "hglft_toOrg"           /* TO organism */
 #define HGLFT_TODB_VAR   "hglft_toDb"           /* TO assembly */
 #define HGLFT_ERRORHELP_VAR "hglft_errorHelp"      /* Print explanatory text */
 #define HGLFT_REFRESHONLY_VAR "hglft_doRefreshOnly"      /* Just refresh drop-down lists */
+#define HGLFT_LAST_CHAIN "hglft_lastChain"
 
 /* liftOver options: */
 #define HGLFT_MINMATCH "hglft_minMatch"          
 #define HGLFT_MINSIZEQ "hglft_minSizeQ"
 #define HGLFT_MINCHAINT "hglft_minChainT"
 #define HGLFT_MULTIPLE "hglft_multiple"
 #define HGLFT_MINBLOCKS "hglft_minBlocks"
 #define HGLFT_FUDGETHICK "hglft_fudgeThick"
 
 /* Global Variables */
 struct cart *cart;	        /* CGI and other variables */
 struct hash *oldVars = NULL;
 
 /* Filename prefix */
 #define HGLFT   "hglft"
 
 /* Javascript to support New Assembly pulldown when Orig Assembly changes */
 /* Copies selected value from the Original Assembly pulldown to a hidden form
 */
 char *onChange = 
 "onchange=\"document.mainForm."
 HGLFT_REFRESHONLY_VAR
 ".value = 1;"
 "document.mainForm.submit();\"";
 
-void webMain(struct liftOverChain *chain, boolean multiple)
+char *chainStringVal(struct liftOverChain *chain)
+/* keep the last chain in memory in this format */
+{
+char chainS[64];
+safef(chainS, sizeof(chainS), "%s.%s", chain->fromDb, chain->toDb);
+return cloneString(chainS);
+}
+
+void webMain(struct liftOverChain *chain, boolean multiple, boolean keepSettings, int minSizeQ, 
+	     int minChainT, float minBlocks, float minMatch, boolean fudgeThick)
 /* set up page for entering data */
 {
 struct dbDb *dbList;
 char *fromOrg = hArchiveOrganism(chain->fromDb), *toOrg = hArchiveOrganism(chain->toDb);
+char *chainString = chainStringVal(chain);
 cgiParagraph(
     "This tool converts genome coordinates and genome annotation files "
     "between assemblies.  "
     "The input data can be pasted into the text box, or uploaded from a file.  "
     "If a pair of assemblies cannot be selected from the pull-down menus,"
     " a direct lift between them is unavailable.  "
     "However, a sequential lift may be possible.  "
     "Example: lift from Mouse, May 2004, to Mouse, Feb. 2006, and then from Mouse, "
     "Feb. 2006 to Mouse, July 2007 to achieve a lift from mm5 to mm9.  "
     "");
 
 /* create HMTL form */
 puts("<FORM ACTION=\"../cgi-bin/hgLiftOver\" METHOD=\"POST\" "
        " ENCTYPE=\"multipart/form-data\" NAME=\"mainForm\">\n");
 cartSaveSession(cart);
@@ -108,82 +119,82 @@
 cgiTableFieldEnd();
 
 cgiSimpleTableFieldStart();
 printAllAssemblyListHtmlParm(chain->toDb, dbList, HGLFT_TODB_VAR, TRUE, "");
 cgiTableFieldEnd();
 
 cgiTableRowEnd();
 cgiTableEnd();
 
 cgiParagraph("&nbsp;");
 cgiSimpleTableStart();
 
 cgiSimpleTableRowStart();
 cgiTableField("Minimum ratio of bases that must remap:");
 cgiSimpleTableFieldStart();
-cgiMakeDoubleVar(HGLFT_MINMATCH,chain->minMatch,6);
+cgiMakeDoubleVar(HGLFT_MINMATCH, (keepSettings) ? minMatch : chain->minMatch,6);
 cgiTableFieldEnd();
 cgiTableRowEnd();
 
 cgiSimpleTableRowStart();
 cgiTableField("&nbsp;");
 cgiTableRowEnd();
 
 cgiSimpleTableRowStart();
 cgiTableField("<B>BED 4 to BED 6 Options</B>");
 cgiTableRowEnd();
 
 cgiSimpleTableRowStart();
 cgiTableField("Allow multiple output regions:");
 cgiSimpleTableFieldStart();
 cgiMakeCheckBox(HGLFT_MULTIPLE,multiple);
 cgiTableFieldEnd();
 cgiTableRowEnd();
 
 cgiSimpleTableRowStart();
 cgiTableField("&nbsp;&nbsp;Minimum hit size in query:");
 cgiSimpleTableFieldStart();
-cgiMakeIntVar(HGLFT_MINSIZEQ,chain->minSizeQ,4);
+cgiMakeIntVar(HGLFT_MINSIZEQ,(keepSettings) ? minSizeQ : chain->minSizeQ,4);
 cgiTableFieldEnd();
 cgiTableRowEnd();
 
 cgiSimpleTableRowStart();
 cgiTableField("&nbsp;&nbsp;Minimum chain size in target:");
 cgiSimpleTableFieldStart();
-cgiMakeIntVar(HGLFT_MINCHAINT,chain->minChainT,4);
+cgiMakeIntVar(HGLFT_MINCHAINT,(keepSettings) ? minChainT : chain->minChainT,4);
 cgiTableFieldEnd();
 cgiTableRowEnd();
 
 cgiSimpleTableRowStart();
 cgiTableField("&nbsp;");
 cgiTableRowEnd();
 
 cgiSimpleTableRowStart();
 cgiTableField("<B>BED 12 Options</B>");
 cgiTableRowEnd();
 
 cgiSimpleTableRowStart();
 cgiTableField("Min ratio of alignment blocks or exons that must map:");
 cgiSimpleTableFieldStart();
-cgiMakeDoubleVar(HGLFT_MINBLOCKS,chain->minBlocks,6);
+cgiMakeDoubleVar(HGLFT_MINBLOCKS,(keepSettings) ? minBlocks : chain->minBlocks,6);
 cgiTableFieldEnd();
 cgiTableRowEnd();
 
 cgiSimpleTableRowStart();
 cgiTableField("If thickStart/thickEnd is not mapped, use the closest mapped base:");
 cgiSimpleTableFieldStart();
-cgiMakeCheckBox(HGLFT_FUDGETHICK,(chain->fudgeThick[0]=='Y') ? TRUE : FALSE);
+cgiMakeCheckBox(HGLFT_FUDGETHICK,(keepSettings) ? fudgeThick : (chain->fudgeThick[0]=='Y'));
 cgiTableFieldEnd();
 cgiTableRowEnd();
 
 cgiTableEnd();
 
 /* text box and two buttons (submit, reset) */
 cgiParagraph("&nbsp;Paste in data:\n");
 cgiSimpleTableStart();
 cgiSimpleTableRowStart();
 
 cgiSimpleTableFieldStart();
 cgiMakeTextArea(HGLFT_USERDATA_VAR, cartCgiUsualString(cart, HGLFT_USERDATA_VAR, NULL), 10, 80);
 cgiTableFieldEnd();
 
 /* right element of table is a nested table
@@ -207,30 +218,31 @@
 cgiTableFieldEnd();
 
 cgiTableRowEnd();
 cgiTableEnd();
 
 /* next  row -- file upload controls */
 cgiParagraph("&nbsp;Or upload data from a file:");
 cgiSimpleTableStart();
 cgiSimpleTableRowStart();
 printf("<TD><INPUT TYPE=FILE NAME=\"%s\"></TD>\n", HGLFT_DATAFILE_VAR);
 puts("<TD><INPUT TYPE=SUBMIT NAME=SubmitFile VALUE=\"Submit File\"></TD>\n");
 cgiTableRowEnd();
 cgiTableEnd();
 printf("<input type=\"hidden\" name=\"%s\" value=\"0\">\n",
                         HGLFT_REFRESHONLY_VAR);
+printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n", HGLFT_LAST_CHAIN, chainString);
 puts("</FORM>\n");
 
 cartSaveSession(cart);
 puts("</FORM>");
 freeMem(fromOrg);
 freeMem(toOrg);
 }
 
 void webParamsUsed(float minMatch, boolean multiple, int minSizeQ, int minChainT, float minBlocks, boolean fudgeThick)
 {
 webNewSection("Parameters Used");
 cgiSimpleTableStart();
 
 cgiSimpleTableRowStart();
 cgiTableField("Minimum ratio of bases that must remap:");
@@ -324,30 +336,33 @@
     char *fromOrg, char *fromDb, char *toOrg, char *toDb,
     char *cartOrg, char *cartDb, struct hash *dbRank, 
     struct hash *dbHash)
 /* Score the chain in terms of best match for cart settings */
 {
 double score = 0;
 struct dbDb *chainFromDbDb = hashFindVal(dbHash, chain->fromDb);
 struct dbDb *chainToDbDb = hashFindVal(dbHash, chain->toDb);
 
 char *chainFromOrg = (chainFromDbDb) ? chainFromDbDb->organism : NULL;
 char *chainToOrg = (chainToDbDb) ? chainToDbDb->organism : NULL;
 int fromRank = hashIntValDefault(dbRank, chain->fromDb, 0);  /* values up to approx. #assemblies */
 int toRank = hashIntValDefault(dbRank, chain->toDb, 0);
 int maxRank = hashIntVal(dbRank, "maxRank"); 
 
+if (!chainFromOrg || !chainToOrg)
+    return 0;
+
 if (sameOk(fromOrg,chainFromOrg) &&
     sameOk(fromDb,chain->fromDb) && 
     sameOk(toOrg,chainToOrg) &&
     sameOk(toDb,chain->toDb))
     score += 10000000;
 
 if (sameOk(fromOrg,chainFromOrg)) 
     score += 2000000;
 if (sameOk(fromDb,chain->fromDb)) 
     score += 1000000;
 
 if (sameOk(toOrg,chainToOrg))
     score += 200000;
 if (sameOk(toDb,chain->toDb))
     score += 100000;
@@ -403,80 +418,83 @@
     {
     double score = scoreLiftOverChain(this, fromOrg, fromDb, toOrg, toDb, cartOrg, cartDb, dbRank, dbDbHash);
     if (score > bestScore)
 	{
 	choice = this;
 	bestScore = score;
 	}
     }
 
 return choice;
 }
 
 void doMiddle(struct cart *theCart)
 /* Set up globals and make web page */
 {
-/* struct liftOverChain *chainList = NULL, *chain; */
 char *userData;
-/* char *dataFile; */
 char *organism;
 char *db;
 float minBlocks, minMatch;
 boolean multiple, fudgeThick;
 int minSizeQ, minChainT;
 boolean refreshOnly = FALSE;
+boolean keepSettings = FALSE;
+char *thisChain = NULL;
+char *lastChain = NULL;
 
-/* char *err = NULL; */
 struct liftOverChain *chainList = NULL, *choice;
 
 cart = theCart;
 
 if (cgiOptionalString(HGLFT_ERRORHELP_VAR))
     {
     puts("<PRE>");
     puts(liftOverErrHelp());
-    //system("/usr/bin/cal");
     puts("</PRE>");
     return;
     }
 
 /* Get data to convert - from userData variable, or if 
  * that is empty from a file. */
 
 if (cartOptionalString(cart, "SubmitFile"))
     userData = cartOptionalString(cart, HGLFT_DATAFILE_VAR);
 else
     userData = cartOptionalString(cart, HGLFT_USERDATA_VAR);
 cartWebStart(cart, NULL, "Lift Genome Annotations");
 
 getDbAndGenome(cart, &db, &organism, oldVars);
 
 chainList = liftOverChainList();
 
 choice = defaultChoices(chainList, db);
+thisChain = chainStringVal(choice);
 if (choice == NULL)
     errAbort("Sorry, no conversions available from this assembly\n");
 
 minSizeQ = cartCgiUsualInt(cart, HGLFT_MINSIZEQ, choice->minSizeQ);
 minChainT = cartCgiUsualInt(cart, HGLFT_MINCHAINT, choice->minChainT);
 minBlocks = cartCgiUsualDouble(cart, HGLFT_MINBLOCKS, choice->minBlocks);
 minMatch = cartCgiUsualDouble(cart, HGLFT_MINMATCH, choice->minMatch);
 fudgeThick = cartCgiUsualBoolean(cart, HGLFT_FUDGETHICK, (choice->fudgeThick[0]=='Y') ? TRUE : FALSE);
 multiple = cartCgiUsualBoolean(cart, HGLFT_MULTIPLE, (choice->multiple[0]=='Y') ? TRUE : FALSE);
 refreshOnly = cartCgiUsualInt(cart, HGLFT_REFRESHONLY_VAR, 0);
+lastChain = cartCgiUsualString(cart, HGLFT_LAST_CHAIN, NULL);
+if (lastChain && thisChain && sameString(lastChain, thisChain))
+    keepSettings = TRUE;
 
-webMain(choice, multiple);
+webMain(choice, multiple, keepSettings, minSizeQ, minChainT, minBlocks, minMatch, fudgeThick);
 liftOverChainFreeList(&chainList);
 
 if (!refreshOnly && userData != NULL && userData[0] != '\0')
     {
     struct hash *chainHash = newHash(0);
     char *chainFile;
     struct tempName oldTn, mappedTn, unmappedTn;
     FILE *old, *mapped, *unmapped;
     char *line;
     int lineSize;
     char *fromDb, *toDb;
     int ct = 0, errCt = 0;
 
     /* read in user data and save to file */
     makeTempName(&oldTn, HGLFT, ".user");