Multi-sample joint genotyping combines information across samples for improved variant detection, consistent site calling, and eligibility for cohort-level filtering (VQSR/VETS). It is not the same operation as merging single-sample VCFs: joint genotyping borrows evidence across samples to rescue low-coverage het sites and produces a squared-off sample-by-site matrix where an unassessed cell (./.) is distinguishable from a confident hom-ref (0/0). The GVCF workflow also solves the N+1 problem, letting a new sample be added without re-calling the whole cohort.
conda install -c bioconda gatk4
Tell your AI agent what you want to do: - "Set up joint calling for my cohort of 50 samples" - "Combine GVCFs and run GenotypeGVCFs" - "Scale joint calling for 1000+ samples by chromosome" - "Choose between CombineGVCFs and GenomicsDBImport" - "Add a new sample to my cohort without re-calling everyone" - "Joint call DeepVariant gVCFs with GLnexus instead of GATK" - "Explain why I should not just bcftools merge my single-sample VCFs"
"Combine these 10 sample GVCFs and run joint genotyping"
"Run CombineGVCFs followed by GenotypeGVCFs for my family trio"
"Set up GenomicsDBImport for 500 samples, processing by chromosome"
"Create a sample map file and import into GenomicsDB"
"Generate GVCFs from all BAM files for joint calling"
"Run HaplotypeCaller in GVCF mode for each sample in the cohort"
"Apply VQSR to my joint-called cohort VCF"
"Joint call my samples and then apply hard filters"
"Shard GenomicsDBImport and GenotypeGVCFs by chromosome for my 5000-sample cohort"
"Reblock my gVCFs and use GnarlyGenotyper for a biobank-scale cohort"
"Run DeepVariant per sample and joint call with GLnexus DeepVariantWGS config"
bcftools merge single-sample VCFs into a cohort matrix: absent records become ./. (missing), not 0/0 (hom-ref), corrupting allele frequencies--java-options -Xmx) at ~80-90% of RAM for GenomicsDBImport; its heavy work is native C/C++, and an over-large heap triggers a native out-of-memory error--sample-name-map file rather than thousands of -V arguments* spanning-deletion alleles and recomputed GQ/PL in the joint VCF; special-case * before annotationSample BAMs -> HaplotypeCaller (GVCF mode) -> CombineGVCFs -> GenotypeGVCFs -> Cohort VCF
gatk HaplotypeCaller \
-R reference.fa \
-I sample1.bam \
-O sample1.g.vcf.gz \
-ERC GVCF
gatk CombineGVCFs \
-R reference.fa \
-V sample1.g.vcf.gz \
-V sample2.g.vcf.gz \
-V sample3.g.vcf.gz \
-O combined.g.vcf.gz
gatk GenomicsDBImport \
-V sample1.g.vcf.gz \
-V sample2.g.vcf.gz \
-V sample3.g.vcf.gz \
--genomicsdb-workspace-path genomicsdb \
-L intervals.bed
# From CombineGVCFs
gatk GenotypeGVCFs \
-R reference.fa \
-V combined.g.vcf.gz \
-O cohort.vcf.gz
# From GenomicsDB
gatk GenotypeGVCFs \
-R reference.fa \
-V gendb://genomicsdb \
-O cohort.vcf.gz
| Cohort Size | Method | Notes |
|---|---|---|
| < 100 | CombineGVCFs | Simple, single command; portable plain gVCF |
| 100-10,000 | GenomicsDBImport | Scalable, interval-based; shard by chromosome |
| > 10,000 | ReblockGVCF + GnarlyGenotyper, or DeepVariant + GLnexus | Naive GenotypeGVCFs stops scaling |
# Import by chromosome
for chr in {1..22} X Y; do
gatk GenomicsDBImport \
--sample-name-map samples.map \
--genomicsdb-workspace-path genomicsdb_chr${chr} \
-L chr${chr}
done
# Genotype by chromosome, then merge
# Apply VQSR (requires large cohorts)
gatk VariantRecalibrator ...
gatk ApplyVQSR ...
# Or hard filter for small cohorts
gatk VariantFiltration \
-V cohort.vcf.gz \
--filter-expression "QD < 2.0" --filter-name "LowQD" \
-O filtered.vcf.gz
./. vs 0/0)