Skip to content

Commit abb968d

Browse files
committed
Add stem plots
1 parent 2556763 commit abb968d

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

examples/plot_types.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ fn main() -> anyhow::Result<()> {
1111
plot_xy()?;
1212
scatter_xy()?;
1313
bar()?;
14+
stem()?;
1415
Ok(())
1516
}
1617

@@ -81,3 +82,20 @@ fn bar() -> anyhow::Result<()> {
8182
fig.save().to_file(format!("{BASE}bar.pdf"))?;
8283
Ok(())
8384
}
85+
86+
fn stem() -> anyhow::Result<()> {
87+
mpl::style::using("_mpl-gallery")?;
88+
89+
let x = Array1::range(0.5, 8.5, 1.);
90+
let y = [4.8, 5.5, 3.5, 4.6, 6.5, 6.6, 2.6, 3.0];
91+
92+
let fig = Figure::new()?;
93+
let [[mut ax]] = fig.subplots()?;
94+
95+
ax.stem(x.as_slice().unwrap(), &y).plot();
96+
97+
ax.set_xlim(0., 8.) .set_xticks(Array1::range(1., 8., 1.))
98+
.set_ylim(0., 8.) .set_yticks(Array1::range(1., 8., 1.));
99+
fig.save().to_file(format!("{BASE}stem.pdf"))?;
100+
Ok(())
101+
}

src/axes.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,22 @@ impl Axes {
231231
Bar::new(self, x, height)
232232
}
233233

234+
/// Create a stem plot.
235+
///
236+
/// A stem plot draws lines perpendicular to a baseline at each
237+
/// location locs from the baseline to heads, and places a marker
238+
/// there. For vertical stem plots (the default), the locs are
239+
/// `x` positions, and the heads are `y` values. For horizontal
240+
/// stem plots, the locs are `y` positions, and the heads are `x`
241+
/// values.
242+
pub fn stem<'a, D1, D2>(&'a mut self, x: D1, y: D2) -> Stem<'a>
243+
where
244+
D1: AsRef<[f64]> + 'a,
245+
D2: AsRef<[f64]> + 'a,
246+
{
247+
Stem::new(self, x, y)
248+
}
249+
234250
/// Set the title to `txt` for the Axes.
235251
pub fn set_title(&mut self, txt: impl AsRef<str>) -> &mut Self {
236252
meth!(self.ax, set_title, (txt.as_ref(),)).unwrap();
@@ -966,6 +982,63 @@ impl<'a> Bar<'a> {
966982
}
967983
}
968984

985+
pub struct Stem<'a> {
986+
axes: &'a Axes,
987+
x: Box<dyn AsRef<[f64]> + 'a>,
988+
y: Box<dyn AsRef<[f64]> + 'a>,
989+
linefmt: &'a str, // FIXME: enum
990+
markerfmt: &'a str,
991+
basefmt: &'a str,
992+
}
993+
994+
impl<'a> Stem<'a> {
995+
fn new<D1, D2>(axes: &'a Axes, x: D1, y: D2) -> Self
996+
where
997+
D1: AsRef<[f64]> + 'a,
998+
D2: AsRef<[f64]> + 'a,
999+
{
1000+
Self {
1001+
axes,
1002+
x: Box::new(x),
1003+
y: Box::new(y),
1004+
linefmt: "C0-",
1005+
markerfmt: "o",
1006+
basefmt: "C3-",
1007+
}
1008+
}
1009+
1010+
pub fn linefmt(mut self, fmt: &'a str) -> Self {
1011+
self.linefmt = fmt;
1012+
self
1013+
}
1014+
1015+
pub fn markerfmt(mut self, fmt: &'a str) -> Self {
1016+
self.markerfmt = fmt;
1017+
self
1018+
}
1019+
1020+
pub fn basefmt(mut self, fmt: &'a str) -> Self {
1021+
self.basefmt = fmt;
1022+
self
1023+
}
1024+
1025+
pub fn plot(self) {
1026+
Python::attach(|py| {
1027+
let x = self.x.as_ref().as_ref().to_pyarray(py);
1028+
let y = self.y.as_ref().as_ref().to_pyarray(py);
1029+
let kwargs = PyDict::new(py);
1030+
kwargs.set_item("linefmt", self.linefmt).unwrap();
1031+
kwargs.set_item("markerfmt", self.markerfmt).unwrap();
1032+
kwargs.set_item("basefmt", self.basefmt).unwrap();
1033+
self.axes.ax.bind(py)
1034+
.call_method(intern!(py, "stem"),
1035+
(x, y),
1036+
Some(&kwargs))
1037+
.unwrap();
1038+
})
1039+
}
1040+
}
1041+
9691042
pub struct QuadContourSet {
9701043
contours: Py<PyAny>,
9711044
}

0 commit comments

Comments
 (0)