pufprobe 0.5.0__tar.gz

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 (75) hide show
  1. pufprobe-0.5.0/LICENSE +21 -0
  2. pufprobe-0.5.0/PKG-INFO +226 -0
  3. pufprobe-0.5.0/README.md +185 -0
  4. pufprobe-0.5.0/pyproject.toml +70 -0
  5. pufprobe-0.5.0/setup.cfg +4 -0
  6. pufprobe-0.5.0/src/pufprobe/__init__.py +10 -0
  7. pufprobe-0.5.0/src/pufprobe/__main__.py +6 -0
  8. pufprobe-0.5.0/src/pufprobe/annotate/__init__.py +1 -0
  9. pufprobe-0.5.0/src/pufprobe/annotate/backfill.py +247 -0
  10. pufprobe-0.5.0/src/pufprobe/annotate/pipeline.py +72 -0
  11. pufprobe-0.5.0/src/pufprobe/cli.py +231 -0
  12. pufprobe-0.5.0/src/pufprobe/clustering/__init__.py +1 -0
  13. pufprobe-0.5.0/src/pufprobe/clustering/mmseqs.py +103 -0
  14. pufprobe-0.5.0/src/pufprobe/clustering/pycluster.py +149 -0
  15. pufprobe-0.5.0/src/pufprobe/config.py +154 -0
  16. pufprobe-0.5.0/src/pufprobe/context/__init__.py +1 -0
  17. pufprobe-0.5.0/src/pufprobe/context/microsynteny.py +65 -0
  18. pufprobe-0.5.0/src/pufprobe/context/operons.py +74 -0
  19. pufprobe-0.5.0/src/pufprobe/context/phyloprofile.py +75 -0
  20. pufprobe-0.5.0/src/pufprobe/context/pipeline.py +264 -0
  21. pufprobe-0.5.0/src/pufprobe/embed/__init__.py +1 -0
  22. pufprobe-0.5.0/src/pufprobe/embed/esm.py +133 -0
  23. pufprobe-0.5.0/src/pufprobe/embed/fallback.py +62 -0
  24. pufprobe-0.5.0/src/pufprobe/embed/pipeline.py +314 -0
  25. pufprobe-0.5.0/src/pufprobe/externals.py +162 -0
  26. pufprobe-0.5.0/src/pufprobe/features.py +132 -0
  27. pufprobe-0.5.0/src/pufprobe/fold/__init__.py +1 -0
  28. pufprobe-0.5.0/src/pufprobe/fold/esmfold.py +147 -0
  29. pufprobe-0.5.0/src/pufprobe/fold/pipeline.py +183 -0
  30. pufprobe-0.5.0/src/pufprobe/geneqc/__init__.py +1 -0
  31. pufprobe-0.5.0/src/pufprobe/geneqc/classifier.py +162 -0
  32. pufprobe-0.5.0/src/pufprobe/io_utils.py +82 -0
  33. pufprobe-0.5.0/src/pufprobe/logging_utils.py +28 -0
  34. pufprobe-0.5.0/src/pufprobe/models.py +239 -0
  35. pufprobe-0.5.0/src/pufprobe/ontology.py +66 -0
  36. pufprobe-0.5.0/src/pufprobe/prepare/__init__.py +1 -0
  37. pufprobe-0.5.0/src/pufprobe/prepare/gbk.py +176 -0
  38. pufprobe-0.5.0/src/pufprobe/prepare/gff.py +216 -0
  39. pufprobe-0.5.0/src/pufprobe/prepare/pipeline.py +195 -0
  40. pufprobe-0.5.0/src/pufprobe/rank/__init__.py +1 -0
  41. pufprobe-0.5.0/src/pufprobe/rank/calibrate.py +186 -0
  42. pufprobe-0.5.0/src/pufprobe/rank/fuse.py +413 -0
  43. pufprobe-0.5.0/src/pufprobe/rank/pipeline.py +139 -0
  44. pufprobe-0.5.0/src/pufprobe/rank/priority.py +98 -0
  45. pufprobe-0.5.0/src/pufprobe/report/__init__.py +1 -0
  46. pufprobe-0.5.0/src/pufprobe/report/html_report.py +270 -0
  47. pufprobe-0.5.0/src/pufprobe/report/pipeline.py +113 -0
  48. pufprobe-0.5.0/src/pufprobe/search/__init__.py +1 -0
  49. pufprobe-0.5.0/src/pufprobe/search/foldseek.py +245 -0
  50. pufprobe-0.5.0/src/pufprobe/search/hhblits.py +124 -0
  51. pufprobe-0.5.0/src/pufprobe/search/idmapping.py +197 -0
  52. pufprobe-0.5.0/src/pufprobe/search/mmseqs_search.py +214 -0
  53. pufprobe-0.5.0/src/pufprobe/search/pipeline.py +125 -0
  54. pufprobe-0.5.0/src/pufprobe/search/sifts.py +71 -0
  55. pufprobe-0.5.0/src/pufprobe/workdir.py +100 -0
  56. pufprobe-0.5.0/src/pufprobe.egg-info/PKG-INFO +226 -0
  57. pufprobe-0.5.0/src/pufprobe.egg-info/SOURCES.txt +73 -0
  58. pufprobe-0.5.0/src/pufprobe.egg-info/dependency_links.txt +1 -0
  59. pufprobe-0.5.0/src/pufprobe.egg-info/entry_points.txt +2 -0
  60. pufprobe-0.5.0/src/pufprobe.egg-info/requires.txt +23 -0
  61. pufprobe-0.5.0/src/pufprobe.egg-info/top_level.txt +1 -0
  62. pufprobe-0.5.0/tests/test_clustering.py +50 -0
  63. pufprobe-0.5.0/tests/test_context.py +63 -0
  64. pufprobe-0.5.0/tests/test_embed.py +123 -0
  65. pufprobe-0.5.0/tests/test_fold.py +88 -0
  66. pufprobe-0.5.0/tests/test_geneqc.py +51 -0
  67. pufprobe-0.5.0/tests/test_hypothetical_faa.py +72 -0
  68. pufprobe-0.5.0/tests/test_idmapping.py +83 -0
  69. pufprobe-0.5.0/tests/test_ontology.py +37 -0
  70. pufprobe-0.5.0/tests/test_prepare.py +55 -0
  71. pufprobe-0.5.0/tests/test_rank.py +413 -0
  72. pufprobe-0.5.0/tests/test_real_formats.py +123 -0
  73. pufprobe-0.5.0/tests/test_report_annotate.py +162 -0
  74. pufprobe-0.5.0/tests/test_search.py +288 -0
  75. pufprobe-0.5.0/tests/test_smoke.py +74 -0
pufprobe-0.5.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LLQ95 and the PUFprobe contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,226 @@
1
+ Metadata-Version: 2.4
2
+ Name: pufprobe
3
+ Version: 0.5.0
4
+ Summary: Second-stage functional inference for hypothetical proteins in bacterial genomes
5
+ Author: LLQ95
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/LLQ95/PUFprobe
8
+ Project-URL: Repository, https://github.com/LLQ95/PUFprobe
9
+ Project-URL: Issues, https://github.com/LLQ95/PUFprobe/issues
10
+ Project-URL: Changelog, https://github.com/LLQ95/PUFprobe/blob/main/CHANGELOG.md
11
+ Keywords: bioinformatics,genome annotation,hypothetical proteins,protein function prediction,protein language models
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
17
+ Classifier: Intended Audience :: Science/Research
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: click>=8.0
22
+ Requires-Dist: numpy>=1.21
23
+ Provides-Extra: ml
24
+ Requires-Dist: torch>=2.0; extra == "ml"
25
+ Requires-Dist: fair-esm>=2.0; extra == "ml"
26
+ Requires-Dist: einops>=0.6; extra == "ml"
27
+ Requires-Dist: scikit-learn>=1.1; extra == "ml"
28
+ Provides-Extra: cluster
29
+ Requires-Dist: igraph>=0.10; extra == "cluster"
30
+ Requires-Dist: leidenalg>=0.9; extra == "cluster"
31
+ Provides-Extra: full
32
+ Requires-Dist: torch>=2.0; extra == "full"
33
+ Requires-Dist: fair-esm>=2.0; extra == "full"
34
+ Requires-Dist: einops>=0.6; extra == "full"
35
+ Requires-Dist: scikit-learn>=1.1; extra == "full"
36
+ Requires-Dist: igraph>=0.10; extra == "full"
37
+ Requires-Dist: leidenalg>=0.9; extra == "full"
38
+ Provides-Extra: test
39
+ Requires-Dist: pytest>=7.0; extra == "test"
40
+ Dynamic: license-file
41
+
42
+ # PUFprobe
43
+
44
+ PUFprobe is a second-stage functional inference layer for bacterial genomes
45
+ annotated with [Bakta](https://github.com/oschwengers/bakta),
46
+ [Prokka](https://github.com/tseemann/prokka) or NCBI PGAP. These pipelines
47
+ leave between roughly 10% and 50% of the coding sequences labelled as
48
+ `hypothetical protein`, `uncharacterized protein` or domains of unknown
49
+ function. PUFprobe takes those records and combines protein language model
50
+ embeddings, predicted structures and structure searches, ligand-binding
51
+ pocket evidence and genomic-context signals into calibrated, auditable
52
+ functional predictions, while moving likely false ORFs out of the queue and
53
+ ranking genuinely unanchored families for wet-lab follow-up.
54
+
55
+ The design follows a detect-warn-skip policy: every heavy dependency
56
+ (ESM-2, ESMFold, MMseqs2, Foldseek, HH-suite) is optional. The full pipeline
57
+ runs on a laptop CPU with lightweight sequence features, and each model or
58
+ external tool adds one more evidence channel when it is available.
59
+
60
+ ![PUFprobe architecture and data flow](docs/architecture.svg)
61
+
62
+ ## Installation
63
+
64
+ The core package only needs Python 3.9 or newer.
65
+
66
+ ```bash
67
+ git clone https://github.com/LLQ95/PUFprobe.git
68
+ cd PUFprobe
69
+ pip install -e .
70
+ ```
71
+
72
+ Install the optional machine-learning dependencies for ESM-2 embeddings and
73
+ ESMFold structure prediction (a CUDA GPU is recommended):
74
+
75
+ ```bash
76
+ pip install -e ".[ml]" # torch + scikit-learn
77
+ pip install -e ".[cluster]" # igraph + leidenalg clustering fallback
78
+ pip install -e ".[full]" # everything
79
+ ```
80
+
81
+ External binaries such as MMseqs2 and Foldseek are installed separately; see
82
+ [docs/server_setup.md](docs/server_setup.md) for a copy-pasteable Linux
83
+ server setup, including database downloads. Run `pufprobe doctor` to list
84
+ what is available in the current environment.
85
+
86
+ ## Quick start
87
+
88
+ PUFprobe reads the GFF3/GBK and protein FASTA produced by your annotation
89
+ pipeline and writes all intermediate and final files into one working
90
+ directory. The eight subcommands are run in order:
91
+
92
+ ```bash
93
+ pufprobe --workdir work prepare --input annotations/
94
+ pufprobe --workdir work embed
95
+ pufprobe --workdir work fold
96
+ pufprobe --workdir work search --dbdir databases/
97
+ pufprobe --workdir work context
98
+ pufprobe --workdir work rank
99
+ pufprobe --workdir work report
100
+ pufprobe --workdir work annotate
101
+ ```
102
+
103
+ On a machine without GPUs or external tools, the same flow runs with the CPU
104
+ fallback:
105
+
106
+ ```bash
107
+ pufprobe --cpu --workdir work prepare --input examples/demo_genome
108
+ pufprobe --cpu --workdir work embed --fallback-only
109
+ pufprobe --cpu --workdir work fold
110
+ pufprobe --cpu --workdir work search
111
+ pufprobe --cpu --workdir work context
112
+ pufprobe --cpu --workdir work rank
113
+ pufprobe --cpu --workdir work report
114
+ pufprobe --cpu --workdir work annotate
115
+ ```
116
+
117
+ Every command resumes from a completion marker; add `--force` to rerun a
118
+ stage.
119
+
120
+ ## Subcommands
121
+
122
+ `prepare` parses Bakta/Prokka GFF3, GenBank and `.faa` files, aligns the
123
+ protein sequences to the CDS records and runs the true-gene quality control.
124
+ Records that look like false ORFs (very short, low-complexity, anomalous
125
+ overlap or extreme composition) are flagged with an interpretable score and
126
+ moved out of the inference queue. `--include-smorf` keeps sub-30 aa
127
+ candidates through a permissive small-protein path.
128
+
129
+ `embed` computes one vector per candidate. It uses ESM-2 when torch and the
130
+ model weights are available, loads vectors from `--precomputed` otherwise, or
131
+ falls back to pure-Python sequence features with `--fallback-only`. It then
132
+ clusters the candidates into families (MMseqs2 when installed, an embedding
133
+ graph fallback otherwise) and selects one representative per family.
134
+
135
+ `fold` predicts structures for the family representatives only. ESMFold is
136
+ used when available; structures can also be supplied from `--precomputed`. A
137
+ pLDDT quality gate marks low-confidence models so that structure-based
138
+ channels do not over-interpret them.
139
+
140
+ `search` runs the remote-homology channels, MMseqs2, Foldseek and HHblits by
141
+ default (TM-Vec optional), against versioned databases under `--dbdir`, and
142
+ normalizes every hit into a unified evidence record. Missing tools or
143
+ databases disable one channel without stopping the run.
144
+
145
+ `context` computes operon and gene-neighbour coupling, phylogenetic profiles
146
+ across samples and cross-strain micro-synteny in pure Python. When CARD or
147
+ VFDB references are supplied with `--card` or `--vfdb`, candidates coupled
148
+ to resistance or virulence genes are flagged.
149
+
150
+ `rank` fuses the evidence channels. Trained learning-to-rank weights are
151
+ used when supplied with `--weights`; otherwise transparent rule weights from
152
+ the configuration are applied. Confidence scores are calibrated, high
153
+ confidence requires agreement between two independent evidence groups, and
154
+ unanchored families receive a wet-lab priority score.
155
+
156
+ `report` writes a machine-readable JSON dump together with auditable
157
+ HTML/Markdown reports that list every channel behind each prediction.
158
+
159
+ `annotate` backfills the high-confidence predictions into new GFF3, GBK and
160
+ renamed FASTA files under the working directory. The original annotation
161
+ files are never modified.
162
+
163
+ ## Outputs
164
+
165
+ The working directory contains one numbered folder per stage, along with run
166
+ metadata and logs:
167
+
168
+ ```text
169
+ work/
170
+ ├── metadata.json
171
+ ├── logs/pufprobe.log
172
+ ├── 00_prepare/ samples.json, cds_records.json
173
+ ├── 01_qc/ qc_summary.json
174
+ ├── 02_embed/ embeddings.npz, manifest.json
175
+ ├── 03_cluster/ families.json, clusters.tsv, representatives.faa
176
+ ├── 04_fold/ structures/, fold_quality.tsv
177
+ ├── 05_search/ *_raw.tsv, search_evidence.json
178
+ ├── 06_context/ neighbours.tsv, phyloprofiles.tsv, context_evidence.json
179
+ ├── 07_rank/ predictions.json, calibration.json, priorities.tsv
180
+ ├── 08_report/ evidence.json, report.html, report.md
181
+ └── 09_annotate/ *.pufprobe.gff3, *.pufprobe.faa, changes.tsv
182
+ ```
183
+
184
+ Each prediction in the reports carries the supporting channel, target
185
+ identifier, raw and calibrated scores, so that every assigned function can be
186
+ traced back to its evidence.
187
+
188
+ ## Try the bundled example
189
+
190
+ A small synthetic two-genome dataset is included under
191
+ [examples/demo_genome](examples/demo_genome):
192
+
193
+ ```bash
194
+ pufprobe --cpu --workdir _demo prepare --input examples/demo_genome
195
+ pufprobe --cpu --workdir _demo embed --fallback-only
196
+ pufprobe --cpu --workdir _demo context
197
+ pufprobe --cpu --workdir _demo rank
198
+ pufprobe --cpu --workdir _demo report
199
+ ```
200
+
201
+ ## Tests
202
+
203
+ ```bash
204
+ pip install -e ".[test]"
205
+ pytest
206
+ ```
207
+
208
+ The test suite contains unit tests for every stage and an end-to-end smoke
209
+ test that runs the complete CPU fallback pipeline on the bundled examples,
210
+ without any external binaries or GPUs.
211
+
212
+ ## Server deployment
213
+
214
+ For running PUFprobe on a Linux HPC node (Bakta/Prokka in existing conda
215
+ environments, MMseqs2/Foldseek/HH-suite databases, GPU or CPU), the
216
+ `server/` directory provides an idempotent, resumable script bundle and a
217
+ Chinese step-by-step runbook:
218
+
219
+ - `server/README_runbook.md` — full walkthrough from code sync to full run
220
+ - `server/configs/server_config.yaml` — paths, threads, mirrors, database tiers
221
+ - `00_setup_env.sh` → `01_download_dbs.sh` → `02_annotate.sh` →
222
+ `03_run_pufprobe.sh` → `04_summary.sh`
223
+
224
+ ## License
225
+
226
+ PUFprobe is released under the MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,185 @@
1
+ # PUFprobe
2
+
3
+ PUFprobe is a second-stage functional inference layer for bacterial genomes
4
+ annotated with [Bakta](https://github.com/oschwengers/bakta),
5
+ [Prokka](https://github.com/tseemann/prokka) or NCBI PGAP. These pipelines
6
+ leave between roughly 10% and 50% of the coding sequences labelled as
7
+ `hypothetical protein`, `uncharacterized protein` or domains of unknown
8
+ function. PUFprobe takes those records and combines protein language model
9
+ embeddings, predicted structures and structure searches, ligand-binding
10
+ pocket evidence and genomic-context signals into calibrated, auditable
11
+ functional predictions, while moving likely false ORFs out of the queue and
12
+ ranking genuinely unanchored families for wet-lab follow-up.
13
+
14
+ The design follows a detect-warn-skip policy: every heavy dependency
15
+ (ESM-2, ESMFold, MMseqs2, Foldseek, HH-suite) is optional. The full pipeline
16
+ runs on a laptop CPU with lightweight sequence features, and each model or
17
+ external tool adds one more evidence channel when it is available.
18
+
19
+ ![PUFprobe architecture and data flow](docs/architecture.svg)
20
+
21
+ ## Installation
22
+
23
+ The core package only needs Python 3.9 or newer.
24
+
25
+ ```bash
26
+ git clone https://github.com/LLQ95/PUFprobe.git
27
+ cd PUFprobe
28
+ pip install -e .
29
+ ```
30
+
31
+ Install the optional machine-learning dependencies for ESM-2 embeddings and
32
+ ESMFold structure prediction (a CUDA GPU is recommended):
33
+
34
+ ```bash
35
+ pip install -e ".[ml]" # torch + scikit-learn
36
+ pip install -e ".[cluster]" # igraph + leidenalg clustering fallback
37
+ pip install -e ".[full]" # everything
38
+ ```
39
+
40
+ External binaries such as MMseqs2 and Foldseek are installed separately; see
41
+ [docs/server_setup.md](docs/server_setup.md) for a copy-pasteable Linux
42
+ server setup, including database downloads. Run `pufprobe doctor` to list
43
+ what is available in the current environment.
44
+
45
+ ## Quick start
46
+
47
+ PUFprobe reads the GFF3/GBK and protein FASTA produced by your annotation
48
+ pipeline and writes all intermediate and final files into one working
49
+ directory. The eight subcommands are run in order:
50
+
51
+ ```bash
52
+ pufprobe --workdir work prepare --input annotations/
53
+ pufprobe --workdir work embed
54
+ pufprobe --workdir work fold
55
+ pufprobe --workdir work search --dbdir databases/
56
+ pufprobe --workdir work context
57
+ pufprobe --workdir work rank
58
+ pufprobe --workdir work report
59
+ pufprobe --workdir work annotate
60
+ ```
61
+
62
+ On a machine without GPUs or external tools, the same flow runs with the CPU
63
+ fallback:
64
+
65
+ ```bash
66
+ pufprobe --cpu --workdir work prepare --input examples/demo_genome
67
+ pufprobe --cpu --workdir work embed --fallback-only
68
+ pufprobe --cpu --workdir work fold
69
+ pufprobe --cpu --workdir work search
70
+ pufprobe --cpu --workdir work context
71
+ pufprobe --cpu --workdir work rank
72
+ pufprobe --cpu --workdir work report
73
+ pufprobe --cpu --workdir work annotate
74
+ ```
75
+
76
+ Every command resumes from a completion marker; add `--force` to rerun a
77
+ stage.
78
+
79
+ ## Subcommands
80
+
81
+ `prepare` parses Bakta/Prokka GFF3, GenBank and `.faa` files, aligns the
82
+ protein sequences to the CDS records and runs the true-gene quality control.
83
+ Records that look like false ORFs (very short, low-complexity, anomalous
84
+ overlap or extreme composition) are flagged with an interpretable score and
85
+ moved out of the inference queue. `--include-smorf` keeps sub-30 aa
86
+ candidates through a permissive small-protein path.
87
+
88
+ `embed` computes one vector per candidate. It uses ESM-2 when torch and the
89
+ model weights are available, loads vectors from `--precomputed` otherwise, or
90
+ falls back to pure-Python sequence features with `--fallback-only`. It then
91
+ clusters the candidates into families (MMseqs2 when installed, an embedding
92
+ graph fallback otherwise) and selects one representative per family.
93
+
94
+ `fold` predicts structures for the family representatives only. ESMFold is
95
+ used when available; structures can also be supplied from `--precomputed`. A
96
+ pLDDT quality gate marks low-confidence models so that structure-based
97
+ channels do not over-interpret them.
98
+
99
+ `search` runs the remote-homology channels, MMseqs2, Foldseek and HHblits by
100
+ default (TM-Vec optional), against versioned databases under `--dbdir`, and
101
+ normalizes every hit into a unified evidence record. Missing tools or
102
+ databases disable one channel without stopping the run.
103
+
104
+ `context` computes operon and gene-neighbour coupling, phylogenetic profiles
105
+ across samples and cross-strain micro-synteny in pure Python. When CARD or
106
+ VFDB references are supplied with `--card` or `--vfdb`, candidates coupled
107
+ to resistance or virulence genes are flagged.
108
+
109
+ `rank` fuses the evidence channels. Trained learning-to-rank weights are
110
+ used when supplied with `--weights`; otherwise transparent rule weights from
111
+ the configuration are applied. Confidence scores are calibrated, high
112
+ confidence requires agreement between two independent evidence groups, and
113
+ unanchored families receive a wet-lab priority score.
114
+
115
+ `report` writes a machine-readable JSON dump together with auditable
116
+ HTML/Markdown reports that list every channel behind each prediction.
117
+
118
+ `annotate` backfills the high-confidence predictions into new GFF3, GBK and
119
+ renamed FASTA files under the working directory. The original annotation
120
+ files are never modified.
121
+
122
+ ## Outputs
123
+
124
+ The working directory contains one numbered folder per stage, along with run
125
+ metadata and logs:
126
+
127
+ ```text
128
+ work/
129
+ ├── metadata.json
130
+ ├── logs/pufprobe.log
131
+ ├── 00_prepare/ samples.json, cds_records.json
132
+ ├── 01_qc/ qc_summary.json
133
+ ├── 02_embed/ embeddings.npz, manifest.json
134
+ ├── 03_cluster/ families.json, clusters.tsv, representatives.faa
135
+ ├── 04_fold/ structures/, fold_quality.tsv
136
+ ├── 05_search/ *_raw.tsv, search_evidence.json
137
+ ├── 06_context/ neighbours.tsv, phyloprofiles.tsv, context_evidence.json
138
+ ├── 07_rank/ predictions.json, calibration.json, priorities.tsv
139
+ ├── 08_report/ evidence.json, report.html, report.md
140
+ └── 09_annotate/ *.pufprobe.gff3, *.pufprobe.faa, changes.tsv
141
+ ```
142
+
143
+ Each prediction in the reports carries the supporting channel, target
144
+ identifier, raw and calibrated scores, so that every assigned function can be
145
+ traced back to its evidence.
146
+
147
+ ## Try the bundled example
148
+
149
+ A small synthetic two-genome dataset is included under
150
+ [examples/demo_genome](examples/demo_genome):
151
+
152
+ ```bash
153
+ pufprobe --cpu --workdir _demo prepare --input examples/demo_genome
154
+ pufprobe --cpu --workdir _demo embed --fallback-only
155
+ pufprobe --cpu --workdir _demo context
156
+ pufprobe --cpu --workdir _demo rank
157
+ pufprobe --cpu --workdir _demo report
158
+ ```
159
+
160
+ ## Tests
161
+
162
+ ```bash
163
+ pip install -e ".[test]"
164
+ pytest
165
+ ```
166
+
167
+ The test suite contains unit tests for every stage and an end-to-end smoke
168
+ test that runs the complete CPU fallback pipeline on the bundled examples,
169
+ without any external binaries or GPUs.
170
+
171
+ ## Server deployment
172
+
173
+ For running PUFprobe on a Linux HPC node (Bakta/Prokka in existing conda
174
+ environments, MMseqs2/Foldseek/HH-suite databases, GPU or CPU), the
175
+ `server/` directory provides an idempotent, resumable script bundle and a
176
+ Chinese step-by-step runbook:
177
+
178
+ - `server/README_runbook.md` — full walkthrough from code sync to full run
179
+ - `server/configs/server_config.yaml` — paths, threads, mirrors, database tiers
180
+ - `00_setup_env.sh` → `01_download_dbs.sh` → `02_annotate.sh` →
181
+ `03_run_pufprobe.sh` → `04_summary.sh`
182
+
183
+ ## License
184
+
185
+ PUFprobe is released under the MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,70 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pufprobe"
7
+ version = "0.5.0"
8
+ description = "Second-stage functional inference for hypothetical proteins in bacterial genomes"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "LLQ95" }]
13
+ keywords = [
14
+ "bioinformatics",
15
+ "genome annotation",
16
+ "hypothetical proteins",
17
+ "protein function prediction",
18
+ "protein language models",
19
+ ]
20
+ classifiers = [
21
+ "Programming Language :: Python :: 3",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Operating System :: POSIX :: Linux",
24
+ "Operating System :: Microsoft :: Windows",
25
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
26
+ "Intended Audience :: Science/Research",
27
+ ]
28
+ dependencies = [
29
+ "click>=8.0",
30
+ "numpy>=1.21",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ ml = [
35
+ "torch>=2.0",
36
+ "fair-esm>=2.0",
37
+ "einops>=0.6",
38
+ "scikit-learn>=1.1",
39
+ ]
40
+ cluster = [
41
+ "igraph>=0.10",
42
+ "leidenalg>=0.9",
43
+ ]
44
+ full = [
45
+ "torch>=2.0",
46
+ "fair-esm>=2.0",
47
+ "einops>=0.6",
48
+ "scikit-learn>=1.1",
49
+ "igraph>=0.10",
50
+ "leidenalg>=0.9",
51
+ ]
52
+ test = [
53
+ "pytest>=7.0",
54
+ ]
55
+
56
+ [project.urls]
57
+ Homepage = "https://github.com/LLQ95/PUFprobe"
58
+ Repository = "https://github.com/LLQ95/PUFprobe"
59
+ Issues = "https://github.com/LLQ95/PUFprobe/issues"
60
+ Changelog = "https://github.com/LLQ95/PUFprobe/blob/main/CHANGELOG.md"
61
+
62
+ [project.scripts]
63
+ pufprobe = "pufprobe.cli:cli"
64
+
65
+ [tool.setuptools.packages.find]
66
+ where = ["src"]
67
+
68
+ [tool.pytest.ini_options]
69
+ testpaths = ["tests"]
70
+ addopts = "-ra"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,10 @@
1
+ """PUFprobe: second-stage functional inference for hypothetical proteins.
2
+
3
+ PUFprobe consumes the output of Bakta, Prokka or NCBI PGAP and adds a
4
+ second-stage inference layer for CDS records annotated as hypothetical
5
+ protein, uncharacterized protein or domains of unknown function.
6
+ """
7
+
8
+ __version__ = "0.4.0"
9
+
10
+ __all__ = ["__version__"]
@@ -0,0 +1,6 @@
1
+ """Allow ``python -m pufprobe`` as an alias for the console script."""
2
+
3
+ from pufprobe.cli import cli
4
+
5
+ if __name__ == "__main__":
6
+ cli()
@@ -0,0 +1 @@
1
+ """annotate stage: backfill predictions into GFF3/GBK/FAA files."""