be36584718d57384b01657483422f51adf29f0bb max Sat Jul 25 18:22:02 2026 -0700 vcfTrack: add minimum alternate allele count (minAc) filter, refs #37927 When a VCF INFO column includes AC, offer a 'minimum allele count' filter in the track UI (e.g. 2 to hide singletons) and drop records whose largest alternate allele count is below the threshold. diff --git src/hg/lib/vcfUi.c src/hg/lib/vcfUi.c index bb3a5188e0c..7ba16bd1580 100644 --- src/hg/lib/vcfUi.c +++ src/hg/lib/vcfUi.c @@ -430,30 +430,44 @@ static void vcfCfgMinAlleleFreq(struct cart *cart, struct trackDb *tdb, struct vcfFile *vcff, char *name, boolean parentLevel) /* Show input for minimum allele frequency, if we can extract it from the VCF INFO column. */ { printf("<B>Minimum minor allele frequency (if INFO column includes AF or AC+AN):</B>\n"); double cartMinFreq = cartOrTdbDouble(cart, tdb, VCF_MIN_ALLELE_FREQ_VAR, VCF_DEFAULT_MIN_ALLELE_FREQ); char varName[1024]; safef(varName, sizeof(varName), "%s." VCF_MIN_ALLELE_FREQ_VAR, name); cgiMakeDoubleVarInRange(varName, cartMinFreq, "minor allele frequency between 0.0 and 0.5", 5, "0.0", "0.5"); puts("<BR>"); } +static void vcfCfgMinAc(struct cart *cart, struct trackDb *tdb, struct vcfFile *vcff, + char *name, boolean parentLevel) +/* Show input for minimum alternate allele count, if INFO column includes AC. This lets + * the user filter on a whole-number count (e.g. 2 to hide singletons) instead of having to + * enter a tiny frequency cutoff. */ +{ +printf("<B>Minimum allele count (if INFO column includes AC), e.g. 2 to hide singletons:</B>\n"); +int cartMinAc = cartOrTdbInt(cart, tdb, VCF_MIN_AC_VAR, VCF_DEFAULT_MIN_AC); +char varName[1024]; +safef(varName, sizeof(varName), "%s." VCF_MIN_AC_VAR, name); +cgiMakeIntVarWithMin(varName, cartMinAc, "minimum allele count", 5, 0); +puts("<BR>"); +} + static char *getChildSample(struct trackDb *tdb) /* Return just the VCF sample name of the phased trio child setting */ { char *childSampleMaybeAlias = cloneString(trackDbLocalSetting(tdb, VCF_PHASED_CHILD_SAMPLE_SETTING)); char *pt = strchr(childSampleMaybeAlias, '|'); if (pt != NULL) *pt = '\0'; return childSampleMaybeAlias; } static struct slPair *vcfPhasedGetSamplesFromTdb(struct trackDb *tdb, boolean hideOtherSamples) /* Get the different VCF Phased Trio setings out of trackDb onto a list */ { // cloneString here because we will be munging the result if there are alternate labels char *childSampleMaybeAlias = cloneString(trackDbLocalSetting(tdb, VCF_PHASED_CHILD_SAMPLE_SETTING)); @@ -688,48 +702,51 @@ printInfoIcon(phasedInfoText); } void vcfCfgUi(struct cart *cart, struct trackDb *tdb, char *name, char *title, boolean boxed) /* VCF: Variant Call Format. redmine #3710 */ { boxed = cfgBeginBoxAndTitle(tdb, boxed, title); printf("<TABLE%s><TR><TD>", boxed ? " width='100%'" : ""); struct vcfFile *vcff = vcfHopefullyOpenHeader(cart, tdb); if (vcff != NULL) { boolean parentLevel = isNameAtParentLevel(tdb, name); boolean doVcfFilterUi = cartOrTdbBoolean(cart, tdb, VCF_DO_FILTER_UI, TRUE); boolean doVcfQualUi = cartOrTdbBoolean(cart, tdb, VCF_DO_QUAL_UI, TRUE); boolean doVcfMafUi = cartOrTdbBoolean(cart, tdb, VCF_DO_MAF_UI, TRUE); + boolean doVcfMinAcUi = cartOrTdbBoolean(cart, tdb, VCF_DO_MIN_AC_UI, TRUE); if (vcff->genotypeCount > 1 && !sameString(tdb->type, "vcfPhasedTrio")) { vcfCfgHapCluster(cart, tdb, vcff, name, parentLevel); } if (sameString(tdb->type, "vcfPhasedTrio")) { vcfCfgPhasedTrioUi(cart, tdb, vcff, name, parentLevel); } if (differentString(tdb->track,"evsEsp6500") && (doVcfFilterUi || doVcfQualUi)) { puts("<H3>Filters</H3>"); if (doVcfQualUi) vcfCfgMinQual(cart, tdb, vcff, name, parentLevel); if (doVcfFilterUi) vcfCfgFilterColumn(cart, tdb, vcff, name, parentLevel); } if (doVcfMafUi) vcfCfgMinAlleleFreq(cart, tdb, vcff, name, parentLevel); + if (doVcfMinAcUi) + vcfCfgMinAc(cart, tdb, vcff, name, parentLevel); } else { printf("Sorry, couldn't access VCF file.<BR>\n"); } puts("</TD>"); if (boxed && fileExists(hHelpFile("hgVcfTrackHelp"))) printf("<TD style='text-align:right'><A HREF=\"../goldenPath/help/hgVcfTrackHelp.html\" " "TARGET=_BLANK>VCF configuration help</A></TD>"); printf("</TR></TABLE>"); wigOption(cart, name, title, tdb); if (!boxed && fileExists(hHelpFile("hgVcfTrackHelp")))