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

1.13 2010/01/31 02:45:46 jsanborn
added sorting
Index: src/hg/instinct/hgGeneset/hgGenesets.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/hgGeneset/hgGenesets.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -b -B -U 4 -r1.12 -r1.13
--- src/hg/instinct/hgGeneset/hgGenesets.c	31 Jan 2010 01:17:07 -0000	1.12
+++ src/hg/instinct/hgGeneset/hgGenesets.c	31 Jan 2010 02:45:46 -0000	1.13
@@ -18,8 +18,9 @@
 #include "hgStatsLib.h"
 #include "featuresLib.h" 
 #include "json.h"
 #include "hgStats.h"
+#include "heatmapUtility.h"
 #include "hgGenesets.h"
 
 static char const rcsid[] = "$Id$";
 /* ---- Global variables. ---- */
@@ -864,51 +865,67 @@
 
 return rdList;
 }
 
-void clusterRawData(struct rawData *rdList, struct mapSettings *settings, 
-		    char *metricStr, char *methodStr)
+void updateSampleOrder(struct mapSettings *settings, struct slName *slList)
 {
-char metric = getClusterMetric(metricStr);
-char method = getClusterMethod(methodStr);
-
-if (method == '-' || metric == '-')
-    errAbort("Invalid clustering method or metric string.\n");
-
-struct slName *sl, *geneOrder = NULL, *sampleOrder = NULL;
-clusterData(rdList, settings, method, metric, &geneOrder, &sampleOrder);
+if (!slList)
+    return;
 
-if (sampleOrder)
-    {    
-    hashFree(&settings->x_index);
-    settings->x_index = hashNew(0);
+struct slName *sl;
+hashFree(&settings->x_index);
+settings->x_index = hashNew(0);
     
-    struct hashEl *el;
-    int numSamples = 0;
-    for (sl = sampleOrder; sl; sl = sl->next)
+struct hashEl *el;
+int numSamples = 0;
+for (sl = slList; sl; sl = sl->next)
 	{
 	if ((el = hashLookup(settings->x_index, sl->name)) != NULL)
 	    continue;
 	hashAddInt(settings->x_index, sl->name, numSamples);
 	numSamples += 1;
 	}
-    }
 
-if (geneOrder)
-    {
-    hashFree(&settings->y_index);
-    settings->y_index = hashNew(0);
+char *list = strFromSlNameList(slList);
+cartSetString(cart, hghSampleIds, list);
+}
     
-    struct hashEl *el;
-    int numFeatures = 0;
-    for (sl = geneOrder; sl; sl = sl->next)
+void updateFeatureOrder(struct mapSettings *settings, struct slName *slList)
+{
+if (!slList)
+    return;
+
+struct slName *sl;
+hashFree(&settings->y_index);
+settings->y_index = hashNew(0);
+
+struct hashEl *el;
+int numFeatures = 0;
+for (sl = slList; sl; sl = sl->next)
 	{
 	if ((el = hashLookup(settings->y_index, sl->name)) != NULL)
 	    continue;
 	hashAddInt(settings->y_index, sl->name, numFeatures);
 	numFeatures += 1;
 	}
-    }
+char *list = strFromSlNameList(slList);
+cartSetString(cart, hghFeatureIds, list);
+}
+
+void clusterRawData(struct rawData *rdList, struct mapSettings *settings, 
+		    char *metricStr, char *methodStr)
+{
+char metric = getClusterMetric(metricStr);
+char method = getClusterMethod(methodStr);
+
+if (method == '-' || metric == '-')
+    errAbort("Invalid clustering method or metric string.\n");
+
+struct slName *geneOrder = NULL, *sampleOrder = NULL;
+clusterData(rdList, settings, method, metric, &geneOrder, &sampleOrder);
+
+updateSampleOrder(settings, sampleOrder);
+updateFeatureOrder(settings, geneOrder);
 }
 
 
 void jsonSettings(struct json *js, struct mapSettings *settings)
@@ -962,8 +977,9 @@
 	continue;
     int start = ceil(((double) i) * settings->hm_x_scale) + settings->hm_x;
     int stop = ceil(((double) i + 1) * settings->hm_x_scale) + settings->hm_x;
     
+    jsonAddInt(new, "id", atoi(el->name));
     jsonAddString(new, "name", name);
     jsonAddInt(new, "start", start);
     jsonAddInt(new, "stop", stop);
 
@@ -985,16 +1001,92 @@
 	continue;
     int start = round(((double) i) * settings->hm_y_scale) + settings->hm_y;
     int stop = round(((double) i + 1) * settings->hm_y_scale) + settings->hm_y;
     
+    jsonAddInt(new, "id", atoi(el->name));
     jsonAddString(new, "name", name);
     jsonAddInt(new, "start", start);
     jsonAddInt(new, "stop", stop);
 
     new = NULL;
     }
 }
 
+struct slData {
+    struct slData *next;
+    char *name;
+    double val;
+};
+
+int slDataCmp(const void *va, const void *vb)
+/* Compare function to sort array of ints. */
+{
+const struct slData *a = *((struct slData **)va);
+const struct slData *b = *((struct slData **)vb);
+double diff = a->val - b->val;
+if (diff < 0)
+    return -1;
+else if (diff > 0)
+    return 1;
+else
+    return 0;
+}
+
+
+void sortByFeature(struct sqlConnection *conn, struct datasets *da, 
+		   int feature_id, char *direction, struct samples *samples, 
+		   struct mapSettings *settings)
+{
+struct samples *sa;
+struct dyString *dy = dyStringNew(100);
+dyStringPrintf(dy, "select sample_id from %s where sample_id in (",
+	       da->data_table);
+for (sa = samples; sa; sa = sa->next)
+    {
+    dyStringPrintf(dy, "%d", sa->sample_id);
+    if (sa->next)
+	dyStringPrintf(dy, ",");
+    }
+dyStringPrintf(dy, ") and feature_id = %d order by val", feature_id);
+char *query = dyStringCannibalize(&dy);
+
+struct slName *slList = sqlQuickList(conn, query);
+if (!direction || sameString(direction, "DESC"))
+    slReverse(&slList);
+
+updateSampleOrder(settings, slList);
+}
+
+void sortBySample(struct sqlConnection *conn, struct datasets *da, 
+		  int sample_id, char *direction, struct analysisFeatures *afList, 
+		  struct mapSettings *settings)
+{
+struct analysisFeatures *af;
+struct dyString *dy = dyStringNew(100);
+dyStringPrintf(dy, "select feature_id from %s where feature_id in (",
+	       da->data_table);
+for (af = afList; af; af = af->next)
+    {
+    dyStringPrintf(dy, "%d", af->id);
+    if (af->next)
+	dyStringPrintf(dy, ",");
+    }
+dyStringPrintf(dy, ") and sample_id = %d order by val", sample_id);
+char *query = dyStringCannibalize(&dy);
+
+struct slName *slList = sqlQuickList(conn, query);
+if (!direction || sameString(direction, "DESC"))
+    slReverse(&slList);
+
+updateFeatureOrder(settings, slList);
+}
+
+void cartUpdateSettings(struct mapSettings *settings)
+{
+cartSetInt(cart, hghWidth, settings->width);
+cartSetInt(cart, hghHeight, settings->height);
+}
+
 void drawHeatmap()
 {
 struct sqlConnection *conn = hAllocConnProfile(localDb, db);
 
@@ -1005,11 +1097,17 @@
 int dataset_id   = cartUsualInt(cart, hghDatasetId, -1);
 
 int getFirst = cartUsualInt(cart, hghGetFirst, -1);
 
+/* Clustering */
 char *metric = cartOptionalString(cart, hghClusterMetric);
 char *method = cartOptionalString(cart, hghClusterMethod);
 
+/* Sorting by sample/gene */
+int sortFeatureId = cartUsualInt(cart, hghSortFeatureId, -1);
+int sortSampleId  = cartUsualInt(cart, hghSortSampleId, -1);
+char *sortDir     = cartOptionalString(cart, hghSortDir);
+
 struct datasets *da = getDatasetById(conn, dataset_id);
 if (!da)
     errAbort("No dataset matching id = %d\n", dataset_id);
 
@@ -1019,9 +1117,12 @@
     //errAbort("%s is required\n", hghSampleIds);
     }
 
 if (!featureIds && getFirst > 0)
+    {
     featureIds = getNumAnalysisFeatureIdsInDataset(conn, da, getFirst);
+    cartSetString(cart, hghFeatureIds, featureIds);
+    }
 
 if (!featureIds)
     errAbort("%s is required\n", hghFeatureIds);
 
@@ -1046,8 +1146,14 @@
     errAbort("No data matching input parameters.");
 
 if (metric && method)
     clusterRawData(rdList, settings, metric, method);
+else if (sortFeatureId > 0)
+    sortByFeature(conn, da, sortFeatureId, sortDir, samples, settings);
+else if (sortSampleId > 0)
+    sortBySample(conn, da, sortSampleId, sortDir, afList, settings);
+
+cartUpdateSettings(settings);
 
 char *filename = heatmapGif(conn, rdList, settings);
 
 struct json *js = newJson();
@@ -1051,14 +1157,15 @@
 char *filename = heatmapGif(conn, rdList, settings);
 
 struct json *js = newJson();
 jsonAddString(js, "image", filename);
-
 jsonSettings(js, settings);
 if (js)
     hPrintf("%s\n", js->print(js));
-}
 
+cartRemovePrefix(cart, hghSortPrefix);
+cartRemovePrefix(cart, hghClusterPrefix);
+}
 
 struct searchResults {
     struct searchResults *next;
     int id;
@@ -1190,8 +1296,66 @@
 cartRemovePrefix(cart, hghInfoPrefix);
 }
 
 
+struct slInt *slIntListFromComma(char *list)
+{ /* very dumb/lazy way of doing this */
+
+struct slName *sl, *slList = slNameListFromComma(list);
+struct slInt *si, *siList = NULL;
+
+for (sl = slList; sl; sl = sl->next)
+    {
+    si = slIntNew(atoi(sl->name));
+    slAddHead(&siList, si);
+    }
+slReverse(&siList);
+
+return siList;
+}
+
+void requestState()
+{
+int datasetId = cartUsualInt(cart, hghDatasetId, -1);
+int width = cartUsualInt(cart, hghWidth, -1);
+int height = cartUsualInt(cart, hghHeight, -1);
+
+char *samples = cartOptionalString(cart, hghSampleIds);
+char *features = cartOptionalString(cart, hghFeatureIds);
+
+struct json *js = newJson();
+
+if (datasetId >= 0)
+    jsonAddInt(js, hghDatasetId, datasetId);
+if (width >= 0)
+    jsonAddInt(js, hghWidth, width);
+if (height >= 0)
+    jsonAddInt(js, hghHeight, height);
+
+if (samples)
+    {
+    struct slInt *siList = slIntListFromComma(samples);
+    jsonAddSlInt(js, hghSampleIds, siList);
+    }
+
+if (features)
+    {
+    struct slInt *siList = slIntListFromComma(features);
+    jsonAddSlInt(js, hghFeatureIds, siList);
+    }
+
+if (js)
+    hPrintf("%s\n", js->print(js));
+}
+
+void resetState()
+{
+cartRemovePrefix(cart, hghPrefix);
+struct json *js = newJson();
+if (js)
+    hPrintf("%s\n", js->print(js));
+}
+
 void dispatchRoutines()
 /* Look at command variables in cart and figure out which
  * page to draw. */
 {
@@ -1209,10 +1373,12 @@
 else if (sameString(mode, "getCohorts"))
     getCohorts();
 else if (sameString(mode, "getSamples"))
     getSamples();
+else if (sameString(mode, "requestState"))
+    requestState();
 else if (sameString(mode, "resetState"))
-    cartRemovePrefix(cart, hghPrefix);
+    resetState();
 else
     errAbort("Incorrect mode = %s", mode);
 
 //cartRemovePrefix(cart, hghPrefix);