跳转到主要内容

Matplotlib的新(或)Cairo后端。

项目描述

GitHub PyPI Fedora Rawhide

这是Matplotlib的新、本质上完整的cairo后端实现。它可以与Qt、GTK、Tk、wx或macOS UI结合使用,或非交互式使用(例如,将图形保存到各种文件格式)。

值得关注的有

  • 提高精度(例如,使用标记定位、四边形网格和文本间距;支持浮点表面,需要cairo≥1.17.2)。

  • 可选的多线程绘制标记和路径集合。

  • 可选支持复杂文本布局(例如,从右到左的语言)和OpenType字体功能(见examples/opentype_features.py),以及部分支持彩色字体(例如,表情符号),使用Raqm注意 Raqm默认依赖于Fribidi,其许可协议为LGPLv2.1+。

  • 支持在PDF(但不是SVG)输出中嵌入URL(需要cairo≥1.15.4)。

  • 支持PDF和PS的多页输出(Matplotlib仅支持多页PDF)。

  • 支持自定义混合模式(见examples/operators.py)。

  • 在矢量格式中改进字体嵌入:字体通常是子集并以其原生格式嵌入(Matplotlib≥3.5还提供了改进的字体嵌入)。

安装

mplcairo需要

  • Python≥3.7,

  • Matplotlib≥2.2(作为install_requires声明),

  • 在Linux和macOS上,pycairo≥1.16.0 [1](作为 install_requires 声明),

  • 在Windows上,cairo≥1.11.4 [2](与wheel一起提供)。

建议使用cairo≥1.17.4。

此外,从源代码构建mplcairo需要

  • pybind11≥2.6.0 [3](作为 setup_requires 声明),

  • pycairo≥1.16.0(作为 setup_requires 声明)。

像往常一样,使用pip进行安装

$ pip install mplcairo  # from PyPI
$ pip install git+https://github.com/matplotlib/mplcairo  # from Github

请注意,由于macOS<10.13中包含的libc++版本太旧,且libc++的供应商似乎很脆弱,因此macOS<10.13的wheels不可用。欢迎提供打包方面的帮助。

mplcairo可以使用Raqm(≥0.7.0;推荐使用≥0.7.2,因为它提供了更好的emoji支持,特别是在存在连字的情况下)进行复杂的文本布局和OpenType字体特性的处理。请参考该项目的网站上的说明,以了解Linux和macOS上的安装方法。在Windows上,可以考虑使用Christoph Gohlke的构建(包含 libraqm.dlllibfribidi-0.dll 的目录需要添加到 DLL搜索路径)。

在Fedora上,该软件包作为 python-mplcairo 提供。

构建/打包

本节仅在你希望自行构建mplcairo或打包分发时适用。否则,请转到 使用 部分。

在任何情况下,一旦安装了下面描述的依赖项,就可以使用任何标准命令(pip wheel --no-deps .pip install .pip install -e .python setup.py build_ext -i 最为相关)来构建和安装mplcairo。

Unix

还需要以下附加依赖项

  • 一个支持C++17的C++编译器,例如GCC≥7.2或Clang≥5.0。

  • cairo和FreeType头文件,以及pkg-config信息以定位它们。

    如果使用conda,可以使用以下命令进行安装

    conda install -y -c conda-forge pycairo pkg-config

    因为pycairo(也是一个依赖项)依赖于cairo,而cairo依赖于freetype。请注意,来自 anaconda 通道的cairo和pkg-config 不会 工作。

    在Linux上,您也可以使用您发行版的软件包管理器进行安装(Arch:cairo,Debian/Ubuntu:libcairo2-dev,Fedora:cairo-devel)。

还需要Raqm (≥0.2)头文件,但如果没有找到,将自动下载。

Linux

conda的编译器(anaconda通道上的gxx_linux-64目前与conda-forge中安装cairo和pkg-config交互不佳,因此您需要自行安装最新的编译器(例如,使用您发行版的软件包管理器)。如果您使用的C++编译器不是标准的,您可能需要设置CCCXX环境变量,使其指向您的C++编译器。[4](#footnote-4)在这种情况下,请务必将它们设置为例如g++-7而不是gcc-7,否则编译将成功,但共享对象将链接错误并无法加载。

manylinux wheel是用tools/build-manylinux-wheel.sh构建的。

macOS

Clang≥5.0可以从conda的anaconda通道安装(conda install -c anaconda clangxx_osx-64),或者也可以使用Homebrew安装(brew install llvm)。请注意,Homebrew的llvm公式是keg-only,即它需要手动修改PATH和LDFLAGS(如brew info llvm中所述)。

在macOS<10.14上,还需要使用clang<8.0(例如,使用brew install llvm@7)),因为clang 8.0似乎认为依赖于C++17的代码只能在macOS≥10.14+上运行。

macOS wheel是用tools/build-macos-wheel.sh构建的,它依赖于delocate-wheel(提供最新版本的libc++)。目前,它只能从Homebrew-clang wheel构建,而不能从conda-clang wheel构建(由于某些路径的复杂性...)。

由于我只能在CI上亲自测试macOS构建,因此对该平台上的构建和包装的任何帮助都将受到欢迎。

Windows

还需要以下附加依赖项

  • VS2019(确切的最小版本尚不清楚,但已知mplcairo在Github Actions windows-2016代理上无法构建,并需要windows-2019代理。)

  • 带有FreeType支持的cairo头文件和导入和动态库(cairo.libcairo.dll)。

    目前首选的解决方案是从Linux发行版软件包中获取头文件,从pycairo wheel(例如从PyPI)中获取DLL,并使用dumpbinlib生成导入库。

    或者,非常新的conda-forge构建(≥1.16.0构建1005)也包括FreeType支持。为了使用它们,需要修改以下描述的包含路径。(目前默认禁用,以避免如果cairo构建太旧而导致的混淆错误。)

  • FreeType头文件和导入以及动态库(freetype.libfreetype.dll),可以从https://github.com/ubawurinna/freetype-windows-binaries获取,或者使用conda

    conda install -y freetype

(标准)CLLINK环境变量(它们分别始终添加到编译器和链接器的调用之前)应设置如下

set CL=/IC:\path\to\dir\containing\cairo.h /IC:\same\for\ft2build.h
set LINK=/LIBPATH:C:\path\to\dir\containing\cairo.lib /LIBPATH:C:\same\for\freetype.lib

特别是,为了使用上面描述的conda-forge cairo,需要将{sys.prefix}\Library\include\cairo添加到包含路径。

此外,我们还需要找到cairo.dllfreetype.dll并将它们复制到mplcairo扩展模块旁边。由于动态库通常位于导入库旁边,我们搜索LINK环境变量中的/LIBPATH:条目,并复制其中找到的第一个cairo.dllfreetype.dll

脚本tools/build-windows-wheel.py自动检索cairo(假设pycairo已经安装)和FreeType DLLs,以及wheel构建。

使用

在Linux和Windows上,mplcairo可以用作任何正常Matplotlib后端:在导入pyplot之前调用例如matplotlib.use("module://mplcairo.qt"),在您的matplotlibrc中添加backend: module://mplcairo.qt行,或将MPLBACKEND环境变量设置为module://mplcairo.qt。更具体地说,以下后端提供

  • module://mplcairo.base(无GUI,但可以使用cairo的实现输出EPS、PDF、PS、SVG和SVGZ,而不是Matplotlib的),

  • module://mplcairo.gtk(GTK小部件,从cairo图像表面复制数据——通过在导入后端之前调用gi.require_version("Gtk", "3.0")gi.require_version("Gtk", "4.0")来选择GTK3或GTK4),

  • module://mplcairo.gtk_native(GTK小部件,直接绘制到原生表面上;不支持位块传输——见上文以选择版本),

  • module://mplcairo.qt(Qt小部件,从cairo图像表面复制数据——通过在导入mplcairo之前导入它或通过设置QT_API环境变量来选择要使用的绑定),

  • module://mplcairo.tk(Tk小部件,从cairo图像表面复制数据),

  • module://mplcairo.wx(wx小部件,从cairo图像表面复制数据),

  • module://mplcairo.macosx(macOS小部件,从cairo图像表面复制数据)。

由于与最近版libc++使用相关的不兼容性,在macOS上,在导入Matplotlib之前必须显式导入mplcairo。因此,最实际的选择是导入mplcairo,然后调用例如matplotlib.use("module://mplcairo.macosx")

Jupyter完全不受支持(欢迎提交补丁)。一种可能的做法是在导入Matplotlib之前将环境变量MPLCAIRO_PATCH_AGG设置为一个非空值;这将完全用cairo渲染器替换Matplotlib中的Agg渲染器。然而,这种方法效率低下(由于需要Premultiplied ARGB32和直通的RGBA8888缓冲区之间的复制和转换);此外,由于相应画布类的特殊性,它不适用于wx和macosx后端。另一方面,这是目前基于webagg的后端(例如,Jupyter的交互式小部件)使用mplcairo的唯一方法。

在导入时,mplcairo将尝试加载Raqm。可以使用set_optionsget_options函数控制并检查该库的使用。

examples目录中包含一些情况,其中该渲染器的输出比默认渲染器Agg更准确。

基准测试

在虚拟环境中安装pytest>=3.1.0pytest-benchmark,然后调用(例如)

pytest --benchmark-group-by=fullfunc --benchmark-timer=time.process_time

请注意,conda-forge的cairo在我的设置中比“原生”构建的cairo慢约2倍。

测试套件

运行run-mpl-test-suite.py(它依赖于pytest>=3.2.2)以使用mplcairo后端修补的Agg后端运行Matplotlib测试套件。请注意,Matplotlib必须与测试数据一起安装,这不是从conda或大多数Linux发行版安装的情况;相反,应从PyPI或源安装。

几乎所有图像比较测试“失败”,因为渲染器在本质上不同;目前,打算手动检查差异图像。传递--tolerance=inf将这些测试标记为“通过”(同时仍然以文本形式报告图像差异),以便可以发现问题与渲染差异无关。实际上,--tolerance=50似乎足够。

一些其他(非图像比较)测试也已知会失败(它们在ISSUES.rst中列出,并附有相关说明),并且会自动跳过。

运行run-examples.py以运行一些测试mplcairo更多方面的示例。

注释

抗锯齿

艺术家的抗锯齿属性可以设置为cairo_antialias_t枚举值中的任何一个,或者设置为True(默认值)或False(与NONE同义)。

将抗锯齿设置为True将使用对于大于1/3px的线条使用FAST抗锯齿,对于小于该值的线条使用BEST抗锯齿:对于小于1/3px的线条,前者会导致诸如线条在某些部分消失之类的伪影(例如,在强制抗锯齿为FAST后查看test_cycles.test_property_collision_plot)。1/3px的阈值是经验确定的,请参阅examples/thin_line_antialiasing.py

请注意,为了将 lines.antialiasedpatch.antialiased rcparams 设置为 cairo_antialias_t 枚举值,需要绕过 rcparam 验证,例如使用。

dict.__setitem__(plt.rcParams, "lines.antialiased", antialias_t.FAST)

同样,可以将 text.antialiased rcparam 设置为任何 cairo_antialias_t 枚举值,或 True(默认值,对应于 SUBPIXELGRAY 不足以从 Raqm 的子像素定位中受益;另见 cairo 问题 #152)或 False(对应于 NONE)。

请注意,在极少数情况下,在 cairo<1.17.4 上,FAST 抗锯齿可能会触发 cairo 中的“双重释放或损坏”错误(#44)。如果您遇到此问题,请考虑使用 BESTNONE 抗锯齿(根据您的质量和速度要求而定)。

快速绘制

对于快速绘制具有许多段的路径,应将 agg.path.chunksize rcparam 设置为例如 1000(有关此值的确定,请参阅 examples/time_drawing_per_element.py);这将导致更长的路径被分割成每个 1000 段的独立渲染部分(直接渲染较长的路径似乎具有略微超线性的复杂度)。

简化阈值

path.simplify_threshold rcparam 用于控制标记戳记的精度,直至任意选择的 1/16px 阈值。如果阈值设置为较低的值,将使用精确(较慢)的标记绘制路径。标记戳记还适用于散点图(可以具有多种颜色)。同样,不同大小的标记被映射到离散大小的标记,误差受阈值限制。

注意pcolor 和 mplot3d 的 plot_surface 在面片连接处显示一些伪影。这是因为这些函数内部使用 PathCollection;这触发了近似戳记,即使不这样做(通过将 path.simplify_threshold 设置为零),cairo 对面片之间边缘的光栅化也较差。通常应首选 pcolormesh(内部使用 QuadMesh)。plot_surface 可以使用 QuadMesh 来表示表面,这样可以避免此类伪影。

字体格式和功能

为了使用 Matplotlib 可能无法使用的特定字体,请直接传递文件名

from matplotlib.font_manager import FontProperties
fig.text(.5, .5, "hello, world",
         fontproperties=FontProperties(fname="/path/to/font.ttf"))

或者更简单,在 Matplotlib≥3.3 之后

from pathlib import Path
fig.text(.5, .5, "hello, world", font=Path("/path/to/font.ttf"))

mplcairo 仍然依赖于 Matplotlib 的字体缓存,因此 Matplotlib 不支持的字体仍然无法通过其他方式使用。

对于 TTC 字体(以及更普遍的包含单个文件中多个字体字形的字体格式),可以通过在文件名后附加 #n 来选择第 n 个字体(n≥0)(例如,"/path/to/font.ttc#1")。

OpenType 字体功能可以通过在文件名后附加 |feature,... 来选择,后跟一个 HarfBuzz 功能字符串(例如,"/path/to/font.otf|frac,onum");请参阅 examples/opentype_features.py。同样,可以使用 |language=... 来设置 语言 标签;目前,这始终适用于整个缓冲区,但添加支持切片语法的 PR 将会考虑。

选择 TTC 子字体、OpenType 字体功能和语言标签的语法是 实验性的,可能会更改,特别是在这些功能在 Matplotlib 本身实现的情况下。

处理颜色字体(例如表情符号)。

多页输出

Matplotlib 的 PdfPages 类与内置的 backend_pdf 深度绑定(实际上,它甚至不能与 Matplotlib 自身的 cairo 后端一起使用)。相反,使用 mplcairo.multipage.MultiPage 生成多页 PDF 和 PS 输出。API 类似。

from mplcairo.multipage import MultiPage

fig1 = ...
fig2 = ...
with MultiPage(path_or_stream, metadata=...) as mp:
    mp.savefig(fig1)
    mp.savefig(fig2)

请参阅类的文档字符串以获取更多信息。

矢量格式版本控制

cairo 能够写入 PDF 1.4 和 1.5(默认为 1.5),PostScript 2 和 3(默认为 3),以及 SVG 1.1 和 1.2(默认为 1.1)。这可以通过传递一个包含 MaxVersion 条目的 metadata 字典到 savefig 来控制,该字符串必须是以下字符串之一:"1.4"/"1.5"(对于 pdf),"2"/"3"(对于 ps),或 "1.1"/"1.2"(对于 svg)。

cairo-script 输出

在导入 mplcairo 之前设置 MPLCAIRO_SCRIPT_SURFACE 环境变量为 vectorraster 允许将图形(使用 savefig)保存为 .cairoscript 格式,这是一种“与 cairo 绘图模型匹配的本地脚本”。变量的值决定了使用的渲染路径(例如,是否使用标记盖章)。这可能有助于故障排除。

注意,由于 cairo 问题 #277,写入文件后可能会崩溃。

贝塞尔控制点的标记

draw_markers 在给定路径的每个控制点上绘制一个标记,这是文档化的行为,尽管所有内置渲染器只在直线或 Bézier 段的末端绘制标记。

已知差异

由于缺少 cairo 的支持

  • SVG 输出不支持全局元数据或为任何元素设置 URL 或 ids,因为 cairo 提供了相应的支持。

  • PS 输出不尊重 SOURCE_DATE_EPOCH。

  • PS 输出不支持 Creator 元数据键;然而,它支持 Title 键。

  • 以下 rcparams 没有效果

    • pdf.fonttype(字体类型由 cairo 内部选择),

    • pdf.inheritcolor(实际上始终为 False),

    • pdf.use14corefonts(实际上始终为 False),

    • ps.fonttype(字体类型由 cairo 内部选择),

    • ps.useafm(实际上始终为 False),

    • svg.fonttype(实际上始终为 "path",请参阅 cairo 问题 #253),

    • svg.hashsalt.

此外,Matplotlib 3.5 中已删除的 qualityoptimizeprogressive 参数到 savefig,这些参数不支持。

可能的优化

  • draw_path_collection 的缓存淘汰策略和持久缓存。

  • 使用 QtOpenGLWidget 和 cairo-gl 后端。

关于已经存在的cairo(gtk/qt/wx/tk/…cairo)后端呢?

它们的速度非常慢(尝试运行 examples/mplot3d/wire3d_animation.py)并且渲染数学表达式不佳(尝试 title(r"$\sqrt{2}$"))。

项目详情


下载文件

下载适合您平台的应用程序文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。

源代码发行版

mplcairo-0.5.tar.gz (93.8 kB 查看散列值)

上传时间 源代码

构建发行版

mplcairo-0.5-cp310-cp310-win_amd64.whl (1.8 MB 查看散列值)

上传时间 CPython 3.10 Windows x86-64

mplcairo-0.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl (873.2 kB 查看散列值)

上传时间 CPython 3.10 manylinux: glibc 2.5+ x86-64

mplcairo-0.5-cp310-cp310-macosx_10_15_x86_64.whl (329.2 kB 查看散列值)

上传时间 CPython 3.10 macOS 10.15+ x86-64

mplcairo-0.5-cp39-cp39-win_amd64.whl (1.8 MB 查看散列值)

上传时间 CPython 3.9 Windows x86-64

mplcairo-0.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl (873.4 kB 查看散列值)

上传时间 CPython 3.9 manylinux: glibc 2.5+ x86-64

mplcairo-0.5-cp39-cp39-macosx_10_15_x86_64.whl (329.7 kB 查看散列值)

上传时间 CPython 3.9 macOS 10.15+ x86-64

mplcairo-0.5-cp38-cp38-win_amd64.whl (1.8 MB 查看哈希值)

上传时间: CPython 3.8 Windows x86-64

mplcairo-0.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl (873.2 kB 查看哈希值)

上传时间: CPython 3.8 manylinux: glibc 2.5+ x86-64

mplcairo-0.5-cp38-cp38-macosx_10_15_x86_64.whl (329.2 kB 查看哈希值)

上传时间: CPython 3.8 macOS 10.15+ x86-64

mplcairo-0.5-cp37-cp37m-win_amd64.whl (1.8 MB 查看哈希值)

上传时间: CPython 3.7m Windows x86-64

mplcairo-0.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl (881.1 kB 查看哈希值)

上传时间: CPython 3.7m manylinux: glibc 2.5+ x86-64

mplcairo-0.5-cp37-cp37m-macosx_10_15_x86_64.whl (324.5 kB 查看哈希值)

上传时间: CPython 3.7m macOS 10.15+ x86-64

由以下机构支持