2b21a977be741c62d8db2fa7869f1be0c120cf63
max
  Wed Nov 16 11:40:22 2011 -0800
display code for publications (t2g) track, most of them by larrym
diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c
index 2a60580..bea1589 100644
--- src/hg/hgTracks/simpleTracks.c
+++ src/hg/hgTracks/simpleTracks.c
@@ -18,30 +18,32 @@
 #include "hgColors.h"
 #include "trackDb.h"
 #include "bedCart.h"
 #include "wiggle.h"
 #include "lfs.h"
 #include "grp.h"
 #include "chromColors.h"
 #include "hgTracks.h"
 #include "subText.h"
 #include "cds.h"
 #include "mafTrack.h"
 #include "wigCommon.h"
 #include "hui.h"
 #include "imageV2.h"
 #include "bigBed.h"
+#include "htmshell.h"
+#include "kxTok.h"
 
 #ifndef GBROWSE
 #include "encode.h"
 #include "expRatioTracks.h"
 #include "hapmapTrack.h"
 #include "retroGene.h"
 #include "switchGear.h"
 #include "variation.h"
 #include "wiki.h"
 #include "wormdna.h"
 #include "aliType.h"
 #include "agpGap.h"
 #include "cgh.h"
 #include "bactigPos.h"
 #include "genePred.h"
@@ -12121,51 +12123,154 @@
 // end stuff copied from hgTracks.c
 enum trackVisibility trackVis = track->tdb->visibility;
 if (s != NULL)
     trackVis = hTvFromString(s);
 if (trackVis != tvHide)
     {
     track->visibility = tvDense;
     track->limitedVis = tvDense;
     track->limitedVisSet = TRUE;
     }
 track->nextItemButtonable = track->nextExonButtonable = FALSE;
 track->nextPrevItem = NULL;
 track->nextPrevExon = NULL;
 }
 
+static void tokenizeAndAddToHash(struct hash *hash, char *str)
+{
+// Pull all words out of a string and add them to an existence hash.
+char *s;
+str = htmlTextReplaceTagsWithChar(str, ' ');
+
+// strip out chars that crash kxTokenize
+for(s = str; *s; s++)
+    {
+    if(*s < 32 || !isalnum(*s))
+        *s = ' ';
+    }
+
+struct kxTok *kx = kxTokenize(str, FALSE);
+for( ; kx != NULL; kx = kx->next)
+    {
+    char *str = kx->string;
+    toLowerN(str, strlen(str));
+    hashAddInt(hash, str, 1);
+    }
+}
+
+static void t2gLoadItems(struct track *tg)
+/* apply filter to t2g items */
+{
+loadGappedBed(tg);
+struct linkedFeatures *lf, *next, *newList = NULL;
+struct sqlConnection *conn = hAllocConn(database);
+
+char *articleTable = trackDbSetting(tg->tdb, "articleTable");
+char *keyWords = cartOptionalString(cart, "t2gKeywords");
+if(articleTable != NULL && isNotEmpty(keyWords))
+    {
+    for( lf = tg->items; lf != NULL; lf = next)
+        {
+        char query[512];
+        struct sqlResult *sr;
+        char **row;
+        next = lf->next;
+        lf->next = NULL;
+
+        safef(query, sizeof(query), "select authors, title, citation, abstract from %s where displayId = '%s'", articleTable, lf->name);
+        sr = sqlGetResult(conn, query);
+        if ((row = sqlNextRow(sr)) != NULL)
+            {
+            struct hash *hash = newHash(0);
+            boolean pass = TRUE;
+            struct kxTok *kx;
+
+            tokenizeAndAddToHash(hash, row[0]);
+            tokenizeAndAddToHash(hash, row[1]);
+            tokenizeAndAddToHash(hash, row[2]);
+            tokenizeAndAddToHash(hash, row[3]);
+
+            // we pass articles where keywords is a subset of words in article metadata.
+            kx = kxTokenize(keyWords, FALSE);
+            for( ; pass && kx != NULL; kx = kx->next)
+                {
+                toLowerN(kx->string, strlen(kx->string));
+                pass = hashLookup(hash, kx->string) != NULL;
+                }
+            if(pass)
+                slAddTail(&newList, lf);
+            }
+        else
+            errAbort("Couldn't find article with displayId: '%s'", lf->name);
+        sqlFreeResult(&sr);
+        }
+    tg->items = newList;
+    }
+hFreeConn(&conn);
+}
+
+static void t2gMapItem(struct track *tg, struct hvGfx *hvg, void *item,
+				char *itemName, char *mapItemName, int start, int end,
+				int x, int y, int width, int height)
+{
+if(!theImgBox || tg->limitedVis != tvDense || !tdbIsCompositeChild(tg->tdb))
+    {
+    char query[1024], title[4096];
+    char *label = NULL;
+    char *articleTable = trackDbSetting(tg->tdb, "articleTable");
+    if(!isEmpty(articleTable))
+        {
+        struct sqlConnection *conn = hAllocConn(database);
+        safef(query, sizeof(query), "select title from %s where displayId = '%s'", articleTable, mapItemName);
+        label = sqlQuickQuery(conn, query, title, sizeof(title));
+        hFreeConn(&conn);
+        }
+    if(isEmpty(label))
+        label = mapItemName;
+    mapBoxHc(hvg, start, end, x, y, width, height, tg->track, mapItemName, label);
+    }
+}
+
+static void t2gMethods(struct track *tg)
+{
+tg->loadItems = t2gLoadItems;
+tg->mapItem = t2gMapItem;
+}
+
 
 void fillInFromType(struct track *track, struct trackDb *tdb)
 /* Fill in various function pointers in track from type field of tdb. */
 {
 char *typeLine = tdb->type, *words[8], *type;
 int wordCount;
 if (typeLine == NULL)
     return;
 wordCount = chopLine(cloneString(typeLine), words);
 if (wordCount <= 0)
     return;
 type = words[0];
 
 #ifndef GBROWSE
 if (sameWord(type, "bed"))
     {
     complexBedMethods(track, tdb, FALSE, wordCount, words);
     /* bed.h includes genePred.h so should be able to use these trackDb
        settings. */
     if (trackDbSetting(track->tdb, GENEPRED_CLASS_TBL) !=NULL)
         track->itemColor = genePredItemClassColor;
+    if (startsWith("t2g", track->table))
+        t2gMethods(track);
     }
 /*
 else if (sameWord(type, "bedLogR"))
     {
     wordCount++;
     words[1] = "9";
     complexBedMethods(track, tdb, FALSE, wordCount, words);
     //track->bedSize = 10;
     }
     */
 else if (sameWord(type, "bigBed"))
     {
     bigBedMethods(track, tdb, wordCount, words);
     if (trackShouldUseAjaxRetrieval(track))
         track->loadItems = dontLoadItems;