PopComm (Population-Level Cell–Cell Communication Analysis Tools) is a computational framework designed to quantify sample-level ligand–receptor (LR)–mediated cell–cell communication from human large-scale single-cell and single-nucleus RNA-seq datasets. It infers LR interactions between sender/receiver cell types, computes per-sample communication strength, and supports association with phenotypes (e.g., aging, disease) as well as comprehensive visualization.
PopComm is available in R and Python. It uses a human LR database by default, but users can easily swap it for a species-specific database (e.g., mouse) to suit their research needs.

PopComm provides three primary modules for population-scale cell–cell communication analysis:
Install the PopComm R package from CRAN (stable) or GitHub (development version):
# Stable version (CRAN - Windows/macOS/Linux)
install.packages("PopComm")
# Development version (GitHub - Windows/macOS/Linux)
# install.packages("devtools") # If not already installed
# devtools::install_github("JusticeGO/PopComm")
install.packages("PopComm", repos = c('https://justicego.r-universe.dev', 'https://cloud.r-project.org'))
The Python version of PopComm (available on PyPI) mirrors the R workflow (filter → score → visualize):
# Stable Version (PyPI)
pip install PopComm
Prepare single-cell or single-nucleus RNA-seq data plus an LR database table. PopComm works in Seurat mode or Matrix mode.
rna: A Seurat object (v4+) or a matrix of scRNA/snRNA-seq expression.lr_database: A data.frame with columns ligand_gene_symbol and receptor_gene_symbol.sender and receiver (Optional): Cell type designated as the ligand sender and the receptor receiver.Gene identifiers: Must match the LR database (e.g., HGNC for human, MGI for mouse); keep naming/case consistent.
rna@meta.data:
sample_col: column name for sample IDs (e.g., "sample").cell_type_col: column name for cell type (e.g., "cell_type").min_cells: minimum cells per (sample × cell type).min_cell_ratio: fraction of cells expressing the ligand/receptor within sender/receiver.Cardiomyocyte--sample_01, Fibroblast--sample_02.id_sep: the separator string (e.g., "--").cell_type_col, sample_col: numeric positions after splitting the column name by id_sep
(e.g., for "Cardiomyocyte--sample_01", use cell_type_col=1, sample_col=2).min_cells and min_cell_ratio apply to Seurat mode, not Matrix mode.min_samples: minimum valid samples to proceed.min_sample_ratio: fraction of samples where both ligand and receptor are expressed.cor_method: "spearman" (default), "pearson", or "kendall".adjust_method: multiple-testing correction (default "BH").min_adjust_p: adjusted p-value cutoff.min_cor, min_r2, min_fstat: optional thresholds on correlation and regression quality.num_cores: CPU cores for parallelization. Automatically capped at max(1, {system_cores} - 1) if overspecified.verbose: progress messages.sample column matching the sample IDs used above.See the CRAN reference manual for full details. Example below uses Perivascular → Endothelial in Matrix mode.
# Load package and example data
library(PopComm)
data(matrix_object) # example column name: "Endothelial--sample01"
data(lr_db)
Filter LR pairs and compute correlations for Perivascular -> Endothelial
filtered_lr <- filter_lr_single(
rna = matrix_object,
sender = "Perivascular",
receiver = "Endothelial",
lr_database = lr_db,
cell_type_col = 1, # after splitting colnames by id_sep, cell type is part 1
sample_col = 2, # sample is part 2
id_sep = "--",
min_samples = 10,
min_sample_ratio = 0.1,
cor_method = "spearman",
adjust_method = "BH",
min_adjust_p = 0.05,
min_cor = 0,
min_r2 = 0,
min_fstat = 0,
num_cores = 10,
verbose = TRUE
)
if (is.null(filtered_lr) || nrow(filtered_lr) == 0L) {
stop("No LR pairs passed filters for Perivascular -> Endothelial.")
}
head(filtered_lr)
If you don’t specify a
senderandreceiver, usefilter_lr_all()to analyze all sender–receiver combinations.
Output (
filtered_lr)
ligand,receptor— ligand and receptor gene symbolscor,p_val,adjust.p— correlation and p-valuessender,receiver— sender and receiver cell typesslope,intercept,r2,fstat— regression metrics
Rows are ordered by ascending
adjust.pand then descendingcor.
Compute per-sample LR projection scores using the filtered pairs
lr_scores <- score_lr_single(
rna = matrix_object,
sender = "Perivascular",
receiver = "Endothelial",
filtered_lr = filtered_lr,
cell_type_col = 1,
sample_col = 2,
id_sep = "--",
num_cores = 10,
verbose = TRUE
)
if (is.null(lr_scores) || nrow(lr_scores) == 0L) {
stop("No LR scores returned; check filters and inputs.")
}
head(lr_scores)
If you used
filter_lr_all()in the previous step, usescore_lr_all()here.
Output (
lr_scores)
- Inherits key columns from
filtered_lr(ligand/receptor/sender/receiver, etc.)sample— sample identifierscore— raw projection scorenormalized_score— 0–1 scaled score
Rows are ordered by the
filtered_lrkeys and descendingscore.
Run filtering + scoring in one call
res_single <- one_step_single(
rna = matrix_object,
sender = "Perivascular",
receiver = "Endothelial",
lr_database = lr_db,
cell_type_col = 1,
sample_col = 2,
id_sep = "--",
min_samples = 10,
min_sample_ratio = 0.1,
cor_method = "spearman",
adjust_method = "BH",
min_adjust_p = 0.05,
num_cores = 10,
verbose = TRUE
)
if (!is.null(res_single)) {
lapply(res_single, head) # res1 (LR stats), res2 (sample scores)
}
For all sender–receiver combinations, use
one_step_all(). Returns two data frames:res1(LR statistics) andres2(per-sample scores). ReturnsNULLif required cell types/samples are missing or no LR pairs pass thresholds.
PopComm includes views such as circular networks, dot plots, heatmaps, PCA, and box/violin or scatter/line for associations.
Prepare
metadata: a data.frame with asamplecolumn matchinglr_scores$sample, plus variables to analyze.
# Load package and example data
library(PopComm)
data(filtered_lr_eg)
data(lr_scores_eg)
data(metadata_eg)
circle_plotPlots a circular LR interaction network with curved directed edges. Nodes are arranged in a circle, and edge widths and colors represent interaction strengths.
p_net <- circle_plot(
filtered_lr = filtered_lr_eg,
edge_width = "count", # <character> one of c("count", "cor")
node_colors = NULL,
show_self_interactions = TRUE,
cutoff = 0
)
print(p_net)
dot_plotThis function generates a dot plot to visualize LR interaction. Dot sizes are scaled by the correlation coefficient and dot colors represent -log10(adjust.p). The function supports plotting the top interactions per sender-receiver pair or user-specified LR pairs.
p_dot <- dot_plot(
filtered_lr = filtered_lr_eg,
top_n = 5,
axis ="LR-SR", # <character> one of c("LR-SR", "SR-LR")
type_scale = "size", # <character> one of c("size", "radius")
selected_LR = NULL
)
print(p_dot)
heatmap_sampleThis function generates a heatmap to visualize the LR interaction scores across samples. Rows represent LR pairs and columns represent samples. Optionally, sample metadata can be used to annotate the columns. Hierarchical clustering of samples and LRSR features was performed using 1 − Spearman correlation as the distance measure (pairwise.complete.obs) and average linkage, unless otherwise specified.
p_hm <- heatmap_sample(
lr_scores = lr_scores_eg,
metadata = metadata_eg,
score = "normalized", # <character> one of c("normalized", "raw")
selected_sender = "Endothelial",
selected_receiver = "Perivascular",
selected_metadata = c("Sex", "Age_group", "IFN_type"),
treeheight_row = 50,
treeheight_col = 50,
show_LR = FALSE,
show_sample = FALSE,
basic_title = NULL,
dist_method = "correlation", # <character> one of c("correlation", "euclidean")
clustering_method = "average" # <character> one of c("average", "complete", "ward.D2", "single", "mcquitty", "median", "centroid")
)
print(p_hm)
pca_sampleThis function performs principal component analysis (PCA) on LR interaction scores across samples, and generates a scatter plot of the first two principal components. Optionally, sample metadata can be used to color the points.
pca_res <- pca_sample(
lr_scores = lr_scores_eg,
metadata = metadata_eg,
selected_sender = NULL,
selected_receiver = NULL,
color_by = "IFN_type",
n_components = 2
)
print(pca_res$plot)
head(pca_res$df)
boxplot_lr_group_comparison (discrete variable)This function generates a boxplot comparing LR interaction scores across sample groups with optional significance testing (t-test or Wilcoxon).
p_box <- boxplot_lr_group_comparison(
lr_scores = lr_scores_eg,
metadata = metadata_eg,
ligand = "PSAP",
receptor = "LRP1",
sender = "Perivascular",
receiver = "Fibroblast",
group_by = "IFN_type",
score = "normalized", # <character> one of c("normalized", "raw")
show_counts = TRUE,
test = TRUE,
paired = FALSE,
test_method = "wilcox.test" # <character> one of c("wilcox.test", "t.test")
stat_label = "p.signif" # <character> one of c("p.signif", "p.format", "p.value", "none")
colors = c("#5fa9d1", "#154778"),
title = NULL
)
print(p_box$plot)
head(p_box$df)
dotplot_lr_continuous_group (continuous variable)This function creates a dotplot (scatter plot) of LR interaction scores against a continuous variable with optional regression line.
p_scatter <- dotplot_lr_continuous_group(
lr_scores = lr_scores_eg,
metadata = metadata_eg,
ligand = "HLA-A",
receptor = "LILRB2",
sender = "Lymphoid",
receiver = "Myeloid",
group_by = "IFNscore",
score = "normalized", # <character> one of c("normalized", "raw")
point_size = 3,
point_color = "dodgerblue4",
add_regression = TRUE,
title = NULL
)
print(p_scatter$plot)
head(p_scatter$df)
num_cores automatically capped at max(1, {system_cores} - 1) if overspecified.sample_col/cell_type_col are numeric positions after splitting column names by id_sep.sample_col/cell_type_col; min_cells/min_cell_ratio are Seurat-only.filter_lr_all() / score_lr_all() / one_step_all().PopComm supports using curated LR tables. This package uses the CellTalkDB resource as the default LR database for human (and optionally mouse) LR interactions.
data.frame/table with at least two columns: ligand_gene_symbol and receptor_gene_symbol.lr_database.Q1. What advantages does PopComm offer over single-sample communication tools?
Q2. Can I analyze a specific sender–receiver pair only?
Q3. Does PopComm work with non-human data?
PopComm: A Population-Scale Single-Cell Atlas of the Human Heart Reveals Cellular Remodeling and Cell–Cell Communication in Aging and Cardiac Disease (Submission in progress)
Database Source: We thanks the CellTalk Database developed by Professor Xiaohui Fan. If you use the default LR database in PopComm, please also cite the orignal paper of CellTalkDB: Shao X., Liao J., Li C., et al. CellTalkDB: A manually curated database of ligand-receptor interactions in human and mouse. Briefings in Bioinformatics (2021).
PopComm is released under the MIT License. If you distribute an LR database derived from third-party resources (e.g., CellTalkDB), please respect their terms and acknowledge/cite those resources.