use crate::{
scale::HistogramEma,
stencil::{N_ARMS, normalized_arms_at},
};
const SHAPE_BETA: f64 = 0.004;
#[derive(Clone)]
pub(crate) struct ShapeAnchor {
weight: f64,
profile: [f64; N_ARMS],
}
impl ShapeAnchor {
pub(crate) fn new(weight: f64) -> Self {
Self {
weight,
profile: [1.0 / N_ARMS as f64; N_ARMS],
}
}
pub(crate) fn score(&self, ema: &HistogramEma, bin: i64) -> f64 {
if self.weight == 0.0 {
return 0.0;
}
self.weight * self.shape_match(ema, bin)
}
pub(crate) fn update(&mut self, ema: &HistogramEma, pick: i64) {
if self.weight == 0.0 {
return;
}
if let Some(arms) = normalized_arms_at(ema, pick) {
(0..N_ARMS).for_each(|i| {
self.profile[i] = (1.0 - SHAPE_BETA) * self.profile[i] + SHAPE_BETA * arms[i];
});
}
}
fn shape_match(&self, ema: &HistogramEma, center: i64) -> f64 {
match normalized_arms_at(ema, center) {
Some(arms) => {
1.0 - (0..N_ARMS)
.map(|i| (arms[i] - self.profile[i]).abs())
.sum::<f64>()
}
None => 0.0,
}
}
}