# 第 06 章 环境搭建与工具链

> 本章解决“代码跑在哪”的问题。建议跟着本章把环境装好，再开始第 7 章的数据下载。装环境是新手最挫败的环节之一，但请放心：本章给出的命令在 Windows 和 macOS/Linux 上都可用（差异点单独标注），装完本章 6.6 节的验证代码能跑通，就说明环境合格。

## 本章目标

学完本章，你应该能够：

1. 解释为什么用 conda/mamba 管理 Python 环境，以及 renv 对 R 环境的作用；
2. 从零创建 Python 空间转录组环境（Python 3.10 + scanpy + squidpy + matplotlib）；
3. 安装 R ≥ 4.3 生态：Seurat v5、CellChat v2、BayesSpace、tidyverse、patchwork、ComplexHeatmap；
4. 处理 Windows 用户特有的坑（Rtools、Bioconductor 依赖）；
5. 导出环境文件（conda env export、renv snapshot）实现可复现；
6. 用最小代码验证 Seurat、CellChat、squidpy 可用。

## 6.1 为什么用 conda/mamba 管理环境

空间转录组分析横跨 Python 与 R 两大生态，依赖几十上百个包，版本错一个就可能跑出“灵异结果”：同样是 scanpy，1.9 和 1.10 的 API 不同；CellChat v1 与 v2 的用法差异更大（00-TECH 第 2 节特意标注了版本）。**可复现**的核心是“环境即代码”：把环境内容导出成文件，任何人（包括三个月后的你自己）都能用一条命令恢复出一模一样的环境。

conda/mamba 的价值有三点：① 隔离——每个项目一个环境，互不污染，装坏了直接删掉重建；② 版本锁定——`conda env export` 把包名与版本号写进 yaml 文件；③ 跨平台——同一份 yaml 在 Windows 和 Linux 上都能恢复。mamba 是 conda 的 C++ 重写版，解决依赖的速度快得多，装生信包强烈建议用 mamba（安装方式见 00-TECH 第 2 节）。R 侧用 `renv` 做类似的“项目级包仓库”管理，见 6.5 节。

还有一个新手常问的问题：为什么不直接用系统 Python？因为系统 Python（尤其是 Windows 上）被大量软件共享，`pip install` 很容易装出版本冲突，升级系统包还可能破坏其他软件。conda 的哲学是“一次项目、一个环境、随建随删”：实验做完环境可以删掉，需要时按 yaml 一分钟重建，完全不污染系统。这套哲学在生物信息领域已是事实标准，本书第 8 章之后所有 Python 操作都默认在 spatial 环境中进行。

## 6.2 创建 Python 空间转录组环境

打开终端（Windows 用 Anaconda Prompt 或 PowerShell），依次执行。代码里 `-c conda-forge` 指定通道（channel）很关键：conda 默认通道包不全、解析慢，而生信包的多数依赖在 conda-forge 与 bioconda 两个社区通道维护得最好。先装核心四件套（scanpy、squidpy、anndata、matplotlib），一次装太多包更容易触发依赖冲突。装包卡住时优先怀疑网络（代理）与通道顺序，见 6.7 表格。

```bash
# 用 mamba 创建独立环境（若没装 mamba，把 mamba 换成 conda 即可）
mamba create -n spatial python=3.10 -y

# 激活环境
conda activate spatial

# 安装空间转录组核心包（版本参考 00-TECH 第 2 节：scanpy>=1.10, squidpy>=1.4）
mamba install -c conda-forge scanpy squidpy anndata matplotlib pandas numpy -y

# 可选：cell2location（去卷积用，依赖 scvi-tools，训练建议内存 >=16 GB）
mamba install -c conda-forge -c bioconda cell2location -y

# 检查版本（应显示 scanpy 1.10+、squidpy 1.4+）
python -c "import scanpy; print('scanpy', scanpy.__version__)"
python -c "import squidpy; print('squidpy', squidpy.__version__)"
```

运行结果解读：最后一行应输出形如 `scanpy 1.10.x`、`squidpy 1.4.x` 的版本号，说明环境可用。若 `squidpy` 安装报依赖冲突，请把 `cell2location` 留到第 9 章前再装（它依赖较重，是可选组件）。cell2location 体积大、依赖多，新手可以暂时跳过，先用 marker 打分注释（第 9 章策略 A）。

补充一点：`python -c "import ..."` 这种“一行式验证”是判断环境可用与否的最快方法，第 16 章排错会反复用到。另外环境名可以自定义，但建议与项目绑定（本书统一用 spatial），并在所有脚本注释与笔记里保持一致，避免“我这个脚本到底在哪个环境跑过”的混乱。

## 6.3 安装 R 环境与关键包

安装 R 本身很简单：到 CRAN（The Comprehensive R Archive Network）下载 Windows 安装包（Linux 用系统包管理器），注意选择 **R ≥ 4.3** 并勾选 64 位；Windows 用户在安装 R 后必须先装 Rtools，见 6.4 节。RStudio 是社区推荐的免费集成开发环境，提供脚本编辑、控制台、变量查看与绘图面板，本书所有 R 操作默认在 RStudio 中完成。一个常见疑问是“R 版本与包版本的关系”：Bioconductor 的包（如 BayesSpace）与 R 版本对齐，R 版本太老就装不上较新的 Bioconductor 包，所以本书把 R ≥ 4.3 定为硬性要求。R 包安装代码（复制到 RStudio 控制台或脚本运行，单次约 10–30 分钟）：

```r
# ===== code/01_setup.R 核心部分：R 环境与包安装 =====
# 运行环境：R >= 4.3，建议在 RStudio 中逐段运行

# 1) 安装包管理器 BiocManager（Bioconductor 包的统一入口）
if (!requireNamespace("BiocManager", quietly = TRUE))
  install.packages("BiocManager")

# 2) 基础包：tidyverse（数据处理）、patchwork（拼图）、devtools（装 GitHub 包）
install.packages(c("tidyverse", "patchwork", "devtools"))

# 3) Seurat v5（单细胞/空间分析主框架）
#    注意：v5 与 v4 语法有差异，见 00-TECH 第 2 节
install.packages("Seurat")

# 4) ComplexHeatmap（CellChat 的依赖之一，也从 Bioconductor 装）
BiocManager::install("ComplexHeatmap")

# 5) BayesSpace（空间聚类，第 10 章使用，Bioconductor 渠道）
BiocManager::install("BayesSpace")

# 6) CellChat v2（本书通讯分析主线，GitHub 开发版）
#    依赖 NMF 与 ComplexHeatmap，若提示缺失先装：
install.packages("NMF")
devtools::install_github("jinworks/CellChat")

# 7) 验证加载（全部应返回 "载入需要的程辑包" 无报错）
library(Seurat)
library(CellChat)
library(BayesSpace)
library(patchwork)
```

运行结果解读：每行 `install.packages` 或 `BiocManager::install` 结束后若无红色 error 即成功；最后 `library()` 全部无报错说明安装完成。安装过程中出现的黄色 warning（警告）通常不影响使用，只有红色 error 需要处理；若 error 反复出现，把完整报错复制存档，方便后续检索。常见提示 “package ‘xxx’ is not available for this version of R” 通常意味着来源不对（普通包用 CRAN、Bioconductor 包必须走 BiocManager，见 6.7 表格）。

## 6.4 Windows 用户必看：Rtools 与依赖

Windows 上装 R 包有三个必踩的坑，提前处理可以省下几小时：

1. **Rtools 必须先装**。Windows 上编译 R 包需要工具链。请到 CRAN 的 “Rtools” 页面下载与你的 R 版本匹配的 Rtools（如 R 4.3 对应 Rtools43），安装时保持默认路径。**Bioconductor 包（BayesSpace 等）几乎必然需要 Rtools**，漏装会出现 “cannot find Rtools” 或编译报错。
2. **Bioconductor 包必须走 BiocManager**，不能 `install.packages("BayesSpace")`——普通 CRAN 渠道没有这些包。统一用 `BiocManager::install()` 即可自动处理依赖。
3. **CellChat 的依赖**：CellChat 依赖 `NMF`（非负矩阵分解）与 `ComplexHeatmap`，其中 `NMF` 依赖较多（如 `registry`、`rngtools`），`ComplexHeatmap` 必须从 Bioconductor 装。按 6.3 的顺序先装依赖再装 CellChat，可避免一半的报错。

安装 Rtools 后请确认 R 能找到它：在 R 里运行 `Sys.which("make")`，若返回空字符串，说明工具链没被识别，重启 RStudio 或手动把 Rtools 的 bin 目录加入系统 PATH 再试。注意 R 与 Rtools 的**大版本必须匹配**（R 4.3 配 Rtools43，R 4.4 配 Rtools44），混用会出现莫名其妙的编译错误。Windows 用户若报 “there is no package called ‘curl’” 之类的基础依赖缺失，先 `install.packages("curl")` 补上再装 Bioconductor 包。这条规则同样适用于 Linux 用户：部分系统库（如 libxml2、libcurl）缺失会导致 R 包编译失败，报错里出现 `configure: error` 时先用系统包管理器补齐再重试。

## 6.5 环境导出与复现

环境装好只是第一步，**导出环境文件才算完成**（conda-environments 技能强调“锁定文件是复现基准”）：

```bash
# Python 侧：导出环境（在 spatial 环境激活状态下）
conda activate spatial
conda env export --no-builds > envs/spatial.yml        # 人类可读版
conda env export > envs/spatial.lock.yml               # 完整锁定版（含构建号）

# 恢复（换电脑/换人时执行，先建好 envs 目录）
conda env create -f envs/spatial.lock.yml
```

```r
# R 侧：renv 项目级包管理（在项目根目录运行一次）
install.packages("renv")
renv::init()          # 初始化项目库，记录当前所有 R 包版本
# 分析中途新增包后，更新快照：
renv::snapshot()
# 恢复（新电脑上）：
renv::restore()
```

运行结果解读：`conda env export` 生成的两个 yml 文件与 `renv.lock` 都应提交进版本库（git）。之后任何人（包括你换电脑后）都能用 `conda env create -f` 和 `renv::restore()` 重建环境。注意 yml 文件里的包版本是安装当天的解析结果，**更新包后必须重新导出**，并顺手在 envs 目录写一行 CHANGELOG 记录改了什么。

还有一个常见问题：R 环境为什么推荐 renv 而不是也在 conda 里装 R？两种做法都可行，但 renv 更贴近 R 生态的习惯（Bioconductor 包、GitHub 包都能被记录），而 conda 里 R 包来源有限。本书约定：**Python 用 conda/mamba，R 用 renv**，各管各的依赖，互不干扰。环境文件（spatial.yml、spatial.lock.yml、renv.lock）是论文方法节“软件与版本”的素材——评审问“分析环境怎么复现”，这三份文件就是答案。

## 6.6 验证安装：最小可运行测试

环境装完必须冒烟测试（smoke test）。下面三段代码分别验证 Python 侧、R 侧、CellChat 侧：

```python
# 冒烟测试 1（Python，在 spatial 环境运行）：squidpy 加载示例数据
import scanpy as sc
import squidpy as sq

adata = sq.datasets.visium_hne()   # 内置 Visium 示例数据（人淋巴结）
sq.gr.spatial_neighbors(adata, coord_type="generic", n_neighs=6)
print("squidpy OK, obs =", adata.n_obs, "genes =", adata.n_vars)
```

```r
# 冒烟测试 2（R）：Seurat 读入内置数据并降维聚类
library(Seurat)
obj <- CreateSeuratObject(counts = pbmc_small[["RNA"]]$counts)
obj <- NormalizeData(obj) %>% FindVariableFeatures() %>% ScaleData() %>% RunPCA()
cat("Seurat OK, PCs =", ncol(Embeddings(obj, "pca")), "\n")
```

```r
# 冒烟测试 3（R）：CellChat 能否加载数据库
library(CellChat)
db <- CellChatDB.human   # 加载人类配体-受体数据库
cat("CellChat OK, interactions =", nrow(db$interaction))
```

冒烟测试（smoke test）是“装完即测”的工程习惯：用最小代码确认核心功能可用，而不是等到第 8 章跑真实数据才发现环境问题。三段测试分别覆盖最容易出错的三个环节——Python 空间对象构建、Seurat 标准流程、CellChat 数据库加载，任何一段通过都说明对应依赖链完整。若某段报错又不确定原因，把报错原文贴到搜索引擎或 R/Python 社区提问，附上 `sessionInfo()` 输出会大幅提高被解答的概率。

运行结果解读：三段分别输出 `squidpy OK`、`Seurat OK, PCs = 50`、`CellChat OK, interactions = ...` 即全部通过。任何一段报错，先对照 6.7 的坑表格排查，不要带着报错环境进入第 8 章。

## 6.7 常见安装坑与解法

| 现象 | 原因 | 解法 |
| --- | --- | --- |
| `cannot find Rtools` | Windows 未装 Rtools 或版本不匹配 | 到 CRAN 下载与 R 版本对应的 Rtools 并重装；R 4.3 → Rtools43 |
| `package 'BayesSpace' is not available` | 用了 CRAN 渠道 | 改用 `BiocManager::install("BayesSpace")` |
| CellChat 安装报缺 `NMF`/`ComplexHeatmap` | 依赖未先装 | 先 `install.packages("NMF")` 与 `BiocManager::install("ComplexHeatmap")`，再装 CellChat |
| `devtools::install_github` 超时/失败 | 网络访问 GitHub 不稳 | 挂代理或重试；必要时用 `options(timeout = 600)` 调大下载超时 |
| conda 解析依赖极慢/卡住 | 用了默认 channels | 换 mamba；明确指定 `-c conda-forge`；或使用 `--solver libmamba` |
| Python 包装好后 `import scanpy` 报错 | 环境被污染或版本冲突 | 删环境重建：`conda env remove -n spatial` 后按 6.2 重来 |
| `squidpy` 与 `cell2location` 依赖冲突 | 两包依赖矩阵重叠冲突 | cell2location 单独建环境，或推迟到第 9 章再装 |
| 内存不足（Out of Memory） | Visium 单切片 Seurat 约需 2–6 GB（00-TECH 第 2 节） | 关闭其他程序；cell2location 训练至少 16 GB 内存 |

表格按出现频率排序，前四行覆盖了 Windows 用户 80% 的安装报错。如果你遇到的问题不在表内，先判断“报错是否与环境有关”（比如换一个包重装能否复现），再决定查环境还是查代码。

## 6.8 配套脚本说明

本章完整代码在配套脚本 `code/01_setup.R`（含分段注释与报错提示），正文 6.3 节给出的是其核心部分。Python 侧命令在 `envs/spatial.yml` 导出后即可复现。环境验证通过后，请做第 6.5 节的导出，并把 `spatial.yml`、`spatial.lock.yml`、`renv.lock` 一并交给版本库——这是你整个课题可复现的起点。

最后提醒两点关于“顺序”的纪律：其一，**环境先于数据**——第 7 章的数据有数百 MB，先装好环境再下载，避免下载完才发现环境装不上；其二，**报错先查环境**——后续章节任何“跑不通”，第一步都回到第 6.6 节的冒烟测试：先 `conda activate spatial`，再重跑版本检查命令。这能排除一半以上的疑难杂症（第 16 章排错清单也是这个顺序）。

![图 6-1 全书技术路线图（重复引用 fig01）：环境搭建位于“环境数据”阶段，是数据下载（第 7 章）与预处理（第 8 章）之前的前置步骤。](figures/fig01_roadmap.png){width=60%}

## 本章小结

- conda/mamba 提供 Python 环境的隔离、锁定与跨平台复现；renv 为 R 提供同样的能力。
- Python 侧：`mamba create -n spatial python=3.10` + scanpy ≥ 1.10 + squidpy ≥ 1.4 + matplotlib。
- R 侧：R ≥ 4.3 + RStudio，Seurat v5、CellChat v2（GitHub）、BayesSpace（Bioconductor）、tidyverse、patchwork、ComplexHeatmap。
- Windows 三坑：Rtools、Bioconductor 走 BiocManager、CellChat 依赖 NMF/ComplexHeatmap。
- 环境导出（conda env export / renv snapshot）与冒烟测试是交付前的必做项。

## 练习与思考

1. **动手题**：完成 6.2 与 6.3 的环境安装，运行 6.6 的三段冒烟测试，把三个 OK 输出截图存档。
2. **动手题**：执行 6.5 的导出命令，把 `spatial.yml` 与 `renv.lock` 提交到你的版本库，并在 envs 目录写一行 CHANGELOG。
3. **判断题**：以下说法对错？（a）BayesSpace 可以用 `install.packages()` 安装；（b）R 4.2 的 Rtools 可以给 R 4.3 用；（c）conda env export 的 yml 可以直接恢复出逐字节一致的环境。
4. **思考题**：为什么“环境即代码”比“我帮你装好了”更可靠？请结合三个月后换电脑的场景说明。
5. **讨论题**：scanpy 1.9 与 1.10、CellChat v1 与 v2 的差异提示我们什么版本的坑？查阅本书 00-TECH 第 2 节，列出你需要注意的三处版本差异。
