• Scanpy(七)基于scanorama整合scRNA-seq实现空间数据分析


    本篇内容介绍如何使用多个Visium数据集,以及如何用scRNA-seq数据集进行整合。我们将使用Scanorama来进行整合。首先我们要安装Scanorama:

    pip install scanorama
    
    • 1

    加载相关框架:

    import scanpy as sc
    import anndata as an
    import pandas as pd
    import numpy as np
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    import seaborn as sns
    import scanorama
    
    sc.logging.print_versions()
    sc.set_figure_params(facecolor="white", figsize=(8, 8))
    sc.settings.verbosity = 3
    
    """
    anndata     0.8.0
    scanpy      1.9.1
    scanorama   1.7.2
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    建议先阅读论文阅读笔记-利用Scanorama高效整合异质单细胞转录组


    Reading the data

    我们将使用两个小鼠大脑的Visium空间转录组数据集,该数据集可从10x genomics website获取。

    函数datasets.visium_sge()从10x genomics下载数据集并返回adata对象(包含counts,images和spatial coordinates),我们使用pp.calculate_qc_metrics计算质量控制的指标,并做可视化。

    adata_spatial_anterior = sc.datasets.visium_sge(
        sample_id="V1_Mouse_Brain_Sagittal_Anterior"
    ) # 数据集1
    adata_spatial_posterior = sc.datasets.visium_sge(
        sample_id="V1_Mouse_Brain_Sagittal_Posterior"
    ) # 数据集2
    
    adata_spatial_anterior
    """
    AnnData object with n_obs × n_vars = 2695 × 32285
        obs: 'in_tissue', 'array_row', 'array_col'
        var: 'gene_ids', 'feature_types', 'genome'
        uns: 'spatial'
        obsm: 'spatial'
    """
    
    adata_spatial_posterior
    """
    AnnData object with n_obs × n_vars = 3355 × 32285
        obs: 'in_tissue', 'array_row', 'array_col'
        var: 'gene_ids', 'feature_types', 'genome'
        uns: 'spatial'
        obsm: 'spatial'
    """
    
    adata_spatial_anterior.var_names_make_unique()
    adata_spatial_posterior.var_names_make_unique()
    sc.pp.calculate_qc_metrics(adata_spatial_anterior, inplace=True)
    sc.pp.calculate_qc_metrics(adata_spatial_posterior, inplace=True)
    
    for name, adata in [
        ("anterior", adata_spatial_anterior),
        ("posterior", adata_spatial_posterior),
    ]:
        fig, axs = plt.subplots(1, 4, figsize=(12, 3))
        fig.suptitle(f"Covariates for filtering: {name}")
    
        sns.distplot(adata.obs["total_counts"], kde=False, ax=axs[0])
        sns.distplot(
            adata.obs["total_counts"][adata.obs["total_counts"] < 20000],
            kde=False,
            bins=40,
            ax=axs[1],
        )
        sns.distplot(adata.obs["n_genes_by_counts"], kde=False, bins=60, ax=axs[2])
        sns.distplot(
            adata.obs["n_genes_by_counts"][adata.obs["n_genes_by_counts"] < 4000],
            kde=False,
            bins=60,
            ax=axs[3],
        )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    fig1
    sc.datasets.visium_sge下载的是已经过滤过的visium数据集,通过查看QC指标,我们可以观察到样本中几乎不包含空白点。

    我们进一步对visium的counts数据进行标准化(使用内置的normalize_total函数),然后检测高变基因。

    for adata in [
        adata_spatial_anterior,
        adata_spatial_posterior,
    ]:
        sc.pp.normalize_total(adata, inplace=True)
        sc.pp.log1p(adata)
        sc.pp.highly_variable_genes(adata, flavor="seurat", n_top_genes=2000, inplace=True)
    
    """
    normalizing counts per cell
        finished (0:00:00)
    If you pass `n_top_genes`, all cutoffs are ignored.
    extracting highly variable genes
        finished (0:00:00)
    --> added
        'highly_variable', boolean vector (adata.var)
        'means', float vector (adata.var)
        'dispersions', float vector (adata.var)
        'dispersions_norm', float vector (adata.var)
    normalizing counts per cell
        finished (0:00:00)
    If you pass `n_top_genes`, all cutoffs are ignored.
    extracting highly variable genes
        finished (0:00:00)
    --> added
        'highly_variable', boolean vector (adata.var)
        'means', float vector (adata.var)
        'dispersions', float vector (adata.var)
        'dispersions_norm', float vector (adata.var)
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    查看两个数据集:

    adata_spatial_anterior
    
    """
    AnnData object with n_obs × n_vars = 2695 × 32285
        obs: 'in_tissue', 'array_row', 'array_col', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_50_genes', 'pct_counts_in_top_100_genes', 'pct_counts_in_top_200_genes', 'pct_counts_in_top_500_genes'
        var: 'gene_ids', 'feature_types', 'genome', 'n_cells_by_counts', 'mean_counts', 'log1p_mean_counts', 'pct_dropout_by_counts', 'total_counts', 'log1p_total_counts', 'highly_variable', 'means', 'dispersions', 'dispersions_norm'
        uns: 'spatial', 'log1p', 'hvg'
        obsm: 'spatial'
    """
    
    adata_spatial_posterior
    
    """
    AnnData object with n_obs × n_vars = 3355 × 32285
        obs: 'in_tissue', 'array_row', 'array_col', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_50_genes', 'pct_counts_in_top_100_genes', 'pct_counts_in_top_200_genes', 'pct_counts_in_top_500_genes'
        var: 'gene_ids', 'feature_types', 'genome', 'n_cells_by_counts', 'mean_counts', 'log1p_mean_counts', 'pct_dropout_by_counts', 'total_counts', 'log1p_total_counts', 'highly_variable', 'means', 'dispersions', 'dispersions_norm'
        uns: 'spatial', 'log1p', 'hvg'
        obsm: 'spatial'
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Data integration

    现在,我们已经准备好对这两个数据集进行整合。如前所述,我们将使用Scanorama实现这一点。Scanorama返回包含两个adata的列表(每个adata包含了整合后的embedding)。关于数据整合,我们也可以使用BBKNN或Ingest。

    adatas = [adata_spatial_anterior, adata_spatial_posterior]
    adatas_cor = scanorama.correct_scanpy(adatas, return_dimred=True)
    
    adatas_cor
    """
    [AnnData object with n_obs × n_vars = 2695 × 32285
         obs: 'in_tissue', 'array_row', 'array_col', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_50_genes', 'pct_counts_in_top_100_genes', 'pct_counts_in_top_200_genes', 'pct_counts_in_top_500_genes'
         var: 'gene_ids', 'feature_types', 'genome', 'n_cells_by_counts', 'mean_counts', 'log1p_mean_counts', 'pct_dropout_by_counts', 'total_counts', 'log1p_total_counts', 'highly_variable', 'means', 'dispersions', 'dispersions_norm'
         uns: 'spatial', 'log1p', 'hvg'
         obsm: 'spatial', 'X_scanorama',
     AnnData object with n_obs × n_vars = 3355 × 32285
         obs: 'in_tissue', 'array_row', 'array_col', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_50_genes', 'pct_counts_in_top_100_genes', 'pct_counts_in_top_200_genes', 'pct_counts_in_top_500_genes'
         var: 'gene_ids', 'feature_types', 'genome', 'n_cells_by_counts', 'mean_counts', 'log1p_mean_counts', 'pct_dropout_by_counts', 'total_counts', 'log1p_total_counts', 'highly_variable', 'means', 'dispersions', 'dispersions_norm'
         uns: 'spatial', 'log1p', 'hvg'
         obsm: 'spatial', 'X_scanorama']
    """
    
    len(adatas_cor) # 2
    adatas_cor[0].obsm['X_scanorama'].shape # (2695, 100)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    然后,我们拼接整合后的embedding,整合后的数据集为adata_spatial,embedding保存为adata_spatial.obsm['scanorama_embedding']。此外,我们将计算UMAP以可视化结果并定性评估数据整合任务。

    请注意,我们使用uns_merge="unique"策略连接两个数据集,这是为了在连接的anndata对象中保留visium数据集中的两个images。

    adata_spatial = sc.concat(
        adatas_cor,
        label="library_id",
        uns_merge="unique",
        keys=[
            k
            for d in [
                adatas_cor[0].uns["spatial"],
                adatas_cor[1].uns["spatial"],
            ]
            for k, v in d.items()
        ],
        index_unique="-",
    )
    
    sc.pp.neighbors(adata_spatial, use_rep="X_scanorama")
    sc.tl.umap(adata_spatial)
    sc.tl.leiden(adata_spatial, key_added="clusters")
    """
    computing neighbors
        finished: added to `.uns['neighbors']`
        `.obsp['distances']`, distances for each pair of neighbors
        `.obsp['connectivities']`, weighted adjacency matrix (0:00:06)
    computing UMAP
        finished: added
        'X_umap', UMAP coordinates (adata.obsm) (0:00:09)
    running Leiden clustering
        finished: found 22 clusters and added
        'clusters', the cluster labels (adata.obs, categorical) (0:00:00)
    """
    
    adata_spatial
    """
    AnnData object with n_obs × n_vars = 6050 × 32285
        obs: 'in_tissue', 'array_row', 'array_col', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_50_genes', 'pct_counts_in_top_100_genes', 'pct_counts_in_top_200_genes', 'pct_counts_in_top_500_genes', 'library_id', 'clusters'
        uns: 'spatial', 'log1p', 'hvg', 'neighbors', 'umap', 'leiden'
        obsm: 'spatial', 'X_scanorama', 'X_umap'
        obsp: 'distances', 'connectivities'
    """
    
    sc.pl.umap(
        adata_spatial, color=["clusters", "library_id"], palette=sc.pl.palettes.default_20
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    fig2
    我们还可以在空间坐标中可视化聚类结果。为此,我们首先需要将簇颜色保存在字典中。然后,我们可以在前后两个数据集的视图中可视化,并将结果并排显示。

    clusters_colors = dict(
        zip([str(i) for i in range(18)], adata_spatial.uns["clusters_colors"])
    )
    
    fig, axs = plt.subplots(1, 2, figsize=(15, 10))
    
    for i, library in enumerate(
        ["V1_Mouse_Brain_Sagittal_Anterior", "V1_Mouse_Brain_Sagittal_Posterior"]
    ):
        ad = adata_spatial[adata_spatial.obs.library_id == library, :].copy()
        sc.pl.spatial(
            ad,
            img_key="hires",
            library_id=library,
            color="clusters",
            size=1.5,
            palette=[
                v
                for k, v in clusters_colors.items()
                if k in ad.obs.clusters.unique().tolist()
            ],
            legend_loc=None,
            show=False,
            ax=axs[i],
        )
    
    plt.tight_layout()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    fig3
    从这些簇中,我们可以清楚地看到两种组织中的分层。这证明,数据集整合确实工作正确。

  • 相关阅读:
    实现按钮悬停动画
    pnpm凭什么这么快
    网站如何优化
    Flutter高仿微信-第52篇-群聊-清空聊天记录
    使用LVM方式创建linux文件系统,详细教程
    mac苹果电脑有什么免费的系统清理软件?
    2022-7-5 随机过程之条件期望及其性质 (三)
    java计算机毕业设计社区健康信息管理系统源码+数据库+系统+lw文档+mybatis+运行部署
    如何提高redux开发效率?当然是redux-tookit啦!
    033-使用UIManager设置组件外观界面,适应不同操作系统
  • 原文地址:https://blog.csdn.net/qq_40943760/article/details/125443802