src/utils/plotDataMatrix/plotDataMatrix.c 1.1

1.1 2010/05/26 22:41:32 kent
Matrix plotter seems to work.
Index: src/utils/plotDataMatrix/plotDataMatrix.c
===================================================================
RCS file: src/utils/plotDataMatrix/plotDataMatrix.c
diff -N src/utils/plotDataMatrix/plotDataMatrix.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/utils/plotDataMatrix/plotDataMatrix.c	26 May 2010 22:41:32 -0000	1.1
@@ -0,0 +1,240 @@
+/* plotDataMatrix - Create an image showing a matrix of data values.. */
+#include "common.h"
+#include "linefile.h"
+#include "hash.h"
+#include "options.h"
+#include "sqlNum.h"
+#include "vGfx.h"
+#include "memgfx.h"
+
+struct vGfx *vgOpenGif(int width, int height, char *fileName, boolean useTransparency);
+
+static char const rcsid[] = "$Id$";
+
+int cellWidth = 25;
+int cellHeight = 25;
+
+boolean clCorrelate = FALSE;
+
+void usage()
+/* Explain usage and exit. */
+{
+errAbort(
+  "plotDataMatrix - Create an image showing a matrix of data values.\n"
+  "usage:\n"
+  "   plotDataMatrix inPairs.tab xLabels.tab yLabels.tab output.gif\n"
+  "where the three inputs are all tab-separated text files:\n"
+  "   inPairs.tab has 3 columns:  xId, yId, and a floating point number\n"
+  "   xLabels.tab has 2 columns: xId and xLabel\n"
+  "   yLabels.tab has 2 column: yId and yLabel\n"
+  "The label files also determine the order (top to bottom, right to left)\n"
+  "of the display.\n"
+  "options:\n"
+  "   -correlate Treat as a correlation matrix.  Fill in the diagonal with\n"
+  "              perfect score and reflect other squares\n"
+  );
+}
+
+static struct optionSpec options[] = {
+   {"correlate", OPTION_BOOLEAN},
+   {NULL, 0},
+};
+
+struct sparseCell
+/* Two id's and a value - a representation of a sparse matrix cell. */
+    {
+    struct sparseCell *next;
+    char *xId;		/* ID for columns.  Allocated in matrix hash.  */
+    char *yId;		/* ID for rows.  Allocated in matrix hash.  */
+    double val;		/* Value at this position in matrix. */
+    };
+
+struct sparseMatrix
+/* A matrix stored as a list of cells with values. */
+    {
+    struct sparseMatrix *next;
+    struct sparseCell *cellList;	/* List of all cells */
+    struct hash *xIdHash;	/* Hash of column IDs. */
+    struct hash *yIdHash;	/* Hash of row IDs. */
+    };
+
+struct sparseMatrix *sparseMatrixRead(char *fileName)
+/* Read in a sparse matrix file and return it in memory structure. */
+{
+/* Open up file */
+struct lineFile *lf = lineFileOpen(fileName, TRUE);
+char *row[3];
+
+/* Start up matrix data structure. */
+struct sparseMatrix *mat;
+AllocVar(mat);
+mat->xIdHash = hashNew(0);
+mat->yIdHash = hashNew(0);
+
+/* Loop through file adding cells. */
+while (lineFileRow(lf, row))
+    {
+    struct sparseCell *cell;
+    AllocVar(cell);
+    cell->xId = hashStoreName(mat->xIdHash, row[0]);
+    cell->yId = hashStoreName(mat->yIdHash, row[1]);
+    cell->val = sqlDouble(row[2]);
+    slAddHead(&mat->cellList, cell);
+    }
+slReverse(&mat->cellList);
+
+/* Clean up and go home. */
+lineFileClose(&lf);
+return mat;
+}
+
+struct sparseCell *sparseMatrixFindCell(struct sparseMatrix *mat, char *xId, char *yId)
+/* Rummage through cell list looking for match. */
+{
+struct sparseCell *cell;
+for (cell = mat->cellList; cell != NULL; cell = cell->next)
+    {
+    if (sameString(cell->xId, xId) && sameString(cell->yId, yId))
+        return cell;
+    }
+return NULL;
+}
+
+struct slPair *labelsRead(char *fileName, struct hash *idHash, char *inPairsFile)
+/* Read in file into a list of pairs where name is id, val is label. */
+{
+/* Open up file */
+struct lineFile *lf = lineFileOpen(fileName, TRUE);
+char *row[2];
+
+/* Loop through file adding pairs to list. */
+struct slPair *list = NULL;
+while (lineFileRowTab(lf, row))
+    {
+    char *id = row[0];
+    char *label = row[1];
+    if (!hashLookup(idHash, id))
+        verbose(2, "id %s is in line %d of %s, but not in %s", id, 
+		lf->lineIx, lf->fileName, inPairsFile);
+    struct slPair *el = slPairNew(id, cloneString(label));
+    slAddHead(&list, el);
+    }
+slReverse(&list);
+
+lineFileClose(&lf);
+return list;
+}
+
+int widestLabelWidth(MgFont *font, struct slPair *labelList)
+/* Return width in pixels of widest label in list. */
+{
+int widest = 0;
+struct slPair *label;
+for (label = labelList; label != NULL; label = label->next)
+    {
+    int width = mgFontStringWidth(font, label->val);
+    if (widest < width)
+        widest = width;
+    }
+return widest;
+}
+
+void makeImage(struct sparseMatrix *mat, struct slPair *xLabelList, struct slPair *yLabelList, char *fileName)
+/* Make image file from matrix and labels. */
+{
+/* Figure out dimensions */
+int xCount = slCount(xLabelList);
+int yCount = slCount(yLabelList);
+MgFont *font = mgTimes12Font();
+int spaceWidth = mgFontCharWidth(font, ' ');
+int lineHeight = mgFontLineHeight(font);
+int labelWidth = 2*spaceWidth + widestLabelWidth(font, yLabelList);
+int totalWidth = labelWidth + cellWidth * xCount;
+int totalHeight = lineHeight + cellHeight * yCount;
+int matrixX = labelWidth;
+int matrixY = lineHeight;
+
+/* Start up image. */
+struct vGfx *vg = vgOpenGif(totalWidth, totalHeight, fileName, FALSE);
+
+/* Print row labels */
+struct slPair *yLabel;
+int y = matrixY;
+for (yLabel = yLabelList; yLabel != NULL; yLabel = yLabel->next)
+    {
+    vgTextCentered(vg, 0, y, labelWidth, cellHeight, MG_BLACK, font, yLabel->val);
+    y += cellHeight;
+    }
+
+/* Print x labels */
+struct slPair *xLabel;
+int x = matrixX;
+for (xLabel = xLabelList; xLabel != NULL; xLabel = xLabel->next)
+    {
+    vgTextCentered(vg, x, 0, cellWidth, lineHeight, MG_BLACK, font, xLabel->val);
+    x += cellWidth;
+    }
+
+/* Print matrix. */
+y = matrixY;
+for (yLabel = yLabelList; yLabel != NULL; yLabel = yLabel->next)
+    {
+    x = matrixX;
+    for (xLabel = xLabelList; xLabel != NULL; xLabel = xLabel->next)
+        {
+	boolean gotData = FALSE;
+	struct sparseCell *cell = sparseMatrixFindCell(mat, xLabel->name, yLabel->name);
+	if (cell == NULL && clCorrelate)
+	    cell = sparseMatrixFindCell(mat, yLabel->name, xLabel->name);
+	int grayLevel;
+	if (cell != NULL)
+	    {
+	    grayLevel = 255 - 255 * cell->val;
+	    gotData = TRUE;
+	    }
+	else	/* No data - maybe try and fake it? */
+	    {
+	    if (clCorrelate)  
+	        {
+		if (sameString(xLabel->name, yLabel->name))
+		    {
+		    grayLevel = 0;
+		    gotData = TRUE;
+		    }
+		}
+	    }
+	Color color;
+	if (gotData)
+	    color = vgFindColorIx(vg, grayLevel, grayLevel, grayLevel);
+	else
+	    color = MG_YELLOW;
+	vgBox(vg, x, y, cellWidth, cellHeight, color);
+	x += cellWidth;
+	}
+    y += cellHeight;
+    }
+
+/* Clean up */
+vgClose(&vg);
+}
+
+void plotDataMatrix(char *inPairsFile, char *xLabelsFile, char *yLabelsFile, char *outFile)
+/* plotDataMatrix - Create an image showing a matrix of data values.. */
+{
+struct sparseMatrix *mat = sparseMatrixRead(inPairsFile);
+struct slPair *xLabelList = labelsRead(xLabelsFile, mat->xIdHash, inPairsFile);
+struct slPair *yLabelList = labelsRead(yLabelsFile, mat->yIdHash, inPairsFile);
+verbose(2, "got %d cells, %d x dims, %d y dims\n", slCount(mat->cellList), slCount(xLabelList), slCount(yLabelList));
+makeImage(mat, xLabelList, yLabelList, outFile);
+}
+
+int main(int argc, char *argv[])
+/* Process command line. */
+{
+optionInit(&argc, argv, options);
+if (argc != 5)
+    usage();
+clCorrelate = optionExists("correlate");
+plotDataMatrix(argv[1], argv[2], argv[3], argv[4]);
+return 0;
+}