Skip to main content

ironlab/
lib.rs

1//! MATLAB-flavoured Rust API for building, viewing and exporting scientific figures.
2//!
3//! A [`Figure`] is built by placing axes in a grid of tiles and adding plots to them
4//! with functions named after their MATLAB equivalents: [`plot`](AxesMut::plot),
5//! [`scatter`](AxesMut::scatter), [`contour`](AxesMut::contour),
6//! [`quiver`](AxesMut::quiver), [`surf`](AxesMut::surf), [`image`](AxesMut::image)
7//! and their relatives (MATLAB's `imagesc` is [`mapped_image`](AxesMut::mapped_image),
8//! and MATLAB's `pcolor` is [`surface`](AxesMut::surface) in a two-dimensional axes).
9//! Each plotting function returns a handle whose chained setters change the properties
10//! of the new plot, in the way that MATLAB name–value arguments do. The figure can then
11//! be shown in the interactive viewer, saved as a `.fig` file (or as JSON) or exported
12//! to PDF.
13//!
14//! Every call writes directly to the retained figure IR of the [`ir`] crate, which is
15//! the single source of truth for what is drawn. Builder calls never panic because of
16//! inconsistent input (such as arrays of different lengths or a tile outside the
17//! layout); such problems are reported by [`Figure::validate`], and are checked again
18//! before the figure is exported or shown.
19//!
20//! # Example
21//!
22//! ```
23//! use ironlab::prelude::*;
24//!
25//! let x = linspace(0.0, 2.0 * std::f64::consts::PI, 200);
26//! let sin: Vec<f64> = x.iter().map(|x| x.sin()).collect();
27//! let cos: Vec<f64> = x.iter().map(|x| x.cos()).collect();
28//!
29//! let mut fig = Figure::new().size_mm(120.0, 80.0).title("Trigonometric functions");
30//! let mut ax = fig.axes(0, 0);
31//! ax.plot(&x, &sin).display_name("$\\sin x$");
32//! ax.plot(&x, &cos).display_name("$\\cos x$").dash(Dash::Dashed);
33//! ax.xlabel("$x$").ylabel("$f(x)$").legend(LegendLocation::NorthEast);
34//!
35//! assert!(fig.validate().is_valid());
36//! ```
37//!
38//! Showing and exporting a figure:
39//!
40//! ```no_run
41//! use ironlab::prelude::*;
42//!
43//! # fn main() -> Result<(), ironlab::Error> {
44//! let x = linspace(-1.5, 1.5, 61);
45//! let y = linspace(-1.5, 1.5, 61);
46//! let z = Matrix::from_fn(y.len(), x.len(), |row, col| x[col].powi(2) - y[row].powi(2));
47//!
48//! let mut fig = Figure::new().title("A saddle");
49//! fig.axes(0, 0).surf(&x, &y, &z);
50//! fig.export_pdf("saddle.pdf")?;
51//! fig.show()?;
52//! # Ok(())
53//! # }
54//! ```
55
56mod artists;
57mod axes;
58mod color;
59mod error;
60mod figure;
61mod grid;
62mod matrix;
63mod pixels;
64
65pub use ironlab_ir as ir;
66
67pub use artists::{
68    ContourMut, ImageMut, IndexedImageMut, LineMut, MappedImageMut, QuiverMut, ScatterMut,
69    SurfaceMut,
70};
71pub use axes::AxesMut;
72pub use color::IntoColorSpec;
73pub use error::Error;
74pub use figure::Figure;
75pub use grid::GridCoords;
76pub use matrix::{Matrix, linspace, logspace, meshgrid};
77pub use pixels::{ByteMatrix, ImageValues, Pixels};
78
79/// The coordinate dimension of an axes, used to link axes and set limits.
80pub use ironlab_ir::Dimension as Dim;
81
82/// The shape of the markers drawn at data points.
83pub use ironlab_ir::MarkerShape as Marker;
84
85/// The dash pattern of a line.
86pub use ironlab_ir::DashStyle as Dash;
87
88/// The name of a colormap.
89pub use ironlab_ir::ColormapName as Colormap;
90
91/// The plane of an axes in which an image lies, with its offset along the third axis.
92pub use ironlab_ir::ImagePlane;
93
94/// What a colour-indexed or colour-mapped image draws for a pixel it cannot colour.
95pub use ironlab_ir::OutOfRange;
96
97pub use ironlab_ir::{
98    Color, ColorSpec, Interpreter, IssueKind, LegendLocation, NodeId, Parameter, Scale, Text,
99    ValidationIssue, ValidationReport,
100};
101
102/// How a dense artist is drawn when the figure is exported, and at what resolution it is
103/// rasterised. See [`Figure::export_pdf_with`].
104pub use ironlab_pdf::{RasterOptions, RasterPolicy};
105
106/// A problem the scene compiler found while drawing a figure that did not prevent the
107/// figure from being drawn, naming the node it concerns. See [`ExportReport`].
108pub use ironlab_scene::SceneWarning;
109
110/// What an export left off the page, returned by [`Figure::export_pdf`] and
111/// [`Figure::export_pdf_with`].
112///
113/// A warning never refuses a figure, so the page is written whatever the report holds;
114/// the report tells a program what the page does not show. Both lists are empty for a
115/// figure from which nothing was left out. The two lists overlap where the compiler
116/// leaves out an artist that validation warned of, such as a surface whose field has a
117/// single row, and differ where the compiler finds a reason that validation cannot see,
118/// such as a piece of LaTeX the typesetter does not support. A program that wants one
119/// reason per artist reads `validation`; one that wants every reason reads both.
120#[derive(Debug, Clone, Default, PartialEq)]
121pub struct ExportReport {
122    /// The warnings of the figure's validation, as [`Figure::validate`] returns them: an
123    /// artist with nothing to draw, data that a logarithmic axis cannot show, or an image
124    /// that cannot be placed. Each names the node it concerns.
125    pub validation: Vec<ValidationIssue>,
126    /// The warnings the scene compiler raised while drawing the figure, each naming the
127    /// node it concerns.
128    pub scene: Vec<SceneWarning>,
129}
130
131/// The types and functions needed to build figures, for glob import.
132///
133/// ```
134/// use ironlab::prelude::*;
135/// ```
136pub mod prelude {
137    pub use crate::AxesMut;
138    pub use crate::{
139        ByteMatrix, Color, ColorSpec, Colormap, ContourMut, Dash, Dim, Error, Figure, GridCoords,
140        ImageMut, ImagePlane, ImageValues, IndexedImageMut, IntoColorSpec, LegendLocation, LineMut,
141        MappedImageMut, Marker, Matrix, NodeId, OutOfRange, Parameter, Pixels, QuiverMut,
142        RasterOptions, RasterPolicy, Scale, ScatterMut, SurfaceMut, Text, linspace, logspace,
143        meshgrid,
144    };
145}