ba5f4c097ecdf323f94adab36f4cf52f7f59e8cf jcasper Mon Mar 3 09:47:13 2025 -0800 Initial commit of heatmap code for bigBeds, still plenty to do, refs #31812 diff --git src/hg/hgTracks/bigBedTrack.c src/hg/hgTracks/bigBedTrack.c index 8f6eec78be5..c28a2322e19 100644 --- src/hg/hgTracks/bigBedTrack.c +++ src/hg/hgTracks/bigBedTrack.c @@ -18,30 +18,31 @@ #include "bbiFile.h" #include "obscure.h" #include "bigWig.h" #include "bigBed.h" #include "bigWarn.h" #include "errCatch.h" #include "trackHub.h" #include "net.h" #include "bigPsl.h" #include "bigBedFilter.h" #include "bigBedLabel.h" #include "variation.h" #include "chromAlias.h" #include "quickLift.h" #include "hgConfig.h" +#include "heatmap.h" static unsigned getFieldNum(struct bbiFile *bbi, char *field) // get field number for field name in bigBed. errAbort if field not found. { int fieldNum = bbFieldIndex(bbi, field); if (fieldNum < 0) fieldNum = defaultFieldLocation(field); if (fieldNum < 0) errAbort("error building filter with field %s. Field not found.", field); return fieldNum; } struct bigBedFilter *bigBedMakeNumberFilter(struct cart *cart, struct bbiFile *bbi, struct trackDb *tdb, char *filter, char *defaultLimits, char *field, boolean isHighlight) /* Make a filter/highlight on this column if the trackDb or cart wants us to. */ @@ -777,30 +778,40 @@ } if (lf == NULL) { filtered++; continue; } if (lf->label == NULL) lf->label = bigBedMakeLabel(track->tdb, track->labelColumns, bb, chromName); if (startsWith("bigGenePred", track->tdb->type) || startsWith("genePred", track->tdb->type)) { lf->original = genePredFromBedBigGenePred(chromName, bedCopy, bb); } + if (startsWith("bigBed", track->tdb->type)) + { + // Clone bb so that we'll have access the to extra fields contents. This is used in + // alternate display modes for bigBeds (so far just "heatmap", but more are likely to come). + struct bigBedInterval *bbCopy = CloneVar(bb); + bbCopy->rest = cloneMem(bbCopy->rest, strlen(bbCopy->rest)+1); + bbCopy->next = NULL; + lf->original = bbCopy; + } + if (lf->mouseOver == NULL) { if (mouseOverIdx > 0) lf->mouseOver = restField(bb, mouseOverIdx); else if (mouseOverPattern) lf->mouseOver = replaceFieldInPattern(mouseOverPattern, bbi->fieldCount, fieldNames, bedRow); } slAddHead(pLfList, lf); } if (filtered) labelTrackAsFilteredNumber(track, filtered); if (doWindowSizeFilter) // add the number of merged items to the track longLabel @@ -912,41 +923,54 @@ struct bbiFile *bbi = NULL; struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { bbi = fetchBbiForTrack(track); } errCatchEnd(errCatch); if (bbi) return bbi->definedFieldCount; return 3; // if we can't get the bbi, use the minimum } #endif -void bigBedMethods(struct track *track, struct trackDb *tdb, +void commonBigBedMethods(struct track *track, struct trackDb *tdb, int wordCount, char *words[]) -/* Set up bigBed methods. */ +/* Set up common bigBed methods used by several track types that depend on the bigBed format. */ { char *newWords[wordCount]; int ii; for(ii=0; ii < wordCount; ii++) newWords[ii] = words[ii]; #ifdef NOTNOW // let's help the user out and get the definedFieldCount if they didn't specify it on the type line if (!tdbIsSuper(track->tdb) && (track->tdb->subtracks == NULL) && (wordCount == 1) && sameString(words[0], "bigBed")) { int fieldCount = getFieldCount(track); if (fieldCount > 3) { char buffer[1024]; safef(buffer, sizeof buffer, "%d", fieldCount); newWords[1] = cloneString(buffer); wordCount = 2; } } #endif complexBedMethods(track, tdb, TRUE, wordCount, newWords); } + +void bigBedMethods(struct track *track, struct trackDb *tdb, + int wordCount, char *words[]) +/* Set up bigBed methods for tracks that are type bigBed. */ +{ +commonBigBedMethods(track, tdb, wordCount, words); +if (sameWordOk(trackDbSetting(tdb, "style"), "heatmap")) + { + // Might want to check here if required heatmap settings/fields are in place, + // maybe some combo of row count and labels. + heatmapMethods(track); + } +}