use tracing::debug;
use crate::annotations::GeneId;
use crate::stats::hypergeom::statrs::Hypergeometric;
use crate::stats::{f64_from_u64, Enrichment, SampleSet};
use crate::HpoTerm;
pub fn gene_enrichment<'a, T, U>(background: T, set: U) -> Vec<Enrichment<GeneId>>
where
T: IntoIterator<Item = HpoTerm<'a>>,
U: IntoIterator<Item = HpoTerm<'a>>,
{
fn inner_gene_enrichment(
background: &SampleSet<GeneId>,
sample_set: &SampleSet<GeneId>,
) -> Vec<Enrichment<GeneId>> {
let mut res = Vec::new();
for (gene, observed_successes) in sample_set {
if observed_successes == 0 {
debug!("Skipping {}", gene);
continue;
}
let successes = background
.get(&gene)
.expect("gene must be present in background set");
let hyper = Hypergeometric::new(
background.len(),
*successes,
sample_set.len(),
)
.expect("the set must not be larger than the ontology");
let pvalue = hyper.sf(observed_successes - 1);
let enrichment = (f64_from_u64(observed_successes) / f64_from_u64(sample_set.len()))
/ (f64_from_u64(*successes) / f64_from_u64(background.len()));
res.push(Enrichment::gene(
gene,
pvalue,
observed_successes,
enrichment,
));
debug!(
"Gene:{}\tPopulation: {}, Successes: {}, Draws: {}, Observed: {}",
gene,
background.len(),
successes,
sample_set.len(),
observed_successes
);
}
res
}
let background = SampleSet::gene(background);
let sample_set = SampleSet::gene(set);
inner_gene_enrichment(&background, &sample_set)
}