| name | single-cell-cellphonedb-communication-mapping |
| title | Single-cell CellPhoneDB communication mapping |
| description | CellPhoneDB v5 ligand-receptor analysis, cell-cell communication networks, and CellChat-style visualization in OmicVerse. |
Single-cell CellPhoneDB communication mapping
Overview
Apply this skill when a user wants to quantify ligand–receptor communication between annotated single-cell populations and display the networks with CellChatViz. It distils the workflow from t_cellphonedb.ipynb, which analyses EVT trophoblast data.
Instructions
- Prepare the environment
- Use an environment with
omicverse>=0.2, scanpy, anndata, pandas, matplotlib, and cellphonedb resources. The tutorial assumes the pre-built CellPhoneDB v5 SQLite bundle downloaded as cellphonedb.zip in the working directory.
- Activate omicverse plotting defaults via
ov.plot_set() so that downstream figures follow the project palette.
- Load and subset the annotated AnnData object
- Load a local AnnData export prepared from the tutorial inputs; the public tutorial page documents the example CellPhoneDB dataset and expected preprocessing before running
adata = ov.read(...).
- Filter to the cell populations of interest using
adata.obs['cell_labels'] (e.g., EVT, dNK, VCT). Ensure adata.obs['cell_labels'] is categorical and free of missing values so CellPhoneDB groups cells correctly.
- Confirm values are log-normalised (
adata.X.max() should be <10 and non-integer); raw counts inflate CellPhoneDB permutations.
- Run CellPhoneDB via omicverse
- Execute
ov.single.run_cellphonedb_v5 with the curated AnnData and metadata column:
cpdb_results, adata_cpdb = ov.single.run_cellphonedb_v5(
adata,
cpdb_file_path='./cellphonedb.zip',
celltype_key='cell_labels',
min_cell_fraction=0.005,
min_genes=200,
min_cells=3,
iterations=1000,
threshold=0.1,
pvalue=0.05,
threads=10,
output_dir='./cpdb_results',
cleanup_temp=True,
)
- Persist the outputs for reuse (
ov.utils.save(cpdb_results, ...), adata_cpdb.write(...)). Saving avoids recomputing permutations.
- Initialise CellChat-style visualisation
- Create a colour dictionary that maps ordered
cell_labels categories to adata.uns['cell_labels_colors'] from previous plots.
- Instantiate the viewer:
viz = ov.pl.CellChatViz(adata_cpdb, palette=color_dict). Inspect adata_cpdb to ensure communication slots (uns/obsm) were populated.
- Summarise global communication
- Derive aggregated counts/weights with
viz.compute_aggregated_network(pvalue_threshold=0.05, use_means=True).
- Plot overall interaction strength and counts using
viz.netVisual_circle(...) with matching figure sizes and colormaps.
- Generate outgoing/incoming per-celltype circles using
viz.netVisual_individual_circle and viz.netVisual_individual_circle_incoming to highlight senders versus receivers.
- Interrogate specific pathways
- Compute pathway summaries:
pathway_comm = viz.compute_pathway_communication(method='mean', min_lr_pairs=2, min_expression=0.1).
- Identify significant signalling routes with
viz.get_significant_pathways_v2(...), then plot selected pathways using viz.netVisual_aggregate(..., layout='circle'), viz.netVisual_chord_cell(...), or viz.netVisual_heatmap_marsilea(...).
- For ligand–receptor focus, call
viz.netVisual_chord_LR(...) or viz.netAnalysis_contribution(pathway) to surface dominant pairs.
- System-level visualisations
- Compose bubble summaries for multiple pathways with
viz.netVisual_bubble_marsilea(...), optionally restricting sources_use/targets_use.
- Display gene-level chords via
viz.netVisual_chord_gene(...) to inspect signalling directionality.
- Evaluate signalling roles using
viz.netAnalysis_computeCentrality(), viz.netAnalysis_signalingRole_network_marsilea(...), viz.netAnalysis_signalingRole_scatter(...), and viz.netAnalysis_signalingRole_heatmap(...) for incoming/outgoing programmes.
- Defensive validation
assert celltype_key in adata.obs.columns, f"Column '{celltype_key}' not found in adata.obs"
adata.obs[celltype_key] = adata.obs[celltype_key].astype('category').cat.remove_unused_categories()
assert not adata.obs[celltype_key].isna().any(), f"NaN values in '{celltype_key}' — clean before running CellPhoneDB"
min_per_group = adata.obs[celltype_key].value_counts().min()
if min_per_group < 10:
print(f"WARNING: smallest cell group has {min_per_group} cells — may cause permutation failures")
- Troubleshooting tips
- Metadata alignment: CellPhoneDB requires a categorical
celltype_key. If the column contains spaces, mixed casing, or NaN, clean it (adata.obs['cell_labels'] = adata.obs['cell_labels'].astype('category').cat.remove_unused_categories()).
- Database bundle:
cpdb_file_path must point to a full CellPhoneDB v5 SQLite zip. If omicverse raises FileNotFoundError or missing receptor tables, re-download the bundle from the official release and ensure the zip is not corrupted.
- Permutation failures: Low cell counts per group (<
min_cells) cause early termination. Increase min_cell_fraction thresholds or merge sparse clusters before rerunning.
- Palette mismatches: When colours render incorrectly, rebuild
color_dict from adata.uns['cell_labels_colors'] after sorting categories to keep nodes and legends consistent.
Examples
- "Run CellPhoneDB on our trophoblast dataset and export both the cpdb results pickle and processed AnnData."
- "Highlight significant 'Signaling by Fibroblast growth factor' interactions with chord and bubble plots."
- "Generate outgoing versus incoming communication circles to compare dNK subsets."
References