use std::borrow::Borrow;
use rust_htslib::bcf::Record;
pub use crate::common::cluster_settings::ClusteringSettings;
impl ClusteringSettings {
pub fn belongs<R: Borrow<Record>>(
&self,
last: Option<R>,
candidate: R,
) -> anyhow::Result<bool> {
let Some(last) = last else {
return Ok(true);
};
Ok(candidate.borrow().pos().saturating_sub(last.borrow().end())
<= self.max_gap.try_into()?)
}
pub fn is_cluster<R, F: Fn(&R) -> &Record, G: Fn(&R) -> Option<u32>>(
&self,
cluster: &[R],
get_record: F,
get_allele: G,
) -> bool {
if cluster.is_empty() {
return false;
}
let first = get_record(cluster.first().unwrap().borrow());
let last = get_record(cluster.last().unwrap().borrow());
let l_ref = first.pos().abs_diff(last.end()) as f64 + 1.0;
let (mass, net) = cluster
.iter()
.map(|r| (get_record(r), get_allele(r)))
.filter_map(|(r, a)| self.chosen_allele_lens(r, a))
.fold((0.0, 0.0), |(mass, net), (ref_len, alt_len)| {
(
mass + self.event_mass(ref_len, alt_len),
net + alt_len as f64 - ref_len as f64,
)
});
let span = self.span(l_ref, l_ref + net);
self.is_valid_cluster(mass, span, cluster.len())
}
fn chosen_allele_lens(&self, record: &Record, allele: Option<u32>) -> Option<(usize, usize)> {
let alls = record.alleles();
if alls.len() < 2 {
return None;
}
let ref_len = alls[0].len();
let alt_len = if let Some(a) = allele {
alls.get(a as usize)?.len()
} else {
alls[1..]
.iter()
.map(|a| a.len())
.max_by(|x, y| {
self.event_mass(ref_len, *x)
.partial_cmp(&self.event_mass(ref_len, *y))
.unwrap()
})
.unwrap()
};
Some((ref_len, alt_len))
}
}