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;