b50a4586bd9b4cf56a85705bd1b00b415803b5ab
kent
  Fri May 11 07:21:49 2012 -0700
Adding support for IUPAC nucleotide ambiguity codes to 'short match' track.  Made iupac.c library module.
diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index 16e8e81..63d83c1 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -45,30 +45,31 @@
 #include "hubConnect.h"
 #include "cytoBand.h"
 #include "ensFace.h"
 #include "liftOver.h"
 #include "pcrResult.h"
 #include "wikiLink.h"
 #include "jsHelper.h"
 #include "mafTrack.h"
 #include "hgConfig.h"
 #include "encode.h"
 #include "agpFrag.h"
 #include "imageV2.h"
 #include "suggest.h"
 #include "search.h"
 #include "errCatch.h"
+#include "iupac.h"
 
 
 /* Other than submit and Submit all these vars should start with hgt.
  * to avoid weeding things out of other program's namespaces.
  * Because the browser is a central program, most of it's cart
  * variables are not hgt. qualified.  It's a good idea if other
  * program's unique variables be qualified with a prefix though. */
 char *excludeVars[] = { "submit", "Submit", "dirty", "hgt.reset",
             "hgt.in1", "hgt.in2", "hgt.in3", "hgt.inBase",
             "hgt.out1", "hgt.out2", "hgt.out3",
             "hgt.left1", "hgt.left2", "hgt.left3",
             "hgt.right1", "hgt.right2", "hgt.right3",
             "hgt.dinkLL", "hgt.dinkLR", "hgt.dinkRL", "hgt.dinkRR",
             "hgt.tui", "hgt.hideAll", "hgt.visAllFromCt",
 	    "hgt.psOutput", "hideControls", "hgt.toggleRevCmplDisp",
@@ -957,110 +958,116 @@
 tdb->canPack = tg->canPack;
 trackDbPolish(tdb);
 addUserSeqBaseAndIndelSettings(tdb);
 tg->tdb = tdb;
 return tg;
 }
 
 char *oligoMatchSeq()
 /* Return sequence for oligo matching. */
 {
 char *s = cartOptionalString(cart, oligoMatchVar);
 if (s != NULL)
     {
     int len;
     tolowers(s);
-    dnaFilter(s, s);
+    iupacFilter(s, s);
     len = strlen(s);
     if (len < 2)
        s = NULL;
     }
 if (s == NULL)
     s = cloneString(oligoMatchDefault);
 return s;
 }
 
 char *oligoMatchName(struct track *tg, void *item)
 /* Return name for oligo, which is just the base position. */
 {
 struct bed *bed = item;
 static char buf[22];
 buf[0] = bed->strand[0];
 sprintLongWithCommas(buf+1, bed->chromStart+1);
 return buf;
 }
 
 char *dnaInWindow()
 /* This returns the DNA in the window, all in lower case. */
 {
 static struct dnaSeq *seq = NULL;
 if (seq == NULL)
     seq = hDnaFromSeq(database, chromName, winStart, winEnd, dnaLower);
 return seq->dna;
 }
 
+char *stringInWrapper(char *needle, char *haystack)
+/* Wrapper around string in to make it so it's a function rather than a macro. */
+{
+return stringIn(needle, haystack);
+}
 
 void oligoMatchLoad(struct track *tg)
 /* Create track of perfect matches to oligo on either strand. */
 {
 char *dna = dnaInWindow();
 char *fOligo = oligoMatchSeq();
+char *(*finder)(char *needle, char *haystack) = (anyIupac(fOligo) ? iupacIn : stringInWrapper);
 int oligoSize = strlen(fOligo);
 char *rOligo = cloneString(fOligo);
 char *rMatch = NULL, *fMatch = NULL;
 struct bed *bedList = NULL, *bed;
 char strand;
 int count = 0, maxCount = 1000000;
 
 if (oligoSize >= 2)
     {
-    fMatch = stringIn(fOligo, dna);
-    reverseComplement(rOligo, oligoSize);
+    fMatch = finder(fOligo, dna);
+    iupacReverseComplement(rOligo, oligoSize);
     if (sameString(rOligo, fOligo))
         rOligo = NULL;
     else
-    rMatch = stringIn(rOligo, dna);
+	rMatch = finder(rOligo, dna);
     for (;;)
         {
 	char *oneMatch = NULL;
 	if (rMatch == NULL)
 	    {
 	    if (fMatch == NULL)
 		break;
 	    else
 		{
 		oneMatch = fMatch;
-		fMatch = stringIn(fOligo, fMatch+1);
+		fMatch = finder(fOligo, fMatch+1);
 		strand = '+';
 		}
 	    }
 	else if (fMatch == NULL)
 	    {
 	    oneMatch = rMatch;
-	    rMatch = stringIn(rOligo, rMatch+1);
+	    rMatch = finder(rOligo, rMatch+1);
 	    strand = '-';
 	    }
 	else if (rMatch < fMatch)
 	    {
 	    oneMatch = rMatch;
-	    rMatch = stringIn(rOligo, rMatch+1);
+	    rMatch = finder(rOligo, rMatch+1);
 	    strand = '-';
 	    }
 	else
 	    {
 	    oneMatch = fMatch;
-	    fMatch = stringIn(fOligo, fMatch+1);
+	    fMatch = finder(fOligo, fMatch+1);
 	    strand = '+';
 	    }
 	if (count < maxCount)
 	    {
 	    ++count;
 	    AllocVar(bed);
 	    bed->chromStart = winStart + (oneMatch - dna);
 	    bed->chromEnd = bed->chromStart + oligoSize;
 	    bed->strand[0] = strand;
 	    slAddHead(&bedList, bed);
 	    }
 	else
 	    break;
 	}
     slReverse(&bedList);