Skip to contents

Overview

colocPipeline() runs pairwise QTL ↔︎ GWAS colocalization using coloc::coloc.bf_bf on the SuSiE log Bayes-factor (LBF) matrices carried by each fine-mapping entry. For multi-trait colocalization across many QTL outcomes in one model, use colocboostPipeline instead.

Inputs:

  • QTL input — a QtlFineMappingResult produced by fineMappingPipeline.
  • GWAS input — either a GwasSumStats (fine-mapping run internally) or a GwasFineMappingResult (used directly).

The output is a long-format data frame with one row per (QTL tuple, GWAS tuple, credible-set pair) combination and the standard coloc posterior columns PP.H0.abfPP.H4.abf.

Bundled inputs

data(qtl_dataset_example, gwas_sumstats_s4_example)

# Build a QtlFineMappingResult from the bundled QtlDataset.
qtlFmr <- fineMappingPipeline(qtl_dataset_example, methods = "susie",
                               cisWindow = 1e6)

QTL FMR + GWAS sumstats (inline GWAS fine-mapping)

The recommend approach is to provide colocPipeline() a QtlFineMappingResult and a GwasSumStats. The pipeline runs fineMappingPipeline() internally on the GWAS sumstats (with finemappingMethods) over the exact window used in the QtlFineMappingResult, then runs coloc.bf_bf per (QTL, GWAS) pair.

res <- colocPipeline(
  qtlFineMappingResult = qtlFmr,
  gwasInput            = gwas_sumstats_s4_example,
  finemappingMethods   = "susie")
head(res)
##    study context        trait method gwasStudy gwasMethod nsnps
## 1 study1   brain ENSG_example  susie    trait1      susie   198
## 2 study1   brain ENSG_example  susie    trait1      susie   198
## 3 study1   brain ENSG_example  susie    trait1      susie   198
## 4 study1   brain ENSG_example  susie    trait1      susie   198
## 5 study1   brain ENSG_example  susie    trait1      susie   198
## 6 study1   brain ENSG_example  susie    trait1      susie   198
##                 hit1               hit2 PP.H0.abf PP.H1.abf  PP.H2.abf
## 1 chr22:15611133:C:G chr22:15698333:A:G         0         0 0.83948430
## 2 chr22:15611133:C:G chr22:15570730:C:T         0         0 0.07236177
## 3 chr22:15611133:C:G chr22:15567276:C:T         0         0 0.08044104
## 4 chr22:15611133:C:G chr22:15569194:A:G         0         0 0.07556434
## 5 chr22:15611133:C:G chr22:15567276:C:T         0         0 0.08044104
## 6 chr22:15611133:C:G chr22:15776459:C:T         0         0 0.82919861
##    PP.H3.abf  PP.H4.abf idx1 idx2 nSnps
## 1 0.14897480 0.01154090    1    1    NA
## 2 0.01101005 0.91662818    1    2    NA
## 3 0.01246308 0.90709588    1    3    NA
## 4 0.01158602 0.91284964    1    4    NA
## 5 0.01246308 0.90709588    1    5    NA
## 6 0.14712494 0.02367645    1    6    NA

Use returnGwasFineMapping = TRUE to get the inline GWAS FMR back as an attribute on the result:

res2 <- colocPipeline(
  qtlFineMappingResult  = qtlFmr,
  gwasInput             = gwas_sumstats_s4_example,
  returnGwasFineMapping = TRUE)
attr(res2, "gwasFineMapping")

If the QTL FineMappingResult has an LD sketch because it was run on summary statistics it must match the LD sketch for the GWASSumStats.

QTL FMR + pre-computed GWAS FMR

If you already have a GwasFineMappingResult (typically computed over LD blocks), you can use that fine-mapping result directly:

gwasFmr <- fineMappingPipeline(gwas_sumstats_s4_example, methods = "susie")
colocPipeline(qtlFineMappingResult = qtlFmr,
              gwasInput            = gwasFmr)

The disadvantage of this approach is that LD blocks will not align with cis-QTL windows. Ultimately this means that the variable selection in the QTL and GWAS fine-mapping will have been done over different variant sets, which may reduce the sensitivity for colocalizations, particuarly in areas with complex LD.

Filtering effects fed into coloc

coloc::coloc.bf_bf accepts one LBF matrix for the QTL and one for hte GWAS. By default, every effect with non-trivial prior variance (V > priorTol) gets included. Two opt-in filters can adjust this:

Filter Description Default
filterLbfCs TRUE keeps only effects that produced a credible set (trimmedFit$sets$cs_index). FALSE
filterLbfCsSecondary Numeric coverage in (0,1). Runs a CS-concentration filter at that coverage. NULL
filterLbfCsConcentration Numeric in (0,1). Concentration factor: a CS at coverage X is kept only if it spans fewer than nVariants * X * concentration variants. 0.5
priorTol Drop effects whose estimated prior variance is at or below this threshold. 1e-9
colocPipeline(
  qtlFineMappingResult     = qtlFmr,
  gwasInput                = gwas_sumstats_s4_example,
  filterLbfCsSecondary     = 0.5,   # 50% CS concentration filter
  filterLbfCsConcentration = 0.5)   # span < 25% of locus variants

Enrichment-aware coloc (enloc mode)

Pass a per-(gwasStudy, qtlContext) enrichment table (the output of qtlEnrichmentPipeline()) to scale the shared-signal prior:

p_{12}^{\text{used}} = \min\bigl(p_{12}\,(1 + \text{enrichment}),\, p_{12,\max}\bigr)

Pairs without a matching enrichment row fall back to the baseline p12 with a warning. Two extra columns are added to the output: enrichment (the lookup) and p12Used (what was actually passed to coloc.bf_bf).

enrichmentTable <- data.frame(
  gwasStudy  = "trait1",
  qtlContext = "brain",
  enrichment = 2.5,
  stringsAsFactors = FALSE)
colocPipeline(
  qtlFineMappingResult = qtlFmr,
  gwasInput            = gwas_sumstats_s4_example,
  enrichment           = enrichmentTable,
  p12Max               = 1e-3)

PIP renormalization on variant intersection

When the QTL and GWAS fine-mapping results were fit on different variant sets (common when the user declines RAISS imputation, or when the GWAS FMR carries variants the QTL FMR doesn’t), adjustPips = TRUE (default) renormalizes the PIPs for each objectl to the cross-FMR variant intersection before any per-pair inference. Pass FALSE to use the FMRs as supplied.

colocPipeline(
  qtlFineMappingResult = qtlFmr,
  gwasInput            = gwas_sumstats_s4_example,
  adjustPips           = TRUE)   # default

Common parameters

colocPipeline(
  qtlFineMappingResult     = qtlFmr,
  gwasInput                = gwas_sumstats_s4_example,
  filterLbfCs              = FALSE,
  filterLbfCsSecondary     = NULL,    # e.g. 0.5
  filterLbfCsConcentration = 0.5,
  priorTol                 = 1e-9,
  p1                       = 1e-4,
  p2                       = 1e-4,
  p12                      = 5e-6,
  finemappingMethods       = "susie", # inline GWAS FM when needed
  returnGwasFineMapping    = FALSE,
  enrichment               = NULL,    # data.frame for enloc mode
  p12Max                   = 1e-3,
  adjustPips               = TRUE)

Reading the result

str(res, max.level = 1L)
## 'data.frame':    20 obs. of  17 variables:
##  $ study     : chr  "study1" "study1" "study1" "study1" ...
##  $ context   : chr  "brain" "brain" "brain" "brain" ...
##  $ trait     : chr  "ENSG_example" "ENSG_example" "ENSG_example" "ENSG_example" ...
##  $ method    : chr  "susie" "susie" "susie" "susie" ...
##  $ gwasStudy : chr  "trait1" "trait1" "trait1" "trait1" ...
##  $ gwasMethod: chr  "susie" "susie" "susie" "susie" ...
##  $ nsnps     : int  198 198 198 198 198 198 198 198 198 198 ...
##  $ hit1      : chr  "chr22:15611133:C:G" "chr22:15611133:C:G" "chr22:15611133:C:G" "chr22:15611133:C:G" ...
##  $ hit2      : chr  "chr22:15698333:A:G" "chr22:15570730:C:T" "chr22:15567276:C:T" "chr22:15569194:A:G" ...
##  $ PP.H0.abf : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ PP.H1.abf : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ PP.H2.abf : num  0.8395 0.0724 0.0804 0.0756 0.0804 ...
##  $ PP.H3.abf : num  0.149 0.011 0.0125 0.0116 0.0125 ...
##  $ PP.H4.abf : num  0.0115 0.9166 0.9071 0.9128 0.9071 ...
##  $ idx1      : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ idx2      : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ nSnps     : logi  NA NA NA NA NA NA ...
head(res[order(res$PP.H4.abf, decreasing = TRUE), ])
##     study context        trait method gwasStudy gwasMethod nsnps
## 2  study1   brain ENSG_example  susie    trait1      susie   198
## 4  study1   brain ENSG_example  susie    trait1      susie   198
## 7  study1   brain ENSG_example  susie    trait1      susie   198
## 3  study1   brain ENSG_example  susie    trait1      susie   198
## 5  study1   brain ENSG_example  susie    trait1      susie   198
## 10 study1   brain ENSG_example  susie    trait1      susie   198
##                  hit1               hit2 PP.H0.abf PP.H1.abf  PP.H2.abf
## 2  chr22:15611133:C:G chr22:15570730:C:T         0         0 0.07236177
## 4  chr22:15611133:C:G chr22:15569194:A:G         0         0 0.07556434
## 7  chr22:15611133:C:G chr22:15569194:A:G         0         0 0.07556434
## 3  chr22:15611133:C:G chr22:15567276:C:T         0         0 0.08044104
## 5  chr22:15611133:C:G chr22:15567276:C:T         0         0 0.08044104
## 10 chr22:15611133:C:G chr22:15567276:C:T         0         0 0.08044104
##     PP.H3.abf PP.H4.abf idx1 idx2 nSnps
## 2  0.01101005 0.9166282    1    2    NA
## 4  0.01158602 0.9128496    1    4    NA
## 7  0.01158602 0.9128496    1    7    NA
## 3  0.01246308 0.9070959    1    3    NA
## 5  0.01246308 0.9070959    1    5    NA
## 10 0.01246308 0.9070959    1   10    NA

Each row is one CS-pair combination; in particular the idx1 / idx2 columns identify the QTL / GWAS effect indices within the respective LBF matrices, and PP.H4.abf is the standard coloc shared-signal posterior.