13b584581e6d7b1860e0cab97adc3594b1899308
braney
  Mon Aug 7 12:05:10 2023 -0700
add instaPort to bigBed support

diff --git src/hg/hgTracks/bigBedTrack.c src/hg/hgTracks/bigBedTrack.c
index a5d7c3b..8f1b6c4 100644
--- src/hg/hgTracks/bigBedTrack.c
+++ src/hg/hgTracks/bigBedTrack.c
@@ -16,30 +16,31 @@
 #include "localmem.h"
 #include "wigCommon.h"
 #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 "instaPort.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)
 /* Make a filter on this column if the trackDb or cart wants us to. */
@@ -408,31 +409,30 @@
 	    {
 	    char *denseCoverage = trackDbSettingClosestToHome(track->tdb, "denseCoverage");
 	    if (denseCoverage != NULL)
 		{
 		double endVal = atof(denseCoverage);
 		if (endVal <= 0)
 		    {
 		    AllocVar(track->sumAll);
 		    *track->sumAll = bbiTotalSummary(bbi);
 		    }
 		}
 	    }
 	else
 	    freez(&track->summary);
 	}
-    bbiFileClose(&bbi);
     track->bbiFile = NULL;
     }
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     {
     track->networkErrMsg = cloneString(errCatch->message->string);
     track->drawItems = bigDrawWarning;
     track->totalHeight = bigWarnTotalHeight;
     result = NULL;
     }
 errCatchFree(&errCatch);
 
 return result;
 }
 
@@ -449,31 +449,30 @@
 if (fieldIdx < restCount)
     field = cloneString(restFields[fieldIdx]);
 freeMem(rest);
 return field;
 }
 
 
 void bigBedAddLinkedFeaturesFromExt(struct track *track,
 	char *chrom, int start, int end, int scoreMin, int scoreMax, boolean useItemRgb,
 	int fieldCount, struct linkedFeatures **pLfList, int maxItems)
 /* 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 = bigBedSelectRangeExt(track, chrom, start, end, lm, maxItems);
 char *mouseOverField = cartOrTdbString(cart, track->tdb, "mouseOverField", NULL);
 
 // check if this track can merge large items, this setting must be allowed in the trackDb
 // stanza for the track, but can be enabled/disabled via trackUi/right click menu so
 // we also need to check the cart for the current status
 int mergeCount = 0;
 boolean doWindowSizeFilter = trackDbSettingOn(track->tdb, MERGESPAN_TDB_SETTING);
 if (doWindowSizeFilter)
     {
     char hasMergedItemsSetting[256];
     safef(hasMergedItemsSetting, sizeof(hasMergedItemsSetting), "%s.%s", track->track, MERGESPAN_CART_SETTING);
     if (cartVarExists(cart, hasMergedItemsSetting))
         doWindowSizeFilter = cartInt(cart, hasMergedItemsSetting) == 1;
     else // save the cart var so javascript can offer the right toggle
         cartSetInt(cart, hasMergedItemsSetting, 1);
@@ -483,30 +482,38 @@
 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);
 
+struct bigBedInterval *bb, *bbList; 
+char *instaFile = cloneString(trackDbSetting(track->tdb, "instaPortUrl"));
+struct hash *chainHash = NULL;
+if (instaFile)
+    bbList = instaIntervals(instaFile, 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");
     }
 
 int mouseOverIdx = bbExtraFieldIndex(bbi, mouseOverField);
 
 track->bbiFile = NULL;
 
 struct bigBedFilter *filters = bigBedBuildFilters(cart, bbi, track->tdb) ;
 if (compositeChildHideEmptySubtracks(cart, track->tdb, NULL, NULL))
@@ -521,30 +528,31 @@
     mouseOverPattern = cartOrTdbString(cart, track->tdb, "mouseOver", NULL);
 
     if (mouseOverPattern)
         {
         AllocArray(fieldNames, bbi->fieldCount);
         struct slName *field = NULL, *fields = bbFieldNames(bbi);
         int i =  0;
         for (field = fields; field != NULL; field = field->next)
             fieldNames[i++] = field->name;
         }
     }
 
 // a fake item that is the union of the items that span the current  window
 struct linkedFeatures *spannedLf = NULL;
 unsigned filtered = 0;
+struct bed *bed = NULL, *bedCopy = NULL;
 for (bb = bbList; bb != NULL; bb = bb->next)
     {
     struct linkedFeatures *lf = NULL;
     char *bedRow[bbi->fieldCount];
     if (sameString(track->tdb->type, "bigPsl"))
         {
         // fill out bedRow to support mouseOver pattern replacements
         char startBuf[16], endBuf[16];
         bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, ArraySize(bedRow));
         char *seq, *cds;
         struct psl *psl = pslFromBigPsl(chromName, bb, seqTypeField,  &seq, &cds);
         int sizeMul =  pslIsProtein(psl) ? 3 : 1;
         boolean isXeno = 0;  // just affects grayIx
         boolean nameGetsPos = FALSE; // we want the name to stay the name
 
@@ -559,34 +567,47 @@
             lf->filterColor = itemRgbColumn(bedRow[8]);
         }
     else if (sameString(tdb->type, "bigDbSnp"))
         {
         // bigDbSnp does not have a score field, but I want to compute the freqSourceIx from
         // trackDb and settings one time instead of for each item, so I'm overloading scoreMin.
         int freqSourceIx = scoreMin;
         lf = lfFromBigDbSnp(tdb, bb, filters, freqSourceIx);
         }
     else
 	{
         char startBuf[16], endBuf[16];
         bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, ArraySize(bedRow));
         if (bigBedFilterInterval(bedRow, filters))
             {
-            struct bed *bed = bedLoadN(bedRow, fieldCount);
+            if (instaFile)
+                {
+                if ((bed = instaBed(bbi, chainHash, bb)) != NULL)
+                    {
+                    bedCopy = cloneBed(bed);
                     lf = bedMungToLinkedFeatures(&bed, tdb, fieldCount,
                         scoreMin, scoreMax, useItemRgb);
                     }
+                }
+            else
+                {
+                bed = bedLoadN(bedRow, fieldCount);
+                bedCopy = cloneBed(bed);
+                lf = bedMungToLinkedFeatures(&bed, tdb, fieldCount,
+                    scoreMin, scoreMax, useItemRgb);
+                }
+            }
 
         if (lf && squishFieldIdx)
             lf->squishyPackVal = atof(restField(bb, squishFieldIdx));
 
         if (track->visibility != tvDense && lf && doWindowSizeFilter && bb->start < winStart && bb->end > winEnd)
             {
             mergeCount++;
             struct bed *bed = bedLoadN(bedRow, fieldCount);
             struct linkedFeatures *tmp = bedMungToLinkedFeatures(&bed, tdb, fieldCount,
                 scoreMin, scoreMax, useItemRgb);
             if (spannedLf)
                 {
                 if (tmp->start < spannedLf->start)
                     spannedLf->start = tmp->start;
                 if (tmp->end > spannedLf->end)
@@ -619,31 +640,31 @@
                 }
             continue; // lf will be NULL, but these items aren't "filtered", they're merged
             }
 	}
 
     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 = genePredFromBigGenePred(chromName, bb); 
+        lf->original = genePredFromBedBigGenePred(chromName, bedCopy, bb); 
         }
 
     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);