cgrustplot/lib.rs
1//! This is a plotting util for rust which uses ascii/unicode art to display graphs, plots, and images in the standard output, in a string, or saved to a file.
2//!
3//! Check out the documentation for more information on each of the plot types and options.
4//!
5//! # Basic Syntax / Example Usage
6//!
7//! Each plot file contains a public function by the name of that plot. For example,
8//! `pub fn array_plot<T>(data: &Vec<Vec<T>>) -> ArrayPlotBuilder<T>`
9//! creates an ArrayPlotBuilder instance.
10//!
11//! You can then set options for it such as title, axes, output size, and more (depending on the type of plot). Finally, you can call .print() or .as_string() or .pyplot() to print it to the standard output, or return the plot as a string, or display an interactive window with matplotlib, respectively.
12//!
13//! For example:
14//! ```
15//! use cgrustplot::{
16//! plots::array_plot::{array_plot, bin_arr},
17//! helper::charset::gradient_chars::shade_chars,
18//! };
19//!
20//! // table of sin(x + y)
21//! let my_data: Vec<Vec<f64>> = (0..10).map(|x| {(0..30).map(|y| (x as f64 + y as f64).sin()).collect()}).collect();
22//!
23//! array_plot(&bin_arr(&my_data, 4)) // Bins the array to have four values
24//! .set_title("A Plot of my Data:") // Sets the title of the plot
25//! .set_axes(true) // Turns on the axes for the plot
26//! .set_chars(shade_chars()) // uses unicode shade characters
27//! .print() // Displays the plot
28//! ```
29//!
30//! And the output of the above code is this plot:
31//!
32//! *NOTE: some plots may not display correctly without a monowidth font, such as on github*
33//!
34//! ```text
35//! A Plot of my Data:
36//! │▓██▓ ░██▓ ▓██░ ▓██░ ░██▓
37//! 8.500 ┼██▓ ░██▓ ▓██░ ▓██░ ░██▓
38//! │█▓ ░██▓ ▓██░ ▓██░ ░██▓ ░
39//! 6.500 ┼▓ ░██▓ ▓██░ ▓██░ ░██▓ ░█
40//! │ ░██▓ ▓██░ ▓██░ ░██▓ ░██
41//! 4.500 ┼ ░██▓ ▓██░ ▓██░ ░██▓ ░███
42//! │░██▓ ▓██░ ▓██░ ░██▓ ░███░
43//! 2.500 ┼██▓ ▓██░ ▓██░ ░██▓ ░███░
44//! │█▓ ▓██░ ▓██░ ░██▓ ░███░
45//! 0.500 ┼▓ ▓██░ ▓██░ ░██▓ ░███░ ▓
46//! └┼──────┼──────┼──────┼────────
47//! 0.5000 7.5000 14.500 21.500
48//! ```
49//! # Plot Types
50//! In no particular order, here are some of the various types of plots that can be used
51//! (more plots than listed here may already be available. Check the /src/plots/ for a full list while in development).
52//!
53//! ## Array Plot
54//! Filename: array_plot.rs
55//!
56//! Displays a table with varying brightness across it's characters.
57//! Takes in a `&Vec<Vec<T>>`, representing the brightness value at each point.
58//!
59//! The dimensions of the output string are equal to the dimensions of the input table, so if you give a 15x12 grid of values, the output will be about 15x12 characters in size. (Note that axes and title will change this).
60//!
61//! ### Options
62//! `title: Option<&str>` Sets the title to be displayed above the output. Default is None, which has no displayed title.
63//!
64//! `axes: bool` Selects whether to turn on or off the axes. Axes display in units of the number of characters. Default is true
65//!
66//! `chars: Vec<String>` The character set to be used. Defaults are based on `rustplot::helper::charset::gradient_chars`, depending on the number of distinct values in the table.
67//!
68//! `bins: Option<u32>` Only for plots of f64. It bins close-together datapoints and plots based on those. Not so much a plot option as much as a transformation, as it actually creates a new struct of `<u32>` instead of `<f64>`.
69//!
70//! ### Example
71//!
72//! Code:
73//! ```
74//! use cgrustplot::plots::array_plot::array_plot;
75//!
76//! let data: Vec<Vec<i32>> = (-5..=5)
77//! .map(|i: i32|
78//! (-15..=15).map(|j: i32|
79//! i.pow(2) + j.pow(2)
80//! ).collect()
81//! ).collect();
82//!
83//! array_plot(&data)
84//! .print()
85//! ```
86//!
87//! Output:
88//! ```text
89//! 10.50 ┼@%%#**++=---:::::::---=++**#%%@
90//! │@%##**+==--::.....::--==+**##%@
91//! 8.500 ┼@%##*++=--::.......::--=++*##%@
92//! │@%##*+==-::... ...::-==+*##%@
93//! 6.500 ┼@%#**+==-::.. ..::-==+**#%@
94//! │%%#**+=--::.. ..::--=+**#%%
95//! 4.500 ┼@%#**+==-::.. ..::-==+**#%@
96//! │@%##*+==-::... ...::-==+*##%@
97//! 2.500 ┼@%##*++=--::.......::--=++*##%@
98//! │@%##**+==--::.....::--==+**##%@
99//! 0.500 ┼@%%#**++=---:::::::---=++**#%%@
100//! └┼──────┼──────┼──────┼─────────
101//! 0.5000 7.5000 14.500 21.500
102//! ```
103//!
104//! ## Function Plot
105//! Filename: func_plot.rs
106//!
107//! Displays the output of a numerically-valued function over a domain.
108//! Takes in a `Fn(U) -> V` for types which can be cast to and from f64, respectively.
109//!
110//! ### Options
111//! `domain: (f64, f64)` Sets the domain (i.e. min and max x values) over which to plot the function. If no domain is selected, `rustplot::helper::func_plot_domain::determine_plot_domain` will be used as a default. By a variety of heuristic methods, it is usually able to determine a domain over which some useful behavior can be observed.
112//!
113//! `range: (f64, f64)` Sets the range (i.e. min and max y values) over which to plot the function. Default comes from the min and max values of the function within it's domain.
114//!
115//! `domain_padding: f64` Pads the domain by some percentage. For example, with padding of 0.01, the domain (0, 10) gets turned into (-0.1, 10.1).
116//!
117//! `range_padding: f64` Pads the range by some percentage.
118//!
119//! `size: (u32, u32)` Sets the size of the output of the plot, measured in number of characters.
120//!
121//! `title: Option<&str>`
122//!
123//! `axes: bool`
124//!
125//! ### Example
126//!
127//! Code:
128//! ```
129//! use cgrustplot::plots::function_plot::function_plot;
130//!
131//! let f = |x: f64| x.powi(3);
132//!
133//! function_plot(&f)
134//! .set_size((30, 10))
135//! .print();
136//! ```
137//!
138//! Output:
139//! ```text
140//! │ _‾
141//! 1.293 ┼ /
142//! │ _‾
143//! 0.554 ┼ _―‾
144//! │ _――――――――――‾
145//! -0.18 ┼ _―‾
146//! │ _‾
147//! -0.92 ┼ /
148//! │ /
149//! -1.66 ┼ /
150//! └┼──────┼──────┼──────┼────────
151//! -1.339 -0.692 -0.046 0.6004
152//! ```
153//!
154//! ## Scatter Plot
155//! Filename: scatter_plot.rs
156//!
157//! Displays a scatter plot from a given set of points `Vec<(f64, f64)>`.
158//!
159//! ### Options
160//! `range: ((f64, f64), (f64, f64))` Sets the domain as well as range (i.e. min and max x and values) over which to plot the function. Sorry about the inconsistency between range here and in other places. It may be fixed in the future.
161//!
162//! `padding: f64` Pads both the domain and range by some percentage.
163//!
164//! `size: (u32, u32)`
165//!
166//! `title: Option<&str>`
167//!
168//! `axes: bool`
169//!
170//! `chars: (Vec<char>, (u32, u32))` The character set to be used. Defaults are based on `rustplot::helper::charset::subdiv_chars`, depending on the number of unique points that would be overwritten at each size. (i.e. it tries not to show two points in only a single character). You must specify the dimension of each character. For example, braille characters allow you to plot a grid of 2x4 dots for each character, so you must pass in (2, 4) in addition to the character set.
171//!
172//! ### Example
173//! Code:
174//! ```
175//! use cgrustplot::plots::scatter_plot::scatter_plot;
176//! use cgrustplot::helper::charset::subdiv_chars::dots_two_by_four;
177//! use rand::{Rng, SeedableRng, rngs::StdRng};
178//!
179//! // Generate some random data points within ((0, 60), (0, 30))
180//! let mut rng: StdRng = SeedableRng::seed_from_u64(0);
181//! let data: Vec<(f64, f64)> = (0..100).map(|_|
182//! (rng.gen_range(0.0..60.0), rng.gen_range(0.0..30.0))
183//! ).collect();
184//!
185//! scatter_plot(&data)
186//! .set_size((30, 10))
187//! .set_chars((dots_two_by_four(), (2, 4)))
188//! .set_range(((0., 60.), (0., 30.)))
189//! .set_padding(0.)
190//! .print();
191//! ```
192//!
193//! Output:
194//! ```text
195//! │⠔⡈⢀⠀⠂⠀⠀⠂⠀⠀⠀⠀⠀⠀⠀⡀⠀⠀⠂⢁⠀⠀⠂⠀⠀⠀⡀⠀⠀⠄
196//! 25.50 ┼⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⢀⠀⠀⠁⠐⠀⠁⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐
197//! │⠀⠀⠀⠄⠀⠄⠀⠠⠀⠀⡀⠈⠀⠈⠀⠀⠀⠀⠠⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀
198//! 19.50 ┼⠄⠀⠁⠀⠀⠀⠁⠀⠡⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠈⠀⠀⠐⠀⠀
199//! │⠀⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠀
200//! 13.50 ┼⢀⠀⠀⠀⠀⠁⠣⠀⠀⠀⠠⠄⠀⠀⠰⠀⠀⢂⠀⠀⠀⠀⠀⠁⠀⠀⣀⠀⠀⠀
201//! │⠠⢀⠀⠀⠅⠠⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠁⠈⠀⠀⠀⠀⠠⠀⠐⠀⣀⠠⠠
202//! 7.500 ┼⠀⠀⠈⠂⠀⠀⢀⠡⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⡀⠠⠀⠀⠀⠀⠀⠀⠀⠀
203//! │⠀⠐⠀⠀⠐⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠀⢀⠄⠁⠄⠄⠀⠀⠀
204//! 1.500 ┼⠀⢀⡀⠄⠁⠀⢀⠀⠀⠀⠀⠀⠀⠈⠀⢀⠀⠀⠀⠀⠀⢀⠄⠀⠀⠁⠀⠀⠀⠀
205//! └┼──────┼──────┼──────┼────────
206//! 1.0000 15.000 29.000 43.000
207//! ```
208//!
209//!
210//! ## Region Plot
211//! Filename: Region_plot.rs
212//!
213//! Displays the region over which a predicate `pred: Fn(f64, f64) -> bool` is true.
214//!
215//! ### Options
216//! `range: ((f64, f64), (f64, f64))` Sets the domain as well as range (i.e. min and max x and values) over which to plot the predicate
217//!
218//! `padding: f64`
219//!
220//! `size: (u32, u32)`
221//!
222//! `title: Option<&str>`
223//!
224//! `axes: bool`
225//!
226//! ### Example
227//! Code:
228//! ```
229//! use cgrustplot::plots::region_plot::region_plot;
230//!
231//! let p = |x: f64, y: f64| (x.powi(2) + y.powi(2)).sqrt() <= 0.7;
232//!
233//! region_plot(&p)
234//! .set_domain_and_range(((-1., 1.), (-1., 1.)))
235//! .set_size((30, 10))
236//! .print();
237//! ```
238//!
239//! Output:
240//! ```text
241//! │
242//! 0.840 ┼
243//! │ ▄▄▄▄▖
244//! 0.360 ┼ ▗▟█████████▄
245//! │ ▗████████████▙
246//! -0.12 ┼ ▜█████████████▘
247//! │ ▜███████████▘
248//! -0.60 ┼ ▝▀▀████▛▀▀
249//! │
250//! -1.08 ┼
251//! └┼─────┼─────┼─────┼──────
252//! -1.15 -0.57 0.000 0.576
253//! ```
254
255//! # Structure
256//!
257//! This crate is structured into plots, helper functions, and tests.
258//!
259//! The `plots` module contains all the plot types.
260//!
261//! The `helper` module contains extra functions used throughout the crate.
262//!
263//! The 'tests` module (private) implemenents unit tests and full tests for plots and helpers.
264//!
265//! # Contribution and Development
266//!
267//! So far, this has been a completely solo project. If you have anything to add, or would like to
268//! help out in any way, just reach out or submit your changes with a pull request.
269//!
270//! In order to properly run tests involving saving files, create a directory called "testoutput"
271//! in the workspace folder.
272//!
273pub mod helper;
274pub mod plots;
275mod tests;