matplotlib/mplcairo

1st try pdf multipage fail

nbecker opened this issue · 6 comments

1st try, converted my code using PdfPages to MultiPage, but got this:

  File "./plot_results_vs_esno2.py", line 317, in <module>
    pdf.savefig (fig)
  File "/home/nbecker/.local/lib/python3.6/site-packages/mplcairo/multipage.py", line 41, in savefig
    self._renderer._set_size(*figure.canvas.get_width_height(),
AttributeError: 'MultiPage' object has no attribute '_renderer'

It's not at all a minimal test case I can upload, but does anyone know what might be the problem?

from matplotlib import pyplot as plt
from mplcairo.multipage import MultiPage

fig1, _ = plt.subplots(2)
fig2, _ = plt.subplots(3)
with MultiPage("/tmp/test.pdf") as mp:
    mp.savefig(fig1)
    mp.savefig(fig2)

works for me. You definitely need to use the contextmanager form though (this needs to be documented).

Does this help?

Adapting the existing code to use a contextmanager seems difficult, the structure is

if PDF:
        pdf = PdfPages(args.output)
... do something to produce a fig
        if PDF:
            pdf.savefig (fig)
            plt.close()
            
if PDF:
    pdf.close()
else:
    plt.show()

I would need ...do something to produce fig to be inside contextmanager when producing PDF, but not when PDF is false. Not sure how to code that.

The context manager only needs to wrap the savefig (just like one would use open() for normal files), e.g.

# produce the figs first
if PDF:
    with MultiPage(...) as pdf:
        pdf.savefig(...)
else:
    plt.show()

(or you can do various tricks with ExitStack and nullcontext, see https://docs.python.org/3/library/contextlib.html#contextlib.ExitStack and https://docs.python.org/3/library/contextlib.html#contextlib.nullcontext).

OK, works using context manager as you showed.
py3.6 doesn't have nullcontext, but can be simulated using contextlib.suppress().
The fact that it only works with cm needs to be documented.

I fixed it on master: the old pattern (with close()) now works too.
I haven't made a new wheel but you can get away with copy-pasting multipage.py.

Closing as fixed on master, feel free to request a reopen if there are more issues.