主题
换机复现指南(新电脑从头重跑全链)
本页所有数字、路径、版本均为 2026-07-26 在现役机器上实测导出,不是估计值。 环境清单已随代码入库:
mr-pipeline/env/(R_packages.csv、R_packages_toplevel.txt、apt_packages.tsv、python_wsl_requirements.txt、ENV_FINGERPRINT.txt)。
零、先选方案:不是每种需求都要装 Ubuntu
| 方案 A · 只读出图 | 方案 B · 远程连回台式机 | 方案 C · 完整独立环境 | |
|---|---|---|---|
| 装什么 | Windows R + RStudio Desktop | 仅浏览器 | WSL2 + Ubuntu 24.04 + 全套 |
| 要拷多少 | 结果 CSV,几百 MB | 0 | ~140 GB |
| 能出图 / 改 PPT | ✅ | ✅ | ✅ |
| 能跑独立复算脚本 | ✅ | ✅ | ✅ |
| 能跑单细胞 / bulk / GSEA | ✅ | ✅ | ✅ |
| 能跑 SMR / clump / 全链重跑 | ❌ | ✅ | ✅ |
| 需要台式机开机 | ❌ | ✅ 必须 | ❌ |
| 搭建耗时 | ~1 小时 | 0 | 半天 ~ 1 天(主要在搬数据) |
方案 B 已经搭好:https://mr.stlog.cn(autossh 反代腾讯云 8788 → Caddy HTTPS + basicauth, 凭据见 F:\project\凭据库.md)。出门用副机时这是零成本选择。
本页主体讲方案 C。 若只需要 A,跳到附录一。
为什么方案 C 建议 WSL2 而不是"在 Windows 上装齐"
R 层其实高度可移植——R 代码里调外部命令只有 2 处 tar,369 个包里虽有 189 个含编译产物, 但 Windows 装的是 .dll 预编译版,不是障碍。
真正卡住 Windows 的是这几处(实测):
| 脚本 | 依赖 | Windows 替代成本 |
|---|---|---|
03b_run_smr.sh 03c_fix_and_run.sh | smr-1.4.2-linux-x86_64 | SMR 有 Windows 版,但要换二进制 + 改脚本 |
03a_make_ma.sh 02c_chen_extract.sh | awk + zcat | Git Bash 可跑,路径/编码易出问题 |
gen_freq.sh | plink1.9(/usr/bin/) | plink 有 Windows 版,要改路径 |
_ega_download_eqtl.sh | sftp | Windows OpenSSH 可用 |
一共 16 个 shell 脚本,核心分析路径上约 6 个。在 Windows 上补齐这些,每一处都是没人验证过的新坑; 装 WSL2 只是一条命令,现有脚本一行都不用改。
一、清单:必拷 / 可重建 / 需重装
① 必须拷贝(不可再生)
| 内容 | 源路径 | 体积 | 说明 |
|---|---|---|---|
ukbppp_regional | D:\mrdata\ukbppp_regional\ | 50 G | HyPrColoc 共定位用区域数据 |
outcome | D:\mrdata\outcome\ | 37 G | FinnGen R13 等全部结局 |
deCODEdata | D:\mrdata\deCODEdata\ | 33 G | deCODE SomaScan 平台复制 |
singlecell | D:\mrdata\singlecell\ | 2.4 G | |
eqtl_retina_strunz | D:\mrdata\eqtl_retina_strunz\ | 2.2 G | |
ldpanel | D:\mrdata\ldpanel\ | 1.5 G | 1000G EUR,clump 用 |
ldsc | D:\mrdata\ldsc\ | 76 M | LD scores + w_hm3.snplist |
exposure | D:\mrdata\exposure\ | 3.9 M | UKB-PPP ST9 |
D:\mrdata 合计 | 125 G | ||
| ★ EGA 视网膜(受控) | WSL dr-amd-targets/data/ega_retina | 908 M | 见下方红框 |
| 代码(四个 git 仓) | F:\project\{mr-pipeline,multiomics-mr,dr-amd-targets,decode-rep} | ~1.6 M | |
| PPT 生成脚本 + logo | F:\project\汇报PPT\(含 assets/) | 30 M | |
| docs 源码 | F:\project\docs-site\(可排除 node_modules) | ~50 M | |
| 凭据 | F:\project\凭据库.md + ~\.ssh\ | 小 | 单独加密传输 |
★ EGA 受控数据不能靠"重下"
dr-amd-targets/data/ega_retina(908 M)是 EGA 受控访问数据,当初走过 pyega3 审批流程。 换机后重新下载需要重新申请授权,不是几分钟的事。
必须把它当"不可再生"对待:拷进移动硬盘,并建议顺手移到 D:\mrdata\ega_retina\ 统一管理(WSL 侧建软链指回去),避免它继续躲在 WSL 的 vhdx 里。
② 不用拷(可重新生成)
| 内容 | 体积 | 怎么回来 |
|---|---|---|
mr-pipeline/results/ | 7.3 G | 重跑流水线 |
mr-pipeline/results_archive_*.tgz | 5.4 G | 旧备份,直接不要 |
dr-amd-targets/results/ | 1.1 G | 重跑 |
dr-amd-targets/data/scrna | 5.2 G | GEO 重下(GSE165784 / GSE230348) |
multiomics-mr/03_meqtl_smr/gwas | 4.9 G | 03a_make_ma.sh 从 FinnGen 重生成 |
multiomics-mr/03_meqtl_smr/mqtl | 663 M | SMR 资源页重下 |
multiomics-mr/05_retina/data | 1.3 G | Advani 2024 Zenodo 重下 |
| R 包库 / node_modules | — | 重装 |
搬运量因此从 ~170 G 压到 ~140 G。
③ 需重装(不拷,照清单装)
见第二节。核心:Ubuntu 24.04 + R 4.3.3 + 42 个顶层 R 包 + Python。
二、环境重建
2.1 环境指纹(目标状态)
OS Ubuntu 24.04.3 LTS (kernel 6.6.87.2-microsoft-standard-WSL2)
R 4.3.3 (2024-02-29) "Angel Food Cake"
RStudio Server 2024.12.1+563 (Kousa Dogwood)
Python 3.12.3 (WSL 内) / 3.13.3 (Windows 侧,跑 PPT 脚本)
plink PLINK v1.90b7.2 64-bit (/usr/bin/plink1.9)
SMR smr-1.4.2-linux-x86_64
CRAN 源 P3M https://p3m.dev/cran/__linux__/noble/latest
R_LIBS_USER /home/research/R/x86_64-pc-linux-gnu-library/4.3
R 包 398 个(29 base/recommended + 42 顶层 + 其余依赖)⚠️ R 必须是 4.3.3。
R_LIBS_USER路径含4.3,且 189 个包是为 4.3 编译的; 装 4.4/4.5 会导致整库失效需全部重编。Ubuntu 24.04 (noble) 自带的正是 4.3.3, 不要加 CRAN 的 r-base PPA。
2.2 装 WSL2 + Ubuntu
在 Windows PowerShell(管理员):
powershell
wsl --install -d Ubuntu-24.04
wsl --set-default-version 2重启后进入 Ubuntu,创建默认用户(任意名,例如沿用 lovejj)。
2.3 建独立用户 research
必须单独建,与其他用途(本机上是分子动力学的 lovejj + conda)隔离:
bash
sudo adduser research # 设密码,记进凭据库
sudo usermod -aG sudo research之后一律用:wsl -d Ubuntu-24.04 -u research bash -lc "..."
2.4 装系统依赖(apt)
完整清单在 mr-pipeline/env/apt_packages.tsv(137 条,含版本)。关键的一次装齐:
bash
sudo apt update && sudo apt install -y \
r-base r-base-dev build-essential gfortran cmake pandoc \
libcurl4-openssl-dev libssl-dev libxml2-dev \
libfontconfig1-dev libharfbuzz-dev libfribidi-dev \
libfreetype6-dev libpng-dev libtiff5-dev libjpeg-dev \
libgit2-dev libgsl-dev libglpk40 libglpk-dev \
libhdf5-dev libgeos-dev libgdal-dev libudunits2-dev \
libcairo2-dev libxt-dev zlib1g-dev libbz2-dev liblzma-dev \
libblas-dev liblapack-dev plink1.9 python3-pip python3-venv三个容易漏、漏了报错很怪的
libglpk40—— 少了igraph会dyn.load失败(ggraph/tidygraph/CellChat连带全废)libhdf5-dev—— 少了HDF5Array/batchelor装不上;monocle3更是必须(本机因缺它而monocle3至今未装成,所以轨迹分析只有 Slingshot 单方法,见 09 · 细胞通讯与活化轨迹)libgdal-dev+libgeos-dev+libudunits2-dev——terra/spdep需要
2.5 配 Posit PPM 二进制源(关键,决定装包是分钟还是小时)
写入 /usr/lib/R/etc/Rprofile.site:
r
options(
repos = c(P3M = "https://p3m.dev/cran/__linux__/noble/latest"),
HTTPUserAgent = sprintf(
"R/%s R (%s)", getRversion(),
paste(getRversion(), R.version["platform"], R.version["arch"], R.version["os"])
)
)
HTTPUserAgent必须一起设,否则 PPM 不返回 Linux 二进制、退化成源码编译。
2.6 装 R 包(42 个顶层,其余自动带入)
bash
mkdir -p ~/R/x86_64-pc-linux-gnu-library/4.3
Rscript -e 'install.packages(readLines("~/mr-pipeline/env/R_packages_toplevel.txt"),
dependencies = NA)'⚠️
dependencies = NA(只装 Depends/Imports/LinkingTo)。写TRUE会拉 Suggests, 包数爆到 100+ 且大量装不上。
顶层 42 个(env/R_packages_toplevel.txt):
aplot assertthat batchelor biglm BiocVersion CellChat coloc DOSE downloader
edgeR GenomicSEM ggdist ggnewscale ggraph ggrastr gson harmony HDF5Array
hexbin hyprcoloc leidenbase MendelianRandomization meta msigdbr org.Hs.eg.db
pbmcapply presto pscl remotes rsample scatterpie Seurat shadowtext slam
slingshot spdep speedglm terra treeio TwoSampleMR UpSetR WGCNAGitHub 来源的几个(PPM 上没有,需 remotes):
r
remotes::install_github(c(
"MRCIEU/TwoSampleMR", "rondolab/MR-PRESSO", "MRCIEU/ieugwasr",
"jrs95/hyprcoloc", "GenomicSEM/GenomicSEM", "jinworks/CellChat",
"immunogenomics/presto"
))关键包版本(对不上时以 env/R_packages.csv 为准,共 398 条):
| 包 | 版本 | 包 | 版本 |
|---|---|---|---|
| Seurat | 5.5.1 | TwoSampleMR | 0.7.9 |
| CellChat | 2.2.0.9001 | coloc | 5.2.3 |
| slingshot | 2.10.0 | hyprcoloc | 0.0.2 |
| harmony | 2.0.5 | GenomicSEM | 0.0.5 |
| limma | 3.58.1 | MendelianRandomization | 0.10.0 |
| edgeR | 4.0.16 | MRPRESSO | 1.0 |
| WGCNA | 1.74 | ieugwasr | 1.1.0.9000 |
| fgsea | 1.28.0 | data.table | 1.18.4 |
验证:
bash
Rscript -e 'p <- readLines("~/mr-pipeline/env/R_packages_toplevel.txt")
ok <- sapply(p, requireNamespace, quietly = TRUE)
cat(sum(ok), "/", length(ok), "可加载\n"); print(names(ok)[!ok])'2.7 SMR 二进制
bash
mkdir -p ~/multiomics-mr/03_meqtl_smr/tools && cd $_
wget https://yanglab.westlake.edu.cn/software/smr/download/smr-1.4.2-linux-x86_64.zip
unzip smr-1.4.2-linux-x86_64.zip && chmod +x smr-1.4.2-linux-x86_64/smr
03b_run_smr.sh/03c_fix_and_run.sh里的路径就是这个,目录名别改。
2.8 Python
WSL 侧(141 条清单在 env/python_wsl_requirements.txt,主要给 06_ega_pick_files.py、 19_zebrafish_ortholog.py、EGA 下载):
bash
python3 -m pip install --break-system-packages -r ~/mr-pipeline/env/python_wsl_requirements.txt
# 或只装关键几个:
python3 -m pip install --break-system-packages pandas numpy requests pyega3Windows 侧(跑 PPT 与设计图脚本,Python 3.13):
powershell
py -m pip install python-pptx==1.0.2 matplotlib==3.10.3 pillow==11.2.1 `
openpyxl==3.1.5 pypdf==6.14.2 numpy==2.2.6 pandas==2.2.32.9 RStudio Server(可选)
bash
wget https://download2.rstudio.org/server/jammy/amd64/rstudio-server-2024.12.1-563-amd64.deb
sudo gdebi rstudio-server-2024.12.1-563-amd64.deb
sudo systemctl enable --now rstudio-server浏览器 http://localhost:8787,登录 research。
503 陷阱
Windows 系统代理会拦 localhost:8787 返回 503。浏览器天然 bypass localhost 所以正常; 只有 PowerShell 的 Invoke-WebRequest 需要 -NoProxy。
2.10 凭据落位
| 凭据 | 位置 | 用途 |
|---|---|---|
| OpenGWAS token | ~/.Renviron 里 OPENGWAS_JWT= | PheWAS 查 OpenGWAS |
| SSH 私钥 | ~\.ssh\myserver_key(Windows)→ 拷进 WSL ~/.ssh/ | 发布 docs、mrsync |
| SSH config | ~\.ssh\config | ⚠️ UserKnownHostsFile 必须写 /dev/null,不能写 NUL |
| EGA 账号 | dr-amd-targets/ega_credentials.json(不入 git) | EGA 下载 |
| 其余 | F:\project\凭据库.md / Vaultwarden |
三、数据搬运与校验
3.1 搬 D:\mrdata(125 G)
移动硬盘最省事。校验不能只看总大小——要核文件数 + 抽样哈希:
powershell
# 旧机器:生成清单
Get-ChildItem D:\mrdata -Recurse -File |
Select-Object @{n='rel';e={$_.FullName.Replace('D:\mrdata\','')}}, Length |
Export-Csv D:\mrdata_manifest.csv -NoTypeInformation
# 新机器:对照
$old = Import-Csv D:\mrdata_manifest.csv
$new = Get-ChildItem D:\mrdata -Recurse -File |
Select-Object @{n='rel';e={$_.FullName.Replace('D:\mrdata\','')}}, Length
"旧 $($old.Count) 个文件 / 新 $($new.Count) 个"
Compare-Object $old $new -Property rel,Length | Format-Table再对最大的几个抽样哈希(Get-FileHash -Algorithm SHA256),确认逐字节一致。
3.2 目录结构与软链
代码全用相对路径(data/outcome、data/exposure/protein_info.csv), 所以只需重建软链,不改任何代码:
bash
cd ~/mr-pipeline
mkdir -p data
ln -sfn /mnt/d/mrdata/outcome data/outcome
ln -sfn /mnt/d/mrdata/exposure/protein_info.csv data/exposure/protein_info.csv
# EGA 受控数据若已归位 D 盘:
ln -sfn /mnt/d/mrdata/ega_retina ~/dr-amd-targets/data/ega_retinaconfig.yaml 里仍是绝对路径的两处(换机若改了盘符要同步改):
yaml
ld:
bfile: "/mnt/d/mrdata/ldpanel/EUR"
# analysis/04_ldsc.R 里: REFDIR <- "/mnt/d/mrdata/ldsc/eur_w_ld_chr"3.3 为什么不把数据放进 WSL(实测)
| WSL 原生 ext4 | /mnt/d(9p) | 倍数 | |
|---|---|---|---|
| 顺序读 | 859 MB/s | 126 MB/s | 慢 6.8× |
| 300 个小文件 | 0.01 s | 0.23 s | 慢 ~23× |
分层判据是「丢了能不能自动拿回来」,不是「数据 vs 代码」:
- 不可再生(原始数据、EGA、代码)→ Windows 侧(D 盘 / F 盘 + git),要备份
- 可再生(产物、解压中间件)→ WSL 原生,图快,换机不搬
四、代码落位(四个 git 仓)
bash
# ① F 盘已有仓(随移动硬盘拷来即可,它们是 origin)
# F:\project\{mr-pipeline,multiomics-mr,dr-amd-targets,decode-rep}
# ② WSL 侧接成跟踪副本
for p in mr-pipeline multiomics-mr dr-amd-targets decode-rep; do
git config --global --add safe.directory "/mnt/f/project/${p}"
git config --global --add safe.directory "/mnt/f/project/${p}/.git"
git clone "/mnt/f/project/${p}" "/home/research/${p}"
git -C "/home/research/${p}" config core.filemode false
done建仓/克隆的三个坑(本机踩过)
- F 盘的
git init必须在 Windows 侧做 —— WSL 的research用户无法在 NTFS 挂载chmod, 会报could not set 'core.filemode'并建出坏仓库 - 必须加
safe.directory—— F 仓由 Windows 用户创建,WSL UID 不同 →dubious ownership拒绝读 - WSL 侧必须
core.filemode false——/mnt/f挂出来是 777,否则 git 把权限差异 误报成"全部文件已修改"
「F 盘唯一真源」是约定不是机制
2026-07-26 第一次做四项目漂移自检,mr-pipeline 就查出 17 个已改 + 11 个未跟踪代码文件 从未回迁 F 盘——含产出全部当前结果的「分家」实现。换机后第一件事就跑这个自检 (命令见此)。
五、验证复现(★ 最关键的一节)
换机后不能只看"跑起来了"。必须证明算出来的数与旧机一致。 下面四层,从快到慢,每层都有明确的期望值。
5.1 第一层:环境自检(秒级)
bash
cd ~/mr-pipeline
Rscript -e 'p <- readLines("env/R_packages_toplevel.txt")
ok <- sapply(p, requireNamespace, quietly = TRUE)
stopifnot("顶层包必须全部可加载" = all(ok)); cat("✅", length(ok), "个顶层包全部可加载\n")'
diff <(Rscript -e 'cat(R.version.string)') <(grep '^R:' env/ENV_FINGERPRINT.txt) || true5.2 第二层:smoke test(分钟级,有真断言)
bash
cd ~/mr-pipeline
for t in m1 m2 m2b m3 position coloc_region; do
Rscript "tests/smoke_test_${t}.R" > "/tmp/${t}.log" 2>&1
echo "$t exit=$?"
done期望:全部 exit=0。 2026-07-26 已给 5 个原本零断言的测试补了命名 stopifnot (m1 8 条 / m2 7 条 / m2b 9 条 / m3 6 条 / position 4 条),并做过阴性对照—— 故意改错期望值会 exit=1 并报出断言名。
关键期望值(写在断言里,跑错会直接失败):
| 测试 | 断言的核心期望 |
|---|---|
| m1 | cis 过滤后 8 行;pvallog 必须还原为 p ≤ 1e-6;effect≠other allele |
| m2 | overall F > 10;主方法唯一;n_iv 与谐化后一致 |
| m2b | 必须走多 IV 分支(≥3);主方法为 IVW;合成正相关数据的估计 > 1;Steiger 方向正确 |
| m3 | coloc 与 hyprcoloc 均 status=ok;PP.H4 ≥ 0.8 |
| position | 位置键交集 = 全部 SNP(证明等位顺序不同也能对上) |
exit=0 现在真的有意义了
改造前 6 个测试里 5 个零断言、PASSED 是脚本跑到最后无条件打印的——只证明"能跑完不报错"。 现在断言会真的拦住。
5.3 第三层:独立复算(分钟级,不 source 流水线)
这几个脚本是脱离流水线重算同一批统计量、再与产物比对的:
bash
Rscript ~/mr-pipeline/tools/verify_coloc_pqtl.R # 共定位
Rscript ~/mr-pipeline/tools/verify_ldsc.R # LDSC
Rscript ~/mr-pipeline/tools/verify_phewas.R # PheWAS Bonferroni
Rscript ~/mr-pipeline/tools/verify_tier.R # A/B 分层阈值敏感性
Rscript ~/dr-amd-targets/tools/verify_singlecell.R # 单细胞四项
python3 ~/mr-pipeline/tools/manual_verify_tnfrsf10a.py # MR 主体十个量单细胞四项的期望值(换机后必须逐个吻合):
| 量 | 期望 |
|---|---|
| MERTK 平均表达 @小胶质/髓系 | 0.7126 |
| MERTK 阳性率 @小胶质/髓系 | 25.0%(其他细胞类型 7.0%) |
| Slingshot ρ(MERTK vs 伪时序) | −0.3070 |
| 伪 bulk Wilcoxon p(AMD vs Normal) | 0.8212 |
⚠️ 复算口径坑:AverageExpression 是先 expm1 再求均值(0.7126); 直接对 log 值求均值得 0.3063,不是同一个量,会误判成"算错了"。
5.4 第四层:全链重跑并对数(小时级)
bash
cd ~/mr-pipeline && bash run_pipeline.sh R13 # 视机器数小时对这张表(2026-07-22 定稿,原始产物实测):
| 结局 | 病例数 | 显著蛋白 |
|---|---|---|
| 糖网 RetinopathyStrict | 6,970 | 10 |
| 黄斑病变 Maculopathy | 4,766 | 9 |
| 糖尿病神经病变 Neuropathy | 4,145 | 4 |
| 糖尿病肾病 Nephropathy | 6,043 | 6 |
| 新生血管性青光眼 NeovascGlaucoma | 1,576 | 0 |
| AMD | 13,947 | 33 |
| 湿性 WetAMD | 7,529 | 26 |
| 干性 DryAMD | 9,533 | 25 |
下游关键值:deCODE 方向一致 79.4%、两平台都显著者同向 83.6%、 IAMDGC 复制 59/81 ≈ 73%、TNFRSF10A 共定位 PP 0.92 / 复制 p = 1.6e-9。
核时间戳,别凭印象:
bash
ls -l --time-style=+%F_%H:%M results/screen_R13_dm/*_significant.csv同一次运行的产物时间戳应集中在几分钟内。本机曾因编排脚本中断 + 断点缓存 「文件存在=已完成」而静默复用了两天前的旧产物,正是靠核时间戳发现的。
5.5 已知的两处"跑通也不代表干净"
| 项 | 状态 | 换机后要注意 |
|---|---|---|
| PheWAS gwasinfo 降级 | 根因未修 | 若 gwasinfo() 失败会静默降级(打 ⚠️ 但继续跑、exit 0),Bonferroni 阈值宽松 10 倍。用 ndb=50056 钉住,或跑完核 phewas_provenance.csv 的 n_datasets_source 字段 |
00_setup.R 全局选项 | 只在 01_screen.R 生效 | 05/08/10 无显式种子(实测 hyprcoloc 确定性、重跑逐位一致) |
附录一 · 方案 A:Windows 原生 RStudio
只做读结果 / 出图 / 改 PPT,不装 Ubuntu:
powershell
# 1) 装 R 4.3.3 (Windows) + RStudio Desktop
# 2) 装能用的那部分包(跳过 SMR 相关)r
install.packages(c("data.table","ggplot2","ggrepel","Seurat","harmony",
"limma","edgeR","fgsea","WGCNA","coloc","TwoSampleMR"),
dependencies = NA)能跑:01c_figures.R、02b_figure.R、05c_retina_figure.R、split_figs.R、 verify_singlecell.R、verify_phewas.R、verify_tier.R、单细胞/伪 bulk/GSEA 下游。
跑不了:SMR(03b/03c)、gen_freq.sh(plink)、03a_make_ma.sh(awk+zcat)、 EGA sftp 下载、全链 run_pipeline.sh。
PPT 与设计图脚本(make_ppt.py、make_design_fig.py)本来就在 Windows 侧跑, 装第 2.8 节的 Windows Python 依赖即可。
附录二 · 一页速查
① wsl --install -d Ubuntu-24.04 → 建 research 用户
② apt 装 137 条依赖(别漏 libglpk40 / libhdf5-dev / libgdal-dev)
③ 配 PPM 源 + HTTPUserAgent(否则源码编译几小时)
④ install.packages(顶层42个, dependencies = NA) + 7 个 GitHub 包
⑤ 下 SMR 1.4.2 linux 二进制,目录名别改
⑥ 拷 D:\mrdata 125G(核文件数 + 抽样 SHA256)+ EGA 908M(受控,不可重下)
⑦ 拷 F 盘四个 git 仓 → WSL clone(safe.directory + core.filemode false)
⑧ 建软链 data/outcome、data/exposure/protein_info.csv
⑨ 凭据:~/.Renviron 的 OPENGWAS_JWT、~/.ssh/、ega_credentials.json
⑩ 验证四层:环境自检 → smoke test(有断言) → 独立复算 → 全链对数 + 核时间戳