生信学习笔记:ArchR 处理小麦单细胞 ATAC-seq 中的细胞数差异与 Embedding 报错调试

1. 问题描述

在利用 ArchR 处理小麦(Wheat)单细胞 ATAC-seq 数据时,于"降维-聚类-可视化"环节观察到两个异常现象:

  1. 细胞数量的"迷之减少" :在分析流程的不同阶段,细胞总数经历了从 105,317 →\rightarrow→ 101,385 →\rightarrow→ 100,423 的梯度下降。
  2. Embedding 提取报错:在尝试提取 UMAP 坐标进行绘图时,系统提示找不到对应的 Embedding 对象,导致可视化中断。

2. 源码逻辑与代码对比

源码逻辑(ArchR 标准流程)

ArchR 的设计初衷是先构建一个稳定的低维空间(Reduced Dimensions) ,再基于此空间生成流形投影(Embedding),最后进行聚类分析。

  • addIterativeLSI():构建降维特征矩阵。
  • addUMAP():基于 LSI 结果生成二维投影。
  • addClusters():基于 LSI 结果进行聚类。

我的错误代码段(循环嵌套逻辑)

R 复制代码
# 错误示范:在循环中多次尝试生成 UMAP 并动态命名
for(res in c(0.4, 0.6, 0.8)){
  proj <- addClusters(input = proj, reducedDims = "IterativeLSI", resolution = res, name = paste0("Cluster_", res))
  # 报错诱因:在这里重复运行 addUMAP 并赋予了非标准名称
  proj <- addUMAP(ArchRProj = proj, reducedDims = "IterativeLSI", name = paste0("UMAP_", res), force = TRUE)
}
plotEmbedding(ArchRProj = proj, embedding = "UMAP", colorBy = "cellColData", name = "Cluster_0.6")

报错信息

Error: Embedding 'UMAP' does not exist in ArchRProject!

或在某些文件操作时出现:
Permission Error: Cannot write to ArrowFile...


3. 原因深度分析

3.1 细胞数量减少的"三部曲"

细胞数的变动并非数据丢失,而是经过了物理过滤数学算法排除的双重筛选:

  • Step 1 (105,317): 原始 QC(TSS 分数和片段数)达标后的细胞基数。
  • Step 2 (101,385): 运行 filterDoublets 后,物理剔除了 3,932 个统计学意义上的双细胞(Doublets)。这是为了防止伪影细胞干扰下游分析。
  • Step 3 (100,423): 运行 addIterativeLSI 时,剩余的 962 个细胞被排除。通过数据回溯发现,这 962 个细胞恰好构成了整个样本 C_Z8_2d_3
    • 数学原因addIterativeLSI 默认开启了 outlierQuantiles = c(0.02, 0.98),会自动过滤掉特征极其稀疏或偏倚严重的细胞。当整个样本的测序质量或复杂度处于极端分位数时,会被识别为"离群值"而无法投影到高维空间。

3.2 找不到 Embedding 的逻辑陷阱

在 ArchR 对象中,plotEmbedding 默认寻找名为 "UMAP" 的槽位。

  • 在上述循环代码中,用户将 Embedding 命名为 UMAP_0.6 等自定义名称。
  • 随后调用 plotEmbedding(embedding = "UMAP") 时,系统无法在 @embeddings 槽位中找到该名称,从而报错。
  • 此外,在循环中反复对同一个 LSI 空间运行 addUMAP 并多次读写 Arrow 文件,极易触发底层 HDF5 文件的权限冲突。

4. 解决方案与优化建议

纠正后的标准代码

原则:先统一构建空间,后并行探索分辨率。

R 复制代码
# 1. 降维(一次性完成)
proj <- addIterativeLSI(ArchRProj = proj, useMatrix = "TileMatrix", name = "IterativeLSI")

# 2. 生成全局 UMAP 投影(一次性完成,默认名称为 "UMAP")
proj <- addUMAP(ArchRProj = proj, reducedDims = "IterativeLSI", name = "UMAP")

# 3. 循环探索聚类分辨率(仅更新 cellColData,不改动降维和投影)
for(res in c(0.4, 0.6, 0.8)){
  proj <- addClusters(input = proj, reducedDims = "IterativeLSI", resolution = res, name = paste0("Cluster_", res), force = TRUE)
}

# 4. 绘图(此时 Embedding 槽位存在 "UMAP")
p <- plotEmbedding(ArchRProj = proj, embedding = "UMAP", colorBy = "cellColData", name = "Cluster_0.6")

为什么"先 UMAP 再循环聚类"更好?

  • 计算效率:UMAP 投影非常耗时,且它不依赖于聚类标签,只需运行一次即可。
  • 逻辑清晰 :聚类只是给细胞贴标签(存储在 cellColData),而 UMAP 是坐标映射。保持投影稳定,才能客观观察不同分辨率下聚类边界的变化。

5. 核心知识点总结

  1. IterativeLSI 原理 :采用 TF-IDF 归一化和迭代聚类的方法处理稀疏的 ATAC-seq 数据,通过 outlierQuantiles 自动过滤极端偏倚细胞以确保降维空间的鲁棒性。
  2. 双细胞过滤的影响filterDoublets 通过模拟异质性双细胞并计算富集分数来剔除物理上的重叠细胞。
  3. ArchR 槽位逻辑
    • @reducedDims:存储高维特征(如 LSI 矩阵)。
    • @embeddings:存储二维坐标(如 UMAP 结果)。
    • cellColData:存储细胞属性(如样本来源、聚类标签、TSS 分数)。

小结:在处理单细胞数据时,细胞数量的变动往往意味着算法在自动维护数据的"纯净度"。面对报错,理解 ArchR 对象的底层存储逻辑比盲目修改参数更为高效。

相关推荐
世人万千丶7 小时前
参数管理_Flutter在鸿蒙平台路由参数最佳实践
学习·flutter·华为·harmonyos·鸿蒙
遇乐的果园10 小时前
前端学习笔记-vue加载渲染优化
前端·笔记·学习
遇乐的果园12 小时前
前端学习笔记-vue状态管理优化
前端·笔记·学习
从零开始的代码生活_12 小时前
C++ 继承详解:访问控制、对象模型、菱形继承与设计取舍
开发语言·c++·后端·学习·算法
可乐奶茶sky12 小时前
AI Agent 学习
人工智能·学习
茯苓gao13 小时前
嵌入式开发笔记:EtherCAT协议从硬件到软件完整配置指南——从零搭建一套EtherCAT通信系统
笔记·嵌入式硬件·学习
RD_daoyi15 小时前
外链权重暴跌至13%,品牌提及反超传统链接——2026年不做Digital PR,你的独立站等于隐形
运维·网络·学习·机器学习·搜索引擎
chase。15 小时前
【学习笔记】PointWorld:迈向通用机器人操控的3D世界模型
笔记·学习·机器人
AOwhisky16 小时前
Python 学习笔记(第十三期)——运维自动化(下·前篇):远程命令执行——paramiko基础篇
运维·python·学习·云原生·自动化·运维开发·paramiko
前端世界16 小时前
MySQL 基础入门(学习第4天)——约束与 DML 操作详解
数据库·学习·mysql