use crate::error::PaCMAPError;
use flow_dimensional_reduction::Pca;
pub fn pca_init(data: &[f32], n: usize, d: usize) -> Result<Vec<[f32; 2]>, PaCMAPError> {
debug_assert_eq!(data.len(), n * d);
let pca = Pca::new(2).fit(data, n, d)?;
let flat = pca.transform(data, n, d)?;
let k = pca.n_components();
Ok(flat
.chunks(k)
.map(|c| [c[0], if k >= 2 { c[1] } else { 0.0 }])
.collect())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pca_separates_axis_aligned_clusters() {
let mut data: Vec<f32> = Vec::new();
for _ in 0..50 {
data.extend_from_slice(&[0.0_f32, 0.0]);
}
for _ in 0..50 {
data.extend_from_slice(&[10.0_f32, 0.0]);
}
let emb = pca_init(&data, 100, 2).unwrap();
let mean_left_x = emb[..50].iter().map(|p| p[0]).sum::<f32>() / 50.0;
let mean_right_x = emb[50..].iter().map(|p| p[0]).sum::<f32>() / 50.0;
assert!(
(mean_left_x - mean_right_x).abs() > 1.0,
"PCA should separate the two clusters along PC1"
);
}
}