IBS/IBD Neighbor Computation Example

This example demonstrates Stage 2 of the GRiD workflow: using computeIBSpbwt to generate the IBS neighbors file required by GRiD for haploid copy number estimation (Step 5).

The script automatically sources locus coordinates (chromosome and focal midpoint) derived during Stage 1 from data/pipeline_vars.sh.

02-run-ibs.sh — Stage 2: Compute IBS neighbors via PBWT
  1#!/bin/bash
  2#SBATCH --job-name=grid_ibs
  3#SBATCH --output=slurm/%x.out
  4#SBATCH --error=slurm/%x.err
  5#SBATCH --time=2-00:00:00
  6#SBATCH --cpus-per-task=4
  7#SBATCH --mem=100G
  8
  9# Stage 2 of 3 — compute IBS neighbors (needed for haploid CN estimation).
 10# Submit after 01_prep_data.sh completes; sources data/pipeline_vars.sh for
 11# CHR/FOCAL_BP rather than re-deriving them, so this can't disagree with
 12# stage 1's locus coordinates.
 13#
 14# Usage: sbatch 02_run_ibs.sh   (from the same working directory as stage 1)
 15
 16set -euo pipefail
 17
 18module load samtools
 19
 20NUM_NEIGHBORS=200
 21while [[ $# -gt 0 ]]; do
 22    case $1 in
 23        --num-neighbors) NUM_NEIGHBORS="$2"; shift 2 ;;
 24        -h|--help)
 25            echo "Usage: $0 [--num-neighbors N]"
 26            exit 0 ;;
 27        *)
 28            echo "Unknown argument: $1"
 29            exit 1 ;;
 30    esac
 31done
 32
 33WORK_DIR="${WORK_DIR:-$(pwd)}"
 34LOG_DIR="$WORK_DIR/logs"
 35DATA_DIR="$WORK_DIR/data"
 36OUTPUT_DIR="$WORK_DIR/output"
 37QC_DIR="$WORK_DIR/qctool"
 38mkdir -p "$DATA_DIR" "$LOG_DIR" "$OUTPUT_DIR" "$WORK_DIR/slurm" "$QC_DIR"
 39
 40THREADS="${SLURM_CPUS_PER_TASK:-$(nproc)}"
 41
 42timestamp() { date '+%Y-%m-%d %H:%M:%S'; }
 43log() { echo "[$(timestamp)] $*" | tee -a "$LOG_DIR/IBS.log"; }
 44
 45download_with_retry() {
 46    local url="$1" out="$2" attempt
 47    for attempt in 1 2 3 4 5; do
 48        if wget -q --tries=1 --timeout=60 -O "$out" "$url"; then
 49            return 0
 50        fi
 51        rm -f "$out"
 52        sleep $(( attempt * 3 + RANDOM % 3 ))
 53    done
 54    echo "ERROR: failed to download $url after 5 attempts" >&2
 55    return 1
 56}
 57
 58# --- Load locus coordinates written by 01_prep_data.sh ---
 59VARS_FILE="$DATA_DIR/pipeline_vars.sh"
 60if [[ ! -f "$VARS_FILE" ]]; then
 61    echo "ERROR: $VARS_FILE not found — run 01_prep_data.sh first."
 62    exit 1
 63fi
 64source "$VARS_FILE"
 65
 66if ! command -v "$WORK_DIR/qctool/qctool" &> /dev/null; then
 67    log "Installing qctool..."
 68
 69    download_with_retry \
 70        "https://zenodo.org/records/22307601/files/qctool.gz?download=1" \
 71        "$QC_DIR/qctool.gz"
 72
 73    gunzip -f "$QC_DIR/qctool.gz"
 74
 75    chmod +x "$WORK_DIR/qctool/qctool"
 76fi
 77
 78MISSING=()
 79for cmd in "$WORK_DIR/qctool/qctool" wget samtools; do
 80    command -v "$cmd" &>/dev/null || MISSING+=("$cmd")
 81done
 82if [[ ${#MISSING[@]} -gt 0 ]]; then
 83    log "ERROR: missing required tools: ${MISSING[*]}"
 84    exit 1
 85fi
 86
 87COMPUTE_IBS="$WORK_DIR/computeIBSpbwt"
 88if [[ ! -f "$COMPUTE_IBS" ]]; then
 89    log "Downloading computeIBSpbwt binary..."
 90    download_with_retry \
 91        "https://raw.githubusercontent.com/mhujoel/STRs/main/cpp_files/computeIBSpbwt" \
 92        "$COMPUTE_IBS"
 93    chmod +x "$COMPUTE_IBS"
 94fi
 95
 96PHASED_VCF_URL="https://ftp.1000genomes.ebi.ac.uk/vol1/ftp/data_collections/1000G_2504_high_coverage/working/20220422_3202_phased_SNV_INDEL_SV/1kGP_high_coverage_Illumina.chr${CHR}.filtered.SNV_INDEL_SV_phased_panel.vcf.gz"
 97GENETIC_MAP_URL="https://alkesgroup.broadinstitute.org/Eagle/downloads/tables/genetic_map_hg38_withX.txt.gz"
 98
 99LPA_VCF="$DATA_DIR/1kGP_chr${CHR}_LPA_phased.vcf.gz"
100BGEN_FILE="$DATA_DIR/1kGP_chr${CHR}_LPA_phased.bgen"
101SAMPLE_FILE="$DATA_DIR/1kGP_chr${CHR}_LPA_phased.sample"
102GENETIC_MAP="$DATA_DIR/genetic_map_hg38_chr${CHR}.txt"
103OUTPUT_FILE="$DATA_DIR/ibs_neighbors_chr${CHR}.tsv.gz"
104
105# --- Stream LPA region from the 1000G phased VCF ---
106if [[ ! -f "$LPA_VCF" ]]; then
107    log "Streaming LPA region from 1000G phased VCF..."
108    tabix -h "$PHASED_VCF_URL" "$REGION" | bgzip > "$LPA_VCF"
109    tabix -p vcf "$LPA_VCF"
110    find "$WORK_DIR" -maxdepth 1 -name "*.tbi" ! -path "${LPA_VCF}.tbi" -delete
111    log "LPA phased VCF ready: $LPA_VCF"
112else
113    log "LPA phased VCF already present — skipping."
114fi
115
116# --- Convert phased VCF -> BGEN v1.2 ---
117if [[ ! -f "$BGEN_FILE" ]]; then
118    log "Converting phased VCF to BGEN v1.2..."
119    "$WORK_DIR/qctool/qctool" \
120        -g "$LPA_VCF" \
121        -og "$BGEN_FILE" \
122        -os "$SAMPLE_FILE" \
123        -ofiletype bgen_v1.2 \
124        -bgen-bits 16 \
125        -bgen-permitted-input-rounding-error 0 \
126        >> "$LOG_DIR/qctool.log" 2>&1
127    log "BGEN file ready: $BGEN_FILE"
128else
129    log "BGEN file already present — skipping."
130fi
131
132# --- Download + decompress + filter Eagle genetic map ---
133# The map's chrom column is bare (e.g. "6"), not "chr6" — filtering on
134# "chr${CHR}" here would silently match nothing and produce a header-only
135# file, so this must stay as the bare chromosome number.
136if [[ ! -f "$GENETIC_MAP" ]]; then
137    log "Downloading Eagle hg38 genetic map..."
138    wget -q -O - "$GENETIC_MAP_URL" \
139        | gunzip \
140        | awk -v c="${CHR}" 'NR==1 || $1==c' \
141        > "$GENETIC_MAP"
142    log "Genetic map ready: $GENETIC_MAP"
143else
144    log "Genetic map already present — skipping."
145fi
146
147# --- Run computeIBSpbwt ---
148log "Computing IBS neighbors..."
149log "  CHR=$CHR  FOCAL_BP=$FOCAL_BP  NEIGHBORS=$NUM_NEIGHBORS  THREADS=$THREADS"
150
151"$COMPUTE_IBS" \
152    "$CHR"          \
153    "$FOCAL_BP"     \
154    "$BGEN_FILE"    \
155    "$SAMPLE_FILE"  \
156    "$GENETIC_MAP"  \
157    "$NUM_NEIGHBORS"\
158    "$THREADS"      \
159    "$OUTPUT_FILE"
160
161log "IBS neighbors written to: $OUTPUT_FILE"
162log "Next: submit 03_generate_config_and_run.sh"

Key Parameters & Environment Variables

The coordinates and variables used by 02-run-ibs.sh are sourced dynamically from Stage 1 (data/pipeline_vars.sh) or can be passed via command line options:

Parameter / Variable

Description

--num-neighbors

Number of IBS neighbors per haplotype (default: 200).

CHR

Target chromosome (e.g., 6, exported by Stage 1).

FOCAL_BP

Base pair position at center of VNTR (e.g., LPA KIV-2 midpoint in hg38, exported by Stage 1).

COMPUTE_IBS

Path to the auto-downloaded or local computeIBSpbwt binary.

PHASED_VCF_URL

1000 Genomes high-coverage phased VCF URL streamed for the target region via tabix.

GENETIC_MAP

Eagle hg38 genetic map auto-downloaded and filtered for chromosome CHR.

OUTPUT_FILE

Compressed output path (data/ibs_neighbors_chr${CHR}.tsv.gz).

Usage

Submit to SLURM after 01-prep-data.sh completes:

sbatch examples/02-run-ibs.sh

Override the default number of neighbors:

sbatch examples/02-run-ibs.sh --num-neighbors 100

Passing Output to GRiD

Stage 3 (03-run-grid.sh) automatically detects data/ibs_neighbors_chr${CHR}.tsv.gz upon completion and embeds the path directly into config.yaml:

compute_haploid_genotypes:
  run: True
  output_file_prefix: "haploid_genotypes"
  ibs_output: "data/ibs_neighbors_chr6.tsv.gz"
  min_neighbors: 1
  max_neighbors: 10
  n_iters: 100
  method: "ibs"