use rusqlite::Connection;
use std::path::PathBuf;
use timsrust::readers::FrameReader;
fn main() -> anyhow::Result<()> {
let path: PathBuf = std::env::args()
.nth(1)
.expect("usage: validate <PATH.d>")
.into();
let conn = Connection::open(path.join("analysis.tdf"))?;
let mut stmt = conn.prepare("SELECT Id, NumPeaks FROM Frames ORDER BY Id")?;
let meta: Vec<(usize, i64)> = stmt
.query_map([], |r| {
Ok((r.get::<_, i64>(0)? as usize, r.get::<_, i64>(1)?))
})?
.collect::<Result<_, _>>()?;
let comp: String = conn.query_row(
"SELECT Value FROM GlobalMetadata WHERE Key='TimsCompressionType'",
[],
|r| r.get(0),
)?;
let reader = FrameReader::new(&path).map_err(|e| anyhow::anyhow!("{e}"))?;
let n = reader.len();
let mut total = 0u64;
let mut empty = 0u64;
let mut mismatches = 0u64;
for i in 0..n {
let (id, db_peaks) = meta.get(i).copied().unwrap_or((0, -1));
match reader.get(i) {
Ok(frame) => {
let peaks = frame.tof_indices.len();
total += peaks as u64;
if db_peaks >= 0 && db_peaks as usize != peaks {
mismatches += 1;
if mismatches <= 5 {
eprintln!("frame {i} (id {id}): binary {peaks} != db {db_peaks}");
}
}
}
Err(e) => {
if db_peaks == 0 {
empty += 1;
} else {
return Err(anyhow::anyhow!(
"frame {i} (id {id}, db peaks {db_peaks}): {e}"
));
}
}
}
}
println!(
"validate: {n} frames re-read OK ({empty} empty), {total} total points, compression={comp}, {mismatches} db/bin mismatches"
);
if mismatches > 0 {
std::process::exit(1);
}
Ok(())
}