demuxis now part of the defaultclifeature, so the standardescpodbuild ships barcode demultiplexing without a rebuild. It pulls in zero new third-party crates (ndarray/serde_json/rayon/uuid were already in the graph). The accelerator featurestrain,gpu,cnn-detect, andcnn-gpuremain opt-in because they need extra toolchains or a CUDA runtime (#150).
mad_normalizeno longer aborts on a constant signal. A dead pore or flat read produced a zero MAD that panicked; since release builds usepanic = "abort", a single bad read killed a multi-hour job (#150).- Short fingerprints are no longer emitted silently.
extract_fingerprint_from_signaltreatedkeep_lastas a maximum rather than an exact width, so a truncated fingerprint could reach the classifier. GBM errored out, but DTW/SVM scored the truncated query and reported a confident wrong barcode. Observed in real data at 1 ragged row in 9,894 (#150). read_query_csvvalidates row width. Malformed cells were dropped silently; the labeled loader had guarded this for a while, the query loader never did (#150).- A GBM classify failure no longer discards its whole chunk. One failing read dropped all 1,024 reads in the chunk instead of just itself (#150).
filter/subsetwrite real read IDs into the signal table. Theread_idcolumn was zero-filled, diverging from ONT's own tooling and from the schema's documented "UUID for consistency checking" purpose. Files still loaded and round-tripped losslessly because the reads table is the authority for the read→signal mapping, so nothing read the column — but any tool that used it for the check it is named for would have rejected every fileescpod filter/subsetever produced (#151).demux trainoutput is reproducible. Grouping iterated aHashMap, sostd_devsummation order — and its low bits — varied run to run, andTrainingOutput::barcodeswas aHashMap, so serde emitted barcodes in a different order each process. Results are now sorted by read index and the map is aBTreeMap; three consecutive runs are byte-identical (#152).
- Fused
demuxpipeline is 2.3× faster on GBM models (151.0 s → 65.1 s on 1.22M reads / 10.4 GB, 48 cores; CPU utilization 511% → 1273%), and 1.27× on DTW-SVM. The pipeline was neither compute- nor I/O-bound — it ran faster at 8 threads than at 48, because block fill never overlapped with processing and the dominant barcode's writer channel blocked rayon workers that could not then be stolen from. Per-barcode counts are unchanged, and the stageddetect/fingerprintsubcommands still produce byte-identical output (#150). - DTW-SVM classify is faster, bit-identically.
DTW_LANES16→32 anddecision_functionnow skips support vectors that cannot contribute to a class pair: per-read predict 150.1 → 110.4 µs (−26.4%), and the 20-class decision function 366.9 → 26.7 µs (−92.7%), which matters for wider barcode designs (#150). filteris 2.29× faster andsubset1.74× (51.3 s → 22.4 s and 37.9 s → 21.8 s on 1.22M reads / 10.4 GB, 48 CPUs). The signal-table copy ran inline with the IPC writes on one thread, so every page fault stalled the thread that then issued the write — 75% of profile samples inmemmoveplus kernel page-fault time at 24% CPU. Batches now build across rayon and are written in order, with lookahead bounded to 16 batches in flight.mergeis deliberately untouched: it copies whole Arrow IPC blocks and patches footer offsets, so it never rebuilds batches (#151).demux trainis 8.7× faster (231.5 s → 26.5 s on 200k assigned reads, 48 cores; CPU utilization 86% → 1199%).extract_fingerprintsparallelized only across files, so the common single-POD5 training run was effectively serial regardless of-t. It now walks files sequentially — one ascending mmap sweep per Arrow batch, preserving the single-stream I/O — and parallelizes inside each batch. Consensus fingerprints are bit-identical (#152).demux train-svmno longer computes an all-pairs DTW distance matrix and its RBF kernel matrix. Both were discarded: their only consumer took the kernel as an ignored parameter, so ever since the SMO fit was removed the emitted model has been a function of the labels alone. At N=50,000 the command now runs in 0.27 s / 25 MB, where the matrices alone would have wanted ~40 GB — the memory wall that--max-per-classexists to work around (#152).
- The
gpuDTW-classify feature is now marked experimental. On a full node it measured slower than the CPU: 113.0 s on 64 cores versus 132.4 s with--gpuon an A30 (0.85×), plus ~2.2 GB more RSS. The apparent win disappears once the CPU gets the whole node instead of 16 of 64 cores. GPU CNN adapter detection (--method cnn --gpu) remains the GPU path that pays off (#150). demux train-svm --windowand--gpunow warn that they do not affect the fit, instead of silently appearing effective (#152).compute_distance_matrix,distance_to_kernel_matrix, andtrain_svm_from_distancesstay public and tested, so a real SVM fit can be wired back in without a signature change (#152).
- The signal
RecordBatchbuilder is shared betweenfilter/subsetand the incrementalWriter(build_signal_batch+SignalRowinutils::table_builders) rather than duplicated (#151). - New
test_table_conformanceguardrail in the CI compat suite snapshots all three embedded Arrow tables from a pod5-written and an escapepod-written file and diffs schema plus contents, resolving signalread_idthrough each read'ssignal_rows. Validated as a guardrail: it fails against a pre-fix binary. Adds anESCPOD_BINoverride so the suite can target an arbitrary build (#151). - Dependency bumps:
clap4.6.4,libc0.2.189, andactions/setup-python7.
- mold is now the linker full time inside pixi. The base
[activation]block exportsLD_PRELOAD=$CONDA_PREFIX/lib/mold/mold-wrapper.so(+MOLD_PATH) for every environment, so anypixi run [-e <env>] cargo …(and maturin) links with mold — no moremold -runwrappers or-e dev-only mold. Works with the stock system gcc 11.5 on the compute nodes (no-fuse-ld=moldsupport needed) via mold'smold-wrapper.sointerposer, and needs no glibc-static. CI release builds (musl, outside pixi) are unaffected.
-
Auto-warmed read-id index on Python context-manager entry. Entering a
ReaderorDatasetReaderin awithblock now builds the in-memory read-id index, so repeatedreads(selection=…)lookups take an O(k) indexed path instead of re-scanning the reads table each call (~2× faster random-access selection, on par with thepod5package). Plainopen()is unchanged — the index stays lazy for single-pass streaming. Size-gated by read count (default 5,000,000, overridable viaESCAPEPOD_AUTOINDEX_MAX) to bound memory; this is the in-memory index, not the.p5isidecar, so no sidecar file is written (#97). -
PyPI publishing for the
escapepodPython package. Therelease.ymlworkflow now builds abi3 wheels (CPython 3.9+) for Linux (x86_64/aarch64, manylinux + musllinux) and macOS (x86_64/arm64) plus an sdist, and publishes them to PyPI via Trusted Publishing (OIDC) on eachv*tag.pip install escapepodwill work once the first tagged release lands. The bindings crate gainedabi3-py39and complete PyPI metadata (readme, license, URLs, classifiers, type stubs).
- Resquiggle hot paths (band construction and refinement) iterate with
array_windowsinstead of manual index arithmetic, dropping redundant bounds checks from the inner loops (#61).
- Status output no longer escapes ANSI. The
tracingformatter was escaping ANSI control sequences, so styled status/progress output rendered as literal escape codes; it now emits proper styling (#142). - Quiet
SIGPIPEon piped output. Piping CLI output into a consumer that closes early (e.g.| head) no longer produces a broken-pipe error — the CLI exits cleanly on a closed downstream pipe (#140).
- POD5 archives are now written atomically: output is staged to a
temporary file and renamed into place on completion, so an interrupted or
failed write can no longer leave a truncated/partial
.pod5at the target path.
- Dependency bumps:
noodles-bam0.91,noodles-sam0.86,noodles-bgzf0.48,noodles-csi0.57,sha20.11, and the grouped cargo minor/patch and GitHub Actions updates.
- Native GBM (gradient-boosted tree-ensemble) barcode classifier for
demux classify/ fuseddemux, alongside the existing DTW+SVM path. Fingerprints are scored directly by a distilled tree ensemble (no DTW), loaded from the same auto-detected model surface. Fused-pipeline support is included, soescpod demux --model gbm.json …routes reads end-to-end. - Architecture-agnostic GPU CNN/TCN adapter detection (
demux detect --method cnn --gpu, featurecnn-gpu): runs any[B,1,L] -> [B,2,L]ONNX graph batched through onnxruntime's CUDA execution provider via theortcrate (load-dynamic— needs a CUDA-enabledlibonnxruntimeonORT_DYLIB_PATHand a visible GPU at run time, nothing at build time). TCN detect is inference-bound, so this pays off (~7.6× end-to-end on an A30 at 20k reads). This is the ONNX-generic backend anticipated by the removal of the old arch-locked CUDA kernel below — it replaces it without hardcoding a topology. - pod5-parity Python API: a multi-file
DatasetReader,to_dict/to_pandas/to_polarsexporters,missing_okhandling,calibrate_signal_array,Writer.add_reads, and per-readbyte_count, bringing theescapepodbindings closer to the referencepod5package. - Python bindings for the signal layer:
normalize, aKmerTablewrapper, andrefine_signal_mapare now exposed fromescapepod-signal, so the resquiggle/normalization primitives are usable from Python. -t/--threadsonfilter,subset, andmerge(matchingdemux) to cap the worker pool; these commands now default to a bounded pool of 8 threads instead of grabbing every CPU on a shared node.- POD5 reads-table schema V5: the
expected_open_pore_levelandselected_read_levelfields (bothfloat32), introduced upstream in pod5 0.3.44, are now read, written, merged/filtered, surfaced inview/inspect(and as selectable output fields), and exposed on the PythonReadData/Writer.add_readAPI. Files escapepod writes are now stampedpod5_version0.3.44 and verified readable by the reference ONTpod5reader; existing V0–V4 files still read, with the new fields defaulting to 0.0. - Defensive pre-mmap probe when opening a POD5 file: the header and footer are
read through ordinary I/O before the file is memory-mapped, so a truncated
file or an archive "stub" (unresident data on HSM/tape-backed filesystems)
surfaces a recoverable error instead of an uncatchable SIGBUS on first page
fault. Mirrors upstream pod5 0.3.37; set
POD5_DISABLE_MMAP_OPEN=1to skip. escpod demux <file> --model M -d OUTnow runs a fused, streaming pipeline by default: each read's signal is decoded once, then detect + fingerprint + classify run in a single pass and reads are routed (block-level compressed copy) into per-barcode POD5s — no intermediate boundaries/fingerprints/classifications files. The granulardetect/fingerprint/classify/split/trainsubcommands remain for advanced use.--classificationswrites the per-read CSV only when asked.- Experimental GPU primitives (behind
--features gpu) for the demux signal chain — SVB16 decode, t-test fingerprint, LLR detect — kept as validated, reusable kernels. They are not used byescpod demux: measurement shows the prep stages run faster on a multi-core CPU than on the GPU.
- The GPU CNN adapter-detection path (
demux detect --method cnn --gpu, plus the--cnn-weightsflag andscripts/dump_adapter_cnn_weights.py). Its hand-written CUDA kernels were hardcoded to ADAPTed'sBoundariesCNNtopology (3× Conv1d + ConvTranspose1d, fixed K=7/C=64) and could not run any other architecture — including escapepod-models' replacement TCN. CNN detection (--method cnn) now runs only through the architecture-agnostic tract-onnx CPU path (adapter_cnn.rs), which accepts any[B,1,L] -> [B,2,L]ONNX graph. This is not a regression at typical scales:detectis dominated by POD5 read + signal prep, not CNN compute, so the CPU path is as fast or faster (the GPU flag's own help already said as much). Removing it also drops the CC-BY-NC.weightsdumper. If a GPU CNN path is ever needed again, add an ONNX-generic backend (e.g. ORT CUDA EP) rather than a per-architecture kernel — which is exactly what the newcnn-gpupath (see Added) does.
- The CLI crate is renamed
escapepod→escapepod-cli, matching itsescapepod-{pod5,signal,demux}siblings and making its role explicit. Theescpodbinary name is unchanged, and installation is unchanged (cargo install --git …). Library consumers of the umbrella crate now import it asescapepod_cli(e.g.use escapepod_cli::signal) instead ofescapepod. (Theescapepodname on PyPI already belongs to the Python bindings, so this also removes the crate-name overlap.) - CLI output split into logs vs. data. All status/progress/warning output
now flows through
tracingto stderr (timestamp LEVEL [target] message), while command data (TSV/CSV rows,inspect/summaryreports, ID lists) stays on stdout, so it can be piped/redirected independently of logs. Default level isinfo; control it with-v/-vv/-qorRUST_LOG. Progress bars auto-hide under-q. - Minimum supported Rust version raised to 1.95 (from 1.92).
- The resquiggle module is relicensed to MIT as an independent implementation, bringing it in line with the rest of the workspace.
- The Theil–Sen rescale subsample seed is now configurable (
resquiggle --seed), making refinement runs bit-for-bit reproducible. - The LLR detect
--downscaledefault is now 10 (the WarpDemuX-native mode) fordemuxanddemux detect, up from 1. This makes detect — the dominant prep stage — ~5× faster, with ~98% barcode agreement versus full-resolution (ds=1). Pass--downscale 1to restore full-resolution detect. - Dependency bumps (no behavior change): Arrow ecosystem
arrow+parquet58 → 59,tabled0.20 → 0.21, thenoodles-*BAM stack (bam0.90,sam0.85,bgzf0.47,core0.20,csi0.56),ndarray0.16 → 0.17,cudarc0.12 → 0.19, andtract-onnx0.21 → 0.23.
- Demux classify DTW is much faster, bit-identical. Per-call DTW allocation eliminated from the SVM classifier (~1.8×), then extended with lane-parallel SIMD DTW (8 signals/vector) covering windowed/penalty models as well — together a large end-to-end speedup on the DTW-bound path.
- GBM classify ~3.1× faster (compact tree arena + 8-read batched walk), bit-identical.
- Cold-read demux I/O fixed. Signal is now read in a single sequential memory-mapped stream with O(1) Arrow-batch seeks and dictionary pre-scan / readahead, instead of per-read random access across many threads (which degraded to demand-paging on cold files). Removes the large-POD5 startup stall and the cold-read throughput cliff.
- Zero-copy single-read signal fetch with adaptive prefix decode (#94): the reader's per-read signal path avoids materializing intermediate buffers, and fingerprint prep streams only the needed prefix.
- Faster Python read iteration: per-batch column resolution for the lazy
for rd in reader:iterator andreads(), plus numpy-backed metadata columns forto_dict/to_pandas/to_polars. - Parallelized bulk-file copies:
filter,subset, andmergenow copy reads across threads (bounded default pool of 8;-tto override), and the experimentalindexcommand adopts the same bounded default instead of inheriting rayon's all-CPU global pool. - Single-pass
demux split: reads are routed to per-barcode outputs in one pass, and the--unclassifiedflag now works correctly. - Codebase-wide optimization/refactor sweep (#86), all bit-identical output:
- Resquiggle adaptive banded DP ~31% faster — the per-base traceback no
longer heap-allocates a
Vecper base; the whole read shares one flat buffer. - O(1) POD5 read-batch access —
read_batch(i)/read_ids_from_batch(i)now seek via the Arrow IPC footer instead of decoding every preceding batch. Iterating a many-read-batch file (e.g. the PythonReaderread iterator) drops from O(B²) to O(B) batch decodes: ~10× faster random batch access and ~2.6× faster full-file iteration on a 1.65M-read / 166-batch file. - Signal median computations are O(n) instead of O(n log n) — the SVM
kernel γ-heuristic, Theil–Sen rescale, and resquiggle dwell median now use
select_nth_unstableinstead of a full sort. - Smaller per-read allocations on the demux/classify and fingerprint hot paths (MAD-normalization scratch reuse, Platt coupling workspace sized once).
- Resquiggle adaptive banded DP ~31% faster — the per-base traceback no
longer heap-allocates a
- Internal consolidation with no behavior change: six duplicated median impls
unified into
escapepod-signal::stats; the SVM RBF-kernel mapping and the CPU/GPU CNN batch packing/scatter each live in one shared helper.
- Resolved a PyPI name collision: both the
escapepodCLI crate and theescapepod-pythonbindings crate declaredname = "escapepod". The PyPIescapepoddistribution is the PythonReaderbindings (escapepod-python); theescpodCLI now ships viacargo install escapepodand GitHub release binaries only, so its maturinpyproject.toml(abindings = "bin"wheel) has been removed. This reverses the 0.5.1 note aboutpip install escapepodinstalling the CLI.
- The CLI now ships from the
escapepodcrate (renamed fromescapepod-cli), socargo install escapepodinstalls theescpodbinary. The same crate doubles as an umbrella library: withdefault-features = falsepluspod5/signal/demux, it re-exports each layer (e.g.escapepod::signal) without pulling in the CLI's dependency tree.demuxstays opt-in until it stabilizes. - The maturin binary wheel is published as
escapepod(wasescapepod-cli) sopip install escapepodmatchescargo install.
- Packaging
readmepointed at a nonexistent path, which madecargo packagefail; the workspace now points every publishable crate at the rootREADME.md.escapepod-pythonis markedpublish = false. demux fingerprint(test fixture): labeled-Parquet temp files lacked a.parquetsuffix, so format detection read them as CSV and the parquet loaders failed with an "invalid UTF-8" error.
- Gated the
train-only labeled-fingerprint loaders behind#[cfg(feature = "train")], removing dead-code warnings from--features demuxbuilds. - Bumped GitHub Actions to current majors (checkout v6, upload-artifact v7, download-artifact v8, setup-python v6, setup-pixi v0.9.6, action-gh-release v3, actions-netlify v4), clearing the Node 20 deprecation warnings.
demux fingerprint: Parquet output when-oends in.parquet, plus an--emit-dwellflag that adds per-segment dwell-time features.demux classify(CLI):fp_iomodule reads fingerprint inputs from both Parquet and CSV (gzipped CSV included); new flags--gpu-chunk-cellsand--threads, with model auto-detection so--modelaccepts any supported format.escapepod-demux:AnyModelenum andload_any_model()for format-agnostic SVM/DTW model loading.escapepod-signal: SVM helper CUDA kernels exposed via function handles for downstream GPU pipelines.
demux classify(GPU): on-GPU RBF + OvO decision pipeline (GpuSvmContext) keeps SVM evaluation on the device; producer/ consumer pipeline parallelizes the consumer side and bumps the default chunk to 4G cells with channel depth 2 for better GPU utilization on long runs. Per-chunk indicatif progress bar surfaces throughput.escapepod-demux: RBF kernel fast paths forpower == 1.0andpower == 2.0skip the genericpowfcall.escapepod-pod5: filter and merge hot paths reworked; remainingreader.reads()callers now batch-amortize the schema/footer parse, and aPoreTypenewtype removes per-read string churn.
train(multiclass OvO): dropped an unused SMO solve path that ran during training without contributing to the final model.
- Pixi
devenv wiresmold -runfor fast local links (system gcc 11.5, no glibc-static needed); release artifacts in CI continue to build against musl. - Docs: benchmark page leads with bulk operations (
merge,filter,subset,repack);inspectandviewdemoted to a secondary section.
demux fingerprint: nestedpar_iterstreams signals across files and reads so fingerprinting a 48-file run drops from ~32 min to ~9.8 s on the rna partition.demux classify/train-svm: reusable per-threadSvmWorkspaceand a streaming (rayon fan-out + single writer) output path cut RSS by ~37% and remove a serialize-then-write stall.svb16: AVX2 decode path (16 samples/iter), preferred at runtime over SSSE3 when available.dtw: split the inner band loop so the trailing segment auto- vectorizes under AVX2; the x86-64-v3 baseline (AVX2 + FMA + BMI2 + POPCNT + F16C) is now pinned in.cargo/config.tomlfor portability across Broadwell/Cascade Lake/Ice Lake cluster nodes.segmentation::llr: allocation-freebest_splitand an opt-in early-stop variant.- CLI: progress-bar updates throttled out of hot paths.
- Moved from CLI into libraries (additive for library consumers):
ReadBoundariesand fingerprint types/helpers now live inescapepod-demux.normalize_signal(&[i16])and the CLI'sdownscale_signalnow live inescapepod-signal(the CLI's duplicate was removed).
- Docs: recommend
srun -c 48for throughput-sensitive demux runs on the rna partition (fills one socket without crossing NUMA).
resquiggle::banded_dp_with_penalty_table— banded Viterbi DP variant that accepts a caller-supplied short-dwell penalty table and uses its length as the check horizon. Tie-break is strict (<), matching the Remora-compatible refinement pipeline. Complements the existingbanded_dpwhich builds the asymmetric penalty internally.segmentation::mad_normalize_robust— median-MAD normalization with the 1.4826 Gaussian scale factor and graceful fallback (returnssignal - medianwithout dividing) when MAD is essentially zero. Complementsmad_normalize, which panics on constant signals.
- Hot-path audit across fingerprint MAD, SVM prediction,
view, andmerge. Fingerprint MAD uses a single-pass median/MAD with an in-place partition; SVM prediction reuses per-thread scratch buffers and avoids redundant kernel evaluations on the OvO dual path; CLIviewstreams reads with reused formatting buffers;mergeswitches to mmap-backed readers where possible to cut per-file overhead.
escapepod-pythoncdylib now links cleanly under a plaincargo buildon macOS. Abuild.rsemits the pyo3 extension-module link args (equivalent topyo3_build_config::add_extension_module_link_args()), scoped to the cdylib, so the build no longer fails with undefined_Py*symbols when maturin is not driving the build. macOS is now in the CI matrix forcheck,test, andclippyto catch regressions.
- Workspace crates moved under
crates/(no public-API change). - Docs reorganised with an "experimental tools" section;
resquiggleandindexCLI subcommands are gated behind their respective Cargo features.
- Barcode demultiplexing moved out of
escapepod-signalinto a newescapepod-demuxcrate. Theescapepod_signal::demuxmodule is gone; downstream code should depend onescapepod-demuxdirectly and import fromescapepod_demux::...(model loaders,classify_read, SVM predictor/trainer, Platt scaling, GPU batch classify, ADAPTed CNN adapter detection). Theescpod demuxCLI surface is unchanged, butescapepod-cli'sdemuxCargo feature now pulls in the new crate; thetrain,gpu, andcnn-detectfeatures forward to it.
- GPU-accelerated DTW for demux, opt-in via
--features gpuonescapepod-signalandescapepod-cli. Wires upescpod demux classify --gpu(WarpDemuX model, CSV reference, and SVM model paths) andescpod demux train-svm --gpu. CUDA kernel is NVRTC-compiled at runtime, so nonvccis required at build time — only the CUDA driver andlibnvrtcat run time. On the lab cluster,pixi run -e gpu …provisionscuda-nvrtcvia conda-forge and setsLD_LIBRARY_PATH. Anti-diagonal kernel with shared-memory-cached fingerprints; single- warp blocks with__syncwarp()and__launch_bounds__(32, 64). Measured ~7.7× speedup over CPU rayon on A30 at 1024×40×110 and 8192×40×110 workloads (criterion, band w=10). GpuDtwContext,dtw_distance_matrix_gpu,classify_reads_gpu,classify_with_svm_batch_gpu,compute_distance_matrix_gpu,train_svm_gpupublic API onescapepod-signal(allgpu-gated).- CPU
classify_readnow usesdtw_distance_boundedwith the running second-best squared distance as an upper bound, skipping DTW work for training fingerprints that cannot change the top-2. Safe for both ratio and kernel threshold paths.
- Behavior change for windowed DTW. The 2-row banded DP in
dtw_distance/dtw_distance_boundedwas leaving stalecurr[j_start - 1]values from earlier rows, letting the recurrence read an out-of-band predecessor and occasionally find a shorter-than- valid path. The classical Sakoe-Chiba band treats those cells as unreachable; we now re-seed the boundary toINFat the top of each row and also short-circuit toINFwhen|n − m| > w(the endpoint itself is outside the band and the DP would otherwise propagate a stale in-band value through the trailing empty rows). Only affects callers that passSome(window); unwindowed DTW is unchanged. In practice the difference is small but non-zero on real data — any downstream classify output produced with a band constraint may shift slightly, with GPU and CPU now agreeing bit-for-bit up to f32 summation order.
- Workspace split into two library crates. POD5 format I/O (reader, writer,
VBZ compression, merge/filter/repack/subset, schema, footer, types, errors)
now lives in the new
escapepod-pod5crate. The crate formerly calledescapepodhas been renamed toescapepod-signaland contains the signal-processing algorithms (DTW, resquiggle, segmentation) layered on top ofescapepod-pod5. Downstream consumers depending onescapepodby name must rename toescapepod-signal; the pod5 surface is re-exported fromescapepod-signalso mostuse escapepod::...paths translate touse escapepod_signal::...with no other changes. - Barcode demultiplexing is now opt-in. The
escapepod-signal::demuxmodule and theescpod demuxCLI subcommand require building with--features demux; thetrainfeature now impliesdemux.
escapepod-pod5crate for POD5 format I/O.demuxCargo feature on bothescapepod-signalandescapepod-cli.
- README no longer advertises barcode demultiplexing as a shipped feature;
docs/cli/demux.mdcarries an experimental admonition. - CLI now declares demux and resquiggle commands as experimental in the commands index.
- Empty
escapepod-vortex/directory (content preserved on theescapepod-vortexbranch). - Stale
PROGRESS.mdand the top-levelexamples/test_ipc.rsscratch file;examples/dtw_example.rsmoved underescapepod-signal/examples/.
- Tracing-based runtime verbosity (
-v/-vv/-q,RUST_LOG) release-with-debugandprofilingbuild profiles; phase timer- Criterion microbenches covering audit hot paths (
escapepod/benches/hot_paths.rs)
- SSSE3 SIMD encode/decode for SVB16 (~2× vs scalar on x86_64)
- Audit-driven hot-path optimizations across reader, DTW, demux, DP
- Dropped
escapepod-vortexworkspace member [profile.bench]pinned to inherit from release
- Clippy lints:
unnecessary_sort_by,needless_range_loop
First stable release of escapepod-rs.
- index:
.p5isidecar read index for fast UUID lookup (escpod index), with zstd-compressed entry blocks, sorted-vec binary search, and file size checksum validation - filter: Sample count and end reason filters, stdin support for read IDs, fast
reads_by_ids()path for UUID-only filtering - subset: Accelerated subsetting via indexed batch lookup
- merge: Parallel I/O optimization
- Include ZSTD content size in VBZ frames for Dorado/pod5 compatibility
- POD5 forward compatibility with Python pod5 library
- Correct pore count in summary table