41460d9448c20807b3f2589a198ca1dc26481861
angie
  Wed Jul 23 13:23:37 2014 -0700
SNP tracks have an option to include orthologous chimp allele andobserved alleles in the item names.  So far, this option has been
offered only when there is an ortho table for the SNP track, and
alleles have been included only when a chimp allele is found.
However, for comparison with other annotations, it is useful to
see observed alleles even when chimp alleles aren't available.
Now, if there is no ortho table, the option to include just observed
alleles is given.  If enabled, then when there is no ortho table, or
no ortho allele for a particular SNP, observed alleles are added to
the item name.

diff --git src/hg/hgTracks/variation.c src/hg/hgTracks/variation.c
index b5e6bb9..d6229f1 100644
--- src/hg/hgTracks/variation.c
+++ src/hg/hgTracks/variation.c
@@ -444,98 +444,120 @@
 struct bed4 *b = *((struct bed4 **)vb);
 int dif;
 
 if(a==0||b==0)
     return 0;
 dif = differentWord(a->chrom, b->chrom);
 if (dif == 0)
     dif = a->chromStart - b->chromStart;
 if (dif == 0)
     dif = a->chromEnd - b->chromEnd;
 if (dif == 0)
     dif = differentWord(a->name, b->name);
 return dif;
 }
 
+static char *snp125ExtendName(char *rsId, char *chimpAllele, char *observedAlleles)
+/* Allocate and return a string of the format "rsId chimpAllele>observedAlleles" if
+ * chimpAllele is non-empty, otherwise "rsId observedAlleles". */
+{
+struct dyString *dy = dyStringNew(64);
+if (isNotEmpty(chimpAllele))
+    dyStringPrintf(dy, "%s %s>%s", rsId, chimpAllele, observedAlleles);
+else
+    dyStringPrintf(dy, "%s %s", rsId, observedAlleles);
+return dyStringCannibalize(&dy);
+}
+
+static void setSnp125ExtendedNameObserved(struct snp125 *snpList)
+/* Append observed alleles to each snp's name. */
+{
+struct snp125 *snpItem = snpList;
+for (;  snpItem != NULL;  snpItem = snpItem->next)
+    snpItem->name = snp125ExtendName(snpItem->name, NULL, snpItem->observed);
+}
+
 void setSnp125ExtendedNameExtra(struct track *tg)
 /* add extra text to be drawn in snp name field.  This works by
    walking through two sorted lists and updating the name value
    for the SNP list with data from a table of orthologous state
    information */
 {
 char cartVar[512];
     safef(cartVar, sizeof(cartVar), "%s.extendedNames", tg->tdb->track);
 boolean enabled = cartUsualBoolean(cart, cartVar,
 			  // Check old cart var name for backwards compatibility w/ old sessions:
 				   cartUsualBoolean(cart, "snp125ExtendedNames", FALSE));
 if (!enabled)
     return;
 struct sqlConnection *conn          = hAllocConn(database);
 int                   rowOffset     = 0;
 char                **row           = NULL;
 struct orthoBed      *orthoItemList = NULL;      /* list of orthologous state info */
 struct orthoBed      *orthoItem     = orthoItemList;
 char                 *orthoTable    = snp125OrthoTable(tg->tdb, NULL);
 struct sqlResult     *sr            = NULL;
 int                   cmp           = 0;
-struct dyString      *extra         = newDyString(256);
 
-/* if orthologous info is not available, don't add it! */
+/* if orthologous info is not available, show only observed alleles */
 if(isEmpty(orthoTable) || !sqlTableExists(conn, orthoTable))
     {
+    setSnp125ExtendedNameObserved((struct snp125 *)tg->items);
     hFreeConn(&conn);
     return;
     }
 /* get list of orthologous alleles */
 sr = hRangeQuery(conn, orthoTable, chromName, winStart, winEnd, NULL, &rowOffset);
 while ((row = sqlNextRow(sr)) != NULL)
     {
     orthoItem = orthoBedLoad(row + rowOffset);
     if (orthoItem)
         slAddHead(&orthoItemList, orthoItem);
     }
 
 /* List of SNPs is already sorted, so sort list of Ortho info */
 slSort(&orthoItemList, snpOrthoCmp);
 
 /* Walk through two sorted lists together */
 struct snp125 *snpItem = tg->items;
 orthoItem = orthoItemList;
 while (snpItem!=NULL && orthoItem!=NULL)
     {
     /* check to see that we're not at the end of either list and that
      * the two list elements represent the same human position */
     cmp = snpOrthoCmp(&snpItem, &orthoItem);
     if (cmp < 0)
         {
+	// Update snp->name with observed alleles even if we don't have ortho data
+	snpItem->name = snp125ExtendName(snpItem->name, NULL, snpItem->observed);
 	snpItem = snpItem->next;
 	continue;
 	}
     if (cmp > 0)
         {
 	orthoItem = orthoItem->next;
 	continue;
 	}
     /* update the snp->name with the ortho data */
-    dyStringPrintf(extra, "%s %s>%s", snpItem->name, orthoItem->chimp, snpItem->observed);
-    snpItem->name = cloneString(extra->string);
-    dyStringClear(extra);
+    snpItem->name = snp125ExtendName(snpItem->name, orthoItem->chimp, snpItem->observed);
     /* increment the list pointers */
     snpItem = snpItem->next;
     orthoItem = orthoItem->next;
     }
-freeDyString(&extra);
+// If orthoItemList ends before snpItemList, add observed alleles to remaining snps:
+if (snpItem != NULL)
+    setSnp125ExtendedNameObserved(snpItem);
 sqlFreeResult(&sr);
 hFreeConn(&conn);
 }
 
 static char *snp125MapItemName(struct track *tg, void *item)
 /* Now that snp125->name is overwritten when adding chimp allele suffix, we need
  * to strip it back off for links to hgc. */
 {
 static char mapName[256];
 struct snp125 *snp = item;
 safecpy(mapName, sizeof(mapName), snp->name);
 char *ptr = strchr(mapName, ' ');
 if (ptr != NULL)
     *ptr = '\0';
 return mapName;