src/hg/instinct/bioInt2/bioIntUI.c 1.6
1.6 2009/03/31 04:08:23 jsanborn
added search
Index: src/hg/instinct/bioInt2/bioIntUI.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/bioInt2/bioIntUI.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -b -B -U 1000000 -r1.5 -r1.6
--- src/hg/instinct/bioInt2/bioIntUI.c 31 Mar 2009 01:06:15 -0000 1.5
+++ src/hg/instinct/bioInt2/bioIntUI.c 31 Mar 2009 04:08:23 -0000 1.6
@@ -1,519 +1,683 @@
/* bioIntUI */
#include "common.h"
#include "bed.h"
#include "cart.h"
#include "linefile.h"
#include "customTrack.h"
#include "genoLay.h"
#include "hash.h"
#include "hCommon.h"
#include "hdb.h"
#include "hPrint.h"
#include "htmshell.h"
#include "hui.h"
#include "trackLayout.h"
#include "web.h"
#include "microarray.h"
#include "ra.h"
#include "hgStatsLib.h"
#include "featuresLib.h"
#include "json.h"
#include "bioIntDb.h"
#include "bioIntDriver.h"
#include "bioIntUI.h"
static char const rcsid[] = "$Id$";
/* ---- Global variables. ---- */
struct cart *cart; /* This holds cgi and other variables between clicks. */
struct hash *oldVars; /* Old cart hash. */
char *db = "bioInt";
char *localDb = "localDb";
void usage()
/* Explain usage and exit. */
{
errAbort(
"bioIntUI\n"
"usage:\n"
" bioIntUI\n"
);
}
/****** BEGIN HELPER FUNCTIONS *******/
struct analyses *getAnalysesById(struct sqlConnection *conn, int analysis_id)
{
char query[256];
safef(query, sizeof(query),
"select * from %s where id = %d;",
AN_TABLE, analysis_id);
return analysesLoadByQuery(conn, query);
}
struct analyses *getAnalysesByCohortId(struct sqlConnection *conn, int cohort_id)
{
char query[256];
safef(query, sizeof(query),
"select * from %s where cohort_id = %d;",
AN_TABLE, cohort_id);
return analysesLoadByQuery(conn, query);
}
struct analysisFeatures *getAnalysisFeaturesByName(struct sqlConnection *conn,
char *name)
{
char query[256];
safef(query, sizeof(query),
"select * from %s where feature_name = \"%s\"",
AF_TABLE, name);
return analysisFeaturesLoadByQuery(conn, query);
}
struct analysisFeatures *getAnalysisFeaturesById(struct sqlConnection *conn,
int id)
{
char query[256];
safef(query, sizeof(query),
"select * from %s where id = %d",
AF_TABLE, id);
return analysisFeaturesLoadByQuery(conn, query);
}
struct features *getFeaturesByName(struct sqlConnection *conn,
char *name)
{
char query[256];
safef(query, sizeof(query),
"select * from %s where name = \"%s\"",
FE_TABLE, name);
return featuresLoadByQuery(conn, query);
}
struct features *getFeaturesById(struct sqlConnection *conn,
int id)
{
char query[256];
safef(query, sizeof(query),
"select * from %s where id = %d",
FE_TABLE, id);
return featuresLoadByQuery(conn, query);
}
struct datasets *getDatasetsByCohortId(struct sqlConnection *conn, int cohort_id)
{
char query[256];
safef(query, sizeof(query),
"select %s.* from %s join %s on %s.id = %s.dataset_id "
"where %s.cohort_id = %d",
DA_TABLE, DA_TABLE, DC_TABLE, DA_TABLE, DC_TABLE, DC_TABLE, cohort_id);
return datasetsLoadByQuery(conn, query);
}
struct cohortCorr *getCohortCorrByCohortId(struct sqlConnection *conn, int cohort_id)
{
char query[256];
safef(query, sizeof(query),
"select * from %s where cohort_id = %d",
CC_TABLE, cohort_id);
return cohortCorrLoadByQuery(conn, query);
}
char *getFieldFromKgXref(struct sqlConnection *conn, char *geneSymbol,
char *field)
{
char query[256];
safef(query, sizeof(query),
"select %s from %s where geneSymbol = \"%s\" ",
field, KX_TABLE, geneSymbol);
return sqlQuickString(conn, query);
}
+void setAnalysisFeatureDesc(struct sqlConnection *conn, struct json *js,
+ struct analysisFeatures *af)
+{
+char *desc = getFieldFromKgXref(conn, af->feature_name, "description");
+if (!desc)
+ desc = cloneString(af->feature_name);
+
+/* String 'isoform xxx' from description... almost all entries have them */
+char *ptr = rStringIn("isoform", desc);
+if (ptr)
+ *ptr = '\0';
+
+jsonAddString(js, "description", desc);
+}
+
+void setAnalysisFeatureLink(struct sqlConnection *conn, struct json *js,
+ struct analysisFeatures *af)
+{
+char *kgId = getFieldFromKgXref(conn, af->feature_name, "kgId");
+if (kgId)
+ jsonAddString(js, "hgg_gene", kgId);
+}
+
/****** END HELPER FUNCTIONS *******/
/* get a list of the current analyses */
void getAnalyses()
{
char query[256];
safef(query, sizeof(query),
"select * from analyses;");
struct sqlConnection *conn = hAllocConnProfile(localDb, db);
struct analyses *an, *anList = analysesLoadByQuery(conn, query);
struct json *js = newJson();
struct json *analysis, *analyses = jsonAddContainerList(js, "analyses");
analysis = analyses;
for (an = anList; an; an = an->next)
{
jsonAddInt(analysis, "id", an->id);
jsonAddInt(analysis, "cohort_id", an->cohort_id);
jsonAddInt(analysis, "module_id", an->module_id);
jsonAddString(analysis, "result_table", an->result_table);
jsonAddString(analysis, "input_tables", an->input_tables);
if (an->next)
analysis = jsonAddContainerToList(&analyses);
}
if (js)
hPrintf("%s\n", js->print(js));
hFreeConn(&conn);
}
-void getFeatureData()
+struct slPair *searchForFeatures(struct sqlConnection *conn, int cohort_id,
+ struct datasets *daList, char *feature_name)
{
-int cohort_id = cartUsualInt(cart, bioIntCohortId, -1);
-if (cohort_id == -1)
- cohort_id = 1; // hard code for first analysis during testing!
+int maxResponse = 5;
+/* Check analysis features */
+char query[256];
+safef(query, sizeof(query),
+ "select feature_name from %s where feature_name like \"%%%s%%\" ",
+ AF_TABLE, feature_name);
-int feature_id = cartUsualInt(cart, bioIntFeatureId, -1);
-char *feature_name = cartOptionalString(cart, bioIntFeatureName);
-if (!feature_name && feature_id == -1)
- errAbort("%s or %s must be set for mode=getFeatureData\n", bioIntFeature, bioIntFeatureId);
+int count = 0;
+struct slPair *sp, *spList = NULL;
+struct sqlResult *sr = sqlGetResult(conn, query);
+char **row = NULL;
+while ((row = sqlNextRow(sr)) != NULL)
+ {
+ char *name = row[0];
+ AllocVar(sp);
+ sp->name = cloneString(name);
+ sp->val = cloneString("gene/geneset");
+ slAddHead(&spList, sp);
+ if (count > maxResponse)
+ break;
+ count++;
+ }
+sqlFreeResult(&sr);
-struct sqlConnection *conn = hAllocConnProfile(localDb, db);
+/* Check clinical features */
+struct datasets *da;
+struct dyString *dy = dyStringNew(100);
+dyStringPrintf(dy,
+ "select DISTINCT %s.name from %s join %s on %s.sample_id = %s.id ",
+ FE_TABLE, CD_TABLE, SA_TABLE, CD_TABLE, SA_TABLE);
+dyStringPrintf(dy,
+ "join %s on %s.id = %s.feature_id ",
+ FE_TABLE, FE_TABLE, CD_TABLE);
+dyStringPrintf(dy,
+ "where %s.name like \"%%%s%%\" and %s.dataset_id in (",
+ FE_TABLE, feature_name, SA_TABLE);
+for (da = daList; da; da = da->next)
+ {
+ dyStringPrintf(dy, "%d", da->id);
+ if (da->next)
+ dyStringPrintf(dy, ",");
+ }
+dyStringPrintf(dy, ")");
+char *cquery = dyStringCannibalize(&dy);
-struct analysisFeatures *af = NULL;
-if (feature_id == -1)
- af = getAnalysisFeaturesByName(conn, feature_name);
-else
- af = getAnalysisFeaturesById(conn, feature_id);
+count = 0;
+sr = sqlGetResult(conn, cquery);
+while ((row = sqlNextRow(sr)) != NULL)
+ {
+ char *name = row[0];
+ AllocVar(sp);
+ sp->name = cloneString(name);
+ sp->val = cloneString("clinical");
+ slAddHead(&spList, sp);
+ if (count < maxResponse)
+ break;
+ count++;
+ }
+sqlFreeResult(&sr);
+return spList;
+}
+
+void sendNoMatch(struct json *js)
+{
+return;
+}
+
+void sendAmbiguities(struct json *js, struct slPair *spList)
+{
+struct slPair *sp;
+for (sp = spList; sp; sp = sp->next)
+ {
+ char *source = sp->val;
+ jsonAddString(js, sp->name, source);
+ }
+}
+
+void sendAnalysisFeatureData(struct sqlConnection *conn, struct json *js,
+ int cohort_id, char *feature_name)
+{
+struct analysisFeatures *af = getAnalysisFeaturesByName(conn, feature_name);
if (!af)
{
hFreeConn(&conn);
- errAbort("Could not find analysisFeature in db");
+ errAbort("Could not find analysisFeature named in %s in db", feature_name);
}
struct analyses *an, *anList = getAnalysesByCohortId(conn, cohort_id);
if (!anList)
{
hFreeConn(&conn);
errAbort("No analyses with cohort_id = %d.\n", cohort_id);
}
char query[512];
for (an = anList; an; an = an->next)
{
safef(query, sizeof(query),
"select DISTINCT %s.name, %s.val from %s join %s on %s.sample_id = %s.id "
"where %s.feature_id = %d;",
SA_TABLE, an->result_table, an->result_table, SA_TABLE, an->result_table, SA_TABLE,
an->result_table, af->id);
if (sqlExists(conn, query))
break;
}
-struct json *js = newJson();
-
-char *desc = getFieldFromKgXref(conn, af->feature_name, "description");
-if (!desc)
- desc = cloneString(af->feature_name);
-
-/* String 'isoform xxx' from description... almost all entries have them */
-char *ptr = rStringIn("isoform", desc);
-if (ptr)
- *ptr = '\0';
-jsonAddString(js, "description", desc);
-
-char *kgId = getFieldFromKgXref(conn, af->feature_name, "kgId");
-if (kgId)
- jsonAddString(js, "hgg_gene", kgId);
+setAnalysisFeatureDesc(conn, js, af);
+setAnalysisFeatureLink(conn, js, af); // e.g. 'hgg_gene' = kgId
struct json *data = jsonAddContainer(js, "data");
struct sqlResult *sr = sqlGetResult(conn, query);
char **row = NULL;
while ((row = sqlNextRow(sr)) != NULL)
{
char *name = row[0];
double val = atof(row[1]);
jsonAddDouble(data, name, val);
}
sqlFreeResult(&sr);
+}
+
+void sendClinicalData(struct sqlConnection *conn, struct json *js,
+ int cohort_id, char *feature_name, struct datasets *daList)
+{
+struct features *fe = getFeaturesByName(conn, feature_name);
+
+if (!fe)
+ {
+ hFreeConn(&conn);
+ errAbort("Could not find clinical feature in db");
+ }
+
+struct dyString *dy = dyStringNew(100);
+dyStringPrintf(dy,
+ "select DISTINCT %s.name, %s.val from %s join %s on %s.sample_id = %s.id ",
+ SA_TABLE, CD_TABLE, CD_TABLE, SA_TABLE, CD_TABLE, SA_TABLE);
+dyStringPrintf(dy,
+ "where %s.feature_id = %d and %s.dataset_id in (",
+ CD_TABLE, fe->id, SA_TABLE);
+
+struct datasets *da;
+for (da = daList; da; da = da->next)
+ {
+ dyStringPrintf(dy, "%d", da->id);
+ if (da->next)
+ dyStringPrintf(dy, ",");
+ }
+dyStringPrintf(dy, ")");
+
+char *query = dyStringCannibalize(&dy);
+struct sqlResult *sr = sqlGetResult(conn, query);
+char **row = NULL;
+while ((row = sqlNextRow(sr)) != NULL)
+ {
+ char *name = row[0];
+ double val = atof(row[1]);
+ jsonAddDouble(js, name, val);
+ }
+}
+
+void sendUniqueMatch(struct sqlConnection *conn, struct json *js,
+ int cohort_id, char *feature_name, char *source,
+ struct datasets *daList)
+{
+if (sameString(source, "gene/geneset"))
+ sendAnalysisFeatureData(conn, js, cohort_id, feature_name);
+else if (sameString(source, "clinical"))
+ sendClinicalData(conn, js, cohort_id, feature_name, daList);
+}
+
+void getFeatureData()
+{
+int cohort_id = cartUsualInt(cart, bioIntCohortId, -1);
+if (cohort_id == -1)
+ cohort_id = 1; // hard code for first analysis during testing!
+
+/* feature source = gene,geneset,clinical... */
+char *source = cartOptionalString(cart, bioIntSourceName);
+
+char *feature_name = cartOptionalString(cart, bioIntFeatureName);
+if (!feature_name)
+ errAbort("%s or %s must be set for mode=getFeatureData\n", bioIntFeature, bioIntFeatureId);
+
+struct sqlConnection *conn = hAllocConnProfile(localDb, db);
+
+struct datasets *daList = getDatasetsByCohortId(conn, cohort_id);
+if (!daList)
+ errAbort("No datasets matching cohort_id = %d", cohort_id);
+
+struct json *js = newJson();
+if (source)
+ sendUniqueMatch(conn, js, cohort_id, feature_name, source, daList);
+else
+ {
+ struct slPair *spList = searchForFeatures(conn, cohort_id, daList, feature_name);
+
+ int numMatched = slCount(spList);
+ if (numMatched == 0)
+ sendNoMatch(js);
+ else if (numMatched == 1)
+ {
+ source = spList->val;
+ sendUniqueMatch(conn, js, cohort_id, spList->name, source, daList);
+ }
+ else
+ sendAmbiguities(js, spList);
+ }
if (js)
hPrintf("%s\n", js->print(js));
hFreeConn(&conn);
}
void getClinicalFeatures()
{
int cohort_id = cartUsualInt(cart, bioIntCohortId, -1);
if (cohort_id == -1)
cohort_id = 1; // hard code for first analysis during testing!
struct sqlConnection *conn = hAllocConnProfile(localDb, db);
struct datasets *da, *daList = getDatasetsByCohortId(conn, cohort_id);
if (!daList)
{
hFreeConn(&conn);
errAbort("No datasets matching cohort_id = %d", cohort_id);
}
struct dyString *dy = dyStringNew(100);
dyStringPrintf(dy,
"select DISTINCT %s.* from %s join %s on %s.id = %s.feature_id "
"join %s on %s.sample_id = %s.id where %s.dataset_id in (",
FE_TABLE, FE_TABLE, CD_TABLE, FE_TABLE, CD_TABLE,
SA_TABLE, CD_TABLE, SA_TABLE, SA_TABLE);
for (da = daList; da; da = da->next)
{
dyStringPrintf(dy, "%d", da->id);
if (da->next)
dyStringPrintf(dy, ",");
}
dyStringPrintf(dy, ")");
char *query = dyStringCannibalize(&dy);
struct features *fe, *feList = featuresLoadByQuery(conn, query);
struct json *js = newJson();
struct json *feature, *features = jsonAddContainerList(js, "features");
feature = features;
for (fe = feList; fe; fe = fe->next)
{
jsonAddInt(feature, "id", fe->id);
jsonAddString(feature, "name", fe->name);
jsonAddString(feature, "shortLabel", fe->shortLabel);
jsonAddString(feature, "longLabel", fe->longLabel);
if (fe->next)
feature = jsonAddContainerToList(&features);
}
if (js)
hPrintf("%s\n", js->print(js));
hFreeConn(&conn);
}
void getClinicalData()
{
int cohort_id = cartUsualInt(cart, bioIntCohortId, -1);
if (cohort_id == -1)
cohort_id = 1; // hard code for first analysis during testing!
int feature_id = cartUsualInt(cart, bioIntFeatureId, -1);
char *feature_name = cartOptionalString(cart, bioIntFeatureName);
if (!feature_name && feature_id == -1)
errAbort("%s or %s must be set for mode=getClinicalData\n", bioIntFeature, bioIntFeatureId);
struct sqlConnection *conn = hAllocConnProfile(localDb, db);
struct features *fe = NULL;
if (feature_id == -1)
fe = getFeaturesByName(conn, feature_name);
else
fe = getFeaturesById(conn, feature_id);
if (!fe)
{
hFreeConn(&conn);
errAbort("Could not find clinical feature in db");
}
struct datasets *da, *daList = getDatasetsByCohortId(conn, cohort_id);
if (!daList)
{
hFreeConn(&conn);
errAbort("No datasets matching cohort_id = %d", cohort_id);
}
struct dyString *dy = dyStringNew(100);
dyStringPrintf(dy,
"select DISTINCT %s.name, %s.val from %s join %s on %s.sample_id = %s.id ",
SA_TABLE, CD_TABLE, CD_TABLE, SA_TABLE, CD_TABLE, SA_TABLE);
dyStringPrintf(dy,
"where %s.feature_id = %d and %s.dataset_id in (",
CD_TABLE, fe->id, SA_TABLE);
for (da = daList; da; da = da->next)
{
dyStringPrintf(dy, "%d", da->id);
if (da->next)
dyStringPrintf(dy, ",");
}
dyStringPrintf(dy, ")");
char *query = dyStringCannibalize(&dy);
struct json *js = newJson();
struct sqlResult *sr = sqlGetResult(conn, query);
char **row = NULL;
while ((row = sqlNextRow(sr)) != NULL)
{
char *name = row[0];
double val = atof(row[1]);
jsonAddDouble(js, name, val);
}
if (js)
hPrintf("%s\n", js->print(js));
hFreeConn(&conn);
}
void getMostCorrelated()
{
int takeTop = cartUsualInt(cart, bioIntTakeTop, 5);
int cohort_id = cartUsualInt(cart, bioIntCohortId, -1);
if (cohort_id == -1)
cohort_id = 1; // hard code for first analysis during testing!
int feature_id = cartUsualInt(cart, bioIntFeatureId, -1);
char *feature_name = cartOptionalString(cart, bioIntFeatureName);
if (!feature_name && feature_id == -1)
- errAbort("%s or %s must be set for mode=getFeatureData\n", bioIntFeature, bioIntFeatureId);
+ errAbort("%s or %s must be set for mode=getMostCorrelated\n", bioIntFeature, bioIntFeatureId);
struct sqlConnection *conn = hAllocConnProfile(localDb, db);
struct analysisFeatures *af = NULL;
if (feature_id == -1)
af = getAnalysisFeaturesByName(conn, feature_name);
else
af = getAnalysisFeaturesById(conn, feature_id);
if (!af)
{
hFreeConn(&conn);
errAbort("Could not find analysisFeature in db");
}
struct cohortCorr *cc = getCohortCorrByCohortId(conn, cohort_id);
if (!cc)
{
hFreeConn(&conn);
errAbort("No cohort correlation table with cohort_id = %d.\n", cohort_id);
}
struct dyString *dy = dyStringNew(100);
dyStringPrintf(dy, "select a1.feature_name, a2.feature_name, %s.val from %s "
"join %s as a1 on %s.feature_id1 = a1.id ",
cc->result_table, cc->result_table, AF_TABLE, cc->result_table);
dyStringPrintf(dy, "join %s as a2 on %s.feature_id2 = a2.id ",
AF_TABLE, cc->result_table);
dyStringPrintf(dy, "where feature_id1 = %d or feature_id2 = %d order by %s.val DESC",
af->id, af->id, cc->result_table);
char *query = dyStringCannibalize(&dy);
struct slPair *sp, *spList = NULL;
struct sqlResult *sr = sqlGetResult(conn, query);
char **row = NULL;
while ((row = sqlNextRow(sr)) != NULL)
{
char *name = NULL;
char *name1 = row[0];
char *name2 = row[1];
double val = atof(row[2]);
if (sameString(name1, af->feature_name))
name = name2;
else if (sameString(name2, af->feature_name))
name = name1;
else // doesn't match either, should *never* get here
continue;
AllocVar(sp);
sp->name = cloneString(name);
sp->val = slDoubleNew(val);
slAddHead(&spList, sp);
}
slReverse(&spList);
int count;
struct json *js = newJson();
struct json *corrs = jsonAddContainer(js, "Top Correlated");
for (sp = spList, count = 0; sp && (count < takeTop); sp = sp->next, count++)
{
struct slDouble *sd = sp->val;
if (sd->val < 0.0)
continue;
jsonAddDouble(corrs, sp->name, sd->val);
}
slReverse(&spList);
corrs = jsonAddContainer(js, "Top Anti-Correlated");
for (sp = spList, count = 0; sp && (count < takeTop); sp = sp->next, count++)
{
struct slDouble *sd = sp->val;
if (sd->val > 0.0)
continue;
jsonAddDouble(corrs, sp->name, sd->val);
}
if (js)
hPrintf("%s", js->print(js));
hFreeConn(&conn);
}
void dispatchRoutines()
/* Look at command variables in cart and figure out which
* page to draw. */
{
/* retrieve cart variables, handle various modes */
char *mode = cartOptionalString(cart, bioIntMode);
if (!mode)
errAbort("%s is required.", bioIntMode);
if (sameString(mode, "getAnalyses"))
getAnalyses();
else if (sameString(mode, "getFeatureData"))
getFeatureData();
else if (sameString(mode, "getClinicalData"))
getClinicalData();
else if (sameString(mode, "getClinicalFeatures"))
getClinicalFeatures();
else if (sameString(mode, "getMostCorrelated"))
getMostCorrelated();
else
errAbort("Incorrect mode = %s", mode);
cartRemovePrefix(cart, bioIntPrefix);
}
void hghDoUsualHttp()
/* Wrap html page dispatcher with code that writes out
* HTTP header and write cart back to database. */
{
cartWriteCookie(cart, hUserCookie());
printf("Content-Type:application/x-javascript\r\n\r\n");
/* Dispatch other pages, that actually want to write HTML. */
cartWarnCatcher(dispatchRoutines, cart, jsonEarlyWarningHandler);
cartCheckout(&cart);
}
char *excludeVars[] = {"Submit", "submit", NULL};
int main(int argc, char *argv[])
/* Process command line. */
{
htmlPushEarlyHandlers();
cgiSpoof(&argc, argv);
htmlSetStyle(htmlStyleUndecoratedLink);
oldVars = hashNew(12);
cart = cartForSession(hUserCookie(), excludeVars, oldVars);
hghDoUsualHttp();
return 0;
}