# VCF Preprocessing User Guide

Marta Sevilla Porras1,2* and Carlos Ruiz Arenas3**

1Universitat Pompeu Fabra (UPF)
2Centro de Investigación Biomédica en Red (CIBERER)
3Universidad de Navarra (UNAV)

*marta.sevilla@upf.edu
**cruizarenas@unav.es

#### 1 June 2026

This vignette shows how to preprocess individual trio VCFs (proband, father, mother) into a clean trio VCF suitable for UPDhmm.

## Inputs

You should have one VCF (e.g. oputput from GATK) per family member:

- `proband.vcf.gz`
- `mother.vcf.gz`
- `father.vcf.gz`

Each file should be bgzipped (`.vcf.gz`) and indexed with tabix (`.tbi`).

## 0. Normalize and Left-Align Variants (optional)

For this step you will need a reference genome FASTA indexed with `samtools faidx`.

    bcftools norm -m-any -f reference.fa proband.vcf.gz -Oz -o proband.norm.vcf.gz
    bcftools norm -m-any -f reference.fa mother.vcf.gz  -Oz -o mother.norm.vcf.gz
    bcftools norm -m-any -f reference.fa father.vcf.gz  -Oz -o father.norm.vcf.gz

    tabix -p vcf proband.norm.vcf.gz
    tabix -p vcf mother.norm.vcf.gz
    tabix -p vcf father.norm.vcf.gz

## 1. Remove Extra Annotations

Keep only essential fields (drop INFO/FORMAT annotations not required downstream). The resulting VCFs are lighter.

    # Keep only GT, AD, DP, and GQ fields (remove all other INFO)
    bcftools annotate -x INFO,^FORMAT/GT,FORMAT/AD,FORMAT/DP,FORMAT/GQ \
      proband.norm.vcf.gz -Oz -o proband.clean.vcf.gz

    bcftools annotate -x INFO,^FORMAT/GT,FORMAT/AD,FORMAT/DP,FORMAT/GQ \
      mother.norm.vcf.gz  -Oz -o mother.clean.vcf.gz

    bcftools annotate -x INFO,^FORMAT/GT,FORMAT/AD,FORMAT/DP,FORMAT/GQ \
      father.norm.vcf.gz  -Oz -o father.clean.vcf.gz

    # Index the cleaned VCFs
    tabix -p vcf proband.clean.vcf.gz
    tabix -p vcf mother.clean.vcf.gz
    tabix -p vcf father.clean.vcf.gz

## 2. Merge Trio into a Single VCF

Goal:

- Combine the proband, mother, and father into a single VCF.
- Retain only biallelic and informative variants.
- Remove positions where all trio members are homozygous for the reference (0/0).

If the input files are gVCFs, you can directly merge them, as they already include all genomic positions.
If they are standard VCFs, merge the files first and then remove missing genotypes (`./.`) to keep only fully called variants.

    #--------------------------------------------------------------
    # Option 1: For standard VCFs
    #--------------------------------------------------------------

    # Merge the three individuals
    bcftools merge \
      proband.clean.vcf.gz \
      mother.clean.vcf.gz \
      father.clean.vcf.gz \
     -Oz -o trio_merged_raw.vcf.gz

    # Retain only biallelic variants
    bcftools view -m2 -M2 trio_merged_raw.vcf.gz -Oz -o trio_merged_biallelic.vcf.gz

    # Remove sites where all genotypes are homozygous reference (0/0)
    bcftools view \
      -i 'COUNT(FORMAT/GT="0/0") != 3' \
      trio_merged_biallelic.vcf.gz -Oz -o trio_merged_nohom.vcf.gz

    # Remove missing genotypes (./.) to keep only fully called variants
    bcftools view \
      -e 'GT="./."' \
      trio_merged_nohom.vcf.gz -Oz -o trio_merged_clean.vcf.gz

    #--------------------------------------------------------------
    # Option 2: For gVCFs
    #--------------------------------------------------------------

    # gVCFs already include all genomic sites, so intersection is not needed
    bcftools merge \
      proband.clean.vcf.gz \
      mother.clean.vcf.gz \
      father.clean.vcf.gz \
      -Oz -o trio_merged_raw.vcf.gz

    # Retain only biallelic variants
    bcftools view -m2 -M2 trio_merged_raw.vcf.gz -Oz -o trio_merged_biallelic.vcf.gz

    # Remove sites where all are 0/0 (non-informative for UPD analysis)
    bcftools view \
      -i 'COUNT(FORMAT/GT="0/0") != 3' \
      trio_merged_biallelic.vcf.gz -Oz -o trio_merged_clean.vcf.gz

    #--------------------------------------------------------------
    # Normalize and index the merged VCF
    #--------------------------------------------------------------

    # Normalize (split multi-allelics if any remain and remove duplicates)
    bcftools norm -m -both -d all -Oz -o trio_merged_norm.vcf.gz trio_merged_clean.vcf.gz

    # Index for downstream tools
    tabix -p vcf trio_merged_norm.vcf.gz

## 3. Mask Structural Variant Regions

Before detecting UPD events, it is recommended to exclude genomic regions prone to alignment artifacts or abnormal variant density — such as centromeres, segmental duplications, and immune complex regions (e.g., HLA and KIR).
These regions can lead to false-positive signals due to mapping ambiguity or high polymorphism.

To simplify this step, a curated set of BED masks is available in the following Zenodo repository:
🔗 Zenodo – UPDhmm Excluded Regions

The repository provides BED files for both reference genome builds:

- `hg19_excluded_regions.bed`
- `hg38_excluded_regions.bed`

These files include merged genomic intervals covering:

- Centromeric and telomeric regions
- Segmental duplications
- HLA and KIR loci
- Low-mappability or highly repetitive regions

Download the appropriate BED file for your genome build and use it to mask excluded regions from the merged trio VCF:

    # Mask problematic regions
    bcftools view -T ^merged_mask.bed \
      trio_merged_norm.vcf.gz -Oz -o trio_masked.vcf.gz

    # Index the masked VCF
    tabix -p vcf trio_masked.vcf.gz

# Session Info

    sessionInfo()

    ## R version 4.6.0 Patched (2026-05-01 r89994)
    ## Platform: aarch64-apple-darwin23
    ## Running under: macOS Tahoe 26.3.1
    ##
    ## Matrix products: default
    ## BLAS:   /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRblas.0.dylib
    ## LAPACK: /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1
    ##
    ## locale:
    ## [1] C/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
    ##
    ## time zone: America/New_York
    ## tzcode source: internal
    ##
    ## attached base packages:
    ## [1] stats4    stats     graphics  grDevices utils     datasets  methods
    ## [8] base
    ##
    ## other attached packages:
    ##  [1] karyoploteR_1.39.0          regioneR_1.45.0
    ##  [3] VariantAnnotation_1.59.0    Rsamtools_2.29.0
    ##  [5] Biostrings_2.81.2           XVector_0.53.0
    ##  [7] SummarizedExperiment_1.43.0 Biobase_2.73.1
    ##  [9] GenomicRanges_1.65.0        IRanges_2.47.2
    ## [11] S4Vectors_0.51.3            Seqinfo_1.3.0
    ## [13] MatrixGenerics_1.25.0       matrixStats_1.5.0
    ## [15] BiocGenerics_0.59.6         generics_0.1.4
    ## [17] dplyr_1.2.1                 UPDhmm_1.9.0
    ## [19] BiocStyle_2.41.0
    ##
    ## loaded via a namespace (and not attached):
    ##   [1] DBI_1.3.0                bitops_1.0-9             gridExtra_2.3
    ##   [4] rlang_1.2.0              magrittr_2.0.5           biovizBase_1.61.0
    ##   [7] otel_0.2.0               compiler_4.6.0           RSQLite_3.53.1
    ##  [10] GenomicFeatures_1.65.0   png_0.1-9                vctrs_0.7.3
    ##  [13] ProtGenerics_1.45.0      stringr_1.6.0            pkgconfig_2.0.3
    ##  [16] crayon_1.5.3             fastmap_1.2.0            magick_2.9.1
    ##  [19] backports_1.5.1          rmarkdown_2.31           UCSC.utils_1.9.0
    ##  [22] tinytex_0.59             bit_4.6.0                xfun_0.58
    ##  [25] cachem_1.1.0             cigarillo_1.3.0          GenomeInfoDb_1.49.1
    ##  [28] jsonlite_2.0.0           blob_1.3.0               DelayedArray_0.39.3
    ##  [31] BiocParallel_1.47.0      parallel_4.6.0           cluster_2.1.8.2
    ##  [34] R6_2.6.1                 stringi_1.8.7            bslib_0.11.0
    ##  [37] RColorBrewer_1.1-3       bezier_1.1.2             rtracklayer_1.73.0
    ##  [40] rpart_4.1.27             jquerylib_0.1.4          Rcpp_1.1.1-1.1
    ##  [43] bookdown_0.46            knitr_1.51               base64enc_0.1-6
    ##  [46] BiocBaseUtils_1.15.1     Matrix_1.7-5             nnet_7.3-20
    ##  [49] tidyselect_1.2.1         rstudioapi_0.18.0        dichromat_2.0-0.1
    ##  [52] abind_1.4-8              yaml_2.3.12              codetools_0.2-20
    ##  [55] curl_7.1.0               lattice_0.22-9           tibble_3.3.1
    ##  [58] KEGGREST_1.53.0          S7_0.2.2                 evaluate_1.0.5
    ##  [61] foreign_0.8-91           pillar_1.11.1            BiocManager_1.30.27
    ##  [64] checkmate_2.3.4          RCurl_1.98-1.18          ensembldb_2.37.1
    ##  [67] ggplot2_4.0.3            scales_1.4.0             glue_1.8.1
    ##  [70] lazyeval_0.2.3           Hmisc_5.2-5              tools_4.6.0
    ##  [73] BiocIO_1.23.3            data.table_1.18.4        BSgenome_1.81.0
    ##  [76] GenomicAlignments_1.49.0 XML_3.99-0.23            grid_4.6.0
    ##  [79] colorspace_2.1-2         AnnotationDbi_1.75.0     htmlTable_2.5.0
    ##  [82] restfulr_0.0.16          Formula_1.2-5            cli_3.6.6
    ##  [85] HMM_1.0.2                S4Arrays_1.13.0          AnnotationFilter_1.37.0
    ##  [88] gtable_0.3.6             sass_0.4.10              digest_0.6.39
    ##  [91] SparseArray_1.13.2       rjson_0.2.23             htmlwidgets_1.6.4
    ##  [94] farver_2.1.2             memoise_2.0.1            htmltools_0.5.9
    ##  [97] lifecycle_1.0.5          httr_1.4.8               bit64_4.8.2
    ## [100] bamsignals_1.45.1