ff70fc9c934dd856c7ba5c723f2cdcc3568ad09e
braney
  Mon Nov 3 15:20:19 2025 -0800
one path for bigBed, bigPs, bigGenePred, bigDbSNp.  refs #19984

diff --git src/hg/hgTracks/bigBedTrack.c src/hg/hgTracks/bigBedTrack.c
index 4927afdc448..eb89704d949 100644
--- src/hg/hgTracks/bigBedTrack.c
+++ src/hg/hgTracks/bigBedTrack.c
@@ -694,30 +694,35 @@
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
     bbi = fetchBbiForTrack(track);
     }
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     {
     track->networkErrMsg = cloneString(errCatch->message->string);
     track->drawItems = bigDrawWarning;
     track->totalHeight = bigWarnTotalHeight;
     return;
     }
 errCatchFree(&errCatch);
 
+boolean bigBedOnePath = cfgOptionBooleanDefault("bigBedOnePath", FALSE);
+if (bigBedOnePath )
+    // always use the definedFieldCount as gospel
+    track->bedSize = fieldCount = bbi->definedFieldCount;
+
 struct bigBedInterval *bb, *bbList; 
 char *quickLiftFile = cloneString(trackDbSetting(track->tdb, "quickLiftUrl"));
 struct hash *chainHash = NULL;
 if (quickLiftFile)
     bbList = quickLiftGetIntervals(quickLiftFile, bbi, chromName, winStart, winEnd, &chainHash);
 else
     bbList = bigBedSelectRangeExt(track, chrom, start, end, lm, maxItems);
 
 char *squishField = cartOrTdbString(cart, track->tdb, "squishyPackField", NULL);
 int squishFieldIdx = bbExtraFieldIndex(bbi, squishField);
 
 int seqTypeField =  0;
 if (sameString(track->tdb->type, "bigPsl"))
     {
     seqTypeField =  bbExtraFieldIndex(bbi, "seqType");
@@ -879,30 +884,31 @@
         // bedRow[5] has original strand in it, bedCopy has new strand.  If they're different we want to reverse exonFrames
         boolean changedStrand = FALSE;
         if (quickLiftFile)
             {
             if (*bedRow[5] != *bedCopy->strand)
                 changedStrand = TRUE;
             }
         lf->original = genePredFromBedBigGenePred(chromName, bedCopy, bb, changedStrand); 
         }
 
     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);
+        if (bbCopy->rest)
             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);
     }
 
@@ -1023,52 +1029,77 @@
     {
     bbi = fetchBbiForTrack(track);
     }
 errCatchEnd(errCatch);
 
 if (bbi)
     return bbi->definedFieldCount;
 
 return 3; // if we can't get the bbi, use the minimum
 }
 #endif
 
 void commonBigBedMethods(struct track *track, struct trackDb *tdb, 
                                 int wordCount, char *words[])
 /* Set up common bigBed methods used by several track types that depend on the bigBed format. */
+{
+boolean bigBedOnePath = cfgOptionBooleanDefault("bigBedOnePath", FALSE);
+
+if (bigBedOnePath)
+    {
+    track->isBigBed = TRUE;
+    linkedFeaturesMethods(track);
+    track->extraUiData = newBedUiData(track->track);
+    track->loadItems = loadGappedBed;
+
+    // make sure that hgTracks completely ignore the items following "bigBed" in the type line
+    char *type = cloneString(tdb->type);
+    char *space = strchr(type, ' ');
+    if (space)
+        *space = 0;
+    tdb->type = type;
+
+    if (trackDbSetting(tdb, "colorByStrand"))
+        {
+        Color lfItemColorByStrand(struct track *tg, void *item, struct hvGfx *hvg);
+        track->itemColor = lfItemColorByStrand;
+        }
+    }
+else 
     {
     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);
+    }
 track->loadSummary = loadBigBedSummary;
 }
 
 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);
     }
 }