> Status: `draft` > > Template class: SOURCE-BACKED WORKFLOW ## Purpose Construct co-expression modules and module eigengenes with hdWGCNA from a processed Seurat object. This is network/module inference, not predefined gene-set scoring. ## Inputs and parameters The object must contain an expression assay, a reduction for metacell construction, a sample column, and a biological grouping column. ```{r} library(Seurat) library(hdWGCNA) library(qs2) library(patchwork) library(ggplot2) library(readr) input_object <- "input/seurat_object_processed.qs2" output_object <- "output/seurat_object_hdwgcna.qs2" output_modules <- "output/hdwgcna_modules.tsv" output_hubs <- "output/hdwgcna_hub_genes.tsv" output_power <- "output/hdwgcna_power_table.tsv" output_power_plot <- "output/hdwgcna_soft_powers.png" output_kme_plot <- "output/hdwgcna_kme.png" assay_name <- "SCT" expression_layer <- "data" metacell_reduction <- "harmony" metacell_group_columns <- c("sample_id", "cluster") module_group_column <- "cluster" eigengene_batch_column <- "sample_id" metacell_k <- 25 max_shared <- 10 wgcna_name <- "wgcna" network_type <- "signed hybrid" soft_power <- 4 n_variable_features <- 3000 seed <- 1234 ``` ## Analysis ```{r} object <- qs2::qs_read(input_object) DefaultAssay(object) <- assay_name stopifnot(all(metacell_group_columns %in% colnames(object[[]]))) stopifnot(metacell_reduction %in% Reductions(object)) features <- head(VariableFeatures(object), n_variable_features) stopifnot(length(features) > 0) object <- SetupForWGCNA( object, features = features, wgcna_name = wgcna_name ) object <- MetacellsByGroups( seurat_obj = object, group.by = metacell_group_columns, reduction = metacell_reduction, k = metacell_k, max_shared = max_shared, ident.group = module_group_column ) object <- NormalizeMetacells(object) module_groups <- unique(as.character(object[[module_group_column]][, 1])) object <- SetDatExpr( object, group_name = module_groups, group.by = module_group_column, assay = assay_name, layer = expression_layer ) object <- TestSoftPowers(object, networkType = network_type) power_table <- GetPowerTable(object) object <- ConstructNetwork( object, randomSeed = seed, soft_power = soft_power, overwrite_tom = TRUE, tom_name = wgcna_name ) object <- ModuleEigengenes( object, assay = assay_name, group.by.vars = eigengene_batch_column ) object <- ModuleConnectivity( object, group.by = module_group_column, group_name = module_groups ) modules <- GetModules(object) modules <- modules[modules$module != "grey", , drop = FALSE] hub_genes <- modules[order(-abs(modules$kME_max), na.last = NA), , drop = FALSE] ``` ## Diagnostics ```{r} dir.create(dirname(output_power_plot), recursive = TRUE, showWarnings = FALSE) power_plot <- wrap_plots(PlotSoftPowers(object), ncol = 2) ggsave(output_power_plot, power_plot, width = 10, height = 7, dpi = 150) print(power_table) print(head(modules)) print(head(hub_genes)) kme_plot <- PlotKMEs(object, ncol = 3) ggsave(output_kme_plot, kme_plot, width = 10, height = 7, dpi = 150) ``` ## Outputs ```{r} dir.create(dirname(output_object), recursive = TRUE, showWarnings = FALSE) dir.create(dirname(output_modules), recursive = TRUE, showWarnings = FALSE) qs2::qs_save(object, output_object) write_tsv(as.data.frame(power_table), output_power) write_tsv(as.data.frame(modules), output_modules) write_tsv(as.data.frame(hub_genes), output_hubs) ``` ## Method notes Metacell grouping, sample grouping, network type, soft power, and hub ranking are scientific decisions. The source used cluster-focused grouping; this template exposes sample and cluster grouping so replicate structure is not silently discarded. A soft-power value should be justified from diagnostics. AddModuleScore-style scoring is not this network analysis.