做生信最怕的不是没数据,而是好不容易拿到一批差异基因,却卡在“怎么从基因列表变成通路解释”这一步。手动去数据库一个个查,效率低不说,还容易漏;想写脚本又发现编程基础不够。今年我最大的体会是:只要把需求描述清楚,这些工具完全可以交给 Codex 这类 AI 编程助手去生成。这篇文章会完整记录我如何零基础起步,用 Codex 配合生信数据库,自制一个可复用的富集分析工具,从环境配置、原理讲解到代码实现和踩坑排查都覆盖到。如果你是非科班的生信学习者,或者想做分析工具但被编程卡住,这篇应该能帮你省下不少时间。
1. 生信富集分析到底在做什么
1.1 什么是富集分析
富集分析是组学数据中最常用的解释手段之一。拿到一批差异表达基因后,单个基因很难讲清楚生物学意义,但如果几十个基因同时落在同一条代谢通路或同一个生物学过程里,结论就可靠得多。富集分析做的就是这个事情:把基因列表映射到已知的 GO(Gene Ontology,基因本体)功能条目或 KEGG(Kyoto Encyclopedia of Genes and Genomes,京都基因与基因组百科全书)通路上,再看哪些功能或通路被“富集”了。
富集分析有许多实现方式,常见的有:
- ORA(Over-Representation Analysis,过表达分析):把基因列表看成样本,用超几何分布检验某个通路中的基因是否在列表中显著富集。
- GSEA(Gene Set Enrichment Analysis,基因集富集分析):不需要先设定差异基因阈值,直接用全部基因的表达排序分析。
- 模块/网络分析:基于共表达网络或蛋白互作网络寻找功能模块。
本文要做的工具属于第一类 ORA,最典型的应用就是:
- 输入一个差异基因列表;
- 自动查询 GO/KEGG 注释;
- 计算每个通路的富集显著性和富集倍数;
- 输出排序后的结果表格和可视化图表。
1.2 为什么零基础也能自己写生信工具
过去做富集分析,主流方案是在 R 里用 clusterProfiler。R 语言本身对非科班同学就不太友好,更不用说安装 Bioconductor 依赖、处理 OrgDb 注释包这类操作。很多初学者在“装包”这一步就放弃了。
而 Python 生态下的生信工具链已经相当成熟。pandas处理表格、scipy做统计检验、gseapy封装了 Enrichr 数据库和 GSEA 算法,整个流程可以非常简洁。即使不懂统计公式,也能写出能用的脚本。
更关键的是,Codex 这类 AI 编程工具根本上改变了学习路径。以前写脚本需要先学习语法、函数、数据结构,现在只需要把你的需求、输入输出格式、运行环境描述清楚,Codex 就能生成相当完整的代码。你不需要把所有 API 记住,只需要会“提出需求”和“检查结果”。
1.3 Codex 能让工具开发变得多简单
Codex 是 OpenAI 推出的 AI 编程代理,它不只会生成一段代码,还能理解你在终端、编辑器和浏览器里的完整任务。你可以让它读取文件、执行命令、修改代码、根据报错信息自行修复,更像一个“会写代码的协作者”。
在实际的生信场景里,我用 Codex 做的事包括:
- 读取差异基因 Excel 表,自动清洗和格式转换;
- 调用 Enrichr 接口做 GO/KEGG 富集分析;
- 把结果画成可发表的柱状图和气泡图;
- 写一个命令行工具,以后换一批基因也能直接跑。
这就是“自制富集分析工具”的本质:不是从零研究算法,而是把成熟的统计方法和数据库封装成好用的小工具。
2. 环境准备:安装并配置 Codex
2.1 先分清楚 Codex CLI、桌面版与 VSCode 插件
网上搜“Codex 安装”,会看到很多不同名字,新手很容易混淆。简单区分一下:
- Codex CLI:命令行工具,在终端里使用,适合自动化操作,也是很多教程默认的安装方式。
- Codex 桌面版:带图形界面的应用,适合不想碰命令行的用户,界面更接近聊天工具。
- Codex VSCode 插件:集成在 VSCode 编辑器里,写生信脚本时可以直接在编辑器里让 AI 改代码,体验很顺滑。
我的建议是:如果只为了跑通“富集分析工具”,优先装 CLI;如果以后长期要在编辑器里做数据分析,可以装 VSCode 插件。两者可以共存,不冲突。
2.2 安装 Codex CLI
Codex CLI 本质上是一个 Node.js 应用,所以安装前需要确认本机有 Node.js 环境。不同系统命令稍有差异,但思路一致。
macOS 或 Linux 用户如果安装了 Homebrew,可以直接在终端执行:
brew install codex如果想用 npm 安装,官方推荐的方式是:
npm install -g @openai/codexWindows 用户更建议先安装 Node.js LTS 版本,然后同样使用 npm 全局安装:
npm install -g @openai/codex安装完成后,用下面的命令确认版本:
codex --version如果提示找不到命令,通常是把 npm 全局目录加入了环境变量。这一步比较常见,不同系统配置方式不同,可以在终端里执行npm root -g找到全局目录后按系统环境变量说明添加。
需要说明的是,Node.js 与 Codex 版本更新都比较快,这里不建议写死某个版本号,以你实际安装时的官方说明为准。
2.3 使用 API 网关接入第三方模型
Codex 默认连接的是 OpenAI 官方端点,但很多人会遇到账号、付费或可用性问题。这时候社区常见的做法是:使用cc switch这类 API 切换与本地路由配置工具,把 Codex 的请求转发到其他兼容端点。
cc switch本身是一个配置工具,核心作用是把 Codex 默认请求路径替换为你自定义的API Base URL和模型名。比如你想用 DeepSeek 的兼容接口,大致思路是:
- 安装并打开
cc switch; - 添加一个新的 Provider,填写接口地址、API Key、模型名称;
- 在 Codex 配置中指向
cc switch的本地服务地址; - 保存配置后重启 Codex。
这里不展开细讲某个工具的私有配置界面,因为它升级很快,界面变化也大。但有一点是通用的:你换任何第三方端点,都要确认它是否兼容 OpenAI 的请求/响应格式,特别要关注是否支持流式输出、是否支持 reasoning 内容回传。后面第 5 节会专门讲相关报错。
2.4 验证 Codex 是否能正常对话
配置完成后,先做一次最简单测试,在终端里输入:
codex或者在 Codex 里发送:
请用中文回复,并告诉我你现在可用的模型名称。如果正常,Codex 会返回可用的模型信息。如果出现connection failed、error sending request、一直重新连接,按第 5 节的排查方法处理。
验证通过后,可以继续准备 Python 环境。
3. 富集分析工具背后的统计学原理
很多教程一上来就让用户跑代码,但我觉得富集分析工具和其他脚本不一样:如果不理解统计原理,结果输出后你根本不知道该怎么解读。这里用尽量通俗的方式拆解。
3.1 从“基因列表”到“通路富集”
假设数据库里有 10000 个人类基因,其中某条 KEGG 通路包含 200 个基因。你手里有 500 个差异基因,其中有 40 个属于这条通路。
表面上看,40/500 的占比是 8%,而全基因组中该通路的占比是 200/10000 = 2%。8% 明显高于 2%,但问题是:这个差异是真实的还是随机造成的?
富集分析的统计检验回答的就是这个问题。
3.2 超几何分布与 Fisher 精确检验
超几何分布适合描述“不放回抽样”的场景。在富集分析里,我们可以这样对照:
| 概念 | 含义 |
|---|---|
| 全部基因总数 | 背景基因总数,比如所有被检测到的基因数 |
| 通路基因数 | 属于某个 GO/KEGG 条目的基因数 |
| 差异基因总数 | 你输入待分析的基因数 |
| 通路中的差异基因数 | 差异基因里落在该通路上的数量 |
Fisher 精确检验基于超几何分布,计算“当前这种重合程度或更极端情况出现的概率”,得到的p-value就是富集显著性。
如果再算一个富集倍数(Fold Enrichment),公式大致是:
富集倍数 = (通路中的差异基因数 / 差异基因总数) / (通路基因数 / 背景基因总数)富集倍数越大,表示该通路在基因列表中的比例相对背景越突出。
3.3 多重检验校正:为什么看 adjusted p-value
一个基因列表通常会同时检验几百上千条通路。假设显著阈值是 0.05,检验 1000 条通路时,即使全部都是随机,也可能有大约 50 条因为偶然因素“显著”。
所以要引入多重检验校正。最常用的是:
- BH(Benjamini-Hochberg)校正,控制错误发现率(FDR);
- Bonferroni 校正,更严格,适合通路数少的情况。
绝大多数富集分析工具结果里的Adjusted P-value或FDR,用的就是 BH 校正思路。理解这一点非常重要,因为:
- 筛选时优先看
Adjusted P-value,而不是原始p-value; - 如果
Adjusted P-value大于 0.05,不要强行解释为显著; - 如果通路数特别多,可以适当放宽到 0.25 做为筛选条件,但要在文章里说明。
4. 用 Codex 自制富集分析工具
4.1 写清需求:提示词比代码更重要
让 Codex 写代码前,先把需求描述清楚。我习惯把提示词拆成下面几个部分:
- 角色设定:告诉 Codex 你是生信工程师,方便它使用专业术语。
- 任务描述:要做什么分析,输入是什么,输出是什么。
- 技术约束:用 Python,使用 gseapy,命令行工具,兼容常见操作系统。
- 功能细节:去重、过滤、排序、画图、输出格式。
- 异常处理要求:文件不存在、基因名无效、网络超时都要有提示。
下面是一个可以完整发给 Codex 的提示词示例:
你是一名生信工程师。请用 Python 编写一个命令行富集分析工具,要求如下: 1. 从输入文件 gene_list.txt 中读取人类基因 Symbol 列表; 2. 使用 gseapy 库调用 Enrichr 数据库,支持 KEGG 和 GO Biological Process 等基因集; 3. 输出富集结果 CSV 文件,按 adjusted p-value 从低到高排序; 4. 绘制 Top 10 富集通路的条形图和气泡图,保存为 PNG; 5. 命令行参数包括:--input、--gene-sets、--outdir、--top; 6. 对输入基因做去重、空值过滤、大小写标准化; 7. 加上详细的中文注释和必要的异常处理; 8. 依赖库写到 requirements.txt。你会发现,这个提示词已经相当于一份小需求文档。Codex 生成的代码未必一次完美,但你可以继续追问:“如果输入文件是 Excel 怎么办?”“帮我增加 Log 日志输出”“统计失败的通路并写到 error.log”。AI 编程助手的核心用法就是迭代修改。
4.2 联网版:基于 gseapy 的快速实现
下面是我整理后的“联网版”富集分析脚本,核心逻辑和上面提示词描述一致。脚本会调用 Enrichr 数据库,所以需要联网。
先创建项目目录结构:
enrichment_tool/ ├── gene_list.txt ├── enrichr_enrich.py ├── requirements.txt └── output/requirements.txt内容:
pandas matplotlib gseapyenrichr_enrich.py完整代码:
# 文件路径:enrichment_tool/enrichr_enrich.py # 功能:读取基因列表,调用 Enrichr 做 GO/KEGG 富集分析并可视化 import argparse import logging from pathlib import Path import pandas as pd from gseapy import barplot, dotplot, enrichr # 配置日志,方便定位问题 logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", ) logger = logging.getLogger(__name__) def load_gene_list(input_file: str) -> list: """读取基因列表文件,去重、去空、标准化大小写。""" genes = [] with open(input_file, "r", encoding="utf-8") as fh: for line in fh: gene = line.strip() if not gene: continue # 统一转为大写,避免 TP53 和 tp53 被当成两个基因 genes.append(gene.upper()) # 去重并保持顺序 seen = set() unique_genes = [] for gene in genes: if gene not in seen: seen.add(gene) unique_genes.append(gene) logger.info("共读取 %d 个唯一基因", len(unique_genes)) return unique_genes def run_enrichment( gene_list: list, gene_sets: str, outdir: str, top: int, ) -> pd.DataFrame: """调用 Enrichr 执行富集分析,返回结果 DataFrame。""" out_path = Path(outdir) out_path.mkdir(parents=True, exist_ok=True) logger.info("正在使用基因集: %s", gene_sets) enr = enrichr( gene_list=gene_list, gene_sets=gene_sets, organism="human", outdir=str(out_path), ) results = enr.res2d.copy() # 统一列名,方便后续处理 results.columns = [str(col).strip() for col in results.columns] return results def save_results(results: pd.DataFrame, gene_sets: str, outdir: str) -> str: """保存 CSV 结果,并返回文件路径。""" out_path = Path(outdir) out_path.mkdir(parents=True, exist_ok=True) # Enrichr 结果一般包含 Adjusted P-value 列 pvalue_col = [ col for col in results.columns if "adjusted p-value" in col.lower() or "adj p-value" in col.lower() ] if pvalue_col: results = results.sort_values(by=pvalue_col[0]) csv_path = out_path / f"{gene_sets}_enrichment_results.csv" results.to_csv(csv_path, index=False) logger.info("结果已保存到: %s", csv_path) return str(csv_path) def plot_top_results(results: pd.DataFrame, gene_sets: str, outdir: str, top: int) -> None: """绘制 Top N 富集通路图。""" out_path = Path(outdir) out_path.mkdir(parents=True, exist_ok=True) # 按 adjusted p-value 排序后取 Top N pvalue_col = [ col for col in results.columns if "adjusted p-value" in col.lower() or "adj p-value" in col.lower() ] if pvalue_col: plot_df = results.sort_values(by=pvalue_col[0]).head(top) else: plot_df = results.head(top) # gseapy 自带的条形图和气泡图 barplot( plot_df, top=top, ofname=str(out_path / f"{gene_sets}_barplot.png"), ) dotplot( plot_df, top=top, ofname=str(out_path / f"{gene_sets}_dotplot.png"), ) logger.info("图表已保存到: %s", out_path) def parse_args(): parser = argparse.ArgumentParser(description="基于 Enrichr 的富集分析工具") parser.add_argument("--input", required=True, help="基因列表文件路径") parser.add_argument( "--gene-sets", default="KEGG_2021_Human", help="基因集名称,如 KEGG_2021_Human、GO_Biological_Process_2021", ) parser.add_argument("--outdir", default="output", help="输出目录") parser.add_argument("--top", type=int, default=10, help="画图时保留 Top N") return parser.parse_args() def main(): args = parse_args() gene_list = load_gene_list(args.input) if len(gene_list) == 0: logger.error("基因列表为空,请检查输入文件") return results = run_enrichment( gene_list=gene_list, gene_sets=args.gene_sets, outdir=args.outdir, top=args.top, ) if results is None or results.empty: logger.error("富集分析未返回结果") return csv_path = save_results(results, args.gene_sets, args.outdir) plot_top_results(results, args.gene_sets, args.outdir, args.top) logger.info("全部完成,CSV 结果: %s", csv_path) if __name__ == "__main__": main()gene_list.txt示例内容(一行一个基因):
TP53 BRCA1 EGFR MYC PTEN AKT1 MTOR PIK3CA KRAS MAPK1这里说明一下:gseapy的enrichr函数会通过 Enrichr 公共数据库查询,所以必须联网。基因集名称也不是固定不变的,比如KEGG_2021_Human、GO_Biological_Process_2021都可能随数据库更新而变化,运行时如果提示基因集不存在,可以去 Enrichr 官网查看新的基因集名称,或者报错后让 Codex 帮你换成正确名称。
4.3 本地版:自写 Fisher 精确检验
如果不想依赖外部数据库,或者分析环境在内网,可以做一个“本地版”。它需要一个通路注释文件,格式是每行一条通路:
通路ID 通路名称 基因1,基因2,基因3比如custom_pathways.txt:
hsa04110 Cell cycle TP53,RB1,CDK2,CCND1,CDC25A hsa04151 PI3K-Akt signaling pathway PIK3CA,AKT1,MTOR,EGFR,BRCA1 hsa05200 Pathways in cancer TP53,EGFR,MYC,KRAS,PTEN,AKT1本地版脚本核心代码如下,完整的项目方式与联网版相同:
# 文件路径:enrichment_tool/fisher_enrich.py # 功能:基于 Fisher 精确检验的本地富集分析工具 import argparse from pathlib import Path import numpy as np import pandas as pd from scipy.stats import fisher_exact def load_annotation(anno_file: str) -> pd.DataFrame: """读取三列注释文件:通路ID、通路名、基因列表。""" rows = [] with open(anno_file, "r", encoding="utf-8") as fh: for line in fh: parts = line.strip().split("\t") if len(parts) < 3: continue pathway_id, pathway_name, gene_str = parts[0], parts[1], parts[2] genes = {g.strip().upper() for g in gene_str.split(",") if g.strip()} rows.append( { "pathway_id": pathway_id.strip(), "pathway_name": pathway_name.strip(), "genes": genes, } ) return pd.DataFrame(rows) def enrich_local( gene_list: list, annotation: pd.DataFrame, background_total: int, ) -> pd.DataFrame: """对每条通路做 Fisher 精确检验。""" gene_set = set(gene_list) n_queried = len(gene_set) results = [] for _, row in annotation.iterrows(): pathway_genes = row["genes"] # 四个格子的数字 a = len(gene_set & pathway_genes) # 在基因列表且属于通路 b = len(pathway_genes - gene_set) # 不在基因列表但属于通路 c = n_queried - a # 在基因列表但不属于通路 # d = background_total - a - b - c # 不在基因列表也不属于通路 odds_ratio, p_value = fisher_exact( [[a, b], [c, background_total - a - b - c]] ) # 富集倍数 fold = (a / n_queried) / (len(pathway_genes) / background_total) if n_queried and len(pathway_genes) else np.nan results.append( { "pathway_id": row["pathway_id"], "pathway_name": row["pathway_name"], "overlap_genes": a, "overlap_gene_names": ",".join(sorted(gene_set & pathway_genes)), "p_value": p_value, "odds_ratio": odds_ratio, "fold_enrichment": fold, } ) df = pd.DataFrame(results) df["p_adjusted"] = df["p_value"] * len(df) # Bonferroni 校正,通路数少时可用 df = df.sort_values(by="p_adjusted") return df def main(): parser = argparse.ArgumentParser(description="本地 Fisher 富集分析工具") parser.add_argument("--input", required=True, help="基因列表文件") parser.add_argument("--annotation", required=True, help="通路注释文件") parser.add_argument("--background", type=int, default=20000, help="背景基因总数") parser.add_argument("--out", default="fisher_results.csv", help="输出 CSV") args = parser.parse_args() with open(args.input, "r", encoding="utf-8") as fh: genes = [line.strip().upper() for line in fh if line.strip()] annotation = load_annotation(args.annotation) df = enrich_local(genes, annotation, background_total=args.background) df.to_csv(args.out, index=False) print(f"分析完成,结果: {args.out}") if __name__ == "__main__": main()本地版的好处是容易理解每一步统计计算,不依赖外部服务;缺点是需要自己准备通路注释文件,背景基因总数也需要按实际物种和检测范围调整。背景总数设得不对,富集倍数和 p 值都会偏差。线上项目里建议把它当成教学练习,生产分析还是优先用gseapy这类维护良好的库。
4.4 运行与验证
安装依赖:
cd enrichment_tool pip install -r requirements.txt运行联网版:
python enrichr_enrich.py --input gene_list.txt --gene-sets KEGG_2021_Human --outdir output --top 10运行本地版:
python fisher_enrich.py --input gene_list.txt --annotation custom_pathways.txt --background 20000 --out fisher_results.csv4.5 结果说明
联网版运行成功后,会输出两个关键文件:
output/KEGG_2021_Human_enrichment_results.csv:所有通路富集结果;output/KEGG_2021_Human_barplot.png:Top 10 条形图;output/KEGG_2021_Human_dotplot.png:Top 10 气泡图。
打开 CSV 后,重点看以下几列:
Term:通路的名称;Overlap:例如5/87,表示你输入的基因里有 5 个落在该通路,通路总基因数 87;P-value:原始 p 值;Adjusted P-value:多重检验校正后的值,排序和筛选的主要依据;Genes:具体命中该通路的基因名,结果解读时经常要看。
画出的条形图,条形越长代表富集显著性越高(通常按-log10(p)展示);气泡图中,点越大说明命中基因越多,颜色越深显著性越高。
这里有一个很重要的建议:拿到显著通路后,不要只看排名第一的条目,要把 Top 10 甚至 Top 20 合在一起看方向。比如多条通路都指向细胞周期、DNA 修复,那么结论就比单条通路可靠得多。
5. Codex 使用中的常见问题排查
使用 Codex 辅助写生信工具时,环境层面最容易出问题。下面列出几个我实际遇到或社区里高频出现的报错。
5.1 codex connection failed / 一直重新连接
错误现象:
codex connection failed: error sending request或者 Codex 界面上一直显示“正在重新连接”。
常见原因:
- 当前网络环境无法访问 Codex 配置的 API 端点;
- API Base URL 填错,比如多了空格、少了协议头;
- API Key 无效或过期;
- 本地代理服务没有启动。
排查步骤:
- 检查 API Key 是否配置正确,可以重填一次;
- 确认 API Base URL 是否与你使用的服务商一致;
- 如果你使用了
cc switch这类本地路由工具,先确认软件本身是否处于启动状态; - 换一个简单的网络环境或服务节点测试;
- 查看 Codex 日志,通常日志里会写明具体是 DNS 错误、超时还是鉴权失败。
5.2 cc switch local proxy failed 类报错
错误现象:
cc switch local proxy failed while handling codex endpoint /responses常见原因:
cc switch启动的本地路由不能正常把 Codex 的请求转发到目标模型服务。原因通常是 Provider 配置不完整,或者目标服务端点返回了非预期状态码。
解决思路:
- 在
cc switch里重新检查 Provider 的模型名称、接口地址、API Key; - 换一个模型名后再试,有些服务商对模型名大小写敏感;
- 把 Codex 和
cc switch都重启一次,让其重新读取配置; - 查看上游请求日志,确认是请求格式问题还是鉴权问题。
5.3 reasoning_content 与 thinking mode 报错
错误现象:
upstream_status: http 400 cause: the `reasoning_content` in the thinking mode must be passed back to the api常见原因:
这个报错主要在接入 DeepSeek 等带“思考模式”的模型时出现。简单来说,这类模型在流式输出时会把一部分思考过程放在reasoning_content字段里,Codex 或本地路由工具没有把该字段正确透传回去,导致上游拒绝请求。
解决思路:
- 在 Codex 中关闭或降低思考模式、推理模式;
- 升级
cc switch或 Codex 到较新版本,旧版本可能不支持新字段透传; - 更换为不支持思考模式的模型,例如改用普通对话模型;
- 如果错误仍然存在,把报错信息完整复制给 Codex 或路由工具维护者,通常更新配置就能解决。
这类报错不是代码写错了,而是工具链版本和模型能力之间不匹配,遇到时不用慌,优先从“模型、工具版本、模式开关”三方面排查。
5.4 模型不支持或账号限制
错误现象:
the 'gpt-5.6-sol' model is not supported when using codex with a chatgpt account常见原因:
如果你使用 ChatGPT 账号登录 Codex,可用的模型集合由账号套餐决定,而不是任意模型都能用。手动把模型改成未开放的名称,就会报“模型不支持”。
解决思路:
- 换回 Codex 配置文件中默认支持的模型;
- 如果确实需要使用其他模型,考虑使用 API Key 方式而不是 ChatGPT 账号登录;
- 不要在生产流程里硬编码某个测试模型名,把模型名放到配置文件里,方便切换。
6. 生信工具开发的工程建议
6.1 让 Codex 生成更稳定、可维护的代码
使用 AI 编程助手时,很多人只描述“实现 XXX”,生成的代码能用但很脆弱。我的建议是:
- 把输入输出说得非常具体。例如“输入是一行一个基因的 txt”,而不是“输入基因列表”。
- 要求参数化。所有文件路径、阈值、数据库名称都做成命令行参数或配置文件,避免硬编码。
- 要求异常处理。明确告诉 Codex:“文件不存在时打印友好提示并退出,不要抛一堆 traceback”。
- 要求日志输出。分析耗时可能很长,有日志才能判断卡在哪一步。
- 分步生成,而不是一次生成大项目。先让 Codex 写读取文件的部分,验证通过后再让它加统计和画图,最后组装成命令行工具。
6.2 数据安全、结果校验与可复现性
生信数据往往涉及课题未发表结果或临床信息,使用云端 AI 工具时需要注意:
- 敏感样本信息不要直接出现在代码和提示词里。最好把数据路径写进配置,而不是把数据内容粘贴给模型。
- 不要在一个不可信的公共环境里提交带患者编号、样本编号的数据。
- 对 AI 生成的代码,要保留生成时使用的提示词、模型版本和参数。记录这些信息可以保证后续复现或回溯。
- 每次运行后,把输入文件的哈希值、输出文件的日期版本一起记录下来,方便论文投稿时的数据可追溯性。
# 生成输入文件的校验值,便于后续核对 sha256sum gene_list.txt6.3 从“单次脚本”到“自动化富集分析流程”
做成脚本只是第一步,实际项目里更推荐把它升级成流程:
- 差异基因表自动筛选(例如
log2FC > 1且padj < 0.05); - 自动导出基因列表;
- 自动跑多个基因集(KEGG、GO BP、GO CC、Reactome);
- 把多个结果合并成 Excel 报告;
- 用 Codex 根据富集结果起草“我的差异基因显著富集在细胞周期和 DNA 修复通路”这类结论草稿,再由人工确认。
这样一个流程跑下来,从原始差异表到一份带图表和结论草稿的分析报告,基本可以在一小时内完成。
7. 总结与下一步实践
这篇文章解决了三件事:第一,把富集分析的概念和统计学原理用容易理解的方式讲清楚,让你知道结果里的p-value、adjusted p-value、富集倍数到底是什么意思;第二,用可运行的 Python 代码配合 gseapy,搭建了一个输入基因列表就能出结果的富集分析工具,同时也提供了本地版 Fisher 精确检验脚本,让你能深入理解计算逻辑;第三,整理了 Codex 在安装、配置第三方模型、接入推理模型时常见的高频报错和排查思路。
对我来说,Codex 最有价值的地方不是替我把代码写出来,而是把我从“背语法”中解放出来,让我能把更多精力放在实验设计和结果解释上。建议你拿到这篇文章的脚本后,先用自己手头的差异基因列表跑一遍,再尝试修改提示词,让 Codex 加入新的数据库、新的图表样式或新的统计方法。踩过几次坑、改过几版代码之后,你就拥有了一个完全属于自己的自动化富集分析小工具。