src/hg/instinct/hgBamBam/hgAnnotations.c 1.3

1.3 2010/05/31 00:02:34 jsanborn
big update
Index: src/hg/instinct/hgBamBam/hgAnnotations.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/hgBamBam/hgAnnotations.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -b -B -U 4 -r1.2 -r1.3
--- src/hg/instinct/hgBamBam/hgAnnotations.c	26 May 2010 05:20:33 -0000	1.2
+++ src/hg/instinct/hgBamBam/hgAnnotations.c	31 May 2010 00:02:34 -0000	1.3
@@ -22,8 +22,9 @@
 #include "cytoBand.h"
 #include "hCytoBand.h"
 #include "spaceSaver.h"
 #include "hgBamBam.h"
+#include "chromColors.h"
 
 static char const rcsid[] = "$Id$";
 
 static char *heatMapDbProfile = "localDb";  // database profile to use
@@ -58,8 +59,43 @@
 sqlFreeResult(&sr);
 return tupleList;
 }
 
+struct bed *getSNPs(struct sqlConnection *conn, char *tableName, char *chromName, 
+		    int start, int stop)
+{
+char **row = NULL; 
+char query[256];
+if (chromName)
+    safef(query, sizeof(query), 
+	  "select * from %s where chrom = \"%s\" and chromStart > %d and chromEnd <= %d", 
+	  tableName, chromName, start, stop);
+else
+    safef(query, sizeof(query), "select * from %s", tableName);
+
+if (!sqlExists(conn, query))
+    return NULL;
+
+struct sqlResult *sr = sqlGetResult(conn, query);
+struct bed *bed = NULL;
+struct bed *bedList = NULL;
+
+while ((row = sqlNextRow(sr)) != NULL)
+    {
+    AllocVar(bed);
+    bed->chrom = cloneString(row[0]);
+    bed->chromStart = atoi(row[1]);
+    bed->chromEnd   = atoi(row[2]);
+    bed->thickStart = bed->chromStart;
+    bed->thickEnd   = bed->chromEnd;
+    bed->name = cloneString(row[4]);
+    slAddHead(&bedList, bed);
+    }
+
+sqlFreeResult(&sr);
+return bedList;
+}
+
 int hmPixelCmpCount(const void *va, const void *vb)
 /* Compare to sort columns based on priority. */
 {
 const struct hmPixel *a = *((struct hmPixel **)va);
@@ -118,21 +154,25 @@
 }
 
 
 void drawTable(struct vGfx *vg, struct settings *settings,
-	       char *db, char *tableName, int height)
+	       char *db, char *tableName, char *profile, int height)
 /* Draw chromosome graph on all chromosomes in layout at given
  * y offset and height. */
 {
 if (!settings)
     return;
 
 /* get remote database connection */
-struct sqlConnection *conn = hAllocConn(db);
+struct sqlConnection *conn;
+if (!profile)
+    conn = hAllocConn(db);
+else
+    conn = hAllocConnProfile(profile, db);
 
 struct bed *nb, *ghBed = NULL;
 
-double pixPerBase = (double) settings->width / (double) settings->totalBases;
+double pixPerBase = (double) settings->dataWidth / (double) settings->totalBases;
 
 Color upShades[EXPR_DATA_SHADES];
 static struct rgbColor zeroColor = {0, 0, 0}; // black
 static struct rgbColor highColor = {255, 0, 0};     // red
@@ -254,8 +294,10 @@
 slSort(&hmList, hmPixelCmpCount);
 struct hmPixel *last = slLastEl(hmList);
 int maxVal = last->count;
 
+vgSetClip(vg, settings->dataOffsetX, 0, settings->dataWidth, settings->height);
+
 Color valCol;
 for (hm = hmList; hm ; hm = hm->next)
     {
     double val = (double) hm->count / (double) maxVal;
@@ -268,10 +310,12 @@
 	colorIndex = EXPR_DATA_SHADES-1;
 
     valCol = upShades[colorIndex];
     
-    vgBox(vg, hm->x, hm->y, hm->w, hm->h, valCol);
+    vgBox(vg, hm->x, hm->y + settings->dataOffsetY, hm->w, hm->h, valCol);
     }
+
+vgUnclip(vg);
 } 
 
 struct spaceSaver *bedToSS(struct settings *settings, char *db, 
 			   char *tableName, boolean drawLabels)
@@ -294,19 +338,59 @@
     bedFilterListInRange(ghBed, NULL, cl->chrom, cl->baseStart, cl->baseEnd);
 
 struct spaceSaver *ss = spaceSaverNew(cl->pxStart, cl->pxStart + cl->pxWidth, 100);
 
-double pixPerBase = (double) settings->width / (double) settings->totalBases;
+double pixPerBase = (double) cl->pxWidth / (double) settings->totalBases;
 
 int baseStart = cl->baseStart;
 
 for(nb = filterList; nb; nb = nb->next)
     {
     int cStart = nb->chromStart;
     int cEnd = nb->chromEnd;
     
-    int x1 = round(pixPerBase * (double) (cStart - baseStart));
-    int x2 = round(pixPerBase * (double) (cEnd - baseStart));
+    int x1 = round(pixPerBase * (double) (cStart - baseStart)) + cl->pxStart;
+    int x2 = round(pixPerBase * (double) (cEnd - baseStart)) + cl->pxStart;
+    
+    if (drawLabels)
+	x1 -= mgFontStringWidth(settings->font, nb->name) + 4;
+    spaceSaverAdd(ss, x1, x2, nb);
+    }
+spaceSaverFinish(ss);
+    
+return ss;
+}
+
+struct spaceSaver *snpsToSS(struct settings *settings, char *db, 
+			    char *tableName, boolean drawLabels)
+{
+if (!settings)
+    return NULL;
+
+/* get remote database connection */
+struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, db);
+
+struct bed *nb, *ghBed = NULL;
+
+struct chromLay *cl = settings->layoutList;
+
+ghBed = getSNPs(conn, tableName, cl->chrom, cl->baseStart, cl->baseEnd);
+if (!ghBed)
+    return NULL;
+
+struct spaceSaver *ss = spaceSaverNew(cl->pxStart, cl->pxStart + cl->pxWidth, 100);
+
+double pixPerBase = (double) settings->dataWidth / (double) settings->totalBases;
+
+int baseStart = cl->baseStart;
+
+for(nb = ghBed; nb; nb = nb->next)
+    {
+    int cStart = nb->chromStart;
+    int cEnd   = nb->chromEnd;
+    
+    int x1 = round(pixPerBase * (double) (cStart - baseStart)) + cl->pxStart;
+    int x2 = round(pixPerBase * (double) (cEnd - baseStart)) + cl->pxStart;
     
     if (drawLabels)
 	x1 -= mgFontStringWidth(settings->font, nb->name) + 4;
     spaceSaverAdd(ss, x1, x2, nb);
@@ -320,9 +404,9 @@
 		  struct spaceSaver *ss, boolean drawLabels)
 /* Draw chromosome graph on all chromosomes in layout at given
  * y offset and height. */
 {
-double pixPerBase = (double) settings->width / (double) settings->totalBases;
+double pixPerBase = (double) settings->dataWidth / (double) settings->totalBases;
 
 Color upShades[EXPR_DATA_SHADES];
 static struct rgbColor zeroColor = {0, 0, 0}; // black
 static struct rgbColor highColor = {255, 0, 0};     // red
@@ -332,12 +416,14 @@
 
 int pStart    = cl->pxStart;
 int baseStart = cl->baseStart;
 
+vgSetClip(vg, settings->dataOffsetX, 0, settings->dataWidth, settings->height);
+
 struct spaceNode *sn;
 for (sn = ss->nodeList; sn; sn = sn->next)
     {
-    int row = sn->row * GENE_HEIGHT;
+    int row = sn->row * GENE_HEIGHT + settings->dataOffsetY;
     struct bed *nb = (struct bed *) sn->val;
     
     int cStart = nb->chromStart;
     int cEnd   = nb->chromEnd;
@@ -348,9 +434,9 @@
     x1 = pixPerBase * (double) (cStart - baseStart);
     x2 = pixPerBase * (double) (cEnd - baseStart);
 
     if (drawLabels)
-	vgTextRight(vg, 0, row, x1-2, settings->fontHeight,
+	vgTextRight(vg, 0, row, x1-2+pStart, settings->fontHeight,
 		    MG_BLACK, settings->font, nb->name);
 
     if ( (x2 - x1) > 2.0)
 	{ /* width > two pixels, attempt to draw exon/utr structure
@@ -423,9 +509,54 @@
 	x2 = pixPerBase * (double) (cEnd - baseStart);
 	drawBox(vg, x1, x2, pStart, 0 + row, 9, MG_BLACK);
 	}
     }
+vgUnclip(vg);
+spaceSaverFree(&ss);
+} 
+
+void drawSnpTable(struct vGfx *vg, struct settings *settings, 
+		  struct spaceSaver *ss, boolean drawLabels)
+/* Draw chromosome graph on all chromosomes in layout at given
+ * y offset and height. */
+{
+if (!settings | !ss)
+    return;
+
+double pixPerBase = (double) settings->dataWidth / (double) settings->totalBases;
+
+Color upShades[EXPR_DATA_SHADES];
+static struct rgbColor zeroColor = {0, 0, 0}; // black
+static struct rgbColor highColor = {255, 0, 0};     // red
+vgMakeColorGradient(vg, &zeroColor, &highColor, EXPR_DATA_SHADES, upShades);
+
+struct chromLay *cl = settings->layoutList;
 
+int pStart    = cl->pxStart;
+int baseStart = cl->baseStart;
+
+struct spaceNode *sn;
+for (sn = ss->nodeList; sn; sn = sn->next)
+    {
+    int row = sn->row * GENE_HEIGHT + settings->dataOffsetY;
+    struct bed *nb = (struct bed *) sn->val;
+    
+    int cStart = nb->chromStart;
+    int cEnd   = nb->chromEnd;
+    
+    double x1, x2;
+    
+    x1 = pixPerBase * (double) (cStart - baseStart);
+    x2 = pixPerBase * (double) (cEnd - baseStart);
+
+    if (drawLabels)
+	vgTextRight(vg, 0, row, x1-2, settings->fontHeight,
+		    MG_BLACK, settings->font, nb->name);
+    
+    x1 = pixPerBase * (double) (cStart - baseStart);
+    x2 = pixPerBase * (double) (cEnd - baseStart);
+    drawBox(vg, x1, x2, pStart, 0 + row, 9, MG_BLACK);
+    }
 spaceSaverFree(&ss);
 } 
 
 
@@ -445,9 +576,11 @@
 if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
     {
     struct hvGfx *vg = hvGfxOpenGif(width, height, md5Tn.forCgi, FALSE);
 
-    drawTable(vg->vg, settings, db, tableName, height);
+    prepareImage(vg->vg, settings);
+
+    drawTable(vg->vg, settings, db, tableName, NULL, height);
 
     hvGfxClose(&vg);
     }
 
@@ -474,10 +607,10 @@
     }
 if (maxRow == -1)
     return NULL;
 
-settings->height = (maxRow + 1) * GENE_HEIGHT;
-
+settings->dataHeight = (maxRow + 1) * GENE_HEIGHT;
+settings->height     = settings->dataHeight + TITLE_HEIGHT;
 struct tempName md5Tn;
 char *strToHash = cartSettingsString(bbPrefix, "annotationGif");
 trashDirMD5File(&md5Tn, "hgh", ".gif", strToHash);
 
@@ -485,8 +618,10 @@
 if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
     {
     struct hvGfx *vg = hvGfxOpenGif(settings->width, settings->height, md5Tn.forCgi, FALSE);
 
+    prepareImage(vg->vg, settings);
+
     drawBedTable(vg->vg, settings, ss, drawLabels);
     
     hvGfxClose(&vg);
     }
@@ -508,8 +643,106 @@
 else
     return annotationSingleGenome(settings, db, tableName);
 }
 
+
+char *snpsWholeGenome(struct settings *settings, char *db, char *tableName)
+{
+int width  = settings->width;
+int height = 10;  // was set to 10
+
+if (width * height == 0)
+    return NULL;
+
+struct tempName md5Tn;
+char *strToHash = cartSettingsString(bbPrefix, "snpsGif");
+trashDirMD5File(&md5Tn, "hgh", ".gif", strToHash);
+
+off_t size = fileSize(md5Tn.forCgi);
+if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
+    {
+    struct hvGfx *vg = hvGfxOpenGif(width, height, md5Tn.forCgi, FALSE);
+
+    drawTable(vg->vg, settings, db, tableName, heatMapDbProfile, height);
+
+    hvGfxClose(&vg);
+    }
+
+char *filename = replaceChars(md5Tn.forHtml, "..", "");
+return filename;
+}
+
+char *snpsSingleGenome(struct settings *settings, char *db, char *tableName)
+{
+if (!settings)
+    return NULL;
+
+struct chromLay *cl = settings->layoutList;
+
+boolean drawLabels = TRUE;
+if (cl->baseEnd - cl->baseStart > 500000)
+    drawLabels = FALSE;
+
+struct spaceSaver *ss = snpsToSS(settings, db, tableName, drawLabels);
+if (!ss)
+    return NULL;
+
+int maxRow = -1;
+struct spaceNode *sn;
+for (sn = ss->nodeList; sn; sn = sn->next)
+    {
+    if (sn->row > maxRow)
+	maxRow = sn->row;
+    }
+if (maxRow == -1)
+    return NULL;
+
+settings->dataHeight = (maxRow + 1) * GENE_HEIGHT;
+settings->height = settings->dataHeight + TITLE_HEIGHT;
+
+struct tempName md5Tn;
+char *strToHash = cartSettingsString(bbPrefix, "snpsGif");
+trashDirMD5File(&md5Tn, "hgh", ".gif", strToHash);
+
+off_t size = fileSize(md5Tn.forCgi);
+if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
+    {
+    struct hvGfx *vg = hvGfxOpenGif(settings->width, settings->height, md5Tn.forCgi, FALSE);
+
+    prepareImage(vg->vg, settings);
+
+    drawSnpTable(vg->vg, settings, ss, drawLabels);
+
+    hvGfxClose(&vg);
+    }
+
+char *filename = replaceChars(md5Tn.forHtml, "..", "");
+return filename;
+}
+
+char *snpsGif(struct settings *settings, char *tableName)
+/* Create genome GIF file and HT that includes it. */
+{
+if (!settings || !tableName)
+    return NULL;
+
+char *db = "pdata";
+
+if (slCount(settings->layoutList) > 1)
+    return NULL;  // don't do whole genome yet.  snpsWholeGenome(settings, db, tableName);
+else
+    {
+    struct chromLay *cl = settings->layoutList;
+    if (!cl) 
+	return NULL;
+    if ((cl->baseEnd - cl->baseStart) > 5000000)  // large region, compress.
+	return NULL;   // snpsWholeGenome(settings, db, tableName);
+    else
+	return snpsSingleGenome(settings, db, tableName);
+    }
+return NULL;
+}
+
 double basesInScale(double numBases)
 {
 double exp = floor(log(numBases)/log(10.0));
 if (exp < 0.0)
@@ -568,9 +801,9 @@
 return cbHash;
 }
 
 
-void drawIdeogram(struct hvGfx *hvg, struct settings *settings, int yOff)
+void drawIdeogram(struct hvGfx *hvg, struct settings *settings, struct chromLay *clList, int yOff)
 {
 if (!settings)
     return;
 
@@ -590,14 +823,12 @@
 static struct rgbColor white = {255, 255, 255};
 vgMakeColorGradient(vg, &white, &black, 10, shadesOfGray);
 shadesOfGray[10] = MG_RED;  // to check for overflow, should never see red.
 
-int width = settings->width;
-
 struct chromLay *cl;
-vgSetClip(vg, 0, yOff, width, CYTO_HEIGHT);
+vgSetClip(vg, settings->dataOffsetX, 0, settings->dataWidth, settings->height);
 
-for (cl = settings->layoutList; cl; cl = cl->next)
+for (cl = clList; cl; cl = cl->next)
     {
     struct hashEl *el = hashLookup(cbHash, cl->chrom);
     if (!el)
 	continue;
@@ -692,24 +923,273 @@
 	}
     }
 }
 
-void drawChromLabels(struct vGfx *vg, struct settings *settings)
+Color getChromColor(struct vGfx *vg, char *chrom)
+{
+if (!chrom)
+    return MG_BLACK;
+
+int r, g, b;
+switch (chromToInt(chrom)) 
+    {
+    case 1:
+	r = CHROM_1_R;
+	g = CHROM_1_G;
+	b = CHROM_1_B;
+	break;
+    case 2:
+	r = CHROM_2_R;
+	g = CHROM_2_G;
+	b = CHROM_2_B;
+	break;
+    case 3:
+	r = CHROM_3_R;
+	g = CHROM_3_G;
+	b = CHROM_3_B;
+	break;
+    case 4:
+	r = CHROM_4_R;
+	g = CHROM_4_G;
+	b = CHROM_4_B;
+	break;
+    case 5:
+	r = CHROM_5_R;
+	g = CHROM_5_G;
+	b = CHROM_5_B;
+	break;
+    case 6:
+	r = CHROM_6_R;
+	g = CHROM_6_G;
+	b = CHROM_6_B;
+	break;
+    case 7:
+	r = CHROM_7_R;
+	g = CHROM_7_G;
+	b = CHROM_7_B;
+	break;
+    case 8:
+	r = CHROM_8_R;
+	g = CHROM_8_G;
+	b = CHROM_8_B;
+	break;
+    case 9:
+	r = CHROM_9_R;
+	g = CHROM_9_G;
+	b = CHROM_9_B;
+	break;
+    case 10:
+	r = CHROM_10_R;
+	g = CHROM_10_G;
+	b = CHROM_10_B;
+	break;
+    case 11:
+	r = CHROM_11_R;
+	g = CHROM_11_G;
+	b = CHROM_11_B;
+	break;
+    case 12:
+	r = CHROM_12_R;
+	g = CHROM_12_G;
+	b = CHROM_12_B;
+	break;
+    case 13:
+	r = CHROM_13_R;
+	g = CHROM_13_G;
+	b = CHROM_13_B;
+	break;
+    case 14:
+	r = CHROM_14_R;
+	g = CHROM_14_G;
+	b = CHROM_14_B;
+	break;
+    case 15:
+	r = CHROM_15_R;
+	g = CHROM_15_G;
+	b = CHROM_15_B;
+	break;
+    case 16:
+	r = CHROM_16_R;
+	g = CHROM_16_G;
+	b = CHROM_16_B;
+	break;
+    case 17:
+	r = CHROM_17_R;
+	g = CHROM_17_G;
+	b = CHROM_17_B;
+	break;
+    case 18:
+	r = CHROM_18_R;
+	g = CHROM_18_G;
+	b = CHROM_18_B;
+	break;
+    case 19:
+	r = CHROM_19_R;
+	g = CHROM_19_G;
+	b = CHROM_19_B;
+	break;
+    case 20:
+	r = CHROM_20_R;
+	g = CHROM_20_G;
+	b = CHROM_20_B;
+	break;
+    case 21:
+	r = CHROM_21_R;
+	g = CHROM_21_G;
+	b = CHROM_21_B;
+	break;
+    case 22:
+	r = CHROM_22_R;
+	g = CHROM_22_G;
+       	b = CHROM_22_B;
+	break;    
+    case 23:
+	r = CHROM_X_R;
+	g = CHROM_X_G;
+	b = CHROM_X_B;
+	break;
+    case 24:
+	r = CHROM_Y_R;
+	g = CHROM_Y_G;
+	b = CHROM_Y_B;
+	break;
+    default:
+	r = 0;
+	g = 0;
+	b = 0;
+    }
+
+return vgFindColorIx(vg, r, g, b);
+}
+
+
+void drawColorIdeogram(struct hvGfx *hvg, struct settings *settings, 
+		       struct chromLay *clList, int yOff)
+{
+if (!settings)
+    return;
+
+struct vGfx *vg = hvg->vg;
+
+struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, "hg18");
+struct hash *cbHash = getCytoBandHash(conn);
+hFreeConn(&conn);
+
+if (!cbHash)
+    return;
+
+/* Make grayscale for bands */
+struct chromLay *cl;
+vgSetClip(vg, 0, 0, settings->width, settings->height);
+
+for (cl = clList; cl; cl = cl->next)
+    {
+    struct hashEl *el = hashLookup(cbHash, cl->chrom);
+    if (!el)
+	continue;
+    struct cytoBand *cb, *cbList = el->val;
+
+    int pixStart = cl->pxStart;
+    int pixEnd   = cl->pxStart + cl->pxWidth;
+    int pixSize  = cl->pxWidth;
+
+    unsigned bStart = cl->baseStart;
+    unsigned bEnd   = cl->baseEnd;
+    unsigned bSize  = bEnd - bStart;
+
+    double basesPerPixel = (double) bSize / (double) pixSize;
+ 
+    int xBuffer = 0; //Start = pixStart; 
+    if (pixStart == 0)
+	xBuffer = 0;
+
+    Color col = getChromColor(vg, cl->chrom);    
+
+    /* Draw box around cytoband */
+    vgBox(vg, pixStart+1, yOff, pixSize-1, 1, MG_BLACK);
+    vgBox(vg, pixStart+1, yOff + CYTO_HEIGHT-1, pixSize-1, 1, MG_BLACK);
+    
+    unsigned minBand = INT_MAX;
+    unsigned maxBand = 0;
+    for (cb = cbList; cb; cb = cb->next)
+	{
+	unsigned start = cb->chromStart;  // our bases start at 1 TODO: FIX!
+	unsigned stop = cb->chromEnd;
+	if ((stop < bStart) || (start > bEnd)) // out of scope
+	    continue;
+
+	int pStart = round(((double) start - (double) bStart) / basesPerPixel) + pixStart;
+	if (pStart < pixStart)
+	    pStart = pixStart;
+	if (pStart <= 0)
+	    pStart = 1;
+
+	int pEnd = round(((double) stop - (double) bStart) / basesPerPixel) + pixStart;
+	if (pEnd >= pixEnd)
+	    pEnd = pixEnd;
+	
+	vgBox(vg, pStart, yOff+1, (pEnd - pStart), CYTO_HEIGHT-2, col);
+
+	if (start < minBand)
+	    minBand = start;
+	if (stop > maxBand)
+	    maxBand = stop;
+	}
+
+    /* If very near left/right edges, if we see the chromosome edge */
+    if (abs(minBand - bStart) < 100)
+	vgBox(vg, pixStart, yOff+1, 1, CYTO_HEIGHT-2, MG_BLACK);
+    if (abs(maxBand- bEnd) < 100)
+	vgBox(vg, pixEnd-1, yOff+1, 1, CYTO_HEIGHT-2, MG_BLACK);
+    
+    for (cb = cbList; cb; cb = cb->next)
+	{
+        /* If centromere do some drawing. */
+	if(!sameString(cb->gieStain, "acen"))
+	    continue;
+	int cenLeft, cenRight, cenTop, cenBottom;
+	
+	/* Get the coordinates of the edges of the centromere. */
+	cenLeft = round(((double) cb->chromStart - (double) bStart) / basesPerPixel) + pixStart; 
+	cenRight = round(((double) cb->next->chromEnd - (double) bStart)/basesPerPixel) + pixStart;
+	cenTop = yOff + CYTO_HEIGHT;
+	cenBottom = yOff;
+	
+	if (cenLeft < 0 && cenRight < 0)
+	    break;
+	if (cenLeft > pixEnd || cenRight < pixStart)
+	    break;
+
+	/* Draw centromere itself. */
+	hCytoBandDrawCentromere(hvg, cenLeft, yOff, cenRight - cenLeft,
+				CYTO_HEIGHT, MG_WHITE, hCytoBandCentromereColor(hvg));
+	break; 
+	}
+    char *name = cl->chrom;
+    Color textCol = MG_BLACK; //hvGfxContrastingColor(hvg, col);
+    vgTextCentered(vg, pixStart, 
+		   settings->dataOffsetY + DEFAULT_LABEL_HEIGHT - settings->fontHeight, 
+		   (pixEnd - pixStart), DEFAULT_LABEL_HEIGHT, textCol, settings->font, name);
+    
+    }
+}
+
+void drawChromLabels(struct vGfx *vg, struct settings *settings, struct chromLay *clList)
 {
 if (!settings)
     return;
 
 int width       = settings->width;
 int labelHeight = DEFAULT_LABEL_HEIGHT;
 
 struct chromLay *cl;
-vgSetClip(vg, 0, 0, width, labelHeight);
+vgSetClip(vg, settings->dataOffsetX, 0, settings->dataWidth, settings->height);
 
 boolean singleChrom = FALSE;
 if (slCount(settings->layoutList) == 1)
     singleChrom = TRUE;
 
-for(cl = settings->layoutList; cl; cl = cl->next)
+for(cl = clList; cl; cl = cl->next)
     {
     int chromWidth = cl->pxWidth;
 
     int leftX = cl->pxStart;
@@ -810,10 +1290,13 @@
 if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
     {
     vg = hvGfxOpenGif(width, height, md5Tn.forCgi, FALSE);
 
-    drawChromLabels(vg->vg, settings);
-    drawIdeogram(vg, settings, DEFAULT_LABEL_HEIGHT);
+    prepareImage(vg->vg, settings);
+
+    drawChromLabels(vg->vg, settings, settings->layoutList);
+
+    drawIdeogram(vg, settings, settings->layoutList, DEFAULT_LABEL_HEIGHT);
 
     hvGfxClose(&vg);
     }
 
@@ -873,10 +1356,9 @@
 
 if (!scaleStr)
     return;
 
-vgSetClip(vg, 0, 0, width, height);
-vgBox(vg, 0, 0, width, height, MG_WHITE); 
+vgSetClip(vg, settings->dataOffsetX, 0, settings->dataWidth, height);
 
 int midY = height / 2;
 int buffer = 3;
 int scaleWidth = round(((double) width) * scaleBases / numBases);
@@ -916,8 +1398,10 @@
 if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
     {
     struct hvGfx *vg = hvGfxOpenGif(totalW, totalH, md5Tn.forCgi, FALSE);
     
+    prepareImage(vg->vg, settings);
+
     drawGenomeScale(vg->vg, settings, totalW, totalH, settings->totalBases);
 
     hvGfxClose(&vg);
     }