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.
106 lines
3.9 KiB
Rust
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(())
|
|
}
|