Loading [MathJax]/jax/output/HTML-CSS/jax.js
  • Setting up
    • Libraries and helper functions
    • Load all data
  • Calculate sex bias in expression for each transcript
  • Overlap between our significant SNPs and known eQTls
  • Correlating our fitness measures to transcriptome data from Huang et al. 2015
    • Linear models to find transcripts that correlate with fitness across DGRP lines (“TWAS”)
    • Run mashr to adjust the TWAS results
    • Find mixture probabilities for each transcript
  • Identify significantly antagonistic and concordant transcripts

Last updated: 2021-02-28

Checks: 6 1

Knit directory: fitnessGWAS/

This reproducible R Markdown analysis was created with workflowr (version 1.6.2). The Checks tab describes the reproducibility checks that were applied when the results were created. The Past versions tab lists the development history.


The R Markdown file has unstaged changes. To know which version of the R Markdown file created these results, you’ll want to first commit it to the Git repo. If you’re still working on the analysis, you can ignore this warning. When you’re finished, you can run wflow_publish to commit the R Markdown file and build the HTML.

Great job! The global environment was empty. Objects defined in the global environment can affect the analysis in your R Markdown file in unknown ways. For reproduciblity it’s best to always run the code in an empty environment.

The command set.seed(20180914) was run prior to running the code in the R Markdown file. Setting a seed ensures that any results that rely on randomness, e.g. subsampling or permutations, are reproducible.

Great job! Recording the operating system, R version, and package versions is critical for reproducibility.

Nice! There were no cached chunks for this analysis, so you can be confident that you successfully produced the results during this run.

Great job! Using relative paths to the files within your workflowr project makes it easier to run your code on other machines.

Great! You are using Git for version control. Tracking code development and connecting the code version to the results is critical for reproducibility.

The results in this page were generated with repository version c386787. See the Past versions tab to see a history of the changes made to the R Markdown and HTML files.

Note that you need to be careful to ensure that all relevant files for the analysis have been committed to Git prior to generating the results (you can use wflow_publish or wflow_git_commit). workflowr only checks the R Markdown file, but you know if there are other scripts or data files that it depends on. Below is the status of the Git repository when the results were generated:


Ignored files:
    Ignored:    .DS_Store
    Ignored:    .Rapp.history
    Ignored:    .Rhistory
    Ignored:    .Rproj.user/
    Ignored:    .httr-oauth
    Ignored:    .pversion
    Ignored:    analysis/.DS_Store
    Ignored:    analysis/correlations_SNP_effects_cache/
    Ignored:    analysis/plot_models_variant_effects_cache/
    Ignored:    code/.DS_Store
    Ignored:    code/Drosophila_GWAS.Rmd
    Ignored:    data/.DS_Store
    Ignored:    data/derived/
    Ignored:    data/input/.DS_Store
    Ignored:    data/input/.pversion
    Ignored:    data/input/dgrp.fb557.annot.txt
    Ignored:    data/input/dgrp2.bed
    Ignored:    data/input/dgrp2.bim
    Ignored:    data/input/dgrp2.fam
    Ignored:    data/input/huang_transcriptome/
    Ignored:    figures/.DS_Store

Untracked files:
    Untracked:  Rplots.pdf
    Untracked:  analysis/GO_KEGG_enrichment.Rmd
    Untracked:  analysis/TWAS_tables.Rmd
    Untracked:  analysis/plot_models_variant_effects.Rmd
    Untracked:  code/GO_and_KEGG_gsea.R
    Untracked:  code/make_sites_files_for_ARGweaver.R
    Untracked:  code/run_argweaver.R
    Untracked:  code/run_mashr.R
    Untracked:  data/argweaver/
    Untracked:  data/input/TF_binding_sites.csv
    Untracked:  figures/GWAS_mixture_proportions.rds
    Untracked:  figures/GWAS_stats_figure.pdf
    Untracked:  figures/TWAS_mixture_proportions.rds
    Untracked:  figures/TWAS_stats_figure.pdf
    Untracked:  figures/antagonism_ratios.pdf
    Untracked:  figures/composite_mixture_figure.pdf
    Untracked:  figures/eff_size_histos.pdf
    Untracked:  figures/stats_figure.pdf
    Untracked:  manuscript/

Unstaged changes:
    Modified:   .gitignore
    Modified:   analysis/GWAS_tables.Rmd
    Modified:   analysis/TWAS.Rmd
    Modified:   analysis/checking_mashr_results.Rmd
    Modified:   analysis/eQTL_analysis.Rmd
    Modified:   analysis/get_predicted_line_means.Rmd
    Modified:   analysis/gwas_adaptive_shrinkage.Rmd
    Modified:   analysis/index.Rmd
    Modified:   analysis/make_annotation_database.Rmd
    Modified:   analysis/perform_gwas.Rmd
    Modified:   analysis/plot_line_means.Rmd
    Modified:   analysis/plotting_results.Rmd
    Deleted:    code/gwas_adaptive_shrinkage.R
    Modified:   data/input/female_fitness.csv
    Modified:   data/input/female_fitness_CLEANED.csv
    Modified:   data/input/male_fitness.csv
    Modified:   data/input/male_fitness_CLEANED.csv
    Deleted:    figures/figure1.eps
    Deleted:    figures/figure1.png
    Deleted:    figures/figure2.eps

Note that any generated files, e.g. HTML, png, CSS, etc., are not included in this status report because it is ok for generated content to have uncommitted changes.


These are the previous versions of the repository in which changes were made to the R Markdown (analysis/TWAS.Rmd) and HTML (docs/TWAS.html) files. If you’ve configured a remote Git repository (see ?wflow_git_remote), click on the hyperlinks in the table below to view the files as they were in that past version.

File Version Author Date Message
Rmd 8d54ea5 Luke Holman 2018-12-23 Initial commit

Setting up

Libraries and helper functions

library(edgeR)
library(tidyverse)
library(glue)
library(future)
library(future.apply)
library(parallel)
library(kableExtra)
library(DT)
library(ashr)
library(mashr)

options(stringsAsFactors = FALSE)

# Connect to the database of annotations
db <- DBI::dbConnect(RSQLite::SQLite(), "data/derived/annotations.sqlite3")

# Helper to run shell commands
run_command <- function(shell_command, wd = getwd(), path = ""){
  cat(system(glue("cd ", wd, path, "\n",shell_command), intern = TRUE), sep = '\n')
}

kable_table <- function(df) { # cool tables
  kable(df, "html") %>%
  kable_styling() %>%
  scroll_box(height = "300px")
}

my_data_table <- function(df){ # Make html tables:
  datatable(
    df, rownames=FALSE,
    autoHideNavigation = TRUE,
    extensions = c("Scroller",  "Buttons"),
    options = list(
      dom = 'Bfrtip',
      deferRender=TRUE,
      scrollX=TRUE, scrollY=400,
      scrollCollapse=TRUE,
      buttons = 
        list('pageLength', 'colvis', 'csv', list(
          extend = 'pdf',
          pageSize = 'A4',
          orientation = 'landscape',
          filename = 'TWAS_enrichment')),
       columnDefs = list(list(targets = c(8,10), visible = FALSE)),
      pageLength = 50
    )
  )
}

# Helper to load Huang et al.'s data
load_expression_data <- function(sex){
  
  if(sex != "both"){
    expression <- glue("data/input/huang_transcriptome/dgrp.array.exp.{sex}.txt") %>% read_delim(delim = " ")
    sample_names <- names(expression)[names(expression) != "gene"] %>% str_remove(":[12]") 
    gene_names <- expression$gene
    expression <- expression %>% select(-gene) %>% as.matrix() %>% t() 
    rownames(expression) <- sample_names # rows are samples, columns are genes
    colnames(expression) <- gene_names 
    return(expression %>% as.data.frame() %>% 
             tibble::rownames_to_column("line") %>% 
             as_tibble() %>%
             mutate(line = str_remove_all(line, "[.]1")))
  }
  
  females <- read_delim("data/input/huang_transcriptome/dgrp.array.exp.female.txt", delim = " ")
  names(females)[-1] <- paste("F_", names(females)[-1],sep="") #%>% str_remove(":[12]") 
  females <- females %>% left_join(read_delim("data/input/huang_transcriptome/dgrp.array.exp.male.txt", delim = " "), by = "gene")
  sample_names <- names(females)[names(females) != "gene"] %>% str_remove(":[12]") 
  gene_names <- females$gene
  sex <- ifelse(str_detect(sample_names, "F_"), "female", "male")
  line <- str_remove_all(sample_names, "F_")
  females <- females %>% select(-gene) %>% t()
  colnames(females) <- gene_names
  list(
    sampleIDs = tibble(sex, line),
    expression = females
  )
}

Load all data

# Load the predicted line means, as calculated in get_predicted_line_means.Rmd
predicted_line_means <- read_csv("data/derived/predicted_line_means.csv")

# Load the results of four univariate linear mixed models run in GEMMA and corrected by mashr
univariate_lmm_results <- tbl(db, "univariate_lmm_results") %>%
  left_join(tbl(db, "variants") %>% select(SNP, FBID, site.class, MAF), by = "SNP") %>%
  left_join(tbl(db, "genes") %>% select(FBID, gene_name), by = "FBID")

# Results of one multivariate linear mixed model run in GEMMA:
# multivariate_lmm_results <- read_tsv("data/derived/output/all_four_traits.assoc.txt") %>%
#   select(-contains("Vbeta")) %>%
#   left_join(tbl(db, "variants") %>% select(SNP, FBID, site.class, MAF) %>% collect(), by = "SNP") %>% 
#   left_join(tbl(db, "genes") %>% 
#               select(FBID, gene_name) %>% 
#               collect(), by = "FBID") %>% 
#   left_join(univariate_lmm_results %>% select(SNP, SNP_clump) %>% collect(n=Inf), by = "SNP") %>%
#   select(SNP, SNP_clump, gene_name, FBID, contains("male"), p_wald, fdr) 


# Load the supplementary data files from Huang et al. 2015 PNAS
# Table S2: results of statistical tests for sex, line and sex-by-line effects on expression of each transcript
# huang_expression <- read_csv("data/input/huang_2015_tableS2_gene_expression.csv")

# Table S5: heritability of the expression level of each transcript (as measured in males, or females)
huang_heritability <- read_csv("data/input/huang_2015_tableS5_transcript_heritability.csv")

# Table S11+S12: statistically significant eQTLs, and the transcripts they affect (for each sex)
huang_eQTL_females <- read_csv("data/input/huang_2015_tableS11_eQTL_females.csv") %>%
  left_join(tbl(db, "genes") %>% select(FBID, gene_name) %>% collect(), by = "FBID") %>%
  rename(Affected_FBID = FBID, Affected_gene = gene_name)

huang_eQTL_males <- read_csv("data/input/huang_2015_tableS12_eQTL_males.csv") %>%
  left_join(tbl(db, "genes") %>% select(FBID, gene_name) %>% collect(), by = "FBID") %>%
  rename(Affected_FBID = FBID, Affected_gene = gene_name)

Calculate sex bias in expression for each transcript

The following takes the 368 female samples and the 369 male samples, and finds the log fold difference in expression between sexes, and the average expression across both sexes, using the edgeR package.

expression_data_both_sexes <- load_expression_data("both") %>% unname()

voom_gene_data <- calcNormFactors(DGEList(t(expression_data_both_sexes[[2]])))
mm <- model.matrix(~ sex, data = expression_data_both_sexes[[1]])
colnames(mm) <- gsub("sex", "", colnames(mm))

sex_bias_in_expression <- voom_gene_data %>% 
  voom(mm, plot = FALSE) %>% 
  lmFit(mm) %>% 
  eBayes() %>%
  topTable(n = Inf) %>% 
  rownames_to_column("FBID") %>%
  select(FBID, logFC, AveExpr) %>% 
  rename(male_bias_in_expression = logFC) %>%
  as_tibble() %>% arrange(male_bias_in_expression)

write_csv(sex_bias_in_expression, "data/derived/gene_expression_by_sex.csv")

rm(expression_data_both_sexes)

Overlap between our significant SNPs and known eQTls

make_eQTL_overlap_table <- function(huang_data){
  huang_data %>%
    select(Affected_FBID, Affected_gene, eQTL) %>%
    inner_join(univariate_lmm_results %>%
                 select(SNP, FBID, gene_name, contains("mashr_ED")) %>%
                 filter(SNP %in% !!huang_data$eQTL) %>%
                 collect(n = Inf) %>%
                 filter_at(vars(contains("LFSR")), any_vars(. < 0.001)) %>%    
                 rename(eQTL_location_FBID = FBID,
                        eQTL_location_gene = gene_name), 
               by = c("eQTL" = "SNP")) %>%
    mutate(`Cis- or trans- eQTL` = ifelse(eQTL_location_FBID == Affected_FBID, "cis", "trans")) %>%
    arrange(`Cis- or trans- eQTL`, Affected_FBID, eQTL) %>% as_tibble() %>%
    select(eQTL, `Cis- or trans- eQTL`, everything()) %>%
    rename_all(~ str_remove_all(.x, "_mashr_ED"))
}

eQTL_uv_females <- huang_eQTL_females %>% make_eQTL_overlap_table() 
eQTL_uv_females %>% kable_table()
eQTL Cis- or trans- eQTL Affected_FBID Affected_gene eQTL_location_FBID eQTL_location_gene beta_female_early beta_female_late beta_male_early beta_male_late LFSR_female_early LFSR_female_late LFSR_male_early LFSR_male_late
X_21274093_SNP cis FBgn0031176 what else FBgn0031176 what else -0.1333078 -0.1824160 -0.0611220 -0.0427285 0.0004122 0.0004200 0.0681336 0.0557023
2R_13997270_SNP trans FBgn0033458 uncharacterized protein FBgn0085225 uncharacterized protein -0.1299065 -0.1793745 -0.0840465 -0.0566265 0.0004116 0.0004148 0.0235637 0.0186034
3L_21605763_SNP trans FBgn0037105 S1P FBgn0261953 Transcription factor AP-2 0.1399953 0.1942367 0.0608650 0.0462437 0.0005357 0.0005106 0.0820276 0.0518360
eQTL_uv_males <- huang_eQTL_males %>% make_eQTL_overlap_table()
eQTL_uv_males %>% kable_table()
eQTL Cis- or trans- eQTL Affected_FBID Affected_gene eQTL_location_FBID eQTL_location_gene beta_female_early beta_female_late beta_male_early beta_male_late LFSR_female_early LFSR_female_late LFSR_male_early LFSR_male_late
2R_9134192_SNP cis FBgn0002789 Muscle protein 20 FBgn0002789 Muscle protein 20 0.1439750 0.2008961 0.1141324 0.0756790 0.0003439 0.0003443 0.0087368 0.0066229
X_21274093_SNP cis FBgn0031176 what else FBgn0031176 what else -0.1333078 -0.1824160 -0.0611220 -0.0427285 0.0004122 0.0004200 0.0681336 0.0557023
X_19894144_SNP trans FBgn0033697 Cyp6t3 FBgn0031082 uncharacterized protein -0.3578681 -0.4860429 -0.1268685 -0.0978162 0.0001314 0.0001304 0.0701469 0.0424578
3L_21605763_SNP trans FBgn0037105 S1P FBgn0261953 Transcription factor AP-2 0.1399953 0.1942367 0.0608650 0.0462437 0.0005357 0.0005106 0.0820276 0.0518360
3R_6527736_SNP trans FBgn0037822 uncharacterized protein FBgn0020385 pugilist -0.1281636 -0.1762774 -0.0759458 -0.0518217 0.0009473 0.0009594 0.0350998 0.0277776
3R_6528878_SNP trans FBgn0037822 uncharacterized protein FBgn0020385 pugilist 0.1437165 0.1984026 0.0932149 0.0619507 0.0001868 0.0001923 0.0164408 0.0137944
3R_6528878_SNP trans FBgn0037822 uncharacterized protein FBgn0051391 uncharacterized protein 0.1437165 0.1984026 0.0932149 0.0619507 0.0001868 0.0001923 0.0164408 0.0137944
3R_6532086_SNP trans FBgn0037822 uncharacterized protein FBgn0051467 uncharacterized protein -0.1297557 -0.1786540 -0.0561335 -0.0426859 0.0007140 0.0006844 0.0806250 0.0519942
3R_6532086_SNP trans FBgn0037822 uncharacterized protein FBgn0037824 uncharacterized protein -0.1297557 -0.1786540 -0.0561335 -0.0426859 0.0007140 0.0006844 0.0806250 0.0519942
3R_6540298_SNP trans FBgn0037822 uncharacterized protein FBgn0037827 uncharacterized protein -0.1397973 -0.1910744 -0.0533950 -0.0397492 0.0003836 0.0003840 0.0962945 0.0717692
3R_6528878_SNP trans FBgn0051344 uncharacterized protein FBgn0020385 pugilist 0.1437165 0.1984026 0.0932149 0.0619507 0.0001868 0.0001923 0.0164408 0.0137944
3R_6528878_SNP trans FBgn0051344 uncharacterized protein FBgn0051391 uncharacterized protein 0.1437165 0.1984026 0.0932149 0.0619507 0.0001868 0.0001923 0.0164408 0.0137944
2L_1218925_SNP trans FBgn0262944 long non-coding RNA:CR43263 FBgn0259229 uncharacterized protein -0.1232712 -0.1719202 -0.0879173 -0.0606464 0.0008857 0.0008480 0.0205153 0.0137868
2L_1218927_SNP trans FBgn0262944 long non-coding RNA:CR43263 FBgn0259229 uncharacterized protein -0.1232712 -0.1719202 -0.0879173 -0.0606464 0.0008857 0.0008480 0.0205153 0.0137868
3R_6858736_SNP trans XLOC_004644 NA FBgn0083950 sidestep VI -0.1423042 -0.1979479 -0.0391265 -0.0339783 0.0002255 0.0002115 0.1824399 0.1169837
3R_6859823_SNP trans XLOC_004644 NA FBgn0083950 sidestep VI -0.1309664 -0.1819359 -0.0173173 -0.0188698 0.0007034 0.0006829 0.3301192 0.2523757
X_4131416_SNP NA FBgn0032521 uncharacterized protein NA NA 0.1948985 0.2700297 0.1460801 0.0927518 0.0003243 0.0003421 0.0106182 0.0098071

Correlating our fitness measures to transcriptome data from Huang et al. 2015

Huang et al.’s microarray data was downloaded from the DGRP website.

Linear models to find transcripts that correlate with fitness across DGRP lines (“TWAS”)

Here, we perform a large number of simple linear regressions, and obtain the slope (beta or β) and its standard error from a regression of transcript i on fitness trait j. The number of regression run was 72,560, i.e. 4 fitness traits × 18,140 transcripts. We nickname this approach ‘TWAS’.

transcript_selection_analysis <- function(expression_data, phenotypes){
  
  if("block" %in% names(phenotypes)) phenotypes <- phenotypes %>% select(-block)
  
  expression_data <- expression_data %>% 
    filter(line %in% phenotypes$line)
  
  # Find line mean expression for each gene (average across the c. 2 replicate samples per line) 
  chunk_cols <- split(2:ncol(expression_data), ceiling(seq_along(2:ncol(expression_data)) / 500))
  
  mean_expression_data <- mclapply(1:2, function(i){  
    expression_data[, c(1, chunk_cols[[i]])] %>% 
      group_by(line) %>% 
      summarise_all(mean) %>% 
      ungroup()
  }) %>% bind_rows()

  # Scale each transcript's expression level so that mean is 0, and the variance is 1, across all the lines measured by Huang et al.
  for(i in 2:ncol(mean_expression_data)) mean_expression_data[,i] <- as.numeric(scale(mean_expression_data[,i]))
  
  # Join the microarray data with the phenotypes (i.e. our fitness data), and keep only the lines where we have both sets of measurements
  expression_data <- phenotypes %>% left_join(expression_data, by = "line")
  expression_data <- expression_data[complete.cases(expression_data), ] %>% select(-line)
  
  print("Data ready for analysis. Starting TWAS...")

  # Create chunks of transcript names, which will be used to facilitate parallel processing
  transcripts <- names(expression_data)[-c(1:4)]
  transcripts <- split(transcripts, ceiling(seq_along(transcripts) / 100))
  
  # Define a function to run 4 linear models, and get the beta and SE for regressions of expression level on the 4 fitness traits
  do_one_transcript <- function(transcript){
    expression_level <- expression_data %>% pull(!!transcript)
    FE <- summary(lm(female.fitness.early ~ expression_level, data = expression_data))$coefficients
    FL <- summary(lm(female.fitness.late ~ expression_level, data = expression_data))$coefficients
    ME <- summary(lm(male.fitness.early ~ expression_level, data = expression_data))$coefficients
    ML <- summary(lm(male.fitness.late ~ expression_level, data = expression_data))$coefficients
    c(FE[2,1], FL[2,1], ME[2,1], ML[2,1], FE[2,2], FL[2,2], ME[2,2], ML[2,2])
  }
  
  # Runs do_one_transcript() on all the transcripts listed in the vector 'transcripts'
  do_chunk_of_transcripts <- function(transcripts){
    output <- data.frame(transcripts, lapply(transcripts, do_one_transcript) %>% do.call("rbind", .))
    names(output) <- c("gene", "beta_FE", "beta_FL", "beta_ME", "beta_ML", "SE_FE", "SE_FL", "SE_ME", "SE_ML")
    output
  }
  
  # Run it all, in parallel
  transcripts %>% 
    mclapply(do_chunk_of_transcripts) %>% 
    do.call("rbind", .) %>% as_tibble() %>% mutate(gene = as.character(gene))
}

if(!file.exists("data/derived/TWAS/TWAS_result_males.csv")){

  TWAS_result_females <- load_expression_data("female") %>% transcript_selection_analysis(predicted_line_means) 
  TWAS_result_females %>% write_csv("data/derived/TWAS/TWAS_result_females.csv")
  TWAS_result_males <- load_expression_data("male") %>% transcript_selection_analysis(predicted_line_means)
  TWAS_result_males %>% write_csv("data/derived/TWAS/TWAS_result_males.csv")
} else {
  TWAS_result_females <- read_csv("data/derived/TWAS/TWAS_result_females.csv")
  TWAS_result_males <- read_csv("data/derived/TWAS/TWAS_result_males.csv")
}

Run mashr to adjust the TWAS results

This section re-uses the custom function run_mashr(). See the earlier script (where mashr was applied to the GWAS data) for the function definition. Essentially, run_mashr() helps us to run mashr twice, once using canonical and once using data-driven covariance matrices.

Similar to for the GWAS data, we use the canonical analysis to estimate the frequency of different types of transcripts (rather than loci), which we do for the entire transcriptome, as well as separately for each of the individual chromosome arms. We use the data-driven (“ED”) approach to derive the most accurate adjusted beta terms (i.e. the slope of the regression of transcript abundance on the phenotype of interest).

if(!file.exists("data/derived/TWAS/TWAS_ED.rds")){
  
  input_data <- data.frame(TWAS_result_females[,1:3], 
                           TWAS_result_males[,4:5], 
                           TWAS_result_females[,6:7], 
                           TWAS_result_males[,8:9])
  
  with_chrs <- input_data %>%
    left_join(tbl(db, "genes") %>% 
                select(FBID, chromosome) %>% 
                collect(), by = c("gene" = "FBID"))
  
  TWAS_canonical <- input_data %>% 
    run_mashr(mashr_mode = "canonical") 
  
  TWAS_canonical_2L <- with_chrs %>% 
    filter(chromosome == "2L") %>% select(-chromosome) %>%
    run_mashr(mashr_mode = "canonical") 
  
  TWAS_canonical_2R <- with_chrs %>% 
    filter(chromosome == "2R") %>% select(-chromosome) %>%
    run_mashr(mashr_mode = "canonical") 
  
  TWAS_canonical_3L <- with_chrs %>% 
    filter(chromosome == "3L") %>% select(-chromosome) %>%
    run_mashr(mashr_mode = "canonical") 
  
  TWAS_canonical_3R <- with_chrs %>% 
    filter(chromosome == "3R") %>% select(-chromosome) %>%
    run_mashr(mashr_mode = "canonical") 
  
  TWAS_canonical_X <- with_chrs %>% 
    filter(chromosome == "X") %>% select(-chromosome) %>%
    run_mashr(mashr_mode = "canonical") 
  
  saveRDS(TWAS_canonical, "data/derived/TWAS/TWAS_canonical.rds")
  saveRDS(TWAS_canonical_2L, "data/derived/TWAS/TWAS_canonical_2L.rds")
  saveRDS(TWAS_canonical_2R, "data/derived/TWAS/TWAS_canonical_2R.rds")
  saveRDS(TWAS_canonical_3L, "data/derived/TWAS/TWAS_canonical_3L.rds")
  saveRDS(TWAS_canonical_3R, "data/derived/TWAS/TWAS_canonical_3R.rds")
  saveRDS(TWAS_canonical_X, "data/derived/TWAS/TWAS_canonical_X.rds")
  
  TWAS_ED <- input_data %>% 
    run_mashr(mashr_mode = "ED", 
              ED_p_cutoff = 0.4) 
  saveRDS(TWAS_ED, "data/derived/TWAS/TWAS_ED.rds")
} else {
  TWAS_canonical <- readRDS("data/derived/TWAS/TWAS_canonical.rds")
  TWAS_ED <- readRDS("data/derived/TWAS/TWAS_ED.rds")
}

TWAS_mashr_results <- 
  data.frame(
    FBID = read_delim("data/input/huang_transcriptome/dgrp.array.exp.female.txt", delim = " ") %>% pull(gene),
    as.data.frame(get_pm(TWAS_canonical)) %>% rename_all(~str_c("canonical_", .)),
    as.data.frame(get_lfsr(TWAS_canonical)) %>% 
      rename_all(~str_replace_all(., "beta", "LFSR")) %>% rename_all(~str_c("canonical_", .))) %>% 
  as_tibble() %>% 
  bind_cols(
    data.frame(
      as.data.frame(get_pm(TWAS_ED)) %>% rename_all(~str_c("ED_", .)),
      as.data.frame(get_lfsr(TWAS_ED)) %>% 
        rename_all(~str_replace_all(., "beta", "LFSR")) %>% rename_all(~str_c("ED_", .))) %>% 
      as_tibble()) 


# get_innocenti_morrow_index <- function(s1, s2) (s1 * s2) / sqrt((s1^2 + s2^2) / 2)
# TWAS_ED_antagonism_effects <- data.frame(
#   FBID = read_delim("data/input/huang_transcriptome/dgrp.array.exp.female.txt", delim = " ") %>% pull(gene),
#   as.data.frame(get_pm(TWAS_ED)) %>%
#   mutate(SA_young  = get_innocenti_morrow_index(beta_FE, beta_ME),
#          SA_old    = get_innocenti_morrow_index(beta_FL, beta_ML),
#          AA_female = get_innocenti_morrow_index(beta_FE, beta_FL),
#          AA_male   = get_innocenti_morrow_index(beta_ME, beta_ML))) %>% as_tibble()

Find mixture probabilities for each transcript

This uses the canonical analysis’ classifications. Each transcript gets a posterior probability that it belongs to the i’th mixture component – only the mixture components that are not very rare are included. These are: equal_effects (i.e. the transcript is predicted to affect all 4 phenotypes equally), female-specific and male-specific (i.e. an effect on females/males only, which is concordant across age categories), sexually antagonistic (again, regardless of age), and null (note: the prior for mashr was that null transcripts are 10× more common than any other type).

# Get the mixture weights, as advised by mashr authors here: https://github.com/stephenslab/mashr/issues/68
posterior_weights_cov <- TWAS_canonical$posterior_weights 
colnames(posterior_weights_cov) <- sapply(
  str_split(colnames(posterior_weights_cov), '\\.'), 
  function(x) {
    if(length(x) == 1) return(x)
    else if(length(x) == 2) return(x[1])
    else if(length(x) == 3) return(paste(x[1], x[2], sep = "."))
  })
posterior_weights_cov <- t(rowsum(t(posterior_weights_cov), 
                                  colnames(posterior_weights_cov)))

# Make a neat dataframe
TWAS_mixture_assignment_probabilities <- data.frame(
  FBID = TWAS_mashr_results$FBID,
  posterior_weights_cov,
  stringsAsFactors = FALSE
) %>% as_tibble() %>%
  rename(P_equal_effects = equal_effects,
         P_female_specific = Female_specific_1,
         P_male_specific = Male_specific_1,
         P_null = null,
         P_sex_antag = Sex_antag_0.25)

TWAS_mixture_assignment_probabilities <- TWAS_mixture_assignment_probabilities %>%
  left_join(huang_heritability, by = "FBID")

saveRDS(TWAS_mixture_assignment_probabilities, 
        "data/derived/TWAS/TWAS_mixture_assignment_probabilities.rds")

Identify significantly antagonistic and concordant transcripts

Here, we define significantly antagonistic transcripts as those where the relationship with fitness is significantly positive for one sex or age class and significantly negative for the other. Similarly, we define significantly concordant transcripts as those where the relationship with fitness is significantly positive for one sex or age class and also significantly positive for the other. This is quite conservative, because a transcript has to have a LFSR < 0.05 for two tests, giving two chances for a ‘false negative’ error.

get_sig <- function(TWAS_mashr){
  FBIDs <- TWAS_result_females$gene
  significant <- ifelse(get_lfsr(TWAS_mashr) < 0.05, 1, 0) %>% as.data.frame()
  positive <- ifelse(get_pm(TWAS_mashr) > 0, 1, 0) %>% as.data.frame()
  sig_SA_early <- which((positive$beta_FE != positive$beta_ME) & (significant$beta_FE==1 & significant$beta_ME==1))
  sig_SA_late <-  which((positive$beta_FL != positive$beta_ML) & (significant$beta_FL==1 & significant$beta_ML==1))
  sig_AA_females <- which((positive$beta_FE != positive$beta_FL) & (significant$beta_FE==1 & significant$beta_FL==1))
  sig_AA_males <-   which((positive$beta_ME != positive$beta_ML) & (significant$beta_ME==1 & significant$beta_ML==1))
  
  sig_SC_early <- which((positive$beta_FE == positive$beta_ME) & (significant$beta_FE==1 & significant$beta_ME==1))
  sig_SC_late <-  which((positive$beta_FL == positive$beta_ML) & (significant$beta_FL==1 & significant$beta_ML==1))
  sig_AC_females <- which((positive$beta_FE == positive$beta_FL) & (significant$beta_FE==1 & significant$beta_FL==1))
  sig_AC_males <-   which((positive$beta_ME == positive$beta_ML) & (significant$beta_ME==1 & significant$beta_ML==1))
  
  helper <- function(sigs){
    x <- get(sigs)
    if(length(x) > 0) x <- data.frame(type = sigs, 
                                      FBID = FBIDs[x], 
                                      get_pm(TWAS_mashr)[x, ])
    else x <- NULL
    x
  }

  bind_rows(
    helper("sig_SA_early"), helper("sig_SA_late"), helper("sig_AA_females"), helper("sig_AA_males"),
    helper("sig_SC_early"), helper("sig_SC_late"), helper("sig_AC_females"), helper("sig_AC_males")) %>%
    mutate(type = as.character(type))
}

sig_transcripts_table <- get_sig(TWAS_ED) %>%
  left_join(tbl(db, "genes") %>% collect(), by = "FBID") %>%
  left_join(sex_bias_in_expression, by = "FBID") %>%
  left_join(TWAS_mixture_assignment_probabilities, by = "FBID") %>%
  mutate(across(where(is.numeric), ~ round(.x, 2))) %>%
  as_tibble() %>%
  distinct()

sig_transcripts_table %>%
  write_csv("data/derived/TWAS/sig_transcripts_table.csv")

sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.7

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
[1] parallel  stats     graphics  grDevices utils     datasets  methods  
[8] base     

other attached packages:
 [1] mashr_0.2.38       ashr_2.2-47        DT_0.13            kableExtra_1.1.0  
 [5] future.apply_1.5.0 future_1.17.0      glue_1.4.2         forcats_0.5.0     
 [9] stringr_1.4.0      dplyr_1.0.0        purrr_0.3.4        readr_1.3.1       
[13] tidyr_1.1.0        tibble_3.0.1       ggplot2_3.3.2      tidyverse_1.3.0   
[17] edgeR_3.30.1       limma_3.44.1      

loaded via a namespace (and not attached):
 [1] nlme_3.1-149      fs_1.4.1          bit64_0.9-7       lubridate_1.7.8  
 [5] webshot_0.5.2     httr_1.4.1        rprojroot_1.3-2   tools_4.0.3      
 [9] backports_1.1.7   R6_2.4.1          irlba_2.3.3       rmeta_3.0        
[13] DBI_1.1.0         colorspace_1.4-1  withr_2.2.0       tidyselect_1.1.0 
[17] bit_1.1-15.2      compiler_4.0.3    git2r_0.27.1      cli_2.0.2        
[21] rvest_0.3.5       xml2_1.3.2        scales_1.1.1      SQUAREM_2020.2   
[25] mvtnorm_1.1-0     mixsqp_0.3-43     digest_0.6.25     rmarkdown_2.5    
[29] pkgconfig_2.0.3   htmltools_0.5.0   highr_0.8         dbplyr_1.4.4     
[33] invgamma_1.1      htmlwidgets_1.5.1 rlang_0.4.6       readxl_1.3.1     
[37] RSQLite_2.2.0     rstudioapi_0.11   generics_0.0.2    jsonlite_1.7.0   
[41] magrittr_2.0.1    Matrix_1.2-18     Rcpp_1.0.4.6      munsell_0.5.0    
[45] fansi_0.4.1       abind_1.4-5       lifecycle_0.2.0   stringi_1.5.3    
[49] whisker_0.4       yaml_2.2.1        plyr_1.8.6        grid_4.0.3       
[53] blob_1.2.1        listenv_0.8.0     promises_1.1.0    crayon_1.3.4     
[57] lattice_0.20-41   haven_2.3.1       hms_0.5.3         locfit_1.5-9.4   
[61] knitr_1.30        pillar_1.4.4      codetools_0.2-16  reprex_0.3.0     
[65] evaluate_0.14     modelr_0.1.8      vctrs_0.3.0       httpuv_1.5.3.1   
[69] cellranger_1.1.0  gtable_0.3.0      assertthat_0.2.1  xfun_0.19        
[73] broom_0.5.6       later_1.0.0       viridisLite_0.3.0 truncnorm_1.0-8  
[77] memoise_1.1.0     workflowr_1.6.2   globals_0.12.5    ellipsis_0.3.1