生物大分子批量仿真开发教程(14):可开发性批量评估(二)——聚集、稳定性与免疫原性,多源分数合成统一风险表
版本声明块
- 工具/软件:TANGO(tango.crg.es);AGGRESCAN→Aggrescan3D(A3D2)/Aggrescan4D(A4D);CamSol/CamSol3.0;TAP;BioLuminate(SAP 商业实现);NetMHCIIpan-4.0;TepiTool(IEDB)
- 语言/环境:Python 3.10 + pandas;服务器状态实测日期2026-09-04
- 本文目标:给第 13 篇的可开发性矩阵补上"聚集、稳定性、免疫原性"三条腿,合成一张多源统一风险表
一句话结论:本篇的硬事实是服务器现状(实测 2026-09-04,铁律 8):TANGO 在线(https://tango.crg.es/)但需注册许可;AGGRESCAN 原站(bioinf.uab.es)已失效、后继 A3D2(http://biocomp.chem.uw.edu.pl/A3D2/)与 pH 依赖的 A4D(https://biocomp.chem.uw.edu.pl/a4d/)在线;CamSol 原剑桥服务器为维护页、只能本地安装;Zyggregator 无维护入口;SAP 的商业实现只在 BioLuminate——所以批量流水线必须带"可用性探针 + 替代路径",再把 TANGO/A3D/CamSol/TAP 分数、第 12 篇 MD 代理量与 NetMHCIIpan-4.0/TepiTool 免疫原性分按"批次内百分位 + 一票否决 + 计数投票"聚合成统一风险表,用 AC-SINS(Liu 2014 mAbs,Δλmax)等实验批次回归校准阈值。
〇、本篇要解决的认知问题
- 聚集预测工具谱系到 2026 年 9 月还能用哪些?TANGO、AGGRESCAN、A3D/A4D、CamSol、Zyggregator、SAP 各自的现状与替代路径是什么?
- 序列级聚集热点(TANGO/AGGRESCAN 系)与结构级聚集倾向(A3D/SFvCSP/SAP)在方法论上差在哪,为什么两条都要?
- Tagg、Tm 这些实验热稳定量,在 MD 侧有什么可用的代理量?"代理"二字边界在哪?
- 免疫原性批量预测怎么做?NetMHCIIpan-4.0 与 TepiTool 各占什么位置,局限是什么?
- 多源分数(量纲、方向、缺失率全不同)怎么合成一张可审计的统一风险表,实验对照(AC-SINS/HIC/BVP-ELISA)怎么进来校准?
一、机制解析
1.1 聚集工具谱系与实测现状(2026-09-04,铁律 8)
引用在线工具不给实测日期等于埋雷。以下为系列基线日期的登记结果,流水线代码必须内嵌同一张表(见 2.1):
| 工具 | 层级 | 方法锚点 | 现状(实测 2026-09-04) | 批量替代路径 |
|---|---|---|---|---|
| TANGO | 序列级 β-聚集成核 | Fernandez-Escamilla 2004 Nat Biotechnol 22:1302 | ✅ https://tango.crg.es/ 在线,需注册许可 | 站内申请账号;Web 服务限速条款遵守其页面 |
| AGGRESCAN | 序列级聚集热点 | Conchillo-Solé 2007 BMC Bioinformatics 8:65 | 🔴 原 bioinf.uab.es 失效、CSIC 镜像 404 | 后继A3D2(下行为准) |
| Aggrescan3D(A3D2) | 结构级 | 折叠态结构遮蔽聚集热点 | ✅ http://biocomp.chem.uw.edu.pl/A3D2/ | 在线或按站点条款批量 |
| Aggrescan4D(A4D) | 结构级 + pH 依赖 | NAR 2024 52:W170 | ✅ https://biocomp.chem.uw.edu.pl/a4d/ | 制剂 pH 敏感场景优先它 |
| CamSol | 序列级本征溶解度 + 突变优化 | Sormanni 2015 JMB 427:478(DOI 10.1016/j.jmb.2014.09.026);3.0 为 pH 版(2023) | 🔴 原 mvsoftware 剑桥服务器为维护页 | 本地安装(许可条款以仓库为准),集成进第 13 篇 run_tap 同款子进程模式 |
| Zyggregator | 序列级 | Tartaglia & Vendruscolo 2008 Chem Soc Rev 37:1395 | 🔴 原服务器无维护入口 | 仅作历史方法对比,不进生产 |
| SAP(spatial aggregation propensity) | 结构级 | Chennamsetty 2009 PNAS 106:11937(DOI 发表前复核) | 商业实现于 BioLuminate | 开源近似= TAP 的 SFvCSP + A3D 分数 |
三条工程教训:URL 是配置不是常量(迁址=改配置文件,脚本不动);许可状态进风险登记表(TANGO 的注册许可意味着自动化提交要过合规,不能偷偷爬);"原站 404"是所有在线工具工具的默认预期——探针先行、失败降级到本地实现,是流水线的常态分支而不是异常。
1.2 序列级 vs 结构级:遮蔽机制是全部差异的来源
同一句序列,TANGO/AGGRESCAN/CamSol 看到的是"氨基酸内在倾向";A3D/SAP/SFvCSP 看到的是"折叠后还剩多少暴露在表面"。一个埋在上表面的聚集六肽,序列级打高分、结构级接近零;一个界面残基在单体里埋藏、在二聚过渡态暴露——于是两层的分歧本身就是信号:序列高分 + 结构低分 ≈ 可控;两边都高 = 真热点;序列低 + 结构高(罕见,多为构象特异斑块)→ 交给第 12 篇 MD 看构象系综会不会路过它。统一风险表因此三层并列,而不是只取其一。
1.3 Tagg/Tm 与 MD 代理量
实验侧的地面真值:Tm(熔解温度,DSC/nanoDSF)与Tagg(聚集起始温度, nanoDSF 背散射通道);色谱面板 HIC/SEC/CEX-IEX/SMAC 补疏水/体积/电荷维度。批量不可能全量做实验,MD 侧可用的代理量(经验法则,不是铁律,且各家 SOP 阈值不同):第 12 篇输出的rmsd_last(构象稳定)、rg_drift(展开趋势)、sb_occ(盐桥网络完整度),加上"斑块面积在系综内的 P95 分位"(把第 13 篇结构级指标从单构象扩展成构象分布)。代理量与 Tagg/Tm 的关系是排序近似:它们大概率能把"最不稳的 5%“捞出来,不能预测"Tagg=68.4 ℃”。风险表把 MD 代理列的置信度标为"低/样本少"正是为此。
1.4 免疫原性:MHC-II 呈递预测的两个层次
T 细胞依赖的免疫原性主流 in silico 路径是肽段-MHC-II 结合预测:
- NetMHCIIpan-4.0(Reynisson 2020 J Proteome Res,DOI 10.1021/acs.jproteome.9b00874):单一 HLA-DR 等位基因的精配模型,实测 2026-09-04 在线(https://services.healthtech.dtu.dk/services/NetMHCIIpan-4.0/),DTU 规则要求非商用/学术用途合规;
- TepiTool(Paul 2016 Curr Protoc Immunol,DOI 10.1002/cpim.12,http://tools.iedb.org/tepitool/):把多等位基因、多类 I/II 分子结果聚合成 population consensus 百分位的流水线——批量选人群覆盖度用 TepiTool 的 consensus,单基因高置信复评用 NetMHCIIpan-4.0,二者是互补而非替代。
局限必须写进报告:呈递 ≠ 实际 T 细胞应答(链接表位显性、竞争、加工都不在模型内),所以免疫原性列只做"相对排序 + 高风险标记",进风险表的权重低于聚集类指标(示例权重见 2.2 配置)。
1.5 实验对照锚点
计算排序不可自证,需要实验批次回归:AC-SINS(亲和力捕获自相互作用纳米颗粒光谱,读出 Δλmax 红移;Liu 2014 mAbs 6:483,DOI 10.4161/mabs.27431)做自相互作用的批量金标准旁证;HIC(疏水作用色谱保留时间)对斑块/疏水列;BVP-ELISA(生物素化 VP 抗原池)与表面等离子共振对多反应性(polyreactivity,锚文献 Jain 2017 PNAS 114:944,DOI 本轮未复核、正式引用前以出版方页面为准)。校准方法:攒一批 ≥30 个有实测值的变体,算风险表综合分与 Δλmax 的 Spearman 相关,阈值随相关结构调——不校准的阈值是装饰。
二、完整代码与逐行剖析
2.1 服务器可用性探针:probe.py(把铁律 8 变成每次运行的例行动作)
#!/usr/bin/env python# -*- coding: utf-8 -*-"""probe.py —— 上线前先问"工具还活着吗",状态写进风险表元数据(不是写进人的记忆)"""importdatetimeimporturllib.requestimportpandasaspd SERVERS={# URL 全部来自本系列素材登记表;改址=改这张配置表"TANGO":"https://tango.crg.es/",# 在线但需注册许可"A3D2":"http://biocomp.chem.uw.edu.pl/A3D2/",# AGGRESCAN 后继"A4D":"https://biocomp.chem.uw.edu.pl/a4d/",# pH 依赖版"NetMHCIIpan":"https://services.healthtech.dtu.dk/services/NetMHCIIpan-4.0/","TepiTool":"http://tools.iedb.org/tepitool/","AGGRESCAN_old":"http://bioinf.uab.es/",# 原站域名(素材核实其已失效):}# 预期不可达,留作回归对照# CamSol 原剑桥服务器(mvsoftware 系)实测为维护页,但其原始 URL 未在本系列素材中逐字核实,# 故不进探针表——这正是"探针清单=已核实登记表"的纪律:宁缺毋假。生产路径=本地安装。defprobe(url:str,timeout:float=15.0)->dict:req=urllib.request.Request(url,headers={"User-Agent":"devrisk-probe/1.0"})# 带 UA 是公共服务器的基本礼貌:部分站点把无 UA 请求直接 403,会造成"假下线"误判try:withurllib.request.urlopen(req,timeout=timeout)asr:# 只 GET 首页:探针不做提交,return{"url":url,"ok":True,"status":r.status}# 避免对限速服务造成负担exceptExceptionase:return{"url":url,"ok":False,"status":type(e).__name__}# 异常类型入库:# 区分 404/超时/TLS 三种死法defmain()->None:today=datetime.date.today().isoformat()df=pd.DataFrame([{"checked_on":today,**probe(u)}foruinSERVERS.values()])df["note"]=df.url.map(lambdau:{SERVERS["TANGO"]:"需注册许可后自动化提交",SERVERS["AGGRESCAN_old"]:"已知失效→用 A3D2"}.get(u,""))df.to_csv(f"server_status_{today}.csv",index=False)print(df.to_string(index=False))if__name__=="__main__":main()# 基线预期(2026-09-04 实测口径):TANGO/A3D2/A4D/NetMHCIIpan/TepiTool 可达;# AGGRESCAN_old 不可达——探针输出与预期不符时先修流水线,再谈跑分2.2 统一风险表聚合器:risk_table.py
#!/usr/bin/env python# -*- coding: utf-8 -*-"""risk_table.py —— 第 13 篇矩阵 + 聚集/免疫原性列 + MD 代理列 → 统一风险表(含实验回归)"""importpandasaspd METRICS=[# 每列登记:方向、权重、层级、置信度 —— 元数据行而非裸列名,是审计的最小代价{"col":"TANGO_score","lower_better":True,"w":1.0,"layer":"seq","conf":0.8},{"col":"A3D_score","lower_better":True,"w":1.0,"layer":"struct","conf":0.8},{"col":"CamSol_score","lower_better":False,"w":1.0,"layer":"seq","conf":0.8},{"col":"FvCSP","lower_better":True,"w":0.8,"layer":"seq","conf":0.9},{"col":"SFvCSP","lower_better":True,"w":0.8,"layer":"struct","conf":0.9},{"col":"md_rmsd_last","lower_better":True,"w":0.5,"layer":"md","conf":0.4},{"col":"imm_pct","lower_better":False,"w":0.4,"layer":"immuno","conf":0.5},]VETO_Q=0.02# 一票否决线:任一指标批次内最差 2%(第 13 篇 1.4 同款规则,跨篇同构)PASS_Q=0.50# 计数投票线EXPERIMENT={# 有实测批次时启用回归校准;键=实验名,值=对应"应该相关的计算列""AC-SINS_dlambda_max":"A3D_score",# Δλmax(Liu 2014)对结构级聚集列"HIC_retention":"CamSol_score",}defpct(s:pd.Series,lower_better:bool)->pd.Series:r=s.rank(pct=True)# 百分位只在提交批次内做:跨批次绝对分不可比(第 13 篇returnriflower_betterelse1-r# 3.3 的同款坑);方向统一成"越大越安全"再进合成defmain(dev_csv:str,md_csv:str,imm_csv:str,out:str)->None:df=pd.read_csv(dev_csv).set_index("variant")# 第 13 篇 A/B/C/D 分层表进这里df=df.join(pd.read_csv(md_csv).set_index("job").rename(columns={"rmsd_last":"md_rmsd_last"}),how="left")df=df.join(pd.read_csv(imm_csv).set_index("variant"),how="left")# imm_pct:TepiTool# ↑ join 不上=该变体没跑 MD/免疫评,列留 NaN——"缺测"和"测了很差"在风险表里必须可区分(铁律 10)cols=[mforminMETRICSifm["col"]indf.columns]# 列白名单交集:上游加列不污染投票df["n_metrics"]=df[[m["col"]formincols]].notna().sum(1)df["veto"]=Falseweighted,voted=pd.Series(0.0,index=df.index),pd.Series(0,index=df.index)formincols:r=pct(df[m["col"]].astype(float),m["lower_better"])# NaN 保持 NaN,不补 0:veto_part=(r<VETO_Q).fillna(False)# 把缺测当差=冤枉,当好=漏判df["veto"]|=veto_part# 缺测变体进复核队列而不是投票池voted+=(r>PASS_Q).fillna(False).astype(int)weighted+=r.fillna(0.5)*m["w"]*m["conf"]# 缺列按中性 0.5+降权是df["risk_score"]=weighted/sum(m["w"]*m["conf"]formincols)# 保守选择,须与 n_metrics 同读df["votes_pass"]=voted df["risk_tier"]="D"df.loc[~df["veto"],"risk_tier"]="C"df.loc[(~df["veto"])&(df["votes_pass"]>=5),"risk_tier"]="B"df.loc[(~df["veto"])&(df["votes_pass"]>=6)&(df["n_metrics"]>=len(cols)),"risk_tier"]="A"forexp_col,calc_colinEXPERIMENT.items():# 有实测列时做排序一致性校准:ifexp_colindf.columns:# Spearman 手写免依赖two=df[[exp_col,calc_col]].dropna()iflen(two)>=10:# n<10 的相关是噪声,直接跳过a=two[exp_col].rank();b=two[calc_col].rank()rho=((a-a.mean())*(b-b.mean())).sum()/(((a-a.mean())**2).sum().sqrt()*((b-b.mean())**2).sum().sqrt())df.attrs[f"spearman_{exp_col}"]=round(float(rho),3)# ρ 写进表元数据,# 报告页引用它;|ρ| 不达标(经验线 <0.5)就先调权重再扩大候选池——顺序不能反df.to_csv(out)print(df["risk_tier"].value_counts())print("缺测复核队列:",df[(df["n_metrics"]<len(cols))&(df["risk_tier"]!="D")].shape[0])if__name__=="__main__":main("dev_matrix_voted.csv","md_metrics.csv","immunogenicity.csv","risk_table.csv")(imm_pct的生成:把每个变体 Fv+Fc 序列切成 15-mer 肽池(窗口/步长为可配置项),逐肽送 NetMHCIIpan-4.0 或本地版,再按 TepiTool 思路聚合人群覆盖百分位——服务的输入输出文件格式以其页面与安装版 --help 为准,本文不臆造字段名;肽切分就是row[i:i+15]的滑窗,属于第 02 篇级别的基础操作。)
2.3 免疫原性肽池生成 + 提交护栏:peptides.py
#!/usr/bin/env python# -*- coding: utf-8 -*-"""peptides.py —— 序列→15-mer 肽池(NetMHCIIpan/TepiTool 通用输入形态),带提交护栏"""frompathlibimportPathimportpandasaspddefmake_peptide_pool(seq:str,length:int=15,step:int=1)->list:return[seq[i:i+length]foriinrange(0,len(seq)-length+1,step)]# 15-mer 是 MHC-II 结合预测的通用肽长惯例;step=1 全覆盖但提交量 = 序列长,批量前先想清楚defmain(csv_in:str,csv_out:str,chunk:int=5000)->None:df=pd.read_csv(csv_in)withopen(csv_out,"w",encoding="utf-8")asfh:for_,rindf.iterrows():pep=make_peptide_pool(str(r["full_sequence"]))forkinrange(0,len(pep),chunk):# 分块文件:Web 服务都有单次/每日限额,part=f"{csv_out}.part{k//chunk}"# 分块=失败只重传一块(幂等思路同铁律 5)withopen(part,"w",encoding="utf-8")aspf:forpinpep[k:k+chunk]:pf.write(f"{r['variant']}|{k}\t{p}\n")# 行首回标 variant:结果回流时# 肽→变体的归属链必须在生成时就写死,事后按序列反查会被重复肽咬死print("peptide chunks written for",len(df),"variants")if__name__=="__main__":main("dev_matrix_voted.csv","peptides.tsv")三、常见报错与排查
- 脚本上周还能连 AGGRESCAN,今天全批 404。现象即铁律 8 的现实版。根因:原站失效不是故障而是终态。解法:跑 2.1 探针→按登记表切 A3D2 路径→对历史批次标注数据源版本;把"探针失败=流水线自动降级"写进编排(第 19 篇的重试分类)。
- TANGO 结果迟迟拿不到/账号被限。根因:服务器在线但需注册许可(2026-09-04 实测),且自动化爬取违反使用条款。解法:走注册与批量接口谈判;流水线里 TANGO 列允许缺测(2.2 已按缺测中性化处理),主投票不依赖单源。
- 风险表里最差档全是"没跑过 MD 的变体"。根因:把缺测按 0 分处理。解法:按 2.2 的纪律——缺列不投票、
n_metrics与risk_score永远同读;缺测变体进复核队列而非淘汰队列。 - 免疫原性两列互相矛盾(NetMHCIIpan 低危、TepiTool consensus 高危)。根因:单等位基因模型 vs 人群覆盖百分位是两个问题。解法:报告里分开陈述——“DRB1*04:01 呈递风险低,但人群覆盖后的 consensus 偏高(多等位基因贡献)”;权重设置(2.2 里 imm 0.4×conf 0.5)已经体现"免疫列只做标记不做主刀"。
- pH 换了,A3D 分数不动、A4D 动了,风险表结论打架。根因:不同 pH 敏感度来自工具方法本身。解法:制剂 pH 敏感候选一律以 A4D/CamSol3.0(pH 版)为准,把 pH 写进列名(
A4D_score_pH5.2风格),风险表按"配方 pH 匹配列"取数。
四、动手练习
- 探针回归(可判定):运行 2.1,与基线预期比对。判定标准:7 个 URL 全部有
ok/status字段;TANGO/A3D2/A4D/NetMHCIIpan/TepiTool 可达,AGGRESCAN_old/CamSol_old 不可达——任何一格与预期不符,先查网络出口再查工具。 - 风险表完整性(可判定):用 100 变体(含 15 个缺 CamSol、10 个缺 MD 列)跑 2.2。判定标准:A 层变体
n_metrics必须等于指标总数(A 层不允许缺测);25 个缺测变体不得出现 veto=True(缺测≠差)。 - 实验校准(可判定):取 ≥30 个有 AC-SINS Δλmax 实测的变体回灌
EXPERIMENT。判定标准:spearman_AC-SINS元数据被写出;若 |ρ|<0.3,把 A3D 权重降半并记录调权日志——调权必须留痕,这是对外报告的可信度底线。
五、小结与下一篇预告
本篇补齐了统一风险表的三条腿:聚集(TANGO/A3D/A4D/CamSol/SAP 谱系 + 2026-09-04 实测现状表)、稳定性(Tagg/Tm 地面真值与 MD 代理量的"排序近似"边界)、免疫原性(NetMHCIIpan-4.0 精配 + TepiTool 人群共识),并把第 13 篇的投票规则跨篇同构地延伸到多源分数合成——方向归一、批次内百分位、缺测中性化、一票否决、实验回归校准五步,一步都不能省。双抗与 ADC 在这张表之上还有专属的界面与偶联风险,第 15 篇《双抗与 ADC 的专项仿真》处理它们;万条序列的漏斗预算与断点续跑在第 17 篇实战中验收,第 18 篇把本篇风险表直接装进双抗流水线。
本篇认知问题回显(FAQ)
Q1:2026-09-04 实测下,各聚集预测服务器现状如何,替代路径是什么?
A:TANGO(tango.crg.es)在线但需注册许可;AGGRESCAN 原站 bioinf.uab.es 失效、CSIC 镜像 404;后继 A3D2(biocomp.chem.uw.edu.pl/A3D2/)与 pH 依赖的 A4D(biocomp.chem.uw.edu.pl/a4d/)在线;CamSol 原剑桥服务器为维护页→只能本地安装;Zyggregator 无维护入口仅作历史对比;SAP 商业实现在 BioLuminate,开源近似为 TAP 的 SFvCSP + A3D。
Q2:序列级和结构级聚集预测差在哪,为什么都要跑?
A:序列级(TANGO/AGGRESCAN 系/CamSol)量氨基酸内在倾向,结构级(A3D/A4D/SAP/SFvCSP)量折叠后的表面暴露——差异来源是"埋藏遮蔽"。两层分歧本身就是信号:双高=真热点,序列高结构低=可控,序列低结构高=构象特异,交 MD 构象系综复核。
Q3:Tagg/Tm 与 MD 代理量是什么关系?
A:Tm(DSC/nanoDSF 熔解温度)与 Tagg(nanoDSF 背散射聚集起始温度)是实验地面真值;MD 代理量用轨迹分析指标 rmsd_last、rg_drift、盐桥占用率及斑块面积的系综 P95,只能做"最不稳 5% 排序"的近似,不能预测绝对温度值——风险表里该层置信度权重最低(示例 0.5×0.4)。
Q4:NetMHCIIpan-4.0 和 TepiTool 在批量免疫原性里各干什么?
A:NetMHCIIpan-4.0(Reynisson 2020,实测 2026-09-04 在线于 DTU 服务站)做单一 HLA-DR 等位基因的精配结合预测;TepiTool(Paul 2016,tools.iedb.org/tepitool)把多等位基因/类别结果聚成人群覆盖 consensus 百分位。批量用 consensus 保覆盖度,重点分子用前者复评;呈递≠应答,免疫列只做标记(权重 0.4、置信 0.5)。
Q5:多源分数怎么合成统一风险表,实验对照怎么用?
A:五步——方向归一(越安全越大)、批次内百分位(跨批不可比)、缺测中性化 0.5 并单独记 n_metrics、一票否决 + 计数投票出 A/B/C/D 层、有 AC-SINS/HIC 实测列时对相应计算列做 Spearman 排序一致性校准(n≥10 才做,|ρ|<0.5 先调权重再扩池,调权留痕)。