src/hg/instinct/hgBamBam/drawingCode.c 1.5
1.5 2010/05/31 00:55:19 jsanborn
minor tweakpdate
Index: src/hg/instinct/hgBamBam/drawingCode.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/hgBamBam/drawingCode.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -b -B -U 1000000 -r1.4 -r1.5
--- src/hg/instinct/hgBamBam/drawingCode.c 31 May 2010 00:02:34 -0000 1.4
+++ src/hg/instinct/hgBamBam/drawingCode.c 31 May 2010 00:55:19 -0000 1.5
@@ -1,803 +1,831 @@
/********************************************************************************/
/* Copyright 2007-2009 -- The Regents of the University of California */
/********************************************************************************/
#include <limits.h>
#include "common.h"
#include "bed.h"
#include "cart.h"
#include "customTrack.h"
#include "errCatch.h"
#include "genoLay.h"
#include "trackLayout.h"
#include "hash.h"
#include "hdb.h"
#include "hgColors.h"
#include "hPrint.h"
#include "htmshell.h"
#include "jsHelper.h"
#include "psGfx.h"
#include "trashDir.h"
#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 5
#define INTER_BREAK_HEIGHT 5
struct trackLayout tl; /* Dimensions of things, fonts, etc. */
/***** BEGIN HELPER *****/
#define CLIP(p,limit) if (p < 0) p = 0; if (p >= (limit)) p = (limit)-1;
void verticalTextLeft(struct vGfx *vg, int x, int y,
int width, int height, int colorIx, int fontHeight,
MgFont *font, char *string)
{
/* don't let this run wild */
//CLIP(width, vg->width);
//CLIP(height, vg->height);
if ((width <= 0) || (height <= 0))
return;
struct vGfx *vgHoriz;
int i, j;
/* reversed meanings of width and height here since this is going
* to rotate 90 degrees
*/
int offset = round((double) (width - fontHeight) / 2.0);
if (offset < 0)
offset = 0;
vgHoriz = vgOpenGif(height, width, "/dev/null", FALSE);
vgText(vgHoriz, 0, offset, colorIx, font, string);
/* now, blit from the horizontal to the vertical, rotate -90 (CCW) */
for (i = 0; i < height; i++) /* xSrc -> yDest */
{
int yDest = height - (i + 1);
for (j = 0; j < width; j++) /* ySrc -> xDest */
vgDot(vg, x + (j+1), y + yDest, vgGetDot(vgHoriz, i, j));
}
vgClose(&vgHoriz);
}
void vgMakeColorGradient(struct vGfx *vg,
struct rgbColor *start, struct rgbColor *end,
int steps, Color *colorIxs)
/* Make a color gradient that goes smoothly from start
* to end colors in given number of steps. Put indicesLis
* in color table in colorIxs */
{
double scale = 0, invScale;
double invStep;
int i; int r,g,b;
steps -= 1; /* Easier to do the calculation in an inclusive way. */
invStep = 1.0/steps;
for (i=0; i<=steps; ++i)
{
invScale = 1.0 - scale;
r = invScale * start->r + scale * end->r;
g = invScale * start->g + scale * end->g;
b = invScale * start->b + scale * end->b;
colorIxs[i] = vgFindColorIx(vg, r, g, b);
scale += invStep;
}
}
char *cartSettingsString(char *prefix, char *functionName)
{
if (!prefix || !functionName)
return NULL;
struct hashEl *hEl = cartFindPrefix(cart, prefix);
if (!hEl)
return NULL;
struct dyString *dy = newDyString(1000);
while (hEl)
{
char *name = hEl->name;
char *val = hEl->val;
dyStringPrintf(dy, "%s=%s,", name, val);
hEl = hEl->next;
}
dyStringPrintf(dy, "%s,%s", functionName, VERSION);
char *str = dyStringCannibalize(&dy);
return str;
}
void drawBackgroundLines(struct vGfx *vg, int startX, int startY, int width, int height)
{ // draw background lines like genome browser.
int x, spacing = 12;
/* First line is red */
Color lightRed = vgFindColorIx(vg, 220, 0, 0);
x = startX;
vgBox(vg, x, startY, 1, height, lightRed);
x += spacing;
/* Remaining are blue */
Color lightBlue = vgFindColorIx(vg, 220, 220, 255);
vgSetClip(vg, startX, startY, width, height);
for ( ; x < (startX + width); x += spacing)
vgBox(vg, x, startY, 1, height, lightBlue);
vgUnclip(vg);
}
void prepareImage(struct vGfx *vg, struct settings *settings)
{
drawBackgroundLines(vg, settings->dataOffsetX - 1, 0, settings->dataWidth + 1, settings->height);
if (settings->title)
vgTextCentered(vg, settings->dataOffsetX, 0, settings->dataWidth, TITLE_HEIGHT,
MG_BLACK, settings->font, settings->title);
}
static int calcX(struct chromLay *cl, int base, int min, int max)
{
if (!cl)
return -1;
int x = round(cl->pxStart+cl->pxWidth*((float)(base - cl->baseStart)/cl->baseWidth));
if (x < min)
x = min;
if (x > max)
x = max;
return x;
}
/***** END HELPER *****/
struct chromLay *getChromLayBreaks(struct sqlConnection *conn,
struct breaks *breaks, struct settings *settings)
{
if (!breaks || !settings || slCount(settings->layoutList) > 1)
return NULL;
char *currentChrom = settings->layoutList->chrom;
/* Find all chroms that have inter chrom breakpoints */
struct hash *chromHash = hashNew(0);
struct breaks *br;
for (br = breaks; br; br = br->next)
{
struct hashEl *el = hashLookup(chromHash, br->chrom);
if (!el)
hashAddInt(chromHash, br->chrom, 1);
el = hashLookup(chromHash, br->chrom2);
if (!el)
hashAddInt(chromHash, br->chrom2, 1);
}
struct genoLayChrom *gl, *glList = genoLayDbChroms(conn, FALSE);
float totalBases = 0.0;
for (gl = glList; gl; gl = gl->next)
{
if (sameString(gl->fullName, currentChrom))
continue;
struct hashEl *el = hashLookup(chromHash, gl->fullName);
if (el)
totalBases += gl->size;
}
float cbases = 0.0;
struct chromLay *cl, *clList = NULL;
for (gl = glList; gl; gl = gl->next)
{
if (sameString(gl->fullName, currentChrom))
continue;
struct hashEl *el = hashLookup(chromHash, gl->fullName);
if (el)
{
AllocVar(cl);
cl->chrom = cloneString(gl->fullName);
cl->baseStart = 0.0;
cl->baseEnd = (float) gl->size;
cl->baseWidth = cl->baseEnd - cl->baseStart;
cl->pxWidth = (float) settings->dataWidth * cl->baseWidth / totalBases;
cl->pxStart = (float) settings->dataWidth * cbases / totalBases + settings->dataOffsetX;
cbases += (float) gl->size;
slAddHead(&clList, cl);
}
}
slReverse(&clList);
return clList;
}
int breaksCmp(const void *va, const void *vb)
/* Compare to sort columns based on priority. */
{
const struct breaks *a = *((struct breaks **)va);
const struct breaks *b = *((struct breaks **)vb);
float dif = 0;
if (sameString(a->chrom, b->chrom))
dif = a->chromStart - b->chromStart;
else if (sameString(a->chrom, b->chrom2))
dif = a->chromStart - b->chromStart2;
else if (sameString(a->chrom2, b->chrom2))
dif = a->chromStart2 - b->chromStart2;
if (dif < 0)
return 1;
else if (dif > 0)
return -1;
else
return 0;
}
+void sortBreaks(struct breaks **breaksPtr, char *currentChrom)
+{
+struct breaks *br, *breaks = *breaksPtr;
+
+for (br = breaks; br; br = br->next)
+ {
+ if (sameString(br->chrom, br->chrom2) || sameString(br->chrom, currentChrom))
+ continue;
+
+ char *tmpc = br->chrom;
+ int tmpS = br->chromStart;
+ int tmpE = br->chromEnd;
+ char tmpSt[2];
+ strcpy(tmpSt, br->strand);
+
+ br->chrom = br->chrom2;
+ br->chromStart = br->chromStart2;
+ br->chromEnd = br->chromEnd2;
+ strcpy(br->strand, br->strand2);
+
+ br->chrom2 = tmpc;
+ br->chromStart2 = tmpS;
+ br->chromEnd2 = tmpE;
+ strcpy(br->strand2, tmpSt);
+ }
+
+slSort(breaksPtr, breaksCmp);
+}
void drawInterChromBreaks(struct hvGfx *hvg, struct breaks *breaks,
struct chromLay *clList, struct settings *settings)
{
if (!settings || slCount(settings->layoutList) > 1)
return;
char *currentChrom = settings->layoutList->chrom;
struct vGfx *vg = hvg->vg;
struct breaks *br;
struct chromLay *cl;
struct hash *clHash = hashNew(0);
for (cl = clList; cl; cl = cl->next)
{
if (sameString(cl->chrom, currentChrom))
continue;
hashAdd(clHash, cl->chrom, cl);
}
int xl1, xl2, wl, xr1, xr2, wr, ldir, rdir;
char *lstrand, *rstrand;
struct chromLay *clL, *clR;
struct hashEl *el;
drawColorIdeogram(hvg, settings, clList, settings->dataOffsetY + DEFAULT_LABEL_HEIGHT);
int yfoot = FOOT_HEIGHT;
int yl = settings->height - settings->dataOffsetY - yfoot;
int yr = yfoot + CYTO_HEIGHT + DEFAULT_LABEL_HEIGHT;
vgSetClip(vg, settings->dataOffsetX, 0, settings->dataWidth, settings->height);
int ibreak = 0;
-slSort(&breaks, breaksCmp);
+sortBreaks(&breaks, currentChrom);
int yOff;
for (br = breaks; br; br = br->next)
{
yOff = settings->dataOffsetY;
clL = NULL;
clR = NULL;
int yBreak = INTER_BREAK_HEIGHT * ibreak + CYTO_HEIGHT + DEFAULT_LABEL_HEIGHT + yfoot + INTER_BREAK_HEIGHT/2;
- ibreak++;
int csL, ceL;
int csR, ceR;
if (sameString(currentChrom, br->chrom))
{
el = hashLookup(settings->layoutHash, br->chrom);
if (el)
clL = el->val;
csL = br->chromStart;
ceL = br->chromEnd;
lstrand = br->strand;
el = hashLookup(clHash, br->chrom2);
if (el)
clR = el->val;
csR = br->chromStart2;
ceR = br->chromEnd2;
rstrand = br->strand2;
}
else
{
el = hashLookup(settings->layoutHash, br->chrom2);
if (el)
clL = el->val;
csL = br->chromStart2;
ceL = br->chromEnd2;
lstrand = br->strand2;
el = hashLookup(clHash, br->chrom);
if (el)
clR = el->val;
csR = br->chromStart;
ceR = br->chromEnd;
rstrand = br->strand;
}
/* +/- FOOT_HEIGHT to push far away breakpoint outside of clipped regions, so
* they are not displayed */
xl1 = calcX(clL, csL, settings->dataOffsetX-FOOT_HEIGHT-1, settings->width+FOOT_HEIGHT);
xl2 = calcX(clL, ceL, settings->dataOffsetX-FOOT_HEIGHT-1, settings->width+FOOT_HEIGHT);
wl = (xl2 - xl1 > 0) ? (xl2 - xl1) : 1;
xr1 = calcX(clR, csR, settings->dataOffsetX-FOOT_HEIGHT-1, settings->width+FOOT_HEIGHT);
xr2 = calcX(clR, ceR, settings->dataOffsetX-FOOT_HEIGHT-1, settings->width+FOOT_HEIGHT);
wr = (xr2 - xr1 > 0) ? (xr2 - xr1) : 1;
ldir = 1;
if (sameString(lstrand, "+"))
ldir = -1;
rdir = 1; // reversed
if (sameString(rstrand, "+"))
rdir = -1;
Color col = getChromColor(vg, clR->chrom);
//vgLine(vg, xl2, yOff + yl, xr1, yOff + yr, col);
vgLine(vg, xl2, yOff + yBreak, xr1, yOff + yBreak, col);
if (xl1 >= 0 && xl2 >= 0)
{
vgBox(vg, xl1, yOff + yl, wl, 1, MG_BLACK);
vgLine(vg, xl1, yOff + yl, xl1 + ldir * FOOT_HEIGHT, yOff + yl + yfoot, MG_BLACK);
vgLine(vg, xl1, yOff + yl, xl1, yOff + yBreak, col);
}
if (xr1 >= 0 && xr2 >= 0)
{
vgBox(vg, xr1, yOff + yr, wr, 1, MG_BLACK);
vgLine(vg, xr1, yOff + yr, xr1 + rdir * FOOT_HEIGHT, yOff + yr - yfoot, MG_BLACK);
vgLine(vg, xr1, yOff + yr, xr1, yOff + yBreak, col);
}
+ ibreak++;
}
vgUnclip(vg);
}
char *interBreaksGif(struct sqlConnection *conn, struct breaks *breaks,
struct settings *settings)
/* Create genome GIF file and HT that includes it. */
{
if (!breaks || !settings)
return NULL;
if (settings->height <= 0 || settings->width <= 0)
return NULL;
struct chromLay *clList = getChromLayBreaks(conn, breaks, settings);
if (!clList)
return NULL;
int numBreaks = slCount(breaks);
settings->dataHeight = (numBreaks + 1) * INTER_BREAK_HEIGHT + CYTO_HEIGHT + DEFAULT_LABEL_HEIGHT + FOOT_HEIGHT * 2;
settings->height = settings->dataHeight + TITLE_HEIGHT;
struct hvGfx *vg;
struct tempName md5Tn;
char *strToHash = cartSettingsString(bbPrefix, "interBreaks");
trashDirMD5File(&md5Tn, "hgg", ".gif", strToHash);
off_t size = fileSize(md5Tn.forCgi);
if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
{
vg = hvGfxOpenGif(settings->width, settings->height, md5Tn.forCgi, FALSE);
prepareImage(vg->vg, settings);
drawInterChromBreaks(vg, breaks, clList, settings);
hvGfxClose(&vg);
}
char *filename = replaceChars(md5Tn.forHtml, "..", "");
return filename;
}
void drawIntraChromBreaks(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;
vgSetClip(vg, settings->dataOffsetX, 0, settings->dataWidth, settings->height);
int yOff;
for (sn = ss->nodeList; sn; sn = sn->next)
{
yOff = sn->row * FOOT_HEIGHT * 2 + settings->dataOffsetY;
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;
/* +/- FOOT_HEIGHT to push far away breakpoint outside of clipped regions, so
* they are not displayed */
xl1 = calcX(clL, br->chromStart, settings->dataOffsetX-FOOT_HEIGHT-1, settings->width+FOOT_HEIGHT);
xl2 = calcX(clL, br->chromEnd, settings->dataOffsetX-FOOT_HEIGHT-1, settings->width+FOOT_HEIGHT);
wl = (xl2 - xl1 > 0) ? (xl2 - xl1) : 1;
lstrand = br->strand;
xr1 = calcX(clR, br->chromStart2, settings->dataOffsetX-FOOT_HEIGHT-1, settings->width+FOOT_HEIGHT);
xr2 = calcX(clR, br->chromEnd2, settings->dataOffsetX-FOOT_HEIGHT-1, settings->width+FOOT_HEIGHT);
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 < xr1)
vgBox(vg, xl2, yOff + yline, (xr1-xl2), hline, MG_RED);
if (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);
}
}
vgUnclip(vg);
}
struct spaceSaver *intraBreaksToSS(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->dataOffsetX, settings->width);
x2 = calcX(clR, br->chromEnd2, settings->dataOffsetX, settings->width);
spaceSaverAdd(ss, x1, x2, br);
}
spaceSaverFinish(ss);
return ss;
}
char *intraBreaksGif(struct sqlConnection *conn, struct breaks *breaks,
struct settings *settings)
/* Create genome GIF file and HT that includes it. */
{
if (!breaks || !settings)
return NULL;
if (settings->height <= 0 || settings->width <= 0)
return NULL;
struct spaceSaver *ss = intraBreaksToSS(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->dataHeight = (maxRow + 1) * FOOT_HEIGHT * 2;
settings->height = settings->dataHeight + TITLE_HEIGHT;
struct hvGfx *vg;
struct tempName md5Tn;
char *strToHash = cartSettingsString(bbPrefix, "intraBreaks");
trashDirMD5File(&md5Tn, "hgg", ".gif", strToHash);
off_t size = fileSize(md5Tn.forCgi);
if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
{
vg = hvGfxOpenGif(settings->width, settings->height, md5Tn.forCgi, FALSE);
prepareImage(vg->vg, settings);
drawIntraChromBreaks(vg->vg, ss, settings);
hvGfxClose(&vg);
}
char *filename = replaceChars(md5Tn.forHtml, "..", "");
return filename;
}
void drawCopyNumber(struct vGfx *vg, struct bed *bedList,
struct settings *settings, float medVal, Color col)
{
int x1, x2, y, w;
float val;
struct bed *bed;
struct chromLay *cl = NULL;
char *prevChrom = NULL;
struct hash *pixelHash = hashNew(0);
struct hmPixel *hm, *hmList = NULL;
char pixelStr[256];
struct hashEl *el;
for (bed = bedList; bed; bed = bed->next)
{
if (!cl || !sameString(bed->chrom, prevChrom))
{
el = hashLookup(settings->layoutHash, bed->chrom);
if (!el)
errAbort("couldn't find chrom %s in layout", bed->chrom);
cl = el->val;
prevChrom = bed->chrom;
}
if (bed->chromStart > cl->baseEnd || bed->chromEnd < cl->baseStart)
continue;
x1 = calcX(cl, bed->chromStart, settings->dataOffsetX, settings->width);
x2 = calcX(cl, bed->chromEnd, settings->dataOffsetX, settings->width);
w = (x2 - x1 > 0) ? x2 - x1 : 1;
val = sqlFloat(bed->name);
safef(pixelStr,sizeof (pixelStr), "%d", x1);
el = hashLookup(pixelHash, pixelStr);
if (!el)
{
hm = AllocA(struct hmPixel);
hm->x = x1;
hm->y = 0;
hm->w = w;
hm->h = 0;
hm->val = 0.0;
hm->count = 0;
slAddHead(&hmList, hm);
hashAdd(pixelHash, pixelStr, hm);
}
else
hm = el->val;
if (x2 - hm->x > hm->w)
hm->w = x2 - hm->x;
hm->val += val;
hm->count += 1;
}
struct rgbColor rgb = vgColorIxToRgb(vg, col);
int r = rgb.r + floor((float) (255 - rgb.r) * 0.8);
int g = rgb.g + floor((float) (255 - rgb.g) * 0.8);
int b = rgb.b + floor((float) (255 - rgb.b) * 0.8);
Color fillCol = vgFindColorIx(vg, r, g, b);
medVal = medVal / (settings->maxVal - settings->minVal);
if (medVal > 1.0)
medVal = 1.0;
int medY = round((float) settings->dataHeight * (1.0 - medVal) ) + settings->dataOffsetY;
vgSetClip(vg, settings->dataOffsetX, 0, settings->dataWidth, settings->height);
for (hm = hmList; hm ; hm = hm->next)
{
val = hm->val / hm->count;
val = val / (settings->maxVal - settings->minVal);
if (val > 1.0)
val = 1.0;
y = round((float) settings->dataHeight * (1.0 - val) ) + settings->dataOffsetY;
if (y > medY)
vgBox(vg, hm->x, medY, hm->w, y - medY, fillCol);
else
vgBox(vg, hm->x, y, hm->w, medY - y, fillCol);
vgBox(vg, hm->x, y-1, hm->w, 1, col);
}
vgUnclip(vg);
}
char *copyNumberGif(struct sqlConnection *conn, struct bed *bed,
struct settings *settings, char *suffix, float medVal, Color col)
/* Create genome GIF file and HT that includes it. */
{
if (!bed || !settings)
return NULL;
if (settings->height <= 0 || settings->width <= 0)
return NULL;
struct hvGfx *vg;
struct tempName md5Tn;
char *strToHash = cartSettingsString(bbPrefix, suffix);
trashDirMD5File(&md5Tn, "hgg", ".gif", strToHash);
off_t size = fileSize(md5Tn.forCgi);
if (!fileExists(md5Tn.forCgi) || (size == 0) || DEBUG)
{
vg = hvGfxOpenGif(settings->width, settings->height, md5Tn.forCgi, FALSE);
prepareImage(vg->vg, settings);
drawCopyNumber(vg->vg, bed, settings, medVal, col);
hvGfxClose(&vg);
}
char *filename = replaceChars(md5Tn.forHtml, "..", "");
return filename;
}
struct settings *initSettings(struct sqlConnection *conn,
char *pos, char *name, int width, int height,
float minVal, float maxVal)
{
struct settings *settings = AllocA(struct settings);
trackLayoutInit(&tl, cart);
settings->title = NULL;
if (name)
settings->title = cloneString(name);
settings->fontHeight = tl.fontHeight;
settings->font = tl.font;
settings->width = width;
settings->height = height;
settings->dataOffsetX = GUTTER_WIDTH;
settings->dataWidth = settings->width - GUTTER_WIDTH;
settings->dataOffsetY = TITLE_HEIGHT;
settings->dataHeight = settings->height - TITLE_HEIGHT;
settings->minVal = minVal;
settings->maxVal = maxVal;
char *chrom = NULL;
int start = 0;
int stop = 0;
settings->layoutHash = hashNew(0);
settings->layoutList = NULL;
settings->totalBases = 0.0;
if (pos)
{
if (!hgParseChromRange(NULL, pos, &chrom, &start, &stop))
return NULL;
}
struct genoLayChrom *gl, *glList = genoLayDbChroms(conn, FALSE);
slSort(&glList, genoLayChromCmpName);
for (gl = glList; gl; gl = gl->next)
{
if (!chrom)
settings->totalBases += gl->size;
else if (chrom && sameString(chrom, gl->fullName))
{
settings->totalBases += (float) (stop - start);
break;
}
}
if (settings->totalBases == 0.0)
settings->totalBases = 1.0;
float cbases = 0.0;
struct chromLay *cl;
for (gl = glList; gl; gl = gl->next)
{
if (!chrom)
{
AllocVar(cl);
cl->chrom = cloneString(gl->fullName);
cl->baseStart = 0.0;
cl->baseEnd = (float) gl->size;
cl->baseWidth = cl->baseEnd - cl->baseStart;
cl->pxWidth = (float) settings->dataWidth * cl->baseWidth / settings->totalBases;
cl->pxStart = (float) settings->dataWidth * cbases / settings->totalBases + settings->dataOffsetX;
hashAdd(settings->layoutHash, cl->chrom, cl);
slAddHead(&settings->layoutList, cl);
cbases += (float) gl->size;
}
else if (chrom && sameString(chrom, gl->fullName))
{
AllocVar(cl);
cl->chrom = cloneString(gl->fullName);
cl->baseStart = (float) start;
cl->baseEnd = (float) stop;
cl->baseWidth = cl->baseEnd - cl->baseStart;
cl->pxWidth = (float) settings->dataWidth;
cl->pxStart = settings->dataOffsetX;
hashAdd(settings->layoutHash, cl->chrom, cl);
slAddHead(&settings->layoutList, cl);
break;
}
}
slReverse(&settings->layoutList);
return settings;
}