You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Feature request - make it simpler to use full OO interface #1094
I would like to start using the matplotlib OO interface more, as I would prefer to use this when interactive plotting is not needed. It it slightly faster, and behaves more intuitively in terms of reference counting (pyplot keeps a reference to each figure, meaning that if figures are not closed by pyplot, memory goes out of control).
The reason I don't use it is because it's not easy to remember all the set-up of the canvas and figure:
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
fig = Figure()
canvas = FigureCanvas(fig)
ax = fig.add_subplot(1, 1, 1)
ax.scatter(np.random.random(10), np.random.random(10))
fig.savefig('test.png')
So I was wondering whether it would be possible to make Figure more intelligent in terms of canvas? The 'ideal' API in my mind would be:
i.e. I want the figure to just use the default backend (since this is set at the root level of matplotlib, not pyplot). So I would expect the following to work:
It would probably be cleaner this way. Currently, pyplot.figure() invokes the new_figure_manager function that is (somehow) established by the init.py module in matplotlib.backends. It would probably be wise to look at this area of code again to see how we can clean this up anyway.
Setting pyplot aside for the moment, is there anything to stop the canvas being set up in the Figure constructor? At the moment, Figure.__init__ has the line:
self.canvas=None
Which is evidenced by:
In [1]: frommatplotlib.figureimportFigureIn [2]: fig=Figure()
In [3]: printfig.canvasNone
One way to work around this is to retrieve the default backend in the __init__ method in the constructor, which should exist either from a matplotlib.use('mybackend') or from rcParams. This can be done using a matplotlib.get_backend() call.
So I tried this out, and it seems to work ok. I can't say anything for pyplot. Though, if you're using pyplot, you're probably not interested in the OO interface. I can submit a PR if any of the more experienced mpl developers would like to give some input...
This might have worked if carefully restricted to non-interactive backends. I think it requres some careful thought and experimentation, though. It may be that the way to handle it is via a kwarg to the Figure constructor, explicitly designating a non-interactive backend; or maybe in the code as you had it, attaching the canvas to the figure upon Figure initialization would be done only if the default backend is non-interactive. All of the messy figure management machinery is needed only for screen display, not for savefig, I believe.
A problem with this approach is that although it simplifies some things, it adds overall complexity in that something that works for a non-interactive backend fails if the default backend is interactive. So, it might cause more trouble (puzzled users, mailing list traffic) than it is worth.
@efiring Do you think we can find a way to implement this issue without changing the interactive workflow? I have some spare time on the next few weeks and would like to work on that.
You are certainly welcome to try. I'm out on a ship until mid-Nov., and then busy into December, so I probably won't be much help. If you can come up with something that makes the whole Figure/Canvas dance simpler and easier to understand at the lowest code level as well as at the user level--and that doesn't break anything--that will be very good.
I'll sure give it a try.
Is there a dev mailing list / irc channel that I can use to find someone if I need guidance? (couldn't find anything on the site)
@berr I've been working on an alternative solution to this, and currently have an implementation illustrating some degree of success. That said, I would be interested to see if you come up with a similar approach. Do you have a branch I can take a cheeky fork of?
@dmcdougall Not yet. I'm planning to start this on the next week. Since you've already started, I can use your work as a starting point or even just continue it. Do you have it on a branch that I could see?
@berr Yes, but don't let it pollute your train of thought. I tried this once before and failed epicly. This new approach is a better version, and I haven't worked on it for a while so I'm not sure if it still works... The branch is here. I hope it's helpful.
Activity
WeatherGod commentedon Aug 16, 2012
It would probably be cleaner this way. Currently, pyplot.figure() invokes the
new_figure_managerfunction that is (somehow) established by the init.py module in matplotlib.backends. It would probably be wise to look at this area of code again to see how we can clean this up anyway.dmcdougall commentedon Aug 21, 2012
Setting
pyplotaside for the moment, is there anything to stop the canvas being set up in theFigureconstructor? At the moment,Figure.__init__has the line:Which is evidenced by:
One way to work around this is to retrieve the default backend in the
__init__method in the constructor, which should exist either from amatplotlib.use('mybackend')or fromrcParams. This can be done using amatplotlib.get_backend()call.Is there something deeper I am missing?
astrofrog commentedon Aug 21, 2012
@dmcdougall - this is exactly what I mean, and I believe it would make it a lot easier for people to use this API.
dmcdougall commentedon Aug 21, 2012
So I tried this out, and it seems to work ok. I can't say anything for
pyplot. Though, if you're usingpyplot, you're probably not interested in the OO interface. I can submit a PR if any of the more experienced mpl developers would like to give some input...dmcdougall commentedon Sep 8, 2012
@efiring Should this be re-opened because of #1221?
efiring commentedon Sep 8, 2012
This might have worked if carefully restricted to non-interactive backends. I think it requres some careful thought and experimentation, though. It may be that the way to handle it is via a kwarg to the Figure constructor, explicitly designating a non-interactive backend; or maybe in the code as you had it, attaching the canvas to the figure upon Figure initialization would be done only if the default backend is non-interactive. All of the messy figure management machinery is needed only for screen display, not for savefig, I believe.
A problem with this approach is that although it simplifies some things, it adds overall complexity in that something that works for a non-interactive backend fails if the default backend is interactive. So, it might cause more trouble (puzzled users, mailing list traffic) than it is worth.
berr commentedon Oct 30, 2012
@efiring Do you think we can find a way to implement this issue without changing the interactive workflow? I have some spare time on the next few weeks and would like to work on that.
efiring commentedon Oct 31, 2012
You are certainly welcome to try. I'm out on a ship until mid-Nov., and then busy into December, so I probably won't be much help. If you can come up with something that makes the whole Figure/Canvas dance simpler and easier to understand at the lowest code level as well as at the user level--and that doesn't break anything--that will be very good.
berr commentedon Oct 31, 2012
I'll sure give it a try.
Is there a dev mailing list / irc channel that I can use to find someone if I need guidance? (couldn't find anything on the site)
mdboom commentedon Oct 31, 2012
matplotlib-devel is a good place to reach other developers:
https://sourceforge.net/mailarchive/forum.php?forum_name=matplotlib-devel
dmcdougall commentedon Oct 31, 2012
@berr I've been working on an alternative solution to this, and currently have an implementation illustrating some degree of success. That said, I would be interested to see if you come up with a similar approach. Do you have a branch I can take a cheeky fork of?
berr commentedon Oct 31, 2012
@dmcdougall Not yet. I'm planning to start this on the next week. Since you've already started, I can use your work as a starting point or even just continue it. Do you have it on a branch that I could see?
dmcdougall commentedon Oct 31, 2012
@berr Yes, but don't let it pollute your train of thought. I tried this once before and failed epicly. This new approach is a better version, and I haven't worked on it for a while so I'm not sure if it still works... The branch is here. I hope it's helpful.
dmcdougall commentedon Oct 31, 2012
IIRC, I had problems with the Qt4 backend...
demitri commentedon Nov 7, 2012
Just want to add my +1 to strongly support a fully OO plotting interface.
dmcdougall commentedon Nov 7, 2012
@demitri Thanks. Good to know this would be used.
@berr Did you try out my branch?
dmcdougall commentedon Feb 19, 2013
Turns out this is rather hard to implement without a significant backend redesign and/or refactor. See discussion in #1457.