Generate consensus FASTA sequences by applying VCF variants to a reference using bcftools consensus. Use when creating sample-specific reference sequences or reconstructing haplotypes.
Reference examples tested with: BioPython 1.83+, bcftools 1.19+, bedtools 2.31+, minimap2 2.26+, samtools 1.19+
Before using code patterns, verify installed versions match. If versions differ:
pip show <package> then help(module.function) to check signatures<tool> --version then <tool> --help to confirm flagsIf code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.
"Generate a consensus sequence from my VCF" → Apply called variants to a reference FASTA, producing a sample-specific genome with optional haplotype selection and low-coverage masking.
bcftools consensus -f reference.fa input.vcf.gzcyvcf2 + Bio.SeqIO for simple SNP-only casesbcftools consensus -f reference.fa input.vcf.gz > consensus.fa
bcftools consensus -f reference.fa -s sample1 input.vcf.gz > sample1.fa
bcftools consensus -f reference.fa -o consensus.fa input.vcf.gz
bcftools consensus -f reference.fa -H 1 input.vcf.gz > haplotype1.fa
bcftools consensus -f reference.fa -H 2 input.vcf.gz > haplotype2.fa
| Option | Description |
|---|---|
-H 1 | First haplotype |
-H 2 | Second haplotype |
-H A | Apply all ALT alleles |
-H R | Apply REF alleles where heterozygous |
-I | Apply IUPAC ambiguity codes (separate flag) |
bcftools consensus -f reference.fa -I input.vcf.gz > consensus_iupac.fa
Heterozygous sites encoded with IUPAC ambiguity codes:
bcftools consensus -f reference.fa -M N input.vcf.gz > consensus.fa
Using a mask BED file:
# Create mask from depth
samtools depth input.bam | awk '$3<10 {print $1"\t"$2-1"\t"$2}' > low_coverage.bed
# Apply mask
bcftools consensus -f reference.fa -m low_coverage.bed input.vcf.gz > consensus.fa
| Option | Description |
|---|---|
-m FILE | Mask regions in BED file with N |
-M CHAR | Character for masked regions (default N) |
bcftools consensus -f reference.fa -r chr1:1000-2000 input.vcf.gz > region.fa
Use with BED file to extract multiple regions.
bcftools consensus -f reference.fa -c chain.txt input.vcf.gz > consensus.fa
Chain files map coordinates between reference and consensus:
chain score ref_name ref_size ref_strand ref_start ref_end query_name query_size query_strand query_start query_end id
for sample in $(bcftools query -l input.vcf.gz); do
bcftools consensus -f reference.fa -s "$sample" input.vcf.gz > "${sample}.fa"
done
sample="sample1"
bcftools consensus -f reference.fa -s "$sample" -H 1 input.vcf.gz > "${sample}_hap1.fa"
bcftools consensus -f reference.fa -s "$sample" -H 2 input.vcf.gz > "${sample}_hap2.fa"
bcftools view -f PASS input.vcf.gz | \
bcftools consensus -f reference.fa > consensus.fa
bcftools filter -i 'QUAL>=30 && INFO/DP>=10' input.vcf.gz | \
bcftools consensus -f reference.fa > consensus.fa
bcftools view -v snps input.vcf.gz | \
bcftools consensus -f reference.fa > consensus_snps.fa
Output uses reference sequence names.
bcftools consensus -f reference.fa -p "sample1_" input.vcf.gz > consensus.fa
Sequences named: sample1_chr1, sample1_chr2, etc.
Goal: Generate consensus sequences for downstream analyses like phylogenetics, viral surveillance, or gene-level comparison.
Approach: Filter variants to high-quality calls, apply per-sample consensus generation, mask low-coverage regions with N, then combine for multi-sample workflows.
# For each sample, generate consensus
mkdir -p consensus
for sample in $(bcftools query -l cohort.vcf.gz); do
bcftools view -s "$sample" cohort.vcf.gz | \
bcftools view -c 1 | \
bcftools consensus -f reference.fa > "consensus/${sample}.fa"
done
# Combine for alignment
cat consensus/*.fa > all_samples.fa
# Apply high-quality variants only
bcftools filter -i 'QUAL>=30 && INFO/DP>=20' variants.vcf.gz | \
bcftools view -f PASS | \
bcftools consensus -f reference.fa -M N > consensus.fa
# Extract gene region
bcftools consensus -f reference.fa -r chr1:1000000-1010000 \
-s sample1 variants.vcf.gz > gene.fa
# Create mask from coverage
samtools depth -a input.bam | \
awk '$3<5 {print $1"\t"$2-1"\t"$2}' | \
bedtools merge > low_coverage.bed
# Generate consensus with mask
bcftools consensus -f reference.fa -m low_coverage.bed \
variants.vcf.gz > consensus.fa
# Align consensus to reference
minimap2 -a reference.fa consensus.fa | samtools view -bS > alignment.bam
# Or simple comparison
diff <(grep -v "^>" reference.fa) <(grep -v "^>" consensus.fa) | head
# Number of differences
bcftools view -H input.vcf.gz | wc -l
bcftools consensus handles overlapping variants automatically:
Check for warnings:
bcftools consensus -f reference.fa input.vcf.gz 2>&1 | grep -i warn
from cyvcf2 import VCF
from Bio import SeqIO
# Load reference
ref_dict = {rec.id: str(rec.seq) for rec in SeqIO.parse('reference.fa', 'fasta')}
# Apply variants (SNPs only, simplified)
vcf = VCF('input.vcf.gz')
changes = {}
for variant in vcf:
if variant.is_snp and len(variant.ALT) == 1:
chrom = variant.CHROM
pos = variant.POS - 1 # 0-based
if chrom not in changes:
changes[chrom] = {}
changes[chrom][pos] = variant.ALT[0]
# Apply changes
for chrom, positions in changes.items():
seq = list(ref_dict[chrom])
for pos, alt in positions.items():
seq[pos] = alt
ref_dict[chrom] = ''.join(seq)
# Write output
with open('consensus.fa', 'w') as f:
for chrom, seq in ref_dict.items():
f.write(f'>{chrom}\n{seq}\n')
Note: Use bcftools consensus for production - handles indels and edge cases properly.
| Task | Command |
|---|---|
| Basic consensus | bcftools consensus -f ref.fa in.vcf.gz |
| Specific sample | bcftools consensus -f ref.fa -s sample in.vcf.gz |
| Haplotype 1 | bcftools consensus -f ref.fa -H 1 in.vcf.gz |
| IUPAC codes | bcftools consensus -f ref.fa -I in.vcf.gz |
| With mask | bcftools consensus -f ref.fa -m mask.bed in.vcf.gz |
| Generate chain | bcftools consensus -f ref.fa -c chain.txt in.vcf.gz |
| Specific region | bcftools consensus -f ref.fa -r chr1:1-1000 in.vcf.gz |
| Error | Cause | Solution |
|---|---|---|
not indexed | VCF not indexed | Run bcftools index |
sequence not found | Chromosome mismatch | Check chromosome names |
overlapping records | Variants overlap | Usually OK, check warnings |
REF does not match | Wrong reference | Use same reference as caller |