molframe_core/annotation/
band.rs1use super::AnnotationColumn;
9use crate::column::Presence;
10
11pub const MISSING_BAND_CODE: u8 = u8::MAX;
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
16pub enum PlddtBand {
17 VeryLow,
19 Low,
21 Confident,
23 VeryHigh,
25}
26
27impl PlddtBand {
28 pub const ALL: [Self; 4] = [Self::VeryLow, Self::Low, Self::Confident, Self::VeryHigh];
30
31 #[must_use]
33 pub fn classify(score: f64) -> Option<Self> {
34 if !score.is_finite() {
35 return None;
36 }
37 Some(if score > 90.0 {
38 Self::VeryHigh
39 } else if score > 70.0 {
40 Self::Confident
41 } else if score > 50.0 {
42 Self::Low
43 } else {
44 Self::VeryLow
45 })
46 }
47
48 #[must_use]
50 pub const fn name(self) -> &'static str {
51 match self {
52 Self::VeryLow => "very_low",
53 Self::Low => "low",
54 Self::Confident => "confident",
55 Self::VeryHigh => "very_high",
56 }
57 }
58
59 #[must_use]
61 pub fn from_name(name: &str) -> Option<Self> {
62 Self::ALL
63 .into_iter()
64 .find(|band| band.name().eq_ignore_ascii_case(name))
65 }
66
67 #[must_use]
69 pub const fn rgb(self) -> [u8; 3] {
70 match self {
71 Self::VeryLow => [255, 125, 69],
72 Self::Low => [255, 219, 19],
73 Self::Confident => [101, 203, 243],
74 Self::VeryHigh => [0, 83, 214],
75 }
76 }
77
78 #[must_use]
80 pub const fn code(self) -> u8 {
81 match self {
82 Self::VeryLow => 0,
83 Self::Low => 1,
84 Self::Confident => 2,
85 Self::VeryHigh => 3,
86 }
87 }
88
89 #[must_use]
91 pub fn codes(column: &AnnotationColumn<f64>) -> Vec<u8> {
92 column
93 .values()
94 .iter()
95 .enumerate()
96 .map(|(row, score)| {
97 let recorded =
98 u32::try_from(row).is_ok_and(|atom| column.presence(atom) == Presence::Present);
99 Self::classify(*score)
100 .filter(|_| recorded)
101 .map_or(MISSING_BAND_CODE, Self::code)
102 })
103 .collect()
104 }
105
106 #[must_use]
108 pub const fn lower_bound(self) -> f64 {
109 match self {
110 Self::VeryLow => f64::NEG_INFINITY,
111 Self::Low => 50.0,
112 Self::Confident => 70.0,
113 Self::VeryHigh => 90.0,
114 }
115 }
116}
117
118#[cfg(test)]
119#[path = "band_tests.rs"]
120mod tests;