7285e559ae48d7db239fb9161931f6d2934230bc
braney
  Wed Sep 24 10:26:02 2014 -0700
add maf SNP view to maf display
diff --git src/hg/hgTracks/wigMafTrack.c src/hg/hgTracks/wigMafTrack.c
index 90459ae..c71ec27 100644
--- src/hg/hgTracks/wigMafTrack.c
+++ src/hg/hgTracks/wigMafTrack.c
@@ -9,30 +9,31 @@
 #include "hash.h"
 #include "linefile.h"
 #include "jksql.h"
 #include "hdb.h"
 #include "hgTracks.h"
 #include "maf.h"
 #include "scoredRef.h"
 #include "wiggle.h"
 #include "hCommon.h"
 #include "hgMaf.h"
 #include "mafTrack.h"
 #include "customTrack.h"
 #include "mafSummary.h"
 #include "mafFrames.h"
 #include "phyloTree.h"
+#include "soTerm.h"
 
 
 #define GAP_ITEM_LABEL  "Gaps"
 #define MAX_SP_SIZE 2000
 
 struct wigMafItem
 /* A maf track item --
  * a line of bases (base level) or pairwise density gradient (zoomed out). */
     {
     struct wigMafItem *next;
     char *name;		/* Common name */
     char *db;		/* Database */
     int group;          /* number of species group/clade */
     int ix;		/* Position in list. */
     int height;		/* Pixel height of item. */
@@ -498,32 +499,37 @@
 {
     return mi->ix != -1;
 }
 
 static struct wigMafItem *loadPairwiseItems(struct track *track)
 /* Make up items for modes where pairwise data are shown.
    First an item for the score wiggle, then a pairwise item
    for each "other species" in the multiple alignment.
    These may be density plots (pack) or wiggles (full).
    Return item list.  Also set customPt with mafList if
    zoomed in */
 {
 struct wigMafItem *miList = NULL, *speciesItems = NULL, *mi;
 struct track *wigTrack = track->subtracks;
 int scoreHeight = tl.fontHeight * 4;
+char *snpTable = trackDbSetting(track->tdb, "snpTable");
+boolean doSnpTable = FALSE;
+if ( (track->limitedVis == tvPack) && (snpTable != NULL))
+    doSnpTable = TRUE;
 
-if (winBaseCount < MAF_SUMMARY_VIEW)
+// the maf's only get loaded if we're not in summary or snpTable views
+if (!doSnpTable && (winBaseCount < MAF_SUMMARY_VIEW))
     {
     /* "close in" display uses actual alignments from file */
     struct mafPriv *mp = getMafPriv(track);
     struct sqlConnection *conn, *conn2;
 
     if (mp->ct)
 	{
 	char *fileName = getCustomMafFile(track);
 	conn = hAllocConn(CUSTOM_TRASH);
 	conn2 = hAllocConn(CUSTOM_TRASH);
 	mp->list = wigMafLoadInRegion(conn, conn2, mp->ct->dbTableName,
 					chromName, winStart, winEnd, fileName);
 	hFreeConn(&conn);
 	hFreeConn(&conn2);
 	}
@@ -991,30 +997,145 @@
                                 int height, int seqStart, int seqEnd,
                                 struct hvGfx *hvg, int xOff, int yOff,
                                 int width, MgFont *font,
                                 Color color, Color altColor,
                                 enum trackVisibility vis)
 {
 struct sqlConnection *conn = hAllocConn(CUSTOM_TRASH);
 
 drawScoreOverviewC(conn, tableName, height, seqStart, seqEnd,
 	hvg, xOff, yOff, width, font, color, altColor, vis);
 
 hFreeConn(&conn);
 }
 
 
+static boolean drawPairsFromSnpTable(struct track *track,
+	char *snpTable,
+        int seqStart, int seqEnd,
+        struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font,
+        Color color, enum trackVisibility vis)
+/* use trackDb variable "snpTable" bed to draw this mode */
+{
+struct wigMafItem *miList = track->items, *mi = miList;
+struct sqlConnection *conn;
+struct sqlResult *sr = NULL;
+char **row = NULL;
+int rowOffset = 0;
+struct hash *componentHash = newHash(6);
+struct hashEl *hel;
+struct dyString *where = dyStringNew(256);
+char *whereClause = NULL;
+
+if (miList == NULL)
+    return FALSE;
+
+if (snpTable == NULL)
+    return FALSE;
+
+/* Create SQL where clause that will load up just the
+ * beds for the species that we are including. */
+conn = hAllocConn(database);
+dyStringAppend(where, "name in (");
+for (mi = miList; mi != NULL; mi = mi->next)
+    {
+    if (!isPairwiseItem(mi))
+	/* exclude non-species items (e.g. conservation wiggle */
+	continue;
+    dyStringPrintf(where, "'%s'", mi->db);
+    if (mi->next != NULL)
+	dyStringAppend(where, ",");
+    }
+dyStringAppend(where, ")");
+/* check for empty where clause */
+if (!sameString(where->string,"name in ()"))
+    whereClause = where->string;
+sr = hOrderedRangeQuery(conn, snpTable, chromName, seqStart, seqEnd,
+                        whereClause, &rowOffset);
+
+/* Loop through result creating a hash of lists of beds .
+ * The hash is keyed by species. */
+while ((row = sqlNextRow(sr)) != NULL)
+    {
+    struct bed *bed = bedLoadN(&row[1], 5);
+    /* prune to fit in window bounds */
+    if (bed->chromStart < seqStart)
+        bed->chromStart = seqStart;
+    if (bed->chromEnd > seqEnd)
+        bed->chromEnd = seqEnd;
+    if ((hel = hashLookup(componentHash, bed->name)) == NULL)
+        hashAdd(componentHash, bed->name, bed);
+    else
+        slAddHead(&(hel->val), bed);
+    }
+sqlFreeResult(&sr);
+hFreeConn(&conn);
+
+/* display pairwise items */
+Color yellow = hvGfxFindRgb(hvg, &undefinedYellowColor);
+for (mi = miList; mi != NULL; mi = mi->next)
+    {
+    if (mi->ix < 0)
+	/* ignore item for the score */
+	continue;
+    struct bed *bedList = (struct bed *)hashFindVal(componentHash, mi->db);
+    if (bedList == NULL)
+	bedList = (struct bed *)hashFindVal(componentHash, mi->name);
+
+    if (bedList != NULL)
+	{
+	hvGfxSetClip(hvg, xOff, yOff, width, mi->height);
+
+	struct bed *bed = bedList;
+
+	double scale = scaleForPixels(width);
+	for(; bed; bed = bed->next)
+	    {
+	    int x1 = round((bed->chromStart - seqStart)*scale);
+	    int x2 = round((bed->chromEnd - seqStart)*scale);
+	    int w = x2-x1+1;
+	    int height1 = mi->height-1;
+	    int color = MG_BLACK;
+	    switch(bed->score)
+		{
+		case 0:
+		    color = yellow;
+		    break;
+		case _5_prime_UTR_variant:
+		case _3_prime_UTR_variant:
+		case coding_sequence_variant:
+		case intron_variant:
+		case intergenic_variant:
+		    color = MG_BLUE;
+		    break;
+		case synonymous_variant:
+		    color = MG_GREEN;
+		    break;
+		case missense_variant:
+		    color = MG_RED;
+		    break;
+		}
+	    hvGfxBox(hvg, x1 + xOff, yOff, w, height1, color);
+
+	    }
+	hvGfxUnclip(hvg);
+	}
+    yOff += mi->height;
+    }
+return TRUE;
+}
+
 static boolean drawPairsFromSummary(struct track *track,
         int seqStart, int seqEnd,
         struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font,
         Color color, enum trackVisibility vis)
 {
 /* Draw pairwise display for this multiple alignment */
 char *summary;
 struct wigMafItem *miList = track->items, *mi = miList;
 struct sqlConnection *conn;
 struct sqlResult *sr = NULL;
 char **row = NULL;
 int rowOffset = 0;
 struct mafSummary *ms, *summaryList;
 struct hash *componentHash = newHash(6);
 struct hashEl *hel;
@@ -1347,33 +1468,38 @@
  * When zoomed in, use on-the-fly scoring of alignments extracted from multiple
  * When zoomed out:
  *  if "pairwise" setting is on, use pairwise tables (maf or wiggle)
  *      <species>_<suffix> for maf, <species>_<suffix>_wig for wiggle
  *              For full mode, display graph.
  *              for pack mode, display density plot.
  *  if "summary" setting is on, use maf summary table
  *      (saves space, and performs better) */
 {
     if (displayZoomedIn(track))
         return drawPairsFromMultipleMaf(track, seqStart, seqEnd, hvg,
                                         xOff, yOff, width, font, color, vis);
     if (isCustomTrack(track->table) || pairwiseSuffix(track))
         return drawPairsFromPairwiseMafScores(track, seqStart, seqEnd, hvg,
                                         xOff, yOff, width, font, color, vis);
-    if (summarySetting(track))
+    if ((winBaseCount >= MAF_SUMMARY_VIEW) && summarySetting(track))
         return drawPairsFromSummary(track, seqStart, seqEnd, hvg,
                                         xOff, yOff, width, font, color, vis);
+    char *snpTable = trackDbSetting(track->tdb, "snpTable");
+    if ( (track->limitedVis == tvPack) && (snpTable != NULL))
+        return drawPairsFromSnpTable(track, snpTable, seqStart, seqEnd, hvg,
+                                        xOff, yOff, width, font, color, vis);
+
     return FALSE;
 }
 
 static void alternateBlocksBehindChars(struct hvGfx *hvg, int x, int y,
 	int width, int height, int charWidth, int charCount,
 	int stripeCharWidth, Color a, Color b)
 /* Draw blocks that alternate between color a and b. */
 {
 int x1,x2 = x + width;
 int color = a;
 int i;
 for (i=0; i<charCount; i += stripeCharWidth)
     {
     x1 = i * width / charCount;
     x2 = (i+stripeCharWidth) * width/charCount;