src/hg/wikiPlot/wikiPlot.c 1.8
1.8 2009/08/19 23:25:19 angie
Added option to mgSaveToGif and its call stack, to use GIF's Graphic Control Extension to make memgfx's background color (0) transparent. Also corrected terminology for PNG in .h files: useAlpha -> useTransparency.
Index: src/hg/wikiPlot/wikiPlot.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/wikiPlot/wikiPlot.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -b -B -U 1000000 -r1.7 -r1.8
--- src/hg/wikiPlot/wikiPlot.c 6 May 2003 07:22:36 -0000 1.7
+++ src/hg/wikiPlot/wikiPlot.c 19 Aug 2009 23:25:19 -0000 1.8
@@ -1,505 +1,505 @@
/* wikiPlot - Quick plots of maps vs. each other. */
#include "common.h"
#include "linefile.h"
#include "hash.h"
#include "cheapcgi.h"
#include "htmshell.h"
#include "portable.h"
#include "memgfx.h"
static char const rcsid[] = "$Id$";
/* Variables that can be overridden by CGI. */
char *contigDir = "/projects/hg3/gs.7/oo.29/19/ctg18433";
char *mapX = "info.noNt";
char *mapY = "gold.99";
int pix = 500;
double xOff = -0.05, yOff = -0.05, zoom = 0.9;
/* Span range of values in x and y. */
int xStart, xEnd, yStart, yEnd;
boolean plotName = TRUE;
MgFont *font;
struct clonePos
{
struct clonePos *next;
char *name; /* Name of clone. */
int pos; /* Position in map. */
double totSize; /* Total fragment size (just for gold) */
double weightedPos; /* Total weighted position (just for gold) */
};
double scaleOne(double raw, double rangeStart, double rangeEnd, int pix,
double offset, double zoom)
/* Scale one coordinate. */
{
double range = rangeEnd - rangeStart + 1;
double pos = ((raw - rangeStart) / range - offset) * zoom;
return pix*pos;
}
void zoomScale(double x, double y, int *retX, int *retY)
/* Scale both coordinates. */
{
*retX = round(scaleOne(x, xStart, xEnd, pix, xOff, zoom));
*retY = round(scaleOne(y, yStart, yEnd, pix, yOff, zoom));
}
void readInfo(char *fileName, struct clonePos **retList, struct hash **retHash)
/* Read info formatted files */
{
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *line, *row[3];
struct clonePos *cpList = NULL, *cp;
struct hash *hash = newHash(0);
if (!lineFileNext(lf, &line, NULL))
errAbort("%s is empty", fileName);
while (lineFileRow(lf, row))
{
if (hashLookup(hash, row[0]))
warn("%s duplicated in %s, ignoring all but first", row[0], fileName);
else
{
AllocVar(cp);
hashAddSaveName(hash, row[0], cp, &cp->name);
cp->pos = lineFileNeedNum(lf, row, 1);
slAddHead(&cpList, cp);
}
}
lineFileClose(&lf);
slReverse(&cpList);
*retList = cpList;
*retHash = hash;
}
void readGold(char *fileName, struct clonePos **retList, struct hash **retHash)
/* Read .agp/gold formatted file */
{
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *line, *words[12];
struct clonePos *cpList = NULL, *cp;
struct hash *hash = newHash(0);
int wordCount;
while ((wordCount = lineFileChop(lf, words)) != 0)
{
char *type = words[4];
char *clone = words[5];
int fragStart, fragEnd;
double fragSize;
if (type[0] == 'N')
continue;
lineFileExpectWords(lf, 9, wordCount);
chopSuffix(clone);
fragStart = lineFileNeedNum(lf, words, 1)-1;
fragEnd = lineFileNeedNum(lf, words, 2);
fragSize = fragEnd - fragStart;
if ((cp = hashFindVal(hash, clone)) == NULL)
{
AllocVar(cp);
hashAddSaveName(hash, clone, cp, &cp->name);
slAddHead(&cpList, cp);
}
cp->weightedPos += fragSize * fragStart;
cp->totSize += fragSize;
}
lineFileClose(&lf);
slReverse(&cpList);
for (cp = cpList; cp != NULL; cp = cp->next)
cp->pos = cp->weightedPos/cp->totSize;
*retList = cpList;
*retHash = hash;
}
void readGl(char *fileName, struct clonePos **retList, struct hash **retHash)
/* Read gl formatted files. */
{
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *line, *row[3];
struct clonePos *cpList = NULL, *cp;
struct hash *hash = newHash(0);
int wordCount;
while (lineFileRow(lf, row))
{
char *clone = row[0];
int fragStart, fragEnd;
double fragSize;
chopSuffix(clone);
fragStart = lineFileNeedNum(lf, row, 1);
fragEnd = lineFileNeedNum(lf, row, 2);
fragSize = fragEnd - fragStart;
if ((cp = hashFindVal(hash, clone)) == NULL)
{
AllocVar(cp);
hashAddSaveName(hash, clone, cp, &cp->name);
slAddHead(&cpList, cp);
}
cp->weightedPos += fragSize * fragStart;
cp->totSize += fragSize;
}
lineFileClose(&lf);
slReverse(&cpList);
for (cp = cpList; cp != NULL; cp = cp->next)
cp->pos = cp->weightedPos/cp->totSize;
*retList = cpList;
*retHash = hash;
}
void readMmBarge(char *fileName, struct clonePos **retList, struct hash **retHash)
/* Read mmBarge formatted files. */
{
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *line, *row[3];
struct clonePos *cpList = NULL, *cp;
struct hash *hash = newHash(0);
/* Open file and verify header. */
if (!lineFileNext(lf, &line, NULL))
errAbort("%s is empty", fileName);
if (!startsWith("Barge", line))
errAbort("%s is not an mmBarge file", fileName);
lineFileNext(lf, &line, NULL);
lineFileNext(lf, &line, NULL);
lineFileNext(lf, &line, NULL);
if (!startsWith("-----", line))
errAbort("%s is not an mmBarge file", fileName);
while (lineFileRow(lf, row))
{
char *offset = row[0];
if (startsWith("-----", offset))
continue;
if (hashLookup(hash, row[1]))
warn("%s duplicated in %s, ignoring all but first", row[0], fileName);
else
{
AllocVar(cp);
hashAddSaveName(hash, row[1], cp, &cp->name);
if (offset[0] == '(')
++offset;
if (!isdigit(offset[0]))
errAbort("Expecting number first field of line %d of %s",
lf->lineIx, lf->fileName);
cp->pos = atoi(offset);
slAddHead(&cpList, cp);
}
}
lineFileClose(&lf);
slReverse(&cpList);
*retList = cpList;
*retHash = hash;
}
void readDat(char *fileName, struct clonePos **retList, struct hash **retHash,
int column)
/* Read in one of Terry Furey's dat files. */
{
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *line, *row[3];
struct clonePos *cpList = NULL, *cp;
struct hash *hash = newHash(0);
while (lineFileRow(lf, row))
{
AllocVar(cp);
hashAddSaveName(hash, row[2], cp, &cp->name);
cp->pos = lineFileNeedNum(lf, row, column);
slAddHead(&cpList, cp);
}
lineFileClose(&lf);
slReverse(&cpList);
*retList = cpList;
*retHash = hash;
}
void loadMap(char *fileName, struct clonePos **retList, struct hash **retHash)
/* Figure out file type and load it. */
{
char file[128], ext[64];
splitPath(fileName, NULL, file, ext);
if (startsWith("info", file))
return readInfo(fileName, retList, retHash);
else if (startsWith("mmBarge", file))
return readMmBarge(fileName, retList, retHash);
else if (startsWith("gold", file) || sameString(".agp", ext))
return readGold(fileName, retList, retHash);
else if (sameString(".gl", ext) || sameString("gl", file))
return readGl(fileName, retList, retHash);
else
errAbort("Unrecognized file type %s%s", file, ext);
}
void loadMaps(char *mapA, char *mapB, struct clonePos **retListA,
struct clonePos **retListB, struct hash **retHashA, struct hash **retHashB)
/* Load some maps. */
{
char file[128], ext[64];
splitPath(mapA, NULL, file, ext);
if (sameString(".dat", ext))
{
readDat(mapA, retListA, retHashA, 0);
readDat(mapA, retListB, retHashB, 1);
}
else
{
loadMap(mapA, retListA, retHashA);
loadMap(mapB, retListB, retHashB);
}
}
void posSpan(struct clonePos *cpList, int *retStart, int *retEnd)
/* Figure out min/max span of clone list. */
{
struct clonePos *cp;
int start, end;
start = end = cpList->pos;
for (cp = cpList->next; cp != NULL; cp = cp->next)
{
if (start > cp->pos) start = cp->pos;
if (end < cp->pos) end = cp->pos;
}
*retStart = start;
*retEnd = end;
}
void mapZoomIn(int x, int y, int width, int height, double zx, double zy, double zScale)
/* Print out image map rectangle that calls self with zoom info. */
{
printf("<AREA SHAPE=RECT COORDS=\"%d,%d,%d,%d\" ", x, y, x+width, y+height);
printf("HREF=\"../cgi-bin/wikiPlot?contigDir=%s&mapX=%s&mapY=%s&pix=%d&xOff=%f&yOff=%f&zoom=%f\" ",
cgiEncode(contigDir), cgiEncode(mapX), cgiEncode(mapY), pix, zx, zy, zScale);
printf(">\n");
}
void plot(struct memGfx *mg, int x, int y, char *name, Color color)
/* Plot a point. */
{
// y = mg->height - 1 - y;
if (plotName)
{
mgTextCentered(mg, x-1, y-1, 3, 3, color, font, name);
}
else
mgDrawBox(mg, x-1, y-1, 3, 3, color);
}
void makePlot(struct clonePos *xList, struct clonePos *yList, struct hash *yHash)
/* Write out graphics for plot. */
{
struct memGfx *mg = NULL;
struct tempName gifTn;
char *mapName = "map";
struct clonePos *xp, *yp;
int i, j, x, y, nextX, nextY;
int divisions = 10;
double invZoom = 1.0/zoom;
double magnify = 2.0;
double newZoom = zoom*magnify;
double invNewZoom = 1.0/newZoom;
int xCount = slCount(xList);
plotName = (xCount/zoom < 50);
if (xList == NULL || yList == NULL)
return;
font = mgSmallFont();
posSpan(xList, &xStart, &xEnd);
posSpan(yList, &yStart, &yEnd);
if (pix < 50 || pix > 5000)
errAbort("Pixels out of range - must be between 50 an 5000");
mg = mgNew(pix, pix);
mgClearPixels(mg);
/* Plot dots. */
for (xp = xList; xp != NULL; xp = xp->next)
{
if ((yp = hashFindVal(yHash, xp->name)) != NULL)
{
zoomScale(xp->pos, yp->pos, &x, &y);
plot(mg, x, y, xp->name, MG_BLACK);
}
}
/* Make zooming image map. */
printf("<MAP Name=%s>\n", mapName);
for (i=0; i<divisions; ++i)
{
double cenX = xOff + (i + 0.5) * (invZoom / divisions);
double sx = cenX - invNewZoom/2;
x = i*pix/divisions;
nextX = (i+1)*pix/divisions;
for (j=0; j<divisions; ++j)
{
double cenY = yOff + (j + 0.5) * (invZoom / divisions);
double sy = cenY - invNewZoom/2;
y = j*pix/divisions;
nextY = (j+1)*pix/divisions;
mapZoomIn(x, y, nextX - x, nextY - y, sx, sy, zoom*magnify);
}
}
printf("</MAP>\n");
/* Save image in temp dir. */
makeTempName(&gifTn, "wikPic", ".gif");
-mgSaveGif(mg, gifTn.forCgi);
+mgSaveGif(mg, gifTn.forCgi, FALSE);
printf(
"<P><IMG SRC = \"%s\" BORDER=1 WIDTH=%d HEIGHT=%d USEMAP=#%s><BR>\n",
gifTn.forHtml, pix, pix, mapName);
mgFree(&mg);
/* Print some extra info. */
printf("X has %d elements ranging from %d to %d<BR>\n", slCount(xList), xStart, xEnd);
printf("Y has %d elements ranging from %d to %d<BR>\n", slCount(yList), yStart, yEnd);
}
void printBox()
/* Make little navigation box. */
{
puts(
"<TABLE BORDER=\"0\" WIDTH=\"100%\">\n"
" <TR>\n"
" <TD WIDTH=\"33%\"><INPUT TYPE=\"SUBMIT\" NAME=\"boxUpLeft\" VALUE=\" \\ \"></TD>\n"
" <TD WIDTH=\"33%\"><INPUT TYPE=\"SUBMIT\" NAME=\"boxUp\" VALUE=\" ^ \"></TD>\n"
" <TD WIDTH=\"34%\"><INPUT TYPE=\"SUBMIT\" NAME=\"boxUpRight\" VALUE=\" / \"></TD>\n"
" </TR>\n"
" <TR>\n"
" <TD WIDTH=\"33%\"><INPUT TYPE=\"SUBMIT\" NAME=\"boxLeft\" VALUE=\" < \"></TD>\n"
" <TD WIDTH=\"33%\"><INPUT TYPE=\"SUBMIT\" NAME=\"boxOut\" VALUE=\" Z \"></TD>\n"
" <TD WIDTH=\"34%\"><INPUT TYPE=\"SUBMIT\" NAME=\"boxRight\" VALUE=\" > \"></TD>\n"
" </TR>\n"
" <TR>\n"
" <TD WIDTH=\"33%\"><INPUT TYPE=\"SUBMIT\" NAME=\"boxDownLeft\" VALUE=\" / \"></TD>\n"
" <TD WIDTH=\"33%\"><INPUT TYPE=\"SUBMIT\" NAME=\"boxDown\" VALUE=\" v \"></TD>\n"
" <TD WIDTH=\"34%\"><INPUT TYPE=\"SUBMIT\" NAME=\"boxDownRight\" VALUE=\" \\ \"></TD>\n"
" </TR>\n"
" <TR>\n"
" </TR>\n"
"</TABLE>\n"
"\n");
cgiMakeButton("unzoom", "unzoom");
}
void wikiPlot()
/* wikiPlot - Quick plots of maps vs. each other. */
{
boolean gotDir = cgiVarExists("contigDir");
double step;
contigDir = cgiUsualString("contigDir", contigDir);
mapX = cgiUsualString("mapX", mapX);
mapY = cgiUsualString("mapY", mapY);
pix = cgiUsualInt("pix", pix);
xOff = cgiUsualDouble("xOff", xOff);
yOff = cgiUsualDouble("yOff", yOff);
zoom = cgiUsualDouble("zoom", zoom);
step = 0.1 * 1/zoom;
if (cgiVarExists("boxOut"))
{
double invZoom = 1.0/zoom;
double xCen = xOff + invZoom*0.5;
double yCen = yOff + invZoom*0.5;
zoom /= 2;
invZoom = 1.0/zoom;
xOff = xCen - invZoom*0.5;
yOff = yCen - invZoom*0.5;
}
else if (cgiVarExists("boxUp"))
yOff -= step;
else if (cgiVarExists("boxDown"))
yOff += step;
else if (cgiVarExists("boxLeft"))
xOff -= step;
else if (cgiVarExists("boxRight"))
xOff += step;
else if (cgiVarExists("boxUpLeft"))
{
yOff -= step;
xOff -= step;
}
else if (cgiVarExists("boxUpRight"))
{
yOff -= step;
xOff += step;
}
else if (cgiVarExists("boxDownLeft"))
{
yOff += step;
xOff -= step;
}
else if (cgiVarExists("boxDownRight"))
{
yOff += step;
xOff += step;
}
else if (cgiVarExists("unzoom"))
{
xOff = yOff = -0.05;
zoom = 0.9;
}
printf("<FORM ACTION=\"../cgi-bin/wikiPlot\" METHOD=\"GET\">\n");
printf("<TABLE BORDER=0 WIDTH=\"100%%\">\n");
printf("<TR>\n");
printf("<TD WIDTH=\"78%%\">\n");
printf("<B>Wiki Plotter</B><BR>\n");
printf("<B>Contig: </B>");
cgiMakeTextVar("contigDir", contigDir, 0);
if (gotDir)
{
cgiMakeButton("refresh", "refresh");
}
else
cgiMakeButton("submit", "submit");
printf("<BR>\n");
printf("<B>Map X: </B>");
cgiMakeTextVar("mapX", mapX, 12);
printf("<B>Map Y: </B>");
cgiMakeTextVar("mapY", mapY, 12);
printf("<B>Pixels: </B>");
cgiMakeIntVar("pix", pix, 4);
printf("</TD>\n");
printf("<TD WIDTH=\"22%%\">\n");
if (gotDir)
printBox();
printf("</TD>\n");
printf("</TR>\n");
printf("</TABLE>\n");
if (gotDir)
{
char xFile[512], yFile[512];
struct hash *xHash = NULL, *yHash = NULL;
struct clonePos *xList = NULL, *yList = NULL;
sprintf(xFile, "%s/%s", contigDir, mapX);
sprintf(yFile, "%s/%s", contigDir, mapY);
loadMaps(xFile, yFile, &xList, &yList, &xHash, &yHash);
makePlot(xList, yList, yHash);
}
/* Save hidden vars. */
{
char buf[256];
sprintf(buf, "%f", zoom);
cgiMakeHiddenVar("zoom", buf);
sprintf(buf, "%f", xOff);
cgiMakeHiddenVar("xOff", buf);
sprintf(buf, "%f", yOff);
cgiMakeHiddenVar("yOff", buf);
}
printf("</FORM>\n");
}
int main(int argc, char *argv[])
/* Process command line. */
{
cgiSpoof(&argc, argv);
htmShell("wikiPlot", wikiPlot, NULL);
return 0;
}