Variant Frequency DB Integrator combines important population-frequency databases into two allele-specific outputs:
- a compact ANNOVAR database containing only the maximum frequency per variant
- a wide TSV database containing the maximum frequency plus all configured population/subpopulation frequencies
It uses a streaming k-way merge, so it does not load all variants into RAM. Memory usage is approximately proportional to the number of source files.
- Every source uses the same genome assembly.
- Every source is represented in exact ANNOVAR form:
Chr Start End Ref Alt .... - Indels have already been normalized consistently.
- Every input is sorted by chromosome, start, end, REF, and ALT using natural chromosome order:
1..22, X, Y, MT, then other contigs. - Aggregation is by exact allele, never by position alone.
For VCF sources, normalize and split them before converting to ANNOVAR:
bcftools norm -f GRCh38.fa -m -any source.vcf.gz -Oz -o source.norm.vcf.gz
convert2annovar.pl -format vcf4 source.norm.vcf.gz > source.avinputmvn clean packageOutput:
target/maxfreq-builder-1.0.0.jar
The configuration is TSV with one source per line. Column numbers are one-based.
Required config columns:
| Column | Meaning |
|---|---|
source |
Stable source name |
path |
Plain, .gz, .bgz, or .bgzip file |
frequency_fields |
One or more AF definitions separated by semicolons |
Variant-location config columns are optional when the source file has a header:
| Column | Default header selector |
|---|---|
chr_col |
Chromosome column |
start_col |
Start column |
end_col |
End column |
ref_col |
REF column |
alt_col |
ALT column |
If omitted or blank, these are detected from common header names such as Chr,
Chromosome, Start, Position, End, Ref, and Alt. You can still provide
one-based numbers, or provide your own partial header strings.
Some source databases have Start and End; others only have one position
column such as Position or POS. If no End/Stop column is found, the tool
derives End from Start and Ref:
End = Start + length(Ref) - 1
For ordinary SNVs this makes End equal to Start.
Optional columns:
| Column | Default | Meaning |
|---|---|---|
min_an |
0 |
Minimum AN for observations from this source |
require_an |
false |
Exclude observations without AN |
priority |
100 |
Lower value wins exact ties |
A frequency field is:
AF_COLUMN:POPULATION[:AC_COLUMN[:AN_COLUMN[:SCALE]]]
Column selectors such as chr_col, start_col, AF_COLUMN, AC_COLUMN, and
AN_COLUMN may be either one-based column numbers or case-insensitive
substrings matched against the source file header. String selectors do not need
to match the full header. If a selector matches more than one column,
validation/build fails and asks for a more specific selector.
Examples:
gnomAD_AF
6
6:global
7:NFE:0:0
8:MID:9:10
gnomAD_AF:global
AF_nfe:NFE:AC_nfe:AN_nfe
11:regional_percent:12:13:100
- A single selector such as
gnomAD_AFor6is accepted as shorthand forgnomAD_AF:globalor6:global. 0or an empty AC/AN column means unavailable.SCALE=100converts a percentage such as2.5into AF0.025.- Multiple population columns in one source are permitted. The largest eligible AF is retained.
- Header-string selectors and omitted variant columns require the first non-comment, non-blank source line to be the tab-delimited header. Numeric selectors keep the old behavior and do not require a source header.
See examples/sources.example.tsv.
java -jar maxfreq-builder.jar validate --config sources.tsvThe command fails on the first unsorted or malformed record.
Large source files must be sorted before the streaming builder can merge them.
Use the helper script instead of PowerShell Sort-Object for multi-GB files:
python scripts\sort_annovar_db.py `
--input "E:\NGSneeds\Annovar_Databases\hg19_databases\hg19_gnomad211_exome.txt" `
--output "E:\NGSneeds\Annovar_Databases\hg19_databases\sorted\hg19_gnomad211_exome.sorted.txt" `
--chr-col 1 `
--start-col 2 `
--end-col 3 `
--ref-col 4 `
--alt-col 5For files with only one position column, use --end-col 0; the script derives
End = Start + length(Ref) - 1.
After sorting, update the path for that source in sources.tsv to the sorted
file and run validate again.
java -jar maxfreq-builder.jar build \
--config sources.tsv \
--output humandb/hg38_maxfreq.txt \
--subpopulations humandb/hg38_maxfreq.subpopulations.tsv.gz \
--details humandb/hg38_maxfreq.details.tsv.gz \
--regions targets.bed \
--min-af 0 \
--progress-every 1000000--regions is optional. When provided, it must point to a BED file. BED files
use 0-based, half-open coordinates, so this BED line:
chr1 499 500
matches ANNOVAR coordinate 1 500 500. A variant is included if its
Start..End span overlaps any BED interval.
Outputs:
hg38_maxfreq.txt: six-column ANNOVAR generic filter database:
Chr Start End Ref Alt MaxAF
hg38_maxfreq.subpopulations.tsv.gz: wide TSV database containing the same allele columns, oneMaxFreqcolumn, and one AF column for every configuredsource_populationfield. Missing or ineligible observations are written as..
Chr Start End Ref Alt MaxFreq gnomad41_exome_global gnomad41_exome_AFR ...
If --subpopulations is omitted, this file is written beside --output as
<output>.subpopulations.tsv.gz.
hg38_maxfreq.details.tsv.gz: provenance table containing source, population, AC, AN, number of eligible observations, source count, and duplicate source-row count.
Create the ANNOVAR index using the index_annovar.pl script distributed/referenced by ANNOVAR:
perl index_annovar.pl humandb/hg38_maxfreq.txt \
-outfile humandb/hg38_maxfreq.txtThen annotate with it as a filter database:
table_annovar.pl patient.vcf humandb/ \
-buildver hg38 \
-protocol refGeneWithVer,maxfreq \
-operation g,f \
-vcfinput \
-nastring .The file name must be hg38_maxfreq.txt for protocol name maxfreq.
For each exact allele:
- Invalid or missing AF values are ignored.
- AF values are converted by their configured scale.
- Observations failing
min_anorrequire_anare ignored. - The maximum AF is selected.
- Ties prefer larger AN, then lower source priority, then stable lexical order.
The main ANNOVAR file contains only the numeric maximum so -score_threshold remains usable. Provenance is stored separately in the details file.
By default, build progress is logged once per 1,000,000 analysed variants. Problem logs, such as malformed source rows when --skip-bad-rows true is enabled, are still printed.
./scripts/demo.shExpected ANNOVAR output:
1\t100\t100\tA\tG\t0.005
1\t100\t100\tA\tT\t0.02
1\t150\t150\tG\tC\t0.0002
1\t200\t200\tC\tT\t0.003
X\t50\t50\tG\tA\t0.1
The sourceB X-chromosome value 0.2 is excluded because its AN is only 100, below the configured min_an=1000.