src/hg/hgGeneRing/hgGeneRing.c 1.8
1.8 2009/08/19 23:25:19 angie
Added option to mgSaveToGif and its call stack, to use GIF's Graphic Control Extension to make memgfx's background color (0) transparent. Also corrected terminology for PNG in .h files: useAlpha -> useTransparency.
Index: src/hg/hgGeneRing/hgGeneRing.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/hgGeneRing/hgGeneRing.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -b -B -U 1000000 -r1.7 -r1.8
--- src/hg/hgGeneRing/hgGeneRing.c 3 Sep 2008 19:18:53 -0000 1.7
+++ src/hg/hgGeneRing/hgGeneRing.c 19 Aug 2009 23:25:19 -0000 1.8
@@ -1,975 +1,975 @@
/* hgGeneRing - Gene Network Browser. */
#include "common.h"
#include "linefile.h"
#include "hash.h"
#include "cheapcgi.h"
#include "htmshell.h"
#include "obscure.h"
#include "web.h"
#include "cart.h"
#include "hdb.h"
#include "dbDb.h"
#include "hgFind.h"
#include "hCommon.h"
#include "hui.h"
#include "interaction.h"
#include "bdgpGeneInfo.h"
#include "portable.h"
static char const rcsid[] = "$Id$";
char *errMsg = NULL;
char *geneList = NULL;
struct slName *geneNames = NULL;
struct hash *aliasHash = NULL;
struct interaction *interactions = NULL;
struct node {
char *name; /* name or id - use also as hash key */
char *alias; /* if used */
struct nodelist *xrays; /* out-going rays in directed graph */
struct nodelist *nrays; /* in-coming rays in directed graph */
boolean ring; /* member of gene-ring? */
int ringRank; /* number of ring members connected to by x or n rays */
int xpos; /* x position */
int ypos; /* y position */
};
struct nodelist {
struct nodelist *next; /* next in list */
struct node *node;
};
struct nodelist* allNodes = NULL;
struct hash *nodeHash = NULL;
int ringCount = 0;
int insideCount = 0;
int outsideCount = 0;
struct cart *cart = NULL;
struct hash *oldVars = NULL;
char *clade = NULL;
char *organism = NULL;
char *db = NULL;
/* ------ old junk cloned from hgGateway --------- */
void hgGateway()
/* hgGateway - Human Genome Browser Gateway. */
{
char *defaultPosition = hDefaultPos(db);
char *position = cloneString(cartUsualString(cart, "position", defaultPosition));
boolean gotClade = hGotClade();
/* JavaScript to copy input data on the change genome button to a hidden form
This was done in order to be able to flexibly arrange the UI HTML
*/
char *onChangeDB = "onchange=\"document.orgForm.db.value = document.mainForm.db.options[document.mainForm.db.selectedIndex].value; document.orgForm.submit();\"";
char *onChangeOrg = "onchange=\"document.orgForm.org.value = document.mainForm.org.options[document.mainForm.org.selectedIndex].value; document.orgForm.db.value = 0; document.orgForm.submit();\"";
char *onChangeClade = "onchange=\"document.orgForm.clade.value = document.mainForm.clade.options[document.mainForm.clade.selectedIndex].value; document.orgForm.org.value = 0; document.orgForm.db.value = 0; document.orgForm.submit();\"";
if (sameString(position, "genome") || sameString(position, "hgBatch"))
position = defaultPosition;
puts(
"<FORM ACTION=\"/cgi-bin/hgTracks\" NAME=\"mainForm\" METHOD=\"GET\">\n"
"<CENTER>"
"<TABLE BGCOLOR=\"FFFEF3\" BORDERCOLOR=\"cccc99\" BORDER=0 CELLPADDING=1>\n"
"<TR><TD><FONT SIZE=\"2\">\n"
"<CENTER>\n"
"The UCSC Genome Browser was created by the \n"
"<A HREF=\"/staff.html\">Genome Bioinformatics Group of UC Santa Cruz</A>.\n"
"<BR>"
"Software Copyright (c) The Regents of the University of California.\n"
"All rights reserved.\n"
"</CENTER>\n"
"</FONT></TD></TR></TABLE></CENTER>\n"
);
puts(
"<input TYPE=\"IMAGE\" BORDER=\"0\" NAME=\"hgt.dummyEnterButton\" src=\"/images/DOT.gif\" WIDTH=1 HEIGHT=1 ALT=dot>\n"
"<center>\n"
"<table bgcolor=\"cccc99\" border=\"0\" CELLPADDING=1 CELLSPACING=0>\n"
"<tr><td>\n"
"<table BGCOLOR=\"FEFDEF\" BORDERCOLOR=\"CCCC99\" BORDER=0 CELLPADDING=0 CELLSPACING=0>\n"
"<tr><td>\n"
"<table bgcolor=\"fffef3\" border=0>\n"
"<tr>\n"
"<td>\n"
"<table><tr>");
if (gotClade)
puts("<td align=center valign=baseline>clade</td>");
puts(
"<td align=center valign=baseline>genome</td>\n"
"<td align=center valign=baseline>assembly</td>\n"
"<td align=center valign=baseline>position</td>\n"
"<td align=center valign=baseline>image width</td>\n"
"<td align=center valign=baseline> </td>\n"
"</tr>\n<tr>"
);
if (gotClade)
{
puts("<td align=center>\n");
printCladeListHtml(organism, onChangeClade);
puts("</td>\n");
}
puts("<td align=center>\n");
if (gotClade)
printGenomeListForCladeHtml(db, onChangeOrg);
else
printGenomeListHtml(db, onChangeOrg);
puts("</td>\n");
puts("<td align=center>\n");
/* HACK ALERT - Zoo needs to have different pulldown behavior - Hiram */
if ( startsWith( "Zoo", organism ) ) {
puts("<select NAME=\"db\" onchange=\"document.orgForm.db.value = document.mainForm.db.options[document.mainForm.db.selectedIndex].value; document.orgForm.submit();\">"
"\t<option SELECTED VALUE=\"zooHuman3\">June 2002</option>"
"\t</select>");
} else {
printAssemblyListHtml(db, onChangeDB);
}
puts("</td>\n");
puts("<td align=center>\n");
cgiMakeTextVar("position", addCommasToPos(position), 30);
printf("</td>\n");
#ifdef SORRY_GILL_I_HIT_INSTEAD_OF_SUBMIT_TOO_MANY_TIMES
puts("<td align=center>\n");
cgiMakeOnClickButton("document.mainForm.position.value=''","clear");
printf("</td>\n");
#endif /* SORRY_GILL_I_HIT_INSTEAD_OF_SUBMIT_TOO_MANY_TIMES */
cartSetString(cart, "position", position);
cartSetString(cart, "db", db);
cartSetString(cart, "org", organism);
if (gotClade)
cartSetString(cart, "clade", clade);
freez(&defaultPosition);
position = NULL;
puts("<td align=center>\n");
cgiMakeIntVar("pix", cartUsualInt(cart, "pix", hgDefaultPixWidth), 4);
cartSaveSession(cart);
printf("</td>\n");
printf("<td align=center>");
cgiMakeButton("Submit", "Submit");
printf("</td>\n");
puts(
"</tr></table>\n"
"</td></tr><tr><td><center>\n"
"<a HREF=\"../cgi-bin/cartReset\">Click here to reset</a> the browser user interface settings to their defaults.<BR>\n"
"</center>\n"
"</td></tr><tr><td><center>\n"
);
cgiMakeButton("customTrackPage", "Add Your Own Custom Tracks");
puts("</center>\n"
"</td></tr></table>\n"
"</td></tr></table>\n"
"</td></tr></table>\n"
);
puts("</center>");
hgPositionsHelpHtml(organism, db);
puts("</FORM>\n"
);
puts("<FORM ACTION=\"/cgi-bin/hgGateway\" METHOD=\"GET\" NAME=\"orgForm\">");
if (gotClade)
printf("<input type=\"hidden\" name=\"clade\" value=\"%s\">\n", clade);
printf("<input type=\"hidden\" name=\"org\" value=\"%s\">\n", organism);
printf("<input type=\"hidden\" name=\"db\" value=\"%s\">\n", db);
cartSaveSession(cart);
puts("</FORM><BR>");
}
/* end of hgGateway junk that this code was cloned from */
/* ----------------------------------------------------------------------- */
boolean getGenesAsList()
/* create name-list from geneString,
so that we don't have to keep re-parsing
the cart string in different places
*/
{
char* ss = cloneString(geneList);
char* s = ss;
char* w = NULL;
int c=0;
char emsg[256];
/* clean up unwanted characters if any */
subChar(ss, ',' ,' ');
subChar(ss, '\t',' ');
subChar(ss, '\n',' ');
subChar(ss, '\r',' ');
while (1)
{
if (!(w = nextWord(&s))) break;
if(slNameInList(geneNames, w))
/* could be optimized, but not expecting large lists for ring */
{
safef(emsg,sizeof(emsg), "Duplicate gene id (%s) found in list.",w);
errMsg = cloneString(emsg);
freez(&ss);
return FALSE;
}
slNameAddHead(&geneNames, w);
c++;
}
slReverse(&geneNames);
if (c==0)
{
errMsg = "No genes in list. Please specify genes for ring.";
return FALSE;
}
freez(&ss);
return TRUE;
}
void updateGeneList()
/* update the cart list of genes */
{
char *sep = "";
struct slName *sn = geneNames;
struct dyString *geneList=newDyString(512);
while(sn)
{
dyStringPrintf(geneList,"%s%s",sep,sn->name);
sep=" ";
sn=sn->next;
}
cartSetString(cart, "ring_geneList", geneList->string);
freeDyString(&geneList);
}
struct bdgpGeneInfo *bdgpGeneInfoLoadByQuery(struct sqlConnection *conn, char *query)
/* Load all interaction from table that satisfy the query given.
* Where query is of the form 'select * from example where something=something'
* or 'select example.* from example, anotherTable where example.something =
* anotherTable.something'.
* Dispose of this with bdgpGeneInfoFreeList(). */
{
struct bdgpGeneInfo *list = NULL, *el;
struct sqlResult *sr;
char **row;
sr = sqlGetResult(conn, query);
while ((row = sqlNextRow(sr)) != NULL)
{
el = bdgpGeneInfoLoad(row);
slAddHead(&list, el);
}
slReverse(&list);
sqlFreeResult(&sr);
return list;
}
void getGeneAliasesFromTable(char* table)
/* read all the gene aliases from database, return bdgpGeneInfo-list */
{
struct bdgpGeneInfo *result = NULL, *this=NULL;
struct dyString *query=newDyString(512);
char *sep = "where";
struct slName *sn = geneNames;
dyStringPrintf(query,"select * from %s",table);
while(sn)
{
char * nm = sn->name;
if (startsWith("CG",nm))
{
dyStringPrintf(query," %s bdgpName='%s'",sep,nm);
sep = "or";
}
else if (!startsWith("FBgn",nm))
{
dyStringPrintf(query," %s symbol='%s'",sep,nm);
sep = "or";
}
sn = sn->next;
}
//uglyf("<br>SQL=%s<br><br>\n",query->string);
struct sqlConnection* conn = hAllocConn();
result = bdgpGeneInfoLoadByQuery(conn, query->string);
for(this=result;this;this=this->next)
{
//uglyf("<br>adding %s=%s<br>\n",this->bdgpName,this->flyBaseId); // debug
hashAdd(aliasHash,this->bdgpName,cloneString(this->flyBaseId));
//uglyf("<br>adding %s=%s<br>\n",this->symbol,this->flyBaseId); // debug
hashAdd(aliasHash,this->symbol,cloneString(this->flyBaseId));
}
// Mysterious crashes if I free this list:
//bdgpGeneInfoFreeList(&result);
hFreeConn(&conn);
freeDyString(&query);
}
struct interaction *getGenesFromTable(char* table)
/* read all the gene interactions from database, returns interaction-list */
{
struct interaction *result = NULL;
struct dyString *query=newDyString(512);
char *sep = "where";
struct slName *sn = geneNames;
getGeneAliasesFromTable("bdgpGeneInfo"); /* load aliases into hash */
dyStringPrintf(query,"select * from %s",table);
while(sn)
{
struct hashEl *hel = NULL, *hf=NULL;
char * nm = sn->name;
char * alias = NULL;
if (!startsWith("FBgn",nm))
{
if (hf = hashLookup(aliasHash,nm))
{
alias = sn->name;
//uglyf("<br>aliasing %s with %s<br>\n",nm,(char *)hf->val); // debug
nm = (char *)hf->val;
}
}
hel = hashStore(nodeHash,nm);
if (!hel->val) /* add geneList elements to the hash */
{
struct node *n;
struct nodelist *nl;
AllocVar(n);
AllocVar(nl);
n->name = cloneString(nm);
n->alias = cloneString(alias);
n->ring = TRUE; /* this is a special ring member */
nl->node = n;
slAddHead(&allNodes,nl); /* all nodes going in hash are added to all-nodes list */
hel->val = n;
}
dyStringPrintf(query," %s fromX='%s' or toY='%s'",sep,nm,nm);
sep = "or";
sn = sn->next;
}
//uglyf("<br>SQL=%s<br><br>\n",query->string);
struct sqlConnection* conn = hAllocConn();
result = interactionLoadByQuery(conn, query->string);
hFreeConn(&conn);
freeDyString(&query);
return result;
}
void getGeneList()
/* hgGeneRing - Gene Network Browser. */
{
/* not much point in this, though called old it's the same as current
at this point. It is not the old value from before the last submit.
char *oldGeneList = hashFindVal(oldVars, "ring_geneList");
*/
if (!sameString(errMsg,""))
{
printf("<CENTER>%s</CENTER>\n",errMsg);
}
puts(
"<FORM ACTION=\"/cgi-bin/hgGeneRing\" NAME=\"mainForm\" METHOD=\"GET\">\n"
"<CENTER>"
"<TABLE BGCOLOR=\"FFFEF3\" BORDERCOLOR=\"cccc99\" BORDER=0 CELLPADDING=1>\n"
"<TR><TD><FONT SIZE=\"2\">\n"
"<CENTER>\n"
"Enter gene list for gene network ring.\n"
"</CENTER>\n"
"</FONT></TD></TR></TABLE></CENTER>\n"
);
puts(
"<center>"
"<table bgcolor=\"cccc99\" border=\"0\" CELLPADDING=1 CELLSPACING=0>\n"
"<tr>\n"
);
puts("<td align=center>\n");
cgiMakeTextArea("ring_geneList", geneList, 25, 30);
printf("</td>\n");
puts(
"</tr><tr>\n"
);
printf("<td align=center>");
cgiMakeButton("Submit", "Submit");
printf("</td>\n");
puts(
"</tr></table></center>\n"
);
puts("</FORM>\n");
cartSetString(cart, "ring_action", "saveGeneList");
cartSetString(cart, "ring_errMsg", "");
}
int compareNodes(const void *va, const void *vb)
{
const struct nodelist *a = *((struct nodelist **)va);
const struct nodelist *b = *((struct nodelist **)vb);
if (a->node->ring && !b->node->ring) return -1;
if (!a->node->ring && b->node->ring) return 1;
if (a->node->ring && b->node->ring)
{
return differentWord(a->node->name,b->node->name)*-1;
}
if (a->node->ringRank == b->node->ringRank)
{
return differentWord(a->node->name,b->node->name)*-1;
}
else
{
return (b->node->ringRank - a->node->ringRank);
}
}
boolean saveGeneList(boolean showAll)
/* Check for valid gene-list: parse and save.
If list not ok, return to getGeneList page.
Otherwise, show user's list and offer some links.
*/
{
struct interaction* intr;
struct nodelist *nl;
if (!getGenesAsList())
{
getGeneList();
return FALSE;
}
if (showAll)
{
puts(
"<center>"
"<table bgcolor=\"cccc99\" border=\"0\" CELLPADDING=1 CELLSPACING=0>\n"
"<tr><td>\n"
);
printf("geneList: %s<br>\n",
geneList
);
puts(
"</td></tr><tr><td>"
"<a href=\"/cgi-bin/hgGeneRing?ring_action=getGeneList\">gene-list</a>\n"
"</td></tr><tr><td>"
"<a href=\"/cgi-bin/hgGeneRing?ring_action=drawScreen\">screen</a>\n"
);
puts(
"</td></tr></table></center>\n"
);
}
interactions = getGenesFromTable("intrP2P"); /* adds geneList elements to hash */
if (showAll)
{
uglyf("slCount = %d for result list for %s.<br><br>\n",slCount(interactions),geneList);
}
/* this might get moved later */
/* add to hash the remaining interactions members */
for(intr=interactions;intr;intr=intr->next)
{
//uglyf("%s %s %f.<br>\n",intr->fromX,intr->toY,intr->score);
struct hashEl *helX = hashStore(nodeHash,intr->fromX);
struct hashEl *helY = hashStore(nodeHash,intr->toY);
struct node *x, *y;
struct nodelist *nl;
if (!helX->val) /* add X to hash for 1st time */
{
AllocVar(x);
AllocVar(nl);
x->name = cloneString(intr->fromX);
nl->node = x;
slAddHead(&allNodes,nl); /* add X to list of all nodes */
helX->val = x;
}
if (!helY->val) /* do same stuff for Y */
{
AllocVar(y);
AllocVar(nl);
y->name = cloneString(intr->toY);
nl->node = y;
slAddHead(&allNodes,nl);
helY->val = y;
}
x = helX->val; /* get X,Y from hash */
y = helY->val;
if (x->ring) y->ringRank++; /* increment ringRank counts */
if (y->ring) x->ringRank++;
AllocVar(nl);
nl->node = y;
slAddHead(&x->xrays,nl); /* add Y to X's list of x-rays */
AllocVar(nl);
nl->node = x;
slAddHead(&y->nrays,nl); /* likewise */
}
interactionFreeList(&interactions);
slReverse(&allNodes);
slSort(&allNodes, compareNodes);
/* sum counts and if showAll, display our structure */
if (showAll)
{
uglyf("<pre>\n");
uglyf("name xrays nrays ring? ringRank \n");
uglyf("-------------------------------------- \n");
}
for(nl=allNodes;nl;nl=nl->next)
{
if (nl->node->ring)
{
ringCount++;
}
else
{
if (nl->node->ringRank > 1)
{
insideCount++;
}
else
{
outsideCount++;
}
}
if (showAll)
{
uglyf("%11s %4d %4d %4s %3d \n",
nl->node->name,
slCount(nl->node->xrays),
slCount(nl->node->nrays),
nl->node->ring ? "ring":"not!",
nl->node->ringRank
);
}
}
if (showAll)
{
uglyf("</pre>\n");
}
// TODO: add some real code for freeing these things properly
// e.g. for xrays and nrays lists, free up the nodelist list itself,
// but not the *node values themselves, which are allocated
// in the main nodelist/hash. If the nodelist is freed up
// properly then hash freeing should be easy enough.
// Do we use valgrind or some other util to verify mem-release?
return TRUE;
}
/* Count up elements in list that are outside ring. */
int slCountOutside(void *list)
{
struct slList *pt = (struct slList *)list;
int len = 0;
while (pt != NULL)
{
struct node *n = ((struct nodelist *)pt)->node;
if ((!n->ring) && (n->ringRank==1))
len += 1;
pt = pt->next;
}
return len;
}
#define NODE_SIZE 10
void addMap(struct nodelist *nl)
{
struct node *node = nl->node;
int x=node->xpos;
int y=node->ypos;
int r=NODE_SIZE;
char *name = node->name;
if (node->alias)
{
name = node->alias;
}
printf(
"<AREA SHAPE=CIRCLE COORDS=\"%d,%d,%d\""
" HREF=\"/cgi-bin/hgGeneRing?ring_action=geneFrame&ring_gene=%s&ring_position=%s\""
" ALT=\"%s\""
" TITLE=\"%s\">",
x,y,r,
name,
node->name,
name,
name
);
}
void drawScreen()
/*
Draw Gene Ring using given genes and interactions
and display it in a page as a .gif
*/
{
#define SCREEN_SIZE 800
#define RING_SIZE 200
#define INRING_SIZE 140
#define OUTRING_SIZE 340
struct tempName filename;
int width,height;
char *mapName="ring_map";
ZeroVar(&filename);
makeTempName(&filename, "hgGeneRing_screen", ".gif");
printf("<MAP Name=%s>\n", mapName);
struct memGfx *mg = mgNew(SCREEN_SIZE,SCREEN_SIZE);
int i;
double angle=0;
int xCen = SCREEN_SIZE/2, yCen = SCREEN_SIZE/2;
int x=0,y=0;
struct nodelist *nl, *saveNl;
/* draw the main RING */
mgCircle(mg, xCen, yCen, SCREEN_SIZE/4, MG_BLACK, FALSE);
/* draw the RING genes and assign position */
angle=(M_PI*2)/ringCount;
nl=allNodes;
for(i=0;i<ringCount;i++)
{
x = xCen + (int) RING_SIZE*cos(i*angle);
y = yCen + (int) RING_SIZE*sin(i*angle);
nl->node->xpos = x;
nl->node->ypos = y;
mgCircle(mg, x, y, NODE_SIZE, MG_BLACK, FALSE);
addMap(nl);
nl=nl->next;
}
/* draw the Inside genes, assign position, and draw rays */
angle=(M_PI*2)/insideCount;
for(i=0;i<insideCount;i++)
{
x = xCen + (int) INRING_SIZE*cos((i+.5)*angle);
y = yCen + (int) INRING_SIZE*sin((i+.5)*angle);
nl->node->xpos = x;
nl->node->ypos = y;
mgCircle(mg, x, y, NODE_SIZE, MG_BLACK, FALSE);
addMap(nl);
/* draw connections to ring */
{ /*local*/
struct nodelist *l;
for(l=nl->node->xrays;l;l=l->next)
{ /* blue = inward = to-ring */
mgDrawLine(mg, x, y, l->node->xpos, l->node->ypos, MG_BLUE);
}
for(l=nl->node->nrays;l;l=l->next)
{ /* red = outward = from-ring */
mgDrawLine(mg, x, y, l->node->xpos, l->node->ypos, MG_RED);
}
}
nl=nl->next;
}
/* draw the Outside genes, assign position, draw rays
do 1 ring member at a time.
*/
angle=(M_PI*2)/ringCount;
nl=allNodes;
for(i=0;i<ringCount;i++)
{
double subAngle=0;
int numOutside=0, doneOutside=0;
numOutside += slCountOutside(nl->node->nrays);
numOutside += slCountOutside(nl->node->xrays);
subAngle = angle / (numOutside+1); /* add 1 to give a little space between ring groups */
/* draw connections to ring */
{ /*local*/
struct nodelist *l;
int j = 0;
struct nodelist *rays;
Color color;
for (j=0;j<2;j++)
{
if (j==0)
{
color = MG_BLUE;
rays = nl->node->xrays;
}
else
{
color = MG_RED;
rays = nl->node->nrays;
}
for(l=rays;l;l=l->next)
{
if (l->node->ring)
{ /* this ring-ring line gets draw twice but that's ok */
x = l->node->xpos;
y = l->node->ypos;
mgDrawLine(mg, x, y, nl->node->xpos, nl->node->ypos, MG_BLACK);
}
else if (l->node->ringRank==1)
{
doneOutside++;
x = xCen + (int) OUTRING_SIZE*cos((i-.5)*angle+(doneOutside*subAngle));
y = yCen + (int) OUTRING_SIZE*sin((i-.5)*angle+(doneOutside*subAngle));
l->node->xpos = x;
l->node->ypos = y;
mgCircle(mg, x, y, NODE_SIZE, MG_BLACK, FALSE);
addMap(l);
mgDrawLine(mg, x, y, nl->node->xpos, nl->node->ypos, color);
}
}
}
}
nl=nl->next;
}
printf("</MAP>\n");
-mgSaveGif(mg, filename.forCgi);
+mgSaveGif(mg, filename.forCgi, FALSE);
width=height=SCREEN_SIZE;
printf("<CENTER><TABLE BORDER=0 CELLPADDING=0>");
printf("<TR><TD HEIGHT=5></TD></TR>");
printf("<TR><TD><IMG SRC = \"%s\" BORDER=1 WIDTH=%d HEIGHT=%d USEMAP=#%s >",
filename.forHtml, width, height, mapName);
printf("</TD></TR>");
printf("<TR><TD HEIGHT=5></TD></TR>");
printf(
"<TR><TD>"
"<a href = \"/cgi-bin/hgGeneRing?ring_action=saveGeneList\">back</a> "
"<a href = \"/cgi-bin/hgGeneRing?ring_action=getGeneList\">gene-list</a> "
"<a href = \"/cgi-bin/hgGeneRing?ring_action=drawScreen\">refresh</a> "
"</TD></TR>");
printf("<TR><TD HEIGHT=5></TD></TR></TABLE></CENTER>");
}
char *unAlias(char *gene)
/* deal with alias mapping for gene names, return FBgn */
{
struct hashEl *hf=NULL;
if (!startsWith("FBgn",gene))
{
if (hf=hashLookup(aliasHash,gene))
{
gene=(char *)hf->val;
}
}
return gene;
}
void drawDetails()
{
char *gene = cartUsualString(cart, "ring_gene", "");
char *targ = unAlias(gene);
struct hashEl *hel = NULL;
struct node *n;
hel = hashLookup(nodeHash,targ);
if (hel)
{
n = hel->val;
printf(
"Details page for gene %s "
"<A HREF=\"/cgi-bin/hgGeneRing?ring_action=%s&ring_gene=%s\" target=\"_parent\" >"
"%s Ring</A> "
" (rank=%d) "
"<A HREF=\"/cgi-bin/hgGeneRing?ring_action=drawScreen\" target=\"_parent\" > return </A>"
"\n",
gene,
n->ring?"removeFromRing":"addToRing",
gene,
n->ring?"Remove From ":"Add To ",
n->ringRank
);
}
else
{
printf("Unknown gene %s",gene);
}
}
void hgGeneRing()
/* hgGeneRing - Gene Network Browser. */
{
char *action = cartUsualString(cart, "ring_action", "");
if (sameWord(action,""))
{
action = "getGeneList";
}
if (sameWord(action,"getGeneList"))
{
getGeneList();
}
else if (sameWord(action,"saveGeneList"))
{
saveGeneList(TRUE);
}
else if (sameWord(action,"drawScreen"))
{
if (saveGeneList(FALSE))
drawScreen();
}
else if (sameWord(action,"drawDetails"))
{
if (saveGeneList(FALSE))
drawDetails();
}
else if (sameWord(action,"addToRing"))
{
char *gene = cartUsualString(cart, "ring_gene", "");
getGenesAsList();
slNameAddTail(&geneNames, gene);
updateGeneList();
/* in lieue of actually just redirecting the browser */
cartSaveSession(cart);
geneList = cloneString(cartUsualString(cart, "ring_geneList", ""));
slFreeList(&geneNames); /* just reset everything */
if (saveGeneList(FALSE))
drawScreen();
}
else if (sameWord(action,"removeFromRing"))
{
char *gene = cartUsualString(cart, "ring_gene", "");
struct slName **psn = &geneNames;
getGenesAsList();
while(*psn)
{
if (sameString((*psn)->name,gene))
{
*psn = (*psn)->next;
break;
}
psn=&((*psn)->next);
}
updateGeneList();
/* in lieue of actually just redirecting the browser */
cartSaveSession(cart);
geneList = cloneString(cartUsualString(cart, "ring_geneList", ""));
slFreeList(&geneNames); /* just reset everything */
if (saveGeneList(FALSE))
drawScreen();
}
else
{
getGeneList();
}
}
void doMiddle(struct cart *theCart)
/* Set up pretty web display and save cart in global. */
{
char *action = cgiUsualString("ring_action", "");
cart = theCart;
getDbGenomeClade(cart, &db, &organism, &clade, oldVars);
if (! hDbIsActive(db))
{
db = hDefaultDb();
organism = hGenome(db);
clade = hClade(organism);
}
/* temporary hack, set db to dm1 fly */
db = "dm1";
organism = "D. melanogaster";
clade = "insect";
cartSetString(cart, "db", db);
cartSetString(cart, "org", organism);
cartSetString(cart, "clade", clade);
hSetDb(db);
if (sameWord(action,"geneFrame"))
{ /* special handling for frameset - can't use cartWebStart etc. */
char *gene = cartUsualString(cart, "ring_gene", "");
char *position = cartUsualString(cart, "ring_position", "");
printf(
"<frameset rows = \"18%%, *\">"
" <frame src =\"/cgi-bin/hgGeneRing?ring_action=drawDetails&ring_gene=%s\" />"
" <frame src =\"/cgi-bin/hgTracks?position=%s&db=%s\" />"
"</frameset>",
gene,
position,
db
);
}
else
{
cartWebStart(theCart, database, "%s Gene Network Browser \n", organism);
geneList = cloneString(cartUsualString(cart, "ring_geneList", ""));
errMsg = cartUsualString(cart, "ring_errMsg", ""); /* any error from last time */
hgGeneRing();
cartSaveSession(cart);
cartWebEnd();
}
freez(&geneList);
}
char *excludeVars[] = {NULL};
int main(int argc, char *argv[])
/* Process command line. */
{
oldVars = hashNew(10);
cgiSpoof(&argc, argv);
nodeHash = newHash(8);
aliasHash = newHash(8);
cartEmptyShell(doMiddle, hUserCookie(), excludeVars, oldVars);
freeHashAndVals(&nodeHash);
return 0;
}