5a73e86ce8424ee217b2b8de96d3a6b1ff6fe470
braney
  Thu Jan 18 12:02:46 2024 -0800
limit VCF track loads to 10,000 items

diff --git src/hg/hgTracks/vcfTrack.c src/hg/hgTracks/vcfTrack.c
index 568d4c6..c38ea89 100644
--- src/hg/hgTracks/vcfTrack.c
+++ src/hg/hgTracks/vcfTrack.c
@@ -15,30 +15,31 @@
 #include "hgColors.h"
 #include "hgTracks.h"
 #include "iupac.h"
 #include "net.h"
 #include "pgSnp.h"
 #include "phyloTree.h"
 #include "trackHub.h"
 #include "trashDir.h"
 #include "variantProjector.h"
 #include "vcf.h"
 #include "vcfUi.h"
 #include "knetUdc.h"
 #include "udc.h"
 #include "memgfx.h"
 #include "chromAlias.h"
+#include "hgConfig.h"
 
 // Russ Corbett-Detig suggested darker shades for coloring non-synonymous variants green
 Color darkerShadesOfGreenOnWhite[EXPR_DATA_SHADES];
 
 static boolean getMinQual(struct trackDb *tdb, double *retMinQual)
 /* Return TRUE and set retMinQual if cart contains minimum QUAL filter */
 {
 if (cartOrTdbBoolean(cart, tdb, VCF_APPLY_MIN_QUAL_VAR, VCF_DEFAULT_APPLY_MIN_QUAL))
     {
     if (retMinQual != NULL)
 	*retMinQual = cartOrTdbDouble(cart, tdb, VCF_MIN_QUAL_VAR, VCF_DEFAULT_MIN_QUAL);
     return TRUE;
     }
 return FALSE;
 }
@@ -3000,30 +3001,45 @@
 /* Load items from a VCF of one individuals phased genotypes */
 {
 knetUdcInstall();
 pgSnpMethods(track);
 track->drawItems = vcfPhasedDrawItems;
 // Disinherit next/prev flag and methods since we don't support next/prev:
 track->nextExonButtonable = FALSE;
 track->nextPrevExon = NULL;
 track->nextPrevItem = NULL;
 track->loadItems = vcfPhasedLoadItems;
 track->totalHeight = vcfPhasedTrackHeight;
 track->itemName = vcfHapClusterTrackName;
 track->mapsSelf = TRUE;
 }
 
+static unsigned vcfMaxItems()
+/* Get the maximum number of items to grab from a vcf file.  Defaults to ten thousand. */
+{
+static boolean set = FALSE;
+static unsigned maxItems = 0;
+
+if (!set)
+    {
+    char *maxItemsStr = cfgOptionDefault("vcfMaxItems", "10000");
+
+    maxItems = sqlUnsigned(maxItemsStr);
+    }
+
+return maxItems;
+}
 
 static void vcfTabixLoadItems(struct track *tg)
 /* Load items in window from VCF file using its tabix index file. */
 {
 char *fileOrUrl = NULL;
 char *tbiFileOrUrl = trackDbSetting(tg->tdb, "bigDataIndex"); // unrelated to mysql
 
 /* Figure out url or file name. */
 if (tg->parallelLoading)
     {
     /* do not use mysql during parallel-fetch load */
     fileOrUrl = trackDbSetting(tg->tdb, "bigDataUrl");
     }
 else
     {
@@ -3032,31 +3048,32 @@
     hFreeConn(&conn);
     }
 
 if (isEmpty(fileOrUrl))
     return;
 fileOrUrl = hReplaceGbdb(fileOrUrl);
 int vcfMaxErr = -1;
 struct vcfFile *vcff = NULL;
 boolean hapClustEnabled = cartOrTdbBoolean(cart, tg->tdb, VCF_HAP_ENABLED_VAR, TRUE);
 if (slCount(windows)>1)
     hapClustEnabled = FALSE;  // haplotype sorting display not currently available with multiple windows.
 /* protect against temporary network error */
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
-    vcff = vcfTabixFileAndIndexMayOpen(fileOrUrl, tbiFileOrUrl, chromName, winStart, winEnd, vcfMaxErr, -1);
+    vcff = vcfTabixFileAndIndexMayOpenExt(fileOrUrl, tbiFileOrUrl, chromName, winStart, winEnd, vcfMaxErr, vcfMaxItems(), 
+        "Too many items in region.Zoom in to view track.");
     if (vcff != NULL)
 	{
 	filterRecords(vcff, tg);
         int vis = tdbVisLimitedByAncestors(cart,tg->tdb,TRUE,TRUE);
 	if (hapClustEnabled && vcff->genotypeCount > 1 &&
 	    (vis == tvPack || vis == tvSquish))
 	    vcfHapClusterOverloadMethods(tg, vcff);
 	else
 	    {
 	    tg->items = vcfFileToPgSnp(vcff, tg->tdb);
 	    // pgSnp bases coloring/display decision on count of items:
 	    tg->customInt = slCount(tg->items);
 	    }
 	// Don't vcfFileFree here -- we are using its string pointers!
 	}