void bigBedAddLinkedFeaturesFrom(struct track *track, char *chrom, int start, int end, int scoreMin, int scoreMax, boolean useItemRgb, int fieldCount, struct linkedFeatures **pLfList) /* Read in items in chrom:start-end from bigBed file named in track->bbiFileName, convert * them to linkedFeatures, and add to head of list. */ { struct lm *lm = lmInit(0); struct trackDb *tdb = track->tdb; struct bigBedInterval *bb, *bbList = bigBedSelectRange(track, chrom, start, end, lm); char *bedRow[32]; char startBuf[16], endBuf[16]; char *scoreFilter = cartOrTdbString(cart, track->tdb, "scoreFilter", NULL); char *mouseOverField = cartOrTdbString(cart, track->tdb, "mouseOverField", NULL); int minScore = 0; if (scoreFilter) minScore = atoi(scoreFilter); int mouseOverIdx = bbExtraFieldIndex(tdb, mouseOverField); for (bb = bbList; bb != NULL; bb = bb->next) { char* mouseOver = restField(bb, mouseOverIdx); bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, ArraySize(bedRow)); struct bed *bed = bedLoadN(bedRow, fieldCount); struct linkedFeatures *lf = bedMungToLinkedFeatures(&bed, tdb, fieldCount, scoreMin, scoreMax, useItemRgb); if (scoreFilter == NULL || lf->score >= minScore) slAddHead(pLfList, lf); lf->mouseOver = mouseOver; // leaks some memory, cloneString handles NULL ifself if (sameString(track->tdb->type, "bigGenePred")) lf->original = genePredFromBigGenePred(chromName, bb); } lmCleanup(&lm); }
void bamMethods(struct track *track) /* Methods for BAM alignment files. */ { knetUdcInstall(); boolean isBamWig = cartUsualBooleanClosestToHome(cart, track->tdb, FALSE, BAMWIG_MODE, (trackDbSettingClosestToHome(track->tdb, BAMWIG_MODE) != NULL)); if (isBamWig) { bamWigMethods(track, track->tdb, 0, NULL); return; } track->canPack = TRUE; boolean isPaired = cartUsualBooleanClosestToHome(cart, track->tdb, FALSE, BAM_PAIR_ENDS_BY_NAME, (trackDbSettingClosestToHome(track->tdb, BAM_PAIR_ENDS_BY_NAME) != NULL)); char *tdbShowNames = trackDbSetting(track->tdb, BAM_SHOW_NAMES); boolean showNames = cartUsualBooleanClosestToHome(cart, track->tdb, FALSE, BAM_SHOW_NAMES, SETTING_IS_ON(tdbShowNames)); char *colorMode = cartOrTdbString(cart, track->tdb, BAM_COLOR_MODE, BAM_COLOR_MODE_DEFAULT); char *userTag = cartOrTdbString(cart, track->tdb, BAM_COLOR_TAG, BAM_COLOR_TAG_DEFAULT); if (sameString(colorMode, BAM_COLOR_MODE_TAG) && userTag != NULL) { if (! (isalpha(userTag[0]) && isalnum(userTag[1]) && userTag[2] == '\0')) { warn("%s: BAM tag '%s' is not valid -- must be a letter followed by a letter or number.", track->tdb->shortLabel, htmlEncode(userTag)); cartRemoveVariableClosestToHome(cart, track->tdb, FALSE, BAM_COLOR_TAG); } } addBamBaseAndIndelSettings(track->tdb); if (isPaired) { linkedFeaturesSeriesMethods(track); track->loadItems = bamPairedLoadItems; track->drawItems = bamLinkedFeaturesSeriesDraw; track->drawItemAt = bamPairedDrawAt; } else { linkedFeaturesMethods(track); track->loadItems = bamLoadItems; track->drawItems = bamLinkedFeaturesDraw; track->drawItemAt = bamDrawAt; } if (!showNames) { track->drawName = TRUE; // ironic, but this is how to suppress item labels in pack mode. track->drawLeftLabels = maybeDrawLeftLabels; } track->nextItemButtonable = track->nextExonButtonable = FALSE; track->nextPrevItem = NULL; track->nextPrevExon = NULL; if (sameString(colorMode, BAM_COLOR_MODE_GRAY)) track->colorShades = shadesOfGray; }
static int multiWigTotalHeight(struct track *tg, enum trackVisibility vis) /* Return total height of multiWigcontainer. */ { char *aggregate = cartOrTdbString(cart, tg->tdb, "aggregate", NULL); boolean overlay = isOverlayTypeAggregate(aggregate); int totalHeight = 0; if (overlay) totalHeight = wigTotalHeight(tg, vis); struct track *subtrack; for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { if (isSubtrackVisible(subtrack)) { // Logic is slightly complicated by fact we want to call the totalHeight // method for each subtrack even if in overlay mode. int oneHeight = subtrack->totalHeight(subtrack, vis); if (!overlay) { if (totalHeight != 0) totalHeight += 1; totalHeight += oneHeight; } } } tg->height = totalHeight; return totalHeight; }
static void multiWigDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw items in multiWig container. */ { struct track *subtrack; char *aggregate = cartOrTdbString(cart, tg->tdb, "aggregate", NULL); boolean overlay = isOverlayTypeAggregate(aggregate); int y = yOff; for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { if (isSubtrackVisible(subtrack)) { int height = subtrack->totalHeight(subtrack, vis); hvGfxSetClip(hvg, xOff, y, width, height); if (sameString(WIG_AGGREGATE_TRANSPARENT, aggregate)) hvGfxSetWriteMode(hvg, MG_WRITE_MODE_MULTIPLY); if (overlay) subtrack->lineHeight = tg->lineHeight; subtrack->drawItems(subtrack, seqStart, seqEnd, hvg, xOff, y, width, font, color, vis); if (!overlay) y += height + 1; hvGfxSetWriteMode(hvg, MG_WRITE_MODE_NORMAL); hvGfxUnclip(hvg); } } char *url = trackUrl(tg->track, chromName); //fprintf(stderr, "mapBoxHgcOrHgGene(id: %s;) in multiWigDraw\n", // tg->track); mapBoxHgcOrHgGene(hvg, seqStart, seqEnd, xOff, y, width, tg->height, tg->track, tg->track, NULL, url, TRUE, NULL); }
static enum hapColorMode getColorMode(struct trackDb *tdb) /* Get the hap-cluster coloring mode from cart & tdb. */ { enum hapColorMode colorMode = altOnlyMode; char *colorBy = cartOrTdbString(cart, tdb, VCF_HAP_COLORBY_VAR, VCF_DEFAULT_HAP_COLORBY); if (sameString(colorBy, VCF_HAP_COLORBY_ALTONLY)) colorMode = altOnlyMode; else if (sameString(colorBy, VCF_HAP_COLORBY_REFALT)) colorMode = refAltMode; else if (sameString(colorBy, VCF_HAP_COLORBY_BASE)) colorMode = baseMode; return colorMode; }
static void colorByCfg(struct cart *cart, struct trackDb *tdb, char *name, boolean parentLevel) { char *colorBy = cartOrTdbString(cart, tdb, SNAKE_COLOR_BY, SNAKE_DEFAULT_COLOR_BY); printf("<B>Block coloring method:</B>\n"); char varName[1024]; safef(varName, sizeof(varName), "%s." SNAKE_COLOR_BY, name); cgiMakeDropListFull(varName, colorByOptionLabels, colorByOptionValues, ArraySize(colorByOptionLabels), colorBy, NULL); puts("<BR>"); }
static void multiWigLeftLabels(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, int height, boolean withCenterLabels, MgFont *font, Color color, enum trackVisibility vis) /* Draw left labels - by deferring to first subtrack. */ { char *aggregate = cartOrTdbString(cart, tg->tdb, "aggregate", NULL); boolean overlay = isOverlayTypeAggregate(aggregate); if (overlay) { struct track *firstVisibleSubtrack = NULL; boolean showNumbers = graphLimitsAllSame(tg->subtracks, &firstVisibleSubtrack); struct track *subtrack = (showNumbers ? firstVisibleSubtrack : tg->subtracks); wigLeftAxisLabels(tg, seqStart, seqEnd, hvg, xOff, yOff, width, height, withCenterLabels, font, color, vis, tg->shortLabel, subtrack->graphUpperLimit, subtrack->graphLowerLimit, showNumbers); } else { struct track *subtrack; int y = yOff; if (withCenterLabels) y += tl.fontHeight+1; for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { if (isSubtrackVisible(subtrack)) { int height = subtrack->totalHeight(subtrack, vis); wigLeftAxisLabels(subtrack, seqStart, seqEnd, hvg, xOff, y, width, height, withCenterLabels, font, subtrack->ixColor, vis, subtrack->shortLabel, subtrack->graphUpperLimit, subtrack->graphLowerLimit, TRUE); y += height+1; } } } }
static void bigBedClick(char *fileName, struct trackDb *tdb, char *item, int start, int end, int bedSize) /* Handle click in generic bigBed track. */ { boolean showUrl = FALSE; char *chrom = cartString(cart, "c"); /* Open BigWig file and get interval list. */ struct bbiFile *bbi = bigBedFileOpen(fileName); struct lm *lm = lmInit(0); int ivStart = start, ivEnd = end; if (start == end) { // item is an insertion; expand the search range from 0 bases to 2 so we catch it: ivStart = max(0, start-1); ivEnd++; } struct bigBedInterval *bbList = bigBedIntervalQuery(bbi, chrom, ivStart, ivEnd, 0, lm); /* Get bedSize if it's not already defined. */ if (bedSize == 0) { bedSize = bbi->definedFieldCount; showUrl = TRUE; } char *scoreFilter = cartOrTdbString(cart, tdb, "scoreFilter", NULL); int minScore = 0; if (scoreFilter) minScore = atoi(scoreFilter); /* Find particular item in list - matching start, and item if possible. */ boolean found = FALSE; boolean firstTime = TRUE; struct bigBedInterval *bb; for (bb = bbList; bb != NULL; bb = bb->next) { if (!(bb->start == start && bb->end == end)) continue; if (bedSize > 3) { char *name = cloneFirstWordByTab(bb->rest); boolean match = sameString(name, item); freez(&name); if (!match) continue; } found = TRUE; if (firstTime) printf("<BR>\n"); int seq1Seq2Fields = 0; // check for seq1 and seq2 in columns 7+8 (eg, pairedTagAlign) boolean seq1Seq2 = sameOk(trackDbSetting(tdb, BASE_COLOR_USE_SEQUENCE), "seq1Seq2"); if (seq1Seq2 && bedSize == 6) seq1Seq2Fields = 2; char *fields[bedSize+seq1Seq2Fields]; char startBuf[16], endBuf[16]; char *rest = cloneString(bb->rest); int bbFieldCount = bigBedIntervalToRow(bb, chrom, startBuf, endBuf, fields, bedSize+seq1Seq2Fields); if (bbFieldCount != bedSize+seq1Seq2Fields) { errAbort("Disagreement between trackDb field count (%d) and %s fieldCount (%d)", bedSize, fileName, bbFieldCount); } struct bed *bed = bedLoadN(fields, bedSize); if (bedSize >= 6 && scoreFilter && bed->score < minScore) continue; if (showUrl && (bedSize >= 4)) printCustomUrl(tdb, item, TRUE); bedPrintPos(bed, bedSize, tdb); // display seq1 and seq2 if (seq1Seq2 && bedSize+seq1Seq2Fields == 8) printf("<table><tr><th>Sequence 1</th><th>Sequence 2</th></tr>" "<tr><td> %s </td><td> %s </td></tr></table>", fields[6], fields[7]); else if (isNotEmpty(rest)) { char *restFields[256]; int restCount = chopTabs(rest, restFields); int restBedFields = bedSize - 3; if (restCount > restBedFields) { if (0 == extraFieldsPrint(tdb,NULL,restFields + restBedFields,restCount - restBedFields)) { int i; char label[20]; safef(label, sizeof(label), "nonBedFieldsLabel"); printf("<B>%s </B>", trackDbSettingOrDefault(tdb, label, "Non-BED fields:")); for (i = restBedFields; i < restCount; i++) printf("%s%s", (i > 0 ? "\t" : ""), restFields[i]); printf("<BR>\n"); } } } if (isCustomTrack(tdb->track)) { time_t timep = bbiUpdateTime(bbi); printBbiUpdateTime(&timep); } } if (!found) { printf("No item %s starting at %d\n", emptyForNull(item), start); } lmCleanup(&lm); bbiFileClose(&bbi); }
void loadSimpleBed(struct track *tg) /* Load the items in one track - just move beds in * window... */ { struct bed *(*loader)(char **row); struct bed *bed, *list = NULL; char **row; int rowOffset; char *words[3]; int wordCt; char query[128]; char *setting = NULL; bool doScoreCtFilter = FALSE; int scoreFilterCt = 0; char *topTable = NULL; if (tg->bedSize <= 3) loader = bedLoad3; else if (tg->bedSize == 4) loader = bedLoad; else if (tg->bedSize == 5) loader = bedLoad5; else loader = bedLoad6; // pairedTagAlign loader is required for base coloring using sequence from seq1 & seq2 // after removing optional bin column, this loader assumes seq1 and seq2 are in // row[6] and row[7] respectively of the sql result. if ((setting = trackDbSetting(tg->tdb, BASE_COLOR_USE_SEQUENCE)) && sameString(setting, "seq1Seq2")) loader = bedLoadPairedTagAlign; /* limit to a specified count of top scoring items. * If this is selected, it overrides selecting item by specified score */ if ((setting = trackDbSettingClosestToHome(tg->tdb, "filterTopScorers")) != NULL) { wordCt = chopLine(cloneString(setting), words); if (wordCt >= 3) { doScoreCtFilter = cartUsualBooleanClosestToHome(cart, tg->tdb, FALSE, "filterTopScorersOn",sameString(words[0], "on")); scoreFilterCt = cartUsualIntClosestToHome(cart, tg->tdb, FALSE, "filterTopScorersCt", atoi(words[1])); topTable = words[2]; /* if there are not too many rows in the table then can define */ /* top table as the track or subtrack table */ if (sameWord(topTable, "self")) topTable = cloneString(tg->table); } } /* Get list of items */ if (tg->isBigBed) { // avoid opening an unneeded db connection for bigBed; required not to use mysql for parallel fetch tracks char *scoreFilter = cartOrTdbString(cart, tg->tdb, "scoreFilter", NULL); struct lm *lm = lmInit(0); struct bigBedInterval *bb, *bbList = bigBedSelectRange(tg, chromName, winStart, winEnd, lm); char *bedRow[32]; char startBuf[16], endBuf[16]; int minScore = 0; if (scoreFilter) minScore = atoi(scoreFilter); for (bb = bbList; bb != NULL; bb = bb->next) { bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, ArraySize(bedRow)); bed = loader(bedRow); if (scoreFilter == NULL || bed->score >= minScore) slAddHead(&list, bed); } lmCleanup(&lm); } else { struct sqlConnection *conn = hAllocConnTrack(database, tg->tdb); struct sqlResult *sr = NULL; /* limit to items above a specified score */ char *scoreFilterClause = getScoreFilterClause(cart, tg->tdb,NULL); if (doScoreCtFilter && (topTable != NULL) && hTableExists(database, topTable)) { sqlSafef(query, sizeof(query),"select * from %s order by score desc limit %d", topTable, scoreFilterCt); sr = sqlGetResult(conn, query); rowOffset = hOffsetPastBin(database, hDefaultChrom(database), topTable); } else if(scoreFilterClause != NULL && tg->bedSize >= 5) { sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, scoreFilterClause, &rowOffset); } else { sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, NULL, &rowOffset); } freeMem(scoreFilterClause); while ((row = sqlNextRow(sr)) != NULL) { bed = loader(row+rowOffset); slAddHead(&list, bed); } sqlFreeResult(&sr); hFreeConn(&conn); } if (doScoreCtFilter) { /* filter out items not in this window */ struct bed *newList = bedFilterListInRange(list, NULL, chromName, winStart, winEnd); list = newList; } slReverse(&list); tg->items = list; }
void bamDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) /* Draw a single bam linkedFeatures item. Borrows a lot from linkedFeaturesDrawAt, * but cuts a lot of unneeded features (like coding region) and adds a couple * additional sources of color. */ { struct linkedFeatures *lf = item; struct simpleFeature *sf; int heightPer = tg->heightPer; int x1 = round((double)((int)lf->start-winStart)*scale) + xOff; int x2 = round((double)((int)lf->end-winStart)*scale) + xOff; int w = x2-x1; int midY = y + (heightPer>>1); char *exonArrowsDense = trackDbSettingClosestToHome(tg->tdb, "exonArrowsDense"); boolean exonArrowsEvenWhenDense = (exonArrowsDense != NULL && SETTING_IS_ON(exonArrowsDense)); boolean exonArrows = (tg->exonArrows && (vis != tvDense || exonArrowsEvenWhenDense)); struct dnaSeq *mrnaSeq = NULL; enum baseColorDrawOpt drawOpt = baseColorDrawOff; boolean indelShowDoubleInsert, indelShowQueryInsert, indelShowPolyA; struct psl *psl = (struct psl *)(lf->original); char *colorMode = cartOrTdbString(cart, tg->tdb, BAM_COLOR_MODE, BAM_COLOR_MODE_DEFAULT); char *grayMode = cartOrTdbString(cart, tg->tdb, BAM_GRAY_MODE, BAM_GRAY_MODE_DEFAULT); bool baseQualMode = (sameString(colorMode, BAM_COLOR_MODE_GRAY) && sameString(grayMode, BAM_GRAY_MODE_BASE_QUAL)); char *qSeq = lf->extra; if (vis != tvDense && isNotEmpty(qSeq) && !sameString(qSeq, "*")) { drawOpt = baseColorDrawSetup(hvg, tg, lf, &mrnaSeq, &psl); if (drawOpt > baseColorDrawOff) exonArrows = FALSE; } static Color darkBlueColor = 0; static Color darkRedColor = 0; if (darkRedColor == 0) { darkRedColor = hvGfxFindColorIx(hvg, 100,0,0); darkBlueColor = hvGfxFindColorIx(hvg, 0,0,100); } if (sameString(colorMode, BAM_COLOR_MODE_STRAND)) color = (lf->orientation < 0) ? darkRedColor : darkBlueColor; else if (lf->filterColor != 0) { // In bamTrack, lf->filterColor is an RGBA value color = lf->filterColor; } else if (tg->colorShades) color = tg->colorShades[lf->grayIx]; else color = tg->ixColor; indelEnabled(cart, tg->tdb, basesPerPixel, &indelShowDoubleInsert, &indelShowQueryInsert, &indelShowPolyA); if (!indelShowDoubleInsert) innerLine(hvg, x1, midY, w, color); for (sf = lf->components; sf != NULL; sf = sf->next) { int s = sf->start, e = sf->end; if (e <= s || e < winStart || s > winEnd) continue; if (baseQualMode) color = tg->colorShades[sf->grayIx]; baseColorDrawItem(tg, lf, sf->grayIx, hvg, xOff, y, scale, font, s, e, heightPer, zoomedToCodonLevel, mrnaSeq, sf, psl, drawOpt, MAXPIXELS, winStart, color); if (tg->exonArrowsAlways || (exonArrows && (sf->start <= winStart || sf->start == lf->start) && (sf->end >= winEnd || sf->end == lf->end))) { Color barbColor = hvGfxContrastingColor(hvg, color); x1 = round((double)((int)s-winStart)*scale) + xOff; x2 = round((double)((int)e-winStart)*scale) + xOff; w = x2-x1; clippedBarbs(hvg, x1+1, midY, x2-x1-2, tl.barbHeight, tl.barbSpacing, lf->orientation, barbColor, TRUE); } } if (indelShowDoubleInsert && psl) { int intronGap = 0; if (vis != tvDense) intronGap = atoi(trackDbSettingClosestToHomeOrDefault(tg->tdb, "intronGap", "0")); lfDrawSpecialGaps(lf, intronGap, TRUE, 0, tg, hvg, xOff, y, scale, color, color, vis); } if (vis != tvDense) { /* If highlighting differences between aligned sequence and genome when * zoomed way out, this must be done in a separate pass after exons are * drawn so that exons sharing the pixel don't overdraw differences. */ if ((indelShowQueryInsert || indelShowPolyA) && psl) baseColorOverdrawQInsert(tg, lf, hvg, xOff, y, scale, heightPer, mrnaSeq, psl, winStart, drawOpt, indelShowQueryInsert, indelShowPolyA); baseColorOverdrawDiff(tg, lf, hvg, xOff, y, scale, heightPer, mrnaSeq, psl, winStart, drawOpt); baseColorDrawCleanup(lf, &mrnaSeq, &psl); } }
void bamLoadItemsCore(struct track *tg, boolean isPaired) /* Load BAM data into tg->items item list, unless zoomed out so far * that the data would just end up in dense mode and be super-slow. */ { /* protect against temporary network error */ struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { struct hash *pairHash = isPaired ? hashNew(18) : NULL; int minAliQual = atoi(cartOrTdbString(cart, tg->tdb, BAM_MIN_ALI_QUAL, BAM_MIN_ALI_QUAL_DEFAULT)); char *colorMode = cartOrTdbString(cart, tg->tdb, BAM_COLOR_MODE, BAM_COLOR_MODE_DEFAULT); char *grayMode = cartOrTdbString(cart, tg->tdb, BAM_GRAY_MODE, BAM_GRAY_MODE_DEFAULT); char *userTag = cartOrTdbString(cart, tg->tdb, BAM_COLOR_TAG, BAM_COLOR_TAG_DEFAULT); int aliQualShadeMin = 0, aliQualShadeMax = 99, baseQualShadeMin = 0, baseQualShadeMax = 40; parseIntRangeSetting(tg->tdb, "aliQualRange", &aliQualShadeMin, &aliQualShadeMax); parseIntRangeSetting(tg->tdb, "baseQualRange", &baseQualShadeMin, &baseQualShadeMax); struct bamTrackData btd = {tg, pairHash, minAliQual, colorMode, grayMode, userTag, aliQualShadeMin, aliQualShadeMax, baseQualShadeMin, baseQualShadeMax}; char *fileName = trackDbSetting(tg->tdb, "bigDataUrl"); if (fileName == NULL) { if (tg->customPt) { errAbort("bamLoadItemsCore: can't find bigDataUrl for custom track %s", tg->track); } else { struct sqlConnection *conn = hAllocConnTrack(database, tg->tdb); fileName = bamFileNameFromTable(conn, tg->table, chromName); hFreeConn(&conn); } } char *fileName2 = hReplaceGbdb(fileName); char posForBam[512]; safef(posForBam, sizeof(posForBam), "%s:%d-%d", chromName, winStart, winEnd); char *cacheDir = cfgOption("cramRef"); char *refUrl = trackDbSetting(tg->tdb, "refUrl"); if (!isPaired) bamFetchPlus(fileName2, posForBam, addBam, &btd, NULL, refUrl, cacheDir); else { char *setting = trackDbSettingClosestToHomeOrDefault(tg->tdb, "pairSearchRange", "20000"); int pairSearchRange = atoi(setting); if (pairSearchRange > 0) safef(posForBam, sizeof(posForBam), "%s:%d-%d", chromName, max(0, winStart-pairSearchRange), winEnd+pairSearchRange); bamFetchPlus(fileName2, posForBam, addBamPaired, &btd, NULL, refUrl, cacheDir); struct hashEl *hel; struct hashCookie cookie = hashFirst(btd.pairHash); while ((hel = hashNext(&cookie)) != NULL) { struct linkedFeatures *lf = hel->val; if (lf->start < winEnd && lf->end > winStart) slAddHead(&(tg->items), lfsFromLf(lf)); } } freez(&fileName2); if (tg->visibility != tvDense) { slReverse(&(tg->items)); if (isPaired) slSort(&(tg->items), linkedFeaturesSeriesCmp); else if (sameString(colorMode, BAM_COLOR_MODE_STRAND)) slSort(&(tg->items), linkedFeaturesCmpOri); else if (sameString(colorMode, BAM_COLOR_MODE_GRAY) && sameString(grayMode, BAM_GRAY_MODE_ALI_QUAL)) slSort(&(tg->items), linkedFeaturesCmpScore); else slSort(&(tg->items), linkedFeaturesCmpStart); if (slCount(tg->items) > MAX_ITEMS_FOR_MAPBOX) { // flag drawItems to make a mapBox for the whole track tg->customInt = 1; tg->mapItem = dontMapItem; } } } errCatchEnd(errCatch); if (errCatch->gotError) { tg->networkErrMsg = cloneString(errCatch->message->string); tg->drawItems = bigDrawWarning; tg->totalHeight = bigWarnTotalHeight; } errCatchFree(&errCatch); }
static void vcfHapClusterDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Split samples' chromosomes (haplotypes), cluster them by center-weighted * alpha similarity, and draw in the order determined by clustering. */ { struct vcfFile *vcff = tg->extraUiData; if (vcff->records == NULL) return; purple = hvGfxFindColorIx(hvg, 0x99, 0x00, 0xcc); undefYellow = hvGfxFindRgb(hvg, &undefinedYellowColor); enum hapColorMode colorMode = getColorMode(tg->tdb); pushWarnHandler(ignoreEm); struct vcfRecord *rec; for (rec = vcff->records; rec != NULL; rec = rec->next) vcfParseGenotypes(rec); popWarnHandler(); unsigned short gtHapCount = 0; int nRecords = slCount(vcff->records); int centerIx = getCenterVariantIx(tg, seqStart, seqEnd, vcff->records); // Limit the number of variants that we compare, to keep from timing out: // (really what we should limit is the number of distinct haplo's passed to hacTree!) // In the meantime, this should at least be a cart var... int maxVariantsPerSide = 50; int startIx = max(0, centerIx - maxVariantsPerSide); int endIx = min(nRecords, centerIx+1 + maxVariantsPerSide); struct hacTree *ht = NULL; unsigned short *gtHapOrder = clusterHaps(vcff, centerIx, startIx, endIx, >HapCount, &ht); struct vcfRecord *centerRec = NULL; int ix; // Unlike drawing order (last drawn is on top), the first mapBox gets priority, // so map center variant before drawing & mapping other variants! for (rec = vcff->records, ix=0; rec != NULL; rec = rec->next, ix++) { if (ix == centerIx) { centerRec = rec; mapBoxForCenterVariant(rec, hvg, tg, xOff, yOff, width); break; } } for (rec = vcff->records, ix=0; rec != NULL; rec = rec->next, ix++) { boolean isClustered = (ix >= startIx && ix < endIx); if (ix != centerIx) drawOneRec(rec, gtHapOrder, gtHapCount, tg, hvg, xOff, yOff, width, isClustered, FALSE, colorMode); } // Draw the center rec on top, outlined with black lines, to make sure it is very visible: drawOneRec(centerRec, gtHapOrder, gtHapCount, tg, hvg, xOff, yOff, width, TRUE, TRUE, colorMode); // Draw as much of the tree as can fit in the left label area: int extraPixel = (colorMode == altOnlyMode) ? 1 : 0; int hapHeight = tg->height- CLIP_PAD - 2*extraPixel; struct yFromNodeHelper yHelper = {0, NULL, NULL}; initYFromNodeHelper(&yHelper, yOff+extraPixel, hapHeight, gtHapCount, gtHapOrder, vcff->genotypeCount); struct titleHelper titleHelper = { NULL, 0, 0, 0, 0, NULL, NULL }; initTitleHelper(&titleHelper, tg->track, startIx, centerIx, endIx, nRecords, vcff); char *treeAngle = cartOrTdbString(cart, tg->tdb, VCF_HAP_TREEANGLE_VAR, VCF_DEFAULT_HAP_TREEANGLE); boolean drawRectangle = sameString(treeAngle, VCF_HAP_TREEANGLE_RECTANGLE); drawTreeInLabelArea(ht, hvg, yOff+extraPixel, hapHeight+CLIP_PAD, &yHelper, &titleHelper, drawRectangle); }