astrup/
lib.rs

1//! # Astrup
2//!
3//! A rust plotting library using [gtk-rs](https://github.com/gtk-rs/gtk) as a backend. This is
4//! *still* very much a small hobby project. For alternative rust plotting libraries, see e.g.
5//!
6//! - [rustplotlib](https://github.com/ubnt-intrepid/rustplotlib)
7//! - [RustGnuplot](https://github.com/SiegeLord/RustGnuplot)
8//! - [dataplotlib](https://github.com/coder543/dataplotlib)
9//!
10//! ## Example
11//!
12//! ```
13//! extern crate ndarray;
14//! extern crate rand;
15//! extern crate astrup;
16//!
17//! use std::f64::consts::PI;
18//!
19//! use ndarray::Array;
20//! use rand::distributions::{IndependentSample, Normal};
21//! use rand::{thread_rng};
22//!
23//! use astrup::view::View;
24//! use astrup::figure::Figure;
25//! use astrup::plot::Plot;
26//! use astrup::chart::Chart;
27//! use astrup::chart::scatter::Scatter;
28//! use astrup::chart::line::Line;
29//!
30//! fn main() {
31//!
32//!     // Create data contained in ndarray
33//!     let x_data = Array::from_iter((0..100).map(|x| (x as f64) * 2.0 * PI / 100.0));
34//!     let y_data1 = Array::from_iter((0..100).map(|i| x_data[i].sin()));
35//!     let y_data2 = Array::from_iter((0..100).map(|i| (x_data[i] - PI / 2.0).sin()));
36//!
37//!     // Plot lines
38//!     let line1 = Line::new(&x_data, &y_data1).set_stroke_style("dotted");
39//!     let line2 = Line::new(&x_data, &y_data2).set_color_rgba(0.9, 0.2, 0.2, 0.9);
40//!
41//!     // Add lines to a plot
42//!     let line_plot = Plot::new().add(Chart::Line(line1))
43//!                                .add(Chart::Line(line2))
44//!                                .set_y_min(-1.2)
45//!                                .set_local_frame(0.0, 0.7, 0.51, 1.0);
46//!
47//!     // Create scatter points
48//!     let normal_0_1 = Normal::new(0.0, 1.0);
49//!     let normal_0_2 = Normal::new(0.0, 2.0);
50//!     let x_data: Vec<f64> = (0..1000)
51//!                            .map(|_| normal_0_1.ind_sample(&mut thread_rng()))
52//!                            .collect();
53//!     let y_data: Vec<f64> = (0..1000)
54//!                            .map(|_| normal_0_2.ind_sample(&mut thread_rng()))
55//!                            .collect();
56//!     let scatter = Scatter::new(&x_data, &y_data).set_color_rgba(0.1, 0.8, 0.3, 0.9)
57//!                                                 .set_point_size(0.005);
58//!
59//!     // Add scatter points to a new plot
60//!     let scatter_plot = Plot::new().set_local_frame(0.3, 1.0, 0.0, 0.49)
61//!                                   .add(Chart::Scatter(scatter));
62//!
63//!     // Add the plots to a figure, and save it
64//!     let fig = Figure::new().add(line_plot)
65//!                            .add(scatter_plot)
66//!                            .set_width(1000)
67//!                            .set_height(800)
68//!                            .set_border_thickness(0.001)
69//!                            .save("assets/frontpage_example.png").expect("Could not save frontpage_example.png")
70//!                           # .save("target/doc/astrup/frontpage_example.png").expect("Could not save doc frontpage_example.png");
71//!
72//!     // Display the result on screen
73//!     View::new_from(fig).expect("Could not add figure to view")
74//!                        .show();
75//!     }
76//! ```
77//!
78//! ![Plot](frontpage_example.png)
79//!
80//! ## Gloals:
81//! - Input `Vec` and `ndarray` containers and slices
82//! - It should be intuitive to build plots, but not as ``easy as possible''. It will probably be
83//! quite verbose and explicit.
84//! - Very configurable.
85//!
86//!
87//! ### Drawable objects
88//!
89//! These methods draw whatever they specify onto its plot. It
90//! should be possible to combine as many as you want of any combination.
91//!
92//! ## About
93//!
94//! ### Structure hierarchy
95//!
96//! There is a natural hierarchy to structs in this library
97//!
98//! ```text,no_run
99//! Level 0           View
100//!                     |
101//! Level 1           Figure
102//!                     |
103//! Level 2           Plot
104//!                     |
105//! Level 3           Canvas
106//!                   /    \
107//! Level 4        Chart   Axis
108//!                         |
109//! Level 5                Mark
110//!                        /  \
111//! Level 6             Tick  GridLine
112//! ```
113//!
114//! One can set the size (the location frame) of each structure, relative to its parent structure.
115//! These local coordinates will be on a grid *(0, 1) х (0, 1)* relative to the size of its parent
116//! structure size.
117//!
118//! #### [View](view/struct.View.html)
119//! Used to display figures on the screen. A View can have multiple figures, but if you do not need
120//! to display anything, you do not need to use it.
121//!
122//! #### [Figure](figure/struct.Figure.html)
123//! The main structure, and can contain multiple plots. You can determine the size of the figure,
124//! and also save the figure as a `.png` image.
125//!
126//! #### [Plot](plot/struct.Plot.html)
127//! A structure that holds the visual that is to be displayed. It contains a canvas (and can
128//! contain more, but this is rarely needed), and some space around the canvas, to make space for
129//! titles, legends, labels, and tick-labels.
130//!
131//! #### [Canvas](plot/struct.Canvas.html)
132//! The structure where the charts are drawn on. It can contain multiple charts and multiple axes.
133//! Depending on the charts that are showed, different axes are placed at default.
134//!
135//! #### [Chart](chart/enum.Chart.html)
136//! A struct that holds the different objects you want to use to display your data. Currently, the
137//! following charts are planned, sorted by an approximate implementation priority. There are still
138//! some hickups with the structure of the library that needs to be in order before the rest are
139//! implemented.
140//!
141//! | Variant       | Supported |
142//! | ------------- | --------- |
143//! | Scatter       | Partially |
144//! | Line          | Parially  |
145//! | Histogram     | No        |
146//! | MatrixHeatmap | No        |
147//! | Image         | No        |
148//! | FilledCurves  | No        |
149//! | BoxPlot       | No        |
150//! | PieChart      | No        |
151//!
152//! #### [Axis](axis/struct.Axis.html)
153//! An axis is used to give context to the chart, as it displays a reference to the data points. It
154//! is intended that a single canvas can have multiple axes, but currently, it is the safest to
155//! only use the two default (ordinate and abcissa).
156//!
157//! #### [Mark](mark/struct.Mark.html)
158//! A mark is the location on a axis where a data point reference can be placed. It is used
159//! internally by the library to determine the data range of an axis, but can be visualised through
160//! ticks and/or gridlines. Normally, one just want *< 10* marks on an axis (to reduce visual
161//! noise), and also, it is common to let the marks be placed at data points *n х {1, 2, 5} х 10^p*
162//! for some integer $n$ and integer power $p$.
163//!
164//! ```text,no_run
165//! Example:
166//!
167//! Data range in [-5.2345, 8.41234], gives something like the following default marks
168//!
169//!     |--------|--------|--------|--------|--------|--------|--------|--------|-->
170//!   -6.0     -4.0     -2.0      0.0      2.0      4.0      6.0      8.0     10.0
171//! ```
172//!
173//! Note that it is possible to set min and max data ranges, but they will (currently) be
174//! considered as ``soft suggestions'', as the above aestetic rules will overrule the exact
175//! suggestion.
176//!
177//! #### [Tick](mark/struct.Tick.html)
178//! A small visualisation of the location of a mark, and is labeled with the data value of the
179//! mark. Currently, only one type of tick is supported, but minor and major ticks will be
180//! implemented sometime in the future.
181//!
182//! #### [GridLine](mark/struct.GridLine.html)
183//! Much the same as a tick, but stretches across the whole canvas, normally on the axis it belongs
184//! to.
185//!
186//! ## TODO:
187//!
188//! ### Close future
189//! - Set axes data range explicitly. Currently it is determined to fit the range of the input
190//! data.
191//! - Set figure dimensions. Currently, non-square looks ugly. Non-square plots looks as expected,
192//! and the figure should work in the same way. This can possibly be done by cropping the figure to
193//! fit its plots at the end of the drawing.
194//! - Let axis labels, tick labels and tics determine the default location of the axes
195//! - Make more examples, and organise them sensibly
196//! - Refactor fit and scaling functions, e.g. one fit_fig, and fit_plot for all drawables
197//! - Make gridlines a part of tick struct. This is because a gridline is just an extension of a tick.
198//! - Also have a flag or something to indicate major / minor ticks.
199//! - Implement dotted gridlines
200//!
201//! - Name frames according to what they are. If it is natural for a struct to have a local frame,
202//! name it struct.local_frame and let this allways be initialized to (0, 1)x(0, 1). Connected to
203//! this local_frame is a global_frame, that holds coordinates relative to the global Figure
204//! coordinate system. The global_frame is used for drawing. If the struct have data attached to
205//! it, name this struct.data_frame.
206//!
207//! ### More distant future
208//! - Implement the above plot variants
209//! - Fix the use of PlotType in the api, hide it somehow.
210//! - Implement minor ticks and grid lines
211//! - Add legend.
212extern crate cairo;
213extern crate gio;
214extern crate gtk;
215extern crate num;
216extern crate failure;
217extern crate palette;
218extern crate ndarray;
219
220pub mod view;
221pub mod figure;
222pub mod plot;
223pub mod canvas;
224pub mod axis;
225pub mod mark;
226pub mod chart;
227pub mod utils;
228pub mod frame;
229pub mod coord;
230pub mod text;