src/hg/hgTracks/netTrack.c 1.26
1.26 2009/06/12 22:19:35 hiram
Implement modes squish and pack for net tracks
Index: src/hg/hgTracks/netTrack.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/hgTracks/netTrack.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -b -B -U 1000000 -r1.25 -r1.26
--- src/hg/hgTracks/netTrack.c 18 Mar 2009 18:27:00 -0000 1.25
+++ src/hg/hgTracks/netTrack.c 12 Jun 2009 22:19:35 -0000 1.26
@@ -1,295 +1,320 @@
/* netTrack - stuff to handle loading and display of
* netAlign type tracks in browser. Nets are derived
* from cross-species alignments usually. */
#include "common.h"
#include "hash.h"
#include "linefile.h"
#include "jksql.h"
#include "hdb.h"
#include "hgTracks.h"
#include "netCart.h"
#include "chainNetDbLoad.h"
static char const rcsid[] = "$Id$";
struct cartOptions
{
enum netColorEnum netColor; /* ChromColors, GrayScale */
enum netLevelEnum netLevel; /* filter chains by level 1 thru 6 (0==All) */
};
struct netItem
/* A net track item. */
{
struct netItem *next;
int level;
char *className;
int yOffset;
};
static char *netClassNames[] = {
"Level 1", "Level 2", "Level 3", "Level 4", "Level 5", "Level 6", };
static struct netItem *makeNetItems()
/* Make the levels for net alignment track. */
{
struct netItem *ni, *niList = NULL;
int i;
int numClasses = ArraySize(netClassNames);
for (i=0; i<numClasses; ++i)
{
AllocVar(ni);
ni->level = i;
ni->className = netClassNames[i];
slAddHead(&niList, ni);
}
slReverse(&niList);
return niList;
}
static void netLoad(struct track *tg)
/* Load up net tracks. (Will query database during drawing for a change.) */
{
tg->items = makeNetItems();
}
static void netFree(struct track *tg)
/* Free up netGroup items. */
{
slFreeList(&tg->items);
}
static char *netName(struct track *tg, void *item)
/* Return name of net level track. */
{
struct netItem *ni = item;
return ni->className;
}
static struct track *rTg;
static struct hvGfx *rHvg;
static int rX; /* X offset of drawing area. */
static int rHeightPer; /* Height of boxes. */
static int rMidLineOff; /* Offset to draw connecting lines. */
static int rNextLine; /* Y offset to next line. */
static double rScale; /* Scale from bases to pixels. */
static boolean rIsFull; /* Full display? */
static char *netColorLastChrom;
static void netColorClearCashe()
{
netColorLastChrom = "UNKNOWN";
}
static Color netColor(struct track *tg, char *chrom, int level)
/* return appropriate color for a chromosome/scaffold */
{
struct cartOptions *netCart;
netCart = (struct cartOptions *) tg->extraUiData;
if (netCart->netColor == netColorGrayScale)
switch(level)
{
case 1: return(shadesOfGray[9]); break;
case 2: return(shadesOfGray[7]); break;
case 3: return(shadesOfGray[6]); break;
case 4: return(shadesOfGray[5]); break;
case 5: return(shadesOfGray[4]); break;
case 6: return(shadesOfGray[3]); break;
default: return(shadesOfGray[2]); break;
}
static Color color;
if (!sameString(chrom, netColorLastChrom))
color = getSeqColor(chrom, rHvg);
if (0 == color)
color = 1; /* don't display in white */
netColorLastChrom = chrom;
return color;
}
static void rNetBox(struct hvGfx *hvg, struct cnFill *fill, int start, int end, int y, int level,
Color color, Color barbColor, int orientation)
/* Draw a scaled box. */
{
int x1,x2,w;
/* Do clipping before scaling because scaling may cause
* integer overflow. */
if (start < winStart) start = winStart;
if (end > winEnd) end = winEnd;
if (start >= end)
return;
x1 = round((double)(start-winStart)*rScale) + rX;
x2 = round((double)(end-winStart)*rScale) + rX;
w = x2-x1;
if (w < 1)
w = 1;
hvGfxBox(rHvg, x1, y, w, rHeightPer, color);
if (w > 3)
clippedBarbs(rHvg, x1, y+rMidLineOff, w, 2, 5, orientation, barbColor, TRUE);
if (w > 1)
{
if (rNextLine > 0) /* Put up click info in full mode. */
{
struct dyString *bubble = newDyString(256);
char depth[8];
snprintf(depth, sizeof(depth), "%d", level);
dyStringPrintf(bubble, "%s %c %dk ",
fill->qName, fill->qStrand, fill->qStart/1000);
mapBoxHc(hvg, start, end, x1, y, w, rHeightPer, rTg->mapName,
depth, bubble->string);
dyStringFree(&bubble);
}
}
}
static void rNetLine(struct hvGfx *hvg, struct cnFill *gap, int y, int level, Color color,
int orientation)
/* Write out line filling gap and associated info. */
{
int start = gap->tStart;
int end = start + gap->tSize;
int x1,x2,w;
/* Do clipping before scaling because scaling may cause
* integer overflow. */
if (start < winStart) start = winStart;
if (end > winEnd) end = winEnd;
if (start >= end)
return;
x1 = round((double)(start-winStart)*rScale) + rX;
x2 = round((double)(end-winStart)*rScale) + rX;
w = x2-x1;
if (w >= 1)
{
struct dyString *bubble = newDyString(256);
char depth[8];
int midY = y + rMidLineOff;
clippedBarbs(rHvg, x1, midY, w, 2, 5, orientation, color, FALSE);
hvGfxLine(rHvg, x1, midY, x2, midY, color);
if (rNextLine > 0) /* Put up click info in full mode. */
{
snprintf(depth, sizeof(depth), "%d", level);
dyStringPrintf(bubble, "size %d/%d Ns %d/%d newRep %d/%d",
gap->qSize, gap->tSize, gap->qN, gap->tN,
gap->qNewR, gap->tNewR);
mapBoxHc(hvg, start, end, x1, y, w, rHeightPer, rTg->mapName,
depth, bubble->string);
dyStringFree(&bubble);
}
}
}
static void rNetDraw(struct track *tg, struct hvGfx *hvg, struct cnFill *fillList, int level, int y)
/* Recursively draw net. */
{
struct cnFill *fill;
struct cnFill *gap;
Color color, invColor;
int orientation;
for (fill = fillList; fill != NULL; fill = fill->next)
{
color = netColor(tg, fill->qName, level);
invColor = hvGfxContrastingColor(rHvg, color);
orientation = orientFromChar(fill->qStrand);
if (fill->children == NULL || fill->tSize * rScale < 2.5)
/* Draw single solid box if no gaps or no room to draw gaps. */
{
- rNetBox(hvg, fill, fill->tStart, fill->tStart + fill->tSize, y, level,
- color, invColor, orientation);
+ rNetBox(hvg, fill, fill->tStart, fill->tStart + fill->tSize,
+ y, level, color, invColor, orientation);
}
else
{
int fStart = fill->tStart;
for ( gap = fill->children; gap != NULL; gap = gap->next)
{
if (gap->tSize * rScale >= 1)
{
rNetBox(hvg, fill, fStart, gap->tStart, y, level,
color, invColor, orientation);
fStart = gap->tStart + gap->tSize;
rNetLine(hvg, gap, y, level+1, color, orientation);
}
}
rNetBox(hvg, fill, fStart, fill->tStart + fill->tSize, y, level,
color, invColor, orientation);
}
for (gap = fill->children; gap != NULL; gap = gap->next)
{
if (gap->children)
{
rNetDraw(tg, hvg, gap->children, level+2, y + rNextLine);
}
}
}
}
static void netDraw(struct track *tg, int seqStart, int seqEnd,
struct hvGfx *hvg, int xOff, int yOff, int width,
MgFont *font, Color color, enum trackVisibility vis)
/* Draw routine for netAlign type tracks. This will load
* the items as well as drawing them. */
{
/* Load Net. */
struct chainNet *net = chainNetLoadRange(database, tg->mapName, chromName,
seqStart, seqEnd, NULL);
if (net != NULL)
{
/* Copy parameters to statics for recursive routine. */
rTg = tg;
rHvg = hvg;
rX = xOff;
/* Clear cashe. */
netColorClearCashe();
/* Compute a few other positional things for recursive routine. */
rHeightPer = tg->heightPer;
rMidLineOff = rHeightPer/2;
- rIsFull = (vis == tvFull);
+ rIsFull = (vis == tvFull || vis == tvPack || vis == tvSquish);
if (rIsFull)
rNextLine = tg->lineHeight;
else
rNextLine = 0;
rScale = scaleForPixels(width);
/* Recursively do main bit of work. */
rNetDraw(tg, hvg, net->fillList, 1, yOff);
chainNetFree(&net);
}
if (vis == tvDense)
mapBoxToggleVis(hvg, xOff, yOff, width, tg->heightPer, tg);
}
+static int netTotalHeight(struct track *tg, enum trackVisibility vis)
+/* A copy of tgFixedTotalHeightNoOverflow() with visibility forced */
+{
+int ret = 0;
+switch (vis)
+ {
+ case tvSquish:
+ ret = tgFixedTotalHeightOptionalOverflow(tg, tvFull, (tl.fontHeight/3)+1, (tl.fontHeight/3), FALSE);
+ break;
+ case tvPack:
+ ret = tgFixedTotalHeightOptionalOverflow(tg, tvFull, (tl.fontHeight/2)+1, (tl.fontHeight/2), FALSE);
+ break;
+ case tvFull:
+ ret = tgFixedTotalHeightOptionalOverflow(tg, tvFull, tl.fontHeight+1, tl.fontHeight, FALSE);
+ break;
+ case tvDense:
+ ret = tgFixedTotalHeightOptionalOverflow(tg, tvDense, tl.fontHeight+1, tl.fontHeight, FALSE);
+ break;
+ case tvHide:
+ default:
+ break;
+ }
+return(ret);
+}
+
void netMethods(struct track *tg)
/* Make track group for chain/net alignment. */
{
struct cartOptions *netCart;
AllocVar(netCart);
netCart->netColor = netFetchColorOption(cart, tg->tdb, FALSE);
netCart->netLevel = netFetchLevelOption(cart, tg->tdb, FALSE);
tg->loadItems = netLoad;
tg->freeItems = netFree;
tg->drawItems = netDraw;
tg->itemName = netName;
tg->mapItemName = netName;
-tg->totalHeight = tgFixedTotalHeightNoOverflow;
+tg->totalHeight = netTotalHeight;
tg->itemHeight = tgFixedItemHeight;
tg->itemStart = tgItemNoStart;
tg->itemEnd = tgItemNoEnd;
tg->mapsSelf = TRUE;
tg->extraUiData = (void *) netCart;
}