39. 注释#

   关键要点

ADT 数据注释通过用表面蛋白标记来补充 RNA 数据,从而改善细胞识别,对免疫细胞尤其有帮助。

动机
   环境设置
  1. 安装 conda:

    • 在创建环境之前,请确保 conda 已安装在您的系统中。

  2. 保存 yml 内容:

    • 将 yml 选项卡中的内容复制到名为 environment.yml 的文件中。

  3. 创建环境:

    • 打开终端或命令提示符。

    • 运行以下命令:

      conda env create -f environment.yml
      
  4. 激活环境:

    • 创建好环境后,使用以下命令激活它:

      conda activate <environment_name>
      
    • 替换 <environment_name> ,名称就是在 environment.yml 文件中指定的那个。在 yml 文件里,它看起来像这样:

      name: <environment_name>
      
  5. 验证安装:

    • 通过运行以下命令,检查环境是否创建成功:

      conda env list
      
name: surface-protein
channels:
  - conda-forge
dependencies:
  - python=3.13
  - scanpy=1.12
  - muon=0.1.7
  - python-igraph=1.0.0
  - ipykernel=7.2.0
  - pip==26.0.1
  - pip:
      - lamindb==2.3.1
      - harmonypy==0.0.9
   获取数据和笔记本

本书使用 lamindb,并通过 theislab/sc-best-practices 实例 来存储、共享和加载数据集与笔记本。感谢 Lamin Labs 提供免费托管服务。

  1. 安装 lamindb

    • 安装 lamindb Python 软件包:

    pip install lamindb
    
  2. 可选择创建 lamin 账户

    • 按照以下 说明 注册并登录。

  3. 验证你的设置

    • 运行 lamin connect 命令:

    import lamindb as ln
    
    ln.Artifact.connect("theislab/sc-best-practices").df()
    

    你现在应该看到最多 100 个存储的数据集。

  4. 访问数据集(Artifact)

    • Artifacts 页面 搜索该数据集。

    • 加载一个 Artifact 及其对应的对象:

    import lamindb as ln
    af = ln.Artifact.connect("theislab/sc-best-practices").get(key="key_of_dataset", is_latest=True)
    obj = af.load()
    

    该对象现在已可在内存中访问,并可用于分析。请调整 ln.Artifact.connect("theislab/sc-best-practices").get("SOMEIDXXXX") 后缀以获取相应的版本。

  5. 访问笔记本(Transform)

    lamin load <notebook url>
    

    这会把笔记本下载到当前工作目录。与 Artifacts 类似,你可以调整后缀 ID 来获取旧版本。

39.1. 动机#

与 scRNA-seq 数据类似,也可以基于表面蛋白标记对 ADT 数据进行注释。这对免疫细胞的注释尤其有益,因为免疫细胞在 RNA 层面很难注释,而它们的表面蛋白却能很好地刻画它们。scRNA-seq 数据可能存在 dropout(基因漏检):即某个基因虽然在某个细胞群中表达,但由于测序流程的限制,在部分细胞中却检测不到。相比之下,由于 ADT 使用抗体来定量表面蛋白,受 dropout 的影响要小得多。因此,单个表面蛋白在 ADT 数据中的信号比在 RNA 数据中更强。

例如,尽管被测序的免疫细胞通常包含 CD45 阳性细胞,但 CD45 基因在 RNA 数据中并不总是高表达。通过(额外)在 ADT 层面进行注释,可以缓解这一问题。

一般的注释流程使用与 RNA 数据相同的函数,不需要 ADT 特有的函数。

39.2. 环境设置#

import warnings

import muon as mu
import scanpy as sc

warnings.filterwarnings("ignore")
mu.set_options(pull_on_update=False)
sc.settings.verbosity = 0
sc.set_figure_params(
    dpi=80,
    facecolor="white",
    frameon=False,
)

import lamindb as ln

ln.track()
→ loaded Transform('BnpvfJLWjHuE0005', key='annotation.ipynb'), re-started Run('QEKKxvVQBGXwIHKf') at 2026-04-10 17:37:56 UTC
→ notebook imports: lamindb-core==2.3.1 muon==0.1.7 scanpy==1.12
• recommendation: to identify the notebook across renames, pass the uid: ln.track("BnpvfJLWjHuE")

39.3. 加载数据#

我们载入上一章 批次校正 末尾保存的 MuData 对象:

af = ln.Artifact.connect("theislab/sc-best-practices").get(
    key="surface-protein/cite_batch_correction.h5mu", is_latest=True
)
mdata = af.load()
mdata
MuData object with n_obs × n_vars = 117951 × 36737
  var:	'gene_ids', 'feature_types'
  2 modalities
    rna:	117951 x 36601
      obs:	'donor', 'batch'
      var:	'gene_ids', 'feature_types'
    prot:	117951 x 136
      obs:	'donor', 'batch', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'n_counts', 'outliers', 'doublets_markers'
      var:	'gene_ids', 'feature_types', 'n_cells_by_counts', 'mean_counts', 'log1p_mean_counts', 'pct_dropout_by_counts', 'total_counts', 'log1p_total_counts'
      uns:	'batch_colors', 'donor_colors', 'doublets_markers_colors', 'neighbors', 'pca', 'umap'
      obsm:	'X_pca', 'X_pca_harmony', 'X_umap'
      varm:	'PCs'
      obsp:	'connectivities', 'distances'

39.4. 手动注释#

首先,我们检查 CD45 的表达。CD45 是 T 细胞质膜上最丰富的蛋白之一,是 TCR 信号传导所必需的。它会激活 Lck,而 Lck 又是磷酸化 TCR 复合体所必需的 [Courtney et al., 2019]。因此,CD45 应在我们的数据集中广泛表达,并在 T 细胞中表达得更高。

sc.pl.umap(mdata["prot"], frameon=False, color="CD45")

由于与 RNA 基因存在名称冲突,所测量的 ADT 使用的命名略有不同。var_names_make_unique 函数用于将基因名与蛋白质名分离,蛋白质可能带有 -1 后缀。我们查找一个示例基因名(CD38),以此示例性地确定其在变量名中的确切命名:

mdata["prot"].var[mdata["prot"].var.gene_ids.str.contains("CD38")]
gene_ids feature_types n_cells_by_counts mean_counts log1p_mean_counts pct_dropout_by_counts total_counts log1p_total_counts
CD38-1 CD38 Antibody Capture 116434 52.892694 3.986995 4.57481 6453755.0 15.680173

我们以相对较低的分辨率对细胞进行聚类。与 scRNA-seq 数据注释类似,也可以提高分辨率以获得更精细的注释。

sc.tl.leiden(
    mdata["prot"],
    resolution=0.1,
    flavor="igraph",
    n_iterations=2,
    directed=False,
    random_state=0,
)

为了检查哪种细胞类型中存在哪些表面标记,我们使用 scanpy 的 rank_genes_groups() 函数,然后绘制一张点图(dotplot)。该点图会标出每个聚类中差异表达最显著的 3 个基因。

sc.tl.rank_genes_groups(mdata["prot"], groupby="leiden")
sc.tl.dendrogram(mdata["prot"], groupby="leiden")
sc.pl.rank_genes_groups_dotplot(
    mdata["prot"], n_genes=3, values_to_plot="logfoldchanges"
)

我们已经可以通过 CD3 的表达把第 0 和第 2 类识别为 T 细胞群,并通过 CD19 的表达把第 7 类识别为 B 细胞。接下来,我们绘制前几章中计算得到的 UMAP,并按聚类进行着色。

sc.pl.umap(mdata["prot"], color="leiden")

我们将检查几个已知的主要免疫细胞类型的标记,以确定每个聚类对应的是哪种细胞类型。

# B cells
sc.pl.umap(mdata["prot"], frameon=False, color=["CD19-1"])

正如点图中所示,第 7 类表达 CD19,这是一个 B 细胞标记。

下面我们更详细地考察 T 细胞,并把它们分成 CD4 和 CD8 细胞。

# T cells
sc.pl.umap(mdata["prot"], color=["CD3", "CD4-1", "CD8"])

在接下来的几张图中,我们继续寻找其他细胞类型的已知标记:NK 细胞、单核细胞和树突状细胞。

# NKT cells are CD3+ and CD56+
# NK cells are CD3- and CD56+
sc.pl.umap(mdata["prot"], color=["CD56"], frameon=False)
# Monocytes
sc.pl.umap(mdata["prot"], color=["CD11b", "CD14-1"], frameon=False)
# Dendritic
sc.pl.umap(mdata["prot"], color=["CD123", "CD11c", "CD303"], frameon=False)
# CD16 is expressed in NK cells and in CD16 monocytes, which are CD14-, CD16+ and CD11c+
sc.pl.umap(mdata["prot"], color="CD16", frameon=False)

现在我们已经知道每个聚类对应哪种细胞类型,下面就用真实的细胞类型名称来替换 0–8 这些聚类编号:

mdata["prot"].obs["celltype"] = mdata["prot"].obs.leiden.copy()
mdata["prot"].obs.celltype.replace(
    {
        "0": "CD4 T",
        "1": "Cytotoxic T",
        "2": "CD8 T",
        "3": "CD14 Mono",
        "4": "Proliferating cells",
        "5": "DC",
        "6": "CD16 Mono",
        "7": "B",
        "8": "NK",
    },
    inplace=True,
)
sc.pl.umap(
    mdata["prot"],
    color="celltype",
    legend_loc="on data",
    legend_fontsize=11,
    legend_fontoutline=2,
)

我们已经发现并注释了数据中的主要细胞类型。现在,我们可以通过提高聚类分辨率、并对由此得到的精细聚类进行注释,来做更精细的注释。

在本章中,我们介绍了如何基于 CITE-seq 的 ADT 数据对细胞类型进行注释。另一个有意思的方向是结合 ADT 和 RNA 数据的信息来注释细胞类型。请参阅 配对整合 章节。

af_annotation = ln.Artifact.from_mudata(
    mdata,
    key="surface-protein/cite_annotation.h5mu",
    description="CITE-seq data after annotation",
)
af_annotation.save()

隐藏代码单元输出

→ creating new artifact version for key 'surface-protein/cite_annotation.h5mu' in storage 's3://lamin-eu-central-1/VPwcjx3CDAa2'
... uploading OyfKOZw9TXUQXeOp0002.h5mu: 100.0%
• replacing the existing cache path /var/cache/user/marchena/.cache/lamindb/lamin-eu-central-1/VPwcjx3CDAa2/surface-protein/cite_annotation.h5mu
Artifact(uid='OyfKOZw9TXUQXeOp0002', key='surface-protein/cite_annotation.h5mu', description='CITE-seq data after annotation', suffix='.h5mu', kind='dataset', otype='MuData', size=1547653954, hash='4ak2wDSMz6ov6E1UoXSPa8', n_files=None, n_observations=117951, branch_id=1, created_on_id=1, space_id=1, storage_id=1, run_id=76, schema_id=None, created_by_id=7, created_at=2026-04-10 17:38:14 UTC, is_locked=False, version_tag=None, is_latest=True)
ln.finish()

隐藏代码单元输出

• please hit CTRL + s to save the notebook in your editor ... ✓
! cells [(0, 2)] were not run consecutively
! returning transform  with same hash & key: Transform(uid='BnpvfJLWjHuE0004', key='annotation.ipynb', description='Annotation', kind='notebook', hash='wGPLIESjWMSUD0apYkREXQ', reference=None, reference_type=None, environment=None, plan=None, branch_id=1, created_on_id=1, space_id=1, created_by_id=7, created_at=2026-04-10 17:10:35 UTC, is_locked=False, version_tag=None, is_latest=False)
• new latest Transform version is: BnpvfJLWjHuE0004
→ finished Run('QEKKxvVQBGXwIHKf') after 48s at 2026-04-10 17:38:44 UTC
→ go to: https://lamin.ai/theislab/sc-best-practices/transform/BnpvfJLWjHuE0004
→ to update your notebook from the CLI, run: lamin save /groups/nils/members/javier/single-cell-best-practices/jupyter-book/surface_protein/annotation.ipynb

39.5. 自动注释#

从技术上讲,可以使用在 ADT 数据上训练的细胞类型分类器,并对照 ADT 参考数据集进行映射。然而,专门针对 ADT 的方法很少,甚至几乎没有;关于方法学细节,请参阅 RNA 注释一章 注释

39.6. 参考文献#

[CSL+19]

Adam H Courtney, Alexey A Shvets, Wen Lu, Gloria Griffante, Marianne Mollenauer, Veronika Horkova, Wan-Lin Lo, Steven Yu, Ondrej Stepanek, Arup K Chakraborty, and Arthur Weiss. Cd45 functions as a signaling gatekeeper in t cells. Sci. Signal., 12(604):eaaw8151, October 2019.

39.7. 贡献者#

我们衷心感谢以下人员的贡献:

39.7.1. 作者#

  • Javier Marchena-Hurtado

  • Daniel Strobl

  • Ciro Ramírez-Suástegui

39.7.2. 审阅者#

  • Lukas Heumos

  • Anna Schaar