tbtools-cli 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. tbtools_cli/__init__.py +18 -0
  2. tbtools_cli/auto_commands.py +1149 -0
  3. tbtools_cli/cli.py +528 -0
  4. tbtools_cli/cli_load.py +352 -0
  5. tbtools_cli/cli_rpc.py +303 -0
  6. tbtools_cli/cli_tools_registry.py +93 -0
  7. tbtools_cli/cli_top.py +1160 -0
  8. tbtools_cli/command_metadata.json +4606 -0
  9. tbtools_cli/command_spec.py +382 -0
  10. tbtools_cli/config.example.toml +19 -0
  11. tbtools_cli/config.py +43 -0
  12. tbtools_cli/core.py +508 -0
  13. tbtools_cli/errors.py +38 -0
  14. tbtools_cli/presets.py +100 -0
  15. tbtools_cli/scenarios.py +92 -0
  16. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/AdmixtureCli.java +91 -0
  17. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/AmazingMetaCli.java +78 -0
  18. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/AssemblyRecommandCli.java +47 -0
  19. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/BamIndexCli.java +31 -0
  20. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/BamSortCli.java +43 -0
  21. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/BamStateCli.java +49 -0
  22. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/BarPlotterCli.java +18 -0
  23. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/BarplotCli.java +168 -0
  24. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/BatchVizMotifsCli.java +47 -0
  25. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/BlastXmlConvertCli.java +45 -0
  26. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/BlatExecutorCli.java +66 -0
  27. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/CalcRepeatCli.java +62 -0
  28. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/CalculateSimilarityCli.java +34 -0
  29. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/CddMotifCli.java +46 -0
  30. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/CircleGeneViewerCli.java +81 -0
  31. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/CircosCli.java +76 -0
  32. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/ColorSchemeCli.java +29 -0
  33. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/CtgGroupCli.java +29 -0
  34. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/CubeHeatmapCli.java +70 -0
  35. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/DeHistCli.java +46 -0
  36. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/DegramdomCli.java +33 -0
  37. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/DiffExpCli.java +44 -0
  38. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/DistanceCli.java +53 -0
  39. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/DualSynCli.java +147 -0
  40. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/EggnogCli.java +39 -0
  41. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/ExprCorrCli.java +27 -0
  42. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/FastaMergerCli.java +36 -0
  43. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/FastaTableConvertCli.java +38 -0
  44. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/FileCleanerCli.java +31 -0
  45. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/FileSplitCli.java +15 -0
  46. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/FindBlockDualCli.java +71 -0
  47. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/FindBlockMultipleCli.java +67 -0
  48. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/FindPathCli.java +15 -0
  49. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GSEAWrapperCli.java +33 -0
  50. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GenBank2FastaCli.java +32 -0
  51. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GeneDensityCli.java +38 -0
  52. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GeneLocGffCli.java +140 -0
  53. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GeneStructureCli.java +90 -0
  54. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GenericCli.java +177 -0
  55. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GetENALinksCli.java +36 -0
  56. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GetSubNewickTreeCli.java +50 -0
  57. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GoEnrichCli.java +42 -0
  58. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GoLevelCli.java +59 -0
  59. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GroupedBarCli.java +95 -0
  60. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GsaDiagCli.java +45 -0
  61. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GxfFilterCli.java +39 -0
  62. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/GxfSortCli.java +23 -0
  63. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/HclustCli.java +43 -0
  64. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/HeatmapCli.java +89 -0
  65. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/HmmerSuiteCli.java +47 -0
  66. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/JgblocksCli.java +65 -0
  67. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/KeggEnrichCli.java +31 -0
  68. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/LayoutHeatmapCli.java +90 -0
  69. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MCScanXCli.java +80 -0
  70. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MCScanXFastCli.java +41 -0
  71. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MSACli.java +46 -0
  72. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MakeMotifCli.java +39 -0
  73. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MarkerDesignCli.java +62 -0
  74. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MarkerToolsCli.java +57 -0
  75. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/Mast2TabCli.java +27 -0
  76. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MastCli.java +54 -0
  77. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MastRunCli.java +39 -0
  78. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/Meme2TabCli.java +26 -0
  79. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MemeCli.java +74 -0
  80. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MemeRunCli.java +40 -0
  81. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MgGxfCli.java +35 -0
  82. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MicroSynCli.java +118 -0
  83. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MirIdentifyCli.java +55 -0
  84. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MotifCli.java +75 -0
  85. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MotifPatternCli.java +67 -0
  86. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MotifShiftCli.java +30 -0
  87. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MountainPlotCli.java +44 -0
  88. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/MultiSuperHeatCli.java +64 -0
  89. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/NeedlemanWunschCli.java +76 -0
  90. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/PafGC.java +15 -0
  91. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/PafVizCli.java +67 -0
  92. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/PeakDistCli.java +58 -0
  93. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/Pep2CodonCli.java +26 -0
  94. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/PfamMotifCli.java +43 -0
  95. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/PhyloTreeCli.java +92 -0
  96. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/PileUpCli.java +55 -0
  97. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/PlantCAREResultClassifyCli.java +36 -0
  98. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/PubmedSearchCli.java +25 -0
  99. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/QpcrCli.java +69 -0
  100. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/QpcrDdctCli.java +28 -0
  101. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/QpcrProcCli.java +28 -0
  102. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/QuickGenomeDotCli.java +66 -0
  103. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/QuickProteinAnnoCli.java +34 -0
  104. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/QuickRunIQtreeCli.java +69 -0
  105. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/QuickTrimALCli.java +67 -0
  106. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/RNAplotCli.java +129 -0
  107. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/RegionBedToGFF3Cli.java +43 -0
  108. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/RegionDepthCli.java +29 -0
  109. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/SamBamCovCli.java +33 -0
  110. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/SeqConverterCli.java +17 -0
  111. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/SeqLenTrackCli.java +41 -0
  112. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/SeveralSpeciesCli.java +132 -0
  113. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/SimpleEnricherCli.java +44 -0
  114. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/SimpleHmmscanCli.java +32 -0
  115. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/SixFrameTranlaterCli.java +35 -0
  116. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/StructAnnoCompareCli.java +66 -0
  117. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/SubmitSMARTCli.java +30 -0
  118. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/SuperCircosCli.java +330 -0
  119. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/TableColManipCli.java +56 -0
  120. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/TableCollapseCli.java +33 -0
  121. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/TargetScoreCli.java +47 -0
  122. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/TauCalcCli.java +28 -0
  123. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/TaxonomyBatchCli.java +72 -0
  124. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/TreeCli.java +75 -0
  125. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/TreeRootingCli.java +30 -0
  126. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/TrimMSACli.java +33 -0
  127. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/UnrootedTreeCli.java +44 -0
  128. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/UpSetCli.java +90 -0
  129. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/Venn5Cli.java +60 -0
  130. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/Venn6Cli.java +65 -0
  131. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/ViolinCli.java +66 -0
  132. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/VisualizeCli.java +57 -0
  133. tbtools_cli-1.2.0.data/data/tbtools_cli/bridges/VizGFACli.java +39 -0
  134. tbtools_cli-1.2.0.dist-info/METADATA +504 -0
  135. tbtools_cli-1.2.0.dist-info/RECORD +139 -0
  136. tbtools_cli-1.2.0.dist-info/WHEEL +5 -0
  137. tbtools_cli-1.2.0.dist-info/entry_points.txt +2 -0
  138. tbtools_cli-1.2.0.dist-info/licenses/LICENSE +21 -0
  139. tbtools_cli-1.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,382 @@
1
+ """command_spec.py — 统一命令模型(CommandSpec, 第八轮评审核心建议骨架)。
2
+
3
+ 目标: 所有命令产物(metadata/docs/help/search/统计)从单一 CommandSpec 模型派生,
4
+ 不再各自从 ENGINE_REGISTRY / CLI_TOOLS / cli.py / CATEGORY_MAP 分散读取。
5
+
6
+ 当前为兼容层骨架: 从现有注册源构建统一 specs(不改运行时行为),
7
+ gen_metadata 与后续工具以 specs 为唯一输入。
8
+ """
9
+ from dataclasses import dataclass, field
10
+
11
+ from tbtools_cli import auto_commands as _ac
12
+ from tbtools_cli.cli_tools_registry import CLI_TOOLS
13
+ from tbtools_cli.cli_load import CATEGORY_MAP
14
+
15
+
16
+ @dataclass
17
+ class InputSpec:
18
+ """命令输入定义(二期 schema: 类型/格式/必填)"""
19
+ name: str
20
+ role: str = "file" # file | param
21
+ format: str = "" # gff3 | fasta | tsv | newick | ...
22
+ required: bool = True
23
+ note: str = ""
24
+
25
+
26
+ @dataclass
27
+ class CommandSpec:
28
+ """单一命令定义(第八轮评审 CommandSpec 模型)"""
29
+ name: str
30
+ group: str
31
+ kind: str # bridge | direct | tool | manual
32
+ class_name: str = ""
33
+ runner: str = "" # plot | java | ""
34
+ xmx: str = "2g"
35
+ doc: str = ""
36
+ status: str = "stable" # stable|beta|legacy|platform-limited|network-required
37
+ aliases: list[str] = field(default_factory=list) # 反向: canonical → 别名们
38
+ alias_of: str = "" # 本命令是某 canonical 的兼容别名(如 treeRooting→rooting)
39
+ inputs: list[InputSpec] = field(default_factory=list)
40
+ outputs: list[str] = field(default_factory=list) # 输出类型(如 svg/png/tsv)
41
+ capabilities: list[str] = field(default_factory=list) # 能力标签(能力图搜索)
42
+ dependencies: list[str] = field(default_factory=list) # 外部依赖(环境解析, GLM #22)
43
+
44
+
45
+ # 核心命令输入输出 schema 样例(证明模型模式; 全量标注为二期)
46
+ KNOWN_SCHEMAS = {
47
+ "volcano": ([InputSpec("deg", format="tsv", note="GeneID\tLog2FC\tpvalue")], ["svg"]),
48
+ "heatmap": ([InputSpec("matrix", format="tsv", note="表达矩阵 gene×sample")], ["svg"]),
49
+ "hclust": ([InputSpec("distance", format="tsv", note="三列: GeneA\tGeneB\tdist")], ["svg"]),
50
+ "venn2": ([InputSpec("list1", format="txt"), InputSpec("list2", format="txt")], ["svg"]),
51
+ "msy": ([InputSpec("pos", format="tsv", note="Chr\tGene\tStart\tEnd"),
52
+ InputSpec("links", format="tsv"), InputSpec("layout", format="txt")], ["svg"]),
53
+ "genestructure": ([InputSpec("gff", format="gff3"), InputSpec("ids", format="txt")], ["svg"]),
54
+ "motif": ([InputSpec("meme_xml", format="xml"), InputSpec("ids", format="txt")], ["svg"]),
55
+ "peaktss": ([InputSpec("gxf", format="gff3"), InputSpec("peaks", format="tsv", note="MACS2")], ["svg"]),
56
+ "tableMerge": ([InputSpec("tables", format="tsv", note="多个输入表")], ["tsv"]),
57
+ "qdot": ([InputSpec("gff", format="tsv", note="4 列简化: Chr\tGene\tStart\tEnd")], ["svg"]),
58
+ # 二期扩展批(高频绘图/工具)
59
+ "dehist": ([InputSpec("deg", format="tsv", note="DEG 表")], ["svg"]),
60
+ "pca": ([InputSpec("matrix", format="tsv", note="表达矩阵")], ["svg"]),
61
+ "barplot": ([InputSpec("enrichment", format="tsv", note="富集表: 列名 Term/Pvalue")], ["svg"]),
62
+ "circos": ([InputSpec("chrLen", format="tsv"), InputSpec("link", format="tsv"),
63
+ InputSpec("genePos", format="tsv")], ["svg"]),
64
+ "dotplot": ([InputSpec("gff", format="tsv", note="4 列简化"), InputSpec("pairs", format="tsv")], ["svg"]),
65
+ "dualsyn": ([InputSpec("gff", format="tsv", note="简化 GFF"), InputSpec("pairs", format="tsv")], ["svg"]),
66
+ "mcscanx": ([InputSpec("gff", format="tsv", note="chr\tgene\tstart\tend"),
67
+ InputSpec("blast", format="tsv", note="tab6")], ["tsv"]),
68
+ "iqtree": ([InputSpec("aln", format="fasta")], ["nwk", "treefile"]),
69
+ "muscle": ([InputSpec("fasta", format="fasta")], ["aln"]),
70
+ "trimal": ([InputSpec("aln", format="fasta")], ["aln"]),
71
+ "blastp": ([InputSpec("query", format="fasta"), InputSpec("db", format="fasta")], ["out"]),
72
+ "sixframe": ([InputSpec("pep", format="fasta", note="蛋白(输出核酸)")], ["fa"]),
73
+ "longestorf": ([InputSpec("seq", format="fasta", note="核酸输入")], ["fa"]),
74
+ "seqlogo": ([InputSpec("seqs", format="fasta")], ["svg"]),
75
+ "stat-fasta": ([InputSpec("fasta", format="fasta")], ["xls"]),
76
+ # 三期批次(schema 标注继续)
77
+ "venn3": ([InputSpec("list1", format="txt"), InputSpec("list2", format="txt"),
78
+ InputSpec("list3", format="txt")], ["svg"]),
79
+ "venn4": ([InputSpec("list1", format="txt"), InputSpec("list2", format="txt"),
80
+ InputSpec("list3", format="txt"), InputSpec("list4", format="txt")], ["svg"]),
81
+ "upset": ([InputSpec("sets", format="txt", note="多个集合文件, 末参为输出")], ["svg"]),
82
+ "tpmCalc": ([InputSpec("counts", format="tsv"), InputSpec("lenInfo", format="tsv")], ["tsv"]),
83
+ "gxfSplit": ([InputSpec("gff", format="gff3")], ["tsv"]),
84
+ "gxfAttr": ([InputSpec("gff", format="gff3")], ["tsv"]),
85
+ "gxfIdAppender": ([InputSpec("gff", format="gff3")], ["gff3"]),
86
+ "recipBlast": ([InputSpec("db", format="fasta"), InputSpec("query", format="fasta")], ["tsv"]),
87
+ "autoMakeBlastDb": ([InputSpec("fasta", format="fasta")], ["db"]),
88
+ "genelocgff": ([InputSpec("gff", format="gff3"), InputSpec("ids", format="txt")], ["svg"]),
89
+ "treeRooting": ([InputSpec("nwk", format="newick", note="需枝长")], ["nwk"]),
90
+ "memerun": ([InputSpec("fasta", format="fasta")], ["meme"]),
91
+ "mastrun": ([InputSpec("meme", format="meme")], ["xml"]),
92
+ "goEnrich": ([InputSpec("background", format="tsv"), InputSpec("target", format="tsv")], ["tsv"]),
93
+ "keggEnrich": ([InputSpec("background", format="tsv"), InputSpec("target", format="tsv")], ["tsv"]),
94
+ "gsea": ([InputSpec("expr", format="tsv"), InputSpec("cls", format="txt")], ["xls"]),
95
+ "efpHeat": ([InputSpec("tga", format="tga", note="TrueColor type2"), InputSpec("expMat", format="tsv")], ["svg"]),
96
+ "multiEfp": ([InputSpec("tga", format="tga"), InputSpec("expMat", format="tsv")], ["svg"]),
97
+ "layoutheatmap": ([InputSpec("expr", format="tsv"), InputSpec("layout", format="tsv")], ["svg"]),
98
+ # 第三批(常用绘图/工具)
99
+ "microsyn": ([InputSpec("gff", format="tsv", note="简化 GFF"),
100
+ InputSpec("links", format="tsv")], ["svg"]),
101
+ "multisyn": ([InputSpec("gff", format="tsv"), InputSpec("gxf_lst", format="txt")], ["svg"]),
102
+ "pafviz": ([InputSpec("paf", format="tsv", note="13 列 PAF")], ["svg"]),
103
+ "pafref": ([InputSpec("paf", format="tsv", note="含 cg:Z CIGAR")], ["svg"]),
104
+ "peakanno": ([InputSpec("peaks", format="tsv", note="MACS2, 百万级坐标")], ["tsv"]),
105
+ "supercircos": ([InputSpec("config", format="txt", note="[chrLen] 等节")], ["svg"]),
106
+ "gel": ([InputSpec("lanes", format="tsv", note="LaneLabels 逗号分隔")], ["svg"]),
107
+ "plotrna": ([InputSpec("seq", format="fasta")], ["pdf"]),
108
+ "pep2codon": ([InputSpec("cds", format="fasta"), InputSpec("pep_aln", format="fasta")], ["fa"]),
109
+ "mcscanxd": ([InputSpec("gff", format="tsv"), InputSpec("blast", format="tsv")], ["collinearity"]),
110
+ "notung": ([InputSpec("tree", format="newick"), InputSpec("gene_tree", format="newick")], ["nwk"]),
111
+ "newickRename": ([InputSpec("nwk", format="newick")], ["nwk"]),
112
+ "hmmerSearch": ([InputSpec("hmm", format="hmm"), InputSpec("seq", format="fasta")], ["tsv"]),
113
+ "memeViz": ([InputSpec("meme", format="meme")], ["svg"]),
114
+ "kallisto": ([InputSpec("fastq", format="fastq", note="RNA-seq")], ["tsv"]),
115
+ "tfbsShift": ([InputSpec("motif", format="meme")], ["tsv"]),
116
+ "smart": ([InputSpec("seq", format="fasta")], ["tsv"]),
117
+ "barplotter": ([InputSpec("gff", format="gff3"), InputSpec("synteny", format="tsv")], ["svg"]),
118
+ "calcRepeat": ([InputSpec("fasta", format="fasta")], ["tsv"]),
119
+ "rnaplot": ([InputSpec("seq", format="fasta")], ["svg"]),
120
+ "preparespecies": ([InputSpec("genome", format="fasta"), InputSpec("gff", format="gff3")], ["fasta"]),
121
+ }
122
+
123
+
124
+ # 命令外部依赖(env 工具级解析; 无依赖命令默认 [])
125
+ KNOWN_DEPENDENCIES = {
126
+ "hmmsearch": ["hmmer"], "simplehmmscan": ["hmmer"],
127
+ "calcRepeat": ["jellyfish"],
128
+ "rnaplot": ["rnafold"], "plotrna": ["rnafold"],
129
+ "kallisto": ["kallisto"],
130
+ "diamond": ["diamond"],
131
+ "mcscanxd": ["mcscanx"],
132
+ "blastp": ["blast+"], "blastn": ["blast+"],
133
+ "muscle": ["muscle"], "mafft": ["mafft"],
134
+ "iqtree": ["iqtree2"], "onesteptree": ["iqtree2"],
135
+ "trimal": ["trimal"],
136
+ }
137
+
138
+
139
+ # 组级能力兜底(无精确标注的命令按组归能力域; 优先精确标注, 后兜底)
140
+ GROUP_CAPABILITIES = {
141
+ "expr": ["expression"], "syn": ["synteny"], "gxf": ["annotation"],
142
+ "table": ["table_operations"], "fastq": ["ngs", "sequence"],
143
+ "blast": ["homology"], "asm": ["assembly"], "chipseq": ["chip_seq"],
144
+ "tree": ["phylogeny"], "seq": ["sequence"], "efp": ["expression"],
145
+ "sets": ["set_operations"], "enrich": ["enrichment"], "virus": ["viral_analysis"],
146
+ "genome": ["genome_analysis"], "assembly": ["assembly"],
147
+ }
148
+
149
+
150
+ # 工具语义关系(能力图: 输入输出衔接; GLM #24)——核心命令标注
151
+ KNOWN_RELATIONS = {
152
+ "volcano": {"accepts": ["DEG_TABLE"], "produces": ["VOLCANO_PLOT"],
153
+ "next_step": ["goEnrich", "keggEnrich"], "related_to": ["dehist", "heatmap"]},
154
+ "dehist": {"accepts": ["DEG_TABLE"], "produces": ["DEG_HISTOGRAM"],
155
+ "related_to": ["volcano"]},
156
+ "heatmap": {"accepts": ["EXPRESSION_MATRIX"], "produces": ["HEATMAP"],
157
+ "next_step": ["hclust"], "related_to": ["pca"]},
158
+ "pca": {"accepts": ["EXPRESSION_MATRIX"], "produces": ["PCA_PLOT"]},
159
+ "hclust": {"accepts": ["DISTANCE_TABLE"], "produces": ["DENDROGRAM"],
160
+ "related_to": ["heatmap"]},
161
+ "mcscanx": {"accepts": ["GFF", "BLAST_TAB6"], "produces": ["COLLINEARITY"],
162
+ "next_step": ["dualsyn", "dotplot"]},
163
+ "dualsyn": {"accepts": ["SIMPLIFIED_GFF", "COLLINEARITY"], "produces": ["SYNTENY_PLOT"]},
164
+ "dotplot": {"accepts": ["SIMPLIFIED_GFF", "COLLINEARITY"], "produces": ["DOTPLOT"]},
165
+ "muscle": {"accepts": ["FASTA"], "produces": ["ALIGNMENT"], "next_step": ["trimal", "iqtree"]},
166
+ "trimal": {"accepts": ["ALIGNMENT"], "produces": ["TRIMMED_ALIGNMENT"], "next_step": ["iqtree"]},
167
+ "iqtree": {"accepts": ["ALIGNMENT"], "produces": ["PHYLOGENY_NWK"], "next_step": ["tree"]},
168
+ "tpmCalc": {"accepts": ["COUNTS_TABLE", "GENE_LENGTH"], "produces": ["TPM_TABLE"],
169
+ "next_step": ["pca", "heatmap", "volcano"]},
170
+ "gsea": {"accepts": ["EXPRESSION_TABLE", "PHENOTYPE_CLS"], "produces": ["GSEA_REPORT"]},
171
+ "genestructure": {"accepts": ["GFF3", "GENE_ID_LIST"], "produces": ["GENE_STRUCTURE_PLOT"]},
172
+ "kallisto": {"accepts": ["FASTQ"], "produces": ["QUANT_TABLE"], "next_step": ["tpmCalc"]},
173
+ }
174
+
175
+
176
+ # 已知别名(兼容层命名; canonical → 命令)
177
+ KNOWN_CAPABILITIES = {
178
+ "volcano": ["differential_expression", "visualization"],
179
+ "heatmap": ["expression_matrix", "clustering", "visualization"],
180
+ "dehist": ["differential_expression", "visualization"],
181
+ "pca": ["dimension_reduction", "expression_matrix"],
182
+ "hclust": ["clustering", "distance"],
183
+ "genestructure": ["gene_structure", "annotation", "visualization"],
184
+ "seqlogo": ["motif", "visualization"],
185
+ "msa": ["alignment", "visualization"],
186
+ "motif": ["motif", "visualization"],
187
+ "sixframe": ["translation", "sequence"],
188
+ "longestorf": ["orf_prediction", "sequence"],
189
+ "blastp": ["homology", "alignment"],
190
+ "mcscanx": ["synteny", "collinearity"],
191
+ "dualsyn": ["synteny", "visualization"],
192
+ "dotplot": ["synteny", "visualization"],
193
+ "msy": ["microsynteny", "visualization"],
194
+ "iqtree": ["phylogeny"],
195
+ "muscle": ["alignment"],
196
+ "trimal": ["alignment", "filtering"],
197
+ "kallisto": ["rna_seq", "quantification"],
198
+ "gsea": ["enrichment"],
199
+ "goEnrich": ["enrichment"],
200
+ "keggEnrich": ["enrichment"],
201
+ "tpmCalc": ["rna_seq", "normalization"],
202
+ "peaktss": ["chip_seq"],
203
+ }
204
+ # 精确标注补充(2026-09-23): 覆盖组级兜底的粗标签, 核心命令细化
205
+ KNOWN_CAPABILITIES.update({
206
+ "mcscanx": ["synteny", "collinearity_detection"],
207
+ "dualsyn": ["synteny", "visualization"],
208
+ "dotplot": ["synteny", "visualization"],
209
+ "circos": ["visualization", "genome_circos"],
210
+ "collinearRegion": ["synteny", "visualization"],
211
+ "pafviz": ["synteny", "visualization"],
212
+ "pafref": ["synteny", "visualization"],
213
+ "microsyn": ["synteny", "visualization"],
214
+ "multisyn": ["synteny", "visualization"],
215
+ "qdot": ["synteny", "visualization"],
216
+ "fimo": ["motif", "scanning"],
217
+ "mastrun": ["motif", "scanning"],
218
+ "memerun": ["motif", "discovery"],
219
+ "memeViz": ["motif", "visualization"],
220
+ "seqlogo": ["motif", "visualization"],
221
+ "tfbsShift": ["motif", "genome_scan"],
222
+ "smart": ["domain", "annotation"],
223
+ "hmmsearch": ["homology", "hmm_scan"],
224
+ "diamond": ["homology", "alignment"],
225
+ "blastp": ["homology", "alignment"],
226
+ "blastn": ["homology", "alignment"],
227
+ "recipBlast": ["homology", "reciprocal_best_hit"],
228
+ "filterCScore": ["homology", "filtering"],
229
+ "kallisto": ["rna_seq", "quantification"],
230
+ "fqTrim": ["ngs", "preprocessing"],
231
+ "fqfaConv": ["sequence", "conversion"],
232
+ "fastaExtract": ["sequence", "extraction"],
233
+ "fastaSubseq": ["sequence", "extraction"],
234
+ "gffFix": ["annotation", "gff_fixing"],
235
+ "gxfAppend": ["annotation", "gff_ops"],
236
+ "genelocation": ["annotation", "visualization"],
237
+ "peaktss": ["chip_seq", "peak_calling"],
238
+ "peakanno": ["chip_seq", "peak_annotation"],
239
+ "tpmCalc": ["rna_seq", "normalization"],
240
+ "efpHeat": ["expression", "visualization"],
241
+ "layoutheatmap": ["expression", "visualization"],
242
+ "gsea": ["enrichment"],
243
+ "goEnrich": ["enrichment", "gene_ontology"],
244
+ "keggEnrich": ["enrichment", "pathway"],
245
+ "multiEfp": ["expression", "visualization"],
246
+ "treeRooting": ["phylogeny", "rooting"],
247
+ "onesteptree": ["phylogeny", "tree_building"],
248
+ "notung": ["phylogeny", "reconciliation"],
249
+ "newickRename": ["phylogeny", "tree_editing"],
250
+ })
251
+
252
+
253
+
254
+ KNOWN_ALIASES = {
255
+ "treeRooting": "rooting",
256
+ "TableCast": "tableCast",
257
+ "gbar": "groupedbar",
258
+ "gdensity": "genedensity",
259
+ "getLongestCompleteORF": "longestorf",
260
+ "one-step": "onesteptree",
261
+ "genestructure": "structure", # 旧名 → seq structure? 保留注释: genestructure 是独立命令
262
+ }
263
+
264
+ # 已知状态(engine 级/环境限制; 未列默认为 stable)
265
+ KNOWN_STATUS = {
266
+ "srr2ena": "network-required",
267
+ "pubmed": "network-required",
268
+ "seqfetch": "network-required",
269
+ "rnaplot": "platform-limited", # 需 RNAfold 在 PATH(Windows 默认缺)
270
+ "calcRepeat": "platform-limited", # 需 jellyfish(Windows 默认缺)
271
+ "hmmsearch": "platform-limited", # 需系统 hmmsearch
272
+ "simplehmmscan": "platform-limited",
273
+ "cubeheatmap": "beta", # 引擎列数假设严格(官方数据仍 ArrayIndexOutOfBounds)
274
+ "groupedbar": "beta",
275
+ "nwAlign": "beta", # 输入格式易错(FASTA 头被当序列)
276
+ }
277
+
278
+
279
+ def build_command_specs() -> dict[str, CommandSpec]:
280
+ """构建统一命令模型(单一源, 兼容层: 不改变现运行行为)。
281
+
282
+ 来源:
283
+ 1. ENGINE_REGISTRY 表驱动(组 CATEGORY_MAP 归属)
284
+ 2. CLI_TOOLS 工具注册表
285
+ 3. 手动命令(经 cli_load 分组注册的 manual 命令, 从分组命令集补)
286
+ """
287
+ specs: dict[str, CommandSpec] = {}
288
+
289
+ # 1. 表驱动引擎命令
290
+ for name, kind, cls, xmx, runner, doc in _ac.ENGINE_REGISTRY:
291
+ specs[name] = CommandSpec(
292
+ name=name, group=CATEGORY_MAP.get(name, "engine"),
293
+ kind=kind, class_name=cls, runner=runner, xmx=xmx, doc=doc,
294
+ )
295
+
296
+ # 2. CLI 工具(runner/xmx 对齐现 metadata 条目: java/3g)
297
+ for name, cls in CLI_TOOLS.items():
298
+ specs.setdefault(name, CommandSpec(name=name, group="tool", kind="tool", class_name=cls,
299
+ runner="java", xmx="3g"))
300
+
301
+
302
+ # 3. 手动命令: 从现有 metadata 回退(kind=manual 且未被表驱动/工具覆盖)
303
+ # (完整版应遍历 cli 分组命令树; 骨架期以 metadata 为准, 单一模型逐步接管)
304
+ try:
305
+ import json as _json
306
+ import os as _os
307
+ meta_path = _os.path.join(_os.path.dirname(_os.path.dirname(_os.path.abspath(__file__))),
308
+ "tbtools_cli", "command_metadata.json")
309
+ if _os.path.isfile(meta_path):
310
+ meta = _json.load(open(meta_path, encoding="utf-8"))
311
+ for name, v in meta.items():
312
+ if v.get("kind") == "manual" and name not in specs:
313
+ specs[name] = CommandSpec(
314
+ name=name, group=v.get("group", "engine"), kind="manual",
315
+ doc=v.get("help", ""),
316
+ )
317
+ except Exception:
318
+ pass
319
+
320
+ # 别名/状态/schema 标注(统一模型增强; 在所有来源构建完成后)
321
+ for name, spec in specs.items():
322
+ spec.aliases = [a for a, target in KNOWN_ALIASES.items() if target == name]
323
+ spec.alias_of = KNOWN_ALIASES.get(name, "")
324
+ spec.status = KNOWN_STATUS.get(name, "stable")
325
+ if name in KNOWN_SCHEMAS:
326
+ ins, outs = KNOWN_SCHEMAS[name]
327
+ spec.inputs, spec.outputs = ins, outs
328
+ spec.capabilities = KNOWN_CAPABILITIES.get(name, []) or GROUP_CAPABILITIES.get(spec.group, [])
329
+ spec.dependencies = KNOWN_DEPENDENCIES.get(name, [])
330
+ return specs
331
+
332
+
333
+ def specs_from_scans(reg, tools, manual, infer_group=None) -> dict[str, dict]:
334
+ """扫描结果 → CommandSpec → metadata 投影(单一组装逻辑, gen_metadata 与工具共用)。
335
+
336
+ reg/tools/manual: scan_* 输出的条目 dict(含 name/kind/class/runner/xmx/help/group)。
337
+ infer_group: 可选分组推断函数(name, kind, src) -> str(manual 命令分组)。
338
+ """
339
+ from tbtools_cli.cli_load import CATEGORY_MAP as _CM
340
+ specs = {}
341
+ for name, e in reg.items():
342
+ specs[name] = CommandSpec(name, _CM.get(name, "engine"), e.get("kind", "direct"),
343
+ e.get("class", ""), e.get("runner") or "plot",
344
+ e.get("xmx") or "2g", e.get("help", ""))
345
+ for name, e in tools.items():
346
+ specs.setdefault(name, CommandSpec(name, "tool", "tool", e.get("class", ""),
347
+ "java", "3g", e.get("help", "")))
348
+ for name, e in manual.items():
349
+ grp = e.get("group") or (infer_group(name, "manual", e.get("src", "")) if infer_group else _CM.get(name, "engine"))
350
+ specs.setdefault(name, CommandSpec(name, grp, "manual", runner="plot", doc=e.get("help", "")))
351
+ for name, s in specs.items():
352
+ s.aliases = [a for a, t in KNOWN_ALIASES.items() if t == name]
353
+ s.alias_of = KNOWN_ALIASES.get(name, "")
354
+ s.status = KNOWN_STATUS.get(name, "stable")
355
+ if name in KNOWN_SCHEMAS:
356
+ s.inputs, s.outputs = KNOWN_SCHEMAS[name]
357
+ s.capabilities = KNOWN_CAPABILITIES.get(name, []) or GROUP_CAPABILITIES.get(s.group, [])
358
+ s.dependencies = KNOWN_DEPENDENCIES.get(name, [])
359
+ return {n: to_metadata_entry(s) for n, s in specs.items()}
360
+
361
+
362
+ def to_metadata_entry(spec: CommandSpec) -> dict:
363
+ """CommandSpec → metadata 条目(与现有 command_metadata.json 结构兼容)"""
364
+ e: dict[str, object] = {"name": spec.name, "kind": spec.kind, "mode": spec.kind,
365
+ "class": spec.class_name, "xmx": spec.xmx, "runner": spec.runner,
366
+ "group": spec.group, "help": spec.doc}
367
+ if spec.alias_of:
368
+ e["alias_of"] = spec.alias_of
369
+ if spec.capabilities:
370
+ e["capabilities"] = spec.capabilities
371
+ if spec.dependencies:
372
+ e["dependencies"] = spec.dependencies
373
+ if spec.inputs:
374
+ e["inputs"] = [{"name": i.name, "role": i.role, "format": i.format,
375
+ "required": i.required, "note": i.note} for i in spec.inputs]
376
+ if spec.outputs:
377
+ e["outputs"] = spec.outputs
378
+ if spec.status != "stable":
379
+ e["status"] = spec.status
380
+ if spec.aliases:
381
+ e["aliases"] = spec.aliases
382
+ return e
@@ -0,0 +1,19 @@
1
+ # tbtools-cli 配置文件
2
+ # 位置: ~/.config/tbtools-cli/config.toml
3
+ # 首次运行 install.sh 自动生成(可手改)
4
+
5
+ # TBtools JAR 路径(优先级: 环境变量 > 配置文件 > 自动探测)
6
+ jar = "/path/to/TBtools_JRE1.6.jar"
7
+
8
+ # 默认参数(可被命令行 --option 覆盖)
9
+ [defaults]
10
+ threads = 4
11
+ format = "svg"
12
+ # preset = "nature" # 取消注释启用默认预设
13
+ # verbose = false
14
+ # quiet = false
15
+
16
+ # 自定义画布尺寸(0=自动)
17
+ [canvas]
18
+ width = 0
19
+ height = 0
tbtools_cli/config.py ADDED
@@ -0,0 +1,43 @@
1
+ """配置文件加载 — ~/.config/tbtools-cli/config.toml"""
2
+ import os
3
+
4
+ try:
5
+ import tomllib
6
+ except ImportError:
7
+ tomllib = None # type: ignore[assignment]
8
+
9
+ DEFAULT_CONFIG_PATH = os.path.expanduser("~/.config/tbtools-cli/config.toml")
10
+
11
+ _config_cache: tuple[str, dict] | None = None # (config路径, 数据)
12
+
13
+ def load_config():
14
+ """加载配置文件。返回 dict(可能为空)。
15
+
16
+ _config_cache 缓存 (路径, 数据)——TBTOOLS_CONFIG env 变化时自动重读
17
+ (第十四轮审计: 原缓存不感知 env 变化,测试/库场景拿旧配置)。
18
+ """
19
+ global _config_cache
20
+ path = os.environ.get("TBTOOLS_CONFIG", DEFAULT_CONFIG_PATH)
21
+ if _config_cache is not None and _config_cache[0] == path:
22
+ return _config_cache[1]
23
+ if not tomllib:
24
+ return {}
25
+ if not os.path.isfile(path):
26
+ return {}
27
+ try:
28
+ with open(path, "rb") as f:
29
+ _config_cache = (path, tomllib.load(f))
30
+ except Exception:
31
+ _config_cache = (path, {})
32
+ return _config_cache[1]
33
+
34
+ def get_default(key, fallback=None):
35
+ """获取默认值(配置文件 < 环境变量 < 命令行)"""
36
+ cfg = load_config()
37
+ defaults = cfg.get("defaults", {})
38
+ return defaults.get(key, fallback)
39
+
40
+ def get_jar():
41
+ """获取 JAR 路径(配置文件优先)"""
42
+ cfg = load_config()
43
+ return cfg.get("jar", "")