src/hg/instinct/hgBamBam/drawingCode.c 1.2

1.2 2010/05/26 05:20:33 jsanborn
updated
Index: src/hg/instinct/hgBamBam/drawingCode.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/hgBamBam/drawingCode.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -b -B -U 4 -r1.1 -r1.2
--- src/hg/instinct/hgBamBam/drawingCode.c	25 May 2010 20:22:44 -0000	1.1
+++ src/hg/instinct/hgBamBam/drawingCode.c	26 May 2010 05:20:33 -0000	1.2
@@ -21,11 +21,13 @@
 #include "vGfx.h"
 #include "hvGfx.h"
 #include "web.h"
 #include "hgBamBam.h"
+#include "spaceSaver.h"
 
 #define MIN_LABEL_SIZE 100 // minimum size of labels 
 #define TEXT_BUFFER 5 // pixels to put between text and heatmap
+#define FOOT_HEIGHT 3
 
 struct trackLayout tl;           /* Dimensions of things, fonts, etc. */
 
 /***** BEGIN HELPER *****/
@@ -123,18 +125,140 @@
     vgBox(vg, x, startY, 1, height, lightBlue);
 vgUnclip(vg);
 }
 
+static int calcX(struct chromLay *cl, int base, int max)
+{
+if (!cl)
+    return -1;
+int x = round(cl->pxStart+cl->pxWidth*((float)(base - cl->baseStart)/cl->baseWidth));
+return (x > max) ? max : x;
+}
+
 
 /***** END HELPER *****/
 
-void drawBreaks(struct vGfx *vg, struct breaks *breaks, 
+void drawChromBreaks(struct vGfx *vg, struct spaceSaver *ss, 
 		struct settings *settings)
 {
+struct breaks *br;
+
+int xl1, xl2, wl, xr1, xr2, wr, ldir, rdir;
+char *lstrand, *rstrand;
+struct chromLay *clL, *clR;
+struct hashEl *el;
+
+int yfoot = 0; 
+int hline = 1;
+int yline = FOOT_HEIGHT; 
+
+struct spaceNode *sn;
+
+int yOff;
+for (sn = ss->nodeList; sn; sn = sn->next)
+    {
+    yOff = sn->row * FOOT_HEIGHT * 2;
+    br   = (struct breaks *)sn->val;
+
+    clL = NULL;
+    clR = NULL;
+    el = hashLookup(settings->layoutHash, br->chrom);
+    if (el)
+	clL = el->val;
+
+    el = hashLookup(settings->layoutHash, br->chrom2);
+    if (el)
+	clR = el->val;
+    
+    xl1 = calcX(clL, br->chromStart, settings->width);
+    xl2 = calcX(clL, br->chromEnd, settings->width);
+    wl = (xl2 - xl1 > 0) ? (xl2 - xl1) : 1;
+    lstrand = br->strand;
+
+    xr1 = calcX(clR, br->chromStart2, settings->width);
+    xr2 = calcX(clR, br->chromEnd2, settings->width);
+    wr = (xr2 - xr1 > 0) ? (xr2 - xr1) : 1;
+    rstrand = br->strand2;
+
+    if (xl1 > xr1)
+	{  // always go from left -> right, flip
+	int tmp1 = xl1;
+	int tmp2 = xl2;
+	int tmpw = wl;
+	char *tmpst = lstrand;
+	xl1 = xr1;
+	xl2 = xr2;
+	wl  = wr;
+	lstrand = rstrand;
+	xr1 = tmp1;
+	xr2 = tmp2;
+	wr  = tmpw;
+	rstrand = tmpst;
+	}
+
+    ldir = 1;
+    if (sameString(lstrand, "+"))
+	ldir = -1;
+
+    rdir = 1;  // reversed
+    if (sameString(rstrand, "+"))
+	rdir = -1;
+
+    if (xl2 >= 0 && xr1 >= 0 && xl2 < xr1)
+	vgBox(vg, xl2, yOff + yline, (xr1-xl2), hline, MG_RED);
+
+    if (xl1 >= 0 && xr2 >= 0 && xr2 < xl1)
+	vgBox(vg, xr2, yOff + yline, (xl1-xr2), hline, MG_RED);
+
+    if (xl1 >= 0 && xl2 >= 0)
+	{
+	vgBox(vg, xl1, yOff + yline, wl, 1, MG_BLACK);
+	vgLine(vg, xl1, yOff + yline, xl1 + ldir * FOOT_HEIGHT, yOff + yfoot + (yline - yfoot) * 2, MG_BLACK);  
+	}
+    if (xr1 >= 0 && xr2 >= 0) 
+	{
+	vgBox(vg, xr1, yOff + yline, wr, 1, MG_BLACK);
+	vgLine(vg, xr1, yOff + yline, xr1 + rdir * FOOT_HEIGHT, yOff + yfoot + (yline - yfoot) * 2, MG_BLACK);  
+	}
+    }
+
+}
+
+struct spaceSaver *breaksToSS(struct breaks *breaks, struct settings *settings)
+{
+struct spaceSaver *ss = spaceSaverNew(0, settings->width, 100);
 
+struct breaks *br;
+int x1, x2;
+struct chromLay *clL, *clR;
+struct hashEl *el;
+
+for (br = breaks; br; br = br->next)
+    {
+    clL = NULL;
+    clR = NULL;
+    el = hashLookup(settings->layoutHash, br->chrom);
+    if (el)
+	clL = el->val;
+    
+    el = hashLookup(settings->layoutHash, br->chrom2);
+    if (el)
+	clR = el->val;
+
+    if (!clL || !clR || !sameString(clL->chrom, clR->chrom))
+	continue;
+    
+    x1 = calcX(clL, br->chromStart, settings->width);   
+    x2 = calcX(clR, br->chromEnd2, settings->width);
+
+    spaceSaverAdd(ss, x1, x2, br);
+    }
 
+spaceSaverFinish(ss);
+return ss;
 }
 
+
 char *breaksGif(struct sqlConnection *conn, struct breaks *breaks, 
 		struct settings *settings)
 /* Create genome GIF file and HT that includes it. */
 {
@@ -143,8 +267,22 @@
 
 if (settings->height <= 0 || settings->width <= 0)
     return NULL;
 
+struct spaceSaver *ss = breaksToSS(breaks, settings);
+
+int maxRow = -1;
+struct spaceNode *sn;
+for (sn = ss->nodeList; sn; sn = sn->next)
+    {
+    if (sn->row > maxRow)
+	maxRow = sn->row;
+    }
+if (maxRow < 0)
+    return NULL;
+
+settings->height = (maxRow + 1) * FOOT_HEIGHT * 2;
+
 struct hvGfx *vg;
 struct tempName md5Tn;
 char *strToHash = cartSettingsString(bbPrefix, "breaks");
 trashDirMD5File(&md5Tn, "hgg", ".gif", strToHash);
@@ -153,9 +291,9 @@
 if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
     {
     vg = hvGfxOpenGif(settings->width, settings->height, md5Tn.forCgi, FALSE);
 
-    drawBreaks(vg->vg, breaks, settings);
+    drawChromBreaks(vg->vg, ss, settings);
 
     hvGfxClose(&vg);
     }