资讯动态

kegg-network-viewer:KGML通路图前端渲染与表达量着色实战

发布时间:2026/10/17 14:49:18 来源:尧图企业网站定制
简介KPV-KEGG PATHWAY VIEWER 是一套面向生物信息学与代谢通路研究者的在线可视化工具源码用于直观呈现 KEGG 代谢途径并支持交互操作。它依据 AP 检测算法对蛋白质进行分类帮助使用者快速识别网络中连接度最高的关键蛋白节点同时提供 KEGG 路径的动态 HTML 可视化可模拟节点去除、边缘添加等基本操作适合需要分析通路瓶颈与蛋白互作关系的中高级科研人员。资源以 zip 压缩包形式提供共 956 个文件约 62.01MB其中 JavaScript 脚本 211 个、PNG 图片 177 个、HTML 页面 167 个另有大量 Markdown 文档、CSS/LESS 样式表及 PHP 后端文件并附带少量 SQL、字体与图标素材构成完整的前后端项目结构。目前已有 1086 人学习下载。借助该源码读者可获取通路可视化实现逻辑、蛋白分类算法落地代码与可运行的交互式页面便于二次开发或嵌入自身研究流程。1. 从一张画不出的通路图说起kegg-network-viewer 能替你省掉哪几步做转录组或代谢组分析的人大概都经历过这个场景差异基因列表跑出来了富集分析也做完了KEGG 通路一条条列在表格里可真要把某条通路里的基因、化合物、酶之间的关系画成一张能放进报告或论文的图就开始犯难。官方 KGML 文件是 XML节点和边的关系藏在entry和relation标签里直接打开是一堆尖括号用通用网络图工具导入坐标全乱通路原本的生物学布局荡然无存。kegg-network-viewer 就是冲着这个痛点来的。它是一个基于 HTML 的可视化工具核心思路是把 KEGG 的 KGML 网络数据解析后在浏览器里还原成可交互的通路图。你不需要装 Cytoscape 那一整套桌面环境也不需要手写 D3 的力导向布局打开一个 HTML 页面、喂进数据节点、边、通路框就能按 KEGG 原本的空间关系渲染出来。适合的人群很明确做生信分析、需要批量出通路图的从业者以及想把 KEGG 网络嵌进自己网页应用的前端开发者。它解决的不是分析问题而是把已有分析结果画对、画快、画得能交互这一步。2. 拆开这个 HTML 工具KGML 解析与渲染链路2.1 为什么是 HTML 而不是桌面软件先讲选型理由这决定了你后面怎么用它。KEGG 通路图的本质是一张带坐标的矢量图每个基因产物、化合物、酶都有 KEGG 预先定义好的位置。桌面工具比如某些通路编辑软件的问题在于部署重、批处理难、不好嵌进 Web 报告。而纯前端方案的优势是零安装、跨平台、天然适合放进自动化流程——你完全可以在服务器端生成好 JSON前端 HTML 只负责渲染。kegg-network-viewer 走的就是这条路后端或脚本负责把 KGML 转成结构化数据前端 HTML 负责画。这样职责清晰也方便你在中间插入自己的逻辑比如按表达量给节点上色、按显著性给边加粗。常见做法是先用 Python 的Bio.KEGG.KGML模块解析 KGML导出成 JSON再交给 viewer 渲染。2.2 把 KGML 转成前端能吃的 JSONKGML 里最关键的两类元素是 entry节点和 relation边。entry 又分 gene、compound、map 等类型relation 描述节点之间的激活、抑制、结合等关系。下面这段脚本把一条通路的 KGML 解析成 viewer 需要的结构# parse_kgml.py # 依赖biopythonpip install biopython from Bio.KEGG.KGML.KGML_parser import read import json def kgml_to_json(kgml_path): pathway read(open(kgml_path)) nodes [] edges [] # 遍历 entry提取节点 id、名称、类型和图形坐标 for entry in pathway.entries.values(): graphics entry.graphics if graphics is None: continue nodes.append({ id: entry.id, name: entry.name, type: entry.type, # gene / compound / map 等 x: graphics.x, y: graphics.y, width: graphics.width, height: graphics.height, fgcolor: graphics.fgcolor, bgcolor: graphics.bgcolor }) # 遍历 relation提取边entry1 - entry2 及关系类型 for relation in pathway.relations: edges.append({ source: relation.entry1.id, target: relation.entry2.id, type: relation.type, # 如 activation / inhibition subtypes: [ {name: s.name, value: s.value} for s in relation.subtypes ] }) return {nodes: nodes, edges: edges} if __name__ __main__: data kgml_to_json(hsa00010.xml) with open(hsa00010.json, w) as f: json.dump(data, f, ensure_asciiFalse, indent2) print(fnodes{len(data[nodes])}, edges{len(data[edges])})逻辑说明read()把 KGML 解析成对象树pathway.entries是节点字典pathway.relations是边列表。参数上entry.type决定前端用什么形状画gene 画矩形、compound 画圆graphics.x/y是 KEGG 原始坐标务必保留否则布局会塌。relation.subtypes里常带value字段比如p表示磷酸化前端可以据此在边上加箭头或标签。跑完看输出的 nodes/edges 数量如果 edges 为 0多半是这条通路本身没有 relation 标签不是脚本错了。2.3 前端渲染坐标映射与交互绑定拿到 JSON 后前端要做两件事把 KEGG 坐标映射到画布尺寸以及给节点绑定交互。KEGG 坐标原点在左上角和 SVG/Canvas 一致所以基本不用翻转 Y 轴这是它比很多通用图数据省事的地方。下面是一个最小渲染骨架// render.js —— 假设用 D3 v7画布尺寸 1200x900 const svg d3.select(#canvas) .attr(viewBox, 0 0 1200 900); d3.json(hsa00010.json).then(data { // 1. 画边用 source/target 的坐标连线 const nodeMap new Map(data.nodes.map(n [n.id, n])); svg.selectAll(line.edge) .data(data.edges) .join(line) .attr(class, edge) .attr(x1, d nodeMap.get(d.source).x) .attr(y1, d nodeMap.get(d.source).y) .attr(x2, d nodeMap.get(d.target).x) .attr(y2, d nodeMap.get(d.target).y) .attr(stroke, #999) .attr(marker-end, url(#arrow)); // 2. 画节点矩形代表 gene圆代表 compound svg.selectAll(g.node) .data(data.nodes) .join(g) .attr(class, node) .attr(transform, d translate(${d.x},${d.y})) .each(function(d) { const g d3.select(this); if (d.type compound) { g.append(circle).attr(r, 8).attr(fill, d.bgcolor || #fff); } else { g.append(rect) .attr(x, -d.width / 2).attr(y, -d.height / 2) .attr(width, d.width).attr(height, d.height) .attr(fill, d.bgcolor || #fff) .attr(stroke, d.fgcolor || #000); } // 3. 绑定 tooltip鼠标悬停显示基因名 g.append(title).text(d.name); }); });逻辑说明viewBox设成和 KEGG 坐标同量级避免缩放失真。nodeMap是为了让边能快速查到端点坐标比每次遍历数组快。节点用g包一层再translate这样矩形和圆都能以坐标为中心绘制。title是最省事的 tooltip 方案不用引第三方库。参数上d.width/d.height直接来自 KGML别自己写死否则不同通路框大小对不上。如果图整体偏小调viewBox的宽高比即可不要改节点坐标。3. 接上自己的数据表达量着色与批量出图3.1 按表达量给节点上色光画出通路结构还不够实际分析里你要把差异表达信息叠上去。思路很简单在 JSON 里给每个 gene 节点加一个log2FC字段前端按值映射颜色。下面是在解析阶段合并表达量的做法# merge_expression.py import json def merge_fc(node_json, fc_table): fc_table: {gene_symbol: log2FC} with open(node_json) as f: data json.load(f) for node in data[nodes]: # KGML 的 name 可能是 hsa:1234 或 cpd:C00031 形式 symbol node[name].split(:)[-1] node[log2FC] fc_table.get(symbol, None) return data # 前端按 log2FC 映射红蓝渐变 # d3.scaleLinear().domain([-2, 0, 2]).range([#2166ac, #f7f7f7, #b2182b])逻辑说明name.split(:)[-1]是为了剥掉hsa:前缀拿到纯 ID但注意 KEGG 的 gene ID 和你表达矩阵里的基因名可能不是一套命名常见做法是先用 ID 映射表转一道。fc_table.get(symbol, None)给没匹配上的节点留空前端遇到 None 就用默认灰色避免整张图因为几个缺失值崩掉。颜色映射用发散色阶0 值居中这是表达量可视化的惯例。3.2 批量处理多条通路单条通路手动跑没问题但富集分析动辄几十条通路必须批量化。下面这个循环把目录下所有 KGML 一次性转成 JSON# batch_convert.sh for kgml in ./kgml/*.xml; do base$(basename $kgml .xml) python parse_kgml.py $kgml ./json/${base}.json echo done: $base done逻辑说明basename ... .xml去掉扩展名作为输出名保证一一对应。如果某条通路解析报错脚本会中断建议加|| echo fail: $base容错。批量出图后前端可以用一个下拉框切换通路或者干脆生成多个 HTML 页面。参数上注意 KGML 文件命名通常是hsaXXXXX.xml保持这个命名能让前端按通路 ID 索引。提示KEGG 的 KGML 文件需要从官方渠道获取不同物种前缀不同hsa 人、mmu 鼠、ath 拟南芥等批量下载时注意区分别把物种搞混。4. 避坑与排查那些让我重画三次的细节4.1 节点重叠成一团现象渲染出来节点全挤在左上角或者互相压在一起。原因KGML 里部分 entry 的 graphics 坐标是相对某个 map 框的不是全局坐标直接当绝对坐标用就会错位。解决检查 entry 是否有map类型的父节点如果有需要把子节点坐标加上父框的偏移量。常见做法是先画 map 框再按层级累加坐标。4.2 边画出来了但方向不对现象箭头指向反了或者激活/抑制关系分不清。原因KGML 的 relation 里entry1和entry2的方向语义要结合 subtype 看有些关系是双向的。解决解析时把subtypes里的name读出来activation画实线箭头inhibition画 T 形端别一律用同一种线型。4.3 中文基因名显示成方块现象tooltip 或节点标签里的中文变成乱码。原因HTML 页面没声明 UTF-8或者 JSON 导出时没加ensure_asciiFalse。解决HTML 头部加meta charsetutf-8Python 导出时显式指定编码两个地方都要改只改一个照样翻车。4.4 大通路渲染卡顿现象节点超过 500 个时页面明显掉帧。原因每个节点都绑了独立的 DOM 事件和 tooltip。解决改用事件委托把鼠标事件绑在 SVG 根节点上通过event.target判断是哪个节点或者对非重点节点延迟渲染。这是前端性能的通用套路不是这个工具特有的问题。4.5 坐标缩放后线宽跟着变现象放大画布后边变得特别粗或特别细。原因用了viewBox缩放但没设vector-effect。解决给边加vector-effectnon-scaling-stroke让线宽不随缩放变化节点大小则按需保留缩放。5. 进阶把 viewer 嵌进自己的报告页并做联动走到这一步你已经能出单张通路图了。但真正提升效率的用法是把它嵌进自动化报告和富集结果表格联动。我的习惯是报告左侧放通路列表点击某条通路右侧 iframe 或 div 里加载对应的 viewer 页面同时把该通路的差异基因高亮。实现上viewer 页面暴露一个全局函数接收基因列表并给对应节点加高亮 class// 在 render.js 末尾暴露接口 window.highlightGenes function(geneIds) { svg.selectAll(g.node) .classed(highlight, d geneIds.includes(d.name.split(:)[-1])) .classed(dim, d !geneIds.includes(d.name.split(:)[-1])); };配套 CSS 里.highlight加粗描边.dim降透明度到 0.3。这样报告页只要iframe.contentWindow.highlightGenes([...])就能联动。参数上geneIds用你表达矩阵里的命名和解析阶段保持一致否则匹配不上。验证方法很直接拿一条你熟悉的通路比如糖酵解手动数一下节点数和脚本输出的 nodes 数量对一遍再挑几个已知有调控关系的基因看边有没有画出来。对不上就回到第 2 章的解析脚本查 entry 和 relation 的遍历逻辑。最后说个血泪经验我早期图省事直接把 KGML 里的坐标当像素用结果换一台分辨率不同的机器图就糊了。从那以后我每次做可视化都强制走一遍坐标归一化 viewBox 自适应的流程再也不敢偷懒。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑