
01 空间转录组 笔记
空间转录组
启动服务器端jupyter notebook的流程:
1 | jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser |
空间转录组的流程分析
- 聚类
- 不同的功能区域
- 对比单细胞转录组分析的聚类:细胞类型
- 不同的功能区域
- 降维
- 主要使用空间信息进行进行降维,如UMAP、t-SNE,同时考虑细胞之间的空间关系,但一般只有在多个切片联合分析才考虑降维
- 对比单细胞转录组分析的降维:基于基因表达矩阵进行降维,通常使用PCA、t-SNE、UMAP等方法
- 主要使用空间信息进行进行降维,如UMAP、t-SNE,同时考虑细胞之间的空间关系,但一般只有在多个切片联合分析才考虑降维
- 差异分析
- 主要发现不同空间区域之间差异表达的基因,如SpatiaIDE
- 对比单细胞转录组分析的差异分析:用于发现不同细胞类型之间的差异表达基因,如Seurat的FindAllMarkers
- 主要发现不同空间区域之间差异表达的基因,如SpatiaIDE
- 富集分析
- 主要用于解释在不同区域或细胞类型中富集的生物学过程,如GO分析、KEGG分析
- 对比单细胞转录组分析的富集分析:用于解释在不同细胞类型中富集的生物学过程,如GO分析、KEGG分析
- 主要用于解释在不同区域或细胞类型中富集的生物学过程,如GO分析、KEGG分析
- 细胞类型
- 相互糅合在一起,强调统一体
- 对比单细胞转录组分析的细胞类型:批次分开,强调细胞类型的精确
- 相互糅合在一起,强调统一体
- 肿瘤细胞区域
- 图片可以直接识别
- 对比单细胞转录组分析的肿瘤细胞区域:算法推断
- 图片可以直接识别
- 细胞类型分布
- 能够在组织中确定不同细胞类型的空间分布情况
- 对比单细胞转录组分析的细胞类型分布:一个或几个cluster
- 能够在组织中确定不同细胞类型的空间分布情况
- 共定位
- 通常指的是组织或者细胞区域内同时表达的基因,这可以通过分析不同区域的基因表达矩阵来确定,共定位基因可能在特定的细胞类型或空间区域中表达,从而解释这些区域的生物学功能或发育过程
- 对比单细胞转录组分析的共定位:通常指的是不同细胞类型之间共同表达的基因,这可以通过分析单细胞数据集中不同细胞簇的基因表达模式来确定,共定位基因可能多个细胞类型中表达,从而揭示这些细胞类型之间的功能联系或分析交互作用
- 通常指的是组织或者细胞区域内同时表达的基因,这可以通过分析不同区域的基因表达矩阵来确定,共定位基因可能在特定的细胞类型或空间区域中表达,从而解释这些区域的生物学功能或发育过程
1 | # 获取当前路径 |
1 | !(python --version) |
DataFrame
pandas 库中的 DataFrame 是一种二维表结构,可以理解为一个类似于 Excel 表格或数据库表的对象,能够存储不同类型的数据。它的特点是带有行标签(index)和列标签(columns),便于数据的组织、操作和分析
1 | import panads as pd |
scverse分析框架 - AnnData数据结构
等同于R中的S4对象,是数据结构
目前单细胞领域的工具分为三种:
Bioconductor:R语言实现的生物信息学生态Seurat:R语言实现的单细胞分析生态Scverse:基于Python实现的单细胞分析生态- 单细胞主要用
anndata - 单细胞多组学主要有
mudata - 空间的多组学用
SpatialData
- 单细胞主要用
SCVI-Tools(Single Cell Variational Inference Tools):是一个开源的Python库,专为单细胞转录组数据的分析而设计
squidpy:专门用于处理和分析空间分子数据,基于scanpy和anndata,继承了它们的模块化和可拓展性,并专门处理带有空间坐标的数据提供独特的方法,包括整合组织图像进行深度分析
AnnData结构:

- 核心属性 X 为一个稀疏矩阵(
scipy.sparse.csr.csr_matrix),用于存储矩阵的值 - 矩阵的行列分别对应观察者 obs(即细胞条形码),变量 var (即基因),这两个属性分别是一个数据框(
panads.core.frame.DataFrame)类型用于存储行列的注释信息,其索引就是对应的 obs_names 和 var_names
| 功能 | 类型 | |
|---|---|---|
adata.X |
矩阵 | numpy矩阵 |
adata.obs |
观测量 | pandas Dataframe |
adata.var |
特征量 | pandas Dataframe |
adata.uns |
非结构化数据 | 字典dict |
X数据槽:
- X slot存储了当前用于分析的表达矩阵,一般使用CSR的稀疏矩阵格式
- X 的一个数据结构是numpy array,是没有行名列名消息的,行名和列名消息存储在
.obs和.var里
1 | adata.X |
Layers数据槽:
- Layers本质上是python的字典,每个layer对应一个表达矩阵的二位数组,比如标准化、对数化等等,这些转换后的数据可以存储在layer中
1 | # 查看layers下哪些数据 |
使用不同的Layer数据画图:
1 | # 创建一个包含两个子图的画布,并指定画布大小为(10, 2.5),ax1和ax2分别代表两个子图 |
导出表达矩阵(就是10X单细胞那三个文件):
1 | # 导出layers中的矩阵 |
基础信息的储存:
obs就是metadata,var就是基因注释的数据框
1 | # 查看细胞注释的内容 |
使用不同降维坐标画图:
1 | # 创建一个图形,并指定大小为(12, 4) |
数据合并和筛选
-
两个对象的合并
1
2
3import anndata as ad
adatas = [adata1, adata2]
adatas = ad.concatenate(adatas) -
metadata更改
1
2
3
4
5
6
7
8
9
10
11# 构建control组和处理组
adata.obs['label'] = "NA"
c = [i for i, word in enumerate(list(adata.obs['batch1'])) if word.startswith('A')]
obs['label'][c] = "A"
c = [i for i, word in enumerate(list(adata.obs['batch1'])) if word.startswith('B')]
obs['label'][c] = "B"
c = [i for i, word in enumerate(list(adata.obs['batch1'])) if word.startswith('C')]
obs['label'][c] = "C"
c = [i for i, word in enumerate(list(adata.obs['batch1'])) if word.startswith('Y')]
obs['label'][c] = "Y" -
数据保存和metadata添加
1
2
3os.getcwd()
adata.write("xxx.h5ad", compression='gzip')
adata.obs.to_csv("scanpy_cell_info.csv", header=True, index=True) -
载入数据
1
2
3
4
5
6
7
8
9# 加入数据
anno = pd.read_csv("scanpy_cell_info.csv", index_col = 1)
# 加入样本分组的信息
adata.obsp['cell_groups'] = anno['label']
# 甚至可以直接赋值 dataframe
adata.obs['cell_groups1'] = list(anno['clusters'])
adata.obs = anno
df = adata.obs -
数据的提取
1
2
3# : 表示基因的过滤
adata = adata[adata.obs.n_genes_by_counts < 2500, :]
adata = adata[adata.obs.pct_counts_mt < 5, :]
空间转录组基本分析流程
流程:
-
导包
1
2
3
4
5
6
7
8
9import os
import anndata
import scanpy as sc
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pooch
from scipy.sparse import csr_matrix
from scipy.io import mmwrite -
查看版本号等
1
2
3
4
5
6
7
8
9
10
11# 输出版本号
sc.logging.print_versions()
# 将图片的背景改为白色
# 设置输出图像格式
sc.set_figure_params(facecolor="white", figsize=(8, 8))
# verbosity 的取值表示测试结果显示的详细程度,数字越大越详细
# errors = 0
# warnings = 1
# info = 2
# hints = 3
sc.settings.verbosity = 3 -
更改当前的路径
1
2
3
4
5
6
7
8# 获取当前工作路径
print(os.getcwd())
# 更改路径
os.chdir('/home/oelab/RunData2/STM_AD_analyze/data/GSE220442_counts_and_images/')
## 更改完再检查一下有没有更改成功
print(os.getcwd()) -
读取数据
1
adata = sc.read_visium('../GSE220442_counts_and_images/counts_and_images/AD1/')
-
查看AnnData的数据结构
1
adata
-
标记线粒体基因
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 线粒体百分比计算
# 进行质控
# 将基因名去重
adata.var_names_make_unique()
# 标记线粒体基因
# 在adata的数据里增加了一行mt
"""
用于标记 adata 中的线粒体基因。这里假设线粒体基因的名称以 "MT-" 开头,adata.var["mt"] 会存储一个布尔值数组,标记每个基因是否为线粒体基因
"""
adata.var["mt"] = adata.var_names.str.startswith("MT-")
# pp指对空转数据的预处理
"""
sc.pp.calculate_qc_metrics 是 Scanpy 中的一个函数,用于计算质量控制指标。
参数 qc_vars=["mt"] 告诉函数将 adata.var["mt"] 中标记的线粒体基因作为一个单独的质量控制变量。
这样可以计算每个细胞中线粒体基因的表达比例等指标,结果会直接添加到 adata.obs 中
"""
sc.pp.calculate_qc_metrics(adata, qc_vars=["mt"], inplace=True) -
两种赋值方法
1
2
3
4
5# 第一种赋值方式,浅拷贝
adata1=adata
# 第二种赋值方式,深拷贝
adata1=adata.copy() -
查看质控图
1
2
3
4
5
6
7
8
9
10
11
12## 使用 plt.subplots 创建一个包含 1 行、4 列的图形布局,每个子图的大小为 (15, 4)
fig, axs = plt.subplots(1, 4, figsize=(15, 4))
## 第一个子图中绘制 adata.obs["total_counts"] 的直方图,用于显示每个细胞的总计数分布情况
sns.histplot(adata.obs["total_counts"], kde=False, ax=axs[0])
## 第二个子图中绘制一个限定了范围的总计数直方图,仅包括总计数少于 10000 的细胞,以便更清晰地观察低计数细胞的分布情况
sns.histplot(adata.obs["total_counts"][adata.obs["total_counts"] < 10000],
kde=False, bins=40,ax=axs[1],)
## 第三个子图中绘制 adata.obs["n_genes_by_counts"] 的直方图,用于显示每个细胞中检测到的基因数分布
sns.histplot(adata.obs["n_genes_by_counts"], kde=False, bins=60, ax=axs[2])
## 第四个子图中绘制基因计数少于 4000 的直方图,方便观察低基因计数的细胞分布
sns.histplot(adata.obs["n_genes_by_counts"][adata.obs["n_genes_by_counts"] < 4000],
kde=False, bins=60, ax=axs[3],) -
过滤低质量的细胞
1
2
3
4
5sc.pp.filter_cells(adata, min_counts=5000)
sc.pp.filter_cells(adata, max_counts=35000)
adata = adata[adata.obs["pct_counts_mt"] < 20].copy()
print(f"#cells after MT filter: {adata.n_obs}")
sc.pp.filter_genes(adata, min_cells=10) -
数据归一化
1
2
3sc.pp.normalize_total(adata, inplace=True)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, flavor="seurat", n_top_genes=2000) -
pca降维,umap可视化,leiden的聚类
1
2
3
4
5sc.pp.pca(adata)
sc.pp.neighbors(adata)
sc.tl.umap(adata)
# 类似于R的findclusters
sc.tl.leiden(adata, key_added="clusters" ) -
展示umap图上基因的表达量
1
2
3
4
5
6
7
8
9
10# 过滤之后的数据是什么样的
plt.rcParams["figure.figsize"] = (4, 4)
# 将三张图放在一张图里面
sc.pl.umap(adata, color=["total_counts", "n_genes_by_counts", "clusters"], wspace=0.4)
# 和上面的结果是一样的
# 分别展示三张图的结果
sc.pl.umap(adata, color=["total_counts" ], wspace=0.4)
sc.pl.umap(adata, color=[ "n_genes_by_counts"], wspace=0.4)
sc.pl.umap(adata, color=[ "clusters"], wspace=0.4) -
可视化空间信息
1
2
3
4
5
6
7
8
9
10
11
12# 查看空转位置上totalcounts和基因数量的分布
plt.rcParams["figure.figsize"] = (8, 8)
sc.pl.spatial(adata, img_key="hires", color=["total_counts", "n_genes_by_counts"])
# 查看每个clusters在空间上是如何分布的
sc.pl.spatial(adata, img_key="hires", color="clusters", size=1.5)
# 筛选出1和3两个cluster的分布
sc.pl.spatial(adata,
img_key="hires",color="clusters",
groups=["1", "3"],crop_coord=[7000, 10000, 0, 6000],
alpha=0.5,size=1.3,) -
差异分析
1
2
3
4# 找出来marker基因
sc.tl.rank_genes_groups(adata, "clusters", method="t-test")
# 基于group2进行展示
sc.pl.rank_genes_groups_heatmap(adata, groups="2", n_genes=10, groupby="clusters") -
个性化展示画图
1
2
3
4
5# 查看cluster的信息
sc.pl.spatial(adata, img_key="hires", color=["clusters" ])
# 查看两个基因表达量的分布
sc.pl.spatial(adata, img_key="hires", color=["COL1A2", "SYPL1"], alpha=0.7) -
对数据进行保存,方便下一次的读取
1
2os.chdir("/home/oelab/RunData2/STM_AD_analyze/")
adata.write("GSE220442.data.anndata.h5ad") -
保存画图
1
fig.savefig(f'./figures/Visium-HE_{reg}.pdf')
scanpy 单个样本的单细胞分析流程
基本的分析流程:
- 对初始的Adata的预处理
- 主成分分析
- 计算 neighborhood graph
- 对 neighborhood graph 进行 embedding
- 对 neighborhood graph 进行聚类
- 找到 marker 基因(簇间比较)
- 根据 marker 基因注释
流程:
-
scanpy单细胞数据读取
- 公共数据常用的单细胞数据文件格式:
- Matrix Market Exchange Format (MEX):
.mtx文件,该文件包含了一个稀疏矩阵,其中每一行代表一个基因,每一列代表一个细胞,而每个素则表示基因在相应细胞中的表达量。通常会有三个文件组成:barcodes.tsv(细胞标识)features.tsv(基因标识)和matrix.mtx(表达矩阵)
- Hierarchical Data Format (HDF5):
h5文件,HDF5 是一种用于存储和组织大规模科学数据的文件格式。在单细胞数据中,可以使用HDF5 存储表达矩阵、基因和细胞的元数据等信息
- AnnData:
.h5ad文件,是基于 HDF5 的文件格式,由 anndata 库定义。它可以包含单细胞数据的表达矩阵、基因和细胞的元数据、样品信息等
- Comma-Separated Values(CSV)或文本文件:
.csv或.txt文件,包含表达矩阵的文本文件。每一行代表一个基因,每一列代表一个细胞,元素是表达量
- Matrix Market Exchange Format (MEX):
- 公共数据常用的单细胞数据文件格式:
-
读取数据(以mtx为例,但是10X单细胞三个文件得解压)
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# 导入scanpy库
import scanpy as sc
# 读取tab文件
data = sc.read_10X_mtx("/GSE121121")
# 查看数据
data
----------------------------------------------------------------------------------------
# 读取h5文件
# 导入scanpy库
import scanpy as sc
# 读取h5文件
data = sc.read_10X_h5("/xxx.h5")
# 查看数据
data
# 读取h5ad文件
adata = sc.read_h5ad('/xxx.h5ad')
# 读取csv文件
data4 = sc.read_csv("/xxx.csv")
# 读取txt文件
data5 = sc.read_text("/xxx.txt") -
加载模块
1
2
3
4
5
6
7
8
9
10import os
import anndata
import scanpy as sc
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pooch
from scipy.sparse import csr_matrix
from scipy.io import mmwrite -
初始化设置
1
2
3sc.logging.print_versions()
sc.set_figure_params(facecolor="white", figsize=(10, 10))
sc.settings.verbosity = 3 -
读取mtx文件
1
2
3
4
5
6
7
8
9
10
11
12
13print(os.getcwd())
os.chdir("/home/oelab/RunData2/STM_AD_analyze/data/")
print(os.getcwd())
# 声明h5ad用于存储分析结果
result_file = 'sample1_h5ad'
adata = sc.read_10x_mtx("../data/AD1/", # mtx文件所在的目录
var_names='gene_symbols', # 将 gene 作为 var
cache=True) # 开启缓存读写
# 消除重复的基因
adata.var_names_make_unique() -
对初始adata的预处理
1
2# 绘制了平均表达量前10的基因箱型图
sc.pl.highest_expr_genes(adata, n_top=10) -
质量控制
1
2
3
4
5# 基本的过滤(质控)
# pp指 pre process 预处理
sc.pp.filter_cells(adata, min_genes=200)
sc.pp.filter_genes(adata, min_cells=3) -
线粒体百分比的计算
1
2
3
4
5# 线粒体百分比的计算
adata.var['mt'] = adata.var_names.str.startswith('MT-')
adata.var['mt']
sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], percent_top=None, log1p=False, inplace=True)
adata.obs -
小提琴图展示
1
2
3
4
5# total_counts:每个细胞的基因总计数(总表达量)
# pct_counts_mt:每个细胞中,线粒体基因表达量占该细胞所有基因表达量的百分比
sc.pl.violin(adata, ['n_genes_by_counts', 'total_counts', 'pct_counts_mt'],
jitter=0.4, multi_panel=True) -
进行过滤
1
2
3# 进行过滤
adata = adata[adata.obs.n_genes_by_counts > 500, :]
adata = adata[adata.obs.pct_counts_mt < 20, :] -
进行归一化处理
1
2
3# 进行归一化处理
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata) -
高变基因的展示
1
2
3
4
5# 高变基因的展示
sc.pp.highly_variable_genes(adata, min_mean=0.0125, max_mean=3, min_disp=0.5)
sc.pl.highly_variable_genes(adata)
adata.raw = adata -
提取高变基因的表达矩阵
1
2
3
4
5
6
7
8# 提取高变基因的表达矩阵
adata = adata[:, adata.var.highly_variable]
# 对两个注释进行回归,消除它俩的影响
sc.pp.regress_out(adata, ['total_counts', 'pct_counts_mt'])
# 按零均值单位方差标准化数据,并裁剪超过标准差10的细胞
sc.pp.scale(adata, max_value=10) -
主成分分析(PCA)
1
2
3
4
5
6sc.tl.pca(adata, svd_solver='arpack')
sc.pl.pca_variance_ratio(adata, log=True)
# 将结果保存到声明的文件results_file
adata.write(result_file) -
计算 neighborhood graph
1
2# 使用PCA来计算细胞的领域图,为了umap降维,也为了聚类
sc.pp.neighbors(adata, n_neighbors=10, n_pcs=40) -
对 neighborhood graph 进行 embedding
1
2
3
4
5
6
7
8# 进行umap的可视化
sc.tl.umap(adata)
# 进行umap的展示
sc.pl.umap(adata, color=['NKG7'])
# 可以不适用原始数据
sc.pl.umap(adata, color=['NKG7'], use_raw=False) -
对 neighborhood graph 进行聚类
1
2
3
4
5# scanpy推荐leiden图聚类的方法
sc.tl.leiden(adata)
# 用umap对leiden聚类结果的可视化
sc.pl.umap(adata, color=['leiden', 'NKG7']) -
找到marker基因
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24# 计算每个簇存在较高程度差异的基因排名
# 在计算差异时,最简单最快的方式是t-检验
sc.tl.rank_genes_groups(adata, 'leiden', method='t-test')
# 展示差异基因
# 每个cluster的top20或者top50marker基因的展示
sc.pl.rank_genes_groups(adata, n_genes=25, sharey=False)
# 还可以使用wilcoxon的检测方式
sc.tl.rank_genes_groups(adata, 'leiden', method='wilcoxon')
sc.pl.rank_genes_groups(adata, n_genes=25, sharey=False)
# 差异基因以表格形式查看
pd.DataFrame(adata.uns['rank_genes_groups']['names']).head(5)
# 显示差异基因的名称和差异度
sc.tl.rank_genes_groups(adata, 'leiden', method='wilcoxon')
sc.pl.rank_genes_groups(adata, n_genes=25, sharey=False)
result = adata.uns['rank_genes_groups']
groups = result['names'].dtype.names
pd.DataFrame(
{group + '_' + key[:1] : result[key][group]
for group in groups for key in ['names', 'pvals']}
).head(5) -
marker基因展示
1
2
3
4
5
6
7
8# 用小提琴图展示前20个差异基因在该簇和剩余簇的分布差异
from matplotlib.pyplot import rc_context
with rc_context({'figure.figsize': (9, 1.5)}):
sc.pl.rank_genes_groups_violin(adata, n_genes=20, jitter=False)
# 直观地显示某个基因在不同簇中的表达
sc.pl.violin(adata, ['NKG7'], groupby='leiden') -
细胞类型注释
1
2
3
4
5
6
7
8
9
10
11
12# 每个cluster对应的细胞类型注释
new_cluster_names = [
'0', '1', '2':'CD14', '3':'endo', '4', '5':'NK'
]
adata.rename_categories('leiden', new_cluster_names)
# 可视化结果展示
pl.umap(adata, color='leiden', legend_loc='on data', title='', frameon=False)
# 用tracksplot验证基因与细胞的关系
sc.pl.rank_genes_groups_tracksplot(adata, n_genes=3)
多个样本单细胞数据整合 - ingest和BBKNN
整合算法介绍
ingest
- 一种基于PCA的简单方法用于集成数据(integrating data)
- 用已知的细胞类型数据去注释未知的
- ingest函数假设有一个带注释的参考数据集(有点类似SingleR),该数据集捕获了感兴趣的生物变异性。ingest是在参考数据上拟合模型,并使用它来投影新数据。目前,该模型是一个结合了邻居查找搜索树(neighbor lookup search tree)的PCA或者UMAP
ingest有以下特点:
- 由于ingest操作简单,过程清晰,因此工作流透明且快速
- 与BBKNN相似,ingest使数据矩阵本身保持不变。因为ingest是在embedding空间做分析
- 与BBKNN不同,ingest在解决了标签映射的同时,维持了可能具有特定簇或轨迹等所需属性的embedding(因为BBKNN是简单粗暴的对齐embedding)
BBKNN
- BBKNN:Batch balanced KNN,BBKNN是一种快速直观的去除批次效应工具,可直接用于scanpy工作流。它是
scanpy.pp.neighbors()的一种替代方法,这两个功能都是创建一个 neighbors graph,以便后续在聚类、pseudo time计算和UMAP可视化中使用 - 标准方法首先确定整个数据集中每个细胞的k个最近邻,然后将候选细胞转换为指数相关连接,然后作为进一步分析的基础。如果数据中存在批次效应(可能是由于不同的数据采集技术、协议变更,甚至是特别严重的操作员影响),那么将很难在不同批次中链接相应的细胞类型
- BBKNN修改了邻域构建步骤,以生成一个跨所有批次数据平衡的图。这种方法将邻居网络视为数据的主要表示形式。对于每个细胞,BBKNN图是通过独立地为每个设备提供的批次(单个数据集)中的每个细胞找到k个最近邻居来构建的,这使得每个细胞在每个批次中都有一个独立的邻居池。同类细胞的这些邻居都被加入列表联系起来
- 注意:BBKNN会将列表中的元素用简单快速的方式对齐,即对齐不同批次的同类细胞。所以才说BBKNN实现了数据整合
- BBKNN的主要假设是,批次间至少存在一些相同类型的细胞,并且批次效应引起的批次间相同细胞类型之间的差异小于批次内不同类型细胞之间的差异,在这种情况下,图的构造将跨批次将相似的细胞类型分组在一起,同时将不相关的细胞类型分开
使用BBKNN进行数据整合
1 | from bbknn import bbknn |
基于scanorama整合scRNA-seq和空间数据分析
官方连接:Spatial — scanpy
与单细胞数据具体整合流程见:使用 scanorama 将空间数据与 scRNA-seq 集成 — scanpy
- Scanorama可以实现scRNA-seq数据集集成和批次矫正
- 文章提出的方法是整合scRNA-seq的高效方案,与过去的ingest不同,不需要指定某个具体的参考数据集,其实过去方法的思想还是将数据整合到一个更大的簇中(域适应到参考数据集)
- Scanorama利用全景生成的思想,可以实现同时多个数据集的整合,可以自动匹配不同数据集下的相同细胞类型,同时保留不同数据集下不同细胞类型的差异,是更合理的整合方法
- 其中的异质指的是整合保留了两个数据集中真正存在差异的信息。Scanorama属于是实现了正确消除了技术,实验带来的批次效应
流程:
-
导包
1
2
3
4
5
6
7
8
9
10
11import os
import anndata
import scanpy as sc
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pooch
from scipy.sparse import csr_matrix
from scipy.io import mmwrite
import scanorama -
设置一些全局参数
1
2
3sc.logging.print_versions()
sc.set_figure_params(facecolor="white", figsize=(10, 10))
sc.settings.verbosity = 3 -
设置路径
1
2
3print(os.getcwd())
os.chdir("/home/oelab/RunData2/STM_AD_analyze/data/GSE220442_counts_and_images/counts_and_images/")
print(os.getcwd()) -
读取数据
1
2
3
4
5
6
7# 读取数据
AD1 = sc.read_visium("../counts_and_images/AD1/")
AD2 = sc.read_visium("../counts_and_images/AD2/")
AD3 = sc.read_visium("../counts_and_images/AD3/")
NC1 = sc.read_visium("../counts_and_images/NC1/")
NC2 = sc.read_visium("../counts_and_images/NC2/")
NC3 = sc.read_visium("../counts_and_images/NC3/") -
质控计算
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 质控计算
AD1.var_names_make_unique()
AD2.var_names_make_unique()
AD3.var_names_make_unique()
NC1.var_names_make_unique()
NC2.var_names_make_unique()
NC3.var_names_make_unique()
sc.pp.calculate_qc_metrics(AD1, inplace=True)
sc.pp.calculate_qc_metrics(AD2, inplace=True)
sc.pp.calculate_qc_metrics(AD3, inplace=True)
sc.pp.calculate_qc_metrics(NC1, inplace=True)
sc.pp.calculate_qc_metrics(NC2, inplace=True)
sc.pp.calculate_qc_metrics(NC3, inplace=True) -
可视化
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# 可视化
for name,adata in [
("AD_sample1", AD1),
("AD_sample2", AD2),
("AD_sample3", AD3),
("Normal_sample1", NC1),
("Normal_sample2", NC2),
("Normal_sample3", NC3)]:
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],)
plt.savefig("/home/oelab/RunData2/STM_AD_analyze/result/" + "qc1.distplot_" + name + ".png") -
数据整合
1
2
3
4
5
6
7
8
9
10
11AD1.obs["orig"] = 'AD'
AD2.obs["orig"] = 'AD'
AD3.obs["orig"] = 'AD'
NC1.obs["orig"] = 'Normal'
NC2.obs["orig"] = 'Normal'
NC3.obs["orig"] = 'Normal'
adatas = [AD1, AD2, AD3, NC1, NC2, NC3]
# 数据整合
adatas_cor = scanorama.correct_scanpy(adatas, return_dimred=True) -
将多个数据整合到一起并保存在整合后的embeddings中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17adatas_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"],
adatas_cor[2].uns["spatial"],
adatas_cor[3].uns["spatial"],
adatas_cor[4].uns["spatial"],
adatas_cor[5].uns["spatial"]
]
for k, v in d.items()
],
index_unique="-"
) -
降维聚类
1
2
3
4
5
6
7
8sc.pp.neighbors(adatas_spatial, use_rep="X_scanorama")
sc.tl.umap(adatas_spatial)
sc.tl.leiden(adatas_spatial, key_added="clusters")
sc.pl.umap(
adatas_spatial, color=["clusters", "library_id", "orig"], 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
23clusters_colors = dict(
zip([str(i) for i in range(18)], adatas_spatial.uns["clusters_colors"])
)
# 开始画图
fig, axs = plt.subplots(1, 6, figsize= (15, 10))
for i, library in enumerate(
["2-8", "T4857", "2-3", "2-5", "18-64", "1-1"]
):
ad = adatas_spatial[adatas_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()
Squidpy
教程:Squidpy - Spatial Single Cell Analysis in Python — squidpy documentation
ImageContainer对象
展示如何使用 squidpy.im.ImageContainer 与图像结构化数据交互
教程:ImageContainer object — squidpy documentation
流程:
-
初始化 ImageContainer
1
2
3
4
5
6
7import squidpy as sq
import scanpy as sc
import anndata as ad
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt1
2# 初始化ImageContainer -- 就是创建ImageContainer数据结构的对象
img = sq.im.ImageContainer(AD1.uns["spatial"]["2-8"]["images"]["hires"], library_id = "2-8", layer="image") -
添加 layers 到 ImageContainer
1
2
3
4
5
6
7# 添加layers到ImageContainer
## uns中存储的是空间信息
img.add_img(AD1.uns["spatial"]["2-8"]["images"]["hires"],
library_id = "2-8", layer="hires")
# 指定属性值,优先展示哪个属性
img["hires"].attrs["hires"] = True -
可视化
1
2
3
4
5
6
7# 可视化
img.show(layer = "image")
img.show("image", segmentation_layer="segmentation", segmentation_alpha=0.5)
for i, cmap in zip(range(3), ['Reds', 'Greens', 'Blues']):
img.show(layer='image', channel=i, cmap=cmap) -
裁剪和缩放图像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# 图像的裁剪和放缩
# x=0.5 代表在横坐标中间的位置
# y=0.5 代表在纵坐标中间的位置
# crop_center:围绕中心进行裁剪
# 左图
img.crop_center(y = 0.5, x = 0.5, radius=200).show(layer="image")
# 右图
img.crop_center(y = 0.5, x = 0.5, radius=100).show(layer="image")
# crop_corner:是将这个点作为起始点截取向右、向上的正方形
img.crop_corner(y = 0.2, x = 0.3, radius=400).show(layer="image")
img.crop_corner(y = 0.2, x = 0.3, radius=200).show(layer="image")
# 查看裁剪之后的图像
sc.pl.spatial(
adata_crop[adata_crop.obs["library_id"] == "2-8"], color = ["CD4"],
library_id="2-8", frameon=False, cmap="Spectral_r", size=1.3
) -
处理图像和提取特征
-
图像的内部表示
添加多个样本,对多个样本进行提取:
1 | # 添加多个样本,对多个样本进行提取 |
使用Napari进行交互式可视化
就是展示如何在Napari中可视化ImageContainer和AnnData
使用 Napari 可视化图像并与之交互 — 使用 Napari 和 Python 进行图像分析(亥姆霍兹成像暑期学院 2022 年)
流程:
-
安装Napari
1
2!(conda install -c conda-forge napari pyqt -y)
pip install deprecated -
加载数据
1
2
3
4
5
6import squidpy as sq
import os
import scanpy as sc
adata = sq.datasets.visium_hne_adata()
adata = sc.read("xxxx")
img = sq.datasets.visium_hne_image() -
启动
1
2# 运行viewer
viewer = img.interactive(adata)
Seurat 空转数据分析
链接:Analysis, visualization, and integration of Visium HD spatial datasets with Seurat • Seurat
代码注释见上面的链接:
1 | # 加载R包 |
做图技巧
去除黑圈:
1 | # 去掉黑圈 |
利用seurat单细胞的函数实现空转spot分布:
1 | # 利用seurat单细胞的函数实现空转spot分布 |
Giotto
Giotto工具箱是Giotto软件包的升级版本,提供了处理、分析和可视化各种尺度和多种分辨率的空间多组学数据的工具。它的基本框架可推广到几乎所有当前和新兴的空间组学技术上,例如:原位杂交(seqFISH+, merFISH, osmFISH, CosMx)、测序(Slide-seq, Visium, STARmap, SeqScope, Stereo-Seq)以及基于成像的多组学技术(CyCIF, MIBI, CODEX)等。这些技术在分辨率(亚细胞、单细胞或多细胞)、空间维度(2D vs 3D)、分子形态(蛋白质、RNA、DNA等)和通量(细胞和分析物的数量)方面有所不同
Seurat调用不了Python,但是Giotto可以调用Python
Giotto链接:Spatial Single-Cell Transcriptomics Toolbox - Giotto
配置环境:
1 | conda create -n giotto_env python=3.10.2 -c https://mirror.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/ |
1 | conda activate giotto_env |
各个包的版本:Giotto python 环境 — giotto_python • GiottoClass
1 | pip3 install pandas==1.5.1 -i https://pypi.tuna.tsinghua.edu.cn/simple |
在Rstudio中使用python分析空转数据:reticulate包
1 | # 安装reticulate包 |
R中配置环境:
1 | # 直接指定使用python版本的执行程序 |
直接在Tools的global option里面选择
1 | # 查看配置信息 |
启动python:
1 | repl_python() |
安装Giotto:
1 | if(!"pak" %in% installed.packages()) { |
检查是否安装成功:
1 | library(Giotto) |
检查环境是否能够调用成功:
1 | > checkGiottoEnvironment() |
创建Giotto Visium对象和可视化流程
1 | ##系统报错改为英文 |
R中单细胞空转联合分析 - RCTD
单细胞联合空间主流软件介绍
R中常用的软件:
Seurat:TransferAnchorsRCTD:robust cell type decomposition 鲁棒细胞类型分解Spotlight:非负矩阵因子分解回归CellTrek:训练多元随机森林(RF)模型,使用共享降维特征预测空间坐标CARD:conditional autoregressive-based deconvolution,基于条件自回归的反卷积Giotto:PAGE(Parametric Analysis of Gene Set Enrichment)Giotto:HyperGeometric test 超几何检验(与MIA相似)Giotto:rank,它不是基于基因集的方法,而是使用单细胞所有的表达数据MIA:Multimodal intersection analysis(多模态交集分析)
python中常用的软件:
ScanoramaTangramCell2location
RCTD
RCTD:一种利用从scRNA-seq中学习细胞类型的表达谱对空间转录组 spot 内混合细胞的类型进行稳健分解的工具 RCTD(robust cell type decomposition),并考虑到了来自不同测序方法数据间的系统误差,克服了平台效应(platform effect)的影响
教程:https://github.com/dmcable/spacexr
RCTD可以将单细胞类型或细胞类型混合分配到空间转录组spots上。RCTD 有三种模式:
- Doublet mode:它为每个Spot分配1-2种细胞类型,推荐用于高空间分辨率的技术,如Slide-seq和MERFISH
- Full mode:它为每个Spot分配任意数量的细胞类型,推荐用于空间分辨率较低的技术,如100微米分辨率的Visium
- Multi mode:doublet mode的扩展,可以在每个点上发现两种以上的细胞类型,作为full mode的替代选项
模式一:Doublet mode
加载数据包:
1 | # install.packages("devtools") |
R中单细胞空转联合分析 - CellTrek(了解)
CellTrek:可以结合单细胞和空间转录组数据来准确地定位组织内单个细胞的位置,并构建空间细胞图谱
- 一种可以基于scRNA-seq和ST数据将单细胞直接映射回组织切片空间坐标的计算工具包。该方法不同于ST解卷积,能够更灵活和直接地研究具有空间地形的单细胞数据
- CellTrek工具包还提供了两个下游分析模块,包括用于空间共定位分析的SColoc和用于空间共表达分析的SCoexp






