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.
Files changed (45) hide show
  1. specimux_suite-0.1.0/LICENSE +28 -0
  2. specimux_suite-0.1.0/PKG-INFO +320 -0
  3. specimux_suite-0.1.0/README.md +283 -0
  4. specimux_suite-0.1.0/pyproject.toml +64 -0
  5. specimux_suite-0.1.0/setup.cfg +4 -0
  6. specimux_suite-0.1.0/src/specimux_suite/__init__.py +3 -0
  7. specimux_suite-0.1.0/src/specimux_suite/cli.py +288 -0
  8. specimux_suite-0.1.0/src/specimux_suite/config.py +236 -0
  9. specimux_suite-0.1.0/src/specimux_suite/console.py +296 -0
  10. specimux_suite-0.1.0/src/specimux_suite/events.py +233 -0
  11. specimux_suite-0.1.0/src/specimux_suite/inat.py +221 -0
  12. specimux_suite-0.1.0/src/specimux_suite/pipeline.py +902 -0
  13. specimux_suite-0.1.0/src/specimux_suite/profiles/__init__.py +314 -0
  14. specimux_suite-0.1.0/src/specimux_suite/profiles/default.yaml +7 -0
  15. specimux_suite-0.1.0/src/specimux_suite/profiles/herbarium.yaml +10 -0
  16. specimux_suite-0.1.0/src/specimux_suite/replay.py +68 -0
  17. specimux_suite-0.1.0/src/specimux_suite/runners/__init__.py +0 -0
  18. specimux_suite-0.1.0/src/specimux_suite/runners/identify_runner.py +395 -0
  19. specimux_suite-0.1.0/src/specimux_suite/runners/specimux_runner.py +212 -0
  20. specimux_suite-0.1.0/src/specimux_suite/runners/speconsense_runner.py +216 -0
  21. specimux_suite-0.1.0/src/specimux_suite/runners/summarize_runner.py +172 -0
  22. specimux_suite-0.1.0/src/specimux_suite/scheduler.py +250 -0
  23. specimux_suite-0.1.0/src/specimux_suite/state.py +339 -0
  24. specimux_suite-0.1.0/src/specimux_suite/util.py +171 -0
  25. specimux_suite-0.1.0/src/specimux_suite/watcher.py +236 -0
  26. specimux_suite-0.1.0/src/specimux_suite/web/__init__.py +0 -0
  27. specimux_suite-0.1.0/src/specimux_suite/web/api.py +4 -0
  28. specimux_suite-0.1.0/src/specimux_suite/web/server.py +246 -0
  29. specimux_suite-0.1.0/src/specimux_suite/web/static/index.html +2196 -0
  30. specimux_suite-0.1.0/src/specimux_suite/web/static/vendor/qrcode.min.js +7 -0
  31. specimux_suite-0.1.0/src/specimux_suite.egg-info/PKG-INFO +320 -0
  32. specimux_suite-0.1.0/src/specimux_suite.egg-info/SOURCES.txt +43 -0
  33. specimux_suite-0.1.0/src/specimux_suite.egg-info/dependency_links.txt +1 -0
  34. specimux_suite-0.1.0/src/specimux_suite.egg-info/entry_points.txt +3 -0
  35. specimux_suite-0.1.0/src/specimux_suite.egg-info/requires.txt +14 -0
  36. specimux_suite-0.1.0/src/specimux_suite.egg-info/top_level.txt +1 -0
  37. specimux_suite-0.1.0/tests/test_config.py +107 -0
  38. specimux_suite-0.1.0/tests/test_console.py +153 -0
  39. specimux_suite-0.1.0/tests/test_events.py +169 -0
  40. specimux_suite-0.1.0/tests/test_pipeline.py +413 -0
  41. specimux_suite-0.1.0/tests/test_replay.py +69 -0
  42. specimux_suite-0.1.0/tests/test_runners.py +426 -0
  43. specimux_suite-0.1.0/tests/test_scheduler.py +322 -0
  44. specimux_suite-0.1.0/tests/test_state.py +380 -0
  45. 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).