Files
obikmer/src/obikindex/examples/compare_sparse.rs
T
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

106 lines
3.9 KiB
Rust

//! Diagnostic tool: verify that a sparse-packed presence index (`pack --sparse`)
//! is bit-for-bit identical to the dense index it was compacted from.
//!
//! Usage: cargo run --example compare_sparse -p obikindex -- <sparse_root> <dense_root>
use obicompactvec::{PersistentBitMatrix, PersistentSparseBitMatrix};
use obikindex::KmerIndex;
fn main() -> anyhow::Result<()> {
let sparse_root = std::env::args().nth(1).expect("usage: compare_sparse <sparse_root> <dense_root>");
let dense_root = std::env::args().nth(2).expect("usage: compare_sparse <sparse_root> <dense_root>");
let sparse = KmerIndex::open(&sparse_root)?;
let dense = KmerIndex::open(&dense_root)?;
let n_parts = sparse.n_partitions();
let n_layers = sparse.n_layers_per_partition()?;
println!("index sparse: {} partitions, {} layers", sparse.n_partitions(), n_layers);
println!("index dense: {} partitions, {} layers", dense.n_partitions(), dense.n_layers_per_partition()?);
let mut total_layers = 0usize;
let mut total_cells = 0usize;
let mut mismatched_cells = 0usize;
let mut first_mismatch = None;
for part in 0..n_parts {
let part_dir_sparse = sparse.partition().part_dir(part);
let part_dir_dense = dense.partition().part_dir(part);
if !part_dir_sparse.join("index").exists() || !part_dir_dense.join("index").exists() {
continue;
}
for layer in 0..n_layers {
let layer_dir_sparse = part_dir_sparse.join("index").join(format!("layer_{layer}"));
let layer_dir_dense = part_dir_dense.join("index").join(format!("layer_{layer}"));
if !layer_dir_sparse.exists() || !layer_dir_dense.exists() {
continue;
}
let presence_sparse = layer_dir_sparse.join("presence");
let presence_dense = layer_dir_dense.join("presence");
if !presence_sparse.exists() || !presence_dense.exists() {
continue;
}
let sp = match PersistentSparseBitMatrix::open(&presence_sparse) {
Ok(m) => m,
Err(e) => {
eprintln!("ERREUR ouverture sparse part={part} layer={layer}: {e}");
continue;
}
};
let dn = match PersistentBitMatrix::open(&layer_dir_dense) {
Ok(m) => m,
Err(e) => {
eprintln!("ERREUR ouverture dense part={part} layer={layer}: {e}");
continue;
}
};
if dn.n_cols() != sp.n_cols() || dn.n() != sp.n() || dn.n() == 0 {
continue;
}
let n = dn.n();
let n_cols = dn.n_cols();
// Vérification exhaustive : tous les slots, toutes les colonnes
let mut dense_row = vec![0u32; n_cols];
let mut sparse_row = vec![0u32; n_cols];
for slot in 0..n {
dn.fill_row(slot, &mut dense_row);
sp.fill_row(slot, &mut sparse_row);
for c in 0..n_cols {
total_cells += 1;
if dense_row[c] != sparse_row[c] {
mismatched_cells += 1;
if first_mismatch.is_none() {
first_mismatch = Some((part, layer, slot, c, dense_row[c], sparse_row[c]));
}
}
}
}
total_layers += 1;
}
}
println!("Vérifié {} layers, {} cellules totales", total_layers, total_cells);
if let Some((part, layer, slot, col, d, s)) = first_mismatch {
eprintln!("PREMIER MISMATCH : part={part} layer={layer} slot={slot} col={col} dense={d} sparse={s}");
println!("MISMATCHES : {} cellules différentes", mismatched_cells);
} else {
println!("OK : toutes les {} cellules sont identiques entre dense et sparse.", total_cells);
}
Ok(())
}