06d7be056190c14b85e71bc12523f18ea6815b5e
markd
  Mon Dec 7 00:50:29 2020 -0800
BLAT mmap index support merge with master

diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c
index 440b04c..85cadb2 100644
--- src/hg/hgTracks/simpleTracks.c
+++ src/hg/hgTracks/simpleTracks.c
@@ -226,33 +226,30 @@
 
 char *virtModeType = "default";  /* virtual chrom mode type */
 char *lastVirtModeType = "default";
 char *virtModeShortDescr = "";   /* short description of virt mode */
 char *virtModeExtraState = "";   /* Other settings that affect the virtMode state such as padding or some parameter */
 char *lastVirtModeExtraState = "";
 struct cart *lastDbPosCart = NULL;   /* store settings for use in lastDbPos and hgTracks.js setupHistory */
 
 char *organism;                 /* Name of organism we're working on. */
 char *database;			/* Name of database we're using. */
 char *chromName;		/* Name of chromosome sequence . */
 int winStart;                   /* Start of window in sequence. */
 int winEnd;                     /* End of window in sequence. */
 char *position = NULL;          /* Name of position. */
 
-int trackTabWidth = 11;
-int leftLabelWidthDefaultChars = 20;   /* default number of characters allowed for left label */
-int leftLabelWidthChars = 20;   /* number of characters allowed for left label */
 int insideX;			/* Start of area to draw track in in pixels. */
 int insideWidth;		/* Width of area to draw tracks in in pixels. */
 int leftLabelX;                 /* Start of area to draw left labels on. */
 int leftLabelWidth;             /* Width of area to draw left labels on. */
 float basesPerPixel = 0;       /* bases covered by a pixel; a measure of zoom */
 boolean zoomedToBaseLevel;      /* TRUE if zoomed so we can draw bases. */
 boolean zoomedToCodonLevel; /* TRUE if zoomed so we can print codons text in genePreds*/
 boolean zoomedToCdsColorLevel; /* TRUE if zoomed so we can color each codon*/
 
 boolean withLeftLabels = TRUE;		/* Display left labels? */
 boolean withIndividualLabels = TRUE;    /* print labels on item-by-item basis (false to skip) */
 boolean withCenterLabels = TRUE;	/* Display center labels? */
 boolean withGuidelines = TRUE;		/* Display guidelines? */
 boolean withNextExonArrows = FALSE;	/* Display next exon navigation buttons near center labels? */
 boolean withExonNumbers = FALSE;	/* Display exon and intron numbers in mouseOver instead of item name */
@@ -276,42 +273,30 @@
 
 Color shadesOfSea[10+1];       /* Ten sea shades. */
 struct rgbColor darkSeaColor = {0, 60, 120};
 struct rgbColor lightSeaColor = {200, 220, 255};
 
 struct hash *hgFindMatches; /* The matches found by hgFind that should be highlighted. */
 
 struct trackLayout tl;
 
 void initTl()
 /* Initialize layout around small font and a picture about 600 pixels
  * wide. */
 {
 trackLayoutInit(&tl, cart);
 
-// label width, but don't exceed 1/2 of image
-leftLabelWidthChars = cartUsualInt(cart, "hgt.labelWidth", leftLabelWidthDefaultChars);
-if (leftLabelWidthChars < 2)
-    leftLabelWidthChars = leftLabelWidthDefaultChars;
-tl.leftLabelWidth = leftLabelWidthChars*tl.nWidth + trackTabWidth + 3;
-int maxLabelWidth = 0.5*tl.picWidth;
-if (tl.leftLabelWidth  > maxLabelWidth)
-    {
-    // overflow, force to 1/2 width
-    leftLabelWidthChars = maxLabelWidth/tl.nWidth;
-    tl.leftLabelWidth = leftLabelWidthChars * tl.nWidth;
-    }
 }
 
 static boolean isTooLightForTextOnWhite(struct hvGfx *hvg, Color color)
 /* Return TRUE if text in this color would probably be invisible on a white background. */
 {
 struct rgbColor rgbColor =  hvGfxColorIxToRgb(hvg, color);
 int colorTotal = rgbColor.r + 2*rgbColor.g + rgbColor.b;
 return colorTotal >= 512;
 }
 
 Color darkerColor(struct hvGfx *hvg, Color color)
 /* Get darker shade of a color - half way between this color and black */
 {
 struct rgbColor rgbColor =  hvGfxColorIxToRgb(hvg, color);
 rgbColor.r = ((int)rgbColor.r)/2;
@@ -2681,36 +2666,44 @@
 	    int w = ex - sx;
 
 	    int exonIntronNumber;
 	    char *exonIntronText;
 	    int numExonIntrons = numExons;
 	    if (isExon)
 		{
 		exonIntronText = exonText;
 		}
 	    else
 		{
 		exonIntronText = intronText;
 		--numExonIntrons;  // introns are one fewer than exons
 		}
 
-	    if (!revStrand)
+            char strandChar;
+	    if (!revStrand) {
 		exonIntronNumber = exonIx;
-	    else
+                strandChar = '+';
+            }
+	    else {
 		exonIntronNumber = numExonIntrons-exonIx+1;
+                strandChar = '-';
+            }
 
-	    safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", exonIntronText, exonIntronNumber, numExonIntrons);
+            if (!isEmpty(lf->name))
+                safef(mouseOverText, sizeof(mouseOverText), "%s, strand %c, %s %d of %d", lf->name, strandChar, exonIntronText, exonIntronNumber, numExonIntrons);
+            else
+                safef(mouseOverText, sizeof(mouseOverText), "strand %c, %s %d of %d", strandChar, exonIntronText, exonIntronNumber, numExonIntrons);
 
 	    if (w > 0) // draw exon or intron if width is greater than 0
 		{
 		tg->mapItem(tg, hvg, item, mouseOverText, tg->mapItemName(tg, item),
 		    sItem, eItem, sx, y, w, heightPer);
 		picStart = ex;  // prevent pileups. is this right? add 1? does it work?
 		}
 	    }
 	}
 
     if (isExon)
 	{
     	eLast = e;
 	ref = ref->next;
 	if (!ref)
@@ -4063,32 +4056,34 @@
 
 boolean nextItemCompatible(struct track *tg)
 /* Check to see if we draw nextPrev item buttons on a track. */
 {
 return (withNextExonArrows && tg->nextExonButtonable && tg->nextPrevExon);
 }
 
 boolean exonNumberMapsCompatible(struct track *tg, enum trackVisibility vis)
 /* Check to see if we draw exon and intron maps labeling their number. */
 {
 if (tg->tdb)
     {
     char *type = tg->tdb->type;
     if (sameString(type, "interact") || sameString(type, "bigInteract"))
         return FALSE;
+    if (startsWith("bigGenePred", type) || startsWith("genePred", type))
+        return TRUE;
     }
-boolean exonNumbers = sameString(trackDbSettingOrDefault(tg->tdb, "exonNumbers", "on"), "on");
+boolean exonNumbers = sameString(trackDbSettingOrDefault(tg->tdb, "exonNumbers", "off"), "on");
 return (withExonNumbers && exonNumbers && (vis==tvFull || vis==tvPack) && (winEnd - winStart < 400000)
  && (tg->nextPrevExon==linkedFeaturesNextPrevItem));
 }
 
 void genericMapItem(struct track *tg, struct hvGfx *hvg, void *item,
 		    char *itemName, char *mapItemName, int start, int end,
 		    int x, int y, int width, int height)
 /* This is meant to be used by genericDrawItems to set to tg->mapItem in */
 /* case tg->mapItem isn't set to anything already. */
 {
 // Don't bother if we are imageV2 and a dense child.
 if (!theImgBox || tg->limitedVis != tvDense || !tdbIsCompositeChild(tg->tdb))
     {
     char *directUrl = trackDbSetting(tg->tdb, "directUrl");
     boolean withHgsid = (trackDbSetting(tg->tdb, "hgsid") != NULL);
@@ -12644,58 +12639,137 @@
 tg->nextPrevItem = linkedFeaturesLabelNextPrevItem;
 }
 
 void oregannoMethods (struct track *tg)
 /* load so can allow filtering on type */
 {
 tg->attrTable = NULL;
 tg->loadItems = loadOreganno;
 tg->itemColor = oregannoColor;
 tg->itemNameColor = oregannoColor;
 tg->nextItemButtonable = TRUE;
 tg->nextPrevItem = linkedFeaturesLabelNextPrevItem;
 }
 
 
+static char *omimGetInheritanceCode(char *inhMode)
+/* Translate inheritance mode strings into much shorter codes. */
+{
+static struct dyString *dy = NULL;  // re-use this string
+if (dy == NULL)
+    dy = dyStringNew(0);
+dyStringClear(dy);
+
+struct slName *modes = slNameListFromString(inhMode, ',');
+
+for(; modes; modes = modes->next)
+    {
+    stripChar(modes->name, '?');
+    char *mode = skipLeadingSpaces(modes->name);
+    if (sameString(mode, "Autosomal dominant"))
+        dyStringAppend(dy, "AD");
+    else if (sameString(mode, "Autosomal recessive"))
+        dyStringAppend(dy, "AR");
+    else if (sameString(mode, "X-linked"))
+        dyStringAppend(dy, "XL");
+    else if (sameString(mode, "X-linked dominant"))
+        dyStringAppend(dy, "XLD");
+    else if (sameString(mode, "X-linked recessive"))
+        dyStringAppend(dy, "XLR");
+    else if (sameString(mode, "Y-linked"))
+        dyStringAppend(dy, "YL");
+    else if (!isEmpty(mode))
+        dyStringAppend(dy, mode);
+
+    if (modes->next)
+        dyStringAppend(dy, "/");
+    }
+return dy->string;
+}
+
 static char *omimGene2DisorderList(char *name)
 /* Return list of disorders associated with a OMIM entry.  Do not free result! */
 {
 static struct dyString *dy = NULL;
 struct sqlConnection *conn;
-char query[256];
+char query[4096];
 
 if (dy == NULL)
     dy = dyStringNew(0);
 dyStringClear(dy);
 
 // get gene symbol(s) first
 conn = hAllocConn(database);
 sqlSafef(query,sizeof(query),
         "select geneSymbol from omimGeneMap2 where omimId =%s", name);
-char buf[256];
+char buf[4096];
 char *ret = sqlQuickQuery(conn, query, buf, sizeof(buf));
 if (isNotEmpty(ret))
-    dyStringAppend(dy, ret);
+    {
+    struct slName *genes = slNameListFromString(ret, ',');
+    dyStringPrintf(dy, "Gene: %s", genes->name);
+    genes = genes->next;
+    if (genes)
+        {
+        if (slCount(genes) > 1)
+            dyStringPrintf(dy, ", Synonyms: ");
+        else
+            dyStringPrintf(dy, ", Synonym: ");
+        for(; genes; genes = genes->next)
+            {
+            dyStringPrintf(dy, "%s", genes->name);
+            if (genes->next)
+                dyStringPrintf(dy, ",");
+        }
+    }
 
+    // now phenotype information
     sqlSafef(query,sizeof(query),
-        "select distinct description from omimPhenotype, omimGene2 where name='%s' and name=cast(omimId as char) order by description", name);
-char *disorders = collapseRowsFromQuery(query, "; ", 20);
-if (isNotEmpty(disorders))
+            "select GROUP_CONCAT(omimPhenotype.description, '|',inhMode  , '|',omimPhenoMapKey SEPARATOR '$') from omimGene2, omimGeneMap, omimPhenotype where omimGene2.name=omimGeneMap.omimId and omimGene2.name=omimPhenotype.omimId and omimGene2.name =%s", name);
+    ret = sqlQuickQuery(conn, query, buf, sizeof(buf));
+
+    if (ret)
         {
-    dyStringAppend(dy, "; disorder(s): ");
-    dyStringAppend(dy, disorders);
+        struct slName *phenotypes = slNameListFromString(ret, '$');
+        if (slCount(phenotypes))
+            {
+            if (slCount(phenotypes) > 1)
+                dyStringPrintf(dy, ", Phenotypes: ");
+            else
+                dyStringPrintf(dy, ", Phenotype: ");
+
+            for(; phenotypes; phenotypes = phenotypes->next)
+                {
+                struct slName *components = slNameListFromString(phenotypes->name, '|');
+                dyStringPrintf(dy, "%s", components->name);
+                components = components->next;
+
+                char *inhCode = omimGetInheritanceCode(components->name);
+                if (!isEmpty(inhCode))
+                    dyStringPrintf(dy, ", %s", inhCode);
+                components = components->next;
+
+                if (!isEmpty(components->name))
+                    dyStringPrintf(dy, ", %s", components->name);
+
+                if (phenotypes->next)
+                    dyStringPrintf(dy, "; ");
+                }
+            }
         }
+    }
+
 hFreeConn(&conn);
 return(dy->string);
 }
 
 #include "omim.h"
 
 boolean isOmimOtherClass(char *omimId)
 /* check if this omimId belongs to the "Others" phenotype class */
 
 /* NOTE: The definition of Others class is kind of tricky.
 
    The Other class is defined as:
 
 	1. does not have class 1 or 2 or 3, or 4; some may have class '-1'.
 	2. for an entry of omimId that the omimPhenotype table does not even have a row with omimId