1use crate::{axis::Axis, FillWith};
23use super::fill::{Fill, FillWithWeighted};
45// 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>;
1011pub(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>;
1415/// 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.
24fn axes(&self) -> &A;
2526/// Read a bin value given an index.
27 /// Return an Option as the given index may not be valid for this histogram.
28fn value_at_index(&self, index: usize) -> Option<&V>;
2930/// Read a bin value given a coordinate.
31 /// Returns an Option as the given coordinate may not be mapped to a bin.
32fn value(&self, coordinate: &A::Coordinate) -> Option<&V> {
33let index = self.axes().index(coordinate)?;
34self.value_at_index(index)
35 }
3637/// Iterator over bin values.
38fn values(&self) -> Values<'_, V>;
3940/// Iterator over bin indices, bin interval and bin values.
41fn iter(&self) -> Iter<'_, A, V>;
4243/// Mutable access to a bin value at a given index.
44fn value_at_index_mut(&mut self, index: usize) -> Option<&mut V>;
4546/// Mutable access to a bin value at a given coordinate.
47#[inline]
48fn value_mut(&mut self, coordinate: &A::Coordinate) -> Option<&mut V> {
49let index = self.axes().index(coordinate)?;
50self.value_at_index_mut(index)
51 }
5253/// Mutable iterator over bin values.
54fn values_mut(&mut self) -> ValuesMut<'_, V>;
55/// Mutable iterator over bin indices, bin interval and bin values.
56fn iter_mut(&mut self) -> IterMut<'_, A, V>;
5758/// 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]
62fn fill(&mut self, coordinate: &A::Coordinate)
63where
64V: Fill,
65 {
66if let Some(value) = self.value_mut(coordinate) {
67 value.fill()
68 }
69 }
7071/// 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]
75fn fill_with<D>(&mut self, coordinate: &A::Coordinate, data: D)
76where
77V: FillWith<D>,
78Self: Sized,
79 {
80if let Some(value) = self.value_mut(coordinate) {
81 value.fill_with(data)
82 }
83 }
8485/// 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]
89fn fill_with_weighted<D, W>(&mut self, coordinate: &A::Coordinate, data: D, weight: W)
90where
91V: FillWithWeighted<D, W>,
92Self: Sized,
93 {
94if let Some(value) = self.value_mut(coordinate) {
95 value.fill_with_weighted(data, weight)
96 }
97 }
98}
99100/// 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
105pub index: usize,
106/// Bin interval. See [Axis::BinInterval].
107pub bin: T,
108/// Bin value.
109pub value: V,
110}
111112impl<T, V> Item<T, V> {
113/// Factory method to create [Item].
114pub fn new(index: usize, bin: T, value: V) -> Self {
115Self { index, bin, value }
116 }
117}