ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

生物大分子批量仿真开发教程(4):第一块地基——序列、编号体系与抗体结构标准

生物大分子批量仿真开发教程(4):第一块地基——序列、编号体系与抗体结构标准 生物大分子批量仿真开发教程4第一块地基——序列、编号体系与抗体结构标准版本声明块工具/软件ANARCIBioinformatics 2016Dunbar Deane、SAbDab / Thera-SAbDab牛津 OPIG、OASObserved Antibody Space、IMGT、PDBRCSB、BioPhimAbs 2022语言/环境Python 3.10 pandas、bash、FASTA / TSV本文目标在你的流水线写下第一个残基号之前先把编号从哪来、谁说了算这件事一次性解决一句话结论抗体批量仿真里A:26、H:228、Asn297、CDR-H3这些写法的含义完全由编号体系numbering scheme决定而 PDB 文件里的残基号往往是 author numbering——因此必须先用 ANARCI 批量标注成一套选定体系Kabat / Chothia / IMGT / Martin / AHo 五选一并把体系名写进元数据铁律 1否则后续的突变命名、CDR 定义、对接盒与结果比对全部失去可比性。〇、本篇要解决的认知问题一颗免疫球蛋白 GIgG的结构里批量仿真必须先锁定哪几个坐标VH、VL、CDR-H1/2/3、Fc 分别管什么为什么不能直接用 PDB 文件里写着的残基号而要先固定编号体系Kabat、Chothia、IMGT、MartinEnhanced Chothia、AHo 这五套体系差别在哪我的项目该选哪一套上万条抗体序列怎么批量打编号ANARCI 命令行怎么组织、结果怎么落表SAbDab、OAS、IMGT、PDB 的数据分别从哪拿、各自用来干什么、合规与引用要注意什么一、机制解析1.1 先把 IgG 画清楚批量仿真的所有名词都落在这张图上抗原结合片段 Fab Fab ┌──────────────────────┐ ┌──────────────────────┐ │ VH ── CH1 ─┐ │ │ ┌─ CH1 ─ VH │ │ │ │ │ │ │ │ │ │ VL ── CL ──┴ hinge ─┴──────────┴─ hinge ┴─ CL │ VL │ └───────────────────┬──────────────────────────────┘ │ ┌────┴─────┐ │ CH2 │ ← Asn297 N-糖链糖型 G0F/G1F/G2F、唾液酸化 │ CH3 │ ← 双抗 KiH / CrossMab 界面改造发生在这里 └──────────┘ Fc可 crystallizable fragment结构元件全称/中文在你的流水线里意味着重链 / 轻链heavy chain / light chain两条不同的 molecule第 02 篇任何整体算一个域的假设都会错VH / VL重链/轻链可变区结合面的主体突变枚举的主要战场CDR-H1 / H2 / H3互补决定区complementarity determining region边界由编号体系定义不是由字符串下标定义H3 最长最不规则建模最难第 07 篇框架区framework, FRframework region人源化时的回突变back-mutation对象BioPhi 在此打分FcCH2CH3可结晶片段效应功能与 FcγR 结合双抗异源二聚化改造位点Asn297CH2 天冬酰胺 N-糖基化位点铁律 9不建糖构象与聚集结论不可信为什么这对你重要可开发性developability指标里聚集倾向aggregation propensity与表面疏水斑块大量落在 CH2/CH3 界面与 CDR 环上你把 Fc 当背景结构随便处理就等于给最终排序引入了系统性偏差。1.2 铁律 1 的机制残基号是外键不是常量写死残基号在批量流水线里属于引用一个没有 schema 的外键。它至少被三件事决定来源PDB 条目里的号往往是作者编号author numbering可能是 sequential 重排、可能按 Kabat、可能按 IMGT取决于当年谁解析的。体系规则不同体系对插入/缺失的处理不同——有的允许带字母的插入位点Kabatype 编号里常见有的用固定列数强制对齐IMGT 风格。同一残基在两套体系下差 1~3 号是常态。计算边界CDR 环的起止由体系定义同一个环用 Kabat 和用 IMGT 截出来的序列长度不同于是 CDR-H3 长度分布、移植边界、对接盒中心全都不一样。由此推出三条工程结论a编号体系名必须作为字段随结构落盘而不是写在 README 里b残基号字段应该用字符串类型存储第 02 篇的s_前缀规约因为带字母的插入位点会直接把整数列撑爆c一切下游突变表、对接约束、MM-GBSA 残基扫描的残基清单都必须引用同一套体系混用即作废。顺带一条来自 MOE 的旁证MOE 2024.06 的 Pro:Pro Dock 会自动选择抗体作为配体、抗原作为受体并支持$CDR_H3自动注释该版本发行说明——也就是说商业工具能自动化的前提同样是结构里已经带着正确的抗体编号与 CDR 注释。1.3 五套编号体系谱系与选择体系依据锚文献机制特点谁最认它选它的理由KabatWu Kabat, 1970 J Exp Med基于序列可变性统计最早被广泛使用老文献、治疗抗体命名如 Asn297 语境常用与历史数据/专利权利要求对齐ChothiaChothia 等1985 J Mol Biol基于结构比对与环长度规则结构建模、环分类环边界更贴合三维构象IMGT unique numberingLefranc et al., 2003固定列式对齐空位保留规则统一IMGT 数据库体系、NGS 生态跨物种/跨链一致性与可自动化MartinEnhanced ChothiaAbhinandan Martin, 2008 Mol Immunol对 Chothia 环规则的改进版ANARCI 提供该选项序列-结构折中鲁棒性好AHoANARCI 支持的第五套方案原始出处本系列未核实请查 ANARCI 文档面向任意免疫球蛋白超家族可变域的跨物种统一编号非典型格式、单域抗体研究单域/嵌合也能对齐具体每条 gap/插入规则的权威表述请以 IMGT 官网与 ANARCI 文档核对本表只用于选型决策。选择原则很实际与团队既有数据和文献命名一致优先如果从零开始且要跑 NGS 大库IMGT 式固定列最省心要和结构环构象库挂钩Chothia/Martin 更合适。定了以后写进配置全系列不再改。为什么这对你重要换体系等于换数据库主键。你今年用 Kabat 存了 8000 条打分明年改用 IMGT这 8000 条不会因为换算而复活——它们只能重算。所以体系是立项时的一次性决策不是随手可换的显示格式。1.4 ANARCI把五套体系一次算出来ANARCIAntibody Numbering and Receptor Class Identification用序列比对/隐马尔可夫模型给抗体与 T 细胞受体的可变量区V domain打编号一次运行即可选定 Kabat / Chothia / IMGT / Martin / AHo 之一是 OPIG 生态SAbDab、SabPred的组成部分开源仓库https://github.com/oxpig/ANARCI也有 Web 入口https://opig.stats.ox.ac.uk/webapps/sabdab-sabpred/sabpred/anarci/。FASTA每行一条链序列头唯一 │ anarci --fatty in.fasta --numbering chothia ▼ 输出目录对齐/编号结果 链类型与物种归属assignment │ 解析 ▼ 元数据表chain, scheme, cdr_start, cdr_end, mutation_ready1 ← 流水线的外键表批量场景下有三条经验法则按链拆分 FASTA一条序列只放一个 V 域混链会污染归属判断分块提交大列表按 chunk 切便于失败重跑与并行一次跑多套体系先用chothia建主表再按需补imgt两套结果并存但主键只认一套。为什么这对你重要编号是唯一能把序列空间与结构空间连起来的键。没有批量标注这一步你手里的万条序列只是字符串既不能说改 Kabat H57 处的酪氨酸也不能把某条序列的预测分数追回它的结构模板。1.5 数据源谱系与合规数据源内容在本系列里的用途入口SAbDabStructural Antibody Database已解析抗体结构及其元数据链序列、CDR、编号、抗原、开发来源模板库、对接复合物、编号一致性基准…/webapps/sabdab-sabpred/sabdab/about新版 SAbDab2https://sabdab.opig.stats.ox.ac.uk/Thera-SAbDab治疗性抗体子库临床阶段、商品名、格式真实世界的可开发性对照集同上站的 therasabdab 路径OASObserved Antibody SpaceNGS 免疫组库序列去重计数万级变体采样、人性化频率基准BioPhi 的 OASis 训练基础https://opig.stats.ox.ac.uk/webapps/oas/文档见同站/documentationIMGT免疫遗传学参考基因/等位基因与标准编号基因分型germline assignment、IMGT 编号权威定义https://www.imgt.org/PDB所有实验结构抗原结构、复合物模板https://www.rcsb.org/BioPhiSapiens 人源化 OASis 人性化打分Merck 出品MIT 许可人源化位点建议与排序第 06、13 篇https://biophi.dichlab.org/、https://github.com/kvetab/BioPhi合规三件事引用义务用 SAbDab/OAS/IMGT 数据发文章或内训教材时按各站要求引用SAbDab 锚文献 Dunbar 2014 NAR 42:D1140OAS 锚 Kovaltsuk 2018 J Immunol 201:2502许可边界PDB 条目本身公共领域但衍生数据表与商业库另论IMGT 部分资源需注册可追溯下载时间、文件 URL、行数一起写进你的元数据表这是铁律 8 的服务器现状必须有实测日期在数据获取侧的体现——本系列实测日期为 2026-09-04。为什么这对你重要公开库不是免费且永远在的代名词。你的流水线如果直接联网取数服务器改版或迁移的那天就是全量重跑的那天把数据落到本地并记下来源与日期等于给流水线买了一份可复现保险。二、完整代码与逐行剖析2.1 ANARCI 命令行批量打编号#!/usr/bin/env bash# anarci_batch.sh —— 分块 多体系标注 运行留痕set-euopipefailSCHEMEchothia# 主编号体系全项目只认这一个铁律 1IN_FASTA$1# 输入每行一条 V 域序列FASTA 头必须唯一OUTanarci/${SCHEME}mkdir-p$OUT# 一条序列含两个 V 域会让链归属判断变脏这里硬性提醒而不是静默通过awk/^/{n; next} {len[n]length($0)} END{for(i1;in;i) if(len[i]130) print WARN 序列 #i 长度 len[i] 130aa疑似多域拼接}$IN_FASTA# 长选项名在不同发行版略有差异正式使用前请用 anarci -h 与官方 README 复核split-l2000$IN_FASTA$OUT/chunk_--additional-suffix.fasta# 分块便于并行与只补缺forfin$OUT/chunk_*.fasta;dotag$(basename$f.fasta)anarci--fatty$f\--output-dir$OUT/$tag\--outfile-prefix$tag\--numbering$SCHEME\$OUT/$tag.log21||echoFAIL$tag# 失败不中断整批但要留痕铁律 10done# 留痕软件版本 体系 输入行数写进 sidecar 供审计{anarci--version2/dev/null||echoanarci version unknown;\echoscheme$SCHEME;echoinput_records$(grep-c^$IN_FASTA);\echorun_at$(date-Is);}$OUT/run_manifest.txt写法为什么这样写分块 2000 条ANARCI 是 CPU 密集且偶发单条卡住分块后失败只损失一个 chunk|| echo FAIL $tag批量分析器最忌一条坏序列让整批退出但绝不能不记录sidecar manifest半年后你需要能回答这批 CDR 边界是哪版 ANARCI、哪套体系算出来的2.2 解析 ANARCI 结果 → 编号契约表#!/usr/bin/env python3build_numbering_ledger.py —— 把 ANARCI 输出压成一张外键表下游只读它 ANARCI 的产物文件名与列对齐方式随发行版略有差异常见为 *.numberings / *.assignments 形态 请先用 anarci -h 与官方 README 确认你这一版再按需调整下面的 glob 与解析规则。importglob,json,os,reimportpandasaspd SCHEMEchothia# 与 2.1 完全一致不一致直接拒绝别硬拼OUT_DIRanarci/chothia# CDR 区间由编号体系决定而不是由下标决定1.2所以边界必须来自该体系的权威表# 请从 IMGT 官网 / ANARCI 文档抄录你所选体系的区间填进 cdr_bounds.json本教程不写死数值CDR_BOUNDSjson.load(open(cdr_bounds.json,encodingutf-8))# {CDR-H1: [27,38], ...}SEQ_REre.compile(r^[\sACDEFGHIKLMNPQRSTVWY\-]$)# 序列行氨基酸单字母 空位 -NUM_REre.compile(r^[\s\dA-Z*\-]$)# 编号行数字、空位、可能的字母后缀defparse_record(head:str,seq_line:str,num_line:str)-dict:把一对上下对齐的行折叠成 {序号: 编号} 映射。 为什么按列 zip 而不是 split编号行里空位与插入位点会破坏 token 数对齐 只有按字符列对齐才与序列行严格一一对应。s,nseq_line.replace( ,),num_line.replace( ,)pairs[(a,b)fora,binzip(s,n)ifa!-]# 丢弃对齐空位保留真实残基nums[bfor_,binpairs]return{query:head,n_residues:len(pairs),first_num:nums[0]ifnumselse,last_num:nums[-1]ifnumselse,# 为什么编号存字符串带插入位点的体系会出现非数字后缀整数列会直接崩1.2 结论 bhas_insertion:any(ch.isalpha()forxinnumsforchinx),numbers:json.dumps(nums)}# 整条编号序列下游按号取残基defparse_numberings_file(path:str):head,seq,num,outNone,None,None,[]forlineinopen(path,encodingutf-8):lineline.rstrip(\n)ifline.startswith():ifheadandseqandnum:out.append(parse_record(head,seq,num))head,seq,numline[1:].split(:)[0],None,None# 记录头里的 query idelifSEQ_RE.match(line)andseqisNone:seqline.strip()elifNUM_RE.match(line)andany(c.isdigit()forcinline):numline.strip()ifheadandseqandnum:out.append(parse_record(head,seq,num))returnout rows[]forfinsorted(glob.glob(os.path.join(OUT_DIR,*,*.numberings))):rows.extend(parse_numberings_file(f))dfpd.DataFrame(rows)df[scheme]SCHEME# 只保留成功标注的无编号 可变量区识别失败必须显式落库而不是悄悄消失铁律 10df[numbering_ok]df[n_residues].fillna(0)0# CDR 覆盖检查用编号是否存在于该链的编号序列判定而不是用下标切片# 下标切片在有空位/插入位点的体系下必然错位defcovers(nums_json,lo,hi):numsset(json.loads(nums_json))returnint(str(lo)innumsandstr(hi)innums)forname,(lo,hi)inCDR_BOUNDS.items():df[fcover_{name}]df[numbers].map(lambdax,lolo,hihi:covers(x,lo,hi))df.to_csv(numbering_ledger.csv,indexFalse)assertdf[scheme].nunique(dropnaTrue)1,编号体系混用整批作废print(fledger rows{len(df)}scheme{SCHEME}ok{int(df[numbering_ok].sum())})这张numbering_ledger.csv就是流水线的外键表第 05 篇的结构准备、第 06 篇的突变枚举、第 09 篇的对接盒全部以query scheme为主键回查它。关键决策是断言编号体系唯一值 ≤ 1——一个批次里出现两套体系等于该批结果不可比宁可停机。2.3 SAbDab 元数据下载与采样#!/usr/bin/env python3sabdab_sample.py —— 取结构抗体库元数据按可开发性对照需求采样 SAbDab 的下载文件清单与确切 URL 以站点 Download/About 页为准实测日期 2026-09-04 https://opig.stats.ox.ac.uk/webapps/sabdab-sabpred/sabdab/about 本脚本接受一个本地 TSV 路径你手工下载后传入避免把 URL 写死在代码里。importsysimportpandasaspd tsvsys.argv[1]dfpd.read_csv(tsv,sep\t,dtypestr)# SAbDab 列名各版有出入这里用候选名解析而不是硬编码找不到就打印实际列名让你填defcol(cands):forcincands:ifcindf.columns:returncraiseKeyError(f缺列候选{cands}实际列名{list(df.columns)[:20]})cidcol([sabdab_id,pdb,pdb_id])spcol([species,organism])isocol([isotype,constant_region])h3col([cdrh3_length,H3_length])seq_ccol([h_seq,H_sequence,vh_seq])keepdf[[cid,sp,iso,h3,seq_c]].copy()keep.columns[sabdab_id,species,isotype,cdrh3_len,vh_seq]# 采样规则经验法则只留人源/人源化、完整 IgG 亚型、CDR-H3 长度非缺失keepkeep[keep[species].fillna().str.contains(human,caseFalse)]keepkeep[keep[isotype].notna()keep[cdrh3_len].notna()]keep[cdrh3_len]keep[cdrh3_len].astype(int)keepkeep[(keep[cdrh3_len]5)(keep[cdrh3_len]30)]# 极端长度单独走第 07 篇建模# 数据溯源列铁律 8来源、下载日期、引用锚文献一起写进结果keep[source]SAbDabkeep[downloaded]2026-09-04keep[citation]Dunbar et al. 2014 NAR 42:D1140keep.to_csv(sabdab_subset.csv,indexFalse)# 同时导出 FASTA 给 2.1 的 ANARCI 用头用 sabdab_id保证唯一withopen(sabdab_subset.fasta,w,encodingutf-8)asfh:forrinkeep.itertuples():fh.write(f{r.sabdab_id}_H\n{r.vh_seq}\n)print(fsampled{len(keep)}- sabdab_subset.csv / .fasta)如果要做 NGS 级序列空间而不是结构空间采样把数据源换成 OAS它提供按物种/亚型/基因过滤后的下载量级远大于 SAbDab用途是万级变体的可开发性扫描第 17 篇而 Thera-SAbDab 提供治疗性抗体子库用来做已上市分子的性质分布参照最合适的基线。三、常见报错与排查ANARCI 输出为空或把序列判成 non-antibody根因输入序列不是单一可变量区scFv / 双抗单链 / 含信号肽 / 纳米抗体单域或 FASTA 头重复导致结果覆盖。解法拆链、去信号肽、保证头唯一单域/非典型格式改用 AHo 体系并复核归属Web 版可用来单条交叉验证。同一抗体在 PDB 里是 27 号、在文献里是 26 号Kabat根因author numbering ≠ Kabat。解法不要相信文件里的号一律 ANARCI 重标并写回元数据scheme列 s_user_numbering_scheme属性第 02 篇。CDR-H3 长度在两个项目里数字不一样根因边界定义不同Kabat 与 IMGT 的 CDR-H3 起止规则本就不同。解法同一项目内只允许一套体系跨项目比较必须重算不能换算。把残基号存成 int 之后脚本报ValueError根因编号体系允许带字母的插入位点。解法所有编号字段用字符串第 02 篇的s_类型需要排序时另存一个数值化的排序键。人源化后原来的位点编号对不上了根因以序列下标当编号。解法改用编号体系做主键IMGT 固定列或 Chothia/Martin下标只用于渲染。数据站打不开或文件路径变了根因在线服务器状态会变本系列实测 2026-09-04SAbDab/OAS/IMGT/BioPhi 在线同类风险案例是 AGGRESCAN 原地址失效、A3D/A4D 迁至biocomp.chem.uw.edu.pl。解法铁律 8——下载即落本地副本 记录 URL 与日期代码只读本地路径。四、动手练习体系差异可视化挑一条你熟悉的抗体 VH用 ANARCI 分别跑chothia与imgt导出两套编号并排表。判定标准能明确指出两套体系下 CDR-H3 起止号各是多少且两列差值不为 0若全为 0说明你的标注根本没生效。外键表建成跑通 2.2生成numbering_ledger.csv。判定标准scheme列唯一值个数为 1numbering_ok为真的行数 ≥ 输入序列数的 80%不足 80% 时你必须列出失败原因分类而不是删掉失败行。可复现取数下载 SAbDab 元数据并用 2.3 采样。判定标准输出文件里source、downloaded、citation三列全部非空且重新执行一次得到相同的行数哈希一致。五、小结与下一篇预告编号体系是抗体批量仿真的第一块地基CDR-H3、Asn297、A:26这些标识只有在指定了体系之后才有意义因此体系名必须像主键一样随结构文件与结果表落盘铁律 1。ANARCI 负责把五套体系一次性算出来SAbDab / OAS / IMGT / PDB 分别提供结构模板、序列空间、参考基因与实验结构取数必须带日期与引用。地基有了下一篇开始动手把原始结构变成能跑仿真的模型Protein Preparation 与structconvert、MOE 侧的质化与修复、氢/互变异构/二硫键/Fc Asn297 糖基化以及 Schrödinger 2026-3 起 Prep 命令行重构与impref弃用会给你的老脚本带来什么破坏。本篇认知问题回显FAQQ1抗体结构里 VH、VL、CDR-H1/2/3、Fc 在批量仿真中分别承担什么角色A重链/轻链各是一个独立 moleculeVH/VL 是结合面主体与突变枚举主战场CDR-H1/H2/H3 的边界由编号体系定义H3 最长最难建模框架区是人源化回突变对象Fc 由 CH2CH3 组成CH2 上的 Asn297 带 N-糖G0F/G1F/G2F、唾液酸化影响 FcγR/ADCC/CDCCH3 是双抗异源二聚化改造位点。铁律 9 要求糖基化与二硫键必须建模。Q2为什么批量仿真前必须先固定残基编号体系APDB 文件里的号常是作者编号author numbering与 Kabat/IMGT 常差 1~3 号CDR 起止、突变命名如 Asn297、对接盒与残基扫描清单都以编号为外键。体系不固定则跨变体分数不可比。对策用 ANARCI 统一标注、体系名写入元数据字段编号字段用字符串存可能有带字母的插入位点。Q3Kabat、Chothia、IMGT、Martin、AHo 编号体系有什么区别该选哪个AKabatWu Kabat 1970基于序列可变性历史文献与治疗抗体命名常用Chothia1985 J Mol Biol基于结构比对与环长度IMGT unique numberingLefranc 2003固定列、空位保留适合 NGS 大库与自动化Martin/Enhanced Chothia2008 Mol Immunol改进环规则、鲁棒性好AHo 面向任意免疫球蛋白超家族可变域适合单域/非典型格式。原则与既有数据一致优先从零开始跑大库选 IMGT定了就写进配置不再改。Q4ANARCI 怎么批量给抗体序列打编号Aanarci --fatty in.fasta --output-dir out --outfile-prefix prefix --numbering chothia长选项名请以anarci -h与官方仓库 README 复核。工程要点一条 FASTA 记录只放一个 V 域、每 2000 条切一个 chunk 便于并行与只补缺、单条失败不中断整批但必须留痕、把 ANARCI 版本/体系/输入行数写进 sidecar manifest。Web 版在opig.stats.ox.ac.uk/webapps/sabdab-sabpred/sabpred/anarci/。Q5SAbDab、OAS、IMGT、PDB 的抗体数据怎么获取有哪些合规注意点ASAbDabopig.stats.ox.ac.uk/webapps/sabdab-sabpred/sabdab/about新版sabdab.opig.stats.ox.ac.uk给结构元数据Thera-SAbDab 是治疗性子库OASopig.stats.ox.ac.uk/webapps/oas/给 NGS 序列空间IMGTimgt.org给参考基因与编号权威定义部分资源需注册PDBrcsb.org给抗原与复合物。三件事必做按各站要求引用如 Dunbar 2014 NAR 42:D1140、Kovaltsuk 2018 J Immunol 201:2502、区分条目公共领域与衍生库许可、下载时记录 URL 与日期并保留本地副本。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进