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 4 -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
@@ -139,8 +139,31 @@
 
 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 */
@@ -173,31 +196,97 @@
 
 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)
@@ -217,23 +306,10 @@
     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;
@@ -243,8 +319,96 @@
     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));
 
@@ -378,9 +542,9 @@
 
 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;