d48268237da501db3dfe40a8712bf18ad4ff53cb
kate
  Sat Feb 1 14:09:18 2014 -0800
Support multiple canonical motifs for a TF.  Also simplify hgc code for motifs. refs #9092
diff --git src/hg/hgc/peakClusters.c src/hg/hgc/peakClusters.c
index e07fdf6..a94aaf5 100644
--- src/hg/hgc/peakClusters.c
+++ src/hg/hgc/peakClusters.c
@@ -365,153 +365,101 @@
 	tdb->track);
 printf("List all items assayed");
 printf("</A><BR>\n");
 webNewSection("Track Description");
 printTrackHtml(tdb);
 hFreeConn(&conn);
 }
 
 void doClusterMotifDetails(struct sqlConnection *conn, struct trackDb *tdb, 
                                 struct factorSource *cluster)
 /* Display details about TF binding motif(s) in cluster */
 {
 char *motifTable = trackDbSetting(tdb, "motifTable");         // localizations
 char *motifPwmTable = trackDbSetting(tdb, "motifPwmTable");   // PWM used to draw sequence logo
 char *motifMapTable = trackDbSetting(tdb, "motifMapTable");   // map target to motif
-char *motifName = cluster->name;         /* default to same as target */
+struct slName *motifNames = NULL, *mn; // list of canonical motifs for the factor
 struct dnaMotif *motif = NULL;
-struct dnaSeq **seqs = NULL;
-struct bed6FloatScore *hits = NULL;
+struct bed6FloatScore *hit = NULL, *maxHit = NULL;
 char **row;
-#ifdef SHOW_MAX_SCORE
-struct sqlResult *sr;
-#endif
-char query[256], buf[256];
+char query[256];
 
 if (motifTable != NULL && sqlTableExists(conn, motifTable))
     {
     struct sqlResult *sr;
     int rowOffset;
     char where[256];
 
-    if (motifMapTable != NULL && sqlTableExists(conn, motifMapTable))
+    if (motifMapTable == NULL || !sqlTableExists(conn, motifMapTable))
+        {
+        // Assume cluster name is motif name if there is no map table
+        motifNames = slNameNew(cluster->name);
+        }
+    else
         {
         sqlSafef(query, sizeof(query),
                 "select motif from %s where target = '%s'", motifMapTable, cluster->name);
-        // TODO: perhaps sqlQuickString ?
-        motifName = sqlQuickQuery(conn, query, buf, sizeof(buf));
-        if (motifName == NULL)
+        char *ret = sqlQuickString(conn, query);
+        if (ret == NULL)
             return;
+        motifNames = slNameListFromString(ret, ',');
         }
-    #define HIGHEST_SCORING
-    #ifdef HIGHEST_SCORING
-    sqlSafefFrag(where, sizeof(where), "name = '%s' order by score desc", motifName);
-    #else
-    sqlSafefFrag(where, sizeof(where), "name = '%s'", motifName);
-    #endif
+    for (mn = motifNames; mn != NULL; mn = mn->next)
+        {
+        sqlSafefFrag(where, sizeof(where), "name='%s' order by score desc limit 1", mn->name);
         sr = hRangeQuery(conn, motifTable, cluster->chrom, cluster->chromStart,
                      cluster->chromEnd, where, &rowOffset);
-    #ifdef HIGHEST_SCORING
         if ((row = sqlNextRow(sr)) != NULL)
-    #else
-    while ((row = sqlNextRow(sr)) != NULL)
-    #endif
             {
-        struct bed6FloatScore *hit = NULL;
-        AllocVar(hit);
-        hit->chromStart = sqlUnsigned(row[rowOffset + 1]);
-        hit->chromEnd = sqlUnsigned(row[rowOffset + 2]);
-        hit->score = sqlFloat(row[rowOffset + 4]);
-        hit->strand[0] = row[rowOffset + 5][0];
-        slAddHead(&hits, hit);
+            hit = bed6FloatScoreLoad(row + rowOffset);
+            if (maxHit == NULL || maxHit->score < hit->score)
+                maxHit = hit;
             }
         sqlFreeResult(&sr);
         }
-if (hits == NULL)
+    }
+if (maxHit == NULL)
     {
     // Maintain table layout
     webNewEmptySection();
     return;
     }
-
-int hitCount = 0;
-if (motifPwmTable != NULL && sqlTableExists(conn, motifPwmTable))
-    {
-    motif = loadDnaMotif(motifName, motifPwmTable);
-    }
-struct bed6FloatScore *hit = NULL;
-int i;
-seqs = needMem(sizeof(struct dnaSeq *) * slCount(hits));
-char posLink[1024];
-hitCount = slCount(hits);
+hit = maxHit;
 
 webNewSection("Canonical Motif in Cluster");
-
-#ifdef SHOW_MAX_SCORE
-float maxScore = -1;
-sqlSafef(query, sizeof(query), 
-    "select max(score) from %s where name = '%s'", motifTable, motifName);
-sr = sqlGetResult(conn, query);
-if ((row = sqlNextRow(sr)) != NULL)
-    {
-    if(!isEmpty(row[0]))
-        {
-        maxScore = sqlFloat(row[0]);
-        }
-    }
-sqlFreeResult(&sr);
-#endif
-
-for (hit = hits, i = 0; hit != NULL; hit = hit->next, i++)
-    {
-    struct dnaSeq *seq = hDnaFromSeq(database, 
-        seqName, hit->chromStart, hit->chromEnd, dnaLower);
-    if(hit->strand[0] == '-')
-        reverseComplement(seq->dna, seq->size);
-    seqs[i] = seq;
-    // TODO: move to hgc.c (with other pos printers)
+char posLink[1024];
 safef(posLink, sizeof(posLink),"<a href=\"%s&db=%s&position=%s%%3A%d-%d\">%s:%d-%d</a>",
         hgTracksPathAndSettings(), database, 
             cluster->chrom, hit->chromStart+1, hit->chromEnd,
             cluster->chrom, hit->chromStart+1, hit->chromEnd);
-    printf("<b>Motif Name:</b>  %s<br>\n", motifName);
+printf("<b>Motif Name:</b>  %s<br>\n", hit->name);
 printf("<b>Motif Score");
-    if (hitCount > 1)
-        {
-        printf("#%d", i + 1);
-        #ifdef SHOW_MAX_SCORE
-        printf(":</b>  %.2f (%s max: %.2f) at %s on <b>%c</font></b> strand<br>", 
-            hit->score, cluster->name, maxScore, posLink, (int)hit->strand[0]);
-        #else
-        printf(":</b>  %.2f at %s on <b>%c</font></b> strand<br>", 
-            hit->score, posLink, (int)hit->strand[0]);
-        #endif
-        }
-    else
-        {
-        #ifdef SHOW_MAX_SCORE
-        printf(":</b>  %.2f (%s max: %.2f)<br>\n", hit->score, cluster->name, maxScore);
-        #else
 printf(":</b>  %.2f<br>\n", hit->score);
-        #endif
 printf("<b>Motif Position:</b> %s<br>\n", posLink);
 printf("<b>Motif Strand:</b> %c<br>\n", (int)hit->strand[0]);
-        }
-    }
-if (seqs != NULL && motif != NULL)
+
+struct dnaSeq *seq = hDnaFromSeq(database, seqName, hit->chromStart, hit->chromEnd, dnaLower);
+if (seq == NULL)
+    return;
+if (hit->strand[0] == '-')
+    reverseComplement(seq->dna, seq->size);
+if (motifPwmTable != NULL && sqlTableExists(conn, motifPwmTable))
     {
-    motifLogoAndMatrix(seqs, hitCount, motif);
+    motif = loadDnaMotif(hit->name, motifPwmTable);
+    if (motif == NULL)
+        return;
+    motifLogoAndMatrix(&seq, 1, motif);
     }
 }
 
 void doFactorSource(struct sqlConnection *conn, struct trackDb *tdb, char *item, int start)
 /* Display detailed info about a cluster of TFBS peaks from other tracks. */
 {
 int rowOffset = hOffsetPastBin(database, seqName, tdb->table);
 char **row;
 struct sqlResult *sr;
 char query[256];
 
 sqlSafef(query, sizeof(query),
 	"select * from %s where name = '%s' and chrom = '%s' and chromStart = %d",
 	tdb->table, item, seqName, start);
 sr = sqlGetResult(conn, query);