use rand::seq::SliceRandom;
use rand::thread_rng;
use crate::collections::{Feature, FeatureSetProvider, RankedFeatureList};
pub struct PermutedRankedFeatureList<'a> {
original: &'a RankedFeatureList,
indices: Vec<usize>,
}
impl<'a> PermutedRankedFeatureList<'a> {
pub fn new(original: &'a RankedFeatureList) -> Self {
let mut indices: Vec<usize> = (0..original.genes().len()).collect();
indices.shuffle(&mut thread_rng());
Self { original, indices }
}
pub fn thresholds(&self) -> &[u32] {
self.original.thresholds()
}
pub fn ranks(&self) -> &[u32] {
self.original.ranks()
}
}
impl FeatureSetProvider for PermutedRankedFeatureList<'_> {
fn get_feature_set_by_threshold(&self, threshold: u32) -> Vec<Feature> {
let mut result = Vec::new();
for (rank, index) in self.ranks().iter().zip(self.indices.iter()) {
if *rank <= threshold {
result.push(self.original.genes()[*index].clone());
}
}
result
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::collections::{Feature, FeatureList, RankedFeatureList};
#[test]
fn test_permuted_ranked_feature_list_with_thresholds() {
let genes = FeatureList::from(vec![
Feature::from("gene1"),
Feature::from("gene2"),
Feature::from("gene3"),
Feature::from("gene4"),
Feature::from("gene5"),
Feature::from("gene6"),
Feature::from("gene7"),
Feature::from("gene8"),
Feature::from("gene9"),
Feature::from("gene10"),
]);
let ranks = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let ranked_feature_list = RankedFeatureList::from(genes.clone(), ranks).unwrap();
let permuted = PermutedRankedFeatureList::new(&ranked_feature_list);
let genes_below_threshold = permuted.get_feature_set_by_threshold(10);
assert_eq!(genes_below_threshold.len(), 10);
let expected_genes: Vec<Feature> = genes.iter().take(10).cloned().collect();
assert_ne!(
genes_below_threshold, expected_genes,
"Features should not be in the same order after permutation"
);
}
}