mplcairo
mplcairo copied to clipboard
workaround for low dpi when rasterizing (pcolormesh saved as pdf)
https://github.com/matplotlib/mplcairo/blob/master/ISSUES.rst mentions that there is an issue with "Invalid dpi manipulations in vector output". Is there an easy workaround for this?
Also, thanks for developing this backend! I don't understand all the details of how fonts are handled internally but mplcairo seems to be giving me better looking text!
Are you running into this issue for a real use case? The main problem I am aware of is with using figimage() (so "per-pixel data") with pdf output (where the notion of "pixel" is not really well defined, but conventionally thought of as 72 dpi); I think there's somewhere where I may forget to switch the canvas from 100 dpi (or whatever the "nominal" resolution is) to the pdf output's 72 dpi, or where mpl does it and I do it too so it happens twice (IIRC (from very long time ago...) mpl's image.py code basically does something slightly weird to match the just as undocumented behavior of backend_pdf.py, and I gave up reverse-engineering that). To be honest it's really low on my priority list because it's quite obscure and not so easy to fix, but if you have a real use case, please describe it. The other problems mostly occur with rasterizing svgs at very low resolution, and whether that should use "nearest" interpolation or some kind of smoothing. I think there's also an issue about that on the mpl tracker.
here is a MWE to reproduce the issue I am facing.
import numpy as np
import matplotlib.pyplot as plt
data = np.arange(25).reshape(5, 5)
for backend in ['pdf', 'module://mplcairo.base']:
plt.switch_backend(backend)
fig, ax = plt.subplots(figsize=(3, 2.5), constrained_layout=True)
im = ax.pcolormesh(data)
cbar = fig.colorbar(im)
im.set_rasterized(True)
cbar.solids.set_rasterized(True)
fig.savefig(f'backend_{backend.split("//")[-1]}_dpi300.pdf', dpi=300)
fig.savefig(f'backend_{backend.split("//")[-1]}_dpi72.pdf', dpi=72)
backend_pdf_dpi72.pdf backend_pdf_dpi300.pdf backend_mplcairo.base_dpi72.pdf backend_mplcairo.base_dpi300.pdf
Looks like mplcairo is always going for 72 dpi (and also causing issue with the rasterized image overflowing the boundaries of axes and colorbar).
I forgot to add that I am using mplcairo v0.2 installed from pypi, matplotlib v3.1.2 (conda-forge) Python 3.7.6 (conda-forge) installed on Windows 10.
I think that the following line is causing the issue. I have created a PR to fix it. (My apologies in advance if I am trivializing the issue but this just feels like an inadvertent oversight).
https://github.com/matplotlib/mplcairo/blob/a54ace541fd10a07e662fa8df0efc8e1f240020c/lib/mplcairo/base.py#L245
def _print_method(self, renderer_factory,
path_or_stream, *, metadata=None, dpi=72, **kwargs):
_check_print_extra_kwargs(**kwargs)
self.figure.set_dpi(72) # This should be self.figure.set_dpi(dpi)
No need to apologize when you're proposing a fix :) (though it does look like the PR CI is failing -- let's continue the discussion there)
https://github.com/matplotlib/matplotlib/issues/16268#issuecomment-576412375 may be related.