This is a new, near-complete implementation of a cairo backend for Matplotlib. Currently, it can be used with either the Qt backend proposed in Matplotlib's PR #8771, or the Gtk3 backend proposed in #8772 (which is also included in #8771).
This implementation "passes" Matplotlib's entire image comparison test suite -- after accounting for inevitable differences in rasterization, and with the exceptions noted below.
Depending on the specific task, the backend can be anywhere from ~10x faster (e.g., stamping circular markers of variable colors) to ~10% faster (e.g., drawing lines) than Agg.
Dependencies:
- Python 3,
- cairo≥1.12 (needed for mesh gradient support),
- a C++ compiler with C++17 support, e.g. GCC≥7.1.
Such dependencies are available on conda and conda-forge. Using conda, the following commands will build and install mpl_cairo.
Then, the backend can be selected by setting the MPLBACKEND
environment
variable to module://mpl_cairo.qt
(or module://mpl_cairo.gtk3
).
The examples
folder contains a few cases where the output of this renderer
is arguably more accurate than the one of the default renderer, Agg:
circle_markers.py
andsquare_markers.py
: more accurate and faster marker stamping.markevery.py
: more accurate marker stamping.quadmesh.py
: better antialiasing of quad meshes, fewer artefacts with masked data.text_kerning.py
: improved text kerning.
Install (in the virtualenv) pytest>=3.1.0
and pytest-benchmark
, then
call (e.g.):
pytest --benchmark-group-by=fullfunc --benchmark-timer=time.process_time
Run run-mpl-test-suite.py
from the Matplotlib source folder to run the
subset of matplotlib tests that rely on png image comparison, while using this
backend. Pass command-line options as you would to pytest, although -k
must not be compressed with another short argument.
Antialiasing uses
CAIRO_ANTIALIAS_FAST
by default. Theantialiased
artist property can also take thempl_cairo.antialias_t.GOOD
(orBEST
, etc.) value for additional control.GOOD
/BEST
antialiasing of lines is ~3x slower than using Agg.NOTE: When drawing very thin lines (<0.5px, e.g.
test_cycles.test_property_collision_plot
),CAIRO_ANTIALIAS_FAST
may lead to artefacts, such that the line disappearing in certain areas. In that case, switching toGOOD
/BEST
antialiasing solves the issue. (It may be possible to do this automatically from within the backend, just as the miter limit is set whenever the line width is set.)path.simplify_threshold
is also used to control the accuracy of marker stamping, down to a arbitrarily chosen threshold of 1/16px. Values lower than that will use the exact (slower) marker drawing path. Marker stamping is also implemented for scatter plots (which can have multiple colors). Likewise, markers of different sizes get mapped into markers of discretized sizes, with an error bounded by the threshold.NOTE:
pcolor
and mplot3d'splot_surface
display some artifacts where the facets join each other. This is because these functions internally use aPathCollection
, thus triggering the approximate stamping.pcolor
should be deprecated in favor ofpcolormesh
(internally using aQuadMesh
), andplot_surface
should likewise instead represent the surface usingQuadMesh
, which is drawn without such artefacts.draw_markers
draws a marker at each control point of the given path, which is the documented behavior, even though all builtin renderers only draw markers at straight or Bézier segment ends.
- Snapping.
- Very large inputs (transforming to pixel values greater than
2**23
in absolute value) will be drawn incorrectly due to overflow in cairo (cairo #20091). A temporary workaround partially handles the issue when only one of the two coordinates is too large, but not when both are. - Blitting-based animation leaves small artefacts at the edges of the blitted region.
- Cache eviction policy and persistent cache for
draw_path_collection
. - Path simplification (although cairo appears to use vertex reduction and Douglas-Peucker internally?).
- Use QtOpenGLWidget and the cairo-gl backend.
hexbin
currently falls back on the slow implementation due to its use of theoffset_position
parameter. This should be fixed on Matplotlib's side.
- Expose the cairo PDF, PS and SVG backends.
- Native mathtext backend (to optimize antialiasing).
- Complex text layout (e.g. using libraqm).
It is slow (try running examples/mplot3d/wire3d_animation.py
), buggy (try
calling imshow
, especially with an alpha channel), and renders math poorly
(try title(r"\sqrt{2}")
).