Пример #1
0
static void transformToCanonical(struct searchResult *list,
	struct sqlConnection *conn)
/* Transform search results to canonical versions.  */
{
struct dyString *dy = newDyString(1024);
char *cannon = genomeSetting("canonicalTable");
char *isoform = genomeSetting("isoformTable");
struct sqlResult *sr;
char **row;
struct searchResult *el;
for (el = list; el != NULL; el = el->next)
    {
    dyStringClear(dy);
    sqlDyStringPrintf(dy, 
    	"select %s.transcript,%s.chrom,%s.chromStart,%s.chromEnd,%s.protein ",
	cannon, cannon, cannon, cannon, cannon);
    sqlDyStringPrintf(dy,
	"from %s,%s ",
	isoform, cannon);
    sqlDyStringPrintf(dy,
        "where %s.transcript = '%s' ",
	isoform, el->gp.name);
    sqlDyStringPrintf(dy,
        "and %s.clusterId = %s.clusterId",
	isoform, cannon);
    sr = sqlGetResult(conn, dy->string);
    if ((row = sqlNextRow(sr)) != NULL)
	genePosFillFrom5(&el->gp, row);
    sqlFreeResult(&sr);
    }
dyStringFree(&dy);
}
Пример #2
0
struct genePos *knownPosAll(struct sqlConnection *conn)
/* Get all positions in knownGene table. */
{
char query[1024];
// just for side-effect of adding NOSQLINJ prefix
if (showOnlyCanonical())
    sqlSafef(query, sizeof query, "%-s", genomeSetting("allGeneQuery"));       
else
    sqlSafef(query, sizeof query, "%-s", genomeSetting("allTranscriptQuery"));
return genePosFromQuery(conn, query, FALSE);
}
Пример #3
0
struct genePos *knownPosOne(struct sqlConnection *conn, char *name)
/* Get all positions of named gene. */
{
char query[1024];
sqlSafef(query, sizeof(query), genomeSetting("oneGeneQuery"), name);
return genePosFromQuery(conn, query, FALSE);
}
Пример #4
0
static struct genePos *findKnownAccessions(struct sqlConnection *conn, 
	char *search)
/* Return list of known accessions. */
{
search = transcriptToCanonical(conn, search);
return findGenePredPos(conn, genomeSetting("geneTable"), search);
}
Пример #5
0
static struct genePred *getCurGenePred(struct sqlConnection *conn)
/* Return current gene in genePred. */
{
char *track = genomeSetting("knownGene");
char table[HDB_MAX_TABLE_STRING];
boolean hasBin;
char query[256];
struct sqlResult *sr;
char **row;
struct genePred *gp = NULL;
if (!hFindSplitTable(sqlGetDatabase(conn), curGeneChrom, track, table, sizeof table, &hasBin))
    errAbort("track %s not found", track);
bool hasAttrId = sqlColumnExists(conn, table, "alignId");
sqlSafef(query, sizeof(query),
	"select * from %s where name = '%s' "
	"and chrom = '%s' and txStart=%d and txEnd=%d"
	, table, curGeneId, curGeneChrom, curGeneStart, curGeneEnd);
sr = sqlGetResult(conn, query);
if ((row = sqlNextRow(sr)) != NULL)
    {
    gp = genePredLoad(row + hasBin);

#define  ALIGNIDFIELD      11  // Gencode Id
    if (hasAttrId)
	curAlignId = cloneString(row[ALIGNIDFIELD]);
    else
	curAlignId = gp->name;
    }
sqlFreeResult(&sr);
if (gp == NULL)
    errAbort("getCurGenePred: Can't find %s", query);
return gp;
}
static void showMrnaFromGenePred(struct sqlConnection *conn, 
	char *geneId, char *geneName)
/* Get mRNA sequence for gene from gene prediction. */
{
char *table = genomeSetting("knownGene");
struct sqlResult *sr;
char **row;
char query[256];
boolean hasBin = hIsBinned(sqlGetDatabase(conn), table);

hPrintf("<TT><PRE>");
safef(query, sizeof(query), 
    "select * from %s where name='%s'"
    " and chrom='%s' and txStart=%d and txEnd=%d", 
    table, geneId, curGeneChrom, curGeneStart, curGeneEnd);
sr = sqlGetResult(conn, query);
if ((row = sqlNextRow(sr)) != NULL)
    {
    struct genePred *gene = genePredLoad(row+hasBin);
    struct bed *bed = bedFromGenePred(gene);
    struct dnaSeq *seq = hSeqForBed(sqlGetDatabase(conn), bed);
    hPrintf(">%s (%s predicted mRNA)\n", geneId, geneName);
    writeSeqWithBreaks(stdout, seq->dna, seq->size, 50);
    dnaSeqFree(&seq);
    bedFree(&bed);
    genePredFree(&gene);
    }
else
    errAbort("Couldn't find %s at %s:%d-%d", geneId, 
    	curGeneChrom, curGeneStart, curGeneEnd);
sqlFreeResult(&sr);
hPrintf("</TT></PRE>");
}
static void showSeq(struct sqlConnection *conn, char *geneId,
	char *geneName, char *tableId)
/* Show some sequence. */
{
char *table = genomeSetting(tableId);
showSeqFromTable(conn, geneId, geneName, table);
}
Пример #8
0
void setupColumnKnownPos(struct column *col, char *parameters)
/* Set up column that links to genome browser based on known gene
 * position. */
{
genePredPosMethods(col, genomeSetting("geneTable"));
col->cellVal = knownPosCellVal;
}
Пример #9
0
static char *transcriptToCanonical(struct sqlConnection *conn, char *transcript)
/* Translate transcript to canonical ID if possible, otherwise just return 
 * a copy of transcript. */
{
struct dyString *dy = newDyString(1024);
char *cannon = genomeSetting("canonicalTable");
char *isoform = genomeSetting("isoformTable");
char buf[128];
char *result = NULL;
sqlDyStringPrintf(dy, "select %s.transcript from %s,%s where %s.transcript = '%s'",
	       cannon, isoform, cannon, isoform, transcript);
sqlDyStringPrintf(dy, " and %s.clusterId = %s.clusterId", isoform, cannon);
result = sqlQuickQuery(conn, dy->string, buf, sizeof(buf));
if (result != NULL)
    return(cloneString(result));
else
    return(cloneString(transcript));
}
Пример #10
0
void doKgMethod()
/* display knownGene.html content (UCSC Known Genes
 * Method, Credits, and Data Use Restrictions) */
{
cartWebStart(cart, database, "Methods, Credits, and Use Restrictions");
struct trackDb *tdb = hTrackDbForTrack(database, genomeSetting("knownGene"));
hPrintf("%s", tdb->html);
cartWebEnd();
}
Пример #11
0
char *genoQuery(char *id, char *settingName, struct sqlConnection *conn)
/* Look up sql query in genome.ra given by settingName,
 * plug id into it, and return. */
{
char query[256];
char *sql = genomeSetting(settingName);
sqlSafef(query, sizeof(query), sql, id);
return sqlQuickString(conn, query);
}
Пример #12
0
struct genePos *knownPosFirst(struct sqlConnection *conn)
/* Get first gene in known gene table. */
{
char query[1024];
// just for side-effect of adding NOSQLINJ prefix
sqlSafef(query, sizeof query, "%-s", genomeSetting("allGeneQuery"));       
struct genePos *gp = genePosFromQuery(conn, query, TRUE);
return gp;
}
Пример #13
0
void webMain(struct sqlConnection *conn)
/* Set up fancy web page with hotlinks bar and
 * sections. */
{
struct section *sectionList = NULL;
printDescription(curGeneId, conn);
sectionList = loadSectionList(conn);
printIndex(sectionList);
struct trackDb *tdb = hTrackDbForTrack(database, genomeSetting("knownGene"));
printUpdateTime(database, tdb, NULL);
printSections(sectionList, conn, curGeneId);
}
Пример #14
0
static char *findGeneId(struct sqlConnection *conn, char *name)
/* Given some sort of gene name, see if it is in our primary gene table, and if not
 * look it up in alias table if we have one. */
{
/* Just check if it's in the main gene table, and if so return input name. */
char *mainTable = genomeSetting("knownGene");
char query[256];
sqlSafef(query, sizeof(query), "select count(*) from %s where name = '%s'", mainTable, name);
if (sqlQuickNum(conn, query) > 0)
    return name;
else
    {
    /* check OMIM gene symbol table first */
    if (sqlTableExists(conn, "omimGeneSymbol"))
    	{
    	sqlSafef(query, sizeof(query), "select geneSymbol from omimGeneSymbol where geneSymbol= '%s'", name);
    	char *symbol = sqlQuickString(conn, query);
    	if (symbol != NULL)
	    {
    	    sqlSafef(query, sizeof(query), "select kgId from kgXref where geneSymbol = '%s'", symbol);
    	    char *kgId = sqlQuickString(conn, query);
	    if (kgId != NULL)
	    	{
    	    	/* The canonical gene is preferred */
	        sqlSafef(query, sizeof(query), 
		"select c.transcript from knownCanonical c,knownIsoforms i where i.transcript = '%s' and i.clusterId=c.clusterId", kgId);
    	        char *canonicalKgId = sqlQuickString(conn, query);
	    	if (canonicalKgId != NULL) 
		    {
		    return canonicalKgId;
		    }
		else
                    return(kgId);
		}
	    }
	}
    }

char *alias = genomeOptionalSetting("kgAlias");
if (alias != NULL && sqlTableExists(conn, alias))
     {
     sqlSafef(query, sizeof(query), "select kgID from %s where alias = '%s'", alias, name);
     char *id = sqlQuickString(conn, query);
     if (id == NULL)
         hUserAbort("Couldn't find %s in %s.%s or %s.%s", name, database, mainTable, database, alias);
     return id;
     }
else
     hUserAbort("Couldn't find %s in %s.%s", name, database, mainTable);
return NULL;
}
void printGenomicSeqLink(struct sqlConnection *conn, char *geneId,
	char *chrom, int start, int end)
/* Figure out known genes table, position of gene, link it. */
{
char *table = genomeSetting("knownGene");
webPrintWideCellStart(3, HG_COL_TABLE);
printGenomicAnchor(table, geneId, chrom, start, end);
hPrintf("Genomic Sequence (%s:", chrom);
printLongWithCommas(stdout, start+1);
hPrintf("-");
printLongWithCommas(stdout, end);
hPrintf(")</A>");
webPrintLinkCellEnd();
}
void doOtherProteinAli(struct sqlConnection *conn, 
	char *localId, char *localName)
/* Put up page that shows alignment between this protein sequence
 * and other species. */
{
char *otherTable = cartString(cart, hggOtherPepTable);
char *otherId = cartString(cart, hggOtherId);
char *localTable = genomeSetting("knownGenePep");
bioSeq *localSeq = getSeq(conn, localTable, localId);
bioSeq *otherSeq = getSeq(conn, otherTable, otherId);

if (localSeq != NULL && otherSeq != NULL)
    {
    struct axtScoreScheme *ss = axtScoreSchemeProteinDefault();
    if (axtAffineSmallEnough(localSeq->size, otherSeq->size))
        {
	struct axt *axt = axtAffine(localSeq, otherSeq, ss);
	hPrintf("<TT><PRE>");
	if (axt != NULL)
	    {
	    printf("ID (including gaps) %3.1f%%, coverage (of both) %3.1f%%, score %d\n",
		     axtIdWithGaps(axt)*100, 
		     axtCoverage(axt, localSeq->size, otherSeq->size)*100, 
		     axt->score);
	    printf("Alignment between %s (top %s %daa) and\n",
		    localName, localSeq->name, localSeq->size);
	    printf("%s homolog (bottom %s %daa)\n",
		     otherTable, otherSeq->name, otherSeq->size);
	    printf("\n");
	    axtPrintTraditional(axt, 60, ss, stdout);
	    axtFree(&axt);
	    }
	else
	    {
	    printf("%s and %s don't align\n", localSeq->name, otherSeq->name);
	    }
	hPrintf("</PRE></TT>");
	}
    else
        {
	printf("Sorry, %s (%d amino acids) and %s (%d amino acids) are too big to align",
	    localSeq->name, localSeq->size, otherSeq->name, otherSeq->size);
	}
    }
else
    {
    warn("Couldn't get sequences, database out of sync?");
    }
}
Пример #17
0
char *getSwissProtAcc(struct sqlConnection *conn, struct sqlConnection *spConn,
	char *geneId)
/* Look up SwissProt id.  Return NULL if not found.  FreeMem this when done.
 * spConn is existing SwissProt database conn.  May be NULL. */
{
char *proteinSql = genomeSetting("proteinSql");
char query[256];
char *someAcc, *primaryAcc = NULL;
if (isRgdGene(conn))
    {
    return(getRgdGeneUniProtAcc(curGeneId, conn));
    }

sqlSafef(query, sizeof(query), proteinSql, geneId);
someAcc = sqlQuickString(conn, query);
if (someAcc == NULL || someAcc[0] == 0)
    return NULL;
primaryAcc = spFindAcc(spConn, someAcc);
freeMem(someAcc);
return primaryAcc;
}
void sequenceTablePrint(struct section *section, struct sqlConnection *conn,
	char *geneId)
/* Print the sequence table. */
{
char *table = genomeSetting("knownGene");
struct dyString *query = newDyString(0);
char **row;
struct sqlResult *sr;
char *chrom;
int start,end;

/* Print the current position. */
webPrintLinkTableStart();
printGenomicSeqLink(conn, geneId, curGeneChrom, curGeneStart, curGeneEnd);
printMrnaSeqLink(conn,geneId);
printProteinSeqLink(conn,geneId);
webPrintLinkTableEnd();

/* Print out any additional positions. */
dyStringPrintf(query, "select chrom,txStart,txEnd from %s", table);
dyStringPrintf(query, " where name = '%s'", curGeneId);
dyStringPrintf(query, " and (chrom != '%s'", curGeneChrom);
dyStringPrintf(query, " or txStart != %d", curGeneStart);
dyStringPrintf(query, " or txEnd != %d)", curGeneEnd);
sr = sqlGetResult(conn, query->string);
while ((row = sqlNextRow(sr)) != NULL)
    {
    struct sqlConnection *conn2 = hAllocConn(database);
    chrom = row[0];
    start = atoi(row[1]);
    end = atoi(row[2]);
    webPrintLinkTableStart();
    printGenomicSeqLink(conn2, geneId, chrom, start, end);
    webPrintLinkTableEnd();
    hFreeConn(&conn2);
    }
sqlFreeResult(&sr);
freeDyString(&query);
}
Пример #19
0
static void getGenePosition(struct sqlConnection *conn)
/* Get gene position from database. */
{
char *table = genomeSetting("knownGene");
char query[256];
struct sqlResult *sr;
char **row;
sqlSafef(query, sizeof(query),
    "select chrom,txStart,txEnd from %s where name = '%s'"
    , table, curGeneId);
sr = sqlGetResult(conn, query);
row = sqlNextRow(sr);
if (row != NULL)
    {
    curGeneChrom = cloneString(row[0]);
    curGeneStart = atoi(row[1]);
    curGeneEnd = atoi(row[2]);
    }
else
    hUserAbort("Couldn't find %s in %s.%s", curGeneId, database, table);
sqlFreeResult(&sr);
}
void printProteinSeqLink(struct sqlConnection *conn, char *geneId)
/* Print out link to fetch protein. */
{
char *table = genomeSetting("knownGenePep");
char query[256];
char title[128];
safef(query, sizeof(query), 
	"select length(seq) from %s where name='%s'" , table,  geneId);
int protSize = sqlQuickNum(conn, query);
if (protSize > 0)
    {
    safef(title, sizeof(title), "Protein (%d aa)", protSize);
    printSeqLink(conn, geneId, "knownGenePep", hggDoGetProteinSeq,
	    title, 1);
    }
else
    {
    webPrintLinkCellStart();
    hPrintf("No protein");
    webPrintLinkCellEnd();
    }
}
Пример #21
0
char *descriptionString(char *id, struct sqlConnection *conn)
/* return description as it would be printed in html, can free after use */
{
char *descrBySql = NULL;
char *summaryTables = genomeOptionalSetting("summaryTables");
struct dyString *description = dyStringNew(0);

descrBySql = genoQuery(id, "descriptionSql", conn);
dyStringPrintf(description, "<B>Description:</B> ");
if (descrBySql != NULL)
    dyStringPrintf(description, "%s<BR>\n", descrBySql);
else
    dyStringPrintf(description, "%s<BR>\n", "No description available");
freez(&descrBySql);
if (summaryTables != NULL)
    {
    if (sqlTablesExist(conn, summaryTables))
	{
	char *summary = genoQuery(id, "summarySql", conn);
	if (summary != NULL && summary[0] != 0)
	    {
	    summary = abbreviateSummary(summary);
	    dyStringPrintf(description, "<B>%s",
		genomeSetting("summarySource"));
	    if (genomeOptionalSetting("summaryIdSql"))
	        {
		char *summaryId = genoQuery(id, "summaryIdSql", conn);
		if (summaryId != NULL)
		    dyStringPrintf(description, " (%s)", summaryId);
		}
	    dyStringPrintf(description, ":</B> %s", summary);
	    freez(&summary);
	    dyStringPrintf(description, "<BR>\n");
	    }
	}
    }
return dyStringCannibalize(&description);
}
Пример #22
0
struct genePred *getCurGenePred(struct sqlConnection *conn)
/* Return current gene in genePred. */
{
char *track = genomeSetting("knownGene");
char table[64];
boolean hasBin;
char query[256];
struct sqlResult *sr;
char **row;
struct genePred *gp = NULL;
hFindSplitTable(sqlGetDatabase(conn), curGeneChrom, track, table, &hasBin);
sqlSafef(query, sizeof(query),
	"select * from %s where name = '%s' "
	"and chrom = '%s' and txStart=%d and txEnd=%d"
	, table, curGeneId, curGeneChrom, curGeneStart, curGeneEnd);
sr = sqlGetResult(conn, query);
if ((row = sqlNextRow(sr)) != NULL)
    gp = genePredLoad(row + hasBin);
sqlFreeResult(&sr);
if (gp == NULL)
    errAbort("getCurGenePred: Can't find %s", query);
return gp;
}
Пример #23
0
static void genePredPosPrint(struct column *col, struct genePos *gp, 
	struct sqlConnection *conn)
/* Print genome position with hyperlink to browser. */
{
char *pos = col->cellVal(col, gp, conn);
char *chrom;
int start, end;

hPrintf("<TD>");
if (pos == NULL)
    hPrintf("n/a");
else
    {
    char numBuf[32];
    hgParseChromRange(database, pos, &chrom, &start, &end);
    sprintLongWithCommas(numBuf, (start+end+1)/2);
    hPrintf("<A HREF=\"%s?db=%s&position=%s&%s&%s=full\">",
	    hgTracksName(), database, pos, cartSidUrlString(cart), genomeSetting("geneTable"));
    hPrintf("%s&nbsp;%s</A>", chrom, numBuf);
    freeMem(pos);
    }
hPrintf("</TD>");
}
static void printSeqLink(struct sqlConnection *conn, char *geneId,
	char *tableId, char *command, char *label, int colCount)
/* Print out link to mRNA or protein. */
{
char *table = genomeSetting(tableId);
boolean gotHyperlink = FALSE;
webPrintWideCellStart(colCount, HG_COL_TABLE);
if (sqlTableExists(conn, table))
    {
    char query[512];
    safef(query, sizeof(query), "select count(*) from %s where name = '%s'",
    	table, geneId);
    if (sqlExists(conn, query))
        {
	hPrintf("<A HREF=\"../cgi-bin/hgGene?%s&%s=1&hgg_gene=%s\" class=\"toc\">",
	       cartSidUrlString(cart), command, geneId);
	hPrintf("%s</A>", label);
	gotHyperlink = TRUE;
	}
    }
if (!gotHyperlink)
    hPrintf("%s", label);
webPrintLinkCellEnd();
}
Пример #25
0
void cartMain(struct cart *theCart)
/* We got the persistent/CGI variable cart.  Now
 * set up the globals and make a web page. */
{
hgBotDelay();
cart = theCart;
getDbAndGenome(cart, &database, &genome, oldVars);
initGenbankTableNames(database);
getGenomeSettings();
if (cartVarExists(cart, hggDoKgMethod))
    doKgMethod();
else if (cartVarExists(cart, hggDoTxInfoDescription))
    doTxInfoDescription();
else
    {
    struct sqlConnection *conn = NULL;
    char *geneName = cartUsualString(cart, hggGene, NULL);
    if (isEmpty(geneName))
	{
	// Silly googlebots.
	hUserAbort("Error: the hgg_gene parameter is missing from the cart and the CGI params.");
	}

    /* if kgProtMap2 table exists, this means we are doing KG III */
    if (hTableExists(database, "kgProtMap2")) kgVersion = KG_III;

    conn = hAllocConn(database);
    curGeneId = findGeneId(conn, geneName);
    getGenePosition(conn);
    curGenePred = getCurGenePred(conn);
    curGeneName = getGeneName(curGeneId, conn);
    spConn = hAllocConn(UNIPROT_DB_NAME);
    swissProtAcc = getSwissProtAcc(conn, spConn, curGeneId);

    if (isRgdGene(conn)) swissProtAcc=getRgdGeneUniProtAcc(curGeneId, conn);
    /* Check command variables, and do the ones that
     * don't want to put up the hot link bar etc. */
    if (cartVarExists(cart, hggDoGetMrnaSeq))
	doGetMrnaSeq(conn, curGeneId, curGeneName);
    else if (cartVarExists(cart, hggDoWikiTrack))
	doWikiTrack(conn);
    else if (cartVarExists(cart, hggDoGetProteinSeq))
	doGetProteinSeq(conn, curGeneId, curGeneName);
    else if (cartVarExists(cart, hggDoRnaFoldDisplay))
	doRnaFoldDisplay(conn, curGeneId, curGeneName);
    else if (cartVarExists(cart, hggDoOtherProteinSeq))
	doOtherProteinSeq(conn, curGeneName);
    else if (cartVarExists(cart, hggDoOtherProteinAli))
	doOtherProteinAli(conn, curGeneId, curGeneName);
    else
	{
	/* Default case - start fancy web page. */
	measureTiming =  isNotEmpty(cartOptionalString(cart, "measureTiming"));
        struct trackDb *tdb = hTrackDbForTrack(database, genomeSetting("knownGene"));
        isGencode = trackDbSettingOn(tdb, "isGencode");
        isGencode2 = trackDbSettingOn(tdb, "isGencode2");
	cartWebStart(cart, database, "%s Gene %s (%s) Description and Page Index",
	    genome, curGeneName, isGencode2 ? curGeneId : curAlignId);
	webMain(conn, tdb);
	cartWebEnd();
	}
    hFreeConn(&spConn);
    hFreeConn(&conn);
    }
cartRemovePrefix(cart, hggDoPrefix);
}
Пример #26
0
static void domainsPrint(struct section *section, 
	struct sqlConnection *conn, char *geneId)
/* Print out protein domains. */
{
char *db = sqlGetDatabase(conn);
struct slName *el, *list;
list = spExtDbAcc1List(spConn, swissProtAcc, "Interpro");
if (list != NULL)
    {
    char query[256], **row, **row2;
    struct sqlResult *sr, *sr2;
    hPrintf("<B>InterPro Domains: </B> ");
    hPrintf("<A HREF=\"http://www.ebi.ac.uk/interpro/protein/%s\" TARGET=_blank>",
    	swissProtAcc);
    hPrintf("Graphical view of domain structure</A><BR>");
    sqlSafef(query, sizeof(query),
    	"select extAcc1,extAcc2 from extDbRef,extDb"
	" where extDbRef.acc = '%s'"
	" and extDb.val = 'Interpro' and extDb.id = extDbRef.extDb"
	, swissProtAcc);
    sr = sqlGetResult(spConn, query);
    while ((row = sqlNextRow(sr)) != NULL)
        {
	//hPrintf("<A HREF=\"http://www.ebi.ac.uk/interpro/entry/%s\" TARGET=_blank>", row[0]);
	//hPrintf("%s</A> - %s<BR>\n", row[0], row[1]);
        char interPro[256];
        char *pdb = hPdbFromGdb(db);
        safef(interPro, 128, "%s.interProXref", pdb);
        if (hTableExists(db, interPro))
                {
                sqlSafef(query, sizeof(query),
                        "select description from %s where accession = '%s' and interProId = '%s'",
                        interPro, swissProtAcc, row[0]);
                sr2 = sqlGetResult(conn, query);
                if ((row2 = sqlNextRow(sr2)) != NULL)
                    {
                    hPrintf("<A HREF=\"http://www.ebi.ac.uk/interpro/entry/%s\" TARGET=_blank>", row[0]);
                    hPrintf("%s</A> - %s <BR>\n", row[0], row2[0]);
                    }
                sqlFreeResult(&sr2);
                }
            else
                {
                hPrintf("<A HREF=\"http://www.ebi.ac.uk/interpro/entry/%s\" TARGET=_blank>", row[0]);
                hPrintf("%s</A> - %s<BR>\n", row[0], row[1]);
                }
	}
    hPrintf("<BR>\n");
    slFreeList(&list);
    }
if (kgVersion == KG_III)
    {
    /* Do Pfam domains here. */
    list = getPfamDomainList(conn, geneId);
    if (list != NULL)
    	{
    	hPrintf("<B>Pfam Domains:</B><BR>");
    	for (el = list; el != NULL; el = el->next)
	    {
	    char query[256];
	    char *description;
	    sqlSafef(query, sizeof(query), 
	          "select description from pfamDesc where pfamAC='%s'", el->name);
	    description = sqlQuickString(conn, query);
	    if (description == NULL)
	    	description = cloneString("n/a");
	    hPrintf("<A HREF=\"http://pfam.xfam.org/family?acc=%s\" TARGET=_blank>", 
	    	    el->name);
	    hPrintf("%s</A> - %s<BR>\n", el->name, description);
	    freez(&description);
	    }
        slFreeList(&list);
        hPrintf("<BR>\n");
	}
    
    /* Do SCOP domains here */
    list = getDomainList(conn, geneId,  "Scop");
    if (list != NULL)
    	{
    	hPrintf("<B>SCOP Domains:</B><BR>");
    	for (el = list; el != NULL; el = el->next)
	    {
	    char query[256];
	    char *description;
	    sqlSafef(query, sizeof(query), 
	          "select description from scopDesc where acc='%s'", el->name);
	    description = sqlQuickString(conn, query);
	    if (description == NULL)
	    	description = cloneString("n/a");
	    hPrintf("<A HREF=\"http://scop.berkeley.edu/sunid=%s\" TARGET=_blank>", 
	    	    el->name);
	    hPrintf("%s</A> - %s<BR>\n", el->name, description);
	    freez(&description);
	    }
        slFreeList(&list);
        hPrintf("<BR>\n");
	}
    }
else
    {
    list = spExtDbAcc1List(spConn, swissProtAcc, "Pfam");
    if (list != NULL)
    	{
    	char *pfamDescSql = genomeSetting("pfamDescSql");
    	hPrintf("<B>Pfam Domains:</B><BR>");
    	for (el = list; el != NULL; el = el->next)
	    {
	    char query[256];
	    char *description;
	    sqlSafef(query, sizeof(query), pfamDescSql, el->name);
	    description = sqlQuickString(conn, query);
	    if (description == NULL)
	    	description = cloneString("n/a");
	    hPrintf("<A HREF=\"http://pfam.xfam.org/family?acc=%s\" TARGET=_blank>",
	    	        el->name);
	    hPrintf("%s</A> - %s<BR>\n", el->name, description);
	    freez(&description);
	    }
    	slFreeList(&list);
    	hPrintf("<BR>\n");
    	}
    }

list = spExtDbAcc1List(spConn, swissProtAcc, "PDB");
if (list != NULL)
    {
    struct sqlConnection *conn2 = sqlConnect(db);
    char query[256], **row;
    struct sqlResult *sr;
    int column = 0, maxColumn=3, rowCount=0;
    hPrintf("<B>Protein Data Bank (PDB) 3-D Structure</B><BR>");
    sqlSafef(query, sizeof(query),
    	"select extAcc1,extAcc2 from extDbRef,extDb"
	" where extDbRef.acc = '%s'"
	" and extDb.val = 'PDB' and extDb.id = extDbRef.extDb"
	, swissProtAcc);
    sr = sqlGetResult(spConn, query);
    hPrintf("<TABLE><TR>\n");
    while ((row = sqlNextRow(sr)) != NULL)
        {
	if (++column > maxColumn)
	    {
	    hPrintf("</TR><TR>");
	    column = 1;
	    if (rowCount == 0)
	        {
		hPrintf("<TD ALIGN=CENTER COLSPAN=4><I>To conserve bandwidth, only the images from the first %d structures are shown.</I>", maxColumn);
		hPrintf("</TR><TR>");
		}
	    ++rowCount;
	    }
	hPrintf("<TD>");
	hPrintf("<A HREF=\"http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=%s\" TARGET=_blank>", row[0]);
	if (rowCount < 1)
	    hPrintf("<IMG SRC=\"http://www.rcsb.org/pdb/images/%s_asym_r_250.jpg\"><BR>", row[0]);
        hPrintf("%s</A> - %s ", row[0], row[1]);
        // include links LS-SNP and to launch viewer in PDB chimera
        struct tempName chimerax;
        lsSnpPdbChimeraSnpAnn(conn, row[0], NULL, &chimerax);
        hPrintf(" <A HREF=\"%s\">Chimera</A>", chimerax.forHtml);
        if (lsSnpPdbHasPdb(conn2, row[0]))
            hPrintf(" <A HREF=\"%s\" TARGET=_blank>LS-SNP</A>", lsSnpPdbGetUrlPdbSnp(row[0], NULL));
	hPrintf("</TD>\n");
	}
    hPrintf("</TR></TABLE>\n");
    hPrintf("<A href=\"../goldenPath/help/chimera.html\" TARGET=_blank>Chimera help</A>\n");
    hPrintf("<BR><BR>\n");
    slFreeList(&list);
    sqlDisconnect(&conn2);
    }

/* Do modBase link. */
    {
    hPrintf("<B>ModBase Predicted Comparative 3D Structure on ");
    modBaseAnchor(swissProtAcc);
    hPrintf("%s", swissProtAcc);
    hPrintf("</A></B><BR>\n");

    hPrintf("<TABLE><TR>");
    hPrintf("<TD>");
    modBaseAnchor(swissProtAcc);
    hPrintf("\n<IMG SRC=\"https://modbase.compbio.ucsf.edu/modbase-cgi/image/modbase.jpg?database_id=%s\"></A></TD>", swissProtAcc);
    hPrintf("<TD>");
    modBaseAnchor(swissProtAcc);
    hPrintf("\n<IMG SRC=\"https://modbase.compbio.ucsf.edu/modbase-cgi/image/modbase.jpg?database_id=%s&axis=x&degree=90\"></A></TD>", swissProtAcc);
    hPrintf("<TD>");
    modBaseAnchor(swissProtAcc);
    hPrintf("\n<IMG SRC=\"https://modbase.compbio.ucsf.edu/modbase-cgi/image/modbase.jpg?database_id=%s&axis=y&degree=90\"></A></TD>", swissProtAcc);
    hPrintf("</TR><TR>\n");
    hPrintf("<TD ALIGN=CENTER>Front</TD>");
    hPrintf("<TD ALIGN=CENTER>Top</TD>");
    hPrintf("<TD ALIGN=CENTER>Side</TD>");
    hPrintf("</TR></TABLE>\n");
    hPrintf("<I>The pictures above may be empty if there is no "
            "ModBase structure for the protein.  The ModBase structure "
	    "frequently covers just a fragment of the protein.  You may "
	    "be asked to log onto ModBase the first time you click on the "
	    "pictures. It is simplest after logging in to just click on "
	    "the picture again to get to the specific info on that model.</I>");
    }
}
char *linkGetUrl(struct link *link, struct sqlConnection *conn,
	char *geneId)
/* Return URL string if possible or NULL if not.  FreeMem this when done. */
{
char query[512];
struct sqlResult *sr;
char **row;
char *url = NULL;

/* Some special case code here for things that need to
 * do more than check a table. */
if (sameString(link->name, "family"))
    {
    if (!hgNearOk(database))
        return NULL;
    }
if (sameString(link->name, "protBrowser"))
    {
    if (!hgPbOk(database))
        return NULL;
    /* special processing for PB, since we need the protein ID, instead everything key off from gene ID */
    /* use UniProt accession instead of displayID, because display ID sometimes changes */
    if (swissProtAcc == NULL || swissProtAcc[0] == 0)
        return NULL;
    if (isRgdGene(conn))
    	{
	safef(query, sizeof(query), "../cgi-bin/pbGlobal?proteinID=%s", swissProtAcc);
    	}
    else
	{
    	safef(query, sizeof(query), "../cgi-bin/pbTracks?db=%s&proteinID=%s", database, swissProtAcc);
    	}
    return(cloneString(query));
    }
if (sameString(link->name, "tbSchema"))
    {
    char *geneTable = genomeSetting("knownGene");
    struct trackDb *tdb = hTrackDbForTrack(sqlGetDatabase(conn), geneTable);
    struct dyString *dy = NULL;
    if (tdb == NULL)
	return NULL;
    dy = newDyString(256);
    dyStringPrintf(dy, link->url, tdb->grp, geneTable, geneTable);
    trackDbFree(&tdb);
    addLinkExtras(link, dy);
    return dyStringCannibalize(&dy);
    }
geneId = cloneAndCut(geneId, link->preCutAt);
safef(query, sizeof(query), link->idSql, geneId);

sr = sqlGetResult(conn, query);
row = sqlNextRow(sr);
if (row != NULL && row[0][0] != 0) /* If not null or empty */
    {
    struct dyString *dy = newDyString(0);
    char *name = cloneAndCut(row[0], link->postCutAt);
    dyStringPrintf(dy, link->url, name, row[1], row[2], row[3]);
    addLinkExtras(link, dy);
    url = dyStringCannibalize(&dy);
    freez(&name);
    }
sqlFreeResult(&sr);
freeMem(geneId);
return url;
}