Archetype Crosstalk Network#
Adapted from [AMG+23]
Packages#
To run this notebook, install ParTIpy with the tutorial extras: pip install partipy[extra].
import scanpy as sc
import liana as li
import partipy as pt
from partipy.datasets import load_fibroblast_data
from partipy.crosstalk import get_specific_genes_per_archetype, get_archetype_crosstalk, plot_weighted_network
Data#
Here we use the data from [MGenoveL+20].
adata = load_fibroblast_data(verbose=True, )
Loading processed data from data/fibroblast_muhl_processed.h5ad
adata = load_fibroblast_data()
sc.pp.normalize_total(adata)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata)
sc.pp.pca(adata, mask_var="highly_variable", n_comps=50)
adata.layers["z_scaled"]= sc.pp.scale(adata.X, max_value=10, copy=True) # save this for later
sc.pl.pca_scatter(adata, color=["Bmp7", "Wnt2"])
Based on the PCA scree plot, we will be using 8 PC dimensions to fit the archetypes.
sc.pl.pca_variance_ratio(adata, n_pcs=50)
pt.set_obsm(adata=adata, obsm_key="X_pca", n_dimensions=8)
pt.compute_selection_metrics(adata=adata, n_archetypes_list=range(2, 10))
pt.plot_var_explained(adata).show()
pt.compute_bootstrap_variance(adata, n_bootstrap=30, n_archetypes_list=range(2, 10))
pt.plot_bootstrap_variance(adata)
Here, we will use 5 archetypes. When fitting 4 archetypes we have observed that running archetypal analysis on bootstrapped data shows that one archetype is quite unstable, whereas using 5 worked much better.
Determine which genes are characteristic for each archetype
pt.compute_archetype_weights(adata=adata, mode="automatic", result_filters={"n_archetypes": 6})
pseudobulk = pt.compute_archetype_expression(adata=adata, layer="z_scaled", result_filters={"n_archetypes": 6})
arch_idx = 2
adata.obs[f"weights_archetype_{arch_idx}"] = pt.get_aa_cell_weights(adata, n_archetypes=6)[:, arch_idx]
pt.plot_archetypes_2D(adata=adata, color=f"weights_archetype_{arch_idx}", result_filters={"n_archetypes": 6})
specific_genes_per_archetype = get_specific_genes_per_archetype(archetype_expression=pseudobulk, min_score=0.05)
[(arch_id, len(arch_genes)) for arch_id, arch_genes in specific_genes_per_archetype.items()]
[(0, 489), (1, 911), (2, 2064), (3, 1793), (4, 6307), (5, 6174)]
Based on the genes we infer the functions of each archetype
for i in range(len(specific_genes_per_archetype)):
print(i, specific_genes_per_archetype[i].head(25)["gene"].to_list())
0 ['Serping1', 'Bcl6', 'Selenop', 'C1qtnf3', 'Gm16559', 'Ms4a4d', 'Cxcl12', 'Edil3', 'Itm2b', 'Gm15635', 'Mfap4', 'Gm16263', 'Rarres2', 'Gask1b', 'Zfp808', 'Zmynd15', 'Lrrc61', 'Sfrp1', 'Hpse2', 'Fbln1', 'C1rb', 'Sod3', 'Icosl', 'Serpina3n', 'Rax']
1 ['Lmod1', 'Cnn1', 'Actg2', 'Pdgfc', 'Cdh6', 'Itga8', 'Asb2', 'Myocd', 'Kcnmb1', 'Acta1', 'Trpc6', 'Tnfrsf19', 'Slc2a4', 'Hspb7', 'Myh11', 'Tspan2', 'Gm16000', 'Pde6h', 'Tagln', 'Ctxn1', 'Ptk2b', 'Chrdl2', 'Pcp4l1', 'Cacna1h', 'E030013I19Rik']
2 ['Cd38', '1700071M16Rik', 'Nrg1', 'Lef1', 'Lpar3', 'Trpa1', 'Lef1os1', 'Ptprr', 'Pla2g7', 'Rab3b', 'Lama5', 'Cdhr17', 'Ano2', 'Tbx3', 'Glp2r', 'Cd300e', 'C5ar1', 'Ednrb', 'Sema4d', 'Abcc4', 'Col6a4', 'Paqr5', 'Eva1a', 'Insc', 'Plau']
3 ['Efnb2', 'Gm42721', 'Pde1c', 'Gm31258', '1700082M22Rik', 'Gm42785', 'Gm37515', 'Ugcg', 'Gm4117', 'Gm37954', 'Bmp3', 'Gm42513', 'Ryr3', 'Gm43577', 'Gm44153', 'Pkib', 'Kcnq1ot1', 'Gm37086', 'Macrod2os1', 'Ksr2', 'Gm37315', 'Gm42635', 'Mir6240', 'Ddx17', 'Gm17131']
4 ['Sox18', 'Mmrn2', 'Robo4', 'Ushbp1', 'Tie1', 'Plvap', 'Flt1', 'Emcn', 'Kdr', 'Egfl7', 'Podxl', 'Cd300lg', 'Dll4', 'Depp1', 'Fabp4', 'Adgrl4', 'Gata2', 'Apold1', 'Mmp3', 'Gimap6', 'Ramp3', 'Sox17', 'Fam110d', 'Gpnmb', 'Car4']
5 ['Efhd1os', 'Efhd1', 'Gm16083', '1700019D03Rik', 'Sema3c', 'Npy1r', 'Adgrg2', 'Cmah', 'Ebf1', 'Tnfrsf11b', 'Cd55', 'Pcolce2', 'Mfap5', 'Adamts5', 'Lrrn4cl', 'Anxa3', 'Tek', 'Nhsl1', 'Ackr4', 'Pi16', 'Fbn1', 'Flrt2', 'Creb5', 'Cadm3', 'Gm12043']
archetype_functions = {
0: "ECM-remodeling fibroblasts",
1: "Vascular-associated fibroblasts",
2: "Neuronal/epithelial-interacting fibroblasts",
3: "Myofibroblasts",
4: "Immune-modulatory fibroblasts"
}
Finally we use LIANA+ to infer ligand and receptor are enriched between archetypes.
mouse_resource = li.rs.select_resource("mouseconsensus")
mouse_resource
| ligand | receptor | |
|---|---|---|
| 31371 | Dll1 | Notch1 |
| 31372 | Dll1 | Notch2 |
| 31373 | Dll1 | Notch4 |
| 31374 | Dll1 | Notch3 |
| 31375 | Nrg2 | Erbb2_Erbb3 |
| ... | ... | ... |
| 35355 | Serpina1a | Lrp1 |
| 35356 | Serpina1b | Lrp1 |
| 35357 | Serpina1c | Lrp1 |
| 35358 | Serpina1d | Lrp1 |
| 35359 | Serpina1e | Lrp1 |
3989 rows × 2 columns
archetype_crosstalk = get_archetype_crosstalk(archetype_genes=specific_genes_per_archetype,
lr_resource=mouse_resource)
for sender_arch in archetype_crosstalk.keys():
for receiever_arch in archetype_crosstalk[sender_arch].keys():
print(f"{sender_arch} -> {receiever_arch}: {len(archetype_crosstalk[sender_arch][receiever_arch])}")
break
0 -> 0: 3
0 -> 1: 7
0 -> 2: 14
0 -> 3: 3
0 -> 4: 15
0 -> 5: 23
plot_weighted_network(
specific_genes_per_archetype=specific_genes_per_archetype,
archetype_crosstalk_dict=archetype_crosstalk,
layout="shell",
seed=42,
)
Session Info#
import session_info2
print(session_info2.session_info(dependencies=True))
pandas 2.2.3
plotnine 0.14.5
scanpy 1.11.2
liana 1.5.1
partipy 0.0.5 (0.0.1)
anndata 0.11.4
---- ----
narwhals 1.41.0
pillow 11.2.1
statsmodels 0.14.4
ipython 9.2.0
Deprecated 1.2.18
pydantic 2.12.0
annotated-types 0.7.0
networkx 3.5
numpy 2.2.6
numcodecs 0.15.1
six 1.17.0
pyparsing 3.2.3
cycler 0.12.1
requests-cache 1.2.1
colorama 0.4.6
dask 2024.11.2
executing 2.2.0
llvmlite 0.44.0
traitlets 5.14.3
requests 2.32.3
decorator 5.2.1
mudata 0.3.2
asttokens 3.0.0
xarray 2024.11.0
jupyter_client 8.6.3
typing_extensions 4.15.0
h5py 3.13.0
packaging 25.0
PyYAML 6.0.2
matplotlib-inline 0.1.7
mizani 0.13.5
legacy-api-wrap 1.4.1
crc32c 2.7.1
tqdm 4.67.1
typing-inspection 0.4.2
pydantic_core 2.41.1
tornado 6.5.1
importlib_metadata 8.7.0
idna 3.10
coverage 7.10.7
prompt_toolkit 3.0.51
wcwidth 0.2.13
numba 0.61.2
jedi 0.19.2
ipywidgets 8.1.7
future 1.0.0
cattrs 24.1.3
debugpy 1.8.14
asciitree 0.3.3
kiwisolver 1.4.8
pyzmq 26.4.0
pytz 2025.2
zarr 2.18.7
zipp 3.22.0
stack-data 0.6.3
Pygments 2.19.1
cloudpickle 3.1.1
pybiomart 0.2.0
psutil 7.0.0
docrep 0.3.2
scipy 1.15.2
plotly 6.1.2
platformdirs 4.3.8
jupyter_core 5.8.1
python-dateutil 2.9.0.post0
setuptools 80.8.0
certifi 2025.4.26 (2025.04.26)
comm 0.2.2
ipykernel 6.29.5
url-normalize 2.2.1
joblib 1.5.1
natsort 8.4.0
charset-normalizer 3.4.2
threadpoolctl 3.6.0
patsy 1.0.1
session-info2 0.1.2
pyarrow 20.0.0
parso 0.8.4
pure_eval 0.2.3
matplotlib 3.10.3
urllib3 2.4.0
scikit-learn 1.6.1
appnope 0.1.4
toolz 1.0.0
wrapt 1.17.2
attrs 25.3.0
---- ----
Python 3.11.0 | packaged by conda-forge | (main, Jan 14 2023, 12:26:40) [Clang 14.0.6 ]
OS macOS-15.7.1-arm64-arm-64bit
Updated 2025-11-11 09:12