Commit Graph
56 Commits
Author SHA1 Message Date
Eric Coissac e101f629e6 Add family overlap computation and CLI options for phylo analysis
Extends the entropy annex pipeline to optionally compute family overlap data in a single pass, introducing a memory-mapped binary format and an in-memory accumulator for efficient storage. Adds --min-shared-family to auto-exclude genomes below a threshold during SNP-family distance computation, and --family-overlap to export a shared family matrix as CSV. Centralizes upper-triangle indexing into a shared helper function to eliminate duplication.
2026-08-28 22:03:21 +02:00
Eric Coissac 4f34a646c5 Implement SNP distance models with gamma correction and PHYLIP output
Renames the CLI flag from --metric to --distance and introduces eight closed-form SNP distance models with optional Jin-Nei gamma correction. Integrates the ndarray crate for matrix operations and adds relaxed PHYLIP output formatting. Updates architecture and theory documentation to cover the new sparse matrix variants, algorithmic fixes, and distance metric implementations.
2026-08-28 21:54:19 +02:00
Eric Coissac 0b40d2d0da Add phylogenetic export support for TNT, PhyG, and IQ-TREE
Extends the phylogenetic pipeline with exporters for TNT, PhyG, and IQ-TREE that generate executable scripts, cost matrices, and recoded alignments. Adds internal helpers for state indexing, floating-point matrix scaling, and Floyd-Warshall metric closure to satisfy external tool constraints. Adjusts visibility modifiers for sibling iterators and entropy annex structs, and updates design documentation for evolutionary distance metrics.
2026-08-28 21:32:32 +02:00
Eric Coissac 1536217ac1 feat: add Sankoff cost-matrix calibration CLI and serialization
Introduce the --sankoff flag to generate subsampled calibration bundles and pairwise cost matrices. Expose internal sibling algorithm types as public to support external consumption. Implement YAML, CSV, and FASTA output serialization using serde, gated by a configurable substitution saturation ceiling and requiring the --subsample flag.
2026-08-28 21:19:20 +02:00
Eric Coissac 9043868228 Add single-pass pairwise reduction pipeline for SNP alignment
Replaces the previous two-pass design with a single-pass reduction that computes per-genome-pair substitution counts, cardinality and base-composition tallies, and transition cost matrices. Introduces internal APIs to derive downstream n×n matrices from reduced data and applies configurable filtering based on SNP ratios and exclusion masks. Adds a fused pipeline entry point aggregating alignment and distance outputs for downstream phylogenetic commands. Adjusts visibility of existing reduction functions to restrict external access while permitting sibling module invocation.
2026-08-28 21:10:16 +02:00
Eric Coissac e015362ce6 Refactor sampling and reduction to use batched SurvivingFamily data
Replace per-family callbacks with a per-layer batch callback that accumulates surviving families into an Arc<Vec<SurvivingFamily>>. Update the alignment reduction routine to iterate over this batched structure, enabling zero-copy sharing for parallel operations and structuring the code for future extensibility.
2026-08-28 21:02:35 +02:00
Eric Coissac 89629e118d Add sibling family size distribution statistics and CLI flags
Introduces `--sibling-stats` and `--sibling-hist` flags to compute and export family-size distributions from pre-built annexes. The new algorithms module implements parallel and sequential scanning routines, while the CLI layer handles CSV export with deduplication and standardized error handling.
2026-08-28 20:59:07 +02:00
Eric Coissac beb2951c20 feat: add phylogenetic sampling, masking, and plain FASTA writer
Introduces configurable phylogenetic sampling and masking controls via new CLI flags (`--subsample`, `--entropy`, `--exclude-genome`, etc.). Adds a complete SNP pseudo-alignment pipeline featuring entropy-biased Gaussian sampling, post-hoc state masking, and proportional per-layer filtering. Extends the FASTA writer with a `write_plain_record` API for bare-header output without JSON annotations.
2026-08-28 20:54:51 +02:00
Eric Coissac 5a0b71d105 Add per-family Shannon entropy calculation and reporting
Introduces an entropy.pent persisted format and algorithms to compute per-family Shannon entropy across genomic partitions. Refactors IndexCache to use Arc-based layer sharing for efficient iteration and restructures the siblings module with extension traits for annex generation. Adds a --shannon CLI flag to export partition-level entropy metrics to CSV.
2026-08-28 20:45:47 +02:00
Eric Coissac bbb58a698f Rename SiblingAnnexBuildExt to SiblingExt and add sibling iterators
Refactors the `SiblingAnnexBuildExt` trait to `SiblingExt` across all imports, implementations, and documentation. Introduces new modules for streaming and batched iteration over sibling layers, along with a two-phase pipeline for resolving minorant families.
2026-08-28 20:36:17 +02:00
Eric Coissac 920120d20e Implement --sibling-annex flag and k-mer family annex builder
Introduces a new `--sibling-annex` CLI flag that triggers the construction of a sibling-count/minorant annex for multi-genome indices. The implementation adds a `FamilyMask` data structure with memory-mapped I/O, enabling lock-free concurrent updates via atomic bitwise operations. Batched processing improves cache locality and parallelism, while helper functions derive family presence and minorant flags dynamically. The feature is exposed through an `IndexCache` extension trait, protected by an exclusive directory lock to prevent index corruption during construction.
2026-08-28 20:29:01 +02:00
Eric Coissac d084396aba Introduce concurrency-bounded parallel processing for index cache layers
Implement an `obipipeline::Throttle` with an RAII guard to acquire and release concurrency slots. Expose new bounded parallel methods on `IndexCache` to process cached layers with a configurable cap. Refactor downstream aggregation logic to use single-pass parallel map-reduce instead of manual collect-map-reduce sequences, enforcing a maximum of 8 concurrent layer scans to bound memory usage.
2026-08-28 20:20:12 +02:00
Eric Coissac 9dee6dcd08 refactor: decouple tree construction from Newick serialization
Refactor phylogenetic algorithms (`neighbor_joining`, `upgma`) to return an explicit `Tree` struct instead of a serialized Newick string. This change makes serialization an explicit step for downstream consumers via the new public `Tree::to_newick()` method, decoupling tree construction from output formatting. The `siblings` module has also been moved to `siblings_old`.
2026-08-28 20:15:23 +02:00
Eric Coissac 635fc830d1 feat: add phylogenetic analysis CLI command and lazy distance traits
Introduce the `obikphylo` crate to support genome-vs-genome distance matrix computation and phylogenetic tree inference via Neighbor-Joining and UPGMA algorithms. Extend the `obikmer2` CLI with a new `phylo` command that exposes configurable metrics, presence thresholds, and CSV/Newick output options. Refactor `obikindex` to expose trait-based partial aggregation for efficient distance metric finalization without full matrix materialization. Update dependency graphs and remove obsolete storage modules.
2026-08-28 20:11:13 +02:00
Eric Coissac 4b6005962e Rename PersistentCompactIntMatrix to PersistentIntMatrix
Update all matrix type references, imports, and instantiations across
the codebase to use the new PersistentIntMatrix name. The change also
includes standardizing code formatting, such as multi-line statements
and import ordering, without altering any behavioral logic or public
API contracts.
2026-08-28 19:59:59 +02:00
Eric Coissac 6bdc9354d3 refactor: restructure obikphylo module layout and adjust visibility
Relocate cardcomp into the siblings directory and update internal import paths to reflect the new hierarchy. Adjust the crate's public API surface by updating module declarations and re-exports. This is a purely structural change with no modifications to logic, data models, or runtime behavior.
2026-08-28 19:46:09 +02:00
Eric Coissac fc4464a0ef Extract index modules into specialized workspace subcrates
This commit partitions the obikindex crate into multiple focused subcrates (obikfilter, obikmerge, obikquery, obikrebuild, obikselect, obikstats, obikdump, and obikidxcache) to reduce coupling and clarify module boundaries. It standardizes error handling across the workspace using OKIError and OKIResult, updates index APIs to support lazy, disk-backed partition access, and migrates NUMA system utilities to a new obisys crate. All modifications are structural, focusing on dependency graph expansion, import path updates, and API surface reorganization without altering core runtime behavior.
2026-08-22 06:25:28 +02:00
Eric Coissac c9d10d55c7 Simplify MphfLayer::open by removing explicit IndexMode parameter
The MphfLayer::open signature now accepts only a directory path. Mode configuration is resolved internally via disk-based auto-detection using LayerEvidence, eliminating the need for explicit arguments from callers. All internal query methods and external call sites have been updated accordingly, while TypedLayer::open temporarily retains the unused parameter for future cleanup.
2026-08-21 22:08:52 +02:00
Eric Coissac 00ba968628 Introduce obikalgorithm crate to unify pipeline algorithms
Define a shared Algorithm trait with an associated Output type and a parameterless run(&mut self) method. Refactor PartitionRouter, Dereplicator, Counter, and LayerBuilder to implement the trait, standardizing receivers to &mut self and moving configuration and progress callbacks to dedicated builder setters. Decouple error handling using a generic boxed error type and update workspace dependencies accordingly.
2026-08-21 22:03:08 +02:00
Eric Coissac 8d6ba6546b refactor: migrate index metadata to on-disk JSON with fallible access
Migrate index state tracking from filesystem sentinel files to an on-disk JSON schema within `index.meta`. The `IndexMeta` struct is now wrapped in an `Arc` with internal locking, exposing only fallible methods for genome and state access. In-memory mutation capabilities have been removed, requiring callers to handle I/O errors explicitly and pass immutable references to downstream components like `PartitionRouter`. Public sentinel constants have been removed from exports.
2026-08-21 21:51:42 +02:00
Eric Coissac da3aa5a2cb refactor: extract index construction state tracking into extension trait
Moves pipeline state bookkeeping, including sentinel file marking and spectrum persistence, into the algorithms' run and close methods. Introduces a crate-private extension trait to satisfy Rust's orphan rule while implementing construction-only operations on KmerIndex. Updates helper function visibility for cross-crate access and removes the now-empty index_layer module.
2026-08-21 10:38:51 +02:00
Eric Coissac 31bb324752 Rename Layer to KmerLayer across obikindex and obikphylo
This commit renames the `Layer` type to `KmerLayer` throughout the `obikindex` and `obikphylo` crates. All imports, struct fields, function signatures, pattern matches, and instantiation calls have been updated accordingly. The change is a purely structural refactor that tightens type constraints without altering runtime behavior or data models.
2026-08-21 10:27:29 +02:00
Eric Coissac 4b7b3c3c1a Extract indexing stage into LayerBuilder with NUMA-aware scheduling
Introduce a dedicated LayerBuilder struct to orchestrate parallel layer 0 construction across partitions. The fluent API supports configurable abundance thresholds and intermediate artifact retention. Parallel execution is delegated to a NUMA-aware PartitionRunner scheduler, while progress reporting and stage timing are shifted to the command layer. A new mark_indexed method cleanly separates state tracking from orchestration by generating a completion sentinel.
2026-08-21 10:20:03 +02:00
Eric Coissac 346095b9eb Rename index methods to hash and expose kmer iteration APIs
The layer API has been updated to rename `index` and `index_batch` to `hash` and `hash_batch`, aligning with raw MPHF slot hashing behavior. New public methods have been added to directly expose kmer hashing and iteration, enforcing strict state validation on empty layers. All other modifications are consistent code formatting adjustments without functional changes.
2026-08-21 10:14:22 +02:00
Eric Coissac 878b63566f Extract k-mer counting logic into a dedicated counter module
Decouple k-mer counting from the partitioner by introducing a new `Counter` struct. The module exposes a fluent builder API with optional partial file retention, executes partition processing in parallel via Rayon with memory-aware chunk sizing, and integrates thread-safe progress callbacks. Update all callers to use the new counter, simplify test pipelines by removing serialization overhead, and clarify algorithm separation in module documentation.
2026-08-21 05:48:02 +02:00
Eric Coissac 96b6517541 refactor: rename obikindex to obikindexer 2026-08-21 05:29:34 +02:00
Eric Coissac 5c1584967f feat: enable index resumption and enforce directory creation
The command now supports reopening existing indexes instead of failing when the output file exists. Control flow branches between opening an existing index and constructing a new one, moving configuration setup exclusively to the creation path. Directory existence is enforced upfront with proper I/O error propagation. The --force flag retains its original semantics by removing the target directory before proceeding with a fresh build.
2026-08-21 05:06:38 +02:00
Eric Coissac abc51c2add Extract dereplication logic into obikderep crate and centralize paths
Move partition dereplication logic into a dedicated `obikderep` crate that implements a two-phase hash-split/merge strategy with Rayon for parallel processing. Centralize superkmer file path construction in `obilayeredmap` and update dependent crates to use the new pipeline and shared path helpers. Adjust test suites to explicitly invoke the dereplication step.
2026-08-20 22:30:03 +02:00
Eric Coissac 616cb76af3 Refactor indexing pipeline and partition path resolution
Invert dependencies by moving partition path primitives to a dedicated module and updating the index crate accordingly. Reshape the partition router to accept a mutable index reference, enabling chainable configuration and resolving lifetime issues with explicit drops. Shift orchestration logic from the index crate to the CLI, replacing monolithic scatter calls with discrete dereplication and counting steps. Introduce a generic progress callback API to decouple rate calculation from UI rendering, and correct file I/O paths to route layer-0 artifacts under the partition index directory.
2026-08-20 22:15:13 +02:00
Eric Coissac c4b69e1af5 Introduce lifecycle-aware Layer::Empty variant and update callers
The `Layer` enum is transformed into a lifecycle-aware state machine with an `Empty` variant representing an unconstructed directory. Read and query operations now explicitly panic when invoked on this state, enforcing explicit progression through `create()` before use. Iterator methods are updated to handle the new variant exhaustively, and module visibility constants are adjusted to support the refactored structure.
2026-08-20 20:41:48 +02:00
Eric Coissac 1c54e60c9a Rename Layer<D> to TypedLayer and introduce heterogeneous Layer enum
Renames `Layer<D>` to `TypedLayer<D>` to establish a distinct typed abstraction. Introduces a new heterogeneous `Layer` enum that unifies count and presence storage with runtime dispatch, delegating operations to the underlying typed variants. Updates cache, index, and phylo consumers to align with the renamed type and new extension traits, preserving full test suite stability while preparing the foundation for multi-partition caching.
2026-08-20 20:35:29 +02:00
Eric Coissac 6c860f120f refactor: merge KmerPartitions into KmerIndex and rename obikpartition
Consolidates partition logic, metadata storage, and layer management directly into KmerIndex. Renames obikpartitionner to obikpartition, retaining only PartitionRouter for superkmer routing. Removes intermediate .partition() accessors in favor of direct methods on the index and updates PartitionCache::build to accept &KmerIndex directly. Derives n_partitions from config.n_bits and consolidates k-mer/minimizer sizes into IndexMeta.config. Fixes a regression where PartitionRouter::open incorrectly defaulted to closed.
2026-08-20 20:23:58 +02:00
Eric Coissac b5ec0122d0 Rename obikpartition crate to obikpartitionner
Update all dependent crates and internal imports to reference the renamed module. Expose configuration parameters and genome metadata through new public accessor methods in the index API, and update documentation comments to align with the new package name.
2026-08-20 19:43:00 +02:00
Eric Coissac 9379bbaad8 refactor: rename obikpartitionner crate to obikpartition
Update Cargo manifests, dependency paths, and Rust imports across the workspace to reflect the `obikpartitionner` to `obikpartition` rename. Synchronize architecture and implementation documentation with the new module structure. Fix minor syntax issues in test assertions to ensure compilation compatibility. No behavioral or API changes are introduced.
2026-08-20 16:41:22 +02:00
Eric Coissac f9ef6b8391 rename KmerPartition to KmerPartitions and update Mat enum
Rename the KmerPartition type to KmerPartitions across obikindex, obikpartitionner, and obikphylo/siblings to reflect an updated data model. Update the Mat enum in siblings/cache.rs to add a SparsePresence variant and simplify opening logic by delegating sparse versus dense detection to PersistentBitMatrix. Apply consistent code formatting, import reordering, and multi-line refactoring throughout the affected modules.
2026-08-20 15:57:33 +02:00
Eric Coissac 76cbd3a886 Centralize partition metadata access and add layer introspection APIs
Replaced scattered direct metadata loading with centralized instance methods on `KmerPartition` to guarantee consistent error mapping and legacy recovery. Introduced `StorageKind`, `LayerContent`, and `EvidenceKind` enums alongside lightweight disk-probe methods that inspect file presence without opening heavy data structures. Updated callers across the index, partitioner, and phylo modules to use the new partition API, and added unit tests validating the introspection behavior.
2026-08-20 15:29:53 +02:00
Eric Coissac f7ebc7a1ab Centralize partition directory resolution and add caching design spec
Introduce a design specification outlining performance bottlenecks in layer data access and an agreed-upon implementation direction for caching. Refactor the codebase to centralize index and layer directory path resolution within the partition object, replacing manual string joining and external helper functions with dedicated accessor methods.
2026-08-20 15:10:57 +02:00
Eric Coissac 7eaa8c2016 Replace manual layer path construction with obilayeredmap::layer_dir
Standardizes layer directory path resolution across obikindex, obikpartitionner, and obikphylo by replacing inline string formatting and join calls with the centralized obilayeredmap::layer_dir utility. This refactoring removes redundant path construction logic while preserving existing iteration bounds, control flow, and public APIs.
2026-08-20 14:54:13 +02:00
Eric Coissac 5a9d903e51 chore: update dependencies and adapt to updated crate APIs
Bumps core dependencies including ndarray, rand, hashbrown, niffler, ureq, sysinfo, indicatif, lru, and remove_dir_all. Adapts source code to accommodate breaking changes by migrating RNG initialization, adjusting HTTP response handling, and replacing the fs4 crate with standard library file locking. Adds a planning document for query benchmarking and sparse index regression tests.
2026-08-20 13:45:41 +02:00
Eric Coissac dbd8af376c Consolidate compare_sparse as example and clean up project artifacts
Restructure the project by moving the standalone compare_sparse utility into an example directory, removing Sankoff parameter configurations and benchmark scripts, updating version control ignores, and expanding the test suite with diagnostic checks and performance benchmarks.
2026-08-20 12:48:42 +02:00
Eric Coissac fceb523f1a chore: disable default features for obikindex
Release / create-release (push) Successful in 2m28s
ci.yml / build (pull_request) Successful in 4m41s
Release / build-linux-x86_64 (push) Successful in 8m23s
Release / build-macos-arm64 (push) Failing after 2m4s
Explicitly sets `default-features = false` for the `obikindex` dependency to ensure no default features are activated during dependency resolution and compilation.
2026-08-17 12:33:59 +02:00
Eric Coissac 700eaeaed2 test: simplify k-mer test setup for updated canonical API
Adapts sibling k-mer tests to the updated canonical API by replacing string-based construction with direct byte conversion. Removes intermediate reverse complement steps and introduces a helper function to compute reverse complement strings directly from canonical k-mers, preserving existing test output while streamlining setup.
2026-08-17 12:32:44 +02:00
Eric Coissac 1f9c6388eb Introduce compare_sparse CLI tool to verify index consistency
Adds a new binary that validates bit-level consistency between dense and sparse K-mer index representations by sampling slots across partitions and reporting discrepancies. Refactors sibling cache matrix initialization into a centralized factory method to simplify control flow and standardize error handling. Introduces diagnostic configurations, benchmark scripts, and an ignored test case to support k-mer resolution analysis.
2026-08-17 11:16:42 +02:00
Eric Coissac 128db64564 feat(phylo): add --iqtree-min-freq to filter rare nucleotide states
Introduces --iqtree-min-freq (default 0.001) to treat low-frequency nucleotide states as missing data during IQ-TREE alignment generation when --free-loss is active. This triggers a recoding pass that folds rare states into the missing symbol, followed by non-informative site removal and alphabet recomputation to maintain output consistency. The change also adds Sankoff model configuration files and updates related tests and documentation.
2026-08-17 11:06:03 +02:00
Eric Coissac c8f2b16b4c fix: prevent probability underflow in pairwise cost matrix
Replaces premature exponentiation-based row normalization with log-sum-exp arithmetic to prevent tiny probabilities from collapsing to exactly zero. This eliminates spurious infinite costs for valid but rare transitions while preserving correct IEEE 754 semantics for genuinely unobserved pairs. Adds explicit guards against NaN in degenerate rows and includes a regression test verifying finite costs for probabilities as low as 1e-200.
2026-08-17 09:41:50 +02:00
Eric Coissac c6cfdac043 perf: optimize entropy computation by pre-filtering monomorphic minorants
Shift monomorphism filtering from the entropy scan layer to a lightweight, annex-only pre-pass. By replacing `Selection::All` with a pre-filtered subset, expensive per-genome resolution is strictly limited to non-monomorphic families. This avoids processing ~98% of minorants that are known to be monomorphic, while preserving positional read speedups for subsequent runs. The change is an internal performance refinement with no public API modifications.
2026-08-17 09:32:45 +02:00
Eric Coissac 7bac0f3850 large refactoring 2026-08-17 09:28:53 +02:00
Eric Coissac 3ba26b3dc1 feat: add sparse on-disk format for presence matrices
The index packing API now accepts a `sparse` parameter to generate `PersistentSparseBitMatrix` files alongside existing dense matrices. The sibling cache automatically detects this format via an `is_multi.prsb` marker file and routes queries identically to the dense variant. A new `--sparse` CLI flag exposes the option, with tests verifying end-to-end pipeline correctness and storage equivalence.
2026-08-16 21:51:02 +02:00
Eric Coissac 50f4820cb9 feat(obicompactvec): introduce sparse bit matrix with supporting primitives
Implements a compact, row-major sparse bit matrix backed by memory-mapped components, introducing EliasFano, PersistentFixedIntVec, and PersistentRankSelectBitVec primitives for efficient storage and decoding. Adds a BinaryMatrix trait to unify row-level operations across dense and sparse implementations. Corrects edge-case behaviors for zero-width bit storage and cardinality-0 rows. Delivers reduced on-disk size and faster random row access, with column reads remaining dense-only. Test suites and benchmarks are included but currently marked as ignored.
2026-08-16 21:43:09 +02:00
Eric Coissac 45b19503a1 Add proportional subsampling and Shannon entropy calculation
Introduces `--subsample N` and `--shannon` CLI flags to cap retained variable families via proportional reservoir sampling and compute per-family Shannon entropy. Updates the family scanning API to support explicit selection filtering with early-exit optimization, resolving an indexing drift issue in monomorphic layers. Streams entropy metrics for 15-state and 4-nucleotide spaces directly to CSV while maintaining parallel processing across sibling layers.
2026-08-16 21:31:06 +02:00