Data plotting library for Rust

Overview

plotlib

Rust codecov Crates.io MIT Documentation

plotlib is a generic data visualisation and plotting library for Rust. It is currently in the very early stages of development.

It can currently produce:

  • histograms
  • scatter plots
  • line graphs from data or from function definitions
  • box plots
  • bar charts

rendering them as either SVG or plain text.

The API is still very much in flux and is subject to change.

For example, code like:

use plotlib::page::Page;
use plotlib::repr::Plot;
use plotlib::view::ContinuousView;
use plotlib::style::{PointMarker, PointStyle};

fn main() {
    // Scatter plots expect a list of pairs
    let data1 = vec![
        (-3.0, 2.3),
        (-1.6, 5.3),
        (0.3, 0.7),
        (4.3, -1.4),
        (6.4, 4.3),
        (8.5, 3.7),
    ];

    // We create our scatter plot from the data
    let s1: Plot = Plot::new(data1).point_style(
        PointStyle::new()
            .marker(PointMarker::Square) // setting the marker to be a square
            .colour("#DD3355"),
    ); // and a custom colour

    // We can plot multiple data sets in the same view
    let data2 = vec![(-1.4, 2.5), (7.2, -0.3)];
    let s2: Plot = Plot::new(data2).point_style(
        PointStyle::new() // uses the default marker
            .colour("#35C788"),
    ); // and a different colour

    // The 'view' describes what set of data is drawn
    let v = ContinuousView::new()
        .add(s1)
        .add(s2)
        .x_range(-5., 10.)
        .y_range(-2., 6.)
        .x_label("Some varying variable")
        .y_label("The response of something");

    // A page with a single view is then saved to an SVG file
    Page::single(&v).save("scatter.svg").unwrap();
}

will produce output like:

scatter plot

Comments
  • Add support for grids

    Add support for grids

    This support is basic so far, and only for continuous views for now.

    The user can choose how many grid points they wish to use for each axis (defaults to 3 each), and the colour of the grid lines (defaults to a grey colour).

    Additionally abstract two functions for drawing horizontal/vertical lines.

    enhancement 
    opened by simonrw 8
  • Difficulty getting started with examples

    Difficulty getting started with examples

    I'm interested in doing some data exploration in Rust, and plotlib looks like it is a promising tool for helping to visualize some things, without having to go through the trouble of writing the data to file and plotting with Python or such.

    Unfortunately, I'm having getting trouble starting up with plotlib at the moment. I'd primarily like to focus on an issue I'm having with the first function in the tests file, test_no_data.rs, called test_data_with_one_length(). This seems like sort of the basic "Hello, world!" of the running a scatter graph, although the current example listed on home page README also doesn't compile at the moment. For reference, I'm using Rust 1.32.0-stable, on Ubuntu 18.04 LTS. My cargo.toml file has the most recent crate available, plotlib = "0.3".

    The function test_data_with_one_length() has the following code, which I'm using in main():

        // Scatter plots expect a list of pairs
        let data1 = [(-3.0, 2.3)];
    
        // We create our scatter plot from the data
        let s1 = Scatter::from_slice(&data1).style(
            scatter::Style::new()
                .marker(Marker::Square) // setting the marker to be a square
                .colour("#DD3355"),
        ); // and a custom colour
    
        // The 'view' describes what set of data is drawn
        let v = ContinuousView::new()
            .add(&s1)
            .x_range(-5., 10.)
            .y_range(-2., 6.)
            .x_label("Some varying variable")
            .y_label("The response of something");
    
        // A page with a single view is then saved to an SVG file
        Page::single(&v)
            .save("/tmp/scatter_one_length.svg")
    .unwrap();
    

    This produces three main errors:

    1. ContinuousView is not an available function. I've confirmed this with the crates.io documentation, and when let v = ContinuousView::new() is replaced with View::new(), the error goes away.
    2. Scatter::from_slice(&data1) is not valid, as the ::as_slice() method doesn't appear in the documentation at all. However, when this is replaced with ::from_vec() instead, this error disappears as well.
    3. unwrap() doesn't appear to be implemented for Page::save(), but we can put a quick hold on error handling and remove that for the time being.

    At this point, cargo build finishes successfully. However, when I try actually running this example, the program panics with the following message: thread 'main' panicked at 'assertion failed: lower < upper', /home/chrism/.cargo/registry/src/github.com-1ecc6299db9ec823/plotlib-0.3.0/src/axis.rs:15:9

    I don't have an obvious solution for fixing this (since the numbers in the axis ranges seem valid) according to the axis.rs bounds checker, so wanted to bring it to your attention. I'm looking forward to have a native library like this be available (as I'm sure others are), and appreciate the time you've put into it so far. Thanks, and if you have any questions on reproducing these bugs, please let me know.

    question 
    opened by quietlychris 5
  • WIP: Error handling

    WIP: Error handling

    Start to implement error handling throughout.

    Motivated by #7, we add error handling through the failure crate, adding context where possible.

    This is WIP so not ready to merge yet. We need to ideally remove every:

    • bare unwrap
    • assert!

    from the codebase.

    enhancement 
    opened by simonrw 5
  • Replace Line, Scatter, Function with Plot

    Replace Line, Scatter, Function with Plot

    Builds on #40. What this PR adds to #40:

    • Replace Line, Scatter and Function with a single struct Plot. Plotting a scatter plot is done by setting the PointStyle of the Plot.
    • And some other small things as I came across them..

    Some questions I have now:

    • Regarding the legend implementation: I wonder if it would be possible to reuse functionality to draw lines and points, to draw the legend. Difficult right now because that requires the axis functions.
    • In overlay functions should we take value or reference of the other style?
    • In builder patterns should we stick to functions of the form fn foo(&mut self, ..) -> &mut Self or fn foo(mut self, ..) -> Self? I would say the latter.

    Fixes #34 Fixes #18

    enhancement 
    opened by Ploppz 4
  • Restructure, start implementing legends

    Restructure, start implementing legends

    Edit: I started making smaller pull requests: #29 and #30 first, more to come later.

    I'm opening this PR for early feedback and review.

    • I have done quite some restructuring of modules, which is maybe best reviewed by generating docs from this branch.
    • Started implementing legends, (only Line so far - to use it just call Line::legend)
    • Fixed #18

    Yet To Do:

    • [ ] Fix tests to reflect these changes
    • [ ] Implement legend_svg() for other representations than Line
    opened by Ploppz 4
  • Plotting to term is broken since 0.5.0

    Plotting to term is broken since 0.5.0

    Hi Matt,

    First thing first thank you a lot for writing this lib: I love it (especially since it means I dont have to resrort to python to plot my graphs).

    You've basically changed most of the APIs between 0.4.0 and 0.5.0, and thats perfectly fine (doc says api are in a state of flux) and I really like the new APIs however it turns out that I can no longer plot my graphs to terminal since I made the change (Saving to SVG is ok though).

    bug 
    opened by xgillard 3
  • Allow building Scatter directly from an external Vec<(f64,f64)>

    Allow building Scatter directly from an external Vec<(f64,f64)>

    This pull request looks to make plotting data represented as an external vector of (f64,f64) tuples more ergonomic to deal with, which helps with representing external data with this library. For example, if we create a vector of points (or, for example, if a 2D column of values was imported from a .csv file), it's possible to build a Scatter structure to be represented in the ContinuousView directly by providing a vector of those tuples and a style. Since style was previously a private field, it wasn't able to be directly modified, and using the from_slice method was more or less required, preventing representation of any data whose size isn't known at compile-time.

    let mut data3: Vec<(f64,f64)> = vec![(-2.6, -2.7),(2.0,1.0)];
    let s3: Scatter = Scatter {data: data3, style: PointStyle::new() }.style(
        PointStyle::new() // uses the default marker
        .colour("red"),
    );
    

    A from_vec() function helps to make this a little bit more easier to do, provided that the PointStyle is defined after the initial Scatter is built (I believe it defaults to not being represented, unless the style is directly modified).

    let mut s3: Scatter = Scatter::from_vec(data3);
    s3.style.colour("red");
    

    I'm happy to make any modifications that might better fit with your preferences or standards for pull requests, and/or to discuss if this is the best way to accomplish making it easier to plot data in this form. Thanks for your time!

    enhancement 
    opened by quietlychris 3
  • Wrong example for scatterplot

    Wrong example for scatterplot

    Hey I tried to implement a scattterplot similar to the example and noticed that I need to use use plotlib::scatter::Scatter; instead of use plotlib::repr::Scatter; as written in the example project.

    bug invalid 
    opened by AntonOellerer 3
  • Some suggestions for changes (which I can implement)

    Some suggestions for changes (which I can implement)

    Most of these suggestions, I will already implement locally as I work on my project (which uses plotlib to plot stuff). I will submit a PR after a while. Until then, I open this issue so that you may discuss or protest against some of my suggestions. I can then change or revert that point. So please state your opinion! I will keep it updated as I think of new things.

    • [x] I think that taking Box<MyTrait> rather than &'a MyTrait in general makes a better programming interface, eliminating lifetimes. Examples: Page::add_plot and ContinuousView::add both take references to traits. In fact I was forced to change the latter function to add(mut self, repr: Box<ContinuousRepresentation>) because of lifetime issues in my project (more specifically, I created the data in a loop. The old solution would require me to store the data in a Vec and then loop again over that Vec to plot the data). It remains, however, to change to Box in other functions. Done in #40

    • [x] [PR #29] Naming: It's rather confusing to have struct line::Line, struct line::Style and also trait style::Line. I think we should find some way to rename them. Especially try to not make the Lines unique only through the module paths. We could for example name them struct Line, struct LineStyle and trait LineStyleTrait.

    • [x] [PR #29] Remove the Style traits. I don't see the need for a trait for every kind of Style. The only one that has two implementors is style::Line. However these two implementors are identical.

    • [ ] Naming: There are some opportunities for shorter names. Some words are quite commonly shortened, such as s/Representation/Repr.

    • [ ] #18

    opened by Ploppz 3
  • Error handling (when saving, but also generally)

    Error handling (when saving, but also generally)

    Page::save silently does nothing when the file extension is not one of a supported format. It should return an error, in my opinion. The reason I make an issue instead of fixing it myself is: what error should it return?

    I think we should use the failure crate. But then the question is: should we make an enum for possible errors, or just bail!("some text message")? Not sure what is common to do.

    opened by Ploppz 3
  • Update svg requirement from 0.10.0 to 0.12.1

    Update svg requirement from 0.10.0 to 0.12.1

    Updates the requirements on svg to permit the latest version.

    Commits

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 2
  • Update svg requirement from 0.10.0 to 0.13.0

    Update svg requirement from 0.10.0 to 0.13.0

    Updates the requirements on svg to permit the latest version.

    Commits

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 1
  • Categorical view to text produces empty string

    Categorical view to text produces empty string

    I get no text output when trying to convert a categorical view to text. When writing to svg, like barchart example, I see them, but when trying to convert to text, the output is empty.

    use plotlib::{ repr::BarChart, style::BoxStyle, view::{CategoricalView, View}, };

    fn main() {
        let b1 = BarChart::new(5.3).label("1");
        let b2 = BarChart::new(2.6)
            .label("2")
            .style(&BoxStyle::new().fill("darkolivegreen"));
    
        let v = CategoricalView::new()
            .add(b1)
            .add(b2)
            .x_label("Experiment")
            .to_text(20, 20)
            .unwrap();
    
        println!("{:?}", v);let v = CategoricalView::new()
            .add(b1)
            .add(b2)
            .x_label("Experiment")
            .to_text(20, 20)
            .unwrap();
    
        println!("{:?}", v);
    }
    
    opened by vlashada 1
  • Flipped CategoricalView

    Flipped CategoricalView

    A view with categorical entries along the x-axis and continuous values along the y-axis

    Is there any way to generate it flipped, i.e. categorical along Y axis and continuous along the X?

    enhancement 
    opened by kvark 1
  • Background color

    Background color

    It seems like currently svg is rendered with transparent background.

    I was able to change background color by changing this line to let mut document = Document::new().set("viewBox", (0, 0, width, height)).set("style", "background-color:white");

    Can we add an option to set background color of the plot ?

    opened by umieat 0
Releases(0.5.1)
  • 0.5.1(Mar 28, 2020)

    Fixed

    • Set default axis bounds for case where all values are equal (Issue #36)
    • Optimise tick generation to jump straight to range (Issue #42)
    • Fix text rendering of scatter plots
    Source code(tar.gz)
    Source code(zip)
  • 0.5.0(Mar 14, 2020)

    Added

    • Legends for line plots

    Changed

    • Remove style traits and replace all style structs with 3 common ones in style
    • Group all representations under a repr module.
    • Add linejoin option to line style.
    • More Box and less & in the interface
    • Replace Line, Scatter and Function with Plot
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Mar 2, 2019)

    Added

    • Line charts.
    • Box plots.
    • Bar charts.
    • Introduce categorical representation, views and axes.
    • Add ability to set dimensions of plot (PR #8)
    • Added ability to display a histogram as densities
    • Add ability to display grids (PR #23)

    Changed

    • Change create_axes, save, to_svg and to_text to return Result indicating an error.
    • Make representation module public.
    • Rename Scatter::from_vec to Scatter::from_slice.
    • Rename Histogram::from_vec to Histogram::from_slice.
    • Rename view::View to view::ContinuousView and introduce view::View as a trait.
    • Change svg_render functions to take data slices rather than Representations.
    • Histogram::from_slice now takes either a bin count or a bin bound list as its second argument.
    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Mar 1, 2018)

  • 0.2.0(Mar 15, 2020)

  • 0.1.0(Mar 9, 2017)

Owner
Matt Williams
Research Software Engineer
Matt Williams
A simple 2D plotting library that outputs graphs to SVG that can be styled using CSS.

Poloto graphs can be stylized using css either directly in the SVG, or from inside of html with an embedded svg. The latter allows the user to dynamically match the svg to their website's theme.

Ken Reed 119 Dec 13, 2022
Render farm simulator & plotting for optimisation written in Rust.

Farm Usage Simulator Given a few basic charasteristics of a render farm and render jobs this app runs a few randomized farm usage scenarios and plots

ford 2 Jul 17, 2022
Externalize easily the plotting process from Rust to gnuplot.

preexplorer Easy plotter and saver of simple data. Handy tool for development stage or small computational projects. Save data, have a quick view and

Raimundo Saona 4 Jan 7, 2022
Vector is a high-performance, end-to-end (agent & aggregator) observability data pipeline that puts you in control of your observability data

Quickstart • Docs • Guides • Integrations • Chat • Download What is Vector? Vector is a high-performance, end-to-end (agent & aggregator) observabilit

Vector 12.1k Jan 2, 2023
A library of to show data (in browser, evcxr_jupyter) as table, chart...

showata A library of to show data (in browser, evcxr_jupyter) as table, chart.... The crate provides display for: image vector and slice (as table) nd

Procyon 20 Dec 12, 2022
below is an interactive tool to view and record historical system data.

A time traveling resource monitor for modern Linux systems

Facebook Incubator 824 Dec 31, 2022
binocle is a graphical tool to visualize binary data

a graphical tool to visualize binary data

David Peter 773 Dec 30, 2022
📝 Web-based, reactive Datalog notebooks for data analysis and visualization

?? Web-based, reactive Datalog notebooks for data analysis and visualization

Eric Zhang 486 Dec 28, 2022
A Rust library for drawing plots, powered by Gnuplot.

RustGnuplot A Gnuplot controller written in Rust. Documentation See here Examples A simple example: let mut fg = Figure::new(); fg.axes2d() .set_titl

null 353 Dec 26, 2022
A pure Rust visualization library inspired by D3.js

charts A pure Rust visualization library inspired by D3.js. See gallery and examples for code and more charts. Install You can add this as a dependenc

Iulian Gulea 186 Dec 29, 2022
A library to generate syntax diagrams for Rust macros.

Live demo (code) A browser add-on for Firefox, Chrome and Edge A library to generate syntax ("railroad") diagrams for Rust's macro_rules!(). Diagrams

null 468 Jan 6, 2023
A small charting/visualization tool and partial vega implementation for Rust

Gust A charting library for rust! Disclaimer This is still very much a work in progress! APIs are very unstable and subject to change. Contributions a

Samuel Resendez 128 Dec 24, 2022
Plotly for Rust

Plotly.rs Plotly for Rust Getting Started | Recipes | API Docs | Changelog | | | A plotting library for Rust powered by Plotly.js. Usage Add this to y

Ioannis Giagkiozis 671 Jan 8, 2023
This is a Rust implementation of a boid flocking simulation using the ggez graphics crate.

Boidflock This is a Rust implementation of a boid flocking simulation using the ggez graphics crate. The CLI for this program is built using the struc

Andrew Lee 12 Jan 4, 2023
Swash is a pure Rust, cross-platform crate that provides font introspection, complex text shaping and glyph rendering.

Swash is a pure Rust, cross-platform crate that provides font introspection, complex text shaping and glyph rendering. Goals This crate aims to

Chad Brokaw 398 Dec 14, 2022
Rust crate for creating beautiful interactive Chord Diagrams

Chord PRO Released Chord PRO is the full-featured chord visualization API, producing beautiful interactive visualizations, e.g. those featured on the

Dr. Shahin Rostami 25 Sep 10, 2022
A Rust API for Vega-Lite V4 to build chart with a rusty API.

Vega-Lite V4 for Rust A Rust API for Vega-Lite V4 to build chart with a rusty API. Similar to the Altair project in python, this crate build upon Vega

Procyon 18 Nov 26, 2022
Graphical Rust program that uses a fractal algorithm to draw a tree of sorts

rusty-vegetation Graphical Rust program that uses a fractal algorithm to draw a "tree" of sorts. To Build and Run On Linux: Install build-essentials o

Stephen G Tuggy 4 Dec 4, 2022