e1988a798585c610e2399538a900fd57cfa83d63
galt
  Tue Apr 22 11:19:22 2025 -0700
Fixes VCF does not work on extended case-color options in Get DNA for vcf, vcfTabix, and vcfPhasedTrio. fixes #16386

diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c
index 675531a22db..de021c5b7fe 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -5868,30 +5868,41 @@
         {
         AllocVar(fb);
         fb->name = bed->name;
         fb->start = bed->chromStart;
         fb->end = bed->chromEnd;
         fb->strand = '+';
         if (bed->strand[0])
             fb->strand = bed->strand[0];
         if (clipFbToWindow(fb, winStart,winEnd))
             slAddHead(&fbList, fb);
         }
     }
 return fbList;
 }
 
+static struct featureBits *vcfLoadInterval(struct trackDb *tdb, int start, int end)
+{
+struct featureBits *fbList = NULL;
+if (sameString(tdb->type, "vcf") || sameString(tdb->type, "vcfPhasedTrio"))
+   doVcfDetailsExt(tdb, NULL, &fbList, start, end);
+else if (sameString(tdb->type, "vcfTabix"))
+   doVcfTabixDetailsExt(tdb, NULL, &fbList, start, end);
+return fbList;
+}
+
+
 void doGetDna3()
 /* Fetch DNA in extended color format */
 {
 struct dnaSeq *seq;
 struct cfm *cfm;
 int i;
 boolean isRc = cartUsualBoolean(cart, "hgSeq.revComp", FALSE);
 boolean defaultUpper = sameString(cartString(cart, "hgSeq.casing"), "upper");
 int winSize;
 int lineWidth = cartInt(cart, "lineWidth");
 struct rgbColor *colors;
 
 struct trackDb *tdbList = loadTracks();
 
 char *pos = NULL;
@@ -5918,30 +5929,31 @@
     touppers(seq->dna);
 
 AllocArray(colors, winSize);
 
 struct trackDb* tdb;
 for (tdb = tdbList; tdb != NULL; tdb = tdb->next)
     {
     char *track = tdb->track;
     char *table = tdb->table;
     struct featureBits *fbList = NULL, *fb;
     struct customTrack *ct = lookupCt(track);
     if (sameString(USER_PSL_TRACK_NAME, table)
     ||  ct != NULL
     ||  (   tdbVisLimitedByAncestors(cart,tdb,TRUE,TRUE) != tvHide
         && forestHasUnderstandableTrack(database, tdb) ) )
+        
         {
         char buf[256];
         int r,g,b;
         /* to save a LOT of time, don't fetch track features unless some
          * coloring/formatting has been specified for them. */
 	boolean hasSettings = FALSE;
 	safef(buf, sizeof(buf), "%s_u", track);
 	hasSettings |= cgiBoolean(buf);
 	safef(buf, sizeof(buf), "%s_b", track);
 	hasSettings |= cgiBoolean(buf);
 	safef(buf, sizeof(buf), "%s_i", track);
 	hasSettings |= cgiBoolean(buf);
 	safef(buf, sizeof(buf), "%s_case", track);
 	hasSettings |= cgiBoolean(buf);
 	safef(buf, sizeof(buf), "%s_red", track);
@@ -5961,31 +5973,31 @@
 	    AllocVar(bf);
 	    bedList = bedFromUserPsl();
 	    bedList2 = bedFilterListInRange(bedList, bf, seqName, winStart,
 					    winEnd);
 	    fbList = fbFromBed(database, track, hti, bedList2, winStart, winEnd,
 			       TRUE, FALSE);
 	    bedFreeList(&bedList);
 	    bedFreeList(&bedList2);
 	    }
 	else if (ct != NULL)
 	    {
 	    struct hTableInfo *hti = ctToHti(ct);
 	    struct bedFilter *bf;
 	    struct bed *bedList2, *ctBedList = NULL;
 	    AllocVar(bf);
-            if (ct->dbTrack)
+            if (ct->dbTrack && (!sameString(tdb->type, "vcf")))
                 {
                 struct bed *bed;
                 int fieldCount = ct->fieldCount;
                 if ((ct->dbTrackType != NULL) && sameString(ct->dbTrackType, "pgSnp"))
                     fieldCount = 4;
                 char query[512];
                 int rowOffset;
                 char **row;
                 struct sqlConnection *conn = hAllocConn(CUSTOM_TRASH);
                 struct sqlResult *sr = NULL;
 
                 sqlSafef(query, sizeof(query), "select * from %s", ct->dbTableName);
                 sr = hRangeQuery(conn, ct->dbTableName, seqName,
                     winStart, winEnd, NULL, &rowOffset);
                 while ((row = sqlNextRow(sr)) != NULL)
@@ -6005,65 +6017,76 @@
                 struct lm *lm = lmInit(0);
                 struct bigBedInterval *bb, *bbList = bigBedIntervalQuery(ct->bbiFile, seqName, winStart, winEnd, 0, lm);
                 char *bedRow[32];
                 char startBuf[16], endBuf[16];
                 for (bb = bbList; bb != NULL; bb = bb->next)
                     {
                     bigBedIntervalToRow(bb, seqName, startBuf, endBuf, bedRow, ArraySize(bedRow));
                     struct bed *bed = bedLoadN(bedRow, ct->bbiFile->definedFieldCount);
                     slAddHead(&ctBedList, bed);
                     }
                 }
             else
                 {
                 ctBedList = ct->bedList;
                 }
+	    if (startsWith("vcf", tdb->type))
+                {
+		fbList = vcfLoadInterval(ct->tdb, winStart, winEnd);
+                }
+            else
+		{
 		bedList2 = bedFilterListInRange(ctBedList, bf, seqName, winStart,
 					    winEnd);
 		fbList = fbFromBed(database, track, hti, bedList2, winStart, winEnd,
 			       TRUE, FALSE);
 		bedFreeList(&bedList2);
+		}
             if (!ct->bedList)
                 bedFreeList(&ctBedList);
 	    }
 	else
             {
             if (tdb->subtracks)
                 {
                 struct slRef *refLeaves = trackDbListGetRefsToDescendantLeaves(tdb->subtracks);
                 struct slRef *refLeaf = NULL;
                 while ((refLeaf = slPopHead(&refLeaves)) != NULL)
                     {
                     struct trackDb *tdbLeaf = refLeaf->val;
                     if (tdbVisLimitedByAncestors(cart,tdbLeaf,TRUE,TRUE) != tvHide
                     &&  fbUnderstandTrack(database, tdbLeaf)
                     && !dnaIgnoreTrack(tdbLeaf->table))
                         {
                         struct featureBits *fbLeafList;
-                        if (startsWith("big", tdbLeaf->type))
+			if (startsWith("vcf", tdbLeaf->type))
+			    fbLeafList = vcfLoadInterval(tdbLeaf, winStart, winEnd);
+                        else if (startsWith("big", tdbLeaf->type))
                             fbLeafList = getBigBedFbList(tdbLeaf, seqName, winStart, winEnd);
                         else
                             fbLeafList = fbGetRange(database, tdbLeaf->table, seqName, winStart, winEnd);
                         if (fbLeafList != NULL)
                             fbList = slCat(fbList,fbLeafList);
                         }
                     freeMem(refLeaf);
                     }
                 }
             else
                 {
-                if (startsWith("big", tdb->type))
+                if (startsWith("vcf", tdb->type))
+                    fbList = vcfLoadInterval(tdb, winStart, winEnd);
+                else if (startsWith("big", tdb->type))
                     fbList = getBigBedFbList(tdb, seqName, winStart, winEnd);
                 else
                     fbList = fbGetRange(database, tdb->table, seqName, winStart, winEnd);
                 }
             }
 
         /* Flip underline/italic/bold bits. */
         getDnaHandleBits(track, "u", uBits, winStart, winEnd, isRc, fbList);
         getDnaHandleBits(track, "b", bBits, winStart, winEnd, isRc, fbList);
 	getDnaHandleBits(track, "i", iBits, winStart, winEnd, isRc, fbList);
 
 	/* Toggle case if necessary. */
 	safef(buf, sizeof buf, "%s_case", track);
 	if (cgiBoolean(buf))
 	    {