| |
| |
| |
|
|
| venn_diagram_server <- function(input, output, session) { |
|
|
| |
| output$venn_inputs <- renderUI({ |
| n_sets <- input$venn_sets |
|
|
| tagList( |
| lapply(1:n_sets, function(i) { |
| fluidRow( |
| column(6, |
| textInput(paste0("venn_name_", i), |
| paste0("集合", i, "名称"), |
| value = paste0("Set", i)) |
| ), |
| column(6, |
| textAreaInput(paste0("venn_data_", i), |
| paste0("集合", i, "数据"), |
| placeholder = "每行一个基因/通路,或逗号分隔", |
| rows = 5) |
| ) |
| ) |
| }) |
| ) |
| }) |
|
|
| |
| venn_data <- eventReactive(input$generate_venn, { |
| req(input$venn_sets) |
|
|
| n_sets <- input$venn_sets |
| set_list <- list() |
| set_names <- c() |
|
|
| for (i in 1:n_sets) { |
| name_input <- input[[paste0("venn_name_", i)]] |
| data_input <- input[[paste0("venn_data_", i)]] |
|
|
| if (!is.null(name_input) && name_input != "" && |
| !is.null(data_input) && data_input != "") { |
|
|
| |
| elements <- unlist(strsplit(data_input, "[\n,]")) |
| elements <- trimws(elements) |
| elements <- elements[elements != ""] |
|
|
| if (length(elements) > 0) { |
| set_list[[name_input]] <- unique(elements) |
| set_names <- c(set_names, name_input) |
| } |
| } |
| } |
|
|
| if (length(set_list) < 2) { |
| showNotification("至少需要2个有效集合才能生成韦恩图", type = "error") |
| return(NULL) |
| } |
|
|
| return(list(sets = set_list, names = set_names)) |
| }) |
|
|
| |
| output$venn_plot <- renderPlot({ |
| req(venn_data()) |
|
|
| data <- venn_data() |
| set_list <- data$sets |
| set_names <- data$names |
|
|
| |
| colors <- c(input$venn_color1, input$venn_color2, input$venn_color3, |
| input$venn_color4, input$venn_color5)[1:length(set_names)] |
|
|
| |
| if (length(set_names) == 2) { |
| |
| grid.newpage() |
| venn_plot <- draw.pairwise.venn( |
| area1 = length(set_list[[1]]), |
| area2 = length(set_list[[2]]), |
| cross.area = length(intersect(set_list[[1]], set_list[[2]])), |
| category = set_names, |
| fill = colors, |
| alpha = input$venn_alpha, |
| cat.col = colors, |
| cat.cex = 1.2, |
| cex = 1.5, |
| cat.pos = c(0, 0), |
| cat.dist = 0.05 |
| ) |
| } else if (length(set_names) == 3) { |
| |
| grid.newpage() |
| venn_plot <- draw.triple.venn( |
| area1 = length(set_list[[1]]), |
| area2 = length(set_list[[2]]), |
| area3 = length(set_list[[3]]), |
| n12 = length(intersect(set_list[[1]], set_list[[2]])), |
| n23 = length(intersect(set_list[[2]], set_list[[3]])), |
| n13 = length(intersect(set_list[[1]], set_list[[3]])), |
| n123 = length(Reduce(intersect, set_list)), |
| category = set_names, |
| fill = colors, |
| alpha = input$venn_alpha, |
| cat.col = colors, |
| cat.cex = 1.2, |
| cex = 1.5 |
| ) |
| } else if (length(set_names) == 4) { |
| |
| grid.newpage() |
| venn_plot <- draw.quad.venn( |
| area1 = length(set_list[[1]]), |
| area2 = length(set_list[[2]]), |
| area3 = length(set_list[[3]]), |
| area4 = length(set_list[[4]]), |
| n12 = length(intersect(set_list[[1]], set_list[[2]])), |
| n13 = length(intersect(set_list[[1]], set_list[[3]])), |
| n14 = length(intersect(set_list[[1]], set_list[[4]])), |
| n23 = length(intersect(set_list[[2]], set_list[[3]])), |
| n24 = length(intersect(set_list[[2]], set_list[[4]])), |
| n34 = length(intersect(set_list[[3]], set_list[[4]])), |
| n123 = length(Reduce(intersect, set_list[1:3])), |
| n124 = length(Reduce(intersect, set_list[c(1,2,4)])), |
| n134 = length(Reduce(intersect, set_list[c(1,3,4)])), |
| n234 = length(Reduce(intersect, set_list[2:4])), |
| n1234 = length(Reduce(intersect, set_list)), |
| category = set_names, |
| fill = colors, |
| alpha = input$venn_alpha, |
| cat.col = colors, |
| cat.cex = 1.1, |
| cex = 1.3 |
| ) |
| } else if (length(set_names) == 5) { |
| |
| grid.newpage() |
| venn_plot <- draw.quintuple.venn( |
| area1 = length(set_list[[1]]), |
| area2 = length(set_list[[2]]), |
| area3 = length(set_list[[3]]), |
| area4 = length(set_list[[4]]), |
| area5 = length(set_list[[5]]), |
| n12 = length(intersect(set_list[[1]], set_list[[2]])), |
| n13 = length(intersect(set_list[[1]], set_list[[3]])), |
| n14 = length(intersect(set_list[[1]], set_list[[4]])), |
| n15 = length(intersect(set_list[[1]], set_list[[5]])), |
| n23 = length(intersect(set_list[[2]], set_list[[3]])), |
| n24 = length(intersect(set_list[[2]], set_list[[4]])), |
| n25 = length(intersect(set_list[[2]], set_list[[5]])), |
| n34 = length(intersect(set_list[[3]], set_list[[4]])), |
| n35 = length(intersect(set_list[[3]], set_list[[5]])), |
| n45 = length(intersect(set_list[[4]], set_list[[5]])), |
| n123 = length(Reduce(intersect, set_list[1:3])), |
| n124 = length(Reduce(intersect, set_list[c(1,2,4)])), |
| n125 = length(Reduce(intersect, set_list[c(1,2,5)])), |
| n134 = length(Reduce(intersect, set_list[c(1,3,4)])), |
| n135 = length(Reduce(intersect, set_list[c(1,3,5)])), |
| n145 = length(Reduce(intersect, set_list[c(1,4,5)])), |
| n234 = length(Reduce(intersect, set_list[2:4])), |
| n235 = length(Reduce(intersect, set_list[c(2,3,5)])), |
| n245 = length(Reduce(intersect, set_list[c(2,4,5)])), |
| n345 = length(Reduce(intersect, set_list[3:5])), |
| n1234 = length(Reduce(intersect, set_list[1:4])), |
| n1235 = length(Reduce(intersect, set_list[c(1,2,3,5)])), |
| n1245 = length(Reduce(intersect, set_list[c(1,2,4,5)])), |
| n1345 = length(Reduce(intersect, set_list[c(1,3,4,5)])), |
| n2345 = length(Reduce(intersect, set_list[2:5])), |
| n12345 = length(Reduce(intersect, set_list)), |
| category = set_names, |
| fill = colors, |
| alpha = input$venn_alpha, |
| cat.col = colors, |
| cat.cex = 1.0, |
| cex = 1.2 |
| ) |
| } |
|
|
| |
| venn_intersections <<- calculate_intersections(set_list) |
|
|
| return(venn_plot) |
| }) |
|
|
| |
| calculate_intersections <- function(set_list) { |
| set_names <- names(set_list) |
| intersections <- list() |
|
|
| |
| for (i in 1:length(set_names)) { |
| combos <- combn(set_names, i, simplify = FALSE) |
| for (combo in combos) { |
| combo_name <- paste(combo, collapse = " & ") |
| if (length(combo) == 1) { |
| |
| elements <- set_list[[combo]] |
| } else { |
| |
| elements <- Reduce(intersect, set_list[combo]) |
| } |
| intersections[[combo_name]] <- elements |
| } |
| } |
|
|
| return(intersections) |
| } |
|
|
| |
| observeEvent(input$venn_click, { |
| req(venn_intersections) |
|
|
| |
| |
| showModal(modalDialog( |
| title = "选择交集区域", |
| selectInput("selected_intersection", "选择交集:", |
| choices = names(venn_intersections)), |
| footer = tagList( |
| actionButton("confirm_intersection", "确认选择"), |
| modalButton("取消") |
| ) |
| )) |
| }) |
|
|
| |
| observeEvent(input$confirm_intersection, { |
| req(input$selected_intersection, venn_intersections) |
|
|
| selected_elements <- venn_intersections[[input$selected_intersection]] |
|
|
| |
| if (length(selected_elements) > 0) { |
| clip_text <- paste(selected_elements, collapse = "\n") |
| writeClipboard(clip_text) |
| showNotification(paste("已复制", length(selected_elements), "个元素到剪贴板"), |
| type = "message") |
| } else { |
| showNotification("选择的交集为空", type = "warning") |
| } |
|
|
| removeModal() |
| }) |
|
|
| |
| output$venn_result_ui <- renderUI({ |
| req(venn_data()) |
|
|
| data <- venn_data() |
| set_list <- data$sets |
| set_names <- data$names |
|
|
| |
| total_elements <- length(unique(unlist(set_list))) |
| intersection_counts <- list() |
|
|
| |
| for (i in 1:length(set_names)) { |
| combos <- combn(set_names, i, simplify = FALSE) |
| for (combo in combos) { |
| combo_name <- paste(combo, collapse = " ∩ ") |
| if (length(combo) == 1) { |
| count <- length(set_list[[combo]]) |
| } else { |
| count <- length(Reduce(intersect, set_list[combo])) |
| } |
| intersection_counts[[combo_name]] <- count |
| } |
| } |
|
|
| |
| tagList( |
| h4("韦恩图统计信息"), |
| div(class = "venn-result-box", |
| p(strong("总唯一元素数: "), total_elements), |
| lapply(names(intersection_counts), function(name) { |
| div( |
| p(strong(name), ": ", intersection_counts[[name]], "个元素", |
| actionButton(paste0("copy_", gsub(" ", "_", name)), "复制", |
| class = "btn-xs copy-btn", |
| onclick = sprintf('Shiny.setInputValue("copy_intersection", "%s", {priority: "event"})', name)) |
| ) |
| ) |
| }) |
| ) |
| ) |
| }) |
|
|
| |
| observeEvent(input$copy_intersection, { |
| req(input$copy_intersection, venn_intersections) |
|
|
| intersection_name <- input$copy_intersection |
| selected_elements <- venn_intersections[[intersection_name]] |
|
|
| if (length(selected_elements) > 0) { |
| clip_text <- paste(selected_elements, collapse = "\n") |
| writeClipboard(clip_text) |
| showNotification(paste("已复制", length(selected_elements), "个元素到剪贴板"), |
| type = "message") |
| } else { |
| showNotification("选择的交集为空", type = "warning") |
| } |
| }) |
|
|
| |
| output$venn_table <- DT::renderDataTable({ |
| req(venn_intersections) |
|
|
| |
| intersection_df <- data.frame( |
| 交集区域 = names(venn_intersections), |
| 元素数量 = sapply(venn_intersections, length), |
| 元素列表 = sapply(venn_intersections, function(x) paste(x, collapse = ", ")), |
| stringsAsFactors = FALSE |
| ) |
|
|
| DT::datatable(intersection_df, |
| options = list(scrollX = TRUE, pageLength = 10), |
| rownames = FALSE) %>% |
| formatStyle(columns = 1:3, fontSize = '14px') |
| }) |
| } |