3003dd8639adc83e45ead18a948ab7e168e9e6cc jcasper Mon May 20 08:11:37 2019 -0700 More changes in response to code review, refs #23481 diff --git src/hg/hgTracks/hicTrack.c src/hg/hgTracks/hicTrack.c index 3d8d02f..0dae825 100644 --- src/hg/hgTracks/hicTrack.c +++ src/hg/hgTracks/hicTrack.c @@ -149,31 +149,32 @@ } } dyStringPrintf(windowPos, "%s:%d:%d", hicChromName, strawStart, winEnd-1); char *filename = trackDbSettingOrDefault(tg->tdb, "bigDataUrl", NULL); if (filename == NULL) return; tg->networkErrMsg = Cstraw(normalization, filename, binSize, dyStringContents(windowPos), dyStringContents(windowPos), "BP", &x, &y, &counts, &numRecords); // Using the interact structure because it has convenient fields, but this is not interact data and // shouldn't be passed to those functions. struct interact *hicItems = NULL; int i = 0, filtNumRecords = 0; tg->maxRange = 0.0; // the max height of an interaction in this window -double *countsCopy = (double*) calloc(numRecords, sizeof(double)); +double *countsCopy = NULL; +AllocArray(countsCopy, numRecords); for (i=0; i<numRecords; i++) { char *drawMode = hicUiFetchDrawMode(cart, tg->track); if (isnan(counts[i])) { // Yes, apparently NAN is possible with normalized values in some methods. Ignore those. continue; } if (sameString(drawMode, HIC_DRAW_MODE_ARC)) { // we omit self-interactions in arc mode (they'd just be weird vertical lines) if (x[i] == y[i]) continue; } countsCopy[filtNumRecords++] = counts[i]; @@ -217,113 +218,121 @@ } void hicLoadItems(struct track *tg) /* Load Hi-C items in (mostly) interact format */ { char *filename = trackDbSettingOrDefault(tg->tdb, "bigDataUrl", NULL); if (filename == NULL) return; tg->customPt = grabHeader(tg); if (tg->customPt == NULL) return; loadAndFilterItems(tg); } -Color *ColorSetForHic(struct hvGfx *hvg, struct track *tg, int bucketCount) +Color *colorSetForHic(struct hvGfx *hvg, struct track *tg, int bucketCount) /* Create the gradient color array for drawing a Hi-C heatmap */ { struct rgbColor rgbLow; char *lowColorText = hicUiFetchBgColor(cart, tg->track); // This is an HTML color like #ffed02 unsigned lowRgbVal = 0; if (!htmlColorForCode(lowColorText, &lowRgbVal)) { warn("Bad RGB background color value %s for track %s", lowColorText, tg->track); return NULL; } int r, g, b; htmlColorToRGB(lowRgbVal, &r, &g, &b); rgbLow.r=(unsigned char)r; rgbLow.g=(unsigned char)g; rgbLow.b=(unsigned char)b; struct rgbColor rgbHigh; char *highColorText = hicUiFetchDrawColor(cart, tg->track); // This is an HTML color like #ffed02 unsigned highRgbVal = 0; if (!htmlColorForCode(highColorText, &highRgbVal)) { warn("Bad RGB color value %s for track %s", highColorText, tg->track); return NULL; } htmlColorToRGB(highRgbVal, &r, &g, &b); rgbHigh.r=(unsigned char)r; rgbHigh.g=(unsigned char)g; rgbHigh.b=(unsigned char)b; -Color *colorIxs = (Color*) calloc (bucketCount, sizeof(Color)); +Color *colorIxs = NULL; +AllocArray(colorIxs, bucketCount); hvGfxMakeColorGradient(hvg, &rgbLow, &rgbHigh, bucketCount, colorIxs); return colorIxs; } double getHicMaxScore(struct track *tg) /* Return the score at which we should reach the maximum intensity color. */ { if (hicUiFetchAutoScale(cart, tg->track)) return tg->graphUpperLimit; else return hicUiFetchMaxValue(cart, tg->track); } +void calcItemLeftRightBoundaries(int *leftStart, int *leftEnd, int *rightStart, int *rightEnd, + int binSize, struct interact *hicItem) +{ +*leftStart = hicItem->sourceStart - winStart; +*leftEnd = *leftStart + binSize; +*rightStart = hicItem->targetStart - winStart; +*rightEnd = *rightStart + binSize; +if (*leftStart < 0) + *leftStart = 0; +if (*leftEnd > winEnd-winStart) + *leftEnd = winEnd-winStart; +if (*rightStart < 0) + *rightStart = 0; +if (*rightEnd > winEnd-winStart) + *rightEnd = winEnd-winStart; +} + static void drawHicTriangle(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw a list of Hi-C interactions in a triangle */ { double xScale = scaleForWindow(width, seqStart, seqEnd); double yScale = xScale; int maxHeight = tg->height; struct interact *hicItem = NULL; int binSize = fetchResolution(tg); if (binSize == 0) return; if (vis == tvDense) { yScale *= 0.5; } double maxScore = getHicMaxScore(tg); -Color *colorIxs = ColorSetForHic(hvg, tg, HIC_SCORE_BINS+1); +Color *colorIxs = colorSetForHic(hvg, tg, HIC_SCORE_BINS+1); if (colorIxs == NULL) return; // something went wrong with colors for (hicItem = (struct interact *)tg->items; hicItem; hicItem = hicItem->next) { - int leftStart = hicItem->sourceStart - winStart; - int leftEnd = leftStart + binSize; - int rightStart = hicItem->targetStart - winStart; - int rightEnd = rightStart + binSize; - if (leftStart < 0) - leftStart = 0; - if (leftEnd > winEnd-winStart) - leftEnd = winEnd-winStart; - if (rightStart < 0) - rightStart = 0; - if (rightEnd > winEnd-winStart) - rightEnd = winEnd-winStart; + int leftStart, leftEnd, rightStart, rightEnd; + calcItemLeftRightBoundaries(&leftStart, &leftEnd, &rightStart, &rightEnd, binSize, hicItem); int colorIx; if (hicItem->value > maxScore) colorIx = colorIxs[HIC_SCORE_BINS]; else colorIx = colorIxs[(int)(HIC_SCORE_BINS * hicItem->value/maxScore)]; // adding four polygon points for a diamond, based on the starts and ends of the source and target coordinate ranges. struct gfxPoly *diamond = gfxPolyNew(); // left point of the diamond double x = xScale * (leftStart+rightStart)/2.0; double y = yScale * (rightStart-leftStart)/2.0; gfxPolyAddPoint(diamond, (int)x+xOff, maxHeight-(int)y+yOff); // top point of the diamond @@ -354,48 +363,38 @@ { double xScale = scaleForWindow(width, seqStart, seqEnd); double yScale = xScale; int maxHeight = tg->height; struct interact *hicItem = NULL; int binSize = fetchResolution(tg); if (binSize == 0) return; if (vis == tvDense) { yScale *= 0.5; } double maxScore = getHicMaxScore(tg); -Color *colorIxs = ColorSetForHic(hvg, tg, HIC_SCORE_BINS+1); +Color *colorIxs = colorSetForHic(hvg, tg, HIC_SCORE_BINS+1); if (colorIxs == NULL) return; // something went wrong with colors for (hicItem = (struct interact *)tg->items; hicItem; hicItem = hicItem->next) { - int leftStart = hicItem->sourceStart - winStart; - int leftEnd = leftStart + binSize; - int rightStart = hicItem->targetStart - winStart; - int rightEnd = rightStart + binSize; - if (leftStart < 0) - leftStart = 0; - if (leftEnd > winEnd-winStart) - leftEnd = winEnd-winStart; - if (rightStart < 0) - rightStart = 0; - if (rightEnd > winEnd-winStart) - rightEnd = winEnd-winStart; + int leftStart, leftEnd, rightStart, rightEnd; + calcItemLeftRightBoundaries(&leftStart, &leftEnd, &rightStart, &rightEnd, binSize, hicItem); int colorIx; if (hicItem->value > maxScore) colorIx = colorIxs[HIC_SCORE_BINS]; else colorIx = colorIxs[(int)(HIC_SCORE_BINS * hicItem->value/maxScore)]; double x = xScale * leftStart; double y = yScale * ((winEnd-winStart)-rightStart); hvGfxBox(hvg, (int)x+xOff, maxHeight-(int)y+yOff, (int)(xScale*(leftEnd-leftStart))+1, (int)(yScale*(rightEnd-rightStart))+1, colorIx); if (leftStart != rightStart) { x = xScale * rightStart; y = yScale * ((winEnd-winStart)-leftStart); hvGfxBox(hvg, (int)x+xOff, maxHeight-(int)y+yOff, (int)(xScale*(rightEnd-rightStart))+1, (int)(yScale*(leftEnd-leftStart))+1, colorIx); } @@ -425,31 +424,31 @@ { double xScale = scaleForWindow(width, seqStart, seqEnd); double yScale = xScale; int maxHeight = tg->height; struct interact *hicItem = NULL; int binSize = fetchResolution(tg); if (binSize == 0) return; if (vis == tvDense) { yScale *= 0.5; } double maxScore = getHicMaxScore(tg); -Color *colorIxs = ColorSetForHic(hvg, tg, HIC_SCORE_BINS+1); +Color *colorIxs = colorSetForHic(hvg, tg, HIC_SCORE_BINS+1); if (colorIxs == NULL) return; // something went wrong with colors slSort(&tg->items, cmpHicItems); // So that the darkest arcs are drawn on top and not lost for (hicItem = (struct interact *)tg->items; hicItem; hicItem = hicItem->next) { int leftStart = hicItem->sourceStart - winStart; int leftMidpoint = leftStart + binSize/2; int rightStart = hicItem->targetStart - winStart; int rightMidpoint = rightStart + binSize/2; if ((leftMidpoint < 0) || (leftMidpoint > winEnd-winStart)) continue; // skip this item - we'd be drawing to a point off the screen if ((rightMidpoint < 0) || (rightMidpoint > winEnd-winStart)) continue; // skip this item - we'd be drawing to a point off the screen