Matplotlib import
Canvas.from_matplotlib(source, strict=False, **canvas_kwargs) accepts an
in-memory Matplotlib figure, axes, or rectangular axes array. This checklist
covers the intended import surface. It is a roadmap, not a promise that every
item already works on every rendering backend.
Checked items are implemented within their stated scope. Unless explicitly stated otherwise, fidelity checks below refer to the Matplotlib backend. Complex built-in artists are retained as detached, editable native geometry; these entries deliberately raise on backends that cannot represent them. Portable entries continue to support the other renderers, with the limitations listed below. Unchecked items are pending or partial. Importing drawn geometry does not recover the original samples, plotting call, callback, or statistical model. Matplotlib, Plotly, TikZ, and plotext have different rendering capabilities; import success does not guarantee that every backend can render the result identically.
Inputs and ownership
Section titled “Inputs and ownership”- Whole
Figure, individualAxes, flat lists/arrays, and 2D lists/arrays. - Explicit 2D array order; infer ordinary grids from flat input.
- Reject empty, ragged, non-axes, duplicate, and mixed-figure inputs.
- Snapshot plot arrays and styles without reparenting source artists.
- Canvas keyword overrides for figure size, DPI, and other canvas options.
- Warnings for recognized unsupported content; strict mode raises.
- Structured import report with artist identities, severity, and fallbacks.
- Complete detection of unsupported style properties in strict mode.
- Version compatibility matrix and fixtures across supported Matplotlib versions.
- Optional serialized figure input with an explicit trust boundary.
PNG/JPEG input and reconstruction of original data from PDF/SVG are separate features, not part of this object importer. Arbitrary custom Python artists need an adapter API or an explicit raster fallback; universal semantic conversion is not possible.
Figure and layout
Section titled “Figure and layout”- Ordinary rectangular subplot grids and individual axes.
- Figure dimensions and export DPI defaults.
- Figure title and shared axis label text.
- One
twinxand onetwinyper primary subplot; import only selected axes. - Full twin-axis spine positioning, multiple twins, and cross-backend parity. Matplotlib supports multiple twins and spine positions; backend parity is pending.
- Shared-axis relationships and linked limits after import.
- Preserve omitted/empty grid cells without drawing extra empty axes.
- Spanning cells, subplot mosaics, nested GridSpec, and subfigures (subfigure rectangles/decorations are flattened into the destination figure).
- Grid width/height ratios, margins, spacing, constrained/tight layout for ordinary/nested GridSpec; subfigures retain their snapshot rectangles.
- Arbitrary axes rectangles, overlapping axes, inset axes, inset-zoom
connectors (
indicate_inset_zoom/indicate_inset, Matplotlib 3.10+). The connector spans two Axes and recomputes its geometry from live limits on every draw, so it is rebuilt against the reconstructed parent/inset pair rather than snapshotted. Matplotlib < 3.10’s tuple-returning API still falls back to native geometry. - Secondary axes with forward/inverse coordinate functions.
- Figure backgrounds, frame styling, and figure-level text/patches/images.
- Figure title/shared-label typography and placement.
- Figure-level legends and shared colorbars.
Irregular grids use one row of addressable Canvas slots and retain the source axes rectangles when rendered with Matplotlib. A 2D input array defines its own layout; slots occupied only by a twin remain empty rather than drawing extra axes. Ordinary/nested GridSpec layout engines reflow on resize. Subfigure layout-engine reflow and full cross-backend layout parity remain pending.
Lines, markers, and collections
Section titled “Lines, markers, and collections”- Numeric 2D lines, markers, NaN gaps, line/marker colors and widths.
- Step draw styles in imported line entries (Matplotlib rendering).
- Horizontal/vertical reference lines with fractional extents (Matplotlib).
- Plain line collections, including
hlines/vlines, as individual lines. - Standard scatter marker shapes, sizes, scalar colors, and per-point colors.
- Scatter colormaps and normalization copied for Matplotlib rendering.
- Preserve date/time, categorical, quantity/unit converters and formatters.
- Custom dash sequences, cap/join styles, markevery, and gap colors.
- Infinite
axlinesemantics, event plots, stem containers. - Scalar-mapped line collections, offset collections, per-point transforms.
- Custom scatter paths and hollow markers on every backend.
- Match scatter area/size semantics and normalization on every backend.
- Preserve ordering between artist types at equal z-order.
Bars, errors, fills, and statistical plots
Section titled “Bars, errors, fills, and statistical plots”- Vertical/horizontal bars, positions, dimensions, baselines, and styling.
- Stacked/grouped bars as their resolved rectangles.
- Histogram bars as geometry (original samples are unavailable).
- Error-bar containers with data lines: symmetric/asymmetric x/y errors, caps, colors, widths, and labels; avoid duplicated component artists.
- Error-only plots and bar errors as line/cap geometry, without inventing asymmetric centers that the source no longer retains.
- Simple data-coordinate polygon collections, including
fill_between,fill_betweenx, and stackplot regions, as filled polygon geometry. - Data-coordinate polygon patches and stairs values/edges/baseline.
- Error limits/arrows, subsampled errors, and independently styled components.
- Restore semantic fill boundaries/where masks when recoverable. Drawn paths and retained container metadata are preserved; Matplotlib usually does not retain the original where-mask or samples.
- Spans in blended coordinates; general rectangles, circles, ellipses, wedges.
- Compound polygons, holes, curved paths, arbitrary PathPatch geometry.
- Box plots, violin plots, pie/donut charts, hist2d, hexbin.
- Preserve statistical groupings when containers/metadata retain them:
subplot.import_groupsand entrysource_container_idsretain bar, errorbar, and stem memberships, labels, orientation, and available data values.
Images, fields, and colorbars
Section titled “Images, fields, and colorbars”-
imshowarrays, extent, origin, colormap, normalization, interpolation copied into entries (Matplotlib rendering). - Match image extent/origin, RGB(A), masks, alpha, and interpolation on all backends.
- Nonlinear normalization, clim, under/over/bad colors on all backends.
-
pcolor,pcolormesh, nonuniform grids, QuadMesh, triangular meshes. - Contours, filled contours, levels, labels, and contour topology.
- Quiver, barbs, streamplots, vector-field keys.
- Axes colorbars tied to the correct image/scatter/mesh mappable.
- Colorbar orientation, label, ticks, limits, extend, and normalization.
- Multiple/shared colorbars and explicit colorbar axes.
Text and annotations
Section titled “Text and annotations”- Data-coordinate text, font family/size/weight/style, color, alignment, rotation (backend support varies).
- Data-coordinate annotations with optional arrows and independent copied arrow properties; references to other patches are explicitly rejected.
- Center title and x/y labels with basic typography and label padding.
- Text boxes, multiline spacing, math/TeX fidelity, wrapping, clipping through Matplotlib (TeX still requires the source environment’s TeX setup).
- Axes/figure fractions, point/pixel offsets, blended and callable coordinates.
- Annotation arrows with full backend parity and artist-relative coordinates.
- Left/right titles, custom title/label positions, offset text.
- AnnotationBbox, OffsetBox, tables, and other composite text artists.
Axes, ticks, grids, and legends
Section titled “Axes, ticks, grids, and legends”- Limits including reversed limits; default linear/log scales.
- Explicit major tick locations/labels with FixedLocator.
- Basic grid visibility, axes visibility, background, aspect, axisbelow.
- Basic per-axes legend visibility and artist labels.
- Non-default log bases; symlog, logit, asinh, function/custom scales.
- Automatic/fixed minor ticks, locator/formatter configuration and units.
- Tick placement, direction, length, width, color, rotation, and font styling.
- Per-axis major/minor grid visibility and line styling.
- Spine visibility, colors, widths, bounds, and positions.
- Autoscale flags, sticky edges, margins, adjustable/anchor/box aspect.
- Legend order, renamed labels, proxy handles, multiple legends, grouping.
- Legend location/anchor, columns, title, typography, frame and spacing.
Transforms, metadata, and advanced axes
Section titled “Transforms, metadata, and advanced axes”- General affine/nonlinear/blended transforms, coordinate rebinding.
- Clip paths/boxes, path effects, rasterization, sketch settings, filters.
- Hidden artists retained as hidden editable entries.
- Artist IDs, URLs, picking, metadata, and accessibility descriptions.
- Polar, geographic/custom projections, axisartist and parasite axes via native axes snapshots; custom projection classes must remain available.
- 3D lines/scatter, surfaces, wireframes, collections, camera/projection.
- Animations, widgets, callbacks, and interactive state (separate adapters). Static artist state is copied; arbitrary callback closures and GUI event loops cannot be reconstructed from a figure’s drawn geometry.
- Optional raster fallback for unsupported artists with explicit loss reporting.
Validation and next priorities
Section titled “Validation and next priorities”- Tests for all three input forms, source independence, strict/warning modes.
- Matplotlib reconstruction tests for supported geometry and axis settings.
- Plotly smoke/geometry tests for representative supported imports.
- Image comparisons with tolerances, plus representative portable export tests for Matplotlib PNG/SVG, Plotly HTML, plotext text, and TikZ source.
- Large figures, empty/masked data, performance and memory benchmarks.
New import controls:
canvas = Canvas.from_matplotlib(fig, strict=True)report = canvas.import_report.to_dict() # identities, severity, fallback, backendscanvas = Canvas.from_matplotlib("figure.pickle", trusted=True)canvas = Canvas.from_matplotlib(fig, fallback="raster")trusted=True is required before any pickle is read. Pickles can execute code;
load only files whose producer you trust and use a matching Matplotlib version.
fallback="native" (default) retains built-in native geometry with rebound
transforms. fallback="skip" warns (or raises in strict mode) for those artists.
fallback="raster" snapshots the selected figure content and records the loss of
editable data and vector geometry; it supports Matplotlib and Plotly. Callback
functions and custom scales remain Python objects, not portable serialization.
Strict mode checks import losses, not universal rendering parity.
Remaining priorities are cross-backend fidelity, subfigure reflow, portable projection adapters, and live interaction adapters. Source metadata does not usually retain original fill masks or box/violin samples; these are imported as geometry without inventing lost statistical inputs.
Reference APIs: Matplotlib artists, containers, and annotations.
Compatibility fixtures live in test_matplotlib_import.py and
test_matplotlib_import_extended.py. The CI matrix covers Matplotlib 3.8, 3.9,
3.10 and 3.11 on Python 3.11. Snapshots use version-sensitive Matplotlib state;
there is no cross-version pickle compatibility promise.
Run python scripts/benchmark_matplotlib_import.py --points 100000 --panels 4
for reproducible timing/allocation observations. A local Matplotlib 3.11.1 run
imported 400,000 points in 0.41 s with 8.75 MiB peak Python allocations and rendered
in 0.79 s. These are observations, not performance guarantees; native allocations
outside Python are excluded from the memory measurement.