Access matplotlib/PyPlot object of Plots.jl plot

I plot using Plots; pyplot()

How can I access the created PyPlot.Figure(PyObject <Figure size 640x480 with 1 Axes>) and PyObject <AxesSubplot:> ? (I can get those when I use PyPlot directly, but then I’m not using Plots).

Plots.PyPlot.gcf() gives an empty (i.e. new) figure, so I suspect Plots closes the figure…

(pinging @daschw @isentropic).

1 Like
p = plot(rand(10));
# PyPlot.Figure(PyObject <Figure size 600x400 with 1 Axes>)
1 Like

you can modify p.o via pyplot standard pyplot API to further tweak the figure to your liking. I use this sometimes to add further minor tweaks (make sure not to use plots API, as it would replot it and erase your modifications)

1 Like

It’s not entirely trivial to modify the .o attribute containing the PyPlot figure in such a way that the changes can be written out to a file.

I’ve found the following to work:

using Plots

function plot_sine_curve(;kwargs...)
    # just for example...
    fig = plot(sin; kwargs...)
    return fig

function adjust_figure(fig)
    pyfig = fig.o
    ax = pyfig[:axes][1]
    ax.set_position([0.2, 0.2, 0.4, 0.4])
    ax.set_xlabel("new x label")
    return pyfig

fig = plot_sine_curve()
Plots.prepare_output(fig) # XXX
pyfig = adjust_figure(fig)

Note the line Plots.prepare_output(fig)! Without this, fig.o[:axes] will be empty. The prepare_output function is not part of the official Plots API, so this might be subject to change.

Instead of prepare_output, it would also work to run savefig(fig, "out.pdf") (which calls prepare_output internally). In that case, we would save the original Plots.jl-generated figure first, and then overwrite it with the “patched” version.

It is also important to point out that once you go to down to the pyplot level, you can’t go back up to the Plots.jl level for that figure. Hence, after adjust_figure, we call the lower-level savefig method of the PyPlot.Figure, not the high-level Plots.savefig method (which would write the original unmodified figure)

1 Like