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);
+    }
+}