ndhistogram/histogram/histogram.rs
1use crate::{axis::Axis, FillWith};
2
3use super::fill::{Fill, FillWithWeighted};
4
5// TODO: Using generic associated types would give a cleaner interface and avoid boxing the iterators
6// https://github.com/rust-lang/rfcs/blob/master/text/1598-generic_associated_types.md
7pub(crate) type Values<'a, V> = Box<dyn Iterator<Item = &'a V> + 'a>;
8pub(crate) type Iter<'a, A, V> =
9 Box<dyn Iterator<Item = Item<<A as Axis>::BinInterval, &'a V>> + 'a>;
10
11pub(crate) type ValuesMut<'a, V> = Box<dyn Iterator<Item = &'a mut V> + 'a>;
12pub(crate) type IterMut<'a, A, V> =
13 Box<dyn Iterator<Item = Item<<A as Axis>::BinInterval, &'a mut V>> + 'a>;
14
15/// A common interface for an ND histograms.
16///
17/// Implementations of this trait should handle storing the histogram bin values
18/// and provide methods to fill and read those values.
19///
20/// The most commonly used implementation is [VecHistogram](crate::VecHistogram).
21/// See [crate::ndhistogram] for examples of its use.
22pub trait Histogram<A: Axis, V> {
23 /// The histogram [Axes](crate::Axes) that map coordinates to bin numbers.
24 fn axes(&self) -> &A;
25
26 /// Read a bin value given an index.
27 /// Return an Option as the given index may not be valid for this histogram.
28 fn value_at_index(&self, index: usize) -> Option<&V>;
29
30 /// Read a bin value given a coordinate.
31 /// Returns an Option as the given coordinate may not be mapped to a bin.
32 fn value(&self, coordinate: &A::Coordinate) -> Option<&V> {
33 let index = self.axes().index(coordinate)?;
34 self.value_at_index(index)
35 }
36
37 /// Iterator over bin values.
38 fn values(&self) -> Values<'_, V>;
39
40 /// Iterator over bin indices, bin interval and bin values.
41 fn iter(&self) -> Iter<'_, A, V>;
42
43 /// Mutable access to a bin value at a given index.
44 fn value_at_index_mut(&mut self, index: usize) -> Option<&mut V>;
45
46 /// Mutable access to a bin value at a given coordinate.
47 #[inline]
48 fn value_mut(&mut self, coordinate: &A::Coordinate) -> Option<&mut V> {
49 let index = self.axes().index(coordinate)?;
50 self.value_at_index_mut(index)
51 }
52
53 /// Mutable iterator over bin values.
54 fn values_mut(&mut self) -> ValuesMut<'_, V>;
55 /// Mutable iterator over bin indices, bin interval and bin values.
56 fn iter_mut(&mut self) -> IterMut<'_, A, V>;
57
58 /// Fill the histogram bin value at coordinate with unit weight.
59 /// If the [Axes](crate::Axes) do not cover that coordinate, do nothing.
60 /// See [Fill](crate::Fill).
61 #[inline]
62 fn fill(&mut self, coordinate: &A::Coordinate)
63 where
64 V: Fill,
65 {
66 if let Some(value) = self.value_mut(coordinate) {
67 value.fill()
68 }
69 }
70
71 /// Fill the histogram bin value at coordinate with some data.
72 /// If the [Axes](crate::Axes) do not cover that coordinate, do nothing.
73 /// See [FillWith](crate::FillWith).
74 #[inline]
75 fn fill_with<D>(&mut self, coordinate: &A::Coordinate, data: D)
76 where
77 V: FillWith<D>,
78 Self: Sized,
79 {
80 if let Some(value) = self.value_mut(coordinate) {
81 value.fill_with(data)
82 }
83 }
84
85 /// Fill the histogram bin value at coordinate with some data.
86 /// If the [Axes](crate::Axes) do not cover that coordinate, do nothing.
87 /// See [FillWithWeighted].
88 #[inline]
89 fn fill_with_weighted<D, W>(&mut self, coordinate: &A::Coordinate, data: D, weight: W)
90 where
91 V: FillWithWeighted<D, W>,
92 Self: Sized,
93 {
94 if let Some(value) = self.value_mut(coordinate) {
95 value.fill_with_weighted(data, weight)
96 }
97 }
98}
99
100/// Struct to be returned when iterating over [Histogram]s bins.
101#[derive(Copy, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
102#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
103pub struct Item<T, V> {
104 /// Bin number
105 pub index: usize,
106 /// Bin interval. See [Axis::BinInterval].
107 pub bin: T,
108 /// Bin value.
109 pub value: V,
110}
111
112impl<T, V> Item<T, V> {
113 /// Factory method to create [Item].
114 pub fn new(index: usize, bin: T, value: V) -> Self {
115 Self { index, bin, value }
116 }
117}