Joint analyse of RNA + Protein multimodal dataset using VIMCCA

This tutorial shows loading, preprocessing, VIMCCA joint analyse of RNA + Protein multimodal dataset.

Import packages

Here, we’ll import scbean along with other popular packages.

[1]:
import matplotlib
matplotlib.use('TkAgg')
import scanpy as sc
from scbean.model import vimcca

# Command for Jupyter Notebooks only
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
from matplotlib.axes._axes import _log as matplotlib_axes_logger
matplotlib_axes_logger.setLevel('ERROR')

Loading dataset

This tutorial uses multimodal single cell data of human PBMCs from a healthy donor, which measured 36,601 genes and 17 proteins on 8,258 cells at the same time, which can be downloaded from 10X Genomics.

[2]:
base_path = '/Users/zhongyuanke/data/'
file_rna = base_path + 'multimodal/protein/vdj_v1_hs_pbmc2_5gex_protein_filtered_feature_bc_matrix.h5'
file_protein = base_path + 'multimodal/protein/protein.csv'

adata_x= sc.read_10x_h5(file_rna)
adata_y = sc.read_csv(file_protein)
adata_x.var_names_make_unique()
adata_y.var_names_make_unique()
Variable names are not unique. To make them unique, call `.var_names_make_unique`.
Variable names are not unique. To make them unique, call `.var_names_make_unique`.

Preprocessing using scanpy

Here, we filter and normalize each modal separately.

[3]:
sc.pp.filter_genes(adata_x, min_cells=10)
sc.pp.log1p(adata_x)
sc.pp.log1p(adata_y)
sc.pp.scale(adata_x)
sc.pp.scale(adata_y)

Joint analyse using VIMCCA

The returned z represents the complementary low-dimensional features of the two modalities learned by VIMCCA, which can be used for downstream analysis.

[4]:
z = vimcca.fit_integration(
    adata_x, adata_y,
    sparse_x=False,
    sparse_y=False,
    hidden_layers=[128, 64, 32, 8],
    epochs=50
)
Model: "VIMCCA_mlp"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to
==================================================================================================
inputs_x (InputLayer)           [(None, 15446)]      0
__________________________________________________________________________________________________
encoder_z (Functional)          [(None, 8), (None, 8 1988752     inputs_x[0][0]
                                                                 inputs_x[0][0]
__________________________________________________________________________________________________
inputs_y (InputLayer)           [(None, 17)]         0
__________________________________________________________________________________________________
decoder_x (Functional)          (None, 15446)        2003926     encoder_z[0][2]
__________________________________________________________________________________________________
decoder_y (Functional)          (None, 17)           13585       encoder_z[1][2]
__________________________________________________________________________________________________
dense (Dense)                   (None, 128)          1977216     inputs_x[0][0]
__________________________________________________________________________________________________
batch_normalization (BatchNorma (None, 128)          384         dense[0][0]
__________________________________________________________________________________________________
activation (Activation)         (None, 128)          0           batch_normalization[0][0]
__________________________________________________________________________________________________
dropout (Dropout)               (None, 128)          0           activation[0][0]
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 64)           8256        dropout[0][0]
__________________________________________________________________________________________________
batch_normalization_1 (BatchNor (None, 64)           192         dense_1[0][0]
__________________________________________________________________________________________________
activation_1 (Activation)       (None, 64)           0           batch_normalization_1[0][0]
__________________________________________________________________________________________________
dropout_1 (Dropout)             (None, 64)           0           activation_1[0][0]
__________________________________________________________________________________________________
tf.math.subtract_2 (TFOpLambda) (None, 17)           0           inputs_y[0][0]
                                                                 decoder_y[0][0]
__________________________________________________________________________________________________
dense_2 (Dense)                 (None, 32)           2080        dropout_1[0][0]
__________________________________________________________________________________________________
tf.math.subtract (TFOpLambda)   (None, 15446)        0           inputs_x[0][0]
                                                                 decoder_x[0][0]
__________________________________________________________________________________________________
tf.math.reduce_mean_4 (TFOpLamb (1, 1)               0           tf.math.subtract_2[0][0]
__________________________________________________________________________________________________
batch_normalization_2 (BatchNor (None, 32)           96          dense_2[0][0]
__________________________________________________________________________________________________
tf.math.reduce_mean_2 (TFOpLamb (1, 1)               0           tf.math.subtract[0][0]
__________________________________________________________________________________________________
tf.math.subtract_3 (TFOpLambda) (None, 17)           0           tf.math.subtract_2[0][0]
                                                                 tf.math.reduce_mean_4[0][0]
__________________________________________________________________________________________________
activation_2 (Activation)       (None, 32)           0           batch_normalization_2[0][0]
__________________________________________________________________________________________________
tf.math.subtract_1 (TFOpLambda) (None, 15446)        0           tf.math.subtract[0][0]
                                                                 tf.math.reduce_mean_2[0][0]
__________________________________________________________________________________________________
tf.convert_to_tensor_1 (TFOpLam (None, 17)           0           decoder_y[0][0]
__________________________________________________________________________________________________
tf.cast_1 (TFOpLambda)          (None, 17)           0           inputs_y[0][0]
__________________________________________________________________________________________________
tf.math.square_1 (TFOpLambda)   (None, 17)           0           tf.math.subtract_3[0][0]
__________________________________________________________________________________________________
dropout_2 (Dropout)             (None, 32)           0           activation_2[0][0]
__________________________________________________________________________________________________
tf.convert_to_tensor (TFOpLambd (None, 15446)        0           decoder_x[0][0]
__________________________________________________________________________________________________
tf.cast (TFOpLambda)            (None, 15446)        0           inputs_x[0][0]
__________________________________________________________________________________________________
tf.math.square (TFOpLambda)     (None, 15446)        0           tf.math.subtract_1[0][0]
__________________________________________________________________________________________________
tf.math.squared_difference_1 (T (None, 17)           0           tf.convert_to_tensor_1[0][0]
                                                                 tf.cast_1[0][0]
__________________________________________________________________________________________________
tf.math.reduce_mean_5 (TFOpLamb ()                   0           tf.math.square_1[0][0]
__________________________________________________________________________________________________
z_log_var (Dense)               (None, 8)            264         dropout_2[0][0]
__________________________________________________________________________________________________
z_mean (Dense)                  (None, 8)            264         dropout_2[0][0]
__________________________________________________________________________________________________
tf.math.squared_difference (TFO (None, 15446)        0           tf.convert_to_tensor[0][0]
                                                                 tf.cast[0][0]
__________________________________________________________________________________________________
tf.math.reduce_mean_3 (TFOpLamb ()                   0           tf.math.square[0][0]
__________________________________________________________________________________________________
tf.math.reduce_mean_1 (TFOpLamb (None,)              0           tf.math.squared_difference_1[0][0
__________________________________________________________________________________________________
tf.math.truediv_2 (TFOpLambda)  ()                   0           tf.math.reduce_mean_5[0][0]
__________________________________________________________________________________________________
tf.math.truediv_3 (TFOpLambda)  ()                   0           tf.math.reduce_mean_5[0][0]
__________________________________________________________________________________________________
tf.math.log_1 (TFOpLambda)      ()                   0           tf.math.reduce_mean_5[0][0]
__________________________________________________________________________________________________
tf.__operators__.add_2 (TFOpLam (None, 8)            0           z_log_var[0][0]
__________________________________________________________________________________________________
tf.math.square_2 (TFOpLambda)   (None, 8)            0           z_mean[0][0]
__________________________________________________________________________________________________
tf.math.reduce_mean (TFOpLambda (None,)              0           tf.math.squared_difference[0][0]
__________________________________________________________________________________________________
tf.math.truediv (TFOpLambda)    ()                   0           tf.math.reduce_mean_3[0][0]
__________________________________________________________________________________________________
tf.math.truediv_1 (TFOpLambda)  ()                   0           tf.math.reduce_mean_3[0][0]
__________________________________________________________________________________________________
tf.math.log (TFOpLambda)        ()                   0           tf.math.reduce_mean_3[0][0]
__________________________________________________________________________________________________
tf.math.multiply_2 (TFOpLambda) (None,)              0           tf.math.reduce_mean_1[0][0]
                                                                 tf.math.truediv_2[0][0]
__________________________________________________________________________________________________
tf.math.multiply_3 (TFOpLambda) ()                   0           tf.math.truediv_3[0][0]
                                                                 tf.math.log_1[0][0]
__________________________________________________________________________________________________
tf.math.subtract_4 (TFOpLambda) (None, 8)            0           tf.__operators__.add_2[0][0]
                                                                 tf.math.square_2[0][0]
__________________________________________________________________________________________________
tf.math.exp (TFOpLambda)        (None, 8)            0           z_log_var[0][0]
__________________________________________________________________________________________________
tf.math.multiply (TFOpLambda)   (None,)              0           tf.math.reduce_mean[0][0]
                                                                 tf.math.truediv[0][0]
__________________________________________________________________________________________________
tf.math.multiply_1 (TFOpLambda) ()                   0           tf.math.truediv_1[0][0]
                                                                 tf.math.log[0][0]
__________________________________________________________________________________________________
tf.__operators__.add_1 (TFOpLam (None,)              0           tf.math.multiply_2[0][0]
                                                                 tf.math.multiply_3[0][0]
__________________________________________________________________________________________________
tf.math.subtract_5 (TFOpLambda) (None, 8)            0           tf.math.subtract_4[0][0]
                                                                 tf.math.exp[0][0]
__________________________________________________________________________________________________
tf.__operators__.add (TFOpLambd (None,)              0           tf.math.multiply[0][0]
                                                                 tf.math.multiply_1[0][0]
__________________________________________________________________________________________________
tf.math.multiply_5 (TFOpLambda) (None,)              0           tf.__operators__.add_1[0][0]
__________________________________________________________________________________________________
tf.math.reduce_sum (TFOpLambda) (None,)              0           tf.math.subtract_5[0][0]
__________________________________________________________________________________________________
tf.__operators__.add_3 (TFOpLam (None,)              0           tf.__operators__.add[0][0]
                                                                 tf.math.multiply_5[0][0]
__________________________________________________________________________________________________
tf.math.multiply_4 (TFOpLambda) (None,)              0           tf.math.reduce_sum[0][0]
__________________________________________________________________________________________________
tf.__operators__.add_4 (TFOpLam (None,)              0           tf.__operators__.add_3[0][0]
                                                                 tf.math.multiply_4[0][0]
__________________________________________________________________________________________________
tf.math.reduce_mean_6 (TFOpLamb ()                   0           tf.__operators__.add_4[0][0]
__________________________________________________________________________________________________
add_loss (AddLoss)              ()                   0           tf.math.reduce_mean_6[0][0]
==================================================================================================
Total params: 4,006,263
Trainable params: 4,004,919
Non-trainable params: 1,344
__________________________________________________________________________________________________
Epoch 1/50
65/65 [==============================] - 8s 68ms/step - loss: 8005.9545
Epoch 2/50
65/65 [==============================] - 4s 69ms/step - loss: 7536.9300
Epoch 3/50
65/65 [==============================] - 4s 67ms/step - loss: 7426.0055
Epoch 4/50
65/65 [==============================] - 4s 69ms/step - loss: 7366.3191
Epoch 5/50
65/65 [==============================] - 4s 68ms/step - loss: 7226.3800
Epoch 6/50
65/65 [==============================] - 4s 69ms/step - loss: 7316.1741
Epoch 7/50
65/65 [==============================] - 4s 68ms/step - loss: 7248.8826
Epoch 8/50
65/65 [==============================] - 4s 68ms/step - loss: 7314.9281
Epoch 9/50
65/65 [==============================] - 4s 69ms/step - loss: 7208.9047
Epoch 10/50
65/65 [==============================] - 4s 69ms/step - loss: 7110.3514
Epoch 11/50
65/65 [==============================] - 4s 69ms/step - loss: 7283.3101
Epoch 12/50
65/65 [==============================] - 4s 68ms/step - loss: 7121.3090
Epoch 13/50
65/65 [==============================] - 4s 68ms/step - loss: 7228.4224
Epoch 14/50
65/65 [==============================] - 4s 68ms/step - loss: 7121.4047
Epoch 15/50
65/65 [==============================] - 4s 69ms/step - loss: 7187.0503
Epoch 16/50
65/65 [==============================] - 4s 69ms/step - loss: 7312.7754
Epoch 17/50
65/65 [==============================] - 4s 69ms/step - loss: 7070.5891
Epoch 18/50
65/65 [==============================] - 4s 68ms/step - loss: 7033.9288
Epoch 19/50
65/65 [==============================] - 5s 75ms/step - loss: 7188.7630
Epoch 20/50
65/65 [==============================] - 5s 70ms/step - loss: 7290.6376
Epoch 21/50
65/65 [==============================] - 5s 75ms/step - loss: 7130.6075
Epoch 22/50
65/65 [==============================] - 5s 72ms/step - loss: 7203.3686
Epoch 23/50
65/65 [==============================] - 5s 75ms/step - loss: 7146.6050
Epoch 24/50
65/65 [==============================] - 5s 73ms/step - loss: 7017.8652
Epoch 25/50
65/65 [==============================] - 5s 78ms/step - loss: 7106.8645
Epoch 26/50
65/65 [==============================] - 5s 81ms/step - loss: 7049.5582
Epoch 27/50
65/65 [==============================] - 5s 77ms/step - loss: 7137.5227
Epoch 28/50
65/65 [==============================] - 5s 75ms/step - loss: 7212.4039
Epoch 29/50
65/65 [==============================] - 5s 70ms/step - loss: 7166.1505
Epoch 30/50
65/65 [==============================] - 5s 70ms/step - loss: 7054.5878
Epoch 31/50
65/65 [==============================] - 5s 77ms/step - loss: 7043.2081
Epoch 32/50
65/65 [==============================] - 4s 68ms/step - loss: 7165.7558
Epoch 33/50
65/65 [==============================] - 4s 65ms/step - loss: 7078.6018
Epoch 34/50
65/65 [==============================] - 4s 64ms/step - loss: 7193.8797
Epoch 35/50
65/65 [==============================] - 4s 68ms/step - loss: 7016.1505
Epoch 36/50
65/65 [==============================] - 5s 85ms/step - loss: 7078.3934
Epoch 37/50
65/65 [==============================] - 5s 79ms/step - loss: 7079.0337
Epoch 38/50
65/65 [==============================] - 5s 73ms/step - loss: 7047.6853
Epoch 39/50
65/65 [==============================] - 5s 72ms/step - loss: 7048.9301
Epoch 40/50
65/65 [==============================] - 5s 73ms/step - loss: 7116.9205
Epoch 41/50
65/65 [==============================] - 5s 72ms/step - loss: 7015.4815
Epoch 42/50
65/65 [==============================] - 5s 71ms/step - loss: 6962.5304
Epoch 43/50
65/65 [==============================] - 5s 72ms/step - loss: 6987.1895
Epoch 44/50
65/65 [==============================] - 5s 78ms/step - loss: 7015.4488
Epoch 45/50
65/65 [==============================] - 5s 75ms/step - loss: 7129.7388
Epoch 46/50
65/65 [==============================] - 5s 71ms/step - loss: 6935.9163
Epoch 47/50
65/65 [==============================] - 5s 72ms/step - loss: 6935.7562
Epoch 48/50
65/65 [==============================] - 5s 71ms/step - loss: 7085.3036
Epoch 49/50
65/65 [==============================] - 5s 71ms/step - loss: 7040.0532
Epoch 50/50
65/65 [==============================] - 5s 72ms/step - loss: 7090.8747

Visualization

[5]:
adata_x.obsm['X_vimcca'] = z
sc.pp.neighbors(adata_x, use_rep='X_vimcca')
sc.tl.leiden(adata_x, resolution=3)
sc.tl.umap(adata_x)
[6]:
sc.pl.umap(adata_x, color='leiden', legend_loc='on data', s=3)
... storing 'feature_types' as categorical
... storing 'genome' as categorical
../_images/tutorials_vimcca_protein_rna_tutorial_11_1.png