Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Chromosome-Specific Enrichment Analysis of Annotations Using Block Jackknife

Tests how strongly a set of significant variants overlaps a genomic annotation relative to the genome, with block-jackknife standard errors.

Overview

A variant set that overlaps an annotation more often than chance would predict is evidence that the annotation marks functional sequence. Counting the overlap is easy; putting an error bar on it is not, because variants are correlated along the genome and so cannot be resampled independently.

This module computes an odds ratio and an enrichment statistic for each annotation, then leaves out one chromosome at a time and recomputes, using the spread across those 22 leave-one-out estimates as a block-jackknife standard error. Blocking by chromosome keeps correlated variants together rather than splitting them across resamples.

When to run it. Run this module after chromosome-level enrichment inputs are available when a combined enrichment estimate and block-jackknife standard error are needed.

Definitions and test statistics

Odds Ratio (OR)

Strength of association between significant variants and an annotation:

OR=∣AB∣/∣A∖B∣∣B∖A∣/∣noA-noB∣OR = \frac{\left| AB \right| / \left| A \setminus B \right|}{\left| B \setminus A \right| / \left| \text{noA-noB} \right|}

where AA = SNPs in the annotation, BB = significant SNPs, ABAB = their intersection, and noA-noB = SNPs in neither.

Enrichment

Whether an annotation contains a higher proportion of significant SNPs than expected by chance:

Enrichment=∣AB∣/∣B∣∣A∣/∣Target Set∣\text{Enrichment} = \frac{|AB|/|B|}{|A|/|\text{Target Set}|}

i.e. proportion of significant SNPs in the annotation divided by proportion of all SNPs in the annotation, where the Target Set is all SNPs in the genome or study region.

Standard Error (LOCO block jackknife)

Standard errors are estimated by removing one chromosome at a time and recomputing the statistic, capturing variability due to genomic structure. With θi\theta_i the statistic (ORiOR_i or Enrichmenti\text{Enrichment}_i) excluding chromosome ii, θˉ\bar{\theta} its mean, and NN the number of chromosomes (22 for autosomes):

SE(θ)=∑i=1N(θi−θˉ)2N⋅(N−1)\text{SE}(\theta) = \sqrt{\frac{\sum_{i=1}^{N} (\theta_i - \bar{\theta})^2}{N \cdot (N-1)}}
<Figure size 1400x1100 with 1 Axes>

When to run it. After a significant variant set exists and an annotation is available to test it against.

Input

  • --significant-variants-path: the variant set being tested, two columns chr and pos with a header. Required. Example tests/fixtures/eoo_enrichment/protocol_example.eoo_significant_variants.tsv.gz:

    chr  pos
    1    100015157
    1    1000291
  • --baseline-anno-path: the annotation table covering the genome, one row per variant, with the annotation columns starting at --annotations-start. Required. Example input/enrichment/protocol_example.eoo_baseline_annotation.tsv:

    chr  BP        ref  alt  rsid    maf     ANNO_baseline
    1    10000654  A    C    rs1_0   0.3734  0
    1    10100228  C    T    rs1_1   0.0602  0
  • --annotations-start: the 1-based column index at which the annotation columns begin, 7 by default. Everything left of it is treated as variant identity and frequency.

  • --trait and --annotation-name: labels, both required. They carry no analytic meaning; the output file is named {trait}.{annotation-name}.enrichment_results.rds.

  • --cwd: the directory outputs are written to.

  • --numThreads: threads for the jackknife, 8 by default.

Output

  • {cwd}/enrichment/{trait}.{annotation-name}.enrichment_results.rds - a list of 10 holding the point estimates, their block-jackknife standard errors and the per-chromosome estimates they derive from. Example output/eoo_enrichment/enrichment/protocol_example.baseline.enrichment_results.rds:

    List of 10
     $ summary                 :'data.frame':  2 obs. of  13 variables:
      ..$ Annotation           : chr [1:2] "maf" "ANNO_baseline"
      ..$ OR                   : num [1:2] 1 1
      ..$ OR_SE                : num [1:2] 0 0
      ..$ Enrichment           : num [1:2] 1 1
      ..$ Enrichment_SE        : num [1:2] 0 0
     $ OR_blockJacknife        : num [1:22, 1:2] 1 1 1 1 1 1 1 1 1 1 ...
     $ Enrichment_blockJacknife: num [1:22, 1:2] 1 1 1 1 1 1 1 1 1 1 ...
     $ OR                      : Named num [1:2] 0 0
     $ Enrichment              : Named num [1:2] 1 1

    summary carries one row per annotation column, here maf and ANNO_baseline. The two blockJacknife matrices are 22 by 2: one row per chromosome left out, one column per annotation, and the spread down each column is what the standard errors are computed from. On this toy annotation every variant scores 0, so the odds ratios come back at 1 with zero standard error; that is the expected result for an annotation with no signal, not a failed run.

Minimal Working Example

One workflow, enrichment, run once per annotation. --trait and --annotation-name are labels only; together they name the output file.

Timing: TBD (on toy dataset)

Command Interface

ERROR: Notebook JSON is invalid: %s
usage: sos run code/SoS/enrichment/eoo_enrichment.ipynb
               [workflow_name | -t targets] [options] [workflow_options]
  workflow_name:        Single or combined workflows defined in this script
  targets:              One or more targets to generate
  options:              Single-hyphen sos parameters (see "sos run -h" for details)
  workflow_options:     Double-hyphen workflow-specific parameters

Workflows:
  enrichment

Global Workflow Options:
  --cwd output (as path)
                        Path to the work directory of the analysis.
  --modular-script-dir code/script (as path)
  --significant-variants-path VAL (as path, required)
  --baseline-anno-path VAL (as path, required)
  --numThreads 8 (as int)
                        Number of threads
  --trait VAL (as str, required)
                        For cluster jobs, number commands to run per job
  --annotation-name VAL (as str, required)
  --job-size 1 (as int)
  --walltime 12h
  --mem 16G

Sections
  enrichment:
    Workflow Options:
      --annotations-start 7 (as int)

Workflow implementation