1.基于python的单细胞数据预处理-质量控制

目录

  • 质量控制
  • 过滤低质量细胞的指南
  • 双细胞过滤
  • 手动过滤低质量读数细胞
  • 自动过滤低质量读数细胞
  • 环境RNA校正

参考
[1] https://github.com/Starlitnightly/single_cell_tutorial
[2] https://github.com/theislab/single-cell-best-practices

质量控制

原始的单细胞测序数据具有以下特点:

  • 由于测序深度不够,测序数据中会存在很多0值,这被称为drop-out事件;这是具有迷惑性的,因为对于一个细胞的具体基因表达量为0,我们不能判断到底是测序深度不够导致的,还是本身这个基因就不表达。
  • 由于细胞状态不同,我们必然会测量到一些即将死亡的细胞,这些衰老细胞的基因表达情况相对正常细胞的数据也是一个误差。
  • 测序技术本身不是百分百精确,比如液滴技术有时候会一个液滴中包含两个细胞,这样的基因表达量会非常高。一般正常细胞的基因表达量在3000-4000左右。

质量控制方法被用于初步过滤以上异常情况。随着大量的工程积累,下面演示为目前大家认可的最佳质量控制步骤。

使用的数据:这是一个基于10x-Multiome技术的数据集。该数据集测量了来自12名健康人类受试者在4个不同site(骨髓抽取的位置:手臂,胸骨等)的骨髓单核细胞的单细胞多组学数据(包含了嵌套的批次效应)。这里使用的数据是受试者8的样本4。

下载地址为:https://figshare.com/ndownloader/files/39546196

读取数据:

import omicverse as ov
import scanpy as sc

ov.utils.ov_plot_set()

adata = sc.read_10x_h5("./data/filtered_feature_bc_matrix.h5")
print(adata)

"""
AnnData object with n_obs × n_vars = 16934 × 36601
    var: 'gene_ids', 'feature_types', 'genome'
"""

由于原始数据中有的obs_names或者var_names会重名,我们执行unique,在重名names字符串后自动添加1,2等字符使变量名唯一:

adata.var_names_make_unique()
adata.obs_names_make_unique()

adata.X形状为16934 × 36601,分别对应着barcodesnumber of transcripts,var里有三个元素,gene_ids为来自Ensembl的基因id,genome为基因组的名字:

  • Ensembl ID是生物学领域中用于唯一标识基因和其他生物学序列的一种标识符
  • 如果已知genome(基因组的名字),我们可以通过额外的注释数据获得基因组所在的坐标,然后就能为RNA特征和ATAC特征建立关联。
print(adata.var.head())
"""
                    gene_ids    feature_types  genome
MIR1302-2HG  ENSG00000243485  Gene Expression  GRCh38
FAM138A      ENSG00000237613  Gene Expression  GRCh38
OR4F5        ENSG00000186092  Gene Expression  GRCh38
AL627309.1   ENSG00000238009  Gene Expression  GRCh38
AL627309.3   ENSG00000239945  Gene Expression  GRCh38
"""

过滤低质量细胞的指南

这是质量控制的第一步,主要针对三个质控协变量:

  • 1.每个barcode的计数数量(计数深度),barcode即一个细胞样本;
  • 2.每个barcode的基因数量;
  • 3.每个barcode的线粒体基因计数比例;

当检测到基因数量较少,计数深度较低,线粒体计数较高时,细胞膜可能会破裂,这说明细胞正在死亡,这种样本一般都不是我们分析的主要目标,从而误导下游分析,应该去除。

说明:如果一个细胞正在死亡,那么其mRNA被释放到内环境,导致线粒体基因的比例较高,所以可以通过线粒体基因的比例来过滤掉低质量的单细胞测序数据。但是如果仅考虑一个变量可能会造成生物学误差,共同考虑三个 QC 协变量至关重要。例如,线粒体计数相对较高的细胞可能参与呼吸过程,不应被过滤掉。然而,计数低或高的细胞可能对应于静止细胞群或尺寸较大的细胞。故在过滤低质量细胞的时候,要同时考虑不同的QC协变量之间的关系。

对于简单的数据,可以观察数据分布来确定协变量过滤的阈值。随着数据规模的增长,手动观察阈值不可行,我们可以通过计算MAD(median absolute deviations)设置阈值,如果计数大于5倍的MAD,我们可以认为这是一个异常值。

这里使用的数据集是人类骨髓,因此线粒体计数是以“ MT-”前缀注释的。对于鼠数据集,前缀通常是小写“ mt-”。

除了统计线粒体基因比例,scanpy还能统计指定基因的计数比例,比如核糖体,血红蛋白基因:

# 线粒体基因
adata.var["mt"] = adata.var_names.str.startswith("MT-")
# 核糖体基因
adata.var["ribo"] = adata.var_names.str.startswith(("RPS", "RPL"))
# 血红蛋白基因
adata.var["hb"] = adata.var_names.str.contains(("^HB[^(P)]"))

sc.pp.calculate_qc_metrics(
    adata, qc_vars=["mt", "ribo", "hb"], inplace=True, percent_top=[20], log1p=True
)

print(adata)
"""
AnnData object with n_obs × n_vars = 16934 × 36601
    obs: 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_20_genes', 'total_counts_mt', 'log1p_total_counts_mt', 'pct_counts_mt', 'total_counts_ribo', 'log1p_total_counts_ribo', 'pct_counts_ribo', 'total_counts_hb', 'log1p_total_counts_hb', 'pct_counts_hb'
    var: 'gene_ids', 'feature_types', 'genome', 'mt', 'ribo', 'hb', 'n_cells_by_counts', 'mean_counts', 'log1p_mean_counts', 'pct_dropout_by_counts', 'total_counts', 'log1p_total_counts'
"""

在obs中有三个变量:

  • n_genes_by_counts:一个细胞中发现的有效基因数量(即表达量不为0)
  • total_counts:一个细胞中发现的分子数量(UMI),通常也可以被认为是这个细胞的文库大小(adata.obs['total_counts'] = adata.X.toarray().sum(axis=1)
  • pct_counts_mt:一个细胞中线粒体基因的表达计数占比(adata.obs['pct_counts_mt'] = adata[:, adata.var["mt"]].X.toarray().sum(axis=1) / adata.obs['total_counts'].values

绘制协变量分布图,可以直观看到三个协变量:

mito_filter = 15
n_counts_filter = 4300
fig, axs = plt.subplots(ncols = 2, figsize = (8,4))
sc.pl.scatter(adata, x='total_counts', y='pct_counts_mt',ax = axs[0], show=False)
sc.pl.scatter(adata, x='total_counts', y='n_genes_by_counts',ax = axs[1], show = False)
#draw horizontal red lines indicating thresholds.
axs[0].hlines(y = mito_filter, xmin = 0, xmax = max(adata.obs['total_counts']), color = 'red', ls = 'dashed')
axs[1].hlines(y = n_counts_filter, xmin = 0, xmax = max(adata.obs['total_counts']), color = 'red', ls = 'dashed')
fig.tight_layout()
plt.savefig("./result/2-1.png")

fig1
在这个案例中,首先对双细胞进行过滤(表达量过大),然后进行质控:过滤比如total_counts小于500的细胞,比如n_genes_by_counts小于250的细胞,线粒体基因的计数比例不超过15%。请不要忽视质量控制的每一步,这对后续分析尤为重要

双细胞过滤

双细胞是可能存在的,两个小尺寸细胞容易被同一个液滴捕获,每个液滴被barcode标记,这也是用barcode而不是cell的原因(没有完美单细胞测量,只能说分辨率几乎接近单细胞)。双细胞存在下面两种:

  • 同型:同型通常被认为是不影响下游分析的,因为其是由一类相同的细胞中的两个所构成,所以这部分细胞不是我们所需要过滤的对象
  • 异型:异型通常是由来自两类不同的细胞所构成的,异型的存在会使得我们后续的细胞分类出现错误

使用sc中的scrublet去除异型双细胞:

# Original QC
n0 = adata.shape[0]
print(f'Original cell number: {n0}')

print('Begin of post doublets removal and QC plot')
sc.external.pp.scrublet(adata, random_state=112)
adata = adata[adata.obs['predicted_doublet']==False, :].copy()
n1 = adata.shape[0]
print(f'Cells retained after scrublet: {n1}, {n0-n1} removed.')
print(f'End of post doublets removal and QC plots.')

"""
Cells retained after scrublet: 16931, 3 removed.
"""

在双细胞过滤后,按照指南,过滤低质量读数细胞,我们分别演示手动和自动过滤,所以,复制两份adata:

adata_manual=adata.copy()
adata_auto=adata.copy()

手动过滤低质量读数细胞

首先定义一个过滤字典,然后按照字典进行过滤:

import numpy as np
tresh={'mito_perc': 15, 'nUMIs': 500, 'detected_genes': 250}

adata_manual.obs['passing_mt'] = adata_manual.obs['pct_counts_mt'] < tresh['mito_perc']
adata_manual.obs['passing_nUMIs'] = adata_manual.obs['total_counts'] > tresh['nUMIs']
adata_manual.obs['passing_ngenes'] = adata_manual.obs['n_genes_by_counts'] > tresh['detected_genes']

print(f'Lower treshold, nUMIs: {tresh["nUMIs"]}; filtered-out-cells: {n1-np.sum(adata_manual.obs["passing_nUMIs"])}')
print(f'Lower treshold, n genes: {tresh["detected_genes"]}; filtered-out-cells: {n1-np.sum(adata_manual.obs["passing_ngenes"])}')
print(f'Lower treshold, mito %: {tresh["mito_perc"]}; filtered-out-cells: {n1-np.sum(adata_manual.obs["passing_mt"])}')

保留剩余的细胞的交集:

QC_test = (adata_manual.obs['passing_mt']) & (adata_manual.obs['passing_nUMIs']) & (adata_manual.obs['passing_ngenes'])
removed = QC_test.loc[lambda x : x == False]
print(f'Total cell filtered out with this last  QC (and its chosen options): {n1-np.sum(QC_test)}')
adata_manual = adata_manual[QC_test, :].copy()
n2 = adata_manual.shape[0]
   
print(f'Cells retained after scrublet and filtering: {n2}, {n0-n2} removed.')

最后,再添加一步,直接过滤掉一些从基因和细胞层面低计数的细胞/基因:

sc.pp.filter_cells(adata_manual, min_genes=200)
sc.pp.filter_genes(adata_manual, min_cells=3)
print(adata_manual)

自动过滤低质量读数细胞

自动过滤也需要设置基础最低阈值,MAD计算可以获得最高阈值:

tresh={'pct_counts_mt': 15, 'total_counts': 500, 'n_genes_by_counts': 250}
adata_auto.obs['passing_mt'] = adata_auto.obs['pct_counts_mt'] < tresh['pct_counts_mt']
adata_auto.obs['passing_nUMIs'] = ov.pp._qc.mads_test(adata_auto.obs, 'total_counts', nmads=5, lt=tresh)
adata_auto.obs['passing_ngenes'] = ov.pp._qc.mads_test(adata_auto.obs, 'n_genes_by_counts', nmads=5, lt=tresh)  

nUMIs_t = ov.pp._qc.mads(adata_auto.obs, 'total_counts', nmads=5, lt=tresh)
n_genes_t = ov.pp._qc.mads(adata_auto.obs, 'n_genes_by_counts', nmads=5, lt=tresh)

print(f'Tresholds used, nUMIs: ({nUMIs_t[0]}, {nUMIs_t[1]}); filtered-out-cells: {n1-np.sum(adata_auto.obs["passing_nUMIs"])}')
print(f'Tresholds used, n genes: ({n_genes_t[0]}, {n_genes_t[1]}); filtered-out-cells: {n1-np.sum(adata_auto.obs["passing_ngenes"])}')
print(f'Lower treshold, mito %: {tresh["pct_counts_mt"]}; filtered-out-cells: {n1-np.sum(adata_auto.obs["passing_mt"])}')

剩下步骤与手动注释一样:

QC_test = (adata_auto.obs['passing_mt']) & (adata_auto.obs['passing_nUMIs']) & (adata_auto.obs['passing_ngenes'])
removed = QC_test.loc[lambda x : x == False]
print(f'Total cell filtered out with this last  QC (and its chosen options): {n1-np.sum(QC_test)}')
adata_auto = adata_auto[QC_test, :].copy()
n2 = adata_auto.shape[0]

print(f'Cells retained after scrublet and filtering: {n2}, {n0-n2} removed.')

sc.pp.filter_cells(adata_auto, min_genes=200)
sc.pp.filter_genes(adata_auto, min_cells=3)
print(adata_auto)

环境RNA校正

对于基于液滴的单细胞RNA测序实验,在分配到含有细胞的液滴中存在一定量的背景mRNA,并且随着液滴一起被测序。这样做的结果是产生了一种背景污染,代表了不是来自液滴中包含的细胞,而是来自含有细胞的溶液中的RNA表达。

无细胞的 mRNA 分子,也被称为环境 RNA,混淆了观察到的计数的数量。对于无细胞 mRNA,纠正基于液滴的 scRNA-seq 数据集非常重要,因为它可能会扭曲我们下游分析中数据的解释。具体校正方法参考:soupX

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/607819.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

模拟实现链表的功能

1.什么是链表&#xff1f; 链表是一种物理存储结构上非连续存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。 实际中链表的结构非常多样&#xff0c;以下情况组合起来就有8种链表结构&#xff1a; 单向或者双向 带头或者不带头 …

猫头虎分享已解决Bug || Node.js安装失败Error: unable to connect to https://nodejs.org/猫头虎

猫头虎分享已解决Bug || Node.js安装失败Error: unable to connect to https://nodejs.org/猫头虎 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — …

活动回顾 |观测云 AI Agent 探索实践

亚马逊云科技“构建全球化软件和互联网新生态——ISV 行业”论坛上&#xff0c;观测云产品架构师刘锐发表了题为“AI Agent 可观测性探索与实践”的主题演讲&#xff0c;不仅展示了观测云在人工智能领域的前沿技术&#xff0c;更强调了在日益复杂的系统环境中&#xff0c;实现有…

autoware.universe 使用之Rosbag replay simulation放包仿真

本文将按照官方文档&#xff0c;通过播放rosbag录制包进行可视化模拟&#xff0c;中间也报了很多错误&#xff0c;特此记录下来&#xff0c;以免后续踩坑。 电脑配置如下&#xff1a;    ubuntu20.04    cuda: cuda-11.6    nvidia-driver 535    ros2: foxy 关于auto…

「MDN web 入门」学习笔记

目录 写在前面 1. MDN 简介 1.1 MDN 的主要特点 1.2 MDN 的主要功能 1.3 MDN 网页开发的指南 2. 安装基础软件 2.1 专业人士工具 2.2 初学者基本工具 3. 设计网站外观 3.1 计划 3.2 绘制草图 3.3 选定素材 3.4 文本 3.5 主题颜色 3.6 图像 3.7 字体 4. 处理文…

Redis(无中心化集群搭建)

文章目录 1.无中心化集群1.基本介绍2.集群说明 2.基本环境搭建1.部署规划&#xff08;6台服务器&#xff09;2.首先删除上次的rdb和aof文件&#xff08;对之前的三台服务器都操作&#xff09;1.首先分别登录命令行&#xff0c;关闭redis2.清除/root/下的rdb和aof文件3.把上次的…

认识卷积神经网络

我们现在开始了解卷积神经网络&#xff0c;卷积神经网络是深度学习在计算机视觉领域的突破性成果&#xff0c;在计算机视觉领域&#xff0c;往往我们输入的图像都很大&#xff0c;使用全连接网络的话&#xff0c;计算的代价较高&#xff0c;图像也很难保留原有的特征&#xff0…

oracle 数据库找到UDUMP的文件名称

oracle 数据库找到UDUMP的文件名称 select p.value||\||i.instance_name||_ora_||spid||.trc as "trace_file_name" from v$parameter p ,v$process pro, v$session s, (select sid from v$mystat where rownum1) m, v$instance i where lower(p.name)user_dump_…

Java_File

介绍&#xff1a; File对象表示路径&#xff0c;可以是文件&#xff0c;也可以是文件夹。这个路径可以是存在的&#xff0c;也可以是不存在的&#xff0c;带盘符的路径是绝对路径&#xff0c;不带盘符的路径是相对路径&#xff0c;相对路径默认到当前项目下去找 构造方法&…

英伟达推出视觉语言模型:VILA

NVIDIA和MIT的研究人员推出了一种新的视觉语言模型(VLM)预训练框架&#xff0c;名为VILA。这个框架旨在通过有效的嵌入对齐和动态神经网络架构&#xff0c;改进语言模型的视觉和文本的学习能力。VILA通过在大规模数据集如Coy0-700m上进行预训练&#xff0c;采用基于LLaVA模型的…

三.Django--ORM(操作数据库)

目录 1 什么是ORM 1.1 ORM优势 1.2ORM 劣势 1.3 ORM与数据库的关系 2 ORM 2.1 作用 2.2 连接数据库 2.3 表操作--设置字段 2.4 数据库的迁移 写路由增删改查操作 项目里的urls.py: app里的views.py: 注意点: 1 什么是ORM ORM中文---对象-关系映射 在MTV,MVC设计…

2024面试自动化测试面试题【含答案】

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

若依框架dialog弹窗取消点击空白出关闭

如果想全局取消的话就找到main.js在里面加上下面的一行代码&#xff0c;添加完成之后记得清楚浏览器缓存重新加载js文件。 Element.Dialog.props.closeOnClickModal.default false;如果想指定某个弹窗取消点击空白处关闭&#xff0c;那么就找到那个弹窗加上。添加完毕之后刷新…

扩散模型~

推荐&#xff1a;write_own_pipeline.ipynb - Colab (google.com) 基本管道 一直显示NVIDIA有问题&#xff0c;所以就把.to("cuda")去掉了&#xff0c;使用Colab运行的&#xff0c;代码如下&#xff1a; from diffusers import DDPMPipelineddpm DDPMPipeline.fr…

哈希题目总结

以下列举了可以用哈希方法&#xff08;包括但不限于用HashMap和HashSet&#xff09;的题目&#xff0c;实质上是把东西丢给这些数据结构去维护。请注意有些题目中用哈希是最优解&#xff0c;有些题目中不是最优解&#xff0c;可以自行探索其时间复杂度和空间复杂度的区别&#…

java入门1.1.1版本

前言&#xff1a; 上面的内容是1.0.0~1.1的内容总结 秉持着先做再定义的理念&#xff0c;这里会带着大家先体验一下类与对象 第一步&#xff1a;新建一个java文件 鼠标右键 → 新建 → 文本文档 → 右键 → 点击重名 → 全选 → hello.java 第二步&#xff1a;用笔记本打开 …

阿里云开发uniapp之uni-starter

一、为什么使用uni-starter uni-starter是集成商用项目常见功能的、云端一体应用快速开发项目模版。 一个应用有很多通用的功能&#xff0c;比如登录注册、个人中心、设置、权限管理、拦截器、banner... uni-starter将这些功能都已经集成好&#xff0c;另外&#xff0c;uni-s…

2023-2024年SaaS行业报告合集(精选22份)

SaaS行业报告/方案&#xff08;精选21份&#xff09; 2023-2024年 报告来源&#xff1a;2023-2024年SaaS行业报告合集&#xff08;精选22份&#xff09; 【以下是资料目录】 2024中国HCM SaaS领导者竞争力持续增强的行业龙头 2024年中国企业级SaaS行业研究报告 2024年SaaS…

基于Transformer网络的多步预测模型

包括完整流程数据代码处理&#xff1a; 多步预测数据集制作、数据加载、模型定义、参数设置、模型训练、模型测试、预测可视化、多步预测、模型评估 ● 环境框架&#xff1a;python 3.9 pytorch 1.8 及其以上版本均可运行 ● 使用对象&#xff1a;论文需求、毕业设计需求者…

Offer必备算法37_记忆化搜索_五道力扣题详解(由易到难)

目录 记忆化搜索概念和使用场景 ①力扣509. 斐波那契数 解析代码1_循环 解析代码2_暴搜递归 解析代码3_记忆化搜索 解析代码4_动态规划 ②力扣62. 不同路径 解析代码1_暴搜递归&#xff08;超时&#xff09; 解析代码2_记忆化搜索 解析代码3_动态规划 ③力扣300. 最…
最新文章