fbdc691703e4bc2d98fcdb2014fe6fa19771c104
braney
  Fri Feb 10 17:05:10 2017 -0800
make building a custom track with blat results an option on the hgBlat
page.   Add some features to bigPsl click support to get the same kind
of UI that hgBlat provides.

diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c
index be8b9f3..9c58a17 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -244,30 +244,31 @@
 #include "parClick.h"
 #include "mdb.h"
 #include "yaleGencodeAssoc.h"
 #include "itemDetailsHtml.h"
 #include "trackVersion.h"
 #include "numtsClick.h"
 #include "geneReviewsClick.h"
 #include "bigBed.h"
 #include "bigPsl.h"
 #include "bedTabix.h"
 #include "longRange.h"
 #include "hmmstats.h"
 #include "aveStats.h"
 #include "trix.h"
 #include "bPlusTree.h"
+#include "customFactory.h"
 
 static char *rootDir = "hgcData";
 
 #define LINESIZE 70  /* size of lines in comp seq feature */
 
 struct cart *cart;	/* User's settings. */
 char *seqName;		/* Name of sequence we're working on. */
 int winStart, winEnd;   /* Bounds of sequence. */
 char *database;		/* Name of mySQL database. */
 char *organism;		/* Colloquial name of organism. */
 char *genome;		/* common name, e.g. Mouse, Human */
 char *scientificName;	/* Scientific name of organism. */
 
 struct hash *trackHash;	/* A hash of all tracks - trackDb valued */
 
@@ -2969,41 +2970,54 @@
                      char *item, int start, int end)
 /* Handle click in big psl track. */
 {
 struct psl* pslList = NULL;
 char *fileName = bbiNameFromSettingOrTable(tdb, conn, tdb->table);
 struct bbiFile *bbi = bigBedFileOpen(fileName);
 struct lm *lm = lmInit(0);
 int ivStart = start, ivEnd = end;
 if (start == end)
     {  
     // item is an insertion; expand the search range from 0 bases to 2 so we catch it:
     ivStart = max(0, start-1);
     ivEnd++;
     }  
 
+boolean showEvery = sameString(item, "PrintAllSequences");
 boolean showAll = trackDbSettingOn(tdb, "showAll");
 unsigned seqTypeField =  bbExtraFieldIndex(bbi, "seqType");
-struct bigBedInterval *bb, *bbList;
+struct bigBedInterval *bb, *bbList = NULL;
 
 // If showAll is on, show all alignments with this qName, not just the
 // selected one.
-if (showAll)
+if (showEvery)
+    {
+    struct bbiChromInfo *chrom, *chromList = bbiChromList(bbi);
+    for (chrom = chromList; chrom != NULL; chrom = chrom->next)
+        {
+        char *chromName = chrom->name;
+        int start = 0, end = chrom->size;
+        int itemsLeft = 0;  // Zero actually means no limit.... 
+        struct bigBedInterval *intervalList = bigBedIntervalQuery(bbi, chromName,
+            start, end, itemsLeft, lm);
+        slCat(&bbList, intervalList);
+        }
+    }
+else if (showAll)
     {
     int fieldIx;
     struct bptFile *bpt = bigBedOpenExtraIndex(bbi, "name", &fieldIx);
-    struct lm *lm = lmInit(0);
     bbList = bigBedNameQuery(bbi, bpt, fieldIx, item, lm);
     }
 else
     bbList = bigBedIntervalQuery(bbi, seqName, ivStart, ivEnd, 0, lm);
 
 
 /* print out extra fields */
 for (bb = bbList; bb != NULL; bb = bb->next)
     {
     char *restFields[256];
     int restCount = chopTabs(cloneString(bb->rest), restFields);
     if (sameString(restFields[0], item))
         {
         int bedSize = 25;
         int restBedFields = bedSize - 3;
@@ -3017,39 +3031,45 @@
         }
     }
 
 char *bedRow[32];
 char startBuf[16], endBuf[16];
 
 int lastChromId = -1;
 char chromName[bbi->chromBpt->keySize+1];
 
 for (bb = bbList; bb != NULL; bb = bb->next)
     {
     bbiCachedChromLookup(bbi, bb->chromId, lastChromId, chromName, sizeof(chromName));
 
     lastChromId=bb->chromId;
     bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, 4);
-    if (sameString(bedRow[3], item))
+    if (showEvery || sameString(bedRow[3], item))
 	{
         struct psl *psl= pslFromBigPsl(chromName, bb, seqTypeField, NULL, NULL);
         slAddHead(&pslList, psl);
 	}
     }
 
+char *sort = cartUsualString(cart, "sort", pslSortList[0]);
+pslSortListByVar(&pslList, sort);
+
+if (showEvery)
+    printf("<H3>Genomic Alignments</H3>");
+else
     printf("<H3>%s/Genomic Alignments</H3>", item);
-if (pslIsProtein(pslList))
+if (showEvery || pslIsProtein(pslList))
     printAlignmentsSimple(pslList, start, "htcBigPslAli", tdb->table, item);
 else
     printAlignmentsExtra(pslList, start, "htcBigPslAli", "htcBigPslAliInWindow",
         tdb->table, item);
 pslFreeList(&pslList);
 printItemDetailsHtml(tdb, item);
 }
 
 void genericPslClick(struct sqlConnection *conn, struct trackDb *tdb,
                      char *item, int start, char *subType)
 /* Handle click in generic psl track. */
 {
 struct psl* pslList = getAlignments(conn, tdb->table, item);
 
 /* check if there is an alignment available for this sequence.  This checks
@@ -5868,51 +5888,55 @@
  */
 {
 return ((psl->tStart == startFirst) && sameString(psl->tName, seqName)) == isClicked;
 }
 
 void printAlignmentsSimple(struct psl *pslList, int startFirst, char *hgcCommand,
                            char *tableName, char *itemIn)
 /* Print list of mRNA alignments, don't add extra textual link when
  * doesn't honor hgcCommand. */
 {
 struct psl *psl;
 int aliCount = slCount(pslList);
 boolean isClicked;
 if (pslList == NULL || tableName == NULL)
     return;
+boolean showEvery = sameString(itemIn, "PrintAllSequences");
 
-if (aliCount > 1)
+if (!showEvery && (aliCount > 1))
     printf("The alignment you clicked on is first in the table below.<BR>\n");
 
 printf("<PRE><TT>");
 if (startsWith("chr", pslList->tName))
     printf("BROWSER | SIZE IDENTITY CHROMOSOME  STRAND    START     END              QUERY      START  END  TOTAL\n");
 else
     printf("BROWSER | SIZE IDENTITY  SCAFFOLD   STRAND    START     END              QUERY      START  END  TOTAL\n");
 printf("-----------------------------------------------------------------------------------------------------\n");
 for (isClicked = 1; isClicked >= 0; isClicked -= 1)
     {
     for (psl = pslList; psl != NULL; psl = psl->next)
 	{
 	if (isPslToPrintByClick(psl, startFirst, isClicked))
 	    {
             char otherString[512];
+            char *qName = itemIn;
+            if (sameString(itemIn, "PrintAllSequences"))
+                qName = psl->qName;
 	    safef(otherString, sizeof(otherString), "%d&aliTable=%s", psl->tStart, tableName);
             printf("<A HREF=\"%s&db=%s&position=%s%%3A%d-%d\">browser</A> | ",
                    hgTracksPathAndSettings(), database, psl->tName, psl->tStart+1, psl->tEnd);
-	    hgcAnchorWindow(hgcCommand, itemIn, psl->tStart, psl->tEnd,  otherString, psl->tName);
+	    hgcAnchorWindow(hgcCommand, qName, psl->tStart, psl->tEnd,  otherString, psl->tName);
 	    printf("%5d  %5.1f%%  %9s     %s %9d %9d  %20s %5d %5d %5d</A>",
 		   psl->match + psl->misMatch + psl->repMatch,
 		   100.0 - pslCalcMilliBad(psl, TRUE) * 0.1,
 		   skipChr(psl->tName), psl->strand, psl->tStart + 1, psl->tEnd,
 		   psl->qName, psl->qStart+1, psl->qEnd, psl->qSize);
 	    printf("\n");
 	    }
 	}
     }
 printf("</TT></PRE>");
 }
 
 void printAlignmentsExtra(struct psl *pslList, int startFirst, char *hgcCommand, char *hgcCommandInWindow,
 		     char *tableName, char *itemIn)
 /* Print list of mRNA alignments with special "in window" alignment function. */
@@ -25111,30 +25135,111 @@
 while (*c != 0) 
     {
     if ((*c=='&') || (*c=='<'))
        doNotBreak = TRUE;
     if (*c==';' || (*c =='>'))
        doNotBreak = FALSE;
 
     printf("%c", *c);
     if (i % distance == 0 && ! doNotBreak) 
         printf("<wbr>");
     c++;
     i++;
     }
 }
 
+static char *replaceSuffix(char *input, char *newSuffix)
+/* Given a filename with a suffix, replace existing suffix with a new suffix. */
+{
+char buffer[4096];
+safecpy(buffer, sizeof buffer, input);
+char *dot = strrchr(buffer, '.');
+safecpy(dot+1, sizeof buffer - 1 - (dot - buffer), newSuffix);
+return cloneString(buffer);
+}
+
+static void makeBigPsl(char *pslName, char *faName, char *db, char *outputBigBed)
+/* Make a bigPsl with the blat results. */
+{
+char *bigPslFile = replaceSuffix(outputBigBed, "bigPsl");
+
+char cmdBuffer[4096];
+safef(cmdBuffer, sizeof(cmdBuffer), "loader/pslToBigPsl %s -fa=%s stdout | sort -k1,1 -k2,2n  > %s", pslName, faName, bigPslFile);  
+system(cmdBuffer);
+char buf[4096];
+char *twoBitDir;
+if (trackHubDatabase(db))
+    {
+    struct trackHubGenome *genome = trackHubGetGenome(db);
+    twoBitDir = genome->twoBitPath;
+    }
+else
+    {
+    safef(buf, sizeof(buf), "/gbdb/%s", db);
+    twoBitDir = hReplaceGbdbSeqDir(buf, db);
+    safef(buf, sizeof(buf), "%s%s.2bit", twoBitDir, db);
+    twoBitDir = buf;
+    }
+
+safef(cmdBuffer, sizeof(cmdBuffer), "loader/bedToBigBed -verbose=0 -udcDir=%s -extraIndex=name -sizesIs2Bit -tab -as=loader/bigPsl.as -type=bed9+16  %s %s %s",  
+        udcDefaultDir(), bigPslFile, twoBitDir, outputBigBed);
+system(cmdBuffer);
+unlink(bigPslFile);
+}
+
+static void buildBigPsl(char *fileNames)
+/* Build a custom track with a bigPsl file out of blat results.
+ * Bring up the bigPsl detail page with all the alignments. */
+{
+char *trackName = cartString(cart, "trackName");
+char *trackDescription = cartString(cart, "trackDescription");
+char *pslName, *faName, *qName;
+parseSs(fileNames, &pslName, &faName, &qName);
+
+struct tempName bigBedTn;
+trashDirDateFile(&bigBedTn, "hgBlat", "bp", ".bb");
+char *bigBedFile = bigBedTn.forCgi;
+makeBigPsl(pslName, faName, database, bigBedFile);
+
+char* host = getenv("HTTP_HOST");
+char* reqUrl = cloneString(getenv("REQUEST_URI"));
+// delete arguements to the url
+char *e = strchr(reqUrl+1, '?');
+if (e) *e = 0;
+// remove the cgi name
+e = strchr(reqUrl+1, '/');
+if (e) *e = 0;
+
+char *customTextTemplate = "track type=bigPsl indelDoubleInsert=on indelQueryInsert=on  pslFile=%s visibility=pack showAll=on htmlUrl=http://%s/goldenPath/help/hgUserPsl.html %s bigDataUrl=http://%s%s/%s name=\"%s\" description=\"%s\"\n";  
+char *extraForMismatch = "showDiffBasesAllScales=. baseColorUseSequence=lfExtra baseColorDefault=diffBases";
+  
+boolean isProt = FALSE;
+if (isProt)
+    extraForMismatch = "";
+char buffer[4096];
+safef(buffer, sizeof buffer, customTextTemplate, bigBedTn.forCgi, host, extraForMismatch, host, reqUrl, bigBedTn.forCgi, trackName, trackDescription);
+
+struct customTrack *ctList = getCtList();
+struct customTrack *newCts = customFactoryParse(database, buffer, FALSE, NULL);
+theCtList = customTrackAddToList(ctList, newCts, NULL, FALSE);
+
+customTracksSaveCart(database, cart, theCtList);
+
+cartSetString(cart, "i", "PrintAllSequences");
+hgCustom(newCts->tdb->track, NULL);
+}
+
 void doMiddle()
 /* Generate body of HTML. */
 {
 char *track = cartString(cart, "g");
 char *item = cloneString(cartOptionalString(cart, "i"));
 char *parentWigMaf = cartOptionalString(cart, "parentWigMaf");
 struct trackDb *tdb = NULL;
 
 
 if (hIsGisaidServer())
     {
     validateGisaidUser(cart);
     }
 
 /*	database and organism are global variables used in many places	*/
@@ -25266,30 +25371,34 @@
     {
     doGetDna1();
     }
 else if (sameWord(table, "htcGetDna2"))
     {
     doGetDna2();
     }
 else if (sameWord(table, "htcGetDna3"))
     {
     doGetDna3();
     }
 else if (sameWord(table, "htcGetDnaExtended1"))
     {
     doGetDnaExtended1();
     }
+else if (sameWord(table, "buildBigPsl"))
+    {
+    buildBigPsl(item);
+    }
 else if (sameWord(table, "htcListItemsAssayed"))
     {
     doPeakClusterListItemsAssayed();
     }
 
 /* Lowe Lab Stuff */
 #ifdef LOWELAB
  else if (loweLabClick(table, item, tdb))
    {
      /* do nothing, everything handled in loweLabClick */
    }
 #endif
 else if (sameWord(table, G_DELETE_WIKI_ITEM))
     {
     doDeleteWikiItem(item, seqName, winStart, winEnd);