a18829b3e826a0e9c52cb145ff0db94b58e8e01d angie Fri Dec 6 13:09:57 2019 -0800 bigDbSnp: fix colors in dense mode by defining itemColor in addition to itemNameColor and sorting items so that most severe consequences are drawn on top. If maxItems is exceeded, warn user. refs #23283 diff --git src/hg/hgTracks/variation.c src/hg/hgTracks/variation.c index c714c0b..7a97ccb 100644 --- src/hg/hgTracks/variation.c +++ src/hg/hgTracks/variation.c @@ -1,26 +1,27 @@ /* variation.c - hgTracks routines that are specific to the tracks in * the variation group */ /* Copyright (C) 2014 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "variation.h" #include "imageV2.h" #include "bedCart.h" #include "bigBed.h" #include "bigDbSnp.h" +#include "bigWarn.h" #include "hvGfx.h" #include "soTerm.h" static double snp125AvHetCutoff = SNP125_DEFAULT_MIN_AVHET; static int snp125WeightCutoff = SNP125_DEFAULT_MAX_WEIGHT; static int snp132MinSubmitters = SNP132_DEFAULT_MIN_SUBMITTERS; static float snp132MinMinorAlFreq = SNP132_DEFAULT_MIN_MINOR_AL_FREQ; static float snp132MaxMinorAlFreq = SNP132_DEFAULT_MAX_MINOR_AL_FREQ; static int snp132MinAlFreq2N = SNP132_DEFAULT_MIN_AL_FREQ_2N; // Globals for caching cart coloring and filtering settings for snp125+ tracks: static enum snp125ColorSource snp125ColorSource = SNP125_DEFAULT_COLOR_SOURCE; static enum snp125Color *snp125LocTypeCart = NULL; static enum snp125Color *snp125ClassCart = NULL; static enum snp125Color *snp125MolTypeCart = NULL; @@ -2529,39 +2530,39 @@ tg->itemNameColor = delConrad2ItemColor; } void delMccarrollMethods(struct track *tg) { tg->itemColor = delMccarrollItemColor; tg->itemNameColor = delMccarrollItemColor; } void delHindsMethods(struct track *tg) { tg->itemColor = delHindsItemColor; tg->itemNameColor = delHindsItemColor; } -// Functional impact coloring scheme with lf->filterColor values (hex RGB) -#define bigDbSnpColorCodingChange 0x00ff0000 -#define bigDbSnpColorSyn 0x0000ff00 -#define bigDbSnpColorUtrNc 0x000000ff +// Functional impact coloring scheme with lf->filterColor values +#define bigDbSnpColorCodingChange MG_RED +#define bigDbSnpColorSyn MG_GREEN +#define bigDbSnpColorUtrNc MG_BLUE -static int lfColorFromSoTerm(enum soTerm term) -/* Assign a lf->filterColor value (hex RGB) according to soTerm. */ +static Color lfColorFromSoTerm(enum soTerm term) +/* Assign a Color according to soTerm. */ { -int color = 0; +Color color = MG_BLACK; switch (term) { case frameshift_variant: case frameshift: case initiator_codon_variant: case stop_gained: case stop_lost: case splice_acceptor_variant: case splice_donor_variant: case inframe_indel: case inframe_insertion: case inframe_deletion: case missense_variant: case terminator_codon_variant: color = bigDbSnpColorCodingChange; @@ -2803,31 +2804,30 @@ bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, ArraySize(bedRow)); if (bigBedFilterInterval(bedRow, filters)) { struct bigDbSnp *bds = bigDbSnpLoad(bedRow); double minMaf = cartUsualDoubleClosestToHome(cart, tdb, FALSE, "minMaf", 0.0); if (! filterMaf(bds, freqSourceIx, minMaf)) return NULL; AllocVar(lf); lf->name = cloneString(bds->name); AllocVar(lf->components); lf->start = lf->components->start = bds->chromStart; lf->tallStart = lf->start + bds->shiftBases; lf->tallEnd = lf ->end = lf->components->end = bds->chromEnd; lf->label = bdsLabel(tdb, bds); lf->mouseOver = bdsMouseOver(bds); - lf->extra = (void *)USE_ITEM_RGB; /* signal for coloring */ lf->filterColor = lfColorFromSoTerm(bds->maxFuncImpact); lf->original = bds; // MNVs in dbSNP are usually linked SNVs; if so, use one sf component for each SNV. if (bds->class == bigDbSnpMnv && bds->chromEnd - bds->chromStart > 2) { paranoidCheckMnvLengths(bds); int len = bds->chromEnd - bds->chromStart; struct simpleFeature *sf = lf->components, *sfList = NULL; int i; for (i = 0; i < len; i++) { if (alleleBasesMatch(bds, i)) { // If in a block, end the block. if (sf != NULL) @@ -2871,35 +2871,50 @@ } return minMaf; } static void bigDbSnpLoadItems(struct track *tg) /* Convert bigDbSnp items in window to linkedFeatures. */ { struct linkedFeatures *lfList = NULL; double minMaf = getMinMaf(tg->tdb); // If minMaf is 0, there's no need to filter so set freqSourceIx to -1. int freqSourceIx = (minMaf == 0.0) ? -1 : getFreqSourceIx(tg->tdb); char *maxItemStr = trackDbSetting(tg->tdb, "maxItems"); int maxItems = isNotEmpty(maxItemStr) ? atoi(maxItemStr) : 250000; bigBedAddLinkedFeaturesFromExt(tg, chromName, winStart, winEnd, freqSourceIx, 0, FALSE, 4, &lfList, maxItems); -slReverse(&lfList); -slSort(&lfList, linkedFeaturesCmp); +// if the summary is filled in then the number of items in the region is greater than maxItems. +if (tg->summary != NULL) + { + // too many items to display + tg->drawItems = bigDrawWarning; + tg->networkErrMsg = "Too many variants in display (zoom in to see details)"; + tg->totalHeight = bigWarnTotalHeight; + tg->items = NULL; + } +else tg->items = lfList; } +static Color bigDbSnpColor(struct track *tg, void *item, struct hvGfx *hvg) +/* Return color stashed away in lf->filterColor. */ +{ +struct linkedFeatures *lf = (struct linkedFeatures *)item; +return lf->filterColor; +} + static boolean bdsIsIndel(struct bigDbSnp *bds, int *retMinAltLen, int *retMaxAltLen) /* Set *ret{Min,Max}AltLen to the {least,greatest} alt allele length. * Return TRUE if any alt is shorter or longer than ref. */ { int refLen = strlen(bds->ref); int minAltLen = refLen, maxAltLen = refLen; int i; for (i = 0; i < bds->altCount; i++) { int altLen = strlen(bds->alts[i]); if (altLen < minAltLen) minAltLen = altLen; if (altLen > maxAltLen) maxAltLen = altLen; } @@ -2990,24 +3005,58 @@ // If I don't subtract 1 from x2, then it sticks out past the end of the last block when // zoomed in so much that each base is multiple pixels. x2--; int midY = y + (tg->heightPer>>1); int w = x2-x1; if (w > 0) hvGfxLine(hvg, x1, midY, x2, midY, color); } for (sf = lf->components; sf != NULL; sf = sf->next) { drawScaledBox(hvg, sf->start, sf->end, scale, xOff, y, heightPer, color); } } } +static int lfColorCmp(const void *va, const void *vb) +/* Compare lf->filterColors to sort based on color -- black first, red last */ +{ +const struct linkedFeatures *a = *((struct linkedFeatures **)va); +const struct linkedFeatures *b = *((struct linkedFeatures **)vb); +const Color ca = (Color)(a->filterColor); +const Color cb = (Color)(b->filterColor); + +return snp125ColorCmpRaw(ca, a->name, cb, b->name); +} + +void bigDbSnpDraw(struct track *tg, int seqStart, int seqEnd, + struct hvGfx *hvg, int xOff, int yOff, int width, + MgFont *font, Color color, enum trackVisibility vis) +/* Draw linked features items. */ +{ +if (vis == tvDense || + (tg->limitedVisSet && tg->limitedVis == tvDense)) + { + // Sort so that items with the strongest colors appear on top. + slSort(&tg->items, lfColorCmp); + } +else + { + // Sort by position as usual + slReverse(&tg->items); + slSort(&tg->items, linkedFeaturesCmp); + } +genericDrawItems(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); +} + void bigDbSnpMethods(struct track *track) /* Special load and draw hooks for type bigDbSnp. */ { linkedFeaturesMethods(track); track->canPack = TRUE; track->loadItems = bigDbSnpLoadItems; +track->drawItems = bigDbSnpDraw; track->drawItemAt = bigDbSnpDrawItemAt; +track->itemColor = bigDbSnpColor; +track->itemNameColor = bigDbSnpColor; track->itemName = bigLfItemName; }