use super::{csc_columns_to_full_samples, widest_support};
use crate::candle::data::indexed::top_k::csc_columns_to_indexed_samples;
use nalgebra_sparse::{CooMatrix, CscMatrix};
const D: usize = 8;
const N: usize = 3;
fn planted() -> CscMatrix<f32> {
let mut coo = CooMatrix::<f32>::new(D, N);
for (g, v) in [(0usize, 3.0f32), (2, 1.0), (5, 7.0), (7, 2.0)] {
coo.push(g, 0, v);
}
coo.push(4, 1, 5.0);
CscMatrix::from(&coo)
}
#[test]
fn every_stored_nonzero_survives_in_its_own_cell() {
let x = planted();
let s = csc_columns_to_full_samples(&x, None);
assert_eq!(s.len(), N);
assert_eq!(s[0].indices, vec![0, 2, 5, 7], "ascending row order");
assert_eq!(s[0].values, vec![3.0, 1.0, 7.0, 2.0], "raw stored counts");
assert_eq!(s[1].indices, vec![4]);
assert_eq!(s[1].values, vec![5.0]);
assert!(
s[2].indices.is_empty() && s[2].values.is_empty(),
"a cell with no observation packs to an empty support, not to padding"
);
}
#[test]
fn values_are_not_reweighted() {
let x = planted();
let s = csc_columns_to_full_samples(&x, None);
let total: f32 = s.iter().flat_map(|c| c.values.iter()).sum();
assert!((total - 18.0).abs() < 1e-6, "3+1+7+2+5 = 18, got {total}");
}
#[test]
fn a_gene_remap_renumbers_and_drops() {
let x = planted();
let remap: Vec<Option<usize>> =
vec![Some(10), None, None, None, Some(11), Some(12), None, None];
let s = csc_columns_to_full_samples(&x, Some(&remap));
assert_eq!(s[0].indices, vec![10, 12], "gene 0 -> 10, gene 5 -> 12");
assert_eq!(s[0].values, vec![3.0, 7.0], "their counts follow them");
assert_eq!(s[1].indices, vec![11]);
assert!(s[2].indices.is_empty());
}
#[test]
fn the_widest_support_is_the_pack_width() {
let x = planted();
let s = csc_columns_to_full_samples(&x, None);
assert_eq!(widest_support(&s), 4, "cell 0 has the widest support");
assert_eq!(widest_support(&[]), 0, "an empty batch has no width");
assert_eq!(
widest_support(&s[2..]),
0,
"a batch of unobserved cells has no width"
);
}
#[test]
fn full_support_equals_top_k_once_k_covers_the_support() {
let x = planted();
let full = csc_columns_to_full_samples(&x, None);
let weights = vec![1.0f32; D];
for k in [4usize, 8, 64] {
let capped = csc_columns_to_indexed_samples(&x, &weights, k, None);
assert_eq!(capped.len(), full.len());
for (n, (a, b)) in capped.iter().zip(&full).enumerate() {
let mut got: Vec<(u32, f32)> = a
.indices
.iter()
.copied()
.zip(a.values.iter().copied())
.collect();
let mut want: Vec<(u32, f32)> = b
.indices
.iter()
.copied()
.zip(b.values.iter().copied())
.collect();
got.sort_by_key(|e| e.0);
want.sort_by_key(|e| e.0);
assert_eq!(got, want, "cell {n} differs at context_size {k}");
}
}
}
#[test]
fn a_window_narrower_than_the_support_drops_genes() {
let x = planted();
let full = csc_columns_to_full_samples(&x, None);
let weights = vec![1.0f32; D];
let capped = csc_columns_to_indexed_samples(&x, &weights, 2, None);
assert_eq!(capped[0].indices.len(), 2);
assert_eq!(full[0].indices.len(), 4);
}