-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclustering_server.R
More file actions
115 lines (96 loc) · 4.85 KB
/
Copy pathclustering_server.R
File metadata and controls
115 lines (96 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# ─────────────────────────────────────────────
# 🧩 Clustering Module - SERVER LOGIC (universal + timer)
# ─────────────────────────────────────────────
clustering_server <- function(id) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
# ───────────── Reactive values ─────────────
clustering_in_progress <- reactiveVal(FALSE)
start_time <- reactiveVal(NULL)
# ───────────── Timer text ─────────────
output$clustering_status <- renderText("")
# ───────────── Reactive timer ─────────────
autoInvalidate <- reactiveTimer(1000) # refresh every second
observe({
autoInvalidate()
if (clustering_in_progress()) {
elapsed <- as.numeric(Sys.time() - start_time(), units = "secs")
output$clustering_status <- renderText(
paste0("⏳ Running clustering... (", round(elapsed), " sec elapsed)")
)
}
})
# ───────────── Run Clustering Button ─────────────
observeEvent(input$run_clustering, {
start_time(Sys.time())
clustering_in_progress(TRUE)
output$clustering_status <- renderText("⏳ Initializing clustering... Please wait.")
tryCatch({
# --- Step 1: Load Seurat object ---
obj <- get("global_dataset", envir = .GlobalEnv)
req(obj)
# --- Step 2: Ensure preprocessing done ---
message("🔧 Checking Seurat object structure...")
obj <- prepare_seurat_object(obj) # from global.R
# --- Step 3: Detect assay type ---
assay_type <- DefaultAssay(obj)
message("✅ Using assay type: ", assay_type)
# --- Step 4: Clustering process ---
resolution <- input$resolution
message("🚀 Running clustering at resolution = ", resolution)
# Run neighborhood graph & clustering
obj <- FindNeighbors(obj, dims = 1:30, verbose = FALSE)
obj <- FindClusters(obj, resolution = resolution, verbose = FALSE)
# --- Step 5: Run UMAP if missing ---
if (!"umap" %in% names(obj@reductions)) {
message("🧭 Running UMAP...")
obj <- RunUMAP(obj, dims = 1:30, verbose = FALSE)
}
# --- Step 6: Save globally for use in other modules ---
assign("global_dataset", obj, envir = .GlobalEnv)
# --- Step 7: Render UMAP plot ---
output$umap_plot <- renderPlot({
DimPlot(obj, reduction = "umap", label = TRUE, repel = TRUE) +
ggtitle(paste0("UMAP of Clusters (Assay: ", assay_type,
", Resolution: ", resolution, ")")) +
theme_minimal(base_size = 14) +
theme(
panel.grid = element_blank(),
plot.background = element_rect(fill = "white", color = NA),
panel.background = element_rect(fill = "white", color = NA)
)
})
# --- Step 8: Success message ---
elapsed <- round(as.numeric(Sys.time() - start_time(), units = "secs"))
output$clustering_status <- renderText(
paste0("✅ Clustering completed successfully in ", elapsed, " seconds!")
)
clustering_in_progress(FALSE)
}, error = function(e) {
clustering_in_progress(FALSE)
output$clustering_status <- renderText(paste0("❌ Error: ", e$message))
message("❌ Error: ", e$message)
})
})
# ───────────── Download UMAP PNG ─────────────
output$download_umap <- downloadHandler(
filename = function() { paste0("UMAP_Clusters_", Sys.Date(), ".png") },
content = function(file) {
obj <- get("global_dataset", envir = .GlobalEnv)
req(obj)
assay_type <- DefaultAssay(obj)
res <- input$resolution
p <- DimPlot(obj, reduction = "umap", label = TRUE, repel = TRUE) +
ggtitle(paste0("UMAP of Clusters (Assay: ", assay_type,
", Resolution: ", res, ")")) +
theme_minimal(base_size = 14) +
theme(
panel.grid = element_blank(),
plot.background = element_rect(fill = "white", color = NA),
panel.background = element_rect(fill = "white", color = NA)
)
ggsave(file, plot = p, width = 8, height = 6, dpi = 1000, bg = "white")
}
)
})
}