src/hg/gsid/gsidTable/gsidTable.c 1.42
1.42 2009/08/06 17:24:49 fanhsu
Added logic to handle missing immuno data.
Index: src/hg/gsid/gsidTable/gsidTable.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/gsid/gsidTable/gsidTable.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -b -B -U 1000000 -r1.41 -r1.42
--- src/hg/gsid/gsidTable/gsidTable.c 17 Sep 2008 16:13:22 -0000 1.41
+++ src/hg/gsid/gsidTable/gsidTable.c 6 Aug 2009 17:24:49 -0000 1.42
@@ -1,1656 +1,1764 @@
/* gsidTable - GSID Table View */
#include "common.h"
#include "dystring.h"
#include "hash.h"
#include "obscure.h"
#include "cheapcgi.h"
#include "memalloc.h"
#include "jksql.h"
#include "htmshell.h"
#include "cart.h"
#include "hPrint.h"
#include "hdb.h"
#include "hui.h"
#include "web.h"
#include "ra.h"
#include "hgColors.h"
#include "trashDir.h"
#include "gsidTable.h"
#include "versionInfo.h"
static char const rcsid[] = "$Id$";
char *excludeVars[] = { "submit", "Submit", "submit_filter", NULL };
/* The excludeVars are not saved to the cart. (We also exclude
* any variables that start "near.do.") */
/* ---- Global variables. ---- */
struct cart *cart; /* This holds cgi and other variables between clicks. */
char *database; /* Name of genome database - hg15, mm3, or the like. */
char *genome; /* Name of genome - mouse, human, etc. */
char *orderOn; /* Current sorting column name. */
int displayCount; /* Number of items to display. */
char *displayCountString; /* Ascii version of display count, including 'all'. */
struct hash *oldCart; /* Old cart hash. */
struct hash *columnHash; /* Hash of active columns keyed by name. */
int passedFilterCount; /* number of subjects passing filter */
struct sqlConnection *conn;
struct column *colList, *col;
void controlPanelStart()
/* Put up start of tables around a control panel. */ {
hPrintf("<TABLE WIDTH=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=4><TR><TD ALIGN=CENTER>");
hPrintf("<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=0 BGCOLOR=\"#"HG_COL_BORDER"\"><TR><TD>");
hPrintf("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 BGCOLOR=\""HG_COL_INSIDE"\"><TR><TD>\n");
hPrintf("<TABLE BORDER=0 CELLSPACING=1 CELLPADDING=1><TR><TD>");
}
void controlPanelEnd()
/* Put up end of tables around a control panel. */
{
hPrintf("</TD></TR></TABLE>");
hPrintf("</TD></TR></TABLE>");
hPrintf("</TD></TR></TABLE>");
hPrintf("</TD></TR></TABLE>");
}
static void mainControlPanel()
/* Make control panel. */
{
controlPanelStart();
/* advFilter, configure buttons */
{
cgiMakeButton(confVarName, "configure");
hPrintf(" ");
if (gotAdvFilter())
cgiMakeButton(advFilterVarName, "filter (now on)");
else
cgiMakeButton(advFilterVarName, "filter (now off)");
hPrintf(" ");
}
/* Do items to display drop-down */
{
int i=0;
static char *menu[] = {"25", "50", "100", "200", "500", "1000", "all"};
hPrintf(" display ");
hPrintf("<SELECT NAME=\"%s\"", countVarName);
hPrintf(" onchange=\"document.mainForm.submit();\">\n");
for (i = 0; i < ArraySize(menu); ++i)
{
hPrintf("<OPTION VALUE=\"%s\"", menu[i]);
if (sameString(menu[i], displayCountString))
hPrintf(" SELECTED");
hPrintf(">%s\n", menu[i]);
}
hPrintf("</SELECT>\n");
}
/* Make getDna, getText buttons */
{
hPrintf(" output ");
cgiMakeOptionalButton(getSeqPageVarName, "sequence", FALSE);
hPrintf(" ");
cgiMakeOptionalButton(getTextVarName, "text", FALSE);
}
controlPanelEnd();
}
void makeTitle(char *title, char *helpName)
/* Make title bar. */
{
hPrintf("<TABLE WIDTH=\"100%%\" BGCOLOR=\"#"HG_COL_HOTLINKS"\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"2\"><TR>\n");
hPrintf("<TD ALIGN=LEFT><A HREF=\"/index.html\">%s</A></TD>", wrapWhiteFont("Home"));
hPrintf("<TD ALIGN=CENTER><FONT COLOR=\"#FFFFFF\" SIZE=4>%s</FONT></TD>", title);
hPrintf("<TD ALIGN=Right>%s", wrapWhiteFont(""));
hPrintf("</TR></TABLE>");
}
int totalHtmlColumns(struct column *colList)
/* Count up columns in big-table html. */
{
int count = 0;
struct column *col;
for (col = colList; col != NULL; col = col->next)
{
if (col->on)
count += col->tableColumns(col);
}
return count;
}
void bigTable(struct sqlConnection *conn, struct column *colList,
struct subjInfo *siList)
/* Put up great big table. */
{
struct column *col;
struct subjInfo *si;
if (siList == NULL)
{
if (gotAdvFilter())
{
warn("No subjects passed filter.");
}
return;
}
hPrintf("<CENTER>");
hPrintf("<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1 COLS=%d BGCOLOR=\"#"HG_COL_INSIDE"\">\n",
totalHtmlColumns(colList));
/* Print label row. */
hPrintf("<TR BGCOLOR=\"#"HG_COL_HEADER"\">");
for (col = colList; col != NULL; col = col->next)
{
if (col->on)
{
col->labelPrint(col);
}
}
hPrintf("</TR>\n");
/* Print other rows. */
hPrintf("<!-- Start Rows -->");
for (si = siList; si != NULL; si = si->next)
{
hPrintf("<TR>");
for (col = colList; col != NULL;
col = col->next)
{
if (col->on)
{
if (col->cellPrint == NULL)
hPrintf("<TD></TD>");
else
col->cellPrint(col,si,conn);
}
}
hPrintf("</TR><!-- Row -->\n");
if (ferror(stdout))
errAbort("Write error to stdout");
}
hPrintf("<!-- End Rows -->");
hPrintf("</TABLE>\n");
hPrintf("<BR>Displayed %d out of %d subjects passing filter.",
slCount(siList), passedFilterCount);
hPrintf("</CENTER>");
}
void doGetText(struct sqlConnection *conn, struct column *colList,
struct subjInfo *subjList)
/* Put up great big table. */
{
struct subjInfo *si;
struct column *col;
boolean first = TRUE;
char *chp, *chp9;
if (subjList == NULL)
{
hPrintf("empty table");
return;
}
hPrintf("<TT><PRE>");
/* Print labels. */
hPrintf("#");
for (col = colList; col != NULL; col = col->next)
{
if (col->on)
{
if (first)
first = FALSE;
else
hPrintf("\t");
hPrintf("%s", col->shortLabel);
}
}
hPrintf("\n");
for (si = subjList; si != NULL; si = si->next)
{
first = TRUE;
for (col = colList; col != NULL; col = col->next)
{
if (col->on)
{
boolean special;
char *val = col->cellVal(col, si, conn);
if (first)
first = FALSE;
else
hPrintf("\t");
if (val == NULL)
hPrintf("n/a");
else
{
special = FALSE;
if (sameWord(col->name, "cd4Count"))
{
if (sameWord(val, "-1") || sameWord(val, "0"))
{
hPrintf("N/A");
special = TRUE;
}
}
if (sameWord(col->name, "hivQuan"))
{
if (sameWord(val, "-1"))
{
hPrintf("N/A");
special = TRUE;
}
}
if (sameWord(col->name, "DAEI"))
{
if (sameWord(val, "-1"))
{
hPrintf("N/A");
special = TRUE;
}
}
if (sameWord(col->name, "esdi"))
{
if (sameWord(val, "-1"))
{
hPrintf("N/A");
special = TRUE;
}
}
if (sameWord(col->name, "hivQuan"))
{
if (sameWord(val, "1000000"))
{
hPrintf("> 1000000");
special = TRUE;
}
}
if (sameWord(col->name, "hivQuan"))
{
if (sameWord(val, "200"))
{
hPrintf("< 400");
special = TRUE;
}
}
if ((sameWord(col->name, "dnaSeqs")) || (sameWord(col->name, "aaSeqs")))
{
chp = val;
chp = strstr(chp, "#35;");
while (chp != NULL)
{
chp = chp +strlen("#35;");
chp9 = strstr(chp, " ");
*chp9 = '\0';
hPrintf("%s ", chp);
chp9++;
chp = strstr(chp9, "#35;");
}
special = TRUE;
}
if (!special)
{
hPrintf("%s", val);
}
}
freez(&val);
}
}
hPrintf("\n");
}
hPrintf("</PRE></TT>");
}
void hotLinks()
/* Put up the hot links bar. */
{
hPrintf("<TABLE WIDTH=\"100%%\" BGCOLOR=\"#000000\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"1\"><TR><TD>\n");
hPrintf("<TABLE WIDTH=\"100%%\" BGCOLOR=\"#2636D1\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"2\"><TR>\n");
/* Home */
hPrintf("<TD ALIGN=CENTER><A HREF=\"/index.html\" class=\"topbar\"><FONT COLOR=\"#FFFFFF\">Home</FONT></A></TD>");
//, orgEnc);
/* Blat */
hPrintf("<TD ALIGN=CENTER><A HREF=\"../cgi-bin/hgBlat?command=start\" class=\"topbar\"><FONT COLOR=\"#FFFFFF\">Blat</FONT></A></TD>");
/* Subject View */
hPrintf("<TD ALIGN=CENTER><A HREF=\"../cgi-bin/gsidSubj\" class=\"topbar\">%s</A></TD>", "<FONT COLOR=\"#FFFFFF\">Subject View</FONT>");
/* Sequence View */
hPrintf("<TD ALIGN=CENTER><A HREF=\"../cgi-bin/hgGateway?db=%s\" class=\"topbar\"><FONT COLOR=\"#FFFFFF\">Sequence View Gateway</FONT></A></TD>", database);
/* Help */
if (cartVarExists(cart, advFilterVarName))
{
hPrintf("<TD ALIGN=CENTER><A HREF=\"/goldenPath/help/gsidTutorial.html#SelectSubject\" TARGET=_blank class=\"topbar\"><FONT COLOR=\"#FFFFFF\">Help</FONT></A></TD>");
}
else
{
hPrintf("<TD ALIGN=CENTER><A HREF=\"/goldenPath/help/gsidTutorial.html#TableView\" TARGET=_blank class=\"topbar\"><FONT COLOR=\"#FFFFFF\">Help</FONT></A></TD>");
}
hPuts("</TR></TABLE>");
hPuts("</TD></TR></TABLE>\n");
}
void doMainDisplay(struct sqlConnection *conn,
struct column *colList, struct subjInfo *subjList)
/* Put up the main gene sorter display - a control panel followed by
* a big table. */
{
char buf[128];
safef(buf, sizeof(buf), "GSID %s Table View", genome);
hPrintf("<FORM ACTION=\"../cgi-bin/gsidTable\" NAME=\"mainForm\" METHOD=GET>\n");
hotLinks();
cartSaveSession(cart);
printf("<font size=5><B>Table View</B></font>");
mainControlPanel();
if (subjList != NULL)
+ {
+printf("Use the \"configure\" button above to access additional data fields, including infection date details, sequencing and ART date information, <BR>and immunogenicity data.");
bigTable(conn, colList,subjList);
-
+ }
printf("<br>* Estimated Study Day of Infection (ESDI), ");
printf("click <a href=\"http://www.gsid.org/downloads/methods_and_conventions.pdf\" target=_blank> here </a>");
printf(" for further explanation.\n");
printf("<br>* Days After Estimated Infection (DAEI), ");
printf("click <a href=\"http://www.gsid.org/downloads/methods_and_conventions.pdf\" target=_blank> here </a>");
printf(" for further explanation.\n");
hPrintf("</FORM>\n");
}
char *mustFindInRaHash(char *fileName, struct hash *raHash, char *name)
/* Look up in ra hash or die trying. */
{
char *val = hashFindVal(raHash, name);
if (val == NULL)
errAbort("Missing required %s field in %s", name, fileName);
return val;
}
/* ---- Some helper routines for column methods. ---- */
boolean anyWild(char *s)
/* Return TRUE if there are '?' or '*' characters in s. */
{
return strchr(s, '?') != NULL || strchr(s, '*') != NULL;
}
boolean wildMatchAny(char *word, struct slName *wildList)
/* Return TRUE if word matches any thing in wildList. */
{
struct slName *w;
for (w = wildList; w != NULL; w = w->next)
if (wildMatch(w->name, word) )
return TRUE;
return FALSE;
}
boolean wildMatchAll(char *word, struct slName *wildList)
/* Return TRUE if word matches all things in wildList. */
{
struct slName *w;
for (w = wildList; w != NULL; w = w->next)
if (!wildMatch(w->name, word) )
return FALSE;
return TRUE;
}
boolean wildMatchList(char *word, struct slName *wildList, boolean orLogic)
/* Return TRUE if word matches things in wildList. */
{
if (orLogic)
return wildMatchAny(word, wildList);
else
return wildMatchAll(word, wildList);
}
char *columnSetting(struct column *col, char *name, char *defaultVal)
/* Return value of named setting in column, or default if it doesn't exist. */
{
char *result = hashFindVal(col->settings, name);
if (result == NULL)
result = defaultVal;
return result;
}
void fixSafariSpaceInQuotes(char *s)
/* Safari on the Mac changes a space (ascii 32) to a
* ascii 160 if it's inside of a single-quote in a
* text input box!? This tuns it back to a 32. */
{
unsigned char c;
while ((c = *s) != 0)
{
if (c == 160)
*s = 32;
++s;
}
}
struct column *findNamedColumn(char *name)
/* Return column of given name from list or NULL if none. */
{
if (columnHash == NULL)
internalErr();
return hashFindVal(columnHash, name);
}
char *colVarName(struct column *col, char *prefix)
/* Return variable name prefix.col->name. This is just a static
* variable, so don't nest these calls*/
{
static char name[64];
safef(name, sizeof(name), "%s%s", prefix, col->name);
return name;
}
void colButton(struct column *col, char *prefix, char *label)
/* Make a button named prefix.col->name with given label. */
{
static char name[64];
safef(name, sizeof(name), "%s%s", prefix, col->name);
cgiMakeButton(name, label);
}
struct column *colButtonPressed(struct column *colList, char *prefix)
/* See if a button named prefix.column is pressed for some
* column, and if so return the column, else NULL. */
{
static char pattern[64];
char colName[64];
char *match;
safef(pattern, sizeof(pattern), "%s*", prefix);
match = cartFindFirstLike(cart, pattern);
if (match == NULL)
return NULL;
/* Construct column name. If variable is from an file upload
* there __filename suffix attached that we need to remove. */
safef(colName, sizeof(colName), "%s", match + strlen(prefix));
if (endsWith(colName, "__filename"))
{
int newLen = strlen(colName) - strlen("__filename");
colName[newLen] = 0;
}
return findNamedColumn(colName);
}
void columnVarsFromSettings(struct column *col, char *fileName)
/* Grab a bunch of variables from col->settings and
* move them into col proper. */
{
struct hash *settings = col->settings;
col->name = mustFindInRaHash(fileName, settings, "name");
spaceToUnderbar(col->name);
col->shortLabel = mustFindInRaHash(fileName, settings, "shortLabel");
col->longLabel = mustFindInRaHash(fileName, settings, "longLabel");
col->priority = atof(mustFindInRaHash(fileName, settings, "priority"));
col->on = col->defaultOn =
sameString(mustFindInRaHash(fileName, settings, "visibility"), "on");
col->filterOn = FALSE;
col->type = mustFindInRaHash(fileName, settings, "type");
col->query = hashFindVal(settings, "query");
col->filterDropDown = sameOk(hashFindVal(settings, "filterDropDown"), "on");
col->colNo = -1;
}
static boolean alwaysExists(struct column *col, struct sqlConnection *conn)
/* We always exist. */
{
return TRUE;
}
static char *noVal(struct column *col, struct subjInfo *si, struct sqlConnection *conn)
/* Return not-available value. */
{
return cloneString("n/a");
}
static int oneColumn(struct column *col)
/* Return that we have single column. */
{
return 1;
}
int columnSettingInt(struct column *col, char *name, int defaultVal)
/* Return value of named integer setting or default if it doesn't exist. */
{
char *result = hashFindVal(col->settings, name);
if (result == NULL)
return defaultVal;
return atoi(result);
}
static void hPrintSpaces(int count)
/* Print count number of spaces. */
{
while (--count >= 0)
hPrintf(" ");
}
void colSortLink(struct column *col)
/* print link that will activate sorting on the column */
{
char *plusMinus = "%2B"; /* "+" cgi encoded */
if (sameString(orderOn+1,col->name)&&orderOn[0]=='+')
plusMinus = "-";
hPrintf("<A href=\"gsidTable?org=%s&db=%s&%s&%s=%s%s\" >",
genome, database, cartSidUrlString(cart), orderVarName, plusMinus, col->name);
}
void labelSimplePrint(struct column *col)
/* This just prints cell->shortLabel. If colWidth is
* set it will add spaces, center justifying it. */
{
int colWidth = columnSettingInt(col, "colWidth", 0);
hPrintf("<TH ALIGN=LEFT VALIGN=BOTTOM><B><PRE>");
/* The <PRE> above helps Internet Explorer avoid wrapping
* in the label column, which helps us avoid wrapping in
* the data columns below. Wrapping in the data columns
* makes the expression display less effective so we try
* to minimize it. -jk */
if (colWidth == 0)
{
colSortLink(col);
hPrintf("%s</A>", col->shortLabel);
}
else
{
int labelLen = strlen(col->shortLabel);
int diff = colWidth - labelLen;
if (diff < 0) diff = 0;
colSortLink(col);
hPrintf("%s</A>", col->shortLabel);
hPrintSpaces(diff);
}
hPrintf("</PRE></B></TH>");
}
void cellSimplePrint(struct column *col, struct subjInfo *si,
struct sqlConnection *conn)
/* This just prints one field from table. */
{
char *s = col->cellVal(col, si, conn);
boolean isSubjID = sameString(col->name,"subjId");
hPrintf("<TD>");
if (s == NULL)
{
hPrintf("n/a");
}
else
{
if (isSubjID)
hPrintf("<A HREF=\"gsidSubj?%s&hgs_subj=%s&submit=Go%c21\">",cartSidUrlString(cart),s, '%');
if (sameString(s,""))
{
freeMem(s);
s = cloneString(" ");
}
if (! (sameString(col->name,"dnaSeqs") || sameString(col->name,"aaSeqs")) )
hPrintNonBreak(s);
else
/* special processing for DNA and protein sequences */
hPrintf("%s", s);
if (isSubjID)
hPrintf("</A>");
freeMem(s);
}
hPrintf("</TD>\n");
}
int sortCmpString(const void *va, const void *vb)
/* Compare to sort rows based on string value. */
{
const struct subjInfo *a = *((struct subjInfo **)va);
const struct subjInfo *b = *((struct subjInfo **)vb);
return strcmp(a->sortString, b->sortString);
}
int sortCmpInteger(const void *va, const void *vb)
/* Compare to sort rows based on integer value. */
{
const struct subjInfo *a = *((struct subjInfo **)va);
const struct subjInfo *b = *((struct subjInfo **)vb);
return a->sortInteger - b->sortInteger;
}
int sortCmpDouble(const void *va, const void *vb)
/* Compare to sort rows based on double value. */
{
const struct subjInfo *a = *((struct subjInfo **)va);
const struct subjInfo *b = *((struct subjInfo **)vb);
return a->sortDouble - b->sortDouble;
}
static char *keyFileName(struct column *col)
/* Return key file name for this column. Return
* NULL if no key file. */
{
char *fileName = advFilterVal(col, "keyFile");
if (fileName == NULL)
return NULL;
if (!fileExists(fileName))
{
cartRemove(cart, advFilterName(col, "keyFile"));
return NULL;
}
return fileName;
}
struct slName *keyFileList(struct column *col)
/* Make up list from key file for this column.
* return NULL if no key file. */
{
char *fileName = keyFileName(col);
char *buf;
struct slName *list;
if (fileName == NULL)
return NULL;
readInGulp(fileName, &buf, NULL);
list = stringToSlNames(buf);
freez(&buf);
return list;
}
static struct hash *upcHashWordsInFile(char *fileName, int hashSize)
/* Create a hash of space delimited uppercased words in file. */
{
struct hash *hash = newHash(hashSize);
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *line, *word;
while (lineFileNext(lf, &line, NULL))
{
while ((word = nextQuotedWord(&line)) != NULL)
{
touppers(word);
hashAdd(hash, word, NULL);
}
}
lineFileClose(&lf);
return hash;
}
int countQuotedWordsInFile(char *fileName)
/* Count Quoted Words in a file */
{
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *line, *word;
int cnt;
cnt = 0;
while (lineFileNext(lf, &line, NULL))
{
while ((word = nextQuotedWord(&line)) != NULL)
{
cnt++;
}
}
lineFileClose(&lf);
return cnt;
}
struct hash *keyFileHash(struct column *col)
/* Make up a hash from key file for this column.
* Return NULL if no key file. */
{
char *fileName = keyFileName(col);
if (fileName == NULL)
return NULL;
return upcHashWordsInFile(fileName, 16);
}
struct subjInfo *intAdvFilter(struct column *col,
struct sqlConnection *conn, struct subjInfo *list)
/* Do advanced filter on string in main table. */
{
char *minString = advFilterVal(col, "min");
char *maxString = advFilterVal(col, "max");
if (minString || maxString)
{
int min = minString ? sqlSigned(minString) : 0;
int max = maxString ? sqlSigned(maxString) : 0;
struct subjInfo *newList = NULL, *next, *si;
for (si = list; si != NULL; si = next)
{
char *cell = col->cellVal(col, si, conn);
int val = sqlSigned(cell);
freez(&cell);
next = si->next;
if (!((minString && (val < min)) || (maxString && (val > max))))
{
slAddHead(&newList, si);
}
}
slReverse(&newList);
list = newList;
}
return list;
}
struct subjInfo *doubleAdvFilter(struct column *col,
struct sqlConnection *conn, struct subjInfo *list)
/* Do advanced filter on string in main table. */
{
char *minString = advFilterVal(col, "min");
char *maxString = advFilterVal(col, "max");
if (minString || maxString)
{
double min = minString ? sqlDouble(minString) : 0.0;
double max = maxString ? sqlDouble(maxString) : 0.0;
struct subjInfo *newList = NULL, *next, *si;
for (si = list; si != NULL; si = next)
{
char *cell = col->cellVal(col, si, conn);
boolean invalid = sameString(cell,".");
double val = invalid ? 0.0 : sqlDouble(cell);
freez(&cell);
next = si->next;
if (!invalid && !((minString && (val < min)) || (maxString && (val > max))))
{
slAddHead(&newList, si);
}
}
slReverse(&newList);
list = newList;
}
return list;
}
struct subjInfo *stringAdvFilter(struct column *col,
struct sqlConnection *conn, struct subjInfo *list)
/* Do advanced filter on string in main table. */
{
char *wild = advFilterVal(col, "wild");
struct hash *keyHash = keyFileHash(col);
if (keyHash != NULL)
{
struct subjInfo *newList = NULL, *next, *si;
for (si = list; si != NULL; si = next)
{
char *cell = col->cellVal(col, si, conn);
next = si->next;
if (hashLookupUpperCase(keyHash, cell))
{
slAddHead(&newList, si);
}
freez(&cell);
}
slReverse(&newList);
list = newList;
}
if (wild != NULL)
{
boolean orLogic = advFilterOrLogic(col, "logic", TRUE);
struct subjInfo *newList = NULL, *next, *si;
struct slName *wildList = stringToSlNames(wild);
for (si = list; si != NULL; si = next)
{
char *cell = col->cellVal(col, si, conn);
next = si->next;
if (wildMatchList(cell, wildList, orLogic))
{
slAddHead(&newList, si);
}
freez(&cell);
}
slReverse(&newList);
list = newList;
}
hashFree(&keyHash);
return list;
}
/* forward reference */
void showListOfFilterValues(struct column *col, struct sqlConnection *conn);
/* Print out list of values availabe for filter. */
void lookupAdvFilterControls(struct column *col, struct sqlConnection *conn)
/* Print out controls for advanced filter on lookup column. */
{
char *fileName = advFilterVal(col, "keyFile");
hPrintf("%s search (including * and ? wildcards):", col->shortLabel);
advFilterRemakeTextVar(col, "wild", 18);
hPrintf("<BR>\n");
hPrintf("Include if ");
advFilterAnyAllMenu(col, "logic", TRUE);
hPrintf("words in search term match.<BR>");
if (!columnSetting(col, "noKeys", NULL))
{
hPrintf("Limit to items (no wildcards) in list: ");
advFilterKeyPasteButton(col);
hPrintf(" ");
advFilterKeyUploadButton(col);
hPrintf(" ");
if (fileName != NULL)
{
if (fileExists(fileName))
{
int count = countQuotedWordsInFile(fileName);
advFilterKeyClearButton(col);
hPrintf("<BR>\n");
if (count == 1)
hPrintf("(There is currently 1 item in the list.)");
else
hPrintf("(There are currently %d items in the list.)", count);
}
else
{
cartRemove(cart, advFilterName(col, "keyFile"));
}
}
}
if (col->filterDropDown)
showListOfFilterValues(col, conn);
}
void columnDefaultMethods(struct column *col)
/* Set up default methods. */
{
col->exists = alwaysExists;
col->cellVal = noVal;
col->sortCmp = sortCmpString;
col->cellPrint = cellSimplePrint;
col->labelPrint = labelSimplePrint;
col->tableColumns = oneColumn;
col->filterControls = lookupAdvFilterControls;
col->advFilter = stringAdvFilter;
}
char *queryCellVal(struct column *col, struct subjInfo *si,
struct sqlConnection *conn)
/* return query lookup on subj id */
{
char query[256];
char *answer;
safef(query, sizeof(query), col->query, si->fields[0]);
answer = sqlQuickString(conn, query);
if (answer == NULL)
{
return(cloneString("-1"));
}
else
{
return answer;
}
}
+char NDString[10] = {"yyN/D"};
+char *stringCellValx(struct column *col, struct subjInfo *si,
+ struct sqlConnection *conn)
+/* Return clone of geneId */
+{
+return(NDString);
+/*
+if (col->query)
+ return queryCellVal(col,si,conn);
+else
+ return cloneString(si->fields[col->colNo]);
+*/
+}
+
char *stringCellVal(struct column *col, struct subjInfo *si,
struct sqlConnection *conn)
/* Return clone of geneId */
{
if (col->query)
return queryCellVal(col,si,conn);
else
return cloneString(si->fields[col->colNo]);
}
void setupColumnString(struct column *col, char *parameters)
/* Set up a column that displays the geneId (accession) */
{
col->cellVal = stringCellVal;
}
void integerCellPrint(struct column *col, struct subjInfo *si,
struct sqlConnection *conn)
/* Print value including favorite hyperlink in debug column. */
{
boolean special;
special = FALSE;
char *s = col->cellVal(col, si, conn);
hPrintf("<TD align=right>");
+/* special processing for missing data */
+if (sameWord(col->name, "SDayLastPTest"))
+ {
+ if (sameWord(s, "-1"))
+ {
+ hPrintf("N/A");
+ special = TRUE;
+ }
+ }
+if (sameWord(col->name, "SDayLastTrTest"))
+ {
+ if (sameWord(s, "-1"))
+ {
+ hPrintf("N/A");
+ special = TRUE;
+ }
+ }
+if (sameWord(col->name, "SDayLastTrTest"))
+ {
+ if (sameWord(s, "-2"))
+ {
+ hPrintf("N/D");
+ special = TRUE;
+ }
+ }
+if (sameWord(col->name, "LastTrVisit"))
+ {
+ if (sameWord(s, "-1"))
+ {
+ hPrintf("N/A");
+ special = TRUE;
+ }
+ }
+if (sameWord(col->name, "LastTrVisit"))
+ {
+ if (sameWord(s, "-2"))
+ {
+ hPrintf("N/D");
+ special = TRUE;
+ }
+ }
+if (sameWord(col->name, "LastTrMnNeutral"))
+ {
+ if (sameWord(s, "-3"))
+ {
+ hPrintf(" ");
+ special = TRUE;
+ }
+ }
if (sameWord(col->name, "cd4Count"))
{
if (sameWord(s, "-1") || sameWord(s, "0"))
{
printf("N/A");
special = TRUE;
}
}
if (sameWord(col->name, "hivQuan"))
{
if (sameWord(s, "-1"))
{
printf("N/A");
special = TRUE;
}
}
if (sameWord(col->name, "DAEI"))
{
if (sameWord(s, "-1"))
{
printf("N/A");
special = TRUE;
}
}
if (sameWord(col->name, "esdi"))
{
if (sameWord(s, "-1"))
{
printf("N/A");
special = TRUE;
}
}
if (sameWord(col->name, "hivQuan"))
{
if (sameWord(s, "1000000"))
{
printf("> 1000000");
special = TRUE;
}
}
if (sameWord(col->name, "hivQuan"))
{
if (sameWord(s, "200"))
{
printf("< 400");
special = TRUE;
}
}
if (!special)
{
hPrintf("%s", s);
}
freeMem(s);
}
void doubleCellPrint(struct column *col, struct subjInfo *si,
struct sqlConnection *conn)
/* print double value */
{
char *s = col->cellVal(col, si, conn);
char buf[256];
if (sameString(s,".")) // known bad data value
safef(buf,sizeof(buf),"%s", s);
else
+ {
+ if (sameWord(col->name, "LastPVisit") ||sameWord(col->name, "LastPCD4Blk"))
+ {
+ if (sameWord(s, "-1"))
+ {
+ safef(buf,sizeof(buf),"N/A");
+ }
+ else if (sameWord(s, "-2"))
+ {
+ safef(buf,sizeof(buf),"N/D");
+ }
+ else if (sameWord(s, "-3"))
+ {
+ safef(buf,sizeof(buf)," ");
+ }
+ else
+ {
+ safef(buf,sizeof(buf),"%.1f",sqlDouble(s));
+ }
+ }
+ else
+ if (sameWord(col->name, "LastTrCD4Blk") || sameWord(col->name, "LastTrAntiGP120"))
+ {
+ if (sameWord(s, "-3"))
+ {
+ safef(buf,sizeof(buf)," ");
+ }
+ else if (sameWord(s, "-2"))
+ {
+ safef(buf,sizeof(buf),"N/D");
+ }
+ else if (sameWord(s, "-1"))
+ {
+ safef(buf,sizeof(buf),"N/A");
+ }
+ else
+ {
+ safef(buf,sizeof(buf),"%.3f",sqlDouble(s));
+ }
+ }
+ else
+ {
safef(buf,sizeof(buf),"%.1f",sqlDouble(s));
+ }
+ }
freeMem(s);
hPrintf("<TD align=right>");
hPrintf("%s", buf);
hPrintf("</TD>");
}
/* TODO:
assuming we want to keep this approach,
for cleanup need to rename struct col member filterDropDown
to something like showAvailableValues.
Then remove dropDownAdvFilterControls()
and rename showListOfFilterValues() to showListOfAvailableValues()
*/
void showListOfFilterValues(struct column *col, struct sqlConnection *conn)
/* Print out list of values availabe for filter. */
{
struct sqlResult *sr;
char **row;
char query[256];
struct slName *list=NULL, *el;
safef(query, sizeof(query),
"select distinct %s from gsidSubjInfo", col->name);
sr = sqlGetResult(conn, query);
while ((row = sqlNextRow(sr)) != NULL)
{
char *val = row[0];
if (col->remap)
val = hashFindVal(col->remap,val);
slNameAddHead(&list, val);
}
sqlFreeResult(&sr);
slNameSort(&list);
hPrintf("<BR>\n");
hPrintf("<B>Available Values:</B><BR>\n");
hPrintf("<TABLE>\n");
for (el = list; el; el = el->next)
{
hPrintf("<TR><TD>%s</TD></TR>\n", el->name);
}
hPrintf("</TABLE>\n");
slFreeList(&list);
}
void dropDownAdvFilterControls(struct column *col, struct sqlConnection *conn)
/* Print out controls for dropdown list filter. */
{
struct sqlResult *sr;
char **row;
char query[256];
struct slName *list=NULL, *el;
safef(query, sizeof(query),
"select distinct %s from gsidSubjInfo", col->name);
sr = sqlGetResult(conn, query);
while ((row = sqlNextRow(sr)) != NULL)
{
char *val = row[0];
if (col->remap)
val = hashFindVal(col->remap,val);
slNameAddHead(&list, val);
}
sqlFreeResult(&sr);
slNameSort(&list);
hPrintf("choose: ");
hPrintf("<SELECT NAME=\"%s\"", "countVarName");
hPrintf(">\n");
hPrintf("<OPTION VALUE=\"\">");
for (el = list; el; el = el->next)
{
hPrintf("<OPTION VALUE=\"%s\"", el->name);
if (sameString(el->name, "displayCountString"))
hPrintf(" SELECTED");
hPrintf(">%s\n", el->name);
}
hPrintf("</SELECT>\n");
slFreeList(&list);
}
void minMaxAdvFilterControls(struct column *col, struct sqlConnection *conn)
/* Print out controls for min/max advanced filter. */
{
hPrintf("minimum: ");
advFilterRemakeTextVar(col, "min", 8);
hPrintf(" maximum: ");
advFilterRemakeTextVar(col, "max", 8);
}
void setupColumnInteger(struct column *col, char *parameters)
/* Set up a column that displays an integer */
{
col->cellVal = stringCellVal;
col->cellPrint = integerCellPrint;
col->sortCmp = sortCmpInteger;
col->filterControls = minMaxAdvFilterControls;
col->advFilter = intAdvFilter;
}
void setupColumnDouble(struct column *col, char *parameters)
/* Set up a column that displays an double */
{
col->cellVal = stringCellVal;
col->cellPrint = doubleCellPrint;
col->sortCmp = sortCmpDouble;
col->filterControls = minMaxAdvFilterControls;
col->advFilter = doubleAdvFilter;
}
char *remapCellVal(struct column *col, struct subjInfo *si,
struct sqlConnection *conn)
/* Return clone of value */
{
char *s = stringCellVal(col,si,conn);
char *result = cloneString(hashFindVal(col->remap,s));
freeMem(s);
return result;
}
void setupColumnRemap(struct column *col, char *parameters)
/* Set up a column that remaps one string to another via .ra settings-made hash */
{
col->remap=newHash(5);
col->cellVal = remapCellVal;
char wordBuf[256];
char valueBuf[256];
char *word = NULL, *wEnd = wordBuf+sizeof(wordBuf);
char *value = NULL, *vEnd = valueBuf+sizeof(valueBuf);
char c = ' ';
while (*parameters != 0)
{
word = wordBuf;
value = valueBuf;
c = (*parameters++);
if (c != '"')
errAbort("remap syntax error in %s",col->name);
while(TRUE)
{
c = *parameters++;
if (c == '"')
break;
*word++= c;
if (word >= wEnd)
errAbort("remap syntax error in %s",col->name);
}
*word = 0;
c = (*parameters++);
if (c != '=')
errAbort("remap syntax error in %s",col->name);
c = (*parameters++);
if (c != '"')
errAbort("remap syntax error in %s",col->name);
while(TRUE)
{
c = *parameters++;
if (c == '"')
break;
*value++= c;
if (value >= vEnd)
errAbort("remap syntax error in %s",col->name);
}
*value = 0;
word = wordBuf;
value = valueBuf;
hashAdd(col->remap, word, cloneString(value));
if (*parameters == ' ')
++parameters;
}
}
void setupColumnType(struct column *col)
/* Set up methods and column-specific variables based on * track type. */
{
char *dupe = cloneString(col->type);
char *s = dupe;
char *type = nextWord(&s);
columnDefaultMethods(col);
if (type == NULL)
warn("Missing type value for column %s", col->name);
if (sameString(type, "integer"))
setupColumnInteger(col, s);
else if (sameString(type, "double"))
setupColumnDouble(col, s);
else if (sameString(type, "string"))
setupColumnString(col, s);
else if (sameString(type, "remap"))
setupColumnRemap(col, s);
else
errAbort("Unrecognized type %s for %s", col->type, col->name);
freez(&dupe);
}
static struct hash *hashColumns(struct column *colList)
/* Return a hash of columns keyed by name. */
{
struct column *col;
struct hash *hash = hashNew(8);
for (col = colList; col != NULL; col = col->next)
{
if (hashLookup(hash, col->name))
warn("duplicate %s in column list", col->name);
hashAdd(hash, col->name, col);
}
return hash;
}
static char *rootDir = "gsidTableData";
struct hash *readRa(char *rootName)
/* Read in ra in root, root/org, and root/org/database. */
{
return hgReadRa(genome, database, rootDir, rootName, NULL);
}
int columnCmpPriority(const void *va, const void *vb)
/* Compare to sort columns based on priority. */
{
const struct column *a = *((struct column **)va);
const struct column *b = *((struct column **)vb);
float dif = a->priority - b->priority;
if (dif < 0)
return -1;
else if (dif > 0)
return 1;
else
return 0;
}
void refineVisibility(struct column *colList)
/* Consult cart to set on/off visibility. */
{
char varName[128], *val;
struct column *col;
for (col = colList; col != NULL; col = col->next)
{
safef(varName, sizeof(varName), "%s%s.vis", colConfigPrefix, col->name);
val = cartOptionalString(cart, varName);
if (val != NULL)
col->on = sameString(val, "1");
}
}
void refineFilterOn(struct column *colList)
/* Consult cart to see if filtering is on/off. */
{
char *val;
struct column *col;
for (col = colList; col != NULL; col = col->next)
{
val = advFilterVal(col,"max");
if (val != NULL)
col->filterOn = TRUE; //sameString(val, "1");
val = advFilterVal(col,"wild");
if (val != NULL)
col->filterOn = TRUE; //sameString(val, "1");
}
}
struct column *getColumns(struct sqlConnection *conn)
/* Return list of columns for big table. */
{
char *raName = "columnDb.ra";
struct column *col, *colList = NULL;
struct hash *raList = readRa(raName), *raHash = NULL;
/* Create built-in columns. */
if (raList == NULL)
errAbort("Couldn't find anything from %s", raName);
for (raHash = raList; raHash != NULL; raHash = raHash->next)
{
AllocVar(col);
col->settings = raHash;
columnVarsFromSettings(col, raName);
if (!hashFindVal(raHash, "hide"))
{
setupColumnType(col);
slAddHead(&colList, col);
}
}
/* Put columns in hash */
columnHash = hashColumns(colList);
/* Tweak ordering and visibilities as per user settings. */
//refinePriorities(columnHash);
refineVisibility(colList);
refineFilterOn(colList);
slSort(&colList, columnCmpPriority);
return colList;
}
boolean anyRealInCart(struct cart *cart, char *wild)
/* Return TRUE if variables are set matching wildcard. */
{
struct hashEl *varList = NULL, *var;
boolean ret = FALSE;
varList = cartFindLike(cart, wild);
for (var = varList; var != NULL; var = var->next)
{
char *s = var->val;
if (s != NULL)
{
s = trimSpaces(s);
if (s[0] != 0)
{
ret = TRUE;
break;
}
}
}
hashElFreeList(&varList);
return ret;
}
void saveSubjList(struct subjInfo *subjList)
/* save the filtered list of subject gsids to a file for other applications to use */
{
char *outName = cartOptionalString(cart, gsidSubjList);
char *outName2= cartOptionalString(cart, gsidSeqList);
struct tempName tn;
struct tempName tn2;
struct sqlResult *sr;
char **row;
char query[255];
char *chp;
int cnt;
if (!outName)
{
trashDirFile(&tn, "ct", "gsidSubj", ".list");
outName = tn.forCgi;
}
if (!outName2)
{
trashDirFile(&tn2, "ct", "gsidSeq", ".list");
outName2 = tn2.forCgi;
}
FILE *outF = mustOpen(outName,"w");
FILE *outF2= mustOpen(outName2,"w");
cnt = 0;
while (subjList)
{
fprintf(outF, "%s\n", subjList->fields[0]);
safef(query, sizeof(query),
"select dnaSeqId from gsIdXref where subjId='%s'",
subjList->fields[0]);
sr = sqlGetResult(conn, query);
while ((row = sqlNextRow(sr)) != NULL)
{
/* Remove "ss." from the front of the DNA sequence ID,
so that they could be used both for DNA and protein MSA maf display */
chp = strstr(row[0], "ss.");
if (chp != NULL)
{
fprintf(outF2, "%s\t%s\n", chp+3L, subjList->fields[0]);
}
else
{
fprintf(outF2, "%s\t%s\n", row[0], subjList->fields[0]);
}
cnt++;
}
sqlFreeResult(&sr);
subjList=subjList->next;
}
carefulClose(&outF);
carefulClose(&outF2);
cartSetString(cart, gsidSubjList, outName);
cartSetString(cart, gsidSeqList, outName2);
}
struct column *curOrder(struct column *ordList)
/* Get ordering currently selected by user, or default
* (first in list that is on) if none selected. */
{
char *selName;
struct column *ord, *ordDefault = NULL;
if (ordList == NULL)
errAbort("No orderings available");
selName = orderOn+1;
for (ord = ordList; ord != NULL; ord = ord->next)
{
if (ord->on && sameString(ord->name, selName))
return ord;
if (!ordDefault && ord->on)
ordDefault = ord;
}
return ordDefault;
}
struct subjInfo *getOrderedList(struct column *ord,
struct column *colList, struct sqlConnection *conn,
int maxCount)
/* Return sorted list of subjects. */
{
struct subjInfo *subjList = advFilterResults(colList, conn);
struct subjInfo *si;
passedFilterCount = slCount(subjList);
for (si=subjList;si;si=si->next)
{
char *s = ord->cellVal(ord, si, conn);
if (sameString(ord->type,"integer"))
{
si->sortInteger = sqlSigned(s);
freeMem(s);
}
else if (sameString(ord->type,"double"))
{
if (sameString(s,"."))
si->sortDouble = 0;
else
si->sortDouble = sqlDouble(s);
freeMem(s);
}
else
{
si->sortString = s;
}
}
slSort(&subjList, ord->sortCmp);
if (orderOn[0]=='-')
slReverse(&subjList);
/* Trim list to max number. */
si = slElementFromIx(subjList, maxCount-1);
if (si != NULL)
si->next = NULL;
return subjList;
}
void displayData(struct sqlConnection *conn, struct column *colList)
/* Display data in neighborhood of gene. */
{
struct subjInfo *subjList = NULL;
struct column *ordList = colList;
struct column *ord = curOrder(ordList);
if (ord == NULL) /* no columns are visible, go to back to configure page */
{
doConfigure(conn, colList);
return;
};
-
if (cartVarExists(cart, getTextVarName))
{
subjList = getOrderedList(ord, colList, conn, BIGNUM);
doGetText(conn, colList, subjList);
}
else if (cartVarExists(cart, getSeqVarName))
{
subjList = getOrderedList(ord, colList, conn, BIGNUM);
doGetSeq(conn, subjList, cartString(cart, getSeqHowVarName));
}
else if (cartVarExists(cart, redirectName))
{
subjList = getOrderedList(ord, colList, conn, BIGNUM);
if (subjList)
{
cartRemove(cart, redirectName);
}
else /* if everything has been filtered out, we'll have to go back */
{
hPrintf("No subject(s) found with the filtering conditions specified.<br>");
hPrintf("Click <a href=\"gsidTable?gsidTable.do.advFilter=filter+%c28now+on%c29\">here</a> to return to Select Subjects.<br>", '%', '%');
}
}
else
{
subjList = getOrderedList(ord, colList, conn, displayCount);
doMainDisplay(conn, colList, subjList);
}
}
void doMiddle(struct cart *theCart)
/* Write the middle parts of the HTML page.
* This routine sets up some globals and then
* dispatches to the appropriate page-maker. */
{
cart = theCart;
if (cartVarExists(cart, confVarName))
doConfigure(conn, colList);
else if (cartVarExists(cart, defaultConfName))
doDefaultConfigure(conn, colList);
else if (cartVarExists(cart, hideAllConfName))
doConfigHideAll(conn, colList);
else if (cartVarExists(cart, showAllConfName))
doConfigShowAll(conn, colList);
else if (cartVarExists(cart, getSeqPageVarName))
doGetSeqPage(conn, colList);
else if (cartVarExists(cart, advFilterVarName))
doAdvFilter(conn, colList);
else if (cartVarExists(cart, advFilterClearVarName))
doAdvFilterClear(conn, colList);
else if ((col = advFilterKeyPastePressed(colList)) != NULL)
doAdvFilterKeyPaste(conn, colList, col);
else if ((col = advFilterKeyPastedPressed(colList)) != NULL)
doAdvFilterKeyPasted(conn, colList, col);
else if ((col = advFilterKeyUploadPressed(colList)) != NULL)
doAdvFilterKeyUpload(conn, colList, col);
else if ((col = advFilterKeyClearPressed(colList)) != NULL)
doAdvFilterKeyClear(conn, colList, col);
else
displayData(conn, colList);
cartRemovePrefix(cart, "gsidTable.do.");
}
void usage()
/* Explain usage and exit. */
{
errAbort(
"gsidTable - subjects table view - a cgi script\n"
"usage:\n"
" gsidTable\n"
);
}
int main(int argc, char *argv[])
/* Process command line. */
{
pushCarefulMemHandler(100000000);
cgiSpoof(&argc, argv);
htmlSetStyle(htmlStyleUndecoratedLink);
htmlSetBgColor(HG_CL_OUTSIDE);
oldCart = hashNew(10);
cart = cartAndCookie(hUserCookie(), excludeVars, oldCart);
getDbAndGenome(cart, &database, &genome, oldCart);
//hSetDb(database);
conn = hAllocConn(database);
/* Get sortOn. Revert to default by subject Id. */
orderOn = cartUsualString(cart, orderVarName, "+subjId");
displayCountString = cartUsualString(cart, countVarName, "50");
if (sameString(displayCountString, "all"))
displayCount = BIGNUM;
else
displayCount = atoi(displayCountString);
colList = getColumns(conn);
if (cgiVarExists("submit_filter"))
{
struct dyString *head = dyStringNew(1024);
boolean redir = cgiVarExists(redirectName);
struct subjInfo *subjList = NULL;
struct column *ordList = colList;
struct column *ord = curOrder(ordList);
subjList = getOrderedList(ord, colList, conn, BIGNUM);
saveSubjList(subjList);
if ((!subjList || redir))
{
if (subjList && redir)
{
dyStringPrintf(head,
"<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0;URL=/cgi-bin/%s\">"
"<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">"
"<META HTTP-EQUIV=\"Expires\" CONTENT=\"-1\">"
, cgiString(redirectName));
cartRemove(cart, redirectName);
}
htmStartWithHead(stdout, head->string, "GSID Table View");
if (!subjList) /* if everything has been filtered out, we'll have to go back */
{
hPrintf("No subject(s) found with the filtering conditions specified.<br>");
hPrintf("Click <a href=\"gsidTable?gsidTable.do.advFilter=filter+%%28now+on%%29\">here</a> "
"to return to Select Subjects.<br>");
}
cartCheckout(&cart);
htmlEnd();
hFreeConn(&conn);
return 0;
}
}
htmStart(stdout, "GSID Table View");
cartWarnCatcher(doMiddle, cart, htmlVaWarn);
cartCheckout(&cart);
htmlEnd();
hFreeConn(&conn);
return 0;
}