BioinformaticsDashboard / BioinformaticsDashboardv0.0..Rmd
TheBobBob's picture
Update BioinformaticsDashboardv0.0..Rmd
966efc7 verified
raw
history blame
34.6 kB
---
title: "Bioinformatics Dashboard v0.0 🧬 🦠 🧫"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
if (!requireNamespace("pacman", quietly = TRUE)) {
install.packages("pacman")
}
pacman::p_load(flexdashboard, shiny, ggplot2, plotly, clusterProfiler, readxl, tidyverse, DESeq2, biomaRt, tidyr, shinyjs, rentrez, dplyr, ggtext, cowplot, UpSetR)
library(flexdashboard)
library(shiny)
library(ggplot2)
library(plotly)
library(clusterProfiler)
library(readxl)
library(tidyverse)
library(DESeq2)
library(biomaRt)
library(tidyr)
library(shinyjs)
library(rentrez)
library(dplyr)
library(ggtext)
library(cowplot)
library(UpSetR)
```
Column {.tabset}
-----------------------------------------------------------------------
### RNAseq analysis
Analyzes RNAseq data using DESeq2 and GSEA. Visualizes using volcano plot, and other plots to show the GSEA analysis results. Please make sure the uploaded data is in xlsx format, has the first column with the gene names, and there is an even number of data columns. The control condition should be first, the mutant condition second.
```{r}
ui <- fluidPage(
titlePanel("Interactive Volcano Plot with Gene and GO Term Search"),
useShinyjs(),
passwordInput("password", "Enter Password:", value = "", placeholder = "Password"),
actionButton("submit_password", "Submit"),
uiOutput("main_ui"),
#if you define a side_ui --> absolute panel, it would have to be defined here
)
# Server logic
server <- function(input, output, session) {
# Password handling
correct_password <- "my_secret_password"
observeEvent(input$submit_password, {
if (input$password == correct_password) {
showModal(modalDialog(
title = "Access Granted",
"Welcome! You can now search for genes and view the volcano plot.",
easyClose = TRUE,
footer = NULL
))
# Hide the password input and button after validation
shinyjs::hide("password")
shinyjs::hide("submit_password")
# Main UI appears after password is correct
output$main_ui <- renderUI({
sidebarLayout(
sidebarPanel(
fluidRow(
fileInput("file", "Choose XLSX File", multiple = FALSE, accept = c(".xlsx", "text/xlsx")),
actionButton("analyze_button", "Analyze"),
tags$hr(),
textInput("gene_search", "Search for a gene or keyword (separate multiple genes with ';'):", ""),
actionButton("search_gene", "Search Gene"),
tags$hr(),
selectInput("GO_search", "Select a GO term:", choices = NULL),
actionButton("search_GO_term", "Search GO Term"),
tags$hr(),
selectInput("description_search", "Search for the name of a pathway:", choices = NULL),
actionButton("search_description", "Search Description"),
tags$hr(),
sliderInput("pvalue", "P-value: ",
min = 0, max = 1,
value = 0.01, step = 0.00001),
tags$hr(),
sliderInput("log2fc", "Log2FoldChange: ",
min = 0.0001, max = 100,
value = 2.5, step = 0.05),
tags$hr(),
actionButton("visualize_gse", "Visualize the GSEGO Results:")
)
),
mainPanel(
plotlyOutput("volcanoPlot"),
plotOutput("dotPlotTitle", width = "100%", height = "100px"),
plotOutput("dotPlot", width = "100%", height = "1000px"),
plotOutput("conceptNetworkTitle", width = "100%", height = "100px"),
plotOutput("conceptNetwork", width = "100%", height = "600px"),
plotOutput("heatMapTitle", width = "100%", height = "100px"),
plotOutput("heatMap", width = "100%", height = "400px"),
plotOutput("upsetPlotTitle", width = "100%", height = "100px"),
plotOutput("upsetPlot", width = "100%", height = "1000px"),
plotOutput("pubmedPathwayPlotTitle", width = "100%", height = "100px"),
plotOutput("pubmedPathwayPlot", width = "100%", height = "1500px")
)
)
})
# Reactive values to store results and search criteria
searchValues <- reactiveValues(
gene_search = "",
GO_search = "All",
description_search = "",
df_inverted = NULL # Store df_inverted here
)
# Process uploaded file and perform DESeq2 analysis
observeEvent(input$analyze_button, {
req(input$file) # Ensure a file is uploaded
# Read in gene counts data
genecounts <- tryCatch({
read_excel(input$file$datapath, sheet = 1, col_names = TRUE)
}, error = function(e) {
showModal(modalDialog(title = "Error", "Could not read the Excel file.", easyClose = TRUE))
return(NULL)
})
if (is.null(genecounts)) return(NULL) # Stop further processing if reading failed
genecounts <- as.data.frame(genecounts)
rownames(genecounts) <- genecounts[, 1]
genecounts$Gene_Name <- NULL
genecounts <- genecounts[, -1]
num_samples <- ncol(genecounts)
# Check if the number of samples is even
if (num_samples %% 2 != 0) {
showModal(modalDialog(
title = "Error",
"The number of samples must be even for proper grouping.",
easyClose = TRUE
))
return(NULL)
}
# Create the condition data frame
condition <- data.frame(genotype = rep(c('C', 'R'), each = num_samples / 2), row.names = colnames(genecounts))
# Create DESeq2 dataset
dds <- DESeqDataSetFromMatrix(countData = genecounts, colData = condition, design = ~genotype)
de <- DESeq(dds)
res_reactive <- reactiveVal()
res_reactive(results(de))
res <<- results(de)
# Create additional columns for plotting
res$pvalue_log10 <- -log10(res$pvalue)
pvalue_threshold <- 0.05
fold_change_threshold <- 2
res$significance <- ifelse(res$pvalue < pvalue_threshold, "Significant", "Not Significant")
res$new_column <- rownames(res)
res$diffexpressed <- ifelse(res$log2FoldChange > 0, "UP", ifelse(res$log2FoldChange < 0, "DOWN", "NO_CHANGE"))
# Generate gene list for GSEA
organism = "org.Hs.eg.db"
original_gene_list <- res$log2FoldChange
names(original_gene_list) <- res$new_column
gene_list <<- na.omit(original_gene_list)
gene_list = sort(gene_list, decreasing = TRUE)
# Perform GO enrichment analysis
gse <<- gseGO(geneList = gene_list,
ont = "ALL",
keyType = "SYMBOL",
minGSSize = 3,
maxGSSize = 800,
pvalueCutoff = 0.05,
verbose = TRUE,
OrgDb = organism,
pAdjustMethod = "none")
# Store inverted results for GO terms in reactive values
searchValues$df_inverted <- gse@result %>% separate_rows(core_enrichment, sep = "/")
# Update GO term and description choices in UI
updateSelectInput(session, "GO_search", choices = unique(searchValues$df_inverted$ID))
updateSelectInput(session, "description_search", choices = unique(searchValues$df_inverted$Description))
# Reactive filtering of results based on user input
filteredRes <- reactive({
data <- as.data.frame(res)
# Apply gene search filter
if (searchValues$gene_search != "") {
genes <- strsplit(searchValues$gene_search, ";")[[1]]
genes <- trimws(genes)
data <- data %>%
filter(rowSums(sapply(genes, function(gene) grepl(gene, new_column, ignore.case = TRUE))) > 0)
}
# Apply GO term filter
if (searchValues$GO_search != "All") {
selected_genes <- searchValues$df_inverted %>%
filter(ID == searchValues$GO_search) %>%
pull(core_enrichment)
data <- data %>%
filter(new_column %in% selected_genes)
}
# Apply description search filter
if (searchValues$description_search != "") {
selected_genes <- searchValues$df_inverted %>%
filter(Description == searchValues$description_search) %>%
pull(core_enrichment)
data <- data %>%
filter(new_column %in% selected_genes)
}
data
})
# Render volcano plot based on filtered results
output$volcanoPlot <- renderPlotly({
data_res <- filteredRes()
p_value <- input$pvalue #need to add slides here
log2fc <- input$log2fc #need to add slider here
p <- ggplot(data_res, aes(x = log2FoldChange, y = pvalue_log10,
text = paste("Gene:", new_column, "<br>Log2 Fold Change:", log2FoldChange,
"<br>P-value:", pvalue, "<br>Significance:", significance,
"<br>Differentially Expressed:", diffexpressed, "<br>-log10 Values:", pvalue_log10))) +
geom_point(aes(color = log2FoldChange, shape = diffexpressed)) +
geom_hline(yintercept = -log10(p_value), linetype = "dotted", color = "red") +
geom_vline(xintercept = c(-log2fc, log2fc), linetype = "dotted", color = "darkblue") +
xlim(-5, 5) +
xlab("Log2 Fold Change") +
ylab("-log10(P-value)") +
ggtitle("Volcano Plot") +
scale_color_gradient2(low = "green", mid = "pink", high = "blue", midpoint = 0,
name = "Log2 Fold Change") # Add a custom color scale for the color legends
ggplotly(p, tooltip = "text")
})
})
# Update search criteria based on user actions
observeEvent(input$search_gene, {
searchValues$gene_search <- input$gene_search
searchValues$GO_search <- "All"
searchValues$description_search <- ""
})
observeEvent(input$search_GO_term, {
searchValues$GO_search <- input$GO_search
searchValues$gene_search <- ""
searchValues$description_search <- ""
})
observeEvent(input$search_description, {
searchValues$description_search <- input$description_search
searchValues$GO_search <- "All"
searchValues$gene_search <- ""
})
observeEvent(input$visualize_gse, {
library(ggplot2)
library(ggtext)
library(gridExtra)
output$dotPlotTitle <- renderPlot({
txt <- "Dot Plot with 10 Pathways"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$dotPlot <- renderPlot({
dot_plot <- dotplot(gse, showCategory = 10)
print(dot_plot)
})
output$conceptNetworkTitle <- renderPlot({
txt <- "Gene Concept Network"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$conceptNetwork <- renderPlot({
gsex <- setReadable(gse, 'org.Hs.eg.db', 'ENTREZID')
geneList <- gse@geneList
p1 <- cnetplot(gsex, foldChange = geneList, max.overlaps = 100)
p2 <- cnetplot(gsex, categorySize = "pvalue", foldChange = geneList, max.overlaps = 100)
p3 <- cnetplot(gsex, foldChange = geneList, circular = TRUE, colorEdge = TRUE, max.overlaps = 100)
maingene_plot <- cowplot::plot_grid(p1, p2, p3, ncol = 3, labels = LETTERS[1:3], rel_widths = c(.8, .8, 1.2))
print(maingene_plot)
})
output$heatMapTitle <- renderPlot({
txt <- "Heatmap-Like Functional Classification"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$heatMap <- renderPlot({
gsex <- setReadable(gse, 'org.Hs.eg.db', 'ENTREZID')
geneList <- gse@geneList
p1 <- heatplot(gsex, showCategory=5)
p2 <- heatplot(gsex, foldChange=geneList, showCategory=5)
mainheatmap_plot <- cowplot::plot_grid(p1, p2, ncol=1, labels=LETTERS[1:2])
print(mainheatmap_plot)
})
output$upsetPlotTitle <- renderPlot({
txt <- "UpSet Plot"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$upsetPlot <- renderPlot({
gse_df <- gse@result
top_terms <- gse_df %>% arrange(pvalue) %>% head(10)
top_gene_sets <- strsplit(top_terms$core_enrichment, "/")
gene_sets_list <- lapply(top_gene_sets, function(x) unique(trimws(x)))
gene_sets_df <- fromList(setNames(gene_sets_list, top_terms$ID))
# Create the UpSet plot
upset_plot <- upset(gene_sets_df,
sets = names(gene_sets_df),
main.bar.color = "steelblue",
sets.bar.color = "darkred",
order.by = "freq",
matrix.color = "gray",
keep.order = TRUE)
print(upset_plot)
})
output$pubmedPathwayPlotTitle <- renderPlot({
txt <- "PubMed Pathway Enrichment"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$pubmedPathwayPlot <- renderPlot({
results <- data.frame(Term = character(), Year = integer(), Count = integer(), stringsAsFactors = FALSE)
terms <- tail(gse$Description, n = 10)
results <- data.frame()
titles_2024 <- data.frame()
for (term in terms) {
for (year in 2014:2024) {
query <- paste(term, "[Title/Abstract] AND", year, "[PDAT]")
# Count results for each term and year
search_results <- entrez_search(db = "pubmed", term = query, retmax = 0)
results <- rbind(results, data.frame(Term = term, Year = year, Count = search_results$count))
# If the year is 2024, retrieve the first 10 article titles
if (year == 2024) {
search_results_2024 <- entrez_search(db = "pubmed", term = query, retmax = 10)
if (search_results_2024$count > 0) {
article_ids <- search_results_2024$ids
articles <- entrez_fetch(db = "pubmed", id = article_ids, rettype = "abstract", retmode = "text")
titles <- sapply(strsplit(articles, "\n"), function(x) x[1])
titles_2024 <- reactive({rbind(titles_2024, data.frame(Term = term, Title = titles, stringsAsFactors = FALSE))})
}
}
}
}
total_counts <- results %>%
group_by(Year) %>%
summarize(Total_Count = sum(Count), .groups = 'drop')
results <- results %>%
left_join(total_counts, by = "Year")
results <- results %>%
mutate(Ratio = Count / Total_Count)
print(results)
mainpubmed_plot <- ggplot(results, aes(x = Year, y = Ratio, color = Term)) +
geom_line() +
geom_point(size = 3, shape = 20, fill = "white", stroke = 1) + # Bolded dots
scale_x_continuous(limits = c(2013, 2025), breaks = seq(2013, 2025, by = 2.5)) + # 2.5-year breaks
labs(title = "Publication Ratio for Enriched Terms", x = "Year", y = "Publication Ratio") +
theme_minimal()
print(mainpubmed_plot)
})
})
} else {
showModal(modalDialog(
title = "Access Denied",
"Incorrect password. Please try again.",
easyClose = TRUE,
footer = NULL
))
}
})
}
shinyApp(ui = ui, server = server)
```
### Proteomics analysis
Analyzes proteomics data using DESeq2 and GSEA. Visualizes using volcano plot, and other plots to show the GSEA analysis results. Please make sure the uploaded data is in xlsx format, has the first column with the gene names, and the second column has the expanded name of each gene and there is an even number of data columns. The control condition should be first, the mutant condition second.
```{r}
ui <- fluidPage(
titlePanel("Interactive Volcano Plot with Gene and GO Term Search"),
useShinyjs(),
passwordInput("password", "Enter Password:", value = "", placeholder = "Password"),
actionButton("submit_password", "Submit"),
uiOutput("main_ui"),
#if you define a side_ui --> absolute panel, it would have to be defined here
)
# Server logic
server <- function(input, output, session) {
# Password handling
correct_password <- "my_secret_password"
observeEvent(input$submit_password, {
if (input$password == correct_password) {
showModal(modalDialog(
title = "Access Granted",
"Welcome! You can now search for genes and view the volcano plot.",
easyClose = TRUE,
footer = NULL
))
# Hide the password input and button after validation
shinyjs::hide("password")
shinyjs::hide("submit_password")
# Main UI appears after password is correct
output$main_ui <- renderUI({
sidebarLayout(
sidebarPanel(
fluidRow(
fileInput("file", "Choose XLSX File", multiple = FALSE, accept = c(".xlsx", "text/xlsx")),
actionButton("analyze_button", "Analyze"),
tags$hr(),
textInput("gene_search", "Search for a gene or keyword (separate multiple genes with ';'):", ""),
actionButton("search_gene", "Search Gene"),
tags$hr(),
selectInput("GO_search", "Select a GO term:", choices = NULL),
actionButton("search_GO_term", "Search GO Term"),
tags$hr(),
selectInput("description_search", "Search for the name of a pathway:", choices = NULL),
actionButton("search_description", "Search Description"),
tags$hr(),
sliderInput("pvalue", "P-value: ",
min = 0, max = 1,
value = 0.01, step = 0.00001),
tags$hr(),
sliderInput("log2fc", "Log2FoldChange: ",
min = 0.0001, max = 100,
value = 2.5, step = 0.05),
tags$hr(),
actionButton("visualize_gse", "Visualize the GSEGO Results:")
)
),
mainPanel(
plotlyOutput("volcanoPlot"),
plotOutput("dotPlotTitle", width = "100%", height = "100px"),
plotOutput("dotPlot", width = "100%", height = "1000px"),
plotOutput("conceptNetworkTitle", width = "100%", height = "100px"),
plotOutput("conceptNetwork", width = "100%", height = "600px"),
plotOutput("heatMapTitle", width = "100%", height = "100px"),
plotOutput("heatMap", width = "100%", height = "400px"),
plotOutput("upsetPlotTitle", width = "100%", height = "100px"),
plotOutput("upsetPlot", width = "100%", height = "1000px"),
plotOutput("pubmedPathwayPlotTitle", width = "100%", height = "100px"),
plotOutput("pubmedPathwayPlot", width = "100%", height = "1500px")
)
)
})
# Reactive values to store results and search criteria
searchValues <- reactiveValues(
gene_search = "",
GO_search = "All",
description_search = "",
df_inverted = NULL # Store df_inverted here
)
# Process uploaded file and perform DESeq2 analysis
observeEvent(input$analyze_button, {
req(input$file) # Ensure a file is uploaded
# Read in gene counts data
genecounts <- tryCatch({
read_excel(input$file$datapath, sheet = 1, col_names = TRUE)
}, error = function(e) {
showModal(modalDialog(title = "Error", "Could not read the Excel file.", easyClose = TRUE))
return(NULL)
})
if (is.null(genecounts)) return(NULL) # Stop further processing if reading failed
genecounts <- as.data.frame(genecounts)
rownames(genecounts) <- genecounts[, 1]
genecounts <- genecounts[, -1]
descriptions <<- data.frame(Description = genecounts[, 1])
rownames(descriptions) <- rownames(genecounts)
genecounts <- genecounts[, -1]
num_samples <- ncol(genecounts)
num_samples <- ncol(genecounts)
# Check if the number of samples is even
if (num_samples %% 2 != 0) {
showModal(modalDialog(
title = "Error",
"The number of samples must be even for proper grouping.",
easyClose = TRUE
))
return(NULL)
}
# Create the condition data frame
condition <- data.frame(genotype = rep(c('C', 'R'), each = num_samples / 2), row.names = colnames(genecounts))
# Create DESeq2 dataset
dds <- DESeqDataSetFromMatrix(countData = genecounts, colData = condition, design = ~genotype)
de <- DESeq(dds)
res_reactive <- reactiveVal()
res_reactive(results(de))
res <<- results(de)
# Create additional columns for plotting
res$pvalue_log10 <- -log10(res$pvalue)
pvalue_threshold <- 0.05
fold_change_threshold <- 2
res$significance <- ifelse(res$pvalue < pvalue_threshold, "Significant", "Not Significant")
res$new_column <- rownames(res)
res$diffexpressed <- ifelse(res$log2FoldChange > 0, "UP", ifelse(res$log2FoldChange < 0, "DOWN", "NO_CHANGE"))
# Generate gene list for GSEA
organism = "org.Hs.eg.db"
original_gene_list <- res$log2FoldChange
names(original_gene_list) <- res$new_column
gene_list <<- na.omit(original_gene_list)
gene_list = sort(gene_list, decreasing = TRUE)
# Perform GO enrichment analysis
gse <<- gseGO(geneList = gene_list,
ont = "ALL",
keyType = "SYMBOL",
minGSSize = 3,
maxGSSize = 800,
pvalueCutoff = 0.05,
verbose = TRUE,
OrgDb = organism,
pAdjustMethod = "none")
# Store inverted results for GO terms in reactive values
searchValues$df_inverted <- gse@result %>% separate_rows(core_enrichment, sep = "/")
# Update GO term and description choices in UI
updateSelectInput(session, "GO_search", choices = unique(searchValues$df_inverted$ID))
updateSelectInput(session, "description_search", choices = unique(searchValues$df_inverted$Description))
# Reactive filtering of results based on user input
filteredRes <- reactive({
data <- as.data.frame(res)
# Apply gene search filter
if (searchValues$gene_search != "") {
genes <- strsplit(searchValues$gene_search, ";")[[1]]
genes <- trimws(genes)
data <- data %>%
filter(rowSums(sapply(genes, function(gene) grepl(gene, new_column, ignore.case = TRUE))) > 0)
}
# Apply GO term filter
if (searchValues$GO_search != "All") {
selected_genes <- searchValues$df_inverted %>%
filter(ID == searchValues$GO_search) %>%
pull(core_enrichment)
data <- data %>%
filter(new_column %in% selected_genes)
}
# Apply description search filter
if (searchValues$description_search != "") {
selected_genes <- searchValues$df_inverted %>%
filter(Description == searchValues$description_search) %>%
pull(core_enrichment)
data <- data %>%
filter(new_column %in% selected_genes)
}
data
})
# Render volcano plot based on filtered results
output$volcanoPlot <- renderPlotly({
data_res <- filteredRes()
p_value <- input$pvalue #need to add slides here
log2fc <- input$log2fc #need to add slider here
p <- ggplot(data_res, aes(x = log2FoldChange, y = pvalue_log10,
text = paste("Gene:", new_column, "<br>Log2 Fold Change:", log2FoldChange,
"<br>P-value:", pvalue, "<br>Significance:", significance,
"<br>Differentially Expressed:", diffexpressed, "<br>-log10 Values:", pvalue_log10))) +
geom_point(aes(color = log2FoldChange, shape = diffexpressed)) +
geom_hline(yintercept = -log10(p_value), linetype = "dotted", color = "red") +
geom_vline(xintercept = c(-log2fc, log2fc), linetype = "dotted", color = "darkblue") +
xlim(-5, 5) +
xlab("Log2 Fold Change") +
ylab("-log10(P-value)") +
ggtitle("Volcano Plot") +
scale_color_gradient2(low = "green", mid = "pink", high = "blue", midpoint = 0,
name = "Log2 Fold Change") # Add a custom color scale for the color legends
ggplotly(p, tooltip = "text")
})
})
# Update search criteria based on user actions
observeEvent(input$search_gene, {
searchValues$gene_search <- input$gene_search
searchValues$GO_search <- "All"
searchValues$description_search <- ""
})
observeEvent(input$search_GO_term, {
searchValues$GO_search <- input$GO_search
searchValues$gene_search <- ""
searchValues$description_search <- ""
})
observeEvent(input$search_description, {
searchValues$description_search <- input$description_search
searchValues$GO_search <- "All"
searchValues$gene_search <- ""
})
observeEvent(input$visualize_gse, {
library(ggplot2)
library(ggtext)
library(gridExtra)
output$dotPlotTitle <- renderPlot({
txt <- "Dot Plot with 10 Pathways"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$dotPlot <- renderPlot({
dot_plot <- dotplot(gse, showCategory = 10)
print(dot_plot)
})
output$conceptNetworkTitle <- renderPlot({
txt <- "Gene Concept Network"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$conceptNetwork <- renderPlot({
gsex <- setReadable(gse, 'org.Hs.eg.db', 'ENTREZID')
geneList <- gse@geneList
p1 <- cnetplot(gsex, foldChange = geneList, max.overlaps = 100)
p2 <- cnetplot(gsex, categorySize = "pvalue", foldChange = geneList, max.overlaps = 100)
p3 <- cnetplot(gsex, foldChange = geneList, circular = TRUE, colorEdge = TRUE, max.overlaps = 100)
maingene_plot <- cowplot::plot_grid(p1, p2, p3, ncol = 3, labels = LETTERS[1:3], rel_widths = c(.8, .8, 1.2))
print(maingene_plot)
})
output$heatMapTitle <- renderPlot({
txt <- "Heatmap-Like Functional Classification"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$heatMap <- renderPlot({
gsex <- setReadable(gse, 'org.Hs.eg.db', 'ENTREZID')
geneList <- gse@geneList
p1 <- heatplot(gsex, showCategory=5)
p2 <- heatplot(gsex, foldChange=geneList, showCategory=5)
mainheatmap_plot <- cowplot::plot_grid(p1, p2, ncol=1, labels=LETTERS[1:2])
print(mainheatmap_plot)
})
output$upsetPlotTitle <- renderPlot({
txt <- "UpSet Plot"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$upsetPlot <- renderPlot({
gse_df <- gse@result
top_terms <- gse_df %>% arrange(pvalue) %>% head(10)
top_gene_sets <- strsplit(top_terms$core_enrichment, "/")
gene_sets_list <- lapply(top_gene_sets, function(x) unique(trimws(x)))
gene_sets_df <- fromList(setNames(gene_sets_list, top_terms$ID))
# Create the UpSet plot
upset_plot <- upset(gene_sets_df,
sets = names(gene_sets_df),
main.bar.color = "steelblue",
sets.bar.color = "darkred",
order.by = "freq",
matrix.color = "gray",
keep.order = TRUE)
print(upset_plot)
})
output$pubmedPathwayPlotTitle <- renderPlot({
txt <- "PubMed Pathway Enrichment"
title_plot <- ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
print(title_plot)
})
output$pubmedPathwayPlot <- renderPlot({
results <- data.frame(Term = character(), Year = integer(), Count = integer(), stringsAsFactors = FALSE)
terms <- tail(gse$Description, n = 10)
results <- data.frame()
titles_2024 <- data.frame()
for (term in terms) {
for (year in 2014:2024) {
query <- paste(term, "[Title/Abstract] AND", year, "[PDAT]")
# Count results for each term and year
search_results <- entrez_search(db = "pubmed", term = query, retmax = 0)
results <- rbind(results, data.frame(Term = term, Year = year, Count = search_results$count))
# If the year is 2024, retrieve the first 10 article titles
if (year == 2024) {
search_results_2024 <- entrez_search(db = "pubmed", term = query, retmax = 10)
if (search_results_2024$count > 0) {
article_ids <- search_results_2024$ids
articles <- entrez_fetch(db = "pubmed", id = article_ids, rettype = "abstract", retmode = "text")
titles <- sapply(strsplit(articles, "\n"), function(x) x[1])
titles_2024 <- reactive({rbind(titles_2024, data.frame(Term = term, Title = titles, stringsAsFactors = FALSE))})
}
}
}
}
total_counts <- results %>%
group_by(Year) %>%
summarize(Total_Count = sum(Count), .groups = 'drop')
results <- results %>%
left_join(total_counts, by = "Year")
results <- results %>%
mutate(Ratio = Count / Total_Count)
print(results)
mainpubmed_plot <- ggplot(results, aes(x = Year, y = Ratio, color = Term)) +
geom_line() +
geom_point(size = 3, shape = 20, fill = "white", stroke = 1) + # Bolded dots
scale_x_continuous(limits = c(2013, 2025), breaks = seq(2013, 2025, by = 2.5)) + # 2.5-year breaks
labs(title = "Publication Ratio for Enriched Terms", x = "Year", y = "Publication Ratio") +
theme_minimal()
print(mainpubmed_plot)
})
})
} else {
showModal(modalDialog(
title = "Access Denied",
"Incorrect password. Please try again.",
easyClose = TRUE,
footer = NULL
))
}
})
}
shinyApp(ui = ui, server = server)
```