Skip to contents

Overview

scSidekick wraps CellChat to provide a streamlined, reproducible cell-cell communication workflow. Four functions cover the full pipeline:

Function What it does
RunCellChat() Run the full CellChat pipeline for each condition; save summary figures
CompareCellChat() Generate cross-condition comparison plots from pre-computed CellChat objects
RankCellChatPathways() Rank pathways by differential activity; flow heatmap + sender/receiver tiles
RenameCellTypeInCC() Rename a cell type label throughout a CellChat object post-hoc

All functions are designed for multi-condition studies where you want to ask “which interactions and pathways are gained or lost between Control and Treated?”

Note: scSidekick requires CellChat >= 2.1.0 (the jinworks/CellChat fork). Install with: devtools::install_github("jinworks/CellChat")


Standard setup

library(scSidekick)
library(Seurat)
library(SeuratData)
library(CellChat)
library(dplyr)

data("bmcite")
bmcite <- UpdateSeuratObject(bmcite)
bmcite <- bmcite %>%
  NormalizeData() %>% FindVariableFeatures() %>% ScaleData() %>% RunPCA()
dims <- Determine_nDims(bmcite, elbow_plot = FALSE)
bmcite <- RunUMAP(bmcite, dims = 1:dims$n_dims)
bmcite <- FindNeighbors(bmcite, dims = 1:dims$n_dims)
bmcite <- FindClusters(bmcite, resolution = 0.5)
bmcite <- PrepObject(bmcite,
  variables   = c("lane", "donor", "celltype.l1", "celltype.l2", "seurat_clusters"),
  group.by    = "celltype.l1",
  split.by    = "donor",
  output_dir  = tempdir(),
  object_name = "bmcite")

Part 1: RunCellChat

1. Basic call

RunCellChat() splits the Seurat object by the levels of group.by, builds one CellChat object per level, runs the full inference pipeline on each, and saves summary figures.

cc_results <- RunCellChat(bmcite,
  cell.by    = "celltype.l1",   # cell identity column for communication inference
  group.by   = "donor",         # one CellChat run per condition/group
  output_dir = file.path(tempdir(), "CellChat"))

cell.by defines the cell-type identity used for communication inference. group.by defines the groups run separately (typically conditions). The function returns a named list of CellChat objects, one per level of group.by.

CellChat RDS files are saved in a CellChatObjects/ subdirectory of output_dir by default.


2. Specifying groups explicitly

Use groups to run only a subset of levels or to fix the comparison order:

cc_results <- RunCellChat(bmcite,
  cell.by    = "celltype.l1",
  group.by   = "Condition",
  groups     = c("Control", "Treated"),
  output_dir = file.path(tempdir(), "CellChat"))

3. Mouse data

Set species = "mouse" to use the CellChatDB.mouse ligand-receptor database:

cc_brain <- RunCellChat(brain,
  cell.by    = "seurat_clusters",
  group.by   = "Condition",
  species    = "mouse",
  output_dir = file.path(tempdir(), "CellChat"))

4. Custom cell-type colors

Pass a named character vector to colors to override the palette used in chord diagrams and network plots. Keys must match levels of cell.by.

cluster_cols <- GetColors(bmcite, "celltype.l1")

cc_results <- RunCellChat(bmcite,
  cell.by    = "celltype.l1",
  group.by   = "Condition",
  colors     = cluster_cols,
  output_dir = file.path(tempdir(), "CellChat"))

5. Resuming an interrupted run

resume = TRUE checks robj_dir for already-completed CellChat .rds files and skips those groups, resuming from where the run stopped.

redo_plots = TRUE reloads all saved .rds files and regenerates PDFs without re-running any CellChat inference - useful after updating colors or fixing cell-type names with RenameCellTypeInCC.

# Resume an interrupted run
cc_results <- RunCellChat(bmcite,
  cell.by    = "celltype.l1",
  group.by   = "Condition",
  output_dir = file.path(tempdir(), "CellChat"),
  resume     = TRUE)

# Regenerate all PDFs from saved RDS (no re-inference)
cc_results <- RunCellChat(bmcite,
  cell.by    = "celltype.l1",
  group.by   = "Condition",
  output_dir = file.path(tempdir(), "CellChat"),
  redo_plots = TRUE)

6. Communication pattern analysis

run.patterns = TRUE (default) additionally runs identifyCommunicationPatterns to extract global signaling patterns (incoming and outgoing) using NMF. pattern_k_range controls which values of k are tested; the best k is selected automatically.

# Skip pattern analysis to save time
cc_results <- RunCellChat(bmcite,
  cell.by        = "celltype.l1",
  group.by       = "Condition",
  output_dir     = file.path(tempdir(), "CellChat"),
  run.patterns   = FALSE)

# Custom k range
cc_results <- RunCellChat(bmcite,
  cell.by        = "celltype.l1",
  group.by       = "Condition",
  output_dir     = file.path(tempdir(), "CellChat"),
  run.patterns   = TRUE,
  pattern_k_range = 2:6)

7. Outputs produced per group

For each level of group.by, RunCellChat() writes a {group}/ sub-folder under output_dir, plus the serialized CellChat object under robj_dir (output_dir/CellChatObjects by default):

File Content
CellChatObjects/{group}CellChat.rds Serialized CellChat object (final; used by redo_plots, CompareCellChat, RankCellChatPathways)
{group}/{group} Number of Interactions.pdf Circle plot: interaction counts between cell types
{group}/{group} Interaction Weights.pdf Circle plot: interaction strength (probability-weighted) between cell types
{group}/{group} Individual Groups.pdf One circle panel per sender cell type, edges scaled to the global max
{group}/Pathways/{group} {pathway} cell-cell communication.pdf One multi-panel PDF per significant pathway: (1) signaling role network, (2) hierarchy layout, (3) circle layout, (4) pathway-aggregate chord diagram, (5) gene-level ligand-receptor chord diagram (netVisual_chord_gene - one sector per ligand/receptor gene by sender/receiver cell type), (6) pairwise communication probability heatmap, (7) L-R pair contribution, (8) sender/receiver scatter
{group}/{group} {cell type} bubble plot.pdf One bubble plot per cell type as sender; dot size = communication probability, color = significance, all targets on the y-axis
{group}/{group} dominant sender receiver.pdf Scatter of outgoing vs. incoming signaling strength per cell type, aggregated across all pathways
{group}/{group} k{k} outgoing communication patterns.pdf Outgoing pattern analysis at latent pattern count k (one PDF per k in pattern_k_range, if run.patterns = TRUE)
{group}/{group} k{k} incoming communication patterns.pdf Incoming pattern analysis at latent pattern count k (one PDF per k in pattern_k_range, if run.patterns = TRUE)

Every PDF above has a matching .legend sidecar file (plain text) describing its panels - see vignette 12 (“Reporting & Utilities”) for the general sidecar convention used package-wide.


Part 2: CompareCellChat

CompareCellChat() takes a named list of CellChat objects (one per condition) and generates comparative visualizations side by side.

Pain point fixed. Two things go wrong natively. (1) When a signaling pathway is detected in one condition but absent in another, the per-pathway plot errors on conditions that lack it, so those panels are silently dropped and the absence becomes invisible. (2) Each object draws its cell groups in its own colors and order, so panels are not comparable position-for-position. CompareCellChat() puts every condition on a shared node layout with the same colors and the same group order in every panel, for every pathway present in any object. Use thresh = 1 to also compare pathways that are active at the L-R level but did not reach pathway-level significance in some conditions.

1. Basic comparison

# cc_results is the named list returned by RunCellChat()
CompareCellChat(
  cellchat_list = cc_results,
  output_dir    = file.path(tempdir(), "CellChat", "Comparison"))

2. Loading saved CellChat objects

If you previously ran RunCellChat() in a different session, reload the .rds files and build the list manually:

cc_ctrl    <- readRDS(file.path(tempdir(), "CellChat", "CellChatObjects",
                                "Control_CellChat.rds"))
cc_treated <- readRDS(file.path(tempdir(), "CellChat", "CellChatObjects",
                                "Treated_CellChat.rds"))

CompareCellChat(
  cellchat_list = list(Control = cc_ctrl, Treated = cc_treated),
  output_dir    = file.path(tempdir(), "CellChat", "Comparison"))

3. What the comparison plots show

File What it shows
Comparison_interaction_count_bar.pdf Interaction counts per cell type per condition
Comparison_interaction_strength_bar.pdf Interaction strength (probability) per cell type
Comparison_differential_heatmap.pdf Differential strength (Treated - Control); red = gained, blue = lost
Comparison_chord_gained.pdf Interactions gained or strengthened in the second condition
Comparison_chord_lost.pdf Interactions diminished or lost in the second condition
Comparison_pathway_heatmap.pdf Pathway-level NES across all conditions
Comparison_scatter_pathway.pdf x = flow (condition 1), y = flow (condition 2); deviations = changed pathways
{pathway}_comparison.pdf Per-pathway: circle plots, chord diagrams, and heatmaps for all conditions

Part 3: RankCellChatPathways

RankCellChatPathways() goes one level deeper than CompareCellChat: it ranks pathways by how much their information flow changes across conditions, then decomposes those changes into which cell types are driving them as senders and receivers.

Four outputs:

  1. Flow heatmap - top N pathways x conditions, row-normalized so color shows which condition has relatively higher activity
  2. Sender tile plot - faceted by pathway; shows how much each cell type sends per condition
  3. Receiver tile plot - same for receivers
  4. Top changed links heatmap - the sender-receiver pairs with the highest variance across conditions, showing exactly which cell-type interactions drive pathway-level changes
  5. CSV - all underlying metrics for custom analysis

1. Basic call

rank_results <- RankCellChatPathways(
  cellchat_list = cc_results,
  output_dir    = file.path(tempdir(), "CellChat", "Ranked"))

top_n controls how many pathways appear in the flow heatmap and tile plots. top_links controls how many sender-receiver pairs appear in the links heatmap. Both are ranked by differential activity (rank_by = "range" or "cv").

rank_results <- RankCellChatPathways(
  cellchat_list = cc_results,
  output_dir    = file.path(tempdir(), "CellChat", "Ranked"),
  top_n         = 30L,
  top_links     = 20L,
  rank_by       = "cv")    # coefficient of variation instead of range

3. Custom colors

Supply condition colors (for the flow heatmap strips) and cell-type colors (for the sender/receiver tile annotation strips):

cond_colors <- c(Control = "#4575b4", Treated = "#d73027")
cell_colors <- GetColors(bmcite, "celltype.l1")

rank_results <- RankCellChatPathways(
  cellchat_list = cc_results,
  output_dir    = file.path(tempdir(), "CellChat", "Ranked"),
  colors        = cond_colors,
  cell_colors   = cell_colors)

4. Return value

# Data frame: pathway x condition flow + ranking columns
head(rank_results$flow_table)

# Long data frame: which cell types send each pathway per condition
head(rank_results$sender_table)

# Long data frame: which cell types receive each pathway per condition
head(rank_results$receiver_table)

# Long data frame: sender-receiver pair flow per condition
head(rank_results$links_table)

# ggplot2 / pheatmap objects
rank_results$flow_heatmap
rank_results$sender_plot
rank_results$receiver_plot
rank_results$links_plot

Part 4: RenameCellTypeInCC

If you rename a cluster or cell type after running CellChat (e.g. to correct an annotation mistake), RenameCellTypeInCC() patches the CellChat object so the new name propagates to all internal arrays: the probability matrices, centrality scores, communication pattern tables, and LR significance tables.

Communication probabilities are not recomputed - only labels change. This is safe because the underlying values are invariant to what the cell type is called.

1. Rename in a single object

cc_fixed <- RenameCellTypeInCC(cc_ctrl,
  old_name = "Immune_contam",
  new_name  = "NK_TCells")

# Save the fixed object back
saveRDS(cc_fixed,
  file.path(tempdir(), "CellChat", "CellChatObjects", "Control_CellChat.rds"))

2. Batch rename across all conditions

The typical workflow: patch and re-save all RDS files, then regenerate comparison figures without any re-inference.

# Step 1: patch and re-save all RDS files
rds_dir   <- file.path(tempdir(), "CellChat", "CellChatObjects")
rds_files <- list.files(rds_dir, pattern = "CellChat\\.rds$", full.names = TRUE)

for (f in rds_files) {
  cc <- RenameCellTypeInCC(readRDS(f),
    old_name = "Immune_contam",
    new_name  = "NK_TCells")
  saveRDS(cc, f)
}

# Step 2: reload the fixed list and regenerate comparison figures
cclist <- setNames(
  lapply(rds_files, readRDS),
  sub("_CellChat\\.rds$", "", basename(rds_files))
)

CompareCellChat(cclist,
  output_dir = file.path(tempdir(), "CellChat", "Comparison"))

RankCellChatPathways(cclist,
  output_dir = file.path(tempdir(), "CellChat", "Ranked"))

# Step 3: regenerate per-group RunCellChat PDFs (plots only, no re-inference)
RunCellChat(bmcite,
  cell.by    = "celltype.l1",
  group.by   = "Condition",
  output_dir = file.path(tempdir(), "CellChat"),
  redo_plots = TRUE)

Typical two-condition workflow

out_dir <- file.path(tempdir(), "CellChat")

# Step 1: run CellChat per condition
cc_results <- RunCellChat(bmcite,
  cell.by    = "celltype.l1",
  group.by   = "Condition",
  groups     = c("Control", "Treated"),
  colors     = GetColors(bmcite, "celltype.l1"),
  output_dir = out_dir,
  resume     = TRUE)

# Step 2: cross-condition comparison
CompareCellChat(
  cellchat_list = cc_results,
  output_dir    = file.path(out_dir, "Comparison"))

# Step 3: pathway ranking
RankCellChatPathways(
  cellchat_list = cc_results,
  output_dir    = file.path(out_dir, "Ranked"),
  top_n         = 20L)

Parameter reference - RunCellChat

Parameter Type Default Description
seurat_object Seurat required Processed, annotated Seurat object
cell.by character required Metadata column defining cell identity
group.by character required Metadata column defining groups (one run per level)
groups character vector NULL Subset or reorder levels of group.by
species character "human" "human" or "mouse"
colors named character NULL Override cell-type color palette
output_dir character required Root directory for saving outputs
robj_dir character or NULL NULL Directory for CellChat RDS files; defaults to output_dir/CellChatObjects/
min.cells integer 0 Minimum cells a group must have to be included
thresh.p numeric 0.05 P-value threshold for CellChat communication inference
run.patterns logical TRUE Run communication pattern NMF analysis
pattern_k_range integer vector 3:10 Range of k values for NMF pattern selection
save.rds logical TRUE Save CellChat objects as RDS files
resume logical FALSE Skip groups with existing RDS files
redo_plots logical FALSE Reload saved RDS and regenerate PDFs only
assay_type character or NULL NULL Seurat assay to extract counts from
caffeinate logical FALSE Prevent system sleep during the run

Parameter reference - CompareCellChat

Parameter Type Default Description
cellchat_list named list required Named list of CellChat objects or paths to .rds files
output_dir character required Directory for saving comparison plots
groups.show character vector NULL Subset of conditions to include
group.merged character NULL Merge these conditions before comparison
colors named character NULL Override cell-type palette
species character "human" "human" or "mouse"
thresh numeric 0.05 P-value threshold; use 1 to include all pathways
caffeinate logical FALSE Prevent system sleep

Parameter reference - RankCellChatPathways

Parameter Type Default Description
cellchat_list named list required Named list of CellChat objects or paths to .rds files
output_dir character or NULL NULL Directory for PDFs and CSV; NULL = return objects only
top_n integer 20 Number of top pathways in flow heatmap and tile plots
top_links integer 15 Number of top sender-receiver pairs in links heatmap
rank_by character "range" Ranking metric: "range" (max - min flow) or "cv" (coefficient of variation)
colors named character NULL Condition colors for heatmap annotation strips
cell_colors named character NULL Cell-type colors for sender/receiver tile annotation

Parameter reference - RenameCellTypeInCC

Parameter Type Default Description
cc CellChat required CellChat object to modify
old_name character required Cell type label to replace
new_name character required Replacement label

See also

  • Vignette 01: PrepObject - register cell-type colors used in chord diagrams
  • Vignette 06: CellTypeAssignmentHelper - assign cell types before CellChat
  • Vignette 08: RunGSEA - pathway-level gene set enrichment
  • Vignette 09: RunGSEA_pseudobulk - sample-level pseudobulk pathway analysis

Session info