Reduce object-oriented boilerplate for users#1125
Conversation
|
This is very handy. +1. |
|
The basic idea seems good. Ideally, I would think that each backend should provide a canvas in way that does not require the huge if...elif structure, but this would require a larger change, so perhaps it should be left until later. figure.py should not need to know about all possible backends; it should be able to do something like "import matplotlib.backends; matplotlib.backends.get_current_canvas()". In any case, all backends supported by rcsetup.validate_backends (and listed in rcsetup.all_backends) should be included; some are missing at present. |
There was a problem hiding this comment.
Perhaps this could be a function in backend_bases? pylab_setup pretty much does this for you. Something like:
import matplotlib.backends as mbackends
# NOTE: requires a change from #1020
backend_mod, _, _, _ = mbackends.pylab_setup()
# NOTE: would require all backend modules to have
# a FigureCanvas rather than say a FigureCanvasGTKAgg
backend_mod.FigureCanvas(self)
There was a problem hiding this comment.
Also, needs a docstring, and the name of the method is misleading.
|
Ah. I've only just read @efiring 's comment. It seems we agree on this issue. I definitely think this should be done properly at this stage, and would think it was cleaner to do this via the "backend_bases" module. Other than that, I think this is a great idea and will make working in a full OO way much easier. |
|
@pelson: Thanks for finding the way to avoid the large |
|
Yes @pelson! Good spot. I didn't think it was possible. I will obviously update to reflect this. Awesome! :D |
Now, one can work with the default backend to create figures, without
the need to attach a canvas manually. For example:
import matplotlib
matplotlib.use('agg')
from matplotlib.figure import Figure
fig = Figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot([1, 2, 3], [1, 2, 3])
fig.savefig('oo.png')
|
I've rebased this against master to get the awesome changes from #1175. This will save me from conflicts with the changes I'm about to make. |
|
I wonder whether as part of this PR, it would make sense to also update the documentation to add clearer information about the pure-OO API? At the moment, it's very hard to find any information about it. Maybe there should be a top-level section under 'User guide' that talks about the pure-OO API and the pros and cons compared to using pyplot or th hybrid pyplot-OO? |
|
@astrofrog That's a great suggestion. Would any of the wider community appreciate a couple of example scripts that use the object-oriented interface? I'd be happy to write some. |
|
Ok, 3e4dea3 is a rather large commit. @pelson's suggestion of making each backend have a I'm still a newbie when it comes to the codebase, which is why I need you guys to tell me if I've put something in a sub-optimal place. You've been really helpful with all of my suggestions. So thank you. Please test it out. Specifically, I don't want this to break anything in |
There was a problem hiding this comment.
I will do it. I promise.
There was a problem hiding this comment.
Double new line was intentional here.
|
Looks good. I would be happy to merge this once there was a docstring on I know I'm always picky with newlines [and I hate myself for it ;-) ] but normally one would put a double new line between top level objects in a module (classes, functions, groups of constants etc.) and a single new line for the rest (in particular methods). I don't this doing this should block this PR though - I think this is a really helpful change. @astrofrog 's suggestion of adding a section on pure OO & its benefits is a good idea, but lets keep this implementation and PR separate - there is no need to hold up one with the other. |
figure.py now uses pylab_setup() to probe for the backend module to set up the figure canvas.
|
@pelson - agree, the docs can be worked on in a different PR. |
|
Should there be a way to optionally make it behave like before, i.e. to disable setting the canvas? e.g. something like EDIT: alternatively, a |
I'm not that worried by it. The easy answer is for users to simply do Unless anybody has any concerns, I will merge this in 18 hours. Good stuff @dmcdougall. |
|
@pelson - ok, I don't have a strong opinion about that, so we can just address it if people ask for it. I might open a PR if I run into issues with this some day. Looking forward to using this! :-) |
|
@astrofrog Thanks for the interest :) Glad I could help make someone's life easier. |
|
Ah. I'm sorry @dmcdougall - I was a bit eager. Would you mind adding an entry in the what's new section? |
|
@pelson And the changelog, too? |
My feeling is not. Your not breaking anything, simply making one use case easier. We only need one entry: whichever you choose will be fine in this case. |
|
I also added a nice example exposing the new change, just because there's no example anywhere else. |
Reduce object-oriented boilerplate for users
|
Thanks to @dmcdougall for doing the work & to @astrofrog for suggesting it. This is a real nice addition. |
There was a problem hiding this comment.
Shouldn't this be FigureCanvasGTKAgg (and moved after the definition of FigureCanvasGTKAgg). At least this doesn't work.
There was a problem hiding this comment.
Oops. Yes. Good spot. I will open another PR to address this.
There was a problem hiding this comment.
Yes, GtkAgg backend currently does not work, which I believe is due to this.
There was a problem hiding this comment.
What if the module from pylab_setup()[0] doesn't have a FigureCanvas class. Then the line return backend_mod.FigureCanvas(self) would result in an error. So it does with IPython that uses his own backend module but without a FigureCanvas class.
The old def _current_figure_canvas(self)works because in case it doesn't find the right FigureCanvas it returns None.
There was a problem hiding this comment.
@verbit Line 508 of lib/matplotlib/backends/backend_tkagg is
FigureCanvas = FigureCanvasTkAggso the return value of pylab_setup[0] does indeed have a FigureCanvas for this backend. Do you see this behaviour with qt4agg or gtk3agg?
Perhaps this is actually a bug in the tkagg backend?
There was a problem hiding this comment.
I saw this behaviour with IPython's custom backend (see: backend_inline.py) that doesn't return a FigureCanvas.
I'm just concerned about the fact, that this new _setup_canvas function might break other applications that don't provide a FigureCanvas class as they are used to the old way.
The attempt to make OO use easier broke the Tkagg and Wx* backends.
Now, one can work with the default backend to create figures, without
the need to attach a canvas manually. For example:
This is an attempt at resolving issue #1094.
Disclaimer: I have no idea what implications this has on
pyplotandpylab, but 'it just works' for me, and I tried theMacOSX,AggandPDFbackends.