plotters_unsable/lib.rs
1/*!
2
3# Plotters - Rust Drawing Library for Visualization 🦀 📈🚀
4
5<a href="https://crates.io/crates/plotters">
6 <img style="display: inline!important" src="https://img.shields.io/crates/v/plotters.svg"></img>
7</a>
8
9<a href="https://docs.rs/plotters">
10 <img style="display: inline!important" src="https://docs.rs/plotters/badge.svg"></img>
11</a>
12
13<a href="https://plumberserver.com/plotters-docs/plotters">
14 <img style="display: inline! important" src="https://img.shields.io/badge/docs-development-lightgrey.svg"></img>
15</a>
16
17*Please note: This library is in a very early stage. I am trying my best to stabilize the APIs and improving the overall quality. APIs may change at this time.*
18
19Plotters is drawing library designed for rendering figures, plots, and charts, in pure rust. Plotters supports various types of backends, including bitmap, vector graph and WebAssembly.
20
21## Gallery
22
23<div class="galleryItem">
24 <a href="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/sample.png">
25 <img src="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/sample.png" class="galleryItem"></img>
26 </a>
27 <div class="galleryText">
28 Multiple Plot
29 <a href="https://github.com/38/plotters/blob/master/examples/chart.rs">[code]</a>
30 </div>
31</div>
32
33<div class="galleryItem">
34 <a href="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/stock.png">
35 <img src="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/stock.png" class="galleryItem"></img>
36 </a>
37 <div class="galleryText">
38 Candlestick Plot
39 <a href="https://github.com/38/plotters/blob/master/examples/stock.rs">[code]</a>
40 </div>
41</div>
42
43<div class="galleryItem">
44 <a href="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/histogram.png">
45 <img src="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/histogram.png" class="galleryItem"></img>
46 </a>
47 <div class="galleryText">
48 Histogram
49 <a href="https://github.com/38/plotters/blob/master/examples/histogram.rs">[code]</a>
50 </div>
51</div>
52
53<div class="galleryItem">
54 <a href="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/0.png">
55 <img src="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/0.png" class="galleryItem"></img>
56 </a>
57 <div class="galleryText">
58 Simple Chart
59 </div>
60</div>
61
62<div class="galleryItem">
63 <a href="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/mandelbrot.png">
64 <img src="https://raw.githubusercontent.com/38/plotters/master/examples/outputs/mandelbrot.png" class="galleryItem"></img>
65 </a>
66 <div class="galleryText">
67 Mandelbrot set
68 <a href="https://github.com/38/plotters/blob/master/examples/mandelbrot.rs">[code]</a>
69 </div>
70</div>
71
72## Quick Start
73
74To use Plotters, you can simply add Plotters into your `Cargo.toml`
75```toml
76[depedencies]
77plotters = "^0.1.13"
78```
79
80And the following code draws a quadratic function. `src/main.rs`,
81
82```rust
83use plotters::prelude::*;
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 let root = BitMapBackend::new("examples/outputs/0.png", (640, 480)).into_drawing_area();
86 root.fill(&White)?;
87 let mut chart = ChartBuilder::on(&root)
88 .caption("y=x^2", &("Arial", 50).into_font())
89 .margin(5)
90 .x_label_area_size(30)
91 .y_label_area_size(30)
92 .build_ranged(-1f32..1f32, -0.1f32..1f32)?;
93
94 chart.configure_mesh().draw()?;
95
96 chart.draw_series(LineSeries::new(
97 (-50..=50).map(|x| x as f32 / 50.0).map(|x| (x, x * x)),
98 &Red,
99 ))?
100 .label("y = x^2")
101 .legend(|(x,y)| Path::new(vec![(x,y), (x + 20,y)], &Red));
102
103 chart.configure_series_labels()
104 .background_style(&White.mix(0.8))
105 .border_style(&Black)
106 .draw()?;
107
108 Ok(())
109}
110```
111
112
113
114
115## Motivation of Plotting in Rust
116
117Rust is a perfect language for data visualization. Although there are many mature visualization libraries in many different languages.
118But Rust is one of the best languages fits the need.
119
120* **Easy to use** Rust has a very good iterator system built into the standard library. With the help of iterators,
121Plotting in Rust can be as easy as most of the high-level programming languages. The Rust based plotting library
122can be very easy to use.
123
124* **Fast** If you need rendering a figure with trillions of data points,
125Rust is a good choice. Rust's performance allows you to combine data processing step
126and rendering step into a single application. When plotting in high-level programming languages,
127e.g. Javascript or Python, data points must be downsampled before feeding into the plotting
128program because of the performance considerations. Rust is fast enough to do the data processing and visualization
129within a single program. You can also integrate the
130figure rendering code into your application handling a huge amount of data and visualize it in real-time.
131
132* **WebAssembly Support** Rust is one of few the language with the best WASM support. Plotting in Rust could be
133very useful for visualization on a web page and would have a huge performance improvement comparing to Javascript.
134
135## What types of figure are supported?
136
137Plotters is not limited to any specific type of figure.
138You can create your own types of figures easily with the Plotters API.
139
140But Plotters provides some builtin figure types for convenience.
141Currently, we support line series, point series, candlestick series, and histogram.
142And the library is designed to be able to render multiple figure into a single image.
143But Plotter is aimed to be a platform that is fully extendable to support any other types of figure.
144
145## Plotting on HTML5 canvas
146
147Plotters currently supports backend that uses the HTML5 canvas. To use the WASM support, you can simply use
148`CanvasBackend` instead of other backend and all other API remains the same!
149
150There's a small demo for Plotters + WASM under `examples/wasm-demo` directory of this repo.
151To play with the deployed version, follow this [link](https://plumberserver.com/plotters-wasm-demo/index.html).
152
153## Concepts by examples
154
155### Drawing Backends
156Plotters can use different drawing backends, including SVG, BitMap, and even real-time rendering. For example, a bitmap drawing backend.
157
158```rust
159use plotters::prelude::*;
160fn main() -> Result<(), Box<dyn std::error::Error>> {
161 // Create a 800*600 bitmap and start drawing
162 let mut backend = BitMapBackend::new("examples/outputs/1.png", (300, 200));
163 // And if we want SVG backend
164 // let backend = SVGBackend::new("output.svg", (800, 600));
165 backend.draw_rect((50, 50), (200, 150), &Red, true)?;
166 Ok(())
167}
168```
169
170
171
172### Drawing Area
173Plotters uses a concept called drawing area for layout purpose.
174Plotters support multiple integrating into a single image.
175This is done by creating sub-drawing-areas.
176
177Besides that, the drawing area also allows the customized coordinate system, by doing so, the coordinate mapping is done by the drawing area automatically.
178
179```rust
180use plotters::prelude::*;
181fn main() -> Result<(), Box<dyn std::error::Error>> {
182 let root_drawing_area =
183 BitMapBackend::new("examples/outputs/2.png", (300, 200)).into_drawing_area();
184 // And we can split the drawing area into 3x3 grid
185 let child_drawing_areas = root_drawing_area.split_evenly((3, 3));
186 // Then we fill the drawing area with different color
187 for (area, color) in child_drawing_areas.into_iter().zip(0..) {
188 area.fill(&Palette99::pick(color))?;
189 }
190 Ok(())
191}
192```
193
194
195
196### Elements
197
198In Plotters, elements are build blocks of figures. All elements are able to draw on a drawing area.
199There are different types of built-in elements, like lines, texts, circles, etc.
200You can also define your own element in the application code.
201
202You may also combine existing elements to build a complex element.
203
204To learn more about the element system, please read the [element module documentation](./element/index.html).
205
206```rust
207use plotters::prelude::*;
208fn main() -> Result<(), Box<dyn std::error::Error>> {
209 let root = BitMapBackend::new("examples/outputs/3.png", (300, 200)).into_drawing_area();
210 root.fill(&White)?;
211 // Draw an circle on the drawing area
212 root.draw(&Circle::new(
213 (100, 100),
214 50,
215 Into::<ShapeStyle>::into(&Green).filled(),
216 ))?;
217 Ok(())
218}
219```
220
221
222
223### Composable Elements
224
225Besides the built-in elements, elements can be composed into a logic group we called composed elements.
226When composing new elements, the upper-left corner is given in the target coordinate, and a new pixel-based
227coordinate which has the upper-left corner defined as `(0,0)` is used for further element composition purpose.
228
229For example, we can have an element which includes a dot and its coordinate.
230
231```rust
232use plotters::prelude::*;
233
234fn main() -> Result<(), Box<dyn std::error::Error>> {
235 let root = BitMapBackend::new("examples/outputs/4.png", (640, 480)).into_drawing_area();
236
237 root.fill(&RGBColor(240, 200, 200))?;
238
239 let root = root.apply_coord_spec(RangedCoord::<RangedCoordf32, RangedCoordf32>::new(
240 0f32..1f32,
241 0f32..1f32,
242 (0..640, 0..480),
243 ));
244 let font = ("Arial", 15.0).into_font();
245
246 let dot_and_label = |x: f32, y: f32| {
247 return EmptyElement::at((x, y))
248 + Circle::new((0, 0), 3, ShapeStyle::from(&Black).filled())
249 + Text::new(format!("({:.2},{:.2})", x, y), (10, 0), &font);
250 };
251
252 root.draw(&dot_and_label(0.5, 0.6))?;
253 root.draw(&dot_and_label(0.25, 0.33))?;
254 root.draw(&dot_and_label(0.8, 0.8))?;
255 Ok(())
256}
257```
258
259
260
261### Chart Context
262
263In order to draw a chart, Plotters need a data object built on top of the drawing area called `ChartContext`.
264The chart context defines even higher level constructs compare to the drawing area.
265For example, you can define the label areas, meshes, and put a data series onto the drawing area with the help
266of the chart context object.
267
268```rust
269use plotters::prelude::*;
270fn main() -> Result<(), Box<dyn std::error::Error>> {
271 let root = BitMapBackend::new("examples/outputs/5.png", (640, 480)).into_drawing_area();
272 root.fill(&White);
273 let root = root.margin(10, 10, 10, 10);
274 // After this point, we should be able to draw construct a chart context
275 let font: FontDesc = ("Arial", 40.0).into();
276 // Create the chart object
277 let mut chart = ChartBuilder::on(&root)
278 // Set the caption of the chart
279 .caption("This is our first plot", &font)
280 // Set the size of the label region
281 .x_label_area_size(20)
282 .y_label_area_size(40)
283 // Finally attach a coordinate on the drawing area and make a chart context
284 .build_ranged(0f32..10f32, 0f32..10f32)?;
285
286 // Then we can draw a mesh
287 chart
288 .configure_mesh()
289 // We can customize the maximum number of labels allowed for each axis
290 .x_labels(5)
291 .y_labels(5)
292 // We can also change the format of the label text
293 .y_label_formatter(&|x| format!("{:.3}", x))
294 .draw()?;
295
296 // And we can draw something in the drawing area
297 let smaller_font = font.resize(10.0);
298 chart.draw_series(LineSeries::new(
299 vec![(0.0, 0.0), (5.0, 5.0), (8.0, 7.0)],
300 &Red,
301 ))?;
302 // Similarly, we can draw point series
303 chart.draw_series(PointSeries::of_element(
304 vec![(0.0, 0.0), (5.0, 5.0), (8.0, 7.0)],
305 5,
306 &Red,
307 &|c, s, st| {
308 return EmptyElement::at(c) // We want to construct a composed element on-the-fly
309 + Circle::new((0,0),s,st.filled()) // At this point, the new pixel coordinate is established
310 + Text::new(format!("{:?}", c), (10, 0), &smaller_font);
311 },
312 ))?;
313 Ok(())
314}
315```
316
317
318
319## Misc
320
321To use the latest development version, pull https://github.com/38/plotters.git. In `Cargo.toml`
322
323```toml
324[dependencies]
325plotters = { git = "https://github.com/38/plotters.git" }
326```
327
328Plotters now supports use features to control the backend dependencies. By default, `BitMapBackend` and `SVGBackend` are supported,
329use `default_features = false` in the dependency description in `Cargo.toml` and you can cherrypick the backend implementations.
330
331- `svg` Enable the `SVGBackend`
332- `bitmap` Enable the `BitMapBackend`
333
334For example, the following dependency description would avoid compiling with bitmap support:
335
336```toml
337[dependencies]
338plotters = { git = "https://github.com/38/plotters.git", default_features = false, features = ["svg"] }
339```
340
341
342<style>
343 img {
344 display: block;
345 margin: 0 auto;
346 max-width: 500px;
347 }
348 .galleryItem {
349 width: 250px;
350 display: inline-block;
351 }
352 .galleryImg {
353 max-width: 100%;
354 }
355 .galleryText {
356 text-align: center;
357 }
358</style>
359
360*/
361pub mod chart;
362pub mod coord;
363pub mod data;
364pub mod drawing;
365pub mod element;
366pub mod series;
367pub mod style;
368
369#[cfg(test)]
370pub use crate::drawing::create_mocked_drawing_area;
371
372/// The module imports the most commonly used types and modules in Plotters
373pub mod prelude {
374 pub use crate::chart::{ChartBuilder, ChartContext};
375 pub use crate::coord::{
376 CoordTranslate, LogCoord, LogRange, LogScalable, Ranged, RangedCoord, RangedCoordf32,
377 RangedCoordf64, RangedCoordi32, RangedCoordi64, RangedCoordu32, RangedCoordu64,
378 };
379
380 #[cfg(feature = "chrono")]
381 pub use crate::coord::{RangedDate, RangedDateTime};
382
383 pub use crate::drawing::*;
384 pub use crate::series::{Histogram, LineSeries, PointSeries};
385 pub use crate::style::{
386 Black, Blue, Color, Cyan, FontDesc, FontTransform, Green, HSLColor, IntoFont, Magenta,
387 Mixable, Palette, Palette100, Palette99, Palette9999, PaletteColor, RGBColor, Red,
388 ShapeStyle, SimpleColor, TextStyle, Transparent, White, Yellow,
389 };
390
391 pub use crate::element::{
392 CandleStick, Circle, Cross, DynElement, EmptyElement, IntoDynElement, MultiLineText, Path,
393 Pixel, Rectangle, Text,
394 };
395
396 #[allow(type_alias_bounds)]
397 /// The type used to returns a drawing operation that can be failed
398 /// - `T`: The return type
399 /// - `D`: The drawing backend type
400 pub type DrawResult<T, D: DrawingBackend> =
401 Result<T, crate::drawing::DrawingAreaErrorKind<D::ErrorType>>;
402}