Files
bttoxin-pipeline/bttoxin/cli.py
hotwa 5883e13c56 feat(shotter): 实现 Shotter v1 活性评估与单 FNA 流程,新增 API/CLI/绘图与报告
- 新增 scripts/bttoxin_shoter.py:从 BPPRC 正样本 CSV 构建 name/亚家族/家族特异性索引,
  解析 BtToxin_Digger All_Toxins.txt,计算 per-hit 权重并以 noisy-OR 合成菌株×目标目/物种分数,
  输出 TSV/JSON;含 HMM 加成与配对毒素规则(Vip1/Vip2,Vpa/Vpb),other/unknown 桶。
- 新增端到端工具链:
  - scripts/run_single_fna_pipeline.py:Digger → Shotter → Plot → 打包
  - scripts/plot_shotter.py:绘制热图并生成论文式/摘要式报告
  - scripts/bttoxin_api.py 与 bttoxin/api.py:纯 Python API;bttoxin/cli.py 暴露 bttoxin-run
  - pyproject.toml:项目打包与 CLI 入口
- docs(README): 增加输入文件格式与结果解读,补充单目录写入方案
- chore(gitignore): 忽略 runs/ 与 tests/output
- ci: 移除 .woodpecker/test.yml
2025-12-01 10:11:26 +08:00

51 lines
2.1 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import argparse
from pathlib import Path
from .api import BtSingleFnaPipeline
def main() -> int:
ap = argparse.ArgumentParser(description="Bttoxin single-FNA pipeline (Digger → Shotter → Plot → Bundle)")
ap.add_argument("--fna", type=Path, required=True, help="Path to a single .fna file")
ap.add_argument("--toxicity_csv", type=Path, default=Path("Data/toxicity-data.csv"))
ap.add_argument("--base_workdir", type=Path, default=None, help="Base working dir (default: runs/bttoxin under repo root)")
ap.add_argument("--image", type=str, default="quay.io/biocontainers/bttoxin_digger:1.0.10--hdfd78af_0")
ap.add_argument("--platform", type=str, default="linux/amd64")
ap.add_argument("--min_identity", type=float, default=0.0)
ap.add_argument("--min_coverage", type=float, default=0.0)
ap.add_argument("--disallow_unknown_families", action="store_true", default=False)
ap.add_argument("--require_index_hit", action="store_true", default=False)
ap.add_argument("--lang", type=str, choices=["zh", "en"], default="zh")
ap.add_argument("--threads", type=int, default=4)
args = ap.parse_args()
pipe = BtSingleFnaPipeline(image=args.image, platform=args.platform, base_workdir=args.base_workdir)
res = pipe.run(
fna=args.fna,
toxicity_csv=args.toxicity_csv,
min_identity=args.min_identity,
min_coverage=args.min_coverage,
allow_unknown_families=not args.disallow_unknown_families,
require_index_hit=args.require_index_hit,
lang=args.lang,
threads=args.threads,
)
if not res.get("ok"):
print(f"[bttoxin-run] FAILED at stage={res.get('stage')}")
return 1
print("[bttoxin-run] ✓ Done")
print(f" run_root: {res['run_root']}")
print(f" digger: {res['digger_dir']}")
print(f" shotter: {res['shotter_dir']}")
print(f" bundle: {res['bundle']}")
print(f" strain: {res.get('strain','')}")
return 0
if __name__ == "__main__":
raise SystemExit(main())