rustplotlib/
axes2d.rs

1use std::io;
2use backend::Backend;
3
4/// Represents an instance of `matplotlib.axes.Axes`.
5#[derive(Debug, Default)]
6pub struct Axes2D<'a> {
7  plot_data: Vec<PlotData<'a>>,
8  xlabel: Option<String>,
9  ylabel: Option<String>,
10  grid: bool,
11  legend: Option<String>,
12  xlim: Option<(f64, f64)>,
13  ylim: Option<(f64, f64)>,
14}
15
16impl<'a> Axes2D<'a> {
17  /// create an empty axes.
18  ///
19  /// This method is the shortcut of `Default::default()`.
20  pub fn new() -> Self {
21    Default::default()
22  }
23
24  /// add a plot data.
25  pub fn add<P: Into<PlotData<'a>>>(mut self, p: P) -> Self {
26    self.plot_data.push(p.into());
27    self
28  }
29
30  /// set the label text of x axis.
31  pub fn xlabel(mut self, text: &str) -> Self {
32    self.xlabel = Some(text.to_owned());
33    self
34  }
35
36  /// set the label text of y axis.
37  pub fn ylabel(mut self, text: &str) -> Self {
38    self.ylabel = Some(text.to_owned());
39    self
40  }
41
42  /// set whether the grid is shown or not.
43  pub fn grid(mut self, enabled: bool) -> Self {
44    self.grid = enabled;
45    self
46  }
47
48  /// set the location of legend in the axes.
49  ///
50  /// if the value of `loc` is empty, the legend is hidden.
51  pub fn legend(mut self, loc: &str) -> Self {
52    self.legend = if loc.trim() != "" {
53      Some(loc.to_owned())
54    } else {
55      None
56    };
57    self
58  }
59
60  /// set the range of x axis.
61  pub fn xlim(mut self, lb: f64, ub: f64) -> Self {
62    self.xlim = Some((lb, ub));
63    self
64  }
65
66  /// set the range of y axis.
67  pub fn ylim(mut self, lb: f64, ub: f64) -> Self {
68    self.ylim = Some((lb, ub));
69    self
70  }
71
72  pub fn apply<B: Backend>(&self, mpl: &mut B) -> io::Result<()> {
73    for ref plot in &self.plot_data {
74      plot.apply(mpl)?;
75    }
76    mpl.grid(self.grid)?;
77    if let Some(ref loc) = self.legend {
78      mpl.legend(loc)?;
79    }
80    if let Some(ref xlim) = self.xlim {
81      mpl.xlim(xlim)?;
82    }
83    if let Some(ref ylim) = self.ylim {
84      mpl.ylim(ylim)?;
85    }
86    Ok(())
87  }
88}
89
90
91/// Plot type.
92#[derive(Debug)]
93pub enum PlotData<'a> {
94  Scatter(Scatter<'a>),
95  Line2D(Line2D<'a>),
96  FillBetween(FillBetween<'a>),
97}
98
99impl<'a> PlotData<'a> {
100  pub fn apply<B: Backend>(&self, mpl: &mut B) -> io::Result<()> {
101    match *self {
102      PlotData::Scatter(ref s) => s.apply(mpl),
103      PlotData::Line2D(ref l) => l.apply(mpl),
104      PlotData::FillBetween(ref f) => f.apply(mpl),
105    }
106  }
107}
108
109#[derive(Debug, Default)]
110pub struct Scatter<'a> {
111  xdata: &'a [f64],
112  ydata: &'a [f64],
113  label: Option<String>,
114  color: Option<String>,
115  marker: Option<String>,
116}
117
118impl<'a> Scatter<'a> {
119  pub fn new(name: &str) -> Scatter<'a> {
120    Scatter::default().label(name)
121  }
122
123  pub fn data(mut self, xdata: &'a [f64], ydata: &'a [f64]) -> Self {
124    self.xdata = xdata;
125    self.ydata = ydata;
126    self
127  }
128
129  pub fn label(mut self, text: &str) -> Self {
130    self.label = Some(text.to_owned());
131    self
132  }
133
134  pub fn color(mut self, color: &str) -> Self {
135    self.color = Some(color.to_owned());
136    self
137  }
138
139  pub fn marker(mut self, marker: &str) -> Self {
140    self.marker = Some(marker.to_owned());
141    self
142  }
143
144  pub fn apply<B: Backend>(&self, mpl: &mut B) -> io::Result<()> {
145    mpl.scatter(self.xdata,
146               self.ydata,
147               &self.label,
148               &self.color,
149               &self.marker)?;
150    Ok(())
151  }
152}
153
154impl<'a> From<Scatter<'a>> for PlotData<'a> {
155  fn from(data: Scatter) -> PlotData {
156    PlotData::Scatter(data)
157  }
158}
159
160
161#[derive(Debug, Default)]
162pub struct Line2D<'a> {
163  xdata: &'a [f64],
164  ydata: &'a [f64],
165  label: Option<String>,
166  color: Option<String>,
167  marker: Option<String>,
168  linestyle: Option<String>,
169  linewidth: Option<f64>,
170}
171
172impl<'a> Line2D<'a> {
173  pub fn new(name: &str) -> Line2D<'a> {
174    Line2D::default().label(name)
175  }
176
177  pub fn data(mut self, xdata: &'a [f64], ydata: &'a [f64]) -> Self {
178    self.xdata = xdata;
179    self.ydata = ydata;
180    self
181  }
182
183  pub fn label(mut self, text: &str) -> Self {
184    self.label = Some(text.to_owned());
185    self
186  }
187
188  pub fn color(mut self, color: &str) -> Self {
189    self.color = Some(color.to_owned());
190    self
191  }
192
193  pub fn marker(mut self, marker: &str) -> Self {
194    self.marker = Some(marker.to_owned());
195    self
196  }
197
198  pub fn linestyle(mut self, style: &str) -> Self {
199    self.linestyle = Some(style.to_owned());
200    self
201  }
202
203  pub fn linewidth(mut self, width: f64) -> Self {
204    self.linewidth = Some(width);
205    self
206  }
207
208  pub fn apply<B: Backend>(&self, mpl: &mut B) -> io::Result<()> {
209    mpl.plot(self.xdata,
210            self.ydata,
211            &self.label,
212            &self.color,
213            &self.marker,
214            &self.linestyle,
215            &self.linewidth)?;
216    Ok(())
217  }
218}
219
220impl<'a> From<Line2D<'a>> for PlotData<'a> {
221  fn from(data: Line2D<'a>) -> PlotData<'a> {
222    PlotData::Line2D(data)
223  }
224}
225
226
227#[derive(Debug, Default)]
228pub struct FillBetween<'a> {
229  x: &'a [f64],
230  y1: &'a [f64],
231  y2: &'a [f64],
232  where_: Option<&'a [bool]>,
233  interpolate: bool,
234  step: Option<String>,
235}
236
237impl<'a> FillBetween<'a> {
238  pub fn new() -> FillBetween<'a> {
239    FillBetween::default()
240  }
241
242  pub fn data(mut self, x: &'a [f64], y1: &'a [f64], y2: &'a [f64]) -> Self {
243    self.x = x;
244    self.y1 = y1;
245    self.y2 = y2;
246    self
247  }
248
249  pub fn where_(mut self, where_: &'a [bool]) -> Self {
250    self.where_ = Some(where_);
251    self
252  }
253
254  pub fn interpolate(mut self, interpolate: bool) -> Self {
255    self.interpolate = interpolate;
256    self
257  }
258
259  pub fn step(mut self, step: &str) -> Self {
260    self.step = Some(step.to_owned());
261    self
262  }
263
264  pub fn apply<B: Backend>(&self, mpl: &mut B) -> io::Result<()> {
265    mpl.fill_between(self.x,
266                    self.y1,
267                    self.y2,
268                    &self.where_,
269                    self.interpolate,
270                    &self.step)?;
271    Ok(())
272  }
273}
274
275impl<'a> From<FillBetween<'a>> for PlotData<'a> {
276  fn from(data: FillBetween<'a>) -> PlotData<'a> {
277    PlotData::FillBetween(data)
278  }
279}