Step 4: Structural Variant Calling (Manta)¶
What This Does¶
Detects large DNA changes (>50bp) that DeepVariant misses: deletions, duplications, inversions, translocations, and insertions.
Why¶
Structural variants cause ~25% of all genetic disease but are invisible to standard SNP/indel callers.
Tool¶
- Manta (Illumina) — structural variant and indel caller
Docker Image¶
MANTA_IMAGE
Pinned in versions.env; Image versions lists the current tag.
Command¶
source versions.env # from the repository root
REF_FASTA=reference/GRCh38_no_alt_analysis_set.fasta # see 00-reference-setup.md#the-reference-path-on-every-page
SAMPLE=your_sample
GENOME_DIR=/path/to/your/data
THREADS=8
# Step 1: Configure Manta
docker run --rm \
--cpus ${THREADS} --memory 16g \
-v ${GENOME_DIR}:/genome \
"${MANTA_IMAGE}" \
configManta.py \
--bam /genome/${SAMPLE}/aligned/${SAMPLE}_sorted.bam \
--referenceFasta "/genome/${REF_FASTA}" \
--runDir /genome/${SAMPLE}/manta
# Step 2: Run Manta
docker run --rm \
--cpus ${THREADS} --memory 16g \
-v ${GENOME_DIR}:/genome \
"${MANTA_IMAGE}" \
/genome/${SAMPLE}/manta/runWorkflow.py -j ${THREADS}
# Step 3: Turn inversion breakend pairs into SVTYPE=INV records with the
# convertInversion.py, samtools, bgzip and tabix inside the Manta image, then
# check each one with bin/manta_inv_filter.py from this repository (mounted
# at /pgp-bin; it runs on the image's Python 2.7).
# Manta's own file is kept as diploidSV.raw.vcf.gz.
docker run --rm \
-v ${GENOME_DIR}:/genome \
-v "$PWD/bin:/pgp-bin:ro" \
"${MANTA_IMAGE}" \
bash -c 'set -euo pipefail
L="$(dirname "$(readlink -f "$(command -v configManta.py)")")/../libexec"
cd "$2"
mv diploidSV.vcf.gz diploidSV.raw.vcf.gz
mv diploidSV.vcf.gz.tbi diploidSV.raw.vcf.gz.tbi
"$L/convertInversion.py" "$L/samtools" "$1" diploidSV.raw.vcf.gz > /tmp/converted.vcf
python /pgp-bin/manta_inv_filter.py diploidSV.raw.vcf.gz /tmp/converted.vcf | "$L/bgzip" -c > diploidSV.vcf.gz
"$L/tabix" -f -p vcf diploidSV.vcf.gz' \
_ "/genome/${REF_FASTA}" "/genome/${SAMPLE}/manta/results/variants"
# Output: diploidSV.vcf.gz (~7-9K structural variants)
scripts/04-manta.sh runs the same three steps. It reads the CPU count from THREADS (default 8) and the BAM from ${SAMPLE}/${ALIGN_DIR}/ (default aligned). With MANTA_CALL_REGIONS set to a bgzipped BED under GENOME_DIR (its .tbi beside it), Manta calls only those regions (configManta.py --callRegions), for example chr1-22, X and Y without the unplaced scaffolds and chrEBV. When Manta reported no inversion, the script copies diploidSV.raw.vcf.gz to diploidSV.vcf.gz instead of starting a container, and says so. Run on a folder that holds Manta's results from before the inversion step, it converts them without calling again.
Inversions with one junction¶
Manta writes each inversion junction as two breakend records, flagged INV3 or INV5. A balanced inversion has two junctions, one of each. convertInversion.py turns every pair into an SVTYPE=INV record from POS to END, a lone junction too, so a junction whose breakends lie 150 Mb apart became a 150 Mb inversion, and AnnotSV (step 5) annotated it over hundreds of genes. bin/manta_inv_filter.py now reads Manta's file and the converted one and:
- marks an inversion
INV_JUNCTIONS=2when the opposite junction is there too (anINV5record for anINV3one, withPOSandENDeach within 1,000 bp, or both in one MantaEVENT); - marks one without it
INV_JUNCTIONS=1. When it spans 1 Mb or more, it puts the two breakend records of Manta's file back in its place (eachINV_JUNCTIONS=1), so no step reads it as a whole-span inversion; - marks a lone junction shorter than 1,000 bp
INVDUP_CANDIDATE: two breakends that close are more likely an inverted insertion or duplication than an inversion.
The step prints one line with the count of each kind (Inversion check: ...). The Nextflow MANTA process runs the same script.
Output¶
results/variants/diploidSV.vcf.gz— main output (all SV calls), with each inversion junction as oneSVTYPE=INVrecord, except a lone junction of 1 Mb or more, which stays its two breakend records (see above); steps 15 and 22 read this file. Step 05 (AnnotSV) reads step 15's duphold-filtered calls (duphold/<sample>_sv_filtered.vcf.gz) first, and this file only when those are missing, have no.tbior are older than itresults/variants/diploidSV.raw.vcf.gz— the same calls as Manta wrote them, where each inversion junction is a pair of breakend (SVTYPE=BND) recordsresults/variants/candidateSV.vcf.gz— unfiltered candidatesresults/variants/candidateSmallIndels.vcf.gz— small indels
Important Notes¶
- Raw Manta output is UNFILTERED — most calls are benign
- Must run AnnotSV (step 5) to classify pathogenicity
- SVs >5MB in short-read WGS are usually artifacts from segmental duplications
- Typical results: 7,000-9,000 SVs per 30X WGS sample