Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ mrbase.oauth
*.rdx
*.rdb

*_cache/
.DS_Store
53 changes: 38 additions & 15 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,21 +1,44 @@
Package: tryx
Title: MR-TRYX (treasure your exceptions)
Version: 0.2.0
Authors@R: c(person("Gibran", "Hemani", email = "g.hemani@bristol.ac.uk", role = c("aut", "cre")), person("Yoonsu", "Cho", email = "yoonsu.cho@bristol.ac.uk", role = c("aut")))
Description: Heterogeneity in MR analyses can arise due to horizontal pleiotropy. This package uses MR-Base to identify possible traits that can explain the heterogeneity, with a view to identifying novel putative associations, and adjusting for their influences to reduce heterogeneity and improve power.
Depends: R (>= 3.6.0),
TwoSampleMR,
dplyr,
RadialMR,
magrittr,
tidyr,
ggplot2,
glmnet,
ggrepel
Version: 0.2.1
Authors@R: c(
person("Gibran", "Hemani", , "g.hemani@bristol.ac.uk", role = c("aut", "cre")),
person("Yoonsu", "Cho", , "yoonsu.cho@bristol.ac.uk", role = "aut")
)
Description: Heterogeneity in MR analyses can arise due to horizontal
pleiotropy. This package uses MR-Base to identify possible traits that
can explain the heterogeneity, with a view to identifying novel
putative associations, and adjusting for their influences to reduce
heterogeneity and improve power.
License: MIT + file LICENSE
URL: https://mrcieu.r-universe.dev/tryx,
https://explodecomputer.github.io/tryx/,
https://github.com/explodecomputer/tryx
BugReports: https://github.com/explodecomputer/tryx/issues
Depends:
R (>= 4.1.0)
Imports:
dplyr,
ggplot2,
ggrepel,
glmnet,
magrittr,
R6,
RadialMR,
tibble,
tidyr,
TwoSampleMR
Suggests:
igraph,
knitr,
rmarkdown,
simulateGP,
testthat
License: MIT + file LICENSE
VignetteBuilder:
knitr
Remotes:
explodecomputer/simulateGP,
MRCIEU/TwoSampleMR,
WSpiller/RadialMR
Config/roxygen2/version: 8.1.0
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.0.2
60 changes: 60 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,63 @@ export(tryx.scan)
export(tryx.sig)
export(tryx.simulate)
export(volcano_plot)
importFrom(R6,R6Class)
importFrom(TwoSampleMR,
available_outcomes,
extract_instruments,
extract_outcome_data,
harmonise_data,
mr,
mr_heterogeneity,
mr_method_list,
mv_extract_exposures,
mv_harmonise_data,
mv_multiple
)
importFrom(dplyr,
arrange,
bind_rows,
desc,
do,
filter,
group_by,
mutate,
n,
summarise
)
importFrom(ggplot2,
aes,
arrow,
element_blank,
element_text,
facet_grid,
geom_abline,
geom_errorbarh,
geom_point,
geom_segment,
geom_vline,
ggplot,
labs,
scale_colour_brewer,
theme,
theme_bw,
unit,
xlim,
ylim
)
importFrom(ggrepel,geom_label_repel)
importFrom(magrittr,
"%$%",
"%>%"
)
importFrom(stats,
as.formula,
coef,
coefficients,
lm,
p.adjust,
rnorm,
sd
)
importFrom(tibble,tibble)
importFrom(utils,combn)
36 changes: 5 additions & 31 deletions R/adjustment.r
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ tryx.adjustment.mv <- function(tryxscan, lasso=TRUE, id_remove=NULL, proxies=FAL
#' @param tryxscan Output from \code{tryx.scan}
#' @param plot Whether to plot or not. Default is TRUE
#' @param id_remove List of IDs to exclude from the adjustment analysis. It is possible that in the outlier search a candidate trait will come up which is essentially just a surrogate for the outcome trait (e.g. if you are analysing coronary heart disease as the outcome then a variable related to heart disease medication might come up as a candidate trait). Adjusting for a trait which is essentially the same as the outcome will erroneously nullify the result, so visually inspect the candidate trait list and remove those that are inappropriate.
#' @param duplicate_outliers_method Sometimes more than one trait will associate with a particular outlier. TRUE = only keep the trait that has the biggest influence on heterogeneity
#' @param filter_duplicate_outliers Sometimes more than one trait will associate with a particular outlier. TRUE = only keep the trait that has the biggest influence on heterogeneity
#'
#' @export
#' @return List of
Expand Down Expand Up @@ -246,11 +246,6 @@ tryx.analyse <- function(tryxscan, plot=TRUE, id_remove=NULL, filter_duplicate_o
# analysis$detection <- detection
# }

cpg <- require(ggrepel)
if(!cpg)
{
stop("Please install the ggrepel package\ninstall.packages('ggrepel')")
}

dat <- subset(tryxscan$dat, mr_keep, select=c(SNP, beta.exposure, beta.outcome, se.exposure, se.outcome))
dat$ratio <- dat$beta.outcome / dat$beta.exposure
Expand Down Expand Up @@ -310,7 +305,7 @@ tryx.analyse <- function(tryxscan, plot=TRUE, id_remove=NULL, filter_duplicate_o
# Outliers removed (all)
tt <- subset(dat, !SNP %in% tryxscan$outliers)
mod <- try(summary(lm(ratiow ~ -1 + weights, data=tt)))
if(class(mod) != "try-error")
if(!inherits(mod, "try-error"))
{
estimates <- bind_rows(estimates,
tibble(
Expand All @@ -328,7 +323,7 @@ tryx.analyse <- function(tryxscan, plot=TRUE, id_remove=NULL, filter_duplicate_o
# Outliers removed (candidates)
tt <- subset(dat, !SNP %in% temp$SNP)
mod <- try(summary(lm(ratiow ~ -1 + weights, data=tt)))
if(class(mod) != "try-error")
if(!inherits(mod, "try-error"))
{
estimates <- bind_rows(estimates,
tibble(
Expand All @@ -348,7 +343,7 @@ tryx.analyse <- function(tryxscan, plot=TRUE, id_remove=NULL, filter_duplicate_o
tt$qi <- cochrans_q(tt$beta.outcome / tt$beta.exposure, tt$se.outcome / abs(tt$beta.exposure))
analysis$Q$adj_Q <- sum(tt$qi)
mod <- try(summary(lm(ratiow ~ -1 + weights, data=tt)))
if(class(mod) != "try-error")
if(!inherits(mod, "try-error"))
{
estimates <- bind_rows(estimates,
tibble(
Expand Down Expand Up @@ -382,7 +377,7 @@ tryx.analyse <- function(tryxscan, plot=TRUE, id_remove=NULL, filter_duplicate_o
{
tt <- subset(dat, !SNP %in% tryxscan$true_outliers)
mod <- try(summary(lm(ratiow ~ -1 + weights, data=tt)))
if(class(mod) != "try-error")
if(!inherits(mod, "try-error"))
{
estimates <- bind_rows(estimates,
tibble(
Expand Down Expand Up @@ -451,26 +446,6 @@ tryx.analyse <- function(tryxscan, plot=TRUE, id_remove=NULL, filter_duplicate_o



#' Analyse tryx results
#'
#' This returns various heterogeneity statistics, IVW estimates for raw,
#' adjusted and outlier removed datasets, and summary of peripheral
#' traits detected etc.
#'
#' @param tryxscan Output from \code{tryx.scan}
#' @param plot Whether to plot or not. Default is TRUE
#' @param filter_duplicate_outliers Whether to only allow each putative outlier to be adjusted by a single trait (in order of largest divergence). Default is TRUE.
#'
#' @export
#' @return List of
#' - adj_full: data frame of SNP adjustments for all candidate traits
#' - adj: The results from adj_full selected to adjust the exposure-outcome model
#' - Q: Heterogeneity stats
#' - estimates: Adjusted and unadjested exposure-outcome effects
#' - plot: Radial plot showing the comparison of different methods and the changes in SNP effects ater adjustment



#' Adjust and analyse the tryx results
#'
#' Similar to tryx.analyse, but when there are multiple traits associated with a single variant then we use a LASSO-based multivariable approach
Expand Down Expand Up @@ -597,7 +572,6 @@ bootstrap_path <- function(gx, gx.se, gp, gp.se, px, px.se, nboot=1000)

radialmr <- function(dat, outlier=NULL)
{
library(ggplot2)
beta.exposure <- dat$beta.exposure
beta.outcome <- dat$beta.outcome
se.outcome <- dat$se.outcome
Expand Down
41 changes: 12 additions & 29 deletions R/plots.r
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,6 @@
#' @return ggplot of volcano plots
volcano_plot <- function(res, what="exposure")
{
cpg <- require(ggplot2)
if(!cpg)
{
stop("Please install the ggplot2 package")
}
cpg <- require(ggrepel)
if(!cpg)
{
stop("Please install the ggrepel package")
}

stopifnot(all(c("outcome", "exposure", "b", "se", "pval") %in% names(res)))
if(!"sig" %in% names(res))
{
Expand Down Expand Up @@ -44,7 +33,7 @@ volcano_plot <- function(res, what="exposure")
geom_vline(xintercept=0, linetype="dotted") +
geom_errorbarh(aes(xmin=b-1.96*se, xmax=b+1.96*se)) +
geom_point(aes(colour=sig)) +
facet_grid(form, scale="free") +
facet_grid(form, scales="free") +
geom_label_repel(data=subset(res, sig), aes(label=exposure), colour="black", segment.colour="black", point.padding = unit(0.7, "lines"), box.padding = unit(0.7, "lines"), segment.size=0.5, force=2, max.iter=3e3) +
# geom_text_repel(data=subset(res, sig), aes(label=outcome, colour=category)) +
geom_point(aes(colour=sig)) +
Expand All @@ -69,16 +58,10 @@ volcano_plot <- function(res, what="exposure")
tryx.network <- function(tryxscan)
{

a <- require(igraph)
if(!a)
if(!requireNamespace("igraph", quietly=TRUE))
{
stop("Please install the igraph R package")
}
a <- require(dplyr)
if(!a)
{
stop("Please install the dplyr R package")
}

stopifnot("candidate_outcome_mr" %in% names(tryxscan))
stopifnot("candidate_exposure_mr" %in% names(tryxscan))
Expand Down Expand Up @@ -174,14 +157,14 @@ tryx.network <- function(tryxscan)


nodes <- rbind(
data_frame(
tibble(
name=c(
ao$trait[ao$id %in% tryxscan$dat$id.exposure[1]],
ao$trait[ao$id %in% tryxscan$dat$id.outcome[1]]),
id=c(tryxscan$dat$id.exposure[1], tryxscan$dat$id.outcome[1]),
what=c("original")
),
data_frame(
tibble(
name=unique(tryxscan$outliers),
id=NA,
what="Outlier instruments"
Expand Down Expand Up @@ -230,20 +213,20 @@ tryx.network <- function(tryxscan)
grp$size <- 0.1
grp$size[grp$what == "Main hypothesis"] <- 0.5

layoutg <- graph_from_data_frame(layoutd2, vertices=nodes)
l <- layout_with_fr(layoutg)
grl <- graph_from_data_frame(grp, directed=TRUE, vertices=nodes)
layoutg <- igraph::graph_from_data_frame(layoutd2, vertices=nodes)
l <- igraph::layout_with_fr(layoutg)
grl <- igraph::graph_from_data_frame(grp, directed=TRUE, vertices=nodes)
plot(grl,
layout=l,
vertex.size=V(grl)$size,
vertex.label=V(grl)$label,
# edge.arrow.size=E(grl)$size,
vertex.size=igraph::V(grl)$size,
vertex.label=igraph::V(grl)$label,
# edge.arrow.size=igraph::E(grl)$size,
edge.arrow.size=0.3,
edge.color=E(grl)$colour,
edge.color=igraph::E(grl)$colour,
vertex.label.cex=0.5,
vertex.label.family="sans",
vertex.label.color="black",
vertex.color=V(grl)$colour,
vertex.color=igraph::V(grl)$colour,
edge.color="red"
)
}
Expand Down
13 changes: 2 additions & 11 deletions R/scan.r
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,6 @@ tryx.scan <- function(dat, outliers="RadialMR", outlier_correction="none", outli
if(outliers[1] == "RadialMR")
{
message("Using RadialMR package to detect outliers")
cpg <- require(RadialMR)
if(!cpg)
{
stop("Please install the RadialMR package\ndevtools::install_github('WSpiller/RadialMR')")
}
cpg <- require(dplyr)
if(!cpg)
{
stop("Please install the RadialMR package\ndevtools::install_github('WSpiller/RadialMR')")
}


# radial <- RadialMR::ivw_radial(RadialMR::format_radial(dat$beta.exposure, dat$beta.outcome, dat$se.exposure, dat$se.outcome, dat$SNP), alpha=0.05/nrow(dat), weights=3)
Expand All @@ -82,7 +72,7 @@ tryx.scan <- function(dat, outliers="RadialMR", outlier_correction="none", outli
# apply outlier_correction method with outlier_threshold to radial SNP-Q statistics


if(radial$outliers[1] == "No significant outliers")
if(is.character(radial$outliers) && radial$outliers[1] == "No significant outliers")
{
message("No outliers found")
message("Try changing the outlier_threshold parameter")
Expand Down Expand Up @@ -318,6 +308,7 @@ strategy1 <- function(dat, het_threshold=0.05, ivw_max_snp=1)

#' Identify putatively significant associations in the outlier scan
#'
#' @param tryxscan Output from \code{tryx.scan}
#' @param mr_threshold_method This is the argument to be passed to \code{p.adjust}. Default is "fdr". If no p-value adjustment is to be applied then specify "unadjusted"
#' @param mr_threshold Threshold to declare significance
#' @export
Expand Down
Loading