2026-08-19 19:17:14 +02:00
|
|
|
//! 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>
|
|
|
|
|
|
2026-08-16 09:22:41 +02:00
|
|
|
use obicompactvec::{PersistentBitMatrix, PersistentSparseBitMatrix};
|
|
|
|
|
use obikindex::KmerIndex;
|
|
|
|
|
|
|
|
|
|
fn main() -> anyhow::Result<()> {
|
2026-08-19 19:17:14 +02:00
|
|
|
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>");
|
2026-08-16 09:22:41 +02:00
|
|
|
|
|
|
|
|
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(())
|
|
|
|
|
}
|