Fig.draw(renderer) vs fig.canvas.draw()

When using a non-interactive backend (specifically the PGF backend), I noticed that fig.canvas.draw() isn’t equivalent to renderer = fig.canvas.get_renderer() followed by fig.draw(renderer). Can anyone please explain the difference between these two approaches?

Interestingly, it looks like for the pgf backend, the fig.canvas.draw method is a no-op (because the default draw implementation is a no-op and pgf backend does not provide it’s own). This is different than the GUI backends who do provide a draw (which serves as the “update the screen” method).

For historical reasons the canvas objects have both a draw method and a set of print_XYZ methods. The later are what are used for saving to files (which pgf/ps/pdf do implement so they can save output). Both the ps and pdf backends explicitly define a no-op draw method from when they came into the library (the no-op methods go back to at least 2004 and 2006 respectively). This is contrary to our more recent suggestions to run fig.canvas.draw() to force a render to update things that we only know after we have drawn (ex tick locations / values).

On the other hand, fig.draw(renderer) is the quasi-internal method that is used by canvas.draw() and canvas.print_XYZ to actually do the rendering (the general model is the “canvas” creates the “renderer” and passing it into Figure.draw which then recursively calls the Artist.draw(renderer) method of all it’s children. The “Artists” then use the methods on the renderer to output the plot (the exact details of what those methods do is dependent on the backend for svg renderer.draw_line() outputs some text but for Agg it updates pixels in an RGBA buffer).

I suspect that we should add code to the draw methods of the non-interactive backends to force the render, but that needs a bit of thought to make sure we don’t have any unintended consequences of that.

1 Like

Thanks for the detailed response. That was helpful.

created an issue on github to make sure that this remains on the radar https://github.com/matplotlib/matplotlib/issues/16558