34f032efa49ab0548b4c604e0316376009501f20
kent
  Thu Aug 21 16:44:20 2014 -0700
Program to assign colors to a list based on distances seems to work.
diff --git src/utils/distributeRgbRainbow/distributeRgbRainbow.c src/utils/distributeRgbRainbow/distributeRgbRainbow.c
new file mode 100644
index 0000000..c8f15a8
--- /dev/null
+++ src/utils/distributeRgbRainbow/distributeRgbRainbow.c
@@ -0,0 +1,107 @@
+/* distributeRgbRainbow - Associate colors with items on a list where distance between colors 
+ * is proportional to distance between items. */
+#include "common.h"
+#include "linefile.h"
+#include "hash.h"
+#include "options.h"
+#include "obscure.h"
+#include "pairDistance.h"
+#include "rainbow.h"
+
+double gStart = 0, gEnd = 0.85;   /* Global start/end and defaults */
+
+void usage()
+/* Explain usage and exit. */
+{
+errAbort(
+  "distributeRgbRainbow - Associate colors with items on a list where distance between colors \n"
+  "is proportional to distance between items.\n"
+  "usage:\n"
+  "   distributeRgbRainbow in.lst in.pairs out.tab\n"
+  "where:\n"
+  "   in.lst has one identifier per line\n"
+  "   in.pairs is whitespace separated with the columns <a> <b> <distance>\n"
+  "      where a and b are items from in.lst\n"
+  "   out.tab is tab-separated with columns <identifier> <pos> <r> <g> <b>\n"
+  "      where identifier is from in.lst, pos is a number between 0 and 1, and\n"
+  "      r,g,b are color components between 0 and 255\n"
+  "options:\n"
+  "   -start=0.N - a number between 0 and 1 that is rainbow start (default %g - red)\n"
+  "   -end=0.N - a number between 0 and 1 that is rainbow end (default %g - purple)\n"
+  "   -invert - deal with cases such as correlation for in.pairs where high numbers are proximite\n"
+  , gStart, gEnd
+  );
+}
+
+/* Command line validation table. */
+static struct optionSpec options[] = {
+   {"start", OPTION_DOUBLE},
+   {"end", OPTION_DOUBLE},
+   {"invert", OPTION_BOOLEAN},
+   {NULL, 0},
+};
+
+void outputItem(FILE *f, char *name, double colorPos)
+/* Print out one item */
+{
+struct rgbColor c = saturatedRainbowAtPos(colorPos);
+fprintf(f, "%s\t%g\t%d\t%d\t%d\n", name, colorPos, c.r, c.g, c.b);
+}
+
+void distributeRgbRainbow(char *inList, char *inPairs, char *outTab)
+/* distributeRgbRainbow - Associate colors with items on a list where distance between colors 
+ * is proportional to distance between items. */
+{
+/* Read in inputs */
+struct slName *item, *itemList = readAllLines(inList);
+verbose(1, "%d items in %s\n", slCount(itemList), inList);
+struct pairDistance *pairList= pairDistanceReadAll(inPairs);
+verbose(1, "%d pairs in %s\n", slCount(pairList), inPairs);
+struct hash *pairHash = pairDistanceHashList(pairList);
+
+/* Open output, and just finish early if it should be empty */
+FILE *f = mustOpen(outTab, "w");
+if (itemList == NULL)
+    return;
+
+/* Cope with invert option. */
+if (optionExists("invert"))
+    pairDistanceInvert(pairList);
+
+/* Add up total distance between all items */
+double totalDistance = 0.0;
+for (item = itemList; item != NULL; item = item->next)
+    {
+    struct slName *nextItem = item->next;
+    if (nextItem == NULL)
+         break;
+    totalDistance += pairDistanceHashLookup(pairHash, item->name, nextItem->name);
+    }
+
+double colorRange = gEnd - gStart;
+outputItem(f, itemList->name, gStart);
+
+double soFar = 0.0;
+for (item = itemList; item != NULL; item = item->next)
+    {
+    struct slName *nextItem = item->next;
+    if (nextItem == NULL)
+         break;
+    double distance = pairDistanceHashLookup(pairHash, item->name, nextItem->name);
+    soFar += distance;
+    outputItem(f, nextItem->name, gStart + (soFar/totalDistance * colorRange));
+    }
+carefulClose(&f);
+}
+
+int main(int argc, char *argv[])
+/* Process command line. */
+{
+optionInit(&argc, argv, options);
+if (argc != 4)
+    usage();
+gStart = optionDouble("start", gStart);
+gEnd = optionDouble("end", gEnd);
+distributeRgbRainbow(argv[1], argv[2], argv[3]);
+return 0;
+}