Load the required packages:
library(tidyverse)
library(glue)
library(pheatmap)
library(viridis)
library(SingleCellExperiment)Global parameters:
result_dir <- file.path("..", "sirv_analysis", "report_data")
sample_ids <- "cdna"Prepare reference data:
annotations_correct_df <- readRDS(file.path(
result_dir, "annotations_correct.rds"
))$tx_df
correct_ref_tx_ids <- annotations_correct_df$compatible_tx %>%
strsplit(",") %>%
unlist() %>%
sort()Prepare Isosceles TPM data:
isosceles_tpm_list <- lapply(sample_ids, function(sample_id) {
se_transcript <- readRDS(file.path(
result_dir, glue("isosceles_{sample_id}_over_se_transcript.rds")
))
tx_df <- as.data.frame(rowData(se_transcript))
tpm_values <- assay(se_transcript, "tpm")[, 1]
names(tpm_values) <- sapply(strsplit(tx_df$compatible_tx, ","), "[", 1)
return(tpm_values)
})
names(isosceles_tpm_list) <- paste0("Isosceles.", sample_ids)
isosceles_correct_tpm_list <- lapply(isosceles_tpm_list, function(tpms) {
tpms[names(tpms) %in% correct_ref_tx_ids]
})
isosceles_fractions <- sapply(isosceles_correct_tpm_list, sum) / sapply(isosceles_tpm_list, sum)Prepare IsoQuant TPM data:
isoquant_tpm_list <- lapply(sample_ids, function(sample_id) {
tx_df <- read_delim(file.path(
result_dir, glue("isoquant_{sample_id}_over_transcript_tpm.tsv")
))
tpm_values <- tx_df$TPM
names(tpm_values) <- tx_df$`#feature_id`
return(tpm_values)
})
names(isoquant_tpm_list) <- paste0("IsoQuant.", sample_ids)
isoquant_correct_tpm_list <- lapply(isoquant_tpm_list, function(tpms) {
tpms[names(tpms) %in% correct_ref_tx_ids]
})
isoquant_fractions <- sapply(isoquant_correct_tpm_list, sum) / sapply(isoquant_tpm_list, sum)Prepare bambu TPM data:
bambu_tpm_list <- lapply(sample_ids, function(sample_id) {
tx_df <- read_delim(file.path(
result_dir, glue("bambu_{sample_id}_over_counts_transcript.txt")
))
tpm_values <- tx_df[, 3, drop = TRUE]
tpm_values <- tpm_values / sum(tpm_values) * 1e6
names(tpm_values) <- tx_df$TXNAME
return(tpm_values)
})
names(bambu_tpm_list) <- paste0("bambu.", sample_ids)
bambu_correct_tpm_list <- lapply(bambu_tpm_list, function(tpms) {
tpms[names(tpms) %in% correct_ref_tx_ids]
})
bambu_fractions <- sapply(bambu_correct_tpm_list, sum) / sapply(bambu_tpm_list, sum)Plot fractions of TPMs from correct transcripts:
plot_df <- data.frame(
tool = c("Isosceles", "IsoQuant", "Bambu"),
value = c(
isosceles_fractions["Isosceles.cdna"],
isoquant_fractions["IsoQuant.cdna"],
bambu_fractions["bambu.cdna"]
)
)
plot_df$tool <- fct_reorder(plot_df$tool, plot_df$value)
ggplot(plot_df, mapping = aes(x = value,
y = tool,
fill = tool)) +
geom_col() +
geom_text(
aes(label = format(round(value, 2), nsmall = 2)),
size = 3,
nudge_x = 0.03,
hjust = "outward"
) +
scale_fill_manual(values = c(Bambu = "mediumseagreen",
Isosceles = "black",
IsoQuant = "gold")) +
lims(x = c(0, 1.1)) +
labs(
x = "Read precision (expression from correct transcripts)",
y = ""
) +
theme_classic() +
theme(legend.position = "none",
axis.text = element_text(size = 7),
axis.title.y = element_blank(),
axis.title.x = element_text(size = 8),
axis.text.x = element_blank(),
axis.ticks.x = element_blank())Prepare reference data:
annotations_correct_df <- readRDS(file.path(
result_dir, "annotations_correct.rds"
))$tx_df
annotations_insufficient_df <- readRDS(file.path(
result_dir, "annotations_insufficient.rds"
))$tx_df
correct_intron_positions <- annotations_correct_df$intron_positions
correct_intron_positions <- unique(correct_intron_positions[
!is.na(correct_intron_positions)
])
insufficient_intron_positions <- annotations_insufficient_df$intron_positions
insufficient_intron_positions <- unique(insufficient_intron_positions[
!is.na(insufficient_intron_positions)
])Helper functions:
precision <- function(intron_positions) {
TP <- sum(intron_positions %in% correct_intron_positions)
FP <- sum(!intron_positions %in% correct_intron_positions)
return(TP / (FP + TP))
}
recall <- function(intron_positions) {
TP <- sum(intron_positions %in% correct_intron_positions)
P <- length(correct_intron_positions)
return(TP / P)
}
f1_score <- function(intron_positions) {
TP <- sum(intron_positions %in% correct_intron_positions)
FP <- sum(!intron_positions %in% correct_intron_positions)
P <- length(correct_intron_positions)
FN <- P - TP
return(2 * TP / (2*TP + FP + FN))
}
classify_tx <- function(intron_positions) {
return(c(
TP = sum(intron_positions %in% correct_intron_positions),
TP_KNOWN = sum(intron_positions %in% insufficient_intron_positions),
TP_NOVEL = sum(
(intron_positions %in% correct_intron_positions) &
!(intron_positions %in% insufficient_intron_positions)
),
FN = length(setdiff(correct_intron_positions, intron_positions)),
FN_KNOWN = length(setdiff(
insufficient_intron_positions, intron_positions
)),
FN_NOVEL = length(setdiff(
setdiff(correct_intron_positions, insufficient_intron_positions),
intron_positions
)),
FP = sum(!intron_positions %in% correct_intron_positions)
))
}Prepare Isosceles intron position data:
isosceles_intron_list <- lapply(sample_ids, function(sample_id) {
se_transcript <- readRDS(file.path(
result_dir, glue("isosceles_{sample_id}_insufficient_se_transcript.rds")
))
tpm_values <- assay(se_transcript, "tpm")[, 1]
se_transcript <- se_transcript[tpm_values > 0,]
intron_positions <- rowData(se_transcript)$intron_positions
intron_positions <- unique(intron_positions[!is.na(intron_positions)])
return(intron_positions)
})
names(isosceles_intron_list) <- paste0("Isosceles.", sample_ids)Prepare IsoQuant intron position data:
isoquant_intron_list <- lapply(sample_ids, function(sample_id) {
splicing_df <- Isosceles:::prepare_reference_annotations(file.path(
result_dir, glue("isoquant_{sample_id}_insufficient_extended_annotations.gtf")
))$splicing_df
tpm_df <- read_delim(file.path(
result_dir, glue("isoquant_{sample_id}_insufficient_transcript_tpm.tsv")
))
tpm_df <- tpm_df[tpm_df$TPM > 0,]
expressed_tx_ids <- tpm_df[, 1, drop = TRUE]
tpm_selector <- sapply(strsplit(splicing_df$compatible_tx, ","),
function(x) {any(x %in% expressed_tx_ids)})
splicing_df <- splicing_df[tpm_selector,]
intron_positions <- splicing_df$intron_positions
return(intron_positions)
})
names(isoquant_intron_list) <- paste0("IsoQuant.", sample_ids)Prepare bambu intron position data:
bambu_intron_list <- lapply(sample_ids, function(sample_id) {
splicing_df <- Isosceles:::prepare_reference_annotations(file.path(
result_dir, glue("bambu_{sample_id}_insufficient_extended_annotations.gtf")
))$splicing_df
count_df <- read_delim(file.path(
result_dir, glue("bambu_{sample_id}_insufficient_counts_transcript.txt")
))
count_df <- count_df[count_df[, 3, drop = TRUE] > 0,]
expressed_tx_ids <- count_df$TXNAME
count_selector <- sapply(strsplit(splicing_df$compatible_tx, ","),
function(x) {any(x %in% expressed_tx_ids)})
splicing_df <- splicing_df[count_selector,]
intron_positions <- splicing_df$intron_positions
return(intron_positions)
})
names(bambu_intron_list) <- paste0("bambu.", sample_ids)Plot transcript detection metrics:
tools <- c("Isosceles", "IsoQuant", "Bambu")
plot_df <- data.frame(
tool = rep(tools, each = 3),
metric = rep(c("Precision", "Recall", "F1"), 3),
value = c(
precision(isosceles_intron_list[["Isosceles.cdna"]]),
recall(isosceles_intron_list[["Isosceles.cdna"]]),
f1_score(isosceles_intron_list[["Isosceles.cdna"]]),
precision(isoquant_intron_list[["IsoQuant.cdna"]]),
recall(isoquant_intron_list[["IsoQuant.cdna"]]),
f1_score(isoquant_intron_list[["IsoQuant.cdna"]]),
precision(bambu_intron_list[["bambu.cdna"]]),
recall(bambu_intron_list[["bambu.cdna"]]),
f1_score(bambu_intron_list[["bambu.cdna"]])
)
)
plot_df$tool <- fct_reorder(plot_df$tool, plot_df$value)
plot_df$metric <- fct_rev(factor(
plot_df$metric, levels = c("Precision", "Recall", "F1")
))
ggplot(plot_df, mapping = aes(x = value,
y = metric,
fill = tool)) +
geom_col(position = position_dodge2()) +
geom_text(
aes(label = format(round(value, 2), nsmall = 2)),
position = position_dodge2(width = .9),
size = 3,
hjust = -0.3
) +
lims(x = c(0, 1.1)) +
scale_fill_manual(values = c(Isosceles = "black",
Bambu = "mediumseagreen",
IsoQuant = "gold")) +
theme_classic() +
theme(legend.title = element_blank(),
legend.position = "top",
legend.key.size = unit(0.3, "cm"),
legend.text = element_text(size = 7),
axis.text = element_text(size = 7),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank())Transcript detection results:
classification_df <- data.frame(
Isosceles = classify_tx(isosceles_intron_list[["Isosceles.cdna"]]),
IsoQuant = classify_tx(isoquant_intron_list[["IsoQuant.cdna"]]),
Bambu = classify_tx(bambu_intron_list[["bambu.cdna"]])
)
classification_dfPlot transcript detection results:
plot_df <- classification_df
plot_df$metric <- rownames(plot_df)
plot_df <- plot_df %>%
pivot_longer(-metric, names_to = "tool", values_to = "value") %>%
filter(metric %in% c("TP_KNOWN", "TP_NOVEL", "FP", "FN_KNOWN", "FN_NOVEL"))
plot_df$metric <- fct_rev(factor(
plot_df$metric,
levels = c(c("TP_KNOWN", "TP_NOVEL", "FN_KNOWN", "FN_NOVEL", "FP"))
))
plot_df$tool <- paste0(
plot_df$tool, " ", ifelse(grepl("^TP", plot_df$metric), "TP", "FP/FN")
)
ggplot(plot_df, mapping = aes(x = value,
y = tool,
fill = metric)) +
geom_col() +
scale_fill_manual(values = c(TP_KNOWN = "darkgreen",
TP_NOVEL = "mediumseagreen",
FN_KNOWN = "royalblue4",
FN_NOVEL = "cornflowerblue",
FP = "darkred")) +
theme_classic() +
theme(legend.title = element_blank(),
legend.position = "top",
legend.key.size = unit(0.3, "cm"),
legend.text = element_text(size = 5),
axis.text = element_text(size = 7),
axis.title.x = element_blank(),
axis.title.y = element_blank())sessionInfo()## R version 4.2.1 (2022-06-23)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 20.04.4 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/liblapack.so.3
##
## locale:
## [1] C
##
## attached base packages:
## [1] stats4 stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] SingleCellExperiment_1.18.1 SummarizedExperiment_1.26.1
## [3] Biobase_2.56.0 GenomicRanges_1.48.0
## [5] GenomeInfoDb_1.32.4 IRanges_2.30.1
## [7] S4Vectors_0.34.0 BiocGenerics_0.42.0
## [9] MatrixGenerics_1.8.1 matrixStats_0.62.0
## [11] viridis_0.6.2 viridisLite_0.4.1
## [13] pheatmap_1.0.12 glue_1.6.2
## [15] forcats_0.5.2 stringr_1.4.1
## [17] dplyr_1.0.10 purrr_0.3.5
## [19] readr_2.1.3 tidyr_1.2.1
## [21] tibble_3.1.8 ggplot2_3.3.6
## [23] tidyverse_1.3.2
##
## loaded via a namespace (and not attached):
## [1] googledrive_2.0.0 colorspace_2.0-3 rjson_0.2.21
## [4] ellipsis_0.3.2 XVector_0.36.0 fs_1.5.2
## [7] farver_2.1.1 bit64_4.0.5 AnnotationDbi_1.58.0
## [10] fansi_1.0.3 lubridate_1.8.0 xml2_1.3.3
## [13] codetools_0.2-18 cachem_1.0.6 knitr_1.40
## [16] jsonlite_1.8.3 Rsamtools_2.12.0 broom_1.0.1
## [19] dbplyr_2.2.1 png_0.1-7 compiler_4.2.1
## [22] httr_1.4.4 backports_1.4.1 assertthat_0.2.1
## [25] Matrix_1.5-1 fastmap_1.1.0 gargle_1.2.1
## [28] cli_3.4.1 htmltools_0.5.3 prettyunits_1.1.1
## [31] tools_4.2.1 igraph_1.3.5 gtable_0.3.1
## [34] GenomeInfoDbData_1.2.8 rappdirs_0.3.3 Rcpp_1.0.9
## [37] cellranger_1.1.0 jquerylib_0.1.4 vctrs_0.5.0
## [40] Biostrings_2.64.1 rtracklayer_1.56.1 xfun_0.34
## [43] rvest_1.0.3 lifecycle_1.0.3 restfulr_0.0.15
## [46] XML_3.99-0.12 googlesheets4_1.0.1 zlibbioc_1.42.0
## [49] scales_1.2.1 vroom_1.6.0 hms_1.1.2
## [52] parallel_4.2.1 RColorBrewer_1.1-3 yaml_2.3.6
## [55] curl_4.3.3 memoise_2.0.1 gridExtra_2.3
## [58] sass_0.4.2 biomaRt_2.52.0 stringi_1.7.8
## [61] RSQLite_2.2.18 highr_0.9 BiocIO_1.6.0
## [64] Isosceles_0.2.0 GenomicFeatures_1.48.4 filelock_1.0.2
## [67] BiocParallel_1.30.4 rlang_1.0.6 pkgconfig_2.0.3
## [70] bitops_1.0-7 evaluate_0.17 lattice_0.20-45
## [73] GenomicAlignments_1.32.1 labeling_0.4.2 bit_4.0.4
## [76] tidyselect_1.2.0 magrittr_2.0.3 R6_2.5.1
## [79] generics_0.1.3 DelayedArray_0.22.0 DBI_1.1.3
## [82] pillar_1.8.1 haven_2.5.1 withr_2.5.0
## [85] KEGGREST_1.36.3 RCurl_1.98-1.9 modelr_0.1.9
## [88] crayon_1.5.2 utf8_1.2.2 BiocFileCache_2.4.0
## [91] tzdb_0.3.0 rmarkdown_2.17 progress_1.2.2
## [94] grid_4.2.1 readxl_1.4.1 blob_1.2.3
## [97] reprex_2.0.2 digest_0.6.30 munsell_0.5.0
## [100] bslib_0.4.0