Skip to contents

Introduction

Differential communication analysis is essential for understanding how cell-cell signaling changes between biological conditions, such as:

  • Disease vs. Normal: Altered communication in cancer, inflammation, or autoimmune diseases
  • Treatment response: Changes after drug treatment or immunotherapy
  • Developmental stages: Communication dynamics during differentiation

NOVA provides comprehensive tools for comparing communication networks between conditions.

Simulating Two Conditions

We’ll create two simulated datasets representing control and treatment conditions.

set.seed(42)

# Common parameters
n_genes <- 200
n_cells <- 400
gene_names <- paste0("Gene", 1:n_genes)
clusters <- c("T_cells", "B_cells", "Macrophages", "Fibroblasts")

# Get LR database genes
lr_db <- GetLRDatabase("lrc2p")
ligands <- unique(lr_db$ligand)[1:25]
receptors <- unique(lr_db$receptor)[1:25]

# Function to create expression matrix
create_expr <- function(n_cells, seed_offset = 0, fold_changes = NULL) {
  set.seed(42 + seed_offset)
  cell_names <- paste0("Cell", 1:n_cells)
  
  expr <- matrix(0, nrow = n_genes, ncol = n_cells,
                 dimnames = list(gene_names, cell_names))
  
  # Base expression
  expressed <- sample(length(expr), size = length(expr) * 0.25)
  expr[expressed] <- abs(rnorm(length(expressed), mean = 2, sd = 1))
  
  # Map genes
  rownames(expr)[1:25] <- ligands
  rownames(expr)[26:50] <- receptors
  
  # Apply fold changes if provided
  if (!is.null(fold_changes)) {
    for (gene in names(fold_changes)) {
      if (gene %in% rownames(expr)) {
        expr[gene, ] <- expr[gene, ] * fold_changes[gene]
      }
    }
  }
  
  # Create annotation
  cluster_assign <- sample(clusters, n_cells, replace = TRUE)
  names(cluster_assign) <- cell_names
  ann <- data.frame(cell = cell_names, cluster = cluster_assign)
  
  list(expr = Matrix::Matrix(expr, sparse = TRUE), annotation = ann)
}

# Create control condition
ctrl <- create_expr(400)

# Create treatment condition with altered expression
# Simulate upregulation of some genes in treatment
treatment_fc <- setNames(rep(1.5, 10), ligands[1:10])
treat <- create_expr(400, seed_offset = 100, fold_changes = treatment_fc)

Running Individual Analyses

# Analyze control
ctrl_result <- ExtractEdges(
  expression = ctrl$expr,
  annotation = ctrl$annotation,
  species = "human",
  database = "lrc2p",
  min_pct = 0.05
)

# Analyze treatment
treat_result <- ExtractEdges(
  expression = treat$expr,
  annotation = treat$annotation,
  species = "human",
  database = "lrc2p",
  min_pct = 0.05
)

cat("Control edges:", nrow(ctrl_result$edges), "\n")
cat("Treatment edges:", nrow(treat_result$edges), "\n")

Differential Analysis

Running DiffEdges

# Compare treatment vs control
diff_result <- DiffEdges(
  reference = ctrl_result,
  target = treat_result,
  log2fc_threshold = 0.5,
  pseudo_count = 0.001
)

print(diff_result)

Understanding the Output

# Summary of differential analysis
summary(diff_result)

# View changed edges
head(diff_result$changed_edges)

Visualization

Differential Heatmap

PlotDiffHeatmap(diff_result, metric = "log2fc")

Volcano Plot

PlotVolcano(diff_result, 
            log2fc_threshold = 0.5,
            label_top = 10,
            title = "Treatment vs Control")

Summarization Functions

By Cluster Pair

# Summarize changes by cluster pairs
cluster_summary <- SummarizeByCluster(diff_result)
head(cluster_summary)

By LR Pair

# Summarize changes by ligand-receptor pairs
lr_summary <- SummarizeByLR(diff_result)
head(lr_summary)

Filtering Significant Changes

# Get strongly upregulated edges
up_edges <- diff_result$changed_edges[log2fc > 1]
cat("Upregulated edges:", nrow(up_edges), "\n")

# Get strongly downregulated edges
down_edges <- diff_result$changed_edges[log2fc < -1]
cat("Downregulated edges:", nrow(down_edges), "\n")

Interpreting Results

Key Metrics

Metric Description Interpretation
log2fc Log2 fold change Positive = increased in treatment
delta_mean Difference in expression weight Magnitude of change
delta_specificity Difference in specificity Change in selectivity

Biological Interpretation

  1. High log2fc + High specificity: Strong, specific upregulation
  2. High log2fc + Low specificity: Widespread upregulation
  3. Negative log2fc: Decreased communication
  4. Near-zero log2fc: Stable communication

Exporting Results

# Export to Excel
ExportDiff(diff_result, "differential_analysis.xlsx")

# Export to CSV
write.csv(diff_result$changed_edges, "changed_edges.csv", row.names = FALSE)

Best Practices

1. Sample Matching

Ensure comparable cell populations between conditions:

# Check cluster proportions
table(ctrl_result$annotation$cluster)
table(treat_result$annotation$cluster)

2. Multiple Testing Consideration

For large-scale analyses, consider adjusting for multiple testing:

# Example: Bonferroni correction
n_tests <- nrow(diff_result$changed_edges)
alpha_adjusted <- 0.05 / n_tests

3. Biological Validation

Prioritize edges for validation based on: - High absolute log2fc - High specificity scores - Known biological relevance

Session Info

sessionInfo()
#> R version 4.4.0 (2024-04-24)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS 15.6.1
#> 
#> Matrix products: default
#> BLAS:   /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib 
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0
#> 
#> locale:
#> [1] C
#> 
#> time zone: Asia/Shanghai
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] ggplot2_4.0.1 NOVA_1.0.0   
#> 
#> loaded via a namespace (and not attached):
#>  [1] Matrix_1.7-4       gtable_0.3.6       jsonlite_2.0.0     dplyr_1.1.4       
#>  [5] compiler_4.4.0     Rcpp_1.1.1         tidyselect_1.2.1   parallel_4.4.0    
#>  [9] dichromat_2.0-0.1  jquerylib_0.1.4    systemfonts_1.3.1  scales_1.4.0      
#> [13] textshaping_1.0.4  yaml_2.3.12        fastmap_1.2.0      lattice_0.22-7    
#> [17] R6_2.6.1           generics_0.1.4     knitr_1.51         htmlwidgets_1.6.4 
#> [21] tibble_3.3.1       desc_1.4.3         bslib_0.9.0        pillar_1.11.1     
#> [25] RColorBrewer_1.1-3 rlang_1.1.7        cachem_1.1.0       xfun_0.56         
#> [29] fs_1.6.6           sass_0.4.10        S7_0.2.1           otel_0.2.0        
#> [33] cli_3.6.5          withr_3.0.2        pkgdown_2.2.0      magrittr_2.0.4    
#> [37] digest_0.6.39      grid_4.4.0         lifecycle_1.0.5    vctrs_0.7.1       
#> [41] data.table_1.18.0  evaluate_1.0.5     glue_1.8.0         farver_2.1.2      
#> [45] ragg_1.5.0         rmarkdown_2.30     tools_4.4.0        pkgconfig_2.0.3   
#> [49] htmltools_0.5.9

Author

Zaoqu Liu