src/hg/instinct/hgGeneset/hgGenesets.c 1.12

1.12 2010/01/31 01:17:07 jsanborn
added search
Index: src/hg/instinct/hgGeneset/hgGenesets.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/hgGeneset/hgGenesets.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -b -B -U 4 -r1.11 -r1.12
--- src/hg/instinct/hgGeneset/hgGenesets.c	29 Jan 2010 23:47:20 -0000	1.11
+++ src/hg/instinct/hgGeneset/hgGenesets.c	31 Jan 2010 01:17:07 -0000	1.12
@@ -120,8 +120,19 @@
 
 return analysisFeaturesLoadByQuery(conn, query);
 }
 
+struct analysisFeatures *getAnalysisFeaturesByNameType(struct sqlConnection *conn, 
+						       char *name, char *type)
+{
+char query[256];
+safef(query, sizeof(query), 
+      "select * from %s where feature_name = \"%s\" and type = \"%s\"", 
+      AF_TABLE, name, type);
+
+return analysisFeaturesLoadByQuery(conn, query);
+}
+
 struct analysisFeatures *getAnalysisFeaturesById(struct sqlConnection *conn, 
 						 int id)
 {
 char query[256];
@@ -207,8 +218,19 @@
 
 return genesetsLoadByQuery(conn, query);
 }
 
+struct slInt *getGenesInGeneset(struct sqlConnection *conn, int id)
+{
+char query[256];
+safef(query, sizeof(query), 
+      "select DISTINCT gene_id from %s where id = %d",
+      GG_TABLE, id);
+
+return sqlQuickNumList(conn, query);
+}
+
+
 char *getDataTypeById(struct sqlConnection *conn, int id)
 {
 char query[256];
 safef(query, sizeof(query), 
@@ -467,14 +489,8 @@
 
 hFreeConn(&conn);
 }
 
-void sendNoMatch(struct json *js)
-{
-return;
-}
-
-
 void sendRawFeatureData(struct sqlConnection *conn, struct json *js, 
 			struct datasets *da, struct samples *saList, 
 			struct analysisFeatures *af)
 {
@@ -1041,8 +1057,141 @@
 if (js)
     hPrintf("%s\n", js->print(js));
 }
 
+
+struct searchResults {
+    struct searchResults *next;
+    int id;
+    char *name;
+    char *type;
+    double val;
+};
+
+int searchResultsCmp(const void *va, const void *vb)
+/* Compare function to sort array of ints. */
+{
+const struct searchResults *a = *((struct searchResults **)va);
+const struct searchResults *b = *((struct searchResults **)vb);
+double diff = a->val - b->val;
+if (diff < 0)
+    return -1;
+else if (diff > 0)
+    return 1;
+else
+    return 0;
+}
+
+struct searchResults *searchForFeatures(struct sqlConnection *conn, char *feature_name)
+{
+int maxResponse = 10;
+/* Check analysis features */
+char query[256];
+safef(query, sizeof(query),
+      "select id,feature_name,type from %s where feature_name like \"%%%s%%\" "
+      "order by length(feature_name);",
+      AF_TABLE, feature_name);
+
+int count = 0;
+struct searchResults *sp, *spList = NULL;
+struct sqlResult *sr = sqlGetResult(conn, query);
+char **row = NULL;
+while ((row = sqlNextRow(sr)) != NULL)
+    {
+    int id = atoi(row[0]);
+    char *name = row[1];
+    char *type = row[2];
+    AllocVar(sp);
+    sp->id   = id;
+    sp->name = cloneString(name);
+    sp->type = cloneString(type);
+    sp->val  = strlen(sp->name);
+    slAddHead(&spList, sp);
+    if (count > maxResponse)
+	break;
+    count++;
+    }
+sqlFreeResult(&sr);
+
+slSort(&spList, searchResultsCmp);
+return spList;
+}
+
+void sendNoMatch(struct json *js)
+{
+return;
+}
+
+void sendAmbiguities(struct json *js, struct searchResults *spList)
+{
+struct searchResults *sp;
+for (sp = spList; sp; sp = sp->next)
+    {
+    struct json *new = jsonAddContainer(js, sp->name);
+    jsonAddInt(new, "id", sp->id);
+    jsonAddString(new, "type", sp->type);
+    }
+}
+
+void getMatching()
+{
+struct sqlConnection *conn = hAllocConnProfile(localDb, db);
+
+char *term = cartOptionalString(cart, hghSearchTerm);
+struct json *js = newJson();
+
+if (sameString(term, ""))  // blank was sent, return no match
+    sendNoMatch(js);
+else
+    {
+    struct searchResults *spList = searchForFeatures(conn, term);
+    int numMatched = slCount(spList);
+    if (numMatched == 0)
+	sendNoMatch(js);
+    else
+	sendAmbiguities(js, spList);
+    }
+
+if (js)
+    hPrintf("%s\n", js->print(js));
+
+cartRemovePrefix(cart, hghSearchTerm);
+}
+
+void getInfo()
+{
+struct sqlConnection *conn = hAllocConnProfile(localDb, db);
+
+int id     = cartUsualInt(cart, hghInfoId, -1);
+char *name = cartOptionalString(cart, hghInfoName);
+char *type = cartOptionalString(cart, hghInfoType);
+
+if (id == -1 && (!name || !type))
+    errAbort("Insufficient input for getInfo().\n");
+
+struct analysisFeatures *af;
+if (id > 0)
+    af = getAnalysisFeaturesById(conn, id);
+else
+    af = getAnalysisFeaturesByNameType(conn, name, type);
+
+if (!sameString(af->type, "geneset"))
+    errAbort("getInfo only supports retrieving geneset information.\n");
+
+
+struct json *js = newJson();
+
+struct slInt *geneIds = getGenesInGeneset(conn, af->id);
+struct json *new = jsonAddContainer(js, af->feature_name);
+jsonAddSlInt(new, "ids", geneIds);
+
+if (js)
+    hPrintf("%s\n", js->print(js));
+
+cartRemovePrefix(cart, hghInfoPrefix);
+}
+
+
 void dispatchRoutines()
 /* Look at command variables in cart and figure out which
  * page to draw. */
 {
@@ -1052,16 +1201,22 @@
     errAbort("%s is required.", hghMode);
 
 if (sameString(mode, "drawHeatmap"))
     drawHeatmap();
+else if (sameString(mode, "getInfo"))
+    getInfo();
+else if (sameString(mode, "getMatching"))
+    getMatching();
 else if (sameString(mode, "getCohorts"))
     getCohorts();
 else if (sameString(mode, "getSamples"))
     getSamples();
+else if (sameString(mode, "resetState"))
+    cartRemovePrefix(cart, hghPrefix);
 else
     errAbort("Incorrect mode = %s", mode);
 
-cartRemovePrefix(cart, hghPrefix);
+//cartRemovePrefix(cart, hghPrefix);
 }
 
 void hghDoUsualHttp()
 /* Wrap html page dispatcher with code that writes out