Fine-mapping with pecotmr
pecotmr authors
2026-07-30
Source:vignettes/fine-mapping.Rmd
fine-mapping.RmdOverview
fineMappingPipeline() is a single pipeline that can
accept any of the following inputs:
| Input class | What it represents | Methods supported |
|---|---|---|
QtlDataset |
Single-study individual-level data | susie, susieInf, susieAsh, mvsusie, fsusie, susieSer |
MultiStudyQtlDataset |
Multiple QtlDataset objects (optionally with an
embedded QtlSumStats) |
susie, susieInf, susieAsh, mvsusie, fsusie (individual-level only), susieSer (individual-level only) |
QtlSumStats |
QTL summary statistics annotated by
(study, context, trait)
|
susie, susieInf, susieAsh, mvsusie |
GwasSumStats |
GWAS summary statistics annotated by study
|
susie, susieInf, susieAsh, mvsusie |
Method arguments are the same across input classes;
fineMappingPipeline() routes methods = "susie"
to susieR::susie for individual-level data and to
susieR::susie_rss for summary-statistics inputs
automatically.
The output is always a FineMappingResult (a
DFrame-subclass collection of per-tuple FineMappingEntry
payloads).
Bundled inputs
data(qtl_dataset_example,
qtl_sumstats_example,
gwas_sumstats_s4_example,
multi_study_qtl_dataset_example)
qtl_dataset_example## QtlDataset for study 'study1'
## 1 context(s): brain
## 1 unique traits across contexts
## Genotypes: plink1 @ pecotmr://extdata/toy_canonical
## Genotype covariates: 0 cols
## Scale residuals: TRUE
The *_sumstats_example objects ship with a non-empty
qcInfo slot so they bypass the
summaryStatsQc() gate. In a real analysis you’d construct
the raw QtlSumStats / GwasSumStats from your
data, then run summaryStatsQc() to populate that slot (see
the summary-statistics QC vignette).
Individual-level fine-mapping
fineMappingPipeline() always needs to know which
genotype window to fit on. With an individual-level
QtlDataset, pass cisWindow (in basepairs
around each trait’s TSS), supply an explicit region, or set
both per-call.
fmr <- fineMappingPipeline(qtl_dataset_example,
methods = "susie",
cisWindow = 1e6)
fmr## QtlFineMappingResult: 1 entries
## 1 studies, 1 contexts, 1 traits, 1 methods
## LD sketch: NULL (individual-level fit)
Per-tuple PIPs:
pip <- getPip(fmr, study = "study1", context = "brain",
trait = "ENSG_example", method = "susie")
head(sort(pip, decreasing = TRUE), 5)## chr22:15611133:C:G chr22:15570730:C:T chr22:15569194:A:G chr22:15567276:C:T
## 0.2111065 0.1427403 0.1361272 0.1270685
## chr22:15594669:T:C
## 0.1169922
Credible sets:
getCs(fmr, study = "study1", context = "brain",
trait = "ENSG_example", method = "susie", coverage = 0.95)## [1] variant_id chrom pos A1 A2 N
## [7] af beta se pip logBF
## <0 rows> (or 0-length row.names)
The top_loci table consolidates per-method PIPs, CS
membership, and sumstats into one long-format data.frame:
head(getTopLoci(fmr, study = "study1", context = "brain",
trait = "ENSG_example", method = "susie"), 5)## variant_id chrom pos A1 A2 N af beta se
## 1 chr22:15567276:C:T 22 15567276 T C 165 0.1993865 0.033635519 0.09184189
## 2 chr22:15569194:A:G 22 15569194 G A 165 0.2006173 0.036217636 0.09504913
## 3 chr22:15570730:C:T 22 15570730 T C 165 0.2000000 0.038109622 0.09729834
## 4 chr22:15583103:G:A 22 15583103 A G 165 0.2639752 0.006303249 0.03957304
## 5 chr22:15594252:T:C 22 15594252 C T 165 0.1737805 0.021518343 0.07410824
## pip logBF cs_95 cs_70 cs_50 cs_95_purity cs_70_purity
## 1 0.12706853 5.418456 susie_0 susie_0 susie_0 0 0
## 2 0.13612718 5.487319 susie_0 susie_0 susie_0 0 0
## 3 0.14274027 5.534756 susie_0 susie_0 susie_0 0 0
## 4 0.02713469 3.874542 susie_0 susie_0 susie_0 0 0
## 5 0.08392514 5.003655 susie_0 susie_0 susie_0 0 0
## cs_50_purity within_cs_pip method gene event grange_start grange_end
## 1 0 NA susie <NA> <NA> NA NA
## 2 0 NA susie <NA> <NA> NA NA
## 3 0 NA susie <NA> <NA> NA NA
## 4 0 NA susie <NA> <NA> NA NA
## 5 0 NA susie <NA> <NA> NA NA
Multi-study fine-mapping
A MultiStudyQtlDataset runs the pipeline per-study and
concatenates the results into a single
QtlFineMappingResult:
msFmr <- fineMappingPipeline(multi_study_qtl_dataset_example,
methods = "susie",
cisWindow = 1e6)
table(msFmr$study)##
## study1 study2
## 1 1
QTL summary-statistics fine-mapping
fmrSs <- fineMappingPipeline(qtl_sumstats_example, methods = "susie")
fmrSs## QtlFineMappingResult: 1 entries
## 1 studies, 1 contexts, 1 traits, 1 methods
## LD sketch: plink1 @ pecotmr://extdata/toy_canonical
The QtlSumStats collection carries an
ldSketch GenotypeHandle; the pipeline pulls
the per-region LD from there automatically.
GWAS summary-statistics fine-mapping
fmrGwas <- fineMappingPipeline(gwas_sumstats_s4_example,
methods = "susie")
fmrGwas## GwasFineMappingResult: 1 entries
## 1 studies, 1 methods
## LD sketch: plink1 @ pecotmr://extdata/toy_canonical
The GWAS path is similar to the QTL-sumstats path but only annotates by study.
Common parameters
fineMappingPipeline(
qtl_dataset_example,
methods = c("susie", "susieInf"),
contexts = "brain",
traitId = "ENSG_example",
region = "chr22:25000000-26000000",
cisWindow = 5e5,
coverage = 0.95,
secondaryCoverage = c(0.7, 0.5),
signalCutoff = 0.025,
minAbsCorr = 0.8,
addSusieInf = TRUE,
naAction = "drop", # "drop" (default) or "impute"
verbose = 1)-
naActioncontrols how phenotype NAs are handled bygetResidualizedPhenotypes():"drop"removes samples with any NA across the requested traits,"impute"mean-imputes each trait independently. -
addSusieInf = TRUEruns SuSiE-inf first and uses its result to initialise the susie fit, which improves credible-set purity in regions with background polygenic signal. -
secondaryCoverageadds secondary CS columns at the requested coverages (alongside the primarycoverage); useful when you want both narrow and broad CS reports.
Joint multi-context / multi-trait fits
jointSpecification triggers the dispatch for cross-axis
joint methods (mvsusie for cross-context,
mvsusie or fsusie for multi-trait):
fineMappingPipeline(
multi_study_qtl_dataset_example,
methods = "mvsusie",
jointSpecification = list(axis = "context",
contexts = c("brain", "liver")))See ?jointSpecification for the specification
grammar.
Reading the result
FineMappingResult is a DFrame subclass: subsetting with
[, concatenating with c(), and column access
via $ all work as on a DataFrame. The per-tuple payload
lives in the entry column as a
FineMappingEntry:
entry <- fmr$entry[[1L]]
class(entry)## [1] "FineMappingEntry"
## attr(,"package")
## [1] "pecotmr"
slotNames(entry)## [1] "variantIds" "susieFit" "topLoci" "cvResult"
Each entry carries:
-
variantIds— the LD-aligned variant set the fit was computed on -
trimmedFit— a slim list containingalpha,lbf_variable,mu,mu2,X_column_scale_factors,pip, and credible-set metadata -
topLoci— the long-format per-variant summary used by downstream pipelines andvcfWriter -
sumstats— optional sumstats passed through for reporting
Next steps
-
QtlFineMappingResultis used bycolocPipelinefor QTL-GWAS colocalization and bytwasWeightsPipelineso that fine-mapping weights are contributed to the TWAS ensemble weights model alongside regularized regression methods. - Run the full
causalInferencePipeline(TWAS + MR) with aFineMappingResultandGwasSumStats.