Intercellular Context Factorization with MOFA

Background

Here, we will adapt the statistical framework of multi-omics factor analysis (MOFA) to obtain intercellular communication programmes - in the form of ligand-receptor interaction scores observed to change across samples. This application of MOFA is inspired by and is in line with the factorization proposed by Tensor-cell2cell Armingol and Baghdassarian et al., 2022 - see existing tutorial.

Such factorization approaches essentially enable us to decipher context-driven intercellular communication by simultaneously accounting for an unlimited number of “contexts” in an untargeted manner. Similarly to Tensor-cell2cell, this application of MOFA is able to handle cell-cell communication results coming from any experimental design, regardless of its complexity.

Simply put, we will use LIANA’s output by sample to build a multi-view structure represented by samples and interactions by cell type pairs (views). We will then use MOFA+ to capture the CCC patterns across samples. To do so, we combine liana with the MuData/muon infrastructure.

Load Packages

mofa, decoupler, and omnipath can be installed via pip with the following commands:

pip install decoupler
pip install mofax
pip install muon
pip install omnipath
[1]:
import numpy as np
import pandas as pd

import scanpy as sc

import plotnine as p9

import liana as li

# load muon and mofax
import muon as mu
import mofax as mofa

import decoupler as dc
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html

Load & Prep Data

As a simple example, we will look at ~25k PBMCs from 8 pooled patient lupus samples, each before and after IFN-beta stimulation (Kang et al., 2018; GSE96583). Note that by focusing on PBMCs, for the purpose of this tutorial, we assume that coordinated events occur among them.

This dataset is downloaded from a link on Figshare; preprocessed for pertpy.

[2]:
adata = li.testing.datasets.kang_2018()
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/testing/datasets.py:36: FutureWarning: The behavior of Series.replace (and DataFrame.replace) with CategoricalDtype is deprecated. In a future version, replace will only be used for cases that preserve the categories. To change the categories, use ser.cat.rename_categories instead.
[3]:
adata
[3]:
AnnData object with n_obs × n_vars = 24673 × 15706
    obs: 'nCount_RNA', 'nFeature_RNA', 'tsne1', 'tsne2', 'condition', 'cluster', 'cell_type', 'patient', 'nCount_SCT', 'nFeature_SCT', 'integrated_snn_res.0.4', 'seurat_clusters', 'sample', 'cell_abbr'
    var: 'name'
    obsm: 'X_pca', 'X_umap'
    layers: 'counts'

Define columns of interest from .obs

Note that we use cell abbreviations because MOFA will use them as labels for the views.

[4]:
sample_key = 'sample'
condition_key = 'condition'
groupby = 'cell_abbr'

Basic Preparation

Note that this data has been largely pre-processed & annotated, we refer the user to the Quality Control and other relevant chapters from the best-practices book for information about pre-processing and annotation steps.

[5]:
# filter cells and genes
sc.pp.filter_cells(adata, min_genes=200)
sc.pp.filter_genes(adata, min_cells=3)
# log1p normalize the data
sc.pp.normalize_total(adata)
sc.pp.log1p(adata)

Showcase the data

[6]:
# Show pre-computed UMAP
sc.pl.umap(adata, color=[condition_key, sample_key, 'cell_type', groupby], frameon=False, ncols=2)
... storing 'sample' as categorical
../_images/notebooks_mofatalk_16_1.png

Ligand-Receptor Inference by Sample

Before we decompose the CCC patterns across contexts/samples with MOFA, we first need to run liana on each sample. To do so, liana provides a utility function called by_sample that runs each method in LIANA on each sample within the AnnData object, and returns a long-format pandas.DataFrame with the results.

In this example, we will use liana’s rank_aggregate method, which provides a robust rank consensus that combines the predictions of multiple ligand-receptor methods. Nevertheless, any other method can be used.

[7]:
li.mt.rank_aggregate.by_sample(
    adata,
    groupby=groupby,
    sample_key=sample_key, # sample key by which we which to loop
    expr_prop = 0.1,
    use_raw=False,
    n_perms=100, # reduce permutations for speed
    return_all_lrs=False, # we don't return all LR values to utilize MOFA's flexible views
    verbose=True, # use 'full' to show all information
    )
Now running: ctrl&101:   0%|          | 0/16 [00:00<?, ?it/s]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: ctrl&107:   6%|▋         | 1/16 [00:03<00:57,  3.84s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: ctrl&1015:  12%|█▎        | 2/16 [00:07<00:51,  3.65s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: ctrl&1016:  19%|█▉        | 3/16 [00:11<00:52,  4.07s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: ctrl&1039:  25%|██▌       | 4/16 [00:15<00:48,  4.06s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: ctrl&1244:  31%|███▏      | 5/16 [00:19<00:42,  3.88s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: ctrl&1256:  38%|███▊      | 6/16 [00:23<00:40,  4.07s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: ctrl&1488:  44%|████▍     | 7/16 [00:28<00:37,  4.21s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: stim&101:  50%|█████     | 8/16 [00:32<00:34,  4.29s/it] /home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: stim&107:  56%|█████▋    | 9/16 [00:37<00:29,  4.26s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: stim&1015:  62%|██████▎   | 10/16 [00:40<00:24,  4.05s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: stim&1016:  69%|██████▉   | 11/16 [00:45<00:20,  4.19s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: stim&1039:  75%|███████▌  | 12/16 [00:49<00:16,  4.13s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: stim&1244:  81%|████████▏ | 13/16 [00:52<00:11,  3.99s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: stim&1256:  88%|████████▊ | 14/16 [00:56<00:08,  4.00s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: stim&1488:  94%|█████████▍| 15/16 [01:01<00:04,  4.07s/it]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:148: ImplicitModificationWarning: Trying to modify attribute `.obs` of view, initializing view as actual.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/_pipe_utils/_pre.py:151: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/liana/method/sc/_liana_pipe.py:256: ImplicitModificationWarning: Setting element `.layers['scaled']` of view, initializing view as actual.
Now running: stim&1488: 100%|██████████| 16/16 [01:05<00:00,  4.10s/it]

Check results

[8]:
adata.uns["liana_res"].sort_values("magnitude_rank").head()
[8]:
sample source target ligand_complex receptor_complex lr_means cellphone_pvals expr_prod scaled_weight lr_logfc spec_weight lrscore specificity_rank magnitude_rank
5806 ctrl&1039 FGR3 CD14 TIMP1 CD63 2.547695 0.0 5.674415 1.301281 1.767435 0.104337 0.981838 0.014324 0.000002
15798 stim&1015 NK NK B2M KLRD1 2.471536 0.0 2.552514 1.650699 0.789530 0.096218 0.977725 0.032177 0.000002
22885 stim&1256 NK NK B2M KLRD1 2.561136 0.0 2.982985 1.479990 0.931471 0.089038 0.979089 0.032345 0.000003
7899 ctrl&1244 FGR3 CD14 TIMP1 CD63 2.504210 0.0 5.661785 1.703509 2.209408 0.116978 0.985015 0.001211 0.000004
1399 ctrl&107 FGR3 CD14 TIMP1 CD63 2.544711 0.0 5.852476 1.065290 1.678028 0.104096 0.982827 0.008478 0.000004
[9]:
adata.uns["liana_res"]['source'].unique()
[9]:
array(['FGR3', 'CD14', 'NK', 'CD8T', 'B', 'DCs', 'CD4T'], dtype=object)

Note

by_sample

We see that in addition to the usual results, we also get sample as a column which corresponds to the name of the sample_key in the AnnData object.

Now that we have obtained results by sample, we can use a dotplot by sample to visualize the ligand-receptor interactions. Let’s pick arbitrarily the interactions with the highest magnitude_rank.

[10]:
(li.pl.dotplot_by_sample(adata, sample_key=sample_key,
                         colour="magnitude_rank", size="specificity_rank",
                         source_labels=["CD4T", "B", "FGR3"],
                         target_labels=["CD8T", 'DCs', 'CD14'],
                         ligand_complex=["B2M"],
                         inverse_colour=True,
                         inverse_size=True,
                         receptor_complex=["KLRD1", "LILRB2", "CD3D"],
                         figure_size=(12, 8),
                         size_range=(0.5, 5),
                         ) +
    # rotate facet labels
    p9.theme(strip_text=p9.element_text(size=10, colour="black", angle=90))
 )
Fontsize 0.00 < 1.0 pt not allowed by FreeType. Setting fontsize = 1 pt
../_images/notebooks_mofatalk_24_1.png

Even on a small subset interactions and cell types, we can see that interpretation becomes challenging. To overcome this, we can use MOFA to find the variable CCC patterns across contexts/samples.

Create a Multi-View Structure

Before we can identify the variable CCC patterns across contexts/samples, we need to create a multi-view structure. In this case, we will use the lrs_to_views function from liana to create a list of views (stored in a MuData object), where each view corresponds to a pair of potentially interacting cell types. The scores of interactions between cell type pairs represent those inferred with liana, stored by default in adata.uns['liana_res']. Here, we will use liana’s aggregate ‘magnitude_rank’.

[11]:
mdata = li.multi.lrs_to_views(adata,
                              score_key='magnitude_rank',
                              obs_keys=['patient', 'condition'], # add those to mdata.obs
                              lr_prop = 0.3, # minimum required proportion of samples to keep an LR
                              lrs_per_sample = 20, # minimum number of interactions to keep a sample in a specific view
                              lrs_per_view = 20, # minimum number of interactions to keep a view
                              samples_per_view = 10, # minimum number of samples to keep a view
                              min_variance = 0, # minimum variance to keep an interaction
                              lr_fill = 0, # fill missing LR values across samples with this
                              verbose=True
                              )
  0%|          | 0/43 [00:00<?, ?it/s]
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
 44%|████▍     | 19/43 [00:00<00:00, 188.44it/s]/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
/home/dbdimitrov/anaconda3/envs/mofatalk/lib/python3.10/site-packages/anndata/_core/anndata.py:430: FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
100%|██████████| 43/43 [00:00<00:00, 224.30it/s]

The lr_fill parameter controls how we deal with missing interaction scores. The default is np.nan and in that case the scores would be imputed by MOFA.

Here, we fill the missing ligand-receptors with 0s because the ligand-receptor interaction missing here, i.e. those when return_all_lrs=False, are such which are not expressed above a certain proportion of cells per cell type (that is controlled via expr_prop when running liana).

Given the assumption that the ligand-receptor interactions occur at the across cell type level, we could thus assume that the genes that are not present in a sufficient proportion of cells are unlikely to be involved in interactions that are relevant to the cell type as a whole.

Note

View Representation

MOFA supports the flexible representation of views, where each view can represent a different type of features (e.g. genes, proteins, metabolites, etc.). In this case, we simply allow for different ligand-receptor to be used in each cell type pair (view).

[12]:
mdata
[12]:
MuData object with n_obs × n_vars = 16 × 1729
  obs:      'patient', 'condition'
  34 modalities
    FGR3&CD14:  16 x 76
    FGR3&DCs:   16 x 87
    CD14&CD14:  16 x 81
    FGR3&NK:    16 x 39
    DCs&NK:     16 x 44
    FGR3&FGR3:  16 x 79
    DCs&CD14:   16 x 79
    CD14&NK:    16 x 43
    NK&CD8T:    14 x 33
    CD14&DCs:   16 x 86
    FGR3&CD8T:  16 x 46
    CD8T&CD8T:  12 x 29
    DCs&DCs:    16 x 89
    CD14&FGR3:  16 x 79
    DCs&FGR3:   16 x 82
    B&CD8T:     14 x 37
    DCs&CD8T:   16 x 52
    CD4T&CD8T:  11 x 27
    CD14&CD8T:  16 x 50
    FGR3&CD4T:  12 x 34
    DCs&CD4T:   13 x 37
    CD14&CD4T:  11 x 32
    CD8T&CD14:  16 x 35
    NK&CD14:    15 x 45
    B&CD14:     14 x 42
    NK&FGR3:    16 x 44
    CD8T&FGR3:  16 x 36
    CD4T&CD14:  15 x 38
    B&FGR3:     16 x 39
    CD4T&FGR3:  16 x 37
    NK&DCs:     14 x 47
    B&DCs:      12 x 50
    CD4T&DCs:   11 x 37
    CD8T&DCs:   12 x 38

Fitting a MOFA model

Now that the putative ligand-receptor interactions across samples aretransformed into a multi-view representation, we can use MOFA to run an intercellular communication factor analysis.

We will attempt to capture the variability across samples and the different cell-type pairs by reducing the data into a number of factors, where each factor captures the coordinated communication events across the cell types.

[13]:
mu.tl.mofa(mdata,
           use_obs='union',
           convergence_mode='medium',
           outfile='models/mofatalk.h5ad',
           n_factors=4,
           )

        #########################################################
        ###           __  __  ____  ______                    ###
        ###          |  \/  |/ __ \|  ____/\    _             ###
        ###          | \  / | |  | | |__ /  \ _| |_           ###
        ###          | |\/| | |  | |  __/ /\ \_   _|          ###
        ###          | |  | | |__| | | / ____ \|_|            ###
        ###          |_|  |_|\____/|_|/_/    \_\              ###
        ###                                                   ###
        #########################################################



Loaded view='FGR3&CD14' group='group1' with N=16 samples and D=76 features...
Loaded view='FGR3&DCs' group='group1' with N=16 samples and D=87 features...
Loaded view='CD14&CD14' group='group1' with N=16 samples and D=81 features...
Loaded view='FGR3&NK' group='group1' with N=16 samples and D=39 features...
Loaded view='DCs&NK' group='group1' with N=16 samples and D=44 features...
Loaded view='FGR3&FGR3' group='group1' with N=16 samples and D=79 features...
Loaded view='DCs&CD14' group='group1' with N=16 samples and D=79 features...
Loaded view='CD14&NK' group='group1' with N=16 samples and D=43 features...
Loaded view='NK&CD8T' group='group1' with N=16 samples and D=33 features...
Loaded view='CD14&DCs' group='group1' with N=16 samples and D=86 features...
Loaded view='FGR3&CD8T' group='group1' with N=16 samples and D=46 features...
Loaded view='CD8T&CD8T' group='group1' with N=16 samples and D=29 features...
Loaded view='DCs&DCs' group='group1' with N=16 samples and D=89 features...
Loaded view='CD14&FGR3' group='group1' with N=16 samples and D=79 features...
Loaded view='DCs&FGR3' group='group1' with N=16 samples and D=82 features...
Loaded view='B&CD8T' group='group1' with N=16 samples and D=37 features...
Loaded view='DCs&CD8T' group='group1' with N=16 samples and D=52 features...
Loaded view='CD4T&CD8T' group='group1' with N=16 samples and D=27 features...
Loaded view='CD14&CD8T' group='group1' with N=16 samples and D=50 features...
Loaded view='FGR3&CD4T' group='group1' with N=16 samples and D=34 features...
Loaded view='DCs&CD4T' group='group1' with N=16 samples and D=37 features...
Loaded view='CD14&CD4T' group='group1' with N=16 samples and D=32 features...
Loaded view='CD8T&CD14' group='group1' with N=16 samples and D=35 features...
Loaded view='NK&CD14' group='group1' with N=16 samples and D=45 features...
Loaded view='B&CD14' group='group1' with N=16 samples and D=42 features...
Loaded view='NK&FGR3' group='group1' with N=16 samples and D=44 features...
Loaded view='CD8T&FGR3' group='group1' with N=16 samples and D=36 features...
Loaded view='CD4T&CD14' group='group1' with N=16 samples and D=38 features...
Loaded view='B&FGR3' group='group1' with N=16 samples and D=39 features...
Loaded view='CD4T&FGR3' group='group1' with N=16 samples and D=37 features...
Loaded view='NK&DCs' group='group1' with N=16 samples and D=47 features...
Loaded view='B&DCs' group='group1' with N=16 samples and D=50 features...
Loaded view='CD4T&DCs' group='group1' with N=16 samples and D=37 features...
Loaded view='CD8T&DCs' group='group1' with N=16 samples and D=38 features...


Model options:
- Automatic Relevance Determination prior on the factors: True
- Automatic Relevance Determination prior on the weights: True
- Spike-and-slab prior on the factors: False
- Spike-and-slab prior on the weights: True
Likelihoods:
- View 0 (FGR3&CD14): gaussian
- View 1 (FGR3&DCs): gaussian
- View 2 (CD14&CD14): gaussian
- View 3 (FGR3&NK): gaussian
- View 4 (DCs&NK): gaussian
- View 5 (FGR3&FGR3): gaussian
- View 6 (DCs&CD14): gaussian
- View 7 (CD14&NK): gaussian
- View 8 (NK&CD8T): gaussian
- View 9 (CD14&DCs): gaussian
- View 10 (FGR3&CD8T): gaussian
- View 11 (CD8T&CD8T): gaussian
- View 12 (DCs&DCs): gaussian
- View 13 (CD14&FGR3): gaussian
- View 14 (DCs&FGR3): gaussian
- View 15 (B&CD8T): gaussian
- View 16 (DCs&CD8T): gaussian
- View 17 (CD4T&CD8T): gaussian
- View 18 (CD14&CD8T): gaussian
- View 19 (FGR3&CD4T): gaussian
- View 20 (DCs&CD4T): gaussian
- View 21 (CD14&CD4T): gaussian
- View 22 (CD8T&CD14): gaussian
- View 23 (NK&CD14): gaussian
- View 24 (B&CD14): gaussian
- View 25 (NK&FGR3): gaussian
- View 26 (CD8T&FGR3): gaussian
- View 27 (CD4T&CD14): gaussian
- View 28 (B&FGR3): gaussian
- View 29 (CD4T&FGR3): gaussian
- View 30 (NK&DCs): gaussian
- View 31 (B&DCs): gaussian
- View 32 (CD4T&DCs): gaussian
- View 33 (CD8T&DCs): gaussian




######################################
## Training the model with seed 1 ##
######################################



Converged!



#######################
## Training finished ##
#######################


Warning: Output file models/mofatalk.h5ad already exists, it will be replaced
Saving model in models/mofatalk.h5ad...
Saved MOFA embeddings in .obsm['X_mofa'] slot and their loadings in .varm['LFs'].

Exploring the MOFA model

For convenience, we provide simple getter function to access the model parameters, in addition to those available via the MuData API & the MOFA model itself.

[14]:
# obtain factor scores
factor_scores = li.ut.get_factor_scores(mdata, obsm_key='X_mofa', obs_keys=['patient', 'condition'])
factor_scores.head()
[14]:
sample Factor1 Factor2 Factor3 Factor4 patient condition
0 ctrl&101 0.383715 -0.006593 -0.017910 0.008964 patient_101 ctrl
1 ctrl&1015 0.322395 -0.010364 -0.017261 0.009955 patient_1015 ctrl
2 ctrl&1016 0.323579 -0.018064 -0.015747 0.010354 patient_1016 ctrl
3 ctrl&1039 0.285905 0.190810 -0.016043 0.010782 patient_1039 ctrl
4 ctrl&107 0.370363 -0.003651 -0.014988 0.009139 patient_107 ctrl

Let’s check if any of the factors are associated with the sample condition:

[15]:
 # we use a paired t-test as the samples are paired
from scipy.stats import ttest_rel
[16]:
# split in control and stimulated
group1 = factor_scores[factor_scores['condition']=='ctrl']
group2 = factor_scores[factor_scores['condition']=='stim']

# get all columns that contain factor & loop
factors = [col for col in factor_scores.columns if 'Factor' in col]
for factor in factors:
    print(ttest_rel(group1[factor], group2[factor]))
TtestResult(statistic=30.384081033829794, pvalue=1.0790597073456392e-08, df=7)
TtestResult(statistic=1.0429820265879368, pvalue=0.33163204477415253, df=7)
TtestResult(statistic=-1.0212383894689707, pvalue=0.3411323268534072, df=7)
TtestResult(statistic=1.0964442206113048, pvalue=0.3091659034570313, df=7)

We can see that the first factor is associated with the sample condition, let’s plot the factor scores:

[17]:
# scatterplot
(p9.ggplot(factor_scores) +
 p9.aes(x='condition', colour='condition', y='Factor1') +
 p9.geom_violin() +
 p9.geom_jitter(size=4, width=0.2) +
 p9.theme_bw(base_size=16) +
 p9.theme(figure_size=(5, 4)) +
 p9.scale_colour_manual(values=['#1f77b4', '#c20019']) +
 p9.labs(x='Condition', y='Factor 1')
 )
Fontsize 0.00 < 1.0 pt not allowed by FreeType. Setting fontsize = 1 pt
../_images/notebooks_mofatalk_44_1.png

Now that we have identified a factor that is associated with the sample condition, we can check the ligand-receptor loadings with the highest loadings:

[18]:
variable_loadings =  li.ut.get_variable_loadings(mdata,
                                                 varm_key='LFs',
                                                 view_sep=':',
                                                 pair_sep="&",
                                                 variable_sep="^") # get loadings for factor 1
variable_loadings.head()
[18]:
ligand_complex receptor_complex source target Factor1 Factor2 Factor3 Factor4
1036 HLA-DRA LAG3 DCs CD8T -3.190789 7.263270 0.042274 0.116837
175 CCL8 CCR1 CD14 CD14 -2.246373 -0.074323 0.007737 0.001949
237 TIMP1 CD63 CD14 CD14 2.214349 0.420502 -0.003632 0.002365
1037 HLA-DRB1 LAG3 DCs CD8T -2.001316 6.398914 -0.036896 0.028387
167 CCL2 CCR1 CD14 CD14 -1.946689 -0.065496 -0.000947 -0.086780
[19]:
# here we will just assign the size of the dots, but this can be replace by any other statistic
variable_loadings['size'] = 4.5
[20]:
my_plot = li.pl.dotplot(liana_res = variable_loadings,
                        size='size',
                        colour='Factor1',
                        orderby='Factor1',
                        top_n=15,
                        source_labels=['NK', 'B', 'CD4T', 'CD8T', 'CD14'],
                        orderby_ascending=False,
                        size_range=(0.1, 5),
                        figure_size=(8, 5)
                        )
# change colour, with mid as white
my_plot + p9.scale_color_gradient2(low='#1f77b4', mid='lightgray', high='#c20019')
Fontsize 0.00 < 1.0 pt not allowed by FreeType. Setting fontsize = 1 pt
../_images/notebooks_mofatalk_49_1.png

Here, we can see that certain interactions from Factor 1 have high positive loadings. These are interactions that are associated with the samples with high factor scores (i.e. the stimulated samples with high scores in Factor 1).

Explore the model

Finally, we can also explore the MOFA model itself and we will specifically check the variance explained by each pair of cell types.

[21]:
model = mofa.mofa_model("models/mofatalk.h5ad")
model
[21]:
MOFA+ model: mofatalk.h5ad
Samples (cells): 16
Features: 1729
Groups: group1 (16)
Views: B&CD14 (42), B&CD8T (37), B&DCs (50), B&FGR3 (39), CD14&CD14 (81), CD14&CD4T (32), CD14&CD8T (50), CD14&DCs (86), CD14&FGR3 (79), CD14&NK (43), CD4T&CD14 (38), CD4T&CD8T (27), CD4T&DCs (37), CD4T&FGR3 (37), CD8T&CD14 (35), CD8T&CD8T (29), CD8T&DCs (38), CD8T&FGR3 (36), DCs&CD14 (79), DCs&CD4T (37), DCs&CD8T (52), DCs&DCs (89), DCs&FGR3 (82), DCs&NK (44), FGR3&CD14 (76), FGR3&CD4T (34), FGR3&CD8T (46), FGR3&DCs (87), FGR3&FGR3 (79), FGR3&NK (39), NK&CD14 (45), NK&CD8T (33), NK&DCs (47), NK&FGR3 (44)
Factors: 4
Expectations: W, Z
[24]:
# get variance explained by view and factor
rsq = model.get_r2()
factor1_rsq = rsq[rsq['Factor']=='Factor1']
# separate view column
factor1_rsq[['source', 'target']] = factor1_rsq['View'].str.split(pat='&', n=1, expand=True)
[26]:
(p9.ggplot(factor1_rsq.reset_index()) +
 p9.aes(x='target', y='source') +
 p9.geom_tile(p9.aes(fill='R2')) +
 p9.scale_fill_gradient2(low='white', high='#c20019') +
 p9.theme_bw(base_size=16) +
 p9.theme(figure_size=(5, 4)) +
 p9.labs(x='Target', y='Source', fill='R²')
 )
Fontsize 0.00 < 1.0 pt not allowed by FreeType. Setting fontsize = 1 pt
../_images/notebooks_mofatalk_55_1.png

Here, we can see that views that include CD14+ Monocytes have the highest variance explained both as source and as target of intercellular communication events. In particular, we see that putative autocrine interactions that occur between CD14+ Monocytes are highly explained by Factor 1.

Pathway enrichment

Let’s also perform an enrichment analysis on the ligand-receptor interactions that are associated with the factor of interest. We will use decoupler with pathway genesets from PROGENy to look for enrichments across the cell type pairs (views).

[27]:
# load PROGENy pathways
net = dc.get_progeny(organism='human', top=5000)
# load full list of ligand-receptor pairs
lr_pairs = li.resource.select_resource('consensus')
Downloading data from `https://omnipathdb.org/queries/enzsub?format=json`
Downloading data from `https://omnipathdb.org/queries/interactions?format=json`
Downloading data from `https://omnipathdb.org/queries/complexes?format=json`
Downloading data from `https://omnipathdb.org/queries/annotations?format=json`
Downloading data from `https://omnipathdb.org/queries/intercell?format=json`
Downloading data from `https://omnipathdb.org/about?format=text`
Downloading annotations for all proteins from the following resources: `['PROGENy']`
[28]:
# generate ligand-receptor geneset
lr_progeny = li.rs.generate_lr_geneset(lr_pairs, net, lr_sep="^")
lr_progeny.head()
[28]:
source interaction weight
60 JAK-STAT LGALS9^PTPRC 1.307807
844 JAK-STAT LGALS9^CD47 2.054778
1130 Trail LGALS9^PTPRK 0.937003
1432 JAK-STAT LGALS9^HAVCR2 1.487678
1779 EGFR DLL1^NOTCH1 -1.000584
[29]:
lr_loadings =  li.ut.get_variable_loadings(mdata,
                                           varm_key='LFs',
                                           view_sep=':',
                                           )
lr_loadings.set_index('variable', inplace=True)
# pivot views to wide
lr_loadings = lr_loadings.pivot(columns='view', values='Factor1')
# replace NaN with 0
lr_loadings.replace(np.nan, 0, inplace=True)
lr_loadings.head()

[29]:
view B&CD14 B&CD8T B&DCs B&FGR3 CD14&CD14 CD14&CD4T CD14&CD8T CD14&DCs CD14&FGR3 CD14&NK ... FGR3&CD14 FGR3&CD4T FGR3&CD8T FGR3&DCs FGR3&FGR3 FGR3&NK NK&CD14 NK&CD8T NK&DCs NK&FGR3
variable
ADAM10^AXL 0.0 0.0 0.0 0.00000 0.0 0.0 0.0 0.000000 0.0 0.0 ... 0.000000 0.000000 0.000000 -0.078498 0.00000 0.000000 0.0 0.0 0.0 0.0
ADAM10^CD44 0.0 0.0 0.0 0.00000 0.0 0.0 0.0 0.000000 0.0 0.0 ... 0.023996 0.110766 -0.025276 -0.037175 0.00698 0.001638 0.0 0.0 0.0 0.0
ADAM17^RHBDF2 0.0 0.0 0.0 0.00000 0.0 0.0 0.0 0.000000 0.0 0.0 ... 0.000000 0.000000 0.000000 -0.142124 0.00000 0.000000 0.0 0.0 0.0 0.0
ADAM28^ITGA4 0.0 0.0 0.0 -0.26761 0.0 0.0 0.0 0.000000 0.0 0.0 ... 0.000000 0.000000 0.000000 0.000000 0.00000 0.000000 0.0 0.0 0.0 0.0
ADM^CALCRL 0.0 0.0 0.0 0.00000 0.0 0.0 0.0 0.249469 0.0 0.0 ... 0.000000 0.000000 0.000000 -0.034572 0.00000 0.000000 0.0 0.0 0.0 0.0

5 rows × 34 columns

[30]:
# run pathway enrichment analysis
estimate, pvals =  dc.run_mlm(lr_loadings.transpose(), lr_progeny,
                              source="source", target="interaction",
                              use_raw=False, min_n=5)
# pivot columns to long
estimate = (estimate.
            melt(ignore_index=False, value_name='estimate', var_name='pathway').
            reset_index().
            rename(columns={'index':'view'})
            )
[31]:
## p9 tile plot
(p9.ggplot(estimate) +
 p9.aes(x='pathway', y='view') +
 p9.geom_tile(p9.aes(fill='estimate')) +
 p9.scale_fill_gradient2(low='#1f77b4', high='#c20019') +
 p9.theme_bw(base_size=14) +
 p9.theme(figure_size=(8, 8))
)
Fontsize 0.00 < 1.0 pt not allowed by FreeType. Setting fontsize = 1 pt
../_images/notebooks_mofatalk_63_1.png

Some of these interactions are not expressed in the data, so we use the lr_fill parameter to fill them with 0s. This is a rather arbitrary choice, but it is a simple way to deal with missing values. Additionally, since we the views (cell type pairs) are rather sparse, it’s possible that the enrichment analysis will not be very informative. Be sure to check the results carefully.

Outlook & Further Analysis

This tutorial is just a short introduction of the use of MOFA, we thus refer the users to the available MOFA & muon tutorials for more applications & details.

Similary, consider citing both muon & MOFA+ if you use them in your work!

[32]:
model.close()
[ ]: