/* gisaidTable - GISAID Table View */
#include "common.h"
#include "hCommon.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 "gisaidTable.h"
#include "versionInfo.h"
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("
");
hPrintf("
");
hPrintf("
\n");
hPrintf("
");
}
void controlPanelEnd()
/* Put up end of tables around a control panel. */
{
hPrintf("
");
hPrintf("
");
hPrintf("
");
hPrintf("
");
}
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("\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("
\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), "GISAID %s Table View", genome);
hPrintf("\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("",
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("
");
/* The
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", col->shortLabel);
}
else
{
int labelLen = strlen(col->shortLabel);
int diff = colWidth - labelLen;
if (diff < 0) diff = 0;
colSortLink(col);
hPrintf("%s", col->shortLabel);
hPrintSpaces(diff);
}
hPrintf("
");
}
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");
boolean isSampleID = sameString(col->name,"EPI_ISOLATE_ID");
hPrintf("
\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(" \n");
hPrintf("Include if ");
advFilterAnyAllMenu(col, "logic", TRUE);
hPrintf("words in search term match. ");
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(" \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 *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("
");
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
safef(buf,sizeof(buf),"%.1f",sqlDouble(s));
freeMem(s);
hPrintf("
");
hPrintf("%s", buf);
hPrintf("
");
}
/* 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 gisaidSubjInfo", 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(" \n");
hPrintf("Available Values: \n");
hPrintf("
\n");
for (el = list; el; el = el->next)
{
hPrintf("
%s
\n", el->name);
}
hPrintf("
\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 gisaidSubjInfo", 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("\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 = "gisaidTableData";
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 *subjListIn)
/* save the filtered list of subject gisaids to a file for other applications to use */
{
struct subjInfo *subjList;
char *outName = cartOptionalString(cart, gisaidSubjList);
char *outName2= cartOptionalString(cart, gisaidSeqList);
char *outName3= cartOptionalString(cart, gisaidAaSeqList);
char *outNameTemp;
struct tempName tn;
struct tempName tn2;
struct tempName tn3;
struct tempName tnTemp;
struct sqlResult *sr;
char **row;
char query[255];
int cnt;
char cmd[512];
if (!outName)
{
trashDirFile(&tn, "ct", "gisaidSubj", ".list");
outName = tn.forCgi;
}
if (!outName2)
{
trashDirFile(&tn2, "ct", "gisaidSeq", ".list");
outName2 = tn2.forCgi;
}
if (!outName3)
{
trashDirFile(&tn3, "ct", "gisaidAaSeq", ".list");
outName3 = tn3.forCgi;
}
trashDirFile(&tnTemp, "ct", "gisaidListTemp", ".list");
outNameTemp = tnTemp.forCgi;
FILE *outF = mustOpen(outName,"w");
FILE *outF2= mustOpen(outName2,"w");
FILE *outF3= mustOpen(outName3,"w");
cnt = 0;
subjList = subjListIn;
while (subjList)
{
fprintf(outF, "%s\n", subjList->fields[1]);
safef(query, sizeof(query),
"select distinct seqId from h1n1SeqXref where islId='%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 */
fprintf(outF2, "%s\t%s\n", row[0], subjList->fields[1]);
cnt++;
}
sqlFreeResult(&sr);
subjList=subjList->next;
}
subjList = subjListIn;
while (subjList)
{
fprintf(outF, "%s\n", subjList->fields[0]);
safef(query, sizeof(query),
"select distinct seqId, geneSymbol from h1n1SeqXref where islId='%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 */
fprintf(outF3, "%s_%s\t%s\n", row[0], row[1], subjList->fields[1]);
cnt++;
}
sqlFreeResult(&sr);
subjList=subjList->next;
}
carefulClose(&outF);
carefulClose(&outF2);
carefulClose(&outF3);
/* sort -u to make the selection lists unique */
sprintf(cmd, "cat %s |sort -u >%s", outName, outNameTemp);
system(cmd);
sprintf(cmd, "mv %s %s", outNameTemp, outName);
system(cmd);
sprintf(cmd, "cat %s |sort -u >%s", outName2, outNameTemp);
system(cmd);
sprintf(cmd, "mv %s %s", outNameTemp, outName2);
system(cmd);
sprintf(cmd, "cat %s |sort -u >%s", outName3, outNameTemp);
system(cmd);
sprintf(cmd, "mv %s %s", outNameTemp, outName3);
system(cmd);
cartSetString(cart, gisaidSubjList, outName);
cartSetString(cart, gisaidSeqList, outName2);
cartSetString(cart, gisaidAaSeqList, outName3);
}
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. ");
hPrintf("Click here to return to Select Subjects. ", '%', '%');
}
}
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 (hIsGisaidServer())
{
validateGisaidUser(cart);
}
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, "gisaidTable.do.");
}
void usage()
/* Explain usage and exit. */
{
errAbort(
"gisaidTable - subjects table view - a cgi script\n"
"usage:\n"
" gisaidTable\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);
database = strdup("h1n1");
/* 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,
""
""
""
, cgiString(redirectName));
cartRemove(cart, redirectName);
}
htmStartWithHead(stdout, head->string, "GISAID 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. ");
hPrintf("Click here "
"to return to Select Subjects. ");
}
cartCheckout(&cart);
htmlEnd();
hFreeConn(&conn);
return 0;
}
}
htmStart(stdout, "GISAID Table View");
cartWarnCatcher(doMiddle, cart, htmlVaWarn);
cartCheckout(&cart);
htmlEnd();
hFreeConn(&conn);
return 0;
}