e70152e44cc66cc599ff6b699eb8adc07f3e656a
kent
Sat May 24 21:09:34 2014 -0700
Adding Copyright NNNN Regents of the University of California to all files I believe with reasonable certainty were developed under UCSC employ or as part of Genome Browser copyright assignment.
diff --git src/hg/hgGene/wikiTrack.c src/hg/hgGene/wikiTrack.c
index 35b2819..8561697 100644
--- src/hg/hgGene/wikiTrack.c
+++ src/hg/hgGene/wikiTrack.c
@@ -1,510 +1,513 @@
/* wikiTrack - handle the wikiTrack section. */
+/* Copyright (C) 2013 The Regents of the University of California
+ * See README in this or parent directory for licensing information. */
+
#include "common.h"
#include "hash.h"
#include "linefile.h"
#include "dystring.h"
#include "spDb.h"
#include "web.h"
#include "hgConfig.h"
#include "hgGene.h"
#include "htmlPage.h"
#include "hgColors.h"
#include "hdb.h"
#include "binRange.h"
#include "wikiLink.h"
#include "wikiTrack.h"
static char *hgGeneUrl()
{
static char retBuf[1024];
safef(retBuf, ArraySize(retBuf), "cgi-bin/hgGene?%s=1&%s",
hggDoWikiTrack, cartSidUrlString(cart));
return retBuf;
}
static char *wikiTrackUserLoginUrl()
/* Return the URL for the wiki user login page. */
{
char *retEnc = encodedReturnUrl(hgGeneUrl);
char buf[2048];
safef(buf, sizeof(buf),
"%s/index.php?title=Special:UserloginUCSC&returnto=%s",
cfgOptionDefault(CFG_WIKI_URL, NULL), retEnc);
freez(&retEnc);
return(cloneString(buf));
}
static void offerLogin()
/* display login prompts to the wiki when user isn't already logged in */
{
char *wikiHost = wikiLinkHost();
char *loginUrl = wikiTrackUserLoginUrl();
printf("
Please login to add annotations to this UCSC gene.
\n");
printf("The login page is handled by our "
"wiki system:\n", wikiHost);
printf("click here to login.
\n", loginUrl);
printf("The wiki also serves as a forum for users "
"to share knowledge and ideas.\n
\n");
freeMem(loginUrl);
}
static struct bed *bedItem(char *chr, int start, int end, char *name,
int plusCount, int negativeCount)
{
struct bed *bb;
AllocVar(bb);
bb->chrom = chr; /* do not need to clone chr string, it is already a clone */
bb->chromStart = start;
bb->chromEnd = end;
bb->name = cloneString(name);
if ((0 == negativeCount) && (plusCount > 0))
safecpy(bb->strand, sizeof(bb->strand), "+");
else if ((0 == plusCount) && (negativeCount > 0))
safecpy(bb->strand, sizeof(bb->strand), "-");
else
safecpy(bb->strand, sizeof(bb->strand), " ");
return bb;
}
static char *canonicalGene(struct sqlConnection *conn, char *id, char **protein)
/* given UCSC gene id, find canonical UCSC gene id and protein if asked for */
{
char *geneName;
struct sqlResult *sr;
char **row;
char query[1024];
sqlSafef(query, ArraySize(query), "SELECT e.transcript,e.protein FROM "
"knownCanonical e, knownIsoforms j "
"WHERE e.clusterId = j.clusterId AND j.transcript ='%s'", id);
sr = sqlGetResult(conn, query);
row = sqlNextRow(sr);
if (row)
{
geneName = cloneString(row[0]);
if (protein)
*protein = cloneString(row[1]);
}
else
geneName = NULL;
sqlFreeResult(&sr);
return geneName;
}
static struct bed *geneCluster(struct sqlConnection *conn, char *geneSymbol,
struct bed **allIsoforms, struct bed **allProteins)
/* simple cluster of all knownGenes with name geneSymbol
* any items overlapping are clustered together
* returned answer is the cluster list
* also, if given, return full list of genes in allIsoforms
*/
{
struct sqlResult *sr;
char **row;
struct bed *bed;
struct bed *protein;
struct bed *bedList = NULL;
struct bed *proteinList = NULL;
struct bed *clustered = NULL;
char query[1024];
if (! (sqlTableExists(conn, "knownGene") && sqlTableExists(conn, "kgXref")))
{
if (allIsoforms)
*allIsoforms = NULL;
return NULL;
}
sqlSafef(query, ArraySize(query),
"SELECT e.chrom,e.txStart,e.txEnd,e.alignID,e.strand "
"FROM knownGene e, kgXref j WHERE e.alignID = j.kgID AND "
"j.geneSymbol ='%s' ORDER BY e.chrom,e.txStart", geneSymbol);
sr = sqlGetResult(conn, query);
while ((row = sqlNextRow(sr)) != NULL)
{
AllocVar(bed);
bed->chrom = cloneString(row[0]);
bed->chromStart = sqlUnsigned(row[1]);
bed->chromEnd = sqlUnsigned(row[2]);
bed->name = cloneString(row[3]);
safecpy(bed->strand, sizeof(bed->strand), row[4]);
slAddHead(&bedList, bed);
}
sqlFreeResult(&sr);
slSort(&bedList, bedCmpExtendedChr);
for (bed = bedList; bed; bed = bed->next)
{
char *swissProtAcc = getSwissProtAcc(conn, spConn, bed->name);
AllocVar(protein);
protein->chrom = cloneString(bed->chrom);
protein->chromStart = bed->chromStart;
protein->chromEnd = bed->chromEnd;
protein->name = cloneString(swissProtAcc);
slAddHead(&proteinList, protein);
}
slSort(&proteinList, bedCmpExtendedChr);
/* now cluster that list, anything overlapping collapses into one item */
int start = BIGNUM;
int end = 0;
char *prevChr = NULL;
int strandPlus = 0;
int strandNegative = 0;
for (bed = bedList; bed; bed = bed->next)
{
int txStart = bed->chromStart;
int txEnd = bed->chromEnd;
if (prevChr)
{
boolean notOverlap = TRUE;
if ((txEnd > start) && (txStart < end))
notOverlap = FALSE;
if (notOverlap || differentWord(prevChr,bed->chrom))
{
struct bed *bb = bedItem(prevChr, start, end, geneSymbol,
strandPlus, strandNegative);
slAddHead(&clustered, bb);
start = txStart;
end = txEnd;
/* do not need to freeMem(prevChr) because it is now used
* in the bed item
*/
prevChr = cloneString(bed->chrom);
strandPlus = 0;
strandNegative = 0;
}
else
{
if (start > txStart)
start = txStart;
if (end < txEnd)
end = txEnd;
}
if (differentWord(prevChr,bed->chrom))
{
freeMem(prevChr);
prevChr = cloneString(bed->chrom);
}
}
else
{
start = txStart;
end = txEnd;
prevChr = cloneString(bed->chrom);
}
if (sameWord("+",bed->strand))
++strandPlus;
if (sameWord("-",bed->strand))
++strandNegative;
}
/* and the final item is waiting to go on the list */
struct bed *bb = bedItem(prevChr, start, end, geneSymbol,
strandPlus, strandNegative);
slAddHead(&clustered, bb);
slSort(&clustered, bedCmpExtendedChr);
if (allIsoforms)
*allIsoforms = bedList;
else
bedFreeList(&bedList);
if (allProteins)
*allProteins = proteinList;
else
bedFreeList(&proteinList);
return clustered;
} /* static struct bed *geneCluster() */
static int addWikiTrackItem(char *db, char *chrom, int start, int end,
char *name, int score, char *strand, char *owner, char *class,
char *color, char *category, char *geneSymbol, char *wikiKey)
/* create new wikiTrack row with given parameters */
{
struct sqlConnection *wikiConn = wikiConnect();
struct wikiTrack *newItem;
AllocVar(newItem);
newItem->bin = binFromRange(start, end);
newItem->chrom = cloneString(chrom);
newItem->chromStart = start;
newItem->chromEnd = end;
newItem->name = cloneString(name);
newItem->score = score;
safef(newItem->strand, sizeof(newItem->strand), "%s", strand);
newItem->db = cloneString(db);
newItem->owner = cloneString(owner);
newItem->class = cloneString(class);
newItem->color = cloneString(color);
newItem->creationDate = cloneString("0");
newItem->lastModifiedDate = cloneString("0");
newItem->descriptionKey = cloneString("0");
newItem->id = 0;
newItem->geneSymbol = cloneString(geneSymbol);
wikiTrackSaveToDb(wikiConn, newItem, WIKI_TRACK_TABLE, 1024);
int id = sqlLastAutoId(wikiConn);
char descriptionKey[256];
/* when wikiKey is NULL, assign the default key of category:db-id,
* else, it is the proper key
*/
if (wikiKey)
safef(descriptionKey,ArraySize(descriptionKey), "%s", wikiKey);
else
safef(descriptionKey,ArraySize(descriptionKey),
"%s:%s-%d", category, db, id);
wikiTrackFree(&newItem);
char query[1024];
sqlSafef(query, ArraySize(query), "UPDATE %s set creationDate=now(),lastModifiedDate=now(),descriptionKey='%s' WHERE id='%d'",
WIKI_TRACK_TABLE, descriptionKey, id);
sqlUpdate(wikiConn,query);
wikiDisconnect(&wikiConn);
return (id);
}
static struct wikiTrack *startNewItem(struct sqlConnection *conn,
char *chrom, int itemStart, int itemEnd, char *name, char *strand,
struct bed *clusterList, struct bed *allIsoforms,
struct bed *allProteins)
/* create the database item to get a new one started */
{
char *userName = NULL;
int score = 0;
int id = 0;
char *description = descriptionString(curGeneId, conn);
char *aliases = aliasString(curGeneId, conn);
struct dyString *extraHeader = dyStringNew(0);
char *protein = NULL;
char *canonical = canonicalGene(conn, curGeneId, &protein);
char transcriptTag[1024];
safef(transcriptTag, ArraySize(transcriptTag), "%s", curGeneId);
if (canonical)
dyStringPrintf(extraHeader,
"Canonical gene details [http://%s/cgi-bin/hgGene?hgg_chrom=none&org=%s&db=0&hgg_gene=%s "
"%s %s]
\n",
cfgOptionDefault(CFG_WIKI_BROWSER, DEFAULT_BROWSER), genome,
canonical, name, canonical);
if ((slCount(allIsoforms) > 1) || (!canonical))
{
dyStringPrintf(extraHeader, "Other loci: ");
struct bed *el;
for (el = allIsoforms; el; el = el->next)
{
if (isNotEmpty(canonical) && sameWord(canonical,el->name))
continue;
dyStringPrintf(extraHeader,
"[http://%s/cgi-bin/hgGene?hgg_chrom=none&org=%s&db=0&hgg_gene=%s %s]",
cfgOptionDefault(CFG_WIKI_BROWSER, DEFAULT_BROWSER),
genome, el->name, el->name);
if (el->next)
dyStringPrintf(extraHeader,", ");
}
dyStringPrintf(extraHeader, "
\n");
}
dyStringPrintf(extraHeader, "%s", description);
/* add a date/time stamp to the description comments */
dyStringPrintf(extraHeader, "\n(description snapshot ~~~~~)
\n");
if (aliases)
{
dyStringPrintf(extraHeader, "%s\n", aliases);
freeMem(aliases);
}
dyStringPrintf(extraHeader, "\n
\n");
if (! wikiTrackEnabled(database, &userName))
errAbort("create new wiki item: wiki track not enabled");
if (NULL == userName)
errAbort("create new wiki item: user not logged in ?");
id = addWikiTrackItem(database, chrom, itemStart, itemEnd, name,
score, strand, userName, GENE_CLASS, "#000000",
"UCSCGeneAnnotation", name, NULL);
char wikiItemId[64];
safef(wikiItemId,ArraySize(wikiItemId),"%d", id);
struct wikiTrack *item = findWikiItemId(wikiItemId);
addDescription(item, userName, chrom, itemStart, itemEnd, cart, database,
extraHeader->string, transcriptTag, NEW_ITEM_CATEGORY);
dyStringFree(&extraHeader);
return(item);
}
static void addComments(struct sqlConnection *conn, struct wikiTrack **item,
char *userName, struct bed *clusterList, struct bed *allIsoforms,
struct bed *allProteins)
{
if (*item)
{
char transcriptTag[1024];
safef(transcriptTag, ArraySize(transcriptTag), "%s", curGeneId);
addDescription(*item, userName, curGeneChrom,
curGeneStart, curGeneEnd, cart, database, NULL, transcriptTag, NEW_ITEM_CATEGORY);
}
else
{
struct bed *el = clusterList;
*item = startNewItem(conn, el->chrom, el->chromStart, el->chromEnd,
el->name, el->strand, clusterList, allIsoforms, allProteins);
el = el->next;
for ( ; el; el = el->next)
{
(void) addWikiTrackItem(database, el->chrom, el->chromStart,
el->chromEnd, el->name, 0, el->strand, userName, GENE_CLASS, "#000000",
"UCSCGeneAnnotation", el->name, (*item)->descriptionKey);
}
}
}
void doWikiTrack(struct sqlConnection *conn)
/* display wiki track business */
{
char *userName = NULL;
struct wikiTrack *item = findWikiItemByGeneSymbol(database, curGeneName);
char title[1024];
struct bed *allIsoforms = NULL;
struct bed *allProteins = NULL;
struct bed *clusterList = geneCluster(conn, curGeneName, &allIsoforms,
&allProteins);
boolean editOK = FALSE;
safef(title,ArraySize(title), "UCSC gene annotations: %s", curGeneName);
/* we already know the wiki track is enabled since we are here,
* now calling this just to see if user is logged into the wiki
*/
if(!wikiTrackEnabled(database, &userName))
{
cartWebStart(cart, database, "%s", title);
errAbort("hgGene.doWikiTrack: called when wiki track is not enabled ?");
}
/* FALSE == do not print message */
if (isNotEmpty(userName) && emailVerified(FALSE))
editOK = TRUE;
if (editOK && cartVarExists(cart, hggDoWikiAddComment))
addComments(conn, &item, userName, clusterList, allIsoforms, allProteins);
else
cartRemove(cart, NEW_ITEM_COMMENT);
/* item exists, show wiki page */
if (item)
{
char *url = cfgOptionDefault(CFG_WIKI_URL, NULL);
puts("");
puts("\n\n");
hPrintf("\n",
url, item->descriptionKey);
puts("\n");
return;
}
cartWebStart(cart, database, "%s", title);
/* safety check, both of these lists should be non-zero */
int locusLocationCount = slCount(clusterList);
int rawListCount = slCount(allIsoforms);
if ((0 == rawListCount) || (0 == locusLocationCount))
{
hPrintf("(Feature under development, not available for "
"all genome browsers yet)
\n");
hPrintf("hgGene.doWikiTrack: can not find any genes "
"of gene symbol %s
\n",curGeneName);
cartWebEnd();
return;
}
if (isEmpty(userName))
{
if (! wikiTrackReadOnly() ) /* read-only option 2012-06-25 */
offerLogin();
}
else if (emailVerified(TRUE)) /* prints message when not verified */
{
hPrintf("