OSCR

Multi-ancestry gene expression models amplify transcriptome-wide association study discovery and validation.

Code ↔ Paper

11 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 11 matches
  1. [1] § Results › Gene-level TWAS associations demonstrate high correlation of effect sizes across ancestries ↔ PGC_master_analysis2.Rmd, lines 1703–1836 · score 0.81 · G2S African American, Puerto Rican, Mexican American, gene unique, gene association, training model
  2. [2] § Results › Gene-level TWAS associations demonstrate high correlation of effect sizes across ancestries ↔ Code.zip/SNP_analysis_p2_zsc.r, lines 826–900 · score 0.73 · G2S African American, Puerto Rican, Mexican American, training model, ZSC, bars
  3. [3] § Methods › Gene expression models ↔ PGC_master_analysis2.Rmd, lines 1839–1934 · score 0.72 · Puerto Rican, Mexican American, African American, training model, Latino, PR
  4. [4] § Results › Parallel ancestry-concordant TWAS recapitulate high correlations in effect size estimates ↔ Code.zip/SNP_analysis_zscore.r, lines 72–141 · score 0.69 · multi ancestry, GReX, shared genes, SNP weight, GTEx models, blood
  5. [5] § Results › Parallel ancestry-concordant TWAS recapitulate high correlations in effect size estimates ↔ Code.zip/SNP_analysis_p2_zsc.r, lines 826–900 · score 0.68 · median weight, Puerto Rican, Mexican American, African American, bars, PR
  6. [6] § Methods › Linkage disequilibrium comparison of cross-model genes ↔ PGC_master_analysis2.Rmd, lines 2621–2716 · score 0.67 · linkage disequilibrium, ASW, GBR, MXL, PUR, YRI
  7. [7] § Results › A majority of TWAS findings derive from admixed models ↔ PGC_master_analysis2.Rmd, lines 3699–3731 · score 0.62 · Puerto Rican, African American, wide FDR, Mexican, BD1, PTSD
  8. [8] § Methods › Evaluation of genetic ancestry as a determinant of model specificity ↔ PGC_master_analysis2.Rmd, lines 3435–3502 · score 0.54 · MAF weighted, allele frequencies, composition, SNP predictor, aggregate, GTEx
  9. [9] § Results › Broad differences exist across prediction models ↔ PGC_master_analysis2.Rmd, lines 1256–1311 · score 0.54 · shared_overlapping, shared_distinct, SNP predictor, PGC, correlation, GTEx
  10. [10] § Methods › Cross-model SNP feature comparison ↔ Code.zip/SNP_analysis_zscore.r, lines 404–465 · score 0.52 · shared_overlapping, shared_distinct, zscore, correlation, disease, SNP
  11. [11] § Methods › Cross-model SNP feature comparison ↔ PGC_master_analysis2.Rmd, lines 1256–1311 · score 0.51 · shared_overlapping, shared_distinct, zscore, correlation, SNP, GTEx

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

R Markdown · 3,731 lines · 139 KB · CC-BY-4.0 · 7 matches

  1. ---
  2. title: "PGC_multi_ancestry_analysis"
  3. author: "Xavier Bledsoe"
  4. date: "4/30/2025"
  5. output:
  6. html_document:
  7. code_folding: show
  8. toc: true
  9. toc_float: true
  10. number_sections: true
  11. ---
  12. ```{r setup, include=FALSE}
  13. knitr::opts_chunk$set(echo = TRUE, collapse = TRUE)
  14. library(data.table)
  15. library(stringr)
  16. library(ggplot2)
  17. library(ggrepel)
  18. library(viridis)
  19. library(pheatmap)
  20. library(RColorBrewer)
  21. library(ggpubr)
  22. #library(kableExtra)
  23. library(data.table)
  24. library(dplyr)
  25. library(ggrepel)
  26. library(stringr)
  27. library(colorspace)
  28. library(data.table)
  29. library(ggplot2)
  30. library(pals)
  31. library(stringr)
  32. library(gridExtra)
  33. library(grid)
  34. library(ggstance)
  35. library(viridis)
  36. library(ggpointdensity)
  37. library(ggh4x)
  38. library(forcats)
  39. ```
  40. # PGC TWAS analysis
  41. ## TWAS descriptive statistics
  42. ### Fig 1a: Nashville Plots of TWAS Data
  43. For all 6 GWAS from the PGC consortium, we want to visualize the distribution of
  44. TWAS results across the GALA II/SAGE (G2S) and GTEx whole blood results.
  45. ```{r fig.height=8, fig.width = 15}
  46. dt_ <- fread('Data/all_exc_assocs_PGCancestryTWAS.txt', header = TRUE)
  47. # exclude replication/comparison data from initial analysis.
  48. gwas <- c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024', 'PGC_EURO_SCZ_2022', 'PGC_LATINO_SCZ_2022')
  49. mod <- c('PrediXcan_Brain_Cortex')
  50. dt <- dt_[!(gwas_phenotype %in% gwas | training_model %in% mod),]
  51. dt[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  52. dt[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  53. dt[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  54. dt[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  55. dt[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  56. tms <- rev(c('G2S All WB', 'G2S African American WB', 'G2S Mexican American WB', 'G2S Puerto Rican WB', 'GTEx European WB'))
  57. dt$`gene expression model` <- factor(dt$`gene expression model`, levels = tms)
  58. adtwas2 <- dt
  59. # print manhattan plots for both the brain specific associations and the raw associations across all tissues
  60. chrom_sizes <- data.table(CHR = c(1:22), chr_length = c(
  61. 248956422, #1
  62. 242193529,
  63. 198295559,
  64. 190214555,
  65. 181538259, #5
  66. 170805979,
  67. 159345973,
  68. 145138636,
  69. 138394717,
  70. 133797422, #10
  71. 135086622,
  72. 133275309,
  73. 114364328,
  74. 114364328,
  75. 101991189, #15
  76. 90338345,
  77. 83257441,
  78. 80373285,
  79. 58617616,
  80. 64444167, #20
  81. 46709983,
  82. 50818468
  83. ))
  84. # Get the cumulative start locations for each chromosome in terms of base pairs.
  85. chrom_sizes[, chr_start := (cumsum(chr_length)-248956422)]
  86. # Set the x-axis label locations for each chromosome to be right in the middle of the chromosome block
  87. chrom_sizes[, chr_label_loc := (chr_start + chr_length/2)]
  88. all_genes <- fread('Data/all_ensembl.txt.gz', header = TRUE, stringsAsFactors=FALSE)
  89. # This file was downloaded from biomart website on 5/25/2022. The parameters were as follows:
  90. # Dataset: Human genes (GRCh38.p13)
  91. # Filters: Chromosome/scaffold: 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22
  92. # Attributes: Gene stable ID, Gene start (bp), Chromosome/scaffold name
  93. # Export all files to: TSV
  94. #
  95. # I then uploaded the file to my personal directory and compressed it via the gzip commandline command.
  96. all_genes <- setNames(all_genes, c('ensembl_gene_id', 'start_position', 'chromosome_name'))
  97. all_genes_loc <- as.data.table(merge(all_genes, chrom_sizes[, c('CHR','chr_start')], by.x = 'chromosome_name', by.y = 'CHR'))
  98. all_genes_loc[, gn_start := rowSums(.SD), .SDcols = c("start_position", "chr_start")]
  99. all_genes_loc <- all_genes_loc[, c('ensembl_gene_id', 'chromosome_name', 'gn_start')]
  100. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  101. dt=adtwas2
  102. dt$gene <- str_remove_all(dt$gene, '\\..+')
  103. # Iterate through the tissue models and NIDPs from the TWAS results
  104. # Get the top 15 p-values for labeling purposes
  105. top15 <- dt[, .(pvalue = min(pvalue)), by = c('gene','gene_name')][order(pvalue)][1:8, c('gene','gene_name','pvalue')]
  106. top15x = setDT(merge(top15, all_genes_loc, by.x = 'gene', by.y = 'ensembl_gene_id'))
  107. top15x$short_name = 'top_15'
  108. top25 <- dt[, .(pvalue = min(pvalue)), by = c('gene','gene_name')][order(pvalue)][1:25, c('gene','gene_name','pvalue')]
  109. top25x = setDT(merge(top25, all_genes_loc, by.x = 'gene', by.y = 'ensembl_gene_id'))
  110. top25x$short_name = 'top_25'
  111. twas2 <- merge(dt, all_genes_loc, by.x = 'gene', by.y = 'ensembl_gene_id')
  112. twas2$`gene expression model` <- factor(twas2$`gene expression model`, levels = tms)
  113. fig2 = ggplot(twas2, aes(x=gn_start, y=-log10(pvalue))) +
  114. # Show all points
  115. geom_point( aes(color=`gene expression model`), alpha=0.8, size=1.5) +
  116. geom_hline(yintercept=-log10(0.05/(dim(adtwas2)[1])), color = "red", size=0.5) +
  117. facet_wrap(vars(gwas_phenotype), scales = 'free', nrow = 3) +
  118. xlab('chromosome') +
  119. ylab('-log 10 pvalue')+
  120. #scale_color_manual(values = rep(c("grey", "skyblue"), 22 )) +
  121. scale_x_continuous(label = chrom_sizes[c(1:18,20,22),]$CHR, breaks= chrom_sizes[c(1:18,20,22),]$chr_label_loc ) +
  122. #scale_y_continuous(expand = c(0, 0),limits = c(0, (max(-log10(twas2$pvalue)) + 3)) ) + # remove space between plot area and x axis
  123. scale_color_discrete_sequential(palette = 'Batlow') +
  124. #scale_color_manual(values=as.vector(watlington(15)[c(3,4,1,5,12)])) +
  125. # Custom the theme:
  126. #guides(color = guide_legend(title = "Training Model", override.aes = list(size = 3), nrow=2, byrow=FALSE)) +
  127. guides(color = guide_legend(nrow=3, byrow=FALSE)) +
  128. theme_minimal()+
  129. theme(
  130. legend.position="bottom",
  131. panel.border = element_blank(),
  132. panel.grid.major.x = element_blank(),
  133. panel.grid.minor.x = element_blank(),
  134. axis.title.x = element_blank(),
  135. plot.title = element_text(hjust = 0.5),
  136. legend.text=element_text()
  137. )
  138. name = 'Output/all_assocs_nashplot_pgc.pdf'
  139. pdf(file = name, width = 15, height = 8, pointsize = 12, bg = "white")
  140. print(fig2)
  141. dev.off()
  142. print(fig2)
  143. ```
  144. ### Fig 1b: Gene sharing in models
  145. Certain genes are only assessed in G2S or GTEx but not both. We noted in computation
  146. analyses that there are far more statistically significant results from the G2S
  147. models than the GTEx. We want to see if differential gene characterization is
  148. unerlying this feature. To answer this question, we go to the original predictDB
  149. models for G2S and GTEx and examine the genes characterized in all the models.
  150. Then we can take the genes that were sgnificantly associated with a disease and
  151. characterize those genes according to if they are captured in a G2S model, GTEx
  152. GTEx model, or both.
  153. ```{r fig.height=7, fig.width = 4.5}
  154. load('Data/dbdata.r')
  155. cotested <- dbdata$cotested
  156. g2s_only <- dbdata$g2s_only
  157. gtx_only <- dbdata$gtx_only
  158. dt_ <- fread('Data/all_exc_BHsig_assocs_PGCancestryTWAS.txt', header = TRUE)
  159. # exclude replication/comparison data from initial analysis.
  160. gwas <- c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024', 'PGC_EURO_SCZ_2022')
  161. mod <- c('PrediXcan_Brain_Cortex')
  162. dt <- dt_[!(gwas_phenotype %in% gwas | training_model %in% mod),]
  163. dt[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  164. dt[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  165. dt[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  166. dt[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  167. dt[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  168. tms <- rev(c('G2S All WB', 'G2S African American WB', 'G2S Mexican American WB', 'G2S Puerto Rican WB', 'GTEx European WB'))
  169. dt$`gene expression model` <- factor(dt$`gene expression model`, levels = tms)
  170. dt[`gene expression model` == 'GTEx European WB', model := 'GTEX WB']
  171. dt[`gene expression model` != 'GTEx European WB', model := 'G2S']
  172. z1 <- unique(dt[, c('gene', 'gwas_phenotype', 'model')])
  173. z2 <- z1[, .(.N), by = c('gene', 'gwas_phenotype')]
  174. z2[N == 2, typ := 'co-sig']
  175. z2[N==1 & gene %in% cotested, typ := 'co-tested']
  176. z2[N==1 & !(gene %in% cotested), typ := 'only']
  177. z3 <- setDT(merge(z1, z2, by = c('gene', 'gwas_phenotype')))
  178. z3[typ != 'co-sig', category := paste(model, typ, sep = ' ')]
  179. z3[typ == 'co-sig', category := 'co-significant']
  180. z4 <- z3[, .(.N), by = c('gwas_phenotype', 'model', 'category')]
  181. z4[gwas_phenotype == 'PGC_ALL_PTSD_2024', dz := 'PTSD']
  182. z4[gwas_phenotype == 'PGC_all_SCZ_2022', dz := 'SCZ']
  183. z4[gwas_phenotype == 'PGC_allADHD_2022', dz := 'ADHD']
  184. z4[gwas_phenotype == 'PGC_allMDD_2023', dz := 'MDD']
  185. z4[gwas_phenotype == 'PGC_BD1_2021', dz := 'BD1']
  186. z4[gwas_phenotype == 'SUD_alc_2019', dz := 'AUD']
  187. z4$category = factor(z4$category, levels = c("G2S only", "G2S co-tested", "GTEX WB only", "GTEX WB co-tested", "co-significant"))
  188. tm_gp_plot6 <- ggplot(z4, aes(x = model, y = N, fill = category)) +
  189. geom_bar(stat = 'identity') +
  190. facet_wrap(vars(dz), scales = 'free', nrow = 3) +
  191. #scale_fill_manual(values=as.vector(watlington(15)[c(3,4,5,12,1)])) +
  192. scale_fill_manual(values=c('#cc6576ff', 'deeppink4', 'darkblue', 'cyan3', 'grey30')) +
  193. theme_minimal() +
  194. theme(legend.position = 'bottom', legend.title=element_blank()) +
  195. guides(fill = guide_legend(nrow = 2))
  196. name = 'Output/all_pgc_ancestry_TMxGP_bar_formatted2g.pdf'
  197. pdf(file = name, width = 4.5, height = 7, pointsize = 12, bg = "white")
  198. print(tm_gp_plot6)
  199. dev.off()
  200. print(tm_gp_plot6)
  201. ```
  202. ### Table of gene overlap across models
  203. Uncomment for results displayed as table
  204. ```{r}
  205. #kable(z4, caption = "Overlap data for genes included in GTEx vs G2S models", align = "ccc", digits = 2) %>%
  206. # kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"), full_width = F) %>%
  207. # column_spec(1, bold = T) %>%
  208. # row_spec(0, bold = T, color = "white", background = "#D7261E")%>%
  209. # scroll_box(width = "100%", height = "400px") # Adjust height as needed
  210. ```
  211. ## SNP level analyses
  212. ### Fig 2e, S12: Correlation of SNP weights
  213. Each model has SNP weights which serve as predictors of gene expression. We can take the
  214. same genes and get all the shared SNP predictors across G2S and GTEx and characterize
  215. the effect size of the weight on the gene. This will tell us if the models expect the same
  216. SNPs to have different effects on the same genes.
  217. ```{r fig.height=11, fig.width = 9}
  218. all_dat <- list.files('Data/rdata', pattern = '.+\\.txt')
  219. duo_snps <- data.table()
  220. for(fil in str_subset(all_dat, '^snpfx_dat_all.+\\.txt')){
  221. newdat <- fread(paste0('Data/rdata/', fil), header = T)
  222. duo_snps <- rbind(duo_snps, newdat)
  223. }
  224. r2_values <- duo_snps[, .(r2 = summary(lm(weight.GTEx ~ weight.G2S))$adj.r.squared), by = .(gwas_phenotype, model)]
  225. r_values <- duo_snps[, .(r_val = cor.test(weight.GTEx, weight.G2S)$estimate), by = .(gwas_phenotype, model)]
  226. fx_shared <- ggplot(data = duo_snps, aes(x = weight.G2S, y = weight.GTEx)) +
  227. geom_point() +
  228. geom_smooth(method = 'lm', se=F) +
  229. geom_text(data = r_values, aes(x = Inf, y = -Inf, label = paste0("R = ", round(r_val, 3))),
  230. hjust = 1.1, vjust = -0.5, check_overlap = TRUE) +
  231. xlab(paste0('SNP weight'))+
  232. ylab(paste0('SNP weight GTEx')) +
  233. facet_grid(gwas_phenotype~model) +
  234. theme(legend.position = 'none') +
  235. theme_bw()
  236. name = 'Output/fxcorr_grid24_cor.pdf'
  237. pdf(file = name, width = 9, height = 11, pointsize = 12, bg = "white")
  238. print(fx_shared)
  239. dev.off()
  240. print(fx_shared)
  241. ```
  242. ### Correlation of gene zscores
  243. While the previous analysis examined the model specific effects of SNP weights on gene expression
  244. this analysis examines the relationship between GReX on disease as characterized by GTEx vs G2S.
  245. We look at the zscores for the relationship of Gene X on disease Y as modeled by the different TWAS.
  246. This tells us if the models predict that the effect of genes on disease differs across models.
  247. ```{r}
  248. dsgene <- data.table()
  249. for(fil in str_subset(all_dat, '^dsgene_dat_all.+\\.txt')){
  250. newdat <- fread(paste0('Data/rdata/', fil), header = T)
  251. dsgene <- rbind(dsgene, newdat)
  252. }
  253. ```
  254. ```{r fig.height=12.5, fig.width = 10}
  255. cor_vals <- dsgene[, .(Zcor = cor(zscore.G2S, zscore.GTEx, use="complete.obs"), Pcor = cor(pvalue.G2S, pvalue.GTEx, use="complete.obs")), by = c( 'gwas_phenotype', 'model')]
  256. dg2 <- setDT(merge(dsgene, cor_vals, by = c('gwas_phenotype', 'model')))
  257. zsc_plot <- ggplot(data = dg2, aes(x = zscore.G2S, y = zscore.GTEx)) +
  258. #geom_point() +
  259. geom_pointdensity(adjust = 4) +
  260. scale_color_viridis() +
  261. geom_smooth(method = 'lm', se=F, color = 'black') +
  262. geom_text(aes(x = Inf, y = Inf, label = paste0("R = ", round(Zcor, 3))),
  263. hjust = 1.1, vjust = -0.3, check_overlap = TRUE, color = 'black', size = 3) +
  264. facet_grid2(gwas_phenotype~model, axes = 'all') +
  265. #facet_grid(gwas_phenotype~model) +
  266. xlab('zscore.G2S') +
  267. ylab('zscore.GTEx') +
  268. coord_cartesian( clip = "off")+
  269. theme_minimal()+
  270. theme(panel.spacing = unit(1, "cm", data = NULL), strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  271. name = 'Output/zsc_corr_grid24.pdf'
  272. pdf(file = name, width = 10, height = 12.5, pointsize = 12, bg = "white")
  273. print(zsc_plot)
  274. dev.off()
  275. print(zsc_plot)
  276. ```
  277. ### Correlation of gene zscores 2 (Fig 2b, S6-7)
  278. Repeat the analysis but instead of a density plot, use black points with red trendline.
  279. ```{r fig.height=12.5, fig.width = 10}
  280. zsc_plotblk <- ggplot(data = dg2, aes(x = zscore.G2S, y = zscore.GTEx)) +
  281. geom_point() +
  282. #geom_pointdensity(adjust = 4) +
  283. #scale_color_viridis() +
  284. geom_smooth(method = 'lm', se=F, color = 'red') +
  285. geom_text(aes(x = -Inf, y = Inf, label = paste0("R = ", round(Zcor, 3))),
  286. hjust = 0.1, vjust = -0.3, check_overlap = TRUE, color = 'red', size = 3) +
  287. facet_grid2(gwas_phenotype~model, axes = 'all') +
  288. #facet_grid(gwas_phenotype~model) +
  289. xlab('zscore.G2S') +
  290. ylab('zscore.GTEx') +
  291. coord_cartesian( clip = "off")+
  292. theme_minimal()+
  293. theme(panel.spacing = unit(1, "cm", data = NULL), strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  294. name = 'Output/zsc_corr_grid24_black.pdf'
  295. pdf(file = name, width = 10, height = 12.5, pointsize = 12, bg = "white")
  296. print(zsc_plotblk)
  297. dev.off()
  298. print(zsc_plotblk)
  299. ```
  300. ### Correlation of pvalues
  301. Similar to the correlation between zscores, we can also examine the relationship between p-values.
  302. This will tell us if the different models call the same gene-disease association with differing
  303. degrees of statistical significance.
  304. ```{r fig.height=12.5, fig.width = 10}
  305. pval_plot <- ggplot(data = dg2, aes(x = pvalue.G2S, y = pvalue.GTEx)) +
  306. #geom_point() +
  307. geom_pointdensity(adjust = 4) +
  308. scale_color_viridis() +
  309. geom_smooth(method = 'lm', se=F, color = 'black') +
  310. geom_text(aes(x = Inf, y = Inf, label = paste0("R = ", round(Pcor, 3))),
  311. hjust = 1.1, vjust = -0.3, check_overlap = TRUE, color = 'black', size = 3) +
  312. scale_fill_manual(values=as.vector(kelly()[8:11])) +
  313. facet_grid2(gwas_phenotype~model, axes = 'all') +
  314. #facet_grid(gwas_phenotype~model) +
  315. xlab('pvalue.G2S') +
  316. ylab('pvalue.GTEx') +
  317. coord_cartesian( clip = "off")+
  318. theme_minimal() +
  319. theme(panel.spacing = unit(1, "cm", data = NULL), strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  320. name = 'Output/pval_corr_grid24.pdf'
  321. pdf(file = name, width = 10, height = 12.5, pointsize = 12, bg = "white")
  322. print(pval_plot)
  323. dev.off()
  324. print(pval_plot)
  325. ```
  326. ### Correlation of p-values 2 (Figure 2c, S8-9)
  327. And again, repeat with black points and red trendline.
  328. ```{r fig.height=12.5, fig.width = 10}
  329. pval_plotblk <- ggplot(data = dg2, aes(x = pvalue.G2S, y = pvalue.GTEx)) +
  330. geom_point() +
  331. #geom_pointdensity(adjust = 4) +
  332. #scale_color_viridis() +
  333. geom_smooth(method = 'lm', se=F, color = 'red') +
  334. geom_text(aes(x = -Inf, y = Inf, label = paste0("R = ", round(Pcor, 3))),
  335. hjust = 0.1, vjust = -0.3, check_overlap = TRUE, color = 'red', size = 3) +
  336. scale_fill_manual(values=as.vector(kelly()[8:11])) +
  337. facet_grid2(gwas_phenotype~model, axes = 'all') +
  338. #facet_grid(gwas_phenotype~model) +
  339. xlab('pvalue.G2S') +
  340. ylab('pvalue.GTEx') +
  341. coord_cartesian( clip = "off")+
  342. theme_minimal() +
  343. theme(panel.spacing = unit(1, "cm", data = NULL), strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  344. name = 'Output/pval_corr_grid24_black.pdf'
  345. pdf(file = name, width = 10, height = 12.5, pointsize = 12, bg = "white")
  346. print(pval_plotblk)
  347. dev.off()
  348. print(pval_plotblk)
  349. ```
  350. ### Fig S12:Comparison of r2 values for GTeX vs G2S
  351. Each gene that is analyzed in the TWAS relies on a number of SNP weights that are used as predictors.
  352. The PredictDB pipeline that is used to make the model includes information about the correlation
  353. between the predicted gene expression using its SNP weights and the measured gene expression from
  354. RNA seq in the original dataset. This R2 is thus a measure of the predictive performance of the model
  355. regarding that specific gene. The difference in TWAS results may be related to the accuracy with which
  356. the different model are predicting gene expression. As a result, the code below compares the R2 values
  357. for genes across the different models that emerged from the TWAS.
  358. ```{r fig.height=12.5, fig.width = 10}
  359. r2corr <- ggplot(data = dsgene, aes(x = pred_perf_r2.G2S, y = pred_perf_r2.GTEx)) +
  360. geom_point() +
  361. geom_abline(intercept = 0, slope = 1, color = 'grey80', linetype = "dashed")+
  362. geom_smooth(method = 'lm', se=F) +
  363. xlab(paste0('R2 G2S'))+
  364. ylab(paste0('R2 GTEx')) +
  365. facet_grid(gwas_phenotype~model) +
  366. theme(legend.position = 'none') +
  367. theme_bw()
  368. name = 'Output/r2_mod_corr_grid24.pdf'
  369. pdf(file = name, width = 9, height = 11, pointsize = 12, bg = "white")
  370. print(r2corr)
  371. dev.off()
  372. print(r2corr)
  373. ```
  374. ### Correlation of zscores by gene significance
  375. Earlier we examined the total zscore correlations across models. It is possible to examine these
  376. in more granularity, splitting categories according to if the genes of interest were deemed significant
  377. in one, both, or none of the models.
  378. ```{r fig.height=5, fig.width = 5}
  379. fdga <- dsgene[, .(Ngroups = sum(!is.na(zscore.G2S) & !is.na(zscore.GTEx))), by = c('eqtl_source', 'twas_specificity', 'gwas_phenotype', 'model')]
  380. fdsgene2 <- setDT(merge(dsgene[!is.na(zscore.G2S) & !is.na(zscore.GTEx),], fdga, by = c('eqtl_source','twas_specificity', 'gwas_phenotype', 'model')))
  381. ffx_corr <- fdsgene2[Ngroups >2,
  382. .(fx_r2 = cor.test(zscore.G2S, zscore.GTEx)$estimate,
  383. fx_r2_ciL = cor.test(zscore.G2S, zscore.GTEx)$conf.int[1],
  384. fx_r2_ciH = cor.test(zscore.G2S, zscore.GTEx)$conf.int[2],
  385. N = .N), by = c('eqtl_source','twas_specificity', 'gwas_phenotype', 'model')]
  386. modnm = c('G2S_aa', 'G2S_all', 'G2S_mx', 'G2S_pr')
  387. ffx_corr$twas_specificity <- factor(ffx_corr$twas_specificity, levels = c('none', 'GTEx_WB', modnm, 'shared'))
  388. ffx_corr[twas_specificity == 'shared', spec := 'G2S & GTEx']
  389. ffx_corr[twas_specificity == 'none', spec := 'none']
  390. ffx_corr[!(twas_specificity %in% c('shared','none')), spec := 'G2S or GTEx']
  391. fx2 <- ffx_corr[, .(mfxr = mean(fx_r2)), by = c('eqtl_source', 'spec')]
  392. fx2_cord <- ggplot(data = fx2, aes(x = spec, y = mfxr, color = eqtl_source, group = eqtl_source)) +
  393. geom_hline(yintercept = 0, color = 'red') +
  394. #geom_errorbar(aes(ymin = fx_r2_ciL, ymax = fx_r2_ciH), width = 0.1, color = 'black', position=position_dodge(width=0.3)) +
  395. geom_point(position=position_dodge(width=0.3), size = 2) +
  396. scale_color_manual(values=c('green4', 'slateblue3')) +
  397. ylab('effect size correlation') +
  398. xlab('twas model significance') +
  399. ylim(c(-1, 1))+
  400. #facet_grid(gwas_phenotype~model, scales = 'free') +
  401. theme_bw() +
  402. theme(axis.text.x = element_text(angle = 60, hjust = 1))
  403. name = 'Output/genefx_corplot_grid24d_all.pdf'
  404. pdf(file = name, width = 5, height = 5, pointsize = 12, bg = "white")
  405. print(fx2_cord)
  406. dev.off()
  407. print(fx2_cord)
  408. ```
  409. ### Fig S16: correlation of zscores by gene significance 2
  410. We extend the analyses from above but split across models and clinical phenotypes
  411. ```{r fig.height=11, fig.width = 13}
  412. fdga <- dsgene[, .(Ngroups = sum(!is.na(zscore.G2S) & !is.na(zscore.GTEx))), by = c('eqtl_source', 'twas_specificity', 'gwas_phenotype', 'model')]
  413. fdsgene2 <- setDT(merge(dsgene[!is.na(zscore.G2S) & !is.na(zscore.GTEx),], fdga, by = c('eqtl_source','twas_specificity', 'gwas_phenotype', 'model')))
  414. ffx_corr <- fdsgene2[Ngroups >2,
  415. .(fx_r2 = cor.test(zscore.G2S, zscore.GTEx)$estimate,
  416. fx_r2_ciL = cor.test(zscore.G2S, zscore.GTEx)$conf.int[1],
  417. fx_r2_ciH = cor.test(zscore.G2S, zscore.GTEx)$conf.int[2],
  418. N = .N), by = c('eqtl_source','twas_specificity', 'gwas_phenotype', 'model')]
  419. modnm = c('G2S_aa', 'G2S_all', 'G2S_mx', 'G2S_pr')
  420. ffx_corr$twas_specificity <- factor(ffx_corr$twas_specificity, levels = c('none', 'GTEx_WB', modnm, 'shared'))
  421. fx_cord <- ggplot(data = ffx_corr, aes(x = twas_specificity, y = fx_r2, color = eqtl_source, group = eqtl_source)) +
  422. geom_hline(yintercept = 0, color = 'red') +
  423. geom_errorbar(aes(ymin = fx_r2_ciL, ymax = fx_r2_ciH), width = 0.1, color = 'black', position=position_dodge(width=0.3)) +
  424. geom_point(position=position_dodge(width=0.3), size = 2) +
  425. scale_color_manual(values=c('green4', 'slateblue3')) +
  426. ylab('effect size correlation') +
  427. xlab('twas model significance') +
  428. ylim(c(-1, 1))+
  429. facet_grid(gwas_phenotype~model, scales = 'free') +
  430. theme_bw() +
  431. theme(axis.text.x = element_text(angle = 60, hjust = 1))
  432. name = 'Output/genefx_corplot_grid24d.pdf'
  433. pdf(file = name, width = 13, height = 11, pointsize = 12, bg = "white")
  434. print(fx_cord)
  435. dev.off()
  436. print(fx_cord)
  437. ```
  438. ### Fig S17: correlation of pvalues by gene significance
  439. And again, we can examine the same analysis according to pvalue to get a visual representation
  440. of how the models handle statistical significance.
  441. ```{r fig.height=11, fig.width = 13}
  442. pdga <- dsgene[, .(Ngroups = sum(!is.na(pvalue.G2S) & !is.na(pvalue.GTEx))), by = c('eqtl_source', 'twas_specificity', 'gwas_phenotype', 'model')]
  443. pdsgene2 <- setDT(merge(dsgene[!is.na(pvalue.G2S) & !is.na(pvalue.GTEx),], pdga, by = c('eqtl_source','twas_specificity', 'gwas_phenotype', 'model')))
  444. pfx_corr <- pdsgene2[Ngroups >2,
  445. .(pv_r = cor.test(pvalue.G2S, pvalue.GTEx)$estimate,
  446. pv_r_ciL = cor.test(pvalue.G2S, pvalue.GTEx)$conf.int[1],
  447. pv_r_ciH = cor.test(pvalue.G2S, pvalue.GTEx)$conf.int[2],
  448. N = .N), by = c('eqtl_source','twas_specificity', 'gwas_phenotype', 'model')]
  449. modnm = c('G2S_aa', 'G2S_all', 'G2S_mx', 'G2S_pr')
  450. pfx_corr$twas_specificity <- factor(pfx_corr$twas_specificity, levels = c('none', 'GTEx_WB', modnm, 'shared'))
  451. pv_cor <- ggplot(data = pfx_corr, aes(x = twas_specificity, y = pv_r, color = eqtl_source, group = eqtl_source)) +
  452. geom_hline(yintercept = 0, color = 'red') +
  453. geom_errorbar(aes(ymin = pv_r_ciL, ymax = pv_r_ciH), width = 0.1, color = 'black', position=position_dodge(width=0.3)) +
  454. geom_point(position=position_dodge(width=0.3), size = 2) +
  455. scale_color_manual(values=c('coral1', 'deepskyblue2')) +
  456. #geom_label(aes(y = -0.75 + 0.25*sum('shared_distinct' %in% eqtl_source), label = paste('N =', N))) +
  457. #geom_label(aes(y = -1 , label = paste(N), color = eqtl_source), position = position_dodgev(height = -0.7)) +
  458. ylab('pvalue correlation') +
  459. xlab('twas model significance') +
  460. ylim(c(-1, 1))+
  461. facet_grid(gwas_phenotype~model, scales = 'free') +
  462. theme_bw() +
  463. theme(axis.text.x = element_text(angle = 60, hjust = 1))
  464. name = 'Output/genepv_corplot_grid24.pdf'
  465. pdf(file = name, width = 13, height = 11, pointsize = 12, bg = "white")
  466. print(pv_cor)
  467. dev.off()
  468. print(pv_cor)
  469. ```
  470. ### Fig 3b,S15: Median SNP weight magnitudes
  471. The SNPs used for the analysis may be different across the models but overall, I'm interested in
  472. seeing if the different models are able to assign SNPs of different effect sizes to the genes. To
  473. capture this, the code below characterizes the median magnitude of the SNP weights across G2S and
  474. GTEx.
  475. ```{r fig.height=11, fig.width = 9}
  476. all_snps <- data.table()
  477. for(fil in str_subset(all_dat, '^snp_dat_all.+\\.txt')){
  478. newdat <- fread(paste0('Data/rdata/', fil), header = T)
  479. all_snps <- rbind(all_snps, newdat)
  480. }
  481. wts <- setDT(melt(all_snps[, c('model', 'gwas_phenotype', 'weight.G2S', 'weight.GTEx')], id.vars = c('model', 'gwas_phenotype')))
  482. eqtl_medwtplot <- ggplot(data = wts, aes(x = variable, y = abs(value), fill = variable)) +
  483. geom_boxplot(outlier.shape = NA) +
  484. xlab('model')+
  485. ylab('median weight magnitude') +
  486. theme_minimal()+
  487. facet_grid(gwas_phenotype~model, scales = 'free') +
  488. coord_cartesian(ylim= c(0,0.15)) +
  489. theme(legend.position = 'none') +
  490. theme_bw()
  491. name = 'Output/eqtl_medwtplot_grid24.pdf'
  492. pdf(file = name, width = 9, height = 11, pointsize = 12, bg = "white")
  493. print(eqtl_medwtplot)
  494. dev.off()
  495. print(eqtl_medwtplot)
  496. ```
  497. ### Fig 2f: SNP, Gene, and Sig Gene correlations
  498. Let's group the zscore and SNP weight correlations into a single figure for easier comparitive
  499. analysis.
  500. ```{r fig.width = 5.5, fig.height = 11}
  501. wt_r2_values <- duo_snps[, .(r2_SNPpredictors = summary(lm(weight.GTEx ~ weight.G2S))$adj.r.squared, wt_rse = summary(lm(weight.GTEx ~ weight.G2S))$sigma, N_r2_SNP = .N), by = .(gwas_phenotype, model)]
  502. #wt_r2_valuessig <- duo_sig[, .(r2_SNPpredictors = summary(lm(weight.GTEx ~ weight.G2S))$adj.r.squared, wt_rse = summary(lm(weight.GTEx ~ weight.G2S))$sigma, N_r2_SNP = .N), by = .(gwas_phenotype, model)]
  503. wt_r_values <- duo_snps[, .(r_SNPpredictors = cor.test(weight.GTEx,weight.G2S)$estimate,
  504. wt_ciL = cor.test(weight.GTEx,weight.G2S)$conf.int[1],
  505. wt_ciH = cor.test(weight.GTEx,weight.G2S)$conf.int[2],
  506. N_wt_SNP = .N), by = .(gwas_phenotype, model)]
  507. gnfx_r_values <- dsgene[, .(r_gnfx = cor.test(zscore.GTEx,zscore.G2S)$estimate,
  508. gnfx_ciL = cor.test(zscore.GTEx,zscore.G2S)$conf.int[1],
  509. gnfx_ciH = cor.test(zscore.GTEx,zscore.G2S)$conf.int[2],
  510. N_gnfx = .N), by = .(gwas_phenotype, model)]
  511. gnfx_r_valsig <- dsgene[twas_specificity != 'none', .(r_gnfx_sig = cor.test(zscore.GTEx,zscore.G2S)$estimate,
  512. gnfx_sig_ciL = cor.test(zscore.GTEx,zscore.G2S)$conf.int[1],
  513. gnfx_sig_ciH = cor.test(zscore.GTEx,zscore.G2S)$conf.int[2],
  514. N_sig_gnfx = .N), by = .(gwas_phenotype, model)]
  515. cordat <- setDT(merge(wt_r_values, merge(gnfx_r_values, gnfx_r_valsig, by = c('gwas_phenotype', 'model')), by = c('gwas_phenotype', 'model')))
  516. wt_r_values <- duo_snps[, .(r = cor.test(weight.GTEx,weight.G2S)$estimate,
  517. ciL = cor.test(weight.GTEx,weight.G2S)$conf.int[1],
  518. ciH = cor.test(weight.GTEx,weight.G2S)$conf.int[2],
  519. N = .N,
  520. measure = 'SNP_predictor'), by = .(gwas_phenotype, model)]
  521. gnfx_r_values <- dsgene[, .(r = cor.test(zscore.GTEx,zscore.G2S)$estimate,
  522. ciL = cor.test(zscore.GTEx,zscore.G2S)$conf.int[1],
  523. ciH = cor.test(zscore.GTEx,zscore.G2S)$conf.int[2],
  524. N = .N,
  525. measure = 'effect size'), by = .(gwas_phenotype, model)]
  526. gnfx_r_valsig <- dsgene[twas_specificity != 'none', .(r = cor.test(zscore.GTEx,zscore.G2S)$estimate,
  527. ciL = cor.test(zscore.GTEx,zscore.G2S)$conf.int[1],
  528. ciH = cor.test(zscore.GTEx,zscore.G2S)$conf.int[2],
  529. N = .N,
  530. measure = 'effect size (sig)'), by = .(gwas_phenotype, model)]
  531. cordat <- rbind(wt_r_values, gnfx_r_values, gnfx_r_valsig)
  532. cordat <- rbind(wt_r_values, gnfx_r_values, gnfx_r_valsig)
  533. cordat$measure <- factor(cordat$measure, levels = c('SNP_predictor', 'effect size', 'effect size (sig)'))
  534. cordat[gwas_phenotype == 'PGC_BD1_2021', disease := 'BD1']
  535. cordat[gwas_phenotype == 'PGC_all_SCZ_2022', disease := 'SCZ']
  536. cordat[gwas_phenotype == 'SUD_alc_2019', disease := 'SUD-A']
  537. cordat[gwas_phenotype == 'PGC_allADHD_2022', disease := 'ADHD']
  538. cordat[gwas_phenotype == 'PGC_ALL_PTSD_2024', disease := 'PTSD']
  539. cordat[gwas_phenotype == 'PGC_allMDD_2023', disease := 'MDD']
  540. allcor_plot <- ggplot(data = cordat, aes(x = measure, y = r, group = model, color = model)) +
  541. #geom_line(position=position_dodge(width=0.5))+
  542. geom_errorbar(aes(ymin = ciL, ymax = ciH), width = 0.3, color = 'black', position=position_dodge(width=0.5)) +
  543. geom_point(position=position_dodge(width=0.5)) +
  544. #facet_grid2(disease~., axes = 'all') +
  545. facet_grid(disease~.) +
  546. guides(color = guide_legend(nrow = 2)) +
  547. xlab('measurement') +
  548. ylab('r correlation coefficient') +
  549. ylim(c(0,1)) +
  550. theme_bw() +
  551. theme(axis.text = element_text(size = 14),
  552. axis.title = element_text(size = 14),
  553. strip.text = element_text(size = 14),
  554. legend.text = element_text(size=14),
  555. legend.title = element_text(size=14),
  556. legend.position = 'bottom')
  557. name = 'Output/allcordat_grid.pdf'
  558. pdf(file = name, width = 5.5, height = 11, pointsize = 12, bg = "white")
  559. print(allcor_plot)
  560. dev.off()
  561. print(allcor_plot)
  562. ```
  563. ### Fig 3e,S22: r2 by model specificity
  564. As before, we split the zscore correlations by model specificity. Here we replicate this analytical design
  565. with the r2 but instead of dots and bars for range, we'll visualize this with violin plots and imbedded boxplots.
  566. ```{r fig.width = 9, fig.height = 11}
  567. r2_dat <- data.table()
  568. for(fil in str_subset(all_dat, '^r2_dat_all.+\\.txt')){
  569. newdat <- fread(paste0('Data/rdata/', fil), header = T)
  570. r2_dat <- rbind(r2_dat, newdat)
  571. }
  572. r2_vplot <- ggplot(data = r2_dat, aes(x = variable, y = value, fill = eqtl_source)) +
  573. geom_violin(scale = 'width', position=position_dodge(1), drop = F) +
  574. geom_boxplot(width = 0.1, color = 'black', position=position_dodge(1), outlier.size = 0.5) +
  575. xlab('eQTL model specificity') +
  576. ylab('R2 per gene') +
  577. facet_grid(gwas_phenotype~model, scales = 'free') +
  578. theme_minimal() +
  579. theme(axis.text.x = element_text(angle = 60, hjust = 1))
  580. name = 'Output/r2_vplot_grid24.pdf'
  581. pdf(file = name, width = 9, height = 11, pointsize = 12, bg = "white")
  582. print(r2_vplot)
  583. dev.off()
  584. print(r2_vplot)
  585. ```
  586. ### r2 plot agregated across all factors
  587. ```{r}
  588. duo_sig <- data.table()
  589. for(fil in str_subset(all_dat, '^fxsig_dat_all.+\\.txt')){
  590. newdat <- fread(paste0('Data/rdata/', fil), header = T)
  591. duo_sig <- rbind(duo_sig, newdat)
  592. }
  593. r2_values <- duo_sig[, .(r2 = summary(lm(weight.GTEx ~ weight.G2S))$adj.r.squared), by = .(gwas_phenotype, model)]
  594. r_values <- duo_sig[, .(r_val = cor.test(weight.GTEx, weight.G2S)$estimate), by = .(gwas_phenotype, model)]
  595. fx_sharedsig <- ggplot(data = duo_sig, aes(x = weight.G2S, y = weight.GTEx, color = model_specificity)) +
  596. geom_point() +
  597. geom_smooth(method = 'lm', se=F, weight = 1, fullrange = T) +
  598. geom_text(inherit.aes = F, data = r_values, aes(x = Inf, y = -Inf, label = paste0("R = ", round(r_val, 3))),
  599. hjust = 1.1, vjust = -0.5, check_overlap = TRUE) +
  600. xlab(paste0('SNP weight'))+
  601. ylab(paste0('SNP weight GTEx')) +
  602. facet_grid(gwas_phenotype~model, scales = 'free') +
  603. theme(legend.position = 'none') +
  604. theme_bw()
  605. name = 'Output/r2_aggregate_1.pdf'
  606. pdf(file = name, width = 4, height = 4, pointsize = 12, bg = "white")
  607. print(fx_sharedsig)
  608. dev.off()
  609. print(fx_sharedsig)
  610. ```
  611. ### Fig 2d, S11: Number of used eQTL's per gene
  612. How many eQTLs were used for each gene that was tested in the different TWAS analyses?
  613. ```{r fig.height=12.5, fig.width = 10}
  614. eqtl_dat <- data.table()
  615. for(fil in str_subset(all_dat, '^eqtl_dat_all.+\\.txt')){
  616. newdat <- fread(paste0('Data/rdata/', fil), header = T)
  617. eqtl_dat <- rbind(eqtl_dat, newdat)
  618. }
  619. eqtl_vplot <- ggplot(data = eqtl_dat, aes(x = variable, y = value, fill = variable)) +
  620. geom_violin(scale = 'width') +
  621. geom_boxplot(width = 0.1, color = 'black', fill = 'white',outlier.shape = NA) +
  622. xlab('eQTL model specificity')+
  623. ylab('Number of eQTLs per gene') +
  624. theme_minimal()+
  625. facet_grid(gwas_phenotype~model, scales = 'free') +
  626. theme_bw() +
  627. theme(legend.position = 'none', axis.text.x = element_text(angle = 60, hjust = 1))
  628. name = 'Output/eqtl_vplot_grid24.pdf'
  629. pdf(file = name, width = 9, height = 11, pointsize = 12, bg = "white")
  630. print(eqtl_vplot)
  631. dev.off()
  632. print(eqtl_vplot)
  633. ```
  634. ### Fig 3c, S13: r2 by model
  635. split r2 by model instead of significance or correlation.
  636. ```{r fig.height=12.5, fig.width = 10}
  637. preds <- melt(dsgene[, c('gwas_phenotype', 'gene', 'model', 'pred_perf_r2.G2S', 'pred_perf_r2.GTEx')], id.vars = c('gwas_phenotype', 'gene', 'model' ))
  638. r2_vplot <- ggplot(data = preds, aes(x = variable, y = value, fill = variable)) +
  639. geom_violin(scale = 'width') +
  640. geom_boxplot(width = 0.1, color = 'black', fill = 'white',outlier.shape = NA) +
  641. xlab('model')+
  642. ylab('Prediction performance r2') +
  643. theme_minimal()+
  644. facet_grid(gwas_phenotype~model, scales = 'free') +
  645. theme_bw() +
  646. theme(legend.position = 'none', axis.text.x = element_text(angle = 60, hjust = 1))
  647. name = 'Output/predperf_vplot_grid24.pdf'
  648. pdf(file = name, width = 9, height = 11, pointsize = 12, bg = "white")
  649. print(r2_vplot)
  650. dev.off()
  651. print(r2_vplot)
  652. ```
  653. ## MDD Ancestry-concordant TWAS
  654. We wanted to see if the results we got were the specific to a study design where we applied two different models
  655. to the same GWAS summary statistics. We pulled GWAS of MDD done in predominantly African Americans vs Europeans
  656. and then applied more ancestry concordant models to each for the TWAS. (G2S_AA + African American MDD GWAS and then
  657. GTEx + Eur GWAS). For this we repeated a number of the descriptive analyzes performed above.
  658. ### zscore corrrelation all
  659. Correlation of Zscores. I performed this multiple times considering different statistical significance thresholds.
  660. ```{r}
  661. library(data.table)
  662. library(ggplot2)
  663. library(pals)
  664. library(gridExtra)
  665. library(ggh4x)
  666. library(DBI)
  667. # get the correlations needed between the different models and twas analyses
  668. mda <- fread('Data/dual_data/all_exc_assocs_PGCancestryTWAS_AA.txt', header = T)[gwas_phenotype == 'PGC_allMDD_2023',]
  669. mde <- fread('Data/dual_data/all_exc_assocs_PGCancestryTWAS_EUR.txt', header = T)
  670. mdeg <- unique(mde$gene_name)
  671. mdag <- unique(mda$gene_name)
  672. uniq_mde <- setdiff(mdeg, mdag)
  673. uniq_mda <- setdiff(mdag, mdeg)
  674. jointmdd <- setDT(merge(mda[training_model != 'PrediXcan_Brain_Cortex',], mde, by = c('gene_name', 'training_model'), suffixes = c('.multi', '.eur')))
  675. cor.test(jointmdd$zscore.multi, jointmdd$zscore.eur)
  676. ```
  677. ### zscore cor all shared
  678. ```{r fig.width = 8, fig.height = 2.6}
  679. # correlation between zscores across the two cohorts is 0.803 across all models.
  680. mdcor <- jointmdd[, .(zsc_cor = cor.test(zscore.multi, zscore.eur)$estimate), by = c('training_model')]
  681. mdcorsig <- jointmdd[bhpval.eur <= 0.05 & bhpval.multi <= 0.05, .(zsc_cor = cor.test(zscore.multi, zscore.eur)$estimate), by = c('training_model')]
  682. mdcorsig2 <- jointmdd[bhpval.eur <= 0.05 | bhpval.multi <= 0.05, .(zsc_cor = cor.test(zscore.multi, zscore.eur)$estimate), by = c('training_model')]
  683. crossmdd <- setDT(merge(mda[training_model != 'PrediXcan_Brain_Cortex' & training_model != 'PrediXcan_Whole_Blood',], mde[training_model == 'PrediXcan_Whole_Blood',], by = c('gene_name'), suffixes = c('.multi_g2S', '.eur_gtex')))
  684. cmdcor <- crossmdd[, .(zsc_cor = cor.test(zscore.multi_g2S, zscore.eur_gtex)$estimate,
  685. zsc_ciL = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[1],
  686. zsc_ciH = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[2],
  687. .N), by = c('training_model.multi_g2S')]
  688. cmdcorsig <- crossmdd[bhpval.eur_gtex <= 0.05 & bhpval.multi_g2S <= 0.05, .(zsc_cor = cor.test(zscore.multi_g2S, zscore.eur_gtex)$estimate,
  689. zsc_ciL = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[1],
  690. zsc_ciH = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[2],
  691. .N), by = c('training_model.multi_g2S')]
  692. cmdcorsig2 <- crossmdd[bhpval.eur_gtex <= 0.05 | bhpval.multi_g2S <= 0.05, .(zsc_cor = cor.test(zscore.multi_g2S, zscore.eur_gtex)$estimate,
  693. zsc_ciL = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[1],
  694. zsc_ciH = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[2],
  695. .N), by = c('training_model.multi_g2S')]
  696. ## Make plots
  697. pdat1 <- setDT(merge(crossmdd, cmdcor, by = 'training_model.multi_g2S'))
  698. cmd_genecorr <- ggplot(data = pdat1, aes(x = zscore.multi_g2S, y=zscore.eur_gtex)) +
  699. geom_point() +
  700. #geom_pointdensity(adjust = 4) +
  701. #scale_color_viridis() +
  702. geom_smooth(method = 'lm', se=F, color = 'green4') +
  703. geom_text(aes(x = -Inf, y = Inf, label = paste0("R = ", round(zsc_cor, 3))),
  704. hjust = 0.1, vjust = -0.3, check_overlap = TRUE, color = 'green4', size = 3) +
  705. facet_grid2(.~training_model.multi_g2S, axes = 'all') +
  706. ggtitle('All shared genes') +
  707. xlab('zscore.G2S') +
  708. ylab('zscore.GTEx') +
  709. coord_cartesian( clip = "off")+
  710. theme_minimal()+
  711. theme(panel.spacing = unit(1, "cm", data = NULL),
  712. strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  713. name='Output/dual_zsc_corr_grid_all.pdf'
  714. pdf(file = name, width = 8, height = 2.6, pointsize = 12, bg = "white")
  715. print(cmd_genecorr)
  716. dev.off()
  717. print(cmd_genecorr)
  718. ```
  719. ### zscore cor all co-sig
  720. ```{r fig.width = 8, fig.height = 2.6}
  721. pdat2 <- setDT(merge(crossmdd[bhpval.eur_gtex <= 0.05 & bhpval.multi_g2S <= 0.05,], cmdcorsig, by = 'training_model.multi_g2S'))
  722. cmd_genecorr_sig <- ggplot(data = pdat2, aes(x = zscore.multi_g2S, y=zscore.eur_gtex)) +
  723. geom_point() +
  724. #geom_pointdensity(adjust = 4) +
  725. #scale_color_viridis() +
  726. geom_smooth(method = 'lm', se=F, color = 'springgreen3') +
  727. geom_text(aes(x = -Inf, y = Inf, label = paste0("R = ", round(zsc_cor, 3))),
  728. hjust = 0.1, vjust = -0.3, check_overlap = TRUE, color = 'springgreen3', size = 3) +
  729. facet_grid2(.~training_model.multi_g2S, axes = 'all') +
  730. ggtitle('All co-significant genes') +
  731. xlab('zscore.G2S') +
  732. ylab('zscore.GTEx') +
  733. coord_cartesian( clip = "off")+
  734. theme_minimal()+
  735. theme(panel.spacing = unit(1, "cm", data = NULL),
  736. strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  737. name='Output/dual_zsc_corr_grid_sig.pdf'
  738. pdf(file = name, width = 8, height = 2.6, pointsize = 12, bg = "white")
  739. print(cmd_genecorr_sig)
  740. dev.off()
  741. print(cmd_genecorr_sig)
  742. ```
  743. ### zscore cor all sig
  744. ```{r fig.width = 8, fig.height = 2.6}
  745. pdat3 <- setDT(merge(crossmdd[bhpval.eur_gtex <= 0.05 | bhpval.multi_g2S <= 0.05,], cmdcorsig2, by = 'training_model.multi_g2S'))
  746. cmd_genecorr_sig2 <- ggplot(data = pdat3, aes(x = zscore.multi_g2S, y=zscore.eur_gtex)) +
  747. geom_point() +
  748. #geom_pointdensity(adjust = 4) +
  749. #scale_color_viridis() +
  750. geom_smooth(method = 'lm', se=F, color = 'lightgreen') +
  751. geom_text(aes(x = -Inf, y = Inf, label = paste0("R = ", round(zsc_cor, 3))),
  752. hjust = 0.1, vjust = -0.3, check_overlap = TRUE, color = 'lightgreen', size = 3) +
  753. facet_grid2(.~training_model.multi_g2S, axes = 'all') +
  754. ggtitle('All significant genes') +
  755. xlab('zscore.G2S') +
  756. ylab('zscore.GTEx') +
  757. coord_cartesian( clip = "off")+
  758. theme_minimal()+
  759. theme(panel.spacing = unit(1, "cm", data = NULL),
  760. strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  761. name='Output/dual_zsc_corr_grid2_sig2.pdf'
  762. pdf(file = name, width = 8, height = 2.6, pointsize = 12, bg = "white")
  763. print(cmd_genecorr_sig2)
  764. dev.off()
  765. cmd_genecorr_sig2
  766. ```
  767. ### pval cor all shared 1
  768. ```{r fig.width = 8, fig.height = 2.6}
  769. cmdcor <- crossmdd[, .(zsc_cor = cor.test(pvalue.multi_g2S, pvalue.eur_gtex)$estimate,
  770. zsc_ciL = cor.test(pvalue.multi_g2S, pvalue.eur_gtex)$conf.int[1],
  771. zsc_ciH = cor.test(pvalue.multi_g2S, pvalue.eur_gtex)$conf.int[2],
  772. .N), by = c('training_model.multi_g2S')]
  773. cmdcorsig <- crossmdd[bhpval.eur_gtex <= 0.05 & bhpval.multi_g2S <= 0.05, .(zsc_cor = cor.test(pvalue.multi_g2S, pvalue.eur_gtex)$estimate,
  774. zsc_ciL = cor.test(pvalue.multi_g2S, pvalue.eur_gtex)$conf.int[1],
  775. zsc_ciH = cor.test(pvalue.multi_g2S, pvalue.eur_gtex)$conf.int[2],
  776. .N), by = c('training_model.multi_g2S')]
  777. cmdcorsig2 <- crossmdd[bhpval.eur_gtex <= 0.05 | bhpval.multi_g2S <= 0.05, .(zsc_cor = cor.test(pvalue.multi_g2S, pvalue.eur_gtex)$estimate,
  778. zsc_ciL = cor.test(pvalue.multi_g2S, pvalue.eur_gtex)$conf.int[1],
  779. zsc_ciH = cor.test(pvalue.multi_g2S, pvalue.eur_gtex)$conf.int[2],
  780. .N), by = c('training_model.multi_g2S')]
  781. ## Make plots
  782. pdat1 <- setDT(merge(crossmdd, cmdcor, by = 'training_model.multi_g2S'))
  783. cmd_genecorr <- ggplot(data = pdat1, aes(x = zscore.multi_g2S, y=zscore.eur_gtex)) +
  784. geom_point() +
  785. #geom_pointdensity(adjust = 4) +
  786. #scale_color_viridis() +
  787. geom_smooth(method = 'lm', se=F, color = 'gold') +
  788. geom_text(aes(x = -Inf, y = Inf, label = paste0("R = ", round(zsc_cor, 3))),
  789. hjust = 0.1, vjust = -0.3, check_overlap = TRUE, color = 'gold', size = 3) +
  790. facet_grid2(.~training_model.multi_g2S, axes = 'all') +
  791. ggtitle('All shared genes') +
  792. xlab('pvalue.G2S') +
  793. ylab('pvalue.GTEx') +
  794. coord_cartesian( clip = "off")+
  795. theme_minimal()+
  796. theme(panel.spacing = unit(1, "cm", data = NULL),
  797. strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  798. name='Output/dual_pval_corr_grid_all.pdf'
  799. pdf(file = name, width = 8, height = 2.6, pointsize = 12, bg = "white")
  800. print(cmd_genecorr)
  801. dev.off()
  802. print(cmd_genecorr)
  803. ```
  804. ### pval cor all co-sig
  805. And then again with pvalues.
  806. ```{r fig.width = 8, fig.height = 2.6}
  807. pdat2 <- setDT(merge(crossmdd[bhpval.eur_gtex <= 0.05 & bhpval.multi_g2S <= 0.05,], cmdcorsig, by = 'training_model.multi_g2S'))
  808. cmd_genecorr_sig <- ggplot(data = pdat2, aes(x = zscore.multi_g2S, y=zscore.eur_gtex)) +
  809. geom_point() +
  810. #geom_pointdensity(adjust = 4) +
  811. #scale_color_viridis() +
  812. geom_smooth(method = 'lm', se=F, color = 'yellow3') +
  813. geom_text(aes(x = -Inf, y = Inf, label = paste0("R = ", round(zsc_cor, 3))),
  814. hjust = 0.1, vjust = -0.3, check_overlap = TRUE, color = 'yellow3', size = 3) +
  815. facet_grid2(.~training_model.multi_g2S, axes = 'all') +
  816. ggtitle('All co-significant genes') +
  817. xlab('pvalue.G2S') +
  818. ylab('pvalue.GTEx') +
  819. coord_cartesian( clip = "off")+
  820. theme_minimal()+
  821. theme(panel.spacing = unit(1, "cm", data = NULL),
  822. strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  823. name='Output/dual_pval_corr_grid2_sig.pdf'
  824. pdf(file = name, width = 8, height = 2.6, pointsize = 12, bg = "white")
  825. print(cmd_genecorr_sig)
  826. dev.off()
  827. print(cmd_genecorr_sig)
  828. ```
  829. ### pval cor all sig
  830. ```{r fig.width = 8, fig.height = 2.6}
  831. pdat3 <- setDT(merge(crossmdd[bhpval.eur_gtex <= 0.05 | bhpval.multi_g2S <= 0.05,], cmdcorsig2, by = 'training_model.multi_g2S'))
  832. cmd_genecorr_sig2 <- ggplot(data = pdat3, aes(x = zscore.multi_g2S, y=zscore.eur_gtex)) +
  833. geom_point() +
  834. #geom_pointdensity(adjust = 4) +
  835. #scale_color_viridis() +
  836. geom_smooth(method = 'lm', se=F, color = 'lightgreen') +
  837. geom_text(aes(x = -Inf, y = Inf, label = paste0("R = ", round(zsc_cor, 3))),
  838. hjust = 0.1, vjust = -0.3, check_overlap = TRUE, color = 'goldenrod', size = 3) +
  839. facet_grid2(.~training_model.multi_g2S, axes = 'all') +
  840. ggtitle('All significant genes') +
  841. xlab('pvalue.G2S') +
  842. ylab('pvalue.GTEx') +
  843. coord_cartesian( clip = "off")+
  844. theme_minimal()+
  845. theme(panel.spacing = unit(1, "cm", data = NULL),
  846. strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  847. name='Output/dual_pval_corr_grid2_sig2.pdf'
  848. pdf(file = name, width = 8, height = 2.6, pointsize = 12, bg = "white")
  849. print(cmd_genecorr_sig2)
  850. dev.off()
  851. print(cmd_genecorr_sig2)
  852. ```
  853. ### Pval cor All shared
  854. ```{r fig.width = 8, fig.height = 2.6}
  855. snp_dat_all <- fread('Data/dual_data/dual_duo_snps_used.txt', header = T)
  856. cmd_snpcor <- snp_dat_all[, .(wt_cor = cor.test(weight.G2S, weight.GTEx)$estimate,
  857. zsc_ciL = cor.test(weight.G2S, weight.GTEx)$conf.int[1],
  858. zsc_ciH = cor.test(weight.G2S, weight.GTEx)$conf.int[2],
  859. .N), by = c('model')]
  860. cordat <- setDT(merge(snp_dat_all, cmd_snpcor, by = 'model'))
  861. cmd_snpcorr <- ggplot(data = cordat, aes(x = weight.G2S, y=weight.GTEx)) +
  862. geom_point() +
  863. #geom_pointdensity(adjust = 4) +
  864. #scale_color_viridis() +
  865. geom_smooth(method = 'lm', se=F, color = 'purple') +
  866. geom_text(aes(x = -Inf, y = Inf, label = paste0("R = ", round(wt_cor, 3))),
  867. hjust = 0.1, vjust = -0.3, check_overlap = TRUE, color = 'purple', size = 3) +
  868. facet_grid2(.~model, axes = 'all') +
  869. ggtitle('All shared genes') +
  870. xlab('weight.G2S') +
  871. ylab('weight.GTEx') +
  872. coord_cartesian( clip = "off")+
  873. theme_minimal()+
  874. theme(panel.spacing = unit(1, "cm", data = NULL),
  875. strip.text.x = element_text(margin = margin(5, 5, 12, 5, "pt")))
  876. name='Output/dual_weight_corr_grid_all.pdf'
  877. pdf(file = name, width = 8, height = 2.6, pointsize = 12, bg = "white")
  878. print(cmd_snpcorr)
  879. dev.off()
  880. print(cmd_snpcorr)
  881. ```
  882. ### Effect size correlation
  883. normalized zscore correlation across models
  884. ```{r fig.width = 12, fig.height = 4.25}
  885. duo_snps <- snp_dat_all
  886. ds_gene <- duo_snps[, .(N_g2s_SNPs = sum(!(is.na(weight.G2S)) & shared == F),
  887. N_GTeX_SNPs = sum(!(is.na(weight.GTEx)) & shared == F),
  888. N_shared_SNPs = sum(shared == TRUE),
  889. N_total_snps = length(unique(rsid)),
  890. prop_g2s = sum(!(is.na(weight.G2S)))/length(unique(rsid))), by = 'gene']
  891. #group genes by model presence
  892. ds_gene[, eqtl_source := fcase(N_g2s_SNPs == 0 & N_shared_SNPs == 0, "GTEx",
  893. N_GTeX_SNPs == 0 & N_shared_SNPs == 0, "G2S",
  894. N_shared_SNPs != 0, "shared_overlapping",
  895. N_shared_SNPs == 0 & (N_g2s_SNPs != 0 & N_GTeX_SNPs != 0), "shared_distinct")]
  896. dubs <- setDT(merge(crossmdd, ds_gene, by.x = c('gene.multi_g2S'), by.y = c('gene')))
  897. cmdcor_source <- dubs[, .(zsc_cor = cor.test(zscore.multi_g2S, zscore.eur_gtex)$estimate,
  898. zsc_ciL = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[1],
  899. zsc_ciH = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[2],
  900. .N), by = c('training_model.multi_g2S', 'eqtl_source')]
  901. fx_cor <- ggplot(data = cmdcor_source, aes(x = eqtl_source, y = zsc_cor, color = training_model.multi_g2S)) +
  902. geom_hline(yintercept = 0, color = 'red') +
  903. geom_errorbar(aes(ymin = zsc_ciL, ymax = zsc_ciH), width = 0.1, color = 'black') +
  904. geom_point(size = 2) +
  905. geom_label(aes(y = -0.75, label = paste('N =', N)), size = 3) +
  906. #scale_color_manual(values=c('green4', 'slateblue3')) +
  907. ylab('normalized effect size correlation') +
  908. xlab('SNP predictor model specificity') +
  909. ylim(c(-1, 1))+
  910. facet_grid(.~training_model.multi_g2S, scales = 'free') +
  911. theme_bw() +
  912. theme(axis.text.x = element_text(angle = 60, hjust = 1))
  913. name = 'Output/dual_genefx_corplot_grid.pdf'
  914. pdf(file = name, width = 12, height = 4.25, pointsize = 12, bg = "white")
  915. print(fx_cor)
  916. dev.off()
  917. print(fx_cor)
  918. ```
  919. ### Fig 4b: N SNPs per gene
  920. N Snp weights used per gene across the two models.
  921. ```{r fig.width = 12, fig.height = 4.25}
  922. cmdcor_source <- dubs[eqtl_source == 'shared_overlapping' & (bhpval.eur_gtex <= 0.05 | bhpval.multi_g2S <= 0.05), .(zsc_cor = cor.test(zscore.multi_g2S, zscore.eur_gtex)$estimate,
  923. zsc_ciL = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[1],
  924. zsc_ciH = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[2],
  925. .N), by = c('training_model.multi_g2S', 'eqtl_source')]
  926. cmd_sigs <- dubs[bhpval.eur_gtex <= 0.05 | bhpval.multi_g2S <= 0.05, .(.N), by = c('training_model.multi_g2S', 'eqtl_source')]
  927. snp_dat_all_L <- setDT(melt(snp_dat_all[, -c('shared')], id.vars = c('gene', 'rsid','model')))
  928. snp_dat_N <- snp_dat_all_L[!is.na(value) & variable == 'weight.G2S', .(N = length(unique(rsid))), by = c('gene', 'model')]
  929. snp_dat_all_L2 <- snp_dat_all_L
  930. snp_dat_all_L2[,gr := paste0(gene, rsid)]
  931. snp_dat_N2 <- snp_dat_all_L2[!is.na(value) & variable == 'weight.GTEx', .(N = length(unique(gr))), by = 'gene']
  932. snp_dat_N2[, model := 'GTEx_Whole_Blood']
  933. snp_dat_Ns <- rbind(snp_dat_N, snp_dat_N2)
  934. # median weight across all SNPs used
  935. eqtl_vplot <- ggplot(data = snp_dat_Ns, aes(x = model, y = N, fill = model)) +
  936. geom_violin(scale = 'width', position=position_dodge(1), drop = F) +
  937. geom_boxplot(width = 0.1, color = 'black', position=position_dodge(1), outlier.size = 0.5) +
  938. xlab('SNP predictor model ')+
  939. ylab('SNP predictors per gene') +
  940. theme_minimal()+
  941. theme(legend.position = 'none') +
  942. theme_bw() +
  943. theme(text = element_text(size = 13), axis.text = element_text(size = 13))
  944. name = 'Output/dual_snpPredNplot_gridvplot.pdf'
  945. pdf(file = name, width = 11, height = 3, pointsize = 12, bg = "white")
  946. print(eqtl_vplot)
  947. dev.off()
  948. print(eqtl_vplot)
  949. ```
  950. ### Fig 4c: Median SNP magnitude
  951. Median magnitude of the used SNP weights across the models.
  952. ```{r fig.width = 12, fig.height = 4.25}
  953. snp_dat_all_L1 <- snp_dat_all_L[!is.na(value) & variable == 'weight.G2S', -c('variable')]
  954. snp_dat_all_L2 <- unique(snp_dat_all_L[!is.na(value) & variable == 'weight.GTEx', -c('variable', 'model')])
  955. snp_dat_all_L2[, model := 'GTEx_Whole_Blood']
  956. snp_dat_wts <- rbind(snp_dat_all_L1, snp_dat_all_L2)
  957. eqtl_wtplot <- ggplot(data = snp_dat_wts, aes(x = model, y = abs(value), fill = model)) +
  958. geom_boxplot(color = 'black', position=position_dodge(1), outlier.shape = NA) +
  959. xlab('SNP predictor model ')+
  960. ylab('median SNP weight magnitude') +
  961. coord_cartesian(ylim= c(0,0.125)) +
  962. theme_minimal()+
  963. theme(legend.position = 'none') +
  964. theme_bw() +
  965. theme(text = element_text(size = 13), axis.text = element_text(size = 13))
  966. name = 'Output/dual_snpPred_wt_plot_gridvplot.pdf'
  967. pdf(file = name, width = 11, height = 3, pointsize = 12, bg = "white")
  968. print(eqtl_wtplot)
  969. dev.off()
  970. print(eqtl_wtplot)
  971. ```
  972. ### Fig 4d: All correlation Comparison
  973. Compile into single figure
  974. ```{r fig.width = 12, fig.height = 4.25}
  975. crossmdd2 <- crossmdd
  976. crossmdd2[bhpval.eur_gtex <= 0.05 | bhpval.multi_g2S <= 0.05, sig := 'sig']
  977. crossmdd2[!(bhpval.eur_gtex <= 0.05 | bhpval.multi_g2S <= 0.05), sig := 'nonsig']
  978. cmd_snpcor <- snp_dat_all[, .(wt_cor = cor.test(weight.G2S, weight.GTEx)$estimate,
  979. zsc_ciL = cor.test(weight.G2S, weight.GTEx)$conf.int[1],
  980. zsc_ciH = cor.test(weight.G2S, weight.GTEx)$conf.int[2],
  981. .N), by = c('model')]
  982. cmdcor <- crossmdd[, .(zsc_cor = cor.test(zscore.multi_g2S, zscore.eur_gtex)$estimate,
  983. zsc_ciL = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[1],
  984. zsc_ciH = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[2],
  985. .N), by = c('training_model.multi_g2S')]
  986. cmdcorsig <- crossmdd[bhpval.eur_gtex <= 0.05 & bhpval.multi_g2S <= 0.05, .(zsc_cor = cor.test(zscore.multi_g2S, zscore.eur_gtex)$estimate,
  987. zsc_ciL = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[1],
  988. zsc_ciH = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[2],
  989. .N), by = c('training_model.multi_g2S')]
  990. cmdcorsig2 <- crossmdd[bhpval.eur_gtex <= 0.05 | bhpval.multi_g2S <= 0.05, .(zsc_cor = cor.test(zscore.multi_g2S, zscore.eur_gtex)$estimate,
  991. zsc_ciL = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[1],
  992. zsc_ciH = cor.test(zscore.multi_g2S, zscore.eur_gtex)$conf.int[2],
  993. .N), by = c('training_model.multi_g2S')]
  994. snp1 <- setnames(cmd_snpcor, c('wt_cor', 'zsc_ciL', 'zsc_ciH'), c('cor', 'ciL', 'ciH'))
  995. #snp1 <- cmd_snpcor
  996. snp1$group <- 'SNP weights'
  997. gene1 <- setnames(cmdcor, c('training_model.multi_g2S', 'zsc_cor', 'zsc_ciL', 'zsc_ciH'), c('model','cor', 'ciL', 'ciH'))
  998. #gene1 <- cmdcor
  999. gene1$group <- 'all genes'
  1000. genesig <- setnames(cmdcorsig2, c('training_model.multi_g2S', 'zsc_cor', 'zsc_ciL', 'zsc_ciH'), c('model','cor', 'ciL', 'ciH'))
  1001. #genesig <- cmdcorsig2
  1002. genesig$group <- 'sig genes'
  1003. compdata <- setDT(rbind(snp1, gene1, genesig))
  1004. compdata$group <- factor(compdata$group, levels=c('SNP weights', 'all genes', 'sig genes'))
  1005. allcor_plot <- ggplot(data = compdata, aes(x = group, y = cor, color = model, group = model)) +
  1006. geom_errorbar(aes(ymin = ciL, ymax = ciH), width = 0.3, color = 'black', position=position_dodge(width=0.9)) +
  1007. geom_point( position=position_dodge(width = 0.9), size = 3) +
  1008. xlab('measurement') +
  1009. ylab('r correlation coefficient') +
  1010. ylim(c(0,1)) +
  1011. theme_bw() +
  1012. theme(text = element_text(size = 13), axis.text = element_text(size = 13))
  1013. name = 'Output/dual_allcordat_mddcomp.pdf'
  1014. pdf(file = name, width = 11, height = 3, pointsize = 12, bg = "white")
  1015. print(allcor_plot)
  1016. dev.off()
  1017. print(allcor_plot)
  1018. ```
  1019. ## NeuroimaGene analysis
  1020. Use the NeuroimaGene resource to get the neuroimaging features associated with the
  1021. TWAS results for each disease.
  1022. ### Fig 6a: Neuroimaging visualizations
  1023. ```{r neuroimaGene1}
  1024. library(neuroimaGene)
  1025. ########## NeuroimaGene analysis
  1026. all <- dt
  1027. bdg <- unique(all[gwas_phenotype == 'PGC_BD1_2021',]$gene)
  1028. szg <- unique(all[gwas_phenotype == 'PGC_all_SCZ_2022']$gene)
  1029. adg <- unique(all[gwas_phenotype == 'PGC_allADHD_2022']$gene)
  1030. mdg <- unique(all[gwas_phenotype == 'PGC_allMDD_2023']$gene)
  1031. ptg <- unique(all[gwas_phenotype == 'PGC_ALL_PTSD_2024']$gene)
  1032. aug <- unique(all[gwas_phenotype == 'SUD_alc_2019']$gene)
  1033. bdng <- neuroimaGene(bdg)
  1034. neuro_vis(bdng)
  1035. ```
  1036. ```{r}
  1037. szng <- neuroimaGene(szg)
  1038. neuro_vis(szng)
  1039. ```
  1040. ```{r}
  1041. adng <- neuroimaGene(adg)
  1042. neuro_vis(adng)
  1043. ```
  1044. ```{r}
  1045. mdng <- neuroimaGene(mdg)
  1046. neuro_vis(mdng)
  1047. ```
  1048. ```{r}
  1049. ptng <- neuroimaGene(ptg)
  1050. neuro_vis(ptng)
  1051. ```
  1052. ```{r}
  1053. aung <- neuroimaGene(aug)
  1054. neuro_vis(aung)
  1055. ```
  1056. ```{r}
  1057. bdng2 <- neuroimaGene(bdg, atlas = 'aseg_volume')
  1058. neuro_vis(bdng2, atlas = 'Subcortex')
  1059. ```
  1060. ```{r}
  1061. szng2 <- neuroimaGene(szg, atlas = 'aseg_volume')
  1062. neuro_vis(szng2, atlas = 'Subcortex')
  1063. ```
  1064. ```{r}
  1065. adng2 <- neuroimaGene(adg, atlas = 'aseg_volume')
  1066. neuro_vis(adng2, atlas = 'Subcortex')
  1067. ```
  1068. ```{r}
  1069. mdng2 <- neuroimaGene(mdg, atlas = 'aseg_volume')
  1070. neuro_vis(mdng2, atlas = 'Subcortex')
  1071. ```
  1072. ```{r}
  1073. ptng2 <- neuroimaGene(ptg, atlas = 'aseg_volume')
  1074. neuro_vis(ptng2, atlas = 'Subcortex')
  1075. ```
  1076. ```{r}
  1077. aung2 <- neuroimaGene(aug, atlas = 'aseg_volume')
  1078. neuro_vis(aung2, atlas = 'Subcortex')
  1079. ```
  1080. Compile data
  1081. ```{r}
  1082. adng$group <- 'ADHD'
  1083. adng2$group <- 'ADHD'
  1084. aung2$group <- 'AUD'
  1085. aung$group <- 'AUD'
  1086. bdng$group <- 'BD1'
  1087. bdng2$group <- 'BD1'
  1088. mdng$group <- 'MDD'
  1089. mdng2$group <- 'MDD'
  1090. ptng$group <- 'PTSD'
  1091. ptng2$group <- 'PTSD'
  1092. szng$group <- 'SCZ'
  1093. szng2$group <- 'SCZ'
  1094. ng_data_ <- rbind(bdng, szng, adng, mdng, ptng, aung, bdng2, szng2, adng2, mdng2, ptng2, aung2)
  1095. ng_data <- setDT(merge(ng_data_, neuroimaGene::anno, by = 'gwas_phenotype'))
  1096. ```
  1097. Comparison with no G2S
  1098. ```{r}
  1099. eur <- dt[training_model == 'PrediXcan_Whole_Blood']
  1100. bdg_e <- unique(eur[gwas_phenotype == 'PGC_BD1_2021',]$gene)
  1101. szg_e <- unique(eur[gwas_phenotype == 'PGC_all_SCZ_2022']$gene)
  1102. adg_e <- unique(eur[gwas_phenotype == 'PGC_allADHD_2022']$gene)
  1103. mdg_e <- unique(eur[gwas_phenotype == 'PGC_allMDD_2023']$gene)
  1104. ptg_e <- unique(eur[gwas_phenotype == 'PGC_ALL_PTSD_2024']$gene)
  1105. aug_e <- unique(eur[gwas_phenotype == 'SUD_alc_2019']$gene)
  1106. bdng_e <- neuroimaGene(bdg_e)
  1107. szng_e <- neuroimaGene(szg_e)
  1108. adng_e <- neuroimaGene(adg_e)
  1109. mdng_e <- neuroimaGene(mdg_e)
  1110. ptng_e <- neuroimaGene(ptg_e)
  1111. aung_e <- neuroimaGene(aug_e)
  1112. bdng2_e <- neuroimaGene(bdg_e, atlas = 'aseg_volume')
  1113. szng2_e <- neuroimaGene(szg_e, atlas = 'aseg_volume')
  1114. adng2_e <- neuroimaGene(adg_e, atlas = 'aseg_volume')
  1115. mdng2_e <- neuroimaGene(mdg_e, atlas = 'aseg_volume')
  1116. ptng2_e <- neuroimaGene(ptg_e, atlas = 'aseg_volume')
  1117. aung2_e <- neuroimaGene(aug_e, atlas = 'aseg_volume')
  1118. adng_e$group <- 'ADHD'
  1119. adng2_e$group <- 'ADHD'
  1120. aung2_e$group <- 'AUD'
  1121. aung_e$group <- 'AUD'
  1122. bdng_e$group <- 'BD1'
  1123. bdng2_e$group <- 'BD1'
  1124. mdng_e$group <- 'MDD'
  1125. mdng2_e$group <- 'MDD'
  1126. ptng_e$group <- 'PTSD'
  1127. ptng2_e$group <- 'PTSD'
  1128. szng_e$group <- 'SCZ'
  1129. szng2_e$group <- 'SCZ'
  1130. ng_data_e_ <- rbind(bdng_e, szng_e, adng_e, mdng_e, ptng_e, aung_e, bdng2_e, szng2_e, adng2_e, mdng2_e, ptng2_e, aung2_e)
  1131. ng_data_e <- setDT(merge(ng_data_e_, neuroimaGene::anno, by = 'gwas_phenotype'))[, -c('zscore', 'atl_BHpval', 'fMRI_node_1', 'fMRI_node_2')]
  1132. ```
  1133. now g2s
  1134. ```{r}
  1135. g2s <- dt[training_model != 'PrediXcan_Whole_Blood']
  1136. bdg_g <- unique(g2s[gwas_phenotype == 'PGC_BD1_2021',]$gene)
  1137. szg_g <- unique(g2s[gwas_phenotype == 'PGC_all_SCZ_2022']$gene)
  1138. adg_g <- unique(g2s[gwas_phenotype == 'PGC_allADHD_2022']$gene)
  1139. mdg_g <- unique(g2s[gwas_phenotype == 'PGC_allMDD_2023']$gene)
  1140. ptg_g <- unique(g2s[gwas_phenotype == 'PGC_ALL_PTSD_2024']$gene)
  1141. aug_g <- unique(g2s[gwas_phenotype == 'SUD_alc_2019']$gene)
  1142. bdng_g <- neuroimaGene(bdg_g)
  1143. szng_g <- neuroimaGene(szg_g)
  1144. adng_g <- neuroimaGene(adg_g)
  1145. mdng_g <- neuroimaGene(mdg_g)
  1146. ptng_g <- neuroimaGene(ptg_g)
  1147. aung_g <- neuroimaGene(aug_g)
  1148. bdng2_g <- neuroimaGene(bdg_g, atlas = 'aseg_volume')
  1149. szng2_g <- neuroimaGene(szg_g, atlas = 'aseg_volume')
  1150. adng2_g <- neuroimaGene(adg_g, atlas = 'aseg_volume')
  1151. mdng2_g <- neuroimaGene(mdg_g, atlas = 'aseg_volume')
  1152. ptng2_g <- neuroimaGene(ptg_g, atlas = 'aseg_volume')
  1153. aung2_g <- neuroimaGene(aug_g, atlas = 'aseg_volume')
  1154. adng_g$group <- 'ADHD'
  1155. adng2_g$group <- 'ADHD'
  1156. aung2_g$group <- 'AUD'
  1157. aung_g$group <- 'AUD'
  1158. bdng_g$group <- 'BD1'
  1159. bdng2_g$group <- 'BD1'
  1160. mdng_g$group <- 'MDD'
  1161. mdng2_g$group <- 'MDD'
  1162. ptng_g$group <- 'PTSD'
  1163. ptng2_g$group <- 'PTSD'
  1164. szng_g$group <- 'SCZ'
  1165. szng2_g$group <- 'SCZ'
  1166. ng_data_g_ <- rbind(bdng_g, szng_g, adng_g, mdng_g, ptng_g, aung_g, bdng2_g, szng2_g, adng2_g, mdng2_g, ptng2_g, aung2_g)
  1167. ng_data_g <- setDT(merge(ng_data_g_, neuroimaGene::anno, by = 'gwas_phenotype'))[, -c('zscore', 'atl_BHpval', 'fMRI_node_1', 'fMRI_node_2')]
  1168. ```
  1169. Separate out and print the neuroimagene findings specific to G2S models
  1170. ```{r}
  1171. ng_data_g$id <- paste0(ng_data_g$gwas_phenotype, ng_data_g$group)
  1172. ng_data_e$id <- paste0(ng_data_e$gwas_phenotype, ng_data_e$group)
  1173. ng_data_gonly <- ng_data_g[!(id %in% ng_data_e$id),][measurement != 'QC',]
  1174. ng_data_gonly[, xlabel := paste0(atlas, '\n', measurement)]
  1175. ng_plotdata <- ng_data_gonly[, .(N = length(unique(gwas_phenotype))), by = c('group', 'xlabel')]
  1176. ng_plotdata$group <- factor(ng_plotdata$group, levels = c("PTSD", "SCZ", "ADHD", "MDD", "BD1", "AUD"))
  1177. ng_barplot <- ggplot(ng_plotdata, aes(y = N, x = xlabel, fill = xlabel)) +
  1178. geom_bar(stat = 'identity') +
  1179. facet_grid(group~.) +
  1180. scale_fill_brewer(palette = 'Dark2') +
  1181. ylab('G2S specific NIDPs') +
  1182. xlab('measurement') +
  1183. theme_minimal() +
  1184. theme(axis.text.x = element_text(angle = 270), legend.position = 'none')
  1185. name = 'Output/ng_g2s_barplot.pdf'
  1186. pdf(file = name, width = 2.5, height = 7, pointsize = 12, bg = "white")
  1187. print(ng_barplot)
  1188. dev.off()
  1189. print(ng_barplot)
  1190. ```
  1191. ### Fig S1: Descriptive Summary Data
  1192. Show the number of results for each model/disease pair and split by shared vs individually significant.
  1193. **Special thanks to Nathan Watkins and Tavian Bowen-Moore**
  1194. ```{r, echo=FALSE}
  1195. library(data.table)
  1196. library(ggplot2)
  1197. library(gridExtra)
  1198. dt[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  1199. dt[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  1200. dt[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  1201. dt[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  1202. dt[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  1203. dt1 <- dt[!training_model == 'PrediXcan_Whole_Blood']
  1204. dt2 <- dt[training_model == 'PrediXcan_Whole_Blood']
  1205. # Function to clean gene names
  1206. clean_gene_name <- function(gene_name) {
  1207. sub("\\..*", "", gene_name)
  1208. }
  1209. # Function to create and store plots
  1210. create_plots <- function(MAtwas, MUtwas) {
  1211. # Clean gene names in both datasets
  1212. MAtwas[, gene_name := clean_gene_name(gene_name)]
  1213. MUtwas[, gene_name := clean_gene_name(gene_name)]
  1214. # List to store plots
  1215. plots <- list()
  1216. for (blood_type in unique(MUtwas$training_model)) {
  1217. # Loop through each unique blood type in MUtwas
  1218. for (phenotype in unique(MAtwas$gwas_phenotype)) {
  1219. # Subset the data based on the current phenotype and blood type
  1220. tut <- MUtwas[training_model == blood_type & gwas_phenotype == phenotype,]
  1221. tot <- MAtwas[training_model == 'PrediXcan_Whole_Blood' & gwas_phenotype == phenotype,]
  1222. # Check if all entries in tut are 'GTEX_whole_blood'
  1223. if (all(tut$training_model == 'PrediXcan_Whole_Blood')) {
  1224. next
  1225. }
  1226. # Split the tut data.table into 2 data.tables according to training model
  1227. aa <- tut[training_model == blood_type,]
  1228. eur <- tot
  1229. # Get vectors of all gene associations with the disease in each set
  1230. aa_gns <- unique(aa$gene_name)
  1231. eur_gns <- unique(eur$gene_name)
  1232. # Create vectors of gene names that are unique to AA, GTEx, and shared
  1233. unique_eur <- setdiff(eur_gns, aa_gns)
  1234. unique_aa <- setdiff(aa_gns, eur_gns)
  1235. shared <- intersect(aa_gns, eur_gns)
  1236. # Custom names and color mapping for plotting
  1237. custom_names <- c('AA_Whole_Blood' = 'AA',
  1238. 'All_Whole_Blood' = 'ALL',
  1239. 'MX_Whole_Blood' = 'MX',
  1240. 'PR_Whole_Blood' = 'PR',
  1241. 'PrediXcan_Whole_Blood' = 'GTEx')
  1242. color_mapping <- c('AA' = 'orange',
  1243. 'ALL' = 'red',
  1244. 'MX' = 'pink',
  1245. 'PR' = 'green',
  1246. 'GTEx' = 'blue',
  1247. 'shared' = 'cyan')
  1248. dz_names <- c('PGC_allADHD_2022' = 'ADHD',
  1249. 'PGC_all_SCZ_2022' = 'SCZ',
  1250. 'PGC_allMDD_2023' = 'MDD',
  1251. 'PGC_BD1_2021' = 'BD1',
  1252. 'SUD_alc_2019' = 'SUD-A',
  1253. 'PGC_ALL_PTSD_2024' = 'PTSD')
  1254. # Set the disease name
  1255. dz_name <- dz_names[unique(aa$gwas_phenotype)]
  1256. # Create data.table with data for plotting
  1257. gene_cts <- data.table(study_specificity = c('GTEx', custom_names[blood_type], 'shared'),
  1258. N = c(length(unique_eur), length(unique_aa), length(shared)))
  1259. # Set the factor levels for study_specificity
  1260. gene_cts$study_specificity <- factor(gene_cts$study_specificity, levels = names(color_mapping))
  1261. # Create and plot the ggplot object
  1262. p2 <- ggplot(data = gene_cts,
  1263. aes(x = study_specificity, y = N, fill = study_specificity)) +
  1264. geom_bar(stat = 'identity') +
  1265. ggtitle(dz_name) +
  1266. xlab("Study Specificity") +
  1267. ylab("Number of Genes") +
  1268. scale_fill_manual(values = color_mapping) +
  1269. theme_minimal() +
  1270. theme(
  1271. plot.title = element_text(size = 10), # Reduce title size
  1272. axis.title = element_text(size = 9), # Reduce axis titles size
  1273. axis.text = element_text(size = 9), # Reduce axis text size
  1274. plot.margin = margin(10, 10, 10, 10),
  1275. legend.position = 'none'
  1276. )
  1277. # Store the plot in the list
  1278. plots[[paste(phenotype, blood_type, sep = "_")]] <- p2
  1279. }
  1280. }
  1281. return(plots)
  1282. }
  1283. # Generate and save plots to PDF
  1284. save_plots_to_pdf <- function(plots, file_name) {
  1285. pdf(file_name, width = 13, height = 8)
  1286. do.call(grid.arrange, c(plots, ncol = 6, padding = unit(1, "lines")))
  1287. dev.off()
  1288. }
  1289. # usage
  1290. plots <- create_plots(dt2, dt1)
  1291. save_plots_to_pdf(plots, "Output/gene_unique_comp2.pdf")
  1292. knitr::include_graphics("Output/gene_unique_comp2.pdf")
  1293. ```
  1294. # Corrplots
  1295. ### Fig 5a: correlation plots
  1296. Get correlation of disase TWAS results across models to see if the models are predicting the same
  1297. inter-disease transcriptomic relationships.
  1298. ```{r}
  1299. library(data.table)
  1300. library(corrplot)
  1301. dt_ <- fread('Data/all_exc_assocs_PGCancestryTWAS.txt', header = TRUE)
  1302. # exclude replication/comparison data from initial analysis.
  1303. gwas <- c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024', 'PGC_EURO_SCZ_2022', 'PGC_LATINO_SCZ_2022')
  1304. mod <- c('PrediXcan_Brain_Cortex')
  1305. dt <- dt_[!(gwas_phenotype %in% gwas | training_model %in% mod),]
  1306. dt[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  1307. dt[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  1308. dt[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  1309. dt[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  1310. dt[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  1311. dt1a <- dt[!training_model == 'PrediXcan_Whole_Blood']
  1312. dt2a <- dt[training_model == 'PrediXcan_Whole_Blood']
  1313. # Function to clean gene names
  1314. clean_gene_name <- function(gene_name) {
  1315. sub("\\..*", "", gene_name)
  1316. }
  1317. # Function to create and save correlation plots
  1318. create_and_save_corr_plots <- function(MAtwas, MUtwas) {
  1319. # Clean gene names in both datasets
  1320. MAtwas[, gene_name := clean_gene_name(gene_name)]
  1321. MUtwas[, gene_name := clean_gene_name(gene_name)]
  1322. # Get unique training models from MUtwas and add GTEX from MAtwas
  1323. training_models <- unique(MUtwas$training_model)
  1324. training_models <- c(training_models, 'PrediXcan_Whole_Blood')
  1325. # Define a custom color palette
  1326. custom_colors <- colorRampPalette(c("red", "grey60", "blue"))(1000)
  1327. # Open a PDF device with Letter dimensions
  1328. pdf("Output/correlograms.pdf", width = 8.5, height = 11)
  1329. for (model in training_models) {
  1330. modl <- copy(model)
  1331. # Filter data for the current training model
  1332. if (model == 'PrediXcan_Whole_Blood') {
  1333. filtered_data <- MAtwas[training_model == 'PrediXcan_Whole_Blood', c('gwas_phenotype', 'gene', 'zscore')]
  1334. } else {
  1335. filtered_data <- MUtwas[training_model == modl, c('gwas_phenotype', 'gene', 'zscore')]
  1336. }
  1337. unique_genes <- unique(filtered_data$gene)
  1338. unique_phenotypes <- unique(filtered_data$gwas_phenotype)
  1339. matrix_data <- matrix(NA, nrow = length(unique_genes), ncol = length(unique_phenotypes))
  1340. rownames(matrix_data) <- unique_genes
  1341. colnames(matrix_data) <- unique_phenotypes
  1342. for (i in 1:nrow(filtered_data)) {
  1343. row <- filtered_data[i, ]
  1344. matrix_data[row$gene, row$gwas_phenotype] <- row$zscore
  1345. }
  1346. cor_matrix <- cor(matrix_data, use = "pairwise.complete.obs")
  1347. # Adjust plot margins to accommodate longer titles
  1348. par(mar = c(1, 1, 5, 1))
  1349. corrplot(corr = cor_matrix,
  1350. method = "circle",
  1351. type = "lower",
  1352. tl.pos = "tl",
  1353. order = "original",
  1354. col = custom_colors, # Use custom colors
  1355. title = paste("Correlation plot for training model:", model),
  1356. mar = c(0, 0, 2, 0)) # Adjust margins to fit the title
  1357. }
  1358. # Close the PDF device
  1359. dev.off()
  1360. }
  1361. # Example usage
  1362. create_and_save_corr_plots(dt2a, dt1a)
  1363. ```
  1364. ## Cell type analysis
  1365. What are the cell types most implicated in the brain analyses based on the TWAS genes that emerged as significant.
  1366. ```{r}
  1367. pg <- fread('../../PanglaoDB_markers_27_Mar_2020.tsv', header = T)
  1368. overlap <- merge(
  1369. dt[, .(`gene_name`, gwas_phenotype)],
  1370. pg[, .(`official gene symbol`, `cell type`)],
  1371. by.x = "gene_name",
  1372. by.y = "official gene symbol",
  1373. allow.cartesian = TRUE
  1374. )
  1375. # Count overlaps for each disease × cell_type pair
  1376. result <- overlap[, .(n_genes = uniqueN(gene_name), genes = paste(unique(gene_name), collapse = '|')), by = c('gwas_phenotype', 'cell type')]
  1377. # Optional: ensure long format (already long here)
  1378. setorder(result, gwas_phenotype, `n_genes`)
  1379. write.table(result[n_genes > 1, ], 'Output/disease_cell_types.txt', col.names = T, row.names = F, quote = F, sep = '\t')
  1380. ```
  1381. ## TWAS Power from GWAS ancestries
  1382. ### Fig S24: Ancestry specific TWAS
  1383. We hypothesized that the derivation of statistically significant twas results from different GWAS was affected by the N for each ancestry specific GWAS. We next examine how similar the TWAS results from the GWAS subsets are to the general data across multiple significance cutoffs.
  1384. ```{r}
  1385. allnom <- fread('Data/all_exc_assocs_PGCancestryTWAS.txt', header = T)
  1386. allnom <- allnom[pvalue <= 0.05,]
  1387. # exclude replication/comparison data from initial analysis.
  1388. gwas <- c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024')
  1389. mod <- c('PrediXcan_Brain_Cortex')
  1390. anc <- allnom[gwas_phenotype %in% gwas & !(training_model %in% mod),]
  1391. gpdict1 <- data.table(gwas_phenotype = gwas, diagnosis = c('MDD', 'PTSD', 'SCZ', 'SCZ', 'PTSD', 'PTSD'), gwas_ancestry = c('AA', 'AA', 'AA', 'EA', 'EUR', 'HNA'))
  1392. gpdict2 <- data.table(gwas_phenotype = c('PGC_allADHD_2022', 'PGC_allMDD_2023', 'PGC_ALL_PTSD_2024', 'PGC_all_SCZ_2022', 'PGC_BD1_2021', 'SUD_alc_2019'),
  1393. diagnosis = c('ADHD', 'MDD', 'PTSD', 'SCZ', 'BD1', 'AUD'),
  1394. gwas_ancestry = c('multi', 'multi', 'multi', 'multi', 'EUR', 'multi'))
  1395. dt_ <- fread('Data/all_exc_BHsig_assocs_PGCancestryTWAS.txt', header = TRUE)
  1396. dt <- dt_[!(gwas_phenotype %in% gwas | training_model %in% mod),]
  1397. dt[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  1398. dt[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  1399. dt[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  1400. dt[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  1401. dt[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  1402. anc2 <- setDT(merge(anc, gpdict1, by = 'gwas_phenotype'))
  1403. dt2 <- setDT(merge(dt, gpdict2, by = c('gwas_phenotype')))
  1404. duo <- setDT(merge(dt2, anc2, by = c('gene', 'diagnosis', 'training_model'), suffixes = c('.multi', '.sa')))
  1405. pdata <- data.table()
  1406. for (dz in unique(duo$diagnosis)) {
  1407. for (g_anc in unique(duo$gwas_ancestry.sa)) {
  1408. for(pthresh in c(5*10^seq(-2, -5, -1), 1*10^seq(-2, -5, -1))) {
  1409. if(nrow(duo[pvalue.sa <= pthresh & (diagnosis == dz & gwas_ancestry.sa == g_anc),]) >= 5) {
  1410. mod <- lm(data = duo[pvalue.sa <= pthresh & (diagnosis == dz & gwas_ancestry.sa == g_anc),], zscore.multi~zscore.sa)
  1411. newdat <- data.table(pvalue = pthresh, diagnosis = dz, gwas_ancestry = g_anc, N = nrow(duo[pvalue.sa <= pthresh & (diagnosis == dz & gwas_ancestry.sa == g_anc),]), r2 = summary(mod)$adj.r.squared, regression_p = summary(mod)$coefficients[2,4])
  1412. pdata <- rbind(pdata, newdat)
  1413. }
  1414. }
  1415. }
  1416. }
  1417. pz <- ggplot(pdata, aes(x = -log10(pvalue), y = r2, color = -log10(regression_p))) +
  1418. geom_hline(yintercept = 0) +
  1419. geom_point() +
  1420. facet_wrap(diagnosis~gwas_ancestry, scales = 'free', nrow = 6) +
  1421. scale_y_continuous(limits = c(-0.5, 1)) +
  1422. scale_x_continuous(limits = c(0, 5)) +
  1423. theme_minimal() +
  1424. theme(legend.position = 'bottom')
  1425. name = 'Output/anc_specific_r2.pdf'
  1426. pdf(file = name, width = 3.5, height = 10, pointsize = 12, bg = "white")
  1427. print(pz)
  1428. dev.off()
  1429. print(pz)
  1430. ```
  1431. ### Fig S25: produce TWAS plots for multi-ancestry GWAS
  1432. ```{r}
  1433. library(data.table)
  1434. library(ggplot2)
  1435. library(ggrepel)
  1436. library(stringr)
  1437. library(colorspace)
  1438. dt_ <- fread('Data/all_exc_assocs_PGCancestryTWAS.txt', header = TRUE)
  1439. # include replication/comparison data from initial analysis.
  1440. gwas <- c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024', 'PGC_EURO_SCZ_2022','PGC_LATINO_SCZ_2022')
  1441. mod <- c('PrediXcan_Brain_Cortex')
  1442. dt <- dt_[gwas_phenotype %in% gwas & !(training_model %in% mod),]
  1443. dt[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  1444. dt[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  1445. dt[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  1446. dt[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  1447. dt[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  1448. tms <- rev(c('G2S All WB', 'G2S African American WB', 'G2S Mexican American WB', 'G2S Puerto Rican WB', 'GTEx European WB'))
  1449. dt$`gene expression model` <- factor(dt$`gene expression model`, levels = tms)
  1450. dt$gene <- str_remove_all(dt$gene, '\\..+')
  1451. # Iterate through the tissue models and NIDPs from the TWAS results
  1452. # Get the top 15 p-values for labeling purposes
  1453. top15 <- dt[, .(pvalue = min(pvalue)), by = c('gene','gene_name')][order(pvalue)][1:8, c('gene','gene_name','pvalue')]
  1454. top15x = setDT(merge(top15, all_genes_loc, by.x = 'gene', by.y = 'ensembl_gene_id'))
  1455. top15x$short_name = 'top_15'
  1456. top25 <- dt[, .(pvalue = min(pvalue)), by = c('gene','gene_name')][order(pvalue)][1:25, c('gene','gene_name','pvalue')]
  1457. top25x = setDT(merge(top25, all_genes_loc, by.x = 'gene', by.y = 'ensembl_gene_id'))
  1458. top25x$short_name = 'top_25'
  1459. twas2 <- merge(dt, all_genes_loc, by.x = 'gene', by.y = 'ensembl_gene_id')
  1460. twas2$`gene expression model` <- factor(twas2$`gene expression model`, levels = tms)
  1461. fig2 = ggplot(twas2, aes(x=gn_start, y=-log10(pvalue))) +
  1462. # Show all points
  1463. geom_point( aes(color=`gene expression model`), alpha=0.8, size=1.5) +
  1464. geom_hline(yintercept=-log10(0.05/(dim(adtwas2)[1])), color = "red", size=0.5) +
  1465. facet_wrap(vars(gwas_phenotype), scales = 'free', nrow = 6) +
  1466. xlab('chromosome') +
  1467. ylab('-log 10 pvalue')+
  1468. #scale_color_manual(values = rep(c("grey", "skyblue"), 22 )) +
  1469. scale_x_continuous(label = chrom_sizes[c(1:18,20,22),]$CHR, breaks= chrom_sizes[c(1:18,20,22),]$chr_label_loc ) +
  1470. scale_color_discrete_diverging(palette = 'Berlin') +
  1471. guides(color = guide_legend(nrow=3, byrow=FALSE)) +
  1472. theme_minimal()+
  1473. theme(
  1474. legend.position="bottom",
  1475. panel.border = element_blank(),
  1476. panel.grid.major.x = element_blank(),
  1477. panel.grid.minor.x = element_blank(),
  1478. axis.title.x = element_blank(),
  1479. plot.title = element_text(hjust = 0.5),
  1480. legend.text=element_text()
  1481. )
  1482. name = 'Output/all_assocs_nashplot_pgc_ancs2.pdf'
  1483. pdf(file = name, width = 14, height = 15, pointsize = 12, bg = "white")
  1484. print(fig2)
  1485. dev.off()
  1486. ```
  1487. ```{r}
  1488. print(fig2)
  1489. ```
  1490. # Revisions Round 1
  1491. ```{r}
  1492. dir.create('Output/revisions')
  1493. ```
  1494. ### Fig S2: Statistical contributors to model power
  1495. ```{r}
  1496. # Do power comparison for N individuals in training set vs number of associations.
  1497. # Read in all significant data and subset GWAS findings of interest
  1498. sig <- fread('Data/all_exc_BHsig_assocs_PGCancestryTWAS.txt', header = T)
  1499. dt <- sig[!(gwas_phenotype %in% c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024', 'PGC_EURO_SCZ_2022')),]
  1500. dt[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  1501. dt[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  1502. dt[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  1503. dt[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  1504. dt[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  1505. dt[training_model == 'PrediXcan_Brain_Cortex', `gene expression model` := 'GTEx European Brain']
  1506. dtn <- dt[, .(N_assocs =.N), by = c('gene expression model')]
  1507. dtn[ `gene expression model` == 'G2S All WB', N_samples := 2733]
  1508. dtn[`gene expression model` == 'G2S African American WB', N_samples := 757]
  1509. dtn[`gene expression model` == 'G2S Mexican American WB', N_samples := 784]
  1510. dtn[ `gene expression model` == 'G2S Puerto Rican WB', N_samples := 893]
  1511. dtn[ `gene expression model` == 'GTEx European WB', N_samples := 670]
  1512. dtn[ `gene expression model` == 'GTEx European Brain', N_samples := 205]
  1513. dtn[ `gene expression model` == 'G2S All WB', Mean_Afr := 0.32]
  1514. dtn[`gene expression model` == 'G2S African American WB', Mean_Afr := 0.8]
  1515. dtn[`gene expression model` == 'G2S Mexican American WB', Mean_Afr := 0.04]
  1516. dtn[ `gene expression model` == 'G2S Puerto Rican WB', Mean_Afr := 0.22]
  1517. dtn[ `gene expression model` == 'G2S All WB', Mean_IAM := 0.24]
  1518. dtn[`gene expression model` == 'G2S African American WB', Mean_IAM := 0.01]
  1519. dtn[`gene expression model` == 'G2S Mexican American WB', Mean_IAM := 0.57]
  1520. dtn[ `gene expression model` == 'G2S Puerto Rican WB', Mean_IAM := 0.10]
  1521. library(ggrepel)
  1522. lmod <- lm(data = dtn, N_assocs ~ N_samples)
  1523. lmod <- lm(data = dtn, N_assocs ~ N_samples)
  1524. lmodall <- lm(data = dtn[c(1,2,3,6),], N_assocs ~ Mean_Afr)
  1525. summary(lmodall)
  1526. lmod_g2s <- lm(data = dtn[!(`gene expression model` %in% c('GTEx European WB', 'GTEx European Brain')),], N_assocs ~ N_samples)
  1527. dtn_plot_g2s <- ggplot(dtn[!(`gene expression model` %in% c('GTEx European WB', 'GTEx European Brain')),], aes(x = N_samples, y = N_assocs, color = `gene expression model`)) +
  1528. geom_point() +
  1529. geom_smooth(method = 'lm', color = 'black', se = F) +
  1530. #geom_text(aes(x = -Inf, y = -Inf, label = summary(lmod_g2s)$pvalue)) +
  1531. annotate(geom="text", x=Inf, y=-Inf, label=paste('r2=',round(summary(lmod_g2s)$adj.r.squared, 3)), color="red3", hjust = 1.2, vjust = -0.25) +
  1532. geom_label_repel(aes(label = `gene expression model`)) +
  1533. theme_minimal() +
  1534. theme(legend.position = 'none')
  1535. name = 'Output/revisions/assoc_by_modelN_g2s.pdf'
  1536. pdf(file = name, width = 5, height = 4, pointsize = 12, bg = "white")
  1537. print(dtn_plot_g2s)
  1538. dev.off()
  1539. print(dtn_plot_g2s)
  1540. ```
  1541. ```{r}
  1542. lmod_g2s2 <- lm(data = dtn[!(`gene expression model` %in% c('GTEx European WB', 'GTEx European Brain', 'G2S All WB')),], N_assocs ~ N_samples)
  1543. summary(lmod_g2s2)
  1544. dtn_plot_g2s2 <- ggplot(dtn[!(`gene expression model` %in% c('GTEx European WB', 'GTEx European Brain', 'G2S All WB')),], aes(x = N_samples, y = N_assocs, color = `gene expression model`)) +
  1545. geom_point() +
  1546. geom_smooth(method = 'lm', color = 'black', se = F) +
  1547. annotate(geom="text", x=Inf, y=-Inf, label=paste('r2=',round(summary(lmod_g2s2)$adj.r.squared, 3)), color="red3", hjust = 1.2, vjust = -0.25) +
  1548. geom_label_repel(aes(label = `gene expression model`)) +
  1549. theme(legend.position = 'none')
  1550. name = 'Output/revisions/assoc_by_modelN_g2s_single.pdf'
  1551. pdf(file = name, width = 5, height = 4, pointsize = 12, bg = "white")
  1552. print(dtn_plot_g2s2)
  1553. dev.off()
  1554. print(dtn_plot_g2s2)
  1555. ```
  1556. ```{r}
  1557. lmod_g2s2b <- lm(data = dtn[!(`gene expression model` %in% c('GTEx European WB', 'GTEx European Brain', 'G2S All WB')),], N_assocs ~ Mean_Afr)
  1558. summary(lmod_g2s2b)
  1559. dtn_plot_g2s2b <- ggplot(dtn[!(`gene expression model` %in% c('GTEx European WB', 'GTEx European Brain', 'G2S All WB')),], aes(x = Mean_Afr, y = N_assocs, color = `gene expression model`)) +
  1560. geom_point() +
  1561. geom_smooth(method = 'lm', color = 'black', se = F) +
  1562. scale_color_brewer(palette = 'Accent') +
  1563. annotate(geom="text", x=Inf, y=-Inf, label=paste('r2=',round(summary(lmod_g2s2b)$adj.r.squared, 3)), color="red3", hjust = 1.2, vjust = -0.25) +
  1564. geom_label_repel(aes(label = `gene expression model`)) +
  1565. theme(legend.position = 'none')
  1566. name = 'Output/revisions/assoc_by_Afr_g2s.pdf'
  1567. pdf(file = name, width = 5, height = 4, pointsize = 12, bg = "white")
  1568. print(dtn_plot_g2s2b)
  1569. dev.off()
  1570. print(dtn_plot_g2s2b)
  1571. ```
  1572. ```{r}
  1573. lmod_g2s2c <- lm(data = dtn[!(`gene expression model` %in% c('GTEx European WB', 'GTEx European Brain', 'G2S All WB')),], N_assocs ~ Mean_IAM)
  1574. dtn_plot_g2s2c <- ggplot(dtn[!(`gene expression model` %in% c('GTEx European WB', 'GTEx European Brain', 'G2S All WB')),], aes(x = Mean_IAM, y = N_assocs, color = `gene expression model`)) +
  1575. geom_point() +
  1576. geom_smooth(method = 'lm', color = 'black', se = F) +
  1577. scale_color_brewer(palette = 'Accent') +
  1578. annotate(geom="text", x=Inf, y=-Inf, label=paste('r2=',round(summary(lmod_g2s2c)$adj.r.squared, 3)), color="red3", hjust = 1.2, vjust = -0.25) +
  1579. geom_label_repel(aes(label = `gene expression model`)) +
  1580. theme(legend.position = 'none')
  1581. name = 'Output/revisions/assoc_by_IAM_g2s.pdf'
  1582. pdf(file = name, width = 5, height = 4, pointsize = 12, bg = "white")
  1583. print(dtn_plot_g2s2c)
  1584. dev.off()
  1585. print(dtn_plot_g2s2c)
  1586. ```
  1587. ## Werth Replication Analysis
  1588. ### Figure S5: Comparisons of TWAS vs prior discoveries
  1589. ```{r}
  1590. library(data.table)
  1591. library(ggplot2)
  1592. library(reshape2)
  1593. library(pals)
  1594. library(stringr)
  1595. dt_ <- fread('Data/all_exc_BHsig_assocs_PGCancestryTWAS.txt', header = TRUE)
  1596. # exclude replication/comparison data from initial analysis.
  1597. gwas <- c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024', 'PGC_EURO_SCZ_2022')
  1598. mod <- c('PrediXcan_Brain_Cortex')
  1599. dt <- dt_[!(gwas_phenotype %in% gwas | training_model %in% mod),]
  1600. euro <- dt[training_model == 'PrediXcan_Whole_Blood',]
  1601. anc <- dt[training_model != 'PrediXcan_Whole_Blood',]
  1602. dup <- setDT(merge(anc, euro, by = c('gene_name', 'gwas_phenotype')))
  1603. euro$gptm <- paste0(euro$gene_name, '_', euro$gwas_phenotype)
  1604. anc$gptm <- paste0(anc$gene_name, '_', anc$gwas_phenotype)
  1605. anc2 <- anc[!(gptm %in% euro$gptm),]
  1606. euro2 <- euro[!(gptm %in% anc$gptm),]
  1607. #Run ADHD replication analysis.
  1608. adhd_w <- fread('Data/twas_atlas_data/replication_datasets/adhd_22_werth.txt', header = T)
  1609. adhd_w_wb <- adhd_w[, c('gene_name', 'Whole_Blood_unconditioned')][!is.na(Whole_Blood_unconditioned),]
  1610. adhd_w_wb$fdr_p <- p.adjust(adhd_w_wb$Whole_Blood_unconditioned, 'BH')
  1611. adhd_ta <- adhd_w_wb[Whole_Blood_unconditioned <= 0.05,]
  1612. adhd_anc_specific <- anc2[gwas_phenotype == 'PGC_allADHD_2022' & !(gene_name %in% adhd_ta$gene_name),]
  1613. a1 <- nrow(adhd_anc_specific[, .(.N), by = 'gene_name'])
  1614. adhd_euro_specific <- euro2[gwas_phenotype == 'PGC_allADHD_2022' & !(gene_name %in% adhd_ta$gene_name),]
  1615. a2 <- nrow(adhd_euro_specific[, .(.N), by = 'gene_name'])
  1616. a3 <- adhd_ta_specific <- length(unique(adhd_ta[!(gene_name %in% dt$gene_name),]$gene_name))
  1617. a4 <- length(unique(anc2[gwas_phenotype == 'PGC_allADHD_2022' & (gene_name %in% adhd_ta$gene_name),]$gene_name))
  1618. a5 <- length(unique(euro2[gwas_phenotype == 'PGC_allADHD_2022' & (gene_name %in% adhd_ta$gene_name),]$gene_name))
  1619. # then BD
  1620. bd_w <- fread('Data/twas_atlas_data/replication_datasets/bd_22_werth.txt', header = T)
  1621. bd_w_wb <- bd_w[, c('gene_name', 'Whole_Blood_unconditioned')][!is.na(Whole_Blood_unconditioned),]
  1622. bd_w_wb$fdr_p <- p.adjust(bd_w_wb$Whole_Blood_unconditioned, 'BH')
  1623. bd_ta <- bd_w_wb[Whole_Blood_unconditioned <= 0.05,]
  1624. bd_anc_specific <- anc2[gwas_phenotype == 'PGC_BD1_2021' & !(gene_name %in% bd_ta$gene_name),]
  1625. b1 <- nrow(bd_anc_specific[, .(.N), by = 'gene_name'])
  1626. bd_euro_specific <- euro2[gwas_phenotype == 'PGC_BD1_2021' & !(gene_name %in% bd_ta$gene_name),]
  1627. b2 <- nrow(bd_euro_specific[, .(.N), by = 'gene_name'])
  1628. b3 <- bd_ta_specific <- length(unique(bd_ta[!(gene_name %in% dt$gene_name),]$gene_name))
  1629. b4 <- length(unique(anc2[gwas_phenotype == 'PGC_BD1_2021' & (gene_name %in% bd_ta$gene_name),]$gene_name))
  1630. b5 <- length(unique(euro2[gwas_phenotype == 'PGC_BD1_2021' & (gene_name %in% bd_ta$gene_name),]$gene_name))
  1631. # and MDD
  1632. mdd_w <- fread('Data/twas_atlas_data/replication_datasets/mdd_22_werth.txt', header = T)
  1633. mdd_w_wb <- mdd_w[, c('gene_name', 'Whole_Blood_unconditioned')][!is.na(Whole_Blood_unconditioned),]
  1634. mdd_w_wb$fdr_p <- p.adjust(mdd_w_wb$Whole_Blood_unconditioned, 'BH')
  1635. mdd_ta <- mdd_w_wb[Whole_Blood_unconditioned <= 0.05,]
  1636. mdd_anc_specific <- anc2[gwas_phenotype == 'PGC_allMDD_2023' & !(gene_name %in% mdd_ta$gene_name),]
  1637. m1 <- nrow(mdd_anc_specific[, .(.N), by = 'gene_name'])
  1638. mdd_euro_specific <- euro2[gwas_phenotype == 'PGC_allMDD_2023' & !(gene_name %in% mdd_ta$gene_name),]
  1639. m2 <- nrow(mdd_euro_specific[, .(.N), by = 'gene_name'])
  1640. m3 <- mdd_ta_specific <- length(unique(mdd_ta[!(gene_name %in% dt$gene_name),]$gene_name))
  1641. m4 <- length(unique(anc2[gwas_phenotype == 'PGC_allMDD_2023' & (gene_name %in% mdd_ta$gene_name),]$gene_name))
  1642. m5 <- length(unique(euro2[gwas_phenotype == 'PGC_allMDD_2023' & (gene_name %in% mdd_ta$gene_name),]$gene_name))
  1643. # and lastly scz
  1644. scz_w <- fread('Data/twas_atlas_data/replication_datasets/scz_22_werth.txt', header = T)
  1645. scz_w_wb <- scz_w[, c('gene_name', 'Whole_Blood_unconditioned')][!is.na(Whole_Blood_unconditioned),]
  1646. scz_w_wb$fdr_p <- p.adjust(scz_w_wb$Whole_Blood_unconditioned, 'BH')
  1647. scz_ta <- scz_w_wb[Whole_Blood_unconditioned <= 0.05,]
  1648. scz_anc_specific <- anc2[gwas_phenotype == 'PGC_all_SCZ_2022' & !(gene_name %in% scz_ta$gene_name),]
  1649. s1 <- nrow(scz_anc_specific[, .(.N), by = 'gene_name'])
  1650. scz_euro_specific <- euro2[gwas_phenotype == 'PGC_all_SCZ_2022' & !(gene_name %in% scz_ta$gene_name),]
  1651. s2 <- nrow(scz_euro_specific[, .(.N), by = 'gene_name'])
  1652. s3 <- scz_ta_specific <- length(unique(scz_ta[!(gene_name %in% dt$gene_name),]$gene_name))
  1653. s4 <- length(unique(anc2[gwas_phenotype == 'PGC_all_SCZ_2022' & (gene_name %in% scz_ta$gene_name),]$gene_name))
  1654. s5 <- length(unique(euro2[gwas_phenotype == 'PGC_all_SCZ_2022' & (gene_name %in% scz_ta$gene_name),]$gene_name))
  1655. #compile data into single object
  1656. ant_twas_dat <- data.table(study = c('ADHD', 'MDD', 'BD1', 'SCZ'),
  1657. g2s_new = c(a1, m1, b1, s1),
  1658. euro_new = c(a2, m2, b2, s2),
  1659. Werth_unique = c(a3,m3,b3,s3),
  1660. g2s_rep = c(a4,m4,b4,s4),
  1661. euro_rep = c(a5, m5, b5, s5))
  1662. atd <- setDT(melt(ant_twas_dat, id.vars = 'study'))
  1663. atd[variable %in% c('g2s_new', 'g2s_rep'), cohort := 'G2S']
  1664. atd[variable %in% c('euro_new', 'euro_rep'), cohort := 'GTEx']
  1665. atd[variable %in% c('Werth_unique'), cohort := 'Werth']
  1666. tots <- atd[, .(value = sum(value)), by = c('variable', 'cohort')]
  1667. tots$study = 'All Conditions'
  1668. atd2 <- rbind(atd, tots)
  1669. #visualize data
  1670. p10 <- ggplot(atd[variable %in% c('g2s_rep', 'euro_rep'),], aes(x = cohort, y = value, color = cohort, fill = cohort)) +
  1671. geom_bar(stat = 'identity', position = 'dodge') +
  1672. geom_label(aes(label = value, y = value +2), fill = "white", color = 'black', label.size = NA) +
  1673. facet_grid(.~study) +
  1674. ylab('Replicated Genes') +
  1675. scale_fill_brewer(palette = 'Dark2') +
  1676. scale_color_brewer(palette = 'Dark2') +
  1677. theme_minimal() +
  1678. theme(axis.text.x = element_text(angle = 60, hjust = 1),
  1679. axis.title.x = element_blank(),
  1680. legend.position = 'none')
  1681. name = 'Output/revisions/werth_rep.pdf'
  1682. pdf(file = name, width = 7, height = 3, pointsize = 12, bg = "white")
  1683. print(p10)
  1684. dev.off()
  1685. print(p10)
  1686. p11 <- ggplot(tots[variable %in% c('g2s_rep', 'euro_rep'),], aes(x = cohort, y = value, color = cohort, fill = cohort)) +
  1687. geom_bar(stat = 'identity', position = 'dodge') +
  1688. geom_label(aes(label = value, y = value +4), fill = "white", color = 'black', label.size = NA) +
  1689. facet_grid(.~study) +
  1690. ylab('Replicated Genes') +
  1691. scale_fill_brewer(palette = 'Dark2') +
  1692. scale_color_brewer(palette = 'Dark2') +
  1693. theme_minimal() +
  1694. theme(axis.text.x = element_text(angle = 60, hjust = 1),
  1695. axis.title = element_blank(),
  1696. legend.position = 'none')
  1697. name = 'Output/revisions/werth_total_rep.pdf'
  1698. pdf(file = name, width = 1.8, height = 3, pointsize = 12, bg = "white")
  1699. print(p11)
  1700. dev.off()
  1701. ```
  1702. ## Pvalue vs Zscore monotonicity
  1703. ### Fig S10: Pvalue change relative to zscores
  1704. ```{r}
  1705. dt <- fread("Data/all_exc_assocs_PGCancestryTWAS.txt", header = T)
  1706. plotdata <- dt[gwas_phenotype == 'PGC_allADHD_2022' & training_model %in% c('PrediXcan_Whole_Blood', 'AA_Whole_Blood')]
  1707. pz_comp <- setDT(merge(plotdata[training_model == 'PrediXcan_Whole_Blood', c('gene_name', 'gwas_phenotype', 'zscore', 'pvalue')],
  1708. plotdata[training_model == 'AA_Whole_Blood', c('gene_name', 'gwas_phenotype', 'zscore', 'pvalue')],
  1709. suffixes = c('.gtex', '.g2s_AA'), by = c('gene_name', 'gwas_phenotype')))
  1710. pz_comp[, zdif := abs(zscore.gtex - zscore.g2s_AA)]
  1711. pz_comp[, pdif := abs(pvalue.gtex - pvalue.g2s_AA)]
  1712. zp_gtg2 <- ggplot(pz_comp, aes(x = zscore.gtex, y = pvalue.g2s_AA)) +
  1713. geom_point(color = 'seagreen')
  1714. zp_g2g2 <- ggplot(pz_comp, aes(x = zscore.g2s_AA, y = pvalue.g2s_AA)) +
  1715. geom_point(color = 'magenta')
  1716. zp_g2gt <- ggplot(pz_comp, aes(x = zscore.g2s_AA, y = pvalue.gtex)) +
  1717. geom_point(color = 'goldenrod2')
  1718. zp_gtgt <- ggplot(pz_comp, aes(x = zscore.gtex, y = pvalue.gtex)) +
  1719. geom_point(color = 'slateblue')
  1720. z_vs_p_plot <- ggarrange(zp_gtg2, zp_g2g2, zp_gtgt, zp_g2gt, ncol = 2, nrow = 2)
  1721. pdf(file = 'Output/revisions/z_vs_p_analysis.pdf', height = 9, width = 9)
  1722. print(z_vs_p_plot)
  1723. dev.off()
  1724. print(z_vs_p_plot)
  1725. #
  1726. zp_gtg2 <- ggplot(pz_comp, aes(x = zscore.gtex, y = pvalue.g2s_AA)) +
  1727. geom_point(color = 'seagreen')
  1728. zp_g2g2 <- ggplot(pz_comp, aes(x = zscore.g2s_AA, y = pvalue.g2s_AA)) +
  1729. geom_point(color = 'magenta')
  1730. zp_g2gt <- ggplot(pz_comp, aes(x = zscore.g2s_AA, y = pvalue.gtex)) +
  1731. geom_point(color = 'goldenrod2')
  1732. zp_gtgt <- ggplot(pz_comp, aes(x = zscore.gtex, y = pvalue.gtex)) +
  1733. geom_point(color = 'slateblue')
  1734. z_vs_p_plot <- ggarrange(zp_gtg2, zp_g2g2, zp_gtgt, zp_g2gt, ncol = 2, nrow = 2)
  1735. pdf(file = 'Output/revisions/z_vs_p_analysis.pdf', height = 9, width = 9)
  1736. print(z_vs_p_plot)
  1737. dev.off()
  1738. pp_gtg2 <- ggplot(pz_comp, aes(x = pvalue.gtex, y = pvalue.g2s_AA)) +
  1739. geom_point(color = 'seagreen')
  1740. pp_g2g2 <- ggplot(pz_comp, aes(x = pvalue.g2s_AA, y = pvalue.g2s_AA)) +
  1741. geom_point(color = 'magenta')
  1742. pp_g2gt <- ggplot(pz_comp, aes(x = pvalue.g2s_AA, y = pvalue.gtex)) +
  1743. geom_point(color = 'goldenrod2')
  1744. pp_gtgt <- ggplot(pz_comp, aes(x = pvalue.gtex, y = pvalue.gtex)) +
  1745. geom_point(color = 'slateblue')
  1746. p_vs_p_plot <- ggarrange(pp_gtg2, pp_g2g2, pp_gtgt, pp_g2gt, ncol = 2, nrow = 2)
  1747. pdf(file = 'Output/revisions/p_vs_p_analysis.pdf', height = 9, width = 9)
  1748. print(p_vs_p_plot)
  1749. dev.off()
  1750. print(p_vs_p_plot)
  1751. zz_gtg2 <- ggplot(pz_comp, aes(x = zscore.gtex, y = zscore.g2s_AA)) +
  1752. geom_point(color = 'seagreen')
  1753. zz_g2g2 <- ggplot(pz_comp, aes(x = zscore.g2s_AA, y = zscore.g2s_AA)) +
  1754. geom_point(color = 'magenta')
  1755. zz_g2gt <- ggplot(pz_comp, aes(x = zscore.g2s_AA, y = zscore.gtex)) +
  1756. geom_point(color = 'goldenrod2')
  1757. zz_gtgt <- ggplot(pz_comp, aes(x = zscore.gtex, y = zscore.gtex)) +
  1758. geom_point(color = 'slateblue')
  1759. z_vs_z_plot <- ggarrange(zz_gtg2, zz_g2g2, zz_gtgt, zz_g2gt, ncol = 2, nrow = 2)
  1760. pdf(file = 'Output/revisions/z_vs_z_analysis.pdf', height = 9, width = 9)
  1761. print(z_vs_z_plot)
  1762. dev.off()
  1763. print(z_vs_z_plot)
  1764. #####
  1765. pzc <- copy(pz_comp)
  1766. pzc[, pdif := pvalue.gtex - pvalue.g2s_AA]
  1767. pzc[, zdif := abs(zscore.gtex) - abs(zscore.g2s_AA)]
  1768. pzc[, zpsign := sign(zdif) * sign(pdif)]
  1769. zmagpplot <- ggplot(pzc, aes(x = zdif, y = pdif)) +
  1770. geom_point()
  1771. pdf(file = 'Output/revisions/deltazmagvsp.pdf', height = 9, width = 9)
  1772. print(zmagpplot)
  1773. dev.off()
  1774. print(zmagpplot)
  1775. azp_gtg2 <- ggplot(pz_comp, aes(x = abs(zscore.gtex), y = pvalue.g2s_AA)) +
  1776. geom_point(color = 'seagreen')
  1777. azp_g2g2 <- ggplot(pz_comp, aes(x = abs(zscore.g2s_AA), y = pvalue.g2s_AA)) +
  1778. geom_point(color = 'magenta')
  1779. azp_g2gt <- ggplot(pz_comp, aes(x = abs(zscore.g2s_AA), y = pvalue.gtex)) +
  1780. geom_point(color = 'goldenrod2')
  1781. azp_gtgt <- ggplot(pz_comp, aes(x = abs(zscore.gtex), y = pvalue.gtex)) +
  1782. geom_point(color = 'slateblue')
  1783. zm_vs_p_plot <- ggarrange(azp_gtg2, azp_g2g2, azp_gtgt, azp_g2gt, ncol = 2, nrow = 2)
  1784. pdf(file = 'Output/revisions/zmag_vs_p_analysis.pdf', height = 9, width = 9)
  1785. print(zm_vs_p_plot)
  1786. dev.off()
  1787. print(zm_vs_p_plot)
  1788. ```
  1789. ## Fig S18-20: Linkage Disequilibrium analyses
  1790. How does linkage disequilibrium affect the relationship of genes that are called significant for a phenotype?
  1791. ```{r}
  1792. lddir <- 'Data/LD_genelists_shared_distinct/'
  1793. assocs <- c ('ENSG00000172247_MX_Whole_Blood_SUD_alc_2019_snps_20',
  1794. # 'ENSG00000237513_AA_Whole_Blood_PGC_ALL_PTSD_2024_snps_15',
  1795. 'ENSG00000237513_AA_Whole_Blood_PGC_all_SCZ_2022_snps_15',
  1796. 'ENSG00000255284_MX_Whole_Blood_PGC_allADHD_2022_snps_17')
  1797. assoc <- c ('ENSG00000172247_MX_Whole_Blood_SUD_alc_2019_snps_20')
  1798. pops <- c('CEU', 'GBR', 'YRI', 'MXL', 'PUR', 'ASW')
  1799. for(assoc in assocs){
  1800. tab_all <- fread(paste0(lddir, 'LD_results2/',assoc,'_LD_all.txt'), header = F)
  1801. tab_all$population <- str_remove(tab_all$V11, '.+:')
  1802. pop_charts <- c()
  1803. for( pop in pops){
  1804. tab <- tab_all[population == pop,]
  1805. head(pop)
  1806. setnames(tab, c('V1', 'V5', 'V9', 'V10'), c('SNP1', 'SNP2', 'R2', 'Dprime'))
  1807. init <- fread(paste0(lddir, assoc, '.txt'), header = T)
  1808. g2s_rsids <- init[!is.na(weight.G2S),]$rsid
  1809. gtex_rsids <- init[!is.na(weight.GTEx),]$rsid
  1810. comp <- tab[, c('SNP1', 'SNP2', 'R2', 'Dprime')]
  1811. comp2 <- comp[(SNP1 %in% g2s_rsids & SNP2 %in% gtex_rsids),]
  1812. comp3 <- comp[(SNP2 %in% g2s_rsids & SNP1 %in% gtex_rsids) , ]
  1813. comp3 <- setnames(comp3, c('SNP2' , 'SNP1'), c('SNP1' , 'SNP2'))
  1814. comp4 <- setDT(rbind(comp2, comp3))
  1815. setnames(comp4, c('SNP1' , 'SNP2'), c('G2S', 'GTEx'))
  1816. mattabl <- matrix(, nrow = length(g2s_rsids), ncol = length(gtex_rsids))
  1817. rownames(mattabl) <- g2s_rsids
  1818. colnames(mattabl) <- gtex_rsids
  1819. for(i in 1:nrow(comp4)){
  1820. g2 <- comp4[i,]$G2S
  1821. gt <- comp4[i,]$GTEx
  1822. r2 <- comp4[i,]$R2
  1823. mattabl[g2, gt] <- r2
  1824. }
  1825. snp_locs1 <- tab[, c(1,2)]
  1826. snp_locs1$pos <- str_remove(snp_locs1$V2, '.+:')
  1827. snp_locs1 <- unique(snp_locs1)
  1828. setnames(snp_locs1, 'SNP1', 'SNP')
  1829. snp_locs2 <- tab[, c(5,6)]
  1830. snp_locs2$pos <- str_remove(snp_locs2$V6, '.+:')
  1831. snp_locs2 <- unique(snp_locs2)
  1832. setnames(snp_locs2, 'SNP2', 'SNP')
  1833. allsnps <- setDT(rbind(snp_locs1[, c('SNP', 'pos')], snp_locs2[, c('SNP', 'pos')]))
  1834. g2_ord <- unique(allsnps[SNP %in% g2s_rsids,])[order(pos)]$SNP
  1835. gt_ord <- unique(allsnps[SNP %in% gtex_rsids,])[order(pos)]$SNP
  1836. comp4$G2S <- factor(comp4$G2S, levels = g2_ord)
  1837. comp4$GTEx <- factor(comp4$GTEx, levels = gt_ord)
  1838. LDplot1 <- ggplot(comp4, aes( x = G2S, y = GTEx, fill = R2)) +
  1839. geom_tile() +
  1840. theme_minimal() +
  1841. ggtitle(pop) +
  1842. scale_fill_distiller(palette = "RdYlGn", direction = 1) +
  1843. theme(axis.text.x = element_text(angle = 40, hjust = 1))
  1844. pop_charts[[pop]] = LDplot1
  1845. }
  1846. name <- paste0('Output/revisions/ALL_', assoc,'_LD_corplots.pdf')
  1847. pdf(file = name, width = 9, height = 10, pointsize = 12, bg = "white")
  1848. do.call(grid.arrange, c(pop_charts, ncol = 2, padding = unit(1, "lines")))
  1849. dev.off()
  1850. }
  1851. #images are output to output directory, not in std out.
  1852. ```
  1853. ### Fig S21: Max R2 to SNP weight comparison
  1854. For each gene, how does the maximum LD between SNPs used in the model compare to the weight of the SNP? We want to assess whether SNPs that are more frequently in LD have greater effects on gene expression.
  1855. ```{r}
  1856. ######## get relationship between max r2 and SNP weight
  1857. library(data.table)
  1858. library(ggplot2)
  1859. library(gridExtra)
  1860. library(stringr)
  1861. lddir <- 'Data/LD_genelists_shared_distinct/'
  1862. assocs <- c('ENSG00000172247_MX_Whole_Blood_SUD_alc_2019_snps_20',
  1863. #'ENSG00000237513_AA_Whole_Blood_PGC_ALL_PTSD_2024_snps_15',
  1864. 'ENSG00000237513_AA_Whole_Blood_PGC_all_SCZ_2022_snps_15',
  1865. 'ENSG00000255284_MX_Whole_Blood_PGC_allADHD_2022_snps_17')
  1866. pops <- c('CEU', 'GBR', 'YRI', 'MXL', 'PUR', 'ASW')
  1867. all_dat <- list.files('Data/rdata', pattern = '.+\\.txt')
  1868. snp_dat <- data.table()
  1869. for(fil in str_subset(all_dat, '^snp_dat_all.+\\.txt')){
  1870. newdat <- fread(paste0('Data/rdata/', fil), header = T)
  1871. snp_dat <- rbind(snp_dat , newdat)
  1872. }
  1873. #initiate data.table to hold r2 and pvalue results
  1874. cordat <- data.table(association = c(), gene = c(), training_model = c(), gwas_phenotype = c(), population = c(), group = c(), adj.r.squared = c(), lm_pvalue = c())
  1875. #initiate data.table to hold all points from plots
  1876. fulldata <- data.table()
  1877. for(assoc in assocs){
  1878. tab_all <- fread(paste0(lddir, 'LD_results2/',assoc,'_LD_all.txt'), header = F)
  1879. tab_all$population <- str_remove(tab_all$V11, '.+:')
  1880. gene_nm <- str_remove(assoc, '_.+')
  1881. mod1 <- str_remove(assoc, paste0(gene_nm , '_'))
  1882. mod <- str_remove(mod1, '_PGC.+')
  1883. mod <- str_remove(mod, '_SUD.+')
  1884. phen1 <- str_remove(assoc, paste0(gene_nm , '_', mod, '_'))
  1885. phen <- str_remove(phen1, '_snps.+')
  1886. sdat <- snp_dat[gene == gene_nm & (model == mod & gwas_phenotype == phen),]
  1887. pop_charts2 <- c()
  1888. for( pop in pops){
  1889. tab <- tab_all[population == pop,]
  1890. head(pop)
  1891. setnames(tab, c('V1', 'V5', 'V9', 'V10'), c('SNP1', 'SNP2', 'R2', 'Dprime'))
  1892. init <- fread(paste0(lddir, assoc, '.txt'), header = T)
  1893. g2s_rsids <- init[!is.na(weight.G2S),]$rsid
  1894. gtex_rsids <- init[!is.na(weight.GTEx),]$rsid
  1895. comp <- tab[, c('SNP1', 'SNP2', 'R2', 'Dprime')]
  1896. comp2 <- comp[(SNP1 %in% g2s_rsids & SNP2 %in% gtex_rsids),]
  1897. comp3 <- comp[(SNP2 %in% g2s_rsids & SNP1 %in% gtex_rsids) , ]
  1898. comp3 <- setnames(comp3, c('SNP2' , 'SNP1'), c('SNP1' , 'SNP2'))
  1899. comp4 <- setDT(rbind(comp2, comp3))
  1900. setnames(comp4, c('SNP1' , 'SNP2'), c('G2S', 'GTEx'))
  1901. g2s_max1 <- comp4[, .(maxr2 = max(R2)), by = 'G2S']
  1902. gtex_max1 <- comp4[, .(maxr2 = max(R2)), by = 'GTEx']
  1903. g2s_max <- setDT(merge(g2s_max1, sdat[, c('rsid', 'weight.G2S')], by.x = 'G2S', by.y = 'rsid'))
  1904. g2s_max$group <- 'G2S'
  1905. gtex_max <- setDT(merge(gtex_max1, sdat[, c('rsid', 'weight.GTEx')], by.x = 'GTEx', by.y = 'rsid'))
  1906. gtex_max$group <- 'GTEx'
  1907. setnames(g2s_max, c('G2S', 'weight.G2S'), c('SNP', 'weight'))
  1908. setnames(gtex_max, c('GTEx', 'weight.GTEx'),c('SNP', 'weight'))
  1909. lmg2s = lm(abs(g2s_max$weight)~g2s_max$maxr2)
  1910. lmgtex = lm(abs(gtex_max$weight)~gtex_max$maxr2)
  1911. newdat_g2s = data.table(association = assoc,
  1912. gene = gene_nm,
  1913. training_model = mod,
  1914. gwas_phenotype = phen,
  1915. population = pop,
  1916. group = 'G2S',
  1917. adj.r.squared = summary(lmg2s)$adj.r.squared,
  1918. lm_pvalue = summary(lmg2s)$coefficients[2,4])
  1919. newdat_gtex = data.table(association = assoc,
  1920. gene = gene_nm,
  1921. training_model = mod,
  1922. gwas_phenotype = phen,
  1923. population = pop,
  1924. group = 'GTEx',
  1925. adj.r.squared = summary(lmgtex)$adj.r.squared,
  1926. lm_pvalue = summary(lmgtex)$coefficients[2,4])
  1927. cordat <- rbind(cordat, newdat_g2s)
  1928. cordat <- rbind(cordat, newdat_gtex)
  1929. plotdata <- setDT(rbind(g2s_max, gtex_max))
  1930. plotdata[, association := assoc]
  1931. plotdata[, population := pop]
  1932. fulldata <- setDT(rbind(fulldata, plotdata))
  1933. }
  1934. }
  1935. write.table(cordat, file = paste0(lddir, 'LD_results2/all_results_correlation_data.txt'), col.names = T, row.names = F, quote = F, sep = '\t')
  1936. write.table(fulldata, file = paste0(lddir, 'LD_results2/all_results_r2byweight_data.txt'), col.names = T, row.names = F, quote = F, sep = '\t')
  1937. ld_all <- fread(paste0(lddir, 'LD_results2/all_results_r2byweight_data.txt'), header = T)
  1938. lda_lm <- lm(data = ld_all, abs(weight)~maxr2 + association)
  1939. lda_lm2 <- lm(data = ld_all, abs(weight)~maxr2 + association + population)
  1940. lda_lm3 <- lm(data = ld_all, abs(weight)~maxr2 + population)
  1941. allplot <- ggplot(ld_all, aes(x = maxr2, y = abs(weight), color = association)) +
  1942. geom_smooth(method = "lm", color = "grey70") +
  1943. geom_point() +
  1944. theme_minimal() +
  1945. facet_wrap(.~population) +
  1946. guides(color = guide_legend(nrow = 3)) +
  1947. theme(legend.position = 'bottom')
  1948. name <- paste0('Output/revisions/ALL_LD_corplots_weights.pdf')
  1949. pdf(file = name, width = 6, height = 6, pointsize = 12, bg = "white")
  1950. print(allplot)
  1951. dev.off()
  1952. print(allplot)
  1953. ```
  1954. ## Correlogram and heatmap in fig 5
  1955. ### Fig 5: Updated correlogram and heatmap
  1956. ```{r}
  1957. library(data.table)
  1958. library(corrplot)
  1959. dt_ <- fread("Data/all_exc_assocs_PGCancestryTWAS.txt", header = T)
  1960. # exclude replication/comparison data from initial analysis.
  1961. gwas <- c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024')
  1962. mod <- c('PrediXcan_Brain_Cortex')
  1963. dt <- dt_[!(gwas_phenotype %in% c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024', 'PGC_LATINO_SCZ_2022', 'PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024', 'PGC_EURO_SCZ_2022')) & training_model != 'PrediXcan_Brain_Cortex',]
  1964. dt[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  1965. dt[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  1966. dt[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  1967. dt[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  1968. dt[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  1969. dt1 <- dt[!training_model == 'PrediXcan_Whole_Blood']
  1970. dt2 <- dt[training_model == 'PrediXcan_Whole_Blood']
  1971. # Clean gene names in both datasets
  1972. MAtwas <- dt2
  1973. MUtwas <- dt1
  1974. # Get unique training models from MUtwas and add GTEX from MAtwas
  1975. training_models <- unique(MUtwas$training_model)
  1976. training_models <- c(training_models, 'PrediXcan_Whole_Blood')
  1977. # Define a custom color palette
  1978. custom_colors <- colorRampPalette(c("#1a9850","#1a9850", "#ffffbf", "#d73027"))(1000)
  1979. # Open a PDF device with Letter dimensions
  1980. pdf('Output/revisions/correlograms.pdf', width = 5, height = 5.5)
  1981. for (model in training_models[1]) {
  1982. # Filter data for the current training model
  1983. if (model == 'PrediXcan_Whole_Blood') {
  1984. filtered_data <- MAtwas[training_model == model, .(gwas_phenotype, gene, zscore)]
  1985. } else {
  1986. filtered_data <- MUtwas[training_model == model, .(gwas_phenotype, gene, zscore)]
  1987. }
  1988. unique_genes <- unique(filtered_data$gene)
  1989. unique_phenotypes <- unique(filtered_data$gwas_phenotype)
  1990. matrix_data <- matrix(NA, nrow = length(unique_genes), ncol = length(unique_phenotypes))
  1991. rownames(matrix_data) <- unique_genes
  1992. dz_names <- c('PGC_allADHD_2022' = 'ADHD',
  1993. 'PGC_all_SCZ_2022' = 'SCZ',
  1994. 'PGC_allMDD_2023' = 'MDD',
  1995. 'PGC_BD1_2021' = 'BD1',
  1996. 'SUD_alc_2019' = 'SUD-A',
  1997. 'PGC_ALL_PTSD_2024' = 'PTSD')
  1998. colnames(matrix_data) <- unique_phenotypes
  1999. colnames(matrix_data) <- dz_names[colnames(matrix_data)]
  2000. for (i in 1:nrow(filtered_data)) {
  2001. row <- filtered_data[i, ]
  2002. matrix_data[row$gene, dz_names[row$gwas_phenotype]] <- row$zscore
  2003. }
  2004. cor_matrix <- cor(matrix_data, use = "pairwise.complete.obs")
  2005. cor_matrix[cor_matrix == 1.0] <- NA
  2006. # Adjust plot margins to accommodate longer titles
  2007. par(mar = c(1, 1, 5, 1))
  2008. corrplot(corr = cor_matrix,
  2009. method = "circle",
  2010. type = "lower",
  2011. #tl.pos = "tl",
  2012. order = "original",
  2013. tl.col = 'black',
  2014. diag = FALSE,
  2015. is.corr = FALSE,
  2016. col.lim = range(cor_matrix, na.rm = T),
  2017. col = custom_colors, # Use custom colors
  2018. title = paste("Correlation plot for training model:", model),
  2019. mar = c(0, 0, 2, 0)) # Adjust margins to fit the title
  2020. }
  2021. # Close the PDF device
  2022. dev.off()
  2023. ```
  2024. ```{r}
  2025. # and heat map too
  2026. cleardups <- function(t1){
  2027. otpt <- t1[2,]
  2028. for(nn in 3:nrow(t1)){
  2029. d1 <- t1[nn,1]
  2030. d2 <- t1[nn,2]
  2031. d_combo <- paste0(d1, d2)
  2032. d_combo2 <- paste0(d2, d1)
  2033. if( d_combo %in% paste0(otpt[[1]], otpt[[2]]) | d_combo2 %in% paste0(otpt[[1]], otpt[[2]])){
  2034. #print(TRUE)
  2035. } else if(d1 != d2){
  2036. #print(FALSE)
  2037. otpt <- setDT(rbind(otpt, t1[nn,]))
  2038. }
  2039. }
  2040. otpt[1 != 2,]
  2041. otpt[[3]] <- rank(-otpt[[3]])
  2042. return(otpt)
  2043. }
  2044. load('Data/correlation_matrices/AA_Whole_Blood_cor_matrix.rdata')
  2045. cortab <- as.data.table(cor_matrix)
  2046. cortab$disease1 <- rownames(cor_matrix)
  2047. cortab <- setnames(melt(cortab, id.vars = 'disease1', value.name = 'G2S_AA'), 'variable', 'disease2')
  2048. cortab$disease2 <- as.character(cortab$disease2)
  2049. cortab <- cleardups(cortab)
  2050. AA_cor <- copy(cortab)
  2051. load('Data/correlation_matrices/All_Whole_Blood_cor_matrix.rdata')
  2052. cortab <- as.data.table(cor_matrix)
  2053. cortab$disease1 <- rownames(cor_matrix)
  2054. cortab <- setnames(melt(cortab, id.vars = 'disease1', value.name = 'G2S_All'), 'variable', 'disease2')
  2055. cortab$disease2 <- as.character(cortab$disease2)
  2056. cortab <- cleardups(cortab)
  2057. All_cor <- copy(cortab)
  2058. load('Data/correlation_matrices/MX_Whole_Blood_cor_matrix.rdata')
  2059. cortab <- as.data.table(cor_matrix)
  2060. cortab$disease1 <- rownames(cor_matrix)
  2061. cortab <- setnames(melt(cortab, id.vars = 'disease1', value.name = 'G2S_MX'), 'variable', 'disease2')
  2062. cortab$disease2 <- as.character(cortab$disease2)
  2063. cortab <- cleardups(cortab)
  2064. MX_cor <- copy(cortab)
  2065. load('Data/correlation_matrices/PR_Whole_Blood_cor_matrix.rdata')
  2066. cortab <- as.data.table(cor_matrix)
  2067. cortab$disease1 <- rownames(cor_matrix)
  2068. cortab <- setnames(melt(cortab, id.vars = 'disease1', value.name = 'G2S_PR'), 'variable', 'disease2')
  2069. cortab$disease2 <- as.character(cortab$disease2)
  2070. cortab <- cleardups(cortab)
  2071. PR_cor <- copy(cortab)
  2072. load('Data/correlation_matrices/PrediXcan_Whole_Blood_cor_matrix.rdata')
  2073. cortab <- as.data.table(cor_matrix)
  2074. cortab$disease1 <- rownames(cor_matrix)
  2075. cortab <- setnames(melt(cortab, id.vars = 'disease1', value.name = 'GTEx_WB'), 'variable', 'disease2')
  2076. cortab$disease2 <- as.character(cortab$disease2)
  2077. cortab <- cleardups(cortab)
  2078. GT_cor <- copy(cortab)
  2079. multicor <- data.table()
  2080. multicor <- setDT(merge(AA_cor, All_cor, by = c('disease1', 'disease2')))
  2081. multicor <- setDT(merge(multicor, MX_cor, by = c('disease1', 'disease2')))
  2082. multicor <- setDT(merge(multicor, PR_cor, by = c('disease1', 'disease2')))
  2083. multicor <- setDT(merge(multicor, GT_cor, by = c('disease1', 'disease2')))
  2084. rowmean <- rowMeans(multicor[,-c(1,2)])
  2085. multicor$mean <- rowmean
  2086. multicor$traits = paste0(multicor$disease1, ' - ', multicor$disease2)
  2087. mcL <- setDT(melt(multicor, id.vars = c('disease1', 'disease2', 'traits')))
  2088. order_vec <- mcL[variable == 'mean', c('variable', 'value', 'traits')][order(-value)]$traits
  2089. mcL$traits <- factor(mcL$traits, levels = order_vec)
  2090. cor_rank <- ggplot(mcL[variable != 'mean',], aes(x = variable, y = traits, fill = value)) +
  2091. geom_tile(color = 'black') +
  2092. geom_text(aes(label = value)) +
  2093. scale_fill_distiller(palette = "RdYlGn", direction = 1) +
  2094. xlab('model') +
  2095. ylab('disease pair')+
  2096. labs(fill = "Correlation\nRanking") +
  2097. theme_minimal() +
  2098. theme(axis.text.x = element_text(angle = 40, hjust = 1))
  2099. name = 'Output/revisions/mod_cor_rank.pdf'
  2100. pdf(file = name, width = 6.5, height = 6, pointsize = 12, bg = "white")
  2101. print(cor_rank)
  2102. dev.off()
  2103. print(cor_rank)
  2104. ```
  2105. ### Figure S26: brain model vs whole blood model comparison
  2106. ```{r}
  2107. # Create comparison for brain vs G2S vs whole blood GTEx
  2108. # Read in all significant data and subset GWAS findings of interest
  2109. sig <- fread('Data/all_exc_BHsig_assocs_PGCancestryTWAS.txt', header = T)
  2110. dt <- sig[!(gwas_phenotype %in% c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024', 'PGC_EURO_SCZ_2022')),]
  2111. dt[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  2112. dt[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  2113. dt[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  2114. dt[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  2115. dt[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  2116. dt[training_model == 'PrediXcan_Brain_Cortex', `gene expression model` := 'GTEx European Brain']
  2117. G2S_mods <- c('All_Whole_Blood', 'AA_Whole_Blood', 'MX_Whole_Blood', 'PR_Whole_Blood')
  2118. mod_dz_tabl <- data.table()
  2119. for( dz in unique(dt$gwas_phenotype)){
  2120. gns <- unique(dt[gwas_phenotype == dz,]$gene_name)
  2121. temp <- data.table( gwas_phenotype = dz, gene_name = gns )
  2122. temp[, GTEx_WB := gene_name %in% unique(dt[gwas_phenotype == dz & training_model == 'PrediXcan_Whole_Blood',]$gene_name)]
  2123. temp[, GTEx_Brain := gene_name %in% unique(dt[gwas_phenotype == dz & training_model == 'PrediXcan_Brain_Cortex',]$gene_name)]
  2124. temp[, G2S := gene_name %in% unique(dt[gwas_phenotype == dz & training_model %in% G2S_mods,]$gene_name)]
  2125. temp[ (GTEx_WB == F & GTEx_Brain == F) & G2S == F, type := 'none']
  2126. temp[ (GTEx_WB == F & GTEx_Brain == F) & G2S == T, type := 'G2S_only']
  2127. temp[ (GTEx_WB == F & GTEx_Brain == T) & G2S == F, type := 'GTEx brain only']
  2128. temp[ (GTEx_WB == F & GTEx_Brain == T) & G2S == T, type := 'GTEx_brain + G2S']
  2129. temp[ (GTEx_WB == T & GTEx_Brain == F) & G2S == F, type := 'GTEx_WB only']
  2130. temp[ (GTEx_WB == T & GTEx_Brain == F) & G2S == T, type := 'GTEx_WB + G2S']
  2131. temp[ (GTEx_WB == T & GTEx_Brain == T) & G2S == F, type := 'GTEx_WB + GTEx_brain']
  2132. temp[ (GTEx_WB == T & GTEx_Brain == T) & G2S == T, type := 'all']
  2133. newtemp <- temp[, .(.N), by = type]
  2134. newtemp[, gwas_phenotype := dz]
  2135. mod_dz_tabl <- rbind(mod_dz_tabl, newtemp)
  2136. }
  2137. mod_typs <- ggplot(mod_dz_tabl, aes(x = type, y = N, fill = type)) +
  2138. geom_bar(stat = 'identity') +
  2139. facet_wrap(gwas_phenotype~., nrow = 3) +
  2140. theme(axis.text.x = element_text(angle = 60, hjust = 1))
  2141. pdf(file = 'Output/revisions/mod_types_brain.pdf', height = 12, width = 10)
  2142. print(mod_typs)
  2143. dev.off()
  2144. print(mod_typs)
  2145. mod_typs2 <- ggplot(mod_dz_tabl[type %in% c('GTEx_brain + G2S', 'GTEx brain only')], aes(x = type, y = N, fill = type)) +
  2146. geom_bar(stat = 'identity') +
  2147. facet_wrap(gwas_phenotype~., nrow = 3, scales = 'free_y') +
  2148. theme(axis.text.x = element_text(angle = 60, hjust = 1))
  2149. pdf(file = 'Output/revisions/mod_types_brain2.pdf', height = 10, width = 6)
  2150. print(mod_typs2)
  2151. dev.off()
  2152. print(mod_typs2)
  2153. newmod <- mod_dz_tabl[type %in% c('GTEx_brain + G2S', 'GTEx brain only')]
  2154. sums <- newmod[, .(sum = sum(N)), by = 'gwas_phenotype']
  2155. newmod1 <- setDT(merge(newmod, sums, by = 'gwas_phenotype'))
  2156. newmod1[, percentage := N / sum]
  2157. mod_typs3 <- ggplot(newmod1, aes(x = gwas_phenotype, y = percentage, fill = type, color = type)) +
  2158. geom_bar(stat = 'identity', position = 'stack') +
  2159. geom_label(data = newmod1[type == 'GTEx_brain + G2S',], aes(x = gwas_phenotype, y = percentage - 0.06, label = round(percentage, 3)), fill = 'white', show.legend = F)+
  2160. #facet_wrap(gwas_phenotype~., nrow = 3) +
  2161. theme_minimal() +
  2162. theme(axis.text.x = element_text(angle = 45, hjust = 1))
  2163. pdf(file = 'Output/revisions/mod_types_brain3.pdf', height = 4, width = 7)
  2164. print(mod_typs3)
  2165. dev.off()
  2166. print(mod_typs3)
  2167. ```
  2168. # Revisions Round 2
  2169. ### Cell-type gene expression analysis using DEGs
  2170. ```{r}
  2171. library(data.table)
  2172. library(ggplot2)
  2173. dt_ <- fread('Data/trimmed_means.csv', header = T)
  2174. dt <- dt_[!(rowSums(dt_[,-1] == 0)),]
  2175. genes <- dt[[1]]
  2176. expr_mat <- as.matrix(dt[, -1])
  2177. rownames(expr_mat) <- genes
  2178. cell_types <- colnames(expr_mat)
  2179. # Row-wise z-score (across cell types, per gene)
  2180. expr_scaled <- t(scale(t(expr_mat)))
  2181. # scale() works column-wise, so transpose, scale, transpose back
  2182. # Now each gene has mean=0, sd=1 across cell types
  2183. # Build results table
  2184. results <- rbindlist(lapply(cell_types, function(ct) {
  2185. data.table(
  2186. gene = genes,
  2187. cell_type = ct,
  2188. expr = expr_mat[, ct], # raw trimmed mean (log2 CPM)
  2189. z_score = expr_scaled[, ct], # how extreme vs other cell types
  2190. log2fc = expr_mat[, ct] - rowMeans(expr_mat[, cell_types != ct])
  2191. # log2FC: already in log space so subtraction = fold change
  2192. )
  2193. }))
  2194. # Convert z-score to p-value and correct for multiple testing
  2195. results[, p_nominal := 2 * pnorm(-abs(z_score))]
  2196. results[, p_adj := p.adjust(p_nominal, method = "BH")]
  2197. # Filter to DEGs: significant + meaningfully upregulated
  2198. degs <- results[
  2199. p_adj < 0.05 & # statistically specific
  2200. log2fc > 1 & # at least 2-fold above mean of other cell types
  2201. expr > 1 # expressed at least log2(CPM) > 1 in this cell type
  2202. ][order(cell_type, -z_score)]
  2203. # How many DEGs per cell type?
  2204. degs[, .N, by = 'cell_type'][order(-N)]
  2205. ```
  2206. ```{r}
  2207. # write top findings to output file
  2208. top_markers <- degs[, head(.SD, 10), by = cell_type, .SDcols = names(degs)[-2]]
  2209. write.table(top_markers, 'Output/revisions2/cell/brain_degs.txt', col.names = T, row.names = F, quote = F)
  2210. ```
  2211. ### Cell type enrichment analysis
  2212. ```{r}
  2213. sdt_ <- fread('Data/all_exc_BHsig_assocs_PGCancestryTWAS.txt', header = TRUE)
  2214. gwas <- c('PGC_AA_MDD_2023', 'PGC_AA_PTSD_2024','PGC_AA_SCZ_2022','PGC_ASIAN_SCZ_2022','PGC_EUR_PTSD_2024','PGC_HNA_PTSD_2024', 'PGC_EURO_SCZ_2022')
  2215. mod <- c('PrediXcan_Brain_Cortex')
  2216. sdt <- sdt_[!(gwas_phenotype %in% gwas | training_model %in% mod),]
  2217. overlap_b <- merge(
  2218. sdt[, .(`gene_name`, gwas_phenotype)],
  2219. top_markers[, .(`gene`, `cell_type`)],
  2220. by.x = "gene_name",
  2221. by.y = "gene",
  2222. allow.cartesian = TRUE
  2223. )
  2224. # Count overlaps for each disease × cell_type pair
  2225. result_b <- overlap_b[, .(n_genes = uniqueN(gene_name), genes = paste(unique(gene_name), collapse = '|')), by = c('gwas_phenotype', 'cell_type')]
  2226. write.table(result_b, 'Output/revisions2/cell/disease_cell_types_brain.txt', col.names = T, row.names = F, quote = F, sep = '\t')
  2227. ```
  2228. ### Cell type overlap with DEGs from brain
  2229. ```{r}
  2230. dt <- copy(sdt)
  2231. pg <- fread('Data/PanglaoDB_markers_27_Mar_2020.tsv', header = T)
  2232. overlap <- merge(
  2233. dt[, .(`gene_name`, gwas_phenotype)],
  2234. pg[, .(`official gene symbol`, `cell type`)],
  2235. by.x = "gene_name",
  2236. by.y = "official gene symbol",
  2237. allow.cartesian = TRUE
  2238. )
  2239. # Count overlaps for each disease × cell_type pair
  2240. result <- overlap[, .(n_genes = uniqueN(gene_name), genes = paste(unique(gene_name), collapse = '|')), by = c('gwas_phenotype', 'cell type')]
  2241. duo <- intersect(overlap$gene_name, overlap_b$gene_name)
  2242. combo <- result[sapply(strsplit(genes, "\\|"), function(g) any(g %in% duo))]
  2243. write.table(combo, 'Output/revisions2/cell/disease_cell_types_brain_DuoDEGs.txt', col.names = T, row.names = F, quote = F, sep = '\t')
  2244. combo
  2245. ```
  2246. # Genetic Ancestry and SNP predictors
  2247. First I want to get all the SNPs used by GTEx and G2S and annotate them with population specific allele frequencies.
  2248. ```{r}
  2249. otpt <- 'Output/revisions2/allelefreq/'
  2250. dir.create(otpt)
  2251. # read in 1000 genomes allele frequency data and SNP annotations
  2252. rsids <- fread('Data/all_rsid_locs_af_anc.annovar.hg38_multianno.txt', header = T)
  2253. anno_ <- fread('Data/all_snplist_avsnp151_convert.avinput', header = F)
  2254. anno <- setNames(anno_, c('Chr', 'Start', 'End', 'Ref', 'Alt', 'rsid'))
  2255. freq <- setDT(merge(anno, rsids, by = c('Chr', 'Start', 'End', 'Ref', 'Alt')))
  2256. # Read in all SNP data from GTEx and G2S models
  2257. all_snps <- fread('Data/all_snpdata.txt', header = T)
  2258. # remove multi-allelic SNPs for now.
  2259. multi_allelic <- freq[, .(.N), by = 'rsid'][N > 1]$rsid
  2260. #annotate GTEx and G2S SNPs and rename columns
  2261. dt_ <- setDT(merge(all_snps, freq[!(rsid %in% multi_allelic),], by = 'rsid'))
  2262. setnames(dt_, c('gnomad41_genome_AF', 'gnomad41_genome_AF_afr', 'gnomad41_genome_AF_ami', 'gnomad41_genome_AF_amr', 'gnomad41_genome_AF_asj', 'gnomad41_genome_AF_eas', 'gnomad41_genome_AF_fin', 'gnomad41_genome_AF_mid', 'gnomad41_genome_AF_nfe', 'gnomad41_genome_AF_sas'),
  2263. c('ALL', 'AFR', 'AMISH', 'ADM_AMR', 'ASHKENAZI', 'E_ASIAN', 'FINN', 'MIDEAST', 'EUR', 'S_ASIAN'))
  2264. cols <- c(names(all_snps),c('Ref', 'Alt', 'ALL', 'AFR', 'AMISH', 'ADM_AMR', 'ASHKENAZI', 'E_ASIAN', 'FINN', 'MIDEAST', 'EUR', 'S_ASIAN'))
  2265. dt <- dt_[, ..cols]
  2266. dt <- dt %>% mutate_at(c('ALL', 'AFR', 'AMISH', 'ADM_AMR', 'ASHKENAZI', 'E_ASIAN', 'FINN', 'MIDEAST', 'EUR', 'S_ASIAN'), as.numeric)
  2267. # get magnitude of difference between African and european allele frequency.
  2268. dt <- dt[, afr_eu_dif := abs(dt$AFR - dt$EUR)][!is.na(afr_eu_dif),]
  2269. # first, get weights that are not shared and assess the AF difference between the two groups
  2270. dt[shared == TRUE, type := 'shared']
  2271. dt[shared == FALSE & !is.na(weight.G2S), type := 'G2S']
  2272. dt[shared == FALSE & !is.na(weight.GTEx), type := 'GTEx']
  2273. #SNP data table created
  2274. ```
  2275. next I want to add the weights for each SNP-gene combination.
  2276. ATTN: You will have to download the following models from the kachuri et al zenodo page located at the following address:
  2277. - AA.cis-eQTL.tar.gz
  2278. -after unzipping the tarball, the file for AA will be ._gala.sage.AA_Whole_Blood_tw_0.5_signif.db. I renamed this to AA_Whole_Blood.db and put it in [KACHURI_MODELS_DIR]
  2279. - MX.cis-eQTL.tar.gz
  2280. - PR.cis-eQTL.tar.gz
  2281. - All.cis-eQTL.tar.gz
  2282. [https://zenodo.org/records/7735723]
  2283. The gtex model can be found here
  2284. - PrediXcan_Whole_Blood.db
  2285. [https://zenodo.org/records/3842289]
  2286. ```{r}
  2287. # Extract weights from all SNPs in the models of interest
  2288. aamod <- '[KACHURI_MODELS_DIR]/AA_Whole_Blood.db'
  2289. allmod <- '[KACHURI_MODELS_DIR]/All_Whole_Blood.db'
  2290. mamod <- '[KACHURI_MODELS_DIR]/MX_Whole_Blood.db'
  2291. prmod <- '[KACHURI_MODELS_DIR]/PR_Whole_Blood.db'
  2292. gtmod <- '[GTEx_MODELS_DIR]/db/PrediXcan_Whole_Blood.db'
  2293. mods <- data.table(modpath = c(aamod, allmod, mamod, prmod),
  2294. modnm = c('G2S_aa', 'G2S_all', 'G2S_mx', 'G2S_pr'),
  2295. modlongnm = c('AA_Whole_Blood', 'All_Whole_Blood', 'MX_Whole_Blood', 'PR_Whole_Blood'))
  2296. gtx <- dbConnect(RSQLite::SQLite(), gtmod)
  2297. gtx_weight <- setDT(dbReadTable(gtx, 'weights'))
  2298. dbDisconnect(gtx)
  2299. g2s <- data.table()
  2300. for(modp in mods$modpath) {
  2301. # first read in the model data
  2302. mod <- dbConnect(RSQLite::SQLite(), modp)
  2303. mod_weight <- setDT(dbReadTable(mod, 'weights'))
  2304. nm <- mods[modpath == modp,]$modlongnm
  2305. mod_weight$training_model <- nm
  2306. mod_weight$gene <- str_remove(mod_weight$gene, '\\..+')
  2307. g2s <- rbind(g2s, mod_weight)
  2308. dbDisconnect(mod)
  2309. }
  2310. gtx_weight$training_model <- 'GTEx'
  2311. ```
  2312. Now having gotten the weights and the SNPs, I want to harmonize the SNPs for the sake of merging. the ref and alt alleles may not be the same across G2S and GTEx. When this is the case, the weight is inaccurate. I need to find the matching and flipped alleles and then adjust the weight accordingly.
  2313. ```{r}
  2314. #check rsid matching gtex vs g2s
  2315. g2s_rsid <- unique(g2s[, c('rsid', 'ref_allele','eff_allele')])
  2316. gtx_rsid <- unique(gtx_weight[, c('rsid', 'ref_allele','eff_allele')])
  2317. dim(g2s_rsid)
  2318. length(unique(g2s_rsid$rsid))
  2319. # one rsid per rsid/ref/alt grouping
  2320. dim(gtx_rsid)
  2321. length(unique(gtx_rsid$rsid))
  2322. # same for gtex
  2323. length(intersect(gtx_rsid$rsid, g2s_rsid$rsid))
  2324. #52,284 shared rsids
  2325. #merge across rsid, ref, and alt,
  2326. rsid_both <- setDT(merge(gtx_rsid, g2s_rsid, by = c('rsid', 'ref_allele', 'eff_allele')))
  2327. rsid2 <- intersect(gtx_rsid$rsid, g2s_rsid$rsid)
  2328. discordant <- setDT(rbind(gtx_rsid, g2s_rsid))[rsid %in% rsid2 & !(rsid %in% rsid_both$rsid),][order(rsid)]
  2329. # get all aligned SNP weights
  2330. all_rsids <- setDT(rbind(gtx_rsid, g2s_rsid))[ !(rsid %in% discordant$rsid),]
  2331. ## Harmonize SNPs across GTEx and G2S
  2332. # Subset the used rsids by those that have consistent ref and eff alleles
  2333. # then get the frequencies relying on both rsid, ref, and alt
  2334. dt_same_ <- setDT(merge(dt, all_rsids, by.x = c('rsid', 'Ref', 'Alt'), by.y = c('rsid' ,'ref_allele', 'eff_allele')))
  2335. dt_same_$allele_order <- 'match'
  2336. dt_dif_ <- setDT(merge(dt, all_rsids, by.x = c('rsid', 'Alt', 'Ref'), by.y = c('rsid' ,'ref_allele', 'eff_allele')))
  2337. dt_dif_$allele_order <- 'flip'
  2338. # adjust allele frequencies (assuming biallelic SNPs)
  2339. af_cols <- c('ALL', 'AFR', 'AMISH', 'ADM_AMR', 'ASHKENAZI', 'E_ASIAN', 'FINN', 'MIDEAST', 'EUR', 'S_ASIAN')
  2340. dt_dif_[ , (af_cols) := lapply(.SD, function(x) 1-x), .SDcols = af_cols]
  2341. # adjust weights for opposite direction of effect
  2342. dt_dif_$weight.G2S <- -1 * dt_dif_$weight.G2S
  2343. dt_dif_$weight.GTEx <- -1 * dt_dif_$weight.GTEx
  2344. # join all
  2345. dt2 <- unique(setDT(rbind(dt_same_, dt_dif_)))
  2346. ## Now we can treat the allele frequencies as true values rather than just the differences
  2347. dt2a <- dt2[model == 'All_Whole_Blood',]
  2348. dt2a
  2349. ```
  2350. Now that I have harmonized and annotated the SNPs of interest with allele frequencies, I want to begin characterizing the genes according to aggregate statistics derived from the SNP predictors.
  2351. ```{r}
  2352. # Read in all eQTL data
  2353. eqtldat <- fread('Data/eQTL_data_all.txt', header = T)
  2354. eqtldat[is.na(weight.G2S), snptype := 'GTEx_SNP']
  2355. eqtldat[is.na(weight.GTEx), snptype := 'G2S_SNP']
  2356. eqtldat[is.na(snptype), snptype := 'shared_SNP']
  2357. edat_type <- eqtldat[Significant == 'Significant', .(.N, N_genes = length(unique(gene))), by = c('gwas_phenotype', 'snptype', 'category')][order(gwas_phenotype)]
  2358. # plot each gene. data is percentage of SNPs that are G2S specific
  2359. eqtldat[snptype == 'GTEx_SNP', snptype_q := -1]
  2360. eqtldat[snptype == 'shared_SNP', snptype_q := 0]
  2361. eqtldat[snptype == 'G2S_SNP', snptype_q := 1]
  2362. edat_prop <- eqtldat[ Significant == 'Significant', .(type_quant = sum(snptype_q)), by = c('gwas_phenotype', 'category', 'gene')]
  2363. eqtldat[, category_collapsed := fct_collapse(category,
  2364. "G2S" = c("G2S only", "G2S co-tested"),
  2365. "GTEX" = c("GTEX WB co-tested"),
  2366. "Shared" = c("co-significant")
  2367. )]
  2368. gene_features <- eqtldat[, .(
  2369. # SNP counts
  2370. n_snps = .N,
  2371. # model-specific SNP counts
  2372. n_g2s_snps = sum(!is.na(weight.G2S)),
  2373. n_gtex_snps = sum(!is.na(weight.GTEx)),
  2374. # proportions
  2375. prop_g2s_snps = mean(!is.na(weight.G2S)),
  2376. prop_gtex_snps = mean(!is.na(weight.GTEx)),
  2377. # weights
  2378. mean_g2s_weight_magnitude = mean(abs(weight.G2S), na.rm = TRUE),
  2379. mean_gtex_weight_magnitude = mean(abs(weight.GTEx), na.rm = TRUE),
  2380. # MAF
  2381. mean_afr_maf = mean(AFR, na.rm = TRUE),
  2382. mean_eur_maf = mean(EUR, na.rm = TRUE),
  2383. mean_afr_eur_maf_diff = mean(abs(AFR -EUR), na.rm = TRUE),
  2384. n_maf_diff_over_0.3 = sum(AFR-EUR > 0.3, na.rm = TRUE), #total number of SNPs with maf dif > 0.3
  2385. mean_afr_maf_weighted = mean(AFR*abs(weight.G2S), na.rm = TRUE),
  2386. mean_eur_maf_weighted = mean(EUR*abs(weight.GTEx), na.rm = TRUE),
  2387. mean_maf_diff_weighted = mean(AFR*abs(weight.G2S), na.rm = TRUE)-mean(EUR*abs(weight.GTEx), na.rm = TRUE),
  2388. # SNP type composition
  2389. prop_common = mean(SNP_type == "COMMON"),
  2390. prop_rare = mean(SNP_type == "RARE"),
  2391. prop_afr_specific = mean(SNP_type == "AFR"),
  2392. prop_eur_specific = mean(SNP_type == "EUR"),
  2393. n_afr_specific = sum(SNP_type == "AFR"),
  2394. n_eur_specific = sum(SNP_type == "EUR")
  2395. ), by = .(gene, gwas_phenotype, category_collapsed)]
  2396. dt <- gene_features[gwas_phenotype == "PGC_all_SCZ_2022",]
  2397. dt$category_collapsed <- as.factor(dt$category_collapsed)
  2398. dt[is.nan(mean_gtex_weight_magnitude), mean_gtex_weight_magnitude := 0]
  2399. dt[is.nan(mean_g2s_weight_magnitude), mean_g2s_weight_magnitude := 0]
  2400. ```
  2401. Now we have data on the SNP characteristics for each gene involved in gene-trait associations. Next I want to figure out how the SNP characteristics differ for genes that were significantly associated with Schizophrenia in different models.
  2402. ```{r}
  2403. # Melt to long format for plotting
  2404. features_of_interest <- names(dt)[-c(1:3)]
  2405. gf_long <- melt(dt[category_collapsed != "None"],
  2406. id.vars = "category_collapsed",
  2407. measure.vars = features_of_interest)
  2408. # Violin plots - distribution of each feature by category
  2409. ff <- ggplot(gf_long, aes(x = category_collapsed, y = value,
  2410. fill = category_collapsed)) +
  2411. geom_violin(alpha = 0.7) +
  2412. geom_boxplot(width = 0.1, outlier.shape = NA) +
  2413. facet_wrap(~variable, scales = "free_y") +
  2414. theme_minimal() +
  2415. labs(title = "Feature distributions by association category",
  2416. x = NULL, y = NULL) +
  2417. theme(legend.position = "none",
  2418. axis.text.x = element_text(angle = 45, hjust = 1))
  2419. name = 'Output/revisions2/all_measures_SCZ.png'
  2420. png(filename = name, width = 11, height = 6, units = "in", pointsize = 12, bg = "white", type = 'cairo', res = 600)
  2421. print(ff)
  2422. dev.off()
  2423. print(ff)
  2424. ```
  2425. ### Fig S4: Odds ratios for G2S vs GTEx significance
  2426. ```{r}
  2427. library(coin) # for permutation tests - robust with small groups
  2428. # The key scientific contrasts
  2429. # G2S only vs None: what makes a gene significant in G2S?
  2430. # G2S only vs Shared: what makes a gene G2S-exclusive vs both?
  2431. # GTEX only vs Shared: what makes a gene GTEx-exclusive?
  2432. # For each feature, test G2S vs GTEX vs Shared
  2433. kruskal_results <- dt[category_collapsed != "None",
  2434. lapply(.SD, function(x) kruskal.test(x ~ category_collapsed)$p.value),
  2435. .SDcols = features_of_interest]
  2436. # Tidy it up
  2437. kruskal_long <- setDT(melt(kruskal_results, variable.name = "feature",
  2438. value.name = "p_value"))
  2439. kruskal_long[, p_adj := p.adjust(p_value, method = "BH")]
  2440. kruskal_long[, `-log10 p_adj` := -1*log10(p_adj)]
  2441. kruskal_long[order(p_adj)]
  2442. kruskal_long[, Significance := fifelse(p_adj <= 0.05, "Sig", "Insig")]
  2443. f1 <- ggplot(data = kruskal_long, aes(x = feature, y = `-log10 p_adj`, color = Significance, shape = Significance)) +
  2444. geom_segment( aes(x=feature, xend=feature, y=0, yend=`-log10 p_adj`), color="grey") +
  2445. geom_point(size=4) +
  2446. theme_minimal() +
  2447. coord_flip()
  2448. name = 'Output/revisions2/all_measures_SCZ_kruskal.png'
  2449. png(filename = name, width = 6, height = 6, units = "in", pointsize = 12, bg = "white", type = 'cairo', res = 600)
  2450. print(f1)
  2451. dev.off()
  2452. print(f1)
  2453. ```
  2454. ### Fig S3: Print significantly different features with DOE
  2455. ```{r}
  2456. # Get significant features first
  2457. sig_features <- kruskal_long[p_adj <= 0.05, as.character(feature)]
  2458. dtz <- copy(dt)
  2459. dtz[, (sig_features) := lapply(.SD, scale), .SDcols =sig_features]
  2460. # Pairwise Wilcoxon for each significant feature
  2461. # The three scientifically meaningful contrasts
  2462. contrasts <- list(
  2463. c("G2S", "Shared"), # G2S-exclusive vs both models
  2464. c("GTEX", "Shared"), # GTEX-exclusive vs both models
  2465. c("G2S", "GTEX") # the key contrast you care about most
  2466. )
  2467. direction_results <- rbindlist(lapply(sig_features, function(feat) {
  2468. rbindlist(lapply(contrasts, function(pair) {
  2469. x <- dtz[category_collapsed == pair[1], get(feat)]
  2470. y <- dtz[category_collapsed == pair[2], get(feat)]
  2471. wt <- wilcox.test(x, y, conf.int = TRUE)
  2472. data.table(
  2473. feature = feat,
  2474. contrast = paste(pair[1], "vs", pair[2]),
  2475. median_A = median(x, na.rm = TRUE),
  2476. median_B = median(y, na.rm = TRUE),
  2477. difference = median(x, na.rm = TRUE) - median(y, na.rm = TRUE),
  2478. direction = fifelse(median(x, na.rm=TRUE) > median(y, na.rm=TRUE),
  2479. paste("higher in", pair[1]),
  2480. paste("higher in", pair[2])),
  2481. p_value = wt$p.value,
  2482. p_adj = p.adjust(wt$p.value, method = "BH")
  2483. )
  2484. }))
  2485. }))
  2486. # View ordered by contrast then significance
  2487. direction_results[order(contrast, p_adj)]
  2488. ```
  2489. ### Fig S3: DOE and effect size of feature regression
  2490. ```{r}
  2491. library(viridis)
  2492. # Dot plot: effect size on x, feature on y, faceted by contrast
  2493. f3 <- ggplot(direction_results[p_adj <= 0.05],
  2494. aes(color = abs(difference),
  2495. y = reorder(feature, abs(difference)),
  2496. shape = direction,
  2497. x = -log10(p_adj))) +
  2498. geom_vline(xintercept = 0, linetype = "dashed", color = "gray60") +
  2499. geom_point(alpha = 1, size = 3) +
  2500. facet_wrap(~contrast, ncol = 3) +
  2501. scale_color_viridis_c(option = "viridis") +
  2502. #scale_color_manual(
  2503. # values = c("#3B8BD4", "#1D9E75"),
  2504. # labels = c("Higher in B", "Higher in A")
  2505. #) +
  2506. theme_minimal() +
  2507. labs(#title = "Direction of effect for significant SNP features",
  2508. #subtitle = "Point size = -log10 adjusted p-value",
  2509. color = "Median difference abs(A - B)",
  2510. y = NULL,
  2511. color = NULL,
  2512. x = "-log10 p-adj",
  2513. shape = "Model impact")
  2514. name = 'Output/revisions2/all_measures_SCZ_wilcoxon.png'
  2515. png(filename = name, width = 9, height = 5, units = "in", pointsize = 12, bg = "white", type = 'cairo', res = 600)
  2516. print(f3)
  2517. dev.off()
  2518. print(f3)
  2519. ```
  2520. ```{r}
  2521. #now look specifically for the effects when binning for coverage
  2522. # Among genes where GTEx coverage is EQUAL (n_gtex_snps similar),
  2523. # does prop_afr_specific still differ between G2S and GTEX?
  2524. # Bin by prop_g2s-prop_gtex to control for coverage
  2525. dt[category_collapsed != "None",
  2526. model_coverage := cut(abs(prop_g2s_snps-prop_gtex_snps),
  2527. breaks = quantile(abs(prop_g2s_snps-prop_gtex_snps),
  2528. probs = seq(0,1,0.25),
  2529. na.rm = TRUE),
  2530. include.lowest = TRUE)]
  2531. #dt[ ,':='(model_coverage=NULL)]
  2532. # Now test mean_maf_diff_weighted within coverage-matched genes
  2533. dt[category_collapsed %in% c("G2S", "GTEX") &
  2534. model_coverage == levels(model_coverage)[1], # mindist coverage bin
  2535. wilcox.test(mean_maf_diff_weighted ~ category_collapsed)]
  2536. ```
  2537. ```{r}
  2538. dt[, g2s_binary := fifelse(
  2539. category_collapsed %in% c("G2S", "Shared"), 1, 0)]
  2540. dt[, g2s_binary := fifelse(
  2541. category_collapsed %in% c("G2S"), 1, 0)]
  2542. model_logistic <- glm(
  2543. g2s_binary ~ n_snps + n_g2s_snps + n_gtex_snps +
  2544. prop_g2s_snps + prop_gtex_snps + mean_g2s_weight_magnitude +
  2545. mean_gtex_weight_magnitude + n_maf_diff_over_0.3 +
  2546. mean_maf_diff_weighted + prop_common + prop_rare +
  2547. n_eur_specific,
  2548. data = dt[category_collapsed != "None"],
  2549. family = binomial
  2550. )
  2551. summary(model_logistic)
  2552. exp(coef(model_logistic)) # odds ratios
  2553. exp(confint(model_logistic)) # confidence intervals
  2554. summary(model_logistic)
  2555. ```
  2556. ## Model-wide FDR thresholding
  2557. ```{r}
  2558. dt_ <- fread('Data/all_exc_assocs_PGCancestryTWAS.txt', header =T)
  2559. mods <- c("AA_Whole_Blood","All_Whole_Blood","MX_Whole_Blood","PrediXcan_Whole_Blood","PR_Whole_Blood")
  2560. test_phens <- c("PGC_allADHD_2022", "PGC_allMDD_2023","PGC_ALL_PTSD_2024","PGC_all_SCZ_2022","PGC_BD1_2021","SUD_alc_2019")
  2561. dt <- dt_[gwas_phenotype %in% test_phens & training_model %in% mods, -c('bhpval','bfpval')]
  2562. dt$bfpval <- p.adjust(dt$pvalue, "bonferroni")
  2563. dt$bhpval <- p.adjust(dt$pvalue, "BH")
  2564. dtbh <- dt[bhpval <= 0.05,]
  2565. dtbh$gg <- paste(dtbh$gene, dtbh$gwas_phenotype, sep = '_')
  2566. dtbh_shared <- dtbh[training_model != "PrediXcan_Whole_Blood" & gg %in% dtbh[training_model == "PrediXcan_Whole_Blood",]$gg,]
  2567. dtbh[gg %in% dtbh_shared$gg, status := 'shared']
  2568. dtbh_g2s <- dtbh[training_model != "PrediXcan_Whole_Blood" & !(gg %in% dtbh[training_model == "PrediXcan_Whole_Blood",]$gg),]
  2569. dtbh[gg %in% dtbh_g2s$gg, status := 'G2S only']
  2570. dtbh_gtex <- dtbh[training_model == "PrediXcan_Whole_Blood" & !(gg %in% dtbh_shared$gg),]
  2571. dtbh[gg %in% dtbh_gtex$gg, status := 'GTEx only']
  2572. dtbhn <- dtbh[, .(.N), by = c('gwas_phenotype', 'training_model')]
  2573. dtbhn[training_model == 'All_Whole_Blood', `gene expression model` := 'G2S All WB']
  2574. dtbhn[training_model == 'AA_Whole_Blood', `gene expression model` := 'G2S African American WB']
  2575. dtbhn[training_model == 'MX_Whole_Blood', `gene expression model` := 'G2S Mexican American WB']
  2576. dtbhn[training_model == 'PR_Whole_Blood', `gene expression model` := 'G2S Puerto Rican WB']
  2577. dtbhn[training_model == 'PrediXcan_Whole_Blood', `gene expression model` := 'GTEx European WB']
  2578. dtbhn
  2579. ```

PGC_master_analysis2.Rmd, under CC-BY-4.0 · at the source

Overview

Authors: Xavier Bledsoe1,2, Nathan Watkins3, Tavian Bowen-Moore4, Marlisa Shaw1, Ravi V Shah5, Eric R Gamazon2,5,6
  1. Medical Scientist Training Program, Vanderbilt University, Nashville, TN USA
  2. Division of Genetic Medicine, Vanderbilt University Medical Center, Nashville, TN USA
  3. Chapman University, Orange, CA USA
  4. Gonzaga University, Spokane, WA USA
  5. Vanderbilt Diabetes Center, Nashville, TN USA
  6. Vanderbilt Memory & Alzheimer’s Center, Nashville, TN USA
Institutions: Vanderbilt University (United States); Vanderbilt University Medical Center (United States); Chapman University (United States); Gonzaga University (United States); Vanderbilt Health (United States)
Journal: Nature communications, volume 17, issue 1, article 8331
Dates: received 14 March 2025; accepted 25 June 2026; published online 4 July 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s41467-026-75193-4 · PMID 42401576 · PMCID PMC13470059 · OpenAlex W7167358232
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), human (organism), cellular / molecular (subfield)
Methods: Statistics, Machine learning, Preprocessing, Connectivity
Keywords: Gene expression, Computational biology and bioinformatics, Genetic association study
MeSH: Genome-Wide Association Study*, Mental Disorders*, Models, Genetic*, Transcriptome*, Black People, Gene Expression Profiling, Genetic Predisposition to Disease, Humans, Indigenous Peoples, Polymorphism, Single Nucleotide, White People (* major topic)
Topic: Genetic Associations and Epidemiology (Genetics, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: U.S. Department of Health &amp; Human Services | NIH | National Institute of General Medical Sciences (R01GM140287); U.S. Department of Health & Human Services | NIH | National Institute of Diabetes and Digestive and Kidney Diseases (National Institute of Diabetes & Digestive & Kidney Diseases) (P30DK020593); NIGMS NIH HHS (R01 GM140287); U.S. Department of Health & Human Services | NIH | National Institute of Mental Health (NIMH) (R01MH126459); U.S. Department of Health & Human Services | NIH | National Institute on Aging (U.S. National Institute on Aging) (AG068026); NIMH NIH HHS (R01 MH126459); U.S. Department of Health & Human Services | NIH | National Institute of General Medical Sciences (NIGMS) (R01GM140287); U.S. Department of Health &amp; Human Services | NIH | National Institute of Diabetes and Digestive and Kidney Diseases (P30DK020593); NHGRI NIH HHS (R35 HG010718, R01 HG011138); U.S. Department of Health & Human Services | NIH | National Human Genome Research Institute (NHGRI) (R35HG010718, R01HG011138); NIA NIH HHS (R56 AG068026); NIDDK NIH HHS (P30 DK020593); U.S. Department of Health &amp; Human Services | NIH | National Institute on Aging (AG068026); U.S. Department of Health &amp; Human Services | NIH | National Human Genome Research Institute (R35HG010718, R01HG011138); U.S. Department of Health &amp; Human Services | NIH | National Institute of Mental Health (R01MH126459)
Citations: cited by 1 paper (Europe PMC); 51 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repositories

Its files are read in the Code ↔ Paper reader above, with 11 matches between paragraphs and lines of code.

Zenodo 14889757

License: CC-BY-4.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Languages: R (1)
Size: 5 files, 1 script
Software Heritage: not checked
Found in: “Code availability”
Holds: README, 1 notebook
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: data.table (4 files), tidyverse (4 files), ggplot2 (3 files), ggpubr (1 file), pandas (1 file), pheatmap (1 file), reshape2 (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
11 files
At the source:

hakyimlab/MetaXcan

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: e069063a10539fe92adadb645fc667a40c2cf885, 8 September 2026
Languages: Python (118), R (2), Shell (2)
Size: 318 files, 122 scripts
Software Heritage: not archived
Found in: “Data availability”
Holds: README, license file, environment (software/conda_env.yaml, software/requirements.txt, software/setup.cfg, software/setup.py), tests, documentation, 1 notebook
Not found: CITATION.cff, continuous integration
Tools: NumPy (52 files), pandas (40 files), SciPy (7 files), h5py (4 files), statsmodels (4 files)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
124 files

qingnanl/gsdensity_manuscript_code

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 733148850a249f17016b7ba8a4d4f89177f81f8d, 20 November 2023
Languages: R (13), Python (2), Jupyter (1)
Size: 23 files, 16 scripts
Software Heritage: not archived
Found in: “Data availability”
Holds: README, 1 notebook
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Seurat (11 files), tidyverse (9 files), ggplot2 (8 files), reshape2 (5 files), pheatmap (4 files), NumPy (3 files), pandas (3 files), igraph (2 files), ComplexHeatmap (1 file), data.table (1 file), Monocle 3 (1 file), patchwork (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
17 files

Zenodo 18315835

License: CC-BY-4.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Languages: R (1)
Size: 5 files, 1 script
Software Heritage: not checked
Found in: the references
Holds: README, 1 notebook
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: data.table (4 files), tidyverse (4 files), ggplot2 (3 files), ggpubr (1 file), pandas (1 file), pheatmap (1 file), reshape2 (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
11 files
At the source:

Code availability statement

The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s41467-026-75193-4.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 4 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 158 scripts, each with its path and the digest of its content;
  • 11 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Code and data availability statement

The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s41467-026-75193-4.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 6 authors, 3 keywords, 11 MeSH terms, 15 funders, 47 references.

Cite

This paper

Bledsoe, X., Watkins, N., Bowen-Moore, T., Shaw, M., Shah, R. V., & Gamazon, E. R. (2026). Multi-ancestry gene expression models amplify transcriptome-wide association study discovery and validation. Nature communications, 17(1), 8331. https://doi.org/10.1038/s41467-026-75193-4

BibTeX

@article{bledsoe2026multi,
author = {Bledsoe, Xavier and Watkins, Nathan and Bowen-Moore, Tavian and Shaw, Marlisa and Shah, Ravi V and Gamazon, Eric R},
title = {{Multi-ancestry gene expression models amplify transcriptome-wide association study discovery and validation}},
journal = {Nature communications},
year = {2026},
month = jul,
volume = {17},
number = {1},
pages = {8331},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-75193-4},
url = {https://doi.org/10.1038/s41467-026-75193-4},
pmid = {42401576},
pmcid = {PMC13470059}
}

RIS

TY - JOUR
AU - Bledsoe, Xavier
AU - Watkins, Nathan
AU - Bowen-Moore, Tavian
AU - Shaw, Marlisa
AU - Shah, Ravi V
AU - Gamazon, Eric R
TI - Multi-ancestry gene expression models amplify transcriptome-wide association study discovery and validation
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/07/04
VL - 17
IS - 1
SP - 8331
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-75193-4
UR - https://doi.org/10.1038/s41467-026-75193-4
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-75193-4",
"type": "article-journal",
"title": "Multi-ancestry gene expression models amplify transcriptome-wide association study discovery and validation",
"container-title": "Nature communications",
"author": [
{
"family": "Bledsoe",
"given": "Xavier"
},
{
"family": "Watkins",
"given": "Nathan"
},
{
"family": "Bowen-Moore",
"given": "Tavian"
},
{
"family": "Shaw",
"given": "Marlisa"
},
{
"family": "Shah",
"given": "Ravi V"
},
{
"family": "Gamazon",
"given": "Eric R"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "8331",
"DOI": "10.1038/s41467-026-75193-4",
"PMID": "42401576",
"PMCID": "PMC13470059",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-75193-4",
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
4
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1038/s41380-026-03571-x [code]
Convergent coexpression reveals shared biological mechanisms underlying common and rare variant risk in six neuropsychiatric disorders.
Journal: Molecular psychiatry
In common: Monocle 3, igraph, Seurat, 10 other tools, genetics / omics, cellular / molecular, 5 references
[2] doi:10.1016/j.celrep.2026.117500 [code]
Spatio-molecular gene expression reflects dorsal anterior cingulate cortex structure and function in the human brain.
Journal: Cell reports
In common: igraph, ComplexHeatmap, pheatmap, 8 other tools, genetics / omics, cellular / molecular, 5 references
[3] doi:10.1016/j.xcrm.2026.102766 [code]
A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.
Journal: Cell reports. Medicine
In common: Monocle 3, igraph, ComplexHeatmap, 12 other tools, genetics / omics, cellular / molecular
[4] doi:10.1038/s41467-026-69944-6 [code]
Multi-modal dissection of cell-type specific TDP-43 pathology in the motor cortex.
Journal: Nature communications
In common: Monocle 3, igraph, ComplexHeatmap, 11 other tools, genetics / omics, 1 reference
[5] doi:10.1038/s42003-026-10957-8 [code]
Brain defence by the extracellular matrix protein Cochlin.
Journal: Communications biology
In common: Monocle 3, igraph, ComplexHeatmap, 12 other tools, cellular / molecular
[6] doi:10.1038/s41467-026-76675-1 [code]
Long-read proteogenomic atlas of human neuronal differentiation reveals isoform diversity informing neurodevelopmental risk mechanisms.
Journal: Nature communications
In common: Monocle 3, igraph, pheatmap, 11 other tools, genetics / omics, 1 reference
[7] doi:10.1038/s41380-026-03497-4 [code]
Transcriptome-informed brain cartography of polygenic risk and association with brain structure in major psychiatric disorders.
Journal: Molecular psychiatry
In common: ComplexHeatmap, pheatmap, patchwork, 6 other tools, genetics / omics, cellular / molecular, 6 references
[8] doi:10.1002/imt2.70163 [code]
Spatial multi-omics unveils sphingolipid metabolic reprogramming within the retinal pathological niche.
Journal: iMeta
In common: Monocle 3, igraph, ComplexHeatmap, 11 other tools, genetics / omics, cellular / molecular
[9] doi:10.1038/s41586-026-10214-2 [code]
Multidimensional profiling of heterogeneity in supratentorial ependymomas.
Journal: Nature
In common: Monocle 3, igraph, ComplexHeatmap, 11 other tools, genetics / omics
[10] doi:10.1038/s41588-026-02646-3 [code]
Co-expression-based models improve eQTL predictions for transcriptome-wide association studies and highlight new schizophrenia-associated genes.
Journal: Nature genetics
In common: pheatmap, reshape2, h5py, 6 other tools, genetics / omics, cellular / molecular, 6 references

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.