# GutPath.org & WebR: Single-Cell Architectural Specification ## Leveraging a 1-Million-Cell Gut Infection Atlas in In-Browser WebAssembly This document outlines the technical specification, memory budgets, and implementation plan for integrating the **GutPath.org** 1-million-cell annotated mucosal infection single-cell atlas into an in-browser **WebR workspace**. --- ## 1. Executive Summary & The WebAssembly Scale Challenge ### The Data Asset **GutPath.org** houses a curated single-cell RNA-seq atlas of the gastrointestinal tract during health and parasitic/bacterial/viral infections (*Cryptosporidium*, *Toxoplasma*, *Giardia*, *Salmonella*, helminths, and naive controls). The atlas encompasses approximately **1,000,000 cells** with fine-grained lineage annotations (stem, transit-amplifying, enterocytes, goblet, tuft, enteroendocrine, Paneth, innate lymphoid cells, myeloid subsets, and adaptive lymphocytes). ### The In-Browser Memory Constraint Standard 32-bit WebAssembly runtimes (including WebR) operate under strict memory caps: * **Browser Tab Ceiling:** ~2.0 to 4.0 GB total virtual memory. * **1M-Cell Raw Sparse Matrix (dgCMatrix):** $$1{,}000{,}000\text{ cells} \times 1{,}500\text{ detected genes/cell} = 1.5 \times 10^9\text{ non-zero entries}$$ Storing this matrix in R requires at least **18–24 GB of RAM**, making a monolithic in-browser load impossible. * **Network Payload:** An uncompressed 1M-cell matrix exceeds 10 GB; compressed it is ~2–4 GB, creating prohibitive download barriers. ### The Decoupled Solution Researchers and students rarely need to perform global matrix algebra on 1,000,000 cells simultaneously. By decoupling global visual querying from in-depth statistical computing, the atlas can be fully operational in WebR via **three synergistic strategies**: ```mermaid flowchart TD Atlas[("GutPath 1M Cell Atlas
1,000,000 Cells / Curated Metadata")] --> WGL["Global WebGL Navigator
(Deck.gl / Regl - 10 MB payload)"] Atlas --> Distill["Atlas Distillation Pipeline
(HPC Pre-computation)"] WGL -->|"Filter: Infection & Lineage
Lasso Select (1.5k - 5k cells)"| S1["Strategy 1: Dynamic Cohort Slicing
Seurat v5 Sandbox (~150 MB RAM)"] Distill -->|"Replicate-Level Summation
(Gene x Mouse x CellType)"| S2["Strategy 2: On-Demand Pseudobulk
limma-voom / edgeR TMM (~30 MB RAM)"] Distill -->|"Centroid / Marker Distillation
(30k Genes x 60 Cell Types)"| S4["Strategy 4: Curated Reference Atlas
SingleR / Azimuth Transfer (~15 MB RAM)"] S1 --> WebR[("WebR Browser Workspace
(Zero Server / Total Privacy)")] S2 --> WebR S4 --> WebR ``` --- ## 2. Strategy 1: Dynamic Cohort Slicing & Visual Atlas Bridge ### 2.1 Concept & User Experience Users explore the entire 1M-cell atlas visually in GutPath's web portal using GPU-accelerated WebGL. Once a specific biological question is framed, a targeted cohort of cells is dynamically extracted and dispatched into a live WebR Seurat workspace. ```mermaid flowchart LR A["1. Explore 1M Cells
Global UMAP Canvas"] --> B["2. Metadata Filter / Lasso
e.g. Tuft Cells in Naive vs Toxo"] B --> C["3. Validation Guardrail
Selected: 3,420 cells (~48 MB)"] C --> D["4. Dispatch to WebR
Mount /home/web_user/cohort/"] D --> E["5. Live Seurat Sandbox
QC, PCA, UMAP, Marker DEG"] ``` ### 2.2 Global WebGL Visualization Layer * **Lightweight Coordinate Storage:** The full 1,000,000 cell embedding requires only two single-precision floats per cell ($X, Y$ coordinates = $8\text{ MB}$) plus cluster/infection IDs ($2\text{ MB}$). * **Rendering:** Rendered at 60 FPS using `deck.gl` (`ScatterplotLayer` with binary buffers) or `regl`. * **Selection Tools:** 1. **Faceted Filter Panel:** Select by Organ/Region (Duodenum, Jejunum, Ileum, Cecum, Colon, Mesenteric Lymph Nodes), Pathogen/Condition (*Cryptosporidium*, *Toxoplasma*, *Giardia*, Naive), Lineage, Timepoint, or Mouse Strain. 2. **Spatial Polygon/Lasso Tool:** Freehand drawing directly on the 2D UMAP projection. ### 2.3 Slicing Engine & Virtual Filesystem Mounting When the user clicks **`[ Open Selected Cohort in WebR ]`**: 1. The client-side application queries a static cloud bucket (e.g. Cloudflare R2 / S3) using **HTTP Range Requests** or a lightweight edge worker to retrieve only the binary sparse column slices for the selected cell IDs. 2. The payload (typically 8–35 MB gzipped) is written to the WebR Emscripten Virtual Filesystem: * `/home/web_user/cohort/matrix.mtx.gz` * `/home/web_user/cohort/barcodes.tsv.gz` * `/home/web_user/cohort/features.tsv.gz` * `/home/web_user/cohort/cell_metadata.csv` 3. WebR automatically launches with a tailored single-cell analysis script pre-loaded into the editor. ### 2.4 Default Analysis Script Template (`GUTPATH_COHORT_SEURAT.R`) ```R # ============================================================================== # GutPath.org - Cohort Subcluster Analysis # Cohort: Cryptosporidium vs Naive - Small Intestinal Epithelium # ============================================================================== library(tidyverse) library(Seurat) library(Matrix) library(DT) # 1. Load Filtered Cohort from Virtual Filesystem datadir <- "cohort" counts <- Read10X(data.dir = datadir) meta <- read.csv(file.path(datadir, "cell_metadata.csv"), row.names = 1) # 2. Initialize Seurat Object gut_cohort <- CreateSeuratObject(counts = counts, meta.data = meta, min.cells = 3) # 3. Quality Assessment & Filtering gut_cohort[["percent.mt"]] <- PercentageFeatureSet(gut_cohort, pattern = "^mt-") VlnPlot(gut_cohort, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), group.by = "infection_status", pt.size = 0.1) # 4. Normalization & High-Variance Feature Selection gut_cohort <- NormalizeData(gut_cohort, normalization.method = "LogNormalize", scale.factor = 10000) gut_cohort <- FindVariableFeatures(gut_cohort, selection.method = "vst", nfeatures = 2000) # 5. Dimensional Reduction (PCA & UMAP) gut_cohort <- ScaleData(gut_cohort, features = VariableFeatures(gut_cohort)) gut_cohort <- RunPCA(gut_cohort, npcs = 30, verbose = FALSE) gut_cohort <- RunUMAP(gut_cohort, dims = 1:20) # 6. Visualization Across Experimental Variables DimPlot(gut_cohort, reduction = "umap", group.by = "curated_cell_type", label = TRUE) DimPlot(gut_cohort, reduction = "umap", split.by = "infection_status") # 7. Cluster Marker & Infection Response Discovery Idents(gut_cohort) <- "infection_status" infection_degs <- FindMarkers(gut_cohort, ident.1 = "Cryptosporidium", ident.2 = "Naive", min.pct = 0.25) datatable(infection_degs, caption = "Differentially Expressed Genes: Cryptosporidium vs Naive", options = list(pageLength = 10, searchHighlight = TRUE)) %>% formatRound(columns = c("p_val", "avg_log2FC", "pct.1", "pct.2", "p_val_adj"), digits = 3) ``` ### 2.5 Memory Budget & Guardrails * **Recommended Cohort Limit:** $\le 5{,}000$ cells. * **Typical Memory Consumption:** 120–280 MB RAM. * **Protective Downsampling:** If a user selects $>8{,}000$ cells, the UI prompts: > *"You have selected 14,200 cells. To guarantee responsive WebAssembly performance without browser tab freezing, GutPath will downsample to 4,000 representative cells (stratified across conditions)."* --- ## 3. Strategy 2: On-Demand Sample $\times$ Cell-Type Pseudobulking ### 3.1 Biological & Statistical Rationale While single-cell workflows often default to cell-level Wilcoxon tests, cell-level testing treats individual cells as independent observations, creating severe **pseudoreplication** and inflated false-discovery rates (FDR) in multi-animal studies. **Pseudobulking** aggregates UMI counts across cells belonging to the same cell type within each biological replicate (individual mouse): $$\text{Count}_{g, c, m} = \sum_{k \in \text{Cells}(c, m)} Y_{g, k}$$ where $g$ is the gene, $c$ is the curated cell type, and $m$ is the mouse replicate. This transforms single-cell data into an authentic replicated bulk count matrix, unlocking the gold-standard statistical rigor of **`limma-voom`** and **`edgeR` (TMM normalization)**. ### 3.2 Dimensions & Unbeatable Performance in WebR * **Input Atlas:** 1,000,000 cells across 40 mice and 30 curated cell types. * **Pseudobulk Matrix Dimensions:** $30{,}000\text{ genes} \times (40\text{ mice} \times 30\text{ cell types}) \le 30{,}000 \times 1{,}200$. * **Typical Filtered Contrast Matrix:** When focusing on a specific cell lineage (e.g. Enterocytes across 12 infected vs 12 control mice): $$30{,}000\text{ genes} \times 24\text{ biological samples} \approx \mathbf{5.8\text{ MB uncompressed}}$$ * **Execution Time:** Linear model fitting (`lmFit`), empirical Bayes shrinkage (`eBayes`), and volcano plot rendering execute in $<2.5$ seconds in WebR! ### 3.3 Pseudobulk Data Flow ```mermaid flowchart TD A["GutPath 1M Cell Atlas"] -->|"Offline Pre-aggregation
Matrix.utils / presto"| B[("Pseudobulk Data Store
counts_pseudobulk.parquet / hdf5")] B --> C["User Contrast Selector
1. Cell Type: Tuft Cells
2. Comparison: Salmonella vs Naive"] C --> D["Instant Slice Generation
counts.tsv (24 samples) + studydesign.txt"] D --> E["Mount to WebR VFS
/home/web_user/"] E --> F["Execute Course limma/edgeR Engine
TMM, voom, eBayes, Volcano, DT"] ``` ### 3.4 Integration with Existing WebR Course Shims This strategy has **zero friction** with the existing DIY Transcriptomics architecture. The pseudobulk slice is formatted as standard `counts.tsv` and `studydesign.txt`, directly utilizing: 1. `webr_shims$DGEList` & `webr_shims$calcNormFactors` (TMM normalization). 2. `webr_shims$filterByExpr` (low-count expression filtering). 3. `webr_shims$voom`, `webr_shims$lmFit`, `webr_shims$makeContrasts`, and `webr_shims$eBayes`. 4. High-performance GPU-accelerated volcano plots and interactive `DT::datatable()` widgets. ### 3.5 Default Pseudobulk Analysis Script (`GUTPATH_PSEUDOBULK_LIMMA.R`) ```R # ============================================================================== # GutPath.org - Cell-Type-Specific Pseudobulk Differential Expression # Target: Mature Enterocytes | Comparison: Salmonella enterica vs Naive # ============================================================================== library(tidyverse) library(edgeR) library(limma) library(DT) library(plotly) # 1. Load Count Matrix and Sample Metadata counts <- read.delim("counts.tsv", row.names = 1, check.names = FALSE) targets <- read_tsv("studydesign.txt", show_col_types = FALSE) # 2. Build DGEList Container dge <- DGEList(counts = counts) # 3. Filter Lowly Expressed Genes infection_group <- factor(targets$infection_status) keep <- filterByExpr(dge, group = infection_group) dge <- dge[keep, , keep.lib.sizes = FALSE] # 4. TMM Normalization dge <- calcNormFactors(dge, method = "TMM") # 5. Formulate Linear Model Design Matrix design <- model.matrix(~ 0 + infection_group) colnames(design) <- levels(infection_group) # 6. Empirical Bayes Variance Modeling via Voom v <- voom(dge, design, plot = TRUE) fit <- lmFit(v, design) # 7. Evaluate Statistical Contrast contrast_matrix <- makeContrasts(InfectionEffect = Salmonella - Naive, levels = design) fit_contrast <- contrasts.fit(fit, contrast_matrix) fit_bayes <- eBayes(fit_contrast) # 8. Extract Differential Hits top_hits <- topTable(fit_bayes, coef = "InfectionEffect", number = Inf, sort.by = "P") top_hits_df <- as_tibble(top_hits, rownames = "geneID") # 9. Interactive Volcano Plot p <- ggplot(top_hits_df, aes(x = logFC, y = -log10(adj.P.Val), text = geneID)) + geom_point(aes(color = adj.P.Val < 0.05 & abs(logFC) > 1), alpha = 0.7, size = 1.5) + scale_color_manual(values = c("grey60", "#dc2626")) + theme_bw() + labs(title = "Salmonella Response in Mature Enterocytes (Pseudobulk)", x = "Log2 Fold Change", y = "-Log10 Adjusted P-Value") ggplotly(p, tooltip = "text") # 10. Interactive Searchable DEG Table datatable(top_hits_df %>% filter(adj.P.Val < 0.05), options = list(pageLength = 15, searchHighlight = TRUE)) %>% formatRound(columns = c("logFC", "AveExpr", "t", "P.Value", "adj.P.Val"), digits = 3) ``` --- ## 4. Strategy 4: GutPath as an Automated Reference Atlas (SingleR / Azimuth) ### 4.1 Concept & Value Proposition Researchers frequently generate their own gut single-cell experiments (e.g. from mouse disease models or biopsies) and face steep annotation bottlenecks. By distilling GutPath’s 1M-cell curated dataset into a lightweight reference profile, external users can upload their own unannotated single-cell matrices into WebR and receive **high-confidence cell-type predictions in $<5$ seconds**. ```mermaid flowchart LR A["User Uploads Own Single-Cell Data
(10X matrix.mtx / counts.tsv)"] --> B["WebR Workspace"] C[("GutPath Curated Reference
30,000 Genes x 60 Cell Types
(~8 MB)")] --> B B --> D["webr_shims$SingleR()
Rank-Correlation Label Transfer"] D --> E["plotScoreHeatmap()
Diagnostic Classification Scores"] D --> F["Annotated User Dataset
SingleR.labels on UMAP"] ``` ### 4.2 Atlas Distillation Architecture Instead of using the entire 1M individual cell vectors as a reference, the atlas is distilled into two optimized tiers: 1. **Centroid Reference Matrix (`GutPath_Reference_Centroids.rds`):** * Computes the normalized pseudo-median or trimmed-mean expression vector for each of the ~60 curated cell types/states across the 1,000,000 cells. * Dimensions: $30{,}000\text{ genes} \times 60\text{ cell types} = 1.8 \times 10^6\text{ values} \approx \mathbf{7.2\text{ MB}}$. 2. **Discriminant Feature Marker Subsets:** * Top 50–100 specific marker genes for each lineage and activation state. ### 4.3 WebR Shim Implementation (`webr_shims$GutPathReferenceData`) We register `GutPathReferenceData()` inside `webr_shims` alongside existing `celldex` references (`MonacoImmuneData`, `MouseRNAseqData`): ```R webr_shims$GutPathReferenceData <- function(level = c("fine", "main")) { level <- match.arg(level) ref_path <- file.path("/home/web_user/.webr_lib/references", paste0("gutpath_", level, ".rds")) if (!file.exists(ref_path)) { # Auto-fetch pre-distilled reference profile on first invocation download.file("https://gutpath.org/data/references/gutpath_reference.rds", ref_path, quiet = TRUE) } readRDS(ref_path) } ``` ### 4.4 User Label Transfer Script Template (`GUTPATH_LABEL_TRANSFER.R`) ```R # ============================================================================== # GutPath.org - Automated Reference-Based Cell Type Annotation # Mapping Query scRNA-seq Data to the GutPath 1M Cell Atlas # ============================================================================== library(SingleR) library(SingleCellExperiment) library(DropletUtils) library(pheatmap) library(ggplot2) # 1. Load User's Unannotated Query Dataset query_sce <- read10xCounts("user_query_10x") # 2. Access the Pre-Distilled GutPath Mucosal Reference gutpath_ref <- GutPathReferenceData(level = "fine") # 3. Perform High-Speed Label Transfer predictions <- SingleR(test = query_sce, ref = gutpath_ref, labels = gutpath_ref$cell_type, de.method = "wilcox") # 4. Diagnostic Prediction Score Heatmap plotScoreHeatmap(predictions, main = "SingleR Prediction Confidence Scores (GutPath Reference)") # 5. Project Transferred Labels onto Query Embedding query_sce$GutPath_CellType <- predictions$labels plotUMAP(query_sce, colour_by = "GutPath_CellType") # 6. Cell Type Proportions Table as.data.frame(table(query_sce$GutPath_CellType)) %>% rename(CellType = Var1, CellCount = Freq) %>% arrange(desc(CellCount)) ``` --- ## 5. Architectural & Resource Comparison Matrix | Architectural Dimension | Strategy 1: Dynamic Cohort Slicing | Strategy 2: On-Demand Pseudobulk | Strategy 4: Automated Reference Atlas | | :--- | :--- | :--- | :--- | | **Primary Biological Question** | High-resolution single-cell subclustering & marker discovery | Rigorous multi-replicate differential expression (DEG) | Cell-type classification of external/user datasets | | **Typical Matrix Dimensions** | 30,000 genes $\times$ 1,500–5,000 cells | 30,000 genes $\times$ 12–40 biological samples | 30,000 genes $\times$ 60 reference profiles | | **Network Transfer Size** | 8 – 35 MB (compressed MTX / CSV) | 1.5 – 6 MB (TSV) | ~7.2 MB (pre-cached RDS) | | **WebR Memory Footprint** | 120 – 280 MB RAM | 25 – 45 MB RAM | 15 – 35 MB RAM | | **Execution Latency in WebR** | 10 – 25 seconds (PCA + UMAP) | $< 2.5$ seconds (TMM + eBayes) | $< 4.0$ seconds (Spearman rank math) | | **Existing Shim Reuse** | Uses `Seurat` proxy, `Read10X`, `DimPlot` | 100% reuse of `edgeR`, `limma`, `voom` | Uses `SingleR`, `celldex`, `plotScoreHeatmap` | | **Tab Crash Risk** | Zero (guarded by $\le 5{,}000$ cell cap) | Absolutely zero | Absolutely zero | --- ## 6. Implementation Roadmap ```mermaid timeline title GutPath WebR Implementation Timeline section Phase 1: Reference Distillation Extract 60 cell-type centroids from 1M cells : Done offline Package GutPathReferenceData into webr_shims : Week 1 Verify SingleR label transfer in WebR : Week 1 section Phase 2: Pseudobulk Pipeline Generate replicate-level counts across 40 mice : Week 2 Deploy contrast selector UI on GutPath : Week 2 Connect to WebR limma-voom engine : Week 3 section Phase 3: WebGL Cohort Slicing Build WebGL UMAP navigator (Deck.gl) : Week 4 Implement HTTP Range Request slice generator : Week 5 End-to-end integration with Seurat WebR sandbox : Week 6 ``` ### Phase 1: Reference Distillation & SingleR Integration (Fastest Win) 1. **HPC Matrix Aggregation:** Compute median expression per curated cell type across the 1M cells in R/Python. 2. **Hosting:** Place `gutpath_reference.rds` on static CDN / GitHub releases. 3. **Shim Registration:** Add `webr_shims$GutPathReferenceData` into `js/src/webr/webr-engine.js`. 4. **Verification:** Confirm external query datasets can be annotated in WebR in under 5 seconds. ### Phase 2: Pseudobulk Pipeline & Contrast Selector 1. **Pre-Aggregation Matrix:** Generate `gutpath_pseudobulk_master.tsv` ($30{,}000 \times 1{,}200$). 2. **UI Contrast Selector:** Add a dropdown on GutPath.org allowing users to select: * Target Lineage (e.g. *Tuft Cells*). * Comparison (e.g. *Cryptosporidium parvum* Day 4 vs Naive). 3. **WebR Handoff:** Launch WebR with the dynamically sliced 24-column matrix, running full `voom` + `eBayes` DEG analysis. ### Phase 3: Visual Atlas Navigator & WebGL Cohort Bridge 1. **Coordinate Export:** Export 2D UMAP coordinates and cell metadata to compressed binary buffers. 2. **Client-Side WebGL Viewer:** Embed `deck.gl` scatterplot viewer on GutPath.org. 3. **Cohort Exporter:** Connect spatial lasso and metadata filter selections to an in-browser zip generator that writes to WebR virtual memory. 4. **Seurat Template:** Pre-load `GUTPATH_COHORT_SEURAT.R` in the WebR script pane. --- ## 7. Architectural Guarantees & Verification Gate 1. **Client-Side Privacy Invariant:** No user data or filtered cohort slices are ever uploaded to an external server; all single-cell algebra and differential modeling execute strictly within local browser memory via WebAssembly. 2. **Tier 1 & Tier 2 Search Path Isolation:** Genuine WASM packages (`Matrix`, `tidyverse`, `DT`, `plotly`) operate natively without `.GlobalEnv` shadowing, while curated shims (`SingleR`, `limma`, `edgeR`) reside inside `webr_shims`. 3. **Build Gate:** Any client-side code added to support these workflows must satisfy: ```bash npm run build && bundle exec jekyll build ``` with 100% passing invariant checks.