Matplotlib的新(或)Cairo后端。
项目描述
这是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.dll 和 libfribidi-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++编译器不是标准的,您可能需要设置CC和CXX环境变量,使其指向您的C++编译器。[4](#footnote-4)在这种情况下,请务必将它们设置为例如g++-7而不是gcc-7,否则编译将成功,但共享对象将链接错误并无法加载。
manylinux wheel是用tools/build-manylinux-wheel.sh构建的。
distutils使用CC来编译C++源文件,但使用CXX来链接它们(不要问为什么)。如果CC或CXX包含多个单词,例如如果CC设置为ccache g++,您还需要将CXX设置为ccache gcc。
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.lib和cairo.dll)。
目前首选的解决方案是从Linux发行版软件包中获取头文件,从pycairo wheel(例如从PyPI)中获取DLL,并使用dumpbin和lib生成导入库。
或者,非常新的conda-forge构建(≥1.16.0构建1005)也包括FreeType支持。为了使用它们,需要修改以下描述的包含路径。(目前默认禁用,以避免如果cairo构建太旧而导致的混淆错误。)
FreeType头文件和导入以及动态库(freetype.lib和freetype.dll),可以从https://github.com/ubawurinna/freetype-windows-binaries获取,或者使用conda
conda install -y freetype
(标准)CL和LINK环境变量(它们分别始终添加到编译器和链接器的调用之前)应设置如下
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.dll和freetype.dll并将它们复制到mplcairo扩展模块旁边。由于动态库通常位于导入库旁边,我们搜索LINK环境变量中的/LIBPATH:条目,并复制其中找到的第一个cairo.dll和freetype.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_options和get_options函数控制并检查该库的使用。
在examples目录中包含一些情况,其中该渲染器的输出比默认渲染器Agg更准确。
circle_markers.py和square_markers.py:更准确和更快的标记戳记。
marker_stamping.py:更准确的标记戳记。
quadmesh.py:更好的四边形网格抗锯齿,带有掩码数据时较少的伪影。
text_kerning.py:改进的文本字距。
基准测试
在虚拟环境中安装pytest>=3.1.0和pytest-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.antialiased 或 patch.antialiased rcparams 设置为 cairo_antialias_t 枚举值,需要绕过 rcparam 验证,例如使用。
dict.__setitem__(plt.rcParams, "lines.antialiased", antialias_t.FAST)
同样,可以将 text.antialiased rcparam 设置为任何 cairo_antialias_t 枚举值,或 True(默认值,对应于 SUBPIXEL — GRAY 不足以从 Raqm 的子像素定位中受益;另见 cairo 问题 #152)或 False(对应于 NONE)。
请注意,在极少数情况下,在 cairo<1.17.4 上,FAST 抗锯齿可能会触发 cairo 中的“双重释放或损坏”错误(#44)。如果您遇到此问题,请考虑使用 BEST 或 NONE 抗锯齿(根据您的质量和速度要求而定)。
快速绘制
对于快速绘制具有许多段的路径,应将 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 环境变量为 vector 或 raster 允许将图形(使用 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 中已删除的 quality、optimize 和 progressive 参数到 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的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 3d2595431ec968399ac8d63ea4b6f35baecdd071a14a031d178da3cc83fe652e |
|
MD5 | eaa9995acd2c91aa10a0cbd938716f23 |
|
BLAKE2b-256 | 734cd30237614ad1c6e7b6987346e72c60db61145a09e09dd8ff28217da390db |
mplcairo-0.5-cp310-cp310-win_amd64.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 6a953d38f02cc0947dcfad15186b6b3625d916253a5b37386046156db237c5fb |
|
MD5 | bdb39dfbe151882c7d3d20bec7198b7e |
|
BLAKE2b-256 | 34d5156d86750b5332138ac4487a2a4cfd95e8027391cb44bf2f2042f50a4517 |
mplcairo-0.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 1b7016b4dcbd6805d183fd2cc8d5d32222edb2450ef510e57dc898c60017ef71 |
|
MD5 | 2ffbf4575e28f5b6dc6a56e84c697d1b |
|
BLAKE2b-256 | b3a3b2087a950508da60ee49297424c553eaa7414b524954f36f76f0d535dd61 |
mplcairo-0.5-cp310-cp310-macosx_10_15_x86_64.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 4b881a51df52a44858d7ac3a9dba850246fd9503766240b5b11de1ef4eed5556 |
|
MD5 | eb93470347314641f1df295f8e9b1d75 |
|
BLAKE2b-256 | 83c288438acef78ee4dd53cbd49867129dfca684298308a95a32a8591029658c |
mplcairo-0.5-cp39-cp39-win_amd64.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | d1e7a234999060625c83012829a4068eabdd63cad220390ec21e9713770d5340 |
|
MD5 | fe87cce7100f87481ec28f9bf3fc9246 |
|
BLAKE2b-256 | b31b89cef7bfbe3b928ea1e35850f7160b8c6bdd7c912f45ec2cc88aac7ba30f |
mplcairo-0.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 技术文档中的数字指纹:e30898e082ec3936dc3236d13b077f53d0c1998f865d5762f779ecd0b64a3335 |
|
MD5 | 技术文档中的数字指纹:85d106ba59e436a687e202c5cddb37c0 |
|
BLAKE2b-256 | 技术文档中的数字指纹:b20f7714d74b689a3a422ac05b650191d8dc6c0e2a12293992d406d9b95cfe47 |
哈希值 用于 mplcairo-0.5-cp39-cp39-macosx_10_15_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 哈希值:a2f6d4753d6c459dfd70ecd7fd7c756f7cf0cf91ff4140fe2a28a775daa92545 |
|
MD5 | 哈希值:ebfc5e4ffaebb80757e7bf570e7f495e |
|
BLAKE2b-256 | 哈希值:79425eac973153915515d22601a82df0d7ef71f3455793606a3fd4c01aa388bd |
哈希值 用于 mplcairo-0.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 哈希值:2b14f493bbc39e76104799de7cfcf8990754e359cfe47f5f216d56800f85d252 |
|
MD5 | 哈希值:6d70f9df5299461637344def2413a607 |
|
BLAKE2b-256 | 哈希值:89e2000be31bac105cb5d38c3ba3e3fbfb688b3f764855be6313c952f0499863 |
哈希值 用于 mplcairo-0.5-cp38-cp38-macosx_10_15_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 哈希值:d9ac0fde99cac407d1853f410308d73e9d6f2d05fc3fbbd2f086f4d5588c8420 |
|
MD5 | 哈希值:1c2b62f10e597272e0600f3c85d18788 |
|
BLAKE2b-256 | 哈希值:a591566bb0d867111119adafbacce2e4adc107fa7f622aa65c090eb816bd6997 |
哈希值 用于 mplcairo-0.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 哈希值:c497d4585ea53a69dc1c68b1a30b20b7536c95290b807712d7bd1ea0304fd1f8 |
|
MD5 | 哈希值:d450bbdbd83c03bf3bdde39aa0fb22d1 |
|
BLAKE2b-256 | 哈希值:6947acd5b75267a630705544fe1cded0e3b420dfc2db99344f8907dd5c2c4847 |
哈希值 用于 mplcairo-0.5-cp37-cp37m-macosx_10_15_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 哈希值:8ef73bd9f4711166b95b54d20eb81f45245bb78bbcb74f26568995683f1ce056 |
|
MD5 | 哈希值:3b93b86429e8c568cea789f2f49a452f |
|
BLAKE2b-256 | 哈希值:ce6b3583abcf477e60e52d17197ab0461d32e43ed917c75c3323c96fc77a8a47 |