phenotypes/
observation.rs

1/// An `Observable` entity is either in a *present* or an *excluded* state
2/// in the investigated item.
3///
4/// For instance, a phenotypic feature such as [Polydactyly](https://hpo.jax.org/browse/term/HP:0010442)
5/// can either be present or excluded in the study subject.
6pub trait Observable {
7    /// Test if the feature was observed in one or more items.
8    fn is_present(&self) -> bool;
9    /// Test if the feature was not observed in any of the items.
10    fn is_excluded(&self) -> bool {
11        !self.is_present()
12    }
13}
14
15/// Common functionalities for containers of [`Observable`] features.
16pub trait ObservableFeatures {
17    /// The feature.
18    type Feature;
19
20    /// Get an iterator over features that were observed in the investigated item.
21    fn present_features(&self) -> impl Iterator<Item = &Self::Feature>;
22    /// Get the number of observed features.
23    fn present_feature_count(&self) -> usize {
24        self.present_features().count()
25    }
26
27    /// Get an iterator over features whose presence was specifically excluded in the investigated item.
28    fn excluded_features(&self) -> impl Iterator<Item = &Self::Feature>;
29    /// Get the number of features whose presence was specifically excluded.
30    fn excluded_feature_count(&self) -> usize {
31        self.excluded_features().count()
32    }
33}
34
35impl<T> ObservableFeatures for &[T]
36where
37    T: Observable,
38{
39    type Feature = T;
40
41    fn present_features(&self) -> impl Iterator<Item = &Self::Feature> {
42        self.iter().filter(|&t| t.is_present())
43    }
44
45    fn excluded_features(&self) -> impl Iterator<Item = &Self::Feature> {
46        self.iter().filter(|&t| t.is_excluded())
47    }
48}
49
50impl<T, const N: usize> ObservableFeatures for [T; N]
51where
52    T: Observable,
53{
54    type Feature = T;
55
56    fn present_features(&self) -> impl Iterator<Item = &Self::Feature> {
57        self.iter().filter(|&t| t.is_present())
58    }
59
60    fn excluded_features(&self) -> impl Iterator<Item = &Self::Feature> {
61        self.iter().filter(|&t| t.is_excluded())
62    }
63}
64
65impl<T> ObservableFeatures for Vec<T>
66where
67    T: Observable,
68{
69    type Feature = T;
70
71    fn present_features(&self) -> impl Iterator<Item = &Self::Feature> {
72        self.iter().filter(|&t| t.is_present())
73    }
74
75    fn excluded_features(&self) -> impl Iterator<Item = &Self::Feature> {
76        self.iter().filter(|&t| t.is_excluded())
77    }
78}