6. 互操作性#

   关键要点

语言之间的互操作性使分析人员能够利用不同生态系统的优势。

动机

基于磁盘的互操作性使用标准文件格式来传输数据,通常也更可靠。

简单格式

内存中的互操作性可在并行会话之间直接传输数据,便于交互式分析。

关键要点 3

虽然互操作性目前已经可行,但开发者仍在持续改进相关体验。

动机
   环境设置
  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: interoperability
channels:
  - conda-forge
  - bioconda
  - defaults
dependencies:
  - conda-forge::python=3.12.9
  - conda-forge::scanpy=1.11.0
  - anndata2ri=1.3.2
  - bioconductor-basilisk=1.14.1
  - bioconductor-mudata=1.6.0
  - bioconductor-scuttle=1.12.0
  - bioconductor-singlecellexperiment=1.24.0
  - bioconductor-zellkonverter=1.12.1
  - mudata=0.3.1
  - r-base=4.3.3
  - r-hdf5r=1.3.12
  - r-remotes=2.5.0
  - r-reticulate=1.40.0
  - r-sessioninfo=1.2.3
  - r-seurat=5.2.1
  - r-seuratobject=5.0.2
  - rpy2=3.5.11
  - session-info=1.0.0
  - pip
  - pip:
      - lamindb[bionty,jupyter]
  # Additional R packages installed manually using {remotes}
  # remotes::install_github("mojaveazure/seurat-disk@9b89970eac2a3bd770e744f63c7763419486b14c")
  # remotes::install_github("cellgeni/sceasy@v0.0.7")
  # remotes::install_github("PMBio/MuDataSeurat@e34e908")
   获取数据和笔记本

本书使用 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 来获取旧版本。

6.1. 动机#

正如分析框架与工具章节所述,单细胞分析有三个主要生态系统:BioconductorSeurat,以及基于 Python 的 scverse。新分析人员常问的一个问题是:应该专注于哪个生态系统。虽然从其中一个入手是合理的,而且在任何一个生态系统中都能完成出色的分析,但一名称职的分析人员应当熟悉这三个生态系统,并能在它们之间自如切换。这样,分析人员就能始终使用性能最佳的工具,而不必在意它们是用什么实现的。不习惯切换生态系统的分析人员,往往会默认使用自己熟悉的软件包,即便别处有更好的替代方案。跨生态系统的灵活性还能让开发者发挥不同语言的长处:R 对统计建模有着强大的内置支持,而大多数深度学习库则面向 Python。通过支持通用的磁盘格式和内存数据结构,开发者可以确保分析人员在最合适的平台上使用他们的软件包。追求多生态系统熟练度的另一个动机,是数据、结果和文档的可获取性。数据和结果往往只以某一种格式提供,需要熟悉相应的生态系统才能访问它们。在评估该使用哪些方法时,阅读文档和教程也需要对其他生态系统有基本的了解。

虽然我们鼓励分析人员熟悉所有主要生态系统,但只有在这些生态系统能够互操作时,跨生态系统切换才可行。好在这一领域已经有大量工作积累,如今在大多数情况下使用标准软件包完成转换相对简单。本章讨论通过磁盘或内存让数据在生态系统之间移动的各种方式,以及它们的差异和优势。我们侧重于单模态数据,以及 R 与 Python 之间的数据移动,因为这些是最常见的场景;同时也会涉及多模态数据和其他语言。

在学习本章内容之前,我们先导入所有必需的 Python 包。

import tempfile
from pathlib import Path

import anndata2ri
import lamindb as ln
import rpy2.robjects

%load_ext rpy2.ipython

ln.track()
→ connected lamindb: theislab/sc-best-practices
→ created Transform('QaILJZMpZyJ40000'), started new Run('1YEGroVZ...') at 2025-03-26 12:58:46 UTC

6.2. 命名约定#

由于在讨论不同编程语言时容易产生混淆,我们在此约定以下命名规范:

  • {package} - 一个 R 包

  • package::function() - R 包中的函数

  • package - 一个 Python 软件包

  • package.function() - Python 软件包中的函数

  • 强调文本 - 其他一些重要概念

  • code - 代码的其他部分,包括对象、变量等。这也用于文件或目录。

6.3. 基于磁盘的互操作性#

在语言间迁移的第一种方法是基于磁盘的互操作性:先在一种语言中把文件写入磁盘,再在另一种语言中读取该文件。在许多情况下,这种方法比内存中的互操作性(下文将讨论)更简单、更可靠、也更易扩展。不过,其代价是需要更多存储空间,交互性也会降低。基于磁盘的互操作性尤其适合这样的场景:分析的每个阶段都有成熟的流程,而你希望把对象从一个阶段传递到下一个阶段,尤其是在用 Nextflowsnakemake 这类工作流(workflow)管理器开发的流程(pipeline)中。然而,对于数据探索或方法试验等交互式步骤,基于磁盘的互操作性就不太方便,因为每次在语言之间切换时都需要写出一个新文件。

6.3.1. 简单格式#

在讨论专为单细胞数据开发的文件格式之前,我们先简要说明:常见的简单文本格式(如 CSV、TSV、JSON 等)往往就足以完成语言间数据传输。当某些分析已经完成,而你只想传输实验信息的一个子集时,它们很合适。例如,你可能只需要传输细胞元数据,而不需要特征(feature)元数据、表达矩阵等。简单文本格式的优点是几乎所有语言都能很好地支持它们,也不需要单细胞专用软件包。不过,随着待传输内容变得更复杂,它们很快就会变得不实用。

6.3.2. 基于 HDF5 的格式#

第 5 版层次数据格式(Hierarchical Data Format version 5)(HDF5)是存储单细胞数据最常见的开源文件格式。它专为大型、复杂且异构的数据集设计,采用类似计算机文件系统的目录结构。这使得多种类型的数据可以按有组织的层次结构存储在单个文件中。尽管 HDF5 非常灵活,但要与之交互,需要了解数据在文件内部是如何组织的。为使这一过程标准化,人们为在 HDF5 文件中存储单细胞数据制定了专门指南。

6.3.2.1. H5AD#

H5AD 格式是 scverse 包使用的 AnnData 对象的 HDF5 磁盘表示形式,常用于共享单细胞数据集。由于它属于 scverse 生态系统,Python 对这些文件的读写支持很完善,也是 anndata 软件包的核心功能之一(关于该格式的更多信息,请参见 此处)。

为了演示互操作性,我们将加载一个小型的、随机生成的数据集;它已经过标准分析工作流中的一些步骤处理,从而填充了各个槽位。

af = ln.Artifact.connect("theislab/sc-best-practices").get(
    key="introduction/interoperability_adata.h5ad", is_latest=True
)
adata = af.load()
adata
AnnData object with n_obs × n_vars = 100 × 2000
    obs: '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: '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: 'hvg', 'log1p', 'neighbors', 'pca', 'umap'
    obsm: 'X_pca', 'X_umap'
    varm: 'PCs'
    layers: 'counts'
    obsp: 'connectivities', 'distances'

我们将把这个模拟对象写入磁盘,存为 H5AD 文件,以演示如何在 R 中读取这些文件。

temp_dir = tempfile.TemporaryDirectory()
h5ad_file = str(Path(temp_dir.name) / "example.h5ad")

adata.write_h5ad(h5ad_file)

有多个 R 包支持读写 H5AD 文件。不过,它们通常是对用于文件处理的 Python anndata 包进行封装,并借助一个内存中转换步骤在 R 与 Python 之间桥接数据。

6.3.2.1.1. 使用 Bioconductor 读写 H5AD#

Bioconductor {zellkonverter} 软件包 通过使用 {basilisk} 软件包 管理兼容的 Python 环境,简化了 H5AD 文件处理。换言之,它让 Bioconductor 用户无需了解 Python,也能无缝读写 H5AD 文件。

遗憾的是,由于本书的构建方式,我们无法在这里直接运行这段代码。因此下面展示代码本身,以及它在 R 会话中运行时的输出形式:

sce <- zellkonverter::readH5AD(h5ad_file, verbose = TRUE)
ℹ Using the Python reader
ℹ Using anndata version 0.8.0
✔ Read /.../luke.zappia/Downloads/example.h5ad [113ms]
✔ uns$hvg$flavor converted [17ms]
✔ uns$hvg converted [50ms]
✔ uns$log1p converted [25ms]
✔ uns$neighbors converted [18ms]
✔ uns$pca$params$use_highly_variable converted [16ms]
✔ uns$pca$params$zero_center converted [16ms]
✔ uns$pca$params converted [80ms]
✔ uns$pca$variance converted [17ms]
✔ uns$pca$variance_ratio converted [16ms]
✔ uns$pca converted [184ms]
✔ uns$umap$params$a converted [16ms]
✔ uns$umap$params$b converted [16ms]
✔ uns$umap$params converted [80ms]
✔ uns$umap converted [112ms]
✔ uns converted [490ms]
✔ Converting uns to metadata ... done
✔ X matrix converted to assay [29ms]
✔ layers$counts converted [27ms]
✔ Converting layers to assays ... done
✔ var converted to rowData [25ms]
✔ obs converted to colData [24ms]
✔ varm$PCs converted [18ms]
✔ varm converted [47ms]
✔ Converting varm to rowData$varm ... done
✔ obsm$X_pca converted [15ms]
✔ obsm$X_umap converted [16ms]
✔ obsm converted [80ms]
✔ Converting obsm to reducedDims ... done
ℹ varp is empty and was skipped
✔ obsp$connectivities converted [22ms]
✔ obsp$distances converted [23ms]
✔ obsp converted [92ms]
✔ Converting obsp to colPairs ... done
✔ SingleCellExperiment constructed [164ms]
ℹ Skipping conversion of raw
✔ Converting AnnData to SingleCellExperiment ... done

由于开启了详细(verbose)输出,你可以看到 {zellkonverter} 如何使用 Python 读取文件,并将 AnnData 对象的各个部分转换为 Bioconductor 的 SingleCellExperiment 对象。我们可以查看结果的样子:

sce
class: SingleCellExperiment
dim: 2000 100
metadata(5): hvg log1p neighbors pca umap
assays(2): X counts
rownames(2000): Gene_0 Gene_1 ... Gene_1998 Gene_1999
rowData names(11): n_cells_by_counts mean_counts ... dispersions_norm
  varm
colnames(100): Cell_0 Cell_1 ... Cell_98 Cell_99
colData names(8): n_genes_by_counts log1p_n_genes_by_counts ...
  pct_counts_in_top_200_genes pct_counts_in_top_500_genes
reducedDimNames(2): X_pca X_umap
mainExpName: NULL
altExpNames(0):

随后,任何 Bioconductor 包都可以像平常一样使用这个对象。如果想写出一个新的 H5AD 文件,可以使用 writeH5AD() 函数:

zellkonverter_h5ad_file <- tempfile(fileext = ".h5ad")
zellkonverter::writeH5AD(sce, zellkonverter_h5ad_file, verbose = TRUE)
ℹ Using anndata version 0.8.0
ℹ Using the 'X' assay as the X matrix
✔ Selected X matrix [29ms]
✔ assays$X converted to X matrix [50ms]
✔ additional assays converted to layers [30ms]
✔ rowData$varm converted to varm [28ms]
✔ reducedDims converted to obsm [68ms]
✔ metadata converted to uns [24ms]
ℹ rowPairs is empty and was skipped
✔ Converting AnnData to SingleCellExperiment ... done
✔ Wrote '/.../.../rj/.../T/.../file102cfa97cc51.h5ad ' [133ms]

接着可以在 Python 中读取该文件:

scanpy.read_h5ad(zellkonverter_h5ad_file)
AnnData object with n_obs × n_vars = 100 × 2000
    obs: '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: '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: 'X_name', 'hvg', 'log1p', 'neighbors', 'pca', 'umap'
    obsm: 'X_pca', 'X_umap'
    varm: 'PCs'
    layers: 'counts'
    obsp: 'connectivities', 'distances'

当你首次运行 {zellkonverter} 函数时,它会创建一个特殊的 Conda 环境,这可能需要一些时间。一旦创建好,该环境会在后续的函数调用中被重复使用。 {zellkonverter} 还提供了有选择地读取或写入对象部分的选项。详情请参见包文档。

SingleCellExperiment 对象写入 H5AD 文件的类似功能可由 {sceasy} 软件包 提供。这些软件包虽然有效,但封装 Python 会带来一些额外开销,未来原生的 R 版 H5AD 读写器或许有助于优化这一点。

6.3.2.1.2. 使用 {Seurat} 读写 H5AD#

虽然 h5ad_file 是一个 Path 对象,但本笔记本中我们使用 R 的方式需要一个字符串,所以我们把它转换成一个 string 对象。

h5ad_file = str(h5ad_file)

根据此教程的建议,在 Seurat 对象与 H5AD 文件之间进行转换分为两步。首先,使用 {SeuratDisk} 软件包将 H5AD 文件转换为 H5Seurat 文件(一种用于 Seurat 对象的自定义 HDF5 格式)。随后将 H5Seurat 文件读取为 Seurat 对象。

%%R -i h5ad_file

message("Converting H5AD to H5Seurat...")
SeuratDisk::Convert(h5ad_file, dest = "h5seurat", overwrite = TRUE)
message("Reading H5Seurat...")
h5seurat_file <- gsub(".h5ad", ".h5seurat", h5ad_file)
seurat <- SeuratDisk::LoadH5Seurat(h5seurat_file, assays = "RNA")
message("Read Seurat object:")
seurat
R[write to console]: Converting H5AD to H5Seurat...
    WARNING: The R package "reticulate" only fixed recently
    an issue that caused a segfault when used with rpy2:
    https://github.com/rstudio/reticulate/pull/1188
    Make sure that you use a version of that package that includes
    the fix.
    
R[write to console]: Registered S3 method overwritten by 'SeuratDisk':
  method            from  
  as.sparse.H5Group Seurat

R[write to console]: 경고:
R[write to console]:  Unknown file type: h5ad

R[write to console]: 경고:
R[write to console]:  'assay' not set, setting to 'RNA'

R[write to console]: Creating h5Seurat file for version 3.1.5.9900

R[write to console]: Adding X as data

R[write to console]: Adding X as counts

R[write to console]: Adding meta.features from var

R[write to console]: Adding X_pca as cell embeddings for pca

R[write to console]: Adding X_umap as cell embeddings for umap

R[write to console]: Adding PCs as feature loadings fpr pca

R[write to console]: Adding miscellaneous information for pca

R[write to console]: Adding standard deviations for pca

R[write to console]: Adding miscellaneous information for umap

R[write to console]: Adding hvg to miscellaneous data

R[write to console]: Adding log1p to miscellaneous data

R[write to console]: Adding layer counts as data in assay counts

R[write to console]: Adding layer counts as counts in assay counts

R[write to console]: Reading H5Seurat...

R[write to console]: Validating h5Seurat file

R[write to console]: 경고:
R[write to console]:  Feature names cannot have underscores ('_'), replacing with dashes ('-')

R[write to console]: Initializing RNA with data

R[write to console]: Adding counts for RNA

R[write to console]: Adding feature-level metadata for RNA

R[write to console]: Adding reduction pca

R[write to console]: Adding cell embeddings for pca

R[write to console]: Adding feature loadings for pca

R[write to console]: Adding miscellaneous information for pca

R[write to console]: Adding reduction umap

R[write to console]: Adding cell embeddings for umap

R[write to console]: Adding miscellaneous information for umap

R[write to console]: Adding command information

R[write to console]: Adding cell-level metadata

R[write to console]: Read Seurat object:
An object of class Seurat 
2000 features across 100 samples within 1 assay 
Active assay: RNA (2000 features, 0 variable features)
 2 layers present: counts, data
 2 dimensional reductions calculated: pca, umap

请注意,转换 Seurat 对象比 AnnDataSingleCellExperiment 更复杂,这是由于结构上的差异。如需更多细节,请参阅 转换函数文档.

{sceasy} 软件包可以直接将 H5AD 文件读取为 SeuratSingleCellExperiment 对象。与 {zellkonverter} 依赖专用 Python 环境不同,{sceasy} 直接封装 Python 函数,无需特殊设置。不过,这也意味着你必须手动配置环境,确保 R 能定位 Python,并安装必要的软件包。

sceasy_seurat <- sceasy::convertFormat(h5ad_file, from="anndata", to="seurat")
sceasy_seurat
Warning: Feature names cannot have underscores ('_'), replacing with dashes ('-')
X -> counts
An object of class Seurat
2000 features across 100 samples within 1 assay
Active assay: RNA (2000 features, 0 variable features)
 2 dimensional reductions calculated: pca, umap
6.3.2.1.3. 使用 {anndata} 读写 H5AD#

R 的 {anndata} 软件包 也可以用来读取 H5AD 文件。不过,与上面那些包不同,它不会转换成原生的 R 对象,而是为 Python 对象提供一个 R 接口。这对访问数据很有用,但很少有分析包会接受它作为输入,因此通常还需要进一步的内存中转换。

6.3.2.2. Loom#

Loom 文件格式 是一种较早的、基于 HDF5 的组学数据规范。它的结构与 AnnData / SingleCellExperiment 类似,但不像 H5AD 那样绑定到某个特定分析生态系统。RPython 都支持 Loom 格式,也可以通过 Bioconductor 软件包 写出 Loom 文件。不过,使用核心生态系统包提供的更高层接口往往更方便。除了共享数据集,分析剪接和未剪接读段(Read)时也常会遇到 Loom 文件,例如使用 velocyto 进行 RNA velocity 分析

6.3.3. RDS 文件#

用于共享单细胞数据集的另一种文件格式是 RDS 格式。这是一种二进制格式,用于序列化任意的 R 对象(类似于 Python Pickle 文件)。由于 SingleCellExperimentSeurat 对象并不总有对应的磁盘表示形式,因此 RDS 文件有时被用来共享 R 分析的结果。虽然在一个分析项目内部这样做没问题,但由于它与其他生态系统缺乏互操作性,我们不建议用它来公开共享数据、或与协作者共享数据。相反,我们建议使用上面提到的、可被多种语言读取的某种 HDF5 格式。

6.3.4. 新的磁盘格式#

虽然基于 HDF5 的格式目前是单细胞数据磁盘存储格式的标准,但诸如以下这些较新的技术 ZarrTileDB 也具有一些优势,尤其是对于超大数据集和其他模态。我们预计未来会为这些格式制定规范,并可能被社区采纳(anndata 已经为 Zarr 文件提供了支持)。

关键要点

  • SingleCellExperiment:R 中单细胞数据的 Bioconductor 标准。AnnDataSingleCellExperiment 之间的转换可通过 zellkonverter 完成。

  • Seurat:R 中的单细胞分析框架。它可以通过 SeuratDisk 读写 AnnData,也可以通过 sceasy 完成转换。

  • AnnData: Python 中单细胞数据的标准格式

6.4. 内存中的互操作性#

实现互操作性的第二种方法,是在对象的内存表示上进行操作。这种方法需要同时运行两种编程语言的活动会话,要么从两种语言中访问同一个对象,要么按需在二者之间转换。通常,一种语言充当主环境,并提供一个通向另一种语言的接口。这对交互式分析非常有用,因为它让分析人员能够同时使用两种语言;在创建使用多种语言的文档(例如本书)时也常用到。不过,内存中的互操作性也有一些缺点:分析人员必须熟悉两种环境的搭建和使用,复杂对象可能无法在不同语言间得到完全支持,而且数据重复会增加内存开销,使其不太适合大型数据集。

6.4.1. R 生态系统之间的互操作性#

在考察 R 与 Python 之间的内存互操作性之前,我们先来看一个更简单的情形:在两个 R 生态系统之间相互转换。{Seurat} 软件包提供了执行这种转换的函数,详见这篇 vignette

%%R
sce_from_seurat <- Seurat::as.SingleCellExperiment(seurat)
sce_from_seurat
class: SingleCellExperiment 
dim: 2000 100 
metadata(0):
assays(2): counts logcounts
rownames(2000): Gene-0 Gene-1 ... Gene-1998 Gene-1999
rowData names(0):
colnames(100): Cell_0 Cell_1 ... Cell_98 Cell_99
colData names(9): n_genes_by_counts log1p_n_genes_by_counts ...
  pct_counts_in_top_500_genes ident
reducedDimNames(2): PCA UMAP
mainExpName: RNA
altExpNames(0):
%%R
seurat_from_sce <- Seurat::as.Seurat(sce_from_seurat)
seurat_from_sce
An object of class Seurat 
2000 features across 100 samples within 1 assay 
Active assay: RNA (2000 features, 0 variable features)
 2 layers present: counts, data
 2 dimensional reductions calculated: PCA, UMAP

此处的难点在于这两种对象在数据结构上存在差异。重要的是要确保参数的设置正确,使转换函数知道要转换哪些信息以及将其放置在哪里。

在许多情况下,可能没有必要将 Seurat 对象转换为 SingleCellExperiment,因为许多用于单细胞分析的核心 Bioconductor 包也设计为可以接受矩阵输入。

%%R
# Calculate Counts Per Million using the Bioconductor scuttle package
# with a matrix in a Seurat object
cpm <- scuttle::calculateCPM(Seurat::GetAssayData(seurat, slot = "counts"))
cpm[1:10, 1:10]
10 x 10 sparse Matrix of class "dgCMatrix"
R[write to console]:   [[ suppressing 10 column names ‘Cell_0’, ‘Cell_1’, ‘Cell_2’ ... ]]
                                                                      
Gene-0 594.0456    .     984.0238  610.329 964.4394 616.4169    .     
Gene-1 594.0456 1168.519 622.6029    .     608.7911   .         .     
Gene-2   .         .     984.0238    .     608.7911 973.2674 1205.5970
Gene-3 594.0456    .     622.6029  610.329 964.4394 616.4169    .     
Gene-4 594.0456    .     622.6029  966.820 964.4394   .         .     
Gene-5 594.0456  580.157 622.6029  610.329 608.7911   .       601.7422
Gene-6   .         .     622.6029  610.329   .      616.4169  601.7422
Gene-7 594.0456  580.157 622.6029  966.820 608.7911 616.4169    .     
Gene-8 594.0456  580.157   .      1219.608 608.7911 973.2674    .     
Gene-9 942.9097    .       .         .     964.4394   .       954.8014
                                    
Gene-0  576.0808  619.7236  604.3937
Gene-1  918.4111 1234.7593  958.4625
Gene-2    .       619.7236 1209.8233
Gene-3    .       619.7236  958.4625
Gene-4  576.0808  979.8761  604.3937
Gene-5    .       619.7236  958.4625
Gene-6    .      1234.7593    .     
Gene-7    .       619.7236  604.3937
Gene-8 1162.8180  979.8761  958.4625
Gene-9    .      1234.7593    .     

不过,仍需确保你访问的是正确的信息,并在必要时把结果存放到正确位置。

6.4.2. 从 Python 访问 R#

R 的 Python 接口由 rpy2 软件包提供。借助它,你可以从 Python 访问 R 函数和对象。例如:

counts_mat = adata.layers["counts"].T.toarray()

with rpy2.robjects.conversion.localconverter(rpy2.robjects.numpy2ri.converter):
    rpy2.robjects.globalenv["counts_mat"] = counts_mat

cpm = rpy2.robjects.r("scuttle::calculateCPM(counts_mat)")
cpm
FloatMatrix with 200000 elements.
494.804552 494.804552 0.000000 ... 519.750520 519.750520 0.000000

常见的 Python 对象(列表、矩阵、DataFrame 等)也可以传递给 R。

如果你使用的是 Jupyter 笔记本(本书正是如此),可以借助 IPython 的魔术命令(magic)接口创建包含原生 R 代码的单元格(并按需传入对象)。例如,以 %%R -i input -o output 表示指定 input 作为输入,运行 R 代码然后返回 output 作为输出。

%%R -i counts_mat -o magic_cpm
# R code running using IPython magic
magic_cpm <- scuttle::calculateCPM(counts_mat)
# Python code accessing the results
magic_cpm
array([[ 494.8045522 ,    0.        , 1027.2213662 , ...,    0.        ,
           0.        ,  519.75051975],
       [ 494.8045522 , 1445.78313253,  513.6106831 , ...,    0.        ,
         499.5004995 ,  519.75051975],
       [   0.        ,    0.        , 1027.2213662 , ...,  485.90864917,
         499.5004995 ,    0.        ],
       ...,
       [ 494.8045522 ,    0.        ,  513.6106831 , ...,    0.        ,
           0.        ,  519.75051975],
       [ 989.6091044 ,  481.92771084,    0.        , ...,    0.        ,
         499.5004995 ,  519.75051975],
       [2474.02276101,  963.85542169,  513.6106831 , ...,  485.90864917,
         999.000999  ,    0.        ]])

这是你在后续各章中最常见到的做法。如需了解更多有关使用 rpy2 的信息,请参阅文档

要以这种方式处理单细胞数据,anndata2ri 软件包尤其有用。作为 rpy2 的扩展,它允许 R 将 AnnData 对象识别为 SingleCellExperiment 对象,从而省去不必要的转换,并能在 Python 对象上无缝执行 R 代码。此外,它还便于转换稀疏的 scipy 矩阵。

在这个例子中,为了把 Python 会话中的 AnnData 对象传给 R,我们必须先把它转换成 SingleCellExperiment

with rpy2.robjects.conversion.localconverter(anndata2ri.converter):
    r_adata = rpy2.robjects.conversion.py2rpy(adata)

现在,我们可以把它传给 R。

%%R -i r_adata
qc <- scuttle::perCellQCMetrics(r_adata)
head(qc)
DataFrame with 6 rows and 3 columns
             sum  detected     total
       <numeric> <integer> <numeric>
Cell_0      2021      1297      2021
Cell_1      2075      1314      2075
Cell_2      1947      1233      1947
Cell_3      1986      1250      1986
Cell_4      1987      1255      1987
Cell_5      1930      1266      1930

请注意,如果某个对象(或其一部分)无法被正确对接(例如存在不受支持的数据类型),你仍然会遇到问题。这种情况下,你可能需要先修改对象,然后才能访问它。

6.4.3. 从 R 访问 Python#

从 R 会话访问 Python,与从 Python 访问 R 类似,只不过这里的接口由 {reticulate} 软件包提供。加载后,我们就可以从 R 中调用 Python 函数和对象。

%%R
reticulate_list <- reticulate::r_to_py(LETTERS)
print(reticulate_list)
py_builtins <- reticulate::import_builtins()
py_builtins$zip(letters, LETTERS)
List (26 items)
<zip object at 0x15d0dc6c0>

如果你在 RMarkdownQuarto 文档中工作,也可以使用 {reticulate} 的 Python 引擎来编写原生 Python 代码块。这样做时,可以通过魔术变量 rpy 访问另一种语言中的对象(下面的代码是一个未运行的示例)。

```{r}
# An R chunk that accesses a Python object
print(py$py_object)
```

```{python}
# A Python chunk that accesses an R object
print(r$r_object)
```

anndata2ri 不同,目前没有 R 包能提供直接接口,让 Python 将 SingleCellExperimentSeurat 对象视为 AnnData 对象。不过,我们仍然可以使用 {reticulate} 访问 AnnData 的大部分内容(此代码未运行)。

# Print an AnnData object in a Python environment
py$adata
AnnData object with n_obs × n_vars = 100 × 2000
    obs: '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: '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: 'hvg', 'log1p', 'neighbors', 'pca', 'umap'
    obsm: 'X_pca', 'X_umap'
    varm: 'PCs'
    layers: 'counts'
    obsp: 'connectivities', 'distances'
# Alternatively use the Python anndata package to read a H5AD file
anndata <- reticulate::import("anndata")
anndata$read_h5ad(h5ad_file)
AnnData object with n_obs × n_vars = 100 × 2000
    obs: '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: '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: 'hvg', 'log1p', 'neighbors', 'pca', 'umap'
    obsm: 'X_pca', 'X_umap'
    varm: 'PCs'
    layers: 'counts'
    obsp: 'connectivities', 'distances'
# Access the obs slot, pandas DataFrames are automatically converted to R data.frames
head(adata$obs)
       n_genes_by_counts log1p_n_genes_by_counts total_counts
Cell_0              1246                7.128496         1965
Cell_1              1262                7.141245         2006
Cell_2              1262                7.141245         1958
Cell_3              1240                7.123673         1960
Cell_4              1296                7.167809         2027
Cell_5              1231                7.116394         1898
       log1p_total_counts pct_counts_in_top_50_genes
Cell_0           7.583756                  10.025445
Cell_1           7.604396                   9.521436
Cell_2           7.580189                   9.959142
Cell_3           7.581210                   9.183673
Cell_4           7.614805                   9.718796
Cell_5           7.549083                  10.168599
       pct_counts_in_top_100_genes pct_counts_in_top_200_genes
Cell_0                    17.65903                    30.89059
Cell_1                    16.99900                    29.71087
Cell_2                    17.62002                    30.28601
Cell_3                    16.83673                    30.45918
Cell_4                    17.11889                    30.04440
Cell_5                    18.07165                    30.29505
       pct_counts_in_top_500_genes
Cell_0                    61.42494
Cell_1                    59.62114
Cell_2                    60.92952
Cell_3                    61.07143
Cell_4                    59.64480
Cell_5                    61.48577

如上文所述,R 的 {anndata} 软件包为 AnnData 对象提供了 R 接口,但目前还没有被许多分析包使用。

对于需要操作整个对象的更复杂分析,可能需要在 R 与 Python 之间完整地转换对象。虽然这种方法因数据重复而不够省内存,但它能让你使用更广泛的软件包。

{zellkonverter} 软件包提供了执行此转换的函数。与其读取 H5AD 文件的功能不同,这个过程使用标准 Python 环境,而不是专门创建的环境(代码未运行)。

# Convert an AnnData to a SingleCellExperiment
sce <- zellkonverter::AnnData2SCE(adata, verbose = TRUE)
sce
✔ uns$hvg$flavor converted [21ms]
✔ uns$hvg converted [62ms]
✔ uns$log1p converted [22ms]
✔ uns$neighbors converted [21ms]
✔ uns$pca$params$use_highly_variable converted [22ms]
✔ uns$pca$params$zero_center converted [31ms]
✔ uns$pca$params converted [118ms]
✔ uns$pca$variance converted [17ms]
✔ uns$pca$variance_ratio converted [17ms]
✔ uns$pca converted [224ms]
✔ uns$umap$params$a converted [15ms]
✔ uns$umap$params$b converted [17ms]
✔ uns$umap$params converted [80ms]
✔ uns$umap converted [115ms]
✔ uns converted [582ms]
✔ Converting uns to metadata ... done
✔ X matrix converted to assay [44ms]
✔ layers$counts converted [29ms]
✔ Converting layers to assays ... done
✔ var converted to rowData [37ms]
✔ obs converted to colData [23ms]
✔ varm$PCs converted [18ms]
✔ varm converted [49ms]
✔ Converting varm to rowData$varm ... done
✔ obsm$X_pca converted [17ms]
✔ obsm$X_umap converted [17ms]
✔ obsm converted [80ms]
✔ Converting obsm to reducedDims ... done
ℹ varp is empty and was skipped
✔ obsp$connectivities converted [21ms]
✔ obsp$distances converted [22ms]
✔ obsp converted [89ms]
✔ Converting obsp to colPairs ... done
✔ SingleCellExperiment constructed [241ms]
ℹ Skipping conversion of raw
✔ Converting AnnData to SingleCellExperiment ... done
class: SingleCellExperiment
dim: 2000 100
metadata(5): hvg log1p neighbors pca umap
assays(2): X counts
rownames(2000): Gene_0 Gene_1 ... Gene_1998 Gene_1999
rowData names(11): n_cells_by_counts mean_counts ... dispersions_norm
  varm
colnames(100): Cell_0 Cell_1 ... Cell_98 Cell_99
colData names(8): n_genes_by_counts log1p_n_genes_by_counts ...
  pct_counts_in_top_200_genes pct_counts_in_top_500_genes
reducedDimNames(2): X_pca X_umap
mainExpName: NULL
altExpNames(0):

反向转换也一样:

adata2 <- zellkonverter::SCE2AnnData(sce, verbose = TRUE)
adata2
ℹ Using the 'X' assay as the X matrix
✔ Selected X matrix [27ms]
✔ assays$X converted to X matrix [38ms]
✔ additional assays converted to layers [31ms]
✔ rowData$varm converted to varm [15ms]
✔ reducedDims converted to obsm [63ms]
✔ metadata converted to uns [23ms]
ℹ rowPairs is empty and was skipped
✔ Converting AnnData to SingleCellExperiment ... done
AnnData object with n_obs × n_vars = 100 × 2000
    obs: '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: '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: 'X_name', 'hvg', 'log1p', 'neighbors', 'pca', 'umap'
    obsm: 'X_pca', 'X_umap'
    varm: 'PCs'
    layers: 'counts'
    obsp: 'connectivities', 'distances'

6.5. 多模态数据的互操作性#

多模态数据的复杂性给互操作性带来了更多挑战。SingleCellExperiment(通过“备选实验”,且这些实验必须在细胞上共享相同的列维度)和 Seurat(通过“测定(Assay)”)都支持多种模态。不过,AnnData 仅限于单模态数据。

为解决这一限制,MuData 对象(在“分析框架与工具”一章中引入,详见此处)被开发为 AnnData 面向多模态数据集的扩展。开发者在设计时就考虑了互操作性。虽然 MuData 的主要平台是 Python,但作者提供了 MuDataSeurat R 软件包,用于将磁盘上的 H5MU 格式读取为 Seurat 对象;也提供了 MuData R 软件包,用于对 Bioconductor MultiAssayExperiment 对象执行同类操作。这种官方支持非常有用,但由于对象之间存在差异,仍会有一些不一致。MuData 作者还提供了 Julia 实现,覆盖 AnnDataMuData

下面是一个示例,演示如何使用 Python 和 R 软件包读写一个小型的示例 MuData 数据集。

为解决这个问题,MuData 对象——它在“分析框架与工具”一章中引入(详见此处)——将 AnnData 扩展到多模态数据集。MuData 在设计时就考虑了互操作性,主要是一个基于 Python 的框架,但作者也提供了 MuDataSeurat R 软件包。这样可以将磁盘上的 H5MU 格式读取为 Seurat 对象,而 MuData R 软件包 则支持转换为 MultiAssayExperiment 对象。虽然这种官方支持非常有用,但由于对象之间存在差异,仍会有一些不一致。MuData 作者还提供了 Julia 实现,覆盖 AnnDataMuData

下面是一个示例,演示如何使用 Python 和 R 软件包读写一个小型的示例 MuData 数据集。

6.5.1. Python#

# Read file
af_mudata = ln.Artifact.connect("theislab/sc-best-practices").get(
    key="introduction/interoperability_mdata.h5mu", is_latest=True
)
mdata = af_mudata.load()
mdata
/Users/seohyon/miniconda3/envs/interoperability/lib/python3.12/site-packages/mudata/_core/mudata.py:1531: FutureWarning: From 0.4 .update() will not pull obs/var columns from individual modalities by default anymore. Set mudata.set_options(pull_on_update=False) to adopt the new behaviour, which will become the default. Use new pull_obs/pull_var and push_obs/push_var methods for more flexibility.
  self._update_attr("var", axis=0, join_common=join_common)
/Users/seohyon/miniconda3/envs/interoperability/lib/python3.12/site-packages/mudata/_core/mudata.py:1429: FutureWarning: From 0.4 .update() will not pull obs/var columns from individual modalities by default anymore. Set mudata.set_options(pull_on_update=False) to adopt the new behaviour, which will become the default. Use new pull_obs/pull_var and push_obs/push_var methods for more flexibility.
  self._update_attr("obs", axis=1, join_common=join_common)
MuData object with n_obs × n_vars = 1000 × 150
  var:	'dummy_var'
  2 modalities
    A:	1000 x 100
      obs:	'dummy_obs'
      var:	'dummy_var'
    B:	1000 x 50
      obs:	'dummy_obs'
      var:	'dummy_var'

6.5.2. R#

6.5.2.1. Bioconductor#

读取/写入到某个 MultiAssayExperiment 对象

import shutil
from pathlib import Path

# Save MuData file locally for R
Path("data").mkdir(parents=True, exist_ok=True)

local_path = af_mudata.cache().path

target_path = Path("data") / "interoperability_mdata.h5mu"
shutil.copy(local_path, target_path)
print(f"File copied to: {target_path}")
File copied to: data/interoperability_mdata.h5mu
%%R
mae <- MuData::readH5MU("data/interoperability_mdata.h5mu")
print(mae)

bioc_h5mu_file <- tempfile(fileext = ".h5mu")
MuData::writeH5MU(mae, bioc_h5mu_file)
A MultiAssayExperiment object of 2 listed
 experiments with user-defined names and respective classes.
 Containing an ExperimentList class object of length 2:
 [1] A: SingleCellExperiment with 100 rows and 1000 columns
 [2] B: SingleCellExperiment with 50 rows and 1000 columns
Functionality:
 experiments() - obtain the ExperimentList instance
 colData() - the primary/phenotype DataFrame
 sampleMap() - the sample coordination DataFrame
 `$`, `[`, `[[` - extract colData columns, subset, or experiment
 *Format() - convert into a long or wide DataFrame
 assays() - convert ExperimentList to a SimpleList of matrices
 exportClass() - save data to flat files

6.5.2.2. Seurat#

读取/写入到某个 Seurat 对象

%%R
seurat <- MuDataSeurat::ReadH5MU("data/interoperability_mdata.h5mu")
print(seurat)

seurat_h5mu_file <- tempfile(fileext = ".h5mu")
MuDataSeurat::WriteH5MU(seurat, seurat_h5mu_file)
An object of class Seurat 
150 features across 1000 samples within 2 assays 
Active assay: A (100 features, 0 variable features)
 2 layers present: counts, data
 1 other assay present: B

6.6. 与其他语言的互操作性#

这里简要列出一些资源和工具,用于实现单细胞数据与 R、Python 之外语言的互操作。

6.6.1. Julia#

  • Muon.jl 提供 AnnDataMuData 对象的 Julia 实现,以及 H5AD 和 H5MU 格式的 IO

  • scVI.jl 提供 AnnData 的 Julia 实现,以及 H5AD 格式的 IO

6.6.2. JavaScript#

  • Vitessce 包含用于加载以 Zarr 格式存储的 AnnData 对象的加载器

  • kana 系列 支持读取 H5AD 文件,以及保存为 RDS 文件的 SingleCellExperiment 对象。

6.6.3. Rust#

  • anndata-rs 提供 AnnData 的 Rust 实现,以及对 H5AD 格式的高级 IO 支持

6.7. 会话信息#

6.8. Python#

import session_info

session_info.show()
/Users/seohyon/miniconda3/envs/interoperability/lib/python3.12/site-packages/session_info/main.py:213: UserWarning: The '__version__' attribute is deprecated and will be removed in MarkupSafe 3.1. Use feature detection, or `importlib.metadata.version("markupsafe")`, instead.
  mod_version = _find_version(mod.__version__)
Click to view session information
-----
anndata             0.11.3
anndata2ri          1.3.2
lamindb             1.3.0
lamindb_setup       1.3.2
mudata              0.3.1
numpy               2.1.3
rpy2                3.5.11
scanpy              1.11.0
scipy               1.14.1
session_info        1.0.0
-----
Click to view modules imported as dependencies
PIL                 11.1.0
aiobotocore         2.21.1
aiohappyeyeballs    2.6.1
aiohttp             3.11.14
aioitertools        0.12.0
aiosignal           1.3.2
annotated_types     0.7.0
anyio               NA
appdirs             1.4.4
appnope             0.1.4
argcomplete         NA
asgiref             3.8.1
asttokens           NA
attr                25.3.0
bionty              1.1.2
botocore            1.37.1
certifi             2025.01.31
chardet             5.2.0
charset_normalizer  3.4.1
click               8.1.8
colorama            0.4.6
comm                0.2.2
cycler              0.12.1
cython_runtime      NA
dateutil            2.9.0.post0
debugpy             1.8.13
decorator           5.2.1
defusedxml          0.7.1
deprecation         2.1.0
dj_database_url     NA
django              5.1.7
dotenv              NA
executing           2.1.0
fastobo             0.13.0
filelock            3.17.0
frozenlist          1.5.0
fsspec              2025.2.0
gotrue              2.11.4
h11                 0.14.0
h2                  4.2.0
h5py                3.13.0
hpack               4.1.0
httpcore            1.0.7
httpx               0.28.1
hyperframe          6.1.0
idna                3.10
importlib_metadata  NA
ipykernel           6.29.5
jedi                0.19.2
jinja2              3.1.5
jmespath            1.0.1
joblib              1.4.2
kiwisolver          1.4.8
lamin_utils         0.13.11
legacy_api_wrap     NA
llvmlite            0.44.0
markupsafe          3.0.2
matplotlib          3.10.0
mpl_toolkits        NA
multidict           6.2.0
mypy_extensions     NA
natsort             8.4.0
nbproject           0.10.6
numba               0.61.0
orjson              3.10.15
packaging           24.2
pandas              2.2.3
pandera             0.0.0+dev0
parso               0.8.4
platformdirs        4.3.6
postgrest           0.19.3
prompt_toolkit      3.0.50
pronto              2.7.0
propcache           0.3.0
psutil              7.0.0
psycopg2            2.9.10 (dt dec pq3 ext lo64)
pure_eval           0.2.3
pyarrow             19.0.1
pydantic            2.10.6
pydantic_core       2.27.2
pydantic_settings   2.8.1
pydev_ipython       NA
pydevconsole        NA
pydevd              3.2.3
pydevd_file_utils   NA
pydevd_plugins      NA
pydevd_tracing      NA
pygments            2.19.1
pyparsing           3.2.1
pytz                2024.1
realtime            2.4.1
requests            2.32.3
rich                NA
rpycall             NA
rpytools            NA
s3fs                2025.2.0
six                 1.17.0
sklearn             1.5.2
sniffio             1.3.1
sqlparse            0.5.3
stack_data          0.6.3
storage3            0.11.3
supabase            2.11.0
supafunc            NA
threadpoolctl       3.5.0
tornado             6.4.2
traitlets           5.14.3
typeguard           NA
typing_extensions   NA
typing_inspect      NA
tzlocal             NA
upath               0.2.6
urllib3             1.26.20
vscode              NA
wcwidth             0.2.13
websockets          14.2
wrapt               1.17.2
yaml                6.0.2
yarl                1.18.3
zipp                NA
zmq                 26.3.0
-----
IPython             9.0.2
jupyter_client      8.6.3
jupyter_core        5.7.2
-----
Python 3.12.9 | packaged by conda-forge | (main, Mar  4 2025, 22:45:25) [Clang 18.1.8 ]
macOS-15.3.2-x86_64-i386-64bit
-----
Session information updated at 2025-03-26 14:24

6.9. R#

%%R
sessioninfo::session_info()
─ Session info ───────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.3.3 (2024-02-29)
 os       macOS 15.3.2
 system   x86_64, darwin13.4.0
 ui       unknown
 language (EN)
 collate  C
 ctype    UTF-8
 tz       Europe/Berlin
 date     2025-03-26
 pandoc   3.6.3 @ /Users/seohyon/miniconda3/envs/interoperability/bin/pandoc
 quarto   NA

─ Packages ───────────────────────────────────────────────────────────────────
 package              * version    date (UTC) lib source
 abind                  1.4-8      2024-09-12 [1] CRAN (R 4.3.3)
 beachmat               2.18.0     2023-10-24 [1] Bioconductor
 Biobase              * 2.62.0     2023-10-24 [1] Bioconductor
 BiocGenerics         * 0.48.1     2023-11-01 [1] Bioconductor
 BiocParallel           1.36.0     2023-10-24 [1] Bioconductor
 bit                    4.6.0      2025-03-06 [1] CRAN (R 4.3.3)
 bit64                  4.6.0-1    2025-01-16 [1] CRAN (R 4.3.3)
 bitops                 1.0-9      2024-10-03 [1] CRAN (R 4.3.3)
 cli                    3.6.4      2025-02-13 [1] CRAN (R 4.3.3)
 cluster                2.1.8      2024-12-11 [1] CRAN (R 4.3.3)
 codetools              0.2-20     2024-03-31 [1] CRAN (R 4.3.3)
 colorspace             2.1-1      2024-07-26 [1] CRAN (R 4.3.3)
 cowplot                1.1.3      2024-01-22 [1] CRAN (R 4.3.3)
 crayon                 1.5.3      2024-06-20 [1] CRAN (R 4.3.3)
 data.table             1.17.0     2025-02-22 [1] CRAN (R 4.3.3)
 DelayedArray           0.28.0     2023-10-24 [1] Bioconductor
 DelayedMatrixStats     1.24.0     2023-10-24 [1] Bioconductor
 deldir                 2.0-4      2024-02-28 [1] CRAN (R 4.3.3)
 digest                 0.6.37     2024-08-19 [1] CRAN (R 4.3.3)
 dotCall64              1.2        2024-10-04 [1] CRAN (R 4.3.3)
 dplyr                  1.1.4      2023-11-17 [1] CRAN (R 4.3.3)
 farver                 2.1.2      2024-05-13 [1] CRAN (R 4.3.3)
 fastDummies            1.7.5      2025-01-20 [1] CRAN (R 4.3.3)
 fastmap                1.2.0      2024-05-15 [1] CRAN (R 4.3.3)
 fitdistrplus           1.2-2      2025-01-07 [1] CRAN (R 4.3.3)
 future                 1.34.0     2024-07-29 [1] CRAN (R 4.3.3)
 future.apply           1.11.3     2024-10-27 [1] CRAN (R 4.3.3)
 generics               0.1.3      2022-07-05 [1] CRAN (R 4.3.3)
 GenomeInfoDb         * 1.38.1     2023-11-08 [1] Bioconductor
 GenomeInfoDbData       1.2.11     2025-02-21 [1] Bioconductor
 GenomicRanges        * 1.54.1     2023-10-29 [1] Bioconductor
 ggplot2                3.5.1      2024-04-23 [1] CRAN (R 4.3.3)
 ggrepel                0.9.6      2024-09-07 [1] CRAN (R 4.3.3)
 ggridges               0.5.6      2024-01-23 [1] CRAN (R 4.3.3)
 globals                0.16.3     2024-03-08 [1] CRAN (R 4.3.3)
 glue                   1.8.0      2024-09-30 [1] CRAN (R 4.3.3)
 goftest                1.2-3      2021-10-07 [1] CRAN (R 4.3.3)
 gridExtra              2.3        2017-09-09 [1] CRAN (R 4.3.3)
 gtable                 0.3.6      2024-10-25 [1] CRAN (R 4.3.3)
 hdf5r                  1.3.12     2025-01-20 [1] CRAN (R 4.3.3)
 htmltools              0.5.8.1    2024-04-04 [1] CRAN (R 4.3.3)
 htmlwidgets            1.6.4      2023-12-06 [1] CRAN (R 4.3.3)
 httpuv                 1.6.15     2024-03-26 [1] CRAN (R 4.3.3)
 httr                   1.4.7      2023-08-15 [1] CRAN (R 4.3.3)
 ica                    1.0-3      2022-07-08 [1] CRAN (R 4.3.3)
 igraph                 2.1.4      2025-01-23 [1] CRAN (R 4.3.3)
 IRanges              * 2.36.0     2023-10-24 [1] Bioconductor
 irlba                  2.3.5.1    2022-10-03 [1] CRAN (R 4.3.3)
 jsonlite               1.9.1      2025-03-03 [1] CRAN (R 4.3.3)
 KernSmooth             2.23-26    2025-01-01 [1] CRAN (R 4.3.3)
 later                  1.4.1      2024-11-27 [1] CRAN (R 4.3.3)
 lattice                0.22-6     2024-03-20 [1] CRAN (R 4.3.3)
 lazyeval               0.2.2      2019-03-15 [1] CRAN (R 4.3.3)
 lifecycle              1.0.4      2023-11-07 [1] CRAN (R 4.3.3)
 listenv                0.9.1      2024-01-29 [1] CRAN (R 4.3.3)
 lmtest                 0.9-40     2022-03-21 [1] CRAN (R 4.3.3)
 magrittr               2.0.3      2022-03-30 [1] CRAN (R 4.3.3)
 MASS                   7.3-60.0.1 2024-01-13 [1] CRAN (R 4.3.3)
 Matrix               * 1.6-5      2024-01-11 [1] CRAN (R 4.3.3)
 MatrixGenerics       * 1.14.0     2023-10-24 [1] Bioconductor
 matrixStats          * 1.5.0      2025-01-07 [1] CRAN (R 4.3.3)
 mime                   0.12       2021-09-28 [1] CRAN (R 4.3.3)
 miniUI                 0.1.1.1    2018-05-18 [1] CRAN (R 4.3.3)
 MuData                 0.99.9     2025-03-13 [1] Bioconductor
 MuDataSeurat           0.0.0.9000 2025-03-13 [1] Github (PMBio/MuDataSeurat@e34e908)
 MultiAssayExperiment   1.28.0     2023-10-24 [1] Bioconductor
 munsell                0.5.1      2024-04-01 [1] CRAN (R 4.3.3)
 nlme                   3.1-167    2025-01-27 [1] CRAN (R 4.3.3)
 parallelly             1.42.0     2025-01-30 [1] CRAN (R 4.3.3)
 patchwork              1.3.0      2024-09-16 [1] CRAN (R 4.3.3)
 pbapply                1.7-2      2023-06-27 [1] CRAN (R 4.3.3)
 pillar                 1.10.1     2025-01-07 [1] CRAN (R 4.3.3)
 pkgconfig              2.0.3      2019-09-22 [1] CRAN (R 4.3.3)
 plotly                 4.10.4     2024-01-13 [1] CRAN (R 4.3.3)
 plyr                   1.8.9      2023-10-02 [1] CRAN (R 4.3.3)
 png                    0.1-8      2022-11-29 [1] CRAN (R 4.3.3)
 polyclip               1.10-7     2024-07-23 [1] CRAN (R 4.3.3)
 progressr              0.15.1     2024-11-22 [1] CRAN (R 4.3.3)
 promises               1.3.2      2024-11-28 [1] CRAN (R 4.3.3)
 purrr                  1.0.4      2025-02-05 [1] CRAN (R 4.3.3)
 R6                     2.6.1      2025-02-15 [1] CRAN (R 4.3.3)
 RANN                   2.6.2      2024-08-25 [1] CRAN (R 4.3.3)
 RColorBrewer           1.1-3      2022-04-03 [1] CRAN (R 4.3.3)
 Rcpp                   1.0.14     2025-01-12 [1] CRAN (R 4.3.3)
 RcppAnnoy              0.0.22     2024-01-23 [1] CRAN (R 4.3.3)
 RcppHNSW               0.6.0      2024-02-04 [1] CRAN (R 4.3.3)
 RCurl                  1.98-1.16  2024-07-11 [1] CRAN (R 4.3.3)
 reshape2               1.4.4      2020-04-09 [1] CRAN (R 4.3.3)
 reticulate             1.41.0.1   2025-03-09 [1] CRAN (R 4.3.3)
 rhdf5                  2.46.1     2023-11-29 [1] Bioconductor 3.18 (R 4.3.3)
 rhdf5filters           1.14.1     2023-11-06 [1] Bioconductor
 Rhdf5lib               1.24.0     2023-10-24 [1] Bioconductor
 rlang                  1.1.5      2025-01-17 [1] CRAN (R 4.3.3)
 ROCR                   1.0-11     2020-05-02 [1] CRAN (R 4.3.3)
 RSpectra               0.16-2     2024-07-18 [1] CRAN (R 4.3.3)
 Rtsne                  0.17       2023-12-07 [1] CRAN (R 4.3.3)
 S4Arrays               1.2.0      2023-10-24 [1] Bioconductor
 S4Vectors            * 0.40.2     2023-11-23 [1] Bioconductor 3.18 (R 4.3.3)
 scales                 1.3.0      2023-11-28 [1] CRAN (R 4.3.3)
 scattermore            1.2        2023-06-12 [1] CRAN (R 4.3.3)
 sctransform            0.4.1      2023-10-19 [1] CRAN (R 4.3.3)
 scuttle                1.12.0     2023-10-24 [1] Bioconductor
 sessioninfo            1.2.3      2025-02-05 [1] CRAN (R 4.3.3)
 Seurat                 5.2.1      2025-01-24 [1] CRAN (R 4.3.3)
 SeuratDisk             0.0.0.9021 2025-03-13 [1] Github (mojaveazure/seurat-disk@877d4e1)
 SeuratObject           5.0.2      2024-05-08 [1] CRAN (R 4.3.3)
 shiny                  1.10.0     2024-12-14 [1] CRAN (R 4.3.3)
 SingleCellExperiment * 1.24.0     2023-10-24 [1] Bioconductor
 sp                     2.2-0      2025-02-01 [1] CRAN (R 4.3.3)
 spam                   2.11-1     2025-01-20 [1] CRAN (R 4.3.3)
 SparseArray            1.2.2      2023-11-07 [1] Bioconductor
 sparseMatrixStats      1.14.0     2023-10-24 [1] Bioconductor
 spatstat.data          3.1-4      2024-11-15 [1] CRAN (R 4.3.3)
 spatstat.explore       3.3-4      2025-01-08 [1] CRAN (R 4.3.3)
 spatstat.geom          3.3-5      2025-01-18 [1] CRAN (R 4.3.3)
 spatstat.random        3.3-2      2024-09-18 [1] CRAN (R 4.3.3)
 spatstat.sparse        3.1-0      2024-06-21 [1] CRAN (R 4.3.3)
 spatstat.univar        3.1-2      2025-03-05 [1] CRAN (R 4.3.3)
 spatstat.utils         3.1-2      2025-01-08 [1] CRAN (R 4.3.3)
 stringi                1.8.4      2024-05-06 [1] CRAN (R 4.3.3)
 stringr                1.5.1      2023-11-14 [1] CRAN (R 4.3.3)
 SummarizedExperiment * 1.32.0     2023-10-24 [1] Bioconductor
 survival               3.8-3      2024-12-17 [1] CRAN (R 4.3.3)
 tensor                 1.5        2012-05-05 [1] CRAN (R 4.3.3)
 tibble                 3.2.1      2023-03-20 [1] CRAN (R 4.3.3)
 tidyr                  1.3.1      2024-01-24 [1] CRAN (R 4.3.3)
 tidyselect             1.2.1      2024-03-11 [1] CRAN (R 4.3.3)
 uwot                   0.2.3      2025-02-24 [1] CRAN (R 4.3.3)
 vctrs                  0.6.5      2023-12-01 [1] CRAN (R 4.3.3)
 viridisLite            0.4.2      2023-05-02 [1] CRAN (R 4.3.3)
 withr                  3.0.2      2024-10-28 [1] CRAN (R 4.3.3)
 xtable                 1.8-4      2019-04-21 [1] CRAN (R 4.3.3)
 XVector                0.42.0     2023-10-24 [1] Bioconductor
 zlibbioc               1.48.0     2023-10-24 [1] Bioconductor
 zoo                    1.8-13     2025-02-22 [1] CRAN (R 4.3.3)

 [1] /Users/seohyon/miniconda3/envs/interoperability/lib/R/library
 * ── Packages attached to the search path.

─ Python configuration ───────────────────────────────────────────────────────
 python:         /Users/seohyon/miniconda3/envs/interoperability/bin/python
 libpython:      /Users/seohyon/miniconda3/envs/interoperability/bin/python3.12
 pythonhome:     /Users/seohyon/miniconda3/envs/interoperability:/Users/seohyon/miniconda3/envs/interoperability
 version:        3.12.9 | packaged by conda-forge | (main, Mar  4 2025, 22:45:25) [Clang 18.1.8 ]
 numpy:          /Users/seohyon/miniconda3/envs/interoperability/lib/python3.12/site-packages/numpy
 numpy_version:  2.1.3
 
 NOTE: Python version was forced by the current process

──────────────────────────────────────────────────────────────────────────────

6.10. 参考文献#

6.11. 贡献者#

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

6.11.1. 作者#

  • Luke Zappia

  • Seo H. Kim

6.11.2. 审阅者#

  • Lukas Heumos

  • Isaac Virshup

  • Anastasia Litinetskaya

  • Ludwig Geistlinger

  • Peter Hickey