README.md
1# Plotters - A Rust drawing library focus on data plotting for both WASM and native applications
2
3<a href="https://crates.io/crates/plotters">
4 <img style="display: inline!important" src="https://img.shields.io/crates/v/plotters.svg"></img>
5</a>
6<a href="https://docs.rs/plotters">
7 <img style="display: inline!important" src="https://docs.rs/plotters/badge.svg"></img>
8</a>
9<a href="https://plotters-rs.github.io/rustdoc/plotters/">
10 <img style="display: inline! important" src="https://img.shields.io/badge/docs-development-lightgrey.svg"></img>
11</a>
12<a href="https://travis-ci.org/38/plotters">
13 <img style="display: inline! important" src="https://travis-ci.org/38/plotters.svg?branch=master"></img>
14</a>
15<a href="https://codecov.io/gh/38/plotters">
16 <img style="display: inline! important" src="https://codecov.io/gh/38/plotters/branch/master/graph/badge.svg" />
17</a>
18
19Plotters is drawing library designed for rendering figures, plots, and charts, in pure rust. Plotters supports various types of back-ends,
20including bitmap, vector graph, piston window, GTK/Cairo and WebAssembly.
21
22- A new Plotters Developer's Guide is working in progress. The preview version is available at [here](https://plotters-rs.github.io/book).
23- To try Plotters with interactive Jupyter notebook, or view [here](https://plotters-rs.github.io/plotters-doc-data/evcxr-jupyter-integration.html) for the static HTML version.
24- To view the WASM example, go to this [link](https://plumberserver.com/plotters-wasm-demo/index.html)
25- Currently we have all the internal code ready for console plotting, but a console based backend is still not ready. See [this example](https://github.com/38/plotters/blob/master/examples/console.rs) for how to plotting on Console with a customized backend.
26
27## Gallery
28
29To view the source code for each example, please click on the example image.
30
31<a href="https://github.com/38/plotters/blob/master/examples/chart.rs">
32 <img src="https://plotters-rs.github.io/plotters-doc-data/sample.png" class="galleryItem" width=200px></img>
33</a>
34
35<a href="https://github.com/38/plotters/blob/master/examples/stock.rs">
36 <img src="https://plotters-rs.github.io/plotters-doc-data/stock.png" class="galleryItem" width=200px></img>
37</a>
38
39<a href="https://github.com/38/plotters/blob/master/examples/histogram.rs">
40 <img src="https://plotters-rs.github.io/plotters-doc-data/histogram.png" class="galleryItem" width=200px></img>
41</a>
42
43<a href="https://github.com/38/plotters#quick-start">
44 <img src="https://plotters-rs.github.io/plotters-doc-data/0.png" class="galleryItem" width=200px></img>
45</a>
46
47<a href="#">
48 <img src="https://plotters-rs.github.io/plotters-doc-data/console-2.png" class="galleryItem" width=200px></img>
49</a>
50
51<a href="https://github.com/38/plotters/blob/master/examples/mandelbrot.rs">
52 <img src="https://plotters-rs.github.io/plotters-doc-data/mandelbrot.png" class="galleryItem" width=200px></img>
53</a>
54
55<a href="https://github.com/38/plotters#trying-with-jupyter-evcxr-kernel-interactively">
56 <img src="https://plotters-rs.github.io/plotters-doc-data/evcxr_animation.gif" class="galleryItem" width=200px></img>
57</a>
58
59
60<a href="https://github.com/38/plotters/tree/master/examples/piston-demo">
61 <img src="https://plotters-rs.github.io/plotters-doc-data/plotters-piston.gif" class="galleryItem" width=200px></img>
62</a>
63
64<a href="https://github.com/38/plotters/blob/master/examples/normal-dist.rs">
65 <img src="https://plotters-rs.github.io/plotters-doc-data/normal-dist.png" class="galleryItem" width=200px></img>
66</a>
67
68<a href="https://github.com/38/plotters/blob/master/examples/two-scales.rs">
69 <img src="https://plotters-rs.github.io/plotters-doc-data/twoscale.png" class="galleryItem" width=200px></img>
70</a>
71
72<a href="https://github.com/38/plotters/blob/master/examples/matshow.rs">
73 <img src="https://plotters-rs.github.io/plotters-doc-data/matshow.png" class="galleryItem" width=200px></img>
74</a>
75
76<a href="https://github.com/38/plotters/blob/master/examples/sierpinski.rs">
77 <img src="https://plotters-rs.github.io/plotters-doc-data/sierpinski.png" class="galleryItem" width=200px></img>
78</a>
79
80<a href="https://github.com/38/plotters/blob/master/examples/normal-dist2.rs">
81 <img src="https://plotters-rs.github.io/plotters-doc-data/normal-dist2.png" class="galleryItem" width=200px></img>
82</a>
83
84<a href="https://github.com/38/plotters/blob/master/examples/errorbar.rs">
85 <img src="https://plotters-rs.github.io/plotters-doc-data/errorbar.png" class="galleryItem" width=200px></img>
86</a>
87
88<a href="https://github.com/38/plotters/blob/master/examples/slc-temp.rs">
89 <img src="https://plotters-rs.github.io/plotters-doc-data/slc-temp.png" class="galleryItem" width=200px></img>
90</a>
91
92<a href="https://github.com/38/plotters/blob/master/examples/area-chart.rs">
93 <img src="https://plotters-rs.github.io/plotters-doc-data/area-chart.png" class="galleryItem" width=200px></img>
94</a>
95
96<a href="https://github.com/38/plotters/blob/master/examples/snowflake.rs">
97 <img src="https://plotters-rs.github.io/plotters-doc-data/snowflake.png" class="galleryItem" width=200px></img>
98</a>
99
100<a href="https://github.com/38/plotters/blob/master/examples/animation.rs">
101 <img src="https://plotters-rs.github.io/plotters-doc-data/animation.gif" class="galleryItem" width=200px></img>
102</a>
103
104<a href="https://github.com/38/plotters/blob/master/examples/console.rs">
105 <img src="https://plotters-rs.github.io/plotters-doc-data/console-example.png" class="galleryItem" width=200px></img>
106</a>
107
108<a href="https://github.com/38/plotters/blob/master/examples/console.rs">
109 <img src="https://plotters-rs.github.io/plotters-doc-data/console.png" class="galleryItem" width=200px></img>
110</a>
111
112<a href="https://github.com/38/plotters/blob/master/examples/blit-bitmap.rs">
113 <img src="https://plotters-rs.github.io/plotters-doc-data/blit-bitmap.png" class="galleryItem" width=200px></img>
114</a>
115
116<a href="https://github.com/38/plotters/blob/master/examples/boxplot.rs">
117 <img src="https://plotters-rs.github.io/plotters-doc-data/boxplot.svg" class="galleryItem" width=200px></img>
118</a>
119
120<a href="https://github.com/38/plotters/blob/master/examples/3d-plot.rs">
121 <img src="https://plotters-rs.github.io/plotters-doc-data/3d-plot.svg" class="galleryItem" width=200px></img>
122</a>
123
124
125## Table of Contents
126 * [Gallery](#gallery)
127 * [Quick Start](#quick-start)
128 * [Trying with Jupyter evcxr Kernel Interactively](#trying-with-jupyter-evcxr-kernel-interactively)
129 * [Interactive Tutorial with Jupyter Notebook](#interactive-tutorial-with-jupyter-notebook)
130 * [Plotting in Rust](#plotting-in-rust)
131 * [Plotting on HTML5 canvas with WASM Backend](#plotting-on-html5-canvas-with-wasm-backend)
132 * [What types of figure are supported?](#what-types-of-figure-are-supported)
133 * [Concepts by examples](#concepts-by-examples)
134 + [Drawing Back-ends](#drawing-backends)
135 + [Drawing Area](#drawing-area)
136 + [Elements](#elements)
137 + [Composable Elements](#composable-elements)
138 + [Chart Context](#chart-context)
139 * [Misc](#misc)
140 + [Development Version](#development-version)
141 + [Reducing Depending Libraries && Turning Off Backends](#reducing-depending-libraries--turning-off-backends)
142 + [List of Features](#list-of-features)
143 * [FAQ List](#faq-list)
144
145## Quick Start
146
147To use Plotters, you can simply add Plotters into your `Cargo.toml`
148```toml
149[dependencies]
150plotters = "^0.3.0"
151```
152
153And the following code draws a quadratic function. `src/main.rs`,
154
155```rust
156use plotters::prelude::*;
157fn main() -> Result<(), Box<dyn std::error::Error>> {
158 let root = BitMapBackend::new("plotters-doc-data/0.png", (640, 480)).into_drawing_area();
159 root.fill(&WHITE)?;
160 let mut chart = ChartBuilder::on(&root)
161 .caption("y=x^2", ("sans-serif", 50).into_font())
162 .margin(5)
163 .x_label_area_size(30)
164 .y_label_area_size(30)
165 .build_ranged(-1f32..1f32, -0.1f32..1f32)?;
166
167 chart.configure_mesh().draw()?;
168
169 chart
170 .draw_series(LineSeries::new(
171 (-50..=50).map(|x| x as f32 / 50.0).map(|x| (x, x * x)),
172 &RED,
173 ))?
174 .label("y = x^2")
175 .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
176
177 chart
178 .configure_series_labels()
179 .background_style(&WHITE.mix(0.8))
180 .border_style(&BLACK)
181 .draw()?;
182
183 Ok(())
184}
185```
186
187![](https://plotters-rs.github.io/plotters-doc-data/0.png)
188
189
190## Trying with Jupyter evcxr Kernel Interactively
191
192Plotters now supports integrate with `evcxr` and is able to interactively drawing plots in Jupyter Notebook.
193The feature `evcxr` should be enabled when including Plotters to Jupyter Notebook.
194
195The following code shows a minimal example of this.
196
197```text
198:dep plotters = { git = "https://github.com/38/plotters", default_features = false, features = ["evcxr"] }
199extern crate plotters;
200use plotters::prelude::*;
201
202let figure = evcxr_figure((640, 480), |root| {
203 root.fill(&WHITE);
204 let mut chart = ChartBuilder::on(&root)
205 .caption("y=x^2", ("Arial", 50).into_font())
206 .margin(5)
207 .x_label_area_size(30)
208 .y_label_area_size(30)
209 .build_ranged(-1f32..1f32, -0.1f32..1f32)?;
210
211 chart.configure_mesh().draw()?;
212
213 chart.draw_series(LineSeries::new(
214 (-50..=50).map(|x| x as f32 / 50.0).map(|x| (x, x * x)),
215 &RED,
216 )).unwrap()
217 .label("y = x^2")
218 .legend(|(x,y)| PathElement::new(vec![(x,y), (x + 20,y)], &RED));
219
220 chart.configure_series_labels()
221 .background_style(&WHITE.mix(0.8))
222 .border_style(&BLACK)
223 .draw()?;
224 Ok(())
225});
226figure
227```
228
229<img src="https://plotters-rs.github.io/plotters-doc-data/evcxr_animation.gif" width="450px"></img>
230
231## Interactive Tutorial with Jupyter Notebook
232
233*This tutorial is now working in progress and isn't complete*
234
235Thanks to the evcxr, now we have an interactive tutorial for Plotters!
236To use the interactive notebook, you must have Jupyter and evcxr installed on your computer.
237Follow the instruction on [this page](https://github.com/google/evcxr/tree/master/evcxr_jupyter) below to install it.
238
239After that, you should be able to start your Jupyter server locally and load the tutorial!
240
241```bash
242git clone https://github.com/38/plotters-doc-data
243cd plotteres-doc-data
244jupyter notebook
245```
246
247And select the notebook called `evcxr-jupyter-integration.ipynb`.
248
249Also, there's a static HTML version of this notebook available at the [this location](https://plumberserver.com/plotters-docs/evcxr-jupyter-integration.html)
250
251## Plotting in Rust
252
253Rust is a perfect language for data visualization. Although there are many mature visualization libraries in many different languages.
254But Rust is one of the best languages fits the need.
255
256* **Easy to use** Rust has a very good iterator system built into the standard library. With the help of iterators,
257Plotting in Rust can be as easy as most of the high-level programming languages. The Rust based plotting library
258can be very easy to use.
259
260* **Fast** If you need rendering a figure with trillions of data points,
261Rust is a good choice. Rust's performance allows you to combine data processing step
262and rendering step into a single application. When plotting in high-level programming languages,
263e.g. Javascript or Python, data points must be down-sampled before feeding into the plotting
264program because of the performance considerations. Rust is fast enough to do the data processing and visualization
265within a single program. You can also integrate the
266figure rendering code into your application handling a huge amount of data and visualize it in real-time.
267
268* **WebAssembly Support** Rust is one of few the language with the best WASM support. Plotting in Rust could be
269very useful for visualization on a web page and would have a huge performance improvement comparing to Javascript.
270
271## Plotting on HTML5 canvas with WASM Backend
272
273Plotters currently supports backend that uses the HTML5 canvas. To use the WASM support, you can simply use
274`CanvasBackend` instead of other backend and all other API remains the same!
275
276There's a small demo for Plotters + WASM under `examples/wasm-demo` directory of this repo.
277To play with the deployed version, follow this [link](https://plumberserver.com/plotters-wasm-demo/index.html).
278
279
280## What types of figure are supported?
281
282Plotters is not limited to any specific type of figure.
283You can create your own types of figures easily with the Plotters API.
284
285But Plotters provides some builtin figure types for convenience.
286Currently, we support line series, point series, candlestick series, and histogram.
287And the library is designed to be able to render multiple figure into a single image.
288But Plotter is aimed to be a platform that is fully extendable to support any other types of figure.
289
290## Concepts by examples
291
292### Drawing Back-ends
293Plotters can use different drawing back-ends, including SVG, BitMap, and even real-time rendering. For example, a bitmap drawing backend.
294
295```rust
296use plotters::prelude::*;
297fn main() -> Result<(), Box<dyn std::error::Error>> {
298 // Create a 800*600 bitmap and start drawing
299 let mut backend = BitMapBackend::new("plotters-doc-data/1.png", (300, 200));
300 // And if we want SVG backend
301 // let backend = SVGBackend::new("output.svg", (800, 600));
302 backend.draw_rect((50, 50), (200, 150), &RED, true)?;
303 Ok(())
304}
305```
306
307![](https://plotters-rs.github.io/plotters-doc-data/1.png)
308
309### Drawing Area
310Plotters uses a concept called drawing area for layout purpose.
311Plotters support multiple integrating into a single image.
312This is done by creating sub-drawing-areas.
313
314Besides that, the drawing area also allows the customized coordinate system, by doing so, the coordinate mapping is done by the drawing area automatically.
315
316```rust
317use plotters::prelude::*;
318fn main() -> Result<(), Box<dyn std::error::Error>> {
319 let root_drawing_area =
320 BitMapBackend::new("plotters-doc-data/2.png", (300, 200)).into_drawing_area();
321 // And we can split the drawing area into 3x3 grid
322 let child_drawing_areas = root_drawing_area.split_evenly((3, 3));
323 // Then we fill the drawing area with different color
324 for (area, color) in child_drawing_areas.into_iter().zip(0..) {
325 area.fill(&Palette99::pick(color))?;
326 }
327 Ok(())
328}
329```
330
331![](https://plotters-rs.github.io/plotters-doc-data/2.png)
332
333### Elements
334
335In Plotters, elements are build blocks of figures. All elements are able to draw on a drawing area.
336There are different types of built-in elements, like lines, texts, circles, etc.
337You can also define your own element in the application code.
338
339You may also combine existing elements to build a complex element.
340
341To learn more about the element system, please read the [element module documentation](./element/index.html).
342
343```rust
344use plotters::prelude::*;
345fn main() -> Result<(), Box<dyn std::error::Error>> {
346 let root = BitMapBackend::new("plotters-doc-data/3.png", (300, 200)).into_drawing_area();
347 root.fill(&WHITE)?;
348 // Draw an circle on the drawing area
349 root.draw(&Circle::new(
350 (100, 100),
351 50,
352 Into::<ShapeStyle>::into(&GREEN).filled(),
353 ))?;
354 Ok(())
355}
356```
357
358![](https://plotters-rs.github.io/plotters-doc-data/3.png)
359
360### Composable Elements
361
362Besides the built-in elements, elements can be composed into a logic group we called composed elements.
363When composing new elements, the upper-left corner is given in the target coordinate, and a new pixel-based
364coordinate which has the upper-left corner defined as `(0,0)` is used for further element composition purpose.
365
366For example, we can have an element which includes a dot and its coordinate.
367
368```rust
369use plotters::prelude::*;
370use plotters::coord::types::RangedCoordf32;
371
372fn main() -> Result<(), Box<dyn std::error::Error>> {
373 let root = BitMapBackend::new("plotters-doc-data/4.png", (640, 480)).into_drawing_area();
374
375 root.fill(&RGBColor(240, 200, 200))?;
376
377 let root = root.apply_coord_spec(Cartesian2d::<RangedCoordf32, RangedCoordf32>::new(
378 0f32..1f32,
379 0f32..1f32,
380 (0..640, 0..480),
381 ));
382
383 let dot_and_label = |x: f32, y: f32| {
384 return EmptyElement::at((x, y))
385 + Circle::new((0, 0), 3, ShapeStyle::from(&BLACK).filled())
386 + Text::new(
387 format!("({:.2},{:.2})", x, y),
388 (10, 0),
389 ("sans-serif", 15.0).into_font(),
390 );
391 };
392
393 root.draw(&dot_and_label(0.5, 0.6))?;
394 root.draw(&dot_and_label(0.25, 0.33))?;
395 root.draw(&dot_and_label(0.8, 0.8))?;
396 Ok(())
397}
398```
399
400![](https://plotters-rs.github.io/plotters-doc-data/4.png)
401
402### Chart Context
403
404In order to draw a chart, Plotters need a data object built on top of the drawing area called `ChartContext`.
405The chart context defines even higher level constructs compare to the drawing area.
406For example, you can define the label areas, meshes, and put a data series onto the drawing area with the help
407of the chart context object.
408
409```rust
410use plotters::prelude::*;
411fn main() -> Result<(), Box<dyn std::error::Error>> {
412 let root = BitMapBackend::new("plotters-doc-data/5.png", (640, 480)).into_drawing_area();
413 root.fill(&WHITE);
414 let root = root.margin(10, 10, 10, 10);
415 // After this point, we should be able to draw construct a chart context
416 let mut chart = ChartBuilder::on(&root)
417 // Set the caption of the chart
418 .caption("This is our first plot", ("sans-serif", 40).into_font())
419 // Set the size of the label region
420 .x_label_area_size(20)
421 .y_label_area_size(40)
422 // Finally attach a coordinate on the drawing area and make a chart context
423 .build_cartesian_2d(0f32..10f32, 0f32..10f32)?;
424
425 // Then we can draw a mesh
426 chart
427 .configure_mesh()
428 // We can customize the maximum number of labels allowed for each axis
429 .x_labels(5)
430 .y_labels(5)
431 // We can also change the format of the label text
432 .y_label_formatter(&|x| format!("{:.3}", x))
433 .draw()?;
434
435 // And we can draw something in the drawing area
436 chart.draw_series(LineSeries::new(
437 vec![(0.0, 0.0), (5.0, 5.0), (8.0, 7.0)],
438 &RED,
439 ))?;
440 // Similarly, we can draw point series
441 chart.draw_series(PointSeries::of_element(
442 vec![(0.0, 0.0), (5.0, 5.0), (8.0, 7.0)],
443 5,
444 &RED,
445 &|c, s, st| {
446 return EmptyElement::at(c) // We want to construct a composed element on-the-fly
447 + Circle::new((0,0),s,st.filled()) // At this point, the new pixel coordinate is established
448 + Text::new(format!("{:?}", c), (10, 0), ("sans-serif", 10).into_font());
449 },
450 ))?;
451 Ok(())
452}
453```
454
455![](https://plotters-rs.github.io/plotters-doc-data/5.png)
456
457## Misc
458
459### Development Version
460
461To use the latest development version, pull https://github.com/38/plotters.git. In `Cargo.toml`
462
463```toml
464[dependencies]
465plotters = { git = "https://github.com/38/plotters.git" }
466```
467
468### Reducing Depending Libraries && Turning Off Backends
469Plotters now supports use features to control the backend dependencies. By default, `BitMapBackend` and `SVGBackend` are supported,
470use `default_features = false` in the dependency description in `Cargo.toml` and you can cherry-pick the backend implementations.
471
472- `svg` Enable the `SVGBackend`
473- `bitmap` Enable the `BitMapBackend`
474
475For example, the following dependency description would avoid compiling with bitmap support:
476
477```toml
478[dependencies]
479plotters = { git = "https://github.com/38/plotters.git", default_features = false, features = ["svg"] }
480```
481
482The library also allows consumers to make use of the [`Palette`](https://crates.io/crates/palette/) crate's color types by default.
483This behavior can also be turned off by setting `default_features = false`.
484
485### List of Features
486
487This is the full list of features that is defined by `Plotters` crate.
488Use `default_features = false` to disable those default enabled features,
489and then you should be able to cherry-pick what features you want to include into `Plotters` crate.
490By doing so, you can minimize the number of dependencies down to only `itertools` and compile time is less than 6s.
491
492The following list is a complete list of features that can be opt in and out.
493
494- Tier 1 drawing backends
495
496| Name | Description | Additional Dependency |Default?|
497|---------|--------------|--------|------------|
498| bitmap\_encoder | Allow `BitMapBackend` save the result to bitmap files | image, rusttype, font-kit | Yes |
499| svg\_backend | Enable `SVGBackend` Support | None | Yes |
500| bitmap\_gif| Opt-in GIF animation Rendering support for `BitMapBackend`, implies `bitmap` enabled | gif | Yes |
501
502- Font manipulation features
503
504| Name | Description | Additional Dependency |Default?|
505|---------|--------------|--------|------------|
506| ttf | Allows TrueType font support | rusttype, font-kit | Yes |
507
508- Coordinate features
509
510| Name | Description | Additional Dependency |Default?|
511|---------|--------------|--------|------------|
512| datetime | Eanble the date and time coordinate support | chrono | Yes |
513
514- Element, series and util functions
515
516| Name | Description | Additional Dependency |Default?|
517|---------|--------------|--------|------------|
518| errorbar | The errorbar element support | None | Yes |
519| candlestick | The candlestick element support | None | Yes |
520| boxplot | The boxplot element support | None | Yes |
521| area\_series | The area series support | None | Yes |
522| line\_series | The line series support | None | Yes |
523| histogram | The histogram series support | None | Yes |
524| point\_series| The point series support | None | Yes |
525
526- Misc
527
528| Name | Description | Additional Dependency |Default?|
529|---------|--------------|--------|------------|
530| deprecated\_items | This feature allows use of deprecated items which is going to be removed in the future | None | Yes |
531| debug | Enable the code used for debugging | None | No |
532
533
534## FAQ List
535
536* Why does the WASM example break on my machine ?
537
538 The WASM example requires using `wasm32` target to build. Using `cargo build` is likely to use the default target
539 which in most of the case is any of the x86 target. Thus you need add `--target=wasm32-unknown-unknown` in the cargo
540 parameter list to build it.
541
542* How to draw text/circle/point/rectangle/... on the top of chart ?
543
544 As you may realized, Plotters is a drawing library rather than a traditional data plotting library,
545 you have the freedom to draw anything you want on the drawing area.
546 Use `DrawingArea::draw` to draw any element on the drawing area.
547
548
549