specimux-suite 0.1.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.
- specimux_suite-0.1.0/LICENSE +28 -0
- specimux_suite-0.1.0/PKG-INFO +320 -0
- specimux_suite-0.1.0/README.md +283 -0
- specimux_suite-0.1.0/pyproject.toml +64 -0
- specimux_suite-0.1.0/setup.cfg +4 -0
- specimux_suite-0.1.0/src/specimux_suite/__init__.py +3 -0
- specimux_suite-0.1.0/src/specimux_suite/cli.py +288 -0
- specimux_suite-0.1.0/src/specimux_suite/config.py +236 -0
- specimux_suite-0.1.0/src/specimux_suite/console.py +296 -0
- specimux_suite-0.1.0/src/specimux_suite/events.py +233 -0
- specimux_suite-0.1.0/src/specimux_suite/inat.py +221 -0
- specimux_suite-0.1.0/src/specimux_suite/pipeline.py +902 -0
- specimux_suite-0.1.0/src/specimux_suite/profiles/__init__.py +314 -0
- specimux_suite-0.1.0/src/specimux_suite/profiles/default.yaml +7 -0
- specimux_suite-0.1.0/src/specimux_suite/profiles/herbarium.yaml +10 -0
- specimux_suite-0.1.0/src/specimux_suite/replay.py +68 -0
- specimux_suite-0.1.0/src/specimux_suite/runners/__init__.py +0 -0
- specimux_suite-0.1.0/src/specimux_suite/runners/identify_runner.py +395 -0
- specimux_suite-0.1.0/src/specimux_suite/runners/specimux_runner.py +212 -0
- specimux_suite-0.1.0/src/specimux_suite/runners/speconsense_runner.py +216 -0
- specimux_suite-0.1.0/src/specimux_suite/runners/summarize_runner.py +172 -0
- specimux_suite-0.1.0/src/specimux_suite/scheduler.py +250 -0
- specimux_suite-0.1.0/src/specimux_suite/state.py +339 -0
- specimux_suite-0.1.0/src/specimux_suite/util.py +171 -0
- specimux_suite-0.1.0/src/specimux_suite/watcher.py +236 -0
- specimux_suite-0.1.0/src/specimux_suite/web/__init__.py +0 -0
- specimux_suite-0.1.0/src/specimux_suite/web/api.py +4 -0
- specimux_suite-0.1.0/src/specimux_suite/web/server.py +246 -0
- specimux_suite-0.1.0/src/specimux_suite/web/static/index.html +2196 -0
- specimux_suite-0.1.0/src/specimux_suite/web/static/vendor/qrcode.min.js +7 -0
- specimux_suite-0.1.0/src/specimux_suite.egg-info/PKG-INFO +320 -0
- specimux_suite-0.1.0/src/specimux_suite.egg-info/SOURCES.txt +43 -0
- specimux_suite-0.1.0/src/specimux_suite.egg-info/dependency_links.txt +1 -0
- specimux_suite-0.1.0/src/specimux_suite.egg-info/entry_points.txt +3 -0
- specimux_suite-0.1.0/src/specimux_suite.egg-info/requires.txt +14 -0
- specimux_suite-0.1.0/src/specimux_suite.egg-info/top_level.txt +1 -0
- specimux_suite-0.1.0/tests/test_config.py +107 -0
- specimux_suite-0.1.0/tests/test_console.py +153 -0
- specimux_suite-0.1.0/tests/test_events.py +169 -0
- specimux_suite-0.1.0/tests/test_pipeline.py +413 -0
- specimux_suite-0.1.0/tests/test_replay.py +69 -0
- specimux_suite-0.1.0/tests/test_runners.py +426 -0
- specimux_suite-0.1.0/tests/test_scheduler.py +322 -0
- specimux_suite-0.1.0/tests/test_state.py +380 -0
- specimux_suite-0.1.0/tests/test_watcher.py +37 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026, Josh Walker
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: specimux-suite
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Orchestration and UX layer for the Mycomap fungal DNA barcoding pipeline
|
|
5
|
+
Author-email: Josh Walker <joshowalker@yahoo.com>
|
|
6
|
+
License: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/joshuaowalker/specimux-suite
|
|
8
|
+
Project-URL: Repository, https://github.com/joshuaowalker/specimux-suite
|
|
9
|
+
Project-URL: Issues, https://github.com/joshuaowalker/specimux-suite/issues
|
|
10
|
+
Keywords: bioinformatics,nanopore,sequencing,barcoding,pipeline,dashboard
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Operating System :: MacOS
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: specimux>=0.7.2
|
|
24
|
+
Requires-Dist: speconsense>=0.7.0
|
|
25
|
+
Requires-Dist: watchdog>=3.0
|
|
26
|
+
Requires-Dist: fastapi>=0.104
|
|
27
|
+
Requires-Dist: uvicorn>=0.24
|
|
28
|
+
Requires-Dist: sse-starlette>=1.8
|
|
29
|
+
Requires-Dist: adjusted-identity>=0.2.4
|
|
30
|
+
Requires-Dist: biopython>=1.82
|
|
31
|
+
Requires-Dist: pyyaml>=5.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# specimux-suite
|
|
39
|
+
|
|
40
|
+
> **Early preview release.** This project is under active development — APIs, event formats, and CLI options may change between versions. Feedback and bug reports are welcome at [github.com/joshuaowalker/specimux-suite/issues](https://github.com/joshuaowalker/specimux-suite/issues).
|
|
41
|
+
|
|
42
|
+
Orchestration and real-time dashboard for the [Mycomap](https://mycomap.org) fungal DNA barcoding pipeline. Manages the full workflow from raw nanopore reads through demultiplexing, consensus generation, variant summarization, and species identification.
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
Requires Python 3.11+.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install specimux-suite
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or, for development, from a source checkout:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install -e '.[dev]'
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The pipeline invokes external bioinformatics tools as subprocesses — **specimux**, **speconsense**, and **vsearch** must be installed and available on your `PATH`.
|
|
59
|
+
|
|
60
|
+
| Tool | Purpose | Required |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| [specimux](https://github.com/joshuaowalker/specimux) | Demultiplexing reads by primer pool and specimen | Yes |
|
|
63
|
+
| [speconsense](https://github.com/joshuaowalker/speconsense) | Consensus sequence generation and variant summarization | Yes |
|
|
64
|
+
| [vsearch](https://github.com/torognes/vsearch) | Reference database matching for species identification | Only if `--reference-db` is provided |
|
|
65
|
+
|
|
66
|
+
See each tool's repository for installation instructions. These tools have system-level dependencies that pip cannot install:
|
|
67
|
+
|
|
68
|
+
| Dependency | Required by | Install |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| [SPOA](https://github.com/rvaser/spoa) | speconsense | `conda install bioconda::spoa` |
|
|
71
|
+
| [MCL](https://micans.org/mcl/) | speconsense (optional, recommended) | `conda install bioconda::mcl` |
|
|
72
|
+
| [vsearch](https://github.com/torognes/vsearch) | speconsense (scalability mode), specimux-suite (identification) | `conda install bioconda::vsearch` |
|
|
73
|
+
|
|
74
|
+
## Quick start
|
|
75
|
+
|
|
76
|
+
### Batch mode
|
|
77
|
+
|
|
78
|
+
Process a single FASTQ file end-to-end:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
specimux-suite batch primers.fasta specimens.tsv reads.fastq \
|
|
82
|
+
--reference-db references.fasta
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Live mode
|
|
86
|
+
|
|
87
|
+
Watch a directory for new FASTQ files (e.g., from a running MinION sequencer) and process them incrementally as they appear:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
specimux-suite live primers.fasta specimens.tsv /path/to/minknow/output/ \
|
|
91
|
+
--reference-db references.fasta
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
A web dashboard opens automatically at `http://127.0.0.1:8077` showing real-time progress. Press Ctrl+C to finalize — the pipeline will drain remaining files, process all eligible specimens regardless of threshold, and run summarization before exiting.
|
|
95
|
+
|
|
96
|
+
### Profiles
|
|
97
|
+
|
|
98
|
+
Profiles bundle pipeline settings and tool configurations into reusable presets:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# List available profiles
|
|
102
|
+
specimux-suite batch --list-profiles
|
|
103
|
+
|
|
104
|
+
# Use a profile
|
|
105
|
+
specimux-suite batch -p herbarium primers.fasta specimens.tsv reads.fastq
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Bundled profiles include `default` (standard settings) and `herbarium` (relaxed thresholds for degraded DNA). Custom profiles can be placed in `~/.config/specimux-suite/profiles/`.
|
|
109
|
+
|
|
110
|
+
## Input files
|
|
111
|
+
|
|
112
|
+
**Primers** — FASTA file containing primer sequences used for demultiplexing.
|
|
113
|
+
|
|
114
|
+
**Specimens** — Tab-separated file with at least `SampleID` and `PrimerPool` columns. Specimen IDs containing an iNaturalist observation ID (e.g., `iNat12345`) enable automatic community taxon lookup for on-target/off-target detection.
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
SampleID PrimerPool
|
|
118
|
+
spec001 pool1
|
|
119
|
+
spec002 pool1
|
|
120
|
+
specimen-B--iNat12345 pool2
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Reads** — Standard FASTQ format (batch mode expects a single file; live mode watches a directory for `*.fastq` files).
|
|
124
|
+
|
|
125
|
+
**Reference database** — Optional FASTA file of reference sequences for species identification via vsearch. The sequence ID (first whitespace-delimited token) is used as the match key. An optional `name="..."` field in the header provides a display name; without it, the name is derived from the ID by replacing underscores with spaces (e.g., `Genus_species_authority` becomes "Genus species").
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
>MycoMap_12345_Trametes_versicolor_US_Indiana name="Trametes versicolor"
|
|
129
|
+
ACGTACGT...
|
|
130
|
+
>MycoMap_67890_Stereum_ostrea_US_Ohio
|
|
131
|
+
TGCATGCA...
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Options
|
|
135
|
+
|
|
136
|
+
### Common options
|
|
137
|
+
|
|
138
|
+
| Option | Default | Description |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| `-p, --profile` | — | Load a suite profile preset |
|
|
141
|
+
| `--list-profiles` | — | List available profiles and exit |
|
|
142
|
+
| `-o, --output-dir` | `specimux-suite-output` | Output directory |
|
|
143
|
+
| `--reference-db` | — | Reference FASTA for identification |
|
|
144
|
+
| `--min-reads` | `30` | Minimum reads before running consensus |
|
|
145
|
+
| `--reprocess-ratio` | `0.5` | Ratio of new/previous reads to trigger reprocessing |
|
|
146
|
+
| `--workers` | half of CPU cores | Number of worker threads |
|
|
147
|
+
| `--identify-min-coverage` | `0.5` | Minimum query/target coverage for identification hits |
|
|
148
|
+
| `--specimux-args` | — | Extra arguments passed through to specimux |
|
|
149
|
+
| `--speconsense-args` | — | Extra arguments passed through to speconsense |
|
|
150
|
+
| `--summarize-args` | — | Extra arguments passed through to speconsense-summarize |
|
|
151
|
+
| `--log-level` | `INFO` | Logging verbosity (`DEBUG`, `INFO`, `WARNING`, `ERROR`) |
|
|
152
|
+
|
|
153
|
+
### Web dashboard options
|
|
154
|
+
|
|
155
|
+
| Option | Default | Description |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `--web-host` | `127.0.0.1` | Dashboard listen address |
|
|
158
|
+
| `--web-port` | `8077` | Dashboard listen port |
|
|
159
|
+
| `--share [N]` | — | Share dashboard on LAN with QR code (optional max client limit, default 20) |
|
|
160
|
+
| `--no-web` | — | Disable the web dashboard |
|
|
161
|
+
| `--no-open` | — | Don't auto-open dashboard in browser |
|
|
162
|
+
|
|
163
|
+
### Live mode options
|
|
164
|
+
|
|
165
|
+
| Option | Default | Description |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `--settle-time` | `30` | Seconds to wait for a file to stabilize before processing |
|
|
168
|
+
| `--presample` | `100` | Reads to subsample for incremental consensus (0 = unlimited) |
|
|
169
|
+
|
|
170
|
+
## Pipeline
|
|
171
|
+
|
|
172
|
+
### Processing stages
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
FASTQ reads
|
|
176
|
+
→ specimux (demultiplex into per-specimen FASTQs)
|
|
177
|
+
→ speconsense (generate consensus sequences per specimen)
|
|
178
|
+
→ vsearch + adjusted-identity (identify species from reference DB)
|
|
179
|
+
→ speconsense-summarize (extract and identify variant sequences)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Scheduling
|
|
183
|
+
|
|
184
|
+
The scheduler uses two-tier prioritization:
|
|
185
|
+
|
|
186
|
+
1. **Never-processed specimens** — prioritized by read count (highest first), processed once they reach `--min-reads`
|
|
187
|
+
2. **Reprocessing candidates** — specimens with enough new reads since last consensus (controlled by `--reprocess-ratio`)
|
|
188
|
+
|
|
189
|
+
In live mode, watched specimens (starred in the dashboard) receive a priority boost and are processed first.
|
|
190
|
+
|
|
191
|
+
Within the reprocessing tier, candidates are ordered by **result confidence** —
|
|
192
|
+
uncertain results are revisited first, since additional depth might change the
|
|
193
|
+
answer:
|
|
194
|
+
|
|
195
|
+
1. **No match** — consensus produced but nothing hit the reference database
|
|
196
|
+
2. **Low identity** — best hit below 90% adjusted identity
|
|
197
|
+
3. **Off-target** — no hit matches the iNaturalist community genus (a
|
|
198
|
+
mycoparasite or yeast contaminant may be dominating the true target), or the
|
|
199
|
+
community genus appears only in a minority cluster
|
|
200
|
+
4. **Marginal** — identity 90–98%, or ambiguous bases in the consensus
|
|
201
|
+
5. **Confident** — ≥98% identity and on-target
|
|
202
|
+
|
|
203
|
+
Uncertain results (the first three) also re-enter the queue at half the
|
|
204
|
+
configured `--reprocess-ratio`, so depth reaches them sooner. Confidence only
|
|
205
|
+
reorders work — confident specimens still reprocess whenever workers are free,
|
|
206
|
+
and finalization always processes every specimen with unprocessed reads,
|
|
207
|
+
regardless of confidence. The dashboard shows a small ↻ chip on each queued
|
|
208
|
+
reprocess candidate with the reason it was prioritized.
|
|
209
|
+
|
|
210
|
+
### Live mode concurrency
|
|
211
|
+
|
|
212
|
+
Consensus jobs read copy-on-write snapshots of their input FASTQs (instant on APFS/btrfs/XFS, a plain copy elsewhere), so when a new FASTQ file stabilizes, specimux demultiplexes it immediately — appending to the live per-specimen files while in-flight consensus jobs keep running on their snapshots. Demultiplexing uses whatever worker threads aren't occupied by consensus jobs, and newly-ready specimens are scheduled as soon as it finishes.
|
|
213
|
+
|
|
214
|
+
## Web dashboard
|
|
215
|
+
|
|
216
|
+
The built-in dashboard provides a real-time view of pipeline progress, streamed via server-sent events (SSE).
|
|
217
|
+
|
|
218
|
+
### Processing tab
|
|
219
|
+
|
|
220
|
+
- Specimen table with status, read count, top identification match, and identity score
|
|
221
|
+
- Color-coded status badges (queued, processing, identified, no match, error)
|
|
222
|
+
- On-target/off-target indicators when community taxa are available
|
|
223
|
+
- Identity warnings for low-confidence matches (<98% or <90%)
|
|
224
|
+
- Expandable cluster-level detail with per-cluster identification and sequence viewer
|
|
225
|
+
- Cluster quality badges: NS/LQ routing preview and CHIMERA (speconsense 0.8.6+ two-parent recombinant flag; routed to the `.chimera` track when summarize runs with `--filter-chimeras`, otherwise kept in Summary and badged for review)
|
|
226
|
+
- Search, sort, and filter (novel, on-target, off-target, no-match, watched)
|
|
227
|
+
|
|
228
|
+
### Summary tab
|
|
229
|
+
|
|
230
|
+
- Variant-level results after summarization
|
|
231
|
+
- Variant count per specimen with expandable detail rows
|
|
232
|
+
- Per-variant identification, read count, and sequence length
|
|
233
|
+
- Identification results shown only after variant-level identification completes
|
|
234
|
+
|
|
235
|
+
### Forecast tab
|
|
236
|
+
|
|
237
|
+
A live stop estimator for the sequencing operator (live mode, after at least two
|
|
238
|
+
files have been demultiplexed). From the per-file demultiplex history it estimates
|
|
239
|
+
each specimen's read-accumulation rate on the cumulative-matched-reads clock and
|
|
240
|
+
projects when below-threshold specimens will cross — with 90% intervals — plus:
|
|
241
|
+
|
|
242
|
+
- A headline: how many specimens are over threshold, how many more are projected
|
|
243
|
+
to cross within the next hour, and how many will likely never make it
|
|
244
|
+
- A viewer-selectable forecast threshold (chips for common values plus a custom
|
|
245
|
+
input) — view-only, the scheduler keeps using `min_reads`
|
|
246
|
+
- Threshold sensitivity (≥10 / min_reads / ≥100 / selected), since downstream
|
|
247
|
+
verification often succeeds well below `min_reads`
|
|
248
|
+
- The specimens-over-threshold accumulation curve for the run so far
|
|
249
|
+
- A rate-drift self-check that flags when the forecast's stationarity assumption
|
|
250
|
+
looks shaky for the current run
|
|
251
|
+
|
|
252
|
+
### Watch feature
|
|
253
|
+
|
|
254
|
+
Click the star on any specimen row to boost its scheduling priority. Watched specimens are processed ahead of all others in live mode.
|
|
255
|
+
|
|
256
|
+
### Sharing
|
|
257
|
+
|
|
258
|
+
Use `--share` to bind the dashboard to your LAN address and display a QR code for easy access from other devices.
|
|
259
|
+
|
|
260
|
+
## Replay
|
|
261
|
+
|
|
262
|
+
For testing or demos, `specimux-replay` splits a source FASTQ into timed chunks that mimic MinKNOW output:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
specimux-replay source.fastq simulated_output/ --reads-per-file 4000 --delay 30
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
| Option | Default | Description |
|
|
269
|
+
|---|---|---|
|
|
270
|
+
| `--reads-per-file` | `4000` | Reads per output file |
|
|
271
|
+
| `--delay` | `30` | Seconds between files |
|
|
272
|
+
| `--gzip` | — | Compress output files (.fastq.gz) |
|
|
273
|
+
|
|
274
|
+
Files are written atomically with MinKNOW-style filenames. Pair with live mode to replay a sequencing run:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
# Terminal 1: start the pipeline
|
|
278
|
+
specimux-suite live primers.fasta specimens.tsv simulated_output/ --reference-db refs.fasta
|
|
279
|
+
|
|
280
|
+
# Terminal 2: replay sequencer output
|
|
281
|
+
specimux-replay source.fastq simulated_output/
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Output
|
|
285
|
+
|
|
286
|
+
The output directory contains:
|
|
287
|
+
|
|
288
|
+
```
|
|
289
|
+
output_dir/
|
|
290
|
+
├── events.jsonl # Append-only event log (rotates at 100 MB)
|
|
291
|
+
├── inat_taxon_cache.json # Cached iNaturalist community taxa
|
|
292
|
+
├── specimux/full/{pool}/
|
|
293
|
+
│ └── {specimen_id}.fastq # Demultiplexed reads per specimen
|
|
294
|
+
├── consensus/{specimen_id}/
|
|
295
|
+
│ └── {specimen_id}-all.fasta # Consensus sequences (one or more clusters)
|
|
296
|
+
├── summary/
|
|
297
|
+
│ ├── {variant_id}-RiC*.fasta # Individual variant sequences
|
|
298
|
+
│ └── summary.fasta # Aggregated summary sequences
|
|
299
|
+
└── identification/
|
|
300
|
+
└── {specimen_id}.tsv # vsearch hits with adjusted-identity scores
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
The event log (`events.jsonl`) records every state change and is the single source of truth for pipeline state. Pipeline state is an in-memory materialized view rebuilt by replaying all events — it is never persisted to disk.
|
|
304
|
+
|
|
305
|
+
## Development
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
# Install with dev dependencies
|
|
309
|
+
pip install -e '.[dev]'
|
|
310
|
+
|
|
311
|
+
# Run tests
|
|
312
|
+
pytest tests/
|
|
313
|
+
|
|
314
|
+
# Run a single test
|
|
315
|
+
pytest tests/test_state.py::test_read_totals -v
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## License
|
|
319
|
+
|
|
320
|
+
BSD 3-Clause. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# specimux-suite
|
|
2
|
+
|
|
3
|
+
> **Early preview release.** This project is under active development — APIs, event formats, and CLI options may change between versions. Feedback and bug reports are welcome at [github.com/joshuaowalker/specimux-suite/issues](https://github.com/joshuaowalker/specimux-suite/issues).
|
|
4
|
+
|
|
5
|
+
Orchestration and real-time dashboard for the [Mycomap](https://mycomap.org) fungal DNA barcoding pipeline. Manages the full workflow from raw nanopore reads through demultiplexing, consensus generation, variant summarization, and species identification.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Requires Python 3.11+.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install specimux-suite
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or, for development, from a source checkout:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install -e '.[dev]'
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The pipeline invokes external bioinformatics tools as subprocesses — **specimux**, **speconsense**, and **vsearch** must be installed and available on your `PATH`.
|
|
22
|
+
|
|
23
|
+
| Tool | Purpose | Required |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| [specimux](https://github.com/joshuaowalker/specimux) | Demultiplexing reads by primer pool and specimen | Yes |
|
|
26
|
+
| [speconsense](https://github.com/joshuaowalker/speconsense) | Consensus sequence generation and variant summarization | Yes |
|
|
27
|
+
| [vsearch](https://github.com/torognes/vsearch) | Reference database matching for species identification | Only if `--reference-db` is provided |
|
|
28
|
+
|
|
29
|
+
See each tool's repository for installation instructions. These tools have system-level dependencies that pip cannot install:
|
|
30
|
+
|
|
31
|
+
| Dependency | Required by | Install |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| [SPOA](https://github.com/rvaser/spoa) | speconsense | `conda install bioconda::spoa` |
|
|
34
|
+
| [MCL](https://micans.org/mcl/) | speconsense (optional, recommended) | `conda install bioconda::mcl` |
|
|
35
|
+
| [vsearch](https://github.com/torognes/vsearch) | speconsense (scalability mode), specimux-suite (identification) | `conda install bioconda::vsearch` |
|
|
36
|
+
|
|
37
|
+
## Quick start
|
|
38
|
+
|
|
39
|
+
### Batch mode
|
|
40
|
+
|
|
41
|
+
Process a single FASTQ file end-to-end:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
specimux-suite batch primers.fasta specimens.tsv reads.fastq \
|
|
45
|
+
--reference-db references.fasta
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Live mode
|
|
49
|
+
|
|
50
|
+
Watch a directory for new FASTQ files (e.g., from a running MinION sequencer) and process them incrementally as they appear:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
specimux-suite live primers.fasta specimens.tsv /path/to/minknow/output/ \
|
|
54
|
+
--reference-db references.fasta
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
A web dashboard opens automatically at `http://127.0.0.1:8077` showing real-time progress. Press Ctrl+C to finalize — the pipeline will drain remaining files, process all eligible specimens regardless of threshold, and run summarization before exiting.
|
|
58
|
+
|
|
59
|
+
### Profiles
|
|
60
|
+
|
|
61
|
+
Profiles bundle pipeline settings and tool configurations into reusable presets:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# List available profiles
|
|
65
|
+
specimux-suite batch --list-profiles
|
|
66
|
+
|
|
67
|
+
# Use a profile
|
|
68
|
+
specimux-suite batch -p herbarium primers.fasta specimens.tsv reads.fastq
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Bundled profiles include `default` (standard settings) and `herbarium` (relaxed thresholds for degraded DNA). Custom profiles can be placed in `~/.config/specimux-suite/profiles/`.
|
|
72
|
+
|
|
73
|
+
## Input files
|
|
74
|
+
|
|
75
|
+
**Primers** — FASTA file containing primer sequences used for demultiplexing.
|
|
76
|
+
|
|
77
|
+
**Specimens** — Tab-separated file with at least `SampleID` and `PrimerPool` columns. Specimen IDs containing an iNaturalist observation ID (e.g., `iNat12345`) enable automatic community taxon lookup for on-target/off-target detection.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
SampleID PrimerPool
|
|
81
|
+
spec001 pool1
|
|
82
|
+
spec002 pool1
|
|
83
|
+
specimen-B--iNat12345 pool2
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Reads** — Standard FASTQ format (batch mode expects a single file; live mode watches a directory for `*.fastq` files).
|
|
87
|
+
|
|
88
|
+
**Reference database** — Optional FASTA file of reference sequences for species identification via vsearch. The sequence ID (first whitespace-delimited token) is used as the match key. An optional `name="..."` field in the header provides a display name; without it, the name is derived from the ID by replacing underscores with spaces (e.g., `Genus_species_authority` becomes "Genus species").
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
>MycoMap_12345_Trametes_versicolor_US_Indiana name="Trametes versicolor"
|
|
92
|
+
ACGTACGT...
|
|
93
|
+
>MycoMap_67890_Stereum_ostrea_US_Ohio
|
|
94
|
+
TGCATGCA...
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Options
|
|
98
|
+
|
|
99
|
+
### Common options
|
|
100
|
+
|
|
101
|
+
| Option | Default | Description |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `-p, --profile` | — | Load a suite profile preset |
|
|
104
|
+
| `--list-profiles` | — | List available profiles and exit |
|
|
105
|
+
| `-o, --output-dir` | `specimux-suite-output` | Output directory |
|
|
106
|
+
| `--reference-db` | — | Reference FASTA for identification |
|
|
107
|
+
| `--min-reads` | `30` | Minimum reads before running consensus |
|
|
108
|
+
| `--reprocess-ratio` | `0.5` | Ratio of new/previous reads to trigger reprocessing |
|
|
109
|
+
| `--workers` | half of CPU cores | Number of worker threads |
|
|
110
|
+
| `--identify-min-coverage` | `0.5` | Minimum query/target coverage for identification hits |
|
|
111
|
+
| `--specimux-args` | — | Extra arguments passed through to specimux |
|
|
112
|
+
| `--speconsense-args` | — | Extra arguments passed through to speconsense |
|
|
113
|
+
| `--summarize-args` | — | Extra arguments passed through to speconsense-summarize |
|
|
114
|
+
| `--log-level` | `INFO` | Logging verbosity (`DEBUG`, `INFO`, `WARNING`, `ERROR`) |
|
|
115
|
+
|
|
116
|
+
### Web dashboard options
|
|
117
|
+
|
|
118
|
+
| Option | Default | Description |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| `--web-host` | `127.0.0.1` | Dashboard listen address |
|
|
121
|
+
| `--web-port` | `8077` | Dashboard listen port |
|
|
122
|
+
| `--share [N]` | — | Share dashboard on LAN with QR code (optional max client limit, default 20) |
|
|
123
|
+
| `--no-web` | — | Disable the web dashboard |
|
|
124
|
+
| `--no-open` | — | Don't auto-open dashboard in browser |
|
|
125
|
+
|
|
126
|
+
### Live mode options
|
|
127
|
+
|
|
128
|
+
| Option | Default | Description |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| `--settle-time` | `30` | Seconds to wait for a file to stabilize before processing |
|
|
131
|
+
| `--presample` | `100` | Reads to subsample for incremental consensus (0 = unlimited) |
|
|
132
|
+
|
|
133
|
+
## Pipeline
|
|
134
|
+
|
|
135
|
+
### Processing stages
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
FASTQ reads
|
|
139
|
+
→ specimux (demultiplex into per-specimen FASTQs)
|
|
140
|
+
→ speconsense (generate consensus sequences per specimen)
|
|
141
|
+
→ vsearch + adjusted-identity (identify species from reference DB)
|
|
142
|
+
→ speconsense-summarize (extract and identify variant sequences)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Scheduling
|
|
146
|
+
|
|
147
|
+
The scheduler uses two-tier prioritization:
|
|
148
|
+
|
|
149
|
+
1. **Never-processed specimens** — prioritized by read count (highest first), processed once they reach `--min-reads`
|
|
150
|
+
2. **Reprocessing candidates** — specimens with enough new reads since last consensus (controlled by `--reprocess-ratio`)
|
|
151
|
+
|
|
152
|
+
In live mode, watched specimens (starred in the dashboard) receive a priority boost and are processed first.
|
|
153
|
+
|
|
154
|
+
Within the reprocessing tier, candidates are ordered by **result confidence** —
|
|
155
|
+
uncertain results are revisited first, since additional depth might change the
|
|
156
|
+
answer:
|
|
157
|
+
|
|
158
|
+
1. **No match** — consensus produced but nothing hit the reference database
|
|
159
|
+
2. **Low identity** — best hit below 90% adjusted identity
|
|
160
|
+
3. **Off-target** — no hit matches the iNaturalist community genus (a
|
|
161
|
+
mycoparasite or yeast contaminant may be dominating the true target), or the
|
|
162
|
+
community genus appears only in a minority cluster
|
|
163
|
+
4. **Marginal** — identity 90–98%, or ambiguous bases in the consensus
|
|
164
|
+
5. **Confident** — ≥98% identity and on-target
|
|
165
|
+
|
|
166
|
+
Uncertain results (the first three) also re-enter the queue at half the
|
|
167
|
+
configured `--reprocess-ratio`, so depth reaches them sooner. Confidence only
|
|
168
|
+
reorders work — confident specimens still reprocess whenever workers are free,
|
|
169
|
+
and finalization always processes every specimen with unprocessed reads,
|
|
170
|
+
regardless of confidence. The dashboard shows a small ↻ chip on each queued
|
|
171
|
+
reprocess candidate with the reason it was prioritized.
|
|
172
|
+
|
|
173
|
+
### Live mode concurrency
|
|
174
|
+
|
|
175
|
+
Consensus jobs read copy-on-write snapshots of their input FASTQs (instant on APFS/btrfs/XFS, a plain copy elsewhere), so when a new FASTQ file stabilizes, specimux demultiplexes it immediately — appending to the live per-specimen files while in-flight consensus jobs keep running on their snapshots. Demultiplexing uses whatever worker threads aren't occupied by consensus jobs, and newly-ready specimens are scheduled as soon as it finishes.
|
|
176
|
+
|
|
177
|
+
## Web dashboard
|
|
178
|
+
|
|
179
|
+
The built-in dashboard provides a real-time view of pipeline progress, streamed via server-sent events (SSE).
|
|
180
|
+
|
|
181
|
+
### Processing tab
|
|
182
|
+
|
|
183
|
+
- Specimen table with status, read count, top identification match, and identity score
|
|
184
|
+
- Color-coded status badges (queued, processing, identified, no match, error)
|
|
185
|
+
- On-target/off-target indicators when community taxa are available
|
|
186
|
+
- Identity warnings for low-confidence matches (<98% or <90%)
|
|
187
|
+
- Expandable cluster-level detail with per-cluster identification and sequence viewer
|
|
188
|
+
- Cluster quality badges: NS/LQ routing preview and CHIMERA (speconsense 0.8.6+ two-parent recombinant flag; routed to the `.chimera` track when summarize runs with `--filter-chimeras`, otherwise kept in Summary and badged for review)
|
|
189
|
+
- Search, sort, and filter (novel, on-target, off-target, no-match, watched)
|
|
190
|
+
|
|
191
|
+
### Summary tab
|
|
192
|
+
|
|
193
|
+
- Variant-level results after summarization
|
|
194
|
+
- Variant count per specimen with expandable detail rows
|
|
195
|
+
- Per-variant identification, read count, and sequence length
|
|
196
|
+
- Identification results shown only after variant-level identification completes
|
|
197
|
+
|
|
198
|
+
### Forecast tab
|
|
199
|
+
|
|
200
|
+
A live stop estimator for the sequencing operator (live mode, after at least two
|
|
201
|
+
files have been demultiplexed). From the per-file demultiplex history it estimates
|
|
202
|
+
each specimen's read-accumulation rate on the cumulative-matched-reads clock and
|
|
203
|
+
projects when below-threshold specimens will cross — with 90% intervals — plus:
|
|
204
|
+
|
|
205
|
+
- A headline: how many specimens are over threshold, how many more are projected
|
|
206
|
+
to cross within the next hour, and how many will likely never make it
|
|
207
|
+
- A viewer-selectable forecast threshold (chips for common values plus a custom
|
|
208
|
+
input) — view-only, the scheduler keeps using `min_reads`
|
|
209
|
+
- Threshold sensitivity (≥10 / min_reads / ≥100 / selected), since downstream
|
|
210
|
+
verification often succeeds well below `min_reads`
|
|
211
|
+
- The specimens-over-threshold accumulation curve for the run so far
|
|
212
|
+
- A rate-drift self-check that flags when the forecast's stationarity assumption
|
|
213
|
+
looks shaky for the current run
|
|
214
|
+
|
|
215
|
+
### Watch feature
|
|
216
|
+
|
|
217
|
+
Click the star on any specimen row to boost its scheduling priority. Watched specimens are processed ahead of all others in live mode.
|
|
218
|
+
|
|
219
|
+
### Sharing
|
|
220
|
+
|
|
221
|
+
Use `--share` to bind the dashboard to your LAN address and display a QR code for easy access from other devices.
|
|
222
|
+
|
|
223
|
+
## Replay
|
|
224
|
+
|
|
225
|
+
For testing or demos, `specimux-replay` splits a source FASTQ into timed chunks that mimic MinKNOW output:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
specimux-replay source.fastq simulated_output/ --reads-per-file 4000 --delay 30
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| Option | Default | Description |
|
|
232
|
+
|---|---|---|
|
|
233
|
+
| `--reads-per-file` | `4000` | Reads per output file |
|
|
234
|
+
| `--delay` | `30` | Seconds between files |
|
|
235
|
+
| `--gzip` | — | Compress output files (.fastq.gz) |
|
|
236
|
+
|
|
237
|
+
Files are written atomically with MinKNOW-style filenames. Pair with live mode to replay a sequencing run:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Terminal 1: start the pipeline
|
|
241
|
+
specimux-suite live primers.fasta specimens.tsv simulated_output/ --reference-db refs.fasta
|
|
242
|
+
|
|
243
|
+
# Terminal 2: replay sequencer output
|
|
244
|
+
specimux-replay source.fastq simulated_output/
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Output
|
|
248
|
+
|
|
249
|
+
The output directory contains:
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
output_dir/
|
|
253
|
+
├── events.jsonl # Append-only event log (rotates at 100 MB)
|
|
254
|
+
├── inat_taxon_cache.json # Cached iNaturalist community taxa
|
|
255
|
+
├── specimux/full/{pool}/
|
|
256
|
+
│ └── {specimen_id}.fastq # Demultiplexed reads per specimen
|
|
257
|
+
├── consensus/{specimen_id}/
|
|
258
|
+
│ └── {specimen_id}-all.fasta # Consensus sequences (one or more clusters)
|
|
259
|
+
├── summary/
|
|
260
|
+
│ ├── {variant_id}-RiC*.fasta # Individual variant sequences
|
|
261
|
+
│ └── summary.fasta # Aggregated summary sequences
|
|
262
|
+
└── identification/
|
|
263
|
+
└── {specimen_id}.tsv # vsearch hits with adjusted-identity scores
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The event log (`events.jsonl`) records every state change and is the single source of truth for pipeline state. Pipeline state is an in-memory materialized view rebuilt by replaying all events — it is never persisted to disk.
|
|
267
|
+
|
|
268
|
+
## Development
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Install with dev dependencies
|
|
272
|
+
pip install -e '.[dev]'
|
|
273
|
+
|
|
274
|
+
# Run tests
|
|
275
|
+
pytest tests/
|
|
276
|
+
|
|
277
|
+
# Run a single test
|
|
278
|
+
pytest tests/test_state.py::test_read_totals -v
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## License
|
|
282
|
+
|
|
283
|
+
BSD 3-Clause. See [LICENSE](LICENSE).
|