Skip to content

Commit 8ab818b

Browse files
committed
Added ability to display a histogram as densities
1 parent e89a973 commit 8ab818b

File tree

4 files changed

+37
-12
lines changed

4 files changed

+37
-12
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- Bar charts.
88
- Introduce categorical representation, views and axes.
99
- Add ability to set dimensions of plot (PR #8)
10+
- Added ability to display a histogram as densities
1011

1112
### Changed
1213
- Change `create_axes`, `save`, `to_svg` and `to_text` to return `Result` indicating an error.

src/histogram.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,22 @@ impl style::Bar for Style {
6262
}
6363
}
6464

65+
#[derive(Debug)]
66+
enum HistogramType {
67+
Count,
68+
Density,
69+
}
70+
6571
/**
6672
A one-dimensional histogram with equal binning.
6773
*/
6874
#[derive(Debug)]
6975
pub struct Histogram {
7076
pub bin_bounds: Vec<f64>, // will have N_bins + 1 entries
71-
pub bin_counts: Vec<u32>, // will have N_bins entries
77+
pub bin_counts: Vec<f64>, // will have N_bins entries
7278
pub bin_densities: Vec<f64>, // will have N_bins entries
7379
style: Style,
80+
h_type: HistogramType,
7481
}
7582

7683
impl Histogram {
@@ -117,9 +124,10 @@ impl Histogram {
117124

118125
Histogram {
119126
bin_bounds: bounds,
120-
bin_counts: bins,
127+
bin_counts: bins.iter().map(|&x| f64::from(x)).collect(),
121128
bin_densities: density_per_bin,
122129
style: Style::new(),
130+
h_type: HistogramType::Count,
123131
}
124132
}
125133

@@ -135,18 +143,36 @@ impl Histogram {
135143
}
136144

137145
fn y_range(&self) -> (f64, f64) {
138-
let max = *self.bin_counts.iter().max().unwrap();
139-
(0., f64::from(max))
146+
let max = self
147+
.get_values()
148+
.iter()
149+
.fold(-1. / 0., |a, &b| f64::max(a, b));
150+
(0., max)
140151
}
141152

142153
pub fn style(mut self, style: &Style) -> Self {
143154
self.style.overlay(style);
144155
self
145156
}
146157

158+
/**
159+
Set the histogram to display as normalised densities
160+
*/
161+
pub fn density(mut self) -> Self {
162+
self.h_type = HistogramType::Density;
163+
self
164+
}
165+
147166
pub fn get_style(&self) -> &Style {
148167
&self.style
149168
}
169+
170+
pub fn get_values(&self) -> &[f64] {
171+
match self.h_type {
172+
HistogramType::Count => &self.bin_counts,
173+
HistogramType::Density => &self.bin_densities,
174+
}
175+
}
150176
}
151177

152178
impl ContinuousRepresentation for Histogram {
@@ -185,14 +211,14 @@ mod tests {
185211

186212
#[test]
187213
fn test_histogram_from_slice() {
188-
assert_eq!(Histogram::from_slice(&[], 3).bin_densities, [0., 0., 0.]);
189-
assert_eq!(Histogram::from_slice(&[0.], 3).bin_densities, [0., 3., 0.]);
214+
assert_eq!(Histogram::from_slice(&[], 3).get_values(), [0., 0., 0.]);
215+
assert_eq!(Histogram::from_slice(&[0.], 3).get_values(), [0., 1., 0.]);
190216
assert_eq!(
191-
Histogram::from_slice(&[0., 3.], 3).bin_densities,
217+
Histogram::from_slice(&[0., 3.], 3).get_values(),
192218
[1., 0., 1.]
193219
);
194220
assert_eq!(
195-
Histogram::from_slice(&[0., 1., 2., 3.], 3).bin_densities,
221+
Histogram::from_slice(&[0., 1., 2., 3.], 3).get_values(),
196222
[2., 1., 1.]
197223
);
198224
}

src/svg_render.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ where
237237
{
238238
let mut group = node::element::Group::new();
239239

240-
for ((&l, &u), &count) in h.bin_bounds.pairwise().zip(h.bin_counts.iter()) {
240+
for ((&l, &u), &count) in h.bin_bounds.pairwise().zip(h.get_values()) {
241241
let l_pos = value_to_face_offset(l, x_axis, face_width);
242242
let u_pos = value_to_face_offset(u, x_axis, face_width);
243243
let width = u_pos - l_pos;

src/text_render.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,7 @@ pub fn render_face_bars(
286286
.iter()
287287
.map(|&bin| match bin {
288288
None => 0,
289-
Some(b) => {
290-
value_to_axis_cell_offset(f64::from(h.bin_counts[b as usize]), y_axis, face_height)
291-
}
289+
Some(b) => value_to_axis_cell_offset(h.get_values()[b as usize], y_axis, face_height),
292290
}).collect();
293291

294292
let mut face_strings: Vec<String> = vec![];

0 commit comments

Comments
 (0)