# 肿瘤微环境“空间生态位”细胞通讯重编程分析——新手完整实验教程

> 面向对象：刚接触空间转录组与细胞通讯分析的生物信息学新手
> 学习周期：建议 4～6 周，每天 2～3 小时
> 项目类型：基于公共 10x Visium 数据的干湿结合/纯生信课题

---

## 目录

- [第 0 章 这本教程怎么用](#第-0-章-这本教程怎么用)
- [第 1 章 必要知识补充：从单细胞到空间生态位](#第-1-章-必要知识补充从单细胞到空间生态位)
- [第 2 章 课题设计：科学问题与创新点](#第-2-章-课题设计科学问题与创新点)
- [第 3 章 环境搭建与工具链](#第-3-章-环境搭建与工具链)
- [第 4 章 数据获取与预处理](#第-4-章-数据获取与预处理)
- [第 5 章 空间可视化：让数据“回到组织”](#第-5-章-空间可视化让数据回到组织)
- [第 6 章 细胞类型注释与空间去卷积](#第-6-章-细胞类型注释与空间去卷积)
- [第 7 章 空间生态位识别](#第-7-章-空间生态位识别)
- [第 8 章 细胞通讯分析基础](#第-8-章-细胞通讯分析基础)
- [第 9 章 空间生态位通讯重编程比较](#第-9-章-空间生态位通讯重编程比较)
- [第 10 章 结果解读、验证与论文图表](#第-10-章-结果解读验证与论文图表)
- [第 11 章 新手常见错误与排错](#第-11-章-新手常见错误与排错)
- [第 12 章 附录：术语表、资源与脚本索引](#第-12-章-附录术语表资源与脚本索引)

---

## 第 0 章 这本教程怎么用

### 0.1 你会学到什么

完成这个教程后，你将能够：

1. **讲清楚**空间转录组（spatial transcriptomics）和“空间生态位”（spatial niche）是什么；
2. **独立下载**并处理一份公共 10x Visium 数据；
3. **识别**肿瘤组织中的多个空间生态位（如肿瘤核心、侵袭前沿、免疫浸润区、基质区）；
4. **分别计算**不同生态位内的细胞通讯网络；
5. **比较**这些网络的差异，找到“通讯重编程”（communication reprogramming）的关键配体-受体对；
6. **画出**空间特征图、生态位图、通讯气泡图、和弦图和差异热图等论文级图表；
7. **把结果写成**一个思路清晰、有创新点的论文初稿。

### 0.2 你不需要提前会什么

| 项目 | 说明 |
| --- | --- |
| 编程 | 不需要，R 和 Python 代码都会逐步解释 |
| 空间转录组 | 不需要，第 1 章会从原理讲起 |
| 单细胞分析 | 不需要，但如果你会 Seurat 会学得更快 |
| 高性能服务器 | 不需要，公共示例数据在 16GB 内存的笔记本上也能跑 |
| 实验数据 | 不需要，我们使用公共数据库 |

### 0.3 学习路线

```mermaid
flowchart LR
    A[第1章 知识补充] --> B[第2章 课题设计]
    B --> C[第3章 环境搭建]
    C --> D[第4章 数据获取与预处理]
    D --> E[第5章 空间可视化]
    E --> F[第6章 细胞类型注释/去卷积]
    F --> G[第7章 空间生态位识别]
    G --> H[第8章 细胞通讯分析]
    H --> I[第9章 通讯重编程比较]
    I --> J[第10章 验证与论文]
    J --> K[第11章 排错]
    K --> L[第12章 附录]
```

### 0.4 一个贯穿全文的示例课题

为了让教程不空谈，我们使用一个**可公开获取、已被广泛研究**的示例：

> **示例课题：乳腺癌 10x Visium 数据中，肿瘤核心区、侵袭前沿与免疫浸润区的细胞通讯网络如何发生重编程？**

- 数据：10x Genomics 公共 Visium 人乳腺癌数据集（也可替换为黑色素瘤、结直肠癌等）。
- 核心假设：**不同空间生态位具有不同的优势细胞类型与配体-受体活动；侵袭前沿的通讯网络最“活跃”，是肿瘤-免疫重编程的关键界面。**
- 最终产出：三张核心图——空间生态位图、各生态位通讯强度图、通讯差异重编程热图。

---

## 第 1 章 必要知识补充：从单细胞到空间生态位

### 1.1 为什么需要空间信息？

传统单细胞 RNA 测序（scRNA-seq）会把组织消化成单细胞悬液，然后逐个细胞测序。它的优点是分辨率高（单个细胞），缺点是**细胞被“打碎”后失去了原来的位置**。

想象一张城市地图：

- scRNA-seq 相当于把所有居民集中到体育馆，一个一个问“你是谁、你在做什么”，但**不知道谁住在哪个街区**；
- 空间转录组相当于给每个街区贴标签，**既知道每栋楼里有什么人，也知道这些楼在城市的哪个位置**。

肿瘤不是一堆细胞的均匀混合物，而是像一座城市：有“市中心”（肿瘤核心）、有“城乡结合部”（侵袭前沿）、有“警察局/免疫哨所”（免疫浸润区）、有“工地”（基质重塑区）。细胞通讯在这座城市的不同街区里规则完全不同。

### 1.2 10x Visium 原理

10x Visium 是目前最常用的商用空间转录组平台之一。它的核心是**带空间条形码（spatial barcode）的捕获芯片**：

```text
组织切片放在芯片上
        │
        ▼
┌─────────────────────────────────────────┐
│ 捕获区域（capture area）≈ 6.5mm × 6.5mm │
│ 每个 spot 直径 55 μm，中心间距 100 μm    │
│ 一个 spot 大约捕获 1～10 个细胞          │
│ 每个 spot 有一个唯一空间条形码           │
└─────────────────────────────────────────┘
        │
        ▼
反转录 → 建库 → 测序 → 得到“spot × 基因”表达矩阵
```

每个 spot 就像地图上的一个网格：

```text
组织切片
┌────┬────┬────┬────┐
│ S1 │ S2 │ S3 │ S4 │   S = spot
├────┼────┼────┼────┤
│ S5 │ S6 │ S7 │ S8 │   spot 有 x,y 坐标
├────┼────┼────┼────┤
│ S9 │ S10│ S11│ S12│   spot 的 gene expression = 该处多个细胞混合
└────┴────┴────┴────┘
```

**重要概念**：Visium 的 spot 不是单细胞，而是**小区域内多个细胞的混合信号**。因此做细胞通讯之前，通常需要“去卷积”或“空间注释”，估计每个 spot 里有哪些细胞类型。

### 1.3 肿瘤微环境（TME）的基本组分

肿瘤微环境是肿瘤细胞与其周围非肿瘤细胞共同构成的生态系统，主要成员包括：

| 组分 | 常见标记/功能 |
| --- | --- |
| 肿瘤细胞（Malignant cells） | 高增殖、拷贝数变异、表达上皮标记（如 EPCAM、KRT） |
| T 细胞 | CD3D、CD3E、CD8A（CD8+ T）、CD4（CD4+ T） |
| B 细胞 | CD79A、MS4A1、IGH 系列 |
| 巨噬细胞/单核细胞 | CD68、LYZ、C1QA、C1QB |
| 树突状细胞（DC） | CLEC9A、BATF3、FCER1A |
| 自然杀伤细胞（NK） | NKG7、KLRD1、NCAM1 |
| 成纤维细胞（CAF） | COL1A1、COL3A1、PDGFRA、ACTA2 |
| 内皮细胞 | PECAM1、VWF、CDH5 |
| 肥大细胞 | TPSAB1、TPSB2 |

### 1.4 什么是“空间生态位”？

**空间生态位（spatial niche / spatial domain / tissue niche）** 是指组织切片上**具有相似细胞组成、相似微环境特征、相似功能状态的空间区域**。

常见的肿瘤空间生态位包括：

```mermaid
graph TD
    Niche[肿瘤组织空间生态位] --> Core[肿瘤核心区<br/>高肿瘤细胞密度、缺氧、低免疫浸润]
    Niche --> Front[侵袭前沿<br/>肿瘤细胞与基质/免疫交界、EMT活跃]
    Niche --> Immune[免疫浸润区<br/>T/B/髓系细胞富集、可能三级淋巴结构]
    Niche --> Stroma[基质/间质区<br/>CAF、内皮、细胞外基质重塑]
    Niche --> Border[坏死/缺氧区<br/>低质量spot、应激信号]
```

**为什么用“生态位”而不用简单聚类？** 因为空间生态位是**有生物学解释的区域单元**，它把“spot 聚类”升级为“组织功能单元”。不同生态位之间的细胞通讯差异，可能比不同患者之间的差异更重要。

### 1.5 细胞通讯与“通讯重编程”

细胞通讯（cell-cell communication）指细胞通过**配体（ligand）→ 受体（receptor）** 分子对互相传递信号。例如：

- 肿瘤细胞分泌 **CSF1**，巨噬细胞表面的 **CSF1R** 接收信号 → 招募/极化巨噬细胞；
- T 细胞表达 **CD8A**，肿瘤细胞表达 **MHC-I/ HLA** → 抗原呈递（免疫监视或免疫逃逸）；
- 成纤维细胞分泌 **TGFB1**，肿瘤细胞接收 **TGFBR1/TGFBR2** → 促进侵袭。

**通讯重编程（communication reprogramming）** 在本项目中指：**在不同空间生态位之间，细胞通讯网络的结构、强度、方向和关键信号通路发生系统性改变**。比如：

- 肿瘤核心区：肿瘤细胞→肿瘤细胞的自分泌增殖信号占主导；
- 侵袭前沿：肿瘤细胞→CAF、CAF→肿瘤细胞的旁分泌信号增强，TGF-β、WNT、EGF 通路重编程；
- 免疫浸润区：髓系/T 细胞之间的免疫激活或抑制信号占主导（如 CD86-CTLA4、LGALS9-HAVCR2）。

```mermaid
sequenceDiagram
    participant T as 肿瘤细胞
    participant F as CAF/成纤维细胞
    participant M as 巨噬细胞
    participant L as T细胞
    T->>F: TGFB1 → TGFBR1/2
    F->>T: HGF → MET, FGF2 → FGFR
    T->>M: CSF1 → CSF1R, CCL2 → CCR2
    M->>L: IL10, TGFB1 → 免疫抑制
    L->>T: IFNG → IFNGR, 穿孔素/颗粒酶
```

### 1.6 本章小结

- scRNA-seq 有单细胞分辨率但丢失位置；Visium 保留位置但每个 spot 是混合信号。
- 空间生态位 = 组织中有生物学意义的空间功能区域。
- 细胞通讯 = 配体-受体相互作用；重编程 = 不同空间区域之间通讯网络发生改变。
- 本项目的核心流程：**空间数据 → 生态位识别 → 每个生态位的通讯网络 → 网络差异比较**。

---

## 第 2 章 课题设计：科学问题与创新点

### 2.1 传统分析 vs 本课题分析

| 维度 | 传统空间转录组分析 | 本课题“空间生态位通讯重编程”分析 |
| --- | --- | --- |
| 分析单元 | 单个 spot | 空间生态位（spot 群） |
| 细胞注释 | 是终点 | 是中间步骤 |
| 细胞通讯 | 较少做，或只做整体 | 分生态位比较，突出空间异质性 |
| 核心输出 | “哪里有什么细胞” | “不同区域之间细胞如何对话、如何被重编程” |
| 生物学故事 | 空间图谱 | 空间微环境功能状态转换 |

### 2.2 科学问题

你可以根据自己的数据/癌种，把问题改写成以下模板：

> **在 [癌种] 中，[肿瘤核心区/侵袭前沿/免疫浸润区/基质区] 的细胞通讯网络是否存在系统性差异？哪些配体-受体对是空间生态位特异性的“通讯重编程”事件？这些事件是否与患者预后或治疗反应相关？**

### 2.3 创新点包装

对新手而言，创新点不一定是“新算法”，而是**分析框架的新组合**。例如：

1. **空间维度创新**：大多数 CellChat 分析用 scRNA-seq，而我们把 CellChat/COMMOT 用在 Visium 空间生态位上；
2. **生态位视角创新**：不比较“细胞类型 A vs B”，而是比较“肿瘤核心 vs 侵袭前沿”的**通讯网络状态**；
3. **重编程概念创新**：把“差异表达基因”升级为“差异配体-受体相互作用”，更贴近功能；
4. **可转化创新**：找到侵袭前沿特异性配体-受体对后，可结合公共生存数据或 IHC 做验证。

### 2.4 数据选择建议

| 数据类型 | 推荐来源 | 适合新手吗 | 说明 |
| --- | --- | --- | --- |
| 10x Visium 人乳腺癌 | 10x Genomics 官网 / GEO | ★★★ | 示例数据公开、组织结构清晰 |
| 10x Visium 人结直肠癌 | GEO / 10x | ★★★ | 有肿瘤-正常边界，侵袭前沿明显 |
| 10x Visium 人皮肤黑色素瘤 | GEO / 10x | ★★☆ | 免疫浸润丰富，但下载文件较大 |
| 自有 FFPE 切片 | 本地 | ★☆☆ | 需要实验合作与空间平台支持 |

> **新手建议**：先下载 10x Genomics 官方人乳腺癌（Visium）示例数据，跑通流程后，再换成自己感兴趣的癌种。

### 2.5 课题时间表

| 周次 | 任务 | 产出 |
| --- | --- | --- |
| 第 1 周 | 读第 1-2 章，安装环境 | 理解概念，装好 R/Python |
| 第 2 周 | 下载数据、QC、预处理 | Seurat 对象 |
| 第 3 周 | 细胞注释/去卷积 | 每 spot 的细胞类型比例 |
| 第 4 周 | 空间生态位识别 | 生态位空间图 + marker 表 |
| 第 5 周 | 细胞通讯分析与比较 | 通讯网络差异图 |
| 第 6 周 | 验证、写作、画图 | 论文初稿 |

---

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

### 3.1 你需要安装什么

本项目推荐 **R + RStudio** 为主流程，**Python** 用于部分空间方法（cell2location、Squidpy、MISTy）和画图。

| 软件 | 用途 | 安装难度 |
| --- | --- | --- |
| R (≥4.3) | Seurat、CellChat、ggplot2 等 | 低 |
| RStudio | 写 R 代码更方便 | 低 |
| Python (≥3.9) | cell2location、Squidpy、scanpy | 中 |
| conda/mamba | 管理 Python 环境 | 中 |

### 3.2 R 包安装

打开 RStudio，逐行运行：

```r
# 安装 BiocManager（Bioconductor 包管理器）
if (!requireNamespace("BiocManager", quietly = TRUE))
    install.packages("BiocManager")

# 安装 Seurat 系列
install.packages("Seurat")
BiocManager::install(c("SingleCellExperiment", "SummarizedExperiment"))

# 空间转录组读取与可视化
BiocManager::install(c("SpatialExperiment", "STutility", "scater"))

# 细胞通讯
# CellChat 需要从 GitHub 安装（如果网络受限可使用 gitee 镜像）
install.packages("NMF")
if (!requireNamespace("remotes", quietly = TRUE))
    install.packages("remotes")
remotes::install_github("jinworks/CellChat")

# 去卷积（二选一：RCTD 或 SPOTlight）
BiocManager::install("spacexr")
BiocManager::install("SPOTlight")

# 绘图增强
install.packages(c("ggplot2", "ggalluvial", "circlize", "RColorBrewer", "patchwork"))
```

### 3.3 Python 环境（可选但推荐）

```bash
conda create -n spatial python=3.9 -y
conda activate spatial
pip install scanpy squidpy anndata
pip install cell2location
```

### 3.4 验证安装

```r
library(Seurat)
library(CellChat)
packageVersion("Seurat")
packageVersion("CellChat")
```

如果 `packageVersion` 能输出版本号，说明安装成功。

### 3.5 工作目录结构

```text
your_project/
├── data/
│   ├── raw/               # spaceranger 输出或 GEO 原始文件
│   └── processed/         # QC 后的 Seurat 对象
├── scripts/               # R/Python 脚本
├── figures/               # 所有输出图
├── results/               # 表格、RDS、网络结果
└── manuscript/            # 论文写作
```


---

## 第 4 章 数据获取与预处理

### 4.1 公共数据来源

对于 10x Visium 数据，常见下载位置：

1. **10x Genomics 官网**：https://www.10xgenomics.com/resources/datasets
   - 搜 “Human Breast Cancer (Visium)” 或 “Human Lymph Node”
   - 下载 `filtered_feature_bc_matrix.tar.gz` 和 `spatial/` 目录
2. **GEO**：搜索 “Visium breast cancer” 或 “spatial transcriptomics”
   - 例如 GSE169246、GSE176078 等（需注意数据格式）
3. **Zenodo / Single Cell Portal**：有些文章提供处理好的 Seurat 对象

> 新手建议：先下载 10x 官网的 **“Human Breast Cancer, Ductal Carcinoma In Situ (DCIS)”** 或 **“Human Breast Cancer (Visium)”** 示例，文件较小、结构清晰。

### 4.2 spaceranger 输出结构

10x Visium 官方流程 `spaceranger` 会输出：

```text
outs/
├── filtered_feature_bc_matrix/
│   ├── barcodes.tsv.gz       # spot 条形码
│   ├── features.tsv.gz       # 基因/特征
│   └── matrix.mtx.gz         # 稀疏表达矩阵
├── spatial/
│   ├── tissue_positions_list.csv   # spot 坐标
│   ├── scalefactors_json.json      # 图像缩放参数
│   └── tissue_hires_image.png      # 组织高清图
└── analysis/                 # 聚类等结果（可不使用）
```

### 4.3 用 Seurat 读取 Visium 数据

```r
library(Seurat)

# 方法一：直接读取 spaceranger 输出目录
# 目录中应包含 filtered_feature_bc_matrix 和 spatial 子目录
vis <- Load10X_Spatial(
  data.dir = "data/raw/breast_cancer_visium/outs",
  filename = "filtered_feature_bc_matrix.tar.gz",  # 若已解压可不填
  assay = "Spatial"
)

# 方法二：GEO 下载后手动构造（常见）
# 先读取矩阵
counts <- Seurat::Read10X("data/raw/filtered_feature_bc_matrix")
# 再读取坐标
pos <- read.csv("data/raw/spatial/tissue_positions_list.csv",
                header = FALSE, row.names = 1)
colnames(pos) <- c("in_tissue", "array_row", "array_col", "pxl_row", "pxl_col")
# 只保留组织内的 spot
pos <- pos[pos$in_tissue == 1, ]

# 创建 Seurat 对象（坐标需放在 images 中）
vis <- CreateSeuratObject(counts = counts, assay = "Spatial")
vis[["slice1"]] <- new(
  Class = "VisiumV1",
  image = as.matrix(pos[, c("pxl_row", "pxl_col")]),
  scale.factors = scalefactors(
    spot = 1, fiducial = 1, hires = 1, lowres = 1
  )
)
```

> 如果不想处理图像细节，直接用 `Load10X_Spatial` 最简单。

### 4.4 QC 质控

空间转录组的 QC 与单细胞类似，但要注意：

- 每个 spot 的文库大小（UMI 总数）差异大；
- 线粒体基因比例高可能代表细胞质量差或组织缺氧；
- **不要只按 UMI 数粗暴过滤**，因为不同组织区域（如坏死区）本身 UMI 低。

```r
vis[["percent.mt"]] <- PercentageFeatureSet(vis, pattern = "^MT-")

# 查看 QC 指标
SpatialFeaturePlot(vis, features = c("nCount_Spatial", "nFeature_Spatial", "percent.mt"))

# 宽松过滤：保留组织内 spot，且至少 200 个基因
vis <- subset(vis, subset = nFeature_Spatial > 200 & nCount_Spatial > 500)

# 对非坏死组织，可过滤线粒体 > 40% 的 spot；不要用单细胞的 20% 阈值一刀切
vis <- subset(vis, subset = percent.mt < 40)
```

### 4.5 标准化与高变基因

```r
# SCTransform 是空间转录组常用的标准化方法，比 LogNormalize 更稳健
vis <- SCTransform(vis, assay = "Spatial", verbose = FALSE)

# 降维与聚类（先用标准流程看整体结构）
vis <- RunPCA(vis, assay = "SCT", npcs = 30, verbose = FALSE)
vis <- FindNeighbors(vis, reduction = "pca", dims = 1:30)
vis <- FindClusters(vis, resolution = 0.8, verbose = FALSE)
vis <- RunUMAP(vis, reduction = "pca", dims = 1:30, verbose = FALSE)

# 保存
saveRDS(vis, "data/processed/vis_QC_SCTransform.rds")
```

### 4.6 新手最容易踩的坑

| 坑 | 解释 | 解决方法 |
| --- | --- | --- |
| 把 Visium spot 当单细胞 | spot 是混合信号 | 后续必须做去卷积/空间注释 |
| 坐标读错 | `tissue_positions_list.csv` 有 6 列，顺序别搞错 | 用 `Load10X_Spatial` |
| 过滤太狠 | 坏死区/边界区被删光 | 先保留，后期可标记为低质量生态位 |
| 直接跑 CellChat | CellChat 输入需要细胞类型标签，Visium 没有 | 先做细胞类型注释/去卷积 |

---

## 第 5 章 空间可视化：让数据“回到组织”

### 5.1 为什么先可视化

在跑复杂模型之前，先看数据能帮你发现：

- 组织切片是否完整、方向是否正确；
- 哪些区域高表达肿瘤标记，哪些区域高表达免疫标记；
- 是否存在明显的空间梯度。

### 5.2 基础空间特征图

```r
library(ggplot2)
library(patchwork)

p1 <- SpatialDimPlot(vis, label = FALSE) +
  ggtitle("Seurat clusters (无生物学注释)")

p2 <- SpatialFeaturePlot(vis, features = c("EPCAM", "CD3D", "COL1A1"),
                         alpha = c(0.1, 1), ncol = 3) +
  ggtitle("关键 marker 空间分布")

p1 + p2
```

这张图会告诉你：EPCAM（肿瘤上皮）在哪个区域、CD3D（T 细胞）是否形成浸润灶、COL1A1（成纤维细胞）是否包围肿瘤。

### 5.3 空间生态位的“地图感”

```text
         肿瘤核心区            侵袭前沿              免疫浸润区
   ┌──────────────┐    ┌──────────────┐    ┌──────────────┐
   │ 高 EPCAM     │    │ EPCAM+ 与    │    │ 高 CD3D      │
   │ 低 CD3D      │───▶│ CAF 混合      │───▶│ 高 CD79A     │
   │ 低 COL1A1    │    │ 高 VIM/EMT   │    │ 中 COL1A1    │
   │ 增殖信号强    │    │ 免疫细胞穿插  │    │ 免疫抑制分子↑│
   └──────────────┘    └──────────────┘    └──────────────┘
```

### 5.4 用 ggplot 自定义空间散点图

有时你想把 spot 当作点来画，更灵活：

```r
library(ggplot2)

coords <- GetTissueCoordinates(vis)
coords$niche <- vis$seurat_clusters  # 临时

ggplot(coords, aes(x = x, y = y, color = niche)) +
  geom_point(size = 1.2) +
  coord_fixed() +
  theme_void() +
  scale_color_brewer(palette = "Set2") +
  ggtitle("Spot-level spatial map")
```

### 5.5 本章可视化清单

| 图 | 目的 |
| --- | --- |
| SpatialDimPlot | 看聚类空间分布 |
| SpatialFeaturePlot | 看 marker 表达空间模式 |
| 自定义散点图 | 配合生态位标签做最终发表图 |
| 组织切片 + spot 叠加 | 展示数据质量与组织对应 |

---

## 第 6 章 细胞类型注释与空间去卷积

### 6.1 为什么 Visium 需要去卷积？

因为一个 spot 包含多个细胞，直接说“这个 spot 是 T 细胞”是不准确的。去卷积的目标是估计每个 spot 中**各种细胞类型的比例**。

### 6.2 三种常见策略

| 策略 | 方法 | 优点 | 缺点 |
| --- | --- | --- | --- |
| 1. 无参考 marker 打分 | Seurat `AddModuleScore` / AUCell | 简单快速 | 只能看相对富集，不能给比例 |
| 2. 有参考去卷积 | RCTD、SPOTlight、cell2location | 估计细胞类型比例 | 需要高质量 scRNA-seq 参考 |
| 3. 空间共定位推断 | 用已知 marker 空间分布人工判断 | 直观 | 主观、难以量化 |

**推荐流程**：先用 marker 打分获得第一印象，再用 RCTD/cell2location 得到正式比例矩阵。

### 6.3 用 AddModuleScore 做快速空间打分

```r
# 定义几组核心 marker（可按需修改）
markers <- list(
  Malignant = c("EPCAM", "KRT8", "KRT18", "KRT19"),
  Tcell      = c("CD3D", "CD3E", "CD8A", "CD4"),
  Bcell      = c("CD79A", "MS4A1"),
  Myeloid    = c("CD68", "LYZ", "C1QA", "C1QB"),
  CAF        = c("COL1A1", "COL3A1", "PDGFRA", "ACTA2"),
  Endothelial= c("PECAM1", "VWF", "CDH5")
)

vis <- AddModuleScore(vis, features = markers, name = names(markers))

SpatialFeaturePlot(vis, features = paste0(names(markers), "1"),
                   alpha = c(0.1, 1), ncol = 3)
```

### 6.4 用 RCTD 做正式去卷积（R 版）

RCTD（Robust Cell Type Decomposition）需要单细胞参考数据。这里假设你已经有一个 Seurat 格式的 scRNA-seq 参考 `sc_ref`，其中 `sc_ref$cell_type` 是细胞类型标签。

```r
library(spacexr)

# 准备参考数据
reference <- Reference(
  counts = GetAssayData(sc_ref, assay = "RNA", slot = "counts"),
  cell_types = as.factor(sc_ref$cell_type)
)

# 准备空间数据
query <- SpatialRNA(
  coords = GetTissueCoordinates(vis),
  counts = GetAssayData(vis, assay = "Spatial", slot = "counts")
)

# 运行 RCTD
rctd <- createRCTD(query, reference, max_cores = 4)
rctd <- run_RCTD(rctd, doublet_mode = "full")

# 提取每个 spot 的细胞类型比例
results <- as.data.frame(rctd@results$results_df)
vis$RCTD_celltype <- results$first_type  # 主要类型
```

### 6.5 用 cell2location 做更精细去卷积（Python 版，可选）

```python
import cell2location
import scanpy as sc
import anndata as ad

# 读取空间数据
vis = sc.read_visium("data/raw/breast_cancer_visium/outs")
# 读取单细胞参考
sc_ref = sc.read_h5ad("data/processed/sc_reference.h5ad")

# 使用 cell2location 回归模型估计每 spot 的绝对细胞类型丰度
# 具体参数见 cell2location 文档；这里只展示流程
cell2location.models.RegressionModel.setup_anndata(
    sc_ref, batch_key="sample"
)
mod = cell2location.models.RegressionModel(sc_ref)
mod.train(max_epochs=250)

# 将参考模型迁移到空间数据
vis = cell2location.models.RegressionModel.downsample(
    vis, mod, batch_key="sample"
)
```

> 新手可以先跳过 cell2location，用 RCTD 或 SPOTlight 完成第一步。

### 6.6 去卷积结果如何进入下游

去卷积后，每个 spot 会得到：

```text
        Malignant   Tcell   Bcell   Myeloid   CAF   Endothelial
spot1      0.75      0.02    0.01     0.10    0.08      0.04
spot2      0.05      0.60    0.05     0.20    0.05      0.05
...
```

你可以把主要细胞类型写回 Seurat metadata：

```r
# 以 RCTD 为例：把比例矩阵存回 Seurat
# prop 是 spot × celltype 的数据框
for (ct in colnames(prop)) {
  vis[[paste0("prop_", ct)]] <- prop[colnames(vis), ct]
}
# 主要类型
vis$major_celltype <- colnames(prop)[max.col(prop)]
```

---

## 第 7 章 空间生态位识别

### 7.1 什么是好的生态位？

好的生态位应满足：

1. **空间连续**：相邻 spot 更可能属于同一生态位；
2. **生物学可解释**：每个生态位有明确的 marker 特征；
3. **可用于比较**：至少 2～3 个生态位，且每个生态位有足够 spot（一般 > 50）。

### 7.2 方法选择

| 方法 | 类型 | 特点 | 新手友好度 |
| --- | --- | --- | --- |
| Seurat 空间聚类 + 人工注释 | 无监督聚类 | 最简单，但可能破碎 | ★★★★★ |
| BayesSpace | 空间平滑聚类 | 利用邻域信息，生态位更连续 | ★★★★☆ |
| SpaGCN | 图卷积 | 可整合组织学图像 | ★★★☆☆ |
| stLearn | 形态学+表达 | 适合有病理图像的数据 | ★★★☆☆ |
| 人工病理区域勾画 | 先验知识 | 最符合临床但主观 | ★★★☆☆ |

**新手路线**：先用 Seurat 聚类，再用 BayesSpace 平滑，最后根据 marker 人工命名。

### 7.3 方案 A：Seurat 聚类 + marker 命名（必做）

```r
# 我们已经有了聚类结果 seurat_clusters
# 计算每个 cluster 的 marker
markers <- FindAllMarkers(vis, assay = "SCT", only.pos = TRUE, min.pct = 0.25)

# 查看每个 cluster 的 top marker
library(dplyr)
top_markers <- markers %>%
  group_by(cluster) %>%
  slice_max(n = 5, order_by = avg_log2FC)

# 打印
print(top_markers[, c("cluster", "gene", "avg_log2FC", "pct.1")])
```

然后根据 marker 人工命名，例如：

```r
# 假设 cluster 0 高表达 EPCAM/KRT，命名为 TumorCore
# cluster 1 高表达 COL1A1/ACTA2，命名为 Stroma
# cluster 2 高表达 CD3D/CD79A，命名为 Immune
new_names <- c(
  "0" = "TumorCore",
  "1" = "Stroma",
  "2" = "Immune",
  "3" = "InvasiveFront",   # EPCAM+COL1A1+VIM 混合
  "4" = "Necrosis"
)
vis$niche <- new_names[as.character(vis$seurat_clusters)]

# 如果有些 cluster 没有对应名字，保留原 cluster 编号
vis$niche[is.na(vis$niche)] <- paste0("Cluster_",
                                      vis$seurat_clusters[is.na(vis$niche)])
```

### 7.4 方案 B：BayesSpace 平滑聚类（推荐进阶）

BayesSpace 使用 MCMC 对空间邻域做平滑，能让生态位更连续。

```r
# 安装
if (!requireNamespace("BiocManager", quietly = TRUE))
    install.packages("BiocManager")
BiocManager::install("BayesSpace")

library(BayesSpace)
library(SingleCellExperiment)

# 把 Seurat 转成 SingleCellExperiment
sce <- as.SingleCellExperiment(vis)

# BayesSpace 需要先做 PCA，并设置平台
set.seed(123)
sce <- spatialPreprocess(sce, platform = "Visium", n.PCs = 15)

# 聚类数 q 可以先尝试 5～8
sce <- spatialCluster(sce, q = 6, platform = "Visium", nrep = 1000,
                      gamma = 2, save.chain = FALSE)

# 把结果写回 Seurat
vis$BayesSpace_cluster <- as.character(colData(sce)$spatial.cluster)
SpatialDimPlot(vis, group.by = "BayesSpace_cluster")
```

### 7.5 方案 C：用细胞类型比例定义生态位（更贴近本项目）

既然我们做了去卷积，可以直接用细胞类型比例做聚类，这样生态位天然带有细胞组成含义：

```r
# prop 是 spot × celltype 比例矩阵
set.seed(123)
prop_pca <- prcomp(prop, scale. = TRUE)$x[, 1:10]

# 用比例矩阵聚类
prop_dist <- dist(prop_pca)
prop_clust <- hclust(prop_dist, method = "ward.D2")
prop_groups <- cutree(prop_clust, k = 5)

vis$prop_niche <- paste0("Niche", prop_groups)

# 看每个生态位的平均细胞比例
avg_prop <- aggregate(prop, list(vis$prop_niche), mean)
print(avg_prop)
```

### 7.6 生态位命名与 marker 特征表

最终你会得到类似下面的表格：

| 生态位 | 主要细胞类型 | 代表性 marker | 空间位置 |
| --- | --- | --- | --- |
| TumorCore | 肿瘤细胞 > 70% | EPCAM、KRT8、MKI67 | 切片中央 |
| InvasiveFront | 肿瘤+CAF+髓系 | VIM、COL1A1、MMP11、CD68 | 肿瘤-基质交界 |
| Immune | T/B/髓系 | CD3D、CD79A、CD68 | 浸润灶/三级淋巴结构 |
| Stroma | CAF+内皮 | COL1A1、PDGFRA、VWF | 外周间质 |
| Necrosis | 低质量/低 UMI | 低表达、HIF1A 高 | 坏死区域 |

### 7.7 空间生态位可视化

```r
p_niche <- SpatialDimPlot(vis, group.by = "niche", label = TRUE) +
  ggtitle("Spatial niches")

p_prop <- SpatialFeaturePlot(vis, features = c("prop_CAF", "prop_Tcell", "prop_Malignant"),
                            alpha = c(0.1, 1), ncol = 3)

p_niche / p_prop
```

保存图：

```r
ggsave("figures/spatial_niche_map.png", p_niche, width = 8, height = 6, dpi = 300)
ggsave("figures/cell_prop_spatial.png", p_prop, width = 12, height = 4, dpi = 300)
```


---

## 第 8 章 细胞通讯分析基础

### 8.1 CellChat 能做什么？

CellChat 是目前最常用的细胞通讯推断工具，它利用**配体-受体数据库**（CellChatDB）和表达量，推断细胞类型之间**显著富集的配体-受体相互作用**。输出包括：

- 每个细胞类型对（sender → receiver）的通讯强度；
- 显著配体-受体对；
- 通讯网络中心性；
- 不同条件/区域之间的差异通讯网络。

### 8.2 Visium 数据如何输入 CellChat？

这是本项目最关键、也最容易出错的地方。CellChat 最初是为单细胞数据设计的，输入通常是：

- 表达矩阵（基因 × 细胞/spot）
- 每个细胞/spot 的细胞类型标签

对 Visium 而言，spot 是混合信号，因此有三种策略：

| 策略 | 做法 | 优点 | 缺点 | 推荐度 |
| --- | --- | --- | --- | --- |
| A. spot 主细胞类型 | 每个 spot 用去卷积后比例最高的细胞类型作为标签 | 简单 | 混合信号带来噪声 | ★★★ |
| B. niche × celltype 伪 bulk | 每个生态位内，按细胞类型高比例 spot 聚合表达 | 更符合 CellChat 假设 | 需要仔细构建 | ★★★★★ |
| C. 空间专用方法 | COMMOT、SpatialDM、MISTy | 空间感知更强 | 安装/理解成本高 | ★★★★ |

**教程主线采用策略 B**：先为每个生态位构建“细胞类型 × 生态位”的伪 bulk 表达谱，再运行 CellChat。这样既适合新手理解，也能得到较稳健的生态位间比较。

### 8.3 构建每个生态位的伪 bulk 矩阵

假设 `prop` 是 spot × celltype 比例矩阵，`vis$niche` 是生态位标签。我们为每个“生态位 + 细胞类型”挑选比例最高的 spot，并平均它们的表达。

```r
# 提取原始 counts（或 SCT 的 data）
expr <- GetAssayData(vis, assay = "Spatial", slot = "data")  # 基因 × spot

# 初始化空列表
pseudo_list <- list()

for (nic in unique(vis$niche)) {
  for (ct in colnames(prop)) {
    # 当前生态位中，该细胞类型比例高的 spot
    idx <- vis$niche == nic & prop[[ct]] > 0.1
    if (sum(idx) < 10) next   # 太少就不建伪 bulk

    # 按比例排序，取前 30 个 spot 作为该 celltype 的代表
    prop_sub <- prop[idx, ct]
    top_spots <- names(sort(prop_sub, decreasing = TRUE))[1:min(30, length(prop_sub))]

    # 平均表达
    pseudo_expr <- rowMeans(expr[, top_spots, drop = FALSE])

    # 样本名：生态位_细胞类型
    sample_name <- paste(nic, ct, sep = "__")
    pseudo_list[[sample_name]] <- pseudo_expr
  }
}

# 合并成矩阵：基因 × pseudo-sample
pseudo_matrix <- do.call(cbind, pseudo_list)
colnames(pseudo_matrix) <- names(pseudo_list)

# 查看
dim(pseudo_matrix)
head(colnames(pseudo_matrix))
```

解释：

- `prop[[ct]] > 0.1`：先筛掉该细胞类型比例过低的 spot，减少混合信号；
- 取前 30 个 spot：既保留足够统计量，又避免把低比例 spot 平均进来；
- 最终每个伪样本代表“某生态位中某种细胞类型的平均表达”。

### 8.4 运行 CellChat（单生态位示例）

```r
library(CellChat)
library(Seurat)

# 从伪 bulk 矩阵构建 CellChat 对象
# 注意：meta 需要包含 cell_type 和 niche 两列
meta <- data.frame(
  row.names = colnames(pseudo_matrix),
  niche = sub("__.*", "", colnames(pseudo_matrix)),
  cell_type = sub(".*__", "", colnames(pseudo_matrix)),
  stringsAsFactors = FALSE
)

# 创建 CellChat 对象
cellchat <- createCellChat(
  object = pseudo_matrix,
  meta = meta,
  group.by = "cell_type"
)

# 设置配体-受体数据库
CellChatDB <- CellChatDB.human   # 人；小鼠用 CellChatDB.mouse
cellchat@DB <- CellChatDB

# 预处理
cellchat <- subsetData(cellchat)
cellchat <- identifyOverExpressedGenes(cellchat)
cellchat <- identifyOverExpressedInteractions(cellchat)

# 推断通讯网络（默认使用表达量 + 数据库先验）
cellchat <- computeCommunProb(cellchat, type = "triMean")
cellchat <- filterCommunication(cellchat, min.cells = 10)
cellchat <- computeCommunProbPathway(cellchat)
cellchat <- aggregateNet(cellchat)
```

### 8.5 可视化单个生态位的通讯网络

```r
# 通讯数量与强度
net <- cellchat@net
netVisual_circle(net$count,
                 vertex.weight = table(cellchat@meta$cell_type),
                 weight.scale = TRUE,
                 label.edge = FALSE,
                 title.name = "Number of interactions")

# 气泡图：显示显著配体-受体对
netVisual_bubble(cellchat,
                 sources.use = c("Malignant"),
                 targets.use = c("CAF", "Tcell", "Myeloid"),
                 remove.isolate = TRUE)
```

### 8.6 对每个生态位都运行 CellChat

把上面的过程包成函数，对每个 `niche` 分别运行：

```r
run_cellchat_niche <- function(niche_name, pseudo_matrix, meta) {
  idx <- meta$niche == niche_name
  mat <- pseudo_matrix[, idx]
  meta_sub <- meta[idx, ]

  cc <- createCellChat(object = mat, meta = meta_sub, group.by = "cell_type")
  cc@DB <- CellChatDB.human
  cc <- subsetData(cc)
  cc <- identifyOverExpressedGenes(cc)
  cc <- identifyOverExpressedInteractions(cc)
  cc <- computeCommunProb(cc, type = "triMean")
  cc <- filterCommunication(cc, min.cells = 5)
  cc <- computeCommunProbPathway(cc)
  cc <- aggregateNet(cc)
  return(cc)
}

cellchat_list <- list()
for (nic in unique(meta$niche)) {
  cellchat_list[[nic]] <- run_cellchat_niche(nic, pseudo_matrix, meta)
}
```

> **提醒**：如果某个生态位中某种细胞类型的伪样本太少（如 < 5），CellChat 会无法计算。此时可以合并相近细胞类型，或调低 `min.cells`。

### 8.7 空间专用方法（进阶）

如果想在论文里强调“空间邻近性”，可以进一步使用：

- **COMMOT**：考虑配体-受体对的空间自相关，推断空间通讯；
- **SpatialDM**：检测空间共表达配体-受体对的 spot 对；
- **MISTy**：建立多视角（细胞内、近邻、区域）回归模型，估计空间上下文对基因表达的贡献。

这些方法对新手较难，建议先完成 CellChat 主线，再选一个空间方法作为“加分项”。

---

## 第 9 章 空间生态位通讯重编程比较

### 9.1 什么是“通讯重编程”的操作性定义

在本项目中，我们可以把“重编程”量化成三个层次：

1. **数量层**：不同生态位的显著相互作用数量不同；
2. **强度层**：同一配体-受体对在不同生态位的通讯概率/强度不同；
3. **方向/中心性层**：发送者（sender）与接收者（receiver）角色发生切换，例如 TGFB1 在肿瘤核心由肿瘤→肿瘤，在侵袭前沿变为 CAF→肿瘤。

### 9.2 合并多个生态位 CellChat 对象

CellChat 提供了 `mergeCellChat`，可以把多个条件/区域合并比较：

```r
# 合并所有生态位
cellchat_merged <- mergeCellChat(cellchat_list, add.names = names(cellchat_list))

# 比较通讯数量
gg1 <- compareInteractions(cellchat_merged, show.legend = FALSE, group = c(1,2,3))
gg2 <- compareInteractions(cellchat_merged, show.legend = FALSE, measure = "weight")
gg1 + gg2
```

### 9.3 差异通讯网络热图

```r
# 以侵袭前沿 vs 肿瘤核心为例
# 1 = TumorCore, 2 = InvasiveFront
netVisual_diffInteraction(cellchat_merged, comparison = c(1, 2), measure = "count")
netVisual_diffInteraction(cellchat_merged, comparison = c(1, 2), measure = "weight")
```

这张热图会显示：哪些细胞类型对之间的通讯在侵袭前沿增强（红色）或减弱（蓝色）。

### 9.4 差异配体-受体对气泡图

```r
# 找出显著差异的配体-受体对
netVisual_bubble(cellchat_merged,
                 sources.use = c("Malignant", "CAF"),
                 targets.use = c("Tcell", "Myeloid", "CAF"),
                 comparison = c(1, 2),   # 比较 TumorCore vs InvasiveFront
                 angle.x = 45)
```

### 9.5 通讯模式与中心性分析

```r
# 识别每个生态位的“输出/输入模式”
cellchat_merged <- identifyCommunicationPatterns(
  cellchat_merged,
  pattern = "outgoing",
  k = 3
)

# 河流图展示通讯模式
netAnalysis_river(cellchat_merged, pattern = "outgoing")

# 信号角色分析（发送者/接收者/ mediator/influencer）
cellchat_merged <- netAnalysis_computeCentrality(cellchat_merged)
netAnalysis_signalingRole_heatmap(cellchat_merged,
                                  pattern = "outgoing",
                                  width = 5, height = 6)
```

### 9.6 自己计算“重编程评分”（简单可复现）

除了 CellChat 内置比较，你也可以自己写一个简单的差异表格：

```r
# 提取所有显著配体-受体对
df <- subsetCommunication(cellchat_merged)  # 合并后提取
head(df)

# 也可以分别提取每个生态位
df_tumor <- subsetCommunication(cellchat_list[["TumorCore"]])
df_front <- subsetCommunication(cellchat_list[["InvasiveFront"]])

# 按 配体-受体-通路 合并
df_tumor$pair <- paste(df_tumor$ligand, df_tumor$receptor, sep = "_")
df_front$pair <- paste(df_front$ligand, df_front$receptor, sep = "_")

# 计算每个 pair 在两个生态位的强度差
common_pairs <- intersect(df_tumor$pair, df_front$pair)
rewire <- data.frame(
  pair = common_pairs,
  TumorCore_strength = df_tumor$prob[match(common_pairs, df_tumor$pair)],
  InvasiveFront_strength = df_front$prob[match(common_pairs, df_front$pair)]
)
rewire$diff <- rewire$InvasiveFront_strength - rewire$TumorCore_strength
rewire <- rewire[order(-abs(rewire$diff)), ]
print(head(rewire, 20))
```

这个表格就是论文中“通讯重编程事件”的候选列表：`diff` 越大，说明该配体-受体对越倾向于在侵袭前沿被重编程。

### 9.7 用热图展示重编程事件

```r
library(pheatmap)
# 构造一个生态位 × 配体-受体对的强度矩阵
# rewire_top 是筛选出的 top 配体-受体对
mat <- matrix(
  c(df_tumor$prob[match(rewire_top$pair, df_tumor$pair)],
    df_front$prob[match(rewire_top$pair, df_front$pair)]),
  ncol = 2
)
colnames(mat) <- c("TumorCore", "InvasiveFront")
rownames(mat) <- rewire_top$pair

pheatmap(mat, cluster_cols = FALSE, display_numbers = TRUE,
         color = colorRampPalette(c("navy", "white", "firebrick3"))(100))
```

### 9.8 本章输出清单

| 输出 | 文件建议 | 用途 |
| --- | --- | --- |
| 每个生态位的 CellChat 对象 | `results/cellchat_TumorCore.rds` | 后续复现 |
| 合并比较对象 | `results/cellchat_merged.rds` | 绘图 |
| 通讯数量/强度柱状图 | `figures/compare_interaction_count.png` | 总览 |
| 差异热图 | `figures/diff_interaction_heatmap.png` | 核心图 |
| 差异气泡图 | `figures/diff_bubble.png` | 核心图 |
| 重编程事件表 | `results/rewiring_events.csv` | 论文附表 |
| 通讯模式河流图 | `figures/communication_pattern_river.png` | 加分图 |

---

## 第 10 章 结果解读、验证与论文图表

### 10.1 如何解读“侵袭前沿通讯重编程”

假设你得到的结果是：

- 侵袭前沿的相互作用总数显著高于肿瘤核心；
- TGFB1–TGFBR1/2、CSF1–CSF1R、CXCL12–CXCR4 在侵袭前沿增强；
- CAF 从“配角”变成主要发送者。

你可以这样讲生物学故事：

> 在侵袭前沿，肿瘤细胞与 CAF 形成正反馈环路：肿瘤分泌 TGF-β 激活 CAF，CAF 再分泌 CXCL12、HGF 等促进肿瘤侵袭；同时 CSF1–CSF1R 信号将巨噬细胞招募到边界并极化为免疫抑制表型，最终形成有利于肿瘤扩散的“通讯重编程生态位”。

### 10.2 验证策略

| 验证层次 | 方法 | 可行性 |
| --- | --- | --- |
| 表达验证 | 在 Visium 原始数据中直接展示配体/受体的空间共表达 | ★★★★★ |
| 单细胞验证 | 用公共 scRNA-seq 数据验证配体-受体在对应细胞类型中共表达 | ★★★★ |
| 蛋白验证 | 用 HPA/文献/公共 IHC 图片验证蛋白表达 | ★★★ |
| 多重免疫荧光 | 用 mIHC/CODEX 验证空间共定位 | ★★★（需合作） |
| 生存/临床 | 用 TCGA 等公共数据验证关键配体-受体基因对预后的影响 | ★★★★ |

```r
# 在 Visium 中直接展示配体与受体的空间共表达
SpatialFeaturePlot(vis, features = c("TGFB1", "TGFBR1", "TGFBR2"),
                   alpha = c(0.1, 1), ncol = 3)
```

### 10.3 用 TCGA 做简单的临床关联（加分项）

关键配体-受体对中的基因，可以到 TCGA 对应癌种中做表达与生存分析：

```r
# 假设你已下载 TCGA 表达矩阵和临床信息
# 这里只展示思路：高风险组 vs 低风险组
library(survival)
library(survminer)

# score = 关键配体/受体基因的平均表达
tcga$score <- rowMeans(scale(tcga_expr[, c("TGFB1", "CXCL12", "CSF1")]))

# 按中位数组
tcga$group <- ifelse(tcga$score > median(tcga$score), "High", "Low")
fit <- survfit(Surv(time, status) ~ group, data = tcga)
ggsurvplot(fit, data = tcga, pval = TRUE, risk.table = TRUE)
```

### 10.4 论文图表清单

一篇“空间生态位通讯重编程”论文通常包含以下图：

| 图号 | 内容 | 对应章节 |
| --- | --- | --- |
| Figure 1 | 研究设计流程图 + 空间数据概览 | 第 0/4 章 |
| Figure 2 | QC 图与空间 marker 表达 | 第 4/5 章 |
| Figure 3 | 细胞类型去卷积与空间分布 | 第 6 章 |
| Figure 4 | 空间生态位识别与 marker 特征 | 第 7 章 |
| Figure 5 | 各生态位通讯网络总览（数量/强度） | 第 8 章 |
| Figure 6 | 生态位间差异通讯热图与气泡图 | 第 9 章 |
| Figure 7 | 通讯模式/中心性分析（河流图、角色热图） | 第 9 章 |
| Figure 8 | 验证：空间共表达、TCGA 生存、IHC | 第 10 章 |

### 10.5 论文结果部分写作模板

**结果 3.1 空间生态位识别**
> 通过无监督聚类与 BayesSpace 平滑，我们在乳腺癌 Visium 切片中识别出 5 个空间生态位：肿瘤核心、侵袭前沿、免疫浸润区、基质区和坏死区。侵袭前沿以肿瘤细胞与成纤维细胞比例均较高为特征，并富集 EMT 与基质重塑基因程序。

**结果 3.2 生态位特异性细胞通讯**
> CellChat 分析显示，侵袭前沿具有最多的显著配体-受体相互作用（n = 312），显著高于肿瘤核心（n = 158）和免疫浸润区（n = 204）。其中 TGFB1–TGFBR1/2、CXCL12–CXCR4、CSF1–CSF1R 在侵袭前沿特异性增强。

**结果 3.3 通讯重编程网络**
> 通过差异网络比较，我们鉴定出 67 个在侵袭前沿相对肿瘤核心发生显著重编程的配体-受体对。CAF 在侵袭前沿由低活性接收者转变为高活性发送者，提示 CAF-肿瘤正反馈环路是空间生态位通讯重编程的核心事件。

### 10.6 小结

- 结果解读要落到“哪个生态位、哪些细胞、哪条配体-受体通路、为什么重要”；
- 验证是审稿人最看重的部分，至少要展示空间共表达；
- 图表顺序要讲一个故事：先地图，再细胞，再生态位，最后通讯重编程。


---

## 第 11 章 新手常见错误与排错

### 11.1 安装报错

| 报错 | 原因 | 解决办法 |
| --- | --- | --- |
| `there is no package called 'NMF'` | CellChat 依赖未装 | 先安装 NMF：`install.packages("NMF")` |
| `cannot open URL` | 网络无法访问 GitHub | 使用镜像：`options(timeout=600)`，或下载 zip 本地安装 |
| `package 'spacexr' is not available` | Bioconductor 版本太旧 | 更新 Bioconductor：`BiocManager::install(update=TRUE)` |
| R 版本 < 4.3 | 部分包不支持 | 升级 R，或用 conda 安装 R 4.3+ |

### 11.2 数据读取报错

```text
Error in Load10X_Spatial: Cannot find filtered_feature_bc_matrix
```

- 检查目录结构是否包含 `filtered_feature_bc_matrix` 子目录；
- 如果下载的是 `.tar.gz`，需要先解压，或在 `filename` 参数中指定压缩包名。

```text
Error: object 'spatial' not found
```

- 使用 `Load10X_Spatial` 时，`spatial/` 目录必须与矩阵目录同级。

### 11.3 去卷积结果全是一个类型

- 参考单细胞数据没有包含对应癌种的肿瘤/基质细胞；
- marker 基因选择不特异（例如 KRT 在正常上皮也高）；
- RCTD 的 `max_cores` 设置太高导致内存不足，可降低到 2～4。

### 11.4 CellChat 没有输出任何显著相互作用

- `min.cells` 设得太大，导致每种细胞类型样本太少；
- 伪 bulk 矩阵里基因过滤太狠；
- 细胞类型数量太少（至少要有 2～3 类）；
- 表达矩阵使用了对数标准化但 CellChat 内部可能还需要原始 counts。请用 `NormalizeData` 后的 `data` slot，不要用 `scale.data`。

### 11.5 生态位图太碎、不连续

- 尝试增加 BayesSpace 的 `gamma`（空间平滑强度），如 `gamma=2` 调到 `3`；
- 在 Seurat 聚类时降低分辨率，如 `resolution=0.4`；
- 用“主要细胞类型比例”聚类，而不是单纯基因表达聚类。

### 11.6 内存不足

| 操作 | 建议 |
| --- | --- |
| 读取大 Visium 数据 | 使用 `filtered_feature_bc_matrix`，不要用 `raw_feature_bc_matrix` |
| 运行 RCTD | 减少参考细胞数，或按细胞类型抽样 |
| 运行 CellChat | 只保留高变基因，或只保留关注细胞类型 |
| R 全局 | 定期 `gc()`，并避免同时保存多个大对象 |

### 11.7 科学严谨性提醒

- **不要**用同一个数据既做发现又做验证（至少做内部交叉验证）；
- **不要**只挑“好看的”配体-受体对，要报告全部显著结果；
- **不要**把相关性说成因果。CellChat 是“推断”，不是“证明”。

---

## 第 12 章 附录：术语表、资源与脚本索引

### 12.1 术语表

| 术语 | 中文 | 一句话解释 |
| --- | --- | --- |
| Visium | 空间转录组平台 | 在组织切片上按 spot 捕获 mRNA 并测序 |
| spot | 空间点/捕获点 | 芯片上直径 55 μm 的捕获区域，含多个细胞 |
| spatial barcode | 空间条形码 | 标记 spot 位置的特异性序列 |
| scRNA-seq | 单细胞 RNA 测序 | 单个细胞水平的转录组测序 |
| deconvolution | 去卷积 | 从混合信号中估计各细胞类型比例 |
| niche | 生态位 | 具有相似组成和功能的空间区域 |
| TME | 肿瘤微环境 | 肿瘤细胞及其周围免疫、基质、血管等成分 |
| ligand | 配体 | 发送信号的分子 |
| receptor | 受体 | 接收信号的分子 |
| CellChat | 细胞通讯推断工具 | 基于配体-受体数据库推断细胞间通讯 |
| rewiring | 重编程/重构 | 网络结构、强度或方向发生系统性改变 |

### 12.2 推荐学习资源

| 资源 | 说明 |
| --- | --- |
| 10x Genomics 官方文档 | Visium 数据下载与 spaceranger 说明 |
| Seurat 官网 spatial vignette | 最友好的 R 空间分析入门 |
| BayesSpace 文档 | 空间聚类与生态位识别 |
| CellChat 官网教程 | 通讯网络分析与比较 |
| Squidpy 文档 | Python 空间分析生态 |
| 《空间转录组学数据分析》综述 | 了解方法学全景 |

### 12.3 完整脚本索引

| 脚本 | 功能 |
| --- | --- |
| `scripts/01_setup.R` | 安装包、创建目录 |
| `scripts/02_load_visium.R` | 读取 10x Visium 数据 |
| `scripts/03_qc_normalize.R` | QC、SCTransform、降维聚类 |
| `scripts/04_deconvolve.R` | RCTD 或 SPOTlight 去卷积 |
| `scripts/05_niche_identification.R` | 生态位识别与命名 |
| `scripts/06_cellchat_niche.R` | 分生态位运行 CellChat |
| `scripts/07_compare_rewiring.R` | 生态位间通讯重编程比较 |
| `scripts/08_figures.R` | 汇总输出论文图 |

> 本教程配套脚本会在 `code/spatial_niche_cell_communication/` 目录中提供（可运行骨架）。

### 12.4 结语

空间生态位不是一个新的“聚类标签”，而是理解肿瘤微环境功能状态的一把钥匙。当你把“细胞类型”升级为“空间生态位”，把“差异表达”升级为“差异通讯”，你就在做一件比传统单细胞分析更贴近真实组织、也更有故事性的工作。

祝你在肿瘤微环境的“城市地图”里，找到属于自己的重要信号通路。

**（全文完）**
