/* mainPage - draws the main hgGenome page, including some controls * on the top and the graphic. */ #include "common.h" #include "psGfx.h" #include "pscmGfx.h" #include "linefile.h" #include "hash.h" #include "cheapcgi.h" #include "htmshell.h" #include "cart.h" #include "hui.h" #include "dbDb.h" #include "ra.h" #include "hdb.h" #include "web.h" #include "portable.h" #include "hgColors.h" #include "trackLayout.h" #include "chromInfo.h" #include "hvGfx.h" #include "genoLay.h" #include "cytoBand.h" #include "hCytoBand.h" #include "errCatch.h" #include "chromGraph.h" #include "customTrack.h" #include "hPrint.h" #include "jsHelper.h" #include "hgGenome.h" #include "trashDir.h" static char *allColors[] = { "black", "blue", "purple", "red", "orange", "yellow", "green", "gray", }; static char *defaultColors[maxLinesOfGraphs][maxGraphsPerLine] = { {"blue", "red", "black", "yellow", }, {"gray", "purple", "green", "orange",}, {"blue", "red", "black", "yellow", }, {"gray", "purple", "green", "orange",}, {"blue", "red", "black", "yellow", }, {"gray", "purple", "green", "orange",}, }; char *graphColorAt(int row, int col) /* Return graph color at given row/column, NULL if nonw. */ { char *varName = graphColorVarName(row, col); char *color = cartUsualString(cart, varName, defaultColors[row][col]); if (color == NULL) color = defaultColors[0][0]; return color; } Color colorFromAscii(struct hvGfx *hvg, char *asciiColor) /* Get color index for a named color. */ { if (sameWord("red", asciiColor)) return MG_RED; else if (sameWord("blue", asciiColor)) return MG_BLUE; else if (sameWord("yellow", asciiColor)) return hvGfxFindColorIx(hvg, 220, 220, 0); else if (sameWord("purple", asciiColor)) return hvGfxFindColorIx(hvg, 150, 0, 200); else if (sameWord("orange", asciiColor)) return hvGfxFindColorIx(hvg, 230, 120, 0); else if (sameWord("green", asciiColor)) return hvGfxFindColorIx(hvg, 0, 180, 0); else if (sameWord("gray", asciiColor)) return MG_GRAY; else return MG_BLACK; } /* Page drawing stuff. */ void drawChromGraph(struct hvGfx *hvg, struct sqlConnection *conn, struct genoLay *gl, char *chromGraph, int yOff, int height, Color color, boolean leftLabel, boolean rightLabel, boolean firstInRow) /* Draw chromosome graph on all chromosomes in layout at given * y offset and height. */ { boolean yellowMissing = getYellowMissing(); struct genoGraph *gg = hashFindVal(ggHash, chromGraph); if (gg != NULL) { /* Get binary data source and scaling info etc. */ struct chromGraphBin *cgb = gg->cgb; struct chromGraphSettings *cgs = gg->settings; int maxGapToFill = cgs->maxGapToFill; static struct rgbColor missingDataColor = { 180, 180, 120}; Color missingColor = hvGfxFindRgb(hvg, &missingDataColor); double pixelsPerBase = 1.0/gl->basesPerPixel; double gMin = cgs->minVal, gMax = cgs->maxVal, gScale; gScale = height/(gMax-gMin); /* Draw significance threshold as a light blue line */ if (leftLabel) { static struct rgbColor guidelineColor = { 220, 220, 255}; Color lightBlue = hvGfxFindRgb(hvg, &guidelineColor); struct slRef *ref; struct genoLayChrom *chrom; int rightX = gl->picWidth - gl->rightLabelWidth - gl->margin; int leftX = gl->leftLabelWidth + gl->margin; int width = rightX - leftX; double threshold = getThreshold(); if (threshold >= gMin && threshold <= gMax) { int y = height - ((threshold - gMin)*gScale) + yOff; for (ref = gl->leftList; ref != NULL; ref = ref->next) { chrom = ref->val; hvGfxBox(hvg, leftX, y + chrom->y, width, 1, lightBlue); } ref = gl->bottomList; if (ref != NULL) { chrom = ref->val; hvGfxBox(hvg, leftX, y + chrom->y, width, 1, lightBlue); } } } /* Draw graphs on each chromosome */ chromGraphBinRewind(cgb); while (chromGraphBinNextChrom(cgb)) { struct genoLayChrom *chrom = hashFindVal(gl->chromHash, cgb->chrom); if (chrom) { int chromX = chrom->x, chromY = chrom->y; int minY = chromY + yOff; int maxY = chromY + yOff + height - 1; if (chromGraphBinNextVal(cgb)) { /* Set clipping so can't scribble outside of box. */ hvGfxSetClip(hvg, chromX, chromY, chrom->width+1, chrom->height); /* Handle first point as special case here, so don't * have to test for first point in inner loop. */ double x,lastX; int y,start,lastStart,lastY; start = lastStart = cgb->chromStart; x = lastX = pixelsPerBase*start + chromX; y = lastY = (height - ((cgb->val - gMin)*gScale)) + chromY+yOff; if (y < minY) y = minY; else if (y > maxY) y = maxY; struct pscmGfx *pscm = NULL; if (hvg->pixelBased) { hvGfxDot(hvg, x, y, color); } else { pscm = (struct pscmGfx *)hvg->vg->data; pscmSetColor(pscm, color); psFillEllipse(pscm->ps, x, y, 0.01, 0.01); psSetLineWidth(pscm->ps, 0.01); } /* Draw rest of points, connecting with line to previous point * if not too far off. */ while (chromGraphBinNextVal(cgb)) { start = cgb->chromStart; x = pixelsPerBase*start + chromX; if (hvg->pixelBased) x = (int) x; y = (height - ((cgb->val - gMin)*gScale)) + chromY+yOff; if (y < minY) y = minY; else if (y > maxY) y = maxY; if (x != lastX || y != lastY) { if (start - lastStart <= maxGapToFill) { if (hvg->pixelBased) hvGfxLine(hvg, lastX, lastY, x, y, color); else { pscmSetColor(pscm, color); psDrawLine(pscm->ps, lastX, lastY, x, y); } } else { if (yellowMissing && leftLabel) { int width = x - lastX - 1; if (width > 0) hvGfxBox(hvg, lastX+1, minY, width, height, missingColor); } if (hvg->pixelBased) { hvGfxDot(hvg, x, y, color); } else { pscmSetColor(pscm, color); psFillEllipse(pscm->ps, x, y, 0.01, 0.01); } } } lastX = x; lastY = y; lastStart = start; } if (!hvg->pixelBased) { psSetLineWidth(pscm->ps, 1); } hvGfxUnclip(hvg); } } else { /* Just read and discard data. */ while (chromGraphBinNextVal(cgb)) ; } } /* Draw labels. */ if (withLabels && (leftLabel || rightLabel)) { int lineY = yOff; int i,j; int spaceWidth = tl.nWidth; int tickWidth = spaceWidth*2/3; int fontPixelHeight = mgFontPixelHeight(gl->font); for (i=0; ilineCount; ++i) { hvGfxSetClip(hvg, 0, lineY, gl->picWidth, gl->lineHeight); for (j=0; j< cgs->linesAtCount; ++j) { double lineAt = cgs->linesAt[j]; int y = (height - ((lineAt - gMin)*gScale)) + lineY; int textTop = y - fontPixelHeight/2+1; int textBottom = textTop + fontPixelHeight; char label[24]; safef(label, sizeof(label), "%g", lineAt); if (leftLabel) { hvGfxBox(hvg, gl->margin + gl->leftLabelWidth - tickWidth-1, y, tickWidth, 1, color); if (textTop >= lineY && textBottom < lineY + height) { hvGfxTextRight(hvg, gl->margin, textTop, gl->leftLabelWidth-spaceWidth, fontPixelHeight, color, gl->font, label); } } if (rightLabel) { hvGfxBox(hvg, gl->picWidth - gl->margin - gl->rightLabelWidth+1, y, tickWidth, 1, color); if (textTop >= lineY && textBottom < lineY + height) { hvGfxText(hvg, gl->picWidth - gl->margin - gl->rightLabelWidth + spaceWidth, textTop, color, gl->font, label); } } } lineY += gl->lineHeight; hvGfxUnclip(hvg); } } } } void genomeGif(struct sqlConnection *conn, struct genoLay *gl, int graphRows, int graphCols, int oneRowHeight, char *psOutput) /* Create genome GIF file and HTML that includes it. */ { struct hvGfx *hvg; struct tempName gifTn; Color shadesOfGray[10]; int maxShade = ArraySize(shadesOfGray)-1; int spacing = 1; int yOffset = 2*spacing; int innerHeight = oneRowHeight - 3*spacing; int i,j; if (psOutput) { hvg = hvGfxOpenPostScript(gl->picWidth, gl->picHeight, psOutput); } else { /* Create gif file and make reference to it in html. */ trashDirFile(&gifTn, "hgg", "ideo", ".png"); hvg = hvGfxOpenPng(gl->picWidth, gl->picHeight, gifTn.forCgi, FALSE); hPrintf("", gifTn.forHtml, gl->picWidth, gl->picHeight, hggClick); } /* Get our grayscale. */ hMakeGrayShades(hvg, shadesOfGray, maxShade); /* Draw the labels and then the chromosomes. */ genoLayDrawChromLabels(gl, hvg, MG_BLACK); genoLayDrawBandedChroms(gl, hvg, database, conn, shadesOfGray, maxShade, MG_BLACK); /* Draw chromosome graphs. */ for (i=0; i=0; --j) { char *graph = graphSourceAt(i,j); if (graph != NULL && graph[0] != 0) { Color color = colorFromAscii(hvg, graphColorAt(i,j)); drawChromGraph(hvg, conn, gl, graph, gl->betweenChromOffsetY + yOffset, innerHeight, color, j==0, j==1, firstInRow); firstInRow = FALSE; } } yOffset += oneRowHeight; } hvGfxBox(hvg, 0, 0, gl->picWidth, 1, MG_GRAY); hvGfxBox(hvg, 0, gl->picHeight-1, gl->picWidth, 1, MG_GRAY); hvGfxBox(hvg, 0, 0, 1, gl->picHeight, MG_GRAY); hvGfxBox(hvg, gl->picWidth-1, 0, 1, gl->picHeight, MG_GRAY); hvGfxClose(&hvg); } void graphDropdown(struct sqlConnection *conn, char *varName, char *curVal, char *js) /* Make a drop-down with available chrom graphs */ { int totalCount = 1; char **menu, **values; int i = 0; struct slRef *ref; for (ref = ggList; ref != NULL; ref = ref->next) { struct genoGraph *gg = ref->val; if (gg->isComposite == FALSE) totalCount++; } AllocArray(menu, totalCount); AllocArray(values, totalCount); menu[0] = "-- nothing --"; values[0] = ""; for (ref = ggList; ref != NULL; ref = ref->next) { struct genoGraph *gg = ref->val; if (gg->isComposite == FALSE) { ++i; menu[i] = gg->shortLabel; values[i] = gg->name; } } cgiMakeDropListFull(varName, menu, values, totalCount, curVal, js); freez(&menu); freez(&values); } void colorDropdown(int row, int col, char *js) /* Put up color drop down menu. */ { char *varName = graphColorVarName(row, col); char *curVal = graphColorAt(row, col); cgiMakeDropListFull(varName, allColors, allColors, ArraySize(allColors), curVal, js); } static void addThresholdGraphCarries(struct dyString *dy, int graphRows, int graphCols, boolean cgaOnly) /* Add javascript that carries over threshold and graph vars * to new form. */ { if (cgaOnly) return; jsTextCarryOver(dy, getThresholdName()); int i,j; for (i=0; i